UNPKG

19.2 kBJavaScriptView Raw
1import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
2import _createClass from "@babel/runtime/helpers/esm/createClass";
3import _inherits from "@babel/runtime/helpers/esm/inherits";
4import _possibleConstructorReturn from "@babel/runtime/helpers/esm/possibleConstructorReturn";
5import _getPrototypeOf from "@babel/runtime/helpers/esm/getPrototypeOf";
6import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
7import _typeof from "@babel/runtime/helpers/esm/typeof";
8import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
9import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
10
11function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
12
13function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }
14
15function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
16
17function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
18
19import React from 'react';
20import generateSelector from "rc-select/es/generate";
21import { getLabeledValue } from "rc-select/es/utils/valueUtil";
22import { convertDataToEntities } from "rc-tree/es/utils/treeUtil";
23import { conductCheck } from "rc-tree/es/utils/conductUtil";
24import { INTERNAL_PROPS_MARK } from "rc-select/es/interface/generator";
25import warning from "rc-util/es/warning";
26import OptionList from './OptionList';
27import TreeNode from './TreeNode';
28import { flattenOptions, filterOptions, isValueDisabled, findValueOption, addValue, removeValue, getRawValueLabeled, toArray } from './utils/valueUtil';
29import warningProps from './utils/warningPropsUtil';
30import { SelectContext } from './Context';
31import useTreeData from './hooks/useTreeData';
32import useKeyValueMap from './hooks/useKeyValueMap';
33import useKeyValueMapping from './hooks/useKeyValueMapping';
34import { formatStrategyKeys, SHOW_ALL, SHOW_PARENT, SHOW_CHILD } from './utils/strategyUtil';
35import { fillAdditionalInfo } from './utils/legacyUtil';
36import useSelectValues from './hooks/useSelectValues';
37var OMIT_PROPS = ['expandedKeys', 'treeData', 'treeCheckable', 'showCheckedStrategy', 'searchPlaceholder', 'treeLine', 'treeIcon', 'showTreeIcon', 'switcherIcon', 'treeNodeFilterProp', 'filterTreeNode', 'dropdownPopupAlign', 'treeDefaultExpandAll', 'treeCheckStrictly', 'treeExpandedKeys', 'treeLoadedKeys', 'treeMotion', 'onTreeExpand', 'onTreeLoad', 'loadData', 'treeDataSimpleMode', 'treeNodeLabelProp', 'treeDefaultExpandedKeys'];
38var RefSelect = generateSelector({
39 prefixCls: 'rc-tree-select',
40 components: {
41 optionList: OptionList
42 },
43 // Not use generate since we will handle ourself
44 convertChildrenToData: function convertChildrenToData() {
45 return null;
46 },
47 flattenOptions: flattenOptions,
48 // Handle `optionLabelProp` in TreeSelect component
49 getLabeledValue: getLabeledValue,
50 filterOptions: filterOptions,
51 isValueDisabled: isValueDisabled,
52 findValueOption: findValueOption,
53 omitDOMProps: function omitDOMProps(props) {
54 var cloneProps = _objectSpread({}, props);
55
56 OMIT_PROPS.forEach(function (prop) {
57 delete cloneProps[prop];
58 });
59 return cloneProps;
60 }
61});
62RefSelect.displayName = 'Select';
63var RefTreeSelect = React.forwardRef(function (props, ref) {
64 var multiple = props.multiple,
65 treeCheckable = props.treeCheckable,
66 treeCheckStrictly = props.treeCheckStrictly,
67 _props$showCheckedStr = props.showCheckedStrategy,
68 showCheckedStrategy = _props$showCheckedStr === void 0 ? 'SHOW_CHILD' : _props$showCheckedStr,
69 labelInValue = props.labelInValue,
70 loadData = props.loadData,
71 treeLoadedKeys = props.treeLoadedKeys,
72 _props$treeNodeFilter = props.treeNodeFilterProp,
73 treeNodeFilterProp = _props$treeNodeFilter === void 0 ? 'value' : _props$treeNodeFilter,
74 treeNodeLabelProp = props.treeNodeLabelProp,
75 treeDataSimpleMode = props.treeDataSimpleMode,
76 treeData = props.treeData,
77 treeExpandedKeys = props.treeExpandedKeys,
78 treeDefaultExpandedKeys = props.treeDefaultExpandedKeys,
79 treeDefaultExpandAll = props.treeDefaultExpandAll,
80 children = props.children,
81 treeIcon = props.treeIcon,
82 showTreeIcon = props.showTreeIcon,
83 switcherIcon = props.switcherIcon,
84 treeLine = props.treeLine,
85 treeMotion = props.treeMotion,
86 filterTreeNode = props.filterTreeNode,
87 dropdownPopupAlign = props.dropdownPopupAlign,
88 onChange = props.onChange,
89 onTreeExpand = props.onTreeExpand,
90 onTreeLoad = props.onTreeLoad,
91 onDropdownVisibleChange = props.onDropdownVisibleChange,
92 onSelect = props.onSelect,
93 onDeselect = props.onDeselect;
94 var mergedCheckable = treeCheckable || treeCheckStrictly;
95 var mergedMultiple = multiple || mergedCheckable;
96 var treeConduction = treeCheckable && !treeCheckStrictly;
97 var mergedLabelInValue = treeCheckStrictly || labelInValue; // ========================== Ref ==========================
98
99 var selectRef = React.useRef(null);
100 React.useImperativeHandle(ref, function () {
101 return {
102 focus: selectRef.current.focus,
103 blur: selectRef.current.blur
104 };
105 }); // ======================= Tree Data =======================
106 // Legacy both support `label` or `title` if not set.
107 // We have to fallback to function to handle this
108
109 var getTreeNodeLabelProp = function getTreeNodeLabelProp(node) {
110 if (treeNodeLabelProp) {
111 return node[treeNodeLabelProp];
112 }
113
114 if (!treeData) {
115 return node.title;
116 }
117
118 return node.label || node.title;
119 };
120
121 var mergedTreeData = useTreeData(treeData, children, {
122 getLabelProp: getTreeNodeLabelProp,
123 simpleMode: treeDataSimpleMode
124 });
125 var flattedOptions = React.useMemo(function () {
126 return flattenOptions(mergedTreeData);
127 }, [mergedTreeData]);
128
129 var _useKeyValueMap = useKeyValueMap(flattedOptions),
130 _useKeyValueMap2 = _slicedToArray(_useKeyValueMap, 2),
131 cacheKeyMap = _useKeyValueMap2[0],
132 cacheValueMap = _useKeyValueMap2[1];
133
134 var _useKeyValueMapping = useKeyValueMapping(cacheKeyMap, cacheValueMap),
135 _useKeyValueMapping2 = _slicedToArray(_useKeyValueMapping, 2),
136 getEntityByKey = _useKeyValueMapping2[0],
137 getEntityByValue = _useKeyValueMapping2[1]; // Only generate keyEntities for check conduction when is `treeCheckable`
138
139
140 var _React$useMemo = React.useMemo(function () {
141 if (treeConduction) {
142 return convertDataToEntities(mergedTreeData);
143 }
144
145 return {
146 keyEntities: null
147 };
148 }, [mergedTreeData, treeCheckable, treeCheckStrictly]),
149 conductKeyEntities = _React$useMemo.keyEntities; // ========================= Value =========================
150
151
152 var _React$useState = React.useState(props.defaultValue),
153 _React$useState2 = _slicedToArray(_React$useState, 2),
154 value = _React$useState2[0],
155 setValue = _React$useState2[1];
156
157 var mergedValue = 'value' in props ? props.value : value;
158 /** Get `missingRawValues` which not exist in the tree yet */
159
160 var splitRawValues = function splitRawValues(newRawValues) {
161 var missingRawValues = [];
162 var existRawValues = []; // Keep missing value in the cache
163
164 newRawValues.forEach(function (val) {
165 if (getEntityByValue(val)) {
166 existRawValues.push(val);
167 } else {
168 missingRawValues.push(val);
169 }
170 });
171 return {
172 missingRawValues: missingRawValues,
173 existRawValues: existRawValues
174 };
175 };
176
177 var _React$useMemo2 = React.useMemo(function () {
178 var valueHalfCheckedKeys = [];
179 var newRawValues = [];
180 toArray(mergedValue).forEach(function (item) {
181 if (item && _typeof(item) === 'object' && 'value' in item) {
182 if (item.halfChecked && treeCheckStrictly) {
183 var entity = getEntityByValue(item.value);
184 valueHalfCheckedKeys.push(entity ? entity.key : item.value);
185 } else {
186 newRawValues.push(item.value);
187 }
188 } else {
189 newRawValues.push(item);
190 }
191 }); // We need do conduction of values
192
193 if (treeConduction) {
194 var _splitRawValues = splitRawValues(newRawValues),
195 missingRawValues = _splitRawValues.missingRawValues,
196 existRawValues = _splitRawValues.existRawValues;
197
198 var keyList = existRawValues.map(function (val) {
199 return getEntityByValue(val).key;
200 });
201
202 var _conductCheck = conductCheck(keyList, true, conductKeyEntities),
203 checkedKeys = _conductCheck.checkedKeys,
204 halfCheckedKeys = _conductCheck.halfCheckedKeys;
205
206 return [[].concat(_toConsumableArray(missingRawValues), _toConsumableArray(checkedKeys.map(function (key) {
207 return getEntityByKey(key).data.value;
208 }))), halfCheckedKeys];
209 }
210
211 return [newRawValues, valueHalfCheckedKeys];
212 }, [mergedValue, mergedMultiple, mergedLabelInValue, treeCheckable, treeCheckStrictly]),
213 _React$useMemo3 = _slicedToArray(_React$useMemo2, 2),
214 rawValues = _React$useMemo3[0],
215 rawHalfCheckedKeys = _React$useMemo3[1];
216
217 var selectValues = useSelectValues(rawValues, {
218 treeConduction: treeConduction,
219 value: mergedValue,
220 showCheckedStrategy: showCheckedStrategy,
221 conductKeyEntities: conductKeyEntities,
222 getEntityByValue: getEntityByValue,
223 getEntityByKey: getEntityByKey,
224 getLabelProp: getTreeNodeLabelProp
225 });
226
227 var triggerChange = function triggerChange(newRawValues, extra, source) {
228 setValue(mergedMultiple ? newRawValues : newRawValues[0]);
229
230 if (onChange) {
231 var eventValues = newRawValues;
232
233 if (treeConduction && showCheckedStrategy !== 'SHOW_ALL') {
234 var keyList = newRawValues.map(function (val) {
235 var entity = getEntityByValue(val);
236 return entity ? entity.key : val;
237 });
238 var formattedKeyList = formatStrategyKeys(keyList, showCheckedStrategy, conductKeyEntities);
239 eventValues = formattedKeyList.map(function (key) {
240 var entity = getEntityByKey(key);
241 return entity ? entity.data.value : key;
242 });
243 }
244
245 var _ref = extra || {
246 triggerValue: undefined,
247 selected: undefined
248 },
249 triggerValue = _ref.triggerValue,
250 selected = _ref.selected;
251
252 var returnValues = mergedLabelInValue ? getRawValueLabeled(eventValues, mergedValue, getEntityByValue, getTreeNodeLabelProp) : eventValues; // We need fill half check back
253
254 if (treeCheckStrictly) {
255 var halfValues = rawHalfCheckedKeys.map(function (key) {
256 var entity = getEntityByKey(key);
257 return entity ? entity.data.value : key;
258 }).filter(function (val) {
259 return !eventValues.includes(val);
260 });
261 returnValues = [].concat(_toConsumableArray(returnValues), _toConsumableArray(getRawValueLabeled(halfValues, mergedValue, getEntityByValue, getTreeNodeLabelProp)));
262 }
263
264 var additionalInfo = {
265 // [Legacy] Always return as array contains label & value
266 preValue: selectValues,
267 triggerValue: triggerValue
268 }; // [Legacy] Fill legacy data if user query.
269 // This is expansive that we only fill when user query
270 // https://github.com/react-component/tree-select/blob/fe33eb7c27830c9ac70cd1fdb1ebbe7bc679c16a/src/Select.jsx
271
272 var showPosition = true;
273
274 if (treeCheckStrictly || source === 'selection' && !selected) {
275 showPosition = false;
276 }
277
278 fillAdditionalInfo(additionalInfo, triggerValue, newRawValues, mergedTreeData, showPosition);
279
280 if (mergedCheckable) {
281 additionalInfo.checked = selected;
282 } else {
283 additionalInfo.selected = selected;
284 }
285
286 onChange(mergedMultiple ? returnValues : returnValues[0], mergedLabelInValue ? null : eventValues.map(function (val) {
287 var entity = getEntityByValue(val);
288 return entity ? getTreeNodeLabelProp(entity.data) : null;
289 }), additionalInfo);
290 }
291 };
292
293 var onInternalSelect = function onInternalSelect(selectValue, option, source) {
294 var eventValue = mergedLabelInValue ? selectValue : selectValue;
295
296 if (!mergedMultiple) {
297 // Single mode always set value
298 triggerChange([selectValue], {
299 selected: true,
300 triggerValue: selectValue
301 }, source);
302 } else {
303 var newRawValues = addValue(rawValues, selectValue); // Add keys if tree conduction
304
305 if (treeConduction) {
306 // Should keep missing values
307 var _splitRawValues2 = splitRawValues(newRawValues),
308 missingRawValues = _splitRawValues2.missingRawValues,
309 existRawValues = _splitRawValues2.existRawValues;
310
311 var keyList = existRawValues.map(function (val) {
312 return getEntityByValue(val).key;
313 });
314
315 var _conductCheck2 = conductCheck(keyList, true, conductKeyEntities),
316 checkedKeys = _conductCheck2.checkedKeys;
317
318 newRawValues = [].concat(_toConsumableArray(missingRawValues), _toConsumableArray(checkedKeys.map(function (key) {
319 return getEntityByKey(key).data.value;
320 })));
321 }
322
323 triggerChange(newRawValues, {
324 selected: true,
325 triggerValue: selectValue
326 }, source);
327 }
328
329 if (onSelect) {
330 onSelect(eventValue, option);
331 }
332 };
333
334 var onInternalDeselect = function onInternalDeselect(selectValue, option, source) {
335 var eventValue = mergedLabelInValue ? selectValue : selectValue;
336 var newRawValues = removeValue(rawValues, selectValue); // Remove keys if tree conduction
337
338 if (treeConduction) {
339 var _splitRawValues3 = splitRawValues(newRawValues),
340 missingRawValues = _splitRawValues3.missingRawValues,
341 existRawValues = _splitRawValues3.existRawValues;
342
343 var keyList = existRawValues.map(function (val) {
344 return getEntityByValue(val).key;
345 });
346
347 var _conductCheck3 = conductCheck(keyList, {
348 checked: false,
349 halfCheckedKeys: rawHalfCheckedKeys
350 }, conductKeyEntities),
351 checkedKeys = _conductCheck3.checkedKeys;
352
353 newRawValues = [].concat(_toConsumableArray(missingRawValues), _toConsumableArray(checkedKeys.map(function (key) {
354 return getEntityByKey(key).data.value;
355 })));
356 }
357
358 triggerChange(newRawValues, {
359 selected: false,
360 triggerValue: selectValue
361 }, source);
362
363 if (onDeselect) {
364 onDeselect(eventValue, option);
365 }
366 };
367
368 var onInternalClear = function onInternalClear() {
369 triggerChange([], null, 'clear');
370 }; // ========================= Open ==========================
371
372
373 var onInternalDropdownVisibleChange = React.useCallback(function (open) {
374 if (onDropdownVisibleChange) {
375 var legacyParam = {};
376 Object.defineProperty(legacyParam, 'documentClickClose', {
377 get: function get() {
378 warning(false, 'Second param of `onDropdownVisibleChange` has been removed.');
379 return false;
380 }
381 });
382 onDropdownVisibleChange(open, legacyParam);
383 }
384 }, [onDropdownVisibleChange]); // ======================== Warning ========================
385
386 if (process.env.NODE_ENV !== 'production') {
387 warningProps(props);
388 } // ======================== Render =========================
389 // We pass some props into select props style
390
391
392 var selectProps = {
393 optionLabelProp: null,
394 optionFilterProp: treeNodeFilterProp,
395 dropdownAlign: dropdownPopupAlign,
396 internalProps: {
397 mark: INTERNAL_PROPS_MARK,
398 onClear: onInternalClear,
399 skipTriggerChange: true,
400 skipTriggerSelect: true,
401 onRawSelect: onInternalSelect,
402 onRawDeselect: onInternalDeselect
403 }
404 };
405
406 if ('filterTreeNode' in props) {
407 selectProps.filterOption = filterTreeNode;
408 }
409
410 return React.createElement(SelectContext.Provider, {
411 value: {
412 checkable: mergedCheckable,
413 loadData: loadData,
414 treeLoadedKeys: treeLoadedKeys,
415 onTreeLoad: onTreeLoad,
416 checkedKeys: rawValues,
417 halfCheckedKeys: rawHalfCheckedKeys,
418 treeDefaultExpandAll: treeDefaultExpandAll,
419 treeExpandedKeys: treeExpandedKeys,
420 treeDefaultExpandedKeys: treeDefaultExpandedKeys,
421 onTreeExpand: onTreeExpand,
422 treeIcon: treeIcon,
423 treeMotion: treeMotion,
424 showTreeIcon: showTreeIcon,
425 switcherIcon: switcherIcon,
426 treeLine: treeLine,
427 treeNodeFilterProp: treeNodeFilterProp
428 }
429 }, React.createElement(RefSelect, Object.assign({
430 ref: selectRef,
431 mode: mergedMultiple ? 'multiple' : null
432 }, props, selectProps, {
433 value: selectValues,
434 // We will handle this ourself since we need calculate conduction
435 labelInValue: true,
436 options: mergedTreeData,
437 onChange: null,
438 onSelect: null,
439 onDeselect: null,
440 onDropdownVisibleChange: onInternalDropdownVisibleChange
441 })));
442}); // Use class component since typescript not support generic
443// by `forwardRef` with function component yet.
444
445var TreeSelect =
446/** @class */
447function () {
448 var TreeSelect = /*#__PURE__*/function (_React$Component) {
449 _inherits(TreeSelect, _React$Component);
450
451 var _super = _createSuper(TreeSelect);
452
453 function TreeSelect() {
454 var _this;
455
456 _classCallCheck(this, TreeSelect);
457
458 _this = _super.apply(this, arguments);
459 _this.selectRef = React.createRef();
460
461 _this.focus = function () {
462 _this.selectRef.current.focus();
463 };
464
465 _this.blur = function () {
466 _this.selectRef.current.blur();
467 };
468
469 return _this;
470 }
471
472 _createClass(TreeSelect, [{
473 key: "render",
474 value: function render() {
475 return React.createElement(RefTreeSelect, Object.assign({
476 ref: this.selectRef
477 }, this.props));
478 }
479 }]);
480
481 return TreeSelect;
482 }(React.Component);
483
484 TreeSelect.TreeNode = TreeNode;
485 TreeSelect.SHOW_ALL = SHOW_ALL;
486 TreeSelect.SHOW_PARENT = SHOW_PARENT;
487 TreeSelect.SHOW_CHILD = SHOW_CHILD;
488 return TreeSelect;
489}();
490
491export default TreeSelect;
\No newline at end of file