swapy
Version:
_A framework-agnostic tool that converts any layout into a drag-to-swap one with just a few lines of code._
1,220 lines (1,219 loc) • 34.9 kB
JavaScript
function rt(t) {
return typeof t == "object" && t !== null && "x" in t && "y" in t && "unit" in t && typeof t.unit == "string" && typeof t.x == "object" && typeof t.y == "object" && "topLeft" in t.x && "topRight" in t.x && "bottomRight" in t.x && "bottomLeft" in t.x && "topLeft" in t.y && "topRight" in t.y && "bottomRight" in t.y && "bottomLeft" in t.y;
}
function gt(t) {
var h;
const e = t.match(/(\d+(?:\.\d+)?)(px|%)/g);
if (!e)
return {
x: { topLeft: 0, topRight: 0, bottomRight: 0, bottomLeft: 0 },
y: { topLeft: 0, topRight: 0, bottomRight: 0, bottomLeft: 0 },
unit: "px"
};
const n = e.map((c) => {
const [s, f, y] = c.match(/(\d+(?:\.\d+)?)(px|%)/) ?? [];
return { value: parseFloat(f), unit: y };
}), o = ((h = n[0]) == null ? void 0 : h.unit) || "px";
if (n.some((c) => c.unit !== o))
throw new Error("Inconsistent units in border-radius string.");
const [l, i, d, u] = n.map((c) => c.value), a = {
topLeft: l ?? 0,
topRight: i ?? l ?? 0,
bottomRight: d ?? l ?? 0,
bottomLeft: u ?? i ?? l ?? 0
};
return {
x: { ...a },
y: { ...a },
unit: o
};
}
function ht({ x: t, y: e, unit: n }, o, l) {
if (n === "px") {
const i = {
topLeft: t.topLeft / o,
topRight: t.topRight / o,
bottomLeft: t.bottomLeft / o,
bottomRight: t.bottomRight / o
}, d = {
topLeft: e.topLeft / l,
topRight: e.topRight / l,
bottomLeft: e.bottomLeft / l,
bottomRight: e.bottomRight / l
};
return { x: i, y: d, unit: "px" };
} else if (n === "%")
return { x: t, y: e, unit: "%" };
return { x: t, y: e, unit: n };
}
function G(t) {
return `
${t.x.topLeft}${t.unit} ${t.x.topRight}${t.unit} ${t.x.bottomRight}${t.unit} ${t.x.bottomLeft}${t.unit}
/
${t.y.topLeft}${t.unit} ${t.y.topRight}${t.unit} ${t.y.bottomRight}${t.unit} ${t.y.bottomLeft}${t.unit}
`;
}
function it(t) {
return t.x.topLeft === 0 && t.x.topRight === 0 && t.x.bottomRight === 0 && t.x.bottomLeft === 0 && t.y.topLeft === 0 && t.y.topRight === 0 && t.y.bottomRight === 0 && t.y.bottomLeft === 0;
}
function at(t) {
return typeof t == "object" && "x" in t && "y" in t;
}
function R(t, e) {
return { x: t, y: e };
}
function xt(t, e) {
return R(t.x + e.x, t.y + e.y);
}
function vt(t, e) {
return R(t.x - e.x, t.y - e.y);
}
function It(t, e) {
return R(t.x * e, t.y * e);
}
function C(t, e, n) {
return t + (e - t) * n;
}
function At(t, e, n) {
return xt(t, It(vt(e, t), n));
}
function pt(t, e, n) {
return {
x: {
topLeft: C(t.x.topLeft, e.x.topLeft, n),
topRight: C(t.x.topRight, e.x.topRight, n),
bottomRight: C(t.x.bottomRight, e.x.bottomRight, n),
bottomLeft: C(t.x.bottomLeft, e.x.bottomLeft, n)
},
y: {
topLeft: C(t.y.topLeft, e.y.topLeft, n),
topRight: C(t.y.topRight, e.y.topRight, n),
bottomRight: C(t.y.bottomRight, e.y.bottomRight, n),
bottomLeft: C(t.y.bottomLeft, e.y.bottomLeft, n)
},
unit: t.unit
};
}
function Et(t, e, n) {
return V((n - t) / (e - t), 0, 1);
}
function U(t, e, n, o, l) {
return C(n, o, Et(t, e, l));
}
function V(t, e, n) {
return Math.min(Math.max(t, e), n);
}
const Xt = {
duration: 350,
easing: (t) => t
};
function mt(t, e, n, o) {
let l = !1;
const i = () => {
l = !0;
}, d = { ...Xt, ...o };
let u;
function a(h) {
u === void 0 && (u = h);
const c = h - u, s = V(c / d.duration, 0, 1), f = Object.keys(t), y = Object.keys(e);
if (!f.every((g) => y.includes(g))) {
console.error("animate Error: `from` keys are different than `to`");
return;
}
const v = {};
f.forEach((g) => {
typeof t[g] == "number" && typeof e[g] == "number" ? v[g] = C(
t[g],
e[g],
d.easing(s)
) : rt(t[g]) && rt(e[g]) ? v[g] = pt(
t[g],
e[g],
d.easing(s)
) : at(t[g]) && at(e[g]) && (v[g] = At(
t[g],
e[g],
d.easing(s)
));
}), n(v, s >= 1, s), s < 1 && !l && requestAnimationFrame(a);
}
return requestAnimationFrame(a), i;
}
const Tt = {
startDelay: 0,
targetEl: null
};
function Mt(t, e) {
const n = { ...Tt, ...e };
let o = t.el(), l = !1, i = null, d = null, u = null, a = null, h = 0, c = 0, s = 0, f = 0, y = 0, v = 0, g = 0, T = 0, r = 0, I = 0, E = null, p;
o.addEventListener("pointerdown", w), document.body.addEventListener("pointerup", x), document.body.addEventListener("pointermove", X), document.body.addEventListener("touchmove", M, { passive: !1 });
function w(m) {
if (n.targetEl && m.target !== n.targetEl && !n.targetEl.contains(m.target) || l || !m.isPrimary) return;
n.startDelay > 0 ? (u == null || u({ el: m.target }), p = setTimeout(() => {
B();
}, n.startDelay)) : B();
function B() {
E = m.target;
const L = t.boundingRect(), F = t.layoutRect();
y = F.x, v = F.y, s = L.x - y, f = L.y - v, h = m.clientX - s, c = m.clientY - f, g = m.clientX, T = m.clientY, r = (m.clientX - L.x) / L.width, I = (m.clientY - L.y) / L.height, l = !0, X(m);
}
}
function A() {
const m = t.layoutRect();
h -= y - m.x, c -= v - m.y, y = m.x, v = m.y;
}
function x(m) {
if (!l) {
p && (clearTimeout(p), p = null, a == null || a({ el: m.target }));
return;
}
if (!m.isPrimary) return;
l = !1;
const B = m.clientX - g, L = m.clientY - T;
d == null || d({
x: s,
y: f,
pointerX: m.clientX,
pointerY: m.clientY,
width: B,
height: L,
relativeX: r,
relativeY: I,
el: E
}), E = null;
}
function X(m) {
if (!l) {
p && (clearTimeout(p), p = null, a == null || a({ el: m.target }));
return;
}
if (!m.isPrimary) return;
const B = m.clientX - g, L = m.clientY - T, F = s = m.clientX - h, Z = f = m.clientY - c;
i == null || i({
width: B,
height: L,
x: F,
y: Z,
pointerX: m.clientX,
pointerY: m.clientY,
relativeX: r,
relativeY: I,
el: E
});
}
function M(m) {
if (!l) return !0;
m.preventDefault();
}
function D(m) {
i = m;
}
function H(m) {
d = m;
}
function _(m) {
u = m;
}
function P(m) {
a = m;
}
function $() {
o.removeEventListener("pointerdown", w), o = t.el(), o.addEventListener("pointerdown", w);
}
function N() {
t.el().removeEventListener("pointerdown", w), document.body.removeEventListener("pointerup", x), document.body.removeEventListener("pointermove", X), document.body.removeEventListener("touchmove", M), i = null, d = null, u = null, a = null;
}
return {
onDrag: D,
onDrop: H,
onHold: _,
onRelease: P,
onElementUpdate: $,
destroy: N,
readjust: A
};
}
function Dt(t) {
return 1 + 2.70158 * Math.pow(t - 1, 3) + 1.70158 * Math.pow(t - 1, 2);
}
function bt(t) {
return 1 - Math.pow(1 - t, 3);
}
function z(t) {
return {
x: t.x,
y: t.y,
width: t.width,
height: t.height
};
}
function Lt(t) {
const e = t.getBoundingClientRect();
let n = 0, o = 0, l = t.parentElement;
for (; l; ) {
const d = getComputedStyle(l).transform;
if (d && d !== "none") {
const u = d.match(/matrix.*\((.+)\)/);
if (u) {
const a = u[1].split(", ").map(Number);
n += a[4] || 0, o += a[5] || 0;
}
}
l = l.parentElement;
}
return {
y: e.top - o,
x: e.left - n,
width: e.width,
height: e.height
};
}
function J(t) {
let e = t, n = 0, o = 0;
for (; e; )
n += e.offsetTop, o += e.offsetLeft, e = e.offsetParent;
return {
x: o,
y: n,
width: t.offsetWidth,
height: t.offsetHeight
};
}
function st(t, e) {
return t.x >= e.x && t.x <= e.x + e.width && t.y >= e.y && t.y <= e.y + e.height;
}
function Yt(t) {
let e = t, n = 0, o = 0;
for (; e; ) {
const l = (i) => {
const d = getComputedStyle(i);
return /(auto|scroll)/.test(
d.overflow + d.overflowY + d.overflowX
);
};
if (e === document.body) {
o += window.scrollX, n += window.scrollY;
break;
}
l(e) && (o += e.scrollLeft, n += e.scrollTop), e = e.parentElement;
}
return { x: o, y: n };
}
function Q(t) {
let e = "unread", n, o, l, i, d, u, a, h, c, s, f;
function y() {
n = t.currentTransform(), o = Lt(t.el()), l = Yt(t.el()), f = ct(t.el()).map(({ parent: I, children: E }) => ({
parent: {
el: I,
initialRect: z(I.getBoundingClientRect())
},
children: E.filter((p) => p instanceof HTMLElement).map((p) => {
const w = p;
return w.originalBorderRadius || (w.originalBorderRadius = getComputedStyle(p).borderRadius), {
el: p,
borderRadius: gt(w.originalBorderRadius),
initialRect: z(
p.getBoundingClientRect()
)
};
})
})), e = "readInitial";
}
function v() {
if (e !== "readInitial")
throw new Error(
"FlipView: Cannot read final values before reading initial values"
);
c = t.layoutRect(), u = o.width / c.width, a = o.height / c.height, i = o.x - c.x - n.dragX + l.x, d = o.y - c.y - n.dragY + l.y, h = ht(
t.borderRadius(),
u,
a
);
const r = ct(t.el());
f = f.map(
({ parent: E, children: p }, w) => {
const A = r[w].parent;
return {
parent: {
...E,
el: A,
finalRect: J(A)
},
children: p.map((x, X) => {
const M = r[w].children[X];
let D = J(M);
return M.hasAttribute("data-swapy-text") && (D = {
...D,
width: x.initialRect.width,
height: x.initialRect.height
}), {
...x,
el: M,
finalRect: D
};
})
};
}
);
const I = {
translateX: i,
translateY: d,
scaleX: u,
scaleY: a
};
t.el().style.transformOrigin = "0 0", t.el().style.borderRadius = G(
h
), t.setTransform(I), s = [], f.forEach(({ parent: E, children: p }) => {
const w = p.map(
({ el: A, initialRect: x, finalRect: X, borderRadius: M }) => Ct(
A,
x,
X,
M,
E.initialRect,
E.finalRect
)
);
s.push(...w);
}), e = "readFinal";
}
function g() {
if (e !== "readFinal")
throw new Error("FlipView: Cannot get transition values before reading");
return {
from: {
width: o.width,
height: o.height,
translate: R(i, d),
scale: R(u, a),
borderRadius: h
},
to: {
width: c.width,
height: c.height,
translate: R(0, 0),
scale: R(1, 1),
borderRadius: t.borderRadius()
}
};
}
function T() {
if (e !== "readFinal")
throw new Error(
"FlipView: Cannot get children transition values before reading"
);
return s;
}
return {
readInitial: y,
readFinalAndReverse: v,
transitionValues: g,
childrenTransitionData: T
};
}
function Ct(t, e, n, o, l, i) {
t.style.transformOrigin = "0 0";
const d = l.width / i.width, u = l.height / i.height, a = e.width / n.width, h = e.height / n.height, c = ht(
o,
a,
h
), s = e.x - l.x, f = n.x - i.x, y = e.y - l.y, v = n.y - i.y, g = (s - f * d) / d, T = (y - v * u) / u;
return t.style.transform = `translate(${g}px, ${T}px) scale(${a / d}, ${h / u})`, t.style.borderRadius = G(c), {
el: t,
fromTranslate: R(g, T),
fromScale: R(a, h),
fromBorderRadius: c,
toBorderRadius: o,
parentScale: { x: d, y: u }
};
}
function ct(t) {
const e = [];
function n(o) {
const l = Array.from(o.children).filter(
(i) => i instanceof HTMLElement
);
l.length > 0 && (e.push({
parent: o,
children: l
}), l.forEach((i) => n(i)));
}
return n(t), e;
}
function yt(t) {
const e = [];
let n = t, o = {
dragX: 0,
dragY: 0,
translateX: 0,
translateY: 0,
scaleX: 1,
scaleY: 1
};
const l = gt(
window.getComputedStyle(n).borderRadius
), i = {
el: () => n,
setTransform: d,
clearTransform: u,
currentTransform: () => o,
borderRadius: () => l,
layoutRect: () => J(n),
boundingRect: () => z(n.getBoundingClientRect()),
usePlugin: h,
destroy: c,
updateElement: s
};
function d(f) {
o = { ...o, ...f }, a();
}
function u() {
o = {
dragX: 0,
dragY: 0,
translateX: 0,
translateY: 0,
scaleX: 1,
scaleY: 1
}, a();
}
function a() {
const { dragX: f, dragY: y, translateX: v, translateY: g, scaleX: T, scaleY: r } = o;
f === 0 && y === 0 && v === 0 && g === 0 && T === 1 && r === 1 ? n.style.transform = "" : n.style.transform = `translate(${f + v}px, ${y + g}px) scale(${T}, ${r})`;
}
function h(f, y) {
const v = f(i, y);
return e.push(v), v;
}
function c() {
e.forEach((f) => f.destroy());
}
function s(f) {
if (!f) return;
const y = n.hasAttribute("data-swapy-dragging"), v = n.style.cssText;
n = f, y && n.setAttribute("data-swapy-dragging", ""), n.style.cssText = v, e.forEach((g) => g.onElementUpdate());
}
return i;
}
function Rt(t, e, n) {
return n.map((o) => ({
slotId: o.slot,
itemId: o.item,
item: o.item === "" ? null : t.find((l) => o.item === l[e])
}));
}
function Ht(t, e) {
return t.map((n) => ({
item: n[e],
slot: n[e]
}));
}
function $t(t, e, n, o, l, i = !1) {
const d = e.filter(
(h) => !o.some((c) => c.item === h[n])
).map((h) => ({
slot: h[n],
item: h[n]
}));
let u;
i ? u = o.map((h) => e.some((c) => c[n] === h.item) ? h : { slot: h.slot, item: "" }) : u = o.filter(
(h) => e.some((c) => c[n] === h.item) || !h.item
);
const a = [
...u,
...d
];
l(a), (d.length > 0 || u.length !== o.length) && requestAnimationFrame(() => {
t == null || t.update();
});
}
const jt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
__proto__: null,
dynamicSwapy: $t,
initSlotItemMap: Ht,
toSlottedItems: Rt
}, Symbol.toStringTag, { value: "Module" })), Bt = {
animation: "dynamic",
enabled: !0,
swapMode: "hover",
dragOnHold: !1,
autoScrollOnDrag: !1,
dragAxis: "both",
manualSwap: !1
};
function wt(t) {
switch (t) {
case "dynamic":
return { easing: bt, duration: 300 };
case "spring":
return { easing: Dt, duration: 350 };
case "none":
return { easing: (e) => e, duration: 1 };
}
}
function kt(t, e) {
const n = { ...Bt, ...e }, o = Ot({ slots: [], items: [], config: n });
let l = [], i = [];
d();
function d() {
if (!qt(t))
throw new Error(
"Cannot create a Swapy instance because your HTML structure is invalid. Fix all above errors and then try!"
);
l = Array.from(t.querySelectorAll("[data-swapy-slot]")).map(
(r) => _t(r, o)
), o.setSlots(l), i = Array.from(t.querySelectorAll("[data-swapy-item]")).map(
(r) => Pt(r, o)
), o.setItems(i), o.syncSlotItemMap(), i.forEach((r) => {
r.onDrag(({ pointerX: I, pointerY: E }) => {
a();
let p = !1;
l.forEach((w) => {
const A = w.rect();
st({ x: I, y: E }, A) && (p = !0, w.isHighlighted() || w.highlight());
}), !p && o.config().swapMode === "drop" && r.slot().highlight(), n.swapMode === "hover" && u(r, { pointerX: I, pointerY: E });
}), r.onDrop(({ pointerX: I, pointerY: E }) => {
h(), n.swapMode === "drop" && u(r, { pointerX: I, pointerY: E });
}), r.onHold(() => {
a();
}), r.onRelease(() => {
h();
});
});
}
function u(r, { pointerX: I, pointerY: E }) {
l.forEach((p) => {
const w = p.rect();
if (st({ x: I, y: E }, w)) {
if (r.id() === p.itemId()) return;
o.config().swapMode === "hover" && r.setContinuousDrag(!0);
const A = r.slot(), x = p.item();
if (!o.eventHandlers().onBeforeSwap({
fromSlot: A.id(),
toSlot: p.id(),
draggingItem: r.id(),
swapWithItem: (x == null ? void 0 : x.id()) || ""
}))
return;
if (o.config().manualSwap) {
const X = structuredClone(o.slotItemMap());
o.swapItems(r, p);
const M = o.slotItemMap(), D = Q(r.view());
D.readInitial();
const H = x ? Q(x.view()) : null;
H == null || H.readInitial();
let _ = 0, P = 0;
const $ = et(
r.view().el()
);
$ instanceof Window ? (_ = $.scrollY, P = $.scrollX) : (_ = $.scrollTop, P = $.scrollLeft), o.eventHandlers().onSwap({
oldSlotItemMap: X,
newSlotItemMap: M,
fromSlot: A.id(),
toSlot: p.id(),
draggingItem: r.id(),
swappedWithItem: (x == null ? void 0 : x.id()) || ""
}), requestAnimationFrame(() => {
const N = t.querySelectorAll("[data-swapy-item]");
o.items().forEach((m) => {
const B = Array.from(N).find(
(L) => L.dataset.swapyItem === m.id()
);
m.view().updateElement(B);
}), o.syncSlotItemMap(), D.readFinalAndReverse(), H == null || H.readFinalAndReverse(), tt(r, D), x && H && tt(x, H), $.scrollTo({
left: P,
top: _
});
});
} else {
let X = 0, M = 0;
const D = et(
r.view().el()
);
D instanceof Window ? (X = D.scrollY, M = D.scrollX) : (X = D.scrollTop, M = D.scrollLeft), ft(r, p, !0), x && ft(x, A), D.scrollTo({
left: M,
top: X
});
const H = o.slotItemMap();
o.syncSlotItemMap();
const _ = o.slotItemMap();
o.eventHandlers().onSwap({
oldSlotItemMap: H,
newSlotItemMap: _,
fromSlot: A.id(),
toSlot: p.id(),
draggingItem: r.id(),
swappedWithItem: (x == null ? void 0 : x.id()) || ""
});
}
}
});
}
function a() {
t.querySelectorAll("img").forEach((r) => {
r.style.pointerEvents = "none";
}), t.style.userSelect = "none", t.style.webkitUserSelect = "none";
}
function h() {
t.querySelectorAll("img").forEach((r) => {
r.style.pointerEvents = "";
}), t.style.userSelect = "", t.style.webkitUserSelect = "";
}
function c(r) {
o.config().enabled = r;
}
function s(r) {
o.eventHandlers().onSwapStart = r;
}
function f(r) {
o.eventHandlers().onSwap = r;
}
function y(r) {
o.eventHandlers().onSwapEnd = r;
}
function v(r) {
o.eventHandlers().onBeforeSwap = r;
}
function g() {
T(), requestAnimationFrame(() => {
d();
});
}
function T() {
i.forEach((r) => r.destroy()), l.forEach((r) => r.destroy()), o.destroy(), i = [], l = [];
}
return {
enable: c,
slotItemMap: () => o.slotItemMap(),
onSwapStart: s,
onSwap: f,
onSwapEnd: y,
onBeforeSwap: v,
update: g,
destroy: T
};
}
function Ot({
slots: t,
items: e,
config: n
}) {
const o = {
slots: t,
items: e,
config: n,
slotItemMap: { asObject: {}, asMap: /* @__PURE__ */ new Map(), asArray: [] },
zIndexCount: 1,
eventHandlers: {
onSwapStart: () => {
},
onSwap: () => {
},
onSwapEnd: () => {
},
onBeforeSwap: () => !0
},
scrollOffsetWhileDragging: { x: 0, y: 0 },
scrollHandler: null
};
let l = {
...o
};
const i = (s) => {
var f;
(f = l.scrollHandler) == null || f.call(l, s);
};
window.addEventListener("scroll", i);
function d(s) {
return l.slots.find((f) => f.id() === s);
}
function u(s) {
return l.items.find((f) => f.id() === s);
}
function a() {
const s = {}, f = /* @__PURE__ */ new Map(), y = [];
l.slots.forEach((v) => {
var r;
const g = v.id(), T = ((r = v.item()) == null ? void 0 : r.id()) || "";
s[g] = T, f.set(g, T), y.push({ slot: g, item: T });
}), l.slotItemMap = { asObject: s, asMap: f, asArray: y };
}
function h(s, f) {
var p;
const y = l.slotItemMap, v = s.id(), g = ((p = f.item()) == null ? void 0 : p.id()) || "", T = f.id(), r = s.slot().id();
y.asObject[T] = v, y.asObject[r] = g, y.asMap.set(T, v), y.asMap.set(r, g);
const I = y.asArray.findIndex(
(w) => w.slot === T
), E = y.asArray.findIndex(
(w) => w.slot === r
);
y.asArray[I].item = v, y.asArray[E].item = g;
}
function c() {
window.removeEventListener("scroll", i), l = { ...o };
}
return {
slots: () => l.slots,
items: () => l.items,
config: () => n,
setItems: (s) => l.items = s,
setSlots: (s) => l.slots = s,
slotById: d,
itemById: u,
zIndex: (s = !1) => s ? ++l.zIndexCount : l.zIndexCount,
resetZIndex: () => {
l.zIndexCount = 1;
},
eventHandlers: () => l.eventHandlers,
syncSlotItemMap: a,
slotItemMap: (s = !1) => s ? structuredClone(l.slotItemMap) : l.slotItemMap,
onScroll: (s) => {
l.scrollHandler = s;
},
swapItems: h,
destroy: c
};
}
function _t(t, e) {
const n = yt(t);
function o() {
return n.el().dataset.swapySlot;
}
function l() {
const c = n.el().children[0];
return (c == null ? void 0 : c.dataset.swapyItem) || null;
}
function i() {
return z(n.el().getBoundingClientRect());
}
function d() {
const c = n.el().children[0];
if (c)
return e.itemById(c.dataset.swapyItem);
}
function u() {
e.slots().forEach((c) => {
c.view().el().removeAttribute("data-swapy-highlighted");
});
}
function a() {
u(), n.el().setAttribute("data-swapy-highlighted", "");
}
function h() {
}
return {
id: o,
view: () => n,
itemId: l,
rect: i,
item: d,
highlight: a,
unhighlightAllSlots: u,
isHighlighted: () => n.el().hasAttribute("data-swapy-highlighted"),
destroy: h
};
}
function Pt(t, e) {
const n = yt(t), o = {};
let l = null, i = null, d = !1, u = !0, a;
const h = Nt();
let c = () => {
}, s = () => {
}, f = () => {
}, y = () => {
};
const { onDrag: v, onDrop: g, onHold: T, onRelease: r } = n.usePlugin(Mt, {
startDelay: e.config().dragOnHold ? 400 : 0,
targetEl: P()
}), I = R(0, 0), E = R(0, 0), p = R(0, 0), w = R(0, 0);
let A = null, x = null;
T((S) => {
e.config().enabled && (N() && !$(S.el) || L() && B(S.el) || f == null || f(S));
}), r((S) => {
e.config().enabled && (N() && !$(S.el) || L() && B(S.el) || y == null || y(S));
});
function X(S) {
var q;
F(), K().highlight(), (q = o.drop) == null || q.call(o);
const Y = e.slots().map((O) => O.view().boundingRect());
e.slots().forEach((O, W) => {
const j = Y[W];
O.view().el().style.width = `${j.width}px`, O.view().el().style.maxWidth = `${j.width}px`, O.view().el().style.flexShrink = "0", O.view().el().style.height = `${j.height}px`;
});
const b = e.slotItemMap(!0);
e.eventHandlers().onSwapStart({
draggingItem: nt(),
fromSlot: ot(),
slotItemMap: b
}), i = b, n.el().style.position = "relative", n.el().style.zIndex = `${e.zIndex(!0)}`, A = et(S.el), e.config().autoScrollOnDrag && (l = Wt(
A,
e.config().dragAxis
), l.updatePointer({
x: S.pointerX,
y: S.pointerY
})), I.x = window.scrollX, I.y = window.scrollY, p.x = 0, p.y = 0, A instanceof HTMLElement && (E.x = A.scrollLeft, E.y = A.scrollTop, x = () => {
w.x = A.scrollLeft - E.x, w.y = A.scrollTop - E.y, n.setTransform({
dragX: ((a == null ? void 0 : a.width) || 0) + p.x + w.x,
dragY: ((a == null ? void 0 : a.height) || 0) + p.y + w.y
});
}, A.addEventListener("scroll", x)), e.onScroll(() => {
p.x = window.scrollX - I.x, p.y = window.scrollY - I.y;
const O = w.x || 0, W = w.y || 0;
n.setTransform({
dragX: ((a == null ? void 0 : a.width) || 0) + p.x + O,
dragY: ((a == null ? void 0 : a.height) || 0) + p.y + W
});
});
}
v((S) => {
var Y;
if (e.config().enabled) {
if (!d) {
if (N() && !$(S.el) || L() && B(S.el))
return;
X(S);
}
d = !0, l && l.updatePointer({
x: S.pointerX,
y: S.pointerY
}), a = S, (Y = o.drop) == null || Y.call(o), h(() => {
n.el().style.position = "relative";
const b = S.width + p.x + w.x, q = S.height + p.y + w.y;
e.config().dragAxis === "y" ? n.setTransform({
dragY: q
}) : e.config().dragAxis === "x" ? n.setTransform({
dragX: b
}) : n.setTransform({
dragX: b,
dragY: q
}), c == null || c(S);
});
}
}), g((S) => {
if (!d) return;
Z(), d = !1, u = !1, a = null, A && (A.removeEventListener("scroll", x), x = null), A = null, w.x = 0, w.y = 0, p.x = 0, p.y = 0, l && (l.destroy(), l = null), K().unhighlightAllSlots(), s == null || s(S), e.eventHandlers().onSwapEnd({
slotItemMap: e.slotItemMap(),
hasChanged: i != null && i.asMap ? !Ft(
i == null ? void 0 : i.asMap,
e.slotItemMap().asMap
) : !1
}), i = null, e.onScroll(null), e.slots().forEach((b) => {
b.view().el().style.width = "", b.view().el().style.maxWidth = "", b.view().el().style.flexShrink = "", b.view().el().style.height = "";
}), e.config().manualSwap && e.config().swapMode === "drop" ? requestAnimationFrame(Y) : Y();
function Y() {
const b = n.currentTransform(), q = b.dragX + b.translateX, O = b.dragY + b.translateY;
o.drop = mt(
{ translate: R(q, O) },
{ translate: R(0, 0) },
({ translate: W }, j) => {
j ? d || (n.clearTransform(), n.el().style.transformOrigin = "") : n.setTransform({
dragX: 0,
dragY: 0,
translateX: W.x,
translateY: W.y
}), j && (e.items().forEach((lt) => {
lt.isDragging() || (lt.view().el().style.zIndex = "");
}), e.resetZIndex(), n.el().style.position = "", u = !0);
},
wt(e.config().animation)
);
}
});
function M(S) {
c = S;
}
function D(S) {
s = S;
}
function H(S) {
f = S;
}
function _(S) {
y = S;
}
function P() {
return n.el().querySelector("[data-swapy-handle]");
}
function $(S) {
const Y = P();
return Y ? Y === S || Y.contains(S) : !1;
}
function N() {
return P() !== null;
}
function m() {
return Array.from(n.el().querySelectorAll("[data-swapy-no-drag]"));
}
function B(S) {
const Y = m();
return !Y || Y.length === 0 ? !1 : Y.includes(S) || Y.some((b) => b.contains(S));
}
function L() {
return m().length > 0;
}
function F() {
n.el().setAttribute("data-swapy-dragging", "");
}
function Z() {
n.el().removeAttribute("data-swapy-dragging");
}
function St() {
c = null, s = null, f = null, y = null, a = null, i = null, l && (l.destroy(), l = null), A && x && A.removeEventListener("scroll", x), n.destroy();
}
function nt() {
return n.el().dataset.swapyItem;
}
function K() {
return e.slotById(n.el().parentElement.dataset.swapySlot);
}
function ot() {
return n.el().parentElement.dataset.swapySlot;
}
return {
id: nt,
view: () => n,
slot: K,
slotId: ot,
onDrag: M,
onDrop: D,
onHold: H,
onRelease: _,
destroy: St,
isDragging: () => d,
cancelAnimation: () => o,
dragEvent: () => a,
store: () => e,
continuousDrag: () => u,
setContinuousDrag: (S) => u = S
};
}
function ft(t, e, n = !1) {
if (n) {
const l = e.item();
l && (e.view().el().style.position = "relative", l.view().el().style.position = "absolute");
} else {
const l = t.slot();
l.view().el().style.position = "", t.view().el().style.position = "";
}
if (!t)
return;
const o = Q(t.view());
o.readInitial(), e.view().el().appendChild(t.view().el()), o.readFinalAndReverse(), tt(t, o);
}
function Nt() {
let t = !1;
return (e) => {
t || (t = !0, requestAnimationFrame(() => {
e(), t = !1;
}));
};
}
function tt(t, e) {
var u, a, h, c;
(a = (u = t.cancelAnimation()).moveToSlot) == null || a.call(u), (c = (h = t.cancelAnimation()).drop) == null || c.call(h);
const n = wt(t.store().config().animation), o = e.transitionValues();
let l = t.view().currentTransform(), i = 0, d = !1;
t.cancelAnimation().moveToSlot = mt(
{
translate: o.from.translate,
scale: o.from.scale,
borderRadius: o.from.borderRadius
},
{
translate: o.to.translate,
scale: o.to.scale,
borderRadius: o.to.borderRadius
},
({ translate: s, scale: f, borderRadius: y }, v, g) => {
if (t.isDragging()) {
i !== 0 && (d = !0);
const r = t.dragEvent().relativeX, I = t.dragEvent().relativeY;
t.continuousDrag() ? t.view().setTransform({
translateX: C(
l.translateX,
l.translateX + (o.from.width - o.to.width) * r,
n.easing(g - i)
),
translateY: C(
l.translateY,
l.translateY + (o.from.height - o.to.height) * I,
n.easing(g - i)
),
scaleX: f.x,
scaleY: f.y
}) : t.view().setTransform({ scaleX: f.x, scaleY: f.y });
} else
l = t.view().currentTransform(), i = g, d ? t.view().setTransform({
scaleX: f.x,
scaleY: f.y
}) : t.view().setTransform({
dragX: 0,
dragY: 0,
translateX: s.x,
translateY: s.y,
scaleX: f.x,
scaleY: f.y
});
const T = e.childrenTransitionData();
T.forEach(
({
el: r,
fromTranslate: I,
fromScale: E,
fromBorderRadius: p,
toBorderRadius: w,
parentScale: A
}) => {
const x = C(
A.x,
1,
n.easing(g)
), X = C(
A.y,
1,
n.easing(g)
);
r.style.transform = `translate(${I.x + (0 - I.x / x) * n.easing(g)}px, ${I.y + (0 - I.y / X) * n.easing(g)}px) scale(${C(
E.x / x,
1 / x,
n.easing(g)
)}, ${C(
E.y / X,
1 / X,
n.easing(g)
)})`, it(p) || (r.style.borderRadius = G(
pt(
p,
w,
n.easing(g)
)
));
}
), it(y) || (t.view().el().style.borderRadius = G(y)), v && (t.isDragging() || (t.view().el().style.transformOrigin = "", t.view().clearTransform()), t.view().el().style.borderRadius = "", T.forEach(({ el: r }) => {
r.style.transform = "", r.style.transformOrigin = "", r.style.borderRadius = "";
}));
},
n
);
}
function k(...t) {
console.error("Swapy Error:", ...t);
}
function qt(t) {
const e = t;
let n = !0;
const o = e.querySelectorAll("[data-swapy-slot]");
e || (k("container passed to createSwapy() is undefined or null"), n = !1), o.forEach((u) => {
const a = u, h = a.dataset.swapySlot, c = a.children, s = c[0];
(!h || h.length === 0) && (k(a, "does not contain a slotId using data-swapy-slot"), n = !1), c.length > 1 && (k("slot:", `"${h}"`, "cannot contain more than one element"), n = !1), s && (!s.dataset.swapyItem || s.dataset.swapyItem.length === 0) && (k(
"slot",
`"${h}"`,
"does not contain an element with an item id using data-swapy-item"
), n = !1);
});
const l = Array.from(o).map(
(u) => u.dataset.swapySlot
), i = e.querySelectorAll("[data-swapy-item]"), d = Array.from(i).map(
(u) => u.dataset.swapyItem
);
if (ut(l)) {
const u = dt(l);
k(
"your container has duplicate slot ids",
`(${u.join(", ")})`
), n = !1;
}
if (ut(d)) {
const u = dt(d);
k(
"your container has duplicate item ids",
`(${u.join(", ")})`
), n = !1;
}
return n;
}
function ut(t) {
return new Set(t).size !== t.length;
}
function dt(t) {
const e = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Set();
for (const o of t)
e.has(o) ? n.add(o) : e.add(o);
return Array.from(n);
}
function Ft(t, e) {
if (t.size !== e.size) return !1;
for (const [n, o] of t)
if (e.get(n) !== o) return !1;
return !0;
}
function et(t) {
let e = t;
for (; e; ) {
const n = window.getComputedStyle(e), o = n.overflowY, l = n.overflowX;
if ((o === "auto" || o === "scroll") && e.scrollHeight > e.clientHeight || (l === "auto" || l === "scroll") && e.scrollWidth > e.clientWidth)
return e;
e = e.parentElement;
}
return window;
}
function Wt(t, e) {
let l = !1, i, d = 0, u = 0, a = 0, h = 0, c = 0, s = 0, f = null;
t instanceof HTMLElement ? (i = z(t.getBoundingClientRect()), d = t.scrollHeight - i.height, u = t.scrollWidth - i.width) : (i = {
x: 0,
y: 0,
width: window.innerWidth,
height: window.innerHeight
}, d = document.documentElement.scrollHeight - window.innerHeight, u = document.documentElement.scrollWidth - window.innerWidth);
function y() {
t instanceof HTMLElement ? (a = t.scrollTop, h = t.scrollLeft) : (a = window.scrollY, h = window.scrollX);
}
function v(r) {
l = !1;
const I = i.y, E = i.y + i.height, p = i.x, w = i.x + i.width, A = Math.abs(I - r.y) < Math.abs(E - r.y), x = Math.abs(p - r.x) < Math.abs(w - r.x);
if (y(), e !== "x")
if (A) {
const X = I - r.y;
if (X >= -100) {
const M = V(X, -100, 0);
c = -U(-100, 0, 0, 5, M), l = !0;
}
} else {
const X = E - r.y;
if (X <= 100) {
const M = V(X, 0, 100);
c = U(100, 0, 0, 5, M), l = !0;
}
}
if (e !== "y")
if (x) {
const X = p - r.x;
if (X >= -100) {
const M = V(X, -100, 0);
s = -U(-100, 0, 0, 5, M), l = !0;
}
} else {
const X = w - r.x;
if (X <= 100) {
const M = V(X, 0, 100);
s = U(100, 0, 0, 5, M), l = !0;
}
}
l && (f && cancelAnimationFrame(f), g());
}
function g() {
y(), e !== "x" && (c = a + c >= d ? 0 : c), e !== "y" && (s = h + s >= u ? 0 : s), t.scrollBy({ top: c, left: s }), l && (f = requestAnimationFrame(g));
}
function T() {
l = !1;
}
return {
updatePointer: v,
destroy: T
};
}
export {
kt as createSwapy,
et as getClosestScrollableContainer,
jt as utils
};