UNPKG

winbox-ui-next

Version:

We Design Vue 2.0: A Vue.js 3 UI Library

234 lines (233 loc) 6.59 kB
import { defineComponent, ref, computed, toRefs, createVNode, mergeProps, isVNode } from "vue"; import Input from "../input/index.js"; import Trigger from "../trigger/index.js"; import { getPrefixCls } from "../_utils/global-config.js"; import { useOptions } from "../_hooks/use-options.js"; import { isFunction } from "../_utils/is.js"; import DropdownPanel from "../_components/dropdown/dropdown-panel.js"; import DropDownOption from "../_components/dropdown/dropdown-option.js"; import "../_components/dropdown/dropdown-optgroup.js"; import { getKeyDownHandler, CODE } from "../_utils/keyboard.js"; function _isSlot(s) { return typeof s === "function" || Object.prototype.toString.call(s) === "[object Object]" && !isVNode(s); } var _AutoComplete = defineComponent({ name: "AutoComplete", inheritAttrs: false, props: { modelValue: { type: String, default: void 0 }, defaultValue: { type: String, default: "" }, disabled: { type: Boolean, default: false }, data: { type: Array, default: () => [] }, popupContainer: { type: [String, Object] }, strict: { type: Boolean, default: false }, filterOption: { type: [Boolean, Function], default: true }, triggerProps: { type: Object }, onChange: { type: [Function, Array] }, onSearch: { type: [Function, Array] }, onSelect: { type: [Function, Array] } }, emits: [ "update:modelValue", "change", "search", "select" ], setup(props, { emit, attrs, slots }) { const prefixCls = getPrefixCls("auto-complete"); const _value = ref(props.defaultValue); const inputRef = ref(); const computedValue = computed(() => { var _a; return (_a = props.modelValue) != null ? _a : _value.value; }); const { data } = toRefs(props); const dropdownRef = ref(); const optionRefs = ref({}); const strictFilterOption = (inputValue, optionInfo) => { return optionInfo.label.includes(inputValue); }; const mergedFilterOption = computed(() => { if (isFunction(props.filterOption)) { return props.filterOption; } if (props.filterOption && props.strict) { return strictFilterOption; } return props.filterOption; }); const extraOptions = ref([]); const { nodes, optionInfoMap, activeOption, getNextActiveOption, scrollIntoView } = useOptions({ options: data, extraOptions, inputValue: computedValue, filterOption: mergedFilterOption, dropdownRef, optionRefs }); const handleChange = (value) => { _value.value = value; emit("update:modelValue", value); emit("change", value); }; const _popupVisible = ref(false); const computedPopupVisible = computed(() => _popupVisible.value && nodes.value.length > 0); const handlePopupVisibleChange = (popupVisible) => { _popupVisible.value = popupVisible; }; const handleSelect = (value, e) => { var _a; emit("select", value); handleChange(value); (_a = inputRef.value) == null ? void 0 : _a.blur(); }; const handleMouseEnter = (value, e) => { const optionInfo = optionInfoMap.get(value); if (optionInfo) { activeOption.value = optionInfo; } }; const handleMouseLeave = (e) => { activeOption.value = void 0; }; const handleInputValueChange = (value) => { emit("search", value); handleChange(value); }; const handleKeyDown = getKeyDownHandler(new Map([[CODE.ENTER, (e) => { if (computedPopupVisible.value) { if (activeOption.value) { handleSelect(String(activeOption.value.value)); } e.preventDefault(); } }], [CODE.ESC, (e) => { handlePopupVisibleChange(false); e.preventDefault(); }], [CODE.ARROW_DOWN, (e) => { if (computedPopupVisible.value) { const next = getNextActiveOption("down"); if (next) { activeOption.value = next; scrollIntoView(next.value); } e.preventDefault(); } }], [CODE.ARROW_UP, (e) => { if (computedPopupVisible.value) { const next = getNextActiveOption("up"); if (next) { activeOption.value = next; scrollIntoView(next.value); } e.preventDefault(); } }]])); const getOptionContentFunc = (item) => { if (isFunction(slots.option) && item.value) { const optionInfo = optionInfoMap.get(item.value); const optionSlot = slots.option; return () => optionSlot({ data: optionInfo }); } return () => item.label; }; const renderOption = (item) => { const { value = "" } = item; return createVNode(DropDownOption, { "ref": (ref2) => { if (ref2 == null ? void 0 : ref2.$el) { optionRefs.value[value] = ref2.$el; } }, "key": item.key, "value": value, "disabled": item.disabled, "isActive": activeOption.value && value === activeOption.value.value, "onClick": handleSelect, "onMouseenter": handleMouseEnter, "onMouseleave": handleMouseLeave }, { default: getOptionContentFunc(item) }); }; const renderDropdown = () => { const _children = nodes.value.map((node) => renderOption(node)); if (_children.length === 0) { return null; } return createVNode(DropdownPanel, { "ref": dropdownRef, "class": `${prefixCls}-dropdown` }, _isSlot(_children) ? _children : { default: () => [_children] }); }; return () => createVNode(Trigger, mergeProps({ "trigger": "focus", "position": "bl", "popupVisible": computedPopupVisible.value, "clickToClose": false, "preventFocus": true, "popupOffset": 4, "disabled": props.disabled, "autoFitPopupWidth": true }, props.triggerProps, { "onPopupVisibleChange": handlePopupVisibleChange }), { default: () => [createVNode(Input, mergeProps({ "ref": inputRef, "modelValue": computedValue.value, "onInput": handleInputValueChange, "disabled": props.disabled }, attrs, { "onKeydown": handleKeyDown }), slots)], content: renderDropdown }); } }); export { _AutoComplete as default };