@douyinfe/semi-ui 2.1.6-alpha.0 → 2.2.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/_base/_story/a11y.jsx +1302 -0
- package/_base/_story/a11y.scss +49 -0
- package/_base/_story/index.stories.js +3 -1
- package/_utils/index.ts +2 -1
- package/cascader/__test__/cascader.test.js +221 -0
- package/cascader/_story/cascader.stories.js +138 -0
- package/cascader/index.tsx +37 -21
- package/cascader/item.tsx +4 -2
- package/datePicker/__test__/datePicker.test.js +67 -2
- package/datePicker/_story/datePicker.stories.js +3 -1
- package/datePicker/_story/v2/YearButton.jsx +17 -0
- package/datePicker/_story/v2/index.js +1 -0
- package/datePicker/monthsGrid.tsx +12 -1
- package/datePicker/navigation.tsx +55 -29
- package/descriptions/__test__/descriptions.test.js +27 -1
- package/descriptions/_story/descriptions.stories.js +52 -2
- package/descriptions/item.tsx +1 -1
- package/dist/css/semi.css +38 -20
- package/dist/css/semi.min.css +1 -1
- package/dist/umd/semi-ui.js +699 -160
- 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/lib/cjs/_utils/index.d.ts +1 -0
- package/lib/cjs/_utils/index.js +3 -2
- package/lib/cjs/cascader/index.d.ts +7 -0
- package/lib/cjs/cascader/index.js +35 -22
- package/lib/cjs/cascader/item.d.ts +2 -0
- package/lib/cjs/cascader/item.js +4 -2
- package/lib/cjs/datePicker/monthsGrid.d.ts +1 -0
- package/lib/cjs/datePicker/monthsGrid.js +6 -0
- package/lib/cjs/datePicker/navigation.js +47 -7
- package/lib/cjs/descriptions/item.js +1 -1
- package/lib/cjs/form/baseForm.d.ts +6 -1
- package/lib/cjs/form/field.d.ts +6 -1
- package/lib/cjs/locale/source/es.d.ts +7 -0
- package/lib/cjs/locale/source/es.js +168 -0
- package/lib/cjs/rating/item.js +1 -1
- package/lib/cjs/select/index.d.ts +9 -0
- package/lib/cjs/select/index.js +10 -8
- package/lib/cjs/timeline/item.d.ts +3 -0
- package/lib/cjs/timeline/item.js +10 -4
- package/lib/cjs/typography/title.d.ts +1 -1
- package/lib/cjs/upload/fileCard.d.ts +2 -0
- package/lib/cjs/upload/fileCard.js +70 -45
- package/lib/cjs/upload/index.d.ts +23 -2
- package/lib/cjs/upload/index.js +133 -25
- package/lib/cjs/upload/interface.d.ts +3 -0
- package/lib/es/_utils/index.d.ts +1 -0
- package/lib/es/_utils/index.js +3 -2
- package/lib/es/cascader/index.d.ts +7 -0
- package/lib/es/cascader/index.js +34 -25
- package/lib/es/cascader/item.d.ts +2 -0
- package/lib/es/cascader/item.js +4 -2
- package/lib/es/datePicker/monthsGrid.d.ts +1 -0
- package/lib/es/datePicker/monthsGrid.js +6 -0
- package/lib/es/datePicker/navigation.js +48 -8
- package/lib/es/descriptions/item.js +1 -1
- package/lib/es/form/baseForm.d.ts +6 -1
- package/lib/es/form/field.d.ts +6 -1
- package/lib/es/locale/source/es.d.ts +7 -0
- package/lib/es/locale/source/es.js +157 -0
- package/lib/es/rating/item.js +1 -1
- package/lib/es/select/index.d.ts +9 -0
- package/lib/es/select/index.js +14 -8
- package/lib/es/timeline/item.d.ts +3 -0
- package/lib/es/timeline/item.js +9 -4
- package/lib/es/typography/title.d.ts +1 -1
- package/lib/es/upload/fileCard.d.ts +2 -0
- package/lib/es/upload/fileCard.js +69 -44
- package/lib/es/upload/index.d.ts +23 -2
- package/lib/es/upload/index.js +133 -24
- package/lib/es/upload/interface.d.ts +3 -0
- package/locale/source/es.ts +160 -0
- package/package.json +8 -8
- package/popover/Arrow.tsx +1 -1
- package/rating/item.tsx +1 -1
- package/select/_story/select.stories.js +25 -0
- package/select/index.tsx +17 -6
- package/timeline/_story/timeline.stories.js +50 -0
- package/timeline/item.tsx +7 -2
- package/upload/__test__/upload.test.js +50 -1
- package/upload/fileCard.tsx +110 -95
- package/upload/index.tsx +147 -53
- package/upload/interface.ts +3 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
body[data-page="a11y"] {
|
|
2
|
+
overflow: hidden;
|
|
3
|
+
|
|
4
|
+
#root {
|
|
5
|
+
padding: 0 !important;
|
|
6
|
+
|
|
7
|
+
.semi-slider {
|
|
8
|
+
padding: 0;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.rows-container > .semi-row {
|
|
12
|
+
margin-bottom: 24px;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.mt12 {
|
|
16
|
+
margin-top: 12px;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.mb12 {
|
|
20
|
+
margin-bottom: 12px;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.grid {
|
|
25
|
+
|
|
26
|
+
.semi-row,
|
|
27
|
+
.semi-row-flex {
|
|
28
|
+
text-align: center;
|
|
29
|
+
|
|
30
|
+
.semi-col {
|
|
31
|
+
min-height: 30px;
|
|
32
|
+
line-height: 30px;
|
|
33
|
+
background: var(--semi-color-primary-light-default);
|
|
34
|
+
outline: 1px solid var(--semi-color-primary-light-active);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
&.grid-gutter {
|
|
39
|
+
|
|
40
|
+
.semi-col {
|
|
41
|
+
|
|
42
|
+
.gutter-box,
|
|
43
|
+
.col-content {
|
|
44
|
+
background: var(--semi-color-primary-light-hover);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { useMemo } from 'react';
|
|
2
2
|
import { Button, Typography, Card, Tooltip, Tag, Avatar, Rating, Nav, Layout } from '../../index';
|
|
3
3
|
import { IconHelpCircle, IconUser, IconStar, IconSetting } from '@douyinfe/semi-icons';
|
|
4
|
+
import SemiA11y from './a11y';
|
|
4
5
|
import './index.scss';
|
|
5
6
|
|
|
6
7
|
export default {
|
|
@@ -8,7 +9,8 @@ export default {
|
|
|
8
9
|
};
|
|
9
10
|
|
|
10
11
|
export {
|
|
11
|
-
TestAlwaysDarkLight
|
|
12
|
+
TestAlwaysDarkLight,
|
|
13
|
+
SemiA11y
|
|
12
14
|
};
|
|
13
15
|
|
|
14
16
|
const TestAlwaysDarkLight = () => {
|
package/_utils/index.ts
CHANGED
|
@@ -83,7 +83,7 @@ export const getHighLightTextHTML = ({
|
|
|
83
83
|
const markEle = option.highlightTag || 'mark';
|
|
84
84
|
const highlightClassName = option.highlightClassName || '';
|
|
85
85
|
const highlightStyle = option.highlightStyle || {};
|
|
86
|
-
return chunks.map((chunk: HighLightTextHTMLChunk) => {
|
|
86
|
+
return chunks.map((chunk: HighLightTextHTMLChunk, index: number) => {
|
|
87
87
|
const { end, start, highlight } = chunk;
|
|
88
88
|
const text = sourceString.substr(start, end - start);
|
|
89
89
|
if (highlight) {
|
|
@@ -92,6 +92,7 @@ export const getHighLightTextHTML = ({
|
|
|
92
92
|
{
|
|
93
93
|
style: highlightStyle,
|
|
94
94
|
className: highlightClassName,
|
|
95
|
+
key: text + index
|
|
95
96
|
},
|
|
96
97
|
text
|
|
97
98
|
);
|
|
@@ -997,6 +997,149 @@ describe('Cascader', () => {
|
|
|
997
997
|
).toEqual('美国');
|
|
998
998
|
});
|
|
999
999
|
|
|
1000
|
+
it('multiple select enableLeafClick', () => {
|
|
1001
|
+
const cascaderWithMultiple = render({
|
|
1002
|
+
multiple: true,
|
|
1003
|
+
enableLeafClick: true,
|
|
1004
|
+
treeData: [
|
|
1005
|
+
{
|
|
1006
|
+
label: '北美洲',
|
|
1007
|
+
value: 'Beimeizhou',
|
|
1008
|
+
key: 'beimeizhou',
|
|
1009
|
+
children: [
|
|
1010
|
+
{
|
|
1011
|
+
label: '美国',
|
|
1012
|
+
value: 'Meiguo',
|
|
1013
|
+
key: 'meiguo',
|
|
1014
|
+
},
|
|
1015
|
+
{
|
|
1016
|
+
label: '加拿大',
|
|
1017
|
+
value: 'Jianada',
|
|
1018
|
+
key: 'jianada',
|
|
1019
|
+
},
|
|
1020
|
+
],
|
|
1021
|
+
},
|
|
1022
|
+
{
|
|
1023
|
+
label: '南美洲',
|
|
1024
|
+
value: 'Nanmeiguo',
|
|
1025
|
+
key: 'Nanmeiguo',
|
|
1026
|
+
}
|
|
1027
|
+
]
|
|
1028
|
+
})
|
|
1029
|
+
const selectBox = cascaderWithMultiple.find(`.${BASE_CLASS_PREFIX}-cascader-selection`).at(0);
|
|
1030
|
+
selectBox.simulate('click');
|
|
1031
|
+
// click checkbox
|
|
1032
|
+
cascaderWithMultiple
|
|
1033
|
+
.find(`.${BASE_CLASS_PREFIX}-cascader-option-list`)
|
|
1034
|
+
.at(0)
|
|
1035
|
+
.find(`.${BASE_CLASS_PREFIX}-cascader-option`)
|
|
1036
|
+
.at(1)
|
|
1037
|
+
.find(`.${BASE_CLASS_PREFIX}-cascader-option-label`)
|
|
1038
|
+
.at(0)
|
|
1039
|
+
.find(`.${BASE_CLASS_PREFIX}-checkbox`)
|
|
1040
|
+
.at(0)
|
|
1041
|
+
.simulate('click');
|
|
1042
|
+
expect(cascaderWithMultiple.state().checkedKeys.size).toEqual(1);
|
|
1043
|
+
// click option cancel checked
|
|
1044
|
+
cascaderWithMultiple
|
|
1045
|
+
.find(`.${BASE_CLASS_PREFIX}-cascader-option-list`)
|
|
1046
|
+
.at(0)
|
|
1047
|
+
.find(`.${BASE_CLASS_PREFIX}-cascader-option`)
|
|
1048
|
+
.at(1)
|
|
1049
|
+
.simulate('click')
|
|
1050
|
+
expect(cascaderWithMultiple.state().checkedKeys.size).toEqual(0);
|
|
1051
|
+
// click option select
|
|
1052
|
+
cascaderWithMultiple
|
|
1053
|
+
.find(`.${BASE_CLASS_PREFIX}-cascader-option-list`)
|
|
1054
|
+
.at(0)
|
|
1055
|
+
.find(`.${BASE_CLASS_PREFIX}-cascader-option`)
|
|
1056
|
+
.at(0)
|
|
1057
|
+
.simulate('click')
|
|
1058
|
+
cascaderWithMultiple
|
|
1059
|
+
.find(`.${BASE_CLASS_PREFIX}-cascader-option-list`)
|
|
1060
|
+
.at(1)
|
|
1061
|
+
.find(`.${BASE_CLASS_PREFIX}-cascader-option`)
|
|
1062
|
+
.at(0)
|
|
1063
|
+
.simulate('click')
|
|
1064
|
+
expect(cascaderWithMultiple.state().checkedKeys.size).toEqual(1);
|
|
1065
|
+
const states = cascaderWithMultiple.state()
|
|
1066
|
+
cascaderWithMultiple.unmount();
|
|
1067
|
+
})
|
|
1068
|
+
|
|
1069
|
+
it('multiple select disable enableLeafClick', () => {
|
|
1070
|
+
const cascaderWithMultiple = render({
|
|
1071
|
+
multiple: true,
|
|
1072
|
+
treeData: [
|
|
1073
|
+
{
|
|
1074
|
+
label: '北美洲',
|
|
1075
|
+
value: 'Beimeizhou',
|
|
1076
|
+
key: 'beimeizhou',
|
|
1077
|
+
children: [
|
|
1078
|
+
{
|
|
1079
|
+
label: '美国',
|
|
1080
|
+
value: 'Meiguo',
|
|
1081
|
+
key: 'meiguo',
|
|
1082
|
+
},
|
|
1083
|
+
{
|
|
1084
|
+
label: '加拿大',
|
|
1085
|
+
value: 'Jianada',
|
|
1086
|
+
key: 'jianada',
|
|
1087
|
+
},
|
|
1088
|
+
],
|
|
1089
|
+
},
|
|
1090
|
+
{
|
|
1091
|
+
label: '南美洲',
|
|
1092
|
+
value: 'Nanmeiguo',
|
|
1093
|
+
key: 'Nanmeiguo',
|
|
1094
|
+
}
|
|
1095
|
+
]
|
|
1096
|
+
})
|
|
1097
|
+
const selectBox = cascaderWithMultiple.find(`.${BASE_CLASS_PREFIX}-cascader-selection`).at(0);
|
|
1098
|
+
selectBox.simulate('click');
|
|
1099
|
+
// click checkbox
|
|
1100
|
+
cascaderWithMultiple
|
|
1101
|
+
.find(`.${BASE_CLASS_PREFIX}-cascader-option-list`)
|
|
1102
|
+
.at(0)
|
|
1103
|
+
.find(`.${BASE_CLASS_PREFIX}-cascader-option`)
|
|
1104
|
+
.at(1)
|
|
1105
|
+
.find(`.${BASE_CLASS_PREFIX}-cascader-option-label`)
|
|
1106
|
+
.at(0)
|
|
1107
|
+
.find(`.${BASE_CLASS_PREFIX}-checkbox`)
|
|
1108
|
+
.at(0)
|
|
1109
|
+
.simulate('click');
|
|
1110
|
+
expect(cascaderWithMultiple.state().checkedKeys.size).toEqual(1);
|
|
1111
|
+
// click option can't cancel checked
|
|
1112
|
+
cascaderWithMultiple
|
|
1113
|
+
.find(`.${BASE_CLASS_PREFIX}-cascader-option-list`)
|
|
1114
|
+
.at(0)
|
|
1115
|
+
.find(`.${BASE_CLASS_PREFIX}-cascader-option`)
|
|
1116
|
+
.at(1)
|
|
1117
|
+
.simulate('click')
|
|
1118
|
+
expect(cascaderWithMultiple.state().checkedKeys.size).toEqual(1);
|
|
1119
|
+
cascaderWithMultiple.unmount();
|
|
1120
|
+
})
|
|
1121
|
+
|
|
1122
|
+
it('separator', () => {
|
|
1123
|
+
const cascader = render({
|
|
1124
|
+
filterTreeNode: true,
|
|
1125
|
+
defaultValue: ['Yazhou', 'Zhongguo', 'Beijing'],
|
|
1126
|
+
separator: ' > ',
|
|
1127
|
+
defaultOpen: true,
|
|
1128
|
+
});
|
|
1129
|
+
const input = cascader.find(`.${BASE_CLASS_PREFIX}-cascader-selection input`);
|
|
1130
|
+
expect(input.props().placeholder).toEqual('亚洲 > 中国 > 北京');
|
|
1131
|
+
const event = { target: { value: '中国' } };
|
|
1132
|
+
input.simulate('change', event);
|
|
1133
|
+
expect(
|
|
1134
|
+
cascader
|
|
1135
|
+
.find(`.${BASE_CLASS_PREFIX}-cascader-option-list li`)
|
|
1136
|
+
.at(0)
|
|
1137
|
+
.getDOMNode()
|
|
1138
|
+
.textContent
|
|
1139
|
+
).toEqual('亚洲 > 中国 > 北京');
|
|
1140
|
+
cascader.unmount();
|
|
1141
|
+
});
|
|
1142
|
+
|
|
1000
1143
|
it('triggerRender', () => {
|
|
1001
1144
|
const spyTriggerRender = sinon.spy(() => <span>123</span>);
|
|
1002
1145
|
const cascaderAutoMerge = render({
|
|
@@ -1027,4 +1170,82 @@ describe('Cascader', () => {
|
|
|
1027
1170
|
expect(args2.value).toEqual(new Set(['0','0-0','0-0-1','0-0-0']));
|
|
1028
1171
|
cascaderNoAutoMerge.unmount();
|
|
1029
1172
|
});
|
|
1173
|
+
|
|
1174
|
+
it('autoMergeValue', () => {
|
|
1175
|
+
const cascader = render({
|
|
1176
|
+
multiple: true,
|
|
1177
|
+
autoMergeValue: false,
|
|
1178
|
+
defaultValue: 'Yazhou',
|
|
1179
|
+
});
|
|
1180
|
+
const tags = cascader.find(`.${BASE_CLASS_PREFIX}-cascader-selection .${BASE_CLASS_PREFIX}-tag`)
|
|
1181
|
+
expect(tags.length).toEqual(4);
|
|
1182
|
+
cascader.unmount();
|
|
1183
|
+
|
|
1184
|
+
const cascaderAutoMerge = render({
|
|
1185
|
+
multiple: true,
|
|
1186
|
+
autoMergeValue: true,
|
|
1187
|
+
defaultValue: 'Yazhou',
|
|
1188
|
+
});
|
|
1189
|
+
const tags2 = cascaderAutoMerge.find(`.${BASE_CLASS_PREFIX}-cascader-selection .${BASE_CLASS_PREFIX}-tag`)
|
|
1190
|
+
expect(tags2.length).toEqual(1);
|
|
1191
|
+
expect(
|
|
1192
|
+
tags2
|
|
1193
|
+
.find(`.${BASE_CLASS_PREFIX}-tag-content`)
|
|
1194
|
+
.getDOMNode()
|
|
1195
|
+
.textContent
|
|
1196
|
+
).toEqual('亚洲');
|
|
1197
|
+
cascaderAutoMerge.unmount();
|
|
1198
|
+
});
|
|
1199
|
+
|
|
1200
|
+
it('leafOnly', () => {
|
|
1201
|
+
/* autoMergeValue and leafOnly are both false */
|
|
1202
|
+
const cascader = render({
|
|
1203
|
+
multiple: true,
|
|
1204
|
+
autoMergeValue: false,
|
|
1205
|
+
leafOnly: false,
|
|
1206
|
+
defaultValue: 'Yazhou',
|
|
1207
|
+
});
|
|
1208
|
+
const tags = cascader.find(`.${BASE_CLASS_PREFIX}-cascader-selection .${BASE_CLASS_PREFIX}-tag`)
|
|
1209
|
+
expect(tags.length).toEqual(4);
|
|
1210
|
+
cascader.unmount();
|
|
1211
|
+
|
|
1212
|
+
/* autoMergeValue and leafOnly are both true */
|
|
1213
|
+
const cascader2 = render({
|
|
1214
|
+
multiple: true,
|
|
1215
|
+
autoMergeValue: true,
|
|
1216
|
+
leafOnly: true,
|
|
1217
|
+
defaultValue: 'Yazhou',
|
|
1218
|
+
});
|
|
1219
|
+
const tags2 = cascader2.find(`.${BASE_CLASS_PREFIX}-cascader-selection .${BASE_CLASS_PREFIX}-tag`)
|
|
1220
|
+
expect(tags2.length).toEqual(2);
|
|
1221
|
+
cascader2.unmount();
|
|
1222
|
+
|
|
1223
|
+
/* autoMergeValue is false, leafOnly is true */
|
|
1224
|
+
const cascader3 = render({
|
|
1225
|
+
multiple: true,
|
|
1226
|
+
autoMergeValue: false,
|
|
1227
|
+
leafOnly: true,
|
|
1228
|
+
defaultValue: 'Yazhou',
|
|
1229
|
+
});
|
|
1230
|
+
const tags3 = cascader3.find(`.${BASE_CLASS_PREFIX}-cascader-selection .${BASE_CLASS_PREFIX}-tag`)
|
|
1231
|
+
expect(tags3.length).toEqual(2);
|
|
1232
|
+
cascader3.unmount();
|
|
1233
|
+
|
|
1234
|
+
/* autoMergeValue is true, leafOnly is false */
|
|
1235
|
+
const cascader4 = render({
|
|
1236
|
+
multiple: true,
|
|
1237
|
+
autoMergeValue: true,
|
|
1238
|
+
leafOnly: false,
|
|
1239
|
+
defaultValue: 'Yazhou',
|
|
1240
|
+
});
|
|
1241
|
+
const tags4 = cascader4.find(`.${BASE_CLASS_PREFIX}-cascader-selection .${BASE_CLASS_PREFIX}-tag`)
|
|
1242
|
+
expect(tags4.length).toEqual(1);
|
|
1243
|
+
expect(
|
|
1244
|
+
tags4
|
|
1245
|
+
.find(`.${BASE_CLASS_PREFIX}-tag-content`)
|
|
1246
|
+
.getDOMNode()
|
|
1247
|
+
.textContent
|
|
1248
|
+
).toEqual('亚洲');
|
|
1249
|
+
cascader4.unmount();
|
|
1250
|
+
});
|
|
1030
1251
|
});
|
|
@@ -273,6 +273,25 @@ export const _Cascader = () => {
|
|
|
273
273
|
/>
|
|
274
274
|
<br />
|
|
275
275
|
<br />
|
|
276
|
+
<Cascader
|
|
277
|
+
style={{ width: 300 }}
|
|
278
|
+
treeData={treeData1}
|
|
279
|
+
placeholder="Multiple select"
|
|
280
|
+
multiple
|
|
281
|
+
motion={false}
|
|
282
|
+
/>
|
|
283
|
+
<br />
|
|
284
|
+
<br />
|
|
285
|
+
<Cascader
|
|
286
|
+
style={{ width: 300 }}
|
|
287
|
+
treeData={treeData1}
|
|
288
|
+
placeholder="Multiple select enableLeafClick"
|
|
289
|
+
multiple
|
|
290
|
+
enableLeafClick
|
|
291
|
+
motion={false}
|
|
292
|
+
/>
|
|
293
|
+
<br />
|
|
294
|
+
<br />
|
|
276
295
|
<Cascader
|
|
277
296
|
style={{ width: 300 }}
|
|
278
297
|
treeData={[]}
|
|
@@ -374,6 +393,23 @@ export const Disabled = () => {
|
|
|
374
393
|
filterTreeNode
|
|
375
394
|
disabled
|
|
376
395
|
/>
|
|
396
|
+
<br /><br />
|
|
397
|
+
<Cascader
|
|
398
|
+
defaultValue={['yazhou', 'zhongguo']}
|
|
399
|
+
style={{ width: 300 }}
|
|
400
|
+
treeData={treeData2}
|
|
401
|
+
multiple
|
|
402
|
+
filterTreeNode
|
|
403
|
+
disabled
|
|
404
|
+
/>
|
|
405
|
+
<br /><br />
|
|
406
|
+
<Cascader
|
|
407
|
+
defaultValue={['yazhou', 'zhongguo']}
|
|
408
|
+
style={{ width: 300 }}
|
|
409
|
+
treeData={treeData2}
|
|
410
|
+
multiple
|
|
411
|
+
disabled
|
|
412
|
+
/>
|
|
377
413
|
</div>
|
|
378
414
|
);
|
|
379
415
|
};
|
|
@@ -420,6 +456,20 @@ export const DisabledOption = () => {
|
|
|
420
456
|
defaultValue={['yazhou', 'riben']}
|
|
421
457
|
placeholder="Japan node is disabled"
|
|
422
458
|
/>
|
|
459
|
+
<br />
|
|
460
|
+
<br />
|
|
461
|
+
<div>multiple selection + filterTreeNode + defaultValue is disabled option</div>
|
|
462
|
+
<Cascader
|
|
463
|
+
filterTreeNode
|
|
464
|
+
multiple
|
|
465
|
+
style={{ width: 300 }}
|
|
466
|
+
treeData={treeData2}
|
|
467
|
+
defaultValue={[
|
|
468
|
+
['yazhou', 'riben'],
|
|
469
|
+
['beimeizhou', 'jianada']
|
|
470
|
+
]}
|
|
471
|
+
placeholder="Japan node is disabled"
|
|
472
|
+
/>
|
|
423
473
|
</div>
|
|
424
474
|
);
|
|
425
475
|
};
|
|
@@ -1211,3 +1261,91 @@ export const OnChangeWithObject = () => (
|
|
|
1211
1261
|
/>
|
|
1212
1262
|
</>
|
|
1213
1263
|
);
|
|
1264
|
+
|
|
1265
|
+
export const LeafOnly = () => {
|
|
1266
|
+
const [value, setValue] = useState([])
|
|
1267
|
+
return (
|
|
1268
|
+
<div>
|
|
1269
|
+
<div>autoMergeValue=false,leafOnly=false</div>
|
|
1270
|
+
<Cascader
|
|
1271
|
+
style={{ width: 300 }}
|
|
1272
|
+
treeData={treeData4}
|
|
1273
|
+
placeholder="请选择所在地区"
|
|
1274
|
+
multiple
|
|
1275
|
+
autoMergeValue={false}
|
|
1276
|
+
leafOnly={false}
|
|
1277
|
+
defaultValue={['zhejiang']}
|
|
1278
|
+
/>
|
|
1279
|
+
<br />
|
|
1280
|
+
<br />
|
|
1281
|
+
<div>autoMergeValue=false,leafOnly=true, leafOnly生效</div>
|
|
1282
|
+
<Cascader
|
|
1283
|
+
style={{ width: 300 }}
|
|
1284
|
+
treeData={treeData4}
|
|
1285
|
+
placeholder="请选择所在地区"
|
|
1286
|
+
multiple
|
|
1287
|
+
autoMergeValue={false}
|
|
1288
|
+
leafOnly={true}
|
|
1289
|
+
defaultValue={['zhejiang']}
|
|
1290
|
+
/>
|
|
1291
|
+
<br />
|
|
1292
|
+
<br />
|
|
1293
|
+
<div>受控,autoMergeValue=false,leafOnly=true, leafOnly生效</div>
|
|
1294
|
+
<Cascader
|
|
1295
|
+
style={{ width: 300 }}
|
|
1296
|
+
treeData={treeData4}
|
|
1297
|
+
placeholder="请选择所在地区"
|
|
1298
|
+
multiple
|
|
1299
|
+
onChange={v=>{
|
|
1300
|
+
console.log(v);
|
|
1301
|
+
setValue(v)
|
|
1302
|
+
}}
|
|
1303
|
+
autoMergeValue={false}
|
|
1304
|
+
leafOnly={true}
|
|
1305
|
+
value={value}
|
|
1306
|
+
/>
|
|
1307
|
+
<br />
|
|
1308
|
+
<br />
|
|
1309
|
+
<div>受控 onChangeWithObject, autoMergeValue=false,leafOnly=true, leafOnly生效</div>
|
|
1310
|
+
<Cascader
|
|
1311
|
+
style={{ width: 300 }}
|
|
1312
|
+
treeData={treeData4}
|
|
1313
|
+
placeholder="请选择所在地区"
|
|
1314
|
+
multiple
|
|
1315
|
+
onChange={v=>{
|
|
1316
|
+
console.log(v);
|
|
1317
|
+
setValue(v)
|
|
1318
|
+
}}
|
|
1319
|
+
onChangeWithObject
|
|
1320
|
+
autoMergeValue={false}
|
|
1321
|
+
leafOnly={true}
|
|
1322
|
+
value={value}
|
|
1323
|
+
/>
|
|
1324
|
+
<br />
|
|
1325
|
+
<br />
|
|
1326
|
+
<div>autoMergeValue=true,leafOnly=false</div>
|
|
1327
|
+
<Cascader
|
|
1328
|
+
style={{ width: 300 }}
|
|
1329
|
+
treeData={treeData4}
|
|
1330
|
+
placeholder="请选择所在地区"
|
|
1331
|
+
multiple
|
|
1332
|
+
autoMergeValue={true}
|
|
1333
|
+
leafOnly={false}
|
|
1334
|
+
defaultValue={['zhejiang']}
|
|
1335
|
+
/>
|
|
1336
|
+
<br />
|
|
1337
|
+
<br />
|
|
1338
|
+
<br />
|
|
1339
|
+
<div>autoMergeValue=true,leafOnly=true</div>
|
|
1340
|
+
<Cascader
|
|
1341
|
+
style={{ width: 300 }}
|
|
1342
|
+
treeData={treeData4}
|
|
1343
|
+
placeholder="请选择所在地区"
|
|
1344
|
+
multiple
|
|
1345
|
+
autoMergeValue={true}
|
|
1346
|
+
leafOnly={true}
|
|
1347
|
+
defaultValue={['zhejiang']}
|
|
1348
|
+
/>
|
|
1349
|
+
</div>
|
|
1350
|
+
);
|
|
1351
|
+
}
|
package/cascader/index.tsx
CHANGED
|
@@ -14,10 +14,10 @@ import CascaderFoundation, {
|
|
|
14
14
|
} from '@douyinfe/semi-foundation/cascader/foundation';
|
|
15
15
|
import { cssClasses, strings } from '@douyinfe/semi-foundation/cascader/constants';
|
|
16
16
|
import { numbers as popoverNumbers } from '@douyinfe/semi-foundation/popover/constants';
|
|
17
|
-
import { isEqual, isString, isEmpty, isFunction, isNumber, noop } from 'lodash';
|
|
17
|
+
import { isEqual, isString, isEmpty, isFunction, isNumber, noop, flatten } from 'lodash';
|
|
18
18
|
import '@douyinfe/semi-foundation/cascader/cascader.scss';
|
|
19
19
|
import { IconClear, IconChevronDown } from '@douyinfe/semi-icons';
|
|
20
|
-
import { findKeysForValues, convertDataToEntities } from '@douyinfe/semi-foundation/cascader/util';
|
|
20
|
+
import { findKeysForValues, convertDataToEntities, calcMergeType } from '@douyinfe/semi-foundation/cascader/util';
|
|
21
21
|
import { calcCheckedKeys, normalizeKeyList, calcDisabledKeys } from '@douyinfe/semi-foundation/tree/treeUtil';
|
|
22
22
|
import ConfigContext from '../configProvider/context';
|
|
23
23
|
import BaseComponent, { ValidateStatus } from '../_base/baseComponent';
|
|
@@ -143,15 +143,19 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
|
|
|
143
143
|
showRestTagsPopover: PropTypes.bool,
|
|
144
144
|
restTagsPopoverProps: PropTypes.object,
|
|
145
145
|
max: PropTypes.number,
|
|
146
|
+
separator: PropTypes.string,
|
|
146
147
|
onExceed: PropTypes.func,
|
|
147
148
|
onClear: PropTypes.func,
|
|
148
149
|
loadData: PropTypes.func,
|
|
149
150
|
onLoad: PropTypes.func,
|
|
150
151
|
loadedKeys: PropTypes.array,
|
|
151
152
|
disableStrictly: PropTypes.bool,
|
|
153
|
+
leafOnly: PropTypes.bool,
|
|
154
|
+
enableLeafClick: PropTypes.bool,
|
|
152
155
|
};
|
|
153
156
|
|
|
154
157
|
static defaultProps = {
|
|
158
|
+
leafOnly: false,
|
|
155
159
|
arrowIcon: <IconChevronDown />,
|
|
156
160
|
stopPropagation: true,
|
|
157
161
|
motion: true,
|
|
@@ -168,6 +172,7 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
|
|
|
168
172
|
filterLeafOnly: true,
|
|
169
173
|
showRestTagsPopover: false,
|
|
170
174
|
restTagsPopoverProps: {},
|
|
175
|
+
separator: ' / ',
|
|
171
176
|
size: 'default' as const,
|
|
172
177
|
treeNodeFilterProp: 'label' as const,
|
|
173
178
|
displayProp: 'label' as const,
|
|
@@ -177,6 +182,7 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
|
|
|
177
182
|
onClear: noop,
|
|
178
183
|
onDropdownVisibleChange: noop,
|
|
179
184
|
onListScroll: noop,
|
|
185
|
+
enableLeafClick: false,
|
|
180
186
|
};
|
|
181
187
|
|
|
182
188
|
options: any;
|
|
@@ -185,6 +191,7 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
|
|
|
185
191
|
triggerRef: React.RefObject<HTMLDivElement>;
|
|
186
192
|
optionsRef: React.RefObject<any>;
|
|
187
193
|
clickOutsideHandler: any;
|
|
194
|
+
mergeType: string;
|
|
188
195
|
|
|
189
196
|
constructor(props: CascaderProps) {
|
|
190
197
|
super(props);
|
|
@@ -215,8 +222,8 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
|
|
|
215
222
|
checkedKeys: new Set([]),
|
|
216
223
|
/* Key of half checked node, when multiple */
|
|
217
224
|
halfCheckedKeys: new Set([]),
|
|
218
|
-
/* Auto merged checkedKeys, when multiple */
|
|
219
|
-
|
|
225
|
+
/* Auto merged checkedKeys or leaf checkedKeys, when multiple */
|
|
226
|
+
resolvedCheckedKeys: new Set([]),
|
|
220
227
|
/* Keys of loaded item */
|
|
221
228
|
loadedKeys: new Set(),
|
|
222
229
|
/* Keys of loading item */
|
|
@@ -226,6 +233,7 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
|
|
|
226
233
|
};
|
|
227
234
|
this.options = {};
|
|
228
235
|
this.isEmpty = false;
|
|
236
|
+
this.mergeType = calcMergeType(props.autoMergeValue, props.leafOnly);
|
|
229
237
|
this.inputRef = React.createRef();
|
|
230
238
|
this.triggerRef = React.createRef();
|
|
231
239
|
this.optionsRef = React.createRef();
|
|
@@ -346,7 +354,9 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
|
|
|
346
354
|
multiple,
|
|
347
355
|
value,
|
|
348
356
|
defaultValue,
|
|
349
|
-
onChangeWithObject
|
|
357
|
+
onChangeWithObject,
|
|
358
|
+
leafOnly,
|
|
359
|
+
autoMergeValue,
|
|
350
360
|
} = props;
|
|
351
361
|
const { prevProps } = prevState;
|
|
352
362
|
let keyEntities = prevState.keyEntities || {};
|
|
@@ -402,21 +412,18 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
|
|
|
402
412
|
});
|
|
403
413
|
realKeys = formatKeys;
|
|
404
414
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
const calRes = calcCheckedKeys(v, keyEntities);
|
|
409
|
-
checkedKeys = new Set([...checkedKeys, ...calRes.checkedKeys]);
|
|
410
|
-
halfCheckedKeys = new Set([...halfCheckedKeys, ...calRes.halfCheckedKeys]);
|
|
411
|
-
});
|
|
415
|
+
const calRes = calcCheckedKeys(flatten(realKeys as string[]), keyEntities);
|
|
416
|
+
const checkedKeys = new Set(calRes.checkedKeys);
|
|
417
|
+
const halfCheckedKeys = new Set(calRes.halfCheckedKeys);
|
|
412
418
|
// disableStrictly
|
|
413
419
|
if (props.disableStrictly) {
|
|
414
420
|
newState.disabledKeys = calcDisabledKeys(keyEntities);
|
|
415
421
|
}
|
|
422
|
+
const isLeafOnlyMerge = calcMergeType(autoMergeValue, leafOnly) === strings.LEAF_ONLY_MERGE_TYPE;
|
|
416
423
|
newState.prevProps = props;
|
|
417
424
|
newState.checkedKeys = checkedKeys;
|
|
418
425
|
newState.halfCheckedKeys = halfCheckedKeys;
|
|
419
|
-
newState.
|
|
426
|
+
newState.resolvedCheckedKeys = new Set(normalizeKeyList(checkedKeys, keyEntities, isLeafOnlyMerge));
|
|
420
427
|
}
|
|
421
428
|
}
|
|
422
429
|
return newState;
|
|
@@ -493,7 +500,6 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
|
|
|
493
500
|
const {
|
|
494
501
|
size,
|
|
495
502
|
disabled,
|
|
496
|
-
autoMergeValue,
|
|
497
503
|
placeholder,
|
|
498
504
|
maxTagCount,
|
|
499
505
|
showRestTagsPopover,
|
|
@@ -503,11 +509,13 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
|
|
|
503
509
|
inputValue,
|
|
504
510
|
checkedKeys,
|
|
505
511
|
keyEntities,
|
|
506
|
-
|
|
512
|
+
resolvedCheckedKeys
|
|
507
513
|
} = this.state;
|
|
508
514
|
const tagInputcls = cls(`${prefixcls}-tagInput-wrapper`);
|
|
509
515
|
const tagValue: Array<Array<string>> = [];
|
|
510
|
-
const realKeys =
|
|
516
|
+
const realKeys = this.mergeType === strings.NONE_MERGE_TYPE
|
|
517
|
+
? checkedKeys
|
|
518
|
+
: resolvedCheckedKeys;
|
|
511
519
|
[...realKeys].forEach(checkedKey => {
|
|
512
520
|
if (!isEmpty(keyEntities[checkedKey])) {
|
|
513
521
|
tagValue.push(keyEntities[checkedKey].valuePath);
|
|
@@ -592,6 +600,7 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
|
|
|
592
600
|
dropdownStyle,
|
|
593
601
|
loadData,
|
|
594
602
|
emptyContent,
|
|
603
|
+
separator,
|
|
595
604
|
topSlot,
|
|
596
605
|
bottomSlot,
|
|
597
606
|
showNext,
|
|
@@ -606,6 +615,7 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
|
|
|
606
615
|
<Item
|
|
607
616
|
activeKeys={activeKeys}
|
|
608
617
|
selectedKeys={selectedKeys}
|
|
618
|
+
separator={separator}
|
|
609
619
|
loadedKeys={loadedKeys}
|
|
610
620
|
loadingKeys={loadingKeys}
|
|
611
621
|
onItemClick={this.handleItemClick}
|
|
@@ -658,8 +668,10 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
|
|
|
658
668
|
|
|
659
669
|
renderMultipleTags = () => {
|
|
660
670
|
const { autoMergeValue, maxTagCount } = this.props;
|
|
661
|
-
const { checkedKeys,
|
|
662
|
-
const realKeys =
|
|
671
|
+
const { checkedKeys, resolvedCheckedKeys } = this.state;
|
|
672
|
+
const realKeys = this.mergeType === strings.NONE_MERGE_TYPE
|
|
673
|
+
? checkedKeys
|
|
674
|
+
: resolvedCheckedKeys;
|
|
663
675
|
const displayTag: Array<ReactNode> = [];
|
|
664
676
|
const hiddenTag: Array<ReactNode> = [];
|
|
665
677
|
[...realKeys].forEach((checkedKey, idx) => {
|
|
@@ -729,11 +741,15 @@ class Cascader extends BaseComponent<CascaderProps, CascaderState> {
|
|
|
729
741
|
};
|
|
730
742
|
|
|
731
743
|
renderCustomTrigger = () => {
|
|
732
|
-
const { disabled, triggerRender, multiple
|
|
733
|
-
const { selectedKeys, inputValue, inputPlaceHolder,
|
|
744
|
+
const { disabled, triggerRender, multiple } = this.props;
|
|
745
|
+
const { selectedKeys, inputValue, inputPlaceHolder, resolvedCheckedKeys, checkedKeys } = this.state;
|
|
734
746
|
let realValue;
|
|
735
747
|
if (multiple) {
|
|
736
|
-
|
|
748
|
+
if (this.mergeType === strings.NONE_MERGE_TYPE) {
|
|
749
|
+
realValue = checkedKeys;
|
|
750
|
+
} else {
|
|
751
|
+
realValue = resolvedCheckedKeys;
|
|
752
|
+
}
|
|
737
753
|
} else {
|
|
738
754
|
realValue = [...selectedKeys][0];
|
|
739
755
|
}
|
package/cascader/item.tsx
CHANGED
|
@@ -54,6 +54,7 @@ export interface CascaderItemProps {
|
|
|
54
54
|
emptyContent: React.ReactNode;
|
|
55
55
|
loadData: (selectOptions: CascaderData[]) => Promise<void>;
|
|
56
56
|
data: Array<Data | Entity>;
|
|
57
|
+
separator: string;
|
|
57
58
|
multiple: boolean;
|
|
58
59
|
checkedKeys: Set<string>;
|
|
59
60
|
halfCheckedKeys: Set<string>;
|
|
@@ -75,6 +76,7 @@ export default class Item extends PureComponent<CascaderItemProps> {
|
|
|
75
76
|
checkedKeys: PropTypes.object,
|
|
76
77
|
halfCheckedKeys: PropTypes.object,
|
|
77
78
|
onItemCheckboxClick: PropTypes.func,
|
|
79
|
+
separator: PropTypes.string,
|
|
78
80
|
keyword: PropTypes.string
|
|
79
81
|
};
|
|
80
82
|
|
|
@@ -142,7 +144,7 @@ export default class Item extends PureComponent<CascaderItemProps> {
|
|
|
142
144
|
|
|
143
145
|
highlight = (searchText: React.ReactNode[]) => {
|
|
144
146
|
const content: React.ReactNode[] = [];
|
|
145
|
-
const { keyword } = this.props;
|
|
147
|
+
const { keyword, separator } = this.props;
|
|
146
148
|
searchText.forEach((item, idx) => {
|
|
147
149
|
if (typeof item === 'string' && includes(item, keyword)) {
|
|
148
150
|
item.split(keyword).forEach((node, index) => {
|
|
@@ -159,7 +161,7 @@ export default class Item extends PureComponent<CascaderItemProps> {
|
|
|
159
161
|
content.push(item);
|
|
160
162
|
}
|
|
161
163
|
if (idx !== searchText.length - 1) {
|
|
162
|
-
content.push(
|
|
164
|
+
content.push(separator);
|
|
163
165
|
}
|
|
164
166
|
});
|
|
165
167
|
return content;
|