231 lines
8.5 KiB
Plaintext
231 lines
8.5 KiB
Plaintext
'use client';
|
|
|
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
import * as React from 'react';
|
|
import { DEFAULT_MODE_STORAGE_KEY, DEFAULT_COLOR_SCHEME_STORAGE_KEY } from './getInitColorSchemeScript';
|
|
export function getSystemMode(mode) {
|
|
if (typeof window !== 'undefined' && mode === 'system') {
|
|
var 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;
|
|
}
|
|
export function getColorScheme(state) {
|
|
return processState(state, function (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;
|
|
}
|
|
var 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;
|
|
}
|
|
export default function useCurrentColorScheme(options) {
|
|
var _options$defaultMode = options.defaultMode,
|
|
defaultMode = _options$defaultMode === void 0 ? 'light' : _options$defaultMode,
|
|
defaultLightColorScheme = options.defaultLightColorScheme,
|
|
defaultDarkColorScheme = options.defaultDarkColorScheme,
|
|
_options$supportedCol = options.supportedColorSchemes,
|
|
supportedColorSchemes = _options$supportedCol === void 0 ? [] : _options$supportedCol,
|
|
_options$modeStorageK = options.modeStorageKey,
|
|
modeStorageKey = _options$modeStorageK === void 0 ? DEFAULT_MODE_STORAGE_KEY : _options$modeStorageK,
|
|
_options$colorSchemeS = options.colorSchemeStorageKey,
|
|
colorSchemeStorageKey = _options$colorSchemeS === void 0 ? DEFAULT_COLOR_SCHEME_STORAGE_KEY : _options$colorSchemeS,
|
|
_options$storageWindo = options.storageWindow,
|
|
storageWindow = _options$storageWindo === void 0 ? typeof window === 'undefined' ? undefined : window : _options$storageWindo;
|
|
var joinedColorSchemes = supportedColorSchemes.join(',');
|
|
var _React$useState = React.useState(function () {
|
|
var initialMode = initializeValue(modeStorageKey, defaultMode);
|
|
var lightColorScheme = initializeValue("".concat(colorSchemeStorageKey, "-light"), defaultLightColorScheme);
|
|
var darkColorScheme = initializeValue("".concat(colorSchemeStorageKey, "-dark"), defaultDarkColorScheme);
|
|
return {
|
|
mode: initialMode,
|
|
systemMode: getSystemMode(initialMode),
|
|
lightColorScheme: lightColorScheme,
|
|
darkColorScheme: darkColorScheme
|
|
};
|
|
}),
|
|
state = _React$useState[0],
|
|
setState = _React$useState[1];
|
|
var colorScheme = getColorScheme(state);
|
|
var setMode = React.useCallback(function (mode) {
|
|
setState(function (currentState) {
|
|
if (mode === currentState.mode) {
|
|
// do nothing if mode does not change
|
|
return currentState;
|
|
}
|
|
var newMode = !mode ? defaultMode : mode;
|
|
try {
|
|
localStorage.setItem(modeStorageKey, newMode);
|
|
} catch (e) {
|
|
// Unsupported
|
|
}
|
|
return _extends({}, currentState, {
|
|
mode: newMode,
|
|
systemMode: getSystemMode(newMode)
|
|
});
|
|
});
|
|
}, [modeStorageKey, defaultMode]);
|
|
var setColorScheme = React.useCallback(function (value) {
|
|
if (!value) {
|
|
setState(function (currentState) {
|
|
try {
|
|
localStorage.setItem("".concat(colorSchemeStorageKey, "-light"), defaultLightColorScheme);
|
|
localStorage.setItem("".concat(colorSchemeStorageKey, "-dark"), defaultDarkColorScheme);
|
|
} catch (e) {
|
|
// Unsupported
|
|
}
|
|
return _extends({}, currentState, {
|
|
lightColorScheme: defaultLightColorScheme,
|
|
darkColorScheme: defaultDarkColorScheme
|
|
});
|
|
});
|
|
} else if (typeof value === 'string') {
|
|
if (value && !joinedColorSchemes.includes(value)) {
|
|
console.error("`".concat(value, "` does not exist in `theme.colorSchemes`."));
|
|
} else {
|
|
setState(function (currentState) {
|
|
var newState = _extends({}, currentState);
|
|
processState(currentState, function (mode) {
|
|
try {
|
|
localStorage.setItem("".concat(colorSchemeStorageKey, "-").concat(mode), value);
|
|
} catch (e) {
|
|
// Unsupported
|
|
}
|
|
if (mode === 'light') {
|
|
newState.lightColorScheme = value;
|
|
}
|
|
if (mode === 'dark') {
|
|
newState.darkColorScheme = value;
|
|
}
|
|
});
|
|
return newState;
|
|
});
|
|
}
|
|
} else {
|
|
setState(function (currentState) {
|
|
var newState = _extends({}, currentState);
|
|
var newLightColorScheme = value.light === null ? defaultLightColorScheme : value.light;
|
|
var newDarkColorScheme = value.dark === null ? defaultDarkColorScheme : value.dark;
|
|
if (newLightColorScheme) {
|
|
if (!joinedColorSchemes.includes(newLightColorScheme)) {
|
|
console.error("`".concat(newLightColorScheme, "` does not exist in `theme.colorSchemes`."));
|
|
} else {
|
|
newState.lightColorScheme = newLightColorScheme;
|
|
try {
|
|
localStorage.setItem("".concat(colorSchemeStorageKey, "-light"), newLightColorScheme);
|
|
} catch (error) {
|
|
// Unsupported
|
|
}
|
|
}
|
|
}
|
|
if (newDarkColorScheme) {
|
|
if (!joinedColorSchemes.includes(newDarkColorScheme)) {
|
|
console.error("`".concat(newDarkColorScheme, "` does not exist in `theme.colorSchemes`."));
|
|
} else {
|
|
newState.darkColorScheme = newDarkColorScheme;
|
|
try {
|
|
localStorage.setItem("".concat(colorSchemeStorageKey, "-dark"), newDarkColorScheme);
|
|
} catch (error) {
|
|
// Unsupported
|
|
}
|
|
}
|
|
}
|
|
return newState;
|
|
});
|
|
}
|
|
}, [joinedColorSchemes, colorSchemeStorageKey, defaultLightColorScheme, defaultDarkColorScheme]);
|
|
var handleMediaQuery = React.useCallback(function (e) {
|
|
if (state.mode === 'system') {
|
|
setState(function (currentState) {
|
|
return _extends({}, currentState, {
|
|
systemMode: e != null && e.matches ? 'dark' : 'light'
|
|
});
|
|
});
|
|
}
|
|
}, [state.mode]);
|
|
|
|
// Ref hack to avoid adding handleMediaQuery as a dep
|
|
var mediaListener = React.useRef(handleMediaQuery);
|
|
mediaListener.current = handleMediaQuery;
|
|
React.useEffect(function () {
|
|
var handler = function handler() {
|
|
return mediaListener.current.apply(mediaListener, arguments);
|
|
};
|
|
|
|
// Always listen to System preference
|
|
var media = window.matchMedia('(prefers-color-scheme: dark)');
|
|
|
|
// Intentionally use deprecated listener methods to support iOS & old browsers
|
|
media.addListener(handler);
|
|
handler(media);
|
|
return function () {
|
|
return media.removeListener(handler);
|
|
};
|
|
}, []);
|
|
|
|
// Handle when localStorage has changed
|
|
React.useEffect(function () {
|
|
var handleStorage = function handleStorage(event) {
|
|
var 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);
|
|
}
|
|
};
|
|
if (storageWindow) {
|
|
// For syncing color-scheme changes between iframes
|
|
storageWindow.addEventListener('storage', handleStorage);
|
|
return function () {
|
|
return storageWindow.removeEventListener('storage', handleStorage);
|
|
};
|
|
}
|
|
return undefined;
|
|
}, [setColorScheme, setMode, modeStorageKey, colorSchemeStorageKey, joinedColorSchemes, defaultMode, storageWindow]);
|
|
return _extends({}, state, {
|
|
colorScheme: colorScheme,
|
|
setMode: setMode,
|
|
setColorScheme: setColorScheme
|
|
});
|
|
} |