@douyinfe/semi-ui 2.6.0-beta.0 → 2.7.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/button/__test__/button.test.js +7 -0
- package/button/buttonGroup.tsx +5 -2
- package/button/index.tsx +1 -1
- package/cascader/__test__/cascader.test.js +159 -81
- package/cascader/_story/cascader.stories.js +36 -23
- package/cascader/index.tsx +26 -5
- package/datePicker/_story/v2/InsetInput.jsx +104 -0
- package/datePicker/_story/v2/InsetInputE2E.jsx +69 -0
- package/datePicker/_story/v2/index.js +2 -0
- package/datePicker/dateInput.tsx +95 -9
- package/datePicker/datePicker.tsx +89 -15
- package/datePicker/index.tsx +15 -0
- package/datePicker/insetInput.tsx +76 -0
- package/datePicker/monthsGrid.tsx +14 -7
- package/dist/css/semi.css +105 -2
- package/dist/css/semi.min.css +1 -1
- package/dist/umd/semi-ui.js +949 -163
- 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/hooks/useFormApi.tsx +3 -2
- package/input/_story/input.stories.js +13 -0
- package/lib/cjs/button/Button.d.ts +4 -4
- package/lib/cjs/button/buttonGroup.d.ts +3 -2
- package/lib/cjs/button/buttonGroup.js +6 -2
- package/lib/cjs/button/index.d.ts +5 -6
- package/lib/cjs/cascader/index.d.ts +1 -0
- package/lib/cjs/cascader/index.js +38 -9
- package/lib/cjs/datePicker/dateInput.d.ts +9 -2
- package/lib/cjs/datePicker/dateInput.js +92 -9
- package/lib/cjs/datePicker/datePicker.d.ts +7 -2
- package/lib/cjs/datePicker/datePicker.js +123 -18
- package/lib/cjs/datePicker/index.js +24 -2
- package/lib/cjs/datePicker/insetInput.d.ts +21 -0
- package/lib/cjs/datePicker/insetInput.js +80 -0
- package/lib/cjs/datePicker/monthsGrid.js +19 -7
- package/lib/cjs/form/hooks/useFormApi.d.ts +2 -1
- package/lib/cjs/iconButton/index.d.ts +2 -2
- package/lib/cjs/navigation/Item.d.ts +2 -2
- package/lib/cjs/navigation/Item.js +8 -6
- package/lib/cjs/navigation/SubNav.js +2 -2
- package/lib/cjs/radio/radioGroup.js +6 -0
- package/lib/cjs/select/index.js +5 -2
- package/lib/cjs/table/Body/index.d.ts +2 -0
- package/lib/cjs/table/Body/index.js +13 -4
- package/lib/cjs/tag/group.d.ts +2 -0
- package/lib/cjs/tag/group.js +4 -2
- package/lib/cjs/tooltip/index.js +6 -2
- package/lib/cjs/tree/index.js +5 -3
- package/lib/cjs/tree/interface.d.ts +1 -0
- package/lib/cjs/tree/nodeList.js +3 -1
- package/lib/cjs/treeSelect/index.js +11 -3
- package/lib/es/button/Button.d.ts +4 -4
- package/lib/es/button/buttonGroup.d.ts +3 -2
- package/lib/es/button/buttonGroup.js +5 -2
- package/lib/es/button/index.d.ts +5 -6
- package/lib/es/cascader/index.d.ts +1 -0
- package/lib/es/cascader/index.js +35 -6
- package/lib/es/datePicker/dateInput.d.ts +9 -2
- package/lib/es/datePicker/dateInput.js +91 -9
- package/lib/es/datePicker/datePicker.d.ts +7 -2
- package/lib/es/datePicker/datePicker.js +124 -18
- package/lib/es/datePicker/index.js +20 -0
- package/lib/es/datePicker/insetInput.d.ts +21 -0
- package/lib/es/datePicker/insetInput.js +65 -0
- package/lib/es/datePicker/monthsGrid.js +19 -7
- package/lib/es/form/hooks/useFormApi.d.ts +2 -1
- package/lib/es/iconButton/index.d.ts +2 -2
- package/lib/es/navigation/Item.d.ts +2 -2
- package/lib/es/navigation/Item.js +8 -6
- package/lib/es/navigation/SubNav.js +2 -2
- package/lib/es/radio/radioGroup.js +6 -0
- package/lib/es/select/index.js +5 -2
- package/lib/es/table/Body/index.d.ts +2 -0
- package/lib/es/table/Body/index.js +13 -4
- package/lib/es/tag/group.d.ts +2 -0
- package/lib/es/tag/group.js +4 -2
- package/lib/es/tooltip/index.js +6 -2
- package/lib/es/tree/index.js +5 -3
- package/lib/es/tree/interface.d.ts +1 -0
- package/lib/es/tree/nodeList.js +3 -1
- package/lib/es/treeSelect/index.js +11 -3
- package/navigation/Item.tsx +15 -12
- package/navigation/SubNav.tsx +4 -4
- package/package.json +9 -9
- package/radio/__test__/radioGroup.test.jsx +9 -1
- package/radio/_story/radio.stories.js +22 -1
- package/radio/radioGroup.tsx +9 -0
- package/select/_story/select.stories.js +73 -2
- package/select/index.tsx +5 -3
- package/table/Body/index.tsx +15 -4
- package/table/__test__/table.test.js +18 -0
- package/table/_story/v2/FixedExpandedRow/index.jsx +95 -0
- package/table/_story/v2/index.js +2 -1
- package/tag/group.tsx +5 -3
- package/tooltip/_story/tooltip.stories.js +702 -625
- package/tooltip/index.tsx +2 -2
- package/tree/__test__/tree.test.js +87 -2
- package/tree/_story/tree.stories.js +65 -5
- package/tree/index.tsx +4 -2
- package/tree/interface.ts +1 -0
- package/tree/nodeList.tsx +3 -2
- package/treeSelect/__test__/treeSelect.test.js +28 -0
- package/treeSelect/_story/treeSelect.stories.js +55 -2
- package/treeSelect/index.tsx +14 -3
package/lib/es/select/index.js
CHANGED
|
@@ -688,7 +688,9 @@ class Select extends BaseComponent {
|
|
|
688
688
|
});
|
|
689
689
|
}
|
|
690
690
|
|
|
691
|
-
const
|
|
691
|
+
const mapItems = maxTagCount ? _sliceInstanceProperty(selectedItems).call(selectedItems, 0, maxTagCount) : selectedItems; // no need to render rest tag when maxTagCount is setting
|
|
692
|
+
|
|
693
|
+
const tags = _mapInstanceProperty(mapItems).call(mapItems, (item, i) => {
|
|
692
694
|
const label = item[0];
|
|
693
695
|
const {
|
|
694
696
|
value
|
|
@@ -747,12 +749,13 @@ class Select extends BaseComponent {
|
|
|
747
749
|
const placeholderText = placeholder && !inputValue ? /*#__PURE__*/React.createElement("span", {
|
|
748
750
|
className: spanCls
|
|
749
751
|
}, placeholder) : null;
|
|
750
|
-
const n =
|
|
752
|
+
const n = selectedItems.length > maxTagCount ? maxTagCount : undefined;
|
|
751
753
|
const NotOneLine = !maxTagCount; // Multiple lines (that is, do not set maxTagCount), do not use TagGroup, directly traverse with Tag, otherwise Input cannot follow the correct position
|
|
752
754
|
|
|
753
755
|
const tagContent = NotOneLine ? tags : /*#__PURE__*/React.createElement(TagGroup, {
|
|
754
756
|
tagList: tags,
|
|
755
757
|
maxTagCount: n,
|
|
758
|
+
restCount: maxTagCount ? selectedItems.length - maxTagCount : undefined,
|
|
756
759
|
size: "large",
|
|
757
760
|
mode: "custom"
|
|
758
761
|
});
|
|
@@ -43,6 +43,8 @@ export interface BodyState {
|
|
|
43
43
|
}
|
|
44
44
|
export interface BodyContext {
|
|
45
45
|
getVirtualizedListRef: GetVirtualizedListRef;
|
|
46
|
+
flattenedColumns: ColumnProps[];
|
|
47
|
+
getCellWidths: (flattenedColumns: ColumnProps[]) => number[];
|
|
46
48
|
}
|
|
47
49
|
declare const _default: React.ForwardRefExoticComponent<Omit<BodyProps, "forwardedRef"> & React.RefAttributes<HTMLDivElement>>;
|
|
48
50
|
export default _default;
|
|
@@ -389,8 +389,13 @@ class Body extends BaseComponent {
|
|
|
389
389
|
const {
|
|
390
390
|
flattenedColumns,
|
|
391
391
|
getCellWidths
|
|
392
|
-
} = _this.context;
|
|
393
|
-
|
|
392
|
+
} = _this.context; // we use memoized cellWidths to avoid re-render expanded row (fix #686)
|
|
393
|
+
|
|
394
|
+
if (flattenedColumns !== _this.flattenedColumns) {
|
|
395
|
+
_this.flattenedColumns = flattenedColumns;
|
|
396
|
+
_this.cellWidths = getCellWidths(flattenedColumns);
|
|
397
|
+
}
|
|
398
|
+
|
|
394
399
|
return /*#__PURE__*/React.createElement(ExpandedRow, {
|
|
395
400
|
style: style,
|
|
396
401
|
components: components,
|
|
@@ -402,7 +407,7 @@ class Body extends BaseComponent {
|
|
|
402
407
|
index: index,
|
|
403
408
|
virtualized: virtualized,
|
|
404
409
|
key: genExpandedRowKey(key),
|
|
405
|
-
cellWidths: cellWidths
|
|
410
|
+
cellWidths: _this.cellWidths
|
|
406
411
|
});
|
|
407
412
|
};
|
|
408
413
|
/**
|
|
@@ -580,7 +585,9 @@ class Body extends BaseComponent {
|
|
|
580
585
|
};
|
|
581
586
|
this.listRef = /*#__PURE__*/React.createRef();
|
|
582
587
|
const {
|
|
583
|
-
getVirtualizedListRef
|
|
588
|
+
getVirtualizedListRef,
|
|
589
|
+
flattenedColumns,
|
|
590
|
+
getCellWidths
|
|
584
591
|
} = context;
|
|
585
592
|
|
|
586
593
|
if (getVirtualizedListRef) {
|
|
@@ -592,6 +599,8 @@ class Body extends BaseComponent {
|
|
|
592
599
|
}
|
|
593
600
|
|
|
594
601
|
this.foundation = new BodyFoundation(this.adapter);
|
|
602
|
+
this.flattenedColumns = flattenedColumns;
|
|
603
|
+
this.cellWidths = getCellWidths(flattenedColumns);
|
|
595
604
|
this.observer = null;
|
|
596
605
|
}
|
|
597
606
|
|
package/lib/es/tag/group.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export interface TagGroupProps {
|
|
|
7
7
|
style?: React.CSSProperties;
|
|
8
8
|
className?: string;
|
|
9
9
|
maxTagCount?: number;
|
|
10
|
+
restCount?: number;
|
|
10
11
|
tagList?: (TagProps | React.ReactNode)[];
|
|
11
12
|
size?: 'small' | 'large';
|
|
12
13
|
showPopover?: boolean;
|
|
@@ -26,6 +27,7 @@ export default class TagGroup extends PureComponent<TagGroupProps> {
|
|
|
26
27
|
style: PropTypes.Requireable<object>;
|
|
27
28
|
className: PropTypes.Requireable<string>;
|
|
28
29
|
maxTagCount: PropTypes.Requireable<number>;
|
|
30
|
+
restCount: PropTypes.Requireable<number>;
|
|
29
31
|
tagList: PropTypes.Requireable<any[]>;
|
|
30
32
|
size: PropTypes.Requireable<string>;
|
|
31
33
|
mode: PropTypes.Requireable<string>;
|
package/lib/es/tag/group.js
CHANGED
|
@@ -46,9 +46,10 @@ export default class TagGroup extends PureComponent {
|
|
|
46
46
|
renderMergeTags(tags) {
|
|
47
47
|
const {
|
|
48
48
|
maxTagCount,
|
|
49
|
-
tagList
|
|
49
|
+
tagList,
|
|
50
|
+
restCount
|
|
50
51
|
} = this.props;
|
|
51
|
-
const n = tagList.length - maxTagCount;
|
|
52
|
+
const n = restCount ? restCount : tagList.length - maxTagCount;
|
|
52
53
|
let renderTags = tags;
|
|
53
54
|
|
|
54
55
|
const normalTags = _sliceInstanceProperty(tags).call(tags, 0, maxTagCount);
|
|
@@ -128,6 +129,7 @@ TagGroup.propTypes = {
|
|
|
128
129
|
style: PropTypes.object,
|
|
129
130
|
className: PropTypes.string,
|
|
130
131
|
maxTagCount: PropTypes.number,
|
|
132
|
+
restCount: PropTypes.number,
|
|
131
133
|
tagList: PropTypes.array,
|
|
132
134
|
size: PropTypes.oneOf(tagSize),
|
|
133
135
|
mode: PropTypes.string,
|
package/lib/es/tooltip/index.js
CHANGED
|
@@ -184,7 +184,9 @@ export default class Tooltip extends BaseComponent {
|
|
|
184
184
|
} = _ref;
|
|
185
185
|
return /*#__PURE__*/React.createElement("div", _Object$assign({
|
|
186
186
|
className: classNames(className, animateCls),
|
|
187
|
-
style: _Object$assign(_Object$assign(_Object$assign({
|
|
187
|
+
style: _Object$assign(_Object$assign(_Object$assign({
|
|
188
|
+
visibility: 'visible'
|
|
189
|
+
}, animateStyle), {
|
|
188
190
|
transformOrigin
|
|
189
191
|
}), style)
|
|
190
192
|
}, portalEventSet, animateEvents, {
|
|
@@ -196,7 +198,9 @@ export default class Tooltip extends BaseComponent {
|
|
|
196
198
|
className: className
|
|
197
199
|
}, portalEventSet, {
|
|
198
200
|
"x-placement": placement,
|
|
199
|
-
style:
|
|
201
|
+
style: _Object$assign({
|
|
202
|
+
visibility: motion ? undefined : 'visible'
|
|
203
|
+
}, style)
|
|
200
204
|
}), content, icon);
|
|
201
205
|
return /*#__PURE__*/React.createElement(Portal, {
|
|
202
206
|
getPopupContainer: this.props.getPopupContainer,
|
package/lib/es/tree/index.js
CHANGED
|
@@ -216,7 +216,8 @@ class Tree extends BaseComponent {
|
|
|
216
216
|
const isSeaching = Boolean(props.filterTreeNode && prevState.inputValue && prevState.inputValue.length);
|
|
217
217
|
const newState = {
|
|
218
218
|
prevProps: props
|
|
219
|
-
};
|
|
219
|
+
};
|
|
220
|
+
const isExpandControlled = ('expandedKeys' in props); // Accept a props field as a parameter to determine whether to update the field
|
|
220
221
|
|
|
221
222
|
const needUpdate = name => {
|
|
222
223
|
const firstInProps = !prevProps && name in props;
|
|
@@ -260,7 +261,8 @@ class Tree extends BaseComponent {
|
|
|
260
261
|
}
|
|
261
262
|
}
|
|
262
263
|
|
|
263
|
-
const
|
|
264
|
+
const dataUpdated = needUpdate('treeDataSimpleJson') || needUpdate('treeData');
|
|
265
|
+
const expandAllWhenDataChange = dataUpdated && props.expandAll;
|
|
264
266
|
|
|
265
267
|
if (!isSeaching) {
|
|
266
268
|
// Update expandedKeys
|
|
@@ -286,7 +288,7 @@ class Tree extends BaseComponent {
|
|
|
286
288
|
newState.expandedKeys = calcExpandedKeys(props.defaultExpandedKeys, keyEntities);
|
|
287
289
|
} else if (!prevProps && props.defaultValue) {
|
|
288
290
|
newState.expandedKeys = calcExpandedKeysForValues(props.defaultValue, keyEntities, props.multiple, valueEntities);
|
|
289
|
-
} else if (!prevProps && props.value) {
|
|
291
|
+
} else if ((!prevProps || !isExpandControlled && dataUpdated) && props.value) {
|
|
290
292
|
newState.expandedKeys = calcExpandedKeysForValues(props.value, keyEntities, props.multiple, valueEntities);
|
|
291
293
|
}
|
|
292
294
|
|
|
@@ -109,6 +109,7 @@ export interface NodeListProps {
|
|
|
109
109
|
motionKeys: Set<string>;
|
|
110
110
|
motionType: string;
|
|
111
111
|
flattenList: FlattenNode[] | undefined;
|
|
112
|
+
searchTargetIsDeep?: boolean;
|
|
112
113
|
renderTreeNode: (treeNode: FlattenNode, ind?: number, style?: React.CSSProperties) => ReactNode;
|
|
113
114
|
}
|
|
114
115
|
export declare type TransitionNodes<T> = Array<T | Array<T>>;
|
package/lib/es/tree/nodeList.js
CHANGED
|
@@ -22,6 +22,7 @@ export default class NodeList extends PureComponent {
|
|
|
22
22
|
super(props);
|
|
23
23
|
|
|
24
24
|
this.onMotionEnd = () => {
|
|
25
|
+
typeof this.props.onMotionEnd === 'function' && this.props.onMotionEnd();
|
|
25
26
|
this.setState({
|
|
26
27
|
transitionNodes: []
|
|
27
28
|
});
|
|
@@ -83,12 +84,13 @@ export default class NodeList extends PureComponent {
|
|
|
83
84
|
const {
|
|
84
85
|
flattenNodes,
|
|
85
86
|
motionType,
|
|
87
|
+
searchTargetIsDeep,
|
|
86
88
|
renderTreeNode
|
|
87
89
|
} = this.props;
|
|
88
90
|
const {
|
|
89
91
|
transitionNodes
|
|
90
92
|
} = this.state;
|
|
91
|
-
const mapData = transitionNodes.length ? transitionNodes : flattenNodes;
|
|
93
|
+
const mapData = transitionNodes.length && !searchTargetIsDeep ? transitionNodes : flattenNodes;
|
|
92
94
|
|
|
93
95
|
const options = _mapInstanceProperty(mapData).call(mapData, treeNode => {
|
|
94
96
|
const isMotionNode = _Array$isArray(treeNode);
|
|
@@ -741,7 +741,8 @@ class TreeSelect extends BaseComponent {
|
|
|
741
741
|
const {
|
|
742
742
|
flattenNodes,
|
|
743
743
|
motionKeys,
|
|
744
|
-
motionType
|
|
744
|
+
motionType,
|
|
745
|
+
filteredKeys
|
|
745
746
|
} = this.state;
|
|
746
747
|
const {
|
|
747
748
|
direction
|
|
@@ -750,6 +751,7 @@ class TreeSelect extends BaseComponent {
|
|
|
750
751
|
virtualize,
|
|
751
752
|
motionExpand
|
|
752
753
|
} = this.props;
|
|
754
|
+
const isExpandControlled = ('expandedKeys' in this.props);
|
|
753
755
|
|
|
754
756
|
if (!virtualize || _isEmpty(virtualize)) {
|
|
755
757
|
return /*#__PURE__*/React.createElement(NodeList, {
|
|
@@ -757,6 +759,8 @@ class TreeSelect extends BaseComponent {
|
|
|
757
759
|
flattenList: this._flattenNodes,
|
|
758
760
|
motionKeys: motionExpand ? motionKeys : new _Set([]),
|
|
759
761
|
motionType: motionType,
|
|
762
|
+
// When motionKeys is empty, but filteredKeys is not empty (that is, the search hits), this situation should be distinguished from ordinary motionKeys
|
|
763
|
+
searchTargetIsDeep: isExpandControlled && motionExpand && _isEmpty(motionKeys) && !_isEmpty(filteredKeys),
|
|
760
764
|
onMotionEnd: this.onMotionEnd,
|
|
761
765
|
renderTreeNode: this.renderTreeNode
|
|
762
766
|
});
|
|
@@ -897,6 +901,10 @@ class TreeSelect extends BaseComponent {
|
|
|
897
901
|
this.clickOutsideHandler = null;
|
|
898
902
|
this.foundation = new TreeSelectFoundation(this.adapter);
|
|
899
903
|
this.treeSelectID = _sliceInstanceProperty(_context2 = Math.random().toString(36)).call(_context2, 2);
|
|
904
|
+
|
|
905
|
+
this.onMotionEnd = () => {
|
|
906
|
+
this.adapter.rePositionDropdown();
|
|
907
|
+
};
|
|
900
908
|
} // eslint-disable-next-line max-lines-per-function
|
|
901
909
|
|
|
902
910
|
|
|
@@ -1076,8 +1084,8 @@ class TreeSelect extends BaseComponent {
|
|
|
1076
1084
|
notifySelect: (selectKey, bool, node) => {
|
|
1077
1085
|
this.props.onSelect && this.props.onSelect(selectKey, bool, node);
|
|
1078
1086
|
},
|
|
1079
|
-
notifySearch: input => {
|
|
1080
|
-
this.props.onSearch && this.props.onSearch(input);
|
|
1087
|
+
notifySearch: (input, filteredExpandedKeys) => {
|
|
1088
|
+
this.props.onSearch && this.props.onSearch(input, filteredExpandedKeys);
|
|
1081
1089
|
},
|
|
1082
1090
|
cacheFlattenNodes: bool => {
|
|
1083
1091
|
this._flattenNodes = bool ? cloneDeep(this.state.flattenNodes) : null;
|
package/navigation/Item.tsx
CHANGED
|
@@ -4,12 +4,16 @@ import BaseComponent, { BaseProps } from '../_base/baseComponent';
|
|
|
4
4
|
import React from 'react';
|
|
5
5
|
import PropTypes from 'prop-types';
|
|
6
6
|
import cls from 'classnames';
|
|
7
|
-
import {
|
|
7
|
+
import { noop, times } from 'lodash';
|
|
8
8
|
|
|
9
9
|
import isNullOrUndefined from '@douyinfe/semi-foundation/utils/isNullOrUndefined';
|
|
10
10
|
import { cloneDeep, isSemiIcon } from '../_utils';
|
|
11
|
-
import ItemFoundation, {
|
|
12
|
-
|
|
11
|
+
import ItemFoundation, {
|
|
12
|
+
ItemAdapter,
|
|
13
|
+
ItemProps,
|
|
14
|
+
SelectedItemProps
|
|
15
|
+
} from '@douyinfe/semi-foundation/navigation/itemFoundation';
|
|
16
|
+
import { cssClasses, strings } from '@douyinfe/semi-foundation/navigation/constants';
|
|
13
17
|
|
|
14
18
|
import Tooltip from '../tooltip';
|
|
15
19
|
import NavContext from './nav-context';
|
|
@@ -114,7 +118,7 @@ export default class NavItem extends BaseComponent<NavItemProps, NavItemState> {
|
|
|
114
118
|
};
|
|
115
119
|
}
|
|
116
120
|
|
|
117
|
-
renderIcon(icon: React.ReactNode, pos: string, isToggleIcon = false) {
|
|
121
|
+
renderIcon(icon: React.ReactNode, pos: string, isToggleIcon = false, key: number | string = 0) {
|
|
118
122
|
if (this.props.isSubNav) {
|
|
119
123
|
return null;
|
|
120
124
|
}
|
|
@@ -134,8 +138,8 @@ export default class NavItem extends BaseComponent<NavItemProps, NavItemState> {
|
|
|
134
138
|
});
|
|
135
139
|
|
|
136
140
|
return (
|
|
137
|
-
<i className={className}>
|
|
138
|
-
{isSemiIcon(icon) ? React.cloneElement((icon as React.ReactElement), {size: (icon as React.ReactElement).props.size || iconSize}) : icon}
|
|
141
|
+
<i className={className} key={key}>
|
|
142
|
+
{isSemiIcon(icon) ? React.cloneElement((icon as React.ReactElement), { size: (icon as React.ReactElement).props.size || iconSize }) : icon}
|
|
139
143
|
</i>
|
|
140
144
|
);
|
|
141
145
|
}
|
|
@@ -189,7 +193,6 @@ export default class NavItem extends BaseComponent<NavItemProps, NavItemState> {
|
|
|
189
193
|
const selected = this.adapter.getSelected();
|
|
190
194
|
|
|
191
195
|
|
|
192
|
-
|
|
193
196
|
let itemChildren = null;
|
|
194
197
|
if (!isNullOrUndefined(children)) {
|
|
195
198
|
itemChildren = children;
|
|
@@ -197,15 +200,15 @@ export default class NavItem extends BaseComponent<NavItemProps, NavItemState> {
|
|
|
197
200
|
let placeholderIcons = null;
|
|
198
201
|
if (mode === strings.MODE_VERTICAL && !limitIndent && !isCollapsed) {
|
|
199
202
|
const iconAmount = (icon && !indent) ? level : level - 1;
|
|
200
|
-
placeholderIcons = times(iconAmount, () => this.renderIcon(null, strings.ICON_POS_RIGHT, false));
|
|
203
|
+
placeholderIcons = times(iconAmount, (index) => this.renderIcon(null, strings.ICON_POS_RIGHT, false, index));
|
|
201
204
|
}
|
|
202
205
|
itemChildren = (
|
|
203
206
|
<>
|
|
204
207
|
{placeholderIcons}
|
|
205
|
-
{this.context.toggleIconPosition === strings.TOGGLE_ICON_LEFT && this.renderIcon(toggleIcon, strings.ICON_POS_RIGHT, true)}
|
|
206
|
-
{icon || indent || isInSubNav ? this.renderIcon(icon, strings.ICON_POS_LEFT) : null}
|
|
208
|
+
{this.context.toggleIconPosition === strings.TOGGLE_ICON_LEFT && this.renderIcon(toggleIcon, strings.ICON_POS_RIGHT, true, 'key-toggle-pos-right')}
|
|
209
|
+
{icon || indent || isInSubNav ? this.renderIcon(icon, strings.ICON_POS_LEFT, false, 'key-position-left') : null}
|
|
207
210
|
{!isNullOrUndefined(text) ? <span className={`${cssClasses.PREFIX}-item-text`}>{text}</span> : ''}
|
|
208
|
-
{this.context.toggleIconPosition === strings.TOGGLE_ICON_RIGHT && this.renderIcon(toggleIcon, strings.ICON_POS_RIGHT, true)}
|
|
211
|
+
{this.context.toggleIconPosition === strings.TOGGLE_ICON_RIGHT && this.renderIcon(toggleIcon, strings.ICON_POS_RIGHT, true, 'key-toggle-pos-right')}
|
|
209
212
|
</>
|
|
210
213
|
);
|
|
211
214
|
}
|
|
@@ -246,7 +249,7 @@ export default class NavItem extends BaseComponent<NavItemProps, NavItemState> {
|
|
|
246
249
|
);
|
|
247
250
|
} else {
|
|
248
251
|
// Items are divided into normal and sub-wrap
|
|
249
|
-
const popoverItemCls = cls(`${className || `${clsPrefix
|
|
252
|
+
const popoverItemCls = cls(`${className || `${clsPrefix}-normal`}`, {
|
|
250
253
|
[clsPrefix]: true,
|
|
251
254
|
[`${clsPrefix}-sub`]: isSubNav,
|
|
252
255
|
[`${clsPrefix}-selected`]: selected && !isSubNav,
|
package/navigation/SubNav.tsx
CHANGED
|
@@ -240,15 +240,15 @@ export default class SubNav extends BaseComponent<SubNavProps, SubNavState> {
|
|
|
240
240
|
if (mode === strings.MODE_VERTICAL && !limitIndent && !isCollapsed) {
|
|
241
241
|
/* Different icons' amount means different indents.*/
|
|
242
242
|
const iconAmount = (icon && !indent) ? level : level - 1;
|
|
243
|
-
placeholderIcons = times(iconAmount, index => this.renderIcon(null, strings.ICON_POS_RIGHT, false,
|
|
243
|
+
placeholderIcons = times(iconAmount, index => this.renderIcon(null, strings.ICON_POS_RIGHT, false, false, index));
|
|
244
244
|
}
|
|
245
245
|
|
|
246
246
|
const titleDiv = (
|
|
247
247
|
<div
|
|
248
248
|
role="menuitem"
|
|
249
249
|
tabIndex={-1}
|
|
250
|
-
ref={this.setTitleRef as any}
|
|
251
|
-
className={titleCls}
|
|
250
|
+
ref={this.setTitleRef as any}
|
|
251
|
+
className={titleCls}
|
|
252
252
|
onClick={this.handleClick}
|
|
253
253
|
onKeyPress={this.handleKeyPress}
|
|
254
254
|
>
|
|
@@ -256,7 +256,7 @@ export default class SubNav extends BaseComponent<SubNavProps, SubNavState> {
|
|
|
256
256
|
{placeholderIcons}
|
|
257
257
|
{this.context.toggleIconPosition === strings.TOGGLE_ICON_LEFT && this.renderIcon(toggleIconType, strings.ICON_POS_RIGHT, withTransition, true, 'key-toggle-position-left')}
|
|
258
258
|
{icon || indent || (isInSubNav && mode !== strings.MODE_HORIZONTAL)
|
|
259
|
-
? this.renderIcon(icon, strings.ICON_POS_LEFT,
|
|
259
|
+
? this.renderIcon(icon, strings.ICON_POS_LEFT, false, false, 'key-inSubNav-position-left')
|
|
260
260
|
: null}
|
|
261
261
|
<span className={`${prefixCls}-item-text`}>{text}</span>
|
|
262
262
|
{this.context.toggleIconPosition === strings.TOGGLE_ICON_RIGHT && this.renderIcon(toggleIconType, strings.ICON_POS_RIGHT, withTransition, true, 'key-toggle-position-right')}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@douyinfe/semi-ui",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "lib/cjs/index.js",
|
|
6
6
|
"module": "lib/es/index.js",
|
|
@@ -14,12 +14,12 @@
|
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"@babel/runtime-corejs3": "^7.15.4",
|
|
17
|
-
"@douyinfe/semi-animation": "2.
|
|
18
|
-
"@douyinfe/semi-animation-react": "2.
|
|
19
|
-
"@douyinfe/semi-foundation": "2.
|
|
20
|
-
"@douyinfe/semi-icons": "2.
|
|
21
|
-
"@douyinfe/semi-illustrations": "2.
|
|
22
|
-
"@douyinfe/semi-theme-default": "2.
|
|
17
|
+
"@douyinfe/semi-animation": "2.7.0",
|
|
18
|
+
"@douyinfe/semi-animation-react": "2.7.0",
|
|
19
|
+
"@douyinfe/semi-foundation": "2.7.0",
|
|
20
|
+
"@douyinfe/semi-icons": "2.7.0",
|
|
21
|
+
"@douyinfe/semi-illustrations": "2.7.0",
|
|
22
|
+
"@douyinfe/semi-theme-default": "2.7.0",
|
|
23
23
|
"@types/react-window": "^1.8.2",
|
|
24
24
|
"async-validator": "^3.5.0",
|
|
25
25
|
"classnames": "^2.2.6",
|
|
@@ -69,13 +69,13 @@
|
|
|
69
69
|
],
|
|
70
70
|
"author": "",
|
|
71
71
|
"license": "MIT",
|
|
72
|
-
"gitHead": "
|
|
72
|
+
"gitHead": "b6e4e0a1e22d4dabe68cbf7e3d2cfd0202da0424",
|
|
73
73
|
"devDependencies": {
|
|
74
74
|
"@babel/plugin-proposal-decorators": "^7.15.8",
|
|
75
75
|
"@babel/plugin-transform-runtime": "^7.15.8",
|
|
76
76
|
"@babel/preset-env": "^7.15.8",
|
|
77
77
|
"@babel/preset-react": "^7.14.5",
|
|
78
|
-
"@douyinfe/semi-scss-compile": "2.
|
|
78
|
+
"@douyinfe/semi-scss-compile": "2.7.0",
|
|
79
79
|
"@storybook/addon-knobs": "^6.3.1",
|
|
80
80
|
"@types/lodash": "^4.14.176",
|
|
81
81
|
"babel-loader": "^8.2.2",
|
|
@@ -196,4 +196,12 @@ describe('RadioGroup', () => {
|
|
|
196
196
|
expect(middleRadio.exists(`.${BASE_CLASS_PREFIX}-radio-addon-buttonRadio-middle`)).toEqual(true);
|
|
197
197
|
expect(largeRadio.exists(`.${BASE_CLASS_PREFIX}-radio-addon-buttonRadio-large`)).toEqual(true);
|
|
198
198
|
});
|
|
199
|
-
|
|
199
|
+
|
|
200
|
+
it('does not trigger Maximum update exceeded when setting radio-group\'s value to NaN', () => {
|
|
201
|
+
const radioGroup = mount(
|
|
202
|
+
createRadioGroup({ value: NaN }),
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
expect(radioGroup.exists(`${BASE_CLASS_PREFIX}-radio-checked`)).toEqual(false);
|
|
206
|
+
});
|
|
207
|
+
});
|
|
@@ -865,4 +865,25 @@ export const FixWithFieldLossRef = () => {
|
|
|
865
865
|
</Form>
|
|
866
866
|
);
|
|
867
867
|
}
|
|
868
|
-
FixWithFieldLossRef.storyName = '修复 Form Field 丢失 ref 问题 #384';
|
|
868
|
+
FixWithFieldLossRef.storyName = '修复 Form Field 丢失 ref 问题 #384';
|
|
869
|
+
|
|
870
|
+
|
|
871
|
+
export const SwitchValueToNaN = () => {
|
|
872
|
+
const [val, setVal] = useState(1);
|
|
873
|
+
|
|
874
|
+
return (
|
|
875
|
+
<>
|
|
876
|
+
<RadioGroup direction="vertical" aria-label="单选组合示例" value={val}>
|
|
877
|
+
<Radio value={1}>A</Radio>
|
|
878
|
+
<Radio value={2}>B</Radio>
|
|
879
|
+
<Radio value={3}>C</Radio>
|
|
880
|
+
<Radio value={4}>D</Radio>
|
|
881
|
+
</RadioGroup>
|
|
882
|
+
<Space>
|
|
883
|
+
<Button onClick={() => setVal(NaN)}>NaN</Button>
|
|
884
|
+
<Button onClick={() => setVal(2)}>2</Button>
|
|
885
|
+
</Space>
|
|
886
|
+
</>
|
|
887
|
+
);
|
|
888
|
+
}
|
|
889
|
+
SwitchValueToNaN.storyName = 'SwitchValueToNaN';
|
package/radio/radioGroup.tsx
CHANGED
|
@@ -97,6 +97,15 @@ class RadioGroup extends BaseComponent<RadioGroupProps, RadioGroupState> {
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
componentDidUpdate(prevProps: RadioGroupProps) {
|
|
100
|
+
if (typeof prevProps.value === 'number'
|
|
101
|
+
&& isNaN(prevProps.value)
|
|
102
|
+
&& typeof this.props.value === 'number'
|
|
103
|
+
&& isNaN(this.props.value)
|
|
104
|
+
) {
|
|
105
|
+
// `NaN === NaN` returns false, and this will fail the next if check
|
|
106
|
+
// therefore triggering an infinite loop
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
100
109
|
if (prevProps.value !== this.props.value) {
|
|
101
110
|
this.foundation.handlePropValueChange(this.props.value);
|
|
102
111
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useState, useRef, useEffect } from 'react';
|
|
2
2
|
|
|
3
3
|
import './select.scss';
|
|
4
|
-
import { Input, Select, Button, Icon, Avatar, Checkbox, Form, withField, Space } from '../../index';
|
|
4
|
+
import { Input, Select, Button, Icon, Avatar, Checkbox, Form, withField, Space, Tag } from '../../index';
|
|
5
5
|
import CustomTrigger from './CustomTrigger';
|
|
6
6
|
import classNames from 'classnames';
|
|
7
7
|
import { getHighLightTextHTML } from '../../_utils/index';
|
|
@@ -2903,4 +2903,75 @@ export const AutoClearSearchValue = () => {
|
|
|
2903
2903
|
|
|
2904
2904
|
SelectInputPropsDemo.story = {
|
|
2905
2905
|
name: 'AutoClearSearchValue',
|
|
2906
|
-
};
|
|
2906
|
+
};
|
|
2907
|
+
|
|
2908
|
+
|
|
2909
|
+
export const RenderSelectedItemCallCount = () => {
|
|
2910
|
+
const list = [
|
|
2911
|
+
{ "name": "夏可漫", "email": "xiakeman@example.com", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/avatarDemo.jpeg" },
|
|
2912
|
+
{ "name": "申悦", "email": "shenyue@example.com", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/bf8647bffab13c38772c9ff94bf91a9d.jpg" },
|
|
2913
|
+
{ "name": "曲晨一", "email": "quchenyi@example.com", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/8bd8224511db085ed74fea37205aede5.jpg" },
|
|
2914
|
+
{ "name": "文嘉茂", "email": "wenjiamao@example.com", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/6fbafc2d-e3e6-4cff-a1e2-17709c680624.png" },
|
|
2915
|
+
{ "name": "文嘉茂2", "email": "wenjiamao@example.com", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/6fbafc2d-e3e6-4cff-a1e2-17709c680624.png" },
|
|
2916
|
+
{ "name": "文嘉茂3", "email": "wenjiamao@example.com", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/6fbafc2d-e3e6-4cff-a1e2-17709c680624.png" },
|
|
2917
|
+
]
|
|
2918
|
+
|
|
2919
|
+
const renderMultipleWithCustomTag = (optionNode, { onClose }) => {
|
|
2920
|
+
console.count('rerender')
|
|
2921
|
+
const content = (
|
|
2922
|
+
<Tag
|
|
2923
|
+
avatarSrc={optionNode.avatar}
|
|
2924
|
+
avatarShape='circle'
|
|
2925
|
+
closable={true}
|
|
2926
|
+
onClose={onClose}
|
|
2927
|
+
size='large'
|
|
2928
|
+
>
|
|
2929
|
+
{optionNode.name}
|
|
2930
|
+
</Tag>
|
|
2931
|
+
);
|
|
2932
|
+
return {
|
|
2933
|
+
isRenderInTag: false,
|
|
2934
|
+
content
|
|
2935
|
+
};
|
|
2936
|
+
}
|
|
2937
|
+
|
|
2938
|
+
const renderCustomOption = (item, index) => {
|
|
2939
|
+
const optionStyle = {
|
|
2940
|
+
display: 'flex',
|
|
2941
|
+
paddingLeft: 24,
|
|
2942
|
+
paddingTop: 10,
|
|
2943
|
+
paddingBottom: 10
|
|
2944
|
+
}
|
|
2945
|
+
return (
|
|
2946
|
+
<Select.Option key={index} value={item.name} style={optionStyle} showTick={true} {...item} key={item.email}>
|
|
2947
|
+
<Avatar size="small" src={item.avatar} />
|
|
2948
|
+
<div style={{ marginLeft: 8 }}>
|
|
2949
|
+
<div style={{ fontSize: 14 }}>{item.name}</div>
|
|
2950
|
+
<div style={{ color: 'var(--color-text-2)', fontSize: 12, lineHeight: '16px', fontWeight: 'normal' }}>{item.email}</div>
|
|
2951
|
+
</div>
|
|
2952
|
+
</Select.Option>
|
|
2953
|
+
)
|
|
2954
|
+
}
|
|
2955
|
+
|
|
2956
|
+
return (
|
|
2957
|
+
<>
|
|
2958
|
+
<Select
|
|
2959
|
+
placeholder='请选择'
|
|
2960
|
+
showClear
|
|
2961
|
+
multiple
|
|
2962
|
+
maxTagCount={2}
|
|
2963
|
+
style={{ width: 280, height: 40 }}
|
|
2964
|
+
onChange={v => console.log(v)}
|
|
2965
|
+
defaultValue={'夏可漫'}
|
|
2966
|
+
renderSelectedItem={renderMultipleWithCustomTag}
|
|
2967
|
+
>
|
|
2968
|
+
{list.map((item, index) => renderCustomOption(item, index))}
|
|
2969
|
+
</Select>
|
|
2970
|
+
</>
|
|
2971
|
+
);
|
|
2972
|
+
}
|
|
2973
|
+
|
|
2974
|
+
|
|
2975
|
+
RenderSelectedItemCallCount.story = {
|
|
2976
|
+
name: 'RenderSelectedItemCallCount',
|
|
2977
|
+
};
|
package/select/index.tsx
CHANGED
|
@@ -898,8 +898,10 @@ class Select extends BaseComponent<SelectProps, SelectState> {
|
|
|
898
898
|
content: optionNode.label,
|
|
899
899
|
});
|
|
900
900
|
}
|
|
901
|
+
|
|
902
|
+
const mapItems = maxTagCount ? selectedItems.slice(0, maxTagCount) : selectedItems; // no need to render rest tag when maxTagCount is setting
|
|
901
903
|
|
|
902
|
-
const tags =
|
|
904
|
+
const tags = mapItems.map((item, i) => {
|
|
903
905
|
const label = item[0];
|
|
904
906
|
const { value } = item[1];
|
|
905
907
|
const disabled = item[1].disabled || selectDisabled;
|
|
@@ -939,11 +941,11 @@ class Select extends BaseComponent<SelectProps, SelectState> {
|
|
|
939
941
|
// [prefixcls + '-selection-text-inactive']: !inputValue && !tags.length,
|
|
940
942
|
});
|
|
941
943
|
const placeholderText = placeholder && !inputValue ? <span className={spanCls}>{placeholder}</span> : null;
|
|
942
|
-
const n =
|
|
944
|
+
const n = selectedItems.length > maxTagCount ? maxTagCount : undefined;
|
|
943
945
|
|
|
944
946
|
const NotOneLine = !maxTagCount; // Multiple lines (that is, do not set maxTagCount), do not use TagGroup, directly traverse with Tag, otherwise Input cannot follow the correct position
|
|
945
947
|
|
|
946
|
-
const tagContent = NotOneLine ? tags : <TagGroup tagList={tags} maxTagCount={n} size="large" mode="custom" />;
|
|
948
|
+
const tagContent = NotOneLine ? tags : <TagGroup tagList={tags} maxTagCount={n} restCount={maxTagCount ? selectedItems.length - maxTagCount : undefined} size="large" mode="custom" />;
|
|
947
949
|
|
|
948
950
|
return (
|
|
949
951
|
<>
|
package/table/Body/index.tsx
CHANGED
|
@@ -89,6 +89,8 @@ export interface BodyState {
|
|
|
89
89
|
|
|
90
90
|
export interface BodyContext {
|
|
91
91
|
getVirtualizedListRef: GetVirtualizedListRef;
|
|
92
|
+
flattenedColumns: ColumnProps[];
|
|
93
|
+
getCellWidths: (flattenedColumns: ColumnProps[]) => number[];
|
|
92
94
|
}
|
|
93
95
|
|
|
94
96
|
class Body extends BaseComponent<BodyProps, BodyState> {
|
|
@@ -128,6 +130,8 @@ class Body extends BaseComponent<BodyProps, BodyState> {
|
|
|
128
130
|
listRef: React.MutableRefObject<any>;
|
|
129
131
|
observer: ResizeObserver;
|
|
130
132
|
foundation: BodyFoundation;
|
|
133
|
+
cellWidths: number[];
|
|
134
|
+
flattenedColumns: ColumnProps[];
|
|
131
135
|
constructor(props: BodyProps, context: BodyContext) {
|
|
132
136
|
super(props);
|
|
133
137
|
this.ref = React.createRef();
|
|
@@ -142,7 +146,7 @@ class Body extends BaseComponent<BodyProps, BodyState> {
|
|
|
142
146
|
};
|
|
143
147
|
|
|
144
148
|
this.listRef = React.createRef();
|
|
145
|
-
const { getVirtualizedListRef } = context;
|
|
149
|
+
const { getVirtualizedListRef, flattenedColumns, getCellWidths } = context;
|
|
146
150
|
if (getVirtualizedListRef) {
|
|
147
151
|
if (props.virtualized) {
|
|
148
152
|
getVirtualizedListRef(this.listRef);
|
|
@@ -152,6 +156,8 @@ class Body extends BaseComponent<BodyProps, BodyState> {
|
|
|
152
156
|
}
|
|
153
157
|
}
|
|
154
158
|
this.foundation = new BodyFoundation(this.adapter);
|
|
159
|
+
this.flattenedColumns = flattenedColumns;
|
|
160
|
+
this.cellWidths = getCellWidths(flattenedColumns);
|
|
155
161
|
this.observer = null;
|
|
156
162
|
}
|
|
157
163
|
|
|
@@ -199,7 +205,7 @@ class Body extends BaseComponent<BodyProps, BodyState> {
|
|
|
199
205
|
this.observer.unobserve(bodyWrapDOM);
|
|
200
206
|
this.observer = null;
|
|
201
207
|
}
|
|
202
|
-
}
|
|
208
|
+
},
|
|
203
209
|
};
|
|
204
210
|
}
|
|
205
211
|
|
|
@@ -494,7 +500,12 @@ class Body extends BaseComponent<BodyProps, BodyState> {
|
|
|
494
500
|
}
|
|
495
501
|
|
|
496
502
|
const { flattenedColumns, getCellWidths } = this.context;
|
|
497
|
-
|
|
503
|
+
|
|
504
|
+
// we use memoized cellWidths to avoid re-render expanded row (fix #686)
|
|
505
|
+
if (flattenedColumns !== this.flattenedColumns) {
|
|
506
|
+
this.flattenedColumns = flattenedColumns;
|
|
507
|
+
this.cellWidths = getCellWidths(flattenedColumns);
|
|
508
|
+
}
|
|
498
509
|
|
|
499
510
|
return (
|
|
500
511
|
<ExpandedRow
|
|
@@ -508,7 +519,7 @@ class Body extends BaseComponent<BodyProps, BodyState> {
|
|
|
508
519
|
index={index}
|
|
509
520
|
virtualized={virtualized}
|
|
510
521
|
key={genExpandedRowKey(key)}
|
|
511
|
-
cellWidths={cellWidths}
|
|
522
|
+
cellWidths={this.cellWidths}
|
|
512
523
|
/>
|
|
513
524
|
);
|
|
514
525
|
};
|