UNPKG

tw-colors

Version:

Tailwind plugin for switching color theme with just one className

241 lines (240 loc) 8.25 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // lib/index.ts var lib_exports = {}; __export(lib_exports, { createThemes: () => createThemes, resolveTwcConfig: () => resolveTwcConfig }); module.exports = __toCommonJS(lib_exports); var import_color = __toESM(require("color")); var import_plugin = __toESM(require("tailwindcss/plugin")); var import_lodash = __toESM(require("lodash.foreach")); var import_flat = __toESM(require("flat")); var SCHEME = Symbol("color-scheme"); var emptyConfig = {}; var resolveTwcConfig = (config = emptyConfig, { produceCssVariable = defaultProduceCssVariable, produceThemeClass = defaultProduceThemeClass, produceThemeVariant = produceThemeClass, defaultTheme, strict = false } = {}) => { const resolved = { variants: [], utilities: {}, colors: {} }; const configObject = typeof config === "function" ? config({ dark, light }) : config; (0, import_lodash.default)(configObject, (colors, themeName) => { const themeClassName = produceThemeClass(themeName); const themeVariant = produceThemeVariant(themeName); const flatColors = flattenColors(colors); resolved.variants.push({ name: themeVariant, // tailwind will generate only the first matched definition definition: [ generateVariantDefinitions(`.${themeClassName}`), generateVariantDefinitions(`[data-theme='${themeName}']`), generateRootVariantDefinitions(themeName, defaultTheme) ].flat() }); const cssSelector = `.${themeClassName},[data-theme="${themeName}"]`; resolved.utilities[cssSelector] = colors[SCHEME] ? { "color-scheme": colors[SCHEME] } : {}; (0, import_lodash.default)(flatColors, (colorValue, colorName) => { if (colorName === SCHEME) return; const safeColorName = escapeChars(colorName, "/"); let [h, s, l, defaultAlphaValue] = [0, 0, 0, 1]; try { [h, s, l, defaultAlphaValue] = toHslaArray(colorValue); } catch (error) { const message = `\r Warning - In theme "${themeName}" color "${colorName}". ${error.message}`; if (strict) { throw new Error(message); } return console.error(message); } const twcColorVariable = produceCssVariable(safeColorName); const twcOpacityVariable = `${produceCssVariable(safeColorName)}-opacity`; const hslValues = `${h} ${s}% ${l}%`; resolved.utilities[cssSelector][twcColorVariable] = hslValues; addRootUtilities(resolved.utilities, { key: twcColorVariable, value: hslValues, defaultTheme, themeName }); if (typeof defaultAlphaValue === "number") { const alphaValue = defaultAlphaValue.toFixed(2); resolved.utilities[cssSelector][twcOpacityVariable] = alphaValue; addRootUtilities(resolved.utilities, { key: twcOpacityVariable, value: alphaValue, defaultTheme, themeName }); } resolved.colors[colorName] = ({ opacityVariable, opacityValue }) => { if (!isNaN(+opacityValue)) { return `hsl(var(${twcColorVariable}) / ${opacityValue})`; } if (opacityVariable) { return `hsl(var(${twcColorVariable}) / var(${twcOpacityVariable}, var(${opacityVariable})))`; } return `hsl(var(${twcColorVariable}) / var(${twcOpacityVariable}, 1))`; }; }); }); return resolved; }; var createThemes = (config = emptyConfig, options = {}) => { const resolved = resolveTwcConfig(config, options); return (0, import_plugin.default)( ({ addUtilities, addVariant }) => { addUtilities(resolved.utilities); resolved.variants.forEach(({ name, definition }) => addVariant(name, definition)); }, // extend the colors config { theme: { extend: { // @ts-ignore tailwind types are broken colors: resolved.colors } } } ); }; function escapeChars(str, ...chars) { let result = str; for (let char of chars) { const regexp = new RegExp(char, "g"); result = str.replace(regexp, "\\" + char); } return result; } function flattenColors(colors) { const flatColorsWithDEFAULT = (0, import_flat.default)(colors, { safe: true, delimiter: "-" }); return Object.entries(flatColorsWithDEFAULT).reduce((acc, [key, value]) => { acc[key.replace(/\-DEFAULT$/, "")] = value; return acc; }, {}); } function toHslaArray(colorValue) { return (0, import_color.default)(colorValue).hsl().round(1).array(); } function defaultProduceCssVariable(themeName) { return `--twc-${themeName}`; } function defaultProduceThemeClass(themeName) { return themeName; } function dark(colors) { return { ...colors, [SCHEME]: "dark" }; } function light(colors) { return { ...colors, [SCHEME]: "light" }; } function generateVariantDefinitions(selector) { return [ `${selector}&`, `:is(${selector} > &:not([data-theme]))`, `:is(${selector} &:not(${selector} [data-theme]:not(${selector}) * ))`, `:is(${selector}:not(:has([data-theme])) &:not([data-theme]))` ]; } function generateRootVariantDefinitions(themeName, defaultTheme) { const baseDefinitions = [ `:root&`, `:is(:root > &:not([data-theme]))`, `:is(:root &:not([data-theme] *):not([data-theme]))` ]; if (typeof defaultTheme === "string" && themeName === defaultTheme) { return baseDefinitions; } if (typeof defaultTheme === "object" && themeName === defaultTheme.light) { return baseDefinitions.map( (definition) => `@media (prefers-color-scheme: light){${definition}}` ); } if (typeof defaultTheme === "object" && themeName === defaultTheme.dark) { return baseDefinitions.map( (definition) => `@media (prefers-color-scheme: dark){${definition}}` ); } return []; } function addRootUtilities(utilities, { key, value, defaultTheme, themeName }) { if (!defaultTheme) return; if (typeof defaultTheme === "string") { if (themeName === defaultTheme) { if (!utilities[":root"]) { utilities[":root"] = {}; } utilities[":root"][key] = value; } } else if (themeName === defaultTheme.light) { if (!utilities["@media (prefers-color-scheme: light)"]) { utilities["@media (prefers-color-scheme: light)"] = { ":root": {} }; } utilities["@media (prefers-color-scheme: light)"][":root"][key] = value; } else if (themeName === defaultTheme.dark) { if (!utilities["@media (prefers-color-scheme: dark)"]) { utilities["@media (prefers-color-scheme: dark)"] = { ":root": {} }; } utilities["@media (prefers-color-scheme: dark)"][":root"][key] = value; } } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { createThemes, resolveTwcConfig }); //# sourceMappingURL=index.js.map