UNPKG

mldong-flow-designer-plus

Version:

本项目包含了作者为B站课堂视频[《工作流设计器开发最佳实践》](https://www.bilibili.com/cheese/play/ss24484)的过程源码。教程中开发的组件也可用于实际生产环境中。以下是和使用文档和课程章节说明。 ## 实战项目 [演示地址](https://flow-pro.mldong.com/)

1,478 lines 93.2 kB
import { k as isArray, a as buildProps, F as throwError, t as isObject, L as useNamespace, p as isFocusable, s as isNumber, g as definePropType, m as isClient, f as debugWarn, P as withInstall, n as isElement, N as NOOP, o as isEmpty, z as isUndefined, q as isFunction, v as isPlainObject, J as useDebounceFn, r as isIOS, x as isString, R as withNoopInstall } from "./error-DEV4o0cD.js"; import { _ as _plugin_vue_export_helper_default } from "./index-Bjjqy_0d.js"; import { u as useId } from "./index-D7GCrely.js"; import { isVNode, inject, computed, getCurrentInstance, toRaw, watch, defineComponent, unref, reactive, toRefs, onBeforeUnmount, nextTick, withDirectives, openBlock, createElementBlock, withModifiers, normalizeClass, renderSlot, createElementVNode, toDisplayString, vShow, ref, provide, onMounted, shallowRef, toRef, createBlock, Transition, withCtx, normalizeStyle, Fragment, createVNode, onActivated, onUpdated, resolveDynamicComponent, createCommentVNode, useSlots, watchEffect, resolveComponent, resolveDirective, mergeProps, toHandlerKey, renderList, createTextVNode } from "vue"; import { c as castArray, j as get, m as isEqual, n as isNil, d as clamp, h as findLastIndex } from "./index-C41_Bymr.js"; import { C as CHANGE_EVENT, U as UPDATE_MODEL_EVENT } from "./event-BZTOGHfp.js"; import { b as arrow_down_default, i as iconPropType, c as circle_close_default, E as ElIcon, d as close_default, V as ValidateComponentsMap } from "./index-D0I3i9fl.js"; import { c as componentSizes, d as useSizeProp, b as addUnit } from "./style-D2s_cWsv.js"; import { a as useEmptyValuesProps, b as useLocale, u as useEmptyValues } from "./index-BbcOBREW.js"; import { u as useAriaProps } from "./index-E3-NBeOi.js"; import { u as useTooltipContentProps, E as Ee, a as ElTooltip } from "./index-ChSanhjG.js"; import { b as useMutationObserver, c as useResizeObserver, a as useEventListener } from "./index-rPPo0srK.js"; import { c as useFormSize, a as useFormItem, b as useFormItemInputId, u as useFormDisabled } from "./use-form-item-DkmO9Upg.js"; import { g as getEventCode, E as EVENT_CODE } from "./event-bJhzntMi.js"; import { s as scrollIntoView } from "./scroll-CYVj_8on.js"; import { u as useComposition, a as useFocusController } from "./index-D5q4e_u4.js"; const escapeStringRegexp = (string = "") => string.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&").replace(/-/g, "\\x2d"); const flattedChildren = (children) => { const vNodes = isArray(children) ? children : [children]; const result = []; vNodes.forEach((child) => { var _a; if (isArray(child)) result.push(...flattedChildren(child)); else if (isVNode(child) && ((_a = child.component) == null ? void 0 : _a.subTree)) result.push(child, ...flattedChildren(child.component.subTree)); else if (isVNode(child) && isArray(child.children)) result.push(...flattedChildren(child.children)); else if (isVNode(child) && child.shapeFlag === 2) result.push(...flattedChildren(child.type())); else result.push(child); }); return result; }; const selectGroupKey = Symbol("ElSelectGroup"); const selectKey = Symbol("ElSelect"); const COMPONENT_NAME$3 = "ElOption"; const optionProps = buildProps({ /** * @description value of option */ value: { type: [ String, Number, Boolean, Object ], required: true }, /** * @description label of option, same as `value` if omitted */ label: { type: [String, Number] }, created: Boolean, /** * @description whether option is disabled */ disabled: Boolean }); function useOption(props, states) { const select = inject(selectKey); if (!select) throwError(COMPONENT_NAME$3, "usage: <el-select><el-option /></el-select/>"); const selectGroup = inject(selectGroupKey, { disabled: false }); const itemSelected = computed(() => { return contains(castArray(select.props.modelValue), props.value); }); const limitReached = computed(() => { if (select.props.multiple) { const modelValue = castArray(select.props.modelValue ?? []); return !itemSelected.value && modelValue.length >= select.props.multipleLimit && select.props.multipleLimit > 0; } else return false; }); const currentLabel = computed(() => { return props.label ?? (isObject(props.value) ? "" : props.value); }); const currentValue = computed(() => { return props.value || props.label || ""; }); const isDisabled = computed(() => { return props.disabled || states.groupDisabled || limitReached.value; }); const instance = getCurrentInstance(); const contains = (arr = [], target) => { if (!isObject(props.value)) return arr && arr.includes(target); else { const valueKey = select.props.valueKey; return arr && arr.some((item) => { return toRaw(get(item, valueKey)) === get(target, valueKey); }); } }; const hoverItem = () => { if (!isDisabled.value) select.states.hoveringIndex = select.optionsArray.indexOf(instance.proxy); }; const updateOption = (query) => { states.visible = new RegExp(escapeStringRegexp(query), "i").test(String(currentLabel.value)) || props.created; }; watch(() => currentLabel.value, () => { if (!props.created && !select.props.remote) select.setSelected(); }); watch(() => props.value, (val, oldVal) => { const { remote, valueKey } = select.props; if (remote ? val !== oldVal : !isEqual(val, oldVal)) { select.onOptionDestroy(oldVal, instance.proxy); select.onOptionCreate(instance.proxy); } if (!props.created && !remote) { if (valueKey && isObject(val) && isObject(oldVal) && val[valueKey] === oldVal[valueKey]) return; select.setSelected(); } }); watch(() => selectGroup.disabled, () => { states.groupDisabled = selectGroup.disabled; }, { immediate: true }); return { select, currentLabel, currentValue, itemSelected, isDisabled, hoverItem, updateOption }; } var option_vue_vue_type_script_lang_default = defineComponent({ name: COMPONENT_NAME$3, componentName: COMPONENT_NAME$3, props: optionProps, setup(props) { const ns = useNamespace("select"); const id = useId(); const containerKls = computed(() => [ ns.be("dropdown", "item"), ns.is("disabled", unref(isDisabled)), ns.is("selected", unref(itemSelected)), ns.is("hovering", unref(hover)) ]); const states = reactive({ index: -1, groupDisabled: false, visible: true, hover: false }); const { currentLabel, itemSelected, isDisabled, select, hoverItem, updateOption } = useOption(props, states); const { visible, hover } = toRefs(states); const vm = getCurrentInstance().proxy; select.onOptionCreate(vm); onBeforeUnmount(() => { const key = vm.value; nextTick(() => { const { selected: selectedOptions } = select.states; const doesSelected = selectedOptions.some((item) => { return item.value === vm.value; }); if (select.states.cachedOptions.get(key) === vm && !doesSelected) select.states.cachedOptions.delete(key); }); select.onOptionDestroy(key, vm); }); function selectOptionClick() { if (!isDisabled.value) select.handleOptionSelect(vm); } const handleMousedown = (event) => { let target = event.target; const currentTarget = event.currentTarget; while (target && target !== currentTarget) { if (isFocusable(target)) return; target = target.parentElement; } event.preventDefault(); }; return { ns, id, containerKls, currentLabel, itemSelected, isDisabled, select, visible, hover, states, hoverItem, handleMousedown, updateOption, selectOptionClick }; } }); const _hoisted_1$3 = [ "id", "aria-disabled", "aria-selected" ]; function _sfc_render$3(_ctx, _cache, $props, $setup, $data, $options) { return withDirectives((openBlock(), createElementBlock("li", { id: _ctx.id, class: normalizeClass(_ctx.containerKls), role: "option", "aria-disabled": _ctx.isDisabled || void 0, "aria-selected": _ctx.itemSelected, onMousemove: _cache[0] || (_cache[0] = (...args) => _ctx.hoverItem && _ctx.hoverItem(...args)), onMousedown: _cache[1] || (_cache[1] = (...args) => _ctx.handleMousedown && _ctx.handleMousedown(...args)), onClick: _cache[2] || (_cache[2] = withModifiers((...args) => _ctx.selectOptionClick && _ctx.selectOptionClick(...args), ["stop"])) }, [renderSlot(_ctx.$slots, "default", {}, () => [createElementVNode("span", null, toDisplayString(_ctx.currentLabel), 1)])], 42, _hoisted_1$3)), [[vShow, _ctx.visible]]); } var option_default = /* @__PURE__ */ _plugin_vue_export_helper_default(option_vue_vue_type_script_lang_default, [["render", _sfc_render$3]]); const scrollbarProps = buildProps({ /** * @description trigger distance(px) */ distance: { type: Number, default: 0 }, /** * @description height of scrollbar */ height: { type: [String, Number], default: "" }, /** * @description max height of scrollbar */ maxHeight: { type: [String, Number], default: "" }, /** * @description whether to use the native scrollbar */ native: Boolean, /** * @description style of wrap */ wrapStyle: { type: definePropType([ String, Object, Array, Boolean ]), default: "" }, /** * @description class of wrap */ wrapClass: { type: [String, Array], default: "" }, /** * @description class of view */ viewClass: { type: [String, Array], default: "" }, /** * @description style of view */ viewStyle: { type: definePropType([ String, Object, Array, Boolean ]), default: "" }, /** * @description do not respond to container size changes, if the container size does not change, it is better to set it to optimize performance */ noresize: Boolean, /** * @description element tag of the view */ tag: { type: String, default: "div" }, /** * @description always show */ always: Boolean, /** * @description minimum size of scrollbar */ minSize: { type: Number, default: 20 }, /** * @description Wrap tabindex */ tabindex: { type: [String, Number], default: void 0 }, /** * @description id of view */ id: String, /** * @description role of view */ role: String, ...useAriaProps(["ariaLabel", "ariaOrientation"]) }); const scrollbarEmits = { "end-reached": (direction) => [ "left", "right", "top", "bottom" ].includes(direction), scroll: ({ scrollTop, scrollLeft }) => [scrollTop, scrollLeft].every(isNumber) }; const tagProps = buildProps({ /** * @description type of Tag */ type: { type: String, values: [ "primary", "success", "info", "warning", "danger" ], default: "primary" }, /** * @description whether Tag can be removed */ closable: Boolean, /** * @description whether to disable animations */ disableTransitions: Boolean, /** * @description whether Tag has a highlighted border */ hit: Boolean, /** * @description background color of the Tag */ color: String, /** * @description size of Tag */ size: { type: String, values: componentSizes }, /** * @description theme of Tag */ effect: { type: String, values: [ "dark", "light", "plain" ], default: "light" }, /** * @description whether Tag is rounded */ round: Boolean }); const tagEmits = { close: (evt) => evt instanceof MouseEvent, click: (evt) => evt instanceof MouseEvent }; const defaultProps = { label: "label", value: "value", disabled: "disabled", options: "options" }; function useProps(props) { const aliasProps = ref({ ...defaultProps, ...props.props }); let cache = { ...props.props }; watch(() => props.props, (val) => { if (!isEqual(val, cache)) { aliasProps.value = { ...defaultProps, ...val }; cache = { ...val }; } }, { deep: true }); const getLabel = (option) => get(option, aliasProps.value.label); const getValue = (option) => get(option, aliasProps.value.value); const getDisabled = (option) => get(option, aliasProps.value.disabled); const getOptions = (option) => get(option, aliasProps.value.options); return { aliasProps, getLabel, getValue, getDisabled, getOptions }; } const selectProps = buildProps({ /** * @description the name attribute of select input */ name: String, /** * @description native input id */ id: String, /** * @description binding value */ modelValue: { type: definePropType([ Array, String, Number, Boolean, Object ]), default: void 0 }, /** * @description the autocomplete attribute of select input */ autocomplete: { type: String, default: "off" }, /** * @description for non-filterable Select, this prop decides if the option menu pops up when the input is focused */ automaticDropdown: Boolean, /** * @description size of Input */ size: useSizeProp, /** * @description tooltip theme, built-in theme: `dark` / `light` */ effect: { type: definePropType(String), default: "light" }, /** * @description whether Select is disabled */ disabled: { type: Boolean, default: void 0 }, /** * @description whether select can be cleared */ clearable: Boolean, /** * @description whether Select is filterable */ filterable: Boolean, /** * @description whether creating new items is allowed. To use this, `filterable` must be true */ allowCreate: Boolean, /** * @description whether Select is loading data from server */ loading: Boolean, /** * @description custom class name for Select's dropdown */ popperClass: { type: String, default: "" }, /** * @description custom style for Select's dropdown */ popperStyle: { type: definePropType([String, Object]) }, /** * @description [popper.js](https://popper.js.org/docs/v2/) parameters */ popperOptions: { type: definePropType(Object), default: () => ({}) }, /** * @description whether options are loaded from server */ remote: Boolean, /** * @description debounce delay during remote search, in milliseconds */ debounce: { type: Number, default: 300 }, /** * @description displayed text while loading data from server, default is 'Loading' */ loadingText: String, /** * @description displayed text when no data matches the filtering query, you can also use slot `empty`, default is 'No matching data' */ noMatchText: String, /** * @description displayed text when there is no options, you can also use slot `empty`, default is 'No data' */ noDataText: String, /** * @description function that gets called when the input value changes. Its parameter is the current input value. To use this, `filterable` must be true */ remoteMethod: { type: definePropType(Function) }, /** * @description custom filter method, the first parameter is the current input value. To use this, `filterable` must be true */ filterMethod: { type: definePropType(Function) }, /** * @description whether multiple-select is activated */ multiple: Boolean, /** * @description maximum number of options user can select when `multiple` is `true`. No limit when set to 0 */ multipleLimit: { type: Number, default: 0 }, /** * @description placeholder, default is 'Select' */ placeholder: { type: String }, /** * @description select first matching option on enter key. Use with `filterable` or `remote` */ defaultFirstOption: Boolean, /** * @description when `multiple` and `filter` is true, whether to reserve current keyword after selecting an option */ reserveKeyword: { type: Boolean, default: true }, /** * @description unique identity key name for value, required when value is an object */ valueKey: { type: String, default: "value" }, /** * @description whether to collapse tags to a text when multiple selecting */ collapseTags: Boolean, /** * @description whether show all selected tags when mouse hover text of collapse-tags. To use this, `collapse-tags` must be true */ collapseTagsTooltip: Boolean, /** * @description configuration object for the collapse-tags tooltip. To use this, `collapse-tags` and `collapse-tags-tooltip` must be true */ tagTooltip: { type: definePropType(Object), default: () => ({}) }, /** * @description the max tags number to be shown. To use this, `collapse-tags` must be true */ maxCollapseTags: { type: Number, default: 1 }, /** * @description whether select dropdown is teleported, if `true` it will be teleported to where `append-to` sets */ teleported: useTooltipContentProps.teleported, /** * @description when select dropdown is inactive and `persistent` is `false`, select dropdown will be destroyed */ persistent: { type: Boolean, default: true }, /** * @description custom clear icon component */ clearIcon: { type: iconPropType, default: circle_close_default }, /** * @description whether the width of the dropdown is the same as the input */ fitInputWidth: Boolean, /** * @description custom suffix icon component */ suffixIcon: { type: iconPropType, default: arrow_down_default }, /** * @description tag type */ tagType: { ...tagProps.type, default: "info" }, /** * @description tag effect */ tagEffect: { ...tagProps.effect, default: "light" }, /** * @description whether to trigger form validation */ validateEvent: { type: Boolean, default: true }, /** * @description in remote search method show suffix icon */ remoteShowSuffix: Boolean, /** * @description determines whether the arrow is displayed */ showArrow: { type: Boolean, default: true }, /** * @description offset of the dropdown */ offset: { type: Number, default: 12 }, /** * @description position of dropdown */ placement: { type: definePropType(String), values: Ee, default: "bottom-start" }, /** * @description list of possible positions for dropdown */ fallbackPlacements: { type: definePropType(Array), default: [ "bottom-start", "top-start", "right", "left" ] }, /** * @description tabindex for input */ tabindex: { type: [String, Number], default: 0 }, /** * @description which element the selection dropdown appends to */ appendTo: useTooltipContentProps.appendTo, options: { type: definePropType(Array) }, props: { type: definePropType(Object), default: () => defaultProps }, ...useEmptyValuesProps, ...useAriaProps(["ariaLabel"]) }); const selectEmits = { [UPDATE_MODEL_EVENT]: (val) => true, [CHANGE_EVENT]: (val) => true, "popup-scroll": scrollbarEmits.scroll, "end-reached": scrollbarEmits["end-reached"], "remove-tag": (val) => true, "visible-change": (visible) => true, focus: (evt) => evt instanceof FocusEvent, blur: (evt) => evt instanceof FocusEvent, clear: () => true }; var option_group_vue_vue_type_script_lang_default = defineComponent({ name: "ElOptionGroup", componentName: "ElOptionGroup", props: { /** * @description name of the group */ label: String, /** * @description whether to disable all options in this group */ disabled: Boolean }, setup(props) { const ns = useNamespace("select"); const groupRef = ref(); const instance = getCurrentInstance(); const children = ref([]); provide(selectGroupKey, reactive({ ...toRefs(props) })); const visible = computed(() => children.value.some((option) => option.visible === true)); const isOption = (node) => { var _a; return node.type.name === "ElOption" && !!((_a = node.component) == null ? void 0 : _a.proxy); }; const flattedChildren2 = (node) => { const nodes = castArray(node); const children2 = []; nodes.forEach((child) => { var _a; if (!isVNode(child)) return; if (isOption(child)) children2.push(child.component.proxy); else if (isArray(child.children) && child.children.length) children2.push(...flattedChildren2(child.children)); else if ((_a = child.component) == null ? void 0 : _a.subTree) children2.push(...flattedChildren2(child.component.subTree)); }); return children2; }; const updateChildren = () => { children.value = flattedChildren2(instance.subTree); }; onMounted(() => { updateChildren(); }); useMutationObserver(groupRef, updateChildren, { attributes: true, subtree: true, childList: true }); return { groupRef, visible, ns }; } }); function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) { return withDirectives((openBlock(), createElementBlock("ul", { ref: "groupRef", class: normalizeClass(_ctx.ns.be("group", "wrap")) }, [createElementVNode("li", { class: normalizeClass(_ctx.ns.be("group", "title")) }, toDisplayString(_ctx.label), 3), createElementVNode("li", null, [createElementVNode("ul", { class: normalizeClass(_ctx.ns.b("group")) }, [renderSlot(_ctx.$slots, "default")], 2)])], 2)), [[vShow, _ctx.visible]]); } var option_group_default = /* @__PURE__ */ _plugin_vue_export_helper_default(option_group_vue_vue_type_script_lang_default, [["render", _sfc_render$2]]); function useCalcInputWidth() { const calculatorRef = shallowRef(); const calculatorWidth = ref(0); const inputStyle = computed(() => ({ minWidth: `${Math.max(calculatorWidth.value, 11)}px` })); const resetCalculatorWidth = () => { var _a; calculatorWidth.value = ((_a = calculatorRef.value) == null ? void 0 : _a.getBoundingClientRect().width) ?? 0; }; useResizeObserver(calculatorRef, resetCalculatorWidth); return { calculatorRef, calculatorWidth, inputStyle }; } const BAR_MAP = { vertical: { offset: "offsetHeight", scroll: "scrollTop", scrollSize: "scrollHeight", size: "height", key: "vertical", axis: "Y", client: "clientY", direction: "top" }, horizontal: { offset: "offsetWidth", scroll: "scrollLeft", scrollSize: "scrollWidth", size: "width", key: "horizontal", axis: "X", client: "clientX", direction: "left" } }; const renderThumbStyle = ({ move, size, bar }) => ({ [bar.size]: size, transform: `translate${bar.axis}(${move}%)` }); const thumbProps = buildProps({ vertical: Boolean, size: String, move: Number, ratio: { type: Number, required: true }, always: Boolean }); const scrollbarContextKey = Symbol("scrollbarContextKey"); function isGreaterThan(a, b, epsilon = 0.03) { return a - b > epsilon; } const barProps = buildProps({ always: { type: Boolean, default: true }, minSize: { type: Number, required: true } }); const COMPONENT_NAME$2 = "Thumb"; var thumb_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({ __name: "thumb", props: thumbProps, setup(__props) { const props = __props; const scrollbar = inject(scrollbarContextKey); const ns = useNamespace("scrollbar"); if (!scrollbar) throwError(COMPONENT_NAME$2, "can not inject scrollbar context"); const instance = ref(); const thumb = ref(); const thumbState = ref({}); const visible = ref(false); let cursorDown = false; let cursorLeave = false; let baseScrollHeight = 0; let baseScrollWidth = 0; let originalOnSelectStart = isClient ? document.onselectstart : null; const bar = computed(() => BAR_MAP[props.vertical ? "vertical" : "horizontal"]); const thumbStyle = computed(() => renderThumbStyle({ size: props.size, move: props.move, bar: bar.value })); const offsetRatio = computed(() => instance.value[bar.value.offset] ** 2 / scrollbar.wrapElement[bar.value.scrollSize] / props.ratio / thumb.value[bar.value.offset]); const clickThumbHandler = (e) => { var _a; e.stopPropagation(); if (e.ctrlKey || [1, 2].includes(e.button)) return; (_a = window.getSelection()) == null ? void 0 : _a.removeAllRanges(); startDrag(e); const el = e.currentTarget; if (!el) return; thumbState.value[bar.value.axis] = el[bar.value.offset] - (e[bar.value.client] - el.getBoundingClientRect()[bar.value.direction]); }; const clickTrackHandler = (e) => { if (!thumb.value || !instance.value || !scrollbar.wrapElement) return; const thumbPositionPercentage = (Math.abs(e.target.getBoundingClientRect()[bar.value.direction] - e[bar.value.client]) - thumb.value[bar.value.offset] / 2) * 100 * offsetRatio.value / instance.value[bar.value.offset]; scrollbar.wrapElement[bar.value.scroll] = thumbPositionPercentage * scrollbar.wrapElement[bar.value.scrollSize] / 100; }; const startDrag = (e) => { e.stopImmediatePropagation(); cursorDown = true; baseScrollHeight = scrollbar.wrapElement.scrollHeight; baseScrollWidth = scrollbar.wrapElement.scrollWidth; document.addEventListener("mousemove", mouseMoveDocumentHandler); document.addEventListener("mouseup", mouseUpDocumentHandler); originalOnSelectStart = document.onselectstart; document.onselectstart = () => false; }; const mouseMoveDocumentHandler = (e) => { if (!instance.value || !thumb.value) return; if (cursorDown === false) return; const prevPage = thumbState.value[bar.value.axis]; if (!prevPage) return; const thumbPositionPercentage = ((instance.value.getBoundingClientRect()[bar.value.direction] - e[bar.value.client]) * -1 - (thumb.value[bar.value.offset] - prevPage)) * 100 * offsetRatio.value / instance.value[bar.value.offset]; if (bar.value.scroll === "scrollLeft") scrollbar.wrapElement[bar.value.scroll] = thumbPositionPercentage * baseScrollWidth / 100; else scrollbar.wrapElement[bar.value.scroll] = thumbPositionPercentage * baseScrollHeight / 100; }; const mouseUpDocumentHandler = () => { cursorDown = false; thumbState.value[bar.value.axis] = 0; document.removeEventListener("mousemove", mouseMoveDocumentHandler); document.removeEventListener("mouseup", mouseUpDocumentHandler); restoreOnselectstart(); if (cursorLeave) visible.value = false; }; const mouseMoveScrollbarHandler = () => { cursorLeave = false; visible.value = !!props.size; }; const mouseLeaveScrollbarHandler = () => { cursorLeave = true; visible.value = cursorDown; }; onBeforeUnmount(() => { restoreOnselectstart(); document.removeEventListener("mouseup", mouseUpDocumentHandler); }); const restoreOnselectstart = () => { if (document.onselectstart !== originalOnSelectStart) document.onselectstart = originalOnSelectStart; }; useEventListener(toRef(scrollbar, "scrollbarElement"), "mousemove", mouseMoveScrollbarHandler); useEventListener(toRef(scrollbar, "scrollbarElement"), "mouseleave", mouseLeaveScrollbarHandler); return (_ctx, _cache) => { return openBlock(), createBlock(Transition, { name: unref(ns).b("fade"), persisted: "" }, { default: withCtx(() => [withDirectives(createElementVNode("div", { ref_key: "instance", ref: instance, class: normalizeClass([unref(ns).e("bar"), unref(ns).is(bar.value.key)]), onMousedown: clickTrackHandler, onClick: _cache[0] || (_cache[0] = withModifiers(() => { }, ["stop"])) }, [createElementVNode("div", { ref_key: "thumb", ref: thumb, class: normalizeClass(unref(ns).e("thumb")), style: normalizeStyle(thumbStyle.value), onMousedown: clickThumbHandler }, null, 38)], 34), [[vShow, __props.always || visible.value]])]), _: 1 }, 8, ["name"]); }; } }); var thumb_default = thumb_vue_vue_type_script_setup_true_lang_default; var bar_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({ __name: "bar", props: barProps, setup(__props, { expose: __expose }) { const props = __props; const scrollbar = inject(scrollbarContextKey); const moveX = ref(0); const moveY = ref(0); const sizeWidth = ref(""); const sizeHeight = ref(""); const ratioY = ref(1); const ratioX = ref(1); const handleScroll = (wrap) => { if (wrap) { const offsetHeight = wrap.offsetHeight - 4; const offsetWidth = wrap.offsetWidth - 4; moveY.value = wrap.scrollTop * 100 / offsetHeight * ratioY.value; moveX.value = wrap.scrollLeft * 100 / offsetWidth * ratioX.value; } }; const update = () => { const wrap = scrollbar == null ? void 0 : scrollbar.wrapElement; if (!wrap) return; const offsetHeight = wrap.offsetHeight - 4; const offsetWidth = wrap.offsetWidth - 4; const originalHeight = offsetHeight ** 2 / wrap.scrollHeight; const originalWidth = offsetWidth ** 2 / wrap.scrollWidth; const height = Math.max(originalHeight, props.minSize); const width = Math.max(originalWidth, props.minSize); ratioY.value = originalHeight / (offsetHeight - originalHeight) / (height / (offsetHeight - height)); ratioX.value = originalWidth / (offsetWidth - originalWidth) / (width / (offsetWidth - width)); sizeHeight.value = height + 4 < offsetHeight ? `${height}px` : ""; sizeWidth.value = width + 4 < offsetWidth ? `${width}px` : ""; }; __expose({ handleScroll, update }); return (_ctx, _cache) => { return openBlock(), createElementBlock(Fragment, null, [createVNode(thumb_default, { move: moveX.value, ratio: ratioX.value, size: sizeWidth.value, always: __props.always }, null, 8, [ "move", "ratio", "size", "always" ]), createVNode(thumb_default, { move: moveY.value, ratio: ratioY.value, size: sizeHeight.value, vertical: "", always: __props.always }, null, 8, [ "move", "ratio", "size", "always" ])], 64); }; } }); var bar_default = bar_vue_vue_type_script_setup_true_lang_default; const _hoisted_1$2 = ["tabindex"]; const COMPONENT_NAME$1 = "ElScrollbar"; var scrollbar_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({ name: COMPONENT_NAME$1, __name: "scrollbar", props: scrollbarProps, emits: scrollbarEmits, setup(__props, { expose: __expose, emit: __emit }) { const props = __props; const emit = __emit; const ns = useNamespace("scrollbar"); let stopResizeObserver = void 0; let stopWrapResizeObserver = void 0; let stopResizeListener = void 0; let wrapScrollTop = 0; let wrapScrollLeft = 0; let direction = ""; const distanceScrollState = { bottom: false, top: false, right: false, left: false }; const scrollbarRef = ref(); const wrapRef = ref(); const resizeRef = ref(); const barRef = ref(); const wrapStyle = computed(() => { const style = {}; const height = addUnit(props.height); const maxHeight = addUnit(props.maxHeight); if (height) style.height = height; if (maxHeight) style.maxHeight = maxHeight; return [props.wrapStyle, style]; }); const wrapKls = computed(() => { return [ props.wrapClass, ns.e("wrap"), { [ns.em("wrap", "hidden-default")]: !props.native } ]; }); const resizeKls = computed(() => { return [ns.e("view"), props.viewClass]; }); const shouldSkipDirection = (direction2) => { return distanceScrollState[direction2] ?? false; }; const DIRECTION_PAIRS = { top: "bottom", bottom: "top", left: "right", right: "left" }; const updateTriggerStatus = (arrivedStates) => { const oppositeDirection = DIRECTION_PAIRS[direction]; if (!oppositeDirection) return; const arrived = arrivedStates[direction]; const oppositeArrived = arrivedStates[oppositeDirection]; if (arrived && !distanceScrollState[direction]) distanceScrollState[direction] = true; if (!oppositeArrived && distanceScrollState[oppositeDirection]) distanceScrollState[oppositeDirection] = false; }; const handleScroll = () => { var _a; if (wrapRef.value) { (_a = barRef.value) == null ? void 0 : _a.handleScroll(wrapRef.value); const prevTop = wrapScrollTop; const prevLeft = wrapScrollLeft; wrapScrollTop = wrapRef.value.scrollTop; wrapScrollLeft = wrapRef.value.scrollLeft; const arrivedStates = { bottom: !isGreaterThan(wrapRef.value.scrollHeight - props.distance, wrapRef.value.clientHeight + wrapScrollTop), top: wrapScrollTop <= props.distance && prevTop !== 0, right: !isGreaterThan(wrapRef.value.scrollWidth - props.distance, wrapRef.value.clientWidth + wrapScrollLeft) && prevLeft !== wrapScrollLeft, left: wrapScrollLeft <= props.distance && prevLeft !== 0 }; emit("scroll", { scrollTop: wrapScrollTop, scrollLeft: wrapScrollLeft }); if (prevTop !== wrapScrollTop) direction = wrapScrollTop > prevTop ? "bottom" : "top"; if (prevLeft !== wrapScrollLeft) direction = wrapScrollLeft > prevLeft ? "right" : "left"; if (props.distance > 0) { if (shouldSkipDirection(direction)) return; updateTriggerStatus(arrivedStates); } if (arrivedStates[direction]) emit("end-reached", direction); } }; function scrollTo(arg1, arg2) { if (isObject(arg1)) wrapRef.value.scrollTo(arg1); else if (isNumber(arg1) && isNumber(arg2)) wrapRef.value.scrollTo(arg1, arg2); } const setScrollTop = (value) => { if (!isNumber(value)) { debugWarn(COMPONENT_NAME$1, "value must be a number"); return; } wrapRef.value.scrollTop = value; }; const setScrollLeft = (value) => { if (!isNumber(value)) { debugWarn(COMPONENT_NAME$1, "value must be a number"); return; } wrapRef.value.scrollLeft = value; }; const update = () => { var _a, _b; (_a = barRef.value) == null ? void 0 : _a.update(); distanceScrollState[direction] = false; if (wrapRef.value) (_b = barRef.value) == null ? void 0 : _b.handleScroll(wrapRef.value); }; watch(() => props.noresize, (noresize) => { if (noresize) { stopResizeObserver == null ? void 0 : stopResizeObserver(); stopWrapResizeObserver == null ? void 0 : stopWrapResizeObserver(); stopResizeListener == null ? void 0 : stopResizeListener(); } else { ({ stop: stopResizeObserver } = useResizeObserver(resizeRef, update)); ({ stop: stopWrapResizeObserver } = useResizeObserver(wrapRef, update)); stopResizeListener = useEventListener("resize", update); } }, { immediate: true }); watch(() => [props.maxHeight, props.height], () => { if (!props.native) nextTick(() => { update(); }); }); provide(scrollbarContextKey, reactive({ scrollbarElement: scrollbarRef, wrapElement: wrapRef })); onActivated(() => { if (wrapRef.value) { wrapRef.value.scrollTop = wrapScrollTop; wrapRef.value.scrollLeft = wrapScrollLeft; } }); onMounted(() => { if (!props.native) nextTick(() => { update(); }); }); onUpdated(() => update()); __expose({ /** @description scrollbar wrap ref */ wrapRef, /** @description update scrollbar state manually */ update, /** @description scrolls to a particular set of coordinates */ scrollTo, /** @description set distance to scroll top */ setScrollTop, /** @description set distance to scroll left */ setScrollLeft, /** @description handle scroll event */ handleScroll }); return (_ctx, _cache) => { return openBlock(), createElementBlock("div", { ref_key: "scrollbarRef", ref: scrollbarRef, class: normalizeClass(unref(ns).b()) }, [createElementVNode("div", { ref_key: "wrapRef", ref: wrapRef, class: normalizeClass(wrapKls.value), style: normalizeStyle(wrapStyle.value), tabindex: __props.tabindex, onScroll: handleScroll }, [(openBlock(), createBlock(resolveDynamicComponent(__props.tag), { id: __props.id, ref_key: "resizeRef", ref: resizeRef, class: normalizeClass(resizeKls.value), style: normalizeStyle(__props.viewStyle), role: __props.role, "aria-label": __props.ariaLabel, "aria-orientation": __props.ariaOrientation }, { default: withCtx(() => [renderSlot(_ctx.$slots, "default")]), _: 3 }, 8, [ "id", "class", "style", "role", "aria-label", "aria-orientation" ]))], 46, _hoisted_1$2), !__props.native ? (openBlock(), createBlock(bar_default, { key: 0, ref_key: "barRef", ref: barRef, always: __props.always, "min-size": __props.minSize }, null, 8, ["always", "min-size"])) : createCommentVNode("v-if", true)], 2); }; } }); var scrollbar_default = scrollbar_vue_vue_type_script_setup_true_lang_default; const ElScrollbar = withInstall(scrollbar_default); const nodeList = /* @__PURE__ */ new Map(); if (isClient) { let startClick; document.addEventListener("mousedown", (e) => startClick = e); document.addEventListener("mouseup", (e) => { if (startClick) { for (const handlers of nodeList.values()) for (const { documentHandler } of handlers) documentHandler(e, startClick); startClick = void 0; } }); } function createDocumentHandler(el, binding) { let excludes = []; if (isArray(binding.arg)) excludes = binding.arg; else if (isElement(binding.arg)) excludes.push(binding.arg); return function(mouseup, mousedown) { const popperRef = binding.instance.popperRef; const mouseUpTarget = mouseup.target; const mouseDownTarget = mousedown == null ? void 0 : mousedown.target; const isBound = !binding || !binding.instance; const isTargetExists = !mouseUpTarget || !mouseDownTarget; const isContainedByEl = el.contains(mouseUpTarget) || el.contains(mouseDownTarget); const isSelf = el === mouseUpTarget; const isTargetExcluded = excludes.length && excludes.some((item) => item == null ? void 0 : item.contains(mouseUpTarget)) || excludes.length && excludes.includes(mouseDownTarget); const isContainedByPopper = popperRef && (popperRef.contains(mouseUpTarget) || popperRef.contains(mouseDownTarget)); if (isBound || isTargetExists || isContainedByEl || isSelf || isTargetExcluded || isContainedByPopper) return; binding.value(mouseup, mousedown); }; } const ClickOutside = { beforeMount(el, binding) { if (!nodeList.has(el)) nodeList.set(el, []); nodeList.get(el).push({ documentHandler: createDocumentHandler(el, binding), bindingFn: binding.value }); }, updated(el, binding) { if (!nodeList.has(el)) nodeList.set(el, []); const handlers = nodeList.get(el); const oldHandlerIndex = handlers.findIndex((item) => item.bindingFn === binding.oldValue); const newHandler = { documentHandler: createDocumentHandler(el, binding), bindingFn: binding.value }; if (oldHandlerIndex >= 0) handlers.splice(oldHandlerIndex, 1, newHandler); else handlers.push(newHandler); }, unmounted(el) { nodeList.delete(el); } }; const _hoisted_1$1 = ["aria-label"]; const _hoisted_2$1 = ["aria-label"]; var tag_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({ name: "ElTag", __name: "tag", props: tagProps, emits: tagEmits, setup(__props, { emit: __emit }) { const props = __props; const emit = __emit; const tagSize = useFormSize(); const { t } = useLocale(); const ns = useNamespace("tag"); const containerKls = computed(() => { const { type, hit, effect, closable, round } = props; return [ ns.b(), ns.is("closable", closable), ns.m(type || "primary"), ns.m(tagSize.value), ns.m(effect), ns.is("hit", hit), ns.is("round", round) ]; }); const handleClose = (event) => { emit("close", event); }; const handleClick = (event) => { emit("click", event); }; const handleVNodeMounted = (vnode) => { var _a, _b, _c; if ((_c = (_b = (_a = vnode == null ? void 0 : vnode.component) == null ? void 0 : _a.subTree) == null ? void 0 : _b.component) == null ? void 0 : _c.bum) vnode.component.subTree.component.bum = null; }; return (_ctx, _cache) => { return __props.disableTransitions ? (openBlock(), createElementBlock("span", { key: 0, class: normalizeClass(containerKls.value), style: normalizeStyle({ backgroundColor: __props.color }), onClick: handleClick }, [createElementVNode("span", { class: normalizeClass(unref(ns).e("content")) }, [renderSlot(_ctx.$slots, "default")], 2), __props.closable ? (openBlock(), createElementBlock("button", { key: 0, "aria-label": unref(t)("el.tag.close"), class: normalizeClass(unref(ns).e("close")), type: "button", onClick: withModifiers(handleClose, ["stop"]) }, [createVNode(unref(ElIcon), null, { default: withCtx(() => [createVNode(unref(close_default))]), _: 1 })], 10, _hoisted_1$1)) : createCommentVNode("v-if", true)], 6)) : (openBlock(), createBlock(Transition, { key: 1, name: `${unref(ns).namespace.value}-zoom-in-center`, appear: "", onVnodeMounted: handleVNodeMounted }, { default: withCtx(() => [createElementVNode("span", { class: normalizeClass(containerKls.value), style: normalizeStyle({ backgroundColor: __props.color }), onClick: handleClick }, [createElementVNode("span", { class: normalizeClass(unref(ns).e("content")) }, [renderSlot(_ctx.$slots, "default")], 2), __props.closable ? (openBlock(), createElementBlock("button", { key: 0, "aria-label": unref(t)("el.tag.close"), class: normalizeClass(unref(ns).e("close")), type: "button", onClick: withModifiers(handleClose, ["stop"]) }, [createVNode(unref(ElIcon), null, { default: withCtx(() => [createVNode(unref(close_default))]), _: 1 })], 10, _hoisted_2$1)) : createCommentVNode("v-if", true)], 6)]), _: 3 }, 8, ["name"])); }; } }); var tag_default = tag_vue_vue_type_script_setup_true_lang_default; const ElTag = withInstall(tag_default); var select_dropdown_vue_vue_type_script_lang_default = defineComponent({ name: "ElSelectDropdown", componentName: "ElSelectDropdown", setup() { const select = inject(selectKey); const ns = useNamespace("select"); const popperClass = computed(() => select.props.popperClass); const isMultiple = computed(() => select.props.multiple); const isFitInputWidth = computed(() => select.props.fitInputWidth); const minWidth = ref(""); function updateMinWidth() { var _a; const offsetWidth = (_a = select.selectRef) == null ? void 0 : _a.offsetWidth; if (offsetWidth) minWidth.value = `${offsetWidth - 2}px`; else minWidth.value = ""; } onMounted(() => { updateMinWidth(); useResizeObserver(select.selectRef, updateMinWidth); }); return { ns, minWidth, popperClass, isMultiple, isFitInputWidth }; } }); function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) { return openBlock(), createElementBlock("div", { class: normalizeClass([ _ctx.ns.b("dropdown"), _ctx.ns.is("multiple", _ctx.isMultiple), _ctx.popperClass ]), style: normalizeStyle({ [_ctx.isFitInputWidth ? "width" : "minWidth"]: _ctx.minWidth }) }, [ _ctx.$slots.header ? (openBlock(), createElementBlock("div", { key: 0, class: normalizeClass(_ctx.ns.be("dropdown", "header")) }, [renderSlot(_ctx.$slots, "header")], 2)) : createCommentVNode("v-if", true), renderSlot(_ctx.$slots, "default"), _ctx.$slots.footer ? (openBlock(), createElementBlock("div", { key: 1, class: normalizeClass(_ctx.ns.be("dropdown", "footer")) }, [renderSlot(_ctx.$slots, "footer")], 2)) : createCommentVNode("v-if", true) ], 6); } var select_dropdown_default = /* @__PURE__ */ _plugin_vue_export_helper_default(select_dropdown_vue_vue_type_script_lang_default, [["render", _sfc_render$1]]); const useSelect = (props, emit) => { const { t } = useLocale(); const slots = useSlots(); const contentId = useId(); const nsSelect = useNamespace("select"); const nsInput = useNamespace("input"); const states = reactive({ inputValue: "", options: /* @__PURE__ */ new Map(), cachedOptions: /* @__PURE__ */ new Map(), optionValues: [], selected: [], selectionWidth: 0, collapseItemWidth: 0, selectedLabel: "", hoveringIndex: -1, previousQuery: null, inputHovering: false, menuVisibleOnFocus: false, isBeforeHide: false }); const selectRef = ref(); const selectionRef = ref(); const tooltipRef = ref(); const tagTooltipRef = ref(); const inputRef = ref(); const prefixRef = ref(); const suffixRef = ref(); const menuRef = ref(); const tagMenuRef = ref(); const collapseItemRef = ref(); const scrollbarRef = ref(); const expanded = ref(false); const hoverOption = ref(); const debouncing = ref(false); const { form, formItem } = useFormItem(); const { inputId } = useFormItemInputId(props, { formItemContext: formItem }); const { valueOnClear, isEmptyValue } = useEmptyValues(props); const { isComposing, handleCompositionStart, handleCompositionUpdate, handleCompositionEnd } = useComposition({ afterComposition: (e) => onInput(e) }); const selectDisabled = useFormDisabled(); const { wrapperRef, isFocused, handleBlur } = useFocusController(inputRef, { disabled: selectDisabled, afterFocus() { if (props.automaticDropdown && !expanded.value) { expanded.value = true; states.menuVisibleOnFocus = true; } }, beforeBlur(event) { var _a, _b; return ((_a = tooltipRef.value) == null ? void 0 : _a.isFocusInsideContent(event)) || ((_b = tagTooltipRef.value) == null ? void 0 : _b.isFocusInsideContent(event)); }, afterBlur() { var _a; expanded.value = false; states.menuVisibleOnFocus = false; if (props.validateEvent) (_a = formItem == null ? void 0 : formItem.validate) == null ? void 0 : _a.call(formItem, "blur").catch(NOOP); } }); const hasModelValue = computed(() => { return isArray(props.modelValue) ? props.modelValue.length > 0 : !isEmptyValue(props.modelValue); }); const needStatusIcon = computed(() => (form == null ? void 0 : form.statusIcon) ?? false); const showClearBtn = computed(() => { return props.clearable && !selectDisabled.value && hasModelValue.value && (isFocused.value || states.inputHovering); }); const iconComponent = computed(() => props.remote && props.filterable && !props.remoteShowSuffix ? "" : props.suffixIcon); const iconReverse = computed(() => nsSelect.is("reverse", !!(iconComponent.value && expanded.value))); const validateState = computed(() => (formItem == null ? void 0 : formItem.validateState) || ""); const validateIcon = computed(() => validateState.value && ValidateComponentsMap[validateState.value]); const debounce = computed(() => props.remote ? props.debounce : 0); const isRemoteSearchEmpty = computed(() => props.remote && !states.inputValue && states.options.size === 0); const emptyText = computed(() => { if (props.loading) return props.loadingText || t("el.select.loading"); else { if (props.filterable && states.inputValue && states.options.size > 0 && filteredOptionsCount.value === 0) return props.noMatchText || t("el.select.noMatch"); if (states.options.size === 0) return props.noDataText || t("el.select.noData"); } return null; }); const filteredOptionsCount = computed(() => optionsArray.value.filter((option) => option.visible).length); const optionsArray = computed(() => { const list = Array.from(states.options.values()); const newList = []; states.optionValues.forEach((item) => { const index = list.findIndex((i) => i.value === item); if (index > -1) newList.push(list[index]); }); return newList.length >= list.length ? newList : list; }); const cachedOptionsArray = computed(() => Array.from(states.cachedOptions.values())); const showNewOption = computed(() => { const hasExistingOption = optionsArray.value.filter((option) => { return !option.created; }).some((option) => { return option.currentLabel === states.inputValue; }); return props.filterable && props.allowCreate && states.inputValue !== "" && !hasExistingOption; }); const updateOptions = () => { if (props.filterable && isFunction