UNPKG

@blossom-carousel/web

Version:

A native-scroll-first carousel component for the web.

257 lines (256 loc) 8.47 kB
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 };