@douyinfe/semi-ui 2.25.0 → 2.25.2

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)
@@ -170,9 +170,9 @@ export default class Tag extends Component {
170
170
  })) : null;
171
171
  return /*#__PURE__*/React.createElement("div", Object.assign({
172
172
  "aria-label": this.props['aria-label'] || _isString(children) ? "".concat(closable ? 'Closable ' : '', "Tag: ").concat(children) : ''
173
- }, wrapProps), /*#__PURE__*/React.createElement("div", {
173
+ }, wrapProps), avatarSrc ? this.renderAvatar() : null, /*#__PURE__*/React.createElement("div", {
174
174
  className: "".concat(prefixCls, "-content")
175
- }, avatarSrc ? this.renderAvatar() : null, children), closeIcon);
175
+ }, children), closeIcon);
176
176
  }
177
177
 
178
178
  }
@@ -18,16 +18,14 @@ import Popover from '../popover';
18
18
  import Paragraph from '../typography/paragraph';
19
19
  import { IconClear, IconHandle } from '@douyinfe/semi-icons';
20
20
  import { SortableContainer, SortableElement, SortableHandle } from 'react-sortable-hoc';
21
+ const prefixCls = cssClasses.PREFIX;
21
22
  const SortableItem = SortableElement(props => props.item);
22
23
  const SortableList = SortableContainer(_ref => {
23
24
  let {
24
25
  items
25
26
  } = _ref;
26
27
  return /*#__PURE__*/React.createElement("div", {
27
- style: {
28
- display: 'flex',
29
- flexFlow: 'row wrap'
30
- }
28
+ className: "".concat(prefixCls, "-sortable-list")
31
29
  }, items.map((item, index) =>
32
30
  /*#__PURE__*/
33
31
  // @ts-ignore skip SortableItem type check
@@ -37,7 +35,6 @@ const SortableList = SortableContainer(_ref => {
37
35
  item: item.item
38
36
  })));
39
37
  });
40
- const prefixCls = cssClasses.PREFIX;
41
38
 
42
39
  class TagInput extends BaseComponent {
43
40
  constructor(props) {
@@ -143,13 +140,15 @@ class TagInput extends BaseComponent {
143
140
  key: elementKey,
144
141
  visible: true,
145
142
  "aria-label": "".concat(!disabled ? 'Closable ' : '', "Tag: ").concat(value)
143
+ }, /*#__PURE__*/React.createElement("div", {
144
+ className: "".concat(prefixCls, "-tag-content-wrapper")
146
145
  }, showIconHandler && /*#__PURE__*/React.createElement(DragHandle, null), /*#__PURE__*/React.createElement(Paragraph, {
147
146
  className: typoCls,
148
147
  ellipsis: {
149
148
  showTooltip: showContentTooltip,
150
149
  rows: 1
151
150
  }
152
- }, value));
151
+ }, value)));
153
152
  }
154
153
  });
155
154
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@douyinfe/semi-ui",
3
- "version": "2.25.0",
3
+ "version": "2.25.2",
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",
21
- "@douyinfe/semi-animation-react": "2.25.0",
22
- "@douyinfe/semi-foundation": "2.25.0",
23
- "@douyinfe/semi-icons": "2.25.0",
24
- "@douyinfe/semi-illustrations": "2.25.0",
25
- "@douyinfe/semi-theme-default": "2.25.0",
20
+ "@douyinfe/semi-animation": "2.25.2",
21
+ "@douyinfe/semi-animation-react": "2.25.2",
22
+ "@douyinfe/semi-foundation": "2.25.2",
23
+ "@douyinfe/semi-icons": "2.25.2",
24
+ "@douyinfe/semi-illustrations": "2.25.2",
25
+ "@douyinfe/semi-theme-default": "2.25.2",
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": "3c2ec566acd956095fc502690245c9a502251357",
72
+ "gitHead": "d1cdea565d328c70a4de8636aed30c88f60732dd",
73
73
  "devDependencies": {
74
74
  "@babel/plugin-proposal-decorators": "^7.15.8",
75
75
  "@babel/plugin-transform-runtime": "^7.15.8",