@douyinfe/semi-ui 2.3.0-beta.0 → 2.4.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/_base/_story/a11y.scss +0 -1
- package/_base/_story/index.scss +2 -5
- package/avatar/avatarGroup.tsx +1 -1
- package/avatar/index.tsx +0 -4
- package/button/__test__/button.test.js +1 -1
- package/checkbox/_story/checkbox.stories.js +2 -2
- package/collapse/index.tsx +1 -1
- package/collapse/item.tsx +1 -3
- 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/dist/css/semi.css +33 -9
- package/dist/css/semi.min.css +1 -1
- package/dist/umd/semi-ui.js +96 -57
- 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/dropdown/index.tsx +11 -3
- package/empty/index.tsx +1 -1
- package/input/textarea.tsx +5 -3
- package/inputNumber/__test__/inputNumber.test.js +36 -8
- package/inputNumber/index.tsx +2 -1
- package/lib/cjs/avatar/avatarGroup.js +1 -2
- package/lib/cjs/avatar/index.js +1 -6
- package/lib/cjs/collapse/index.js +1 -2
- package/lib/cjs/collapse/item.js +1 -5
- package/lib/cjs/dropdown/index.d.ts +10 -3
- package/lib/cjs/empty/index.js +1 -2
- package/lib/cjs/input/textarea.js +4 -2
- package/lib/cjs/inputNumber/index.js +3 -2
- package/lib/cjs/list/index.d.ts +4 -4
- 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.js +1 -1
- package/lib/cjs/sideSheet/SideSheetContent.js +5 -9
- package/lib/cjs/spin/icon.js +2 -1
- package/lib/cjs/table/Table.js +9 -5
- package/lib/cjs/timePicker/TimePicker.d.ts +2 -0
- package/lib/cjs/timePicker/TimePicker.js +2 -3
- package/lib/cjs/timePicker/index.d.ts +1 -0
- package/lib/cjs/tooltip/index.js +1 -1
- package/lib/cjs/tree/treeNode.js +10 -1
- package/lib/cjs/treeSelect/index.js +11 -3
- package/lib/cjs/typography/util.js +0 -1
- package/lib/cjs/upload/fileCard.js +3 -3
- package/lib/es/avatar/avatarGroup.js +1 -2
- package/lib/es/avatar/index.js +1 -6
- package/lib/es/collapse/index.js +1 -2
- package/lib/es/collapse/item.js +1 -5
- package/lib/es/dropdown/index.d.ts +10 -3
- package/lib/es/empty/index.js +1 -2
- package/lib/es/input/textarea.js +4 -2
- package/lib/es/inputNumber/index.js +3 -2
- package/lib/es/list/index.d.ts +4 -4
- 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.js +1 -1
- package/lib/es/sideSheet/SideSheetContent.js +5 -9
- package/lib/es/spin/icon.js +2 -1
- package/lib/es/table/Table.js +9 -5
- package/lib/es/timePicker/TimePicker.d.ts +2 -0
- package/lib/es/timePicker/TimePicker.js +2 -3
- package/lib/es/timePicker/index.d.ts +1 -0
- package/lib/es/tooltip/index.js +2 -2
- package/lib/es/tree/treeNode.js +9 -1
- package/lib/es/treeSelect/index.js +12 -4
- package/lib/es/typography/util.js +0 -1
- package/lib/es/upload/fileCard.js +3 -3
- package/list/index.tsx +5 -5
- package/navigation/Item.tsx +1 -1
- package/navigation/SubNav.tsx +1 -1
- package/package.json +8 -8
- package/scrollList/scrollItem.tsx +10 -3
- package/select/index.tsx +6 -1
- package/sideSheet/SideSheetContent.tsx +6 -8
- package/spin/icon.tsx +2 -1
- package/table/Table.tsx +9 -6
- package/table/_story/table.stories.js +2 -0
- package/table/_story/v2/FixedColumnsChange/index.jsx +104 -0
- package/table/_story/v2/FixedZIndex/index.jsx +87 -0
- package/timePicker/TimePicker.tsx +3 -1
- package/timePicker/__test__/timePicker.test.js +42 -3
- package/timePicker/_story/timepicker.stories.js +18 -0
- package/tooltip/index.tsx +3 -2
- package/tree/treeNode.tsx +9 -2
- package/treeSelect/__test__/treeSelect.test.js +157 -0
- package/treeSelect/index.tsx +21 -12
- package/typography/_story/typography.stories.js +8 -0
- package/typography/util.tsx +0 -1
- package/upload/fileCard.tsx +2 -2
|
@@ -87,7 +87,7 @@ export default class SideSheetContent extends React.PureComponent<SideSheetConte
|
|
|
87
87
|
let header, closer;
|
|
88
88
|
if (title) {
|
|
89
89
|
header = (
|
|
90
|
-
<div className={`${prefixCls}-title`}
|
|
90
|
+
<div className={`${prefixCls}-title`}>
|
|
91
91
|
{this.props.title}
|
|
92
92
|
</div>
|
|
93
93
|
);
|
|
@@ -106,7 +106,7 @@ export default class SideSheetContent extends React.PureComponent<SideSheetConte
|
|
|
106
106
|
);
|
|
107
107
|
}
|
|
108
108
|
return (
|
|
109
|
-
<div className={`${prefixCls}-header`} role={'heading'} style={{ ...headerStyle }}>
|
|
109
|
+
<div className={`${prefixCls}-header`} role={'heading'} aria-level={1} style={{ ...headerStyle }}>
|
|
110
110
|
{header}
|
|
111
111
|
{closer}
|
|
112
112
|
</div>
|
|
@@ -137,13 +137,13 @@ export default class SideSheetContent extends React.PureComponent<SideSheetConte
|
|
|
137
137
|
style={{ ...props.style, ...style }}
|
|
138
138
|
// id={this.dialogId}
|
|
139
139
|
>
|
|
140
|
-
<div className={`${prefixCls}-content`}
|
|
140
|
+
<div className={`${prefixCls}-content`}>
|
|
141
141
|
{header}
|
|
142
|
-
<div className={`${prefixCls}-body`}
|
|
142
|
+
<div className={`${prefixCls}-body`} style={props.bodyStyle}>
|
|
143
143
|
{props.children}
|
|
144
144
|
</div>
|
|
145
145
|
{props.footer ? (
|
|
146
|
-
<div className={`${prefixCls}-footer`}
|
|
146
|
+
<div className={`${prefixCls}-footer`}>
|
|
147
147
|
{props.footer}
|
|
148
148
|
</div>
|
|
149
149
|
) : null}
|
|
@@ -167,9 +167,7 @@ export default class SideSheetContent extends React.PureComponent<SideSheetConte
|
|
|
167
167
|
wrapperStyle.width = width;
|
|
168
168
|
}
|
|
169
169
|
return (
|
|
170
|
-
<div className={wrapperCls}
|
|
171
|
-
style={wrapperStyle}
|
|
172
|
-
aria-label={this.props['aria-label']}>
|
|
170
|
+
<div className={wrapperCls} style={wrapperStyle}>
|
|
173
171
|
{this.getMaskElement()}
|
|
174
172
|
{this.getDialogElement()}
|
|
175
173
|
</div>
|
package/spin/icon.tsx
CHANGED
package/table/Table.tsx
CHANGED
|
@@ -534,7 +534,6 @@ class Table<RecordType extends Record<string, any>> extends BaseComponent<Normal
|
|
|
534
534
|
this.foundation.initExpandedRowKeys({ groups: stateGroups });
|
|
535
535
|
}
|
|
536
536
|
|
|
537
|
-
|
|
538
537
|
/**
|
|
539
538
|
* After dataSource is updated || (cachedColumns || cachedChildren updated)
|
|
540
539
|
* 1. Cache filtered sorted data and a collection of data rows, stored in this
|
|
@@ -547,17 +546,20 @@ class Table<RecordType extends Record<string, any>> extends BaseComponent<Normal
|
|
|
547
546
|
const filteredSortedDataSource = this.foundation.getFilteredSortedDataSource(_dataSource, stateQueries);
|
|
548
547
|
this.foundation.setCachedFilteredSortedDataSource(filteredSortedDataSource);
|
|
549
548
|
states.dataSource = filteredSortedDataSource;
|
|
550
|
-
// when dataSource has change, should reset currentPage
|
|
551
|
-
states.pagination = isObject(statePagination) ? {
|
|
552
|
-
...statePagination,
|
|
553
|
-
currentPage: isObject(propsPagination) && propsPagination.currentPage ? propsPagination.currentPage : 1,
|
|
554
|
-
} : statePagination;
|
|
555
549
|
|
|
556
550
|
if (this.props.groupBy) {
|
|
557
551
|
states.groups = null;
|
|
558
552
|
}
|
|
559
553
|
}
|
|
560
554
|
|
|
555
|
+
// when dataSource has change, should reset currentPage
|
|
556
|
+
if (dataSource !== prevProps.dataSource) {
|
|
557
|
+
states.pagination = isObject(statePagination) ? {
|
|
558
|
+
...statePagination,
|
|
559
|
+
currentPage: isObject(propsPagination) && propsPagination.currentPage ? propsPagination.currentPage : 1,
|
|
560
|
+
} : statePagination;
|
|
561
|
+
}
|
|
562
|
+
|
|
561
563
|
if (Object.keys(states).length) {
|
|
562
564
|
const {
|
|
563
565
|
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
@@ -1372,6 +1374,7 @@ class Table<RecordType extends Record<string, any>> extends BaseComponent<Normal
|
|
|
1372
1374
|
<div
|
|
1373
1375
|
ref={this.rootWrapRef}
|
|
1374
1376
|
className={classnames(className, `${prefixCls}-wrapper`)}
|
|
1377
|
+
data-column-fixed={anyColumnFixed}
|
|
1375
1378
|
style={wrapStyle}
|
|
1376
1379
|
id={id}
|
|
1377
1380
|
>
|
|
@@ -76,6 +76,8 @@ export { default as ScrollBar } from './ScrollBar';
|
|
|
76
76
|
export { default as TableSpan } from './TableSpan';
|
|
77
77
|
export { default as FixRenderReturnProps } from './FixRenderReturnProps';
|
|
78
78
|
export { default as WarnColumnWithoutDataIndex } from './WarnColumnWithoutDataIndex';
|
|
79
|
+
export { default as FixedColumnsChange } from './v2/FixedColumnsChange';
|
|
80
|
+
export { default as FixedZIndex } from './v2/FixedZIndex';
|
|
79
81
|
|
|
80
82
|
// empty table
|
|
81
83
|
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import React, { useState, useMemo } from 'react';
|
|
2
|
+
import { Table, Avatar } from '@douyinfe/semi-ui';
|
|
3
|
+
import * as dateFns from 'date-fns';
|
|
4
|
+
|
|
5
|
+
const DAY = 24 * 60 * 60 * 1000;
|
|
6
|
+
const figmaIconUrl = 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/figma-icon.png';
|
|
7
|
+
|
|
8
|
+
const getData = () => {
|
|
9
|
+
const data = [];
|
|
10
|
+
for (let i = 0; i < 46; i++) {
|
|
11
|
+
const isSemiDesign = i % 2 === 0;
|
|
12
|
+
const randomNumber = (i * 1000) % 199;
|
|
13
|
+
data.push({
|
|
14
|
+
key: '' + i,
|
|
15
|
+
name: isSemiDesign ? `Semi Design 设计稿${i}.fig` : `Semi Pro 设计稿${i}.fig`,
|
|
16
|
+
owner: isSemiDesign ? '姜鹏志' : '郝宣',
|
|
17
|
+
size: randomNumber,
|
|
18
|
+
updateTime: new Date('2022-01-01').valueOf() + randomNumber * DAY,
|
|
19
|
+
avatarBg: isSemiDesign ? 'grey' : 'red'
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
return data;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const data = getData();
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* fix https://github.com/DouyinFE/semi-design/issues/381
|
|
29
|
+
*/
|
|
30
|
+
App.storyName = 'fixed columns change';
|
|
31
|
+
function App() {
|
|
32
|
+
const [dataSource, setData] = useState(data);
|
|
33
|
+
const [rowKeys, setRowKeys] = useState([]);
|
|
34
|
+
|
|
35
|
+
const columns = [
|
|
36
|
+
{
|
|
37
|
+
title: '标题',
|
|
38
|
+
dataIndex: 'name',
|
|
39
|
+
width: 400,
|
|
40
|
+
render: (text, record, index) => {
|
|
41
|
+
return (
|
|
42
|
+
<div>
|
|
43
|
+
<Avatar size="small" shape="square" src={figmaIconUrl} style={{ marginRight: 12 }}></Avatar>
|
|
44
|
+
{text}
|
|
45
|
+
</div>
|
|
46
|
+
);
|
|
47
|
+
},
|
|
48
|
+
filters: [
|
|
49
|
+
{
|
|
50
|
+
text: 'Semi Design 设计稿',
|
|
51
|
+
value: 'Semi Design 设计稿',
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
text: 'Semi Pro 设计稿',
|
|
55
|
+
value: 'Semi Pro 设计稿',
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
onFilter: (value, record) => record.name.includes(value),
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
title: '大小',
|
|
62
|
+
dataIndex: 'size',
|
|
63
|
+
sorter: (a, b) => a.size - b.size > 0 ? 1 : -1,
|
|
64
|
+
render: (text) => `${text} KB`
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
title: '所有者',
|
|
68
|
+
dataIndex: 'owner',
|
|
69
|
+
render: (text, record, index) => {
|
|
70
|
+
return (
|
|
71
|
+
<div>
|
|
72
|
+
<Avatar size="small" color={record.avatarBg} style={{ marginRight: 4 }}>{typeof text === 'string' && text.slice(0, 1)}</Avatar>
|
|
73
|
+
{text}
|
|
74
|
+
</div>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
title: '更新日期',
|
|
80
|
+
dataIndex: 'updateTime',
|
|
81
|
+
sorter: (a, b) => a.updateTime - b.updateTime > 0 ? 1 : -1,
|
|
82
|
+
render: (value) => {
|
|
83
|
+
return dateFns.format(new Date(value), 'yyyy-MM-dd');
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
];
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
<Table
|
|
90
|
+
columns={columns}
|
|
91
|
+
dataSource={dataSource}
|
|
92
|
+
pagination={{
|
|
93
|
+
pageSize: 5,
|
|
94
|
+
}}
|
|
95
|
+
rowSelection={{
|
|
96
|
+
onChange: rowKeys => setRowKeys(rowKeys),
|
|
97
|
+
selectedRowKeys: rowKeys,
|
|
98
|
+
}}
|
|
99
|
+
scroll={{ y: 300 }}
|
|
100
|
+
/>
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export default App;
|
|
@@ -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
|
+
}
|
|
@@ -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,
|
|
@@ -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
|
+
};
|
package/tooltip/index.tsx
CHANGED
|
@@ -12,7 +12,7 @@ import { ArrayElement } from '@douyinfe/semi-foundation/utils/type';
|
|
|
12
12
|
import { convertDOMRectToObject, DOMRectLikeType } from '@douyinfe/semi-foundation/utils/dom';
|
|
13
13
|
import TooltipFoundation, { TooltipAdapter, Position, PopupContainerDOMRect } from '@douyinfe/semi-foundation/tooltip/foundation';
|
|
14
14
|
import { strings, cssClasses, numbers } from '@douyinfe/semi-foundation/tooltip/constants';
|
|
15
|
-
import {
|
|
15
|
+
import { getUuidShort } from '@douyinfe/semi-foundation/utils/uuid';
|
|
16
16
|
import '@douyinfe/semi-foundation/tooltip/tooltip.scss';
|
|
17
17
|
|
|
18
18
|
import BaseComponent, { BaseProps } from '../_base/baseComponent';
|
|
@@ -174,7 +174,7 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
|
|
|
174
174
|
placement: props.position || 'top',
|
|
175
175
|
transitionStyle: {},
|
|
176
176
|
isPositionUpdated: false,
|
|
177
|
-
id:
|
|
177
|
+
id: getUuidShort(), // auto generate id, will be used by children.aria-describedby & content.id, improve a11y
|
|
178
178
|
};
|
|
179
179
|
this.foundation = new TooltipFoundation(this.adapter);
|
|
180
180
|
this.eventManager = new Event();
|
|
@@ -540,6 +540,7 @@ export default class Tooltip extends BaseComponent<TooltipProps, TooltipState> {
|
|
|
540
540
|
|
|
541
541
|
return (
|
|
542
542
|
<Portal getPopupContainer={this.props.getPopupContainer} style={{ zIndex }}>
|
|
543
|
+
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */}
|
|
543
544
|
<div
|
|
544
545
|
className={`${BASE_CLASS_PREFIX}-portal-inner`}
|
|
545
546
|
style={portalInnerStyle}
|
package/tree/treeNode.tsx
CHANGED
|
@@ -3,7 +3,7 @@ import cls from 'classnames';
|
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
4
|
import { cssClasses } from '@douyinfe/semi-foundation/tree/constants';
|
|
5
5
|
import isEnterPress from '@douyinfe/semi-foundation/utils/isEnterPress';
|
|
6
|
-
import { debounce, isFunction, isString, get } from 'lodash';
|
|
6
|
+
import { debounce, isFunction, isString, get, isEmpty } from 'lodash';
|
|
7
7
|
import { IconTreeTriangleDown, IconFile, IconFolder, IconFolderOpen } from '@douyinfe/semi-icons';
|
|
8
8
|
import { Checkbox } from '../checkbox';
|
|
9
9
|
import TreeContext from './treeContext';
|
|
@@ -392,7 +392,14 @@ export default class TreeNode extends PureComponent<TreeNodeProps, TreeNodeState
|
|
|
392
392
|
...dragProps
|
|
393
393
|
});
|
|
394
394
|
} else {
|
|
395
|
-
|
|
395
|
+
if (isEmpty(style)) {
|
|
396
|
+
return customLabel;
|
|
397
|
+
} else {
|
|
398
|
+
// In virtualization, props.style will contain location information
|
|
399
|
+
return React.cloneElement(customLabel, {
|
|
400
|
+
style: { ...get(customLabel, ['props', 'style']), ...style }
|
|
401
|
+
});
|
|
402
|
+
}
|
|
396
403
|
}
|
|
397
404
|
}
|
|
398
405
|
const labelCls = cls(`${prefixcls}-label`, {
|
|
@@ -97,6 +97,26 @@ const treeData2 = [
|
|
|
97
97
|
}
|
|
98
98
|
];
|
|
99
99
|
|
|
100
|
+
const treeData3 = [
|
|
101
|
+
{
|
|
102
|
+
label: '亚洲',
|
|
103
|
+
value: 'Asia',
|
|
104
|
+
key: '0',
|
|
105
|
+
children: [
|
|
106
|
+
{
|
|
107
|
+
label: '中国',
|
|
108
|
+
value: 'China',
|
|
109
|
+
key: '0-0',
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
label: '北美洲',
|
|
115
|
+
value: 'North America',
|
|
116
|
+
key: '1',
|
|
117
|
+
}
|
|
118
|
+
];
|
|
119
|
+
|
|
100
120
|
let commonProps = {
|
|
101
121
|
motion: false,
|
|
102
122
|
motionExpand: false,
|
|
@@ -780,4 +800,141 @@ describe('TreeSelect', () => {
|
|
|
780
800
|
done();
|
|
781
801
|
}, 100);
|
|
782
802
|
});
|
|
803
|
+
|
|
804
|
+
it('treeData is updated should not clear value when uncontrolled mode and single selection', () => {
|
|
805
|
+
const nativeEvent = { nativeEvent: { stopImmediatePropagation: () => { } } }
|
|
806
|
+
const treeSelect = getTreeSelect({
|
|
807
|
+
defaultExpandAll: true
|
|
808
|
+
});
|
|
809
|
+
treeSelect
|
|
810
|
+
.find(`.${BASE_CLASS_PREFIX}-tree-option-list .${BASE_CLASS_PREFIX}-tree-option`)
|
|
811
|
+
.at(2)
|
|
812
|
+
.simulate('click', nativeEvent);
|
|
813
|
+
expect(
|
|
814
|
+
treeSelect
|
|
815
|
+
.find(`.${BASE_CLASS_PREFIX}-tree-select .${BASE_CLASS_PREFIX}-tree-select-selection span`)
|
|
816
|
+
.getDOMNode()
|
|
817
|
+
.textContent
|
|
818
|
+
).toEqual('北京');
|
|
819
|
+
treeSelect.setProps({ treeData: treeChildren});
|
|
820
|
+
treeSelect.update();
|
|
821
|
+
expect(
|
|
822
|
+
treeSelect
|
|
823
|
+
.find(`.${BASE_CLASS_PREFIX}-tree-select .${BASE_CLASS_PREFIX}-tree-select-selection span`)
|
|
824
|
+
.getDOMNode()
|
|
825
|
+
.textContent
|
|
826
|
+
).toEqual('北京');
|
|
827
|
+
treeSelect.setProps({ treeData: treeData2});
|
|
828
|
+
treeSelect.update();
|
|
829
|
+
expect(
|
|
830
|
+
treeSelect
|
|
831
|
+
.find(`.${BASE_CLASS_PREFIX}-tree-select .${BASE_CLASS_PREFIX}-tree-select-selection span`)
|
|
832
|
+
.getDOMNode()
|
|
833
|
+
.textContent
|
|
834
|
+
).toEqual('');
|
|
835
|
+
});
|
|
836
|
+
|
|
837
|
+
it('treeData is updated should not clear value when uncontrolled mode and multiple selection', () => {
|
|
838
|
+
const nativeEvent = { nativeEvent: { stopImmediatePropagation: () => { } } }
|
|
839
|
+
const treeSelect = getTreeSelect({
|
|
840
|
+
defaultExpandAll: true,
|
|
841
|
+
multiple: true,
|
|
842
|
+
});
|
|
843
|
+
treeSelect
|
|
844
|
+
.find(`.${BASE_CLASS_PREFIX}-tree-option-list .${BASE_CLASS_PREFIX}-tree-option`)
|
|
845
|
+
.at(2)
|
|
846
|
+
.simulate('click', nativeEvent);
|
|
847
|
+
expect(
|
|
848
|
+
treeSelect
|
|
849
|
+
.find(`.${BASE_CLASS_PREFIX}-tree-select-selection .${BASE_CLASS_PREFIX}-tag-group .${BASE_CLASS_PREFIX}-tag`)
|
|
850
|
+
.at(0)
|
|
851
|
+
.find(`.${BASE_CLASS_PREFIX}-tag-content`)
|
|
852
|
+
.getDOMNode()
|
|
853
|
+
.textContent
|
|
854
|
+
).toEqual('北京');
|
|
855
|
+
treeSelect.setProps({ treeData: treeChildren});
|
|
856
|
+
treeSelect.update();
|
|
857
|
+
expect(
|
|
858
|
+
treeSelect
|
|
859
|
+
.find(`.${BASE_CLASS_PREFIX}-tree-select-selection .${BASE_CLASS_PREFIX}-tag-group .${BASE_CLASS_PREFIX}-tag`)
|
|
860
|
+
.at(0)
|
|
861
|
+
.find(`.${BASE_CLASS_PREFIX}-tag-content`)
|
|
862
|
+
.getDOMNode()
|
|
863
|
+
.textContent
|
|
864
|
+
).toEqual('北京');
|
|
865
|
+
treeSelect.setProps({ treeData: treeData2});
|
|
866
|
+
treeSelect.update();
|
|
867
|
+
expect(
|
|
868
|
+
treeSelect
|
|
869
|
+
.find(`.${BASE_CLASS_PREFIX}-tree-select-selection .${BASE_CLASS_PREFIX}-tag-group .${BASE_CLASS_PREFIX}-tag`)
|
|
870
|
+
.at(0)
|
|
871
|
+
.find(`.${BASE_CLASS_PREFIX}-tag-content`)
|
|
872
|
+
.length
|
|
873
|
+
).toEqual(0);
|
|
874
|
+
});
|
|
875
|
+
|
|
876
|
+
it('treeData is updated should not clear value when controlled mode and single selection', () => {
|
|
877
|
+
const treeSelect = getTreeSelect({
|
|
878
|
+
defaultExpandAll: true,
|
|
879
|
+
value: 'Beijing'
|
|
880
|
+
});
|
|
881
|
+
expect(
|
|
882
|
+
treeSelect
|
|
883
|
+
.find(`.${BASE_CLASS_PREFIX}-tree-select .${BASE_CLASS_PREFIX}-tree-select-selection span`)
|
|
884
|
+
.getDOMNode()
|
|
885
|
+
.textContent
|
|
886
|
+
).toEqual('北京');
|
|
887
|
+
treeSelect.setProps({ treeData: treeChildren});
|
|
888
|
+
treeSelect.update();
|
|
889
|
+
expect(
|
|
890
|
+
treeSelect
|
|
891
|
+
.find(`.${BASE_CLASS_PREFIX}-tree-select .${BASE_CLASS_PREFIX}-tree-select-selection span`)
|
|
892
|
+
.getDOMNode()
|
|
893
|
+
.textContent
|
|
894
|
+
).toEqual('北京');
|
|
895
|
+
treeSelect.setProps({ treeData: treeData3});
|
|
896
|
+
treeSelect.update();
|
|
897
|
+
expect(
|
|
898
|
+
treeSelect
|
|
899
|
+
.find(`.${BASE_CLASS_PREFIX}-tree-select .${BASE_CLASS_PREFIX}-tree-select-selection span`)
|
|
900
|
+
.getDOMNode()
|
|
901
|
+
.textContent
|
|
902
|
+
).toEqual('');
|
|
903
|
+
});
|
|
904
|
+
|
|
905
|
+
it('treeData is updated should not clear value when controlled mode and multiple selection', () => {
|
|
906
|
+
const treeSelect = getTreeSelect({
|
|
907
|
+
defaultExpandAll: true,
|
|
908
|
+
multiple: true,
|
|
909
|
+
value: 'Beijing'
|
|
910
|
+
});
|
|
911
|
+
expect(
|
|
912
|
+
treeSelect
|
|
913
|
+
.find(`.${BASE_CLASS_PREFIX}-tree-select-selection .${BASE_CLASS_PREFIX}-tag-group .${BASE_CLASS_PREFIX}-tag`)
|
|
914
|
+
.at(0)
|
|
915
|
+
.find(`.${BASE_CLASS_PREFIX}-tag-content`)
|
|
916
|
+
.getDOMNode()
|
|
917
|
+
.textContent
|
|
918
|
+
).toEqual('北京');
|
|
919
|
+
treeSelect.setProps({ treeData: treeChildren});
|
|
920
|
+
treeSelect.update();
|
|
921
|
+
expect(
|
|
922
|
+
treeSelect
|
|
923
|
+
.find(`.${BASE_CLASS_PREFIX}-tree-select-selection .${BASE_CLASS_PREFIX}-tag-group .${BASE_CLASS_PREFIX}-tag`)
|
|
924
|
+
.at(0)
|
|
925
|
+
.find(`.${BASE_CLASS_PREFIX}-tag-content`)
|
|
926
|
+
.getDOMNode()
|
|
927
|
+
.textContent
|
|
928
|
+
).toEqual('北京');
|
|
929
|
+
treeSelect.setProps({ treeData: treeData3});
|
|
930
|
+
treeSelect.update();
|
|
931
|
+
expect(
|
|
932
|
+
treeSelect
|
|
933
|
+
.find(`.${BASE_CLASS_PREFIX}-tree-select-selection .${BASE_CLASS_PREFIX}-tag-group .${BASE_CLASS_PREFIX}-tag`)
|
|
934
|
+
.at(0)
|
|
935
|
+
.find(`.${BASE_CLASS_PREFIX}-tag-content`)
|
|
936
|
+
.length
|
|
937
|
+
).toEqual(0);
|
|
938
|
+
});
|
|
939
|
+
|
|
783
940
|
})
|