Cascader.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. "use strict";
  2. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  3. Object.defineProperty(exports, "__esModule", {
  4. value: true
  5. });
  6. Object.defineProperty(exports, "SHOW_CHILD", {
  7. enumerable: true,
  8. get: function get() {
  9. return _commonUtil.SHOW_CHILD;
  10. }
  11. });
  12. Object.defineProperty(exports, "SHOW_PARENT", {
  13. enumerable: true,
  14. get: function get() {
  15. return _commonUtil.SHOW_PARENT;
  16. }
  17. });
  18. exports.default = void 0;
  19. exports.internalCascaderProps = internalCascaderProps;
  20. exports.multipleCascaderProps = multipleCascaderProps;
  21. exports.singleCascaderProps = singleCascaderProps;
  22. var _vue = require("vue");
  23. var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
  24. var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
  25. var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
  26. var _BaseSelect = require("../vc-select/BaseSelect");
  27. var _omit = _interopRequireDefault(require("../_util/omit"));
  28. var _vueTypes = _interopRequireDefault(require("../_util/vue-types"));
  29. var _propsUtil = require("../_util/props-util");
  30. var _useId = _interopRequireDefault(require("../vc-select/hooks/useId"));
  31. var _useMergedState5 = _interopRequireDefault(require("../_util/hooks/useMergedState"));
  32. var _commonUtil = require("./utils/commonUtil");
  33. var _useEntities = _interopRequireDefault(require("./hooks/useEntities"));
  34. var _useSearchConfig2 = _interopRequireDefault(require("./hooks/useSearchConfig"));
  35. var _useSearchOptions = _interopRequireDefault(require("./hooks/useSearchOptions"));
  36. var _useMissingValues = _interopRequireDefault(require("./hooks/useMissingValues"));
  37. var _treeUtil = require("./utils/treeUtil");
  38. var _conductUtil = require("../vc-tree/utils/conductUtil");
  39. var _useDisplayValues = _interopRequireDefault(require("./hooks/useDisplayValues"));
  40. var _context = require("./context");
  41. var _OptionList = _interopRequireDefault(require("./OptionList"));
  42. var _vcSelect = require("../vc-select");
  43. var _devWarning = _interopRequireDefault(require("../vc-util/devWarning"));
  44. var _useMaxLevel2 = _interopRequireDefault(require("../vc-tree/useMaxLevel"));
  45. function baseCascaderProps() {
  46. return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, (0, _omit.default)((0, _BaseSelect.baseSelectPropsWithoutPrivate)(), ['tokenSeparators', 'mode', 'showSearch'])), {}, {
  47. // MISC
  48. id: String,
  49. prefixCls: String,
  50. fieldNames: Object,
  51. children: Array,
  52. // Value
  53. value: {
  54. type: [String, Number, Array]
  55. },
  56. defaultValue: {
  57. type: [String, Number, Array]
  58. },
  59. changeOnSelect: {
  60. type: Boolean,
  61. default: undefined
  62. },
  63. displayRender: Function,
  64. checkable: {
  65. type: Boolean,
  66. default: undefined
  67. },
  68. showCheckedStrategy: {
  69. type: String,
  70. default: _commonUtil.SHOW_PARENT
  71. },
  72. // Search
  73. showSearch: {
  74. type: [Boolean, Object],
  75. default: undefined
  76. },
  77. searchValue: String,
  78. onSearch: Function,
  79. // Trigger
  80. expandTrigger: String,
  81. // Options
  82. options: Array,
  83. /** @private Internal usage. Do not use in your production. */
  84. dropdownPrefixCls: String,
  85. loadData: Function,
  86. // Open
  87. /** @deprecated Use `open` instead */
  88. popupVisible: {
  89. type: Boolean,
  90. default: undefined
  91. },
  92. /** @deprecated Use `dropdownClassName` instead */
  93. popupClassName: String,
  94. dropdownClassName: String,
  95. dropdownMenuColumnStyle: {
  96. type: Object,
  97. default: undefined
  98. },
  99. /** @deprecated Use `dropdownStyle` instead */
  100. popupStyle: {
  101. type: Object,
  102. default: undefined
  103. },
  104. dropdownStyle: {
  105. type: Object,
  106. default: undefined
  107. },
  108. /** @deprecated Use `placement` instead */
  109. popupPlacement: String,
  110. placement: String,
  111. /** @deprecated Use `onDropdownVisibleChange` instead */
  112. onPopupVisibleChange: Function,
  113. onDropdownVisibleChange: Function,
  114. // Icon
  115. expandIcon: _vueTypes.default.any,
  116. loadingIcon: _vueTypes.default.any
  117. });
  118. }
  119. function singleCascaderProps() {
  120. return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, baseCascaderProps()), {}, {
  121. checkable: Boolean,
  122. onChange: Function
  123. });
  124. }
  125. function multipleCascaderProps() {
  126. return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, baseCascaderProps()), {}, {
  127. checkable: Boolean,
  128. onChange: Function
  129. });
  130. }
  131. function internalCascaderProps() {
  132. return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, baseCascaderProps()), {}, {
  133. onChange: Function,
  134. customSlots: Object
  135. });
  136. }
  137. function isMultipleValue(value) {
  138. return Array.isArray(value) && Array.isArray(value[0]);
  139. }
  140. function toRawValues(value) {
  141. if (!value) {
  142. return [];
  143. }
  144. if (isMultipleValue(value)) {
  145. return value;
  146. }
  147. return (value.length === 0 ? [] : [value]).map(function (val) {
  148. return Array.isArray(val) ? val : [val];
  149. });
  150. }
  151. var _default = (0, _vue.defineComponent)({
  152. compatConfig: {
  153. MODE: 3
  154. },
  155. name: 'Cascader',
  156. inheritAttrs: false,
  157. props: (0, _propsUtil.initDefaultProps)(internalCascaderProps(), {}),
  158. setup: function setup(props, _ref) {
  159. var attrs = _ref.attrs,
  160. expose = _ref.expose,
  161. slots = _ref.slots;
  162. var mergedId = (0, _useId.default)((0, _vue.toRef)(props, 'id'));
  163. var multiple = (0, _vue.computed)(function () {
  164. return !!props.checkable;
  165. });
  166. // =========================== Values ===========================
  167. var _useMergedState = (0, _useMergedState5.default)(props.defaultValue, {
  168. value: (0, _vue.computed)(function () {
  169. return props.value;
  170. }),
  171. postState: toRawValues
  172. }),
  173. _useMergedState2 = (0, _slicedToArray2.default)(_useMergedState, 2),
  174. rawValues = _useMergedState2[0],
  175. setRawValues = _useMergedState2[1];
  176. // ========================= FieldNames =========================
  177. var mergedFieldNames = (0, _vue.computed)(function () {
  178. return (0, _commonUtil.fillFieldNames)(props.fieldNames);
  179. });
  180. // =========================== Option ===========================
  181. var mergedOptions = (0, _vue.computed)(function () {
  182. return props.options || [];
  183. });
  184. // Only used in multiple mode, this fn will not call in single mode
  185. var pathKeyEntities = (0, _useEntities.default)(mergedOptions, mergedFieldNames);
  186. /** Convert path key back to value format */
  187. var getValueByKeyPath = function getValueByKeyPath(pathKeys) {
  188. var keyPathEntities = pathKeyEntities.value;
  189. return pathKeys.map(function (pathKey) {
  190. var nodes = keyPathEntities[pathKey].nodes;
  191. return nodes.map(function (node) {
  192. return node[mergedFieldNames.value.value];
  193. });
  194. });
  195. };
  196. // =========================== Search ===========================
  197. var _useMergedState3 = (0, _useMergedState5.default)('', {
  198. value: (0, _vue.computed)(function () {
  199. return props.searchValue;
  200. }),
  201. postState: function postState(search) {
  202. return search || '';
  203. }
  204. }),
  205. _useMergedState4 = (0, _slicedToArray2.default)(_useMergedState3, 2),
  206. mergedSearchValue = _useMergedState4[0],
  207. setSearchValue = _useMergedState4[1];
  208. var onInternalSearch = function onInternalSearch(searchText, info) {
  209. setSearchValue(searchText);
  210. if (info.source !== 'blur' && props.onSearch) {
  211. props.onSearch(searchText);
  212. }
  213. };
  214. var _useSearchConfig = (0, _useSearchConfig2.default)((0, _vue.toRef)(props, 'showSearch')),
  215. mergedShowSearch = _useSearchConfig.showSearch,
  216. mergedSearchConfig = _useSearchConfig.searchConfig;
  217. var searchOptions = (0, _useSearchOptions.default)(mergedSearchValue, mergedOptions, mergedFieldNames, (0, _vue.computed)(function () {
  218. return props.dropdownPrefixCls || props.prefixCls;
  219. }), mergedSearchConfig, (0, _vue.toRef)(props, 'changeOnSelect'));
  220. // =========================== Values ===========================
  221. var missingValuesInfo = (0, _useMissingValues.default)(mergedOptions, mergedFieldNames, rawValues);
  222. // Fill `rawValues` with checked conduction values
  223. var _ref2 = [(0, _vue.ref)([]), (0, _vue.ref)([]), (0, _vue.ref)([])],
  224. checkedValues = _ref2[0],
  225. halfCheckedValues = _ref2[1],
  226. missingCheckedValues = _ref2[2];
  227. var _useMaxLevel = (0, _useMaxLevel2.default)(pathKeyEntities),
  228. maxLevel = _useMaxLevel.maxLevel,
  229. levelEntities = _useMaxLevel.levelEntities;
  230. (0, _vue.watchEffect)(function () {
  231. var _missingValuesInfo$va = (0, _slicedToArray2.default)(missingValuesInfo.value, 2),
  232. existValues = _missingValuesInfo$va[0],
  233. missingValues = _missingValuesInfo$va[1];
  234. if (!multiple.value || !rawValues.value.length) {
  235. var _ref3 = [existValues, [], missingValues];
  236. checkedValues.value = _ref3[0];
  237. halfCheckedValues.value = _ref3[1];
  238. missingCheckedValues.value = _ref3[2];
  239. return;
  240. }
  241. var keyPathValues = (0, _commonUtil.toPathKeys)(existValues);
  242. var keyPathEntities = pathKeyEntities.value;
  243. var _conductCheck = (0, _conductUtil.conductCheck)(keyPathValues, true, keyPathEntities, maxLevel.value, levelEntities.value),
  244. checkedKeys = _conductCheck.checkedKeys,
  245. halfCheckedKeys = _conductCheck.halfCheckedKeys;
  246. // Convert key back to value cells
  247. var _ref4 = [getValueByKeyPath(checkedKeys), getValueByKeyPath(halfCheckedKeys), missingValues];
  248. checkedValues.value = _ref4[0];
  249. halfCheckedValues.value = _ref4[1];
  250. missingCheckedValues.value = _ref4[2];
  251. });
  252. var deDuplicatedValues = (0, _vue.computed)(function () {
  253. var checkedKeys = (0, _commonUtil.toPathKeys)(checkedValues.value);
  254. var deduplicateKeys = (0, _treeUtil.formatStrategyValues)(checkedKeys, pathKeyEntities.value, props.showCheckedStrategy);
  255. return [].concat((0, _toConsumableArray2.default)(missingCheckedValues.value), (0, _toConsumableArray2.default)(getValueByKeyPath(deduplicateKeys)));
  256. });
  257. var displayValues = (0, _useDisplayValues.default)(deDuplicatedValues, mergedOptions, mergedFieldNames, multiple, (0, _vue.toRef)(props, 'displayRender'));
  258. // =========================== Change ===========================
  259. var triggerChange = function triggerChange(nextValues) {
  260. setRawValues(nextValues);
  261. // Save perf if no need trigger event
  262. if (props.onChange) {
  263. var nextRawValues = toRawValues(nextValues);
  264. var valueOptions = nextRawValues.map(function (valueCells) {
  265. return (0, _treeUtil.toPathOptions)(valueCells, mergedOptions.value, mergedFieldNames.value).map(function (valueOpt) {
  266. return valueOpt.option;
  267. });
  268. });
  269. var triggerValues = multiple.value ? nextRawValues : nextRawValues[0];
  270. var triggerOptions = multiple.value ? valueOptions : valueOptions[0];
  271. props.onChange(triggerValues, triggerOptions);
  272. }
  273. };
  274. // =========================== Select ===========================
  275. var onInternalSelect = function onInternalSelect(valuePath) {
  276. setSearchValue('');
  277. if (!multiple.value) {
  278. triggerChange(valuePath);
  279. } else {
  280. // Prepare conduct required info
  281. var pathKey = (0, _commonUtil.toPathKey)(valuePath);
  282. var checkedPathKeys = (0, _commonUtil.toPathKeys)(checkedValues.value);
  283. var halfCheckedPathKeys = (0, _commonUtil.toPathKeys)(halfCheckedValues.value);
  284. var existInChecked = checkedPathKeys.includes(pathKey);
  285. var existInMissing = missingCheckedValues.value.some(function (valueCells) {
  286. return (0, _commonUtil.toPathKey)(valueCells) === pathKey;
  287. });
  288. // Do update
  289. var nextCheckedValues = checkedValues.value;
  290. var nextMissingValues = missingCheckedValues.value;
  291. if (existInMissing && !existInChecked) {
  292. // Missing value only do filter
  293. nextMissingValues = missingCheckedValues.value.filter(function (valueCells) {
  294. return (0, _commonUtil.toPathKey)(valueCells) !== pathKey;
  295. });
  296. } else {
  297. // Update checked key first
  298. var nextRawCheckedKeys = existInChecked ? checkedPathKeys.filter(function (key) {
  299. return key !== pathKey;
  300. }) : [].concat((0, _toConsumableArray2.default)(checkedPathKeys), [pathKey]);
  301. // Conduction by selected or not
  302. var checkedKeys;
  303. if (existInChecked) {
  304. var _conductCheck2 = (0, _conductUtil.conductCheck)(nextRawCheckedKeys, {
  305. checked: false,
  306. halfCheckedKeys: halfCheckedPathKeys
  307. }, pathKeyEntities.value, maxLevel.value, levelEntities.value);
  308. checkedKeys = _conductCheck2.checkedKeys;
  309. } else {
  310. var _conductCheck3 = (0, _conductUtil.conductCheck)(nextRawCheckedKeys, true, pathKeyEntities.value, maxLevel.value, levelEntities.value);
  311. checkedKeys = _conductCheck3.checkedKeys;
  312. }
  313. // Roll up to parent level keys
  314. var deDuplicatedKeys = (0, _treeUtil.formatStrategyValues)(checkedKeys, pathKeyEntities.value, props.showCheckedStrategy);
  315. nextCheckedValues = getValueByKeyPath(deDuplicatedKeys);
  316. }
  317. triggerChange([].concat((0, _toConsumableArray2.default)(nextMissingValues), (0, _toConsumableArray2.default)(nextCheckedValues)));
  318. }
  319. };
  320. // Display Value change logic
  321. var onDisplayValuesChange = function onDisplayValuesChange(_, info) {
  322. if (info.type === 'clear') {
  323. triggerChange([]);
  324. return;
  325. }
  326. // Cascader do not support `add` type. Only support `remove`
  327. var valueCells = info.values[0].valueCells;
  328. onInternalSelect(valueCells);
  329. };
  330. // ============================ Open ============================
  331. if (process.env.NODE_ENV !== 'production') {
  332. (0, _vue.watchEffect)(function () {
  333. (0, _devWarning.default)(!props.onPopupVisibleChange, 'Cascader', '`popupVisibleChange` is deprecated. Please use `dropdownVisibleChange` instead.');
  334. (0, _devWarning.default)(props.popupVisible === undefined, 'Cascader', '`popupVisible` is deprecated. Please use `open` instead.');
  335. (0, _devWarning.default)(props.popupClassName === undefined, 'Cascader', '`popupClassName` is deprecated. Please use `dropdownClassName` instead.');
  336. (0, _devWarning.default)(props.popupPlacement === undefined, 'Cascader', '`popupPlacement` is deprecated. Please use `placement` instead.');
  337. (0, _devWarning.default)(props.popupStyle === undefined, 'Cascader', '`popupStyle` is deprecated. Please use `dropdownStyle` instead.');
  338. });
  339. }
  340. var mergedOpen = (0, _vue.computed)(function () {
  341. return props.open !== undefined ? props.open : props.popupVisible;
  342. });
  343. var mergedDropdownClassName = (0, _vue.computed)(function () {
  344. return props.dropdownClassName || props.popupClassName;
  345. });
  346. var mergedDropdownStyle = (0, _vue.computed)(function () {
  347. return props.dropdownStyle || props.popupStyle || {};
  348. });
  349. var mergedPlacement = (0, _vue.computed)(function () {
  350. return props.placement || props.popupPlacement;
  351. });
  352. var onInternalDropdownVisibleChange = function onInternalDropdownVisibleChange(nextVisible) {
  353. var _props$onDropdownVisi, _props$onPopupVisible;
  354. (_props$onDropdownVisi = props.onDropdownVisibleChange) === null || _props$onDropdownVisi === void 0 ? void 0 : _props$onDropdownVisi.call(props, nextVisible);
  355. (_props$onPopupVisible = props.onPopupVisibleChange) === null || _props$onPopupVisible === void 0 ? void 0 : _props$onPopupVisible.call(props, nextVisible);
  356. };
  357. var _toRefs = (0, _vue.toRefs)(props),
  358. changeOnSelect = _toRefs.changeOnSelect,
  359. checkable = _toRefs.checkable,
  360. dropdownPrefixCls = _toRefs.dropdownPrefixCls,
  361. loadData = _toRefs.loadData,
  362. expandTrigger = _toRefs.expandTrigger,
  363. expandIcon = _toRefs.expandIcon,
  364. loadingIcon = _toRefs.loadingIcon,
  365. dropdownMenuColumnStyle = _toRefs.dropdownMenuColumnStyle,
  366. customSlots = _toRefs.customSlots;
  367. (0, _context.useProvideCascader)({
  368. options: mergedOptions,
  369. fieldNames: mergedFieldNames,
  370. values: checkedValues,
  371. halfValues: halfCheckedValues,
  372. changeOnSelect: changeOnSelect,
  373. onSelect: onInternalSelect,
  374. checkable: checkable,
  375. searchOptions: searchOptions,
  376. dropdownPrefixCls: dropdownPrefixCls,
  377. loadData: loadData,
  378. expandTrigger: expandTrigger,
  379. expandIcon: expandIcon,
  380. loadingIcon: loadingIcon,
  381. dropdownMenuColumnStyle: dropdownMenuColumnStyle,
  382. customSlots: customSlots
  383. });
  384. var selectRef = (0, _vue.ref)();
  385. expose({
  386. focus: function focus() {
  387. var _selectRef$value;
  388. (_selectRef$value = selectRef.value) === null || _selectRef$value === void 0 ? void 0 : _selectRef$value.focus();
  389. },
  390. blur: function blur() {
  391. var _selectRef$value2;
  392. (_selectRef$value2 = selectRef.value) === null || _selectRef$value2 === void 0 ? void 0 : _selectRef$value2.blur();
  393. },
  394. scrollTo: function scrollTo(arg) {
  395. var _selectRef$value3;
  396. (_selectRef$value3 = selectRef.value) === null || _selectRef$value3 === void 0 ? void 0 : _selectRef$value3.scrollTo(arg);
  397. }
  398. });
  399. var pickProps = (0, _vue.computed)(function () {
  400. return (0, _omit.default)(props, ['id', 'prefixCls', 'fieldNames',
  401. // Value
  402. 'defaultValue', 'value', 'changeOnSelect', 'onChange', 'displayRender', 'checkable',
  403. // Search
  404. 'searchValue', 'onSearch', 'showSearch',
  405. // Trigger
  406. 'expandTrigger',
  407. // Options
  408. 'options', 'dropdownPrefixCls', 'loadData',
  409. // Open
  410. 'popupVisible', 'open', 'popupClassName', 'dropdownClassName', 'dropdownMenuColumnStyle', 'popupPlacement', 'placement', 'onDropdownVisibleChange', 'onPopupVisibleChange',
  411. // Icon
  412. 'expandIcon', 'loadingIcon', 'customSlots', 'showCheckedStrategy',
  413. // Children
  414. 'children']);
  415. });
  416. return function () {
  417. var emptyOptions = !(mergedSearchValue.value ? searchOptions.value : mergedOptions.value).length;
  418. var _props$dropdownMatchS = props.dropdownMatchSelectWidth,
  419. dropdownMatchSelectWidth = _props$dropdownMatchS === void 0 ? false : _props$dropdownMatchS;
  420. var dropdownStyle =
  421. // Search to match width
  422. mergedSearchValue.value && mergedSearchConfig.value.matchInputWidth ||
  423. // Empty keep the width
  424. emptyOptions ? {} : {
  425. minWidth: 'auto'
  426. };
  427. return (0, _vue.createVNode)(_vcSelect.BaseSelect, (0, _objectSpread2.default)((0, _objectSpread2.default)((0, _objectSpread2.default)({}, pickProps.value), attrs), {}, {
  428. "ref": selectRef,
  429. "id": mergedId,
  430. "prefixCls": props.prefixCls,
  431. "dropdownMatchSelectWidth": dropdownMatchSelectWidth,
  432. "dropdownStyle": (0, _objectSpread2.default)((0, _objectSpread2.default)({}, mergedDropdownStyle.value), dropdownStyle),
  433. "displayValues": displayValues.value,
  434. "onDisplayValuesChange": onDisplayValuesChange,
  435. "mode": multiple.value ? 'multiple' : undefined,
  436. "searchValue": mergedSearchValue.value,
  437. "onSearch": onInternalSearch,
  438. "showSearch": mergedShowSearch.value,
  439. "OptionList": _OptionList.default,
  440. "emptyOptions": emptyOptions,
  441. "open": mergedOpen.value,
  442. "dropdownClassName": mergedDropdownClassName.value,
  443. "placement": mergedPlacement.value,
  444. "onDropdownVisibleChange": onInternalDropdownVisibleChange,
  445. "getRawInputElement": function getRawInputElement() {
  446. var _slots$default;
  447. return (_slots$default = slots.default) === null || _slots$default === void 0 ? void 0 : _slots$default.call(slots);
  448. }
  449. }), slots);
  450. };
  451. }
  452. });
  453. exports.default = _default;