"use client";
import { motion, useReducedMotion } from "motion/react";
type StaggerTypeProps = {
text: string;
className?: string;
/** Where the stagger starts: the first letter, the middle, or the last. */
from?: "start" | "center" | "end";
/** Seconds between neighbouring letters. */
stagger?: number;
/** Play only the first time it scrolls into view. */
once?: boolean;
};
/* StaggerType: letters drop in from above and settle with a spring, timed outward from the start, centre or end of the line. */
export function StaggerType({ text, className = "", from = "center", stagger = 0.03, once = true }: StaggerTypeProps) {
const reduce = useReducedMotion();
if (reduce) return {text};
const words = text.split(" ");
const starts = words.map((_, w) => words.slice(0, w).join("").length);
const last = text.replace(/ /g, "").length - 1;
const origin = from === "start" ? 0 : from === "end" ? last : last / 2;
return (
{text}
{words.map((word, w) => (
{[...word].map((ch, i) => (
({
opacity: 1,
y: 0,
scale: 1,
transition: { type: "spring", stiffness: 300, damping: 20, delay: d * stagger },
}),
}}
>
{ch}
))}
{w < words.length - 1 && " "}
))}
);
}