UNPKG

gatsby-plugin-use-dark-mode

Version:

Gatsby plugin to prevent a flash of default styles when using the use-dark-mode hook

95 lines (91 loc) 3.57 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); exports.__esModule = true; exports.pluginOptionsSchema = exports.onCreateWebpackConfig = void 0; var _esbuild = _interopRequireDefault(require("esbuild")); const pluginOptionsSchema = ({ Joi }) => { return Joi.object({ classNameDark: Joi.string().default('dark-mode').description('CSS class name applied in dark mode'), classNameLight: Joi.string().default('light-mode').description('CSS class name applied in light mode'), storageKey: Joi.string().default('darkMode').description('localStorage key used to persist mode'), minify: Joi.boolean().default(true).description('toggle minification of the injected script') }); }; exports.pluginOptionsSchema = pluginOptionsSchema; const onCreateWebpackConfig = ({ actions, plugins }, pluginOptions) => { const typedOpts = { classNameDark: String(pluginOptions.classNameDark), classNameLight: String(pluginOptions.classNameLight), storageKey: String(pluginOptions.storageKey), minify: Boolean(pluginOptions.minify) }; const { classNameDark, classNameLight, storageKey, minify } = typedOpts; const noFlashScript = generateNoFlashScript({ classNameDark, classNameLight, storageKey }); const finalNoFlashScript = minify ? _esbuild.default.transformSync(noFlashScript, { minifyWhitespace: true, minifyIdentifiers: true, minifySyntax: false }).code.trim() : noFlashScript; actions.setWebpackConfig({ plugins: [ // We can't perform the minification in gatsby-ssr so we do it here // instead and leverage Webpack's DefinePlugin to replace the value of // process.env.GATSBY_PLUGIN_USE_DARK_MODE_NO_FLASH_SCRIPT with the final // script contents, which we consume afterwards in in gatsby-ssr. plugins.define({ 'process.env.GATSBY_PLUGIN_USE_DARK_MODE_NO_FLASH_SCRIPT': JSON.stringify(finalNoFlashScript) })] }); }; // Adapted from: // https://github.com/donavon/use-dark-mode/blob/develop/noflash.js.txt exports.onCreateWebpackConfig = onCreateWebpackConfig; function generateNoFlashScript({ classNameDark, classNameLight, storageKey }) { return ` (function(classNameDark, classNameLight, storageKey) { function setClassOnDocumentBody(darkMode) { document.body.classList.add(darkMode ? classNameDark : classNameLight); document.body.classList.remove(darkMode ? classNameLight : classNameDark); } var preferDarkQuery = '(prefers-color-scheme: dark)'; var mql = window.matchMedia(preferDarkQuery); var supportsColorSchemeQuery = mql.media === preferDarkQuery; var localStorageValue = null; try { localStorageValue = JSON.parse(localStorage.getItem(storageKey)); } catch (err) {} var isLocalStorageValueValid = localStorageValue === true || localStorageValue === false; // Determine the source of truth if (isLocalStorageValueValid) { // source of truth from localStorage setClassOnDocumentBody(localStorageValue); } else if (supportsColorSchemeQuery) { // source of truth from system setClassOnDocumentBody(mql.matches); localStorage.setItem(storageKey, mql.matches); } else { // source of truth from document.body var isDarkMode = document.body.classList.contains(classNameDark); localStorage.setItem(storageKey, JSON.stringify(isDarkMode)); } })('${classNameDark}', '${classNameLight}', '${storageKey}'); `; }