@blossom-carousel/web
Version:
A native-scroll-first carousel component for the web.
257 lines (256 loc) • 8.47 kB
JavaScript
var fe = Object.defineProperty;
var de = (t, l, d) => l in t ? fe(t, l, { enumerable: !0, configurable: !0, writable: !0, value: d }) : t[l] = d;
var ee = (t, l, d) => (de(t, typeof l != "symbol" ? l + "" : l, d), d);
const pe = (t, l) => {
let d = !0;
const v = { x: 0, y: 0 }, c = { x: 0, y: 0 }, u = { x: 0, y: 0 }, C = new Proxy(
{ x: 0, y: 0 },
{
set(e, n, r) {
return e[n] === r || (e[n] = r, (e.x >= 10 || e.y >= 10) && X(!0)), !0;
}
}
), i = new Proxy(
{ x: !1, y: !1 },
{
set(e, n, r) {
return e[n] === r || (e[n] = r, e.x || e.y ? (t.setAttribute("has-overflow", "true"), t.addEventListener("pointerdown", U), t.addEventListener("wheel", J, { passive: !1 })) : (t.removeAttribute("has-overflow"), t.removeEventListener("pointerdown", U), t.removeEventListener("wheel", J))), !0;
}
}
);
let L = 300, m = null, h = !1, x = 300, f = 300, H = 300, $ = 300;
const S = { left: 0, right: 0 }, I = { left: 0, right: 0 };
let R = [], k = null, T = null, O = !1;
function te() {
k = (t == null ? void 0 : t.querySelectorAll("a[href]")) || null, k == null || k.forEach((r) => {
r.addEventListener("click", V);
}), window.addEventListener("keydown", K), t.addEventListener("scroll", z), T = new ResizeObserver(re), T.observe(t);
const e = window.matchMedia(
"(hover: hover) and (pointer: fine)"
).matches, { scrollSnapType: n } = window.getComputedStyle(t);
O = n !== "none", t.style.setProperty("--snap-type", n), e && (t.style["scroll-snap-type"] = "none"), t.setAttribute("has-repeat", l != null && l.repeat ? "true" : "false");
}
function ne() {
T == null || T.disconnect(), m && cancelAnimationFrame(m), window.removeEventListener("keydown", K), t.removeEventListener("scroll", z), k == null || k.forEach((e) => {
e.removeEventListener("click", V);
});
}
function V(e) {
C.x > 10 && e.preventDefault();
}
function re() {
if (!t)
return;
const e = "ontouchmove" in window;
x = t.scrollWidth, f = t.clientWidth, H = t.scrollHeight, $ = t.clientHeight;
const n = window.getComputedStyle(t);
i.x = !e && x > f && ["auto", "scroll"].includes(n.getPropertyValue("overflow-x")), i.y = !e && H > $ && ["auto", "scroll"].includes(n.getPropertyValue("overflow-y")), S.right = parseInt(n.paddingRight) || 0, S.left = parseInt(n.paddingLeft) || 0, I.left = parseInt(n.scrollPaddingLeft) || 0, I.right = parseInt(n.scrollPaddingRight) || 0, L = x - f - 4, R = O ? oe(t) : [], l != null && l.repeat && F(null, null);
}
function oe(e) {
let n = [], r = 0;
const w = (s) => {
if (r++, r > 100)
return;
const y = window.getComputedStyle(s).scrollSnapAlign;
if (y !== "none") {
n.push({
align: y,
el: s
});
return;
}
const A = s.children;
if (A.length !== 0)
for (let a of A)
w(a);
};
w(e);
const q = e.getBoundingClientRect();
let p = n.map(({ el: s, align: y }, A) => {
const a = s.getBoundingClientRect(), M = s.clientWidth, B = a.left - q.left + e.scrollLeft;
switch (y) {
case "start":
return B - I.left;
case "end":
return B + M - f + I.right;
case "center":
return B + M * 0.5 - f / 2;
default:
return null;
}
});
return p = p.filter((s) => s !== null).reduce((s, y) => (s[s.length - 1] !== y && s.push(y), s), []), p;
}
function z() {
if (l != null && l.repeat) {
F(null, null);
return;
}
if (!(h || !t)) {
if (t.scrollLeft < 0) {
const e = t.scrollLeft * -1;
Y(e);
} else if (t.scrollLeft > x - f) {
const e = t.scrollLeft * -1 + x - f;
Y(e);
}
}
}
const o = {
x: 0,
y: 0
};
function U(e) {
t && (i.x && (o.x = t.scrollLeft, v.x = e.clientX, u.x = 0), i.y && (o.y = t.scrollTop, v.y = e.clientY, u.y = 0), C.x = 0, h = !0, window.addEventListener("pointermove", j), window.addEventListener("pointerup", G));
}
function j(e) {
if (e.preventDefault(), i.x) {
const n = v.x - e.clientX;
c.x += n, u.x += n, v.x = e.clientX, C.x += Math.abs(n);
}
if (i.y) {
const n = v.y - e.clientY;
c.y += n, u.y += n, v.y = e.clientY, C.y += Math.abs(n);
}
}
function G() {
window.removeEventListener("pointermove", j), window.removeEventListener("pointerup", G), h = !1, !(C.x <= 10) && (i.x && (u.x *= 2), i.y && (u.y *= 2), le(), ae());
}
function J(e) {
if (e.deltaX > e.deltaY) {
if (X(!1), h || !t)
return;
i.x && (o.x = t.scrollLeft), i.y && (o.y = t.scrollTop);
}
}
function K(e) {
["ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown"].includes(e.key) && X(!1);
}
function le() {
const e = (Z(
ce({ axis: "x" }),
0,
x - f
) - c.x) * (1 - g) * (1 / g);
u.x = e;
}
function F(e, n) {
if (!t)
return;
const r = n ?? t.scrollLeft, w = S.left - r, q = r - (x - f - S.right), p = Array.from(t.children);
let s = 0;
for (let a = p.length - 1; a >= p.length / 2; a--) {
const M = s > w ? 0 : -(x - f);
s += p[a].clientWidth, p[a].style.translate = `${M}px 0`;
}
let y = 0;
for (let a = 0; a < p.length / 2; a++) {
const M = y > q ? 0 : x - f;
y += p[a].clientWidth, p[a].style.translate = `${M}px 0`;
}
if (h)
return;
const A = r > L ? 4 : r < 4 ? L : null;
A && t.scrollTo({
left: A,
behavior: "instant"
});
}
const g = 0.72, W = 0.12;
let N = !1;
function X(e) {
t && (e && !N ? (D = performance.now(), i.x && (c.x = t.scrollLeft), i.y && (c.y = t.scrollTop), m || (m = requestAnimationFrame(Q))) : e || (m && cancelAnimationFrame(m), m = null), N = e, d = !e, t.setAttribute("has-snap", d ? "true" : "false"));
}
let E = 0, D = 0;
function Q(e) {
m = requestAnimationFrame(Q), E = e - D, t && (i.x && (u.x *= g, h ? o.x = P(o.x, c.x, g, E) : (c.x += u.x, o.x = P(o.x, c.x, W, E))), i.y && (u.y *= g, h ? o.y = P(o.y, c.y, g, E) : (c.y += u.y, o.y = P(o.y, c.y, W, E))), l != null && l.repeat && (o.x > L && (o.x = c.x = 4), o.x < 4 && (o.x = c.x = L)), t.scrollTo({
left: o.x,
top: o.y,
behavior: "instant"
}), l != null && l.repeat ? F(null, o.x) : se(_(o.x, 2)), D = e);
}
let b = 0;
function se(e) {
if (!t)
return;
const n = x - f;
let r = 0;
if (e < 0 ? r = h ? e * -0.2 : 0 : e > n && (r = h ? (e - n) * -0.2 : 0), b = P(
b,
r,
h ? 0.8 : W,
E
), Math.abs(b) > 0.01) {
if (Y(b).defaultPrevented)
return;
t.style.transform = `translateX(${_(b, 3)}px)`;
return;
}
t.style.transform = "", b = 0;
}
function Y(e) {
const n = new CustomEvent("overscroll", {
bubbles: !0,
cancelable: !0,
detail: { left: e }
});
return t == null || t.dispatchEvent(n), n;
}
function ie({ axis: e = "x" }) {
return c[e] + u[e] / (1 - g);
}
function ce({ axis: e = "x" }) {
const n = ie({ axis: e });
return R.length ? R.reduce(
(r, w) => Math.abs(w - n) < Math.abs(r - n) ? w : r
) : Z(n, 0, L);
}
function ae() {
const e = (n) => {
n.preventDefault(), n.stopPropagation(), window.removeEventListener("click", e, !0);
};
window.addEventListener("click", e, !0);
}
function ue(e, n, r) {
return (1 - r) * e + r * n;
}
function P(e, n, r, w) {
return ue(e, n, 1 - Math.exp(Math.log(1 - r) * (w / 16.666666666666668)));
}
function Z(e, n, r) {
return e < n ? n : e > r ? r : e;
}
function _(e, n = 0) {
const r = Math.pow(10, n);
return Math.round(e * r) / r;
}
return {
snap: d,
hasOverflow: i,
init: te,
destroy: ne
};
};
class he extends HTMLElement {
constructor() {
super();
ee(this, "carouselInstance");
const d = this.attachShadow({ mode: "open" });
this.setAttribute("blossom-carousel", "true");
const v = document.createElement("slot");
d.appendChild(v);
}
connectedCallback() {
this.carouselInstance = pe(this, {
repeat: !1
// this.hasAttribute("repeat"),
}), this.carouselInstance.init();
}
disconnectedCallback() {
this.carouselInstance.destroy();
}
}
customElements.define("blossom-carousel", he);
export {
he as BlossomCarousel
};