material-theme-builder 3.1.0 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +287 -239
- package/dist/cli.js +520 -105
- package/dist/index.d.ts +30 -1
- package/dist/index.js +120 -67
- package/dist/react.d.ts +87 -52
- package/dist/react.js +141 -84
- package/dist/registry-item.json +75 -0
- package/dist/shadcn.css +43 -0
- package/dist/tailwind-plugin.d.ts +73 -0
- package/dist/tailwind-plugin.js +135 -0
- package/dist/tailwind.css +47 -81
- package/package.json +31 -10
- package/src/tailwind.css +0 -179
package/dist/react.js
CHANGED
|
@@ -3973,6 +3973,39 @@ function toShadcnVars(mergedColors) {
|
|
|
3973
3973
|
});
|
|
3974
3974
|
return Object.fromEntries(entries);
|
|
3975
3975
|
}
|
|
3976
|
+
function toShadcnAliasVars(prefix, fallbacks) {
|
|
3977
|
+
const entries = SHADCN_MAPPING.map(([cssVar, m3Token]) => {
|
|
3978
|
+
const bare = cssVar.slice(2);
|
|
3979
|
+
const property = `--${prefix}-sys-color-${m3Token}`;
|
|
3980
|
+
return [
|
|
3981
|
+
bare,
|
|
3982
|
+
fallbacks ? `var(${property}, ${fallbacks[bare]})` : `var(${property})`
|
|
3983
|
+
];
|
|
3984
|
+
});
|
|
3985
|
+
return Object.fromEntries(entries);
|
|
3986
|
+
}
|
|
3987
|
+
function buildShadcnAliases(ctx) {
|
|
3988
|
+
const lines = Object.entries(toShadcnAliasVars(ctx.prefix)).map(
|
|
3989
|
+
([name, value]) => `--${name}: ${value};`
|
|
3990
|
+
);
|
|
3991
|
+
return `:root,
|
|
3992
|
+
.dark {
|
|
3993
|
+
${lines.join("\n ")}
|
|
3994
|
+
}
|
|
3995
|
+
`;
|
|
3996
|
+
}
|
|
3997
|
+
function buildShadcnRegistryItem(ctx, { fallback = false } = {}) {
|
|
3998
|
+
const concrete = fallback ? buildShadcn(ctx) : void 0;
|
|
3999
|
+
const vars = (mode) => toShadcnAliasVars(ctx.prefix, concrete?.[mode]);
|
|
4000
|
+
return {
|
|
4001
|
+
$schema: "https://ui.shadcn.com/schema/registry-item.json",
|
|
4002
|
+
name: "material-theme-builder",
|
|
4003
|
+
type: "registry:theme",
|
|
4004
|
+
title: "Material Theme Builder",
|
|
4005
|
+
description: `Points shadcn's CSS variables at the M3 custom properties \`<Mtb>\` emits, so every shadcn component follows whichever theme is above it in the tree.${fallback ? " Falls back to this theme's own colors where no `<Mtb>` is mounted." : ""}`,
|
|
4006
|
+
cssVars: { light: vars("light"), dark: vars("dark") }
|
|
4007
|
+
};
|
|
4008
|
+
}
|
|
3976
4009
|
function buildShadcn(ctx) {
|
|
3977
4010
|
const { mergedColorsLight, mergedColorsDark } = ctx;
|
|
3978
4011
|
return {
|
|
@@ -3983,6 +4016,64 @@ function buildShadcn(ctx) {
|
|
|
3983
4016
|
|
|
3984
4017
|
// src/lib/builder.tailwind.ts
|
|
3985
4018
|
import { kebabCase as kebabCase3 } from "lodash-es";
|
|
4019
|
+
|
|
4020
|
+
// src/lib/tokens.ts
|
|
4021
|
+
var DEFAULT_PREFIX = "md";
|
|
4022
|
+
var tokenDescriptions = {
|
|
4023
|
+
background: "Default background color for screens and large surfaces.",
|
|
4024
|
+
error: "Color for error states, used on elements like error text and icons.",
|
|
4025
|
+
errorContainer: "Fill color for error container elements like error banners.",
|
|
4026
|
+
inverseOnSurface: "Color for text and icons on inverse surface backgrounds.",
|
|
4027
|
+
inversePrimary: "Primary color used on inverse surface, e.g. buttons on snackbars.",
|
|
4028
|
+
inverseSurface: "Background for elements that require reverse contrast, such as snackbars.",
|
|
4029
|
+
onBackground: "Color for text and icons displayed on the background.",
|
|
4030
|
+
onError: "Color for text and icons on error-colored elements.",
|
|
4031
|
+
onErrorContainer: "Color for text and icons on error container elements.",
|
|
4032
|
+
onPrimary: "Color for text and icons on primary-colored elements like filled buttons.",
|
|
4033
|
+
onPrimaryContainer: "Color for text and icons on primary container elements like tonal buttons.",
|
|
4034
|
+
onPrimaryFixed: "Color for text and icons on primary fixed elements, constant across themes.",
|
|
4035
|
+
onPrimaryFixedVariant: "Lower-emphasis color for text and icons on primary fixed elements.",
|
|
4036
|
+
onSecondary: "Color for text and icons on secondary-colored elements.",
|
|
4037
|
+
onSecondaryContainer: "Color for text and icons on secondary container elements.",
|
|
4038
|
+
onSecondaryFixed: "Color for text and icons on secondary fixed elements, constant across themes.",
|
|
4039
|
+
onSecondaryFixedVariant: "Lower-emphasis color for text and icons on secondary fixed elements.",
|
|
4040
|
+
onSurface: "High-emphasis color for text and icons on surface backgrounds.",
|
|
4041
|
+
onSurfaceVariant: "Medium-emphasis color for text and icons on surface variant backgrounds.",
|
|
4042
|
+
onTertiary: "Color for text and icons on tertiary-colored elements.",
|
|
4043
|
+
onTertiaryContainer: "Color for text and icons on tertiary container elements.",
|
|
4044
|
+
onTertiaryFixed: "Color for text and icons on tertiary fixed elements, constant across themes.",
|
|
4045
|
+
onTertiaryFixedVariant: "Lower-emphasis color for text and icons on tertiary fixed elements.",
|
|
4046
|
+
outline: "Subtle color for borders and dividers to create visual separation.",
|
|
4047
|
+
outlineVariant: "Lower-emphasis border color used for decorative dividers.",
|
|
4048
|
+
primary: "Main brand color, used for key components like filled buttons and active states.",
|
|
4049
|
+
primaryContainer: "Fill color for large primary elements like cards and tonal buttons.",
|
|
4050
|
+
primaryFixed: "Fixed primary color that stays the same in light and dark themes.",
|
|
4051
|
+
primaryFixedDim: "Dimmed variant of the fixed primary color for lower emphasis.",
|
|
4052
|
+
scrim: "Color overlay for modals and dialogs to obscure background content.",
|
|
4053
|
+
secondary: "Accent color for less prominent elements like filter chips and selections.",
|
|
4054
|
+
secondaryContainer: "Fill color for secondary container elements like tonal buttons and input fields.",
|
|
4055
|
+
secondaryFixed: "Fixed secondary color that stays the same in light and dark themes.",
|
|
4056
|
+
secondaryFixedDim: "Dimmed variant of the fixed secondary color for lower emphasis.",
|
|
4057
|
+
shadow: "Color for elevation shadows applied to surfaces and components.",
|
|
4058
|
+
surface: "Default surface color for cards, sheets, and dialogs.",
|
|
4059
|
+
surfaceBright: "Brightest surface variant, used for elevated surfaces in dark themes.",
|
|
4060
|
+
surfaceContainer: "Middle-emphasis container color for grouping related content.",
|
|
4061
|
+
surfaceContainerHigh: "Higher-emphasis container color for elements like cards.",
|
|
4062
|
+
surfaceContainerHighest: "Highest-emphasis container color for text fields and other input areas.",
|
|
4063
|
+
surfaceContainerLow: "Lower-emphasis container color for subtle surface groupings.",
|
|
4064
|
+
surfaceContainerLowest: "Lowest-emphasis container, typically the lightest surface in light theme.",
|
|
4065
|
+
surfaceDim: "Dimmest surface variant, used for recessed areas or dark theme backgrounds.",
|
|
4066
|
+
surfaceTint: "Tint color applied to surfaces for subtle primary color elevation overlay.",
|
|
4067
|
+
surfaceVariant: "Alternative surface color for differentiated areas like sidebar backgrounds.",
|
|
4068
|
+
tertiary: "Third accent color for complementary elements that balance primary and secondary.",
|
|
4069
|
+
tertiaryContainer: "Fill color for tertiary container elements like complementary cards.",
|
|
4070
|
+
tertiaryFixed: "Fixed tertiary color that stays the same in light and dark themes.",
|
|
4071
|
+
tertiaryFixedDim: "Dimmed variant of the fixed tertiary color for lower emphasis."
|
|
4072
|
+
};
|
|
4073
|
+
function isTokenName(key) {
|
|
4074
|
+
return key in tokenDescriptions;
|
|
4075
|
+
}
|
|
4076
|
+
var tokenNames = Object.keys(tokenDescriptions).filter(isTokenName);
|
|
3986
4077
|
var SHADE_TO_TONE = [
|
|
3987
4078
|
[50, 95],
|
|
3988
4079
|
[100, 90],
|
|
@@ -4004,6 +4095,8 @@ var CORE_PALETTES = [
|
|
|
4004
4095
|
"neutral",
|
|
4005
4096
|
"neutral-variant"
|
|
4006
4097
|
];
|
|
4098
|
+
|
|
4099
|
+
// src/lib/builder.tailwind.ts
|
|
4007
4100
|
function buildTailwind(ctx, options) {
|
|
4008
4101
|
const { prefix, mergedColorsLight, hexCustomColors } = ctx;
|
|
4009
4102
|
const lines = [];
|
|
@@ -4036,17 +4129,8 @@ function buildTailwind(ctx, options) {
|
|
|
4036
4129
|
${lines.join("\n ")}
|
|
4037
4130
|
}
|
|
4038
4131
|
`;
|
|
4039
|
-
if (options?.shadcn)
|
|
4040
|
-
|
|
4041
|
-
([shadcnVar, m3Token]) => `${shadcnVar}: var(--${prefix}-sys-color-${m3Token});`
|
|
4042
|
-
);
|
|
4043
|
-
output += `
|
|
4044
|
-
:root,
|
|
4045
|
-
.dark {
|
|
4046
|
-
${shadcnLines.join("\n ")}
|
|
4047
|
-
}
|
|
4048
|
-
`;
|
|
4049
|
-
}
|
|
4132
|
+
if (options?.shadcn) output += `
|
|
4133
|
+
${buildShadcnAliases(ctx)}`;
|
|
4050
4134
|
return output;
|
|
4051
4135
|
}
|
|
4052
4136
|
|
|
@@ -4064,7 +4148,24 @@ var DEFAULT_SCHEME = "tonalSpot";
|
|
|
4064
4148
|
var DEFAULT_CONTRAST = 0;
|
|
4065
4149
|
var DEFAULT_CUSTOM_COLORS = [];
|
|
4066
4150
|
var DEFAULT_BLEND = true;
|
|
4067
|
-
var
|
|
4151
|
+
var HEX_COLOR = /^#?(?:[0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i;
|
|
4152
|
+
function isHexColor(value) {
|
|
4153
|
+
return HEX_COLOR.test(value);
|
|
4154
|
+
}
|
|
4155
|
+
function assertHexColor(label, value) {
|
|
4156
|
+
if (!isHexColor(value))
|
|
4157
|
+
throw new Error(
|
|
4158
|
+
`Invalid ${label}: '${value}'. Expected a hex color \u2014 3, 6 or 8 hex digits, with or without '#' (e.g. #6750A4).`
|
|
4159
|
+
);
|
|
4160
|
+
}
|
|
4161
|
+
function assertHexInputs(source, cores, customColors) {
|
|
4162
|
+
assertHexColor("source", source);
|
|
4163
|
+
for (const [name, hex] of Object.entries(cores))
|
|
4164
|
+
if (hex !== void 0) assertHexColor(name, hex);
|
|
4165
|
+
customColors.forEach(
|
|
4166
|
+
(color, i) => assertHexColor(`customColors[${i}].hex`, color.hex)
|
|
4167
|
+
);
|
|
4168
|
+
}
|
|
4068
4169
|
var STANDARD_TONES = [
|
|
4069
4170
|
0,
|
|
4070
4171
|
4,
|
|
@@ -4115,61 +4216,6 @@ var schemeToVariant = {
|
|
|
4115
4216
|
fidelity: Variant.FIDELITY,
|
|
4116
4217
|
content: Variant.CONTENT
|
|
4117
4218
|
};
|
|
4118
|
-
var tokenDescriptions = {
|
|
4119
|
-
background: "Default background color for screens and large surfaces.",
|
|
4120
|
-
error: "Color for error states, used on elements like error text and icons.",
|
|
4121
|
-
errorContainer: "Fill color for error container elements like error banners.",
|
|
4122
|
-
inverseOnSurface: "Color for text and icons on inverse surface backgrounds.",
|
|
4123
|
-
inversePrimary: "Primary color used on inverse surface, e.g. buttons on snackbars.",
|
|
4124
|
-
inverseSurface: "Background for elements that require reverse contrast, such as snackbars.",
|
|
4125
|
-
onBackground: "Color for text and icons displayed on the background.",
|
|
4126
|
-
onError: "Color for text and icons on error-colored elements.",
|
|
4127
|
-
onErrorContainer: "Color for text and icons on error container elements.",
|
|
4128
|
-
onPrimary: "Color for text and icons on primary-colored elements like filled buttons.",
|
|
4129
|
-
onPrimaryContainer: "Color for text and icons on primary container elements like tonal buttons.",
|
|
4130
|
-
onPrimaryFixed: "Color for text and icons on primary fixed elements, constant across themes.",
|
|
4131
|
-
onPrimaryFixedVariant: "Lower-emphasis color for text and icons on primary fixed elements.",
|
|
4132
|
-
onSecondary: "Color for text and icons on secondary-colored elements.",
|
|
4133
|
-
onSecondaryContainer: "Color for text and icons on secondary container elements.",
|
|
4134
|
-
onSecondaryFixed: "Color for text and icons on secondary fixed elements, constant across themes.",
|
|
4135
|
-
onSecondaryFixedVariant: "Lower-emphasis color for text and icons on secondary fixed elements.",
|
|
4136
|
-
onSurface: "High-emphasis color for text and icons on surface backgrounds.",
|
|
4137
|
-
onSurfaceVariant: "Medium-emphasis color for text and icons on surface variant backgrounds.",
|
|
4138
|
-
onTertiary: "Color for text and icons on tertiary-colored elements.",
|
|
4139
|
-
onTertiaryContainer: "Color for text and icons on tertiary container elements.",
|
|
4140
|
-
onTertiaryFixed: "Color for text and icons on tertiary fixed elements, constant across themes.",
|
|
4141
|
-
onTertiaryFixedVariant: "Lower-emphasis color for text and icons on tertiary fixed elements.",
|
|
4142
|
-
outline: "Subtle color for borders and dividers to create visual separation.",
|
|
4143
|
-
outlineVariant: "Lower-emphasis border color used for decorative dividers.",
|
|
4144
|
-
primary: "Main brand color, used for key components like filled buttons and active states.",
|
|
4145
|
-
primaryContainer: "Fill color for large primary elements like cards and tonal buttons.",
|
|
4146
|
-
primaryFixed: "Fixed primary color that stays the same in light and dark themes.",
|
|
4147
|
-
primaryFixedDim: "Dimmed variant of the fixed primary color for lower emphasis.",
|
|
4148
|
-
scrim: "Color overlay for modals and dialogs to obscure background content.",
|
|
4149
|
-
secondary: "Accent color for less prominent elements like filter chips and selections.",
|
|
4150
|
-
secondaryContainer: "Fill color for secondary container elements like tonal buttons and input fields.",
|
|
4151
|
-
secondaryFixed: "Fixed secondary color that stays the same in light and dark themes.",
|
|
4152
|
-
secondaryFixedDim: "Dimmed variant of the fixed secondary color for lower emphasis.",
|
|
4153
|
-
shadow: "Color for elevation shadows applied to surfaces and components.",
|
|
4154
|
-
surface: "Default surface color for cards, sheets, and dialogs.",
|
|
4155
|
-
surfaceBright: "Brightest surface variant, used for elevated surfaces in dark themes.",
|
|
4156
|
-
surfaceContainer: "Middle-emphasis container color for grouping related content.",
|
|
4157
|
-
surfaceContainerHigh: "Higher-emphasis container color for elements like cards.",
|
|
4158
|
-
surfaceContainerHighest: "Highest-emphasis container color for text fields and other input areas.",
|
|
4159
|
-
surfaceContainerLow: "Lower-emphasis container color for subtle surface groupings.",
|
|
4160
|
-
surfaceContainerLowest: "Lowest-emphasis container, typically the lightest surface in light theme.",
|
|
4161
|
-
surfaceDim: "Dimmest surface variant, used for recessed areas or dark theme backgrounds.",
|
|
4162
|
-
surfaceTint: "Tint color applied to surfaces for subtle primary color elevation overlay.",
|
|
4163
|
-
surfaceVariant: "Alternative surface color for differentiated areas like sidebar backgrounds.",
|
|
4164
|
-
tertiary: "Third accent color for complementary elements that balance primary and secondary.",
|
|
4165
|
-
tertiaryContainer: "Fill color for tertiary container elements like complementary cards.",
|
|
4166
|
-
tertiaryFixed: "Fixed tertiary color that stays the same in light and dark themes.",
|
|
4167
|
-
tertiaryFixedDim: "Dimmed variant of the fixed tertiary color for lower emphasis."
|
|
4168
|
-
};
|
|
4169
|
-
function isTokenName(key) {
|
|
4170
|
-
return key in tokenDescriptions;
|
|
4171
|
-
}
|
|
4172
|
-
var tokenNames = Object.keys(tokenDescriptions).filter(isTokenName);
|
|
4173
4219
|
function deriveCustomPaletteName(tokenName, allPaletteNamesKebab) {
|
|
4174
4220
|
let baseName = tokenName;
|
|
4175
4221
|
if (/^on[A-Z]/.test(baseName) && baseName.length > 2) {
|
|
@@ -4288,6 +4334,11 @@ function builder(hexSource, {
|
|
|
4288
4334
|
customColors: hexCustomColors = DEFAULT_CUSTOM_COLORS,
|
|
4289
4335
|
prefix = DEFAULT_PREFIX
|
|
4290
4336
|
} = {}) {
|
|
4337
|
+
assertHexInputs(
|
|
4338
|
+
hexSource,
|
|
4339
|
+
{ primary, secondary, tertiary, error, neutral, neutralVariant },
|
|
4340
|
+
hexCustomColors
|
|
4341
|
+
);
|
|
4291
4342
|
const sourceArgb = argbFromHex2(hexSource);
|
|
4292
4343
|
const sourceHct = Hct2.fromInt(sourceArgb);
|
|
4293
4344
|
const effectiveSource = primary || hexSource;
|
|
@@ -4431,6 +4482,8 @@ function builder(hexSource, {
|
|
|
4431
4482
|
toFigmaTokens: () => buildFigmaTokens(ctx),
|
|
4432
4483
|
toTailwind: (options) => buildTailwind(ctx, options),
|
|
4433
4484
|
toShadcn: () => buildShadcn(ctx),
|
|
4485
|
+
toShadcnAliases: () => buildShadcnAliases(ctx),
|
|
4486
|
+
toShadcnRegistryItem: (options) => buildShadcnRegistryItem(ctx, options),
|
|
4434
4487
|
toFlutter: () => buildFlutter(ctx),
|
|
4435
4488
|
mergedColorsLight,
|
|
4436
4489
|
mergedColorsDark,
|
|
@@ -4524,15 +4577,15 @@ var createRequiredContext = () => {
|
|
|
4524
4577
|
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
4525
4578
|
var [useMtb, Provider, MtbContext] = createRequiredContext();
|
|
4526
4579
|
var MtbProvider = ({
|
|
4527
|
-
styleId,
|
|
4580
|
+
styleId: styleId2,
|
|
4528
4581
|
children,
|
|
4529
4582
|
...configProps
|
|
4530
4583
|
}) => {
|
|
4531
4584
|
const [initials] = useState(() => configProps);
|
|
4532
|
-
const [
|
|
4585
|
+
const [mtbConfig, setMtbConfig] = useState(initials);
|
|
4533
4586
|
const configKey = JSON.stringify(configProps);
|
|
4534
4587
|
React.useEffect(() => {
|
|
4535
|
-
|
|
4588
|
+
setMtbConfig(configProps);
|
|
4536
4589
|
}, [configKey]);
|
|
4537
4590
|
const {
|
|
4538
4591
|
css,
|
|
@@ -4543,8 +4596,8 @@ var MtbProvider = ({
|
|
|
4543
4596
|
figmaVariables
|
|
4544
4597
|
} = useMemo(() => {
|
|
4545
4598
|
const { toCss, toFigmaTokens, toFigmaVariables, ...rest } = builder(
|
|
4546
|
-
|
|
4547
|
-
|
|
4599
|
+
mtbConfig.source,
|
|
4600
|
+
mtbConfig
|
|
4548
4601
|
);
|
|
4549
4602
|
return {
|
|
4550
4603
|
css: toCss(),
|
|
@@ -4552,13 +4605,13 @@ var MtbProvider = ({
|
|
|
4552
4605
|
figmaVariables: toFigmaVariables(),
|
|
4553
4606
|
...rest
|
|
4554
4607
|
};
|
|
4555
|
-
}, [
|
|
4556
|
-
const
|
|
4608
|
+
}, [mtbConfig]);
|
|
4609
|
+
const getMtbColor = useCallback(
|
|
4557
4610
|
(colorName, theme) => {
|
|
4558
4611
|
const mergedColors = theme === "light" ? mergedColorsLight : mergedColorsDark;
|
|
4559
4612
|
const colorValue = mergedColors[colorName];
|
|
4560
4613
|
if (colorValue === void 0) {
|
|
4561
|
-
throw new Error(`Unknown
|
|
4614
|
+
throw new Error(`Unknown token '${colorName}'`);
|
|
4562
4615
|
}
|
|
4563
4616
|
return hexFromArgb5(colorValue);
|
|
4564
4617
|
},
|
|
@@ -4567,24 +4620,28 @@ var MtbProvider = ({
|
|
|
4567
4620
|
const value = useMemo(
|
|
4568
4621
|
() => ({
|
|
4569
4622
|
initials,
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4623
|
+
mtbConfig,
|
|
4624
|
+
setMtbConfig,
|
|
4625
|
+
getMtbColor,
|
|
4573
4626
|
allPalettes,
|
|
4574
4627
|
figmaTokens,
|
|
4575
|
-
figmaVariables
|
|
4628
|
+
figmaVariables,
|
|
4629
|
+
// deprecated aliases
|
|
4630
|
+
mcuConfig: mtbConfig,
|
|
4631
|
+
setMcuConfig: setMtbConfig,
|
|
4632
|
+
getMcuColor: getMtbColor
|
|
4576
4633
|
}),
|
|
4577
4634
|
[
|
|
4578
|
-
|
|
4635
|
+
getMtbColor,
|
|
4579
4636
|
initials,
|
|
4580
|
-
|
|
4637
|
+
mtbConfig,
|
|
4581
4638
|
allPalettes,
|
|
4582
4639
|
figmaTokens,
|
|
4583
4640
|
figmaVariables
|
|
4584
4641
|
]
|
|
4585
4642
|
);
|
|
4586
4643
|
return /* @__PURE__ */ jsxs2(Provider, { value, children: [
|
|
4587
|
-
/* @__PURE__ */ jsx3("style", { id:
|
|
4644
|
+
/* @__PURE__ */ jsx3("style", { id: styleId2, dangerouslySetInnerHTML: { __html: css } }),
|
|
4588
4645
|
children
|
|
4589
4646
|
] });
|
|
4590
4647
|
};
|
|
@@ -4592,7 +4649,7 @@ var useMcu = useMtb;
|
|
|
4592
4649
|
|
|
4593
4650
|
// src/Mtb.tsx
|
|
4594
4651
|
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
4595
|
-
var
|
|
4652
|
+
var styleId = "mcu-styles";
|
|
4596
4653
|
var DEFAULT_COLOR_MATCH = false;
|
|
4597
4654
|
function Mtb({
|
|
4598
4655
|
source,
|
|
@@ -4639,7 +4696,7 @@ function Mtb({
|
|
|
4639
4696
|
prefix
|
|
4640
4697
|
]
|
|
4641
4698
|
);
|
|
4642
|
-
return /* @__PURE__ */ jsx4(MtbProvider, { ...config, styleId
|
|
4699
|
+
return /* @__PURE__ */ jsx4(MtbProvider, { ...config, styleId, children });
|
|
4643
4700
|
}
|
|
4644
4701
|
var Mcu = Mtb;
|
|
4645
4702
|
export {
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
+
"name": "material-theme-builder",
|
|
4
|
+
"type": "registry:theme",
|
|
5
|
+
"title": "Material Theme Builder",
|
|
6
|
+
"description": "Points shadcn's CSS variables at the M3 custom properties `<Mtb>` emits, so every shadcn component follows whichever theme is above it in the tree.",
|
|
7
|
+
"cssVars": {
|
|
8
|
+
"light": {
|
|
9
|
+
"background": "var(--md-sys-color-surface)",
|
|
10
|
+
"foreground": "var(--md-sys-color-on-surface)",
|
|
11
|
+
"card": "var(--md-sys-color-surface-container-low)",
|
|
12
|
+
"card-foreground": "var(--md-sys-color-on-surface)",
|
|
13
|
+
"popover": "var(--md-sys-color-surface-container-high)",
|
|
14
|
+
"popover-foreground": "var(--md-sys-color-on-surface)",
|
|
15
|
+
"primary": "var(--md-sys-color-primary)",
|
|
16
|
+
"primary-foreground": "var(--md-sys-color-on-primary)",
|
|
17
|
+
"secondary": "var(--md-sys-color-secondary-container)",
|
|
18
|
+
"secondary-foreground": "var(--md-sys-color-on-secondary-container)",
|
|
19
|
+
"muted": "var(--md-sys-color-surface-container-highest)",
|
|
20
|
+
"muted-foreground": "var(--md-sys-color-on-surface-variant)",
|
|
21
|
+
"accent": "var(--md-sys-color-secondary-container)",
|
|
22
|
+
"accent-foreground": "var(--md-sys-color-on-secondary-container)",
|
|
23
|
+
"destructive": "var(--md-sys-color-error)",
|
|
24
|
+
"border": "var(--md-sys-color-outline-variant)",
|
|
25
|
+
"input": "var(--md-sys-color-outline)",
|
|
26
|
+
"ring": "var(--md-sys-color-primary)",
|
|
27
|
+
"chart-1": "var(--md-sys-color-primary-fixed)",
|
|
28
|
+
"chart-2": "var(--md-sys-color-secondary-fixed)",
|
|
29
|
+
"chart-3": "var(--md-sys-color-tertiary-fixed)",
|
|
30
|
+
"chart-4": "var(--md-sys-color-primary-fixed-dim)",
|
|
31
|
+
"chart-5": "var(--md-sys-color-secondary-fixed-dim)",
|
|
32
|
+
"sidebar": "var(--md-sys-color-surface-container-low)",
|
|
33
|
+
"sidebar-foreground": "var(--md-sys-color-on-surface)",
|
|
34
|
+
"sidebar-primary": "var(--md-sys-color-primary)",
|
|
35
|
+
"sidebar-primary-foreground": "var(--md-sys-color-on-primary)",
|
|
36
|
+
"sidebar-accent": "var(--md-sys-color-secondary-container)",
|
|
37
|
+
"sidebar-accent-foreground": "var(--md-sys-color-on-secondary-container)",
|
|
38
|
+
"sidebar-border": "var(--md-sys-color-outline-variant)",
|
|
39
|
+
"sidebar-ring": "var(--md-sys-color-primary)"
|
|
40
|
+
},
|
|
41
|
+
"dark": {
|
|
42
|
+
"background": "var(--md-sys-color-surface)",
|
|
43
|
+
"foreground": "var(--md-sys-color-on-surface)",
|
|
44
|
+
"card": "var(--md-sys-color-surface-container-low)",
|
|
45
|
+
"card-foreground": "var(--md-sys-color-on-surface)",
|
|
46
|
+
"popover": "var(--md-sys-color-surface-container-high)",
|
|
47
|
+
"popover-foreground": "var(--md-sys-color-on-surface)",
|
|
48
|
+
"primary": "var(--md-sys-color-primary)",
|
|
49
|
+
"primary-foreground": "var(--md-sys-color-on-primary)",
|
|
50
|
+
"secondary": "var(--md-sys-color-secondary-container)",
|
|
51
|
+
"secondary-foreground": "var(--md-sys-color-on-secondary-container)",
|
|
52
|
+
"muted": "var(--md-sys-color-surface-container-highest)",
|
|
53
|
+
"muted-foreground": "var(--md-sys-color-on-surface-variant)",
|
|
54
|
+
"accent": "var(--md-sys-color-secondary-container)",
|
|
55
|
+
"accent-foreground": "var(--md-sys-color-on-secondary-container)",
|
|
56
|
+
"destructive": "var(--md-sys-color-error)",
|
|
57
|
+
"border": "var(--md-sys-color-outline-variant)",
|
|
58
|
+
"input": "var(--md-sys-color-outline)",
|
|
59
|
+
"ring": "var(--md-sys-color-primary)",
|
|
60
|
+
"chart-1": "var(--md-sys-color-primary-fixed)",
|
|
61
|
+
"chart-2": "var(--md-sys-color-secondary-fixed)",
|
|
62
|
+
"chart-3": "var(--md-sys-color-tertiary-fixed)",
|
|
63
|
+
"chart-4": "var(--md-sys-color-primary-fixed-dim)",
|
|
64
|
+
"chart-5": "var(--md-sys-color-secondary-fixed-dim)",
|
|
65
|
+
"sidebar": "var(--md-sys-color-surface-container-low)",
|
|
66
|
+
"sidebar-foreground": "var(--md-sys-color-on-surface)",
|
|
67
|
+
"sidebar-primary": "var(--md-sys-color-primary)",
|
|
68
|
+
"sidebar-primary-foreground": "var(--md-sys-color-on-primary)",
|
|
69
|
+
"sidebar-accent": "var(--md-sys-color-secondary-container)",
|
|
70
|
+
"sidebar-accent-foreground": "var(--md-sys-color-on-secondary-container)",
|
|
71
|
+
"sidebar-border": "var(--md-sys-color-outline-variant)",
|
|
72
|
+
"sidebar-ring": "var(--md-sys-color-primary)"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
package/dist/shadcn.css
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Generated by `scripts/generate.mjs` -- do not edit.
|
|
3
|
+
*
|
|
4
|
+
* Points shadcn's variables at the M3 custom properties `<Mtb>` emits, so
|
|
5
|
+
* shadcn components follow the theme above them in the tree. Import it after
|
|
6
|
+
* shadcn's own `:root` and `.dark` blocks, which it has to override -- or
|
|
7
|
+
* skip the ordering question entirely and install `registry-item.json` with
|
|
8
|
+
* `shadcn add`, which writes the same mapping into those blocks in place.
|
|
9
|
+
*/
|
|
10
|
+
:root,
|
|
11
|
+
.dark {
|
|
12
|
+
--background: var(--md-sys-color-surface);
|
|
13
|
+
--foreground: var(--md-sys-color-on-surface);
|
|
14
|
+
--card: var(--md-sys-color-surface-container-low);
|
|
15
|
+
--card-foreground: var(--md-sys-color-on-surface);
|
|
16
|
+
--popover: var(--md-sys-color-surface-container-high);
|
|
17
|
+
--popover-foreground: var(--md-sys-color-on-surface);
|
|
18
|
+
--primary: var(--md-sys-color-primary);
|
|
19
|
+
--primary-foreground: var(--md-sys-color-on-primary);
|
|
20
|
+
--secondary: var(--md-sys-color-secondary-container);
|
|
21
|
+
--secondary-foreground: var(--md-sys-color-on-secondary-container);
|
|
22
|
+
--muted: var(--md-sys-color-surface-container-highest);
|
|
23
|
+
--muted-foreground: var(--md-sys-color-on-surface-variant);
|
|
24
|
+
--accent: var(--md-sys-color-secondary-container);
|
|
25
|
+
--accent-foreground: var(--md-sys-color-on-secondary-container);
|
|
26
|
+
--destructive: var(--md-sys-color-error);
|
|
27
|
+
--border: var(--md-sys-color-outline-variant);
|
|
28
|
+
--input: var(--md-sys-color-outline);
|
|
29
|
+
--ring: var(--md-sys-color-primary);
|
|
30
|
+
--chart-1: var(--md-sys-color-primary-fixed);
|
|
31
|
+
--chart-2: var(--md-sys-color-secondary-fixed);
|
|
32
|
+
--chart-3: var(--md-sys-color-tertiary-fixed);
|
|
33
|
+
--chart-4: var(--md-sys-color-primary-fixed-dim);
|
|
34
|
+
--chart-5: var(--md-sys-color-secondary-fixed-dim);
|
|
35
|
+
--sidebar: var(--md-sys-color-surface-container-low);
|
|
36
|
+
--sidebar-foreground: var(--md-sys-color-on-surface);
|
|
37
|
+
--sidebar-primary: var(--md-sys-color-primary);
|
|
38
|
+
--sidebar-primary-foreground: var(--md-sys-color-on-primary);
|
|
39
|
+
--sidebar-accent: var(--md-sys-color-secondary-container);
|
|
40
|
+
--sidebar-accent-foreground: var(--md-sys-color-on-secondary-container);
|
|
41
|
+
--sidebar-border: var(--md-sys-color-outline-variant);
|
|
42
|
+
--sidebar-ring: var(--md-sys-color-primary);
|
|
43
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import * as node_modules_tailwindcss_dist_types_CJYAW1ql_mjs from 'node_modules/tailwindcss/dist/types-CJYAW1ql.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Options accepted by `@plugin "material-theme-builder/tailwind" { ... }`.
|
|
5
|
+
*
|
|
6
|
+
* Tailwind parses the block as CSS declarations, so the property names are
|
|
7
|
+
* kebab-case and a comma-separated value arrives as an array. Everything is
|
|
8
|
+
* typed loosely on the way in because the values come from a stylesheet, not
|
|
9
|
+
* from a type-checked call site.
|
|
10
|
+
*/
|
|
11
|
+
type MtbTailwindPluginOptions = {
|
|
12
|
+
/**
|
|
13
|
+
* Custom color names, exactly as passed to `builder()` / `<Mtb>`:
|
|
14
|
+
*
|
|
15
|
+
* ```css
|
|
16
|
+
* @plugin "material-theme-builder/tailwind" {
|
|
17
|
+
* custom-colors: myCustomColor1, myCustomColor2;
|
|
18
|
+
* }
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
"custom-colors"?: string | string[] | number | (string | number)[];
|
|
22
|
+
/** CSS custom-property prefix, matching `builder({ prefix })`. Default `md`. */
|
|
23
|
+
prefix?: string;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* The `--color-*` map the plugin registers, as a plain object.
|
|
27
|
+
*
|
|
28
|
+
* Keys are Tailwind color names (`primary`, `on-primary`, `primary-500`),
|
|
29
|
+
* values are `var()` references into the `--{prefix}-sys-color-*` /
|
|
30
|
+
* `--{prefix}-ref-palette-*` properties `<Mtb>` (or `builder().toCss()`) emits.
|
|
31
|
+
*
|
|
32
|
+
* Custom colors keep the name they were declared with — `myCustomColor1` stays
|
|
33
|
+
* `bg-myCustomColor1` — while the CSS property it points at is kebab-cased,
|
|
34
|
+
* because that is the spelling the builder writes.
|
|
35
|
+
*/
|
|
36
|
+
declare function mtbColors({ customColors, prefix, }?: {
|
|
37
|
+
customColors?: string[];
|
|
38
|
+
prefix?: string;
|
|
39
|
+
}): Record<string, string>;
|
|
40
|
+
/**
|
|
41
|
+
* Tailwind v4 plugin — the `@theme inline` block of
|
|
42
|
+
* `material-theme-builder/tailwind.css`, minus the copy-paste.
|
|
43
|
+
*
|
|
44
|
+
* ```css
|
|
45
|
+
* @import "tailwindcss";
|
|
46
|
+
* @plugin "material-theme-builder/tailwind" {
|
|
47
|
+
* custom-colors: myCustomColor1, myCustomColor2;
|
|
48
|
+
* }
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* Colors declared through a plugin's `theme` are inlined by Tailwind — the
|
|
52
|
+
* utility resolves straight to `var(--md-sys-color-primary)` and no
|
|
53
|
+
* `--color-*` indirection is emitted — which is what the stylesheet's
|
|
54
|
+
* `@theme inline` was there to get. That indirection is not cosmetic: a
|
|
55
|
+
* `--color-primary: var(--md-sys-color-primary)` declared on `:root` resolves
|
|
56
|
+
* once, against `:root`, so a nested `<Mtb>` re-declaring the M3 properties
|
|
57
|
+
* would not reach the utilities.
|
|
58
|
+
*
|
|
59
|
+
* Unlike the stylesheet, custom colors need no hand-written block: name them
|
|
60
|
+
* in the options and their four scheme roles plus eleven shades come with them.
|
|
61
|
+
*
|
|
62
|
+
* One thing the stylesheet does that this cannot: theme values a plugin
|
|
63
|
+
* contributes are defaults, so an `@theme` block in the consumer's own CSS
|
|
64
|
+
* wins over them whatever the order — where a later `@import` of the
|
|
65
|
+
* stylesheet would have won. Only colliding names are affected, and against
|
|
66
|
+
* shadcn there are exactly three (`background`, `primary`, `secondary`), which
|
|
67
|
+
* a three-line `@theme inline` of one's own hands back. See the README.
|
|
68
|
+
*
|
|
69
|
+
* @see https://tailwindcss.com/docs/functions-and-directives#plugin-directive
|
|
70
|
+
*/
|
|
71
|
+
declare const mtbTailwindPlugin: node_modules_tailwindcss_dist_types_CJYAW1ql_mjs.c<MtbTailwindPluginOptions>;
|
|
72
|
+
|
|
73
|
+
export { type MtbTailwindPluginOptions, mtbTailwindPlugin as default, mtbColors };
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
// src/tailwind-plugin.ts
|
|
2
|
+
import { kebabCase } from "lodash-es";
|
|
3
|
+
import plugin from "tailwindcss/plugin";
|
|
4
|
+
|
|
5
|
+
// src/lib/tokens.ts
|
|
6
|
+
var DEFAULT_PREFIX = "md";
|
|
7
|
+
var tokenDescriptions = {
|
|
8
|
+
background: "Default background color for screens and large surfaces.",
|
|
9
|
+
error: "Color for error states, used on elements like error text and icons.",
|
|
10
|
+
errorContainer: "Fill color for error container elements like error banners.",
|
|
11
|
+
inverseOnSurface: "Color for text and icons on inverse surface backgrounds.",
|
|
12
|
+
inversePrimary: "Primary color used on inverse surface, e.g. buttons on snackbars.",
|
|
13
|
+
inverseSurface: "Background for elements that require reverse contrast, such as snackbars.",
|
|
14
|
+
onBackground: "Color for text and icons displayed on the background.",
|
|
15
|
+
onError: "Color for text and icons on error-colored elements.",
|
|
16
|
+
onErrorContainer: "Color for text and icons on error container elements.",
|
|
17
|
+
onPrimary: "Color for text and icons on primary-colored elements like filled buttons.",
|
|
18
|
+
onPrimaryContainer: "Color for text and icons on primary container elements like tonal buttons.",
|
|
19
|
+
onPrimaryFixed: "Color for text and icons on primary fixed elements, constant across themes.",
|
|
20
|
+
onPrimaryFixedVariant: "Lower-emphasis color for text and icons on primary fixed elements.",
|
|
21
|
+
onSecondary: "Color for text and icons on secondary-colored elements.",
|
|
22
|
+
onSecondaryContainer: "Color for text and icons on secondary container elements.",
|
|
23
|
+
onSecondaryFixed: "Color for text and icons on secondary fixed elements, constant across themes.",
|
|
24
|
+
onSecondaryFixedVariant: "Lower-emphasis color for text and icons on secondary fixed elements.",
|
|
25
|
+
onSurface: "High-emphasis color for text and icons on surface backgrounds.",
|
|
26
|
+
onSurfaceVariant: "Medium-emphasis color for text and icons on surface variant backgrounds.",
|
|
27
|
+
onTertiary: "Color for text and icons on tertiary-colored elements.",
|
|
28
|
+
onTertiaryContainer: "Color for text and icons on tertiary container elements.",
|
|
29
|
+
onTertiaryFixed: "Color for text and icons on tertiary fixed elements, constant across themes.",
|
|
30
|
+
onTertiaryFixedVariant: "Lower-emphasis color for text and icons on tertiary fixed elements.",
|
|
31
|
+
outline: "Subtle color for borders and dividers to create visual separation.",
|
|
32
|
+
outlineVariant: "Lower-emphasis border color used for decorative dividers.",
|
|
33
|
+
primary: "Main brand color, used for key components like filled buttons and active states.",
|
|
34
|
+
primaryContainer: "Fill color for large primary elements like cards and tonal buttons.",
|
|
35
|
+
primaryFixed: "Fixed primary color that stays the same in light and dark themes.",
|
|
36
|
+
primaryFixedDim: "Dimmed variant of the fixed primary color for lower emphasis.",
|
|
37
|
+
scrim: "Color overlay for modals and dialogs to obscure background content.",
|
|
38
|
+
secondary: "Accent color for less prominent elements like filter chips and selections.",
|
|
39
|
+
secondaryContainer: "Fill color for secondary container elements like tonal buttons and input fields.",
|
|
40
|
+
secondaryFixed: "Fixed secondary color that stays the same in light and dark themes.",
|
|
41
|
+
secondaryFixedDim: "Dimmed variant of the fixed secondary color for lower emphasis.",
|
|
42
|
+
shadow: "Color for elevation shadows applied to surfaces and components.",
|
|
43
|
+
surface: "Default surface color for cards, sheets, and dialogs.",
|
|
44
|
+
surfaceBright: "Brightest surface variant, used for elevated surfaces in dark themes.",
|
|
45
|
+
surfaceContainer: "Middle-emphasis container color for grouping related content.",
|
|
46
|
+
surfaceContainerHigh: "Higher-emphasis container color for elements like cards.",
|
|
47
|
+
surfaceContainerHighest: "Highest-emphasis container color for text fields and other input areas.",
|
|
48
|
+
surfaceContainerLow: "Lower-emphasis container color for subtle surface groupings.",
|
|
49
|
+
surfaceContainerLowest: "Lowest-emphasis container, typically the lightest surface in light theme.",
|
|
50
|
+
surfaceDim: "Dimmest surface variant, used for recessed areas or dark theme backgrounds.",
|
|
51
|
+
surfaceTint: "Tint color applied to surfaces for subtle primary color elevation overlay.",
|
|
52
|
+
surfaceVariant: "Alternative surface color for differentiated areas like sidebar backgrounds.",
|
|
53
|
+
tertiary: "Third accent color for complementary elements that balance primary and secondary.",
|
|
54
|
+
tertiaryContainer: "Fill color for tertiary container elements like complementary cards.",
|
|
55
|
+
tertiaryFixed: "Fixed tertiary color that stays the same in light and dark themes.",
|
|
56
|
+
tertiaryFixedDim: "Dimmed variant of the fixed tertiary color for lower emphasis."
|
|
57
|
+
};
|
|
58
|
+
function isTokenName(key) {
|
|
59
|
+
return key in tokenDescriptions;
|
|
60
|
+
}
|
|
61
|
+
var tokenNames = Object.keys(tokenDescriptions).filter(isTokenName);
|
|
62
|
+
var SHADE_TO_TONE = [
|
|
63
|
+
[50, 95],
|
|
64
|
+
[100, 90],
|
|
65
|
+
[200, 80],
|
|
66
|
+
[300, 70],
|
|
67
|
+
[400, 60],
|
|
68
|
+
[500, 50],
|
|
69
|
+
[600, 40],
|
|
70
|
+
[700, 30],
|
|
71
|
+
[800, 20],
|
|
72
|
+
[900, 10],
|
|
73
|
+
[950, 5]
|
|
74
|
+
];
|
|
75
|
+
var CORE_PALETTES = [
|
|
76
|
+
"primary",
|
|
77
|
+
"secondary",
|
|
78
|
+
"tertiary",
|
|
79
|
+
"error",
|
|
80
|
+
"neutral",
|
|
81
|
+
"neutral-variant"
|
|
82
|
+
];
|
|
83
|
+
|
|
84
|
+
// src/tailwind-plugin.ts
|
|
85
|
+
function toNames(value) {
|
|
86
|
+
if (value === void 0 || value === null) return [];
|
|
87
|
+
return (Array.isArray(value) ? value : [value]).flatMap((entry) => String(entry).split(/[\s,]+/)).map((name) => name.trim().replace(/^["']|["']$/g, "")).filter(Boolean);
|
|
88
|
+
}
|
|
89
|
+
function mtbColors({
|
|
90
|
+
customColors = [],
|
|
91
|
+
prefix = DEFAULT_PREFIX
|
|
92
|
+
} = {}) {
|
|
93
|
+
const colors = {};
|
|
94
|
+
const sys = (token) => `var(--${prefix}-sys-color-${token})`;
|
|
95
|
+
const ref = (palette, tone) => `var(--${prefix}-ref-palette-${palette}-${tone})`;
|
|
96
|
+
for (const name of tokenNames) {
|
|
97
|
+
const kebab = kebabCase(name);
|
|
98
|
+
colors[kebab] = sys(kebab);
|
|
99
|
+
}
|
|
100
|
+
for (const palette of CORE_PALETTES) {
|
|
101
|
+
for (const [shade, tone] of SHADE_TO_TONE) {
|
|
102
|
+
colors[`${palette}-${shade}`] = ref(palette, tone);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
for (const name of customColors) {
|
|
106
|
+
const kebab = kebabCase(name);
|
|
107
|
+
colors[name] = sys(kebab);
|
|
108
|
+
colors[`on-${name}`] = sys(`on-${kebab}`);
|
|
109
|
+
colors[`${name}-container`] = sys(`${kebab}-container`);
|
|
110
|
+
colors[`on-${name}-container`] = sys(`on-${kebab}-container`);
|
|
111
|
+
for (const [shade, tone] of SHADE_TO_TONE) {
|
|
112
|
+
colors[`${name}-${shade}`] = ref(kebab, tone);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return colors;
|
|
116
|
+
}
|
|
117
|
+
var mtbTailwindPlugin = plugin.withOptions(
|
|
118
|
+
() => () => {
|
|
119
|
+
},
|
|
120
|
+
(options = {}) => ({
|
|
121
|
+
theme: {
|
|
122
|
+
extend: {
|
|
123
|
+
colors: mtbColors({
|
|
124
|
+
customColors: toNames(options["custom-colors"]),
|
|
125
|
+
prefix: options.prefix
|
|
126
|
+
})
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
})
|
|
130
|
+
);
|
|
131
|
+
var tailwind_plugin_default = mtbTailwindPlugin;
|
|
132
|
+
export {
|
|
133
|
+
tailwind_plugin_default as default,
|
|
134
|
+
mtbColors
|
|
135
|
+
};
|