@extclp/vexip-ui
Version:
A Vue 3 UI library, Highly customizability, full TypeScript, performance pretty good
1 lines • 83.2 kB
Source Map (JSON)
{"version":3,"file":"select.vue2.mjs","sources":["../../../components/select/select.vue"],"sourcesContent":["<script setup lang=\"ts\">\r\nimport { Icon } from '@/components/icon'\r\nimport { Input } from '@/components/input'\r\nimport { NativeScroll } from '@/components/native-scroll'\r\nimport { Option } from '@/components/option'\r\nimport { Overflow } from '@/components/overflow'\r\nimport { Popper } from '@/components/popper'\r\nimport { Renderer } from '@/components/renderer'\r\nimport { Tag } from '@/components/tag'\r\nimport { Tooltip } from '@/components/tooltip'\r\nimport { VirtualList } from '@/components/virtual-list'\r\nimport { useFieldStore } from '@/components/form'\r\n\r\nimport { computed, nextTick, onMounted, reactive, ref, toRef, watch, watchEffect } from 'vue'\r\n\r\nimport {\r\n placementWhileList,\r\n useClickOutside,\r\n useHover,\r\n useModifier,\r\n useMounted,\r\n usePopper,\r\n} from '@vexip-ui/hooks'\r\nimport {\r\n createIconProp,\r\n createSizeProp,\r\n createStateProp,\r\n emitEvent,\r\n useIcons,\r\n useLocale,\r\n useNameHelper,\r\n useProps,\r\n} from '@vexip-ui/config'\r\nimport {\r\n decide,\r\n getLast,\r\n getRangeWidth,\r\n isNull,\r\n removeArrayItem,\r\n toAttrValue,\r\n} from '@vexip-ui/utils'\r\nimport { selectProps } from './props'\r\nimport { defaultKeyConfig } from './symbol'\r\n\r\nimport type { InputExposed } from '@/components/input'\r\nimport type { PopperExposed } from '@/components/popper'\r\nimport type { TooltipExposed } from '@/components/tooltip'\r\nimport type { VirtualListExposed } from '@/components/virtual-list'\r\nimport type {\r\n ChangeEvent,\r\n SelectBaseValue,\r\n SelectEvent,\r\n SelectOptionState,\r\n SelectSlots,\r\n SelectValue,\r\n} from './symbol'\r\n\r\nfunction isSameValue(newValue: SelectValue, oldValue: SelectValue) {\r\n const isNewArray = Array.isArray(newValue)\r\n const isOldArray = Array.isArray(oldValue)\r\n\r\n if (isNewArray !== isOldArray) return false\r\n\r\n if (isNewArray && isOldArray) {\r\n if (newValue.length !== oldValue.length) return false\r\n\r\n for (let i = 0, len = newValue.length; i < len; ++i) {\r\n if (newValue[i] !== oldValue[i]) return false\r\n }\r\n\r\n return true\r\n }\r\n\r\n if (isNull(newValue)) return isNull(oldValue)\r\n\r\n return newValue === oldValue\r\n}\r\n\r\ndefineOptions({ name: 'Select' })\r\n\r\nconst {\r\n idFor,\r\n labelId,\r\n state,\r\n disabled,\r\n loading,\r\n size,\r\n validateField,\r\n clearField,\r\n getFieldValue,\r\n setFieldValue,\r\n} = useFieldStore<SelectValue>(focus)\r\n\r\nconst nh = useNameHelper('select')\r\n\r\nconst _props = defineProps(selectProps)\r\nconst props = useProps('select', _props, {\r\n size: createSizeProp(size),\r\n state: createStateProp(state),\r\n locale: null,\r\n visible: {\r\n default: false,\r\n static: true,\r\n },\r\n options: {\r\n default: () => [],\r\n static: true,\r\n },\r\n disabled: () => disabled.value,\r\n transitionName: () => nh.ns('drop'),\r\n outsideClose: true,\r\n placeholder: null,\r\n prefix: createIconProp(),\r\n prefixColor: '',\r\n suffix: createIconProp(),\r\n suffixColor: '',\r\n noSuffix: false,\r\n value: {\r\n default: () => getFieldValue()!,\r\n static: true,\r\n },\r\n multiple: false,\r\n clearable: false,\r\n maxListHeight: 300,\r\n listClass: null,\r\n placement: {\r\n default: 'bottom',\r\n validator: value => placementWhileList.includes(value),\r\n },\r\n transfer: false,\r\n optionCheck: false,\r\n emptyText: null,\r\n staticSuffix: false,\r\n loading: () => loading.value,\r\n loadingIcon: createIconProp(),\r\n loadingLock: false,\r\n loadingEffect: null,\r\n keyConfig: () => ({}),\r\n filter: false,\r\n ignoreCase: false,\r\n creatable: false,\r\n transparent: false,\r\n maxTagCount: 0,\r\n noRestTip: false,\r\n tagType: null,\r\n noPreview: false,\r\n remote: false,\r\n fitPopper: false,\r\n name: {\r\n default: '',\r\n static: true,\r\n },\r\n popperAlive: null,\r\n countLimit: 0,\r\n filterPosition: 'in-control',\r\n slots: () => ({}),\r\n shift: true,\r\n})\r\n\r\nconst emit = defineEmits(['update:value', 'update:visible', 'update:label'])\r\n\r\nconst slots = defineSlots<SelectSlots>()\r\n\r\nconst locale = useLocale('select', toRef(props, 'locale'))\r\nconst icons = useIcons()\r\n\r\nconst currentVisible = ref(props.visible)\r\nconst currentLabels = ref<string[]>([])\r\nconst currentValues = ref<SelectBaseValue[]>([])\r\nconst currentIndex = ref(-1)\r\nconst placement = toRef(props, 'placement')\r\nconst transfer = toRef(props, 'transfer')\r\n// const listHeight = ref<string>()\r\nconst baseOptions = ref<SelectOptionState[]>([])\r\nconst currentFilter = ref('')\r\nconst anchorWidth = ref(0)\r\nconst userOptions = ref<SelectOptionState[]>([])\r\nconst restTagCount = ref(0)\r\nconst restTipShow = ref(false)\r\nconst composing = ref(false)\r\n\r\nconst { isMounted } = useMounted()\r\n\r\nconst dynamicOption = reactive<SelectOptionState>({\r\n disabled: false,\r\n divided: false,\r\n title: '',\r\n value: '',\r\n label: '',\r\n group: false,\r\n depth: 0,\r\n parent: null,\r\n hidden: false,\r\n hitting: true,\r\n data: '',\r\n})\r\n\r\nconst optionValues = reactive(new Set<string | number>())\r\nconst hittingOption = ref<SelectOptionState>()\r\nconst optionStates = computed(() => userOptions.value.concat(baseOptions.value))\r\nconst visibleOptions = computed(() => optionStates.value.filter(state => !state.hidden))\r\n\r\nconst keyConfig = computed(() => ({ ...defaultKeyConfig, ...props.keyConfig }))\r\n\r\nconst wrapper = useClickOutside(handleClickOutside)\r\nconst nativeInput = ref<HTMLInputElement>()\r\nconst filterInput = ref<InputExposed>()\r\nconst device = ref<HTMLElement>()\r\nconst virtualList = ref<VirtualListExposed>()\r\nconst popper = ref<PopperExposed>()\r\nconst restTip = ref<TooltipExposed>()\r\n\r\nconst input = computed(() => filterInput.value?.input ?? nativeInput.value)\r\n\r\nconst { reference, transferTo, updatePopper } = usePopper({\r\n placement,\r\n transfer,\r\n wrapper,\r\n popper: computed(() => popper.value?.wrapper),\r\n isDrop: true,\r\n shift: toRef(props, 'shift'),\r\n})\r\nconst { isHover } = useHover(reference)\r\n\r\nconst cachedSelected = reactive(new Map<SelectBaseValue, SelectOptionState>())\r\nconst optionValueMap = ref(new Map<SelectBaseValue, SelectOptionState>())\r\n\r\nlet emittedValue: typeof props.value | null = props.value\r\n\r\nconst updateTrigger = ref(0)\r\n\r\nwatchEffect(() => {\r\n /* eslint-disable @typescript-eslint/no-unused-expressions */\r\n props.keyConfig.value\r\n props.keyConfig.label\r\n props.keyConfig.disabled\r\n props.keyConfig.divided\r\n props.keyConfig.title\r\n props.keyConfig.group\r\n props.keyConfig.children\r\n\r\n // If we only read the `props.options`, when user use Array native methods to\r\n // change options, Vue will not trigger the watch callback\r\n for (let i = 0, len = props.options.length; i < len; ++i) {\r\n props.options[i]\r\n }\r\n /* eslint-enable */\r\n\r\n updateTrigger.value++\r\n})\r\n\r\nwatch(updateTrigger, initOptionState, { immediate: true })\r\n\r\nfunction initOptionState() {\r\n const {\r\n value: valueKey,\r\n label: labelKey,\r\n disabled: disabledKey,\r\n divided: dividedKey,\r\n title: titleKey,\r\n group: groupKey,\r\n children: childrenKey,\r\n } = keyConfig.value\r\n const oldMap = optionValueMap.value\r\n const map = new Map<string | number, SelectOptionState>()\r\n const states: SelectOptionState[] = []\r\n const loop = props.options\r\n .map(option => ({ option, depth: 0, parent: null as SelectOptionState | null }))\r\n .reverse()\r\n\r\n optionValues.clear()\r\n\r\n for (const option of userOptions.value) {\r\n map.set(option.value, option)\r\n optionValues.add(option.value)\r\n }\r\n\r\n while (loop.length) {\r\n const { option, depth, parent } = loop.pop()!\r\n const rawOption = typeof option === 'string' ? { [valueKey]: option } : option\r\n const group = !!rawOption[groupKey]\r\n const value = rawOption[valueKey]\r\n\r\n if (!group && isNull(value)) continue\r\n\r\n const label = rawOption[labelKey] || String(value)\r\n const {\r\n [disabledKey]: disabled = false,\r\n [dividedKey]: divided = false,\r\n [titleKey]: title = '',\r\n [childrenKey]: children = null,\r\n } = rawOption\r\n const oldState = oldMap.get(rawOption.value)\r\n const optionState = reactive({\r\n disabled,\r\n divided,\r\n title,\r\n value,\r\n label,\r\n group,\r\n depth,\r\n parent,\r\n hidden: oldState?.hidden ?? false,\r\n hitting: oldState?.hitting ?? false,\r\n data: option,\r\n }) as SelectOptionState\r\n\r\n states.push(optionState)\r\n\r\n if (!group) {\r\n map.set(value, optionState)\r\n optionValues.add(String(value))\r\n }\r\n\r\n if (Array.isArray(children) && children.length) {\r\n loop.push(\r\n ...children\r\n .map(child => {\r\n return { option: child, depth: depth + 1, parent: optionState }\r\n })\r\n .reverse(),\r\n )\r\n }\r\n }\r\n\r\n optionValueMap.value = map\r\n baseOptions.value = states\r\n\r\n initValueAndLabel(emittedValue)\r\n}\r\n\r\nuseModifier({\r\n target: wrapper,\r\n passive: false,\r\n onKeyDown: (event, modifier) => {\r\n if (composing.value) {\r\n event.stopPropagation()\r\n return\r\n }\r\n\r\n if (!currentVisible.value) {\r\n if (modifier.space || modifier.enter) {\r\n event.preventDefault()\r\n event.stopPropagation()\r\n toggleVisible()\r\n }\r\n\r\n return\r\n }\r\n\r\n if (modifier.tab || modifier.escape) {\r\n setVisible(false)\r\n modifier.resetAll()\r\n\r\n return\r\n }\r\n\r\n decide(\r\n [\r\n [\r\n () => modifier.up || modifier.down,\r\n () => {\r\n const options = visibleOptions.value\r\n const length = options.length\r\n\r\n if (!length) return\r\n\r\n const step = modifier.down ? 1 : -1\r\n\r\n let index = (Math.max(-1, currentIndex.value + step) + length) % length\r\n let option = options[index]\r\n\r\n for (let i = 0; (option.disabled || option.group) && i < length; ++i) {\r\n index += step\r\n index = (index + length) % length\r\n option = options[index]\r\n }\r\n\r\n updateHitting(index)\r\n },\r\n ],\r\n [\r\n () => modifier.enter || (!props.filter && modifier.space),\r\n () => {\r\n if (currentIndex.value >= 0) {\r\n handleSelect(totalOptions.value[currentIndex.value])\r\n } else if (showDynamic.value) {\r\n handleSelect(dynamicOption)\r\n } else {\r\n setVisible(false)\r\n }\r\n },\r\n ],\r\n ],\r\n {\r\n beforeMatchAny: () => {\r\n event.preventDefault()\r\n event.stopPropagation()\r\n },\r\n afterMatchAny: modifier.resetAll,\r\n },\r\n )\r\n },\r\n})\r\n\r\nconst className = computed(() => {\r\n return {\r\n [nh.b()]: true,\r\n [nh.ns('input-vars')]: true,\r\n [nh.bs('vars')]: true,\r\n [nh.bm('inherit')]: props.inherit,\r\n [nh.bm('multiple')]: props.multiple,\r\n [nh.bm('filter')]: props.filter,\r\n [nh.bm('responsive')]: props.multiple && props.maxTagCount <= 0,\r\n [nh.bm('disabled')]: props.disabled,\r\n }\r\n})\r\nconst readonly = computed(() => props.loading && props.loadingLock)\r\nconst selectorClass = computed(() => {\r\n const baseCls = nh.be('selector')\r\n\r\n return {\r\n [baseCls]: true,\r\n [`${baseCls}--focused`]: !props.disabled && currentVisible.value,\r\n [`${baseCls}--disabled`]: props.disabled,\r\n [`${baseCls}--readonly`]: readonly.value,\r\n [`${baseCls}--loading`]: props.loading,\r\n [`${baseCls}--${props.size}`]: props.size !== 'default',\r\n [`${baseCls}--${props.state}`]: props.state !== 'default',\r\n [`${baseCls}--has-prefix`]: hasPrefix.value,\r\n [`${baseCls}--has-suffix`]: !props.noSuffix,\r\n [`${baseCls}--transparent`]: props.transparent,\r\n }\r\n})\r\nconst hasValue = computed(\r\n () => !isNull(currentValues.value[0]) && (props.multiple || currentValues.value[0] !== ''),\r\n)\r\nconst hasPrefix = computed(() => !!(slots.prefix || props.prefix || props.slots.prefix))\r\nconst showDynamic = computed(() => {\r\n return !!(\r\n props.filter &&\r\n props.creatable &&\r\n dynamicOption.value &&\r\n !optionValues.has(dynamicOption.value)\r\n )\r\n})\r\nconst totalOptions = computed(() => {\r\n return showDynamic.value ? [dynamicOption].concat(visibleOptions.value) : visibleOptions.value\r\n})\r\nconst normalOptions = computed(() => optionStates.value.filter(option => !option.group))\r\nconst optionParentMap = computed(() => {\r\n const options = normalOptions.value\r\n const map = new Map<string | number, SelectOptionState>()\r\n\r\n for (let i = 0, len = options.length; i < len; ++i) {\r\n const option = options[i]\r\n\r\n if (option.parent) {\r\n map.set(option.value, option.parent)\r\n }\r\n }\r\n\r\n return map\r\n})\r\nconst showClear = computed(() => {\r\n return !props.disabled && !readonly.value && props.clearable && isHover.value && hasValue.value\r\n})\r\nconst previewOption = computed(() => {\r\n return !props.noPreview && currentVisible.value ? hittingOption.value : undefined\r\n})\r\nconst limited = computed(() => {\r\n return props.multiple && props.countLimit > 0 && currentValues.value.length >= props.countLimit\r\n})\r\nconst showPlaceholder = computed(() => {\r\n if (props.filterPosition !== 'in-control') {\r\n return (\r\n !hasValue.value && !previewOption.value && !!(props.placeholder ?? locale.value.placeholder)\r\n )\r\n }\r\n\r\n // 采用反推,出现下列情况时不显示:\r\n // 1. 开始组合(如输入了任意拼音)\r\n // 2. 有值且 未开预览/多选模式/未打开列表\r\n // 3. 没有预览选项且没有合法的占位值\r\n // 4. 打开列表且输入了过滤值\r\n return (\r\n !composing.value &&\r\n !(hasValue.value && (props.noPreview || props.multiple || !currentVisible.value)) &&\r\n !(!previewOption.value && !(props.placeholder ?? locale.value.placeholder)) &&\r\n !(currentVisible.value && currentFilter.value)\r\n )\r\n})\r\n\r\nfunction getOptionFromMap(value?: SelectBaseValue | null) {\r\n if (isNull(value)) return null\r\n\r\n return optionValueMap.value.get(value) ?? cachedSelected.get(value) ?? null\r\n}\r\n\r\nfunction fitPopperWidth() {\r\n requestAnimationFrame(() => {\r\n updatePopper()\r\n\r\n if (wrapper.value && popper.value?.wrapper) {\r\n if (typeof props.fitPopper === 'number') {\r\n popper.value.wrapper.style.width = `${props.fitPopper}px`\r\n } else if (props.fitPopper) {\r\n popper.value.wrapper.style.width = `${wrapper.value.offsetWidth}px`\r\n } else {\r\n popper.value.wrapper.style.minWidth = `${wrapper.value.offsetWidth}px`\r\n }\r\n }\r\n })\r\n}\r\n\r\nwatch(\r\n () => props.visible,\r\n value => {\r\n currentVisible.value = value\r\n },\r\n)\r\nwatch(currentVisible, value => {\r\n if (value) {\r\n restTipShow.value = false\r\n initHittingIndex()\r\n fitPopperWidth()\r\n }\r\n\r\n if (props.filterPosition !== 'in-control') {\r\n requestAnimationFrame(syncInputValue)\r\n } else {\r\n syncInputValue()\r\n }\r\n})\r\nwatch(\r\n () => props.value,\r\n value => {\r\n if (!emittedValue || !isSameValue(value, emittedValue)) {\r\n emittedValue = value\r\n initValueAndLabel(value)\r\n syncInputValue()\r\n }\r\n },\r\n)\r\nwatch(\r\n () => props.disabled,\r\n value => {\r\n if (value) {\r\n setVisible(false)\r\n }\r\n },\r\n)\r\nwatch(readonly, value => {\r\n if (value) {\r\n setVisible(false)\r\n }\r\n})\r\nwatch(currentFilter, value => {\r\n dynamicOption.value = value\r\n dynamicOption.label = value\r\n dynamicOption.data = value\r\n\r\n filterOptions(value)\r\n})\r\n\r\ndefineExpose({\r\n idFor,\r\n labelId,\r\n currentVisible,\r\n currentValues,\r\n currentLabels,\r\n optionStates,\r\n isHover,\r\n currentFilter,\r\n composing,\r\n visibleOptions,\r\n totalOptions,\r\n\r\n wrapper,\r\n reference,\r\n popper,\r\n input,\r\n device,\r\n virtualList,\r\n restTip,\r\n\r\n updatePopper,\r\n isSelected,\r\n getOptionFromMap,\r\n updateHitting,\r\n handleClear,\r\n focus,\r\n blur: () => {\r\n input.value?.blur()\r\n reference.value?.blur()\r\n },\r\n})\r\n\r\nonMounted(() => {\r\n syncInputValue()\r\n\r\n if (props.visible) {\r\n restTipShow.value = false\r\n initHittingIndex()\r\n fitPopperWidth()\r\n }\r\n})\r\n\r\nfunction initValueAndLabel(value: SelectValue | null) {\r\n if (isNull(value)) {\r\n currentValues.value = []\r\n currentLabels.value = []\r\n return\r\n }\r\n\r\n const normalizedValue = !Array.isArray(value) ? [value] : value\r\n\r\n const valueSet = new Set(normalizedValue)\r\n const selectedValues: SelectBaseValue[] = []\r\n const selectedLabels: string[] = []\r\n\r\n valueSet.forEach(value => {\r\n let option = getOptionFromMap(value)\r\n\r\n if (option) {\r\n selectedValues.push(option.value)\r\n selectedLabels.push(option.label)\r\n\r\n if (!cachedSelected.has(option.value)) {\r\n cachedSelected.set(option.value, option)\r\n }\r\n } else if (props.remote) {\r\n option = reactive({\r\n value,\r\n disabled: false,\r\n divided: false,\r\n title: '',\r\n label: String(value),\r\n group: false,\r\n depth: -1,\r\n parent: null,\r\n hidden: true,\r\n hitting: false,\r\n data: value,\r\n }) as SelectOptionState\r\n\r\n cachedSelected.set(value, option)\r\n selectedValues.push(value)\r\n selectedLabels.push(option.label)\r\n }\r\n })\r\n\r\n for (const cachedValue of Array.from(cachedSelected.keys())) {\r\n if (!valueSet.has(cachedValue)) {\r\n cachedSelected.delete(cachedValue)\r\n }\r\n }\r\n\r\n currentValues.value = selectedValues\r\n currentLabels.value = selectedLabels\r\n\r\n initHittingIndex()\r\n filterOptions(currentFilter.value)\r\n}\r\n\r\nfunction initHittingIndex() {\r\n const value = currentValues.value[0]\r\n\r\n if (isNull(value)) {\r\n updateHitting(-1)\r\n } else {\r\n if (!isMounted.value) return\r\n\r\n updateHitting(visibleOptions.value.findIndex(option => option.value === value))\r\n }\r\n}\r\n\r\nfunction setVisible(visible: boolean) {\r\n if (currentVisible.value === visible) return\r\n\r\n currentVisible.value = visible\r\n\r\n emit('update:visible', visible)\r\n emitEvent(props.onToggle, visible)\r\n}\r\n\r\nfunction updateHitting(hitting: number, ensureInView = true) {\r\n currentIndex.value = hitting\r\n hittingOption.value = undefined\r\n\r\n let index = -1\r\n\r\n optionStates.value.forEach(option => {\r\n if (!option.hidden) {\r\n index += 1\r\n option.hitting = hitting === index\r\n\r\n if (option.hitting) {\r\n hittingOption.value = option\r\n }\r\n } else {\r\n option.hitting = false\r\n }\r\n })\r\n\r\n if (ensureInView && currentVisible.value && virtualList.value) {\r\n virtualList.value.ensureIndexInView(hitting)\r\n }\r\n}\r\n\r\nfunction isSelected(option: SelectOptionState) {\r\n if (props.multiple) {\r\n return currentValues.value.includes(option.value)\r\n }\r\n\r\n return currentValues.value[0] === option.value\r\n}\r\n\r\nfunction filterOptions(inputValue: string) {\r\n const filter = props.filter\r\n\r\n if (!filter || props.remote) return\r\n\r\n if (!inputValue) {\r\n optionStates.value.forEach(state => {\r\n state.hidden = false\r\n })\r\n } else {\r\n optionStates.value.forEach(state => {\r\n state.hidden = true\r\n })\r\n\r\n if (typeof filter === 'function') {\r\n normalOptions.value.forEach(state => {\r\n state.hidden = !filter(inputValue, state)\r\n })\r\n } else {\r\n if (props.ignoreCase) {\r\n const ignoreCaseValue = inputValue.toString().toLocaleLowerCase()\r\n\r\n normalOptions.value.forEach(state => {\r\n state.hidden = !state.label?.toString().toLocaleLowerCase().includes(ignoreCaseValue)\r\n })\r\n } else {\r\n normalOptions.value.forEach(state => {\r\n state.hidden = !state.label?.toString().includes(inputValue?.toString())\r\n })\r\n }\r\n }\r\n\r\n const parentMap = optionParentMap.value\r\n\r\n normalOptions.value.forEach(option => {\r\n if (!option.hidden && option.parent) {\r\n let parent = parentMap.get(option.value) || null\r\n\r\n while (parent && parent.hidden) {\r\n parent.hidden = false\r\n parent = parent.parent\r\n }\r\n }\r\n })\r\n }\r\n\r\n updateHitting(currentIndex.value)\r\n}\r\n\r\nfunction handleTagClose(value?: SelectBaseValue | null) {\r\n if (props.disabled || readonly.value) return\r\n\r\n !isNull(value) && handleSelect(getOptionFromMap(value))\r\n}\r\n\r\nfunction handleRestTagClose(value?: SelectBaseValue | null) {\r\n handleTagClose(value)\r\n\r\n if (restTipShow.value) {\r\n restTip.value?.updatePopper()\r\n }\r\n}\r\n\r\nfunction handleSelect(option?: SelectOptionState | null) {\r\n if (!option) return\r\n\r\n const selected = isSelected(option)\r\n const value = option.value\r\n\r\n if (selected) {\r\n if (userOptions.value.find(item => item.value === value)) {\r\n removeArrayItem(userOptions.value, item => item.value === value)\r\n optionValueMap.value.delete(value)\r\n }\r\n\r\n cachedSelected.delete(value)\r\n } else {\r\n if (!props.multiple) {\r\n userOptions.value.length = 0\r\n }\r\n\r\n if (limited.value) return\r\n\r\n if (dynamicOption.value && value === dynamicOption.value) {\r\n const newOption = { ...dynamicOption }\r\n\r\n userOptions.value.push(newOption)\r\n optionValueMap.value.set(value, newOption)\r\n }\r\n\r\n cachedSelected.set(option.value, option)\r\n }\r\n\r\n emitEvent(\r\n props[props.multiple && selected ? 'onCancel' : 'onSelect'] as SelectEvent,\r\n value,\r\n option.data,\r\n )\r\n handleChange(option)\r\n\r\n if (props.multiple) {\r\n if (props.filterPosition === 'in-control') {\r\n currentFilter.value = ''\r\n syncInputValue()\r\n }\r\n\r\n requestAnimationFrame(updatePopper)\r\n } else {\r\n setVisible(false)\r\n }\r\n\r\n anchorWidth.value = 0\r\n}\r\n\r\nfunction handleChange(option: SelectOptionState) {\r\n if (props.multiple) {\r\n if (isSelected(option)) {\r\n const index = currentValues.value.findIndex(v => v === option.value)\r\n\r\n if (~index) {\r\n currentValues.value.splice(index, 1)\r\n currentLabels.value.splice(index, 1)\r\n }\r\n } else {\r\n currentValues.value.push(option.value)\r\n currentLabels.value.push(option.label)\r\n }\r\n\r\n emittedValue = Array.from(currentValues.value)\r\n\r\n emit('update:value', emittedValue)\r\n emit('update:label', currentLabels.value)\r\n setFieldValue(emittedValue)\r\n emitEvent(\r\n props.onChange as ChangeEvent,\r\n emittedValue,\r\n emittedValue.map(value => getOptionFromMap(value)?.data ?? value),\r\n )\r\n validateField()\r\n } else {\r\n const prevValue = currentValues.value[0]\r\n\r\n currentValues.value.length = 0\r\n currentLabels.value.length = 0\r\n currentValues.value.push(option.value)\r\n currentLabels.value.push(option.label)\r\n\r\n if (prevValue !== option.value) {\r\n emittedValue = option.value\r\n\r\n emit('update:value', emittedValue)\r\n emit('update:label', currentLabels.value[0])\r\n setFieldValue(emittedValue)\r\n emitEvent(props.onChange as ChangeEvent, emittedValue, option.data)\r\n validateField()\r\n }\r\n }\r\n}\r\n\r\nfunction toggleVisible() {\r\n if (props.disabled || readonly.value) return\r\n\r\n setVisible(!currentVisible.value)\r\n}\r\n\r\nfunction handleClickOutside() {\r\n restTipShow.value = false\r\n emitEvent(props.onClickOutside)\r\n\r\n if (props.outsideClose && currentVisible.value) {\r\n setVisible(false)\r\n emitEvent(props.onOutsideClose)\r\n }\r\n}\r\n\r\nfunction handleClear() {\r\n if (props.disabled || readonly.value) return\r\n\r\n if (props.clearable) {\r\n for (const option of userOptions.value) {\r\n optionValueMap.value.delete(option.value)\r\n }\r\n\r\n cachedSelected.clear()\r\n\r\n userOptions.value.length = 0\r\n currentValues.value.length = 0\r\n currentLabels.value.length = 0\r\n restTipShow.value = false\r\n\r\n emittedValue = props.multiple ? [] : ''\r\n\r\n syncInputValue()\r\n emit('update:value', emittedValue)\r\n emitEvent(props.onChange as ChangeEvent, emittedValue, props.multiple ? [] : '')\r\n emitEvent(props.onClear)\r\n clearField(emittedValue!)\r\n updatePopper()\r\n }\r\n}\r\n\r\nlet focused = false\r\n\r\nfunction handleFocus(event: FocusEvent) {\r\n if (!focused) {\r\n focused = true\r\n emitEvent(props.onFocus, event)\r\n }\r\n}\r\n\r\nfunction handleBlur(event: FocusEvent) {\r\n if (focused) {\r\n focused = false\r\n\r\n setTimeout(() => {\r\n if (!focused) {\r\n emitEvent(props.onBlur, event)\r\n }\r\n }, 120)\r\n }\r\n}\r\n\r\nfunction syncInputValue() {\r\n if (!input.value) return\r\n\r\n const visible = currentVisible.value\r\n\r\n if (props.multiple) {\r\n input.value.value = ''\r\n } else {\r\n input.value.value = visible ? '' : currentLabels.value[0] || ''\r\n }\r\n\r\n visible ? input.value.focus() : input.value.blur()\r\n}\r\n\r\nfunction handleFilterInput() {\r\n if (!input.value || composing.value) return\r\n\r\n let hittingIndex: number\r\n\r\n currentFilter.value = input.value.value\r\n\r\n if (!currentFilter.value) {\r\n hittingIndex = -1\r\n } else if (showDynamic.value || currentIndex.value !== -1) {\r\n hittingIndex = 0\r\n } else {\r\n hittingIndex = visibleOptions.value.findIndex(\r\n option => String(option.label) === currentFilter.value,\r\n )\r\n hittingIndex = hittingIndex === -1 ? 0 : hittingIndex\r\n }\r\n\r\n requestAnimationFrame(() => {\r\n if (!hittingIndex) {\r\n hittingIndex = visibleOptions.value.findIndex(\r\n option => !currentValues.value.includes(option.value),\r\n )\r\n }\r\n\r\n if (hittingIndex !== currentIndex.value) {\r\n updateHitting(hittingIndex)\r\n }\r\n\r\n if (props.multiple && device.value) {\r\n anchorWidth.value = getRangeWidth(device.value)\r\n }\r\n\r\n updatePopper()\r\n })\r\n\r\n emitEvent(props.onFilterInput, currentFilter.value)\r\n}\r\n\r\nfunction handleCompositionEnd() {\r\n if (!composing.value) return\r\n\r\n composing.value = false\r\n\r\n if (input.value) {\r\n input.value.dispatchEvent(new Event('input'))\r\n }\r\n}\r\n\r\nfunction handleFilterKeyDown(event: KeyboardEvent) {\r\n if (!input.value) return\r\n\r\n if (\r\n props.filterPosition !== 'in-list' &&\r\n event.key === 'Backspace' &&\r\n !input.value.value &&\r\n !isNull(getLast(currentValues.value))\r\n ) {\r\n event.stopPropagation()\r\n handleTagClose(getLast(currentValues.value))\r\n }\r\n}\r\n\r\nfunction toggleShowRestTip() {\r\n if (!currentVisible.value) {\r\n restTipShow.value = !restTipShow.value\r\n\r\n if (restTipShow.value) {\r\n nextTick(() => {\r\n restTip.value?.updatePopper()\r\n })\r\n }\r\n } else {\r\n toggleVisible()\r\n restTipShow.value = false\r\n }\r\n}\r\n\r\nfunction focus(options?: FocusOptions) {\r\n if (currentVisible.value) {\r\n ;(input.value || reference.value)?.focus(options)\r\n } else {\r\n reference.value?.focus(options)\r\n }\r\n}\r\n</script>\r\n\r\n<template>\r\n <div\r\n :id=\"idFor\"\r\n ref=\"wrapper\"\r\n :class=\"className\"\r\n role=\"group\"\r\n :aria-disabled=\"toAttrValue(props.disabled)\"\r\n :aria-expanded=\"toAttrValue(currentVisible)\"\r\n aria-haspopup=\"listbox\"\r\n :aria-labelledby=\"labelId\"\r\n @click=\"toggleVisible\"\r\n >\r\n <div\r\n ref=\"reference\"\r\n :class=\"selectorClass\"\r\n tabindex=\"0\"\r\n @focus=\"handleFocus\"\r\n @blur=\";(!props.filter || !currentVisible) && handleBlur($event)\"\r\n >\r\n <div\r\n v-if=\"hasPrefix\"\r\n :class=\"[nh.be('icon'), nh.be('prefix')]\"\r\n :style=\"{ color: props.prefixColor }\"\r\n >\r\n <slot name=\"prefix\">\r\n <Renderer :renderer=\"props.slots.prefix\">\r\n <Icon :icon=\"props.prefix\"></Icon>\r\n </Renderer>\r\n </slot>\r\n </div>\r\n <div :class=\"nh.be('control')\">\r\n <slot name=\"control\">\r\n <Renderer :renderer=\"props.slots.control\">\r\n <template v-if=\"props.multiple\">\r\n <Overflow\r\n inherit\r\n :class=\"[nh.be('tags')]\"\r\n :items=\"currentValues\"\r\n :max-count=\"props.maxTagCount\"\r\n :style=\"{\r\n maxWidth: props.maxTagCount <= 0 && `calc(100% - ${anchorWidth}px)`\r\n }\"\r\n @rest-change=\"restTagCount = $event\"\r\n @click.stop=\"toggleVisible\"\r\n >\r\n <template #default=\"{ item: value, index }\">\r\n <slot\r\n name=\"tag\"\r\n :value=\"value\"\r\n :option=\"getOptionFromMap(value)\"\r\n :handle-close=\"handleTagClose.bind(null, value)\"\r\n >\r\n <Renderer\r\n :renderer=\"props.slots.tag\"\r\n :data=\"{\r\n value,\r\n option: getOptionFromMap(value),\r\n handleClose: handleTagClose.bind(null, value)\r\n }\"\r\n >\r\n <Tag\r\n inherit\r\n :class=\"nh.be('tag')\"\r\n :type=\"props.tagType\"\r\n closable\r\n :disabled=\"props.disabled\"\r\n @close=\"handleTagClose(value)\"\r\n >\r\n <span :class=\"nh.be('label')\">\r\n <slot name=\"selected\" :value=\"value\" :option=\"getOptionFromMap(value)\">\r\n <Renderer\r\n :renderer=\"props.slots.selected\"\r\n :data=\"{ value, option: getOptionFromMap(value) }\"\r\n >\r\n {{ currentLabels[index] }}\r\n </Renderer>\r\n </slot>\r\n </span>\r\n </Tag>\r\n </Renderer>\r\n </slot>\r\n </template>\r\n <template #counter=\"{ count }\">\r\n <slot v-if=\"props.noRestTip\" name=\"restTag\" :rest-count=\"count\">\r\n <Renderer :renderer=\"props.slots.restTag\" :data=\"{ restCount: count }\">\r\n <Tag\r\n inherit\r\n :class=\"[nh.be('tag'), nh.be('counter')]\"\r\n :type=\"props.tagType\"\r\n :disabled=\"props.disabled\"\r\n >\r\n {{ `+${count}` }}\r\n </Tag>\r\n </Renderer>\r\n </slot>\r\n <template v-else>\r\n <Tooltip\r\n ref=\"restTip\"\r\n inherit\r\n :transfer=\"false\"\r\n :visible=\"restTipShow\"\r\n trigger=\"custom\"\r\n placement=\"top-end\"\r\n :tip-class=\"nh.be('rest-tip')\"\r\n @click.stop=\"toggleShowRestTip\"\r\n >\r\n <template #trigger>\r\n <slot name=\"restTag\" :rest-count=\"count\">\r\n <Renderer :renderer=\"props.slots.restTag\" :data=\"{ restCount: count }\">\r\n <Tag\r\n inherit\r\n :class=\"[nh.be('tag'), nh.be('counter')]\"\r\n :type=\"props.tagType\"\r\n :disabled=\"props.disabled\"\r\n >\r\n {{ `+${count}` }}\r\n </Tag>\r\n </Renderer>\r\n </slot>\r\n </template>\r\n <NativeScroll inherit use-y-bar>\r\n <template v-for=\"(value, index) in currentValues\" :key=\"index\">\r\n <slot\r\n v-if=\"index >= currentValues.length - restTagCount\"\r\n name=\"tag\"\r\n :value=\"value\"\r\n :option=\"getOptionFromMap(value)\"\r\n :handle-close=\"handleRestTagClose.bind(null, value)\"\r\n >\r\n <Renderer\r\n :renderer=\"props.slots.tag\"\r\n :data=\"{\r\n value,\r\n option: getOptionFromMap(value),\r\n handleClose: handleRestTagClose.bind(null, value)\r\n }\"\r\n >\r\n <Tag\r\n inherit\r\n :class=\"nh.be('tag')\"\r\n closable\r\n :type=\"props.tagType\"\r\n :disabled=\"props.disabled\"\r\n @close=\"handleRestTagClose(value)\"\r\n >\r\n <span :class=\"nh.be('label')\">\r\n <slot\r\n name=\"selected\"\r\n :value=\"value\"\r\n :option=\"getOptionFromMap(value)\"\r\n >\r\n <Renderer\r\n :renderer=\"props.slots.selected\"\r\n :data=\"{ value, option: getOptionFromMap(value) }\"\r\n >\r\n {{ currentLabels[index] }}\r\n </Renderer>\r\n </slot>\r\n </span>\r\n </Tag>\r\n </Renderer>\r\n </slot>\r\n </template>\r\n </NativeScroll>\r\n </Tooltip>\r\n </template>\r\n </template>\r\n </Overflow>\r\n <div\r\n v-if=\"props.filter && props.filterPosition === 'in-control'\"\r\n :class=\"nh.be('anchor')\"\r\n :style=\"{\r\n width: `${anchorWidth}px`\r\n }\"\r\n >\r\n <input\r\n ref=\"nativeInput\"\r\n :class=\"[\r\n nh.be('input'),\r\n nh.bem('input', 'multiple'),\r\n currentVisible && nh.bem('input', 'visible')\r\n ]\"\r\n :disabled=\"props.disabled\"\r\n autocomplete=\"off\"\r\n tabindex=\"-1\"\r\n role=\"combobox\"\r\n aria-autocomplete=\"list\"\r\n :name=\"props.name\"\r\n @submit.prevent\r\n @input=\"handleFilterInput\"\r\n @keydown=\"handleFilterKeyDown\"\r\n @focus=\"handleFocus($event)\"\r\n @blur=\"handleBlur($event)\"\r\n @compositionstart=\"composing = true\"\r\n @compositionend=\"handleCompositionEnd\"\r\n @change=\"handleCompositionEnd\"\r\n />\r\n <span ref=\"device\" :class=\"nh.be('device')\" aria-hidden=\"true\">\r\n {{ currentFilter }}\r\n </span>\r\n </div>\r\n </template>\r\n <template v-else>\r\n <input\r\n v-if=\"props.filter && props.filterPosition === 'in-control'\"\r\n ref=\"nativeInput\"\r\n :class=\"[nh.be('input'), currentVisible && nh.bem('input', 'visible')]\"\r\n :disabled=\"props.disabled\"\r\n autocomplete=\"off\"\r\n tabindex=\"-1\"\r\n role=\"combobox\"\r\n aria-autocomplete=\"list\"\r\n :name=\"props.name\"\r\n :style=\"{\r\n opacity: currentVisible ? undefined : '0%'\r\n }\"\r\n @submit.prevent\r\n @input=\"handleFilterInput\"\r\n @focus=\"handleFocus($event)\"\r\n @blur=\"handleBlur($event)\"\r\n @compositionstart=\"composing = true\"\r\n @compositionend=\"handleCompositionEnd\"\r\n @change=\"handleCompositionEnd\"\r\n />\r\n <span\r\n v-if=\"\r\n (props.noPreview || !currentVisible) &&\r\n hasValue &&\r\n (props.filterPosition !== 'in-control' || !currentFilter)\r\n \"\r\n :class=\"{\r\n [nh.be('selected')]: true,\r\n [nh.bem('selected', 'placeholder')]: props.filter && currentVisible && hasValue\r\n }\"\r\n >\r\n <slot\r\n v-if=\"getOptionFromMap(currentValues[0])\"\r\n name=\"selected\"\r\n :value=\"currentValues[0]\"\r\n :option=\"getOptionFromMap(currentValues[0])\"\r\n >\r\n <Renderer\r\n :renderer=\"props.slots.selected\"\r\n :data=\"{ value: currentValues[0], option: getOptionFromMap(currentValues[0]) }\"\r\n >\r\n {{ currentLabels[0] }}\r\n </Renderer>\r\n </slot>\r\n <template v-else>\r\n {{ currentLabels[0] }}\r\n </template>\r\n </span>\r\n </template>\r\n <span v-if=\"showPlaceholder\" :class=\"nh.be('placeholder')\">\r\n <slot\r\n v-if=\"previewOption\"\r\n name=\"selected\"\r\n :preview=\"true\"\r\n :value=\"previewOption.value\"\r\n :option=\"previewOption\"\r\n >\r\n <Renderer\r\n :renderer=\"props.slots.selected\"\r\n :data=\"{ value: previewOption.value, preview: true, option: previewOption }\"\r\n >\r\n {{ previewOption.label }}\r\n </Renderer>\r\n </slot>\r\n <template v-else>\r\n {{ props.placeholder ?? locale.placeholder }}\r\n </template>\r\n </span>\r\n </Renderer>\r\n </slot>\r\n </div>\r\n <div\r\n v-if=\"!props.noSuffix\"\r\n :class=\"[nh.be('icon'), nh.be('suffix')]\"\r\n :style=\"{\r\n color: props.suffixColor,\r\n opacity: showClear || props.loading ? '0%' : ''\r\n }\"\r\n >\r\n <slot name=\"suffix\">\r\n <Renderer :renderer=\"props.slots.suffix\">\r\n <Icon\r\n v-if=\"props.suffix\"\r\n :icon=\"props.suffix\"\r\n :class=\"{\r\n [nh.be('arrow')]: !props.staticSuffix\r\n }\"\r\n ></Icon>\r\n <Icon v-else v-bind=\"icons.angleDown\" :class=\"nh.be('arrow')\"></Icon>\r\n </Renderer>\r\n </slot>\r\n </div>\r\n <div\r\n v-else-if=\"props.clearable || props.loading\"\r\n :class=\"[nh.be('icon'), nh.bem('icon', 'placeholder'), nh.be('suffix')]\"\r\n ></div>\r\n <Transition :name=\"nh.ns('fade')\" appear>\r\n <button\r\n v-if=\"showClear\"\r\n :class=\"[nh.be('icon'), nh.be('clear')]\"\r\n type=\"button\"\r\n tabindex=\"-1\"\r\n :aria-label=\"locale.ariaLabel.clear\"\r\n @click.stop=\"handleClear\"\r\n >\r\n <Icon v-bind=\"icons.clear\" label=\"clear\"></Icon>\r\n </button>\r\n <div v-else-if=\"props.loading\" :class=\"[nh.be('icon'), nh.be('loading')]\">\r\n <Icon\r\n v-bind=\"icons.loading\"\r\n :effect=\"props.loadingEffect || icons.loading.effect\"\r\n :icon=\"props.loadingIcon || icons.loading.icon\"\r\n label=\"loading\"\r\n ></Icon>\r\n </div>\r\n </Transition>\r\n </div>\r\n <Popper\r\n ref=\"popper\"\r\n :class=\"[nh.be('popper'), nh.bs('vars')]\"\r\n :visible=\"currentVisible\"\r\n :to=\"transferTo\"\r\n :transition=\"props.transitionName\"\r\n :alive=\"props.popperAlive ?? !transferTo\"\r\n @click.stop=\"focus\"\r\n @after-leave=\"currentFilter = ''\"\r\n >\r\n <slot\r\n name=\"list\"\r\n :options=\"totalOptions\"\r\n :is-selected=\"isSelected\"\r\n :handle-select=\"handleSelect\"\r\n >\r\n <Renderer\r\n :renderer=\"props.slots.list\"\r\n :data=\"{ options: totalOptions, isSelected, handleSelect }\"\r\n >\r\n <div\r\n :class=\"[\r\n nh.be('list'),\r\n (slots.prepend || slots.append) && nh.bem('list', 'with-extra'),\r\n props.listClass\r\n ]\"\r\n >\r\n <div v-if=\"props.filter && props.filterPosition === 'in-list'\" :class=\"nh.be('filter')\">\r\n <Input\r\n ref=\"filterInput\"\r\n :class=\"nh.be('filter-input')\"\r\n transparent\r\n :disabled=\"props.disabled\"\r\n :placeholder=\"locale.search\"\r\n :autocomplete=\"false\"\r\n :tabindex=\"-1\"\r\n role=\"combobox\"\r\n aria-autocomplete=\"list\"\r\n @input=\"handleFilterInput\"\r\n @keydown=\"handleFilterKeyDown\"\r\n @focus=\"handleFocus\"\r\n @blur=\"handleBlur\"\r\n @compositionstart=\"composing = true\"\r\n @compositionend=\"handleCompositionEnd\"\r\n @change=\"handleCompositionEnd\"\r\n >\r\n <template #suffix>\r\n <Icon v-bind=\"icons.search\"></Icon>\r\n </template>\r\n </Input>\r\n </div>\r\n <slot v-if=\"slots.prepend || props.slots.prepend\" name=\"prepend\">\r\n <Renderer :renderer=\"props.slots.prepend\"></Renderer>\r\n </slot>\r\n <VirtualList\r\n ref=\"virtualList\"\r\n inherit\r\n :style=\"{\r\n height: undefined,\r\n maxHeight: `${props.maxListHeight}px`\r\n }\"\r\n :items=\"totalOptions\"\r\n :item-size=\"32\"\r\n use-y-bar\r\n :height=\"'100%'\"\r\n id-key=\"value\"\r\n :items-attrs=\"{\r\n class: [nh.be('options'), props.optionCheck ? nh.bem('options', 'has-check') : ''],\r\n role: 'listbox',\r\n ariaLabel: 'options',\r\n ariaMultiselectable: props.multiple\r\n }\"\r\n >\r\n <template #default=\"{ item: option, index }\">\r\n <li\r\n v-if=\"option.group\"\r\n :class=\"[nh.ns('option-vars'), nh.be('group')]\"\r\n :title=\"option.label\"\r\n >\r\n <slot name=\"group\" :option=\"option\" :index=\"index\">\r\n <Renderer :renderer=\"props.slots.group\" :data=\"{ option, index }\">\r\n <div\r\n :class=\"[nh.be('label'), nh.bem('label', 'group')]\"\r\n :style=\"{ paddingInlineStart: `${option.depth * 6}px` }\"\r\n >\r\n {{ option.label }}\r\n </div>\r\n </Renderer>\r\n </slot>\r\n </li>\r\n <Option\r\n v-else\r\n :label=\"option.label\"\r\n :value=\"option.value\"\r\n :disabled=\"option.disabled || (limited && !isSelected(option))\"\r\n :divided=\"option.divided\"\r\n :no-title=\"option.title\"\r\n :hitting=\"option.hitting\"\r\n :selected=\"isSelected(option)\"\r\n no-hover\r\n @select=\"handleSelect(option)\"\r\n @mousemove=\"updateHitting(index, false)\"\r\n >\r\n <slot :option=\"option\" :index=\"index\" :selected=\"isSelected(option)\">\r\n <Renderer\r\n :renderer=\"props.slots.default\"\r\n :data=\"{ option, index, selected: isSelected(option) }\"\r\n >\r\n <span\r\n :class=\"nh.be('label')\"\r\n :style=\"{ paddingInlineStart: `${option.depth * 6}px` }\"\r\n >\r\n {{ option.label }}\r\n </span>\r\n <Transition v-if=\"props.optionCheck\" :name=\"nh.ns('fade')\" appear>\r\n <Icon\r\n v-if=\"isSelected(option)\"\r\n v-bind=\"icons.check\"\r\n :class=\"nh.be('check')\"\r\n ></Icon>\r\n </Transition>\r\n </Renderer>\r\n </slot>\r\n </Option>\r\n </template>\r\n <template #empty>\r\n <div :class=\"nh.be('empty')\">\r\n <slot name=\"empty\">\r\n <Renderer :renderer=\"props.slots.empty\">\r\n {{ props.emptyText ?? locale.empty }}\r\n </Renderer>\r\n </slot>\r\n </div>\r\n </template>\r\n </VirtualList>\r\n <slot v-if=\"slots.append || props.slots.append\" name=\"append\">\r\n <Renderer :renderer=\"props.slots.append\"></Renderer>\r\n </slot>\r\n </div>\r\n </Renderer>\r\n </slot>\r\n </Popper>\r\n </div>\r\n</template>\r\n"],"names":["isSameValue","newValue","oldValue","isNewArray","isOldArray","i","len","isNull","idFor","labelId","state","disabled","loading","size","validateField","clearField","getFieldValue","setFieldValue","useFieldStore","focus","nh","useNameHelper","props","useProps","__props","createSizeProp","createStateProp","createIconProp","value","placementWhileList","emit","__emit","slots","_useSlots","locale","useLocale","toRef","icons","useIcons","currentVisible","ref","currentLabels","currentValues","currentIndex","placement","transfer","baseOptions","currentFilter","anchorWidth","userOptions","restTagCount","restTipShow","composing","isMounted","useMounted","dynamicOption","reactive","optionValues","hittingOption","optionStates","computed","visibleOptions","keyConfig","defaultKeyConfig","wrapper","useClickOutside","handleClickOutside","nativeInput","filterInput","device","virtualList","popper","restTip","input","_a","reference","transferTo","updatePopper","usePopper","isHover","useHover","cachedSelected","optionValueMap","emittedValue","updateTrigger","watchEffect","watch","initOptionState","valueKey","labelKey","disabledKey","dividedKey","titleKey","groupKey","childrenKey","oldMap","map","states","loop","option","depth","parent","rawOption","group","label","divided","title","children","oldState","optionState","child","initValueAndLabel","useModifier","event","modifier","toggleVisible","setVisible","decide","options","length","step","index","updateHitting","handleSelect","totalOptions","showDynamic","className","readonly","selectorClass","baseCls","hasPrefix","hasValue","normalOptions","optionParentMap","showClear","previewOption","limited","showPlaceholder","getOptionFromMap","fitPopperWidth","initHittingIndex","syncInputValue","filterOptions","__expose","isSelected",