@douyinfe/semi-ui 2.3.1 → 2.5.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cascader/__test__/cascader.test.js +24 -0
- package/cascader/_story/cascader.stories.js +73 -0
- package/cascader/index.tsx +5 -2
- package/datePicker/_story/RenderDate/index.js +13 -3
- package/datePicker/_story/RenderFullDate/index.js +36 -14
- package/datePicker/_story/RenderFullDate/index.scss +1 -1
- package/datePicker/_story/datePicker.stories.js +19 -11
- package/datePicker/_story/v2/PanelOpen.jsx +39 -0
- package/datePicker/_story/v2/index.js +2 -1
- package/datePicker/datePicker.tsx +1 -0
- package/dist/css/semi.css +84 -36
- package/dist/css/semi.min.css +1 -1
- package/dist/umd/semi-ui.js +487 -170
- package/dist/umd/semi-ui.js.map +1 -1
- package/dist/umd/semi-ui.min.js +1 -1
- package/dist/umd/semi-ui.min.js.map +1 -1
- package/form/_story/demo.jsx +1 -0
- package/input/index.tsx +1 -0
- package/input/textarea.tsx +6 -4
- package/inputNumber/__test__/inputNumber.test.js +36 -8
- package/lib/cjs/autoComplete/index.d.ts +1 -1
- package/lib/cjs/cascader/index.js +6 -0
- package/lib/cjs/datePicker/datePicker.js +12 -8
- package/lib/cjs/dropdown/index.d.ts +1 -1
- package/lib/cjs/form/baseForm.d.ts +1 -1
- package/lib/cjs/form/field.d.ts +1 -1
- package/lib/cjs/input/index.js +2 -1
- package/lib/cjs/input/textarea.js +5 -3
- package/lib/cjs/navigation/Item.js +1 -1
- package/lib/cjs/navigation/SubNav.js +1 -1
- package/lib/cjs/scrollList/scrollItem.d.ts +5 -1
- package/lib/cjs/scrollList/scrollItem.js +7 -0
- package/lib/cjs/select/index.d.ts +1 -1
- package/lib/cjs/select/index.js +1 -1
- package/lib/cjs/select/option.js +2 -2
- package/lib/cjs/table/Table.d.ts +1 -1
- package/lib/cjs/table/Table.js +17 -7
- package/lib/cjs/table/interface.d.ts +1 -0
- package/lib/cjs/tabs/interface.d.ts +1 -1
- package/lib/cjs/timePicker/TimePicker.d.ts +2 -0
- package/lib/cjs/timePicker/TimePicker.js +4 -4
- package/lib/cjs/timePicker/index.d.ts +1 -0
- package/lib/cjs/tooltip/index.d.ts +1 -1
- package/lib/cjs/tree/index.d.ts +2 -0
- package/lib/cjs/tree/index.js +15 -8
- package/lib/cjs/tree/treeNode.js +10 -1
- package/lib/cjs/treeSelect/index.d.ts +2 -0
- package/lib/cjs/treeSelect/index.js +75 -30
- package/lib/cjs/typography/util.js +0 -1
- package/lib/cjs/upload/fileCard.js +31 -22
- package/lib/cjs/upload/index.d.ts +6 -0
- package/lib/cjs/upload/index.js +15 -8
- package/lib/cjs/upload/interface.d.ts +8 -6
- package/lib/es/autoComplete/index.d.ts +1 -1
- package/lib/es/cascader/index.js +5 -0
- package/lib/es/datePicker/datePicker.js +12 -8
- package/lib/es/dropdown/index.d.ts +1 -1
- package/lib/es/form/baseForm.d.ts +1 -1
- package/lib/es/form/field.d.ts +1 -1
- package/lib/es/input/index.js +2 -1
- package/lib/es/input/textarea.js +5 -3
- package/lib/es/navigation/Item.js +1 -1
- package/lib/es/navigation/SubNav.js +1 -1
- package/lib/es/scrollList/scrollItem.d.ts +5 -1
- package/lib/es/scrollList/scrollItem.js +7 -0
- package/lib/es/select/index.d.ts +1 -1
- package/lib/es/select/index.js +1 -1
- package/lib/es/select/option.js +2 -2
- package/lib/es/table/Table.d.ts +1 -1
- package/lib/es/table/Table.js +19 -7
- package/lib/es/table/interface.d.ts +1 -0
- package/lib/es/tabs/interface.d.ts +1 -1
- package/lib/es/timePicker/TimePicker.d.ts +2 -0
- package/lib/es/timePicker/TimePicker.js +4 -4
- package/lib/es/timePicker/index.d.ts +1 -0
- package/lib/es/tooltip/index.d.ts +1 -1
- package/lib/es/tree/index.d.ts +2 -0
- package/lib/es/tree/index.js +15 -8
- package/lib/es/tree/treeNode.js +9 -1
- package/lib/es/treeSelect/index.d.ts +2 -0
- package/lib/es/treeSelect/index.js +76 -31
- package/lib/es/typography/util.js +0 -1
- package/lib/es/upload/fileCard.js +31 -24
- package/lib/es/upload/index.d.ts +6 -0
- package/lib/es/upload/index.js +14 -8
- package/lib/es/upload/interface.d.ts +8 -6
- package/navigation/Item.tsx +1 -1
- package/navigation/SubNav.tsx +1 -1
- package/package.json +9 -8
- package/scrollList/scrollItem.tsx +10 -3
- package/select/index.tsx +6 -1
- package/select/option.tsx +2 -2
- package/table/Table.tsx +16 -8
- package/table/_story/table.stories.js +1 -0
- package/table/_story/v2/FixedColumnsChange/index.jsx +104 -0
- package/table/_story/v2/FixedHeaderMerge/index.jsx +98 -0
- package/table/_story/v2/FixedZIndex/index.jsx +87 -0
- package/table/_story/v2/defaultFilteredValue.tsx +123 -0
- package/table/_story/v2/index.js +4 -0
- package/table/interface.ts +1 -0
- package/tabs/interface.ts +1 -1
- package/timePicker/TimePicker.tsx +4 -1
- package/timePicker/__test__/timePicker.test.js +42 -3
- package/timePicker/_story/timepicker.stories.js +18 -0
- package/tooltip/_story/tooltip.stories.js +83 -1
- package/tree/__test__/treeMultiple.test.js +94 -0
- package/tree/_story/tree.stories.js +169 -0
- package/tree/index.tsx +12 -5
- package/tree/treeNode.tsx +9 -2
- package/treeSelect/__test__/treeMultiple.test.js +94 -0
- package/treeSelect/__test__/treeSelect.test.js +157 -0
- package/treeSelect/_story/treeSelect.stories.js +242 -0
- package/treeSelect/index.tsx +93 -52
- package/typography/_story/typography.stories.js +8 -0
- package/typography/util.tsx +0 -1
- package/upload/_story/upload.stories.js +22 -6
- package/upload/fileCard.tsx +23 -23
- package/upload/index.tsx +15 -6
- package/upload/interface.ts +7 -5
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { Table, Button } from '@douyinfe/semi-ui';
|
|
3
|
+
|
|
4
|
+
Demo.storyName = "fixed jsx column nested bug";
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* fixed https://github.com/DouyinFE/semi-design/issues/619
|
|
9
|
+
*
|
|
10
|
+
* Test with Cypress
|
|
11
|
+
*/
|
|
12
|
+
export default function Demo() {
|
|
13
|
+
const columns = [
|
|
14
|
+
{
|
|
15
|
+
title: 'Base Information',
|
|
16
|
+
fixed: 'left',
|
|
17
|
+
children: [
|
|
18
|
+
{
|
|
19
|
+
title: 'Name',
|
|
20
|
+
dataIndex: 'name',
|
|
21
|
+
width: 200,
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
title: 'Age',
|
|
25
|
+
dataIndex: 'age',
|
|
26
|
+
width: 100,
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
title: 'Company Information',
|
|
32
|
+
children: [
|
|
33
|
+
{
|
|
34
|
+
title: 'Company Name',
|
|
35
|
+
dataIndex: 'company.name',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
title: 'Company Address',
|
|
39
|
+
dataIndex: 'company.address',
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
}
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
const data = useMemo(() => {
|
|
46
|
+
const data = [];
|
|
47
|
+
for (let i = 0; i < 100; i++) {
|
|
48
|
+
let age = 40 + (Math.random() > 0.5 ? 1 : -1) * (i % 9);
|
|
49
|
+
let name = `Edward King ${i}`;
|
|
50
|
+
data.push({
|
|
51
|
+
key: '' + i,
|
|
52
|
+
company: {
|
|
53
|
+
name: 'ByteDance',
|
|
54
|
+
address: 'No. 48, Zhichun Road',
|
|
55
|
+
},
|
|
56
|
+
name,
|
|
57
|
+
age,
|
|
58
|
+
address: `No ${i + 1}, Zhongguancun Street`,
|
|
59
|
+
description: `My name is ${name}, I am ${age} years old, living in No ${i + 1}, Zhongguancun Street`,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
return data;
|
|
63
|
+
}, []);
|
|
64
|
+
|
|
65
|
+
const [flag, setFlag] = React.useState(true);
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<>
|
|
69
|
+
<Button data-cy="button" onClick={()=> setFlag(!flag)}>reRender</Button>
|
|
70
|
+
<Table dataSource={data} pagination={true} size="small">
|
|
71
|
+
{columns.map((item, titleIndex) =>
|
|
72
|
+
(
|
|
73
|
+
<Table.Column
|
|
74
|
+
key={titleIndex}
|
|
75
|
+
title={item.title}
|
|
76
|
+
>
|
|
77
|
+
{item.children.map(
|
|
78
|
+
(childItem, columnIndex) =>
|
|
79
|
+
(
|
|
80
|
+
<Table.Column
|
|
81
|
+
title={childItem.title}
|
|
82
|
+
dataIndex={childItem.dataIndex}
|
|
83
|
+
key={titleIndex.toString() + columnIndex.toString()}
|
|
84
|
+
/>
|
|
85
|
+
)
|
|
86
|
+
)}
|
|
87
|
+
</Table.Column>
|
|
88
|
+
)
|
|
89
|
+
)}
|
|
90
|
+
<Table.Column
|
|
91
|
+
title=""
|
|
92
|
+
key="lastColumn"
|
|
93
|
+
render={() => 123}
|
|
94
|
+
/>
|
|
95
|
+
</Table>
|
|
96
|
+
</>
|
|
97
|
+
);
|
|
98
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Table, Tooltip, Tag } from '@douyinfe/semi-ui';
|
|
3
|
+
|
|
4
|
+
App.storyName = 'fixed z-index bug';
|
|
5
|
+
export default function App() {
|
|
6
|
+
const columns = [
|
|
7
|
+
{
|
|
8
|
+
title: 'Name',
|
|
9
|
+
dataIndex: 'name',
|
|
10
|
+
width: 150,
|
|
11
|
+
fixed: true,
|
|
12
|
+
filters: [
|
|
13
|
+
{
|
|
14
|
+
text: 'King 3',
|
|
15
|
+
value: 'King 3',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
text: 'King 4',
|
|
19
|
+
value: 'King 4',
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
onFilter: (value, record) => record.name.includes(value),
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
title: 'Age',
|
|
26
|
+
dataIndex: 'age',
|
|
27
|
+
width: 150,
|
|
28
|
+
sorter: (a, b) => (a.age - b.age > 0 ? 1 : -1),
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
title: 'Address',
|
|
32
|
+
width: 200,
|
|
33
|
+
dataIndex: 'address',
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
title: 'Description',
|
|
37
|
+
// width: 400,
|
|
38
|
+
dataIndex: 'description',
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
fixed: 'right',
|
|
42
|
+
width: 250,
|
|
43
|
+
render: (text, record) => <Tooltip content={record.description}><Tag color="green">Show Info</Tag></Tooltip>
|
|
44
|
+
}
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
let data = [];
|
|
48
|
+
|
|
49
|
+
const rowSelection = {
|
|
50
|
+
onChange: (selectedRowKeys, selectedRows) => {
|
|
51
|
+
// console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
|
|
52
|
+
},
|
|
53
|
+
getCheckboxProps: record => ({
|
|
54
|
+
disabled: record.name === 'Michael James', // Column configuration not to be checked
|
|
55
|
+
name: record.name,
|
|
56
|
+
}),
|
|
57
|
+
// fixed: true,
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
for (let i = 0; i < 46; i++) {
|
|
61
|
+
let age = (i * 1000) % 149;
|
|
62
|
+
let name = `Edward King ${i}`;
|
|
63
|
+
data.push({
|
|
64
|
+
key: `${ i}`,
|
|
65
|
+
name,
|
|
66
|
+
age,
|
|
67
|
+
address: `London, Park Lane no. ${i}`,
|
|
68
|
+
description: `My name is ${name}, I am ${age} years old, living in New York No. ${i + 1} Lake Park.`,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const scroll = { y: 300, x: 1500 };
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<div style={{ position: 'relative', height: '100vh' }}>
|
|
76
|
+
<div style={{ height: 60, background: 'red', position: 'absolute', top: 0, left: 0, right: 0, zIndex: 2 }}>
|
|
77
|
+
Fixed Header
|
|
78
|
+
</div>
|
|
79
|
+
<Table
|
|
80
|
+
columns={columns}
|
|
81
|
+
dataSource={data}
|
|
82
|
+
scroll={scroll}
|
|
83
|
+
rowSelection={rowSelection}
|
|
84
|
+
/>
|
|
85
|
+
</div>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import React, { useState, useEffect, useMemo } from 'react';
|
|
2
|
+
import { Table, Avatar, Button } from '@douyinfe/semi-ui';
|
|
3
|
+
import * as dateFns from 'date-fns';
|
|
4
|
+
import { ColumnProps, ChangeInfoFilter } from '@douyinfe/semi-ui/table';
|
|
5
|
+
|
|
6
|
+
const DAY = 24 * 60 * 60 * 1000;
|
|
7
|
+
const figmaIconUrl = 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/figma-icon.png';
|
|
8
|
+
|
|
9
|
+
function App() {
|
|
10
|
+
const [dataSource, setData] = useState([]);
|
|
11
|
+
const [filteredValue, setFilteredValue] = useState(['Semi Pro 设计稿']);
|
|
12
|
+
|
|
13
|
+
const scroll = useMemo(() => ({ y: 300 }), []);
|
|
14
|
+
|
|
15
|
+
const columns: ColumnProps[] = [
|
|
16
|
+
{
|
|
17
|
+
title: '标题',
|
|
18
|
+
dataIndex: 'name',
|
|
19
|
+
width: 400,
|
|
20
|
+
render: (text, record, index) => {
|
|
21
|
+
return (
|
|
22
|
+
<div>
|
|
23
|
+
<Avatar size="small" shape="square" src={figmaIconUrl} style={{ marginRight: 12 }}></Avatar>
|
|
24
|
+
{text}
|
|
25
|
+
</div>
|
|
26
|
+
);
|
|
27
|
+
},
|
|
28
|
+
filters: [
|
|
29
|
+
{
|
|
30
|
+
text: 'Semi Design 设计稿',
|
|
31
|
+
value: 'Semi Design 设计稿',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
text: 'Semi Pro 设计稿',
|
|
35
|
+
value: 'Semi Pro 设计稿',
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
onFilter: (value, record) => record.name.includes(value),
|
|
39
|
+
sorter: (a, b) => a.name.length - b.name.length > 0 ? 1 : -1,
|
|
40
|
+
// filterMultiple: false,
|
|
41
|
+
// filteredValue: filteredValue,
|
|
42
|
+
defaultFilteredValue: filteredValue,
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
title: '大小',
|
|
46
|
+
dataIndex: 'size',
|
|
47
|
+
sorter: (a, b) => a.size - b.size > 0 ? 1 : -1,
|
|
48
|
+
render: (text) => `${text} KB`
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
title: '所有者',
|
|
52
|
+
dataIndex: 'owner',
|
|
53
|
+
render: (text, record, index) => {
|
|
54
|
+
return (
|
|
55
|
+
<div>
|
|
56
|
+
<Avatar size="small" color={record.avatarBg} style={{ marginRight: 4 }}>{typeof text === 'string' && text.slice(0, 1)}</Avatar>
|
|
57
|
+
{text}
|
|
58
|
+
</div>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
title: '更新日期',
|
|
65
|
+
dataIndex: 'updateTime',
|
|
66
|
+
sorter: (a, b) => a.updateTime - b.updateTime > 0 ? 1 : -1,
|
|
67
|
+
render: (value) => {
|
|
68
|
+
return dateFns.format(new Date(value), 'yyyy-MM-dd');
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
];
|
|
72
|
+
|
|
73
|
+
const getData = (total) => {
|
|
74
|
+
const data = [];
|
|
75
|
+
for (let i = 0; i < total; i++) {
|
|
76
|
+
const isSemiDesign = i % 2 === 0;
|
|
77
|
+
const randomNumber = (i * 1000) % 199;
|
|
78
|
+
data.push({
|
|
79
|
+
key: '' + i,
|
|
80
|
+
name: isSemiDesign ? `Semi Design 设计稿${i}.fig` : `Semi Pro 设计稿${i}.fig`,
|
|
81
|
+
owner: isSemiDesign ? '姜鹏志' : '郝宣',
|
|
82
|
+
size: randomNumber,
|
|
83
|
+
updateTime: new Date().valueOf() + randomNumber * DAY,
|
|
84
|
+
avatarBg: isSemiDesign ? 'grey' : 'red'
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
return data;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const handleFilterChange = (filters: ChangeInfoFilter<any>[]) => {
|
|
91
|
+
console.log('filters', filters);
|
|
92
|
+
if (Array.isArray(filters) && filters.length) {
|
|
93
|
+
const { filteredValue } = filters.find(filter => filter.dataIndex === 'name');
|
|
94
|
+
setFilteredValue(filteredValue);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const handleChange = (options) => {
|
|
99
|
+
const { filters } = options;
|
|
100
|
+
handleFilterChange(filters);
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const toggleChangeData = () => {
|
|
104
|
+
const length = dataSource.length;
|
|
105
|
+
const newData = getData(length === 46 ? 25 : 46);
|
|
106
|
+
setData(newData);
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
useEffect(() => {
|
|
110
|
+
const data = getData(46);
|
|
111
|
+
setData(data);
|
|
112
|
+
}, []);
|
|
113
|
+
|
|
114
|
+
return (
|
|
115
|
+
<div>
|
|
116
|
+
<Button onClick={toggleChangeData}>toggle change dataSource (46/25)</Button>
|
|
117
|
+
<Table columns={columns} dataSource={dataSource} scroll={scroll} onChange={handleChange} />
|
|
118
|
+
</div>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
App.storyName = 'defaultFilteredValue';
|
|
123
|
+
export default App;
|
package/table/interface.ts
CHANGED
|
@@ -79,6 +79,7 @@ export interface ColumnProps<RecordType extends Record<string, any> = any> {
|
|
|
79
79
|
className?: string;
|
|
80
80
|
colSpan?: number;
|
|
81
81
|
dataIndex?: string;
|
|
82
|
+
defaultFilteredValue?: any[];
|
|
82
83
|
defaultSortOrder?: SortOrder;
|
|
83
84
|
filterChildrenRecord?: boolean;
|
|
84
85
|
filterDropdown?: React.ReactNode;
|
package/tabs/interface.ts
CHANGED
|
@@ -90,6 +90,7 @@ export type TimePickerProps = {
|
|
|
90
90
|
zIndex?: number | string;
|
|
91
91
|
onBlur?: React.FocusEventHandler<HTMLInputElement>;
|
|
92
92
|
onChange?: TimePickerAdapter['notifyChange'];
|
|
93
|
+
onChangeWithDateFirst?: boolean;
|
|
93
94
|
onFocus?: React.FocusEventHandler<HTMLInputElement>;
|
|
94
95
|
onOpenChange?: (open: boolean) => void;
|
|
95
96
|
};
|
|
@@ -187,6 +188,7 @@ export default class TimePicker extends BaseComponent<TimePickerProps, TimePicke
|
|
|
187
188
|
onFocus: noop,
|
|
188
189
|
onBlur: noop,
|
|
189
190
|
onChange: noop,
|
|
191
|
+
onChangeWithDateFirst: true,
|
|
190
192
|
use12Hours: false,
|
|
191
193
|
focusOnOpen: false,
|
|
192
194
|
onKeyDown: noop,
|
|
@@ -257,7 +259,7 @@ export default class TimePicker extends BaseComponent<TimePickerProps, TimePicke
|
|
|
257
259
|
}
|
|
258
260
|
},
|
|
259
261
|
notifyOpenChange: (...args) => this.props.onOpenChange(...args),
|
|
260
|
-
notifyChange: (
|
|
262
|
+
notifyChange: (agr1, arg2) => this.props.onChange && this.props.onChange(agr1, arg2),
|
|
261
263
|
notifyFocus: (...args) => this.props.onFocus && this.props.onFocus(...args),
|
|
262
264
|
notifyBlur: (...args) => this.props.onBlur && this.props.onBlur(...args),
|
|
263
265
|
isRangePicker: () => this.props.type === strings.TYPE_TIME_RANGE_PICKER,
|
|
@@ -447,6 +449,7 @@ export default class TimePicker extends BaseComponent<TimePickerProps, TimePicke
|
|
|
447
449
|
panelFooter,
|
|
448
450
|
rangeSeparator,
|
|
449
451
|
onOpenChange,
|
|
452
|
+
onChangeWithDateFirst,
|
|
450
453
|
popupClassName: propPopupClassName,
|
|
451
454
|
hideDisabledOptions,
|
|
452
455
|
use12Hours,
|
|
@@ -22,11 +22,13 @@ describe(`TimePicker`, () => {
|
|
|
22
22
|
const defaultMinute = 24;
|
|
23
23
|
const defaultSeconds = 18;
|
|
24
24
|
|
|
25
|
-
const
|
|
25
|
+
const onFocus = sinon.spy();
|
|
26
|
+
const onChange = sinon.spy();
|
|
26
27
|
|
|
27
28
|
const elem = mount(
|
|
28
29
|
<TimePicker
|
|
29
|
-
|
|
30
|
+
onChange={onChange}
|
|
31
|
+
onFocus={onFocus}
|
|
30
32
|
panelHeader={<strong>Select Time</strong>}
|
|
31
33
|
locale={Locale.TimePicker}
|
|
32
34
|
localeCode={Locale.code}
|
|
@@ -59,7 +61,7 @@ describe(`TimePicker`, () => {
|
|
|
59
61
|
// focus
|
|
60
62
|
elem.find(`input`).simulate('focus');
|
|
61
63
|
await sleep(200);
|
|
62
|
-
expect(
|
|
64
|
+
expect(onFocus.calledOnce).toBeTruthy();
|
|
63
65
|
|
|
64
66
|
// input value
|
|
65
67
|
const newInputHour = 10;
|
|
@@ -82,6 +84,12 @@ describe(`TimePicker`, () => {
|
|
|
82
84
|
|
|
83
85
|
await sleep(200);
|
|
84
86
|
expect(elem.state('open')).toBe(false);
|
|
87
|
+
|
|
88
|
+
expect(onChange.called).toBeTruthy();
|
|
89
|
+
const args = onChange.getCall(0).args;
|
|
90
|
+
expect(args[0] instanceof Date).toBe(true);
|
|
91
|
+
expect(typeof args[1]).toBe('string');
|
|
92
|
+
elem.unmount();
|
|
85
93
|
});
|
|
86
94
|
|
|
87
95
|
it(`test controlled value`, async () => {
|
|
@@ -113,6 +121,7 @@ describe(`TimePicker`, () => {
|
|
|
113
121
|
let currentDate0 = elem0.state('value')[0];
|
|
114
122
|
|
|
115
123
|
expect(currentDate0.getMinutes()).toBe(defaultMinute);
|
|
124
|
+
elem0.unmount();
|
|
116
125
|
});
|
|
117
126
|
|
|
118
127
|
it(`test controlled value with onchange`, async () => {
|
|
@@ -149,6 +158,7 @@ describe(`TimePicker`, () => {
|
|
|
149
158
|
|
|
150
159
|
let currentDate1 = elem1.state('value')[0];
|
|
151
160
|
expect(currentDate1.getMinutes()).toBe(newInputMinute);
|
|
161
|
+
elem1.unmount();
|
|
152
162
|
});
|
|
153
163
|
|
|
154
164
|
it(`test controlled open`, async () => {
|
|
@@ -227,6 +237,7 @@ describe(`TimePicker`, () => {
|
|
|
227
237
|
nextSelectedLi.simulate('click');
|
|
228
238
|
await sleep(200);
|
|
229
239
|
expect(elem.state('value')[0].getHours()).toBe(newHour);
|
|
240
|
+
elem.unmount();
|
|
230
241
|
});
|
|
231
242
|
|
|
232
243
|
it('test isTimeFormatLike function', () => {
|
|
@@ -279,5 +290,33 @@ describe(`TimePicker`, () => {
|
|
|
279
290
|
const args = onChange.getCall(0).args;
|
|
280
291
|
expect(args[0]).toBe(undefined);
|
|
281
292
|
expect(args[1]).toBe('');
|
|
293
|
+
elem.unmount();
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
it('test onChangeWithDateFirst=false', async () => {
|
|
297
|
+
const onChange = sinon.spy();
|
|
298
|
+
let props = {
|
|
299
|
+
defaultValue: "10:23:15",
|
|
300
|
+
onChange,
|
|
301
|
+
defaultOpen: true,
|
|
302
|
+
onChangeWithDateFirst: false,
|
|
303
|
+
autofocus: true,
|
|
304
|
+
locale: Locale.TimePicker,
|
|
305
|
+
localeCode: Locale.code,
|
|
306
|
+
scrollItemProps: { cycled: false }
|
|
307
|
+
};
|
|
308
|
+
const elem = mount(<TimePicker {...props} />);
|
|
309
|
+
// click minute
|
|
310
|
+
const minuteUl = elem.find(`.${BASE_CLASS_PREFIX}-timepicker-panel-list-minute .${BASE_CLASS_PREFIX}-scrolllist-list-outer ul`);
|
|
311
|
+
const minuteLis = minuteUl.find(`li`);
|
|
312
|
+
|
|
313
|
+
minuteUl.simulate('click', { target: minuteLis.at(0).getDOMNode(), nativeEvent: null });
|
|
314
|
+
await sleep(200);
|
|
315
|
+
|
|
316
|
+
expect(onChange.called).toBeTruthy();
|
|
317
|
+
const args = onChange.getCall(0).args;
|
|
318
|
+
expect(typeof args[0]).toBe('string');
|
|
319
|
+
expect(args[1] instanceof Date).toBe(true);
|
|
320
|
+
elem.unmount();
|
|
282
321
|
});
|
|
283
322
|
});
|
|
@@ -262,3 +262,21 @@ export const ShowClear = () => (
|
|
|
262
262
|
/>
|
|
263
263
|
</>
|
|
264
264
|
);
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
export const TimePickerWithOnChangeWithDateFirst = () => {
|
|
268
|
+
return (
|
|
269
|
+
<div>
|
|
270
|
+
onChangeWithDateFirst=true (default)
|
|
271
|
+
<TimePicker onChange={(...val) => console.log(...val)} />
|
|
272
|
+
<br />
|
|
273
|
+
onChangeWithDateFirst=false
|
|
274
|
+
<TimePicker onChangeWithDateFirst={false} onChange={(...val) => console.log(...val)} />
|
|
275
|
+
|
|
276
|
+
</div>
|
|
277
|
+
);
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
TimePickerWithOnChangeWithDateFirst.story = {
|
|
281
|
+
name: 'OnChangeWithDateFirst',
|
|
282
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useState, useMemo } from 'react';
|
|
2
2
|
import Tooltip from '../index';
|
|
3
3
|
import './story.scss';
|
|
4
|
-
import { Tag, Icon, IconButton, Switch, Checkbox, Radio, Button, Select, InputNumber } from '@douyinfe/semi-ui';
|
|
4
|
+
import { Tag, Icon, IconButton, Switch, Checkbox, Radio, Button, Select, InputNumber, Space } from '@douyinfe/semi-ui';
|
|
5
5
|
|
|
6
6
|
import InTableDemo from './InTable';
|
|
7
7
|
import EdgeDemo from './Edge';
|
|
@@ -736,3 +736,85 @@ export const AutoAdjustWithSpacing = () => {
|
|
|
736
736
|
AutoAdjustWithSpacing.story = {
|
|
737
737
|
name: 'AutoAdjustWithSpacing',
|
|
738
738
|
};
|
|
739
|
+
|
|
740
|
+
/**
|
|
741
|
+
* Chromatic UI test
|
|
742
|
+
*/
|
|
743
|
+
export const leftTopOverDemo = () => {
|
|
744
|
+
const [visible, setVisible] = useState(true);
|
|
745
|
+
const content = (
|
|
746
|
+
<div style={{ height: 200, width: 200 }}>
|
|
747
|
+
Semi Design
|
|
748
|
+
</div>
|
|
749
|
+
);
|
|
750
|
+
|
|
751
|
+
const commonProps = {
|
|
752
|
+
content,
|
|
753
|
+
trigger: 'click',
|
|
754
|
+
showArrow: false,
|
|
755
|
+
visible,
|
|
756
|
+
trigger: 'custom',
|
|
757
|
+
motion: false,
|
|
758
|
+
};
|
|
759
|
+
const buttonStyle = {
|
|
760
|
+
width: 200,
|
|
761
|
+
};
|
|
762
|
+
|
|
763
|
+
return (
|
|
764
|
+
<div data-cy='wrapper'>
|
|
765
|
+
<Button onClick={() => setVisible(!visible)}>toggle visible</Button>
|
|
766
|
+
<div style={{ paddingTop: 200 }}>
|
|
767
|
+
<Space spacing={80}>
|
|
768
|
+
<Tooltip {...commonProps} position='leftTopOver' >
|
|
769
|
+
<Button data-cy='leftTopOver' style={buttonStyle}>leftTopOver</Button>
|
|
770
|
+
</Tooltip>
|
|
771
|
+
<Tooltip {...commonProps} position='leftBottomOver'>
|
|
772
|
+
<Button data-cy='leftBottomOver' style={buttonStyle}>leftBottomOver</Button>
|
|
773
|
+
</Tooltip>
|
|
774
|
+
<Tooltip {...commonProps} position='rightTopOver'>
|
|
775
|
+
<Button data-cy='rightTopOver' style={buttonStyle}>rightTopOver</Button>
|
|
776
|
+
</Tooltip>
|
|
777
|
+
<Tooltip {...commonProps} position='rightBottomOver'>
|
|
778
|
+
<Button data-cy='rightBottomOver' style={buttonStyle}>rightBottomOver</Button>
|
|
779
|
+
</Tooltip>
|
|
780
|
+
</Space>
|
|
781
|
+
</div>
|
|
782
|
+
</div>
|
|
783
|
+
)
|
|
784
|
+
};
|
|
785
|
+
leftTopOverDemo.storyName = `leftTopOver visible`;
|
|
786
|
+
leftTopOverDemo.parameters = {
|
|
787
|
+
chromatic: {
|
|
788
|
+
disableSnapshot: false,
|
|
789
|
+
delay: 3000,
|
|
790
|
+
viewports: [1200]
|
|
791
|
+
}
|
|
792
|
+
};
|
|
793
|
+
|
|
794
|
+
/**
|
|
795
|
+
* Cypress test
|
|
796
|
+
*/
|
|
797
|
+
export const leftTopOverAutoAdjustOverflow = () => {
|
|
798
|
+
const content = (
|
|
799
|
+
<div style={{ height: 200, width: 200 }}>
|
|
800
|
+
Semi Design
|
|
801
|
+
</div>
|
|
802
|
+
);
|
|
803
|
+
|
|
804
|
+
const commonProps = {
|
|
805
|
+
content,
|
|
806
|
+
trigger: 'click',
|
|
807
|
+
showArrow: false,
|
|
808
|
+
};
|
|
809
|
+
|
|
810
|
+
return (
|
|
811
|
+
<div data-cy='wrapper' style={{ width: '200vw', height: '200vw', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
|
812
|
+
<div>
|
|
813
|
+
<Tooltip {...commonProps} position='leftTopOver' >
|
|
814
|
+
<Button data-cy='leftTopOver' style={{ width: 200 }}>leftTopOver</Button>
|
|
815
|
+
</Tooltip>
|
|
816
|
+
</div>
|
|
817
|
+
</div>
|
|
818
|
+
)
|
|
819
|
+
};
|
|
820
|
+
leftTopOverAutoAdjustOverflow.storyName = `leftTopOver autoAdjustOverflow`;
|
|
@@ -357,6 +357,100 @@ describe('Tree', () => {
|
|
|
357
357
|
).toEqual(true);
|
|
358
358
|
});
|
|
359
359
|
|
|
360
|
+
it('unRelated', () => {
|
|
361
|
+
const spyOnChange = sinon.spy(() => { });
|
|
362
|
+
const tree = getTree({
|
|
363
|
+
defaultExpandAll: true,
|
|
364
|
+
onChange: spyOnChange,
|
|
365
|
+
checkRelation: 'unRelated',
|
|
366
|
+
});
|
|
367
|
+
const nodelevel2 = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-2`);
|
|
368
|
+
const selectedNode = nodelevel2.at(0);
|
|
369
|
+
selectedNode.simulate('click');
|
|
370
|
+
expect(spyOnChange.calledOnce).toBe(true);
|
|
371
|
+
expect(spyOnChange.calledWithMatch(['Zhongguo'])).toEqual(true);
|
|
372
|
+
// Note: selectedNode cannot be used directly here. selectedNode is the original node in the unselected state
|
|
373
|
+
expect(
|
|
374
|
+
tree
|
|
375
|
+
.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-2`)
|
|
376
|
+
.at(0)
|
|
377
|
+
.exists(`.${BASE_CLASS_PREFIX}-checkbox-checked`)
|
|
378
|
+
).toEqual(true);
|
|
379
|
+
const nodelevel3 = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-3`);
|
|
380
|
+
expect(
|
|
381
|
+
nodelevel3
|
|
382
|
+
.exists(`.${BASE_CLASS_PREFIX}-checkbox-unChecked` )
|
|
383
|
+
).toEqual(true);
|
|
384
|
+
expect(
|
|
385
|
+
nodelevel3
|
|
386
|
+
.at(1)
|
|
387
|
+
.exists(`.${BASE_CLASS_PREFIX}-checkbox-unChecked` )
|
|
388
|
+
).toEqual(true);
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
it('unRelated + value', () => {
|
|
392
|
+
const tree = getTree({
|
|
393
|
+
defaultExpandAll: true,
|
|
394
|
+
checkRelation: 'unRelated',
|
|
395
|
+
value: 'Zhongguo'
|
|
396
|
+
});
|
|
397
|
+
expect(
|
|
398
|
+
tree
|
|
399
|
+
.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-2`)
|
|
400
|
+
.at(0)
|
|
401
|
+
.exists(`.${BASE_CLASS_PREFIX}-checkbox-checked`)
|
|
402
|
+
).toEqual(true);
|
|
403
|
+
const nodelevel3 = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-3`);
|
|
404
|
+
expect(
|
|
405
|
+
nodelevel3
|
|
406
|
+
.exists(`.${BASE_CLASS_PREFIX}-checkbox-unChecked` )
|
|
407
|
+
).toEqual(true);
|
|
408
|
+
expect(
|
|
409
|
+
nodelevel3
|
|
410
|
+
.at(1)
|
|
411
|
+
.exists(`.${BASE_CLASS_PREFIX}-checkbox-unChecked` )
|
|
412
|
+
).toEqual(true);
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
it('unRelated + defaultValue', () => {
|
|
416
|
+
const tree = getTree({
|
|
417
|
+
defaultExpandAll: true,
|
|
418
|
+
checkRelation: 'unRelated',
|
|
419
|
+
defaultValue: 'Zhongguo'
|
|
420
|
+
});
|
|
421
|
+
expect(
|
|
422
|
+
tree
|
|
423
|
+
.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-2`)
|
|
424
|
+
.at(0)
|
|
425
|
+
.exists(`.${BASE_CLASS_PREFIX}-checkbox-checked`)
|
|
426
|
+
).toEqual(true);
|
|
427
|
+
const nodelevel3 = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-3`);
|
|
428
|
+
expect(
|
|
429
|
+
nodelevel3
|
|
430
|
+
.exists(`.${BASE_CLASS_PREFIX}-checkbox-unChecked` )
|
|
431
|
+
).toEqual(true);
|
|
432
|
+
expect(
|
|
433
|
+
nodelevel3
|
|
434
|
+
.at(1)
|
|
435
|
+
.exists(`.${BASE_CLASS_PREFIX}-checkbox-unChecked` )
|
|
436
|
+
).toEqual(true);
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
it('unRelated + onSelect', () => {
|
|
440
|
+
const spyOnSelect = sinon.spy(() => { });
|
|
441
|
+
const tree = getTree({
|
|
442
|
+
defaultExpandAll: true,
|
|
443
|
+
onSelect: spyOnSelect,
|
|
444
|
+
checkRelation: 'unRelated',
|
|
445
|
+
});
|
|
446
|
+
const nodelevel2 = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-2`);
|
|
447
|
+
const selectedNode = nodelevel2.at(0);
|
|
448
|
+
selectedNode.simulate('click');
|
|
449
|
+
expect(spyOnSelect.calledOnce).toBe(true);
|
|
450
|
+
// onSelect first args is key, not value
|
|
451
|
+
expect(spyOnSelect.calledWithMatch('zhongguo')).toEqual(true);
|
|
452
|
+
});
|
|
453
|
+
|
|
360
454
|
it('controlled: leaf values show correct', () => {
|
|
361
455
|
let tree = getTree({
|
|
362
456
|
value: 'Beijing'
|