hongluan-ui
Version:
Hongluan Component Library for Vue 3
1 lines • 12.9 kB
Source Map (JSON)
{"version":3,"file":"cascader2.mjs","sources":["../../../../../../packages/components/cascader/src/cascader.vue"],"sourcesContent":["<template>\n <hl-selector\n ref=\"hlSelector\"\n :size=\"cascaderSize\"\n :fill=\"cascaderFill\"\n :placeholder=\"placeholder\"\n :disabled=\"isDisabled\"\n :clearable=\"!filtering && clearable\"\n :filterable=\"filterable\"\n :collapse-tags=\"collapseTags\"\n :max-collapse-tags=\"maxCollapseTags\"\n :collapse-tags-tooltip=\"collapseTagsTooltip\"\n :tag-type=\"tagType\"\n :tag-effect=\"tagEffect\"\n :popper-class=\"popperClass + ' ' + namespace + '-popper'\"\n :block=\"block\"\n :multiple=\"props.multiple\"\n :fallback-placements=\"fallbackPlacements\"\n :placement=\"placement\"\n :popper-append-to-body=\"popperAppendToBody\"\n :teleported=\"teleported\"\n :popper-offset=\"popperOffset\"\n :persistent=\"persistent\"\n @focus=\"e => $emit('focus', e)\"\n @blur=\"e => $emit('blur', e)\"\n @resize=\"resizePanel\"\n @keyboard-down=\"focusFirstNode\"\n @input=\"handleInput\"\n @clear=\"handleClear\"\n @remove-tag=\"deleteTag\"\n @visible-change=\"e => $emit('visible-change', e)\"\n @after-leave=\"hideSuggestionPanel\"\n >\n <template #default>\n <hl-cascader-panel\n v-show=\"!filtering\"\n ref=\"panel\"\n v-model=\"checkedValue\"\n :options=\"options\"\n :props=\"props\"\n :border=\"false\"\n :render-label=\"$slots.default\"\n @expand-change=\"handleExpandChange\"\n @close=\"togglePopperVisible(false)\"\n />\n <hl-scrollbar\n v-if=\"filterable\"\n v-show=\"filtering\"\n ref=\"suggestionPanel\"\n tag=\"ul\"\n :class=\"[namespace + '-suggestion-panel']\"\n view-class=\"cascader-suggestion-list\"\n @keydown=\"handleSuggestionKeyDown\"\n >\n <template v-if=\"suggestions.length\">\n <li\n v-for=\"item in suggestions\"\n :key=\"item.uid\"\n :class=\"[\n 'cascader-suggestion-item',\n item.checked && 'is-active'\n ]\"\n :tabindex=\"-1\"\n @click=\"handleSuggestionClick(item)\"\n >\n <span>{{ item.text }}</span>\n <i v-if=\"item.checked\" :class=\"['system-icon checked cascader-item-prefix']\"></i>\n </li>\n </template>\n <slot v-else name=\"empty\">\n <li class=\"cascader-empty-text\">{{ t('hl.cascader.noMatch') }}</li>\n </slot>\n </hl-scrollbar>\n </template>\n <template #tag=\"{ tag }\">\n <template v-if=\"tag.key==='-1'\">{{ tag.text }}</template>\n <template v-else>{{ tag.text.calcText(showAllLevels, separator) }}</template>\n </template>\n <template #collapse-tag=\"{ tag }\">\n {{ tag.text.calcText(showAllLevels, separator) }}\n </template>\n </hl-selector>\n</template>\n\n<script lang='ts'>\nimport { computed, defineComponent, ref, watch } from 'vue'\nimport { cloneDeep, debounce } from 'lodash-unified'\nimport { isPromise } from '@vue/shared'\nimport HlCascaderPanel from '@hongluan-ui/components/cascader-panel'\nimport HlScrollbar from '@hongluan-ui/components/scrollbar'\nimport HlSelector from '@hongluan-ui/components/selector'\nimport { debugWarn, focusNode, getSibling } from '@hongluan-ui/utils'\nimport { EVENT_CODE, UPDATE_MODEL_EVENT, CHANGE_EVENT } from '@hongluan-ui/constants'\nimport { useEmptyValues, useLocale, useConsistentProp, useNamespace, useFormItem } from '@hongluan-ui/hooks'\nimport { FormItemEvents } from '@hongluan-ui/tokens'\nimport { cascaderProps } from './cascader'\n\nimport type { ComputedRef, Ref } from 'vue'\nimport type { CascaderValue, CascaderNode, Tag } from '@hongluan-ui/components/cascader-panel'\n\nexport default defineComponent({\n name: 'Cascader',\n components: {\n HlCascaderPanel,\n HlScrollbar,\n HlSelector,\n },\n props: cascaderProps,\n emits: [\n UPDATE_MODEL_EVENT,\n CHANGE_EVENT,\n 'focus',\n 'blur',\n 'clear',\n 'visible-change',\n 'expand-change',\n 'remove-tag',\n ],\n setup(props, { emit }) {\n const { namespace } = useNamespace('cascader')\n const { t } = useLocale()\n\n const { formItem } = useFormItem()\n const { valueOnClear } = useEmptyValues(props)\n\n const hlSelector = ref(null)\n const panel = ref(null)\n const suggestionPanel = ref(null)\n const filtering = ref(false)\n const searchKeyword = ref('')\n const suggestions: Ref<CascaderNode[]> = ref([])\n\n const multiple = computed(() => !!props.props.multiple)\n const checkedNodes: ComputedRef<CascaderNode[]> = computed(() => panel.value?.checkedNodes || [])\n const { size: cascaderSize, disabled: isDisabled, fill: cascaderFill } = useConsistentProp()\n\n const checkedValue = computed<CascaderValue>({\n get () {\n return cloneDeep(props.modelValue) as CascaderValue\n },\n set (val) {\n // https://github.com/element-plus/element-plus/issues/17647\n const value = val ?? valueOnClear.value\n emit(UPDATE_MODEL_EVENT, value)\n emit(CHANGE_EVENT, value)\n if (props.validateEvent) {\n formItem?.validate?.(FormItemEvents.change).catch(err => debugWarn(err))\n }\n },\n })\n const popperPaneRef = computed(() => {\n return hlSelector.value?.popperPaneRef\n })\n\n const togglePopperVisible = (visible?: boolean) => {\n hlSelector.value.togglePopperVisible(visible)\n }\n\n const updatePopperPosition = () => {\n hlSelector.value.updatePopperPosition()\n }\n\n const hideSuggestionPanel = () => {\n filtering.value = false\n }\n\n const deleteTag = (tag: { text: CascaderNode; }) => {\n const node = tag.text\n node.doCheck(false)\n panel.value?.calculateCheckedValue()\n emit('remove-tag', node.valueByOption)\n }\n\n const calculateSuggestions = () => {\n const { filterMethod, showAllLevels, separator } = props\n const res = panel.value.getFlattedNodes(!props.props.checkStrictly)\n .filter(node => {\n if (node.isDisabled) return false\n node.calcText(showAllLevels, separator)\n return filterMethod(node, searchKeyword.value)\n })\n\n if (multiple.value) {\n hlSelector.value.updateTags((tag: Tag) => {\n tag.hitState = false\n })\n }\n\n filtering.value = true\n suggestions.value = res\n updatePopperPosition()\n }\n\n const handleSuggestionKeyDown = (e: KeyboardEvent) => {\n const target = e.target as HTMLElement\n const { code } = e\n\n switch (code) {\n case EVENT_CODE.up:\n case EVENT_CODE.down: {\n const distance = code === EVENT_CODE.up ? -1 : 1\n focusNode(\n getSibling(\n target,\n distance,\n '.cascader-suggestion-item[tabindex=\"-1\"]',\n ) as HTMLElement,\n )\n break\n }\n case EVENT_CODE.enter:\n target.click()\n break\n }\n }\n\n const focusFirstNode = () => {\n let firstNode = null\n\n if (filtering.value && suggestionPanel.value) {\n firstNode = suggestionPanel.value.$el.querySelector('.cascader-suggestion-item')\n } else {\n firstNode = panel.value?.$el.querySelector('.cascader-node[tabindex=\"-1\"]')\n }\n\n if (firstNode) {\n firstNode.focus()\n !filtering.value && firstNode.click()\n }\n }\n\n const resizePanel = (inputInner: HTMLElement) => {\n const suggestionPanelEl = suggestionPanel.value?.$el\n\n if (suggestionPanelEl) {\n const suggestionList = suggestionPanelEl.querySelector('.cascader-suggestion-list')\n suggestionList.style.minWidth = inputInner.offsetWidth + 'px'\n }\n }\n\n const getCheckedNodes = (leafOnly: boolean) => {\n return panel.value?.getCheckedNodes(leafOnly)\n }\n\n const handleExpandChange = (value: CascaderValue) => {\n updatePopperPosition()\n emit('expand-change', value)\n }\n\n const handleClear = () => {\n panel.value?.clearCheckedNodes()\n emit('clear')\n }\n\n const handleSuggestionClick = (node: CascaderNode) => {\n const { checked } = node\n\n if (multiple.value) {\n panel.value?.handleCheckChange(node, !checked, false)\n } else {\n !checked && panel.value?.handleCheckChange(node, true, false)\n togglePopperVisible(false)\n }\n }\n\n const handleFilter = debounce(() => {\n const { value } = searchKeyword\n if (!value) return\n\n const passed = props.beforeFilter(value)\n\n if (isPromise(passed)) {\n passed.then(calculateSuggestions).catch(() => { /* prevent log error */ })\n } else if (passed !== false) {\n calculateSuggestions()\n } else {\n hideSuggestionPanel()\n }\n }, props.debounce)\n\n const handleInput = (val: string) => {\n searchKeyword.value = val\n val ? handleFilter() : hideSuggestionPanel()\n }\n\n watch(filtering, updatePopperPosition)\n watch(checkedNodes, nodes => {\n if (multiple.value) {\n hlSelector.value.setValue(nodes || [])\n } else {\n const { showAllLevels, separator } = props\n hlSelector.value.setValue(nodes.length ? nodes[0].calcText(showAllLevels, separator) : '')\n }\n })\n\n return {\n namespace,\n hlSelector,\n popperPaneRef,\n panel,\n suggestionPanel,\n filtering,\n checkedValue,\n suggestions,\n isDisabled,\n cascaderSize,\n cascaderFill,\n multiple,\n t,\n /**\n * @description toggle the visible of popper\n */\n togglePopperVisible,\n hideSuggestionPanel,\n resizePanel,\n deleteTag,\n focusFirstNode,\n /**\n * @description get an array of currently selected node,(leafOnly) whether only return the leaf checked nodes, default is `false`\n */\n getCheckedNodes,\n handleExpandChange,\n handleClear,\n handleSuggestionClick,\n handleSuggestionKeyDown,\n handleInput,\n }\n },\n})\n</script>\n"],"names":["_withDirectives"],"mappings":"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"}