UNPKG

hongluan-ui

Version:
551 lines (548 loc) 20 kB
import { defineComponent, ref, computed, nextTick, watch, onMounted, resolveComponent, resolveDirective, openBlock, createBlock, withCtx, createElementVNode, renderSlot, withDirectives, createElementBlock, normalizeClass, normalizeStyle, withModifiers, createVNode, createSlots, Fragment, renderList, createTextVNode, toDisplayString, withKeys, vModelText, createCommentVNode } from 'vue'; import { isClient, useResizeObserver } from '@vueuse/core'; import { HlInput } from '../../input/index.mjs'; import { HlTooltip } from '../../tooltip/index.mjs'; import { HlIcon } from '../../icon/index.mjs'; import '../../system-icon/index.mjs'; import { HlTag } from '../../tag/index.mjs'; import '../../../directives/index.mjs'; import '../../popper/index.mjs'; import '../../../hooks/index.mjs'; import '../../../constants/index.mjs'; import '../../../utils/index.mjs'; import _export_sfc from '../../../_virtual/plugin-vue_export-helper.mjs'; import SystemSelectArrow from '../../system-icon/src/select-arrow.mjs'; import SystemClose from '../../system-icon/src/close.mjs'; import ClickOutside from '../../../directives/click-outside/index.mjs'; import { isValidComponentSize } from '../../../utils/vue/validator.mjs'; import { useTooltipContentProps } from '../../tooltip/src/content2.mjs'; import { tagProps } from '../../tag/src/tag2.mjs'; import { useNamespace } from '../../../hooks/use-namespace/index.mjs'; import { useLocale } from '../../../hooks/use-locale/index.mjs'; import { useDeprecateAppendToBody } from '../../popper/src/deprecation.mjs'; import { useComposition } from '../../../hooks/use-composition/index.mjs'; import { useConsistentProp } from '../../../hooks/use-consistent-prop/index.mjs'; import { EVENT_CODE } from '../../../constants/aria.mjs'; const _sfc_main = defineComponent({ name: "Selector", components: { HlInput, HlTooltip, HlTag, HlIcon, SystemSelectArrow, SystemClose }, directives: { Clickoutside: ClickOutside }, props: { size: { type: String, validator: isValidComponentSize }, placeholder: { type: String }, disabled: Boolean, clearable: Boolean, filterable: Boolean, collapseTags: Boolean, maxCollapseTags: { type: Number, default: 1 }, collapseTagsTooltip: { type: Boolean, default: false }, placement: { type: String, default: "bottom-start" }, fallbackPlacements: { type: Array, default: () => [] }, popperClass: { type: String, default: "" }, block: { type: Boolean, default: false }, inputStyle: { type: Object, default: () => ({}) }, multiple: { type: Boolean, default: false }, popperAppendToBody: { type: Boolean, default: void 0 }, teleported: useTooltipContentProps.teleported, fill: Boolean, round: Boolean, thin: Boolean, popperOffset: { type: Number, default: 4 }, persistent: { type: Boolean, default: true }, tagType: { ...tagProps.type, default: "" }, tagEffect: { type: String, default: "" } }, emits: [ "focus", "blur", "input", "resize", "after-leave", "keyboard-down", "visible-change", "popper-visible", "remove-tag", "clear" ], setup(props, { emit }) { const { namespace } = useNamespace("selector"); const { t } = useLocale(); const { compatTeleported } = useDeprecateAppendToBody("Selector", "popperAppendToBody"); const { isComposing, handleComposition } = useComposition({ afterComposition(event) { var _a; const text = (_a = event.target) == null ? void 0 : _a.value; handleInput(text); } }); let pressDeleteCount = 0; const popper = ref(null); const input = ref(null); const tagWrapper = ref(null); const panel = ref(null); const popperVisible = ref(false); const inputHover = ref(false); const inputValue = ref(""); const searchInputValue = ref(""); const presentTags = ref([]); const allPresentTags = ref([]); const presentText = ref(""); const checkedNodes = ref([]); const { size: realSize, disabled: isDisabled, fill: realFill } = useConsistentProp(); const readonly = computed(() => !props.filterable); const inputPlaceholder = computed(() => props.placeholder || t("hl.cascader.placeholder")); const clearBtnVisible = computed(() => { if (!props.clearable || isDisabled.value || !inputHover.value) return false; return props.multiple ? !!checkedNodes.value.length : !!presentText.value; }); const currentPlaceholder = computed(() => searchInputValue.value || presentTags.value.length > 0 ? "" : inputPlaceholder.value); const popperPaneRef = computed(() => { var _a, _b; return (_b = (_a = popper.value) == null ? void 0 : _a.popperRef) == null ? void 0 : _b.contentRef; }); const setValue = (val) => { if (Array.isArray(val)) { checkedNodes.value = [...val]; } else { presentText.value = val; } }; const afterLeave = () => { emit("after-leave"); }; const togglePopperVisible = (visible) => { var _a, _b; if (isDisabled.value) return; visible = visible != null ? visible : !popperVisible.value; if (visible !== popperVisible.value) { popperVisible.value = visible; (_b = (_a = input.value) == null ? void 0 : _a.input) == null ? void 0 : _b.setAttribute("aria-expanded", `${visible}`); if (visible) { updatePopperPosition(); nextTick(() => { emit("popper-visible"); }); } else if (props.filterable) { if (props.multiple) { searchInputValue.value = ""; } else { const { value } = presentText; inputValue.value = value; } emit("input", ""); } emit("visible-change", visible); } }; const updatePopperPosition = () => { var _a; nextTick((_a = popper.value) == null ? void 0 : _a.updatePopper); }; const genTag = (node) => { return { key: String(Math.random()), text: node, hitState: false, closable: !isDisabled.value, isCollapseTag: false }; }; const deleteTag = (tag) => { checkedNodes.value = checkedNodes.value.filter((cn) => cn !== tag.text); !checkedNodes.value.length && resetInput(); emit("remove-tag", tag); }; const calculatePresentTags = () => { if (!props.multiple) return; const nodes = checkedNodes.value; const tags = []; const allTags = []; nodes.forEach((node) => allTags.push(genTag(node))); allPresentTags.value = allTags; if (nodes.length) { nodes.slice(0, props.maxCollapseTags).forEach((node) => tags.push(genTag(node))); const rest = nodes.slice(props.maxCollapseTags); const restCount = rest.length; if (restCount) { if (props.collapseTags) { tags.push({ key: "-1", text: `+ ${restCount}`, closable: false, isCollapseTag: true }); } else { rest.forEach((node) => tags.push(genTag(node))); } } } presentTags.value = tags; }; const updateTags = (cb) => { presentTags.value.forEach(cb); allPresentTags.value.forEach(cb); }; const focusFirstNode = () => { emit("keyboard-down"); }; const updateStyle = () => { var _a; const inputInner = (_a = input.value) == null ? void 0 : _a.input; const tagWrapperEl = tagWrapper.value; if (!isClient || !inputInner) return; emit("resize", input.value.$el); if (tagWrapperEl) { updatePopperPosition(); } }; const handleKeyDown = (e) => { if (isComposing.value) return; switch (e.code) { case EVENT_CODE.enter: togglePopperVisible(); break; case EVENT_CODE.down: togglePopperVisible(true); nextTick(focusFirstNode); e.preventDefault(); break; case EVENT_CODE.esc: if (popperVisible.value === true) { e.preventDefault(); e.stopPropagation(); togglePopperVisible(false); } break; case EVENT_CODE.tab: togglePopperVisible(false); break; } }; const handleClear = () => { togglePopperVisible(false); emit("clear"); resetInput(); }; const resetInput = () => { checkedNodes.value = []; presentText.value = ""; inputValue.value = ""; searchInputValue.value = ""; }; const handleDelete = () => { const tags = presentTags.value; const lastTag = tags[tags.length - 1]; pressDeleteCount = searchInputValue.value ? 0 : pressDeleteCount + 1; if (!lastTag || !pressDeleteCount || props.collapseTags && tags.length > 1) return; if (lastTag.hitState) { deleteTag(lastTag); } else { lastTag.hitState = true; } }; const handleInput = (val, e) => { !popperVisible.value && togglePopperVisible(true); if (e == null ? void 0 : e.isComposing) return; emit("input", val); }; watch([checkedNodes, isDisabled, () => props.collapseTags], calculatePresentTags); watch(presentTags, () => { nextTick(() => updateStyle()); }); watch(presentText, (val) => inputValue.value = val, { immediate: true }); onMounted(() => { var _a; const inputEl = (_a = input.value) == null ? void 0 : _a.$el; useResizeObserver(inputEl, updateStyle); }); return { namespace, compatTeleported, popper, popperPaneRef, input, tagWrapper, panel, popperVisible, inputHover, presentText, checkedNodes, inputValue, inputPlaceholder, searchInputValue, currentPlaceholder, presentTags, allPresentTags, isDisabled, realSize, realFill, readonly, clearBtnVisible, setValue, afterLeave, t, togglePopperVisible, updatePopperPosition, deleteTag, updateTags, focusFirstNode, handleKeyDown, handleComposition, handleClear, handleDelete, handleInput }; } }); function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { const _component_hl_tag = resolveComponent("hl-tag"); const _component_hl_tooltip = resolveComponent("hl-tooltip"); const _component_system_select_arrow = resolveComponent("system-select-arrow"); const _component_hl_icon = resolveComponent("hl-icon"); const _component_system_close = resolveComponent("system-close"); const _component_hl_input = resolveComponent("hl-input"); const _directive_clickoutside = resolveDirective("clickoutside"); return openBlock(), createBlock(_component_hl_tooltip, { ref: "popper", visible: _ctx.popperVisible, teleported: _ctx.compatTeleported, offset: _ctx.popperOffset, placement: _ctx.placement, "popper-class": `${_ctx.namespace}-popper ${_ctx.popperClass}`, "fallback-placements": _ctx.fallbackPlacements, "stop-popper-mouse-event": false, "show-arrow": false, transition: "dropdown", "gpu-acceleration": false, persistent: _ctx.persistent, onHide: _ctx.afterLeave }, { content: withCtx(() => [ createElementVNode("div", { class: "selector-dropdown" }, [ renderSlot(_ctx.$slots, "default") ]) ]), default: withCtx(() => [ withDirectives((openBlock(), createElementBlock("div", { class: normalizeClass([ _ctx.namespace, _ctx.realSize && `cascader-${_ctx.realSize}`, { "is-disabled": _ctx.isDisabled, "block": _ctx.block }, _ctx.$attrs.class ]), style: normalizeStyle(_ctx.$attrs.style), onClick: [ () => _ctx.togglePopperVisible(_ctx.readonly ? void 0 : true), withModifiers(() => { }, ["stop"]) ], onKeydown: _ctx.handleKeyDown, onMouseenter: ($event) => _ctx.inputHover = true, onMouseleave: ($event) => _ctx.inputHover = false }, [ createVNode(_component_hl_input, { ref: "input", modelValue: _ctx.inputValue, "onUpdate:modelValue": ($event) => _ctx.inputValue = $event, placeholder: _ctx.currentPlaceholder, readonly: _ctx.readonly, disabled: _ctx.isDisabled, "validate-event": false, fill: _ctx.realFill, thin: _ctx.thin, round: _ctx.round, size: _ctx.realSize, class: normalizeClass({ "is-focus": _ctx.popperVisible, "is-tags": _ctx.presentTags.length }), "input-style": _ctx.inputStyle, onCompositionstart: _ctx.handleComposition, onCompositionupdate: _ctx.handleComposition, onCompositionend: _ctx.handleComposition, onFocus: (e) => _ctx.$emit("focus", e), onBlur: (e) => _ctx.$emit("blur", e), onInput: _ctx.handleInput }, createSlots({ suffix: withCtx(() => [ createVNode(_component_hl_icon, { class: normalizeClass(["select-caret", _ctx.popperVisible ? "is-open" : "", !_ctx.clearBtnVisible ? "visible" : ""]), onClick: withModifiers(($event) => _ctx.togglePopperVisible(), ["stop"]) }, { default: withCtx(() => [ createVNode(_component_system_select_arrow) ]), _: 1 }, 8, ["class", "onClick"]), createVNode(_component_hl_icon, { key: "clear", class: normalizeClass(["select-close", _ctx.clearBtnVisible ? "visible" : ""]), onClick: withModifiers(_ctx.handleClear, ["stop"]) }, { default: withCtx(() => [ createVNode(_component_system_close) ]), _: 1 }, 8, ["class", "onClick"]) ]), _: 2 }, [ _ctx.multiple ? { name: "tags", fn: withCtx(() => [ _ctx.presentTags.length ? (openBlock(), createElementBlock("div", { key: 0, ref: "tagWrapper", class: "input-tags" }, [ (openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.presentTags, (tag) => { return openBlock(), createBlock(_component_hl_tag, { key: tag.key, type: _ctx.tagType, effect: _ctx.tagEffect, active: tag.hitState, closable: tag.closable, size: _ctx.realSize, "disable-transitions": "", onClose: ($event) => _ctx.deleteTag(tag) }, { default: withCtx(() => [ tag.isCollapseTag === false ? renderSlot(_ctx.$slots, "tag", { key: 0, tag }, () => [ createTextVNode(toDisplayString(tag.text), 1) ]) : (openBlock(), createBlock(_component_hl_tooltip, { key: 1, disabled: _ctx.popperVisible || !_ctx.collapseTagsTooltip, "fallback-placements": ["bottom", "top", "right", "left"], placement: "bottom", "show-arrow": false, "popper-class": `collapse-tags-popper` }, { default: withCtx(() => [ renderSlot(_ctx.$slots, "tag", { tag }, () => [ createTextVNode(toDisplayString(tag.text), 1) ]) ]), content: withCtx(() => [ createElementVNode("div", { class: "collapse-tags" }, [ (openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.allPresentTags.slice(_ctx.maxCollapseTags), (tag2) => { return openBlock(), createBlock(_component_hl_tag, { key: tag2.key, class: "in-tooltip collapse-tag", type: _ctx.tagType, effect: _ctx.tagEffect, size: _ctx.realSize, hit: tag2.hitState, closable: tag2.closable, "disable-transitions": "", onClose: ($event) => _ctx.deleteTag(tag2) }, { default: withCtx(() => [ renderSlot(_ctx.$slots, "collapse-tag", { tag: tag2 }, () => [ createTextVNode(toDisplayString(tag2.text), 1) ]) ]), _: 2 }, 1032, ["type", "effect", "size", "hit", "closable", "onClose"]); }), 128)) ]) ]), _: 2 }, 1032, ["disabled"])) ]), _: 2 }, 1032, ["type", "effect", "active", "closable", "size", "onClose"]); }), 128)), _ctx.filterable && !_ctx.isDisabled ? withDirectives((openBlock(), createElementBlock("input", { key: 0, "onUpdate:modelValue": ($event) => _ctx.searchInputValue = $event, type: "text", class: "selector-input", onInput: (e) => _ctx.handleInput(_ctx.searchInputValue, e), onClick: withModifiers(($event) => _ctx.togglePopperVisible(true), ["stop"]), onKeydown: withKeys(_ctx.handleDelete, ["delete"]), onCompositionstart: _ctx.handleComposition, onCompositionupdate: _ctx.handleComposition, onCompositionend: _ctx.handleComposition }, null, 40, ["onUpdate:modelValue", "onInput", "onClick", "onKeydown", "onCompositionstart", "onCompositionupdate", "onCompositionend"])), [ [vModelText, _ctx.searchInputValue] ]) : createCommentVNode("v-if", true) ], 512)) : createCommentVNode("v-if", true) ]) } : void 0, _ctx.$slots.prefix ? { name: "prefix", fn: withCtx(() => [ renderSlot(_ctx.$slots, "prefix") ]) } : void 0 ]), 1032, ["modelValue", "onUpdate:modelValue", "placeholder", "readonly", "disabled", "fill", "thin", "round", "size", "class", "input-style", "onCompositionstart", "onCompositionupdate", "onCompositionend", "onFocus", "onBlur", "onInput"]) ], 46, ["onClick", "onKeydown", "onMouseenter", "onMouseleave"])), [ [_directive_clickoutside, () => _ctx.togglePopperVisible(false), _ctx.popperPaneRef] ]) ]), _: 3 }, 8, ["visible", "teleported", "offset", "placement", "popper-class", "fallback-placements", "persistent", "onHide"]); } var Selector = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render]]); export { Selector as default }; //# sourceMappingURL=index.mjs.map