import { useEffect, useRef, useState, type ReactNode } from "react"; interface PageTransitionProps { viewKey: string; children: ReactNode; } const EXIT_DURATION_MS = 180; const NAV_ORDER: string[] = [ "home", "workbench", "ecommerce", "ecommerceTemplates", "sizeTemplate", "canvas", "scriptTokens", "tokenUsage", "community", "assets", "more", "imageWorkbench", "resolutionUpscale", "watermarkRemoval", "subtitleRemoval", "dialogGenerator", "digitalHuman", "avatarConsole", "characterMix", "agent", "login", "profile", "report", ]; function getNavIndex(key: string): number { return NAV_ORDER.indexOf(key); } export default function PageTransition({ viewKey, children }: PageTransitionProps) { const [displayedChildren, setDisplayedChildren] = useState(children); const [phase, setPhase] = useState<"idle" | "exit">("idle"); const [exitDirection, setExitDirection] = useState<"forward" | "backward" | "neutral">("neutral"); const prevKeyRef = useRef(viewKey); const timerRef = useRef>(); useEffect(() => { if (viewKey === prevKeyRef.current) { setDisplayedChildren(children); // Cancel any active exit animation — children updated but viewKey stable. setPhase("idle"); return; } const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches; if (prefersReducedMotion) { prevKeyRef.current = viewKey; setDisplayedChildren(children); setPhase("idle"); return; } const prevIndex = getNavIndex(prevKeyRef.current); const nextIndex = getNavIndex(viewKey); if (prevIndex < nextIndex) { setExitDirection("forward"); } else if (prevIndex > nextIndex) { setExitDirection("backward"); } else { setExitDirection("neutral"); } prevKeyRef.current = viewKey; setPhase("exit"); timerRef.current = setTimeout(() => { setDisplayedChildren(children); setPhase("idle"); }, EXIT_DURATION_MS); return () => clearTimeout(timerRef.current); }, [viewKey, children]); const dirClass = exitDirection === "forward" ? " is-forward" : exitDirection === "backward" ? " is-backward" : ""; if (!displayedChildren) return null; return (
{displayedChildren}
); }