UNPKG

@laurabeatris/chakra-ui-flashless

Version:

Tools to implement flashless color modes in Chakra UI

336 lines (317 loc) 14.6 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var React = require('react'); var themeTools = require('@chakra-ui/theme-tools'); var outdent = require('outdent'); var defaultTheme = require('@chakra-ui/theme'); var merge = require('lodash.merge'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var React__default = /*#__PURE__*/_interopDefaultLegacy(React); var defaultTheme__default = /*#__PURE__*/_interopDefaultLegacy(defaultTheme); var merge__default = /*#__PURE__*/_interopDefaultLegacy(merge); /*! ***************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ var __assign = function() { __assign = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; function __makeTemplateObject(cooked, raw) { if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } return cooked; } var baseVariables = { '--bg': ['white', 'gray.800'], '--text': ['gray.800', 'whiteAlpha.900'], '--placeholder-text': ['gray.400', 'whiteAlpha.400'], '--border': ['gray.200', 'whiteAlpha.300'], '--badge-text': ['white', 'whiteAlpha.800'] }; function createVariables(theme, customVariables) { function colorValue(color) { return Array.isArray(color) ? themeTools.transparentize.apply(void 0, color)(theme) : themeTools.getColor(theme, color); } var defaultVariables = Object.entries(theme.colors) .filter(function (entries) { return typeof entries[1] === 'object'; }) .reduce(function (acc, _a) { var _b; var c = _a[0]; var isGray = c === 'gray'; return __assign(__assign({}, acc), (_b = {}, _b["--badge-solid-" + c] = [c + ".500", [c + ".500", 0.6]], _b["--badge-subtle-" + c] = [c + ".100", [c + ".200", 0.16]], _b["--badge-subtle-" + c + "-text"] = [c + ".800", c + ".200"], _b["--badge-outline-" + c] = [c + ".500", [c + ".200", 0.8]], _b["--button-ghost-" + c] = [ isGray ? 'inherit' : c + ".600", isGray ? 'whiteAlpha.900' : c + ".200" ], _b["--button-ghost-" + c + "-hover"] = [ c + "." + (isGray ? 100 : 50), isGray ? 'whiteAlpha.200' : [c + ".200", 0.12] ], _b["--button-ghost-" + c + "-active"] = [ c + "." + (isGray ? 200 : 100), isGray ? 'whiteAlpha.300' : [c + ".200", 0.24] ], _b["--button-solid-" + c] = [ c + "." + (isGray ? 100 : 500), isGray ? 'whiteAlpha.200' : c + ".200" ], _b["--button-solid-" + c + "-hover"] = [ c + "." + (isGray ? 200 : 600), isGray ? 'whiteAlpha.300' : c + ".300" ], _b["--button-solid-" + c + "-active"] = [ c + "." + (isGray ? 300 : 700), isGray ? 'whiteAlpha.400' : c + ".400" ], _b)); }, baseVariables); return outdent.outdent(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n const mql = window.matchMedia('(prefers-color-scheme: dark)');\n const root = document.documentElement;\n ", "\n "], ["\n const mql = window.matchMedia('(prefers-color-scheme: dark)');\n const root = document.documentElement;\n ", "\n "])), Object.entries(__assign(__assign({}, defaultVariables), customVariables)) .map(function (_a) { var name = _a[0], values = _a[1]; return outdent.outdent(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n root.style.setProperty(\n '", "',\n mql.matches\n ? '", "'\n : '", "'\n );\n "], ["\n root.style.setProperty(\n '", "',\n mql.matches\n ? '", "'\n : '", "'\n );\n "])), name, colorValue(values[1]), colorValue(values[0])); }) .join('\n')); } function FlashlessScript(_a) { var theme = _a.theme, customVariables = _a.customVariables; return (React.createElement("script", { dangerouslySetInnerHTML: { __html: createVariables(theme, customVariables) } })); } var templateObject_1, templateObject_2; var BASE_VARIABLES = { '--bg': ['white', 'gray.800'], '--text': ['gray.800', 'whiteAlpha.900'], '--placeholder-text': ['gray.400', 'whiteAlpha.400'], '--border': ['gray.200', 'whiteAlpha.300'], '--badge-text': ['white', 'whiteAlpha.800'] }; function createDefaultVariables(theme) { return Object.entries(theme.colors) .filter(function (entries) { return typeof entries[1] === 'object'; }) .reduce(function (acc, _a) { var _b; var c = _a[0]; var isGray = c === 'gray'; return __assign(__assign({}, acc), (_b = {}, _b["--badge-solid-" + c] = [c + ".500", [c + ".500", 0.6]], _b["--badge-subtle-" + c] = [c + ".100", [c + ".200", 0.16]], _b["--badge-subtle-" + c + "-text"] = [c + ".800", c + ".200"], _b["--badge-outline-" + c] = [c + ".500", [c + ".200", 0.8]], _b["--button-ghost-" + c] = [ isGray ? 'inherit' : c + ".600", isGray ? 'whiteAlpha.900' : c + ".200" ], _b["--button-ghost-" + c + "-hover"] = [ c + "." + (isGray ? 100 : 50), isGray ? 'whiteAlpha.200' : [c + ".200", 0.12] ], _b["--button-ghost-" + c + "-active"] = [ c + "." + (isGray ? 200 : 100), isGray ? 'whiteAlpha.300' : [c + ".200", 0.24] ], _b["--button-solid-" + c] = [ c + "." + (isGray ? 100 : 500), isGray ? 'whiteAlpha.200' : c + ".200" ], _b["--button-solid-" + c + "-hover"] = [ c + "." + (isGray ? 200 : 600), isGray ? 'whiteAlpha.300' : c + ".300" ], _b["--button-solid-" + c + "-active"] = [ c + "." + (isGray ? 300 : 700), isGray ? 'whiteAlpha.400' : c + ".400" ], _b)); }, BASE_VARIABLES); } function getColorValue(theme, color) { return Array.isArray(color) ? themeTools.transparentize.apply(void 0, color)(theme) : themeTools.getColor(theme, color); } function toggleColorVariables(_a) { var theme = _a.theme, colorMode = _a.colorMode, customVariables = _a.customVariables; var defaultVariables = createDefaultVariables(theme); var root = window.document.documentElement; var isDarkMode = colorMode === 'dark'; Object.entries(__assign(__assign({}, defaultVariables), customVariables)).forEach(function (_a) { var name = _a[0], values = _a[1]; return root.style.setProperty(name, isDarkMode ? "" + getColorValue(theme, values[1]) : "" + getColorValue(theme, values[0])); }); root.style.setProperty('--chakra-ui-color-mode', colorMode); } /** * Handles the mounted state of the component. * * Useful for cases where a content should only be rendered on the browser * and the DOM should stay the same on the server and on the re-hydration process. */ function useHasMounted() { var _a = React.useState(false), hasMounted = _a[0], setHasMounted = _a[1]; React.useEffect(function () { setHasMounted(true); }, []); return hasMounted; } function getNewColorScheme(event) { var newColorScheme = event.matches ? 'dark' : 'light'; return newColorScheme; } /** * Gets the color scheme preferred by the user and listen to it's change */ function usePrefersColorScheme() { var hasMounted = useHasMounted(); var _a = React.useState(null), prefersColorScheme = _a[0], setPrefersColorScheme = _a[1]; React.useEffect(function () { if (!hasMounted) { return; } var prefersColorScheme = window.matchMedia('(prefers-color-scheme: dark)'); setPrefersColorScheme(getNewColorScheme(prefersColorScheme)); }, [hasMounted]); React.useEffect(function () { if (!hasMounted) { return; } function changeListenerPrefersColorScheme(event) { setPrefersColorScheme(getNewColorScheme(event)); } var prefersColorScheme = window.matchMedia('(prefers-color-scheme: dark)'); prefersColorScheme.addEventListener('change', changeListenerPrefersColorScheme); return function removeListenerPrefersColorScheme() { prefersColorScheme.removeEventListener('change', changeListenerPrefersColorScheme); }; }, [hasMounted]); return { prefersColorScheme: prefersColorScheme, hasMounted: hasMounted }; } var ColorModeContext = React.createContext({}); function ColorModeToggleProvider(_a) { var theme = _a.theme, children = _a.children, customVariables = _a.customVariables, initialColorMode = _a.initialColorMode; var _b = React.useState(initialColorMode), colorMode = _b[0], setColorMode = _b[1]; var _c = usePrefersColorScheme(), prefersColorScheme = _c.prefersColorScheme, hasMounted = _c.hasMounted; var toggleColorMode = React.useCallback(function () { setColorMode(function (prev) { var newColorMode = prev === 'dark' ? 'light' : 'dark'; return newColorMode; }); }, [colorMode, prefersColorScheme]); React.useEffect(function () { var shouldUsePrefersColorScheme = hasMounted && !initialColorMode && prefersColorScheme; if (!shouldUsePrefersColorScheme) { return; } setColorMode(prefersColorScheme); }, [hasMounted, initialColorMode, prefersColorScheme]); React.useEffect(function () { if (!colorMode) { return; } toggleColorVariables({ theme: theme, colorMode: colorMode, customVariables: customVariables }); }, [theme, customVariables, colorMode]); var payload = React.useMemo(function () { return ({ colorMode: colorMode, toggleColorMode: toggleColorMode }); }, [colorMode, toggleColorMode]); return (React__default['default'].createElement(ColorModeContext.Provider, { value: payload }, children)); } var useColorMode = function () { return React.useContext(ColorModeContext); }; var Badge = { variants: { solid: function (props) { var c = props.colorScheme; return { bg: "var(--badge-solid-" + c + ")", color: 'var(--badge-text)' }; }, subtle: function (props) { var c = props.colorScheme; return { bg: "var(--badge-subtle-" + c + ")", color: "var(--badge-subtle-" + c + "-text)" }; }, outline: function (props) { var c = props.colorScheme; return { color: "var(--badge-outline-" + c + ")", boxShadow: "inset 0 0 0px 1px var(--badge-outline-" + c + ")" }; } } }; function ghost(props) { var c = props.colorScheme; return { color: "var(--button-ghost-" + c + ")", _hover: { bg: "var(--button-ghost-" + c + "-hover)" }, _active: { bg: "var(--button-ghost-" + c + "-active)" } }; } function flashless(theme) { if (theme === void 0) { theme = defaultTheme__default['default']; } return merge__default['default']({ config: { useSystemColorMode: true }, styles: { global: { body: { bg: 'var(--bg)', color: 'var(--text)' }, '*::placeholder': { color: 'var(--placeholder-text)' }, '*, *::before, &::after': { borderColor: 'var(--border)' } } }, components: { Badge: Badge, Button: { variants: { ghost: ghost, solid: function (_a) { var c = _a.colorScheme; return ({ color: c !== 'gray' && 'var(--bg)', bg: "var(--button-solid-" + c + ")", _hover: { bg: "var(--button-solid-" + c + "-hover)" }, _active: { bg: "var(--button-solid-" + c + "-active)" } }); }, outline: function (props) { return (__assign({ borderColor: props.colorScheme === 'gray' ? 'var(--border)' : 'currentColor' }, ghost(props))); } } }, Tag: { variants: { subtle: function (props) { return ({ container: Badge.variants.subtle(props) }); }, solid: function (props) { return ({ container: Badge.variants.solid(props) }); }, outline: function (props) { return ({ container: Badge.variants.outline(props) }); } } } } }, theme); } var types = /*#__PURE__*/Object.freeze({ __proto__: null }); exports.ColorModeToggleProvider = ColorModeToggleProvider; exports.FlashlessScript = FlashlessScript; exports.Types = types; exports.flashless = flashless; exports.useColorMode = useColorMode; //# sourceMappingURL=index.js.map