"use client"; import { useState } from "react"; import { motion, useReducedMotion } from "motion/react"; type NumberFlipProps = { /** What to show, like 1284 or "12:05". Letters and digits flip, the rest stays still. */ value: number | string; /** Replaces the default tile look. Text size comes from the parent. */ className?: string; }; const HALF = "absolute inset-x-0 h-1/2 overflow-hidden bg-inherit"; const Face = ({ char, top }: { char: string; top?: boolean }) => ( {char} ); function Flap({ char, className }: { char: string; className: string }) { const reduce = useReducedMotion(); const [flip, setFlip] = useState({ now: char, was: char }); if (flip.now !== char) setFlip({ now: char, was: flip.now }); const was = reduce ? flip.now : flip.was; return ( {was !== flip.now && ( <> )} ); } /* NumberFlip: a split-flap board. When a character changes, its top half folds down and the new one lands underneath. Only the characters that changed move. */ export function NumberFlip({ value, className = "bg-[#1a1530] text-white" }: NumberFlipProps) { const text = String(value); return ( {text} {[...text].map((char, i) => /[\p{L}\p{N}]/u.test(char) ? : {char}, )} ); }