UNPKG

suspend-vue

Version:

一个悬浮窗组件,支持组件形式 / 自定义指令

335 lines (334 loc) 9.4 kB
import { isRef as Q, ref as y, computed as M, reactive as H, withModifiers as Z, effectScope as ee, watchEffect as $, nextTick as q, defineComponent as te, onBeforeUnmount as ne, openBlock as oe, createElementBlock as ie, renderSlot as se, createElementVNode as ue } from "vue"; const x = (a, i) => { const o = getComputedStyle(a)[i], c = typeof o == "string" ? o.match(/^(\d+\.?\d*)(px)?$/i) : []; return c && c[1] ? +c[1] : o; }; function U(a) { let i; if (typeof a == "number" || ae(a)) return +a; const o = a.match(/^(\-?[0-9]+)(.+)/); if (!o) return 0; const [c, u, v] = o; switch (v) { case "px": i = +u; break; case "rem": { const d = x(document.querySelector("html"), "fontSize"); i = +u * d; } break; case "vw": { const d = x(document.querySelector("html"), "width"); i = +u * 0.01 * d; } break; case "vh": { const d = x(document.querySelector("html"), "height"); i = +u * 0.01 * d; } break; default: i = +u; break; } return i; } function ae(a) { return /^\-?[0-9]*$/.test(a); } function W(a) { return 1 / +a > 0; } const re = (() => /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent))(); function de(a, i) { const o = Object.assign({}, i, a); for (const c in o) c in i && typeof o[c] > "u" && (o[c] = i[c]); return o; } const D = "suspend-box", j = { stopDrag: "suspend-stop-drag-wrapper" }; function V(a, i, o) { const u = Q(a) ? a : y(a); let v; i = de(i, { model: "default", delay: 300, contentMove: !0, zIndex: 999 }); const d = y(!1), E = M(() => i.delay + "ms"), h = y(), T = 1, m = y(!0), C = M( () => Object.assign({ x: !0, y: !0 }, i.move) ), X = M( () => Object.assign({ x: !1, y: !1 }, i.adsorption) ), n = H({ left: 0, top: 0, // 触点与盒子边界的距离 flagX: 0, flagY: 0, width: 0, height: 0, mLeft: 0, mTop: 0 }), l = H({ left: 0, top: 0, width: 0, height: 0 }), g = M(() => ({ MinLeft: -n.mLeft, MaxLeft: l.width - n.width - n.mLeft, MinTop: -n.mTop, MaxTop: l.height - n.height - n.mTop })), S = y(!1); function L(e = u.value) { if (i.model === "window" && e) { if (e.nodeName === "HTML") return; { const t = e.parentNode; return x(t, "position") != "static" ? t : L(t); } } } function Y(e, t) { const s = { left: 0, top: 0 }, { MaxLeft: r, MaxTop: f, MinLeft: P, MinTop: F } = g.value; return s.left = e < P ? P : e > r ? r : e, s.top = t < F ? F : t > f ? f : t, n.left = C.value.x ? s.left : n.left, n.top = C.value.y ? s.top : n.top, s; } function k() { const { defaultSite: e } = i, t = { x: (e == null ? void 0 : e.left) ?? (e == null ? void 0 : e.x) ?? -0, y: (e == null ? void 0 : e.top) ?? (e == null ? void 0 : e.y) ?? "-2vh" }; t.x = U(t.x), t.y = U(t.y); const { MaxLeft: s, MaxTop: r } = g.value; n.left = Math.abs(t.x) > s ? s : W(t.x) ? t.x : s + t.x, n.top = Math.abs(t.y) > r ? r : W(t.y) ? t.y : r + t.y; } function O(e, t) { d.value = !1, S.value = !0, n.flagX = e.offsetX, n.flagY = e.offsetY, h.value = { x: n.left, y: n.top }, m.value = !0, v = setTimeout(() => { var s; (s = o == null ? void 0 : o.moveStart) == null || s.call(o); }, 200); } const R = Z( (e) => { const t = { offsetX: 0, offsetY: 0 }, s = M(() => { var r, f; return { left: ((r = u.value) == null ? void 0 : r.getBoundingClientRect().left) || 0, top: ((f = u.value) == null ? void 0 : f.getBoundingClientRect().top) || 0 }; }); if ("changedTouches" in e && u.value && e.changedTouches) t.offsetX = e.changedTouches[0].clientX - s.value.left, t.offsetY = e.changedTouches[0].clientY - s.value.top, O(t); else { const r = e; t.offsetX = r.clientX - s.value.left, t.offsetY = r.clientY - s.value.top, O(t); } }, [i.contentMove ? "" : "self"] ); function G(e) { if (e.changedTouches) return z(e.changedTouches[0]); } function z(e) { if (!S.value) return; const { clientX: t, clientY: s } = e, r = t - n.flagX - l.left - n.mLeft, f = s - n.flagY - l.top - n.mTop; Y(r, f), h.value && (Math.abs(n.left - h.value.x) > T || Math.abs(n.top - h.value.y) > T) && (m.value = !1); } async function _(e) { var t, s; if (S.value) { if (S.value = !1, i.delay && (d.value = !0), m.value ? (clearTimeout(v), (t = o == null ? void 0 : o.click) == null || t.call(o, e)) : ((s = o == null ? void 0 : o.moveEnd) == null || s.call(o), h.value = void 0), X.value.x) { const r = n.left + n.width / 2 > l.width / 2 - n.mLeft ? g.value.MaxLeft : g.value.MinLeft; n.left = r; } if (X.value.y) { const r = n.top + n.height / 2 > l.height / 2 - n.mTop ? g.value.MaxTop : g.value.MinTop; n.top = r; } } } function w() { const e = L(); e ? (l.left = e.getBoundingClientRect().left, l.top = e.getBoundingClientRect().top, l.width = e.getBoundingClientRect().width, l.height = e.getBoundingClientRect().height) : (l.width = document.documentElement.clientWidth || window.innerWidth, l.height = document.documentElement.clientHeight || window.innerHeight); } function I() { u.value && (n.width = u.value.clientWidth, n.height = u.value.clientHeight, n.mLeft = x( u.value, "marginLeft" ), n.mTop = x( u.value, "marginTop" )); } async function N() { await q(); const e = L(); e && (new MutationObserver(w).observe(e, { attributeFilter: ["style"] }), e.addEventListener( "transitionend", w, !1 )), w(), I(), k(); } const J = () => { const e = `${D}-style`, t = ` .${j.stopDrag} * { user-select: none; -webkit-user-drag: none; } `; document.querySelector(`style[data-${e}=${e}]`) || q(() => { var f; const r = document.createElement("style"); r.setAttribute(`data-${e}`, e), r.innerHTML = t, (f = document.querySelector("head")) == null || f.appendChild(r); }); }; function K(e) { const t = { left: "0", top: "0", userSelect: "none", touchAction: "none", zIndex: i.zIndex + "", position: i.model === "default" ? "fixed" : "absolute", boxSizing: "border-box" }; i.contentMove && e.classList.add(j.stopDrag); for (const s in t) e.style[s] = t[s] || ""; e.setAttribute(`data-${D}`, D), e.onmousedown = R, e.ontouchstart = R, e.addEventListener( "click", (s) => !m.value && s.stopPropagation(), !0 ), J(); } const b = ee(); b.run(() => { $( () => u.value && (K(u.value), N()) ), $(() => { u.value && (d.value ? u.value.style.transition = `transform ${E.value} ease-out` : u.value.style.transition = "none"); }), $( () => u.value && (u.value.style.transform = `translate3d(${n.left}px, ${n.top}px, 0)`) ); }); function A(e = "add") { e === "add" ? p.forEach((t) => window.addEventListener(t.type, t.value, !0)) : p.forEach( (t) => window.removeEventListener(t.type, t.value) ); } const p = /* @__PURE__ */ new Set([ { type: "resize", value: N } ]); return re ? (p.add({ type: "touchmove", value: G }), p.add({ type: "touchend", value: _ })) : (p.add({ type: "mousemove", value: z }), p.add({ type: "mouseup", value: _ }), p.add({ type: "contextmenu", value: _ })), i.model === "window" && p.add({ type: "scroll", value: w }), A("add"), { unmount: () => { const e = L(); e && e.removeEventListener("transitionend", w), b.stop(), A("remove"); }, /** 重新获取 box 的样式 */ reset: () => { I(), Y(n.left, n.top); } }; } const ce = /* @__PURE__ */ ue("div", null, "test", -1), B = /* @__PURE__ */ te({ name: "Suspend", __name: "Suspend", props: { model: {}, move: {}, adsorption: {}, defaultSite: {}, delay: {}, contentMove: { type: Boolean, default: !0 }, zIndex: {} }, emits: ["click", "moveStart", "moveEnd"], setup(a, { expose: i, emit: o }) { const c = a, u = y(); function v(m) { o("click", m); } function d() { o("moveStart"); } function E() { o("moveEnd"); } const { unmount: h, reset: T } = V(u, c, { click: v, moveStart: d, moveEnd: E }); return ne(h), i({ reset: T }), (m, C) => (oe(), ie("div", { id: "suspend-box", class: "suspend-box", ref_key: "suspendBox", ref: u }, [ se(m.$slots, "default", {}, () => [ ce ]) ], 512)); } }); function le(a) { a.directive("suspend", { mounted(i, o, c) { var d; const u = o.value, { unmount: v } = V(i, u, { click: (d = o.value) == null ? void 0 : d.click }); i.unmount = v; }, beforeUnmount(i, o) { i.unmount(); } }); } B.install = (a) => { a.component(B.name, B), le(a); }; const me = B; export { B as Suspend, me as default, V as useSuspend }; //# sourceMappingURL=suspend-vue.es.js.map