UNPKG

@acrool/react-vertical-marquee

Version:

Most modern vertical marquee with hardware accelerated transitions for ReactJS

667 lines (666 loc) 21.5 kB
var xe = Object.defineProperty; var Te = (n, r, e) => r in n ? xe(n, r, { enumerable: !0, configurable: !0, writable: !0, value: e }) : n[r] = e; var u = (n, r, e) => Te(n, typeof r != "symbol" ? r + "" : r, e); import Ee, { Component as ge, createRef as C } from "react"; var M = { exports: {} }, R = {}; /** * @license React * react-jsx-runtime.production.js * * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ var X; function ve() { if (X) return R; X = 1; var n = Symbol.for("react.transitional.element"), r = Symbol.for("react.fragment"); function e(o, i, l) { var s = null; if (l !== void 0 && (s = "" + l), i.key !== void 0 && (s = "" + i.key), "key" in i) { l = {}; for (var f in i) f !== "key" && (l[f] = i[f]); } else l = i; return i = l.ref, { $$typeof: n, type: o, key: s, ref: i !== void 0 ? i : null, props: l }; } return R.Fragment = r, R.jsx = e, R.jsxs = e, R; } var b = {}; /** * @license React * react-jsx-runtime.development.js * * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ var H; function Ie() { return H || (H = 1, process.env.NODE_ENV !== "production" && function() { function n(t) { if (t == null) return null; if (typeof t == "function") return t.$$typeof === me ? null : t.displayName || t.name || null; if (typeof t == "string") return t; switch (t) { case D: return "Fragment"; case ae: return "Profiler"; case oe: return "StrictMode"; case le: return "Suspense"; case ue: return "SuspenseList"; case de: return "Activity"; } if (typeof t == "object") switch (typeof t.tag == "number" && console.error( "Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue." ), t.$$typeof) { case re: return "Portal"; case se: return (t.displayName || "Context") + ".Provider"; case ie: return (t._context.displayName || "Context") + ".Consumer"; case ce: var a = t.render; return t = t.displayName, t || (t = a.displayName || a.name || "", t = t !== "" ? "ForwardRef(" + t + ")" : "ForwardRef"), t; case fe: return a = t.displayName || null, a !== null ? a : n(t.type) || "Memo"; case G: a = t._payload, t = t._init; try { return n(t(a)); } catch { } } return null; } function r(t) { return "" + t; } function e(t) { try { r(t); var a = !1; } catch { a = !0; } if (a) { a = console; var c = a.error, d = typeof Symbol == "function" && Symbol.toStringTag && t[Symbol.toStringTag] || t.constructor.name || "Object"; return c.call( a, "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.", d ), r(t); } } function o(t) { if (t === D) return "<>"; if (typeof t == "object" && t !== null && t.$$typeof === G) return "<...>"; try { var a = n(t); return a ? "<" + a + ">" : "<...>"; } catch { return "<...>"; } } function i() { var t = $.A; return t === null ? null : t.getOwner(); } function l() { return Error("react-stack-top-frame"); } function s(t) { if (L.call(t, "key")) { var a = Object.getOwnPropertyDescriptor(t, "key").get; if (a && a.isReactWarning) return !1; } return t.key !== void 0; } function f(t, a) { function c() { V || (V = !0, console.error( "%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)", a )); } c.isReactWarning = !0, Object.defineProperty(t, "key", { get: c, configurable: !0 }); } function h() { var t = n(this.type); return q[t] || (q[t] = !0, console.error( "Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release." )), t = this.props.ref, t !== void 0 ? t : null; } function p(t, a, c, d, g, T, U, W) { return c = T.ref, t = { $$typeof: w, type: t, key: a, props: T, _owner: g }, (c !== void 0 ? c : null) !== null ? Object.defineProperty(t, "ref", { enumerable: !1, get: h }) : Object.defineProperty(t, "ref", { enumerable: !1, value: null }), t._store = {}, Object.defineProperty(t._store, "validated", { configurable: !1, enumerable: !1, writable: !0, value: 0 }), Object.defineProperty(t, "_debugInfo", { configurable: !1, enumerable: !1, writable: !0, value: null }), Object.defineProperty(t, "_debugStack", { configurable: !1, enumerable: !1, writable: !0, value: U }), Object.defineProperty(t, "_debugTask", { configurable: !1, enumerable: !1, writable: !0, value: W }), Object.freeze && (Object.freeze(t.props), Object.freeze(t)), t; } function x(t, a, c, d, g, T, U, W) { var m = a.children; if (m !== void 0) if (d) if (he(m)) { for (d = 0; d < m.length; d++) v(m[d]); Object.freeze && Object.freeze(m); } else console.error( "React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead." ); else v(m); if (L.call(a, "key")) { m = n(t); var _ = Object.keys(a).filter(function(pe) { return pe !== "key"; }); d = 0 < _.length ? "{key: someKey, " + _.join(": ..., ") + ": ...}" : "{key: someKey}", J[m + d] || (_ = 0 < _.length ? "{" + _.join(": ..., ") + ": ...}" : "{}", console.error( `A props object containing a "key" prop is being spread into JSX: let props = %s; <%s {...props} /> React keys must be passed directly to JSX without using spread: let props = %s; <%s key={someKey} {...props} />`, d, m, _, m ), J[m + d] = !0); } if (m = null, c !== void 0 && (e(c), m = "" + c), s(a) && (e(a.key), m = "" + a.key), "key" in a) { c = {}; for (var Y in a) Y !== "key" && (c[Y] = a[Y]); } else c = a; return m && f( c, typeof t == "function" ? t.displayName || t.name || "Unknown" : t ), p( t, m, T, g, i(), c, U, W ); } function v(t) { typeof t == "object" && t !== null && t.$$typeof === w && t._store && (t._store.validated = 1); } var E = Ee, w = Symbol.for("react.transitional.element"), re = Symbol.for("react.portal"), D = Symbol.for("react.fragment"), oe = Symbol.for("react.strict_mode"), ae = Symbol.for("react.profiler"), ie = Symbol.for("react.consumer"), se = Symbol.for("react.context"), ce = Symbol.for("react.forward_ref"), le = Symbol.for("react.suspense"), ue = Symbol.for("react.suspense_list"), fe = Symbol.for("react.memo"), G = Symbol.for("react.lazy"), de = Symbol.for("react.activity"), me = Symbol.for("react.client.reference"), $ = E.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, L = Object.prototype.hasOwnProperty, he = Array.isArray, F = console.createTask ? console.createTask : function() { return null; }; E = { "react-stack-bottom-frame": function(t) { return t(); } }; var V, q = {}, B = E["react-stack-bottom-frame"].bind( E, l )(), z = F(o(l)), J = {}; b.Fragment = D, b.jsx = function(t, a, c, d, g) { var T = 1e4 > $.recentlyCreatedOwnerStacks++; return x( t, a, c, !1, d, g, T ? Error("react-stack-top-frame") : B, T ? F(o(t)) : z ); }, b.jsxs = function(t, a, c, d, g) { var T = 1e4 > $.recentlyCreatedOwnerStacks++; return x( t, a, c, !0, d, g, T ? Error("react-stack-top-frame") : B, T ? F(o(t)) : z ); }; }()), b; } var Z; function _e() { return Z || (Z = 1, process.env.NODE_ENV === "production" ? M.exports = ve() : M.exports = Ie()), M.exports; } var A = _e(); const ee = "0123456789ABCDEFGHJKMNPQRSTVWXYZ", S = 32, Re = 16, te = 10, Q = 281474976710655; var I; (function(n) { n.Base32IncorrectEncoding = "B32_ENC_INVALID", n.DecodeTimeInvalidCharacter = "DEC_TIME_CHAR", n.DecodeTimeValueMalformed = "DEC_TIME_MALFORMED", n.EncodeTimeNegative = "ENC_TIME_NEG", n.EncodeTimeSizeExceeded = "ENC_TIME_SIZE_EXCEED", n.EncodeTimeValueMalformed = "ENC_TIME_MALFORMED", n.PRNGDetectFailure = "PRNG_DETECT", n.ULIDInvalid = "ULID_INVALID", n.Unexpected = "UNEXPECTED", n.UUIDInvalid = "UUID_INVALID"; })(I || (I = {})); class N extends Error { constructor(r, e) { super(`${e} (${r})`), this.name = "ULIDError", this.code = r; } } function be(n) { let r = Math.floor(n() * S); return r === S && (r = S - 1), ee.charAt(r); } function Ae(n) { const r = Pe(), e = r && (r.crypto || r.msCrypto) || null; if (typeof (e == null ? void 0 : e.getRandomValues) == "function") return () => { const o = new Uint8Array(1); return e.getRandomValues(o), o[0] / 255; }; if (typeof (e == null ? void 0 : e.randomBytes) == "function") return () => e.randomBytes(1).readUInt8() / 255; throw new N(I.PRNGDetectFailure, "Failed to find a reliable PRNG"); } function Pe() { return Ne() ? self : typeof window < "u" ? window : typeof global < "u" ? global : typeof globalThis < "u" ? globalThis : null; } function ke(n, r) { let e = ""; for (; n > 0; n--) e = be(r) + e; return e; } function ye(n, r = te) { if (isNaN(n)) throw new N(I.EncodeTimeValueMalformed, `Time must be a number: ${n}`); if (n > Q) throw new N(I.EncodeTimeSizeExceeded, `Cannot encode a time larger than ${Q}: ${n}`); if (n < 0) throw new N(I.EncodeTimeNegative, `Time must be positive: ${n}`); if (Number.isInteger(n) === !1) throw new N(I.EncodeTimeValueMalformed, `Time must be an integer: ${n}`); let e, o = ""; for (let i = r; i > 0; i--) e = n % S, o = ee.charAt(e) + o, n = (n - e) / S; return o; } function Ne() { return typeof WorkerGlobalScope < "u" && self instanceof WorkerGlobalScope; } function Se(n, r) { const e = Ae(), o = Date.now(); return ye(o, te) + ke(Re, e); } const je = "acrool-react-vertical-marquee__slide-item", Oe = "acrool-react-vertical-marquee__slide-item-text", we = "acrool-react-vertical-marquee__container", Ce = "acrool-react-vertical-marquee__content", Me = "acrool-react-vertical-marquee__root", P = { slideItem: je, slideItemText: Oe, container: we, content: Ce, root: Me }, j = [ "color: #fff", "display: block", "line-height: 20px", "padding-right: 8px" ]; function O(n, r, e) { console.log(`%c ${n}`, r, e); } function De(n, r) { const e = j.concat([ "background-color: #007bff" ]).join(";"); O(n, e, r); } function $e(n, r) { const e = j.concat([ "background-color: #28a745" ]).join(";"); O(n, e, r); } function ne(n, r) { const e = j.concat([ "background-color: #17a2b8" ]).join(";"); O(n, e, r); } function Fe(n, r) { const e = j.concat([ "background-color: #ffc107" ]).join(";"); O(n, e, r); } function Ue(n, r) { const e = j.concat([ "background-color: #ec2127" ]).join(";"); O(n, e, r); } function We(n, r = !1) { const e = document.getElementById("console"); if (e) { const o = /* @__PURE__ */ new Date(), i = [o.getMinutes(), o.getSeconds()].join(""); e.value = `${i}: ${n} ${e.value}`; } else r && ne("mobile", n); } const k = { primary: De, success: $e, info: ne, warning: Fe, danger: Ue, printInText: We }; function K(n) { const { data: r } = n; let e = r ?? [], o = e == null ? void 0 : e.length; const i = Ye( e ), l = i.length, s = 1, f = s, h = 0, p = l - 1; return { info: { formatElement: i, sourceTotal: o, // 來源總數 // 從0開始 element: { total: l, firstIndex: 0, lastIndex: l - 1 }, // 0為實際一開始的位置(往前為負數), 結束值為最後結束位置 actual: { minIndex: h, maxIndex: p, firstIndex: Math.ceil(s), lastIndex: Math.ceil(o + f - 1) }, // 總頁數 pageTotal: o } }; } function Ye(n = []) { const r = []; let e = 0; const o = 1, i = n.length, l = n.length - o; for (const h of n.slice(-1)) r[e] = { actualIndex: e, matchIndex: o + l + e, inPage: i, isClone: !0, element: h.text }, e += 1; let s = e, f = 0; for (const [h, p] of n.entries()) r[e] = { actualIndex: e, matchIndex: e, sourceIndex: h, inPage: f + 1, isClone: !1, onClick: p.onClick, element: p.text }, e += 1, f += 1; for (const h of n.slice(0, o)) r[e] = { actualIndex: e, matchIndex: s, inPage: 1, isClone: !0, element: h.text }, e += 1, s += 1; return r; } const y = { componentDidMount: !0, componentWillUnmount: !0, shouldComponentUpdate: !0, checkAndAutoPlay: !0, goToActualIndex: !0 }; class Ge extends ge { constructor(e) { super(e); u(this, "_verticalMarqueeId", Se().toLowerCase()); u(this, "timer"); u(this, "activePage", 0); // real page location u(this, "activeActualIndex", 0); // real item index location u(this, "info", { formatElement: [], sourceTotal: 0, // Total number of sources // 從0開始 element: { total: 0, firstIndex: 0, lastIndex: 0 }, // 0 is the actual starting position (a negative number forward), and the ending value is the last ending position actual: { minIndex: 0, maxIndex: 0, firstIndex: 1, lastIndex: 1 }, // 總頁數 pageTotal: 0 }); // Ref u(this, "rootRef", C()); u(this, "containerRef", C()); u(this, "slideItemRefs", C()); u(this, "pageRefs", C()); /** * browser focus check auto play * @private */ u(this, "_onWindowFocus", () => { this._checkAndAutoPlay(); }); /** * browser blur clean auto play timer * @private */ u(this, "_onWindowBlur", () => { this.timer && clearTimeout(this.timer); }); /** * Check and autoplay feature */ u(this, "_checkAndAutoPlay", () => { const { autoPlayTime: e } = this.props; this.props.isDebug && y.checkAndAutoPlay && k.printInText(`[_checkAndAutoPlay] autoPlayTime: ${e}`), this.timer && clearTimeout(this.timer), e > 0 && this.info.pageTotal > 1 && (this.timer = setTimeout(() => { this.toNext(); }, e)); }); /** * get next page */ u(this, "getNextPage", () => this.activePage + 1); /** * Get virtual index */ u(this, "checkActualIndexInRange", (e) => e <= this.info.actual.maxIndex && e >= this.info.actual.minIndex); /** * go to next page */ u(this, "toNext", () => { var o; const e = (o = this.info) != null && o.formatElement ? this.info.formatElement : []; e[this.activeActualIndex].isClone ? (this.goToActualIndex(e[this.activeActualIndex].matchIndex, !1), this.goToActualIndex(this.activeActualIndex)) : this.goToActualIndex(this.activeActualIndex + 1); }); /** * go to page * ex: slideView: 2, slideGroup: 2, total: 4 * page1 -> (1-1) * 2) + 1 + (firstIndex -1) = 1 */ u(this, "goToPage", (e, o = !0) => { this.goToActualIndex(e - 1 + 1 + (this.info.actual.firstIndex - 1), o); }); /** * Get the target item distance width(px) * @param slideIndex */ u(this, "_getMoveDistance", (e) => { if (this.slideItemRefs.current) { const o = this.slideItemRefs.current[e]; if (o) return -o.offsetTop; } return 0; }); /** * Go to the actual location */ u(this, "goToActualIndex", (e, o = !0) => { var l, s, f; const { moveTime: i } = this.props; if (this.props.isDebug && y.goToActualIndex && k.printInText(`[goToActualIndex] slideIndex: ${e}, isUseAnimation: ${o}`), Math.ceil(e) !== e) throw Error(`slideIndex(${e}) can't has floating .xx`); if (this.checkActualIndexInRange(e)) { this.activeActualIndex = e, this.activePage = 1, typeof this.info.formatElement[this.activeActualIndex] < "u" && (this.activePage = this.info.formatElement[this.activeActualIndex].inPage); const h = this._getMoveDistance(this.activeActualIndex), p = (l = this.containerRef) == null ? void 0 : l.current; p && (p.style.visibility = "visible", p.style.transitionDuration = o ? `${i}ms` : "0ms", p.style.transform = `translate(0px, ${h}px)`); const x = (s = this.rootRef) == null ? void 0 : s.current; x && (this.activePage === 1 ? x.setAttribute("data-position", this.activePage === this.info.pageTotal ? "hidden" : "first") : x.setAttribute("data-position", this.activePage === this.info.pageTotal ? "last" : "")); const v = (f = this.slideItemRefs) == null ? void 0 : f.current; v && v.forEach((E, w) => { w === this.activeActualIndex ? E.setAttribute("data-active", "true") : E && E.removeAttribute("data-active"); }), this._checkAndAutoPlay(); } }); this.slideItemRefs.current = [], this.pageRefs.current = []; const { info: o } = K(e); this.info = o; } componentDidMount() { var o; this.props.isDebug && y.componentDidMount && k.printInText("[componentDidMount]"), ((o = this.containerRef) == null ? void 0 : o.current) && (this.info.pageTotal > 0 && this.goToPage(1, !1), window.addEventListener("focus", this._onWindowFocus, !1), window.addEventListener("blur", this._onWindowBlur, !1)); } componentWillUnmount() { this.props.isDebug && y.componentWillUnmount && k.printInText("[componentWillUnmount]"), this.timer && clearTimeout(this.timer); } /*** * Optimized rendering * @param nextProps * @param nextState */ shouldComponentUpdate(e, o) { const { data: i, ...l } = this.props, { data: s, ...f } = e, h = i == null ? void 0 : i.map((x) => x.key).join("_"), p = s == null ? void 0 : s.map((x) => x.key).join("_"); if (h !== p) { this.props.isDebug && y.shouldComponentUpdate && k.printInText("[shouldComponentUpdate] true"); const { info: x } = K(e); this.info = x; const v = this; return setTimeout(() => { v.goToPage(1, !1); }, 0), !0; } return !1; } render() { const { style: e, className: o, isDebug: i, isGPURender: l } = this.props; return /* @__PURE__ */ A.jsx( "div", { "data-vertial-marquee-id": this._verticalMarqueeId, style: e, className: [o, P.root].join(" ").trim(), "data-gpu-render": l ? "true" : void 0, "data-actual": `${this.info.actual.minIndex},${this.info.actual.firstIndex}-${this.info.actual.lastIndex},${this.info.actual.maxIndex}`, "data-debug": i ? "true" : void 0, ref: this.rootRef, children: /* @__PURE__ */ A.jsx("div", { className: P.content, children: /* @__PURE__ */ A.jsx( "ul", { ref: this.containerRef, className: P.container, children: this.info.formatElement.map((s, f) => /* @__PURE__ */ A.jsx( "li", { className: P.slideItem, ref: (h) => { this.slideItemRefs.current[f] = h; }, "data-active": s.actualIndex === this.activeActualIndex ? !0 : void 0, "data-actual": s.actualIndex, "data-match": s.isClone ? s.matchIndex : void 0, "data-page": s.inPage, "data-source": s.sourceIndex, "data-is-clone": s.isClone ? !0 : void 0, "data-click": typeof s.onClick < "u", onClick: s.onClick, children: /* @__PURE__ */ A.jsx("div", { className: P.slideItemText, dangerouslySetInnerHTML: { __html: s.element } }) }, `vertical-marquee_${f}` )) } ) }) } ); } } u(Ge, "defaultProps", { data: void 0, moveTime: 500, isEnableAutoPlay: !0, isGPURender: !0, isDebug: !1, autoPlayTime: 5e3 }); export { Ge as default };