@nexim/tailwind-material-colors
Version:
A Tailwind CSS plugin to automatically generate and apply Material Design 3 color palettes.
205 lines (200 loc) • 8.49 kB
JavaScript
/* @nexim/tailwind-material-colors v1.0.0 */
// src/main.ts
import { packageTracer } from "@alwatr/package-tracer";
import { argbFromHex, customColor, Hct } from "@material/material-color-utilities";
import { kebabCase } from "change-case";
import plugin from "tailwindcss/plugin";
// src/lib/constants.ts
import {
SchemeContent,
SchemeExpressive,
SchemeFidelity,
SchemeMonochrome,
SchemeNeutral,
SchemeTonalSpot,
SchemeVibrant,
SchemeRainbow,
SchemeFruitSalad,
MaterialDynamicColors
} from "@material/material-color-utilities";
var SchemeObjects = {
content: SchemeContent,
expressive: SchemeExpressive,
fidelity: SchemeFidelity,
monochrome: SchemeMonochrome,
neutral: SchemeNeutral,
tonalSpot: SchemeTonalSpot,
vibrant: SchemeVibrant,
rainbow: SchemeRainbow,
fruitsalad: SchemeFruitSalad
};
var AllMaterialDynamicColors = {
background: MaterialDynamicColors.background,
onBackground: MaterialDynamicColors.onBackground,
surface: MaterialDynamicColors.surface,
surfaceDim: MaterialDynamicColors.surfaceDim,
surfaceBright: MaterialDynamicColors.surfaceBright,
surfaceContainerLowest: MaterialDynamicColors.surfaceContainerLowest,
surfaceContainerLow: MaterialDynamicColors.surfaceContainerLow,
surfaceContainer: MaterialDynamicColors.surfaceContainer,
surfaceContainerHigh: MaterialDynamicColors.surfaceContainerHigh,
surfaceContainerHighest: MaterialDynamicColors.surfaceContainerHighest,
onSurface: MaterialDynamicColors.onSurface,
surfaceVariant: MaterialDynamicColors.surfaceVariant,
onSurfaceVariant: MaterialDynamicColors.onSurfaceVariant,
inverseSurface: MaterialDynamicColors.inverseSurface,
inverseOnSurface: MaterialDynamicColors.inverseOnSurface,
outline: MaterialDynamicColors.outline,
outlineVariant: MaterialDynamicColors.outlineVariant,
shadow: MaterialDynamicColors.shadow,
scrim: MaterialDynamicColors.scrim,
surfaceTint: MaterialDynamicColors.surfaceTint,
primary: MaterialDynamicColors.primary,
onPrimary: MaterialDynamicColors.onPrimary,
primaryContainer: MaterialDynamicColors.primaryContainer,
onPrimaryContainer: MaterialDynamicColors.onPrimaryContainer,
inversePrimary: MaterialDynamicColors.inversePrimary,
secondary: MaterialDynamicColors.secondary,
onSecondary: MaterialDynamicColors.onSecondary,
secondaryContainer: MaterialDynamicColors.secondaryContainer,
onSecondaryContainer: MaterialDynamicColors.onSecondaryContainer,
tertiary: MaterialDynamicColors.tertiary,
onTertiary: MaterialDynamicColors.onTertiary,
tertiaryContainer: MaterialDynamicColors.tertiaryContainer,
onTertiaryContainer: MaterialDynamicColors.onTertiaryContainer,
error: MaterialDynamicColors.error,
onError: MaterialDynamicColors.onError,
errorContainer: MaterialDynamicColors.errorContainer,
onErrorContainer: MaterialDynamicColors.onErrorContainer,
primaryFixed: MaterialDynamicColors.primaryFixed,
primaryFixedDim: MaterialDynamicColors.primaryFixedDim,
onPrimaryFixed: MaterialDynamicColors.onPrimaryFixed,
onPrimaryFixedVariant: MaterialDynamicColors.onPrimaryFixedVariant,
secondaryFixed: MaterialDynamicColors.secondaryFixed,
secondaryFixedDim: MaterialDynamicColors.secondaryFixedDim,
onSecondaryFixed: MaterialDynamicColors.onSecondaryFixed,
onSecondaryFixedVariant: MaterialDynamicColors.onSecondaryFixedVariant,
tertiaryFixed: MaterialDynamicColors.tertiaryFixed,
tertiaryFixedDim: MaterialDynamicColors.tertiaryFixedDim,
onTertiaryFixed: MaterialDynamicColors.onTertiaryFixed,
onTertiaryFixedVariant: MaterialDynamicColors.onTertiaryFixedVariant
};
// src/lib/utils.ts
import { redFromArgb, greenFromArgb, blueFromArgb } from "@material/material-color-utilities";
var colorToRgbString = (color) => `${redFromArgb(color)}, ${greenFromArgb(color)}, ${blueFromArgb(color)}`;
// src/main.ts
__dev_mode__: packageTracer.add("@nexim/tailwind-material-colors", "1.0.0");
function materialThemeBuilder(options) {
const source = argbFromHex(options.primaryColor);
const SchemeObject = SchemeObjects[options.scheme ?? "content"];
const lightScheme = new SchemeObject(Hct.fromInt(source), false, options.contrast ?? 0);
const darkScheme = new SchemeObject(Hct.fromInt(source), true, options.contrast ?? 0);
const lightColors = {};
const darkColors = {};
Object.entries(AllMaterialDynamicColors).forEach(([name, DynamicColor]) => {
name = kebabCase(name);
lightColors[name] = colorToRgbString(DynamicColor.getArgb(lightScheme));
darkColors[name] = colorToRgbString(DynamicColor.getArgb(darkScheme));
});
if (options.extraColors) {
for (let colorName of Object.keys(options.extraColors)) {
colorName = kebabCase(colorName);
const { hex, blend } = options.extraColors[colorName];
const { light, dark } = customColor(source, {
name: colorName,
value: argbFromHex(hex),
blend: blend ?? true
});
lightColors[colorName] = colorToRgbString(light.color);
lightColors[`on-${colorName}`] = colorToRgbString(light.onColor);
lightColors[`${colorName}-container`] = colorToRgbString(light.colorContainer);
lightColors[`on-${colorName}-container`] = colorToRgbString(light.onColorContainer);
darkColors[colorName] = colorToRgbString(dark.color);
darkColors[`on-${colorName}`] = colorToRgbString(dark.onColor);
darkColors[`${colorName}-container`] = colorToRgbString(dark.colorContainer);
darkColors[`on-${colorName}-container`] = colorToRgbString(dark.onColorContainer);
}
}
return { lightColors, darkColors };
}
function generateColorList(options) {
const allColorNames = [];
Object.keys(AllMaterialDynamicColors).forEach((name) => allColorNames.push(kebabCase(name)));
if (options.extraColors) {
Object.keys(options.extraColors).forEach((colorName) => {
const kebabName = kebabCase(colorName);
allColorNames.push(kebabName);
allColorNames.push(`on-${kebabName}`);
allColorNames.push(`${kebabName}-container`);
allColorNames.push(`on-${kebabName}-container`);
});
}
return allColorNames;
}
var materialThemeBuilderTailwindPlugin = plugin.withOptions(
(options) => {
return (pluginApi) => {
if (options == void 0) {
throw new Error("Material Theme Plugin: options is undefined");
}
const { lightColors, darkColors } = materialThemeBuilder(options);
pluginApi.addBase({
":root": Object.fromEntries(Object.entries(lightColors).map(([name, value]) => [`--ref-color-${name}`, value])),
"@media (prefers-color-scheme: dark)": {
":root": Object.fromEntries(Object.entries(darkColors).map(([name, value]) => [`--ref-color-${name}`, value]))
},
".dark": Object.fromEntries(Object.entries(darkColors).map(([name, value]) => [`--ref-color-${name}`, value]))
});
const stateUtils = {};
for (const name of generateColorList(options)) {
const varName = `--ref-color-${name}`;
const colorVar = `rgb(var(${varName}))`;
const hoverBg = `linear-gradient(rgba(var(${varName}), 0.08), rgba(var(${varName}), 0.08))`;
const focusVisibleBg = `linear-gradient(rgba(var(${varName}), 0.12), rgba(var(${varName}), 0.12))`;
const activeBg = `linear-gradient(rgba(var(${varName}), 0.12), rgba(var(${varName}), 0.12))`;
stateUtils[`.state-${name}`] = {
color: colorVar,
"&:hover": {
backgroundImage: hoverBg
},
"&:focus-visible": {
backgroundImage: focusVisibleBg
},
"&:active": {
backgroundImage: activeBg
}
};
stateUtils[`.stateHover-${name}`] = {
color: colorVar,
"&:hover": {
backgroundImage: hoverBg
}
};
stateUtils[`.stateActive-${name}`] = {
color: colorVar,
"&:active": {
backgroundImage: activeBg
}
};
}
pluginApi.addUtilities(stateUtils);
};
},
(options) => ({
theme: {
extend: {
colors: () => {
if (options == void 0) {
throw new Error("Material Theme Plugin: options is undefined");
}
return Object.fromEntries(generateColorList(options).map((name) => [name, `rgb(var(--ref-color-${name}))`]));
}
}
}
})
);
export {
materialThemeBuilder,
materialThemeBuilderTailwindPlugin
};
//# sourceMappingURL=main.mjs.map