"use strict"; 'use client'; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = useCurrentColorScheme; exports.getColorScheme = getColorScheme; exports.getSystemMode = getSystemMode; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var React = _interopRequireWildcard(require("react")); var _getInitColorSchemeScript = require("./getInitColorSchemeScript"); function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } function getSystemMode(mode) { if (typeof window !== 'undefined' && mode === 'system') { const mql = window.matchMedia('(prefers-color-scheme: dark)'); if (mql.matches) { return 'dark'; } return 'light'; } return undefined; } function processState(state, callback) { if (state.mode === 'light' || state.mode === 'system' && state.systemMode === 'light') { return callback('light'); } if (state.mode === 'dark' || state.mode === 'system' && state.systemMode === 'dark') { return callback('dark'); } return undefined; } function getColorScheme(state) { return processState(state, mode => { if (mode === 'light') { return state.lightColorScheme; } if (mode === 'dark') { return state.darkColorScheme; } return undefined; }); } function initializeValue(key, defaultValue) { if (typeof window === 'undefined') { return undefined; } let value; try { value = localStorage.getItem(key) || undefined; if (!value) { // the first time that user enters the site. localStorage.setItem(key, defaultValue); } } catch (e) { // Unsupported } return value || defaultValue; } function useCurrentColorScheme(options) { const { defaultMode = 'light', defaultLightColorScheme, defaultDarkColorScheme, supportedColorSchemes = [], modeStorageKey = _getInitColorSchemeScript.DEFAULT_MODE_STORAGE_KEY, colorSchemeStorageKey = _getInitColorSchemeScript.DEFAULT_COLOR_SCHEME_STORAGE_KEY, storageWindow = typeof window === 'undefined' ? undefined : window } = options; const joinedColorSchemes = supportedColorSchemes.join(','); const [state, setState] = React.useState(() => { const initialMode = initializeValue(modeStorageKey, defaultMode); const lightColorScheme = initializeValue(`${colorSchemeStorageKey}-light`, defaultLightColorScheme); const darkColorScheme = initializeValue(`${colorSchemeStorageKey}-dark`, defaultDarkColorScheme); return { mode: initialMode, systemMode: getSystemMode(initialMode), lightColorScheme, darkColorScheme }; }); const colorScheme = getColorScheme(state); const setMode = React.useCallback(mode => { setState(currentState => { if (mode === currentState.mode) { // do nothing if mode does not change return currentState; } const newMode = mode != null ? mode : defaultMode; try { localStorage.setItem(modeStorageKey, newMode); } catch (e) { // Unsupported } return (0, _extends2.default)({}, currentState, { mode: newMode, systemMode: getSystemMode(newMode) }); }); }, [modeStorageKey, defaultMode]); const setColorScheme = React.useCallback(value => { if (!value) { setState(currentState => { try { localStorage.setItem(`${colorSchemeStorageKey}-light`, defaultLightColorScheme); localStorage.setItem(`${colorSchemeStorageKey}-dark`, defaultDarkColorScheme); } catch (e) { // Unsupported } return (0, _extends2.default)({}, currentState, { lightColorScheme: defaultLightColorScheme, darkColorScheme: defaultDarkColorScheme }); }); } else if (typeof value === 'string') { if (value && !joinedColorSchemes.includes(value)) { console.error(`\`${value}\` does not exist in \`theme.colorSchemes\`.`); } else { setState(currentState => { const newState = (0, _extends2.default)({}, currentState); processState(currentState, mode => { try { localStorage.setItem(`${colorSchemeStorageKey}-${mode}`, value); } catch (e) { // Unsupported } if (mode === 'light') { newState.lightColorScheme = value; } if (mode === 'dark') { newState.darkColorScheme = value; } }); return newState; }); } } else { setState(currentState => { const newState = (0, _extends2.default)({}, currentState); const newLightColorScheme = value.light === null ? defaultLightColorScheme : value.light; const newDarkColorScheme = value.dark === null ? defaultDarkColorScheme : value.dark; if (newLightColorScheme) { if (!joinedColorSchemes.includes(newLightColorScheme)) { console.error(`\`${newLightColorScheme}\` does not exist in \`theme.colorSchemes\`.`); } else { newState.lightColorScheme = newLightColorScheme; try { localStorage.setItem(`${colorSchemeStorageKey}-light`, newLightColorScheme); } catch (error) { // Unsupported } } } if (newDarkColorScheme) { if (!joinedColorSchemes.includes(newDarkColorScheme)) { console.error(`\`${newDarkColorScheme}\` does not exist in \`theme.colorSchemes\`.`); } else { newState.darkColorScheme = newDarkColorScheme; try { localStorage.setItem(`${colorSchemeStorageKey}-dark`, newDarkColorScheme); } catch (error) { // Unsupported } } } return newState; }); } }, [joinedColorSchemes, colorSchemeStorageKey, defaultLightColorScheme, defaultDarkColorScheme]); const handleMediaQuery = React.useCallback(event => { if (state.mode === 'system') { setState(currentState => { const systemMode = event != null && event.matches ? 'dark' : 'light'; // Early exit, nothing changed. if (currentState.systemMode === systemMode) { return currentState; } return (0, _extends2.default)({}, currentState, { systemMode }); }); } }, [state.mode]); // Ref hack to avoid adding handleMediaQuery as a dep const mediaListener = React.useRef(handleMediaQuery); mediaListener.current = handleMediaQuery; React.useEffect(() => { const handler = (...args) => mediaListener.current(...args); // Always listen to System preference const media = window.matchMedia('(prefers-color-scheme: dark)'); // Intentionally use deprecated listener methods to support iOS & old browsers media.addListener(handler); handler(media); return () => { media.removeListener(handler); }; }, []); // Handle when localStorage has changed React.useEffect(() => { if (storageWindow) { const handleStorage = event => { const value = event.newValue; if (typeof event.key === 'string' && event.key.startsWith(colorSchemeStorageKey) && (!value || joinedColorSchemes.match(value))) { // If the key is deleted, value will be null then reset color scheme to the default one. if (event.key.endsWith('light')) { setColorScheme({ light: value }); } if (event.key.endsWith('dark')) { setColorScheme({ dark: value }); } } if (event.key === modeStorageKey && (!value || ['light', 'dark', 'system'].includes(value))) { setMode(value || defaultMode); } }; // For syncing color-scheme changes between iframes storageWindow.addEventListener('storage', handleStorage); return () => { storageWindow.removeEventListener('storage', handleStorage); }; } return undefined; }, [setColorScheme, setMode, modeStorageKey, colorSchemeStorageKey, joinedColorSchemes, defaultMode, storageWindow]); return (0, _extends2.default)({}, state, { colorScheme, setMode, setColorScheme }); }