UNPKG

@opensig/opendesign

Version:

675 lines (674 loc) 26.8 kB
"use strict"; const vue = require("vue"); const index$1 = require("../scrollbar/index.js"); const index$2 = require("../divider/index.js"); const icons = require("../_utils/icons.js"); const is = require("../_utils/is.js"); const index = require("../locale/index.js"); const cascader = require("../cascader/cascader.js"); const types = require("./types.js"); const provide = require("./provide.js"); const OCascaderV2Label_vue_vue_type_script_setup_true_lang = require("./OCascaderV2Label.vue.js"); const _hoisted_1 = { class: "o-cascader-v2-panel-loading" }; const _hoisted_2 = ["onClick"]; const _hoisted_3 = { key: 1, class: "o-cascader-v2-panel-empty" }; const _hoisted_4 = { class: "o-cascader-v2-options" }; const _hoisted_5 = ["onClick", "onMouseenter"]; const ROOT_KEY = "__root__"; const _sfc_main = /* @__PURE__ */ vue.defineComponent({ __name: "OCascaderV2Panel", props: types.cascaderV2PanelProps, emits: ["change", "update:modelValue"], setup(__props, { emit: __emit }) { const cascaderV2Inject = vue.inject(provide.cascaderV2InjectKey, null); const props = __props; const emits = __emit; const { t } = index.useI18n(); const isMultiple = cascaderV2Inject == null ? void 0 : cascaderV2Inject.multiple; const allowSelectAnyNode = (cascaderV2Inject == null ? void 0 : cascaderV2Inject.allowSelectAnyNode) ?? false; const filterValue = cascaderV2Inject == null ? void 0 : cascaderV2Inject.filterValue; const isSelecting = cascaderV2Inject == null ? void 0 : cascaderV2Inject.isSelecting; const isLoading = cascaderV2Inject == null ? void 0 : cascaderV2Inject.loading; const cascaderTree = new cascader(); const lazyLoadState = vue.ref({}); const panelInfo = vue.ref(); const selectedVal = vue.computed(() => { return (cascaderV2Inject == null ? void 0 : cascaderV2Inject.selectValue.value) ?? []; }); const selectedLeafNode = vue.computed(() => { return selectedVal.value.map((val) => { const node = cascaderTree.getNode(val); if (!node || !node.isLeaf) { return; } return node; }).filter(Boolean); }); const selectedLeafPath = vue.computed(() => { return selectedLeafNode.value.map((val) => { return val == null ? void 0 : val.fullPath; }).filter((item) => item == null ? void 0 : item.length); }); const isNodeFullySelected = (val) => { const node = cascaderTree.getNode(val); if (!node) return false; if (node.isLeaf) return selectedVal.value.includes(val); return node.children.length > 0 && node.children.every((child) => isNodeFullySelected(child.value)); }; const innerExpandTrigger = vue.computed(() => { if (is.isTouchDevice) { return "click"; } if (props.expandTrigger === "hover" || props.expandTrigger === "click") { return props.expandTrigger; } return "click"; }); const leafNodes = vue.ref([]); const collectAllDescendants = (root) => { const result = []; const dfs = (node) => { for (const child of node.children) { result.push(child); dfs(child); } }; dfs(root); return result; }; const splitLabelByKeyword = (label, keyword) => { const parts = []; let lastIndex = 0; while (true) { const index2 = label.indexOf(keyword, lastIndex); if (index2 === -1) break; if (index2 > lastIndex) { parts.push({ text: label.substring(lastIndex, index2), isHighlighted: false }); } parts.push({ text: label.substring(index2, index2 + keyword.length), isHighlighted: true }); lastIndex = index2 + keyword.length; } if (lastIndex < label.length) { parts.push({ text: label.substring(lastIndex), isHighlighted: false }); } return parts; }; const filteredOptions = vue.computed(() => { if (!props.filterable || !(cascaderV2Inject == null ? void 0 : cascaderV2Inject.filterValue.value)) { return []; } const searchValue = cascaderV2Inject.filterValue.value; const sourceNodes = allowSelectAnyNode ? (void leafNodes.value, collectAllDescendants(cascaderTree.root)) : leafNodes.value; return sourceNodes.filter((item) => item.fullLabel.includes(searchValue)).map((node) => ({ label: node.fullLabel, labelParts: splitLabelByKeyword(node.fullLabel, searchValue), value: node.value, disabled: node.disabled, isActive: selectedVal.value.includes(node.value), isLeaf: node.isLeaf })); }); const updateSelectedValue = (option, doSelect = true, path) => { cascaderV2Inject == null ? void 0 : cascaderV2Inject.registerOption(option); if (path) { cascaderV2Inject == null ? void 0 : cascaderV2Inject.registerPath(option.value, path); } if (doSelect) { cascaderV2Inject == null ? void 0 : cascaderV2Inject.doSelect(option, path); } }; const hidePanel = (shouldHide) => { if (!shouldHide) { return; } cascaderV2Inject == null ? void 0 : cascaderV2Inject.hidePanel(); }; const isNonLeafPathCovered = (currPath) => { const currLen = currPath.length; return selectedLeafPath.value.some((path) => { if (path) { const pathLen = path.length; return is.isArrayEqual(currPath, path.slice(0, currLen - pathLen)); } }); }; const deactivateAllNonLeafNodesInColumn = (columnInfo) => { columnInfo.forEach((item) => { item.isActive = !item.isLeaf ? false : item.isActive; }); }; const initColumnInfo = (columnInfo) => { columnInfo.forEach((item) => { if (!item.isLeaf) { item.hasActiveChild = allowSelectAnyNode ? false : isNonLeafPathCovered(item.fullPath); return; } if (selectedVal.value.includes(item.value)) { item.isActive = true; } }); }; const refrashCheckStateByBubble = (option, columnInfo) => { if (allowSelectAnyNode) { return; } const depth = option.depth; if (depth < 2) { return; } const hasActiveChild = columnInfo.some((item) => item.isLeaf && item.isActive || item.hasActiveChild); const prevColumnInfo = panelInfo.value[depth - 2]; const parentOption = prevColumnInfo.find((item) => { var _a; return item.value === ((_a = option.parent) == null ? void 0 : _a.value); }); if (!parentOption) { return; } parentOption.hasActiveChild = hasActiveChild; refrashCheckStateByBubble(parentOption, prevColumnInfo); }; const getOptionList = () => { var _a; const panelInfoLen = ((_a = panelInfo.value) == null ? void 0 : _a.length) || 0; const nonLeafOptionList = []; for (let i = 0; i < panelInfoLen; i++) { const columnInfo = panelInfo.value[i]; const columnInfoLen = columnInfo.length; for (let j = 0; j < columnInfoLen; j++) { const currOption = columnInfo[j]; if (!currOption.isLeaf) { nonLeafOptionList.push(currOption); continue; } if (selectedVal.value.includes(currOption.value)) { currOption.isActive = true; } else { currOption.isActive = false; } } } return nonLeafOptionList; }; const refrashCheckStateByCapture = () => { const nonLeafOptionList = getOptionList(); nonLeafOptionList.forEach((option) => { option.hasActiveChild = allowSelectAnyNode ? false : isNonLeafPathCovered(option.fullPath); }); }; const selectOption = (option, columnInfo) => { var _a; while (option.depth < panelInfo.value.length) { (_a = panelInfo.value) == null ? void 0 : _a.pop(); } if (isMultiple) { option.isActive = !option.isActive; deactivateAllNonLeafNodesInColumn(columnInfo); if (!allowSelectAnyNode) { refrashCheckStateByBubble(option, columnInfo); } } else { columnInfo.forEach((item) => { item.isActive = item.value === option.value; }); } const { label, fullLabel, value, fullPath } = option; const simpleVal = value; if (props.pathMode) { emits("change", fullPath); emits("update:modelValue", fullPath); } else { emits("change", simpleVal); emits("update:modelValue", simpleVal); } updateSelectedValue({ label: props.showAllLevels ? fullLabel : label ?? "", value }, true, fullPath); }; const selectNonLeafStrict = (option) => { updateSelectedValue({ label: props.showAllLevels ? option.fullLabel : option.label ?? "", value: option.value }, true, option.fullPath); }; const getLeafDescendants = (nodeValue) => { const node = cascaderTree.getNode(nodeValue); if (!node) return []; const leaves = []; const traverse = (n) => { if (n.isLeaf) { leaves.push(n); } else { n.children.forEach(traverse); } }; node.children.forEach(traverse); return leaves; }; const toggleNonLeafDescendants = (option) => { const leaves = getLeafDescendants(option.value); if (!leaves.length) return; if (isNodeFullySelected(option.value)) { cascaderV2Inject == null ? void 0 : cascaderV2Inject.doSelectBatch( [], leaves.map((l) => l.value) ); } else { const toAdd = leaves.filter((l) => !l.disabled).map((l) => ({ value: l.value, label: props.showAllLevels ? l.fullLabel : l.label ?? "", path: l.fullPath })); cascaderV2Inject == null ? void 0 : cascaderV2Inject.doSelectBatch(toAdd, []); } refrashCheckStateByCapture(); }; const syncColumnActiveState = (option, columnInfo) => { if (isMultiple) { deactivateAllNonLeafNodesInColumn(columnInfo); option.isActive = !option.isActive; return; } columnInfo.forEach((item) => { item.isActive = item.value === option.value; }); }; const pushChildrenColumn = (node) => { const nextColumnInfo = cascaderTree.getColumnInfo(node, selectedVal.value); initColumnInfo(nextColumnInfo); panelInfo.value.push(nextColumnInfo); }; const triggerLazyLoad = (option, node) => { var _a; lazyLoadState.value[String(option.value)] = "loading"; const lazyNode = { value: node.value, level: node.depth, isLeaf: node.isLeaf, data: { value: node.value, label: node.label }, path: node.fullPath, label: node.fullLabel }; const nodeResolve = (children) => { cascaderTree.addChildren(node.value, children, true); leafNodes.value = cascaderTree.getLeafNodes(); lazyLoadState.value[String(option.value)] = "loaded"; const updatedNode = cascaderTree.getNode(option.value); if (updatedNode) { option.isLeaf = updatedNode.isLeaf; } if (!option.isLeaf && updatedNode) { pushChildrenColumn(updatedNode); } }; const nodeReject = () => { lazyLoadState.value[String(option.value)] = "error"; cascaderV2Inject == null ? void 0 : cascaderV2Inject.onLazyloadError(lazyNode); }; const result = (_a = props.lazyload) == null ? void 0 : _a.call(props, lazyNode, nodeResolve, nodeReject); if (result instanceof Promise) { result.then(nodeResolve).catch(nodeReject); } }; const expandOption = (option, columnInfo) => { var _a; if (props.lazy && lazyLoadState.value[String(option.value)] === "loading") return; while (option.depth < panelInfo.value.length) { (_a = panelInfo.value) == null ? void 0 : _a.pop(); } syncColumnActiveState(option, columnInfo); const node = cascaderTree.getNode(option.value); if (!node) return; if (props.lazy && props.lazyload && lazyLoadState.value[String(option.value)] !== "loaded") { triggerLazyLoad(option, node); return; } pushChildrenColumn(node); }; const selectNonLeafOption = (option) => { if (isMultiple) { if (allowSelectAnyNode) { selectNonLeafStrict(option); return; } toggleNonLeafDescendants(option); return; } const { label, fullLabel, value, fullPath } = option; updateSelectedValue({ label: props.showAllLevels ? fullLabel : label ?? "", value }, true, fullPath); }; const onLabelSelect = (option, columnInfo) => { if (!is.isArray(panelInfo.value) || option.disabled) { return; } if (option.isLeaf) { selectOption(option, columnInfo); hidePanel(!isMultiple); return; } selectNonLeafOption(option); if (!option.isActive && innerExpandTrigger.value === "click") { expandOption(option, columnInfo); } }; const onClick = (option, columnInfo) => { if (!is.isArray(panelInfo.value) || option.disabled) { return; } if (option.isLeaf) { selectOption(option, columnInfo); hidePanel(!isMultiple); return; } if (innerExpandTrigger.value !== "click") return; expandOption(option, columnInfo); }; const onMouseenter = (option, columnInfo) => { if (!is.isArray(panelInfo.value) || option.isLeaf || option.isActive || innerExpandTrigger.value !== "hover") { return; } expandOption(option, columnInfo); }; const getFinalPath = () => { const numSet = /* @__PURE__ */ new Set(); selectedLeafPath.value.forEach((item) => { numSet.add((item == null ? void 0 : item.length) ?? 0); }); const maxPathLen = Math.max(...Array.from(numSet)); const filteredPathList = selectedLeafPath.value.filter((item) => (item == null ? void 0 : item.length) === maxPathLen); return filteredPathList[filteredPathList.length - 1]; }; const buildSelectedOption = (node) => ({ label: props.showAllLevels ? node.fullLabel : node.label ?? "", value: node.value }); const syncMultipleSelection = () => { selectedLeafNode.value.forEach((item) => { updateSelectedValue(buildSelectedOption(item), false, item.fullPath); }); if (!allowSelectAnyNode) return; selectedVal.value.forEach((v) => { const node = cascaderTree.getNode(v); if (node && !node.isLeaf) { updateSelectedValue(buildSelectedOption(node), false, node.fullPath); } }); }; const refreshSingleSelection = (modelValue) => { if (!modelValue && modelValue !== 0) { panelInfo.value = cascaderTree.root.children.length ? [cascaderTree.getColumnInfo(cascaderTree.root)] : void 0; return; } panelInfo.value = cascaderTree.getPanelInfo(modelValue, props.lazy); if (is.isArray(modelValue)) return; const node = cascaderTree.getNode(modelValue); if (!node) return; updateSelectedValue(buildSelectedOption(node), true, node.fullPath); }; const refreshCascaderV2Data = (modelValue) => { if (is.isArray(modelValue) && modelValue.length) { const finalPath = getFinalPath(); panelInfo.value = finalPath ? cascaderTree.getPanelInfo(finalPath, props.lazy) : [cascaderTree.getColumnInfo(cascaderTree.root)]; syncMultipleSelection(); refrashCheckStateByCapture(); return; } refreshSingleSelection(modelValue); }; const loadRoot = () => { if (!props.lazy || !props.lazyload) return; if (lazyLoadState.value[ROOT_KEY] === "loading" || lazyLoadState.value[ROOT_KEY] === "loaded") return; lazyLoadState.value[ROOT_KEY] = "loading"; cascaderV2Inject == null ? void 0 : cascaderV2Inject.setRootLoading(true); const rootNode = { value: null, level: 0, isLeaf: false, data: null, path: [], label: "" }; const rootResolve = (children) => { cascaderTree.addChildren(null, children, true); leafNodes.value = cascaderTree.getLeafNodes(); lazyLoadState.value[ROOT_KEY] = "loaded"; cascaderV2Inject == null ? void 0 : cascaderV2Inject.setRootLoading(false); refreshCascaderV2Data(props.modelValue); }; const rootReject = () => { lazyLoadState.value[ROOT_KEY] = "error"; cascaderV2Inject == null ? void 0 : cascaderV2Inject.setRootLoading(false); cascaderV2Inject == null ? void 0 : cascaderV2Inject.onLazyloadError(rootNode); }; const result = props.lazyload(rootNode, rootResolve, rootReject); if (result instanceof Promise) { result.then(rootResolve).catch(rootReject); } }; vue.watch( () => props.options, (val) => { if (!is.isUndefined(val)) { cascaderTree.updateTree(val, props.lazy); leafNodes.value = cascaderTree.getLeafNodes(); refreshCascaderV2Data(props.modelValue); } else { cascaderTree.updateTree([], props.lazy); leafNodes.value = []; panelInfo.value = void 0; lazyLoadState.value = {}; } }, { immediate: true, deep: true } ); vue.watch( () => props.modelValue, (newValue) => { if (!newValue) return; if (is.isArray(newValue)) { syncMultipleSelection(); refrashCheckStateByCapture(); return; } const node = cascaderTree.getNode(newValue); if (!node) return; updateSelectedValue(buildSelectedOption(node), true, node.fullPath); refrashCheckStateByCapture(); } ); vue.watch( () => cascaderV2Inject == null ? void 0 : cascaderV2Inject.isSelecting.value, (val) => { if (val) { if (props.lazy && cascaderTree.root.children.length === 0) { loadRoot(); } else { refreshCascaderV2Data(props.modelValue); } } } ); vue.watch( () => cascaderV2Inject == null ? void 0 : cascaderV2Inject.filterValue.value, (newVal, oldVal) => { if (oldVal && !newVal && isMultiple) { refreshCascaderV2Data(props.modelValue); } } ); const handleClick = (option) => { if (option.disabled) { return; } const node = cascaderTree.getNode(option.value); updateSelectedValue(option, true, node == null ? void 0 : node.fullPath); hidePanel(!isMultiple); }; return (_ctx, _cache) => { return vue.unref(isSelecting) ? (vue.openBlock(), vue.createElementBlock( "div", { key: 0, class: vue.normalizeClass(["o-cascader-v2-panel", [`o-cascader-v2-panel-${props.size}`]]), onMousedown: _cache[0] || (_cache[0] = vue.withModifiers(() => { }, ["prevent"])) }, [ vue.unref(isLoading) ? (vue.openBlock(), vue.createBlock(vue.unref(index$1.OScroller), { key: 0, class: "o-cascader-v2-panel-scroller", "wrap-class": "o-cascader-v2-panel-container", "show-type": "hover", size: "small", "disabled-x": "" }, { default: vue.withCtx(() => [ vue.createElementVNode("div", _hoisted_1, [ vue.createVNode(vue.unref(icons.IconLoading), { class: "o-rotating" }) ]) ]), _: 1 /* STABLE */ })) : props.filterable && vue.unref(filterValue) ? (vue.openBlock(), vue.createElementBlock( vue.Fragment, { key: 1 }, [ filteredOptions.value.length ? (vue.openBlock(), vue.createBlock(vue.unref(index$1.OScroller), { key: 0, class: "o-cascader-v2-panel-scroller", "wrap-class": "o-cascader-v2-panel-container", "show-type": "hover", size: "small", "disabled-x": "" }, { default: vue.withCtx(() => [ vue.createElementVNode( "ul", { class: vue.normalizeClass(["o-cascader-v2-options", { "o-cascader-v2-options-filterable": props.filterable }]) }, [ (vue.openBlock(true), vue.createElementBlock( vue.Fragment, null, vue.renderList(filteredOptions.value, (option) => { return vue.openBlock(), vue.createElementBlock("li", { key: option.value, class: vue.normalizeClass([{ "o-cascader-v2-option-selected": option.isActive, "o-cascader-v2-option-disabled": option.disabled }, "o-cascader-v2-option"]), onClick: ($event) => handleClick(option) }, [ vue.createVNode(OCascaderV2Label_vue_vue_type_script_setup_true_lang, { label: option.label, "label-parts": option.labelParts, value: option.value, multiple: vue.unref(isMultiple), "allow-select-any-node": vue.unref(allowSelectAnyNode), "is-leaf": true, disabled: option.disabled, "is-fully-selected": vue.unref(isMultiple) ? option.isActive : void 0, onSelect: ($event) => handleClick({ label: option.label, value: option.value }) }, null, 8, ["label", "label-parts", "value", "multiple", "allow-select-any-node", "disabled", "is-fully-selected", "onSelect"]) ], 10, _hoisted_2); }), 128 /* KEYED_FRAGMENT */ )) ], 2 /* CLASS */ ) ]), _: 1 /* STABLE */ })) : (vue.openBlock(), vue.createElementBlock("div", _hoisted_3, [ vue.createElementVNode( "span", null, vue.toDisplayString(vue.unref(t)("common.empty")), 1 /* TEXT */ ) ])) ], 64 /* STABLE_FRAGMENT */ )) : (vue.openBlock(true), vue.createElementBlock( vue.Fragment, { key: 2 }, vue.renderList(panelInfo.value, (columnInfo, index2) => { return vue.openBlock(), vue.createElementBlock( vue.Fragment, { key: index2 }, [ index2 > 0 ? (vue.openBlock(), vue.createBlock(vue.unref(index$2.ODivider), { key: 0, direction: "v", class: "o-cascader-v2-panel-divider" })) : vue.createCommentVNode("v-if", true), vue.createVNode( vue.unref(index$1.OScroller), { class: "o-cascader-v2-panel-scroller", "wrap-class": "o-cascader-v2-panel-container", "show-type": "hover", size: "small", "disabled-x": "" }, { default: vue.withCtx(() => [ vue.createElementVNode("ul", _hoisted_4, [ (vue.openBlock(true), vue.createElementBlock( vue.Fragment, null, vue.renderList(columnInfo, (option) => { return vue.openBlock(), vue.createElementBlock("li", { key: option.value, class: vue.normalizeClass([{ "o-cascader-v2-option-selected": option.isActive && (!option.isLeaf || !vue.unref(isMultiple)), "o-cascader-v2-option-disabled": option.disabled }, "o-cascader-v2-option"]), onClick: ($event) => onClick(option, columnInfo), onMouseenter: ($event) => onMouseenter(option, columnInfo) }, [ vue.createVNode(OCascaderV2Label_vue_vue_type_script_setup_true_lang, { label: option.label, value: option.value, multiple: vue.unref(isMultiple), "allow-select-any-node": vue.unref(allowSelectAnyNode), disabled: option.disabled, "is-leaf": option.isLeaf, indeterminate: !vue.unref(allowSelectAnyNode) && option.hasActiveChild, "is-fully-selected": !option.isLeaf && !vue.unref(allowSelectAnyNode) && vue.unref(isMultiple) ? isNodeFullySelected(option.value) : void 0, loading: props.lazy && lazyLoadState.value[String(option.value)] === "loading", onSelect: ($event) => onLabelSelect(option, columnInfo) }, null, 8, ["label", "value", "multiple", "allow-select-any-node", "disabled", "is-leaf", "indeterminate", "is-fully-selected", "loading", "onSelect"]) ], 42, _hoisted_5); }), 128 /* KEYED_FRAGMENT */ )) ]) ]), _: 2 /* DYNAMIC */ }, 1024 /* DYNAMIC_SLOTS */ ) ], 64 /* STABLE_FRAGMENT */ ); }), 128 /* KEYED_FRAGMENT */ )) ], 34 /* CLASS, NEED_HYDRATION */ )) : vue.createCommentVNode("v-if", true); }; } }); module.exports = _sfc_main;