{"version":3,"sources":["../src/utils/dom.ts"],"sourcesContent":["import { SetupThemeManagementParams, Theme } from '../types';\r\n\r\n/**\r\n * Gets the current system theme preference from the user's OS settings\r\n * @returns {boolean} true if the system prefers dark mode, false if light mode\r\n * @example\r\n * ```ts\r\n * const prefersDark = getSystemThemePreference();\r\n * if (prefersDark) {\r\n *   console.log('System prefers dark mode');\r\n * }\r\n * ```\r\n */\r\nexport const getSystemThemePreference = (): boolean => {\r\n    return window.matchMedia('(prefers-color-scheme: dark)').matches;\r\n};\r\n\r\n/**\r\n * Determines if dark mode should be active based on the current theme setting\r\n * @param theme - The theme setting to check ('dark' | 'light' | 'system')\r\n * @returns {boolean} true if dark mode should be active, false otherwise\r\n * @example\r\n * ```ts\r\n * const shouldDark = shouldUseDarkMode('system'); // Returns true if system prefers dark\r\n * const shouldDark = shouldUseDarkMode('dark');   // Always returns true\r\n * const shouldDark = shouldUseDarkMode('light');  // Always returns false\r\n * ```\r\n */\r\nexport const shouldUseDarkMode = (theme: Theme): boolean => {\r\n    return theme === 'dark' || (theme === 'system' && getSystemThemePreference());\r\n};\r\n\r\n/**\r\n * Applies the specified theme to the DOM by adding/removing classes and attributes\r\n * @param isDark - Whether to apply dark mode (true) or light mode (false)\r\n * @example\r\n * ```ts\r\n * applyThemeToDOM(true);  // Applies dark theme\r\n * applyThemeToDOM(false); // Applies light theme\r\n * ```\r\n */\r\nexport const applyThemeToDOM = (isDark: boolean): void => {\r\n    const html = document.documentElement;\r\n    if (isDark) {\r\n        html.classList.add('dark');\r\n        html.setAttribute('data-theme', 'dark');\r\n    } else {\r\n        html.classList.remove('dark');\r\n        html.setAttribute('data-theme', 'light');\r\n    }\r\n};\r\n\r\n/**\r\n * Sets the theme in localStorage and applies it to the DOM\r\n * @param theme - The theme to set ('dark' | 'light' | 'system')\r\n * @example\r\n * ```ts\r\n * setTheme('dark');   // Sets and applies dark theme\r\n * setTheme('light');  // Sets and applies light theme\r\n * setTheme('system'); // Sets theme to follow system preference\r\n * ```\r\n */\r\nexport const setTheme = (theme: Theme): void => {\r\n    localStorage.setItem('theme', theme);\r\n    const isDark = shouldUseDarkMode(theme);\r\n    applyThemeToDOM(isDark);\r\n};\r\n\r\n/**\r\n * Initializes the theme from localStorage or falls back to system preference\r\n * @returns {Theme} The initialized theme ('dark' | 'light' | 'system')\r\n * @example\r\n * ```ts\r\n * const theme = initializeTheme();\r\n * console.log(`Current theme: ${theme}`);\r\n * ```\r\n */\r\nexport const initializeTheme = (): Theme => {\r\n    const savedTheme = localStorage.getItem('theme') as Theme | null;\r\n    const theme = savedTheme || 'system';\r\n    const isDark = shouldUseDarkMode(theme);\r\n    applyThemeToDOM(isDark);\r\n    return theme;\r\n};\r\n\r\n/**\r\n * Subscribes to system theme changes and calls the provided callback when changes occur\r\n * @param callback - Function to call when system theme changes, receives boolean indicating if dark mode is active\r\n * @returns {() => void} Cleanup function to remove the event listener\r\n * @example\r\n * ```ts\r\n * const unsubscribe = subscribeToSystemTheme((isDark) => {\r\n *   console.log(`System theme changed to: ${isDark ? 'dark' : 'light'}`);\r\n * });\r\n *\r\n * // Later, to cleanup:\r\n * unsubscribe();\r\n * ```\r\n */\r\nexport const subscribeToSystemTheme = (callback: (isDark: boolean) => void): (() => void) => {\r\n    const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\r\n    const handler = (e: MediaQueryListEvent): void => {\r\n        callback(e.matches);\r\n        // Apply theme when system preference changes\r\n        const theme = (localStorage.getItem('theme') as Theme) || 'system';\r\n        if (theme === 'system') {\r\n            applyThemeToDOM(e.matches);\r\n        }\r\n    };\r\n    mediaQuery.addEventListener('change', handler);\r\n    return () => mediaQuery.removeEventListener('change', handler);\r\n};\r\n\r\n/**\r\n * Sets up theme initialization, system theme subscription, and storage synchronization.\r\n * Accepts callbacks for theme changes and system theme changes.\r\n * Returns a cleanup function to remove event listeners.\r\n *\r\n * @param setTheme - Function to set the application's theme state.\r\n * @param initializeTheme - Function to initialize the theme from storage or system preference.\r\n * @param onThemeChange - Optional callback function called when the theme changes.\r\n * @param onSystemThemeChange - Optional callback function called when the system theme changes.\r\n * @returns {() => void} Cleanup function to remove event listeners.\r\n */\r\nexport const setupThemeManagement = (params: SetupThemeManagementParams): (() => void) => {\r\n    const { setTheme, initializeTheme, onThemeChange, onSystemThemeChange } = params;\r\n\r\n    // Initialize theme\r\n    initializeTheme();\r\n\r\n    // Subscribe to system theme changes\r\n    const cleanupSystemTheme = subscribeToSystemTheme((isDark: boolean): void => {\r\n        onSystemThemeChange?.(isDark);\r\n    });\r\n\r\n    // Listen for theme toggle events\r\n    const handleThemeToggle = (event: CustomEvent<Theme>): void => {\r\n        if (event.detail) {\r\n            setTheme(event.detail);\r\n            onThemeChange?.(event.detail);\r\n        } else {\r\n            // If no theme provided, get it from localStorage\r\n            const storedTheme = localStorage.getItem('theme') as Theme | null;\r\n            const theme = storedTheme || 'system';\r\n            setTheme(theme);\r\n            onThemeChange?.(theme);\r\n        }\r\n    };\r\n\r\n    // Listen for storage changes to sync theme across tabs\r\n    const handleStorageChange = (event: StorageEvent): void => {\r\n        if (event.key === 'theme' && event.newValue) {\r\n            const newTheme = event.newValue as Theme;\r\n            setTheme(newTheme);\r\n            onThemeChange?.(newTheme);\r\n        }\r\n    };\r\n\r\n    window.addEventListener('theme-toggle', handleThemeToggle as EventListener);\r\n    window.addEventListener('storage', handleStorageChange);\r\n\r\n    const cleanupEventListeners = (): void => {\r\n        window.removeEventListener('theme-toggle', handleThemeToggle as EventListener);\r\n        window.removeEventListener('storage', handleStorageChange);\r\n    };\r\n\r\n    return () => {\r\n        cleanupSystemTheme();\r\n        cleanupEventListeners();\r\n    };\r\n};\r\n"],"mappings":";;;;;AAaO,IAAM,2BAA2B,6BAAe;AACnD,SAAO,OAAO,WAAW,8BAA8B,EAAE;AAC7D,GAFwC;AAejC,IAAM,oBAAoB,wBAAC,UAA0B;AACxD,SAAO,UAAU,UAAW,UAAU,YAAY,yBAAyB;AAC/E,GAFiC;AAa1B,IAAM,kBAAkB,wBAAC,WAA0B;AACtD,QAAM,OAAO,SAAS;AACtB,MAAI,QAAQ;AACR,SAAK,UAAU,IAAI,MAAM;AACzB,SAAK,aAAa,cAAc,MAAM;AAAA,EAC1C,OAAO;AACH,SAAK,UAAU,OAAO,MAAM;AAC5B,SAAK,aAAa,cAAc,OAAO;AAAA,EAC3C;AACJ,GAT+B;AAqBxB,IAAM,WAAW,wBAAC,UAAuB;AAC5C,eAAa,QAAQ,SAAS,KAAK;AACnC,QAAM,SAAS,kBAAkB,KAAK;AACtC,kBAAgB,MAAM;AAC1B,GAJwB;AAejB,IAAM,kBAAkB,6BAAa;AACxC,QAAM,aAAa,aAAa,QAAQ,OAAO;AAC/C,QAAM,QAAQ,cAAc;AAC5B,QAAM,SAAS,kBAAkB,KAAK;AACtC,kBAAgB,MAAM;AACtB,SAAO;AACX,GAN+B;AAsBxB,IAAM,yBAAyB,wBAAC,aAAsD;AACzF,QAAM,aAAa,OAAO,WAAW,8BAA8B;AACnE,QAAM,UAAU,wBAAC,MAAiC;AAC9C,aAAS,EAAE,OAAO;AAElB,UAAM,QAAS,aAAa,QAAQ,OAAO,KAAe;AAC1D,QAAI,UAAU,UAAU;AACpB,sBAAgB,EAAE,OAAO;AAAA,IAC7B;AAAA,EACJ,GAPgB;AAQhB,aAAW,iBAAiB,UAAU,OAAO;AAC7C,SAAO,MAAM,WAAW,oBAAoB,UAAU,OAAO;AACjE,GAZsC;AAyB/B,IAAM,uBAAuB,wBAAC,WAAqD;AACtF,QAAM,EAAE,UAAAA,WAAU,iBAAAC,kBAAiB,eAAe,oBAAoB,IAAI;AAG1E,EAAAA,iBAAgB;AAGhB,QAAM,qBAAqB,uBAAuB,CAAC,WAA0B;AACzE,0BAAsB,MAAM;AAAA,EAChC,CAAC;AAGD,QAAM,oBAAoB,wBAAC,UAAoC;AAC3D,QAAI,MAAM,QAAQ;AACd,MAAAD,UAAS,MAAM,MAAM;AACrB,sBAAgB,MAAM,MAAM;AAAA,IAChC,OAAO;AAEH,YAAM,cAAc,aAAa,QAAQ,OAAO;AAChD,YAAM,QAAQ,eAAe;AAC7B,MAAAA,UAAS,KAAK;AACd,sBAAgB,KAAK;AAAA,IACzB;AAAA,EACJ,GAX0B;AAc1B,QAAM,sBAAsB,wBAAC,UAA8B;AACvD,QAAI,MAAM,QAAQ,WAAW,MAAM,UAAU;AACzC,YAAM,WAAW,MAAM;AACvB,MAAAA,UAAS,QAAQ;AACjB,sBAAgB,QAAQ;AAAA,IAC5B;AAAA,EACJ,GAN4B;AAQ5B,SAAO,iBAAiB,gBAAgB,iBAAkC;AAC1E,SAAO,iBAAiB,WAAW,mBAAmB;AAEtD,QAAM,wBAAwB,6BAAY;AACtC,WAAO,oBAAoB,gBAAgB,iBAAkC;AAC7E,WAAO,oBAAoB,WAAW,mBAAmB;AAAA,EAC7D,GAH8B;AAK9B,SAAO,MAAM;AACT,uBAAmB;AACnB,0BAAsB;AAAA,EAC1B;AACJ,GA9CoC;","names":["setTheme","initializeTheme"]}