未验证 提交 86da61a4 编写于 作者: 拧巴的猫 提交者: GitHub

fix: elevator 组件props补全、新增单元测试、demo和文档多语言支持 (#180)

上级 dcaccb6a
......@@ -4,8 +4,6 @@ import '@testing-library/jest-dom'
import { Cell } from '../cell'
import { Switch } from '../../switch/switch'
const classPrefix = `nut-avatar`
test('prop title desc subtitle test', () => {
const { getByTestId, container } = render(
<>
......
......@@ -17,28 +17,30 @@ import { Cell, CellGroup } from '@nutui/nutui-react'
:::demo
```tsx
import React from "react";
import { Cell } from '@nutui/nutui-react';
import React from 'react'
import { Cell } from '@nutui/nutui-react'
const App = () => {
const testClick = (event: React.MouseEvent<HTMLDivElement, globalThis.MouseEvent>) => {
const testClick = (
event: React.MouseEvent<HTMLDivElement, globalThis.MouseEvent>
) => {
console.log('Click Test')
}
}
return (
<>
<Cell title="Title" desc="Description" />
<Cell title="Title" subTitle="Subtitle Description" desc="Description" />
<Cell
<Cell title="Title" desc="Description" />
<Cell title="Title" subTitle="Subtitle Description" desc="Description" />
<Cell
title="Click Test"
click={(
event: React.MouseEvent<HTMLDivElement, globalThis.MouseEvent>
event: React.MouseEvent<HTMLDivElement, globalThis.MouseEvent>
) => testClick(event)}
/>
<Cell title="Round Radius 0" roundRadius={0} />
/>
<Cell title="Round Radius 0" roundRadius={0} />
</>
);
};
export default App;
)
}
export default App
```
:::
......@@ -48,23 +50,23 @@ export default App;
:::demo
```tsx
import React from "react";
import { Cell } from '@nutui/nutui-react';
import React from 'react'
import { Cell } from '@nutui/nutui-react'
const App = () => {
return (
<>
<Cell size="large" title="Title" desc="Description" />
<Cell
<Cell size="large" title="Title" desc="Description" />
<Cell
size="large"
title="Title"
subTitle="Subtitle Description"
desc="Description"
/>
/>
</>
);
};
export default App;
)
}
export default App
```
:::
......@@ -74,19 +76,19 @@ export default App;
:::demo
```tsx
import React from "react";
import { Cell } from '@nutui/nutui-react';
import React from 'react'
import { Cell } from '@nutui/nutui-react'
const App = () => {
return (
<>
<Cell>
<Cell>
<div>Content</div>
</Cell>
</Cell>
</>
);
};
export default App;
)
}
export default App
```
:::
......@@ -96,22 +98,22 @@ export default App;
:::demo
```tsx
import React from "react";
import { Cell } from '@nutui/nutui-react';
import React from 'react'
import { Cell } from '@nutui/nutui-react'
const App = () => {
return (
<Cell
title={
title={
<span>
Title <b style={{ color: 'red' }}>1</b>
Title <b style={{ color: 'red' }}>1</b>
</span>
}
desc="Description"
}
desc="Description"
/>
);
};
export default App;
)
}
export default App
```
:::
......@@ -121,29 +123,29 @@ export default App;
:::demo
```tsx
import React from "react";
import { CellGroup,Cell } from '@nutui/nutui-react';
import React from 'react'
import { CellGroup, Cell } from '@nutui/nutui-react'
const App = () => {
return (
<>
<CellGroup
<CellGroup
title="Link | CellGroup Usage"
desc="Usage nut-cell-group support title desc slots"
>
>
<Cell title="Link Usage" isLink />
<Cell
title="URL Jump"
desc="https://jd.com"
isLink
url="https://jd.com"
title="URL Jump"
desc="https://jd.com"
isLink
url="https://jd.com"
/>
<Cell title="Router Jump ’/‘ " to="/" />
</CellGroup>
</CellGroup>
</>
);
};
export default App;
)
}
export default App
```
:::
......@@ -153,17 +155,17 @@ export default App;
:::demo
```tsx
import React from "react";
import { CellGroup,Cell,Switch } from '@nutui/nutui-react';
import React from 'react'
import { CellGroup, Cell, Switch } from '@nutui/nutui-react'
const App = () => {
return (
<CellGroup title="Customize the right arrow area">
<Cell title="Switch" linkSlot={<Switch checked />} />
</CellGroup>
);
};
export default App;
)
}
export default App
```
:::
......@@ -173,26 +175,26 @@ export default App;
:::demo
```tsx
import React from "react";
import { CellGroup,Cell } from '@nutui/nutui-react';
import React from 'react'
import { CellGroup, Cell } from '@nutui/nutui-react'
const App = () => {
return (
<CellGroup title="Customize the left Icon area">
<Cell
<Cell
title="Image"
iconSlot={
<img
<img
className="nut-icon"
alt=""
src="https://img11.360buyimg.com/imagetools/jfs/t1/137646/13/7132/1648/5f4c748bE43da8ddd/a3f06d51dcae7b60.png"
/>
/>
}
/>
/>
</CellGroup>
);
};
export default App;
)
}
export default App
```
:::
......@@ -202,15 +204,13 @@ export default App;
:::demo
```tsx
import React from "react";
import { Cell } from '@nutui/nutui-react';
import React from 'react'
import { Cell } from '@nutui/nutui-react'
const App = () => {
return (
<Cell title="Name" icon="my" desc="Description" isLink />
);
};
export default App;
return <Cell title="Name" icon="my" desc="Description" isLink />
}
export default App
```
:::
......@@ -220,15 +220,13 @@ export default App;
:::demo
```tsx
import React from "react";
import { Cell } from '@nutui/nutui-react';
import React from 'react'
import { Cell } from '@nutui/nutui-react'
const App = () => {
return (
<Cell descTextAlign="left" desc="Description" />
);
};
export default App;
return <Cell descTextAlign="left" desc="Description" />
}
export default App
```
:::
......@@ -240,15 +238,15 @@ You can center the left and right contents of the cell vertically through the 'c
:::demo
```tsx
import React from "react";
import { Cell } from '@nutui/nutui-react';
import React from 'react'
import { Cell } from '@nutui/nutui-react'
const App = () => {
return (
<Cell center title="Title" subTitle="Subtitle Description" desc="Desc" />
);
};
export default App;
<Cell center title="Title" subTitle="Subtitle Description" desc="Desc" />
)
}
export default App
```
:::
......
import * as React from 'react'
import { render, fireEvent } from '@testing-library/react'
import '@testing-library/jest-dom'
import { Elevator } from '../elevator'
const indexList = [
{
title: 'A',
list: [
{
name: '安徽',
id: 1,
},
],
},
{
title: 'B',
list: [
{
name: '北京',
id: 2,
},
],
},
{
title: 'G',
list: [
{
name: '广西',
id: 3,
},
{
name: '广东',
id: 4,
},
],
},
{
title: 'H',
list: [
{
name: '湖南',
id: 5,
},
{
name: '湖北',
id: 6,
},
],
},
]
const clickIndex = (key: string) => {
console.log(key)
}
test('should render elevator list height after height props to be 200', () => {
const { container } = render(<Elevator indexList={indexList} height={200} />)
expect(container.querySelector('.nut-elevator__list')).toHaveAttribute(
'style',
'height: 200px;'
)
})
test('should render list data when indexList props not empty', () => {
const { container } = render(<Elevator indexList={indexList} height={200} />)
expect(container.querySelectorAll('.nut-elevator__list__item').length).toBe(
indexList.length
)
})
test('should list item highlight when clickItem trigger click', () => {
const testClick = jest.fn()
const { container } = render(
<Elevator
indexList={indexList}
height={200}
clickItem={(key: string, item: any) => testClick(key, item)}
/>
)
const listItem = container.querySelectorAll(
'.nut-elevator__list__item__name'
)[0]
fireEvent.click(listItem) // 模拟点击
expect(testClick).toBeCalled() // 断言 是否已经被点击
setTimeout(() => {
expect(
container.querySelector('.nut-elevator__list__item__name--highcolor')
?.innerHTML
).toBe('安徽')
}, 100)
expect(testClick).toBeCalledWith('A', { id: 1, name: '安徽' }) // 点击传参测试
})
test('clickIndex trigger click', () => {
const testClick = jest.fn()
const { container } = render(
<Elevator
indexList={indexList}
height={200}
clickIndex={(key: string) => testClick(key)}
/>
)
const listItem = container.querySelectorAll(
'.nut-elevator__bars__inner__item'
)[2]
fireEvent.click(listItem) // 模拟点击
expect(testClick).toBeCalled() // 断言 是否已经被点击
expect(testClick).toBeCalledWith('G') // 点击传参测试
fireEvent.click(listItem) // 模拟点击
expect(testClick).toBeCalledTimes(2) // 被点击次数
})
test('index is sticky', () => {
const testClick = jest.fn()
const { container } = render(
<Elevator
indexList={indexList}
height={200}
isSticky
clickIndex={(key: string) => testClick(key)}
/>
)
const listItem = container.querySelectorAll(
'.nut-elevator__bars__inner__item'
)[2]
fireEvent.click(listItem) // 模拟点击
setTimeout(() => {
expect(
container.querySelectorAll('.nut-elevator__list__fixed').length
).toBe(1)
}, 300)
})
import React from 'react'
import { Elevator } from './elevator'
import { Elevator, elevatorContext } from './elevator'
import { useTranslate } from '../../sites/assets/locale'
import Icon from '../icon'
interface T {
basic: string
customIndex: string
sticky: string
customContent: string
anhui: string
beijing: string
guangxi: string
guangdong: string
hunan: string
hubei: string
shanghai: string
shenzhen: string
guangzhou: string
hangzhou: string
chengdu: string
xian: string
tianjin: string
wuhan: string
changsha: string
chongqin: string
suzhou: string
nanjing: string
xining: string
lanzhou: string
shijiazhuang: string
qinhuangdao: string
dalian: string
haerbin: string
changchun: string
taiyuan: string
fujian: string
gansu: string
guizhou: string
hainan: string
hebei: string
henan: string
heilongjiang: string
jilin: string
jiangsu: string
jiangxi: string
liaoning: string
one: string
two: string
three: string
}
const ElevatorDemo = () => {
const acceptKey = 'num'
const [translated] = useTranslate<T>({
'zh-CN': {
basic: '基本用法',
customIndex: '自定义索引key',
sticky: '索引吸顶',
customContent: '自定义内容',
anhui: '安徽',
beijing: '北京',
guangxi: '广西',
guangdong: '广东',
hunan: '湖南',
hubei: '湖北',
shanghai: '上海',
shenzhen: '深圳',
guangzhou: '广州',
hangzhou: '杭州',
chengdu: '成都',
xian: '西安',
tianjin: '天津',
wuhan: '武汉',
changsha: '长沙',
chongqin: '重庆',
suzhou: '苏州',
nanjing: '南京',
xining: '西宁',
lanzhou: '兰州',
shijiazhuang: '石家庄',
qinhuangdao: '秦皇岛',
dalian: '大连',
haerbin: '哈尔滨',
changchun: '长春',
taiyuan: '太原',
fujian: '福建',
gansu: '甘肃',
guizhou: '贵州',
hainan: '海南',
hebei: '河北',
henan: '河南',
heilongjiang: '黑龙江',
jilin: '吉林',
jiangsu: '江苏',
jiangxi: '江西',
liaoning: '辽宁',
one: '',
two: '',
three: '',
},
'zh-TW': {
basic: '基本用法',
customIndex: '自定義索引key',
sticky: '索引吸頂',
customContent: '自定義內容',
anhui: '安徽',
beijing: '北京',
guangxi: '廣西',
guangdong: '廣東',
hunan: '湖南',
hubei: '湖北',
shanghai: '上海',
shenzhen: '深圳',
guangzhou: '廣州',
hangzhou: '杭州',
chengdu: '成都',
xian: '西安',
tianjin: '天津',
wuhan: '武漢',
changsha: '長沙',
chongqin: '重慶',
suzhou: '蘇州',
nanjing: '南京',
xining: '西寧',
lanzhou: '蘭州',
shijiazhuang: '石家莊',
qinhuangdao: '秦皇島',
dalian: '大連',
haerbin: '哈爾濱',
changchun: '長春',
taiyuan: '太原',
fujian: '福建',
gansu: '甘肅',
guizhou: '貴州',
hainan: '海南',
hebei: '河北',
henan: '河南',
heilongjiang: '黑龍江',
jilin: '吉林',
jiangsu: '江蘇',
jiangxi: '江西',
liaoning: '遼寧',
one: '',
two: '',
three: '',
},
'en-US': {
basic: 'Basic Usage',
customIndex: 'Custom index key',
sticky: 'Index ceiling',
customContent: 'Custom content',
anhui: 'AnHui',
beijing: 'BeiJing',
guangxi: 'GuangXi',
guangdong: 'GuangDong',
hunan: 'HuNan',
hubei: 'HuBei',
shanghai: 'ShangHai',
shenzhen: 'ShenZhen',
guangzhou: 'GuangZhou',
hangzhou: 'HangZhou',
chengdu: 'ChengDu',
xian: 'XiAn',
tianjin: 'TianJin',
wuhan: 'WuHan',
changsha: 'ChangSha',
chongqin: 'ChongQin',
suzhou: 'SuZhou',
nanjing: 'NanJing',
xining: 'XiNing',
lanzhou: 'LanZhou',
shijiazhuang: 'ShiJiaZhuang',
qinhuangdao: 'QinHuangDao',
dalian: 'DaLian',
haerbin: 'HaErBin',
changchun: 'ChangChun',
taiyuan: 'TaiYuan',
fujian: 'FuJian',
gansu: 'GanSu',
guizhou: 'GuiZhou',
hainan: 'HaiNan',
hebei: 'HeBei',
henan: 'HeNan',
heilongjiang: 'HeiLongJiang',
jilin: 'JiLin',
jiangsu: 'JiangSu',
jiangxi: 'JiangXi',
liaoning: 'LiaoNing',
one: 'one',
two: 'two',
three: 'three',
},
})
const dataList = [
{
title: 'A',
list: [
{
name: '安徽',
name: translated.anhui,
id: 1,
},
],
......@@ -16,7 +205,7 @@ const ElevatorDemo = () => {
title: 'B',
list: [
{
name: '北京',
name: translated.beijing,
id: 2,
},
],
......@@ -25,11 +214,11 @@ const ElevatorDemo = () => {
title: 'G',
list: [
{
name: '广西',
name: translated.guangxi,
id: 3,
},
{
name: '广东',
name: translated.guangdong,
id: 4,
},
],
......@@ -38,16 +227,15 @@ const ElevatorDemo = () => {
title: 'H',
list: [
{
name: '湖南',
name: translated.hunan,
id: 5,
},
{
name: '湖北',
name: translated.hubei,
id: 6,
},
,
{
name: '琥珀',
name: translated.henan,
id: 7,
},
],
......@@ -55,105 +243,219 @@ const ElevatorDemo = () => {
]
const dataList2 = [
{
num: '',
num: translated.one,
list: [
{
name: '北京',
name: translated.beijing,
id: 1,
},
{
name: '上海',
name: translated.shanghai,
id: 2,
},
{
name: '深圳',
name: translated.shenzhen,
id: 3,
},
{
name: '广州',
name: translated.guangzhou,
id: 4,
},
{
name: '杭州',
name: translated.hangzhou,
id: 5,
},
],
},
{
num: '',
num: translated.two,
list: [
{
name: '成都',
name: translated.chengdu,
id: 6,
},
{
name: '西安',
name: translated.xian,
id: 7,
},
{
name: '天津',
name: translated.tianjin,
id: 8,
},
{
name: '武汉',
name: translated.wuhan,
id: 9,
},
{
name: '长沙',
name: translated.changsha,
id: 10,
},
{
name: '重庆',
name: translated.chongqin,
id: 11,
},
{
name: '苏州',
name: translated.suzhou,
id: 12,
},
{
name: '南京',
name: translated.nanjing,
id: 13,
},
],
},
{
num: '',
num: translated.three,
list: [
{
name: '西宁',
name: translated.xining,
id: 14,
},
{
name: '兰州',
name: translated.lanzhou,
id: 15,
},
{
name: '石家庄',
name: translated.shijiazhuang,
id: 16,
},
{
name: '秦皇岛',
name: translated.qinhuangdao,
id: 17,
},
{
name: '大连',
name: translated.dalian,
id: 18,
},
{
name: '哈尔滨',
name: translated.haerbin,
id: 19,
},
{
name: '长春',
name: translated.changchun,
id: 20,
},
{
name: '太原',
name: translated.taiyuan,
id: 21,
},
],
},
]
const dataList3 = [
{
title: 'A',
list: [
{
name: translated.anhui,
id: 1,
},
],
},
{
title: 'B',
list: [
{
name: translated.beijing,
id: 2,
},
],
},
{
title: 'C',
list: [
{
name: translated.chongqin,
id: 3,
},
],
},
{
title: 'F',
list: [
{
name: translated.anhui,
id: 4,
},
],
},
{
title: 'G',
list: [
{
name: translated.guangxi,
id: 5,
},
{
name: translated.guangdong,
id: 6,
},
{
name: translated.gansu,
id: 7,
},
{
name: translated.guizhou,
id: 8,
},
],
},
{
title: 'H',
list: [
{
name: translated.hunan,
id: 9,
},
{
name: translated.hubei,
id: 10,
},
{
name: translated.hainan,
id: 11,
},
{
name: translated.hebei,
id: 12,
},
{
name: translated.henan,
id: 13,
},
{
name: translated.heilongjiang,
id: 14,
},
],
},
{
title: 'J',
list: [
{
name: translated.jilin,
id: 15,
},
{
name: translated.jiangsu,
id: 16,
},
{
name: translated.jiangxi,
id: 17,
},
],
},
{
title: 'L',
list: [
{
name: translated.liaoning,
id: 18,
},
],
},
]
const clickItem = (key: string, item: any) => {
console.log(key, JSON.stringify(item))
}
......@@ -164,21 +466,47 @@ const ElevatorDemo = () => {
return (
<>
<div className="demo">
<h2>基础用法</h2>
<h2>{translated.basic}</h2>
<Elevator
indexList={dataList}
height="260"
clickItem={(key: string, item: any) => clickItem(key, item)}
clickIndex={(key: string) => clickIndex(key)}
/>
<h2>自定义索引key</h2>
<h2>{translated.customIndex}</h2>
<Elevator
indexList={dataList2}
height="220"
acceptKey="num"
acceptKey={acceptKey}
clickItem={(key: string, item: any) => clickItem(key, item)}
clickIndex={(key: string) => clickIndex(key)}
/>
<h2>{translated.sticky}</h2>
<Elevator
indexList={dataList3}
isSticky
height="220"
clickItem={(key: string, item: any) => clickItem(key, item)}
clickIndex={(key: string) => clickIndex(key)}
/>
<h2>{translated.customContent}</h2>
<Elevator
indexList={dataList}
height="260"
clickItem={(key: string, item: any) => clickItem(key, item)}
clickIndex={(key: string) => clickIndex(key)}
>
<elevatorContext.Consumer>
{(value) => {
return (
<>
<Icon name="JD" size="12" />
<span style={{ marginLeft: '15px' }}>{value?.name}</span>
</>
)
}}
</elevatorContext.Consumer>
</Elevator>
</div>
</>
)
......
# Elevator 电梯楼层
# Elevator
### Intro
### 介绍
用于列表快速定位以及索引的显示
### 安装
### Install
```javascript
import { Elevator } from '@nutui/nutui-react'
```
## 代码演示
## Demo
### 基础用法
### Basic Usage
:::demo
```tsx
import React from "react";
import { Elevator } from '@nutui/nutui-react';
import React from 'react'
import { Elevator } from '@nutui/nutui-react'
const App = () => {
const dataList = [
{
title: 'A',
list: [
{
name: '安徽',
id: 1,
},
],
},
{
title: 'B',
list: [
{
name: '北京',
id: 2,
},
],
},
{
title: 'G',
list: [
{
name: '广西',
id: 3,
},
{
name: '广东',
id: 4,
},
],
},
{
title: 'H',
list: [
{
name: '湖南',
id: 5,
},
{
name: '湖北',
id: 6,
},
,
{
name: '琥珀',
id: 7,
},
],
},
]
const clickItem = (key: string, item: any) => {
console.log(key, JSON.stringify(item))
}
const dataList = [
{
title: 'A',
list: [
{
name: 'AnHui',
id: 1,
},
],
},
{
title: 'B',
list: [
{
name: 'BeiJing',
id: 2,
},
],
},
{
title: 'G',
list: [
{
name: 'GuangXi',
id: 3,
},
{
name: 'GuangDong',
id: 4,
},
],
},
{
title: 'H',
list: [
{
name: 'HuNan',
id: 5,
},
{
name: 'HuBei',
id: 6,
},
{
name: 'Henan',
id: 7,
},
],
},
]
const clickItem = (key: string, item: any) => {
console.log(key, JSON.stringify(item))
}
const clickIndex = (key: string) => {
console.log(key)
const clickIndex = (key: string) => {
console.log(key)
}
return (
<Elevator
indexList={dataList}
height="260"
clickItem={(key: string, item: any) => clickItem(key, item)}
clickIndex={(key: string) => clickIndex(key)}
/>
)
}
return (
<Elevator
indexList={dataList}
height="260"
clickItem={(key: string, item: any) => clickItem(key, item)}
clickIndex={(key: string) => clickIndex(key)}
/>
);
};
export default App;
export default App
```
:::
### 自定义索引
### Custom index
## API
:::demo
```tsx
import React from 'react'
import { Elevator } from '@nutui/nutui-react'
const App = () => {
const dataList = [
{
num: 'One',
list: [
{
name: 'BeiJing',
id: 1,
},
{
name: 'ShangHai',
id: 2,
},
{
name: 'ShenZhen',
id: 3,
},
{
name: 'GuangZhou',
id: 4,
},
{
name: 'HangZhou',
id: 5,
},
],
},
{
num: 'Two',
list: [
{
name: 'ChengDu',
id: 6,
},
{
name: 'XiAn',
id: 7,
},
{
name: 'TianJin',
id: 8,
},
{
name: 'WuHan',
id: 9,
},
{
name: 'ChangSha',
id: 10,
},
{
name: 'ChongQin',
id: 11,
},
{
name: 'SuZhou',
id: 12,
},
{
name: 'NanJing',
id: 13,
},
],
},
{
num: 'Three',
list: [
{
name: 'XiNing',
id: 14,
},
{
name: 'LanZhou',
id: 15,
},
{
name: 'ShiJiaZhuang',
id: 16,
},
{
name: 'QinHuangDao',
id: 17,
},
{
name: 'DaLian',
id: 18,
},
{
name: 'HaErBin',
id: 19,
},
{
name: 'ChangChun',
id: 20,
},
{
name: 'TaiYuan',
id: 21,
},
],
},
]
const clickItem = (key: string, item: any) => {
console.log(key, JSON.stringify(item))
}
const clickIndex = (key: string) => {
console.log(key)
}
return (
<Elevator
indexList={dataList}
height="220"
acceptKey="num"
clickItem={(key: string, item: any) => clickItem(key, item)}
clickIndex={(key: string) => clickIndex(key)}
/>
)
}
export default App
```
:::
### Index ceiling
:::demo
```tsx
import React from "react";
import { Elevator } from '@nutui/nutui-react';
import React from 'react'
import { Elevator } from '@nutui/nutui-react'
const App = () => {
const dataList = [
{
num: '',
list: [
{
name: '北京',
id: 1,
},
{
name: '上海',
id: 2,
},
{
name: '深圳',
id: 3,
},
{
name: '广州',
id: 4,
},
{
name: '杭州',
id: 5,
},
],
},
{
num: '',
list: [
{
name: '成都',
id: 6,
},
{
name: '西安',
id: 7,
},
{
name: '天津',
id: 8,
},
{
name: '武汉',
id: 9,
},
{
name: '长沙',
id: 10,
},
{
name: '重庆',
id: 11,
},
{
name: '苏州',
id: 12,
},
{
name: '南京',
id: 13,
},
],
},
{
num: '',
list: [
{
name: '西宁',
id: 14,
},
{
name: '兰州',
id: 15,
},
{
name: '石家庄',
id: 16,
},
{
name: '秦皇岛',
id: 17,
},
{
name: '大连',
id: 18,
},
{
name: '哈尔滨',
id: 19,
},
{
name: '长春',
id: 20,
},
{
name: '太原',
id: 21,
},
],
},
]
const clickItem = (key: string, item: any) => {
console.log(key, JSON.stringify(item))
const dataList = [
{
title: 'A',
list: [
{
name: 'AnHui',
id: 1,
},
],
},
{
title: 'B',
list: [
{
name: 'BeiJing',
id: 2,
},
],
},
{
title: 'C',
list: [
{
name: 'ChongQin',
id: 3,
},
],
},
{
title: 'F',
list: [
{
name: 'FuJian',
id: 4,
},
],
},
{
title: 'G',
list: [
{
name: 'GuangXi',
id: 5,
},
{
name: 'GuangDong',
id: 6,
},
{
name: 'GanSu',
id: 7,
},
{
name: 'GuiZhou',
id: 8,
},
],
},
{
title: 'H',
list: [
{
name: 'HuNan',
id: 9,
},
{
name: 'HuBei',
id: 10,
},
{
name: 'HaiNan',
id: 11,
},
{
name: 'HeBei',
id: 12,
},
{
name: 'HeNan',
id: 13,
},
{
name: 'HeiLongJiang',
id: 14,
},
],
},
{
title: 'J',
list: [
{
name: 'JiLin',
id: 15,
},
{
name: 'JiangSu',
id: 16,
},
{
name: 'JiangXi',
id: 17,
},
],
},
{
title: 'L',
list: [
{
name: 'LiaoNing',
id: 18,
},
],
},
]
const clickItem = (key: string, item: any) => {
console.log(key, JSON.stringify(item))
}
const clickIndex = (key: string) => {
console.log(key)
}
return (
<Elevator
indexList={dataList}
height="220"
isSticky
clickItem={(key: string, item: any) => clickItem(key, item)}
clickIndex={(key: string) => clickIndex(key)}
/>
)
}
export default App
```
:::
const clickIndex = (key: string) => {
console.log(key)
### Custom Content
:::demo
```tsx
import React from 'react'
import { Elevator, elevatorContext, Icon } from '@nutui/nutui-react'
const App = () => {
const dataList = [
{
title: 'A',
list: [
{
name: 'AnHui',
id: 1,
},
],
},
{
title: 'B',
list: [
{
name: 'BeiJing',
id: 2,
},
],
},
{
title: 'G',
list: [
{
name: 'GuangXi',
id: 3,
},
{
name: 'GuangDong',
id: 4,
},
],
},
{
title: 'H',
list: [
{
name: 'HuNan',
id: 5,
},
{
name: 'HuBei',
id: 6,
},
{
name: 'Henan',
id: 7,
},
],
},
]
const clickItem = (key: string, item: any) => {
console.log(key, JSON.stringify(item))
}
const clickIndex = (key: string) => {
console.log(key)
}
return (
<Elevator
indexList={dataList}
height="260"
clickItem={(key: string, item: any) => clickItem(key, item)}
clickIndex={(key: string) => clickIndex(key)}
>
<elevatorContext.Consumer>
{(value) => {
return (
<>
<Icon name="JD" size="12" />
<span style={{ marginLeft: '15px' }}>{value?.name}</span>
</>
)
}}
</elevatorContext.Consumer>
</Elevator>
)
}
return (
<Elevator
indexList={dataList}
height="220"
acceptKey="num"
clickItem={(key: string, item: any) => clickItem(key, item)}
clickIndex={(key: string) => clickIndex(key)}
/>
);
};
export default App;
export default App
```
:::
## API
### Props
| 字段 | 说明 | 类型 | 默认值 |
| --------- | -------------- | ----------------------------------------------------------- | --------------------- |
| height | 电梯区域的高度 | Number、String | `200px` |
| acceptKey | 索引 key 值 | String | `title` |
| indexList | 索引列表 | Array(item 需包含 id、name 属性, name 支持传入 html 结构) | `[{id: 0, name: ''}]` |
| Attribute | Description | Type | Default |
|------------------------|----------------------------------------------------------------|---------|------|
| height | Height of elevator area | Number、String | `200px`
| acceptKey | Index key value | String | `title` |
| indexList | Index list | Array(`item` needs to contain `id` and `name` attributes, and `name` supports passing in `html` structure) | `[{id: 0, name: ''}]` |
| isSticky | Whether the index is ceiling | Boolean | `false` |
| spaceHeight | Up and down spacing of right anchor point | Number | `23` |
| titleHeight | Height of left index | Number | `35` |
### Event
| 名称 | 说明 | 回调参数 |
| ---------- | -------- | -------------------------------------- |
| clickItem | 点击内容 | key: string, item: { id: 0, name: '' } |
| clickIndex | 点击索引 | key: string |
| Event | Description | Arguments |
|-------|----------|-------------|
| click-item | Click content | key: string, item: { id: 0, name: '' } |
| click-index | Click index | key: string |
......@@ -12,221 +12,459 @@ import { Elevator } from '@nutui/nutui-react'
## 代码演示
### 基用法
### 基用法
:::demo
```tsx
import React from "react";
import { Elevator } from '@nutui/nutui-react';
import React from 'react'
import { Elevator } from '@nutui/nutui-react'
const App = () => {
const dataList = [
{
title: 'A',
list: [
{
name: '安徽',
id: 1,
},
],
},
{
title: 'B',
list: [
{
name: '北京',
id: 2,
},
],
},
{
title: 'G',
list: [
{
name: '广西',
id: 3,
},
{
name: '广东',
id: 4,
},
],
},
{
title: 'H',
list: [
{
name: '湖南',
id: 5,
},
{
name: '湖北',
id: 6,
},
,
{
name: '琥珀',
id: 7,
},
],
},
]
const clickItem = (key: string, item: any) => {
console.log(key, JSON.stringify(item))
}
const dataList = [
{
title: 'A',
list: [
{
name: '安徽',
id: 1,
},
],
},
{
title: 'B',
list: [
{
name: '北京',
id: 2,
},
],
},
{
title: 'G',
list: [
{
name: '广西',
id: 3,
},
{
name: '广东',
id: 4,
},
],
},
{
title: 'H',
list: [
{
name: '湖南',
id: 5,
},
{
name: '湖北',
id: 6,
},
{
name: '河南',
id: 7,
},
],
},
]
const clickItem = (key: string, item: any) => {
console.log(key, JSON.stringify(item))
}
const clickIndex = (key: string) => {
console.log(key)
const clickIndex = (key: string) => {
console.log(key)
}
return (
<Elevator
indexList={dataList}
height="260"
clickItem={(key: string, item: any) => clickItem(key, item)}
clickIndex={(key: string) => clickIndex(key)}
/>
)
}
return (
<Elevator
indexList={dataList}
height="260"
clickItem={(key: string, item: any) => clickItem(key, item)}
clickIndex={(key: string) => clickIndex(key)}
/>
);
};
export default App;
export default App
```
:::
### 自定义索引
## API
:::demo
```tsx
import React from "react";
import { Elevator } from '@nutui/nutui-react';
import React from 'react'
import { Elevator } from '@nutui/nutui-react'
const App = () => {
const dataList = [
{
num: '',
list: [
{
name: '北京',
id: 1,
},
{
name: '上海',
id: 2,
},
{
name: '深圳',
id: 3,
},
{
name: '广州',
id: 4,
},
{
name: '杭州',
id: 5,
},
],
},
{
num: '',
list: [
{
name: '成都',
id: 6,
},
{
name: '西安',
id: 7,
},
{
name: '天津',
id: 8,
},
{
name: '武汉',
id: 9,
},
{
name: '长沙',
id: 10,
},
{
name: '重庆',
id: 11,
},
{
name: '苏州',
id: 12,
},
{
name: '南京',
id: 13,
},
],
},
{
num: '',
list: [
{
name: '西宁',
id: 14,
},
{
name: '兰州',
id: 15,
},
{
name: '石家庄',
id: 16,
},
{
name: '秦皇岛',
id: 17,
},
{
name: '大连',
id: 18,
},
{
name: '哈尔滨',
id: 19,
},
{
name: '长春',
id: 20,
},
{
name: '太原',
id: 21,
},
],
},
]
const clickItem = (key: string, item: any) => {
console.log(key, JSON.stringify(item))
}
const clickIndex = (key: string) => {
console.log(key)
}
return (
<Elevator
indexList={dataList}
height="220"
acceptKey="num"
clickItem={(key: string, item: any) => clickItem(key, item)}
clickIndex={(key: string) => clickIndex(key)}
/>
)
}
export default App
```
:::
### 吸顶索引
:::demo
```tsx
import React from 'react'
import { Elevator } from '@nutui/nutui-react'
const App = () => {
const dataList = [
{
num: '',
list: [
{
name: '北京',
id: 1,
},
{
name: '上海',
id: 2,
},
{
name: '深圳',
id: 3,
},
{
name: '广州',
id: 4,
},
{
name: '杭州',
id: 5,
},
],
},
{
num: '',
list: [
{
name: '成都',
id: 6,
},
{
name: '西安',
id: 7,
},
{
name: '天津',
id: 8,
},
{
name: '武汉',
id: 9,
},
{
name: '长沙',
id: 10,
},
{
name: '重庆',
id: 11,
},
{
name: '苏州',
id: 12,
},
{
name: '南京',
id: 13,
},
],
},
{
num: '',
list: [
{
name: '西宁',
id: 14,
},
{
name: '兰州',
id: 15,
},
{
name: '石家庄',
id: 16,
},
{
name: '秦皇岛',
id: 17,
},
{
name: '大连',
id: 18,
},
{
name: '哈尔滨',
id: 19,
},
{
name: '长春',
id: 20,
},
{
name: '太原',
id: 21,
},
],
},
]
const clickItem = (key: string, item: any) => {
console.log(key, JSON.stringify(item))
const dataList = [
{
title: 'A',
list: [
{
name: '安徽',
id: 1,
},
],
},
{
title: 'B',
list: [
{
name: '北京',
id: 2,
},
],
},
{
title: 'C',
list: [
{
name: '重庆',
id: 3,
},
],
},
{
title: 'F',
list: [
{
name: '福建',
id: 4,
},
],
},
{
title: 'G',
list: [
{
name: '广西',
id: 5,
},
{
name: '广东',
id: 6,
},
{
name: '甘肃',
id: 7,
},
{
name: '贵州',
id: 8,
},
],
},
{
title: 'H',
list: [
{
name: '湖南',
id: 9,
},
{
name: '湖北',
id: 10,
},
{
name: '海南',
id: 11,
},
{
name: '河北',
id: 12,
},
{
name: '河南',
id: 13,
},
{
name: '黑龙江',
id: 14,
},
],
},
{
title: 'J',
list: [
{
name: '吉林',
id: 15,
},
{
name: '江苏',
id: 16,
},
{
name: '江西',
id: 17,
},
],
},
{
title: 'L',
list: [
{
name: '辽宁',
id: 18,
},
],
},
]
const clickItem = (key: string, item: any) => {
console.log(key, JSON.stringify(item))
}
const clickIndex = (key: string) => {
console.log(key)
}
return (
<Elevator
indexList={dataList}
height="220"
isSticky
clickItem={(key: string, item: any) => clickItem(key, item)}
clickIndex={(key: string) => clickIndex(key)}
/>
)
}
export default App
```
:::
### 自定义内容
const clickIndex = (key: string) => {
console.log(key)
:::demo
```tsx
import React from 'react'
import { Elevator, elevatorContext, Icon } from '@nutui/nutui-react'
const App = () => {
const dataList = [
{
title: 'A',
list: [
{
name: '安徽',
id: 1,
},
],
},
{
title: 'B',
list: [
{
name: '北京',
id: 2,
},
],
},
{
title: 'G',
list: [
{
name: '广西',
id: 3,
},
{
name: '广东',
id: 4,
},
],
},
{
title: 'H',
list: [
{
name: '湖南',
id: 5,
},
{
name: '湖北',
id: 6,
},
{
name: '河南',
id: 7,
},
],
},
]
const clickItem = (key: string, item: any) => {
console.log(key, JSON.stringify(item))
}
const clickIndex = (key: string) => {
console.log(key)
}
return (
<Elevator
indexList={dataList}
height="260"
clickItem={(key: string, item: any) => clickItem(key, item)}
clickIndex={(key: string) => clickIndex(key)}
>
<elevatorContext.Consumer>
{(value) => {
return (
<>
<Icon name="JD" size="12" />
<span style={{ marginLeft: '15px' }}>{value?.name}</span>
</>
)
}}
</elevatorContext.Consumer>
</Elevator>
)
}
return (
<Elevator
indexList={dataList}
height="220"
acceptKey="num"
clickItem={(key: string, item: any) => clickItem(key, item)}
clickIndex={(key: string) => clickIndex(key)}
/>
);
};
export default App;
export default App
```
:::
## API
### Props
| 字段 | 说明 | 类型 | 默认值 |
......@@ -234,6 +472,9 @@ export default App;
| height | 电梯区域的高度 | Number、String | `200px` |
| acceptKey | 索引 key 值 | String | `title` |
| indexList | 索引列表 | Array(item 需包含 id、name 属性, name 支持传入 html 结构) | `[{id: 0, name: ''}]` |
| isSticky | 索引是否吸顶 | Boolean | `false` |
| spaceHeight | 右侧锚点的上下间距 | Number | `23` |
| titleHeight | 左侧索引的高度 | Number | `35` |
### Event
......
# Elevator 电梯楼层
# Elevator 電梯樓層
### 介
### 介
用于列表快速定位以及索引的
用于列表快速定位以及索引的
### 安
### 安
```javascript
import { Elevator } from '@nutui/nutui-react'
```
## 代演示
## 代演示
### 基用法
### 基用法
:::demo
```tsx
import React from "react";
import { Elevator } from '@nutui/nutui-react';
import React from 'react'
import { Elevator } from '@nutui/nutui-react'
const App = () => {
const dataList = [
{
title: 'A',
list: [
{
name: '安徽',
id: 1,
},
],
},
{
title: 'B',
list: [
{
name: '北京',
id: 2,
},
],
},
{
title: 'G',
list: [
{
name: '广西',
id: 3,
},
{
name: '广东',
id: 4,
},
],
},
{
title: 'H',
list: [
{
name: '湖南',
id: 5,
},
{
name: '湖北',
id: 6,
},
,
{
name: '琥珀',
id: 7,
},
],
},
]
const clickItem = (key: string, item: any) => {
console.log(key, JSON.stringify(item))
}
const dataList = [
{
title: 'A',
list: [
{
name: '安徽',
id: 1,
},
],
},
{
title: 'B',
list: [
{
name: '北京',
id: 2,
},
],
},
{
title: 'G',
list: [
{
name: '廣西',
id: 3,
},
{
name: '廣東',
id: 4,
},
],
},
{
title: 'H',
list: [
{
name: '湖南',
id: 5,
},
{
name: '湖北',
id: 6,
},
{
name: '河南',
id: 7,
},
],
},
]
const clickItem = (key: string, item: any) => {
console.log(key, JSON.stringify(item))
}
const clickIndex = (key: string) => {
console.log(key)
const clickIndex = (key: string) => {
console.log(key)
}
return (
<Elevator
indexList={dataList}
height="260"
clickItem={(key: string, item: any) => clickItem(key, item)}
clickIndex={(key: string) => clickIndex(key)}
/>
)
}
return (
<Elevator
indexList={dataList}
height="260"
clickItem={(key: string, item: any) => clickItem(key, item)}
clickIndex={(key: string) => clickIndex(key)}
/>
);
};
export default App;
export default App
```
:::
### 自定索引
### 自定索引
## API
:::demo
```tsx
import React from "react";
import { Elevator } from '@nutui/nutui-react';
import React from 'react'
import { Elevator } from '@nutui/nutui-react'
const App = () => {
const dataList = [
{
num: '',
list: [
{
name: '北京',
id: 1,
},
{
name: '上海',
id: 2,
},
{
name: '深圳',
id: 3,
},
{
name: '广州',
id: 4,
},
{
name: '杭州',
id: 5,
},
],
},
{
num: '',
list: [
{
name: '成都',
id: 6,
},
{
name: '西安',
id: 7,
},
{
name: '天津',
id: 8,
},
{
name: '武汉',
id: 9,
},
{
name: '长沙',
id: 10,
},
{
name: '重庆',
id: 11,
},
{
name: '苏州',
id: 12,
},
{
name: '南京',
id: 13,
},
],
},
{
num: '',
list: [
{
name: '西宁',
id: 14,
},
{
name: '兰州',
id: 15,
},
{
name: '石家庄',
id: 16,
},
{
name: '秦皇岛',
id: 17,
},
{
name: '大连',
id: 18,
},
{
name: '哈尔滨',
id: 19,
},
{
name: '长春',
id: 20,
},
{
name: '太原',
id: 21,
},
],
},
]
const clickItem = (key: string, item: any) => {
console.log(key, JSON.stringify(item))
const dataList = [
{
num: '',
list: [
{
name: '北京',
id: 1,
},
{
name: '上海',
id: 2,
},
{
name: '深圳',
id: 3,
},
{
name: '廣州',
id: 4,
},
{
name: '杭州',
id: 5,
},
],
},
{
num: '',
list: [
{
name: '成都',
id: 6,
},
{
name: '西安',
id: 7,
},
{
name: '天津',
id: 8,
},
{
name: '武漢',
id: 9,
},
{
name: '長沙',
id: 10,
},
{
name: '重慶',
id: 11,
},
{
name: '蘇州',
id: 12,
},
{
name: '南京',
id: 13,
},
],
},
{
num: '',
list: [
{
name: '西甯',
id: 14,
},
{
name: '蘭州',
id: 15,
},
{
name: '石家莊',
id: 16,
},
{
name: '秦皇島',
id: 17,
},
{
name: '大連',
id: 18,
},
{
name: '哈爾濱',
id: 19,
},
{
name: '長春',
id: 20,
},
{
name: '太原',
id: 21,
},
],
},
]
const clickItem = (key: string, item: any) => {
console.log(key, JSON.stringify(item))
}
const clickIndex = (key: string) => {
console.log(key)
}
return (
<Elevator
indexList={dataList}
height="220"
acceptKey="num"
clickItem={(key: string, item: any) => clickItem(key, item)}
clickIndex={(key: string) => clickIndex(key)}
/>
)
}
export default App
```
:::
### 吸頂索引
:::demo
```tsx
import React from 'react'
import { Elevator } from '@nutui/nutui-react'
const App = () => {
const dataList = [
{
title: 'A',
list: [
{
name: '安徽',
id: 1,
},
],
},
{
title: 'B',
list: [
{
name: '北京',
id: 2,
},
],
},
{
title: 'C',
list: [
{
name: '重慶',
id: 3,
},
],
},
{
title: 'F',
list: [
{
name: '福建',
id: 4,
},
],
},
{
title: 'G',
list: [
{
name: '廣西',
id: 5,
},
{
name: '廣東',
id: 6,
},
{
name: '甘肅',
id: 7,
},
{
name: '貴州',
id: 8,
},
],
},
{
title: 'H',
list: [
{
name: '湖南',
id: 9,
},
{
name: '湖北',
id: 10,
},
{
name: '海南',
id: 11,
},
{
name: '河北',
id: 12,
},
{
name: '河南',
id: 13,
},
{
name: '黑龍江',
id: 14,
},
],
},
{
title: 'J',
list: [
{
name: '吉林',
id: 15,
},
{
name: '江蘇',
id: 16,
},
{
name: '江西',
id: 17,
},
],
},
{
title: 'L',
list: [
{
name: '遼甯',
id: 18,
},
],
},
]
const clickItem = (key: string, item: any) => {
console.log(key, JSON.stringify(item))
}
const clickIndex = (key: string) => {
console.log(key)
const clickIndex = (key: string) => {
console.log(key)
}
return (
<Elevator
indexList={dataList}
height="220"
isSticky
clickItem={(key: string, item: any) => clickItem(key, item)}
clickIndex={(key: string) => clickIndex(key)}
/>
)
}
return (
<Elevator
indexList={dataList}
height="220"
acceptKey="num"
clickItem={(key: string, item: any) => clickItem(key, item)}
clickIndex={(key: string) => clickIndex(key)}
/>
);
};
export default App;
export default App
```
:::
### 自定義內容
:::demo
```tsx
import React from 'react'
import { Elevator, elevatorContext, Icon } from '@nutui/nutui-react'
const App = () => {
const dataList = [
{
title: 'A',
list: [
{
name: '安徽',
id: 1,
},
],
},
{
title: 'B',
list: [
{
name: '北京',
id: 2,
},
],
},
{
title: 'G',
list: [
{
name: '廣西',
id: 3,
},
{
name: '廣東',
id: 4,
},
],
},
{
title: 'H',
list: [
{
name: '湖南',
id: 5,
},
{
name: '湖北',
id: 6,
},
{
name: '河南',
id: 7,
},
],
},
]
const clickItem = (key: string, item: any) => {
console.log(key, JSON.stringify(item))
}
const clickIndex = (key: string) => {
console.log(key)
}
return (
<Elevator
indexList={dataList}
height="260"
clickItem={(key: string, item: any) => clickItem(key, item)}
clickIndex={(key: string) => clickIndex(key)}
>
<elevatorContext.Consumer>
{(value) => {
return (
<>
<Icon name="JD" size="12" />
<span style={{ marginLeft: '15px' }}>{value?.name}</span>
</>
)
}}
</elevatorContext.Consumer>
</Elevator>
)
}
export default App
```
:::
## API
### Props
| 字段 | 说明 | 类型 | 默认值 |
| 字段 | 說明 | 類型 | 默認值 |
| --------- | -------------- | ----------------------------------------------------------- | --------------------- |
| height | 电梯区域的高度 | Number、String | `200px` |
| height | 電梯區域的高度 | Number、String | `200px` |
| acceptKey | 索引 key 值 | String | `title` |
| indexList | 索引列表 | Array(item 需包含 id、name 属性, name 支持传入 html 结构) | `[{id: 0, name: ''}]` |
| indexList | 索引列表 | Array(item 需包含 id、name 屬性, name 支持傳入 html 結構) | `[{id: 0, name: ''}]` |
| isSticky | 索引是否吸頂 | Boolean | `false` |
| spaceHeight | 右側錨點的上下間距 | Number | `23` |
| titleHeight | 左側索引的高度 | Number | `35` |
### Event
| 名称 | 说明 | 回调参数 |
| 名稱 | 說明 | 回調參數 |
| ---------- | -------- | -------------------------------------- |
| clickItem | 点击内容 | key: string, item: { id: 0, name: '' } |
| clickIndex | 点击索引 | key: string |
| clickItem | 點擊內容 | key: string, item: { id: 0, name: '' } |
| clickIndex | 點擊索引 | key: string |
......@@ -2,69 +2,101 @@
width: 100%;
display: block;
position: relative;
overflow: hidden;
&__list {
display: block;
overflow: auto;
position: relative;
top: 1px;
overflow: hidden;
&__inner {
height: 100%;
width: 100%;
display: block;
overflow: auto;
}
&__item {
display: block;
font-size: 12px;
color: #333;
font-size: $elevator-list-item-font-size;
color: $elevator-list-item-font-color;
&__code {
display: inline-flex;
display: flex;
position: relative;
height: 35px;
line-height: 35px;
font-size: 14px;
color: #1a1a1a;
padding: 0 20px;
font-weight: 500;
height: $elevator-list-item-code-height;
line-height: $elevator-list-item-code-line-height;
font-size: $elevator-list-item-code-font-size;
color: $elevator-list-item-code-font-color;
padding: $elevator-list-item-code-padding;
font-weight: $elevator-list-item-code-font-weight;
box-sizing: border-box;
&::after {
content: ' ';
width: 100%;
height: 1px;
width: $elevator-list-item-code-after-width;
height: $elevator-list-item-code-after-height;
position: absolute;
left: 0;
bottom: 7px;
background-color: #eeeff2;
bottom: 0;
background-color: $elevator-list-item-code-after-bg-color;
}
}
&__name {
display: flex;
align-items: center;
padding: 0 20px;
height: 30px;
line-height: 30px;
padding: $elevator-list-item-name-padding;
height: $elevator-list-item-name-height;
line-height: $elevator-list-item-name-line-height;
&--highcolor {
color: $elevator-list-item-highcolor;
}
}
}
&__fixed {
width: 100%;
position: absolute;
top: 0;
left: 0;
z-index: 1;
padding: $elevator-list-item-code-padding;
height: $elevator-list-item-code-height;
line-height: $elevator-list-item-code-line-height;
font-size: $elevator-list-item-code-font-size;
color: $elevator-list-fixed-color;
font-weight: $elevator-list-item-code-font-weight;
background-color: $elevator-list-fixed-bg-color;
box-sizing: border-box;
box-shadow: $elevator-list-fixed-box-shadow;
}
}
&__code--current {
position: absolute;
right: 60px;
top: 50%;
transform: translateY(-50%);
width: 45px;
height: 45px;
line-height: 45px;
border-radius: 50%;
background: $white;
box-shadow: 0 3px 3px 1px rgba(240, 240, 240, 1);
text-align: center;
position: $elevator-list-item-code-current-position;
right: $elevator-list-item-code-current-right;
top: $elevator-list-item-code-current-top;
transform: $elevator-list-item-code-current-transform;
width: $elevator-list-item-code-current-width;
height: $elevator-list-item-code-current-height;
line-height: $elevator-list-item-code-current-line-height;
border-radius: $elevator-list-item-code-current-border-radius;
background: $elevator-list-item-code-current-bg-color;
box-shadow: $elevator-list-item-code-current-box-shadow;
text-align: $elevator-list-item-code-current-text-align;
}
&__bars {
position: absolute;
right: 8px;
top: 50%;
transform: translateY(-50%);
padding: 15px 0;
background-color: #eeeff2;
border-radius: 6px;
text-align: center;
z-index: 10;
position: $elevator-list-item-bars-position;
right: $elevator-list-item-bars-right;
top: $elevator-list-item-bars-top;
transform: $elevator-list-item-bars-transform;
padding: $elevator-list-item-bars-padding;
background-color: $elevator-list-item-bars-background-color;
border-radius: $elevator-list-item-bars-border-radius;
text-align: $elevator-list-item-bars-text-align;
z-index: $elevator-list-item-bars-z-index;
&__inner {
&__item {
display: block;
padding: 3px;
font-size: 10px;
padding: $elevator-list-item-bars-inner-item-padding;
font-size: $elevator-list-item-bars-inner-item-font-size;
&--active {
color: $elevator-list-item-bars-inner-item-active-color;
}
}
}
}
......
import React, { FunctionComponent, useRef, useEffect, useState } from 'react'
import React, {
FunctionComponent,
useRef,
useEffect,
useState,
createContext,
} from 'react'
import bem from '@/utils/bem'
export const elevatorContext = createContext({} as ElevatorData)
export interface ElevatorProps {
height: number | string
acceptKey: string
indexList: any
indexList: any[]
isSticky: boolean
spaceHeight: number
titleHeight: number
className: string
style: React.CSSProperties
children: React.ReactNode
clickItem: (key: string, item: ElevatorData) => void
clickIndex: (key: string) => void
}
const defaultProps = {
height: '200px',
acceptKey: 'title',
indexList: [],
indexList: [] as any[],
isSticky: false,
spaceHeight: 23,
titleHeight: 35,
className: '',
} as ElevatorProps
interface ElevatorData {
......@@ -28,38 +43,48 @@ export const Elevator: FunctionComponent<
height,
acceptKey,
indexList,
isSticky,
spaceHeight,
titleHeight,
className,
clickItem,
clickIndex,
children,
...rest
} = {
...defaultProps,
...props,
}
const b = bem('elevator')
const spaceHeight = 23
const listview = useRef<HTMLDivElement>(null)
const initData = {
anchorIndex: 0,
listHeight: [] as number[],
listGroup: [] as Element[],
scrollY: 0,
diff: -1,
fixedTop: 0,
}
const touchState = useRef({
y1: 0,
y2: 0,
})
const [scrollY, setScrollY] = useState(0)
const [currentData, setCurrentData] = useState<ElevatorData>(
{} as ElevatorData
)
const [currentKey, setCurrentKey] = useState('')
const [currentIndex, setCurrentIndex] = useState<number>(0)
const [codeIndex, setCodeIndex] = useState<number>(0)
const [scrollStart, setScrollStart] = useState<boolean>(false)
const state = useRef(initData)
// 重置滚动参数
const resetScrollState = () => {
state.current.anchorIndex = 0
setCurrentIndex(0)
setScrollStart(false)
touchState.current = {
y1: 0,
y2: 0,
}
}
const clientHeight = () => {
return listview.current ? listview.current.clientHeight : 0
}
const getData = (el: HTMLElement, name: string): string | void => {
......@@ -86,14 +111,18 @@ export const Elevator: FunctionComponent<
if (!state.current.listHeight.length) {
calculateHeight()
}
if (index < 0) index = 0
let cacheIndex = index
if (index < 0) {
cacheIndex = 0
}
if (index > state.current.listHeight.length - 2)
index = state.current.listHeight.length - 2
if (index > state.current.listHeight.length - 2) {
cacheIndex = state.current.listHeight.length - 2
}
setCurrentIndex(index)
setCodeIndex(cacheIndex)
if (listview.current) {
listview.current.scrollTo(0, state.current.listHeight[index])
listview.current.scrollTo(0, state.current.listHeight[cacheIndex])
}
}
......@@ -101,10 +130,9 @@ export const Elevator: FunctionComponent<
const firstTouch = e.touches[0]
touchState.current.y2 = firstTouch.pageY
const delta =
((touchState.current.y2 - touchState.current.y1) / spaceHeight) | 0
(touchState.current.y2 - touchState.current.y1) / spaceHeight || 0
const cacheIndex = state.current.anchorIndex + delta
setCurrentIndex(cacheIndex)
setCodeIndex(cacheIndex)
scrollTo(cacheIndex)
}
......@@ -118,7 +146,7 @@ export const Elevator: FunctionComponent<
const firstTouch = e.touches[0]
touchState.current.y1 = firstTouch.pageY
state.current.anchorIndex = +index
setCurrentIndex((currentIndex) => currentIndex + index)
setCodeIndex((codeIndex) => codeIndex + index)
scrollTo(index)
const target = e.currentTarget as HTMLElement
target.removeEventListener('touchend', touchEnd, false)
......@@ -127,6 +155,8 @@ export const Elevator: FunctionComponent<
const handleClickItem = (key: string, item: ElevatorData) => {
clickItem && clickItem(key, item)
setCurrentData(item)
setCurrentKey(key)
}
const handleClickIndex = (key: string) => {
......@@ -144,44 +174,101 @@ export const Elevator: FunctionComponent<
})
}
}
const listViewScroll = (e: Event) => {
const { listHeight } = state.current
if (!listHeight.length) {
calculateHeight()
}
const target = e.target as Element
const { scrollTop } = target
state.current.scrollY = scrollTop
setScrollY(scrollTop)
for (let i = 0; i < listHeight.length - 1; i++) {
const height1 = listHeight[i]
const height2 = listHeight[i + 1]
if (state.current.scrollY >= height1 && state.current.scrollY < height2) {
setCurrentIndex(i)
state.current.diff = height2 - state.current.scrollY
return
}
}
setCurrentIndex(listHeight.length - 2)
}
useEffect(() => {
if (listview.current) {
setListGroup()
listview.current.addEventListener('scroll', listViewScroll)
}
}, [listview])
useEffect(() => {
const { listHeight, diff, scrollY } = state.current
let fixedTop = diff > 0 && diff < titleHeight ? diff - titleHeight : 0
if (scrollY + clientHeight() === listHeight[listHeight.length - 1]) {
if (fixedTop !== 0) {
fixedTop = 0
}
}
}, [listview.current])
if (state.current.fixedTop === fixedTop) return
state.current.fixedTop = fixedTop
}, [state.current.diff, titleHeight])
return (
<div className={`${b()} ${className}`} {...rest}>
{isSticky && scrollY > 0 ? (
<div className={b('list__fixed')}>
<span className="fixed-title">
{indexList[currentIndex][acceptKey]}
</span>
</div>
) : null}
<div
className={b('list')}
ref={listview}
style={{ height: isNaN(+height) ? height : `${height}px` }}
style={{ height: Number.isNaN(+height) ? height : `${height}px` }}
>
{indexList.map((item: any) => {
return (
<div className={b('list__item')} key={item[acceptKey]}>
<div className={b('list__item__code')}>{item[acceptKey]}</div>
<>
{item.list.map((subitem: any) => {
return (
<div
className={b('list__item__name')}
key={subitem.id}
onClick={() => handleClickItem(item[acceptKey], subitem)}
>
{subitem.name}
</div>
)
})}
</>
</div>
)
})}
<div className={b('list__inner')} ref={listview}>
{indexList.map((item: any, idx: number) => {
return (
<div className={b('list__item')} key={idx}>
<div className={b('list__item__code')}>{item[acceptKey]}</div>
<>
{item.list.map((subitem: ElevatorData) => {
return (
<div
className={b('list__item__name', {
highcolor:
currentData.id === subitem.id &&
currentKey === item[acceptKey],
})}
key={subitem.id}
onClick={() =>
handleClickItem(item[acceptKey], subitem)
}
>
{children ? (
<>
<elevatorContext.Provider value={subitem}>
{children}
</elevatorContext.Provider>
</>
) : (
subitem.name
)}
</div>
)
})}
</>
</div>
)
})}
</div>
</div>
{indexList.length && scrollStart ? (
<div className={b('code', { current: true })}>
{' '}
{indexList[currentIndex][acceptKey]}
<div className={b('code--current', { current: true })}>
{indexList[codeIndex][acceptKey]}
</div>
) : null}
<div
......@@ -193,9 +280,12 @@ export const Elevator: FunctionComponent<
{indexList.map((item: any, index: number) => {
return (
<div
className={b('bars__inner__item')}
className={b('bars__inner__item', {
active:
item[acceptKey] === indexList[currentIndex][acceptKey],
})}
data-index={index}
key={item[acceptKey]}
key={index}
onClick={() => handleClickIndex(item[acceptKey])}
>
{item[acceptKey]}
......
......@@ -477,6 +477,50 @@ $divider-vertical-top: 2px !default;
$divider-vertical-border-left: rgba(0, 0, 0, 0.06) !default;
$divider-vertical-margin: 0 8px !default;
// elevator
$elevator-list-item-highcolor: $primary-color !default;
$elevator-list-item-font-size: 12px !default;
$elevator-list-item-font-color: #333333 !default;
$elevator-list-item-name-padding: 0 20px !default;
$elevator-list-item-name-height: 30px !default;
$elevator-list-item-name-line-height: 30px !default;
$elevator-list-item-code-font-size: 14px !default;
$elevator-list-item-code-font-color: #1a1a1a !default;
$elevator-list-item-code-font-weight: 500 !default;
$elevator-list-item-code-padding: 0 20px !default;
$elevator-list-item-code-height: 35px !default;
$elevator-list-item-code-line-height: 35px !default;
$elevator-list-item-code-after-width: 100% !default;
$elevator-list-item-code-after-height: 1px !default;
$elevator-list-item-code-after-bg-color: #f5f5f5 !default;
$elevator-list-item-code-current-box-shadow: 0 3px 3px 1px
rgba(240, 240, 240, 1) !default;
$elevator-list-item-code-current-bg-color: #fff !default;
$elevator-list-item-code-current-border-radius: 50% !default;
$elevator-list-item-code-current-width: 45px !default;
$elevator-list-item-code-current-height: 45px !default;
$elevator-list-item-code-current-line-height: 45px !default;
$elevator-list-item-code-current-position: absolute !default;
$elevator-list-item-code-current-right: 60px !default;
$elevator-list-item-code-current-top: 50% !default;
$elevator-list-item-code-current-transform: translateY(-50%) !default;
$elevator-list-item-code-current-text-align: center !default;
$elevator-list-item-bars-position: absolute !default;
$elevator-list-item-bars-right: 8px !default;
$elevator-list-item-bars-top: 50% !default;
$elevator-list-item-bars-transform: translateY(-50%) !default;
$elevator-list-item-bars-padding: 15px 0 !default;
$elevator-list-item-bars-background-color: #eeeff2 !default;
$elevator-list-item-bars-border-radius: 6px !default;
$elevator-list-item-bars-text-align: center !default;
$elevator-list-item-bars-z-index: 1 !default;
$elevator-list-item-bars-inner-item-padding: 3px !default;
$elevator-list-item-bars-inner-item-font-size: 10px !default;
$elevator-list-fixed-color: $primary-color !default;
$elevator-list-fixed-bg-color: $white !default;
$elevator-list-fixed-box-shadow: 0 0 10px #eee !default;
$elevator-list-item-bars-inner-item-active-color: $primary-color !default;
//navbar
$navbar-height: 44px !default;
$navbar-margin-bottom: 20px !default;
......@@ -499,3 +543,4 @@ $row-content-border-radius: 6px !default;
$row-content-height: 50px !default;
$row-content-line-height: 40px !default;
$col-default-margin-bottom: 15px !default;
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册