import { i as isElement, a as isComponent, b as isArrayChildren, w as withInstall } from "../badge/index2.js"; import { defineComponent, ref, onMounted, openBlock, createBlock, Teleport, renderSlot, onUpdated, useSlots, useAttrs, inject, shallowRef, reactive, toRefs, computed, onBeforeUnmount, watch, provide, createElementBlock, Fragment, createVNode, unref, mergeProps, withCtx, normalizeClass, normalizeStyle, createCommentVNode, cloneVNode, h, nextTick } from "vue"; import { u as useWindowSize, a as useResizeObserver, o as onClickOutside, b as useThrottleFn } from "../_chunks/@vueuse/index.js"; var index = /* @__PURE__ */ (() => ".layui-dropdown{position:relative;display:inline-block}.layui-dropdown-content{position:absolute;z-index:99999;background-color:#fff;box-sizing:border-box;border:1px solid #e4e7ed;border-radius:2px;box-shadow:0 2px 12px #0000001a}.layui-dropdown-content>.layui-dropdown-menu{border-radius:var(--global-border-radius);margin:5px 0}.layui-dropdown-content .layui-menu{position:relative;background-color:#fff}.layui-dropdown-content .layui-menu li,.layui-dropdown-content .layui-menu-body-title a{padding:5px 15px}.layui-dropdown-content .layui-menu li{position:relative;display:flex;margin:1px 0;line-height:26px;color:#000c;font-size:14px;white-space:nowrap;cursor:pointer}.layui-dropdown-content .layui-menu li:hover{background-color:var(--global-neutral-color-2)}.layui-dropdown-content .layui-menu-body-title{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.layui-dropdown-menu-prefix{margin-right:8px}.layui-dropdown-menu-suffix{margin-left:15px}.layui-dropdown-content .layui-menu li.layui-disabled:hover{background-color:inherit}\n")(); const dropdownInjectionKey = Symbol("dropdownInjectKey"); const __default__$1 = { name: "TeleportWrapper" }; const _sfc_main$1 = defineComponent({ ...__default__$1, props: { to: { default: "" }, disabled: { type: Boolean, default: false } }, setup(__props) { const props = __props; const target = ref(null); onMounted(() => { const observer = new MutationObserver((mutationList, observer2) => { for (const mutation of mutationList) { if (mutation.type !== "childList") continue; const el = document.querySelector(props.to); if (!el) continue; target.value = el; observer2.disconnect(); break; } }); observer.observe(document, { childList: true, subtree: true }); return () => observer.disconnect(); }); return (_ctx, _cache) => { return openBlock(), createBlock(Teleport, { to: target.value, disabled: !target.value || __props.disabled }, [ renderSlot(_ctx.$slots, "default") ], 8, ["to", "disabled"]); }; } }); const isScrollElement = (element) => { return element.scrollHeight > element.offsetHeight || element.scrollWidth > element.offsetWidth; }; const getScrollElements = (container) => { var _a; const scrollElements = []; let element = container; while (element && element !== document.documentElement) { if (isScrollElement(element)) { scrollElements.push(element); } element = (_a = element.parentElement) != null ? _a : void 0; } return scrollElements; }; const getChildrenArray = (vn) => { if (isArrayChildren(vn, vn.children)) { return vn.children; } if (Array.isArray(vn)) { return vn; } return void 0; }; const getFirstElementFromVNode = (vn) => { var _a, _b; if (isElement(vn)) { return vn.el; } if (isComponent(vn)) { if (((_a = vn.el) == null ? void 0 : _a.nodeType) === 1) { return vn.el; } if ((_b = vn.component) == null ? void 0 : _b.subTree) { const ele = getFirstElementFromVNode(vn.component.subTree); if (ele) return ele; } } else { const children = getChildrenArray(vn); return getFirstElementFromChildren(children); } return void 0; }; const getFirstElementFromChildren = (children) => { if (children && children.length > 0) { for (const child of children) { const element = getFirstElementFromVNode(child); if (element) return element; } } return void 0; }; const useFirstElement = () => { const children = {}; const firstElement = ref(); const getFirstElement = () => { const element = getFirstElementFromChildren(children.value); if (element !== firstElement.value) { firstElement.value = element; } }; onMounted(() => getFirstElement()); onUpdated(() => getFirstElement()); return { children, firstElement }; }; const transformPlacement = (placement) => { const shouldTransform = placement.includes("-"); const placementMap = { top: "start", left: "start", bottom: "end", right: "end" }; if (shouldTransform) { const separated = placement.split("-"); return `${separated[0]}-${placementMap[separated[1]] || separated[1]}`; } return placement; }; var RenderFunction = defineComponent({ name: "RenderFunction", props: { renderFunc: { type: Function, default: null } }, setup(props, ctx) { return () => { if (typeof props.renderFunc !== "function") { return null; } return props.renderFunc(ctx.attrs); }; } }); const __default__ = { name: "LayDropdown", inheritAttrs: false }; const _sfc_main = defineComponent({ ...__default__, props: { visible: { type: Boolean, default: false }, trigger: { default: "click" }, placement: { default: "bottom-start" }, disabled: { type: Boolean, default: false }, autoFitPosition: { type: Boolean, default: true }, autoFitWidth: { type: Boolean, default: false }, autoFitMinWidth: { type: Boolean, default: true }, updateAtScroll: { type: Boolean, default: false }, autoFixPosition: { type: Boolean, default: true }, clickToClose: { type: Boolean, default: true }, blurToClose: { type: Boolean, default: true }, clickOutsideToClose: { type: Boolean, default: true }, contentOffset: { default: 2 }, mouseEnterDelay: { default: 150 }, mouseLeaveDelay: { default: 150 }, focusDelay: { default: 150 }, alignPoint: { type: Boolean, default: false }, contentClass: null, contentStyle: null, popupContainer: { default: "body" } }, emits: ["show", "hide"], setup(__props, { expose, emit }) { const props = __props; const slots = useSlots(); const attrs = useAttrs(); const childrenRefs = /* @__PURE__ */ new Set(); const dropdownCtx = inject(dropdownInjectionKey, void 0); const { children, firstElement: dropdownRef } = useFirstElement(); const contentRef = shallowRef(); const contentStyle = ref({}); const { width: windowWidth, height: windowHeight } = useWindowSize(); const mousePosition = reactive({ x: 0, y: 0 }); const { x: mouseLeft, y: mouseTop } = toRefs(mousePosition); const openState = ref(false); let scrollElements; const containerRef = computed(() => { var _a; return props.popupContainer ? (_a = document.querySelector(props.popupContainer)) != null ? _a : document.body : dropdownRef.value; }); const triggerMethods = computed(() => [].concat(props.trigger)); const computedPlacement = computed(() => { return transformPlacement(props.placement); }); let delayTimer = 0; const cleanDelayTimer = () => { if (delayTimer) { window.clearTimeout(delayTimer); delayTimer = 0; } }; const show = (delay) => { if (props.disabled == false) { changeVisible(true, delay); emit("show"); } }; const hide = (delay) => { changeVisible(false, delay); emit("hide"); }; const toggle = () => { if (props.disabled == false) if (openState.value) { hide(); } else { show(); } }; const changeVisible = (visible, delay) => { if (visible === openState.value && delayTimer === 0) { return; } const update = () => { openState.value = visible; nextTick(() => { updateContentStyle(); }); }; if (delay) { cleanDelayTimer(); if (visible !== openState.value) { delayTimer = window.setTimeout(update, delay); } } else { update(); } }; const getElementScrollRect = (element, containerRect) => { const rect = element.getBoundingClientRect(); return { top: rect.top, bottom: rect.bottom, left: rect.left, right: rect.right, width: rect.width, height: rect.height, scrollTop: rect.top - containerRect.top, scrollBottom: rect.bottom - containerRect.top, scrollLeft: rect.left - containerRect.left, scrollRight: rect.right - containerRect.left }; }; const getTriggerRect = () => { return { top: mouseTop.value, bottom: mouseTop.value, left: mouseLeft.value, right: mouseLeft.value, scrollTop: mouseTop.value, scrollBottom: mouseTop.value, scrollLeft: mouseLeft.value, scrollRight: mouseLeft.value, width: 0, height: 0 }; }; const updateContentStyle = () => { if (!containerRef.value || !dropdownRef.value || !contentRef.value) { return; } const containerRect = containerRef.value.getBoundingClientRect(); const triggerRect = props.alignPoint ? getTriggerRect() : getElementScrollRect(dropdownRef.value, containerRect); const contentRect = getElementScrollRect(contentRef.value, containerRect); const { style } = getContentStyle(computedPlacement.value, triggerRect, contentRect); if (props.autoFitMinWidth) { style.minWidth = `${triggerRect.width}px`; } if (props.autoFitWidth) { style.width = `${triggerRect.width}px`; } contentStyle.value = style; if (props.autoFitPosition) { nextTick(() => { const triggerRect2 = props.alignPoint ? getTriggerRect() : getElementScrollRect(dropdownRef.value, containerRect); const contentRect2 = getElementScrollRect(contentRef.value, containerRect); let { top, left } = style; top = Number(top.toString().replace("px", "")); left = Number(left.toString().replace("px", "")); const { top: fitTop, left: fitLeft } = getFitPlacement(top, left, computedPlacement.value, triggerRect2, contentRect2); style.top = `${fitTop}px`; style.left = `${fitLeft}px`; contentStyle.value = { ...style }; }); } }; const updateMousePosition = (e) => { if (props.alignPoint) { const { pageX, pageY } = e; mousePosition.x = pageX; mousePosition.y = pageY; } }; const getContentStyle = (placement, triggerRect, contentRect, { customStyle = {} } = {}) => { let { top, left } = getContentOffset(placement, triggerRect, contentRect); const style = { top: `${top}px`, left: `${left}px`, ...customStyle }; return { style }; }; const getPosition = (placement) => { if (["top", "top-start", "top-end"].includes(placement)) { return "top"; } if (["bottom", "bottom-start", "bottom-end"].includes(placement)) { return "bottom"; } if (["left", "left-start", "left-end"].includes(placement)) { return "left"; } if (["right", "right-start", "right-end"].includes(placement)) { return "right"; } return "bottom"; }; const getFitPlacement = (top, left, placement, triggerRect, contentRect) => { const position = getPosition(placement); if (["top", "bottom"].includes(position)) { if (contentRect.bottom > windowHeight.value) { top = triggerRect.scrollTop - contentRect.height - props.contentOffset; } if (contentRect.top < 0) { top = triggerRect.scrollBottom + props.contentOffset; } if (contentRect.left < 0) { left = left + (0 - contentRect.left); } if (contentRect.right > windowWidth.value) { left = left - (contentRect.right - windowWidth.value); } } if (["left", "right"].includes(position)) { if (contentRect.bottom > windowHeight.value) { top = top - (contentRect.bottom - windowHeight.value); } if (contentRect.top < 0) { top = top + (0 - contentRect.top); } if (contentRect.left < 0) { left = triggerRect.scrollRight + props.contentOffset; } if (contentRect.right > windowWidth.value) { left = triggerRect.scrollLeft - contentRect.width - props.contentOffset; } } return { top, left }; }; const getContentOffset = (placement, triggerRect, contentRect) => { switch (placement) { case "top": return { top: triggerRect.scrollTop - contentRect.height - props.contentOffset, left: triggerRect.scrollLeft + Math.round((triggerRect.width - contentRect.width) / 2) }; case "top-start": return { top: triggerRect.scrollTop - contentRect.height - props.contentOffset, left: triggerRect.scrollLeft }; case "top-end": return { top: triggerRect.scrollTop - contentRect.height - props.contentOffset, left: triggerRect.scrollRight - contentRect.width }; case "bottom": return { top: triggerRect.scrollBottom + props.contentOffset, left: triggerRect.scrollLeft + Math.round((triggerRect.width - contentRect.width) / 2) }; case "bottom-start": return { top: triggerRect.scrollBottom + props.contentOffset, left: triggerRect.scrollLeft }; case "bottom-end": return { top: triggerRect.scrollBottom + props.contentOffset, left: triggerRect.scrollRight - contentRect.width }; case "right": return { top: triggerRect.scrollTop + Math.round((triggerRect.height - contentRect.height) / 2), left: triggerRect.scrollRight + props.contentOffset }; case "right-start": return { top: triggerRect.scrollTop, left: triggerRect.scrollRight + props.contentOffset }; case "right-end": return { top: triggerRect.scrollBottom - contentRect.height, left: triggerRect.scrollRight + props.contentOffset }; case "left": return { top: triggerRect.scrollTop + Math.round((triggerRect.height - contentRect.height) / 2), left: triggerRect.scrollLeft - contentRect.width - props.contentOffset }; case "left-start": return { top: triggerRect.scrollTop, left: triggerRect.scrollLeft - contentRect.width - props.contentOffset }; case "left-end": return { top: triggerRect.scrollBottom - contentRect.height, left: triggerRect.scrollLeft - contentRect.width - props.contentOffset }; default: return { left: 0, top: 0 }; } }; const handleScroll = useThrottleFn(() => { if (openState.value) { updateContentStyle(); } }, 10); const handleClick = (e) => { if (props.disabled || openState.value && !props.clickToClose) { return; } if (triggerMethods.value.includes("click")) { updateMousePosition(e); toggle(); } }; const handleContextMenuClick = (e) => { if (props.disabled || openState.value && !props.clickToClose) { return; } if (triggerMethods.value.includes("contextMenu")) { e.preventDefault(); if (props.alignPoint) { hide(); } updateMousePosition(e); toggle(); } }; const handleMouseEnter = (e) => { if (props.disabled || !triggerMethods.value.includes("hover")) { return; } show(props.mouseEnterDelay); }; const handleMouseEnterWithContext = (e) => { if (!props.popupContainer) { return; } dropdownCtx == null ? void 0 : dropdownCtx.onMouseenter(e); handleMouseEnter(); }; const handleMouseLeave = (e) => { if (props.disabled || !triggerMethods.value.includes("hover")) { return; } hide(props.mouseLeaveDelay); }; const handleMouseLeaveWithContext = (e) => { if (!props.popupContainer) { return; } dropdownCtx == null ? void 0 : dropdownCtx.onMouseleave(e); handleMouseLeave(); }; const handleFocusin = () => { if (props.disabled || !triggerMethods.value.includes("focus")) { return; } show(props.focusDelay); }; const handleFocusout = () => { if (props.disabled || !triggerMethods.value.includes("focus")) { return; } if (!props.blurToClose) { return; } hide(); }; const handleContextHide = () => { hide(); dropdownCtx == null ? void 0 : dropdownCtx.hide(); }; const addChildRef = (ref2) => { childrenRefs.add(ref2); dropdownCtx == null ? void 0 : dropdownCtx.addChildRef(ref2); }; const removeChildRef = (ref2) => { childrenRefs.delete(ref2); dropdownCtx == null ? void 0 : dropdownCtx.removeChildRef(ref2); }; dropdownCtx == null ? void 0 : dropdownCtx.addChildRef(contentRef); const { stop: removeContentResizeObserver } = useResizeObserver(contentRef, () => { if (openState.value && props.autoFixPosition) { updateContentStyle(); } }); const { stop: removeTriggerResizeObserver } = useResizeObserver(dropdownRef, () => { if (openState.value && props.autoFixPosition) { updateContentStyle(); } }); onClickOutside(dropdownRef, (e) => { var _a, _b, _c; if (!props.clickOutsideToClose || !openState.value || ((_a = dropdownRef.value) == null ? void 0 : _a.contains(e.target)) || ((_b = contentRef.value) == null ? void 0 : _b.contains(e.target))) { return; } for (const item of childrenRefs) { if ((_c = item.value) == null ? void 0 : _c.contains(e.target)) { return; } } hide(); }); const onlyChildRenderFunc = () => { const slotContent = slots.default ? slots.default() : []; const transformedSlotContent = slotContent.map((vnode) => cloneVNode(vnode, { onClick: handleClick, onContextmenu: handleContextMenuClick, onMouseenter: handleMouseEnter, onMouseleave: handleMouseLeave, onFocusin: handleFocusin, onFocusout: handleFocusout, ...attrs }, true)); children.value = transformedSlotContent; return h(Fragment, children.value); }; onMounted(() => { if (props.updateAtScroll) { scrollElements = getScrollElements(dropdownRef.value); for (const item of scrollElements) { item.addEventListener("scroll", handleScroll); } } window.addEventListener("resize", handleScroll); }); onBeforeUnmount(() => { dropdownCtx == null ? void 0 : dropdownCtx.removeChildRef(contentRef); if (scrollElements) { for (const item of scrollElements) { item.removeEventListener("scroll", handleScroll); } scrollElements = void 0; } removeContentResizeObserver(); removeTriggerResizeObserver(); window.removeEventListener("resize", handleScroll); }); watch(() => props.visible, (newVal, oldVal) => { openState.value = newVal; }, { immediate: true }); provide(dropdownInjectionKey, reactive({ onMouseenter: handleMouseEnterWithContext, onMouseleave: handleMouseLeaveWithContext, addChildRef, removeChildRef, hide: handleContextHide })); provide("openState", openState); expose({ show, hide, toggle }); return (_ctx, _cache) => { return openBlock(), createElementBlock(Fragment, null, [ createVNode(unref(RenderFunction), mergeProps({ renderFunc: onlyChildRenderFunc }, _ctx.$attrs), null, 16), createVNode(_sfc_main$1, { to: __props.popupContainer, disabled: __props.disabled }, { default: withCtx(() => { var _a; return [ openState.value ? (openBlock(), createElementBlock("div", { key: 0, ref_key: "contentRef", ref: contentRef, class: normalizeClass([ "layui-dropdown-content", "layui-anim", "layui-anim-upbit", props.contentClass ]), style: normalizeStyle([contentStyle.value, (_a = props.contentStyle) != null ? _a : ""]), onMouseenter: handleMouseEnterWithContext, onMouseleave: handleMouseLeaveWithContext }, [ renderSlot(_ctx.$slots, "content") ], 38)) : createCommentVNode("", true) ]; }), _: 3 }, 8, ["to", "disabled"]) ], 64); }; } }); const component = withInstall(_sfc_main); export { RenderFunction as R, _sfc_main as _, component as c, dropdownInjectionKey as d };