UNPKG

15.8 kBJavaScriptView Raw
1import { createVNode as _createVNode } from "vue";
2
3function _extends() { _extends = Object.assign || 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); }
4
5function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
6
7function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
8
9function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
10
11function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); }
12
13function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
14
15function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
16
17var __rest = this && this.__rest || function (s, e) {
18 var t = {};
19
20 for (var p in s) {
21 if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
22 }
23
24 if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
25 if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];
26 }
27 return t;
28};
29
30import { getComponent, getSlot } from '../_util/props-util';
31import PropTypes from '../_util/vue-types';
32import Trigger from '../vc-trigger';
33import Menus from './Menus';
34import KeyCode from '../_util/KeyCode';
35import arrayTreeFilter from 'array-tree-filter';
36import shallowEqualArrays from 'shallow-equal/arrays';
37import { hasProp, getEvents } from '../_util/props-util';
38import BaseMixin from '../_util/BaseMixin';
39import { cloneElement } from '../_util/vnode';
40import { defineComponent } from 'vue';
41var BUILT_IN_PLACEMENTS = {
42 bottomLeft: {
43 points: ['tl', 'bl'],
44 offset: [0, 4],
45 overflow: {
46 adjustX: 1,
47 adjustY: 1
48 }
49 },
50 topLeft: {
51 points: ['bl', 'tl'],
52 offset: [0, -4],
53 overflow: {
54 adjustX: 1,
55 adjustY: 1
56 }
57 },
58 bottomRight: {
59 points: ['tr', 'br'],
60 offset: [0, 4],
61 overflow: {
62 adjustX: 1,
63 adjustY: 1
64 }
65 },
66 topRight: {
67 points: ['br', 'tr'],
68 offset: [0, -4],
69 overflow: {
70 adjustX: 1,
71 adjustY: 1
72 }
73 }
74};
75export default defineComponent({
76 name: 'Cascader',
77 mixins: [BaseMixin],
78 inheritAttrs: false,
79 // model: {
80 // prop: 'value',
81 // event: 'change',
82 // },
83 props: {
84 value: PropTypes.array,
85 defaultValue: PropTypes.array,
86 options: PropTypes.array,
87 // onChange: PropTypes.func,
88 // onPopupVisibleChange: PropTypes.func,
89 popupVisible: PropTypes.looseBool,
90 disabled: PropTypes.looseBool.def(false),
91 transitionName: PropTypes.string.def(''),
92 popupClassName: PropTypes.string.def(''),
93 popupStyle: PropTypes.object.def(function () {
94 return {};
95 }),
96 popupPlacement: PropTypes.string.def('bottomLeft'),
97 prefixCls: PropTypes.string.def('rc-cascader'),
98 dropdownMenuColumnStyle: PropTypes.object,
99 builtinPlacements: PropTypes.object.def(BUILT_IN_PLACEMENTS),
100 loadData: PropTypes.func,
101 changeOnSelect: PropTypes.looseBool,
102 // onKeyDown: PropTypes.func,
103 expandTrigger: PropTypes.string.def('click'),
104 fieldNames: PropTypes.object.def(function () {
105 return {
106 label: 'label',
107 value: 'value',
108 children: 'children'
109 };
110 }),
111 expandIcon: PropTypes.any,
112 loadingIcon: PropTypes.any,
113 getPopupContainer: PropTypes.func
114 },
115 data: function data() {
116 var initialValue = [];
117 var value = this.value,
118 defaultValue = this.defaultValue,
119 popupVisible = this.popupVisible;
120
121 if (hasProp(this, 'value')) {
122 initialValue = value || [];
123 } else if (hasProp(this, 'defaultValue')) {
124 initialValue = defaultValue || [];
125 }
126
127 this.children = undefined; // warning(!('filedNames' in props),
128 // '`filedNames` of Cascader is a typo usage and deprecated, please use `fieldNames` instead.');
129
130 this.defaultFieldNames = {
131 label: 'label',
132 value: 'value',
133 children: 'children'
134 };
135 return {
136 sPopupVisible: popupVisible,
137 sActiveValue: initialValue,
138 sValue: initialValue
139 };
140 },
141 watch: {
142 value: function value(val, oldValue) {
143 if (!shallowEqualArrays(val, oldValue)) {
144 var newValues = {
145 sValue: val || []
146 }; // allow activeValue diff from value
147 // https://github.com/ant-design/ant-design/issues/2767
148
149 if (!hasProp(this, 'loadData')) {
150 newValues.sActiveValue = val || [];
151 }
152
153 this.setState(newValues);
154 }
155 },
156 popupVisible: function popupVisible(val) {
157 this.setState({
158 sPopupVisible: val
159 });
160 }
161 },
162 methods: {
163 getPopupDOMNode: function getPopupDOMNode() {
164 return this.trigger.getPopupDomNode();
165 },
166 getFieldName: function getFieldName(name) {
167 var defaultFieldNames = this.defaultFieldNames,
168 fieldNames = this.fieldNames;
169 return fieldNames[name] || defaultFieldNames[name];
170 },
171 getFieldNames: function getFieldNames() {
172 return this.fieldNames;
173 },
174 getCurrentLevelOptions: function getCurrentLevelOptions() {
175 var _this = this;
176
177 var _this$options = this.options,
178 options = _this$options === void 0 ? [] : _this$options,
179 _this$sActiveValue = this.sActiveValue,
180 sActiveValue = _this$sActiveValue === void 0 ? [] : _this$sActiveValue;
181 var result = arrayTreeFilter(options, function (o, level) {
182 return o[_this.getFieldName('value')] === sActiveValue[level];
183 }, {
184 childrenKeyName: this.getFieldName('children')
185 });
186
187 if (result[result.length - 2]) {
188 return result[result.length - 2][this.getFieldName('children')];
189 }
190
191 return _toConsumableArray(options).filter(function (o) {
192 return !o.disabled;
193 });
194 },
195 getActiveOptions: function getActiveOptions(activeValue) {
196 var _this2 = this;
197
198 return arrayTreeFilter(this.options || [], function (o, level) {
199 return o[_this2.getFieldName('value')] === activeValue[level];
200 }, {
201 childrenKeyName: this.getFieldName('children')
202 });
203 },
204 setPopupVisible: function setPopupVisible(popupVisible) {
205 if (!hasProp(this, 'popupVisible')) {
206 this.setState({
207 sPopupVisible: popupVisible
208 });
209 } // sync activeValue with value when panel open
210
211
212 if (popupVisible && !this.sPopupVisible) {
213 this.setState({
214 sActiveValue: this.sValue
215 });
216 }
217
218 this.__emit('popupVisibleChange', popupVisible);
219 },
220 handleChange: function handleChange(options, setProps, e) {
221 var _this3 = this;
222
223 if (e.type !== 'keydown' || e.keyCode === KeyCode.ENTER) {
224 var value = options.map(function (o) {
225 return o[_this3.getFieldName('value')];
226 });
227
228 this.__emit('change', value, options);
229
230 this.setPopupVisible(setProps.visible);
231 }
232 },
233 handlePopupVisibleChange: function handlePopupVisibleChange(popupVisible) {
234 this.setPopupVisible(popupVisible);
235 },
236 handleMenuSelect: function handleMenuSelect(targetOption, menuIndex, e) {
237 // Keep focused state for keyboard support
238 var triggerNode = this.trigger.getRootDomNode();
239
240 if (triggerNode && triggerNode.focus) {
241 triggerNode.focus();
242 }
243
244 var changeOnSelect = this.changeOnSelect,
245 loadData = this.loadData,
246 expandTrigger = this.expandTrigger;
247
248 if (!targetOption || targetOption.disabled) {
249 return;
250 }
251
252 var sActiveValue = this.sActiveValue;
253 sActiveValue = sActiveValue.slice(0, menuIndex + 1);
254 sActiveValue[menuIndex] = targetOption[this.getFieldName('value')];
255 var activeOptions = this.getActiveOptions(sActiveValue);
256
257 if (targetOption.isLeaf === false && !targetOption[this.getFieldName('children')] && loadData) {
258 if (changeOnSelect) {
259 this.handleChange(activeOptions, {
260 visible: true
261 }, e);
262 }
263
264 this.setState({
265 sActiveValue: sActiveValue
266 });
267 loadData(activeOptions);
268 return;
269 }
270
271 var newState = {};
272
273 if (!targetOption[this.getFieldName('children')] || !targetOption[this.getFieldName('children')].length) {
274 this.handleChange(activeOptions, {
275 visible: false
276 }, e); // set value to activeValue when select leaf option
277
278 newState.sValue = sActiveValue; // add e.type judgement to prevent `onChange` being triggered by mouseEnter
279 } else if (changeOnSelect && (e.type === 'click' || e.type === 'keydown')) {
280 if (expandTrigger === 'hover') {
281 this.handleChange(activeOptions, {
282 visible: false
283 }, e);
284 } else {
285 this.handleChange(activeOptions, {
286 visible: true
287 }, e);
288 } // set value to activeValue on every select
289
290
291 newState.sValue = sActiveValue;
292 }
293
294 newState.sActiveValue = sActiveValue; // not change the value by keyboard
295
296 if (hasProp(this, 'value') || e.type === 'keydown' && e.keyCode !== KeyCode.ENTER) {
297 delete newState.sValue;
298 }
299
300 this.setState(newState);
301 },
302 handleItemDoubleClick: function handleItemDoubleClick() {
303 var changeOnSelect = this.$props.changeOnSelect;
304
305 if (changeOnSelect) {
306 this.setPopupVisible(false);
307 }
308 },
309 handleKeyDown: function handleKeyDown(e) {
310 var _this4 = this;
311
312 var children = this.children; // https://github.com/ant-design/ant-design/issues/6717
313 // Don't bind keyboard support when children specify the onKeyDown
314
315 if (children) {
316 var keydown = getEvents(children).onKeydown;
317
318 if (keydown) {
319 keydown(e);
320 return;
321 }
322 }
323
324 var activeValue = _toConsumableArray(this.sActiveValue);
325
326 var currentLevel = activeValue.length - 1 < 0 ? 0 : activeValue.length - 1;
327 var currentOptions = this.getCurrentLevelOptions();
328 var currentIndex = currentOptions.map(function (o) {
329 return o[_this4.getFieldName('value')];
330 }).indexOf(activeValue[currentLevel]);
331
332 if (e.keyCode !== KeyCode.DOWN && e.keyCode !== KeyCode.UP && e.keyCode !== KeyCode.LEFT && e.keyCode !== KeyCode.RIGHT && e.keyCode !== KeyCode.ENTER && e.keyCode !== KeyCode.SPACE && e.keyCode !== KeyCode.BACKSPACE && e.keyCode !== KeyCode.ESC && e.keyCode !== KeyCode.TAB) {
333 return;
334 } // Press any keys above to reopen menu
335
336
337 if (!this.sPopupVisible && e.keyCode !== KeyCode.BACKSPACE && e.keyCode !== KeyCode.LEFT && e.keyCode !== KeyCode.RIGHT && e.keyCode !== KeyCode.ESC && e.keyCode !== KeyCode.TAB) {
338 this.setPopupVisible(true);
339 return;
340 }
341
342 if (e.keyCode === KeyCode.DOWN || e.keyCode === KeyCode.UP) {
343 e.preventDefault();
344 var nextIndex = currentIndex;
345
346 if (nextIndex !== -1) {
347 if (e.keyCode === KeyCode.DOWN) {
348 nextIndex += 1;
349 nextIndex = nextIndex >= currentOptions.length ? 0 : nextIndex;
350 } else {
351 nextIndex -= 1;
352 nextIndex = nextIndex < 0 ? currentOptions.length - 1 : nextIndex;
353 }
354 } else {
355 nextIndex = 0;
356 }
357
358 activeValue[currentLevel] = currentOptions[nextIndex][this.getFieldName('value')];
359 } else if (e.keyCode === KeyCode.LEFT || e.keyCode === KeyCode.BACKSPACE) {
360 e.preventDefault();
361 activeValue.splice(activeValue.length - 1, 1);
362 } else if (e.keyCode === KeyCode.RIGHT) {
363 e.preventDefault();
364
365 if (currentOptions[currentIndex] && currentOptions[currentIndex][this.getFieldName('children')]) {
366 activeValue.push(currentOptions[currentIndex][this.getFieldName('children')][0][this.getFieldName('value')]);
367 }
368 } else if (e.keyCode === KeyCode.ESC || e.keyCode === KeyCode.TAB) {
369 this.setPopupVisible(false);
370 return;
371 }
372
373 if (!activeValue || activeValue.length === 0) {
374 this.setPopupVisible(false);
375 }
376
377 var activeOptions = this.getActiveOptions(activeValue);
378 var targetOption = activeOptions[activeOptions.length - 1];
379 this.handleMenuSelect(targetOption, activeOptions.length - 1, e);
380
381 this.__emit('keydown', e);
382 },
383 saveTrigger: function saveTrigger(node) {
384 this.trigger = node;
385 }
386 },
387 render: function render() {
388 var $props = this.$props,
389 sActiveValue = this.sActiveValue,
390 handleMenuSelect = this.handleMenuSelect,
391 sPopupVisible = this.sPopupVisible,
392 handlePopupVisibleChange = this.handlePopupVisibleChange,
393 handleKeyDown = this.handleKeyDown;
394
395 var prefixCls = $props.prefixCls,
396 transitionName = $props.transitionName,
397 popupClassName = $props.popupClassName,
398 _$props$options = $props.options,
399 options = _$props$options === void 0 ? [] : _$props$options,
400 disabled = $props.disabled,
401 builtinPlacements = $props.builtinPlacements,
402 popupPlacement = $props.popupPlacement,
403 restProps = __rest($props, ["prefixCls", "transitionName", "popupClassName", "options", "disabled", "builtinPlacements", "popupPlacement"]); // Did not show popup when there is no options
404
405
406 var menus = _createVNode("div", null, null);
407
408 var emptyMenuClassName = '';
409
410 if (options && options.length > 0) {
411 var loadingIcon = getComponent(this, 'loadingIcon');
412 var expandIcon = getComponent(this, 'expandIcon') || '>';
413
414 var menusProps = _extends(_extends(_extends({}, $props), this.$attrs), {
415 fieldNames: this.getFieldNames(),
416 defaultFieldNames: this.defaultFieldNames,
417 activeValue: sActiveValue,
418 visible: sPopupVisible,
419 loadingIcon: loadingIcon,
420 expandIcon: expandIcon,
421 onSelect: handleMenuSelect,
422 onItemDoubleClick: this.handleItemDoubleClick
423 });
424
425 menus = _createVNode(Menus, menusProps, null);
426 } else {
427 emptyMenuClassName = " ".concat(prefixCls, "-menus-empty");
428 }
429
430 var triggerProps = _extends(_extends(_extends({}, restProps), this.$attrs), {
431 disabled: disabled,
432 popupPlacement: popupPlacement,
433 builtinPlacements: builtinPlacements,
434 popupTransitionName: transitionName,
435 action: disabled ? [] : ['click'],
436 popupVisible: disabled ? false : sPopupVisible,
437 prefixCls: "".concat(prefixCls, "-menus"),
438 popupClassName: popupClassName + emptyMenuClassName,
439 popup: menus,
440 onPopupVisibleChange: handlePopupVisibleChange,
441 ref: this.saveTrigger
442 });
443
444 var children = getSlot(this);
445 this.children = children;
446 return _createVNode(Trigger, triggerProps, {
447 default: function _default() {
448 return [children && cloneElement(children[0], {
449 onKeydown: handleKeyDown,
450 tabindex: disabled ? undefined : 0
451 })];
452 }
453 });
454 }
455});
\No newline at end of file