@douyinfe/semi-ui 2.25.0-beta.0 → 2.25.1

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.
@@ -1,6 +1,5 @@
1
- import _isUndefined from "lodash/isUndefined";
2
- import _isNull from "lodash/isNull";
3
- import _omit from "lodash/omit";
1
+ import _get from "lodash/get";
2
+ import _isFunction from "lodash/isFunction";
4
3
  import _isEqual from "lodash/isEqual";
5
4
 
6
5
  /* eslint-disable arrow-body-style */
@@ -8,7 +7,7 @@ import React from 'react';
8
7
  import cls from 'classnames';
9
8
  import BaseComponent from '../_base/baseComponent';
10
9
  import PropTypes from 'prop-types';
11
- import { cssClasses, strings } from '@douyinfe/semi-foundation/lib/es/overflowList/constants';
10
+ import { cssClasses, strings, numbers } from '@douyinfe/semi-foundation/lib/es/overflowList/constants';
12
11
  import ResizeObserver from '../resizeObserver';
13
12
  import IntersectionObserver from './intersectionObserver';
14
13
  import OverflowListFoundation from '@douyinfe/semi-foundation/lib/es/overflowList/foundation';
@@ -36,26 +35,15 @@ class OverflowList extends BaseComponent {
36
35
 
37
36
  this.resize = function () {
38
37
  let entries = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
39
- // if any parent is growing, assume we have more room than before
40
- const growing = entries.some(entry => {
41
- const previousWidth = _this.previousWidths.get(entry.target) || 0;
42
- return entry.contentRect.width > previousWidth;
43
- });
44
-
45
- _this.repartition(growing);
46
-
47
- entries.forEach(entry => _this.previousWidths.set(entry.target, entry.contentRect.width));
48
- };
49
38
 
50
- this.repartition = growing => {
51
- // if not mounted or scroll mode, we do not
52
- if (_isNull(this.spacer) || _isUndefined(this.spacer) || this.isScrollMode()) {
53
- return;
54
- } // spacer has flex-shrink and width 1px so if it's much smaller then we know to shrink
39
+ var _a;
55
40
 
41
+ const containerWidth = (_a = entries[0]) === null || _a === void 0 ? void 0 : _a.target.clientWidth;
56
42
 
57
- const state = growing ? OverflowDirection.GROW : this.spacer.getBoundingClientRect().width < 0.9 ? OverflowDirection.SHRINK : OverflowDirection.NONE;
58
- this.foundation.handlePartition(state);
43
+ _this.setState({
44
+ containerWidth,
45
+ overflowStatus: 'calculating'
46
+ });
59
47
  };
60
48
 
61
49
  this.reintersect = entries => {
@@ -77,6 +65,18 @@ class OverflowList extends BaseComponent {
77
65
  return this.props.overflowRenderer(overflow);
78
66
  };
79
67
 
68
+ this.getItemKey = (item, defalutKey) => {
69
+ const {
70
+ itemKey
71
+ } = this.props;
72
+
73
+ if (_isFunction(itemKey)) {
74
+ return itemKey(item);
75
+ }
76
+
77
+ return _get(item, itemKey || 'key', defalutKey);
78
+ };
79
+
80
80
  this.renderItemList = () => {
81
81
  const {
82
82
  className,
@@ -88,9 +88,32 @@ class OverflowList extends BaseComponent {
88
88
  collapseFrom
89
89
  } = this.props;
90
90
  const {
91
- visible
91
+ visible,
92
+ overflowStatus
92
93
  } = this.state;
93
- const overflow = this.renderOverflow();
94
+ let overflow = this.renderOverflow();
95
+
96
+ if (!this.isScrollMode()) {
97
+ if (Array.isArray(overflow)) {
98
+ overflow = /*#__PURE__*/React.createElement(React.Fragment, null, overflow);
99
+ }
100
+
101
+ if ( /*#__PURE__*/React.isValidElement(overflow)) {
102
+ const child = /*#__PURE__*/React.cloneElement(overflow);
103
+ overflow = /*#__PURE__*/React.createElement(ResizeObserver, {
104
+ onResize: _ref => {
105
+ let [entry] = _ref;
106
+ this.setState({
107
+ overflowWidth: entry.target.clientWidth,
108
+ overflowStatus: 'calculating'
109
+ });
110
+ }
111
+ }, /*#__PURE__*/React.createElement("div", {
112
+ className: "".concat(prefixCls, "-overflow")
113
+ }, child));
114
+ }
115
+ }
116
+
94
117
  const inner = renderMode === RenderMode.SCROLL ? [overflow[0], /*#__PURE__*/React.createElement("div", {
95
118
  className: cls(wrapperClassName, "".concat(prefixCls, "-scroll-wrapper")),
96
119
  ref: ref => {
@@ -98,7 +121,7 @@ class OverflowList extends BaseComponent {
98
121
  },
99
122
  style: Object.assign({}, wrapperStyle),
100
123
  key: "".concat(prefixCls, "-scroll-wrapper")
101
- }, visible.map(visibleItemRenderer).map((item, ind) => {
124
+ }, visible.map(visibleItemRenderer).map(item => {
102
125
  const {
103
126
  forwardRef,
104
127
  key
@@ -108,24 +131,71 @@ class OverflowList extends BaseComponent {
108
131
  'data-scrollkey': "".concat(key),
109
132
  key
110
133
  });
111
- })), overflow[1]] : [collapseFrom === Boundary.START ? overflow : null, visible.map(visibleItemRenderer), collapseFrom === Boundary.END ? overflow : null, /*#__PURE__*/React.createElement("div", {
112
- className: "".concat(prefixCls, "-spacer"),
113
- ref: ref => this.spacer = ref,
114
- key: "".concat(prefixCls, "-spacer")
115
- })];
134
+ })), overflow[1]] : [collapseFrom === Boundary.START ? overflow : null, visible.map((item, idx) => {
135
+ const {
136
+ key
137
+ } = item;
138
+ const element = visibleItemRenderer(item, idx);
139
+ const child = /*#__PURE__*/React.cloneElement(element);
140
+ return /*#__PURE__*/React.createElement(ResizeObserver, {
141
+ key: key,
142
+ onResize: _ref2 => {
143
+ let [entry] = _ref2;
144
+ return this.onItemResize(entry, item, idx);
145
+ }
146
+ }, /*#__PURE__*/React.createElement("div", {
147
+ key: key,
148
+ className: "".concat(prefixCls, "-item")
149
+ }, child));
150
+ }), collapseFrom === Boundary.END ? overflow : null];
116
151
  const list = /*#__PURE__*/React.createElement('div', {
117
152
  className: cls("".concat(prefixCls), className),
118
- style
153
+ style: Object.assign(Object.assign({}, style), renderMode === RenderMode.COLLAPSE ? {
154
+ maxWidth: '100%',
155
+ visibility: overflowStatus === "calculating" ? "hidden" : "visible"
156
+ } : null)
119
157
  }, ...inner);
120
158
  return list;
121
159
  };
122
160
 
161
+ this.onItemResize = (entry, item, idx) => {
162
+ const key = this.getItemKey(item, idx);
163
+ const width = this.itemSizeMap.get(key);
164
+
165
+ if (!width) {
166
+ this.itemSizeMap.set(key, entry.target.clientWidth);
167
+ } else if (width !== entry.target.clientWidth) {
168
+ // 某个item发生resize后,重新计算
169
+ this.itemSizeMap.set(key, entry.target.clientWidth);
170
+ this.setState({
171
+ overflowStatus: 'calculating'
172
+ });
173
+ }
174
+
175
+ const {
176
+ maxCount
177
+ } = this.state; // 已经按照最大值maxCount渲染完毕,触发真正的渲染。(-1 是overflow部分会占1)
178
+ // Already rendered maxCount items, trigger the real rendering. (-1 for the overflow part)
179
+
180
+ if (this.itemSizeMap.size === maxCount - 1) {
181
+ this.setState({
182
+ overflowStatus: 'calculating'
183
+ });
184
+ }
185
+ };
186
+
123
187
  this.state = {
124
188
  direction: OverflowDirection.GROW,
125
189
  lastOverflowCount: 0,
126
190
  overflow: [],
127
- visible: props.items,
128
- visibleState: new Map()
191
+ visible: [],
192
+ containerWidth: 0,
193
+ visibleState: new Map(),
194
+ itemSizeMap: new Map(),
195
+ overflowStatus: "calculating",
196
+ pivot: 0,
197
+ overflowWidth: 0,
198
+ maxCount: 0
129
199
  };
130
200
  this.foundation = new OverflowListFoundation(this.adapter);
131
201
  this.previousWidths = new Map();
@@ -148,8 +218,18 @@ class OverflowList extends BaseComponent {
148
218
  // reset visible state if the above props change.
149
219
  newState.direction = OverflowDirection.GROW;
150
220
  newState.lastOverflowCount = 0;
151
- newState.overflow = [];
152
- newState.visible = props.items;
221
+
222
+ if (props.renderMode === RenderMode.SCROLL) {
223
+ newState.visible = props.items;
224
+ newState.overflow = [];
225
+ } else {
226
+ newState.visible = [];
227
+ newState.overflow = [];
228
+ }
229
+
230
+ newState.pivot = 0;
231
+ newState.maxCount = 0;
232
+ newState.overflowStatus = "calculating";
153
233
  }
154
234
 
155
235
  return newState;
@@ -167,45 +247,45 @@ class OverflowList extends BaseComponent {
167
247
  },
168
248
  notifyIntersect: res => {
169
249
  this.props.onIntersect && this.props.onIntersect(res);
170
- }
250
+ },
251
+ getItemSizeMap: () => this.itemSizeMap
171
252
  });
172
253
  }
173
254
 
174
- componentDidMount() {
175
- this.repartition(false);
176
- }
177
-
178
- shouldComponentUpdate(_nextProps, nextState) {
179
- // We want this component to always re-render, even when props haven't changed, so that
180
- // changes in the renderers' behavior can be reflected.
181
- // The following statement prevents re-rendering only in the case where the state changes
182
- // identity (i.e. setState was called), but the state is still the same when
183
- // shallow-compared to the previous state.
184
- const currState = _omit(this.state, 'prevProps');
185
-
186
- const comingState = _omit(nextState, 'prevProps');
187
-
188
- return !(currState !== comingState && _isEqual(currState, comingState));
189
- }
190
-
191
255
  componentDidUpdate(prevProps, prevState) {
192
256
  if (!_isEqual(prevProps.items, this.props.items)) {
193
257
  this.itemRefs = {};
194
258
  }
195
259
 
196
- if (!_isEqual(_omit(prevState, 'prevProps'), _omit(this.state, 'prevProps'))) {
197
- this.repartition(false);
198
- }
199
-
200
260
  const {
201
- direction,
202
261
  overflow,
203
- lastOverflowCount
262
+ containerWidth,
263
+ visible,
264
+ overflowStatus
204
265
  } = this.state;
205
266
 
206
- if ( // if a resize operation has just completed (transition to NONE)
207
- direction === OverflowDirection.NONE && direction !== prevState.direction && overflow.length !== lastOverflowCount) {
208
- this.props.onOverflow && this.props.onOverflow(overflow);
267
+ if (this.isScrollMode() || overflowStatus !== "calculating") {
268
+ return;
269
+ }
270
+
271
+ if (visible.length === 0 && overflow.length === 0 && this.props.items.length !== 0) {
272
+ // 推测container最多能渲染的数量
273
+ // Figure out the maximum number of items in this container
274
+ const maxCount = Math.min(this.props.items.length, Math.floor(containerWidth / numbers.MINIMUM_HTML_ELEMENT_WIDTH)); // 如果collapseFrom是start, 第一次用来计算容量时,倒转列表顺序渲染
275
+ // If collapseFrom === start, render item from end to start. Figuring out how many items in the end could fit in container.
276
+
277
+ const isCollapseFromStart = this.props.collapseFrom === Boundary.START;
278
+ const visible = isCollapseFromStart ? this.foundation.getReversedItems().slice(0, maxCount) : this.props.items.slice(0, maxCount);
279
+ const overflow = isCollapseFromStart ? this.foundation.getReversedItems().slice(maxCount) : this.props.items.slice(maxCount);
280
+ this.setState({
281
+ overflowStatus: 'calculating',
282
+ visible,
283
+ overflow,
284
+ maxCount: maxCount
285
+ });
286
+ this.itemSizeMap.clear();
287
+ } else {
288
+ this.foundation.handleCollapseOverflow();
209
289
  }
210
290
  }
211
291
 
@@ -237,7 +317,8 @@ OverflowList.defaultProps = {
237
317
  overflowRenderer: () => null,
238
318
  renderMode: 'collapse',
239
319
  threshold: 0.75,
240
- visibleItemRenderer: () => null
320
+ visibleItemRenderer: () => null,
321
+ onOverflow: () => null
241
322
  };
242
323
  OverflowList.propTypes = {
243
324
  // if render in scroll mode, key is required in items
@@ -667,7 +667,8 @@ class Select extends BaseComponent {
667
667
  innerBottomSlot,
668
668
  loading,
669
669
  virtualize,
670
- multiple
670
+ multiple,
671
+ emptyContent
671
672
  } = this.props; // Do a filter first, instead of directly judging in forEach, so that the focusIndex can correspond to
672
673
 
673
674
  const visibleOptions = options.filter(item => item._show);
@@ -690,7 +691,11 @@ class Select extends BaseComponent {
690
691
  // eslint-disable-next-line jsx-a11y/no-static-element-interactions
691
692
  React.createElement("div", {
692
693
  id: "".concat(prefixcls, "-").concat(this.selectOptionListID),
693
- className: cls("".concat(prefixcls, "-option-list-wrapper"), dropdownClassName),
694
+ className: cls({
695
+ // When emptyContent is null and the option is empty, there is no need for the drop-down option for the user,
696
+ // so there is no need to set padding through this className
697
+ ["".concat(prefixcls, "-option-list-wrapper")]: !(isEmpty && emptyContent === null)
698
+ }, dropdownClassName),
694
699
  style: style,
695
700
  ref: this.setOptionContainerEl,
696
701
  onKeyDown: e => this.foundation.handleContainerKeyDown(e)
@@ -442,7 +442,7 @@ class TagInput extends BaseComponent {
442
442
  }
443
443
 
444
444
  blur() {
445
- this.inputRef.current.blur(); // unregister clickOutside event
445
+ this.inputRef.current.blur(); // unregister clickOutside event
446
446
 
447
447
  this.foundation.clickOutsideCallBack();
448
448
  }
@@ -457,7 +457,7 @@ class TagInput extends BaseComponent {
457
457
  });
458
458
 
459
459
  if (!disabled) {
460
- // register clickOutside event
460
+ // register clickOutside event
461
461
  this.foundation.handleClick();
462
462
  }
463
463
  }
@@ -483,13 +483,15 @@ class TagInput extends BaseComponent {
483
483
  ["".concat(prefixCls, "-disabled")]: disabled,
484
484
  ["".concat(prefixCls, "-hover")]: hovering && !disabled,
485
485
  ["".concat(prefixCls, "-error")]: validateStatus === 'error',
486
- ["".concat(prefixCls, "-warning")]: validateStatus === 'warning'
486
+ ["".concat(prefixCls, "-warning")]: validateStatus === 'warning',
487
+ ["".concat(prefixCls, "-small")]: size === 'small',
488
+ ["".concat(prefixCls, "-large")]: size === 'large'
487
489
  });
488
490
  const inputCls = cls("".concat(prefixCls, "-wrapper-input"), "".concat(prefixCls, "-wrapper-input-").concat(size));
489
- const wrapperCls = cls("".concat(prefixCls, "-wrapper"), "".concat(prefixCls, "-wrapper-").concat(size));
491
+ const wrapperCls = cls("".concat(prefixCls, "-wrapper"));
490
492
  return (
491
493
  /*#__PURE__*/
492
- // eslint-disable-next-line
494
+ // eslint-disable-next-line
493
495
  React.createElement("div", {
494
496
  ref: this.tagInputRef,
495
497
  style: style,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@douyinfe/semi-ui",
3
- "version": "2.25.0-beta.0",
3
+ "version": "2.25.1",
4
4
  "description": "",
5
5
  "main": "lib/cjs/index.js",
6
6
  "module": "lib/es/index.js",
@@ -17,12 +17,12 @@
17
17
  "lib/*"
18
18
  ],
19
19
  "dependencies": {
20
- "@douyinfe/semi-animation": "2.25.0-beta.0",
21
- "@douyinfe/semi-animation-react": "2.25.0-beta.0",
22
- "@douyinfe/semi-foundation": "2.25.0-beta.0",
23
- "@douyinfe/semi-icons": "2.25.0-beta.0",
24
- "@douyinfe/semi-illustrations": "2.25.0-beta.0",
25
- "@douyinfe/semi-theme-default": "2.25.0-beta.0",
20
+ "@douyinfe/semi-animation": "2.25.1",
21
+ "@douyinfe/semi-animation-react": "2.25.1",
22
+ "@douyinfe/semi-foundation": "2.25.1",
23
+ "@douyinfe/semi-icons": "2.25.1",
24
+ "@douyinfe/semi-illustrations": "2.25.1",
25
+ "@douyinfe/semi-theme-default": "2.25.1",
26
26
  "async-validator": "^3.5.0",
27
27
  "classnames": "^2.2.6",
28
28
  "copy-text-to-clipboard": "^2.1.1",
@@ -69,7 +69,7 @@
69
69
  ],
70
70
  "author": "",
71
71
  "license": "MIT",
72
- "gitHead": "72351802667e5c906035fb969b65b0ce83ea88f7",
72
+ "gitHead": "571a51134e49bec30e4412b4eacd45dd35d3849f",
73
73
  "devDependencies": {
74
74
  "@babel/plugin-proposal-decorators": "^7.15.8",
75
75
  "@babel/plugin-transform-runtime": "^7.15.8",