UNPKG

@opensig/opendesign

Version:

<p align="center"><img src="../docs/public/opendesign-logo-light.png"/></p> <h1 align="center">opendesign</h1> <p align="center">一个 Vue 3 组件库</p> <p align="center"><b>皮肤可定制,使用 TypeScript</b></p>

600 lines (599 loc) 22.8 kB
import { defineComponent, ref, computed, watch, inject, watchEffect, provide, createElementBlock, openBlock, normalizeStyle, normalizeClass, unref, createBlock, createElementVNode, createVNode, withCtx, createCommentVNode, Fragment, renderList, createTextVNode, toDisplayString, renderSlot, Teleport, withDirectives, vShow, createSlots } from "vue"; import { defaultSize } from "../_utils/global.mjs"; import { IconClose, IconLoading, IconChevronDown } from "../_utils/icons.mjs"; import { OPopup } from "../popup/index.mjs"; import { OPopover } from "../popover/index.mjs"; import { ODialog } from "../dialog/index.mjs"; import { selectOptionInjectKey } from "./provide.mjs"; import { selectProps } from "./types.mjs"; import { getRoundClass } from "../_utils/style-class.mjs"; import ClientOnly from "../_components/client-only.mjs"; import { OScroller } from "../scrollbar/index.mjs"; import { isArray, isUndefined, isArrayEqual, isFunction } from "../_utils/is.mjs"; import _sfc_main$1 from "./SelectOption.vue.mjs"; import slot from "./slot.mjs"; import { filterSlots } from "../_utils/vue-utils.mjs"; import { formItemInjectKey } from "../form/provide.mjs"; import { useI18n } from "../locale/index.mjs"; import { OButton } from "../button/index.mjs"; import { useScreen } from "../hooks/use-screen.mjs"; const _hoisted_1 = ["value", "placeholder"]; const _hoisted_2 = { class: "o-select-tags-wrap" }; const _hoisted_3 = ["onClick"]; const _hoisted_4 = { class: "o-select-tags" }; const _hoisted_5 = ["onClick"]; const _hoisted_6 = { class: "o-select-suffix" }; const _hoisted_7 = { class: "o-select-suffix-icon" }; const _hoisted_8 = { key: 0, class: "o-select-loading" }; const _hoisted_9 = { class: "o-select-option-wrap" }; const _hoisted_10 = { class: "o-select-empty" }; const _hoisted_11 = { class: "o-select-options-head" }; const _sfc_main = /* @__PURE__ */ defineComponent({ __name: "OSelect", props: selectProps, emits: ["update:modelValue", "change", "options-visible-change", "clear"], setup(__props, { emit: __emit }) { const props = __props; const emits = __emit; const { isPhonePad } = useScreen(); const { t } = useI18n(); const selectRef = ref(); const optionsRef = ref(null); const isSelecting = ref(false); const isResponding = computed(() => { return !props.noResponsive && isPhonePad.value; }); const tagPopoverVisible = ref(false); watch( () => isSelecting.value, () => { if (isSelecting.value) { tagPopoverVisible.value = false; } } ); const formItemInjection = inject(formItemInjectKey, null); const color = computed(() => { var _a; if (formItemInjection == null ? void 0 : formItemInjection.fieldResult.value) { return (_a = formItemInjection == null ? void 0 : formItemInjection.fieldResult.value) == null ? void 0 : _a.type; } else { return props.color; } }); const optionLabels = ref({}); const valueList = ref([]); const finalValueList = ref([]); if (isArray(props.modelValue)) { valueList.value = [...props.modelValue]; } else if (isArray(props.defaultValue)) { valueList.value = [...props.defaultValue]; } else { const mrValue = props.modelValue ?? props.defaultValue; if (!isUndefined(mrValue)) { valueList.value = [mrValue]; } else { valueList.value = []; } } finalValueList.value = [...valueList.value]; const valueListDisplay = computed(() => { if (!props.maxTagCount) { return finalValueList.value; } return finalValueList.value.slice(0, props.maxTagCount); }); const valueListFold = computed(() => { if (!props.maxTagCount) { return []; } return finalValueList.value.slice(props.maxTagCount); }); const foldLabel = computed(() => { if (props.foldLabel) { const tags = valueListFold.value.map((item) => ({ value: item, label: optionLabels.value[item] })); return props.foldLabel(tags); } return `+${valueListFold.value.length}...`; }); const foldTrigger = typeof props.showFoldTags === "string" ? props.showFoldTags : "hover"; const round = getRoundClass(props, "select"); watch( () => props.modelValue, (v) => { if (props.multiple) { if (isArray(v)) { if (!isArrayEqual(v, valueList.value)) { valueList.value = [...v]; } } else { valueList.value = []; } } else if (valueList.value[0] !== v) { valueList.value = [v]; } finalValueList.value = [...valueList.value]; } ); watchEffect(() => { if (!isResponding.value) { finalValueList.value = [...valueList.value]; } }); const isClearable = computed(() => props.clearable && !props.disabled && valueList.value.length > 0); const emitChange = (value) => { var _a, _b; if (props.multiple) { emits("change", [...value]); } else { emits("change", value[0]); } (_b = formItemInjection == null ? void 0 : (_a = formItemInjection.fieldHandlers).onChange) == null ? void 0 : _b.call(_a); }; const emitUpdateValue = (value) => { if (props.multiple) { emits("update:modelValue", [...value]); } else { emits("update:modelValue", value[0]); } }; const clearClick = (e) => { e.stopPropagation(); valueList.value = []; emits("clear", e); emitChange(valueList.value); emitUpdateValue(valueList.value); }; const beforeSelect = async (value) => { if (isFunction(props.beforeSelect)) { const rlt = await props.beforeSelect(value, props.multiple ? valueList.value : valueList.value[0]); return rlt; } return true; }; provide(selectOptionInjectKey, { multiple: props.multiple, selectValue: valueList, select: async (option, userSelect) => { if (userSelect) { let toValue = option.value; const rlt = await beforeSelect(option.value); if (rlt === false) { return; } if (typeof rlt !== "boolean") { toValue = rlt; } if (!props.multiple) { isSelecting.value = false; if (valueList.value[0] !== toValue) { valueList.value[0] = toValue; emitUpdateValue(valueList.value); emitChange(valueList.value); } } else { const idx = valueList.value.indexOf(toValue); if (idx > -1) { valueList.value.splice(idx, 1); } else { valueList.value.push(toValue); } if (!isResponding.value) { emitUpdateValue(valueList.value); emitChange(valueList.value); } } } else { if (optionLabels.value[option.value] !== option.label) { optionLabels.value[option.value] = option.label; } } } }); const onOptionVisibleChange = (visible) => { emits("options-visible-change", visible); }; const onRemoveTag = (value, e) => { e.stopPropagation(); const idx = valueList.value.indexOf(value); if (idx > -1) { valueList.value.splice(idx, 1); emitChange(valueList.value); emitUpdateValue(valueList.value); } }; const onFoldTagClick = (e) => { if (foldTrigger === "click") { e.stopPropagation(); } }; const beforeTagPopoverShow = () => { if (isSelecting.value) { return false; } return true; }; const onSelectClick = () => { if (isResponding.value) { if (!props.disabled) { isSelecting.value = true; } } }; const onSelectDlgChange = (visible) => { onOptionVisibleChange(visible); }; const onselectDlgCancelClick = () => { isSelecting.value = false; valueList.value = [...finalValueList.value]; }; const onselectDlgOkClick = () => { isSelecting.value = false; finalValueList.value = [...valueList.value]; emitChange(valueList.value); emitUpdateValue(valueList.value); }; return (_ctx, _cache) => { return openBlock(), createElementBlock( "div", { ref_key: "selectRef", ref: selectRef, class: normalizeClass(["o-select", [ `o-select-${color.value}`, `o-select-${props.variant}`, `o-select-${props.size || unref(defaultSize)}`, unref(round).class.value, { "is-selecting": isSelecting.value, "is-multiple": props.multiple && valueList.value.length > 0, "o-select-disabled": props.disabled, "o-select-clearable": isClearable.value, "o-select-is-loading": props.loading } ]]), style: normalizeStyle(unref(round).style.value), onClick: onSelectClick }, [ !props.multiple || props.multiple && valueList.value.length === 0 ? (openBlock(), createElementBlock("input", { key: 0, value: optionLabels.value[valueList.value[0]], type: "text", placeholder: props.placeholder, class: "o-select-input", readonly: "" }, null, 8, _hoisted_1)) : (openBlock(), createBlock(unref(OScroller), { key: 1, class: "o-select-tags-scroller", "wrap-class": "o-select-value-list", "show-type": "hover", size: "small", "disabled-x": "" }, { default: withCtx(() => [ createElementVNode("div", _hoisted_2, [ (openBlock(true), createElementBlock( Fragment, null, renderList(valueListDisplay.value, (item) => { return openBlock(), createElementBlock("div", { key: item, class: "o-select-tag" }, [ createTextVNode( toDisplayString(optionLabels.value[item]) + " ", 1 /* TEXT */ ), createElementVNode("div", { class: "o-select-tag-remove", onClick: (e) => onRemoveTag(item, e) }, [ createVNode(unref(IconClose)) ], 8, _hoisted_3) ]); }), 128 /* KEYED_FRAGMENT */ )), _ctx.showFoldTags && valueListFold.value.length > 0 ? (openBlock(), createBlock(unref(OPopover), { key: 0, visible: tagPopoverVisible.value, "onUpdate:visible": _cache[0] || (_cache[0] = ($event) => tagPopoverVisible.value = $event), trigger: unref(foldTrigger), class: "o-select-tag-popover", position: "bottom", "before-show": beforeTagPopoverShow }, { target: withCtx(() => [ createElementVNode("div", { class: "o-select-tag", onClick: onFoldTagClick }, [ renderSlot(_ctx.$slots, "tag-fold", {}, () => [ createTextVNode( toDisplayString(foldLabel.value), 1 /* TEXT */ ) ]) ]) ]), default: withCtx(() => [ createElementVNode("div", _hoisted_4, [ (openBlock(true), createElementBlock( Fragment, null, renderList(valueListFold.value, (item) => { return openBlock(), createElementBlock("div", { key: item, class: "o-select-tag" }, [ createTextVNode( toDisplayString(optionLabels.value[item]) + " ", 1 /* TEXT */ ), createElementVNode("div", { class: "o-select-tag-remove", onClick: (e) => onRemoveTag(item, e) }, [ createVNode(unref(IconClose)) ], 8, _hoisted_5) ]); }), 128 /* KEYED_FRAGMENT */ )) ]) ]), _: 3 /* FORWARDED */ }, 8, ["visible", "trigger"])) : createCommentVNode("v-if", true) ]) ]), _: 3 /* FORWARDED */ })), createElementVNode("div", _hoisted_6, [ createElementVNode("div", _hoisted_7, [ props.loading ? (openBlock(), createElementBlock("div", _hoisted_8, [ createVNode(unref(IconLoading), { class: "o-rotating" }) ])) : isClearable.value ? (openBlock(), createElementBlock("div", { key: 1, class: "o-select-clear", onClick: clearClick }, [ createVNode(unref(IconClose), { class: "o-select-clear-icon" }) ])) : createCommentVNode("v-if", true), createElementVNode( "div", { class: normalizeClass(["o-select-arrow", { active: isSelecting.value }]) }, [ renderSlot(_ctx.$slots, "arrow", { active: isSelecting.value }, () => [ createVNode(unref(IconChevronDown)) ]) ], 2 /* CLASS */ ) ]), renderSlot(_ctx.$slots, "suffix", { active: isSelecting.value }) ]), createVNode(unref(ClientOnly), null, { default: withCtx(() => [ (openBlock(), createBlock(Teleport, { to: optionsRef.value, disabled: !optionsRef.value }, [ withDirectives(createElementVNode( "div", _hoisted_9, [ renderSlot(_ctx.$slots, "default", {}, () => [ createElementVNode("div", _hoisted_10, [ renderSlot(_ctx.$slots, "empty", {}, () => [ createElementVNode( "span", null, toDisplayString(unref(t)("common.empty")), 1 /* TEXT */ ) ]) ]) ]) ], 512 /* NEED_PATCH */ ), [ [vShow, optionsRef.value] ]) ], 8, ["to", "disabled"])), isResponding.value ? (openBlock(), createBlock(unref(ODialog), { key: 0, visible: isSelecting.value, "onUpdate:visible": _cache[1] || (_cache[1] = ($event) => isSelecting.value = $event), "before-show": props.beforeOptionsShow, "before-hide": props.beforeOptionsHide, "hide-close": "", class: normalizeClass(["o-select-dlg", { "is-loading": props.loading }]), "mask-close": !props.multiple, size: "small", scrollbar: false, onChange: onSelectDlgChange }, createSlots({ default: withCtx(() => [ createVNode(_sfc_main$1, { size: props.size, "wrap-class": props.optionWrapClass, loading: props.loading, class: "o-select-options-dlg", "option-title": props.optionTitle, multiple: props.multiple }, createSlots({ "option-target": withCtx(() => [ createElementVNode( "div", { ref_key: "optionsRef", ref: optionsRef }, null, 512 /* NEED_PATCH */ ) ]), _: 2 /* DYNAMIC */ }, [ renderList(unref(filterSlots)(_ctx.$slots, unref(slot).option.names), (name) => { return { name, fn: withCtx(() => [ renderSlot(_ctx.$slots, name) ]) }; }) ]), 1032, ["size", "wrap-class", "loading", "option-title", "multiple"]) ]), _: 2 /* DYNAMIC */ }, [ props.optionTitle ? { name: "header", fn: withCtx(() => [ createElementVNode( "div", _hoisted_11, toDisplayString(props.optionTitle), 1 /* TEXT */ ) ]), key: "0" } : void 0, props.multiple ? { name: "actions", fn: withCtx(() => [ createVNode(unref(OButton), { class: "o-dlg-btn", variant: "text", size: "large", onClick: onselectDlgCancelClick }, { default: withCtx(() => [ createTextVNode( toDisplayString(unref(t)("select.cancel")), 1 /* TEXT */ ) ]), _: 1 /* STABLE */ }), createVNode(unref(OButton), { class: "o-dlg-btn", variant: "text", size: "large", onClick: onselectDlgOkClick }, { default: withCtx(() => [ createTextVNode( toDisplayString(unref(t)("select.confirm")), 1 /* TEXT */ ) ]), _: 1 /* STABLE */ }) ]), key: "1" } : void 0 ]), 1032, ["visible", "before-show", "before-hide", "mask-close", "class"])) : (openBlock(), createElementBlock( Fragment, { key: 1 }, [ !props.disabled ? (openBlock(), createBlock(unref(OPopup), { key: 0, visible: isSelecting.value, "onUpdate:visible": _cache[2] || (_cache[2] = ($event) => isSelecting.value = $event), "wrap-class": "o-options-popup", transition: props.transition, "unmount-on-hide": props.unmountOnHide, position: props.optionPosition, wrapper: props.optionsWrapper, target: selectRef.value, trigger: props.trigger, offset: 4, "adjust-min-width": props.optionWidthMode === "min-width", "adjust-width": props.optionWidthMode === "width", "before-show": props.beforeOptionsShow, "before-hide": props.beforeOptionsHide, onChange: onOptionVisibleChange }, { default: withCtx(() => [ createVNode(_sfc_main$1, { size: props.size, "wrap-class": props.optionWrapClass, loading: props.loading, multiple: props.multiple }, createSlots({ "option-target": withCtx(() => [ createElementVNode( "div", { ref_key: "optionsRef", ref: optionsRef }, null, 512 /* NEED_PATCH */ ) ]), _: 2 /* DYNAMIC */ }, [ renderList(unref(filterSlots)(_ctx.$slots, unref(slot).option.names), (name) => { return { name, fn: withCtx(() => [ renderSlot(_ctx.$slots, name) ]) }; }) ]), 1032, ["size", "wrap-class", "loading", "multiple"]) ]), _: 3 /* FORWARDED */ }, 8, ["visible", "transition", "unmount-on-hide", "position", "wrapper", "target", "trigger", "adjust-min-width", "adjust-width", "before-show", "before-hide"])) : createCommentVNode("v-if", true) ], 64 /* STABLE_FRAGMENT */ )) ]), _: 3 /* FORWARDED */ }) ], 6 /* CLASS, STYLE */ ); }; } }); export { _sfc_main as default };