UNPKG

@wfrog/vc

Version:

vue3 组件库 vc

1,450 lines (1,436 loc) 127 kB
import { defineComponent, inject, createVNode, Comment, computed, createElementBlock, openBlock, normalizeClass, unref, createCommentVNode, createBlock, withModifiers, withCtx, createElementVNode, Fragment, getCurrentInstance, ref, renderList, createTextVNode, toDisplayString, renderSlot, useSlots, provide, reactive, watch, onBeforeUpdate, onMounted, nextTick, useAttrs, withDirectives, isRef, vShow, normalizeStyle, createSlots, resolveDynamicComponent, withKeys, vModelText, Transition, mergeProps, toHandlers, onUpdated, h, resolveComponent, useTemplateRef, onBeforeUnmount } from 'vue'; import { j as isLeaf, k as focusNode, l as getSibling, e as useResizeObserver, m as useCssVar, c as useEventListener } from './CEClY-_T.mjs'; import { E as ElInput } from './D19ZZ4OA.mjs'; import { i as unique, c as castArray, u as useTooltipContentProps, E as Ee, a as ElTooltip } from './DUd8IaU9.mjs'; import { E as ElScrollbar } from './CJQcPuNK.mjs'; import { t as tagProps, E as ElTag } from './Bm4zCpG6.mjs'; import { E as ElIcon } from './m2vp1CCf.mjs'; import { Check, Loading, ArrowRight, CircleClose, ArrowDown, CaretRight } from '@element-plus/icons-vue'; import { u as useNamespace, i as isArray, a as isEmpty, j as isFunction, g as isUndefined, C as isPropAbsent, c as buildProps, N as NOOP, d as definePropType, o as isClient, x as isBoolean, e as debugWarn, w as useDebounceFn, G as isPromise, H as hasOwn, k as isNil, h as isString, s as isObject } from './E_WRn0OP.mjs'; import { u as useSizeProp, c as componentSizes } from './CS4VKsqy.mjs'; import { i as iconPropType } from '../components/icon/icon2.mjs'; import { u as useEmptyValuesProps, a as useEmptyValues } from './C5hWsUfD.mjs'; import { C as CHANGE_EVENT, U as UPDATE_MODEL_EVENT } from './Ct6q2FXg.mjs'; import { _ as _export_sfc, w as withInstall } from './D389hx_T.mjs'; import { C as ClickOutside } from './HSv8BL8o.mjs'; import { u as useLocale } from './-m34CPRn.mjs'; import { u as useFormItem, b as useFormDisabled, c as useFormSize } from './BOAz6rgm.mjs'; import { a as useComposition, u as useFocusController } from './JCIyOUEY.mjs'; import { g as getEventCode, E as EVENT_CODE } from './BJS5Pdfp.mjs'; import { c as cloneDeep } from './CyxEcbcy.mjs'; import { b as ElCheckbox, c as ElRadio } from './cUoiVgQs.mjs'; import { u as useVModel } from './eQT9aAiW.mjs'; import { r as removeClass, b as addClass } from './CD1S5tP1.mjs'; import { u as useId, f as formItemContextKey } from './8rLUmOVR.mjs'; import { i as isEqual } from './-EkpfdcW.mjs'; import { s as scrollIntoView } from './DBO1MWUI.mjs'; import { b as baseFlatten } from './C2LgraHx.mjs'; import { _ as _export_sfc$1 } from './pcqpp-6-.mjs'; /** Used as references for various `Number` constants. */ var INFINITY = 1 / 0; /** * Recursively flattens `array`. * * @static * @memberOf _ * @since 3.0.0 * @category Array * @param {Array} array The array to flatten. * @returns {Array} Returns the new flattened array. * @example * * _.flattenDeep([1, [2, [3, [4]], 5]]); * // => [1, 2, 3, 4, 5] */ function flattenDeep(array) { var length = array == null ? 0 : array.length; return length ? baseFlatten(array, INFINITY) : []; } const CASCADER_PANEL_INJECTION_KEY = Symbol(); function isVNodeEmpty(vnodes) { return !!(isArray(vnodes) ? vnodes.every(({ type }) => type === Comment) : (vnodes == null ? void 0 : vnodes.type) === Comment); } var NodeContent$1 = defineComponent({ name: "NodeContent", props: { node: { type: Object, required: true } }, setup(props) { const ns = useNamespace("cascader-node"); const { renderLabelFn } = inject(CASCADER_PANEL_INJECTION_KEY); const { node } = props; const { data, label: nodeLabel } = node; const label = () => { const renderLabel = renderLabelFn == null ? void 0 : renderLabelFn({ node, data }); return isVNodeEmpty(renderLabel) ? nodeLabel : renderLabel != null ? renderLabel : nodeLabel; }; return () => createVNode("span", { "class": ns.e("label") }, [label()]); } }); const __default__$5 = defineComponent({ name: "ElCascaderNode" }); const _sfc_main$9 = /* @__PURE__ */ defineComponent({ ...__default__$5, props: { node: { type: Object, required: true }, menuId: String }, emits: ["expand"], setup(__props, { emit }) { const props = __props; const panel = inject(CASCADER_PANEL_INJECTION_KEY); const ns = useNamespace("cascader-node"); const isHoverMenu = computed(() => panel.isHoverMenu); const multiple = computed(() => panel.config.multiple); const checkStrictly = computed(() => panel.config.checkStrictly); const showPrefix = computed(() => panel.config.showPrefix); const checkedNodeId = computed(() => { var _a; return (_a = panel.checkedNodes[0]) == null ? void 0 : _a.uid; }); const isDisabled = computed(() => props.node.isDisabled); const isLeaf = computed(() => props.node.isLeaf); const expandable = computed(() => checkStrictly.value && !isLeaf.value || !isDisabled.value); const inExpandingPath = computed(() => isInPath(panel.expandingNode)); const inCheckedPath = computed(() => checkStrictly.value && panel.checkedNodes.some(isInPath)); const isInPath = (node) => { var _a; const { level, uid } = props.node; return ((_a = node == null ? void 0 : node.pathNodes[level - 1]) == null ? void 0 : _a.uid) === uid; }; const doExpand = () => { if (inExpandingPath.value) return; panel.expandNode(props.node); }; const doCheck = (checked) => { const { node } = props; if (checked === node.checked) return; panel.handleCheckChange(node, checked); }; const doLoad = () => { panel.lazyLoad(props.node, () => { if (!isLeaf.value) doExpand(); }); }; const handleHoverExpand = (e) => { if (!isHoverMenu.value) return; handleExpand(); !isLeaf.value && emit("expand", e); }; const handleExpand = () => { const { node } = props; if (!expandable.value || node.loading) return; node.loaded ? doExpand() : doLoad(); }; const handleClick = () => { if (isLeaf.value && !isDisabled.value && !checkStrictly.value && !multiple.value) { handleCheck(true); } else if ((panel.config.checkOnClickNode && (multiple.value || checkStrictly.value) || isLeaf.value && panel.config.checkOnClickLeaf) && !isDisabled.value) { handleSelectCheck(!props.node.checked); } else if (!isHoverMenu.value) { handleExpand(); } }; const handleSelectCheck = (checked) => { if (checkStrictly.value) { doCheck(checked); if (props.node.loaded) { doExpand(); } } else { handleCheck(checked); } }; const handleCheck = (checked) => { if (!props.node.loaded) { doLoad(); } else { doCheck(checked); !checkStrictly.value && doExpand(); } }; return (_ctx, _cache) => { return openBlock(), createElementBlock("li", { id: `${__props.menuId}-${__props.node.uid}`, role: "menuitem", "aria-haspopup": !unref(isLeaf), "aria-owns": unref(isLeaf) ? void 0 : __props.menuId, "aria-expanded": unref(inExpandingPath), tabindex: unref(expandable) ? -1 : void 0, class: normalizeClass([ unref(ns).b(), unref(ns).is("selectable", unref(checkStrictly)), unref(ns).is("active", __props.node.checked), unref(ns).is("disabled", !unref(expandable)), unref(inExpandingPath) && "in-active-path", unref(inCheckedPath) && "in-checked-path" ]), onMouseenter: handleHoverExpand, onFocus: handleHoverExpand, onClick: handleClick }, [ createCommentVNode(" prefix "), unref(multiple) && unref(showPrefix) ? (openBlock(), createBlock(unref(ElCheckbox), { key: 0, "model-value": __props.node.checked, indeterminate: __props.node.indeterminate, disabled: unref(isDisabled), onClick: withModifiers(() => { }, ["stop"]), "onUpdate:modelValue": handleSelectCheck }, null, 8, ["model-value", "indeterminate", "disabled", "onClick"])) : unref(checkStrictly) && unref(showPrefix) ? (openBlock(), createBlock(unref(ElRadio), { key: 1, "model-value": unref(checkedNodeId), label: __props.node.uid, disabled: unref(isDisabled), "onUpdate:modelValue": handleSelectCheck, onClick: withModifiers(() => { }, ["stop"]) }, { default: withCtx(() => [ createCommentVNode("\n Add an empty element to avoid render label,\n do not use empty fragment here for https://github.com/vuejs/vue-next/pull/2485\n "), createElementVNode("span") ]), _: 1 }, 8, ["model-value", "label", "disabled", "onClick"])) : unref(isLeaf) && __props.node.checked ? (openBlock(), createBlock(unref(ElIcon), { key: 2, class: normalizeClass(unref(ns).e("prefix")) }, { default: withCtx(() => [ createVNode(unref(Check)) ]), _: 1 }, 8, ["class"])) : createCommentVNode("v-if", true), createCommentVNode(" content "), createVNode(unref(NodeContent$1), { node: __props.node }, null, 8, ["node"]), createCommentVNode(" postfix "), !unref(isLeaf) ? (openBlock(), createElementBlock(Fragment, { key: 3 }, [ __props.node.loading ? (openBlock(), createBlock(unref(ElIcon), { key: 0, class: normalizeClass([unref(ns).is("loading"), unref(ns).e("postfix")]) }, { default: withCtx(() => [ createVNode(unref(Loading)) ]), _: 1 }, 8, ["class"])) : (openBlock(), createBlock(unref(ElIcon), { key: 1, class: normalizeClass(["arrow-right", unref(ns).e("postfix")]) }, { default: withCtx(() => [ createVNode(unref(ArrowRight)) ]), _: 1 }, 8, ["class"])) ], 64)) : createCommentVNode("v-if", true) ], 42, ["id", "aria-haspopup", "aria-owns", "aria-expanded", "tabindex"]); }; } }); var ElCascaderNode = /* @__PURE__ */ _export_sfc(_sfc_main$9, [["__file", "node.vue"]]); const __default__$4 = defineComponent({ name: "ElCascaderMenu" }); const _sfc_main$8 = /* @__PURE__ */ defineComponent({ ...__default__$4, props: { nodes: { type: Array, required: true }, index: { type: Number, required: true } }, setup(__props) { const props = __props; const instance = getCurrentInstance(); const ns = useNamespace("cascader-menu"); const { t } = useLocale(); const id = useId(); let activeNode; let hoverTimer; const panel = inject(CASCADER_PANEL_INJECTION_KEY); const hoverZone = ref(); const isEmpty = computed(() => !props.nodes.length); const isLoading = computed(() => !panel.initialLoaded); const menuId = computed(() => `${id.value}-${props.index}`); const handleExpand = (e) => { activeNode = e.target; }; const handleMouseMove = (e) => { if (!panel.isHoverMenu || !activeNode || !hoverZone.value) return; if (activeNode.contains(e.target)) { clearHoverTimer(); const el = instance.vnode.el; const { left } = el.getBoundingClientRect(); const { offsetWidth, offsetHeight } = el; const startX = e.clientX - left; const top = activeNode.offsetTop; const bottom = top + activeNode.offsetHeight; hoverZone.value.innerHTML = ` <path style="pointer-events: auto;" fill="transparent" d="M${startX} ${top} L${offsetWidth} 0 V${top} Z" /> <path style="pointer-events: auto;" fill="transparent" d="M${startX} ${bottom} L${offsetWidth} ${offsetHeight} V${bottom} Z" /> `; } else if (!hoverTimer) { hoverTimer = window.setTimeout(clearHoverZone, panel.config.hoverThreshold); } }; const clearHoverTimer = () => { if (!hoverTimer) return; clearTimeout(hoverTimer); hoverTimer = void 0; }; const clearHoverZone = () => { if (!hoverZone.value) return; hoverZone.value.innerHTML = ""; clearHoverTimer(); }; return (_ctx, _cache) => { return openBlock(), createBlock(unref(ElScrollbar), { key: unref(menuId), tag: "ul", role: "menu", class: normalizeClass(unref(ns).b()), "wrap-class": unref(ns).e("wrap"), "view-class": [unref(ns).e("list"), unref(ns).is("empty", unref(isEmpty))], onMousemove: handleMouseMove, onMouseleave: clearHoverZone }, { default: withCtx(() => { var _a; return [ (openBlock(true), createElementBlock(Fragment, null, renderList(__props.nodes, (node) => { return openBlock(), createBlock(ElCascaderNode, { key: node.uid, node, "menu-id": unref(menuId), onExpand: handleExpand }, null, 8, ["node", "menu-id"]); }), 128)), unref(isLoading) ? (openBlock(), createElementBlock("div", { key: 0, class: normalizeClass(unref(ns).e("empty-text")) }, [ createVNode(unref(ElIcon), { size: "14", class: normalizeClass(unref(ns).is("loading")) }, { default: withCtx(() => [ createVNode(unref(Loading)) ]), _: 1 }, 8, ["class"]), createTextVNode(" " + toDisplayString(unref(t)("el.cascader.loading")), 1) ], 2)) : unref(isEmpty) ? (openBlock(), createElementBlock("div", { key: 1, class: normalizeClass(unref(ns).e("empty-text")) }, [ renderSlot(_ctx.$slots, "empty", {}, () => [ createTextVNode(toDisplayString(unref(t)("el.cascader.noData")), 1) ]) ], 2)) : ((_a = unref(panel)) == null ? void 0 : _a.isHoverMenu) ? (openBlock(), createElementBlock(Fragment, { key: 2 }, [ createCommentVNode(" eslint-disable-next-line vue/html-self-closing "), (openBlock(), createElementBlock("svg", { ref_key: "hoverZone", ref: hoverZone, class: normalizeClass(unref(ns).e("hover-zone")) }, null, 2)) ], 2112)) : createCommentVNode("v-if", true) ]; }), _: 3 }, 8, ["class", "wrap-class", "view-class"]); }; } }); var ElCascaderMenu = /* @__PURE__ */ _export_sfc(_sfc_main$8, [["__file", "menu.vue"]]); let uid = 0; const calculatePathNodes = (node) => { const nodes = [node]; let { parent } = node; while (parent) { nodes.unshift(parent); parent = parent.parent; } return nodes; }; let Node$1 = class Node { constructor(data, config, parent, root = false) { this.data = data; this.config = config; this.parent = parent; this.root = root; this.uid = uid++; this.checked = false; this.indeterminate = false; this.loading = false; const { value: valueKey, label: labelKey, children: childrenKey } = config; const childrenData = data[childrenKey]; const pathNodes = calculatePathNodes(this); this.level = root ? 0 : parent ? parent.level + 1 : 1; this.value = data[valueKey]; this.label = data[labelKey]; this.pathNodes = pathNodes; this.pathValues = pathNodes.map((node) => node.value); this.pathLabels = pathNodes.map((node) => node.label); this.childrenData = childrenData; this.children = (childrenData || []).map((child) => new Node(child, config, this)); this.loaded = !config.lazy || this.isLeaf || !isEmpty(childrenData); this.text = ""; } get isDisabled() { const { data, parent, config } = this; const { disabled, checkStrictly } = config; const isDisabled = isFunction(disabled) ? disabled(data, this) : !!data[disabled]; return isDisabled || !checkStrictly && !!(parent == null ? void 0 : parent.isDisabled); } get isLeaf() { const { data, config, childrenData, loaded } = this; const { lazy, leaf } = config; const isLeaf = isFunction(leaf) ? leaf(data, this) : data[leaf]; return isUndefined(isLeaf) ? lazy && !loaded ? false : !(isArray(childrenData) && childrenData.length) : !!isLeaf; } get valueByOption() { return this.config.emitPath ? this.pathValues : this.value; } appendChild(childData) { const { childrenData, children } = this; const node = new Node(childData, this.config, this); if (isArray(childrenData)) { childrenData.push(childData); } else { this.childrenData = [childData]; } children.push(node); return node; } calcText(allLevels, separator) { const text = allLevels ? this.pathLabels.join(separator) : this.label; this.text = text; return text; } broadcast(checked) { this.children.forEach((child) => { var _a; if (child) { child.broadcast(checked); (_a = child.onParentCheck) == null ? void 0 : _a.call(child, checked); } }); } emit() { var _a; const { parent } = this; if (parent) { (_a = parent.onChildCheck) == null ? void 0 : _a.call(parent); parent.emit(); } } onParentCheck(checked) { if (!this.isDisabled) { this.setCheckState(checked); } } onChildCheck() { const { children } = this; const validChildren = children.filter((child) => !child.isDisabled); const checked = validChildren.length ? validChildren.every((child) => child.checked) : false; this.setCheckState(checked); } setCheckState(checked) { const totalNum = this.children.length; const checkedNum = this.children.reduce((c, p) => { const num = p.checked ? 1 : p.indeterminate ? 0.5 : 0; return c + num; }, 0); this.checked = this.loaded && this.children.filter((child) => !child.isDisabled).every((child) => child.loaded && child.checked) && checked; this.indeterminate = this.loaded && checkedNum !== totalNum && checkedNum > 0; } doCheck(checked) { if (this.checked === checked) return; const { checkStrictly, multiple } = this.config; if (checkStrictly || !multiple) { this.checked = checked; } else { this.broadcast(checked); this.setCheckState(checked); this.emit(); } } }; const flatNodes = (nodes, leafOnly) => { return nodes.reduce((res, node) => { if (node.isLeaf) { res.push(node); } else { !leafOnly && res.push(node); res = res.concat(flatNodes(node.children, leafOnly)); } return res; }, []); }; class Store { constructor(data, config) { this.config = config; const nodes = (data || []).map((nodeData) => new Node$1(nodeData, this.config)); this.nodes = nodes; this.allNodes = flatNodes(nodes, false); this.leafNodes = flatNodes(nodes, true); } getNodes() { return this.nodes; } getFlattedNodes(leafOnly) { return leafOnly ? this.leafNodes : this.allNodes; } appendNode(nodeData, parentNode) { const node = parentNode ? parentNode.appendChild(nodeData) : new Node$1(nodeData, this.config); if (!parentNode) this.nodes.push(node); this.appendAllNodesAndLeafNodes(node); } appendNodes(nodeDataList, parentNode) { if (nodeDataList.length > 0) { nodeDataList.forEach((nodeData) => this.appendNode(nodeData, parentNode)); } else { parentNode && parentNode.isLeaf && this.leafNodes.push(parentNode); } } appendAllNodesAndLeafNodes(node) { this.allNodes.push(node); node.isLeaf && this.leafNodes.push(node); if (node.children) { node.children.forEach((subNode) => { this.appendAllNodesAndLeafNodes(subNode); }); } } getNodeByValue(value, leafOnly = false) { if (isPropAbsent(value)) return null; const node = this.getFlattedNodes(leafOnly).find((node2) => isEqual(node2.value, value) || isEqual(node2.pathValues, value)); return node || null; } getSameNode(node) { if (!node) return null; const node_ = this.getFlattedNodes(false).find(({ value, level }) => isEqual(node.value, value) && node.level === level); return node_ || null; } } const CommonProps = buildProps({ modelValue: { type: definePropType([Number, String, Array, Object]) }, options: { type: definePropType(Array), default: () => [] }, props: { type: definePropType(Object), default: () => ({}) } }); const DefaultProps = { expandTrigger: "click", multiple: false, checkStrictly: false, emitPath: true, lazy: false, lazyLoad: NOOP, value: "value", label: "label", children: "children", leaf: "leaf", disabled: "disabled", hoverThreshold: 500, checkOnClickNode: false, checkOnClickLeaf: true, showPrefix: true }; const cascaderPanelProps = buildProps({ ...CommonProps, border: { type: Boolean, default: true }, renderLabel: { type: Function } }); const emitChangeFn$1 = (value) => true; const cascaderPanelEmits = { [UPDATE_MODEL_EVENT]: emitChangeFn$1, [CHANGE_EVENT]: emitChangeFn$1, close: () => true, "expand-change": (value) => value }; const useCascaderConfig = (props) => { return computed(() => ({ ...DefaultProps, ...props.props })); }; const getMenuIndex = (el) => { if (!el) return 0; const pieces = el.id.split("-"); return Number(pieces[pieces.length - 2]); }; const checkNode = (el) => { if (!el) return; const input = el.querySelector("input"); if (input) { input.click(); } else if (isLeaf(el)) { el.click(); } }; const sortByOriginalOrder = (oldNodes, newNodes) => { const newNodesCopy = newNodes.slice(0); const newIds = newNodesCopy.map((node) => node.uid); const res = oldNodes.reduce((acc, item) => { const index = newIds.indexOf(item.uid); if (index > -1) { acc.push(item); newNodesCopy.splice(index, 1); newIds.splice(index, 1); } return acc; }, []); res.push(...newNodesCopy); return res; }; const __default__$3 = defineComponent({ name: "ElCascaderPanel" }); const _sfc_main$7 = /* @__PURE__ */ defineComponent({ ...__default__$3, props: cascaderPanelProps, emits: cascaderPanelEmits, setup(__props, { expose, emit }) { const props = __props; let manualChecked = false; const ns = useNamespace("cascader"); const config = useCascaderConfig(props); const slots = useSlots(); let store; const initialLoaded = ref(true); const initialLoadedOnce = ref(false); const menuList = ref([]); const checkedValue = ref(); const menus = ref([]); const expandingNode = ref(); const checkedNodes = ref([]); const isHoverMenu = computed(() => config.value.expandTrigger === "hover"); const renderLabelFn = computed(() => props.renderLabel || slots.default); const initStore = () => { const { options } = props; const cfg = config.value; manualChecked = false; store = new Store(options, cfg); menus.value = [store.getNodes()]; if (cfg.lazy && isEmpty(props.options)) { initialLoaded.value = false; lazyLoad(void 0, (list) => { if (list) { store = new Store(list, cfg); menus.value = [store.getNodes()]; } initialLoaded.value = true; syncCheckedValue(false, true); }); } else { syncCheckedValue(false, true); } }; const lazyLoad = (node, cb) => { const cfg = config.value; node = node || new Node$1({}, cfg, void 0, true); node.loading = true; const resolve = (dataList) => { const _node = node; const parent = _node.root ? null : _node; _node.loading = false; _node.loaded = true; _node.childrenData = _node.childrenData || []; dataList && (store == null ? void 0 : store.appendNodes(dataList, parent)); dataList && (cb == null ? void 0 : cb(dataList)); if (node.level === 0) { initialLoadedOnce.value = true; } }; const reject = () => { node.loading = false; node.loaded = false; if (node.level === 0) { initialLoaded.value = true; } }; cfg.lazyLoad(node, resolve, reject); }; const expandNode = (node, silent) => { var _a; const { level } = node; const newMenus = menus.value.slice(0, level); let newExpandingNode; if (node.isLeaf) { newExpandingNode = node.pathNodes[level - 2]; } else { newExpandingNode = node; newMenus.push(node.children); } if (((_a = expandingNode.value) == null ? void 0 : _a.uid) !== (newExpandingNode == null ? void 0 : newExpandingNode.uid)) { expandingNode.value = node; menus.value = newMenus; !silent && emit("expand-change", (node == null ? void 0 : node.pathValues) || []); } }; const handleCheckChange = (node, checked, emitClose = true) => { const { checkStrictly, multiple } = config.value; const oldNode = checkedNodes.value[0]; manualChecked = true; !multiple && (oldNode == null ? void 0 : oldNode.doCheck(false)); node.doCheck(checked); calculateCheckedValue(); emitClose && !multiple && !checkStrictly && emit("close"); !emitClose && !multiple && expandParentNode(node); }; const expandParentNode = (node) => { if (!node) return; node = node.parent; expandParentNode(node); node && expandNode(node); }; const getFlattedNodes = (leafOnly) => store == null ? void 0 : store.getFlattedNodes(leafOnly); const getCheckedNodes = (leafOnly) => { var _a; return (_a = getFlattedNodes(leafOnly)) == null ? void 0 : _a.filter(({ checked }) => checked !== false); }; const clearCheckedNodes = () => { checkedNodes.value.forEach((node) => node.doCheck(false)); calculateCheckedValue(); menus.value = menus.value.slice(0, 1); expandingNode.value = void 0; emit("expand-change", []); }; const calculateCheckedValue = () => { var _a; const { checkStrictly, multiple } = config.value; const oldNodes = checkedNodes.value; const newNodes = getCheckedNodes(!checkStrictly); const nodes = sortByOriginalOrder(oldNodes, newNodes); const values = nodes.map((node) => node.valueByOption); checkedNodes.value = nodes; checkedValue.value = multiple ? values : (_a = values[0]) != null ? _a : null; }; const syncCheckedValue = (loaded = false, forced = false) => { const { modelValue } = props; const { lazy, multiple, checkStrictly } = config.value; const leafOnly = !checkStrictly; if (!initialLoaded.value || manualChecked || !forced && isEqual(modelValue, checkedValue.value)) return; if (lazy && !loaded) { const values = unique(flattenDeep(castArray(modelValue))); const nodes = values.map((val) => store == null ? void 0 : store.getNodeByValue(val)).filter((node) => !!node && !node.loaded && !node.loading); if (nodes.length) { nodes.forEach((node) => { lazyLoad(node, () => syncCheckedValue(false, forced)); }); } else { syncCheckedValue(true, forced); } } else { const values = multiple ? castArray(modelValue) : [modelValue]; const nodes = unique(values.map((val) => store == null ? void 0 : store.getNodeByValue(val, leafOnly))); syncMenuState(nodes, forced); checkedValue.value = cloneDeep(modelValue != null ? modelValue : void 0); } }; const syncMenuState = (newCheckedNodes, reserveExpandingState = true) => { const { checkStrictly } = config.value; const oldNodes = checkedNodes.value; const newNodes = newCheckedNodes.filter((node) => !!node && (checkStrictly || node.isLeaf)); const oldExpandingNode = store == null ? void 0 : store.getSameNode(expandingNode.value); const newExpandingNode = reserveExpandingState && oldExpandingNode || newNodes[0]; if (newExpandingNode) { newExpandingNode.pathNodes.forEach((node) => expandNode(node, true)); } else { expandingNode.value = void 0; } oldNodes.forEach((node) => node.doCheck(false)); reactive(newNodes).forEach((node) => node.doCheck(true)); checkedNodes.value = newNodes; nextTick(scrollToExpandingNode); }; const scrollToExpandingNode = () => { if (!isClient) return; menuList.value.forEach((menu) => { const menuElement = menu == null ? void 0 : menu.$el; if (menuElement) { const container = menuElement.querySelector(`.${ns.namespace.value}-scrollbar__wrap`); const activeNode = menuElement.querySelector(`.${ns.b("node")}.${ns.is("active")}:last-child`) || menuElement.querySelector(`.${ns.b("node")}.in-active-path`); scrollIntoView(container, activeNode); } }); }; const handleKeyDown = (e) => { const target = e.target; const code = getEventCode(e); switch (code) { case EVENT_CODE.up: case EVENT_CODE.down: { e.preventDefault(); const distance = code === EVENT_CODE.up ? -1 : 1; focusNode(getSibling(target, distance, `.${ns.b("node")}[tabindex="-1"]`)); break; } case EVENT_CODE.left: { e.preventDefault(); const preMenu = menuList.value[getMenuIndex(target) - 1]; const expandedNode = preMenu == null ? void 0 : preMenu.$el.querySelector(`.${ns.b("node")}[aria-expanded="true"]`); focusNode(expandedNode); break; } case EVENT_CODE.right: { e.preventDefault(); const nextMenu = menuList.value[getMenuIndex(target) + 1]; const firstNode = nextMenu == null ? void 0 : nextMenu.$el.querySelector(`.${ns.b("node")}[tabindex="-1"]`); focusNode(firstNode); break; } case EVENT_CODE.enter: case EVENT_CODE.numpadEnter: checkNode(target); break; } }; provide(CASCADER_PANEL_INJECTION_KEY, reactive({ config, expandingNode, checkedNodes, isHoverMenu, initialLoaded, renderLabelFn, lazyLoad, expandNode, handleCheckChange })); watch(config, (newVal, oldVal) => { if (isEqual(newVal, oldVal)) return; initStore(); }, { immediate: true }); watch(() => props.options, initStore, { deep: true }); watch(() => props.modelValue, () => { manualChecked = false; syncCheckedValue(); }, { deep: true }); watch(() => checkedValue.value, (val) => { if (!isEqual(val, props.modelValue)) { emit(UPDATE_MODEL_EVENT, val); emit(CHANGE_EVENT, val); } }); const loadLazyRootNodes = () => { if (initialLoadedOnce.value) return; initStore(); }; onBeforeUpdate(() => menuList.value = []); onMounted(() => !isEmpty(props.modelValue) && syncCheckedValue()); expose({ menuList, menus, checkedNodes, handleKeyDown, handleCheckChange, getFlattedNodes, getCheckedNodes, clearCheckedNodes, calculateCheckedValue, scrollToExpandingNode, loadLazyRootNodes }); return (_ctx, _cache) => { return openBlock(), createElementBlock("div", { class: normalizeClass([unref(ns).b("panel"), unref(ns).is("bordered", _ctx.border)]), onKeydown: handleKeyDown }, [ (openBlock(true), createElementBlock(Fragment, null, renderList(menus.value, (menu, index) => { return openBlock(), createBlock(ElCascaderMenu, { key: index, ref_for: true, ref: (item) => menuList.value[index] = item, index, nodes: [...menu] }, { empty: withCtx(() => [ renderSlot(_ctx.$slots, "empty") ]), _: 2 }, 1032, ["index", "nodes"]); }), 128)) ], 34); }; } }); var CascaderPanel = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["__file", "index.vue"]]); const ElCascaderPanel = withInstall(CascaderPanel); const cascaderProps = buildProps({ ...CommonProps, size: useSizeProp, placeholder: String, disabled: Boolean, clearable: Boolean, clearIcon: { type: iconPropType, default: CircleClose }, filterable: Boolean, filterMethod: { type: definePropType(Function), default: (node, keyword) => node.text.includes(keyword) }, separator: { type: String, default: " / " }, showAllLevels: { type: Boolean, default: true }, collapseTags: Boolean, maxCollapseTags: { type: Number, default: 1 }, collapseTagsTooltip: Boolean, maxCollapseTagsTooltipHeight: { type: [String, Number] }, debounce: { type: Number, default: 300 }, beforeFilter: { type: definePropType(Function), default: () => true }, placement: { type: definePropType(String), values: Ee, default: "bottom-start" }, fallbackPlacements: { type: definePropType(Array), default: ["bottom-start", "bottom", "top-start", "top", "right", "left"] }, popperClass: useTooltipContentProps.popperClass, popperStyle: useTooltipContentProps.popperStyle, teleported: useTooltipContentProps.teleported, effect: { type: definePropType(String), default: "light" }, tagType: { ...tagProps.type, default: "info" }, tagEffect: { ...tagProps.effect, default: "light" }, validateEvent: { type: Boolean, default: true }, persistent: { type: Boolean, default: true }, showCheckedStrategy: { type: String, values: ["parent", "child"], default: "child" }, checkOnClickNode: Boolean, showPrefix: { type: Boolean, default: true }, ...useEmptyValuesProps }); const emitChangeFn = (value) => true; const cascaderEmits = { [UPDATE_MODEL_EVENT]: emitChangeFn, [CHANGE_EVENT]: emitChangeFn, focus: (evt) => evt instanceof FocusEvent, blur: (evt) => evt instanceof FocusEvent, clear: () => true, visibleChange: (val) => isBoolean(val), expandChange: (val) => !!val, removeTag: (val) => !!val }; const __default__$2 = defineComponent({ name: "ElCascader" }); const _sfc_main$6 = /* @__PURE__ */ defineComponent({ ...__default__$2, props: cascaderProps, emits: cascaderEmits, setup(__props, { expose, emit }) { const props = __props; const popperOptions = { modifiers: [ { name: "arrowPosition", enabled: true, phase: "main", fn: ({ state }) => { const { modifiersData, placement } = state; if (["right", "left", "bottom", "top"].includes(placement)) return; if (modifiersData.arrow) { modifiersData.arrow.x = 35; } }, requires: ["arrow"] } ] }; const attrs = useAttrs(); let inputInitialHeight = 0; let pressDeleteCount = 0; const nsCascader = useNamespace("cascader"); const nsInput = useNamespace("input"); const { t } = useLocale(); const { formItem } = useFormItem(); const isDisabled = useFormDisabled(); const { valueOnClear } = useEmptyValues(props); const { isComposing, handleComposition } = useComposition({ afterComposition(event) { var _a; const text = (_a = event.target) == null ? void 0 : _a.value; handleInput(text); } }); const tooltipRef = ref(); const tagTooltipRef = ref(); const inputRef = ref(); const tagWrapper = ref(); const cascaderPanelRef = ref(); const suggestionPanel = ref(); const popperVisible = ref(false); const inputHover = ref(false); const filtering = ref(false); const inputValue = ref(""); const searchInputValue = ref(""); const tags = ref([]); const suggestions = ref([]); const showTagList = computed(() => { if (!props.props.multiple) { return []; } return props.collapseTags ? tags.value.slice(0, props.maxCollapseTags) : tags.value; }); const collapseTagList = computed(() => { if (!props.props.multiple) { return []; } return props.collapseTags ? tags.value.slice(props.maxCollapseTags) : []; }); const cascaderStyle = computed(() => { return attrs.style; }); const inputPlaceholder = computed(() => { var _a; return (_a = props.placeholder) != null ? _a : t("el.cascader.placeholder"); }); const currentPlaceholder = computed(() => searchInputValue.value || tags.value.length > 0 || isComposing.value ? "" : inputPlaceholder.value); const realSize = useFormSize(); const tagSize = computed(() => realSize.value === "small" ? "small" : "default"); const multiple = computed(() => !!props.props.multiple); const readonly = computed(() => !props.filterable || multiple.value); const searchKeyword = computed(() => multiple.value ? searchInputValue.value : inputValue.value); const checkedNodes = computed(() => { var _a; return ((_a = cascaderPanelRef.value) == null ? void 0 : _a.checkedNodes) || []; }); const { wrapperRef, isFocused, handleBlur } = useFocusController(inputRef, { disabled: isDisabled, beforeBlur(event) { var _a, _b; return ((_a = tooltipRef.value) == null ? void 0 : _a.isFocusInsideContent(event)) || ((_b = tagTooltipRef.value) == null ? void 0 : _b.isFocusInsideContent(event)); }, afterBlur() { var _a; if (props.validateEvent) { (_a = formItem == null ? void 0 : formItem.validate) == null ? void 0 : _a.call(formItem, "blur").catch((err) => debugWarn(err)); } } }); const clearBtnVisible = computed(() => { if (!props.clearable || isDisabled.value || filtering.value || !inputHover.value && !isFocused.value) return false; return !!checkedNodes.value.length; }); const presentText = computed(() => { const { showAllLevels, separator } = props; const nodes = checkedNodes.value; return nodes.length ? multiple.value ? "" : nodes[0].calcText(showAllLevels, separator) : ""; }); const validateState = computed(() => (formItem == null ? void 0 : formItem.validateState) || ""); const checkedValue = computed({ get() { return cloneDeep(props.modelValue); }, set(val) { const value = val != null ? val : valueOnClear.value; emit(UPDATE_MODEL_EVENT, value); emit(CHANGE_EVENT, value); if (props.validateEvent) { formItem == null ? void 0 : formItem.validate("change").catch((err) => debugWarn(err)); } } }); const cascaderKls = computed(() => { return [ nsCascader.b(), nsCascader.m(realSize.value), nsCascader.is("disabled", isDisabled.value), attrs.class ]; }); const cascaderIconKls = computed(() => { return [ nsInput.e("icon"), "icon-arrow-down", nsCascader.is("reverse", popperVisible.value) ]; }); const inputClass = computed(() => nsCascader.is("focus", isFocused.value)); const contentRef = computed(() => { var _a, _b; return (_b = (_a = tooltipRef.value) == null ? void 0 : _a.popperRef) == null ? void 0 : _b.contentRef; }); const handleClickOutside = (event) => { if (isFocused.value) { const _event = new FocusEvent("blur", event); handleBlur(_event); } togglePopperVisible(false); }; const togglePopperVisible = (visible) => { var _a, _b, _c; if (isDisabled.value) return; visible = visible != null ? visible : !popperVisible.value; if (visible !== popperVisible.value) { popperVisible.value = visible; (_b = (_a = inputRef.value) == null ? void 0 : _a.input) == null ? void 0 : _b.setAttribute("aria-expanded", `${visible}`); if (visible) { updatePopperPosition(); nextTick((_c = cascaderPanelRef.value) == null ? void 0 : _c.scrollToExpandingNode); } else if (props.filterable) { syncPresentTextValue(); } emit("visibleChange", visible); } }; const updatePopperPosition = () => { nextTick(() => { var _a; (_a = tooltipRef.value) == null ? void 0 : _a.updatePopper(); }); }; const hideSuggestionPanel = () => { filtering.value = false; }; const genTag = (node) => { const { showAllLevels, separator } = props; return { node, key: node.uid, text: node.calcText(showAllLevels, separator), hitState: false, closable: !isDisabled.value && !node.isDisabled }; }; const deleteTag = (tag) => { var _a; const node = tag.node; node.doCheck(false); (_a = cascaderPanelRef.value) == null ? void 0 : _a.calculateCheckedValue(); emit("removeTag", node.valueByOption); }; const getStrategyCheckedNodes = () => { switch (props.showCheckedStrategy) { case "child": return checkedNodes.value; case "parent": { const clickedNodes = getCheckedNodes(false); const clickedNodesValue = clickedNodes.map((o) => o.value); const parentNodes = clickedNodes.filter((o) => !o.parent || !clickedNodesValue.includes(o.parent.value)); return parentNodes; } default: return []; } }; const calculatePresentTags = () => { if (!multiple.value) return; const nodes = getStrategyCheckedNodes(); const allTags = []; nodes.forEach((node) => allTags.push(genTag(node))); tags.value = allTags; }; const calculateSuggestions = () => { var _a, _b; const { filterMethod, showAllLevels, separator } = props; const res = (_b = (_a = cascaderPanelRef.value) == null ? void 0 : _a.getFlattedNodes(!props.props.checkStrictly)) == null ? void 0 : _b.filter((node) => { if (node.isDisabled) return false; node.calcText(showAllLevels, separator); return filterMethod(node, searchKeyword.value); }); if (multiple.value) { tags.value.forEach((tag) => { tag.hitState = false; }); } filtering.value = true; suggestions.value = res; updatePopperPosition(); }; const focusFirstNode = () => { var _a; let firstNode; if (filtering.value && suggestionPanel.value) { firstNode = suggestionPanel.value.$el.querySelector(`.${nsCascader.e("suggestion-item")}`); } else { firstNode = (_a = cascaderPanelRef.value) == null ? void 0 : _a.$el.querySelector(`.${nsCascader.b("node")}[tabindex="-1"]`); } if (firstNode) { firstNode.focus(); !filtering.value && firstNode.click(); } }; const updateStyle = () => { var _a, _b; const inputInner = (_a = inputRef.value) == null ? void 0 : _a.input; const tagWrapperEl = tagWrapper.value; const suggestionPanelEl = (_b = suggestionPanel.value) == null ? void 0 : _b.$el; if (!isClient || !inputInner) return; if (suggestionPanelEl) { const suggestionList = suggestionPanelEl.querySelector(`.${nsCascader.e("suggestion-list")}`); suggestionList.style.minWidth = `${inputInner.offsetWidth}px`; } if (tagWrapperEl) { const { offsetHeight } = tagWrapperEl; const height = tags.value.length > 0 ? `${Math.max(offsetHeight, inputInitialHeight) - 2}px` : `${inputInitialHeight}px`; inputInner.style.height = height; updatePopperPosition(); } }; const getCheckedNodes = (leafOnly) => { var _a; return (_a = cascaderPanelRef.value) == null ? void 0 : _a.getCheckedNodes(leafOnly); }; const handleExpandChange = (value) => { updatePopperPosition(); emit("expandChange", value); }; const handleKeyDown = (e) => { if (isComposing.value) return; const code = getEventCode(e); switch (code) { case EVENT_CODE.enter: case EVENT_CODE.numpadEnter: togglePopperVisible(); break; case EVENT_CODE.down: togglePopperVisible(true); nextTick(focusFirstNode); e.preventDefault(); break; case EVENT_CODE.esc: if (popperVisible.value === true) { e.preventDefault(); e.stopPropagation(); togglePopperVisible(false); } break; case EVENT_CODE.tab: togglePopperVisible(false); break; } }; const handleClear = () => { var _a; (_a = cascaderPanelRef.value) == null ? void 0 : _a.clearCheckedNodes(); if (!popperVisible.value && props.filterable) { syncPresentTextValue(); } togglePopperVisible(false); emit("clear"); }; const syncPresentTextValue = () => { const { value } = presentText; inputValue.value = value; searchInputValue.value = value; }; const handleSuggestionClick = (node) => { var _a, _b; const { checked } = node; if (multiple.value) { (_a = cascaderPanelRef.value) == null ? void 0 : _a.handleCheckChange(node, !checked, false); } else { !checked && ((_b = cascaderPanelRef.value) == null ? void 0 : _b.handleCheckChange(node, true, false)); togglePopperVisible(false); } }; const handleSuggestionKeyDown = (e) => { const target = e.target; const code = getEventCode(e); switch (code) { case EVENT_CODE.up: case EVENT_CODE.down: { e.preventDefault(); const distance = code === EVENT_CODE.up ? -1 : 1; focusNode(getSibling(target, distance, `.${nsCascader.e("suggestion-item")}[tabindex="-1"]`)); break; } case EVENT_CODE.enter: case EVENT_CODE.numpadEnter: target.click(); break; } }; const handleDelete = () => { const lastTag = tags.value[tags.value.length - 1]; pressDeleteCount = searchInputValue.value ? 0 : pressDeleteCount + 1; if (!lastTag || !pressDeleteCount || props.collapseTags && tags.value.length > 1) return; if (lastTag.hitState) { deleteTag(lastTag); } else { lastTag.hitState = true; } }; const debounce = computed(() => props.debounce); const handleFilter = useDebounceFn(() => { const { value } = searchKeyword; if (!value) return; const passed = props.beforeFilter(value); if (isPromise(passed)) { passed.then(calculateSuggestions).catch(() => { }); } else if (passed !== false) { calculateSuggestions(); } else { hideSuggestionPanel(); } }, debounce); const handleInput = (val, e) => { !popperVisible.value && togglePopperVisible(true); if (e == null ? void 0 : e.isComposing) return; val ? handleFilter() : hideSuggestionPanel(); }; const getInputInnerHeight = (inputInner) => Number.parseFloat(useCssVar(nsInput.cssVarName("input-height"), inputInner).value) - 2; const focus = () => { var _a; (_a = inputRef.value) == null ? void 0 : _a.focus(); }; const blur = () => { var _a; (_a = inputRef.value) == null ? void 0 : _a.blur(); }; watch(filtering, updatePopperPosition); watch([ checkedNodes, isDisabled, () => props.collapseTags, () => props.maxCollapseTags ], calculatePresentTags); watch(tags, () => { nextTick(() => updateStyle()); }); watch(realSize, async () => { await nextTick(); const inputInner = inputRef.value.input; inputInitialHeight = getInputInnerHeight(inputInner) || inputInitialHeight; updateStyle(); }); watch(presentText, syncPresentTextValue, { immediate: true }); watch(() => popperVisible.value, (val) => { var _a; if (val && props.props.lazy && props.props.lazyLoad) { (_a = cascaderPanelRef.value) == null ? void 0 : _a.loadLazyRootNodes(); } }); onMounted(() => { const inputInner = inputRef.value.input; const inputInnerHeight = getInputInnerHeight(inputInner); inputInitialHeight = inputInner.offsetHeight || inputInnerHeight; useResizeObserver(inputInner, updateStyle); }); expose({ getCheckedNodes, cascaderPanelRef, togglePopperVisible, contentRef, presentText, focus, blur }); return (_ctx, _cache) => { return openBlock(), createBlock(unref(ElTooltip), { ref_key: "tooltipRef", ref: tooltipRef, visible: popperVisible.value, teleported: _ctx.teleported, "popper-class": [unref(nsCascader).e("dropdown"), _ctx.popperClass], "popper-style": _ctx.popperStyle, "popper-options": popperOptions, "fallback-p