// theme-store.jsx — localStorage-backed theme + floating FAB toggle // Loaded after router.jsx, before components.jsx. const THEME_KEY = "saraslot.theme"; const THEMES = ["gold", "neon", "jade"]; function readStoredTheme() { try { const v = localStorage.getItem(THEME_KEY); return THEMES.includes(v) ? v : null; } catch (e) { return null; } } function useThemeStore(initial) { const [theme, setThemeState] = React.useState(() => readStoredTheme() || initial || "gold"); const setTheme = React.useCallback((v) => { if (!THEMES.includes(v)) return; setThemeState(v); try { localStorage.setItem(THEME_KEY, v); } catch (e) {} }, []); React.useEffect(() => { const onStorage = (e) => { if (e.key === THEME_KEY && THEMES.includes(e.newValue)) { setThemeState(e.newValue); } }; window.addEventListener("storage", onStorage); return () => window.removeEventListener("storage", onStorage); }, []); return [theme, setTheme]; } function ThemeFab({ theme, onChange }) { const [open, setOpen] = React.useState(false); const rootRef = React.useRef(null); React.useEffect(() => { if (!open) return; const onDoc = (e) => { if (rootRef.current && !rootRef.current.contains(e.target)) { setOpen(false); } }; document.addEventListener("mousedown", onDoc); document.addEventListener("touchstart", onDoc); return () => { document.removeEventListener("mousedown", onDoc); document.removeEventListener("touchstart", onDoc); }; }, [open]); const label = { gold: "G", neon: "N", jade: "J" }[theme] || "G"; return (
{open && (
Theme
{THEMES.map((t) => ( ))}
)}
); } window.THEME_KEY = THEME_KEY; window.THEMES = THEMES; window.useThemeStore = useThemeStore; window.ThemeFab = ThemeFab;