UNPKG

birdpaper-ui

Version:

一个通用的 vue3 UI组件库。A common vue3 UI component library.

200 lines (199 loc) 5.79 kB
"use strict"; const vue = require("vue"); const core = require("./core.js"); const util = require("../../utils/util.js"); const clickOutside = require("../../directives/clickOutside.js"); const dom = require("../../utils/dom.js"); const _trigger = /* @__PURE__ */ vue.defineComponent({ name: "Trigger", directives: { clickOutside: clickOutside.vClickOutside }, props: { popupVisible: { type: Boolean, default: false }, /** 触发方式 */ trigger: { type: String, default: "click" }, /** 弹出位置 */ position: { type: String, default: "bottom" }, /** 距离弹出位置的偏移量 */ popupOffset: { type: Number, default: 10 }, /** 距离弹出位置的移动距离 */ popupTranslate: { type: Array, default: [0, 0] }, /** 弹出层是否填充触发器宽度 */ autoFitWidth: { type: Boolean, default: false }, /** 过渡动画名称 */ transition: { type: String, default: "fade" }, /** 点击其他元素关闭触发器 */ clickOutside: { type: Boolean, default: true }, /** 是否禁用 Disabled or not */ disabled: { type: Boolean, default: false }, /** 隐藏触发器 */ hideTrigger: { type: Boolean, default: false }, /** 是否跟随滚动元素更新 */ updateAtScroll: { type: Boolean, default: false }, /** 是否在滚动时关闭 */ scrollToClose: { type: Boolean, default: false }, /** 滚动触发关闭的时间 */ scrollToCloseTime: { type: Number, default: 400 } }, emits: ["update:popupVisible"], setup(props, { emit, slots }) { const name = "bp-trigger"; const triggerRef = vue.ref(); const wrapperRef = vue.ref(); const visible = vue.ref(props.popupVisible || false); const clickOutsideLock = vue.ref(true); const scrollElements = vue.ref([]); const handleClick = () => { if (props.trigger === "hover" || props.disabled) return; updateVisible(!visible.value); handleResize(); }; const handleMouseEnter = () => { if (props.trigger === "click") return; updateVisible(true); handleResize(); }; const handleMouseLeave = () => { if (props.trigger === "click") return; updateVisible(false); }; const handleResize = () => { if (!triggerRef.value || !visible.value) return; const wrapperSize = core.getWrapperSize(wrapperRef.value); const { top, left, width } = core.getPositionData(triggerRef.value.children[0], props.position, { ...wrapperSize }, props.popupTranslate, props.popupOffset, props.autoFitWidth); const styleStr = core.getWrapperPositionStyle(top, left, visible.value, props.autoFitWidth ? width : null); wrapperRef.value.setAttribute("style", styleStr); if (props.scrollToClose && visible.value) { setTimeout(() => { updateVisible(false); }, props.scrollToCloseTime); } }; const onClickOutside = () => { if (!props.clickOutside) return; !clickOutsideLock.value && updateVisible(false); }; const updateVisible = (val, delay = 100) => { visible.value = val; emit("update:popupVisible", visible.value); vue.nextTick(() => { setTimeout(() => { if (props.trigger === "click") { clickOutsideLock.value = !visible.value; } }, delay); }); }; vue.onMounted(() => { vue.nextTick(() => { util.on(window, "resize", util.throttle(handleResize)); if (props.updateAtScroll) { scrollElements.value = dom.getScrollElements(triggerRef.value); for (const item of scrollElements.value) { util.on(item, "scroll", util.throttle(handleResize)); } } }); }); vue.onBeforeUnmount(() => { util.off(window, "resize", util.throttle(handleResize)); util.off(window, "scroll", util.throttle(handleResize)); if (props.updateAtScroll) { scrollElements.value = dom.getScrollElements(triggerRef.value); for (const item of scrollElements.value) { util.off(item, "scroll", util.throttle(handleResize)); } } }); vue.watch(() => props.popupVisible, (v) => { visible.value = v; clickOutsideLock.value = visible.value; }); const render = () => { var _a, _b; const children = ((_a = slots.default) == null ? void 0 : _a.call(slots)) || []; return props.hideTrigger ? (_b = slots.content) == null ? void 0 : _b.call(slots) : vue.createVNode("div", { "class": name, "ref": triggerRef, "id": "triggerRef" }, [vue.h(children[0], { onClick: handleClick, onMouseenter: handleMouseEnter, onMouseleave: handleMouseLeave }), vue.createVNode(vue.Teleport, { "to": "body" }, { default: () => [vue.createVNode(vue.Transition, { "name": props.transition, "appear": true }, { default: () => { var _a2; return [vue.withDirectives(vue.createVNode("div", { "ref": wrapperRef, "class": `${name}-wrapper`, "onMouseenter": handleMouseEnter, "onMouseleave": handleMouseLeave }, [(_a2 = slots.content) == null ? void 0 : _a2.call(slots)]), [[vue.vShow, visible.value], [vue.resolveDirective("clickOutside"), onClickOutside]])]; } })] })]); }; return render; } }); module.exports = _trigger;