@rc-component/cascader 1.0.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 (95) hide show
  1. package/LICENSE.md +9 -0
  2. package/README.md +300 -0
  3. package/assets/index.less +3 -0
  4. package/assets/list.less +106 -0
  5. package/assets/panel.less +7 -0
  6. package/assets/select.less +3 -0
  7. package/es/Cascader.d.ts +88 -0
  8. package/es/Cascader.js +230 -0
  9. package/es/OptionList/CacheContent.d.ts +7 -0
  10. package/es/OptionList/CacheContent.js +8 -0
  11. package/es/OptionList/Checkbox.d.ts +10 -0
  12. package/es/OptionList/Checkbox.js +24 -0
  13. package/es/OptionList/Column.d.ts +21 -0
  14. package/es/OptionList/Column.js +175 -0
  15. package/es/OptionList/List.d.ts +6 -0
  16. package/es/OptionList/List.js +216 -0
  17. package/es/OptionList/index.d.ts +4 -0
  18. package/es/OptionList/index.js +13 -0
  19. package/es/OptionList/useActive.d.ts +6 -0
  20. package/es/OptionList/useActive.js +26 -0
  21. package/es/OptionList/useKeyboard.d.ts +10 -0
  22. package/es/OptionList/useKeyboard.js +165 -0
  23. package/es/Panel.d.ts +5 -0
  24. package/es/Panel.js +116 -0
  25. package/es/context.d.ts +21 -0
  26. package/es/context.js +3 -0
  27. package/es/hooks/useDisplayValues.d.ts +10 -0
  28. package/es/hooks/useDisplayValues.js +44 -0
  29. package/es/hooks/useEntities.d.ts +10 -0
  30. package/es/hooks/useEntities.js +35 -0
  31. package/es/hooks/useMissingValues.d.ts +3 -0
  32. package/es/hooks/useMissingValues.js +17 -0
  33. package/es/hooks/useOptions.d.ts +9 -0
  34. package/es/hooks/useOptions.js +20 -0
  35. package/es/hooks/useSearchConfig.d.ts +2 -0
  36. package/es/hooks/useSearchConfig.js +27 -0
  37. package/es/hooks/useSearchOptions.d.ts +4 -0
  38. package/es/hooks/useSearchOptions.js +63 -0
  39. package/es/hooks/useSelect.d.ts +4 -0
  40. package/es/hooks/useSelect.js +49 -0
  41. package/es/hooks/useValues.d.ts +9 -0
  42. package/es/hooks/useValues.js +21 -0
  43. package/es/index.d.ts +5 -0
  44. package/es/index.js +4 -0
  45. package/es/utils/commonUtil.d.ts +18 -0
  46. package/es/utils/commonUtil.js +69 -0
  47. package/es/utils/treeUtil.d.ts +9 -0
  48. package/es/utils/treeUtil.js +35 -0
  49. package/es/utils/warningPropsUtil.d.ts +4 -0
  50. package/es/utils/warningPropsUtil.js +29 -0
  51. package/lib/Cascader.d.ts +88 -0
  52. package/lib/Cascader.js +239 -0
  53. package/lib/OptionList/CacheContent.d.ts +7 -0
  54. package/lib/OptionList/CacheContent.js +16 -0
  55. package/lib/OptionList/Checkbox.d.ts +10 -0
  56. package/lib/OptionList/Checkbox.js +33 -0
  57. package/lib/OptionList/Column.d.ts +21 -0
  58. package/lib/OptionList/Column.js +185 -0
  59. package/lib/OptionList/List.d.ts +6 -0
  60. package/lib/OptionList/List.js +224 -0
  61. package/lib/OptionList/index.d.ts +4 -0
  62. package/lib/OptionList/index.js +22 -0
  63. package/lib/OptionList/useActive.d.ts +6 -0
  64. package/lib/OptionList/useActive.js +34 -0
  65. package/lib/OptionList/useKeyboard.d.ts +10 -0
  66. package/lib/OptionList/useKeyboard.js +175 -0
  67. package/lib/Panel.d.ts +5 -0
  68. package/lib/Panel.js +125 -0
  69. package/lib/context.d.ts +21 -0
  70. package/lib/context.js +11 -0
  71. package/lib/hooks/useDisplayValues.d.ts +10 -0
  72. package/lib/hooks/useDisplayValues.js +53 -0
  73. package/lib/hooks/useEntities.d.ts +10 -0
  74. package/lib/hooks/useEntities.js +44 -0
  75. package/lib/hooks/useMissingValues.d.ts +3 -0
  76. package/lib/hooks/useMissingValues.js +25 -0
  77. package/lib/hooks/useOptions.d.ts +9 -0
  78. package/lib/hooks/useOptions.js +29 -0
  79. package/lib/hooks/useSearchConfig.d.ts +2 -0
  80. package/lib/hooks/useSearchConfig.js +36 -0
  81. package/lib/hooks/useSearchOptions.d.ts +4 -0
  82. package/lib/hooks/useSearchOptions.js +71 -0
  83. package/lib/hooks/useSelect.d.ts +4 -0
  84. package/lib/hooks/useSelect.js +55 -0
  85. package/lib/hooks/useValues.d.ts +9 -0
  86. package/lib/hooks/useValues.js +29 -0
  87. package/lib/index.d.ts +5 -0
  88. package/lib/index.js +16 -0
  89. package/lib/utils/commonUtil.d.ts +18 -0
  90. package/lib/utils/commonUtil.js +83 -0
  91. package/lib/utils/treeUtil.d.ts +9 -0
  92. package/lib/utils/treeUtil.js +42 -0
  93. package/lib/utils/warningPropsUtil.d.ts +4 -0
  94. package/lib/utils/warningPropsUtil.js +37 -0
  95. package/package.json +88 -0
@@ -0,0 +1,224 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _classnames = _interopRequireDefault(require("classnames"));
8
+ var React = _interopRequireWildcard(require("react"));
9
+ var _context = _interopRequireDefault(require("../context"));
10
+ var _commonUtil = require("../utils/commonUtil");
11
+ var _treeUtil = require("../utils/treeUtil");
12
+ var _CacheContent = _interopRequireDefault(require("./CacheContent"));
13
+ var _Column = _interopRequireWildcard(require("./Column"));
14
+ var _useActive = _interopRequireDefault(require("./useActive"));
15
+ var _useKeyboard = _interopRequireDefault(require("./useKeyboard"));
16
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
17
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
18
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
+ function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } /* eslint-disable default-case */
20
+ const RawOptionList = /*#__PURE__*/React.forwardRef((props, ref) => {
21
+ const {
22
+ prefixCls,
23
+ multiple,
24
+ searchValue,
25
+ toggleOpen,
26
+ notFoundContent,
27
+ direction,
28
+ open,
29
+ disabled
30
+ } = props;
31
+ const containerRef = React.useRef(null);
32
+ const rtl = direction === 'rtl';
33
+ const {
34
+ options,
35
+ values,
36
+ halfValues,
37
+ fieldNames,
38
+ changeOnSelect,
39
+ onSelect,
40
+ searchOptions,
41
+ dropdownPrefixCls,
42
+ loadData,
43
+ expandTrigger
44
+ } = React.useContext(_context.default);
45
+ const mergedPrefixCls = dropdownPrefixCls || prefixCls;
46
+
47
+ // ========================= loadData =========================
48
+ const [loadingKeys, setLoadingKeys] = React.useState([]);
49
+ const internalLoadData = valueCells => {
50
+ // Do not load when search
51
+ if (!loadData || searchValue) {
52
+ return;
53
+ }
54
+ const optionList = (0, _treeUtil.toPathOptions)(valueCells, options, fieldNames);
55
+ const rawOptions = optionList.map(({
56
+ option
57
+ }) => option);
58
+ const lastOption = rawOptions[rawOptions.length - 1];
59
+ if (lastOption && !(0, _commonUtil.isLeaf)(lastOption, fieldNames)) {
60
+ const pathKey = (0, _commonUtil.toPathKey)(valueCells);
61
+ setLoadingKeys(keys => [...keys, pathKey]);
62
+ loadData(rawOptions);
63
+ }
64
+ };
65
+
66
+ // zombieJ: This is bad. We should make this same as `rc-tree` to use Promise instead.
67
+ React.useEffect(() => {
68
+ if (loadingKeys.length) {
69
+ loadingKeys.forEach(loadingKey => {
70
+ const valueStrCells = (0, _commonUtil.toPathValueStr)(loadingKey);
71
+ const optionList = (0, _treeUtil.toPathOptions)(valueStrCells, options, fieldNames, true).map(({
72
+ option
73
+ }) => option);
74
+ const lastOption = optionList[optionList.length - 1];
75
+ if (!lastOption || lastOption[fieldNames.children] || (0, _commonUtil.isLeaf)(lastOption, fieldNames)) {
76
+ setLoadingKeys(keys => keys.filter(key => key !== loadingKey));
77
+ }
78
+ });
79
+ }
80
+ }, [options, loadingKeys, fieldNames]);
81
+
82
+ // ========================== Values ==========================
83
+ const checkedSet = React.useMemo(() => new Set((0, _commonUtil.toPathKeys)(values)), [values]);
84
+ const halfCheckedSet = React.useMemo(() => new Set((0, _commonUtil.toPathKeys)(halfValues)), [halfValues]);
85
+
86
+ // ====================== Accessibility =======================
87
+ const [activeValueCells, setActiveValueCells] = (0, _useActive.default)(multiple, open);
88
+
89
+ // =========================== Path ===========================
90
+ const onPathOpen = nextValueCells => {
91
+ setActiveValueCells(nextValueCells);
92
+
93
+ // Trigger loadData
94
+ internalLoadData(nextValueCells);
95
+ };
96
+ const isSelectable = option => {
97
+ if (disabled) {
98
+ return false;
99
+ }
100
+ const {
101
+ disabled: optionDisabled
102
+ } = option;
103
+ const isMergedLeaf = (0, _commonUtil.isLeaf)(option, fieldNames);
104
+ return !optionDisabled && (isMergedLeaf || changeOnSelect || multiple);
105
+ };
106
+ const onPathSelect = (valuePath, leaf, fromKeyboard = false) => {
107
+ onSelect(valuePath);
108
+ if (!multiple && (leaf || changeOnSelect && (expandTrigger === 'hover' || fromKeyboard))) {
109
+ toggleOpen(false);
110
+ }
111
+ };
112
+
113
+ // ========================== Option ==========================
114
+ const mergedOptions = React.useMemo(() => {
115
+ if (searchValue) {
116
+ return searchOptions;
117
+ }
118
+ return options;
119
+ }, [searchValue, searchOptions, options]);
120
+
121
+ // ========================== Column ==========================
122
+ const optionColumns = React.useMemo(() => {
123
+ const optionList = [{
124
+ options: mergedOptions
125
+ }];
126
+ let currentList = mergedOptions;
127
+ const fullPathKeys = (0, _commonUtil.getFullPathKeys)(currentList, fieldNames);
128
+ for (let i = 0; i < activeValueCells.length; i += 1) {
129
+ const activeValueCell = activeValueCells[i];
130
+ const currentOption = currentList.find((option, index) => (fullPathKeys[index] ? (0, _commonUtil.toPathKey)(fullPathKeys[index]) : option[fieldNames.value]) === activeValueCell);
131
+ const subOptions = currentOption?.[fieldNames.children];
132
+ if (!subOptions?.length) {
133
+ break;
134
+ }
135
+ currentList = subOptions;
136
+ optionList.push({
137
+ options: subOptions
138
+ });
139
+ }
140
+ return optionList;
141
+ }, [mergedOptions, activeValueCells, fieldNames]);
142
+
143
+ // ========================= Keyboard =========================
144
+ const onKeyboardSelect = (selectValueCells, option) => {
145
+ if (isSelectable(option)) {
146
+ onPathSelect(selectValueCells, (0, _commonUtil.isLeaf)(option, fieldNames), true);
147
+ }
148
+ };
149
+ (0, _useKeyboard.default)(ref, mergedOptions, fieldNames, activeValueCells, onPathOpen, onKeyboardSelect, {
150
+ direction,
151
+ searchValue,
152
+ toggleOpen,
153
+ open
154
+ });
155
+
156
+ // >>>>> Active Scroll
157
+ React.useEffect(() => {
158
+ if (searchValue) {
159
+ return;
160
+ }
161
+ for (let i = 0; i < activeValueCells.length; i += 1) {
162
+ const cellPath = activeValueCells.slice(0, i + 1);
163
+ const cellKeyPath = (0, _commonUtil.toPathKey)(cellPath);
164
+ const ele = containerRef.current?.querySelector(`li[data-path-key="${cellKeyPath.replace(/\\{0,2}"/g, '\\"')}"]` // matches unescaped double quotes
165
+ );
166
+
167
+ if (ele) {
168
+ (0, _commonUtil.scrollIntoParentView)(ele);
169
+ }
170
+ }
171
+ }, [activeValueCells, searchValue]);
172
+
173
+ // ========================== Render ==========================
174
+ // >>>>> Empty
175
+ const isEmpty = !optionColumns[0]?.options?.length;
176
+ const emptyList = [{
177
+ [fieldNames.value]: '__EMPTY__',
178
+ [_Column.FIX_LABEL]: notFoundContent,
179
+ disabled: true
180
+ }];
181
+ const columnProps = {
182
+ ...props,
183
+ multiple: !isEmpty && multiple,
184
+ onSelect: onPathSelect,
185
+ onActive: onPathOpen,
186
+ onToggleOpen: toggleOpen,
187
+ checkedSet,
188
+ halfCheckedSet,
189
+ loadingKeys,
190
+ isSelectable
191
+ };
192
+
193
+ // >>>>> Columns
194
+ const mergedOptionColumns = isEmpty ? [{
195
+ options: emptyList
196
+ }] : optionColumns;
197
+ const columnNodes = mergedOptionColumns.map((col, index) => {
198
+ const prevValuePath = activeValueCells.slice(0, index);
199
+ const activeValue = activeValueCells[index];
200
+ return /*#__PURE__*/React.createElement(_Column.default, _extends({
201
+ key: index
202
+ }, columnProps, {
203
+ prefixCls: mergedPrefixCls,
204
+ options: col.options,
205
+ prevValuePath: prevValuePath,
206
+ activeValue: activeValue
207
+ }));
208
+ });
209
+
210
+ // >>>>> Render
211
+ return /*#__PURE__*/React.createElement(_CacheContent.default, {
212
+ open: open
213
+ }, /*#__PURE__*/React.createElement("div", {
214
+ className: (0, _classnames.default)(`${mergedPrefixCls}-menus`, {
215
+ [`${mergedPrefixCls}-menu-empty`]: isEmpty,
216
+ [`${mergedPrefixCls}-rtl`]: rtl
217
+ }),
218
+ ref: containerRef
219
+ }, columnNodes));
220
+ });
221
+ if (process.env.NODE_ENV !== 'production') {
222
+ RawOptionList.displayName = 'RawOptionList';
223
+ }
224
+ var _default = exports.default = RawOptionList;
@@ -0,0 +1,4 @@
1
+ import type { RefOptionListProps } from '@rc-component/select/lib/OptionList';
2
+ import * as React from 'react';
3
+ declare const RefOptionList: React.ForwardRefExoticComponent<React.RefAttributes<RefOptionListProps>>;
4
+ export default RefOptionList;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _select = require("@rc-component/select");
8
+ var React = _interopRequireWildcard(require("react"));
9
+ var _List = _interopRequireDefault(require("./List"));
10
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
12
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
13
+ function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
14
+ const RefOptionList = /*#__PURE__*/React.forwardRef((props, ref) => {
15
+ const baseProps = (0, _select.useBaseProps)();
16
+
17
+ // >>>>> Render
18
+ return /*#__PURE__*/React.createElement(_List.default, _extends({}, props, baseProps, {
19
+ ref: ref
20
+ }));
21
+ });
22
+ var _default = exports.default = RefOptionList;
@@ -0,0 +1,6 @@
1
+ import * as React from 'react';
2
+ /**
3
+ * Control the active open options path.
4
+ */
5
+ declare const useActive: (multiple?: boolean, open?: boolean) => [React.Key[], (activeValueCells: React.Key[]) => void];
6
+ export default useActive;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var React = _interopRequireWildcard(require("react"));
8
+ var _context = _interopRequireDefault(require("../context"));
9
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
10
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
11
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
12
+ /**
13
+ * Control the active open options path.
14
+ */
15
+ const useActive = (multiple, open) => {
16
+ const {
17
+ values
18
+ } = React.useContext(_context.default);
19
+ const firstValueCells = values[0];
20
+
21
+ // Record current dropdown active options
22
+ // This also control the open status
23
+ const [activeValueCells, setActiveValueCells] = React.useState([]);
24
+ React.useEffect(() => {
25
+ if (!multiple) {
26
+ setActiveValueCells(firstValueCells || []);
27
+ }
28
+ }, /* eslint-disable react-hooks/exhaustive-deps */
29
+ [open, firstValueCells]
30
+ /* eslint-enable react-hooks/exhaustive-deps */);
31
+
32
+ return [activeValueCells, setActiveValueCells];
33
+ };
34
+ var _default = exports.default = useActive;
@@ -0,0 +1,10 @@
1
+ import type { RefOptionListProps } from '@rc-component/select/lib/OptionList';
2
+ import * as React from 'react';
3
+ import type { DefaultOptionType, InternalFieldNames, SingleValueType } from '../Cascader';
4
+ declare const _default: (ref: React.Ref<RefOptionListProps>, options: DefaultOptionType[], fieldNames: InternalFieldNames, activeValueCells: React.Key[], setActiveValueCells: (activeValueCells: React.Key[]) => void, onKeyBoardSelect: (valueCells: SingleValueType, option: DefaultOptionType) => void, contextProps: {
5
+ direction?: "ltr" | "rtl" | undefined;
6
+ searchValue: string;
7
+ toggleOpen: (open?: boolean) => void;
8
+ open?: boolean | undefined;
9
+ }) => void;
10
+ export default _default;
@@ -0,0 +1,175 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _KeyCode = _interopRequireDefault(require("@rc-component/util/lib/KeyCode"));
8
+ var React = _interopRequireWildcard(require("react"));
9
+ var _useSearchOptions = require("../hooks/useSearchOptions");
10
+ var _commonUtil = require("../utils/commonUtil");
11
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
12
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
13
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14
+ var _default = (ref, options, fieldNames, activeValueCells, setActiveValueCells, onKeyBoardSelect, contextProps) => {
15
+ const {
16
+ direction,
17
+ searchValue,
18
+ toggleOpen,
19
+ open
20
+ } = contextProps;
21
+ const rtl = direction === 'rtl';
22
+ const [validActiveValueCells, lastActiveIndex, lastActiveOptions, fullPathKeys] = React.useMemo(() => {
23
+ let activeIndex = -1;
24
+ let currentOptions = options;
25
+ const mergedActiveIndexes = [];
26
+ const mergedActiveValueCells = [];
27
+ const len = activeValueCells.length;
28
+ const pathKeys = (0, _commonUtil.getFullPathKeys)(options, fieldNames);
29
+
30
+ // Fill validate active value cells and index
31
+ for (let i = 0; i < len && currentOptions; i += 1) {
32
+ // Mark the active index for current options
33
+ const nextActiveIndex = currentOptions.findIndex((option, index) => (pathKeys[index] ? (0, _commonUtil.toPathKey)(pathKeys[index]) : option[fieldNames.value]) === activeValueCells[i]);
34
+ if (nextActiveIndex === -1) {
35
+ break;
36
+ }
37
+ activeIndex = nextActiveIndex;
38
+ mergedActiveIndexes.push(activeIndex);
39
+ mergedActiveValueCells.push(activeValueCells[i]);
40
+ currentOptions = currentOptions[activeIndex][fieldNames.children];
41
+ }
42
+
43
+ // Fill last active options
44
+ let activeOptions = options;
45
+ for (let i = 0; i < mergedActiveIndexes.length - 1; i += 1) {
46
+ activeOptions = activeOptions[mergedActiveIndexes[i]][fieldNames.children];
47
+ }
48
+ return [mergedActiveValueCells, activeIndex, activeOptions, pathKeys];
49
+ }, [activeValueCells, fieldNames, options]);
50
+
51
+ // Update active value cells and scroll to target element
52
+ const internalSetActiveValueCells = next => {
53
+ setActiveValueCells(next);
54
+ };
55
+
56
+ // Same options offset
57
+ const offsetActiveOption = offset => {
58
+ const len = lastActiveOptions.length;
59
+ let currentIndex = lastActiveIndex;
60
+ if (currentIndex === -1 && offset < 0) {
61
+ currentIndex = len;
62
+ }
63
+ for (let i = 0; i < len; i += 1) {
64
+ currentIndex = (currentIndex + offset + len) % len;
65
+ const option = lastActiveOptions[currentIndex];
66
+ if (option && !option.disabled) {
67
+ const nextActiveCells = validActiveValueCells.slice(0, -1).concat(fullPathKeys[currentIndex] ? (0, _commonUtil.toPathKey)(fullPathKeys[currentIndex]) : option[fieldNames.value]);
68
+ internalSetActiveValueCells(nextActiveCells);
69
+ return;
70
+ }
71
+ }
72
+ };
73
+
74
+ // Different options offset
75
+ const prevColumn = () => {
76
+ if (validActiveValueCells.length > 1) {
77
+ const nextActiveCells = validActiveValueCells.slice(0, -1);
78
+ internalSetActiveValueCells(nextActiveCells);
79
+ } else {
80
+ toggleOpen(false);
81
+ }
82
+ };
83
+ const nextColumn = () => {
84
+ const nextOptions = lastActiveOptions[lastActiveIndex]?.[fieldNames.children] || [];
85
+ const nextOption = nextOptions.find(option => !option.disabled);
86
+ if (nextOption) {
87
+ const nextActiveCells = [...validActiveValueCells, nextOption[fieldNames.value]];
88
+ internalSetActiveValueCells(nextActiveCells);
89
+ }
90
+ };
91
+ React.useImperativeHandle(ref, () => ({
92
+ // scrollTo: treeRef.current?.scrollTo,
93
+ onKeyDown: event => {
94
+ const {
95
+ which
96
+ } = event;
97
+ switch (which) {
98
+ // >>> Arrow keys
99
+ case _KeyCode.default.UP:
100
+ case _KeyCode.default.DOWN:
101
+ {
102
+ let offset = 0;
103
+ if (which === _KeyCode.default.UP) {
104
+ offset = -1;
105
+ } else if (which === _KeyCode.default.DOWN) {
106
+ offset = 1;
107
+ }
108
+ if (offset !== 0) {
109
+ offsetActiveOption(offset);
110
+ }
111
+ break;
112
+ }
113
+ case _KeyCode.default.LEFT:
114
+ {
115
+ if (searchValue) {
116
+ break;
117
+ }
118
+ if (rtl) {
119
+ nextColumn();
120
+ } else {
121
+ prevColumn();
122
+ }
123
+ break;
124
+ }
125
+ case _KeyCode.default.RIGHT:
126
+ {
127
+ if (searchValue) {
128
+ break;
129
+ }
130
+ if (rtl) {
131
+ prevColumn();
132
+ } else {
133
+ nextColumn();
134
+ }
135
+ break;
136
+ }
137
+ case _KeyCode.default.BACKSPACE:
138
+ {
139
+ if (!searchValue) {
140
+ prevColumn();
141
+ }
142
+ break;
143
+ }
144
+
145
+ // >>> Select
146
+ case _KeyCode.default.ENTER:
147
+ {
148
+ if (validActiveValueCells.length) {
149
+ const option = lastActiveOptions[lastActiveIndex];
150
+
151
+ // Search option should revert back of origin options
152
+ const originOptions = option?.[_useSearchOptions.SEARCH_MARK] || [];
153
+ if (originOptions.length) {
154
+ onKeyBoardSelect(originOptions.map(opt => opt[fieldNames.value]), originOptions[originOptions.length - 1]);
155
+ } else {
156
+ onKeyBoardSelect(validActiveValueCells, lastActiveOptions[lastActiveIndex]);
157
+ }
158
+ }
159
+ break;
160
+ }
161
+
162
+ // >>> Close
163
+ case _KeyCode.default.ESC:
164
+ {
165
+ toggleOpen(false);
166
+ if (open) {
167
+ event.stopPropagation();
168
+ }
169
+ }
170
+ }
171
+ },
172
+ onKeyUp: () => {}
173
+ }));
174
+ };
175
+ exports.default = _default;
package/lib/Panel.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ import * as React from 'react';
2
+ import type { CascaderProps, DefaultOptionType } from './Cascader';
3
+ export type PickType = 'value' | 'defaultValue' | 'changeOnSelect' | 'onChange' | 'options' | 'prefixCls' | 'checkable' | 'fieldNames' | 'showCheckedStrategy' | 'loadData' | 'expandTrigger' | 'expandIcon' | 'loadingIcon' | 'className' | 'style' | 'direction' | 'notFoundContent' | 'disabled';
4
+ export type PanelProps<OptionType extends DefaultOptionType = DefaultOptionType, ValueField extends keyof OptionType = keyof OptionType, Multiple extends boolean | React.ReactNode = false> = Pick<CascaderProps<OptionType, ValueField, Multiple>, PickType>;
5
+ export default function Panel<OptionType extends DefaultOptionType = DefaultOptionType, ValueField extends keyof OptionType = keyof OptionType, Multiple extends boolean | React.ReactNode = false>(props: PanelProps<OptionType, ValueField, Multiple>): React.JSX.Element;
package/lib/Panel.js ADDED
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = Panel;
7
+ var _classnames = _interopRequireDefault(require("classnames"));
8
+ var _util = require("@rc-component/util");
9
+ var React = _interopRequireWildcard(require("react"));
10
+ var _context = _interopRequireDefault(require("./context"));
11
+ var _useMissingValues = _interopRequireDefault(require("./hooks/useMissingValues"));
12
+ var _useOptions = _interopRequireDefault(require("./hooks/useOptions"));
13
+ var _useSelect = _interopRequireDefault(require("./hooks/useSelect"));
14
+ var _useValues = _interopRequireDefault(require("./hooks/useValues"));
15
+ var _List = _interopRequireDefault(require("./OptionList/List"));
16
+ var _commonUtil = require("./utils/commonUtil");
17
+ var _treeUtil = require("./utils/treeUtil");
18
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
19
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
20
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
21
+ function noop() {}
22
+ function Panel(props) {
23
+ const {
24
+ prefixCls = 'rc-cascader',
25
+ style,
26
+ className,
27
+ options,
28
+ checkable,
29
+ defaultValue,
30
+ value,
31
+ fieldNames,
32
+ changeOnSelect,
33
+ onChange,
34
+ showCheckedStrategy,
35
+ loadData,
36
+ expandTrigger,
37
+ expandIcon = '>',
38
+ loadingIcon,
39
+ direction,
40
+ notFoundContent = 'Not Found',
41
+ disabled
42
+ } = props;
43
+
44
+ // ======================== Multiple ========================
45
+ const multiple = !!checkable;
46
+
47
+ // ========================= Values =========================
48
+ const [rawValues, setRawValues] = (0, _util.useMergedState)(defaultValue, {
49
+ value,
50
+ postState: _commonUtil.toRawValues
51
+ });
52
+
53
+ // ========================= FieldNames =========================
54
+ const mergedFieldNames = React.useMemo(() => (0, _commonUtil.fillFieldNames)(fieldNames), /* eslint-disable react-hooks/exhaustive-deps */
55
+ [JSON.stringify(fieldNames)]
56
+ /* eslint-enable react-hooks/exhaustive-deps */);
57
+
58
+ // =========================== Option ===========================
59
+ const [mergedOptions, getPathKeyEntities, getValueByKeyPath] = (0, _useOptions.default)(mergedFieldNames, options);
60
+
61
+ // ========================= Values =========================
62
+ const getMissingValues = (0, _useMissingValues.default)(mergedOptions, mergedFieldNames);
63
+
64
+ // Fill `rawValues` with checked conduction values
65
+ const [checkedValues, halfCheckedValues, missingCheckedValues] = (0, _useValues.default)(multiple, rawValues, getPathKeyEntities, getValueByKeyPath, getMissingValues);
66
+
67
+ // =========================== Change ===========================
68
+ const triggerChange = (0, _util.useEvent)(nextValues => {
69
+ setRawValues(nextValues);
70
+
71
+ // Save perf if no need trigger event
72
+ if (onChange) {
73
+ const nextRawValues = (0, _commonUtil.toRawValues)(nextValues);
74
+ const valueOptions = nextRawValues.map(valueCells => (0, _treeUtil.toPathOptions)(valueCells, mergedOptions, mergedFieldNames).map(valueOpt => valueOpt.option));
75
+ const triggerValues = multiple ? nextRawValues : nextRawValues[0];
76
+ const triggerOptions = multiple ? valueOptions : valueOptions[0];
77
+ onChange(triggerValues, triggerOptions);
78
+ }
79
+ });
80
+
81
+ // =========================== Select ===========================
82
+ const handleSelection = (0, _useSelect.default)(multiple, triggerChange, checkedValues, halfCheckedValues, missingCheckedValues, getPathKeyEntities, getValueByKeyPath, showCheckedStrategy);
83
+ const onInternalSelect = (0, _util.useEvent)(valuePath => {
84
+ handleSelection(valuePath);
85
+ });
86
+
87
+ // ======================== Context =========================
88
+ const cascaderContext = React.useMemo(() => ({
89
+ options: mergedOptions,
90
+ fieldNames: mergedFieldNames,
91
+ values: checkedValues,
92
+ halfValues: halfCheckedValues,
93
+ changeOnSelect,
94
+ onSelect: onInternalSelect,
95
+ checkable,
96
+ searchOptions: [],
97
+ dropdownPrefixCls: undefined,
98
+ loadData,
99
+ expandTrigger,
100
+ expandIcon,
101
+ loadingIcon,
102
+ dropdownMenuColumnStyle: undefined
103
+ }), [mergedOptions, mergedFieldNames, checkedValues, halfCheckedValues, changeOnSelect, onInternalSelect, checkable, loadData, expandTrigger, expandIcon, loadingIcon]);
104
+
105
+ // ========================= Render =========================
106
+ const panelPrefixCls = `${prefixCls}-panel`;
107
+ const isEmpty = !mergedOptions.length;
108
+ return /*#__PURE__*/React.createElement(_context.default.Provider, {
109
+ value: cascaderContext
110
+ }, /*#__PURE__*/React.createElement("div", {
111
+ className: (0, _classnames.default)(panelPrefixCls, {
112
+ [`${panelPrefixCls}-rtl`]: direction === 'rtl',
113
+ [`${panelPrefixCls}-empty`]: isEmpty
114
+ }, className),
115
+ style: style
116
+ }, isEmpty ? notFoundContent : /*#__PURE__*/React.createElement(_List.default, {
117
+ prefixCls: prefixCls,
118
+ searchValue: "",
119
+ multiple: multiple,
120
+ toggleOpen: noop,
121
+ open: true,
122
+ direction: direction,
123
+ disabled: disabled
124
+ })));
125
+ }
@@ -0,0 +1,21 @@
1
+ import * as React from 'react';
2
+ import type { CascaderProps, InternalFieldNames, DefaultOptionType, SingleValueType } from './Cascader';
3
+ export interface CascaderContextProps {
4
+ options: NonNullable<CascaderProps['options']>;
5
+ fieldNames: InternalFieldNames;
6
+ values: SingleValueType[];
7
+ halfValues: SingleValueType[];
8
+ changeOnSelect?: boolean;
9
+ onSelect: (valuePath: SingleValueType) => void;
10
+ checkable?: boolean | React.ReactNode;
11
+ searchOptions: DefaultOptionType[];
12
+ dropdownPrefixCls?: string;
13
+ loadData?: (selectOptions: DefaultOptionType[]) => void;
14
+ expandTrigger?: 'hover' | 'click';
15
+ expandIcon?: React.ReactNode;
16
+ loadingIcon?: React.ReactNode;
17
+ dropdownMenuColumnStyle?: React.CSSProperties;
18
+ optionRender?: CascaderProps['optionRender'];
19
+ }
20
+ declare const CascaderContext: React.Context<CascaderContextProps>;
21
+ export default CascaderContext;
package/lib/context.js ADDED
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var React = _interopRequireWildcard(require("react"));
8
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
9
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
10
+ const CascaderContext = /*#__PURE__*/React.createContext({});
11
+ var _default = exports.default = CascaderContext;
@@ -0,0 +1,10 @@
1
+ import * as React from 'react';
2
+ import type { DefaultOptionType, SingleValueType, CascaderProps, InternalFieldNames } from '../Cascader';
3
+ declare const _default: (rawValues: SingleValueType[], options: DefaultOptionType[], fieldNames: InternalFieldNames, multiple: boolean, displayRender: CascaderProps['displayRender']) => {
4
+ label: React.ReactNode;
5
+ value: string;
6
+ key: string;
7
+ valueCells: SingleValueType;
8
+ disabled: boolean | undefined;
9
+ }[];
10
+ export default _default;