@acrool/react-vertical-marquee
Version:
Most modern vertical marquee with hardware accelerated transitions for ReactJS
667 lines (666 loc) • 21.5 kB
JavaScript
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
};