rsuite 5.31.1 → 5.32.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.
Files changed (60) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/cjs/Calendar/CalendarContainer.d.ts +2 -0
  3. package/cjs/Calendar/CalendarContainer.js +4 -1
  4. package/cjs/Calendar/MonthDropdown.js +1 -1
  5. package/cjs/Cascader/Cascader.d.ts +2 -2
  6. package/cjs/Cascader/Cascader.js +83 -71
  7. package/cjs/Cascader/DropdownMenu.d.ts +6 -2
  8. package/cjs/Cascader/DropdownMenu.js +8 -4
  9. package/cjs/Cascader/utils.d.ts +52 -17
  10. package/cjs/Cascader/utils.js +99 -138
  11. package/cjs/DatePicker/DatePicker.d.ts +3 -1
  12. package/cjs/DatePicker/DatePicker.js +4 -1
  13. package/cjs/DateRangePicker/Calendar.d.ts +1 -0
  14. package/cjs/DateRangePicker/Calendar.js +4 -1
  15. package/cjs/DateRangePicker/DateRangePicker.d.ts +3 -1
  16. package/cjs/DateRangePicker/DateRangePicker.js +4 -1
  17. package/cjs/MultiCascader/DropdownMenu.d.ts +2 -2
  18. package/cjs/MultiCascader/MultiCascader.d.ts +1 -1
  19. package/cjs/MultiCascader/MultiCascader.js +12 -7
  20. package/cjs/MultiCascader/utils.d.ts +2 -2
  21. package/cjs/MultiCascader/utils.js +3 -3
  22. package/cjs/Picker/utils.d.ts +4 -3
  23. package/cjs/Picker/utils.js +8 -4
  24. package/cjs/utils/getDataGroupBy.js +1 -1
  25. package/cjs/utils/treeUtils.d.ts +5 -1
  26. package/cjs/utils/treeUtils.js +31 -6
  27. package/cjs/utils/useMap.d.ts +6 -0
  28. package/cjs/utils/useMap.js +35 -0
  29. package/dist/rsuite.js +186 -14
  30. package/dist/rsuite.js.map +1 -1
  31. package/dist/rsuite.min.js +1 -1
  32. package/dist/rsuite.min.js.map +1 -1
  33. package/esm/Calendar/CalendarContainer.d.ts +2 -0
  34. package/esm/Calendar/CalendarContainer.js +4 -1
  35. package/esm/Calendar/MonthDropdown.js +1 -1
  36. package/esm/Cascader/Cascader.d.ts +2 -2
  37. package/esm/Cascader/Cascader.js +85 -75
  38. package/esm/Cascader/DropdownMenu.d.ts +6 -2
  39. package/esm/Cascader/DropdownMenu.js +8 -4
  40. package/esm/Cascader/utils.d.ts +52 -17
  41. package/esm/Cascader/utils.js +100 -135
  42. package/esm/DatePicker/DatePicker.d.ts +3 -1
  43. package/esm/DatePicker/DatePicker.js +4 -1
  44. package/esm/DateRangePicker/Calendar.d.ts +1 -0
  45. package/esm/DateRangePicker/Calendar.js +4 -1
  46. package/esm/DateRangePicker/DateRangePicker.d.ts +3 -1
  47. package/esm/DateRangePicker/DateRangePicker.js +4 -1
  48. package/esm/MultiCascader/DropdownMenu.d.ts +2 -2
  49. package/esm/MultiCascader/MultiCascader.d.ts +1 -1
  50. package/esm/MultiCascader/MultiCascader.js +12 -7
  51. package/esm/MultiCascader/utils.d.ts +2 -2
  52. package/esm/MultiCascader/utils.js +4 -4
  53. package/esm/Picker/utils.d.ts +4 -3
  54. package/esm/Picker/utils.js +8 -4
  55. package/esm/utils/getDataGroupBy.js +2 -2
  56. package/esm/utils/treeUtils.d.ts +5 -1
  57. package/esm/utils/treeUtils.js +30 -6
  58. package/esm/utils/useMap.d.ts +6 -0
  59. package/esm/utils/useMap.js +29 -0
  60. package/package.json +2 -1
@@ -34,6 +34,8 @@ export interface CalendarProps extends WithAsProps, Omit<HTMLAttributes<HTMLDivE
34
34
  isoWeek?: boolean;
35
35
  /** Limit showing how many years in the future */
36
36
  limitEndYear?: number;
37
+ /** Limit showing how many years in the past */
38
+ limitStartYear?: number;
37
39
  /** Custom locale */
38
40
  locale: CalendarLocale;
39
41
  /** Callback after the date has changed */
@@ -28,6 +28,7 @@ var CalendarContainer = /*#__PURE__*/React.forwardRef(function (props, ref) {
28
28
  _props$isoWeek = props.isoWeek,
29
29
  isoWeek = _props$isoWeek === void 0 ? false : _props$isoWeek,
30
30
  limitEndYear = props.limitEndYear,
31
+ limitStartYear = props.limitStartYear,
31
32
  locale = props.locale,
32
33
  onChangeMonth = props.onChangeMonth,
33
34
  onChangeTime = props.onChangeTime,
@@ -45,7 +46,7 @@ var CalendarContainer = /*#__PURE__*/React.forwardRef(function (props, ref) {
45
46
  showMeridian = props.showMeridian,
46
47
  showWeekNumbers = props.showWeekNumbers,
47
48
  inline = props.inline,
48
- rest = _objectWithoutPropertiesLoose(props, ["as", "className", "classPrefix", "dateRange", "disabledBackward", "defaultState", "disabledDate", "disabledForward", "format", "hoverRangeValue", "isoWeek", "limitEndYear", "locale", "onChangeMonth", "onChangeTime", "onMouseMove", "onMoveBackward", "onMoveForward", "onSelect", "onToggleMeridian", "onToggleMonthDropdown", "onToggleTimeDropdown", "calendarDate", "renderCell", "renderTitle", "renderToolbar", "showMeridian", "showWeekNumbers", "inline"]);
49
+ rest = _objectWithoutPropertiesLoose(props, ["as", "className", "classPrefix", "dateRange", "disabledBackward", "defaultState", "disabledDate", "disabledForward", "format", "hoverRangeValue", "isoWeek", "limitEndYear", "limitStartYear", "locale", "onChangeMonth", "onChangeTime", "onMouseMove", "onMoveBackward", "onMoveForward", "onSelect", "onToggleMeridian", "onToggleMonthDropdown", "onToggleTimeDropdown", "calendarDate", "renderCell", "renderTitle", "renderToolbar", "showMeridian", "showWeekNumbers", "inline"]);
49
50
 
50
51
  var _useClassNames = useClassNames(classPrefix),
51
52
  withClassPrefix = _useClassNames.withClassPrefix,
@@ -159,6 +160,7 @@ var CalendarContainer = /*#__PURE__*/React.forwardRef(function (props, ref) {
159
160
  }), renderDate && /*#__PURE__*/React.createElement(CalendarBody, null), renderMonth && /*#__PURE__*/React.createElement(MonthDropdown, {
160
161
  show: showMonth,
161
162
  limitEndYear: limitEndYear,
163
+ limitStartYear: limitStartYear,
162
164
  disabledMonth: isDisabledDate
163
165
  }), renderTime && /*#__PURE__*/React.createElement(TimeDropdown, _extends({}, timeDropdownProps, {
164
166
  show: showTime,
@@ -183,6 +185,7 @@ CalendarContainer.propTypes = {
183
185
  hideSeconds: PropTypes.func,
184
186
  isoWeek: PropTypes.bool,
185
187
  limitEndYear: PropTypes.number,
188
+ limitStartYear: PropTypes.number,
186
189
  locale: PropTypes.object,
187
190
  onChangeMonth: PropTypes.func,
188
191
  onChangeTime: PropTypes.func,
@@ -45,7 +45,7 @@ var MonthDropdown = /*#__PURE__*/React.forwardRef(function (props, ref) {
45
45
  withClassPrefix = _useClassNames.withClassPrefix;
46
46
 
47
47
  var thisYear = DateUtils.getYear(new Date());
48
- var startYear = limitStartYear ? thisYear - limitStartYear : 1900;
48
+ var startYear = limitStartYear ? thisYear - limitStartYear + 1 : 1900;
49
49
  var rowCount = useMemo(function () {
50
50
  var endYear = thisYear + limitEndYear;
51
51
  return endYear - startYear;
@@ -15,7 +15,7 @@ export interface CascaderProps<T = ValueType> extends FormControlPickerProps<T |
15
15
  /** When true, make the parent node selectable */
16
16
  parentSelectable?: boolean;
17
17
  /** Custom render menu */
18
- renderMenu?: (items: ItemDataType[], menu: React.ReactNode, parentNode?: any, layer?: number) => React.ReactNode;
18
+ renderMenu?: (items: readonly ItemDataType[], menu: React.ReactNode, parentNode?: any, layer?: number) => React.ReactNode;
19
19
  /** Custom render menu items */
20
20
  renderMenuItem?: (itemLabel: React.ReactNode, item: ItemDataType) => React.ReactNode;
21
21
  /** Custom render search items */
@@ -29,7 +29,7 @@ export interface CascaderProps<T = ValueType> extends FormControlPickerProps<T |
29
29
  /** Called when searching */
30
30
  onSearch?: (searchKeyword: string, event: React.SyntheticEvent) => void;
31
31
  /** Asynchronously load the children of the tree node. */
32
- getChildren?: (node: ItemDataType) => ItemDataType[] | Promise<ItemDataType[]>;
32
+ getChildren?: (node: ItemDataType<T>) => ItemDataType<T>[] | Promise<ItemDataType<T>[]>;
33
33
  }
34
34
  export interface CascaderComponent {
35
35
  <T>(props: CascaderProps<T> & {
@@ -1,6 +1,7 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
3
- import React, { useRef, useState, useCallback, useEffect } from 'react';
3
+ import React, { useRef, useState, useCallback, useMemo } from 'react';
4
+ import { useSet } from 'react-use-set';
4
5
  import PropTypes from 'prop-types';
5
6
  import omit from 'lodash/omit';
6
7
  import pick from 'lodash/pick';
@@ -8,10 +9,11 @@ import isNil from 'lodash/isNil';
8
9
  import isFunction from 'lodash/isFunction';
9
10
  import shallowEqual from '../utils/shallowEqual';
10
11
  import DropdownMenu from './DropdownMenu';
11
- import { findNodeOfTree, flattenTree, getNodeParents } from '../utils/treeUtils';
12
- import { usePaths } from './utils';
13
- import { getSafeRegExpString, createChainedFunction, mergeRefs, useControlled, useCustom, useClassNames } from '../utils';
12
+ import { findNodeOfTree, flattenTree } from '../utils/treeUtils';
13
+ import { getParentMap, getPathTowardsItem, usePaths } from './utils';
14
+ import { getSafeRegExpString, createChainedFunction, mergeRefs, useControlled, useCustom, useClassNames, useIsMounted } from '../utils';
14
15
  import { PickerToggle, PickerOverlay, SearchBar, PickerToggleTrigger, usePickerClassName, usePublicMethods, useToggleKeyDownEvent, useFocusItemValue, pickTriggerPropKeys, omitTriggerPropKeys, listPickerPropTypes } from '../Picker';
16
+ import { useMap } from '../utils/useMap';
15
17
  var emptyArray = [];
16
18
  var Cascader = /*#__PURE__*/React.forwardRef(function (props, ref) {
17
19
  var _props$as = props.as,
@@ -71,10 +73,6 @@ var Cascader = /*#__PURE__*/React.forwardRef(function (props, ref) {
71
73
  active = _useState[0],
72
74
  setActive = _useState[1];
73
75
 
74
- var _useState2 = useState(flattenTree(data, childrenKey)),
75
- flattenData = _useState2[0],
76
- setFlattenData = _useState2[1];
77
-
78
76
  var triggerRef = useRef(null);
79
77
  var overlayRef = useRef(null);
80
78
  var targetRef = useRef(null);
@@ -84,25 +82,47 @@ var Cascader = /*#__PURE__*/React.forwardRef(function (props, ref) {
84
82
  value = _ref[0],
85
83
  setValue = _ref[1];
86
84
 
85
+ var isMounted = useIsMounted();
86
+ var loadingItemsSet = useSet();
87
+ var asyncChildrenMap = useMap();
88
+ var parentMap = useMemo(function () {
89
+ return getParentMap(data, function (item) {
90
+ var _asyncChildrenMap$get;
91
+
92
+ return (_asyncChildrenMap$get = asyncChildrenMap.get(item)) !== null && _asyncChildrenMap$get !== void 0 ? _asyncChildrenMap$get : item[childrenKey];
93
+ });
94
+ }, [asyncChildrenMap, childrenKey, data]);
95
+ var flattenedData = useMemo(function () {
96
+ return flattenTree(data, function (item) {
97
+ var _asyncChildrenMap$get2;
98
+
99
+ return (_asyncChildrenMap$get2 = asyncChildrenMap.get(item)) !== null && _asyncChildrenMap$get2 !== void 0 ? _asyncChildrenMap$get2 : item[childrenKey];
100
+ });
101
+ }, [asyncChildrenMap, childrenKey, data]); // The item that focus is on
102
+
103
+ var _useState2 = useState(),
104
+ activeItem = _useState2[0],
105
+ setActiveItem = _useState2[1];
106
+
87
107
  var _usePaths = usePaths({
88
108
  data: data,
89
- valueKey: valueKey,
90
- childrenKey: childrenKey,
91
- value: value
109
+ activeItem: activeItem,
110
+ selectedItem: flattenedData.find(function (item) {
111
+ return item[valueKey] === value;
112
+ }),
113
+ getParent: function getParent(item) {
114
+ return parentMap.get(item);
115
+ },
116
+ getChildren: function getChildren(item) {
117
+ var _asyncChildrenMap$get3;
118
+
119
+ return (_asyncChildrenMap$get3 = asyncChildrenMap.get(item)) !== null && _asyncChildrenMap$get3 !== void 0 ? _asyncChildrenMap$get3 : item[childrenKey];
120
+ }
92
121
  }),
93
- selectedPaths = _usePaths.selectedPaths,
94
- valueToPaths = _usePaths.valueToPaths,
95
- columnData = _usePaths.columnData,
96
- addColumn = _usePaths.addColumn,
97
- removeColumnByIndex = _usePaths.removeColumnByIndex,
98
- setValueToPaths = _usePaths.setValueToPaths,
99
- setColumnData = _usePaths.setColumnData,
100
- setSelectedPaths = _usePaths.setSelectedPaths,
101
- enforceUpdate = _usePaths.enforceUpdate;
102
-
103
- useEffect(function () {
104
- setFlattenData(flattenTree(data, childrenKey));
105
- }, [data, childrenKey]);
122
+ columnsToDisplay = _usePaths.columnsToDisplay,
123
+ pathTowardsActiveItem = _usePaths.pathTowardsActiveItem,
124
+ pathTowardsSelectedItem = _usePaths.pathTowardsSelectedItem;
125
+
106
126
  usePublicMethods(ref, {
107
127
  triggerRef: triggerRef,
108
128
  overlayRef: overlayRef,
@@ -118,7 +138,7 @@ var Cascader = /*#__PURE__*/React.forwardRef(function (props, ref) {
118
138
  */
119
139
 
120
140
 
121
- var hasValue = valueToPaths.length > 0 || !isNil(value) && isFunction(renderValue);
141
+ var hasValue = pathTowardsSelectedItem.length > 0 || !isNil(value) && isFunction(renderValue);
122
142
 
123
143
  var _useClassNames = useClassNames(classPrefix),
124
144
  prefix = _useClassNames.prefix,
@@ -133,15 +153,17 @@ var Cascader = /*#__PURE__*/React.forwardRef(function (props, ref) {
133
153
  return true;
134
154
  }
135
155
 
136
- if (item.parent && someKeyword(item.parent)) {
156
+ var parent = parentMap.get(item);
157
+
158
+ if (parent && someKeyword(parent)) {
137
159
  return true;
138
160
  }
139
161
 
140
162
  return false;
141
- }, [labelKey, searchKeyword]);
163
+ }, [labelKey, parentMap, searchKeyword]);
142
164
  var getSearchResult = useCallback(function (keyword) {
143
165
  var items = [];
144
- var result = flattenData.filter(function (item) {
166
+ var result = flattenedData.filter(function (item) {
145
167
  if (!parentSelectable && item[childrenKey]) {
146
168
  return false;
147
169
  }
@@ -158,19 +180,24 @@ var Cascader = /*#__PURE__*/React.forwardRef(function (props, ref) {
158
180
  }
159
181
 
160
182
  return items;
161
- }, [childrenKey, flattenData, someKeyword, parentSelectable]); // Used to hover the focuse item when trigger `onKeydown`
183
+ }, [childrenKey, flattenedData, someKeyword, parentSelectable]); // Used to hover the focuse item when trigger `onKeydown`
162
184
 
163
185
  var _useFocusItemValue = useFocusItemValue(value, {
164
186
  rtl: rtl,
165
- data: flattenData,
187
+ data: flattenedData,
166
188
  valueKey: valueKey,
167
- defaultLayer: valueToPaths !== null && valueToPaths !== void 0 && valueToPaths.length ? valueToPaths.length - 1 : 0,
189
+ defaultLayer: pathTowardsSelectedItem !== null && pathTowardsSelectedItem !== void 0 && pathTowardsSelectedItem.length ? pathTowardsSelectedItem.length - 1 : 0,
168
190
  target: function target() {
169
191
  return overlayRef.current;
170
192
  },
193
+ getParent: function getParent(item) {
194
+ return parentMap.get(item);
195
+ },
171
196
  callback: useCallback(function (value) {
172
- enforceUpdate(value, true);
173
- }, [enforceUpdate])
197
+ setActiveItem(flattenedData.find(function (item) {
198
+ return item[valueKey] === value;
199
+ }));
200
+ }, [flattenedData, setActiveItem, valueKey])
174
201
  }),
175
202
  focusItemValue = _useFocusItemValue.focusItemValue,
176
203
  setFocusItemValue = _useFocusItemValue.setFocusItemValue,
@@ -216,12 +243,9 @@ var Cascader = /*#__PURE__*/React.forwardRef(function (props, ref) {
216
243
  return;
217
244
  }
218
245
 
219
- setColumnData([data]);
220
246
  setValue(null);
221
- setSelectedPaths([]);
222
- setValueToPaths([]);
223
247
  onChange === null || onChange === void 0 ? void 0 : onChange(null, event);
224
- }, [data, disabled, onChange, setSelectedPaths, setColumnData, setValueToPaths, setValue]);
248
+ }, [disabled, onChange, setValue]);
225
249
  var handleMenuPressEnter = useCallback(function (event) {
226
250
  var focusItem = findNodeOfTree(data, function (item) {
227
251
  return item[valueKey] === focusItemValue;
@@ -230,10 +254,9 @@ var Cascader = /*#__PURE__*/React.forwardRef(function (props, ref) {
230
254
 
231
255
  if (isLeafNode) {
232
256
  setValue(focusItemValue);
233
- setValueToPaths(selectedPaths);
234
257
 
235
- if (selectedPaths.length) {
236
- setLayer(selectedPaths.length - 1);
258
+ if (pathTowardsActiveItem.length) {
259
+ setLayer(pathTowardsActiveItem.length - 1);
237
260
  }
238
261
 
239
262
  if (!shallowEqual(value, focusItemValue)) {
@@ -242,7 +265,7 @@ var Cascader = /*#__PURE__*/React.forwardRef(function (props, ref) {
242
265
 
243
266
  handleClose();
244
267
  }
245
- }, [childrenKey, data, focusItemValue, handleClose, onChange, selectedPaths, setLayer, setValue, setValueToPaths, value, valueKey]);
268
+ }, [childrenKey, data, focusItemValue, handleClose, onChange, pathTowardsActiveItem, setLayer, setValue, value, valueKey]);
246
269
  var onPickerKeyDown = useToggleKeyDownEvent(_extends({
247
270
  toggle: !focusItemValue || !active,
248
271
  triggerRef: triggerRef,
@@ -256,44 +279,32 @@ var Cascader = /*#__PURE__*/React.forwardRef(function (props, ref) {
256
279
  }, rest));
257
280
 
258
281
  var handleSelect = function handleSelect(node, cascadePaths, isLeafNode, event) {
259
- var _node$childrenKey, _node$childrenKey2, _triggerRef$current2;
282
+ var _node$childrenKey, _triggerRef$current2;
260
283
 
261
284
  onSelect === null || onSelect === void 0 ? void 0 : onSelect(node, cascadePaths, event);
262
- setSelectedPaths(cascadePaths);
263
- var nextValue = node[valueKey];
264
- var columnIndex = cascadePaths.length; // Lazy load node's children
285
+ setActiveItem(node);
286
+ var nextValue = node[valueKey]; // Lazy load node's children
265
287
 
266
- if (typeof getChildren === 'function' && ((_node$childrenKey = node[childrenKey]) === null || _node$childrenKey === void 0 ? void 0 : _node$childrenKey.length) === 0) {
267
- node.loading = true;
288
+ if (typeof getChildren === 'function' && ((_node$childrenKey = node[childrenKey]) === null || _node$childrenKey === void 0 ? void 0 : _node$childrenKey.length) === 0 && !asyncChildrenMap.has(node)) {
289
+ loadingItemsSet.add(node);
268
290
  var children = getChildren(node);
269
291
 
270
292
  if (children instanceof Promise) {
271
293
  children.then(function (data) {
272
- node.loading = false;
273
- node[childrenKey] = data;
274
-
275
- if (targetRef.current || inline) {
276
- addColumn(data, columnIndex);
294
+ if (isMounted()) {
295
+ loadingItemsSet.delete(node);
296
+ asyncChildrenMap.set(node, data);
277
297
  }
278
298
  });
279
299
  } else {
280
- node.loading = false;
281
- node[childrenKey] = children;
282
- addColumn(children, columnIndex);
300
+ loadingItemsSet.delete(node);
301
+ asyncChildrenMap.set(node, children);
283
302
  }
284
- } else if ((_node$childrenKey2 = node[childrenKey]) !== null && _node$childrenKey2 !== void 0 && _node$childrenKey2.length) {
285
- addColumn(node[childrenKey], columnIndex);
286
- } else {
287
- // Removes subsequent columns of the current column when the clicked node is a leaf node.
288
- removeColumnByIndex(columnIndex);
289
303
  }
290
304
 
291
305
  if (isLeafNode) {
292
306
  // Determines whether the option is a leaf node, and if so, closes the picker.
293
- handleClose(); // Update the selected path to the value path.
294
- // That is, the selected path will be displayed on the button after clicking the child node.
295
-
296
- setValueToPaths(cascadePaths);
307
+ handleClose();
297
308
  setValue(nextValue);
298
309
 
299
310
  if (!shallowEqual(value, nextValue)) {
@@ -308,7 +319,6 @@ var Cascader = /*#__PURE__*/React.forwardRef(function (props, ref) {
308
319
  if (parentSelectable && !shallowEqual(value, nextValue)) {
309
320
  setValue(nextValue);
310
321
  onChange === null || onChange === void 0 ? void 0 : onChange(nextValue, event);
311
- setValueToPaths(cascadePaths);
312
322
  } // Update menu position
313
323
 
314
324
 
@@ -324,16 +334,15 @@ var Cascader = /*#__PURE__*/React.forwardRef(function (props, ref) {
324
334
  handleClose();
325
335
  setSearchKeyword('');
326
336
  setValue(nextValue);
327
- setValueToPaths(nodes);
328
- enforceUpdate(nextValue);
329
337
  onSelect === null || onSelect === void 0 ? void 0 : onSelect(node, nodes, event);
330
338
  onChange === null || onChange === void 0 ? void 0 : onChange(nextValue, event);
331
339
  };
332
340
 
333
341
  var renderSearchRow = function renderSearchRow(item, key) {
334
342
  var regx = new RegExp(getSafeRegExpString(searchKeyword), 'ig');
335
- var nodes = getNodeParents(item);
336
- nodes.push(item);
343
+ var nodes = getPathTowardsItem(item, function (item) {
344
+ return parentMap.get(item);
345
+ });
337
346
  var formattedNodes = nodes.map(function (node) {
338
347
  var _extends2;
339
348
 
@@ -426,12 +435,13 @@ var Cascader = /*#__PURE__*/React.forwardRef(function (props, ref) {
426
435
  menuWidth: menuWidth,
427
436
  menuHeight: menuHeight,
428
437
  disabledItemValues: disabledItemValues,
438
+ loadingItemsSet: loadingItemsSet,
429
439
  valueKey: valueKey,
430
440
  labelKey: labelKey,
431
441
  childrenKey: childrenKey,
432
442
  classPrefix: 'picker-cascader-menu',
433
- cascadeData: columnData,
434
- cascadePaths: selectedPaths,
443
+ cascadeData: columnsToDisplay,
444
+ cascadePaths: pathTowardsActiveItem,
435
445
  activeItemValue: value // FIXME make onSelect generic
436
446
  ,
437
447
  onSelect: handleSelect,
@@ -442,15 +452,15 @@ var Cascader = /*#__PURE__*/React.forwardRef(function (props, ref) {
442
452
 
443
453
  var selectedElement = placeholder;
444
454
 
445
- if (valueToPaths.length > 0) {
455
+ if (pathTowardsSelectedItem.length > 0) {
446
456
  selectedElement = [];
447
- valueToPaths.forEach(function (item, index) {
457
+ pathTowardsSelectedItem.forEach(function (item, index) {
448
458
  var key = item[valueKey] || item[labelKey];
449
459
  selectedElement.push( /*#__PURE__*/React.createElement("span", {
450
460
  key: key
451
461
  }, item[labelKey]));
452
462
 
453
- if (index < valueToPaths.length - 1) {
463
+ if (index < pathTowardsSelectedItem.length - 1) {
454
464
  selectedElement.push( /*#__PURE__*/React.createElement("span", {
455
465
  className: "separator",
456
466
  key: key + "-separator"
@@ -460,7 +470,7 @@ var Cascader = /*#__PURE__*/React.forwardRef(function (props, ref) {
460
470
  }
461
471
 
462
472
  if (!isNil(value) && isFunction(renderValue)) {
463
- selectedElement = renderValue(value, valueToPaths, selectedElement); // If renderValue returns null or undefined, hasValue is false.
473
+ selectedElement = renderValue(value, pathTowardsSelectedItem, selectedElement); // If renderValue returns null or undefined, hasValue is false.
464
474
 
465
475
  if (isNil(selectedElement)) {
466
476
  hasValue = false;
@@ -2,19 +2,23 @@ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { ItemDataType, WithAsProps, RsRefForwardingComponent } from '../@types/common';
4
4
  import { ValueType } from './Cascader';
5
+ declare type SetLike<T = unknown> = {
6
+ has(value: T): boolean;
7
+ };
5
8
  export interface DropdownMenuProps extends Omit<WithAsProps, 'classPrefix'> {
6
9
  classPrefix: string;
7
10
  disabledItemValues: ValueType[];
8
11
  activeItemValue?: ValueType | null;
9
12
  childrenKey: string;
10
- cascadeData: ItemDataType[][];
13
+ cascadeData: (readonly ItemDataType[])[];
14
+ loadingItemsSet?: SetLike<ItemDataType>;
11
15
  cascadePaths: ItemDataType[];
12
16
  valueKey: string;
13
17
  labelKey: string;
14
18
  menuWidth?: number;
15
19
  menuHeight?: number | string;
16
20
  renderMenuItem?: (itemLabel: React.ReactNode, item: ItemDataType) => React.ReactNode;
17
- renderMenu?: (items: ItemDataType[], menu: React.ReactNode, parentNode?: ItemDataType, layer?: number) => React.ReactNode;
21
+ renderMenu?: (items: readonly ItemDataType[], menu: React.ReactNode, parentNode?: ItemDataType, layer?: number) => React.ReactNode;
18
22
  onSelect?: (node: ItemDataType, cascadePaths: ItemDataType[], isLeafNode: boolean, event: React.MouseEvent) => void;
19
23
  }
20
24
  declare const DropdownMenu: RsRefForwardingComponent<'div', DropdownMenuProps>;
@@ -32,12 +32,13 @@ var DropdownMenu = /*#__PURE__*/React.forwardRef(function (props, ref) {
32
32
  cascadeData = _props$cascadeData === void 0 ? emptyArray : _props$cascadeData,
33
33
  _props$cascadePaths = props.cascadePaths,
34
34
  cascadePaths = _props$cascadePaths === void 0 ? emptyArray : _props$cascadePaths,
35
+ loadingItemsSet = props.loadingItemsSet,
35
36
  _props$labelKey = props.labelKey,
36
37
  labelKey = _props$labelKey === void 0 ? 'label' : _props$labelKey,
37
38
  renderMenu = props.renderMenu,
38
39
  renderMenuItem = props.renderMenuItem,
39
40
  onSelect = props.onSelect,
40
- rest = _objectWithoutPropertiesLoose(props, ["as", "activeItemValue", "classPrefix", "className", "childrenKey", "disabledItemValues", "menuWidth", "menuHeight", "valueKey", "cascadeData", "cascadePaths", "labelKey", "renderMenu", "renderMenuItem", "onSelect"]);
41
+ rest = _objectWithoutPropertiesLoose(props, ["as", "activeItemValue", "classPrefix", "className", "childrenKey", "disabledItemValues", "menuWidth", "menuHeight", "valueKey", "cascadeData", "cascadePaths", "loadingItemsSet", "labelKey", "renderMenu", "renderMenuItem", "onSelect"]);
41
42
 
42
43
  var _useClassNames = useClassNames(classPrefix),
43
44
  merge = _useClassNames.merge,
@@ -91,15 +92,18 @@ var DropdownMenu = /*#__PURE__*/React.forwardRef(function (props, ref) {
91
92
  };
92
93
 
93
94
  var renderCascadeNode = function renderCascadeNode(node, index, layer, focus) {
95
+ var _loadingItemsSet$has;
96
+
94
97
  var children = node[childrenKey];
95
98
  var value = node[valueKey];
96
99
  var label = node[labelKey];
97
100
  var disabled = disabledItemValues.some(function (disabledValue) {
98
101
  return shallowEqual(disabledValue, value);
99
- }); // Use `value` in keys when If `value` is string or number
102
+ });
103
+ var loading = (_loadingItemsSet$has = loadingItemsSet === null || loadingItemsSet === void 0 ? void 0 : loadingItemsSet.has(node)) !== null && _loadingItemsSet$has !== void 0 ? _loadingItemsSet$has : false; // Use `value` in keys when If `value` is string or number
100
104
 
101
105
  var onlyKey = typeof value === 'number' || typeof value === 'string' ? value : index;
102
- var Icon = node.loading ? SpinnerIcon : rtl ? AngleLeftIcon : AngleRightIcon;
106
+ var Icon = loading ? SpinnerIcon : rtl ? AngleLeftIcon : AngleRightIcon;
103
107
  return /*#__PURE__*/React.createElement(DropdownMenuItem, {
104
108
  classPrefix: "picker-cascader-menu-item",
105
109
  as: 'li',
@@ -116,7 +120,7 @@ var DropdownMenu = /*#__PURE__*/React.forwardRef(function (props, ref) {
116
120
  }
117
121
  }, renderMenuItem ? renderMenuItem(label, node) : label, children ? /*#__PURE__*/React.createElement(Icon, {
118
122
  className: prefix('caret'),
119
- spin: node.loading
123
+ spin: loading
120
124
  }) : null);
121
125
  };
122
126
 
@@ -1,23 +1,58 @@
1
- /// <reference types="react" />
2
- export declare function getColumnsAndPaths<T extends Record<string, unknown>>(data: T[], value: any, options: any): {
3
- columns: T[][];
4
- paths: T[];
1
+ declare type GetColumnsAndPathsOptions<T> = {
2
+ getParent: (item: T) => T | undefined;
3
+ getChildren: (item: T) => readonly T[] | undefined;
4
+ };
5
+ /**
6
+ * Calculate columns to be displayed:
7
+ *
8
+ * - Every ancestor level of activeItem should be displayed
9
+ * - The level that activeItem is at should be displayed
10
+ * - If activeItem is a parent node, its child level should be displayed
11
+ *
12
+ * @param items
13
+ * @param value
14
+ * @param options
15
+ * @returns
16
+ */
17
+ export declare function getColumnsAndPaths<T extends Record<string, unknown>>(items: readonly T[], pathTarget: T | undefined, options: GetColumnsAndPathsOptions<T>): {
18
+ columns: (readonly T[])[];
19
+ path: T[];
5
20
  };
6
21
  declare type UsePathsParams<T> = {
7
22
  data: T[];
8
- valueKey: string;
9
- childrenKey: string;
10
- value: unknown;
23
+ /**
24
+ * The item where the focus is on
25
+ */
26
+ activeItem: T | undefined;
27
+ /**
28
+ * The item selected by Cascader's value
29
+ */
30
+ selectedItem: T | undefined;
31
+ getParent: (item: T) => T | undefined;
32
+ getChildren: (item: T) => readonly T[] | undefined;
11
33
  };
12
- export declare function usePaths<T extends Record<string, unknown>>(params: UsePathsParams<T>): {
13
- enforceUpdate: (nextValue: any, isAttachChildren?: boolean) => void;
14
- columnData: T[][];
15
- valueToPaths: T[];
16
- selectedPaths: T[];
17
- setValueToPaths: import("react").Dispatch<import("react").SetStateAction<T[]>>;
18
- setColumnData: import("react").Dispatch<import("react").SetStateAction<T[][]>>;
19
- setSelectedPaths: import("react").Dispatch<import("react").SetStateAction<T[]>>;
20
- addColumn: (column: T[], index: number) => void;
21
- removeColumnByIndex: (index: number) => void;
34
+ /**
35
+ * Caculate following 3 things
36
+ *
37
+ * - The columns of items to be displayed
38
+ * - The path towards the current focused item
39
+ * - The path towards the current selected item (referred to by Cascader's value)
40
+ *
41
+ * @param params
42
+ * @returns
43
+ */
44
+ export declare function usePaths<T extends Record<string, unknown>>({ data, activeItem, selectedItem, getParent, getChildren }: UsePathsParams<T>): {
45
+ columnsToDisplay: (readonly T[])[];
46
+ pathTowardsSelectedItem: T[];
47
+ pathTowardsActiveItem: T[];
22
48
  };
49
+ /**
50
+ * Returns a WeakMap that maps each item in `items` to its parent
51
+ * indicated by `getChildren` function
52
+ */
53
+ export declare function getParentMap<T extends Record<string, unknown>>(items: readonly T[], getChildren: (item: T) => readonly T[] | undefined): WeakMap<T, T>;
54
+ /**
55
+ * Returns an array indicating the hirearchy path from root towards `target` item
56
+ */
57
+ export declare function getPathTowardsItem<T>(target: T | undefined, getParent: (item: T) => T | undefined): T[];
23
58
  export {};