UNPKG

ant-design-vue

Version:

An enterprise-class UI design language and Vue-based implementation

455 lines (390 loc) 15.8 kB
import { createVNode as _createVNode } from "vue"; function _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); } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } function _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."); } function _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); } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } function _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; } var __rest = this && this.__rest || function (s, e) { var t = {}; for (var p in s) { if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; } if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; import { getComponent, getSlot } from '../_util/props-util'; import PropTypes from '../_util/vue-types'; import Trigger from '../vc-trigger'; import Menus from './Menus'; import KeyCode from '../_util/KeyCode'; import arrayTreeFilter from 'array-tree-filter'; import shallowEqualArrays from 'shallow-equal/arrays'; import { hasProp, getEvents } from '../_util/props-util'; import BaseMixin from '../_util/BaseMixin'; import { cloneElement } from '../_util/vnode'; import { defineComponent } from 'vue'; var BUILT_IN_PLACEMENTS = { bottomLeft: { points: ['tl', 'bl'], offset: [0, 4], overflow: { adjustX: 1, adjustY: 1 } }, topLeft: { points: ['bl', 'tl'], offset: [0, -4], overflow: { adjustX: 1, adjustY: 1 } }, bottomRight: { points: ['tr', 'br'], offset: [0, 4], overflow: { adjustX: 1, adjustY: 1 } }, topRight: { points: ['br', 'tr'], offset: [0, -4], overflow: { adjustX: 1, adjustY: 1 } } }; export default defineComponent({ name: 'Cascader', mixins: [BaseMixin], inheritAttrs: false, // model: { // prop: 'value', // event: 'change', // }, props: { value: PropTypes.array, defaultValue: PropTypes.array, options: PropTypes.array, // onChange: PropTypes.func, // onPopupVisibleChange: PropTypes.func, popupVisible: PropTypes.looseBool, disabled: PropTypes.looseBool.def(false), transitionName: PropTypes.string.def(''), popupClassName: PropTypes.string.def(''), popupStyle: PropTypes.object.def(function () { return {}; }), popupPlacement: PropTypes.string.def('bottomLeft'), prefixCls: PropTypes.string.def('rc-cascader'), dropdownMenuColumnStyle: PropTypes.object, builtinPlacements: PropTypes.object.def(BUILT_IN_PLACEMENTS), loadData: PropTypes.func, changeOnSelect: PropTypes.looseBool, // onKeyDown: PropTypes.func, expandTrigger: PropTypes.string.def('click'), fieldNames: PropTypes.object.def(function () { return { label: 'label', value: 'value', children: 'children' }; }), expandIcon: PropTypes.any, loadingIcon: PropTypes.any, getPopupContainer: PropTypes.func }, data: function data() { var initialValue = []; var value = this.value, defaultValue = this.defaultValue, popupVisible = this.popupVisible; if (hasProp(this, 'value')) { initialValue = value || []; } else if (hasProp(this, 'defaultValue')) { initialValue = defaultValue || []; } this.children = undefined; // warning(!('filedNames' in props), // '`filedNames` of Cascader is a typo usage and deprecated, please use `fieldNames` instead.'); this.defaultFieldNames = { label: 'label', value: 'value', children: 'children' }; return { sPopupVisible: popupVisible, sActiveValue: initialValue, sValue: initialValue }; }, watch: { value: function value(val, oldValue) { if (!shallowEqualArrays(val, oldValue)) { var newValues = { sValue: val || [] }; // allow activeValue diff from value // https://github.com/ant-design/ant-design/issues/2767 if (!hasProp(this, 'loadData')) { newValues.sActiveValue = val || []; } this.setState(newValues); } }, popupVisible: function popupVisible(val) { this.setState({ sPopupVisible: val }); } }, methods: { getPopupDOMNode: function getPopupDOMNode() { return this.trigger.getPopupDomNode(); }, getFieldName: function getFieldName(name) { var defaultFieldNames = this.defaultFieldNames, fieldNames = this.fieldNames; return fieldNames[name] || defaultFieldNames[name]; }, getFieldNames: function getFieldNames() { return this.fieldNames; }, getCurrentLevelOptions: function getCurrentLevelOptions() { var _this = this; var _this$options = this.options, options = _this$options === void 0 ? [] : _this$options, _this$sActiveValue = this.sActiveValue, sActiveValue = _this$sActiveValue === void 0 ? [] : _this$sActiveValue; var result = arrayTreeFilter(options, function (o, level) { return o[_this.getFieldName('value')] === sActiveValue[level]; }, { childrenKeyName: this.getFieldName('children') }); if (result[result.length - 2]) { return result[result.length - 2][this.getFieldName('children')]; } return _toConsumableArray(options).filter(function (o) { return !o.disabled; }); }, getActiveOptions: function getActiveOptions(activeValue) { var _this2 = this; return arrayTreeFilter(this.options || [], function (o, level) { return o[_this2.getFieldName('value')] === activeValue[level]; }, { childrenKeyName: this.getFieldName('children') }); }, setPopupVisible: function setPopupVisible(popupVisible) { if (!hasProp(this, 'popupVisible')) { this.setState({ sPopupVisible: popupVisible }); } // sync activeValue with value when panel open if (popupVisible && !this.sPopupVisible) { this.setState({ sActiveValue: this.sValue }); } this.__emit('popupVisibleChange', popupVisible); }, handleChange: function handleChange(options, setProps, e) { var _this3 = this; if (e.type !== 'keydown' || e.keyCode === KeyCode.ENTER) { var value = options.map(function (o) { return o[_this3.getFieldName('value')]; }); this.__emit('change', value, options); this.setPopupVisible(setProps.visible); } }, handlePopupVisibleChange: function handlePopupVisibleChange(popupVisible) { this.setPopupVisible(popupVisible); }, handleMenuSelect: function handleMenuSelect(targetOption, menuIndex, e) { // Keep focused state for keyboard support var triggerNode = this.trigger.getRootDomNode(); if (triggerNode && triggerNode.focus) { triggerNode.focus(); } var changeOnSelect = this.changeOnSelect, loadData = this.loadData, expandTrigger = this.expandTrigger; if (!targetOption || targetOption.disabled) { return; } var sActiveValue = this.sActiveValue; sActiveValue = sActiveValue.slice(0, menuIndex + 1); sActiveValue[menuIndex] = targetOption[this.getFieldName('value')]; var activeOptions = this.getActiveOptions(sActiveValue); if (targetOption.isLeaf === false && !targetOption[this.getFieldName('children')] && loadData) { if (changeOnSelect) { this.handleChange(activeOptions, { visible: true }, e); } this.setState({ sActiveValue: sActiveValue }); loadData(activeOptions); return; } var newState = {}; if (!targetOption[this.getFieldName('children')] || !targetOption[this.getFieldName('children')].length) { this.handleChange(activeOptions, { visible: false }, e); // set value to activeValue when select leaf option newState.sValue = sActiveValue; // add e.type judgement to prevent `onChange` being triggered by mouseEnter } else if (changeOnSelect && (e.type === 'click' || e.type === 'keydown')) { if (expandTrigger === 'hover') { this.handleChange(activeOptions, { visible: false }, e); } else { this.handleChange(activeOptions, { visible: true }, e); } // set value to activeValue on every select newState.sValue = sActiveValue; } newState.sActiveValue = sActiveValue; // not change the value by keyboard if (hasProp(this, 'value') || e.type === 'keydown' && e.keyCode !== KeyCode.ENTER) { delete newState.sValue; } this.setState(newState); }, handleItemDoubleClick: function handleItemDoubleClick() { var changeOnSelect = this.$props.changeOnSelect; if (changeOnSelect) { this.setPopupVisible(false); } }, handleKeyDown: function handleKeyDown(e) { var _this4 = this; var children = this.children; // https://github.com/ant-design/ant-design/issues/6717 // Don't bind keyboard support when children specify the onKeyDown if (children) { var keydown = getEvents(children).onKeydown; if (keydown) { keydown(e); return; } } var activeValue = _toConsumableArray(this.sActiveValue); var currentLevel = activeValue.length - 1 < 0 ? 0 : activeValue.length - 1; var currentOptions = this.getCurrentLevelOptions(); var currentIndex = currentOptions.map(function (o) { return o[_this4.getFieldName('value')]; }).indexOf(activeValue[currentLevel]); 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) { return; } // Press any keys above to reopen menu if (!this.sPopupVisible && e.keyCode !== KeyCode.BACKSPACE && e.keyCode !== KeyCode.LEFT && e.keyCode !== KeyCode.RIGHT && e.keyCode !== KeyCode.ESC && e.keyCode !== KeyCode.TAB) { this.setPopupVisible(true); return; } if (e.keyCode === KeyCode.DOWN || e.keyCode === KeyCode.UP) { e.preventDefault(); var nextIndex = currentIndex; if (nextIndex !== -1) { if (e.keyCode === KeyCode.DOWN) { nextIndex += 1; nextIndex = nextIndex >= currentOptions.length ? 0 : nextIndex; } else { nextIndex -= 1; nextIndex = nextIndex < 0 ? currentOptions.length - 1 : nextIndex; } } else { nextIndex = 0; } activeValue[currentLevel] = currentOptions[nextIndex][this.getFieldName('value')]; } else if (e.keyCode === KeyCode.LEFT || e.keyCode === KeyCode.BACKSPACE) { e.preventDefault(); activeValue.splice(activeValue.length - 1, 1); } else if (e.keyCode === KeyCode.RIGHT) { e.preventDefault(); if (currentOptions[currentIndex] && currentOptions[currentIndex][this.getFieldName('children')]) { activeValue.push(currentOptions[currentIndex][this.getFieldName('children')][0][this.getFieldName('value')]); } } else if (e.keyCode === KeyCode.ESC || e.keyCode === KeyCode.TAB) { this.setPopupVisible(false); return; } if (!activeValue || activeValue.length === 0) { this.setPopupVisible(false); } var activeOptions = this.getActiveOptions(activeValue); var targetOption = activeOptions[activeOptions.length - 1]; this.handleMenuSelect(targetOption, activeOptions.length - 1, e); this.__emit('keydown', e); }, saveTrigger: function saveTrigger(node) { this.trigger = node; } }, render: function render() { var $props = this.$props, sActiveValue = this.sActiveValue, handleMenuSelect = this.handleMenuSelect, sPopupVisible = this.sPopupVisible, handlePopupVisibleChange = this.handlePopupVisibleChange, handleKeyDown = this.handleKeyDown; var prefixCls = $props.prefixCls, transitionName = $props.transitionName, popupClassName = $props.popupClassName, _$props$options = $props.options, options = _$props$options === void 0 ? [] : _$props$options, disabled = $props.disabled, builtinPlacements = $props.builtinPlacements, popupPlacement = $props.popupPlacement, restProps = __rest($props, ["prefixCls", "transitionName", "popupClassName", "options", "disabled", "builtinPlacements", "popupPlacement"]); // Did not show popup when there is no options var menus = _createVNode("div", null, null); var emptyMenuClassName = ''; if (options && options.length > 0) { var loadingIcon = getComponent(this, 'loadingIcon'); var expandIcon = getComponent(this, 'expandIcon') || '>'; var menusProps = _extends(_extends(_extends({}, $props), this.$attrs), { fieldNames: this.getFieldNames(), defaultFieldNames: this.defaultFieldNames, activeValue: sActiveValue, visible: sPopupVisible, loadingIcon: loadingIcon, expandIcon: expandIcon, onSelect: handleMenuSelect, onItemDoubleClick: this.handleItemDoubleClick }); menus = _createVNode(Menus, menusProps, null); } else { emptyMenuClassName = " ".concat(prefixCls, "-menus-empty"); } var triggerProps = _extends(_extends(_extends({}, restProps), this.$attrs), { disabled: disabled, popupPlacement: popupPlacement, builtinPlacements: builtinPlacements, popupTransitionName: transitionName, action: disabled ? [] : ['click'], popupVisible: disabled ? false : sPopupVisible, prefixCls: "".concat(prefixCls, "-menus"), popupClassName: popupClassName + emptyMenuClassName, popup: menus, onPopupVisibleChange: handlePopupVisibleChange, ref: this.saveTrigger }); var children = getSlot(this); this.children = children; return _createVNode(Trigger, triggerProps, { default: function _default() { return [children && cloneElement(children[0], { onKeydown: handleKeyDown, tabindex: disabled ? undefined : 0 })]; } }); } });