"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},
)}
);
}