suspend-vue
Version:
一个悬浮窗组件,支持组件形式 / 自定义指令
335 lines (334 loc) • 9.4 kB
JavaScript
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