@douyinfe/semi-ui 2.17.0-beta.1 → 2.18.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/anchor/index.tsx +1 -1
- package/anchor/link.tsx +3 -4
- package/autoComplete/__test__/autoComplete.test.js +6 -6
- package/autoComplete/index.tsx +3 -1
- package/autoComplete/option.tsx +164 -0
- package/calendar/__test__/calendar.test.js +21 -2
- package/calendar/_story/calendar.stories.js +31 -0
- package/calendar/index.tsx +3 -1
- package/calendar/interface.ts +2 -1
- package/carousel/index.tsx +5 -5
- package/checkbox/checkbox.tsx +4 -1
- package/dist/css/semi.css +161 -23
- package/dist/css/semi.min.css +1 -1
- package/dist/umd/semi-ui.js +359 -94
- 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/FieldProps/labelOptional.jsx +30 -0
- package/form/_story/form.stories.js +7 -0
- package/form/hoc/withField.tsx +1 -0
- package/form/label.tsx +21 -7
- package/gulpfile.js +3 -1
- package/lib/cjs/_base/base.css +35 -0
- package/lib/cjs/anchor/index.js +2 -1
- package/lib/cjs/anchor/link.d.ts +1 -1
- package/lib/cjs/anchor/link.js +9 -5
- package/lib/cjs/autoComplete/index.d.ts +1 -1
- package/lib/cjs/autoComplete/index.js +6 -3
- package/lib/cjs/autoComplete/option.d.ts +50 -0
- package/lib/cjs/autoComplete/option.js +218 -0
- package/lib/cjs/calendar/index.d.ts +2 -0
- package/lib/cjs/calendar/index.js +3 -1
- package/lib/cjs/calendar/interface.d.ts +2 -1
- package/lib/cjs/carousel/index.js +2 -2
- package/lib/cjs/checkbox/checkbox.js +4 -1
- package/lib/cjs/form/hoc/withField.js +2 -1
- package/lib/cjs/form/label.d.ts +8 -5
- package/lib/cjs/form/label.js +15 -4
- package/lib/cjs/locale/interface.d.ts +3 -0
- package/lib/cjs/locale/source/ar.js +3 -0
- package/lib/cjs/locale/source/de.js +3 -0
- package/lib/cjs/locale/source/en_GB.js +3 -0
- package/lib/cjs/locale/source/en_US.js +3 -0
- package/lib/cjs/locale/source/es.js +3 -0
- package/lib/cjs/locale/source/fr.js +3 -0
- package/lib/cjs/locale/source/id_ID.js +3 -0
- package/lib/cjs/locale/source/it.js +3 -0
- package/lib/cjs/locale/source/ja_JP.js +3 -0
- package/lib/cjs/locale/source/ko_KR.js +3 -0
- package/lib/cjs/locale/source/ms_MY.js +3 -0
- package/lib/cjs/locale/source/pt_BR.js +3 -0
- package/lib/cjs/locale/source/ru_RU.js +3 -0
- package/lib/cjs/locale/source/th_TH.js +3 -0
- package/lib/cjs/locale/source/tr_TR.js +3 -0
- package/lib/cjs/locale/source/vi_VN.js +3 -0
- package/lib/cjs/locale/source/zh_CN.js +3 -0
- package/lib/cjs/locale/source/zh_TW.js +3 -0
- package/lib/cjs/modal/Modal.js +0 -8
- package/lib/cjs/modal/ModalContent.js +4 -1
- package/lib/cjs/tag/group.d.ts +3 -0
- package/lib/cjs/tag/group.js +24 -6
- package/lib/cjs/tag/index.d.ts +2 -1
- package/lib/cjs/tag/index.js +7 -5
- package/lib/cjs/tag/interface.d.ts +2 -1
- package/lib/cjs/tree/index.d.ts +3 -1
- package/lib/cjs/tree/index.js +23 -0
- package/lib/cjs/tree/interface.d.ts +4 -0
- package/lib/es/_base/base.css +35 -0
- package/lib/es/anchor/index.js +2 -1
- package/lib/es/anchor/link.d.ts +1 -1
- package/lib/es/anchor/link.js +9 -5
- package/lib/es/autoComplete/index.d.ts +1 -1
- package/lib/es/autoComplete/index.js +6 -3
- package/lib/es/autoComplete/option.d.ts +50 -0
- package/lib/es/autoComplete/option.js +188 -0
- package/lib/es/calendar/index.d.ts +2 -0
- package/lib/es/calendar/index.js +3 -1
- package/lib/es/calendar/interface.d.ts +2 -1
- package/lib/es/carousel/index.js +2 -2
- package/lib/es/checkbox/checkbox.js +4 -1
- package/lib/es/form/hoc/withField.js +2 -1
- package/lib/es/form/label.d.ts +8 -5
- package/lib/es/form/label.js +13 -4
- package/lib/es/locale/interface.d.ts +3 -0
- package/lib/es/locale/source/ar.js +3 -0
- package/lib/es/locale/source/de.js +3 -0
- package/lib/es/locale/source/en_GB.js +3 -0
- package/lib/es/locale/source/en_US.js +3 -0
- package/lib/es/locale/source/es.js +3 -0
- package/lib/es/locale/source/fr.js +3 -0
- package/lib/es/locale/source/id_ID.js +3 -0
- package/lib/es/locale/source/it.js +3 -0
- package/lib/es/locale/source/ja_JP.js +3 -0
- package/lib/es/locale/source/ko_KR.js +3 -0
- package/lib/es/locale/source/ms_MY.js +3 -0
- package/lib/es/locale/source/pt_BR.js +3 -0
- package/lib/es/locale/source/ru_RU.js +3 -0
- package/lib/es/locale/source/th_TH.js +3 -0
- package/lib/es/locale/source/tr_TR.js +3 -0
- package/lib/es/locale/source/vi_VN.js +3 -0
- package/lib/es/locale/source/zh_CN.js +3 -0
- package/lib/es/locale/source/zh_TW.js +3 -0
- package/lib/es/modal/Modal.js +0 -8
- package/lib/es/modal/ModalContent.js +4 -1
- package/lib/es/tag/group.d.ts +3 -0
- package/lib/es/tag/group.js +24 -6
- package/lib/es/tag/index.d.ts +2 -1
- package/lib/es/tag/index.js +7 -5
- package/lib/es/tag/interface.d.ts +2 -1
- package/lib/es/tree/index.d.ts +3 -1
- package/lib/es/tree/index.js +22 -0
- package/lib/es/tree/interface.d.ts +4 -0
- package/locale/interface.ts +3 -0
- package/locale/source/ar.ts +3 -0
- package/locale/source/de.ts +3 -0
- package/locale/source/en_GB.ts +3 -0
- package/locale/source/en_US.ts +3 -0
- package/locale/source/es.ts +3 -0
- package/locale/source/fr.ts +3 -0
- package/locale/source/id_ID.ts +3 -0
- package/locale/source/it.ts +3 -0
- package/locale/source/ja_JP.ts +3 -0
- package/locale/source/ko_KR.ts +3 -0
- package/locale/source/ms_MY.ts +3 -0
- package/locale/source/pt_BR.ts +3 -0
- package/locale/source/ru_RU.ts +3 -0
- package/locale/source/th_TH.ts +3 -0
- package/locale/source/tr_TR.ts +4 -1
- package/locale/source/vi_VN.ts +3 -0
- package/locale/source/zh_CN.ts +3 -0
- package/locale/source/zh_TW.ts +3 -0
- package/modal/Modal.tsx +0 -6
- package/modal/ModalContent.tsx +4 -1
- package/modal/__test__/modal.test.js +1 -1
- package/modal/_story/__snapshots__/modal.stories.tsx.snap +203 -0
- package/package.json +7 -7
- package/radio/_story/radio.stories.js +2 -2
- package/rating/__test__/rating.test.js +1 -1
- package/select/__test__/select.test.js +11 -17
- package/select/_story/select.stories.js +6 -6
- package/steps/_story/steps.stories.js +3 -3
- package/switch/_story/switch.stories.js +4 -4
- package/switch/_story/switch.stories.tsx +4 -4
- package/table/_story/v2/FixedFilter/index.tsx +106 -0
- package/table/_story/v2/FixedSorter/index.tsx +102 -0
- package/table/_story/v2/index.js +4 -2
- package/tag/_story/tag.stories.js +57 -1
- package/tag/group.tsx +20 -3
- package/tag/index.tsx +6 -5
- package/tag/interface.ts +2 -1
- package/transfer/_story/transfer.stories.js +2 -2
- package/tree/_story/tree.stories.js +152 -3
- package/tree/index.tsx +16 -1
- package/tree/interface.ts +6 -0
- package/upload/_story/upload.stories.js +2 -2
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
// eslint-disable-next-line semi-design/no-import
|
|
3
|
+
import { Table } from '@douyinfe/semi-ui';
|
|
4
|
+
// eslint-disable-next-line semi-design/no-import
|
|
5
|
+
import { ChangeInfo } from '@douyinfe/semi-ui/table';
|
|
6
|
+
|
|
7
|
+
const data = [
|
|
8
|
+
{
|
|
9
|
+
key: 'a',
|
|
10
|
+
group: 'yes',
|
|
11
|
+
count: 3,
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
key: 'b',
|
|
15
|
+
group: 'no',
|
|
16
|
+
count: 3,
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
key: 'c',
|
|
20
|
+
group: 'no',
|
|
21
|
+
count: 1,
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
key: 'd',
|
|
25
|
+
group: 'yes',
|
|
26
|
+
count: 1,
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
key: 'e',
|
|
30
|
+
group: 'no',
|
|
31
|
+
count: 2,
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
key: 'f',
|
|
35
|
+
group: 'yes',
|
|
36
|
+
count: 2,
|
|
37
|
+
}
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
Demo.storyName = 'fixed sorter';
|
|
41
|
+
/**
|
|
42
|
+
* 保持分组顺序不变的排序方式
|
|
43
|
+
*/
|
|
44
|
+
function Demo() {
|
|
45
|
+
const [filtered, setFiltered] = useState([...data]);
|
|
46
|
+
console.log(filtered);
|
|
47
|
+
const columns = [
|
|
48
|
+
{
|
|
49
|
+
title: 'ID',
|
|
50
|
+
dataIndex: 'key',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
title: 'group',
|
|
54
|
+
dataIndex: 'Group',
|
|
55
|
+
sorter: (a, b) => a.group === 'yes' ? -1 : 1,
|
|
56
|
+
// sortOrder: 'ascend'
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
title: 'Count',
|
|
60
|
+
dataIndex: 'count',
|
|
61
|
+
// sorter: true
|
|
62
|
+
sorter: (a, b) => a.count - b.count > 0 ? 1 : -1,
|
|
63
|
+
},
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
const onTableChange = ({ sorter }: ChangeInfo<any>) => {
|
|
67
|
+
if (sorter) {
|
|
68
|
+
const { dataIndex, sortOrder } = sorter;
|
|
69
|
+
setFiltered(prev => [...prev].sort((a, b) => {
|
|
70
|
+
if (a.group !== b.group) {
|
|
71
|
+
return a.group === 'yes' ? -1 : 1;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
let ascendValue = -1;
|
|
75
|
+
if (dataIndex === 'count') {
|
|
76
|
+
ascendValue = a.count - b.count > 0 ? 1 : -1;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return sortOrder === 'ascend' ? ascendValue : -ascendValue;
|
|
80
|
+
}));
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<div style={{ padding: '20px 0px' }}>
|
|
87
|
+
<Table
|
|
88
|
+
dataSource={filtered}
|
|
89
|
+
onChange={onTableChange}
|
|
90
|
+
rowKey="key"
|
|
91
|
+
groupBy="group"
|
|
92
|
+
columns={columns}
|
|
93
|
+
renderGroupSection={groupKey => <strong>分组 {groupKey}</strong>}
|
|
94
|
+
expandAllGroupRows
|
|
95
|
+
scroll={{ y: 480 }}
|
|
96
|
+
pagination={{ pageSize: 4 }}
|
|
97
|
+
/>
|
|
98
|
+
</div>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export default Demo;
|
package/table/_story/v2/index.js
CHANGED
|
@@ -4,7 +4,9 @@ export { default as FixedZIndex } from './FixedZIndex';
|
|
|
4
4
|
export { default as FixedHeaderMerge } from './FixedHeaderMerge';
|
|
5
5
|
export { default as FixedResizable } from './FixedResizable';
|
|
6
6
|
export { default as FixedExpandedRow } from './FixedExpandedRow';
|
|
7
|
-
export { default as FixedMemoryLeak
|
|
7
|
+
export { default as FixedMemoryLeak } from './FixedMemoryLeak';
|
|
8
8
|
export { default as FixedOnHeaderRow } from './FixedOnHeaderRow';
|
|
9
9
|
export { default as RadioRowSelection } from './radioRowSelection';
|
|
10
|
-
export { default as FixedVirtualizedEmpty } from './FixedVirtualizedEmpty';
|
|
10
|
+
export { default as FixedVirtualizedEmpty } from './FixedVirtualizedEmpty';
|
|
11
|
+
export { default as FixedFilter } from './FixedFilter';
|
|
12
|
+
export { default as FixedSorter } from './FixedSorter';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* argus-disable unPkgSensitiveInfo */
|
|
2
|
-
import React from 'react';
|
|
2
|
+
import React, { useCallback, useState } from 'react';
|
|
3
3
|
import withPropsCombinations from 'react-storybook-addon-props-combinations';
|
|
4
4
|
import { BASE_CLASS_PREFIX } from '../../../semi-foundation/base/constants';
|
|
5
5
|
|
|
@@ -232,3 +232,59 @@ export const AvatarTagGroup = () => <AvatarTagGroupDemo />;
|
|
|
232
232
|
AvatarTagGroup.story = {
|
|
233
233
|
name: 'avatar tagGroup',
|
|
234
234
|
};
|
|
235
|
+
|
|
236
|
+
class TagGroupCloseableDemo extends React.Component {
|
|
237
|
+
constructor(props){
|
|
238
|
+
super(props);
|
|
239
|
+
this.state = {
|
|
240
|
+
tagList: [
|
|
241
|
+
{ tagKey: '1', color: 'white', children: '抖音', closable: true,},
|
|
242
|
+
{ tagKey: '2',color: 'white', children: '火山小视频', closable: true,},
|
|
243
|
+
{ tagKey: '3',color: 'white', children: '剪映', closable: true,},
|
|
244
|
+
{ tagKey: '4',color: 'white', children: '皮皮虾', closable: true,},
|
|
245
|
+
]
|
|
246
|
+
};
|
|
247
|
+
this.tagListClick = this.tagListClick.bind(this);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
tagListClick(value, e, tagKey){
|
|
251
|
+
const newTagList = [...this.state.tagList];
|
|
252
|
+
const closeTagIndex = newTagList.findIndex(t => t.tagKey === tagKey);
|
|
253
|
+
newTagList.splice(closeTagIndex, 1);
|
|
254
|
+
this.setState({
|
|
255
|
+
tagList: newTagList,
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
render() {
|
|
260
|
+
return (
|
|
261
|
+
<div style={ {
|
|
262
|
+
backgroundColor: 'var(--semi-color-fill-0)',
|
|
263
|
+
height: 35,
|
|
264
|
+
width: 300,
|
|
265
|
+
display: 'flex',
|
|
266
|
+
alignItems: 'center',
|
|
267
|
+
padding: '0 10px',
|
|
268
|
+
marginBottom: 30,
|
|
269
|
+
}}>
|
|
270
|
+
<TagGroup
|
|
271
|
+
maxTagCount={3}
|
|
272
|
+
style={ {
|
|
273
|
+
display: 'flex',
|
|
274
|
+
alignItems: 'center',
|
|
275
|
+
width: 350,
|
|
276
|
+
}}
|
|
277
|
+
tagList={this.state.tagList}
|
|
278
|
+
size='large'
|
|
279
|
+
onTagClose={this.tagListClick}
|
|
280
|
+
/>
|
|
281
|
+
</div>
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
export const TagGroupCloseable = () => <TagGroupCloseableDemo />;
|
|
287
|
+
|
|
288
|
+
TagGroupCloseable.story = {
|
|
289
|
+
name: 'tagGroup closable',
|
|
290
|
+
}
|
package/tag/group.tsx
CHANGED
|
@@ -21,6 +21,7 @@ export interface TagGroupProps<T> {
|
|
|
21
21
|
popoverProps?: PopoverProps;
|
|
22
22
|
avatarShape?: AvatarShape;
|
|
23
23
|
mode?: string;
|
|
24
|
+
onTagClose: (tagChildren: React.ReactNode, event: React.MouseEvent<HTMLElement>, tagKey: string | number) => void;
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
export default class TagGroup<T> extends PureComponent<TagGroupProps<T>> {
|
|
@@ -29,6 +30,7 @@ export default class TagGroup<T> extends PureComponent<TagGroupProps<T>> {
|
|
|
29
30
|
className: '',
|
|
30
31
|
size: tagSize[0],
|
|
31
32
|
avatarShape: 'square',
|
|
33
|
+
onTagClose: () => undefined,
|
|
32
34
|
};
|
|
33
35
|
|
|
34
36
|
static propTypes = {
|
|
@@ -40,6 +42,7 @@ export default class TagGroup<T> extends PureComponent<TagGroupProps<T>> {
|
|
|
40
42
|
tagList: PropTypes.array,
|
|
41
43
|
size: PropTypes.oneOf(tagSize),
|
|
42
44
|
mode: PropTypes.string,
|
|
45
|
+
onTagClose: PropTypes.func,
|
|
43
46
|
showPopover: PropTypes.bool,
|
|
44
47
|
popoverProps: PropTypes.object,
|
|
45
48
|
avatarShape: PropTypes.oneOf(avatarShapeSet),
|
|
@@ -95,18 +98,32 @@ export default class TagGroup<T> extends PureComponent<TagGroupProps<T>> {
|
|
|
95
98
|
}
|
|
96
99
|
|
|
97
100
|
renderAllTags() {
|
|
98
|
-
const { tagList, size, mode, avatarShape } = this.props;
|
|
99
|
-
const renderTags = tagList.map((tag
|
|
101
|
+
const { tagList, size, mode, avatarShape, onTagClose } = this.props;
|
|
102
|
+
const renderTags = tagList.map((tag): (Tag | React.ReactNode) => {
|
|
100
103
|
if (mode === 'custom') {
|
|
101
104
|
return tag as React.ReactNode;
|
|
102
105
|
}
|
|
103
106
|
if (!(tag as TagProps).size) {
|
|
104
107
|
(tag as TagProps).size = size;
|
|
105
108
|
}
|
|
109
|
+
|
|
106
110
|
if (!(tag as TagProps).avatarShape) {
|
|
107
111
|
(tag as TagProps).avatarShape = avatarShape;
|
|
108
112
|
}
|
|
109
|
-
|
|
113
|
+
|
|
114
|
+
if (!(tag as TagProps).tagKey) {
|
|
115
|
+
if (typeof (tag as TagProps).children === 'string' || typeof (tag as TagProps).children === 'number') {
|
|
116
|
+
(tag as TagProps).tagKey = (tag as TagProps).children as string | number;
|
|
117
|
+
} else {
|
|
118
|
+
(tag as TagProps).tagKey = Math.random();
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return <Tag {...(tag as TagProps)} key={(tag as TagProps).tagKey} onClose={(tagChildren, e, tagKey) => {
|
|
122
|
+
if ((tag as TagProps).onClose) {
|
|
123
|
+
(tag as TagProps).onClose(tagChildren, e, tagKey);
|
|
124
|
+
}
|
|
125
|
+
onTagClose && onTagClose(tagChildren, e, tagKey);
|
|
126
|
+
}} />;
|
|
110
127
|
});
|
|
111
128
|
return renderTags;
|
|
112
129
|
}
|
package/tag/index.tsx
CHANGED
|
@@ -40,6 +40,7 @@ export default class Tag extends Component<TagProps, TagState> {
|
|
|
40
40
|
|
|
41
41
|
static propTypes = {
|
|
42
42
|
children: PropTypes.node,
|
|
43
|
+
tagKey: PropTypes.oneOf([PropTypes.string, PropTypes.number]),
|
|
43
44
|
size: PropTypes.oneOf(tagSize),
|
|
44
45
|
color: PropTypes.oneOf(tagColors),
|
|
45
46
|
type: PropTypes.oneOf(tagType),
|
|
@@ -79,11 +80,11 @@ export default class Tag extends Component<TagProps, TagState> {
|
|
|
79
80
|
}
|
|
80
81
|
}
|
|
81
82
|
|
|
82
|
-
close(e: React.MouseEvent<HTMLElement>, value: React.ReactNode) {
|
|
83
|
+
close(e: React.MouseEvent<HTMLElement>, value: React.ReactNode, tagKey: string | number) {
|
|
83
84
|
const { onClose } = this.props;
|
|
84
85
|
e.stopPropagation();
|
|
85
86
|
e.nativeEvent.stopImmediatePropagation();
|
|
86
|
-
onClose && onClose(value, e);
|
|
87
|
+
onClose && onClose(value, e, tagKey);
|
|
87
88
|
// when user call e.preventDefault() in onClick callback, tag will not hidden
|
|
88
89
|
if (e.defaultPrevented) {
|
|
89
90
|
return;
|
|
@@ -96,7 +97,7 @@ export default class Tag extends Component<TagProps, TagState> {
|
|
|
96
97
|
switch (event.key) {
|
|
97
98
|
case "Backspace":
|
|
98
99
|
case "Delete":
|
|
99
|
-
closable && this.close(event, this.props.children);
|
|
100
|
+
closable && this.close(event, this.props.children, this.props.tagKey);
|
|
100
101
|
handlePrevent(event);
|
|
101
102
|
break;
|
|
102
103
|
case "Enter":
|
|
@@ -119,7 +120,7 @@ export default class Tag extends Component<TagProps, TagState> {
|
|
|
119
120
|
}
|
|
120
121
|
|
|
121
122
|
render() {
|
|
122
|
-
const { children, size, color, closable, visible, onClose, onClick, className, type, avatarSrc, avatarShape, tabIndex, ...attr } = this.props;
|
|
123
|
+
const { tagKey, children, size, color, closable, visible, onClose, onClick, className, type, avatarSrc, avatarShape, tabIndex, ...attr } = this.props;
|
|
123
124
|
const { visible: isVisible } = this.state;
|
|
124
125
|
const clickable = onClick !== Tag.defaultProps.onClick || closable;
|
|
125
126
|
// only when the Tag is clickable or closable, the value of tabIndex is allowed to be passed in.
|
|
@@ -145,7 +146,7 @@ export default class Tag extends Component<TagProps, TagState> {
|
|
|
145
146
|
const wrapProps = clickable ? ({ ...baseProps, ...a11yProps }) : baseProps;
|
|
146
147
|
const closeIcon = closable ? (
|
|
147
148
|
// eslint-disable-next-line jsx-a11y/click-events-have-key-events
|
|
148
|
-
<div className={`${prefixCls}-close`} onClick={e => this.close(e, children)}>
|
|
149
|
+
<div className={`${prefixCls}-close`} onClick={e => this.close(e, children, tagKey)}>
|
|
149
150
|
<IconClose size="small" />
|
|
150
151
|
</div>
|
|
151
152
|
) : null;
|
package/tag/interface.ts
CHANGED
|
@@ -22,12 +22,13 @@ export type AvatarShape = 'circle' | 'square';
|
|
|
22
22
|
|
|
23
23
|
export interface TagProps {
|
|
24
24
|
children?: React.ReactNode;
|
|
25
|
+
tagKey?: string | number;
|
|
25
26
|
size?: TagSize;
|
|
26
27
|
color?: TagColor;
|
|
27
28
|
type?: TagType;
|
|
28
29
|
closable?: boolean;
|
|
29
30
|
visible?: boolean;
|
|
30
|
-
onClose?: (tagChildren: React.ReactNode, event: React.MouseEvent<HTMLElement
|
|
31
|
+
onClose?: (tagChildren: React.ReactNode, event: React.MouseEvent<HTMLElement>, tagKey: string | number) => void;
|
|
31
32
|
onClick?: React.MouseEventHandler<HTMLDivElement>;
|
|
32
33
|
style?: React.CSSProperties;
|
|
33
34
|
className?: string;
|
|
@@ -195,7 +195,7 @@ TransferDraggableAndDisabled.story = {
|
|
|
195
195
|
}
|
|
196
196
|
|
|
197
197
|
|
|
198
|
-
const
|
|
198
|
+
const ControlledTransfer = () => {
|
|
199
199
|
const [value, setValue] = useState([2, 3]);
|
|
200
200
|
|
|
201
201
|
const handleChange = value => {
|
|
@@ -209,7 +209,7 @@ const ControledTransfer = () => {
|
|
|
209
209
|
);
|
|
210
210
|
};
|
|
211
211
|
|
|
212
|
-
export const ControlledTransfer = () => <
|
|
212
|
+
export const ControlledTransfer = () => <ControlledTransfer />;
|
|
213
213
|
|
|
214
214
|
ControlledTransfer.story = {
|
|
215
215
|
name: '受控Transfer',
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import React, { useRef, useState } from 'react';
|
|
1
|
+
import React, { useRef, useState, useCallback } from 'react';
|
|
2
2
|
import { cloneDeep, difference, isEqual } from 'lodash';
|
|
3
3
|
import { IconEdit, IconMapPin, IconMore } from '@douyinfe/semi-icons';
|
|
4
4
|
import Tree from '../index';
|
|
5
5
|
import AutoSizer from '../autoSizer';
|
|
6
|
-
import { Button, ButtonGroup, Input, Popover, Toast, Space } from '../../index';
|
|
6
|
+
import { Button, ButtonGroup, Input, Popover, Toast, Space, Select, Switch } from '../../index';
|
|
7
7
|
import BigTree from './BigData';
|
|
8
8
|
import testData from './data';
|
|
9
9
|
const TreeNode = Tree.TreeNode;
|
|
@@ -2398,4 +2398,153 @@ export const ValueImpactExpansionWithDynamicTreeData = () => {
|
|
|
2398
2398
|
</Space>
|
|
2399
2399
|
</>
|
|
2400
2400
|
)
|
|
2401
|
-
}
|
|
2401
|
+
}
|
|
2402
|
+
|
|
2403
|
+
class DemoV extends React.Component {
|
|
2404
|
+
constructor() {
|
|
2405
|
+
super();
|
|
2406
|
+
this.state = {
|
|
2407
|
+
gData: [],
|
|
2408
|
+
total: 0,
|
|
2409
|
+
align: 'center',
|
|
2410
|
+
scrollKey: '',
|
|
2411
|
+
expandAll: false,
|
|
2412
|
+
};
|
|
2413
|
+
this.onGen = this.onGen.bind(this);
|
|
2414
|
+
this.onScroll = this.onScroll.bind(this);
|
|
2415
|
+
this.onInputChange = this.onInputChange.bind(this);
|
|
2416
|
+
this.onInputBlur = this.onInputBlur.bind(this);
|
|
2417
|
+
this.onSelectChange = this.onSelectChange.bind(this);
|
|
2418
|
+
this.treeRef = React.createRef();
|
|
2419
|
+
}
|
|
2420
|
+
|
|
2421
|
+
generateData(x = 5, y = 4, z = 3, gData = []) {
|
|
2422
|
+
// x:每一级下的节点总数。y:每级节点里有y个节点、存在子节点。z:树的level层级数(0表示一级)
|
|
2423
|
+
function _loop(_level, _preKey, _tns) {
|
|
2424
|
+
const preKey = _preKey || '0';
|
|
2425
|
+
const tns = _tns || gData;
|
|
2426
|
+
|
|
2427
|
+
const children = [];
|
|
2428
|
+
for (let i = 0; i < x; i++) {
|
|
2429
|
+
const key = `${preKey}-${i}`;
|
|
2430
|
+
tns.push({ label: `${key}-标签`, key: `${key}-key`, value: `${key}-value` });
|
|
2431
|
+
if (i < y) {
|
|
2432
|
+
children.push(key);
|
|
2433
|
+
}
|
|
2434
|
+
}
|
|
2435
|
+
if (_level < 0) {
|
|
2436
|
+
return tns;
|
|
2437
|
+
}
|
|
2438
|
+
const __level = _level - 1;
|
|
2439
|
+
children.forEach((key, index) => {
|
|
2440
|
+
tns[index].children = [];
|
|
2441
|
+
return _loop(__level, key, tns[index].children);
|
|
2442
|
+
});
|
|
2443
|
+
|
|
2444
|
+
return null;
|
|
2445
|
+
}
|
|
2446
|
+
_loop(z);
|
|
2447
|
+
|
|
2448
|
+
function calcTotal(x, y, z) {
|
|
2449
|
+
const rec = n => (n >= 0 ? x * y ** n-- + rec(n) : 0);
|
|
2450
|
+
return rec(z + 1);
|
|
2451
|
+
}
|
|
2452
|
+
return { gData, total: calcTotal(x, y, z) };
|
|
2453
|
+
}
|
|
2454
|
+
|
|
2455
|
+
onGen() {
|
|
2456
|
+
const { gData, total } = this.generateData();
|
|
2457
|
+
this.setState({
|
|
2458
|
+
gData,
|
|
2459
|
+
total
|
|
2460
|
+
});
|
|
2461
|
+
};
|
|
2462
|
+
|
|
2463
|
+
onScroll(scrollKey, align) {
|
|
2464
|
+
this.treeRef?.current.scrollTo({ key: scrollKey, align});
|
|
2465
|
+
}
|
|
2466
|
+
|
|
2467
|
+
onInputChange(value) {
|
|
2468
|
+
this.setState({
|
|
2469
|
+
scrollKey: value,
|
|
2470
|
+
})
|
|
2471
|
+
}
|
|
2472
|
+
|
|
2473
|
+
onInputBlur(e) {
|
|
2474
|
+
const { value } = e.target;
|
|
2475
|
+
this.onScroll(value, this.state.align);
|
|
2476
|
+
}
|
|
2477
|
+
|
|
2478
|
+
onSelectChange(align){
|
|
2479
|
+
this.setState({
|
|
2480
|
+
align: align,
|
|
2481
|
+
})
|
|
2482
|
+
this.onScroll(this.state.scrollKey, align);
|
|
2483
|
+
}
|
|
2484
|
+
|
|
2485
|
+
render() {
|
|
2486
|
+
const style = {
|
|
2487
|
+
width: 260,
|
|
2488
|
+
border: '1px solid var(--semi-color-border)'
|
|
2489
|
+
};
|
|
2490
|
+
return (
|
|
2491
|
+
<div style={{ padding: '0 20px' }}>
|
|
2492
|
+
<Button onClick={this.onGen}>生成数据: </Button>
|
|
2493
|
+
<span>共 {this.state.total} 个节点</span>
|
|
2494
|
+
<br/>
|
|
2495
|
+
<br/>
|
|
2496
|
+
<div style={{ display: 'flex', alignItems: 'center', }}>
|
|
2497
|
+
<span>defaultExpandAll</span>
|
|
2498
|
+
<Switch onChange={(value) => {
|
|
2499
|
+
this.setState({
|
|
2500
|
+
expandAll: value,
|
|
2501
|
+
})
|
|
2502
|
+
}}/>
|
|
2503
|
+
</div>
|
|
2504
|
+
<br/>
|
|
2505
|
+
<span>跳转的key:</span>
|
|
2506
|
+
<Input
|
|
2507
|
+
placeholder={'格式:x-x-key'}
|
|
2508
|
+
style={{ width: 180, marginRight: 20 }}
|
|
2509
|
+
onChange={this.onInputChange}
|
|
2510
|
+
onBlur={this.onInputBlur}
|
|
2511
|
+
></Input>
|
|
2512
|
+
<span>scroll align:</span>
|
|
2513
|
+
<Select
|
|
2514
|
+
defaultValue='center'
|
|
2515
|
+
style={{ width: 180 }}
|
|
2516
|
+
optionList={['center', 'start', 'end', 'smart', 'auto'].map(item => ({
|
|
2517
|
+
value: item,
|
|
2518
|
+
label: item,
|
|
2519
|
+
}))}
|
|
2520
|
+
onChange={this.onSelectChange}
|
|
2521
|
+
>
|
|
2522
|
+
</Select>
|
|
2523
|
+
<br />
|
|
2524
|
+
<br />
|
|
2525
|
+
{this.state.gData.length ? (
|
|
2526
|
+
<Tree
|
|
2527
|
+
key={`key-${this.state.expandAll}`}
|
|
2528
|
+
ref={this.treeRef}
|
|
2529
|
+
defaultExpandAll={this.state.expandAll}
|
|
2530
|
+
treeData={this.state.gData}
|
|
2531
|
+
filterTreeNode
|
|
2532
|
+
showFilteredOnly
|
|
2533
|
+
style={style}
|
|
2534
|
+
virtualize={{
|
|
2535
|
+
// if set height for tree, it will fill 100%
|
|
2536
|
+
height: 300,
|
|
2537
|
+
itemSize: 28,
|
|
2538
|
+
}}
|
|
2539
|
+
/>
|
|
2540
|
+
) : null}
|
|
2541
|
+
</div>
|
|
2542
|
+
);
|
|
2543
|
+
}
|
|
2544
|
+
}
|
|
2545
|
+
|
|
2546
|
+
export const virtualizeTree = () => <DemoV />;
|
|
2547
|
+
|
|
2548
|
+
virtualizeTree.story = {
|
|
2549
|
+
name: 'virtualize tree',
|
|
2550
|
+
};
|
package/tree/index.tsx
CHANGED
|
@@ -39,7 +39,8 @@ import {
|
|
|
39
39
|
TreeNodeData,
|
|
40
40
|
FlattenNode,
|
|
41
41
|
KeyEntity,
|
|
42
|
-
OptionProps
|
|
42
|
+
OptionProps,
|
|
43
|
+
ScrollData,
|
|
43
44
|
} from './interface';
|
|
44
45
|
import CheckboxGroup from '../checkbox/checkboxGroup';
|
|
45
46
|
|
|
@@ -146,6 +147,7 @@ class Tree extends BaseComponent<TreeProps, TreeState> {
|
|
|
146
147
|
onNodeClick: any;
|
|
147
148
|
onMotionEnd: any;
|
|
148
149
|
context: ContextValue;
|
|
150
|
+
virtualizedListRef: React.RefObject<any>;
|
|
149
151
|
|
|
150
152
|
constructor(props: TreeProps) {
|
|
151
153
|
super(props);
|
|
@@ -179,6 +181,7 @@ class Tree extends BaseComponent<TreeProps, TreeState> {
|
|
|
179
181
|
this.optionsRef = React.createRef();
|
|
180
182
|
this.foundation = new TreeFoundation(this.adapter);
|
|
181
183
|
this.dragNode = null;
|
|
184
|
+
this.virtualizedListRef = React.createRef();
|
|
182
185
|
}
|
|
183
186
|
|
|
184
187
|
/**
|
|
@@ -493,6 +496,17 @@ class Tree extends BaseComponent<TreeProps, TreeState> {
|
|
|
493
496
|
this.foundation.handleInputChange(value);
|
|
494
497
|
};
|
|
495
498
|
|
|
499
|
+
scrollTo = (scrollData: ScrollData) => {
|
|
500
|
+
const { key, align = 'center' } = scrollData;
|
|
501
|
+
const { flattenNodes } = this.state;
|
|
502
|
+
if (key) {
|
|
503
|
+
const index = flattenNodes?.findIndex((node) => {
|
|
504
|
+
return node.key === key;
|
|
505
|
+
});
|
|
506
|
+
index >= 0 && (this.virtualizedListRef.current as any)?.scrollToItem(index, align);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
496
510
|
renderInput() {
|
|
497
511
|
const {
|
|
498
512
|
searchClassName,
|
|
@@ -664,6 +678,7 @@ class Tree extends BaseComponent<TreeProps, TreeState> {
|
|
|
664
678
|
<AutoSizer defaultHeight={virtualize.height} defaultWidth={virtualize.width}>
|
|
665
679
|
{({ height, width }: { width: string | number; height: string | number }) => (
|
|
666
680
|
<VirtualList
|
|
681
|
+
ref={this.virtualizedListRef}
|
|
667
682
|
itemCount={flattenNodes.length}
|
|
668
683
|
itemSize={virtualize.itemSize}
|
|
669
684
|
height={height}
|
package/tree/interface.ts
CHANGED
|
@@ -140,3 +140,9 @@ export interface NodeListState {
|
|
|
140
140
|
cachedMotionKeys?: Set<string>;
|
|
141
141
|
cachedData?: FlattenNode[];
|
|
142
142
|
}
|
|
143
|
+
|
|
144
|
+
export interface ScrollData {
|
|
145
|
+
key: string;
|
|
146
|
+
// The align parameter is consistent with react-window
|
|
147
|
+
align?: 'center' | 'start' | 'end' | 'smart' | 'auto';
|
|
148
|
+
}
|
|
@@ -311,7 +311,7 @@ DefaultFileList.story = {
|
|
|
311
311
|
name: 'defaultFileList',
|
|
312
312
|
};
|
|
313
313
|
|
|
314
|
-
class
|
|
314
|
+
class ControlledUpload extends React.Component {
|
|
315
315
|
constructor(props) {
|
|
316
316
|
super(props);
|
|
317
317
|
this.state = {
|
|
@@ -344,7 +344,7 @@ class ControledUpload extends React.Component {
|
|
|
344
344
|
}
|
|
345
345
|
}
|
|
346
346
|
|
|
347
|
-
export const ControlledFileList = () => <
|
|
347
|
+
export const ControlledFileList = () => <ControlledUpload></ControlledUpload>;
|
|
348
348
|
|
|
349
349
|
ControlledFileList.story = {
|
|
350
350
|
name: 'controlled fileList',
|