@dxkit-org/react-marquee
Version:
A modern, lightweight React marquee component with TypeScript support. Features customizable animations, fade effects, direction control, and accessibility-friendly scrolling text.
92 lines (88 loc) • 5.82 kB
JavaScript
// src/index.tsx
import { useLayoutEffect, useState } from "react";
// #style-inject:#style-inject
function styleInject(css, { insertAt } = {}) {
if (!css || typeof document === "undefined") return;
const head = document.head || document.getElementsByTagName("head")[0];
const style = document.createElement("style");
style.type = "text/css";
if (insertAt === "top") {
if (head.firstChild) {
head.insertBefore(style, head.firstChild);
} else {
head.appendChild(style);
}
} else {
head.appendChild(style);
}
if (style.styleSheet) {
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}
}
// src/global.css
styleInject(".dxkit-marquee-flex {\n display: flex;\n}\n.dxkit-marquee-shrink-0 {\n flex-shrink: 0;\n}\n@keyframes dxkit-marquee-marquee-left {\n from {\n transform: translateX(0);\n }\n to {\n transform: translateX(calc(-100% - var(--gap)));\n }\n}\n.dxkit-marquee-animate-marquee-left {\n animation: dxkit-marquee-marquee-left var(--duration, 40s) linear infinite;\n}\n@keyframes dxkit-marquee-marquee-up {\n from {\n transform: translateY(0);\n }\n to {\n transform: translateY(calc(-100% - var(--gap)));\n }\n}\n.dxkit-marquee-animate-marquee-up {\n animation: dxkit-marquee-marquee-up var(--duration, 40s) linear infinite;\n}\n.dxkit-marquee-flex-row {\n flex-direction: row;\n}\n.dxkit-marquee-flex-col {\n flex-direction: column;\n}\n.dxkit-marquee-justify-around {\n justify-content: space-around;\n}\n.dxkit-marquee-gap-\\[1rem\\] {\n gap: 1rem;\n}\n.dxkit-marquee-overflow-hidden {\n overflow: hidden;\n}\n.group:hover .dxkit-marquee-group-hover\\:dxkit-marquee-animation-paused {\n animation-play-state: paused;\n}\n.dxkit-marquee-direction-reverse {\n animation-direction: reverse;\n}\n.dxkit-marquee-animate-marquee-left {\n animation: marquee-left var(--marquee-duration, 15s) linear infinite;\n}\n.dxkit-marquee-animate-marquee-up {\n animation: marquee-up var(--marquee-duration, 15s) linear infinite;\n}\n.dxkit-marquee-flex {\n display: flex;\n}\n.dxkit-marquee-flex-row {\n flex-direction: row;\n}\n.dxkit-marquee-flex-col {\n flex-direction: column;\n}\n.dxkit-marquee-gap-\\[1rem\\] {\n gap: 1rem;\n}\n.dxkit-marquee-overflow-hidden {\n overflow: hidden;\n}\n.dxkit-marquee-justify-around {\n justify-content: space-around;\n}\n.dxkit-marquee-shrink-0 {\n flex-shrink: 0;\n}\n.\\[--gap\\:1rem\\] {\n --gap: 1rem;\n}\n@keyframes marquee-left {\n 0% {\n transform: translateX(0%);\n }\n 100% {\n transform: translateX(-100%);\n }\n}\n@keyframes marquee-up {\n 0% {\n transform: translateY(0%);\n }\n 100% {\n transform: translateY(-100%);\n }\n}\n.dxkit-marquee-flex,\n.dxkit-marquee-animate-marquee-left,\n.dxkit-marquee-animate-marquee-up {\n will-change: transform;\n transform: translateZ(0);\n}\n@media (prefers-reduced-motion: reduce) {\n .dxkit-marquee-animate-marquee-left,\n .dxkit-marquee-animate-marquee-up {\n animation-duration: 30s;\n }\n}\n@supports (transform: translate3d(0, 0, 0)) {\n .dxkit-marquee-animate-marquee-left {\n animation-name: marquee-left-3d;\n }\n .dxkit-marquee-animate-marquee-up {\n animation-name: marquee-up-3d;\n }\n}\n@keyframes marquee-left-3d {\n 0% {\n transform: translate3d(0%, 0, 0);\n }\n 100% {\n transform: translate3d(-100%, 0, 0);\n }\n}\n@keyframes marquee-up-3d {\n 0% {\n transform: translate3d(0, 0%, 0);\n }\n 100% {\n transform: translate3d(0, -100%, 0);\n }\n}\n");
// src/lib/utils.ts
import { clsx } from "clsx";
import { twMerge } from "tailwind-merge";
function cn(...inputs) {
return twMerge(clsx(inputs));
}
// src/index.tsx
import { jsx } from "react/jsx-runtime";
function Marquee({
children,
direction = "left",
pauseOnHover = false,
reverse = false,
fade = false,
numberOfCopies = 2,
containerProps,
childrenWrapperProps
}) {
const { className, ...rest } = containerProps || {};
const { className: innerClassName, ...childrenWrapperRest } = childrenWrapperProps || {};
const [actualCopies, setActualCopies] = useState(1);
useLayoutEffect(() => {
const timer = setTimeout(() => {
setActualCopies(numberOfCopies);
}, 0);
return () => clearTimeout(timer);
}, []);
const isHorizontal = direction === "left" || direction === "right";
return /* @__PURE__ */ jsx(
"div",
{
className: cn(
"group dxkit-marquee-flex dxkit-marquee-gap-[1rem] dxkit-marquee-overflow-hidden",
isHorizontal ? "dxkit-marquee-flex-row" : "dxkit-marquee-flex-col",
className
),
style: {
maskImage: fade ? `linear-gradient(${isHorizontal ? "to right" : "to bottom"}, transparent 0%, rgba(0, 0, 0, 1.0) 10%, rgba(0, 0, 0, 1.0) 90%, transparent 100%)` : void 0,
WebkitMaskImage: fade ? `linear-gradient(${isHorizontal ? "to right" : "to bottom"}, transparent 0%, rgba(0, 0, 0, 1.0) 10%, rgba(0, 0, 0, 1.0) 90%, transparent 100%)` : void 0
},
...rest,
children: Array(actualCopies).fill(0).map((_, i) => /* @__PURE__ */ jsx(
"div",
{
className: cn(
"dxkit-marquee-flex dxkit-marquee-justify-around dxkit-marquee-gap-[1rem] [--gap:1rem] dxkit-marquee-shrink-0",
isHorizontal ? "dxkit-marquee-animate-marquee-left dxkit-marquee-flex-row" : "dxkit-marquee-animate-marquee-up dxkit-marquee-flex-col",
pauseOnHover && "dxkit-marquee-group-hover:dxkit-marquee-animation-paused",
(reverse || direction === "right" || direction === "down") && "dxkit-marquee-direction-reverse",
innerClassName
),
...childrenWrapperRest,
children
},
i
))
}
);
}
export {
Marquee
};
//# sourceMappingURL=index.mjs.map