@douyinfe/semi-ui 2.5.1 → 2.7.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/button/__test__/button.test.js +7 -0
- package/button/buttonGroup.tsx +5 -2
- package/calendar/monthCalendar.tsx +14 -13
- package/cascader/__test__/cascader.test.js +159 -81
- package/cascader/_story/cascader.stories.js +36 -23
- package/cascader/index.tsx +47 -8
- package/cascader/item.tsx +25 -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 +102 -13
- package/datePicker/datePicker.tsx +95 -16
- package/datePicker/index.tsx +15 -0
- package/datePicker/insetInput.tsx +76 -0
- package/datePicker/month.tsx +14 -7
- package/datePicker/monthsGrid.tsx +31 -12
- package/datePicker/navigation.tsx +8 -4
- package/datePicker/quickControl.tsx +1 -0
- package/datePicker/yearAndMonth.tsx +1 -1
- package/dist/css/semi.css +120 -8
- package/dist/css/semi.min.css +1 -1
- package/dist/umd/semi-ui.js +1100 -193
- 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/hoc/withField.tsx +1 -1
- package/input/_story/input.stories.js +13 -0
- package/lib/cjs/_base/base.css +5 -5
- package/lib/cjs/button/buttonGroup.d.ts +1 -0
- package/lib/cjs/button/buttonGroup.js +6 -2
- package/lib/cjs/calendar/monthCalendar.js +21 -5
- package/lib/cjs/cascader/index.d.ts +10 -2
- package/lib/cjs/cascader/index.js +52 -10
- package/lib/cjs/cascader/item.d.ts +6 -2
- package/lib/cjs/cascader/item.js +33 -4
- package/lib/cjs/datePicker/dateInput.d.ts +9 -4
- package/lib/cjs/datePicker/dateInput.js +107 -13
- package/lib/cjs/datePicker/datePicker.d.ts +7 -2
- package/lib/cjs/datePicker/datePicker.js +138 -30
- 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/month.d.ts +1 -0
- package/lib/cjs/datePicker/month.js +18 -2
- package/lib/cjs/datePicker/monthsGrid.js +35 -11
- package/lib/cjs/datePicker/navigation.js +8 -0
- package/lib/cjs/datePicker/quickControl.js +1 -0
- package/lib/cjs/datePicker/yearAndMonth.js +1 -0
- package/lib/cjs/form/hoc/withField.js +1 -1
- 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/scrollList/scrollItem.d.ts +2 -1
- package/lib/cjs/scrollList/scrollItem.js +13 -3
- package/lib/cjs/table/Body/index.d.ts +2 -0
- package/lib/cjs/table/Body/index.js +13 -4
- package/lib/cjs/tree/index.js +5 -3
- package/lib/cjs/tree/interface.d.ts +1 -0
- package/lib/cjs/tree/nodeList.js +2 -1
- package/lib/cjs/treeSelect/index.js +7 -3
- package/lib/es/_base/base.css +5 -5
- package/lib/es/button/buttonGroup.d.ts +1 -0
- package/lib/es/button/buttonGroup.js +5 -2
- package/lib/es/calendar/monthCalendar.js +22 -5
- package/lib/es/cascader/index.d.ts +10 -2
- package/lib/es/cascader/index.js +49 -7
- package/lib/es/cascader/item.d.ts +6 -2
- package/lib/es/cascader/item.js +31 -4
- package/lib/es/datePicker/dateInput.d.ts +9 -4
- package/lib/es/datePicker/dateInput.js +106 -13
- package/lib/es/datePicker/datePicker.d.ts +7 -2
- package/lib/es/datePicker/datePicker.js +139 -30
- 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/month.d.ts +1 -0
- package/lib/es/datePicker/month.js +18 -2
- package/lib/es/datePicker/monthsGrid.js +35 -11
- package/lib/es/datePicker/navigation.js +8 -0
- package/lib/es/datePicker/quickControl.js +2 -0
- package/lib/es/datePicker/yearAndMonth.js +1 -0
- package/lib/es/form/hoc/withField.js +1 -1
- 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/scrollList/scrollItem.d.ts +2 -1
- package/lib/es/scrollList/scrollItem.js +13 -3
- package/lib/es/table/Body/index.d.ts +2 -0
- package/lib/es/table/Body/index.js +13 -4
- package/lib/es/tree/index.js +5 -3
- package/lib/es/tree/interface.d.ts +1 -0
- package/lib/es/tree/nodeList.js +2 -1
- package/lib/es/treeSelect/index.js +7 -3
- package/navigation/Item.tsx +15 -12
- package/navigation/SubNav.tsx +4 -4
- package/package.json +9 -9
- package/scrollList/_story/ScrollList/index.js +3 -0
- package/scrollList/_story/WheelList/index.js +3 -0
- package/scrollList/scrollItem.tsx +30 -9
- 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/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 +2 -2
- package/treeSelect/__test__/treeSelect.test.js +28 -0
- package/treeSelect/_story/treeSelect.stories.js +55 -2
- package/treeSelect/index.tsx +11 -3
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-beta.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-beta.0",
|
|
18
|
+
"@douyinfe/semi-animation-react": "2.7.0-beta.0",
|
|
19
|
+
"@douyinfe/semi-foundation": "2.7.0-beta.0",
|
|
20
|
+
"@douyinfe/semi-icons": "2.7.0-beta.0",
|
|
21
|
+
"@douyinfe/semi-illustrations": "2.7.0-beta.0",
|
|
22
|
+
"@douyinfe/semi-theme-default": "2.7.0-beta.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": "51cc4f6fa52f3275728d2112a98446ba54619c5b",
|
|
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-beta.0",
|
|
79
79
|
"@storybook/addon-knobs": "^6.3.1",
|
|
80
80
|
"@types/lodash": "^4.14.176",
|
|
81
81
|
"babel-loader": "^8.2.2",
|
|
@@ -43,6 +43,7 @@ class ScrollListDemo extends React.Component {
|
|
|
43
43
|
type={1}
|
|
44
44
|
selectedIndex={this.state.selectIndex1}
|
|
45
45
|
onSelect={this.onSelect}
|
|
46
|
+
aria-label="1"
|
|
46
47
|
/>
|
|
47
48
|
<ScrollItem
|
|
48
49
|
mode="normal"
|
|
@@ -50,6 +51,7 @@ class ScrollListDemo extends React.Component {
|
|
|
50
51
|
type={2}
|
|
51
52
|
selectedIndex={this.state.selectIndex2}
|
|
52
53
|
onSelect={this.onSelect}
|
|
54
|
+
aria-label="2"
|
|
53
55
|
/>
|
|
54
56
|
<ScrollItem
|
|
55
57
|
mode="normal"
|
|
@@ -57,6 +59,7 @@ class ScrollListDemo extends React.Component {
|
|
|
57
59
|
type={3}
|
|
58
60
|
selectedIndex={this.state.selectIndex3}
|
|
59
61
|
onSelect={this.onSelect}
|
|
62
|
+
aria-label="3"
|
|
60
63
|
/>
|
|
61
64
|
</ScrollList>
|
|
62
65
|
);
|
|
@@ -92,6 +92,7 @@ class ScrollListDemo extends React.Component {
|
|
|
92
92
|
type={1}
|
|
93
93
|
selectedIndex={this.state.selectIndex1}
|
|
94
94
|
onSelect={this.onSelectAP}
|
|
95
|
+
aria-label="时段"
|
|
95
96
|
/>
|
|
96
97
|
<ScrollItem
|
|
97
98
|
{...commonProps}
|
|
@@ -99,6 +100,7 @@ class ScrollListDemo extends React.Component {
|
|
|
99
100
|
type={2}
|
|
100
101
|
selectedIndex={this.state.selectIndex2}
|
|
101
102
|
onSelect={this.onSelectHour}
|
|
103
|
+
aria-label="小时"
|
|
102
104
|
/>
|
|
103
105
|
<ScrollItem
|
|
104
106
|
{...commonProps}
|
|
@@ -106,6 +108,7 @@ class ScrollListDemo extends React.Component {
|
|
|
106
108
|
type={3}
|
|
107
109
|
selectedIndex={this.state.selectIndex3}
|
|
108
110
|
onSelect={this.onSelectMinute}
|
|
111
|
+
aria-label="分钟"
|
|
109
112
|
/>
|
|
110
113
|
</ScrollList>
|
|
111
114
|
</div>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { AriaAttributes } from 'react';
|
|
2
2
|
import BaseComponent from '../_base/baseComponent';
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
4
|
import classnames from 'classnames';
|
|
@@ -28,6 +28,7 @@ export interface ScrollItemProps<T extends Item> {
|
|
|
28
28
|
motion?: Motion;
|
|
29
29
|
style?: React.CSSProperties;
|
|
30
30
|
type?: string | number; // used to identify the scrollItem, used internally by the semi component, and does not need to be exposed to the user
|
|
31
|
+
'aria-label'?: AriaAttributes['aria-label'];
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
export interface ScrollItemState {
|
|
@@ -413,15 +414,15 @@ export default class ScrollItem<T extends Item> extends BaseComponent<ScrollItem
|
|
|
413
414
|
const { transform: itemTrans } = item;
|
|
414
415
|
|
|
415
416
|
const transform = typeof itemTrans === 'function' ? itemTrans : commonTrans;
|
|
416
|
-
|
|
417
|
+
const selected = selectedIndex === index;
|
|
417
418
|
const cls = classnames({
|
|
418
|
-
[`${cssClasses.PREFIX}-item-sel`]:
|
|
419
|
+
[`${cssClasses.PREFIX}-item-sel`]: selected && mode !== wheelMode,
|
|
419
420
|
[`${cssClasses.PREFIX}-item-disabled`]: Boolean(item.disabled),
|
|
420
421
|
});
|
|
421
422
|
|
|
422
423
|
let text = '';
|
|
423
424
|
|
|
424
|
-
if (
|
|
425
|
+
if (selected) {
|
|
425
426
|
if (typeof transform === 'function') {
|
|
426
427
|
text = transform(item.value, item.text);
|
|
427
428
|
} else {
|
|
@@ -441,7 +442,14 @@ export default class ScrollItem<T extends Item> extends BaseComponent<ScrollItem
|
|
|
441
442
|
|
|
442
443
|
return (
|
|
443
444
|
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
|
|
444
|
-
<li
|
|
445
|
+
<li
|
|
446
|
+
key={prefixKey + index}
|
|
447
|
+
{...events}
|
|
448
|
+
className={cls}
|
|
449
|
+
role="option"
|
|
450
|
+
aria-selected={selected}
|
|
451
|
+
aria-disabled={item.disabled}
|
|
452
|
+
>
|
|
445
453
|
{text}
|
|
446
454
|
</li>
|
|
447
455
|
);
|
|
@@ -457,7 +465,14 @@ export default class ScrollItem<T extends Item> extends BaseComponent<ScrollItem
|
|
|
457
465
|
|
|
458
466
|
return (
|
|
459
467
|
<div style={style} className={wrapperCls} ref={this._cacheWrapperNode}>
|
|
460
|
-
<ul
|
|
468
|
+
<ul
|
|
469
|
+
role="listbox"
|
|
470
|
+
aria-multiselectable={false}
|
|
471
|
+
aria-label={this.props['aria-label']}
|
|
472
|
+
ref={this._cacheListNode}
|
|
473
|
+
>
|
|
474
|
+
{inner}
|
|
475
|
+
</ul>
|
|
461
476
|
</div>
|
|
462
477
|
);
|
|
463
478
|
};
|
|
@@ -470,13 +485,13 @@ export default class ScrollItem<T extends Item> extends BaseComponent<ScrollItem
|
|
|
470
485
|
const { prependCount, appendCount } = this.state;
|
|
471
486
|
|
|
472
487
|
const prependList = times(prependCount).reduce((arr, num) => {
|
|
473
|
-
const items = this.renderItemList(`pre_${
|
|
488
|
+
const items = this.renderItemList(`pre_${num}_`);
|
|
474
489
|
arr.unshift(...items);
|
|
475
490
|
|
|
476
491
|
return arr;
|
|
477
492
|
}, []);
|
|
478
493
|
const appendList = times(appendCount).reduce((arr, num) => {
|
|
479
|
-
const items = this.renderItemList(`app_${
|
|
494
|
+
const items = this.renderItemList(`app_${num}_`);
|
|
480
495
|
arr.push(...items);
|
|
481
496
|
return arr;
|
|
482
497
|
}, []);
|
|
@@ -500,7 +515,13 @@ export default class ScrollItem<T extends Item> extends BaseComponent<ScrollItem
|
|
|
500
515
|
<div className={selectorCls} ref={this._cacheSelectorNode} />
|
|
501
516
|
<div className={postShadeCls} />
|
|
502
517
|
<div className={listWrapperCls} ref={this._cacheWrapperNode} onScroll={this.scrollToSelectItem}>
|
|
503
|
-
<ul
|
|
518
|
+
<ul
|
|
519
|
+
role="listbox"
|
|
520
|
+
aria-label={this.props['aria-label']}
|
|
521
|
+
aria-multiselectable={false}
|
|
522
|
+
ref={this._cacheListNode}
|
|
523
|
+
onClick={this.clickToSelectItem}
|
|
524
|
+
>
|
|
504
525
|
{prependList}
|
|
505
526
|
{inner}
|
|
506
527
|
{appendList}
|
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
|
};
|
|
@@ -1930,4 +1930,22 @@ describe(`Table`, () => {
|
|
|
1930
1930
|
expect(newExpandedRows.length).toEqual(1);
|
|
1931
1931
|
expect(table.state(`expandedRowKeys`)).toEqual(['1']);
|
|
1932
1932
|
});
|
|
1933
|
+
|
|
1934
|
+
it(`test expanded row re-render`, () => {
|
|
1935
|
+
const expandedRowRender = sinon.spy(() => <div>Semi Design</div>);
|
|
1936
|
+
const demo = mount(
|
|
1937
|
+
<Table
|
|
1938
|
+
columns={columns}
|
|
1939
|
+
dataSource={data}
|
|
1940
|
+
expandedRowRender={expandedRowRender}
|
|
1941
|
+
/>
|
|
1942
|
+
);
|
|
1943
|
+
|
|
1944
|
+
const table = demo.find(BaseTable);
|
|
1945
|
+
|
|
1946
|
+
const expandIcons = demo.find(`.semi-table-tbody .semi-table-row .semi-table-expand-icon`);
|
|
1947
|
+
expandIcons.at(0).simulate('click');
|
|
1948
|
+
expandIcons.at(1).simulate('click');
|
|
1949
|
+
expect(expandedRowRender.calledTwice).toBeTruthy();
|
|
1950
|
+
});
|
|
1933
1951
|
});
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Table, Avatar } from '@douyinfe/semi-ui';
|
|
3
|
+
import { IconMore } from '@douyinfe/semi-icons';
|
|
4
|
+
|
|
5
|
+
const columns = [
|
|
6
|
+
{
|
|
7
|
+
title: '标题',
|
|
8
|
+
width: 500,
|
|
9
|
+
dataIndex: 'name',
|
|
10
|
+
render: (text, record, index) => {
|
|
11
|
+
return (
|
|
12
|
+
<span>
|
|
13
|
+
<Avatar size="small" shape="square" src={record.nameIconSrc} style={{ marginRight: 12 }}></Avatar>
|
|
14
|
+
{text}
|
|
15
|
+
</span>
|
|
16
|
+
);
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
title: '大小',
|
|
21
|
+
dataIndex: 'size',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
title: '所有者',
|
|
25
|
+
dataIndex: 'owner',
|
|
26
|
+
render: (text, record, index) => {
|
|
27
|
+
return (
|
|
28
|
+
<div>
|
|
29
|
+
<Avatar size="small" color={record.avatarBg} style={{ marginRight: 4 }}>
|
|
30
|
+
{typeof text === 'string' && text.slice(0, 1)}
|
|
31
|
+
</Avatar>
|
|
32
|
+
{text}
|
|
33
|
+
</div>
|
|
34
|
+
);
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
title: '更新日期',
|
|
39
|
+
dataIndex: 'updateTime',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
title: '',
|
|
43
|
+
dataIndex: 'operate',
|
|
44
|
+
render: () => {
|
|
45
|
+
return <IconMore />;
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
const data = [
|
|
51
|
+
{
|
|
52
|
+
key: '1',
|
|
53
|
+
name: 'Semi Design 设计稿.fig',
|
|
54
|
+
nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/figma-icon.png',
|
|
55
|
+
size: '2M',
|
|
56
|
+
owner: '姜鹏志',
|
|
57
|
+
updateTime: '2020-02-02 05:13',
|
|
58
|
+
avatarBg: 'grey',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
key: '2',
|
|
62
|
+
name: 'Semi Design 分享演示文稿',
|
|
63
|
+
nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
|
|
64
|
+
size: '2M',
|
|
65
|
+
owner: '郝宣',
|
|
66
|
+
updateTime: '2020-01-17 05:31',
|
|
67
|
+
avatarBg: 'red',
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
key: '3',
|
|
71
|
+
name: '设计文档',
|
|
72
|
+
nameIconSrc: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/docs-icon.png',
|
|
73
|
+
size: '34KB',
|
|
74
|
+
owner: 'Zoey Edwards',
|
|
75
|
+
updateTime: '2020-01-26 11:01',
|
|
76
|
+
avatarBg: 'light-blue',
|
|
77
|
+
},
|
|
78
|
+
];
|
|
79
|
+
|
|
80
|
+
export default function App() {
|
|
81
|
+
const expandRowRender = (record, index) => {
|
|
82
|
+
console.log('render', index);
|
|
83
|
+
return <div>semi design</div>;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<Table
|
|
88
|
+
rowKey="name"
|
|
89
|
+
columns={columns}
|
|
90
|
+
dataSource={data}
|
|
91
|
+
expandedRowRender={expandRowRender}
|
|
92
|
+
pagination={false}
|
|
93
|
+
/>
|
|
94
|
+
);
|
|
95
|
+
}
|
package/table/_story/v2/index.js
CHANGED
|
@@ -2,4 +2,5 @@ export { default as DefaultFilteredValue } from './defaultFilteredValue';
|
|
|
2
2
|
export { default as FixedColumnsChange } from './FixedColumnsChange';
|
|
3
3
|
export { default as FixedZIndex } from './FixedZIndex';
|
|
4
4
|
export { default as FixedHeaderMerge } from './FixedHeaderMerge';
|
|
5
|
-
export { default as FixedResizable } from './FixedResizable';
|
|
5
|
+
export { default as FixedResizable } from './FixedResizable';
|
|
6
|
+
export { default as FixedExpandedRow } from './FixedExpandedRow';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { BASE_CLASS_PREFIX } from '../../../semi-foundation/base/constants';
|
|
1
|
+
import { isEqual } from 'lodash';
|
|
3
2
|
import { IconMapPin } from '@douyinfe/semi-icons';
|
|
3
|
+
import { BASE_CLASS_PREFIX } from '../../../semi-foundation/base/constants';
|
|
4
|
+
import { Tree, Button } from '../../index';
|
|
4
5
|
|
|
5
6
|
const treeChildren = [
|
|
6
7
|
{
|
|
@@ -672,6 +673,90 @@ describe('Tree', () => {
|
|
|
672
673
|
expect(tree.state().selectedKeys.length).toEqual(0);
|
|
673
674
|
});
|
|
674
675
|
|
|
676
|
+
|
|
677
|
+
/**
|
|
678
|
+
* Detect whether the expanded item will be expanded according to the value when the value
|
|
679
|
+
* or treeData is changed, when expandedKeys is not controlled
|
|
680
|
+
*/
|
|
681
|
+
const treeJsonData1 = {
|
|
682
|
+
"Node0": {
|
|
683
|
+
"Child Node0-0": '0-0',
|
|
684
|
+
"Child Node0-1": '0-1',
|
|
685
|
+
},
|
|
686
|
+
"Node1": {
|
|
687
|
+
"Child Node1-0": '1-0',
|
|
688
|
+
"Child Node1-1": '1-1',
|
|
689
|
+
}
|
|
690
|
+
};
|
|
691
|
+
const treeJsonData2 = {
|
|
692
|
+
"Updated Node0": {
|
|
693
|
+
"Updated Child Node0-0": {
|
|
694
|
+
'Updated Child Node0-0-0':'0-0'
|
|
695
|
+
},
|
|
696
|
+
"Updated Child Node0-1": '0-1',
|
|
697
|
+
},
|
|
698
|
+
"Updated Node1": {
|
|
699
|
+
"Updated Child Node1-0": '1-0',
|
|
700
|
+
"Updated Child Node1-1": '1-1',
|
|
701
|
+
}
|
|
702
|
+
};
|
|
703
|
+
|
|
704
|
+
it('expandedKeys when treeDataSimpleJson update', () => {
|
|
705
|
+
const tree = mount(
|
|
706
|
+
<Tree
|
|
707
|
+
value='0-0'
|
|
708
|
+
multiple
|
|
709
|
+
treeDataSimpleJson={treeJsonData1}
|
|
710
|
+
/>,
|
|
711
|
+
{
|
|
712
|
+
attachTo: document.getElementById('container')
|
|
713
|
+
}
|
|
714
|
+
);
|
|
715
|
+
const treeDataButton = mount(
|
|
716
|
+
<Button
|
|
717
|
+
onClick={() => {
|
|
718
|
+
if (isEqual(tree.props().treeDataSimpleJson, treeJsonData1)) {
|
|
719
|
+
tree.setProps({ treeDataSimpleJson: treeJsonData2 });
|
|
720
|
+
tree.update();
|
|
721
|
+
} else {
|
|
722
|
+
tree.setProps({ treeDataSimpleJson: treeJsonData1 });
|
|
723
|
+
tree.update();
|
|
724
|
+
}
|
|
725
|
+
}}
|
|
726
|
+
>
|
|
727
|
+
update treeData
|
|
728
|
+
</Button>
|
|
729
|
+
);
|
|
730
|
+
expect(
|
|
731
|
+
tree
|
|
732
|
+
.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`)
|
|
733
|
+
.at(0)
|
|
734
|
+
.hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)
|
|
735
|
+
).toEqual(false);
|
|
736
|
+
expect(
|
|
737
|
+
tree
|
|
738
|
+
.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-2`)
|
|
739
|
+
.at(0)
|
|
740
|
+
.hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)
|
|
741
|
+
).toEqual(true);
|
|
742
|
+
expect(
|
|
743
|
+
tree
|
|
744
|
+
.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`)
|
|
745
|
+
.at(1)
|
|
746
|
+
.hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)
|
|
747
|
+
).toEqual(true);
|
|
748
|
+
treeDataButton.simulate('click');
|
|
749
|
+
expect(
|
|
750
|
+
tree
|
|
751
|
+
.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-2`)
|
|
752
|
+
.at(0)
|
|
753
|
+
.hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)
|
|
754
|
+
).toEqual(false);
|
|
755
|
+
treeDataButton.simulate('click');
|
|
756
|
+
tree.unmount();
|
|
757
|
+
treeDataButton.unmount();
|
|
758
|
+
});
|
|
759
|
+
|
|
675
760
|
it('expandAction = false / default behavior', () => {
|
|
676
761
|
const nativeEvent = { nativeEvent: { stopImmediatePropagation: () => { } } }
|
|
677
762
|
let spyOnExpand = sinon.spy(() => { });
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import React, { useRef, useState } from 'react';
|
|
2
|
+
import { cloneDeep, difference, isEqual } from 'lodash';
|
|
3
|
+
import { IconEdit, IconMapPin, IconMore } from '@douyinfe/semi-icons';
|
|
2
4
|
import Tree from '../index';
|
|
3
5
|
import AutoSizer from '../autoSizer';
|
|
4
|
-
import { Button, ButtonGroup, Input, Popover, Toast } from '../../index';
|
|
6
|
+
import { Button, ButtonGroup, Input, Popover, Toast, Space } from '../../index';
|
|
5
7
|
import BigTree from './BigData';
|
|
6
8
|
import testData from './data';
|
|
7
|
-
import { cloneDeep, difference, isEqual } from 'lodash';
|
|
8
|
-
import { IconEdit, IconMapPin, IconMore } from '@douyinfe/semi-icons';
|
|
9
|
-
|
|
10
9
|
const TreeNode = Tree.TreeNode;
|
|
11
10
|
|
|
12
11
|
export default {
|
|
@@ -2338,4 +2337,65 @@ export const CheckRelationDemo = () => {
|
|
|
2338
2337
|
/>
|
|
2339
2338
|
</>
|
|
2340
2339
|
);
|
|
2341
|
-
};
|
|
2340
|
+
};
|
|
2341
|
+
|
|
2342
|
+
export const ValueImpactExpansionWithDynamicTreeData = () => {
|
|
2343
|
+
const json = {
|
|
2344
|
+
"Node0": {
|
|
2345
|
+
"Child Node0-0": '0-0',
|
|
2346
|
+
"Child Node0-1": '0-1',
|
|
2347
|
+
},
|
|
2348
|
+
"Node1": {
|
|
2349
|
+
"Child Node1-0": '1-0',
|
|
2350
|
+
"Child Node1-1": '1-1',
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
const json2 = {
|
|
2354
|
+
"Updated Node0": {
|
|
2355
|
+
"Updated Child Node0-0": {
|
|
2356
|
+
'Updated Child Node0-0-0':'0-0'
|
|
2357
|
+
},
|
|
2358
|
+
"Updated Child Node0-1": '0-1',
|
|
2359
|
+
},
|
|
2360
|
+
"Updated Node1": {
|
|
2361
|
+
"Updated Child Node1-0": '1-0',
|
|
2362
|
+
"Updated Child Node1-1": '1-1',
|
|
2363
|
+
}
|
|
2364
|
+
}
|
|
2365
|
+
const style = {
|
|
2366
|
+
width: 260,
|
|
2367
|
+
height: 420,
|
|
2368
|
+
border: '1px solid var(--color-border)'
|
|
2369
|
+
}
|
|
2370
|
+
const [value, setValue] = useState('0-0')
|
|
2371
|
+
const [tree, setTree] = useState(json);
|
|
2372
|
+
const handleValueButtonClick = () => {
|
|
2373
|
+
if (value === '0-0') {
|
|
2374
|
+
setValue('1-0');
|
|
2375
|
+
} else {
|
|
2376
|
+
setValue('0-0');
|
|
2377
|
+
}
|
|
2378
|
+
}
|
|
2379
|
+
const handleTreeDataButtonClick = () => {
|
|
2380
|
+
if(isEqual(tree, json)){
|
|
2381
|
+
setTree(json2);
|
|
2382
|
+
} else {
|
|
2383
|
+
setTree(json);
|
|
2384
|
+
}
|
|
2385
|
+
}
|
|
2386
|
+
return (
|
|
2387
|
+
<>
|
|
2388
|
+
<div>value 受控时,当 treeData/treeDataSimpleJson 改变时,应该根据 value 自动展开</div>
|
|
2389
|
+
<Tree
|
|
2390
|
+
value={value}
|
|
2391
|
+
treeDataSimpleJson={tree}
|
|
2392
|
+
style={style}
|
|
2393
|
+
onChange={v => setValue(v)}
|
|
2394
|
+
/>
|
|
2395
|
+
<Space>
|
|
2396
|
+
<Button onClick={handleValueButtonClick}>改变 value</Button>
|
|
2397
|
+
<Button onClick={handleTreeDataButtonClick}>改变 TreeData</Button>
|
|
2398
|
+
</Space>
|
|
2399
|
+
</>
|
|
2400
|
+
)
|
|
2401
|
+
}
|