UNPKG

song-ui-u

Version:

vue3 + js的PC前端组件库

287 lines (283 loc) 9.3 kB
'use strict'; var vue = require('vue'); var index$1 = require('../../../hook/use-namespace/index.cjs'); var icons = require('song-ui-pro-icon'); require('../../../hook/use-zindex/index.cjs'); var constant = require('./constant.cjs'); require('../../button/index.cjs'); require('../../buttonGroup/index.cjs'); var index = require('../../icon/index.cjs'); require('../../input/index.cjs'); require('../../textarea/index.cjs'); require('../../row/index.cjs'); require('../../col/index.cjs'); require('../../container/index.cjs'); require('../../checkbox/index.cjs'); require('../../switch/index.cjs'); require('../../form/index.cjs'); require('../../message/index.cjs'); require('../../mask/src/mask.cjs'); require('../../modal/index.cjs'); require('../../messageBox/index.cjs'); require('../../drawer/index.cjs'); require('../../badge/index.cjs'); require('../../space/index.cjs'); require('../../image/index.cjs'); require('../../radio/index.cjs'); require('../../divider/index.cjs'); require('../../chat/index.cjs'); require('../../progress/index.cjs'); require('../../upload/index.cjs'); require('../../vTree/index.cjs'); require('../../table/index.cjs'); require('../../tabs/index.cjs'); require('../../menu/index.cjs'); require('../../steps/index.cjs'); require('../../header/index.cjs'); require('../../breadcrumble/index.cjs'); require('../../datePicker/index.cjs'); require('../../tooltip/index.cjs'); require('../../popover/index.cjs'); require('../../timePicker/index.cjs'); require('../index.cjs'); require('../../collapse/index.cjs'); require('../../card/index.cjs'); require('../../timeline/index.cjs'); require('../../tag/index.cjs'); require('../../result/index.cjs'); require('../../sender/index.cjs'); var Select = /* @__PURE__ */ vue.defineComponent({ name: "x-select", props: { modelValue: { type: [String, Number, Array], default: "" }, multiple: { type: Boolean, default: false }, disabled: { type: Boolean, default: false }, clearable: { type: Boolean, default: false }, placeholder: { type: String, default: "\u8BF7\u9009\u62E9" }, filterable: { type: Boolean, default: false }, size: { type: String, default: "default" }, width: { type: String, default: "100%" } }, emits: ["update:modelValue", "change", "clear", "blur", "focus"], setup(props, { slots, emit }) { const ns = index$1.useNamespace("select"); const visible = vue.ref(false); const selectedLabel = vue.ref(""); const selectedLabels = vue.ref([]); const inputValue = vue.ref(""); const options = vue.ref([]); const selectRef = vue.ref(null); const inputRef = vue.ref(null); const dropdownRef = vue.ref(null); const isFocus = vue.ref(false); const isHover = vue.ref(false); const styleWidth = vue.computed(() => ({ width: props.width })); const controlSize = vue.computed(() => props.size); const registerOption = (option) => { options.value.push(option); }; const unregisterOption = (id) => { const index = options.value.findIndex((option) => option.id === id); if (index !== -1) { options.value.splice(index, 1); } }; const selectOption = (value, label) => { if (props.multiple) { const values = Array.isArray(props.modelValue) ? [...props.modelValue] : []; const index = values.indexOf(value); if (index === -1) { values.push(value); selectedLabels.value.push(label); } else { values.splice(index, 1); selectedLabels.value.splice(index, 1); } emit("update:modelValue", values); emit("change", values); } else { if (selectedLabel.value == label) { selectedLabel.value = ""; } else { selectedLabel.value = label; } emit("update:modelValue", value); emit("change", value); closeDropdown(); } }; const clearSelection = (e) => { e.stopPropagation(); console.log("clearSelection"); if (props.multiple) { emit("update:modelValue", []); selectedLabels.value = []; } else { emit("update:modelValue", ""); selectedLabel.value = ""; } emit("clear"); }; const toggleDropdown = () => { if (props.disabled) return; visible.value = !visible.value; if (visible.value && props.filterable) { vue.nextTick(() => { inputRef.value?.focus(); }); } }; const closeDropdown = () => { visible.value = false; if (props.filterable) { inputValue.value = ""; } }; const handleInput = (e) => { inputValue.value = e.target.value; }; const handleFocus = () => { isFocus.value = true; emit("focus"); }; const handleBlur = () => { isFocus.value = false; emit("blur"); }; const handleMouseEnter = () => { isHover.value = true; }; const handleMouseLeave = () => { isHover.value = false; }; const isOptionSelected = (value) => { if (props.multiple) { return Array.isArray(props.modelValue) && props.modelValue.includes(value); } return props.modelValue === value && selectedLabel.value; }; vue.watch(() => props.modelValue, (newVal) => { if (props.multiple) ; else { const selectedOption = options.value.find((option) => option.value === newVal); selectedLabel.value = selectedOption ? selectedOption.label : ""; } }, { immediate: true }); vue.provide(constant.SELECT_KEY, { props, registerOption, unregisterOption, selectOption, isOptionSelected, inputValue }); const handleClickOutside = (e) => { if (selectRef.value && !selectRef.value.contains(e.target)) { closeDropdown(); } }; vue.watch(visible, (newVal) => { if (newVal) { document.addEventListener("click", handleClickOutside); } else { document.removeEventListener("click", handleClickOutside); } }); return () => vue.createVNode("div", { "ref": selectRef, "style": styleWidth.value, "class": [ns.b(), ns.is("focus", isFocus.value), ns.is("disabled", props.disabled), ns.m("size", controlSize.value), ns.is("clearable", props.clearable && !props.disabled && (props.multiple ? selectedLabels.value.length > 0 : selectedLabel.value)), ns.is("multiple", props.multiple), ns.is("filterable", props.filterable)], "onClick": toggleDropdown, "onMouseenter": handleMouseEnter, "onMouseleave": handleMouseLeave }, [vue.createVNode("div", { "class": [ns.e("wrapper"), ns.is("hover", isHover.value && !props.disabled)] }, [props.multiple ? vue.createVNode("div", { "class": [ns.e("tags")] }, [selectedLabels.value.length > 0 ? selectedLabels.value.map((label, index$1) => vue.createVNode("span", { "class": [ns.e("tag")], "key": index$1 }, [label, vue.createVNode(index.XIcon, { "onClick": (e) => { e.stopPropagation(); selectOption(props.modelValue[index$1], label); } }, { default: () => [vue.createVNode(icons.X, null, null)] })])) : vue.createVNode("span", { "class": [ns.e("placeholder")] }, null), props.filterable && vue.createVNode("input", { "ref": inputRef, "type": "text", "class": [ns.e("filter-input")], "value": inputValue.value, "onInput": handleInput, "disabled": props.disabled, "onFocus": handleFocus, "onBlur": handleBlur, "placeholder": selectedLabel.value || props.placeholder }, null)]) : ( /* 单选模式 */ vue.createVNode("div", { "class": [ns.e("selected")] }, [props.filterable && visible.value ? vue.createVNode("input", { "ref": inputRef, "type": "text", "class": [ns.e("filter-input")], "value": inputValue.value, "placeholder": selectedLabel.value || props.placeholder, "onInput": handleInput, "onFocus": handleFocus, "onBlur": handleBlur }, null) : vue.createVNode("span", { "class": [selectedLabel.value ? ns.e("label") : ns.e("placeholder")] }, [selectedLabel.value || props.placeholder])]) ), props.clearable && !props.disabled && (props.multiple ? selectedLabels.value.length > 0 : selectedLabel.value) && isHover.value && vue.createVNode(index.XIcon, { "class": [ns.e("clear")], "onClick": clearSelection }, { default: () => [vue.createVNode(icons.X, null, null)] }), vue.createVNode(index.XIcon, { "class": [ns.e("arrow"), visible.value ? ns.is("reverse", true) : ""] }, { default: () => [vue.createVNode(icons.ChevronDown, null, null)] })]), visible.value && vue.createVNode("div", { "ref": dropdownRef, "class": [ns.e("dropdown")] }, [options.value.length === 0 && vue.createVNode("div", { "class": [ns.e("empty")] }, [vue.createTextVNode("\u65E0\u6570\u636E")]), slots.default?.()])]); } }); module.exports = Select; //# sourceMappingURL=select.cjs.map