import React, { useMemo } from 'react'; import { useAtomValue } from 'jotai'; import { settingsAtom } from '../../state/settings'; import { zIndices } from '../../styles/zIndex'; import { SeasonTheme } from './types'; import { getActiveSeason } from './seasonSchedule'; import { HalloweenOverlay } from './themes/Halloween'; import { ChristmasOverlay } from './themes/Christmas'; import { NewYearOverlay } from './themes/NewYear'; import { AutumnOverlay } from './themes/Autumn'; import { AprilFoolsOverlay } from './themes/AprilFools'; import { LunarNewYearOverlay } from './themes/LunarNewYear'; import { ValentinesOverlay } from './themes/Valentines'; import { StPatricksOverlay } from './themes/StPatricks'; import { EarthDayOverlay } from './themes/EarthDay'; import { DeepSpaceOverlay } from './themes/DeepSpace'; import { ArcadeOverlay } from './themes/Arcade'; // SeasonTheme + the date-window logic now live in leaf modules (single source // of truth, shared with the settings UI). Re-exported here for existing // importers that still reach for it from this file. export type { SeasonTheme }; // ─── Overlay content map (shared between SeasonalOverlay and SeasonalPreview) ── function buildOverlayContent(theme: SeasonTheme, reduced: boolean): React.ReactNode { switch (theme) { case 'halloween': return ; case 'christmas': return ; case 'newyear': return ; case 'autumn': return ; case 'aprilfools': return ; case 'lunar': return ; case 'valentines': return ; case 'stpatricks': return ; case 'earthday': return ; case 'deepspace': return ; case 'arcade': return ; default: return null; } } // ─── Full-screen overlay (fixed position, used in App) ──────────────────────── function SeasonalOverlay({ theme, reduced }: { theme: SeasonTheme; reduced: boolean }) { return ( ); } // ─── Preview overlay (absolute position, contained in a card) ───────────────── /** * Renders the ambient (reduced-motion) version of a seasonal overlay inside * a parent container. The parent must have `position: relative; overflow: hidden`. */ export function SeasonalPreview({ theme }: { theme: SeasonTheme }) { return ( ); } // ─── Main exported component ────────────────────────────────────────────────── export function SeasonalEffect() { const settings = useAtomValue(settingsAtom); const reduced = typeof window !== 'undefined' && window.matchMedia('(prefers-reduced-motion: reduce)').matches; const theme = useMemo(() => { const override = settings.seasonalThemeOverride ?? 'auto'; if (override === 'off') return null; if (override === 'auto') return getActiveSeason(new Date()); return override as SeasonTheme; }, [settings.seasonalThemeOverride]); if (!theme) return null; // Suppress seasonal overlay when a chat background is active — both running simultaneously // wastes GPU and looks cluttered. The settings UI enforces mutual exclusion on write; // this guard covers any legacy state already persisted. if (settings.chatBackground !== 'none') return null; return ; }