material-theme-builder 2.1.2 → 3.0.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/dist/index.js CHANGED
@@ -1,17 +1,11 @@
1
- "use client";
2
-
3
1
  // src/lib/builder.ts
4
2
  import {
5
- argbFromHex,
3
+ argbFromHex as argbFromHex2,
6
4
  Blend,
7
- blueFromArgb,
8
5
  DynamicColor,
9
- DynamicScheme,
10
- greenFromArgb,
11
- Hct,
12
- hexFromArgb,
13
- MaterialDynamicColors,
14
- redFromArgb,
6
+ DynamicScheme as DynamicScheme2,
7
+ Hct as Hct2,
8
+ MaterialDynamicColors as MaterialDynamicColors2,
15
9
  SchemeContent,
16
10
  SchemeExpressive,
17
11
  SchemeFidelity,
@@ -19,9 +13,682 @@ import {
19
13
  SchemeNeutral,
20
14
  SchemeTonalSpot,
21
15
  SchemeVibrant,
16
+ TonalPalette as TonalPalette2
17
+ } from "@material/material-color-utilities";
18
+ import { kebabCase as kebabCase4, upperFirst as upperFirst2 } from "lodash-es";
19
+
20
+ // src/lib/builder.css.ts
21
+ import {
22
+ hexFromArgb
23
+ } from "@material/material-color-utilities";
24
+ import { kebabCase } from "lodash-es";
25
+ function buildCss(ctx) {
26
+ const {
27
+ prefix,
28
+ allPalettes,
29
+ mergedColorsLight,
30
+ mergedColorsDark,
31
+ tokenToPalette,
32
+ allPaletteNamesKebab
33
+ } = ctx;
34
+ function buildRefPaletteLookup() {
35
+ const lookup = {};
36
+ for (const [name, palette] of Object.entries(allPalettes)) {
37
+ const paletteName = kebabCase(name);
38
+ for (const tone of STANDARD_TONES) {
39
+ const hex = hexFromArgb(palette.tone(tone));
40
+ if (!lookup[hex]) lookup[hex] = [];
41
+ lookup[hex].push({ paletteName, tone });
42
+ }
43
+ }
44
+ return lookup;
45
+ }
46
+ function sysColorVar(colorName, colorValue, lookup) {
47
+ const name = `--${prefix}-sys-color-${kebabCase(colorName)}`;
48
+ const hex = hexFromArgb(colorValue);
49
+ const matches = lookup[hex];
50
+ if (matches && matches.length > 0) {
51
+ const preferred = tokenToPalette[colorName] ?? deriveCustomPaletteName(colorName, allPaletteNamesKebab);
52
+ const match = (preferred ? matches.find((m) => m.paletteName === preferred) : void 0) ?? matches[0];
53
+ if (match) {
54
+ return `${name}:var(--${prefix}-ref-palette-${match.paletteName}-${match.tone});`;
55
+ }
56
+ }
57
+ return `${name}:${hex};`;
58
+ }
59
+ function toCssVars(mergedColors, lookup) {
60
+ return Object.entries(mergedColors).map(([name, value]) => sysColorVar(name, value, lookup)).join(" ");
61
+ }
62
+ function refPaletteVar(paletteName, tone, colorValue) {
63
+ const name = `--${prefix}-ref-palette-${paletteName}-${tone}`;
64
+ const value = hexFromArgb(colorValue);
65
+ return `${name}:${value};`;
66
+ }
67
+ function generateTonalPaletteVars(paletteName, palette) {
68
+ return STANDARD_TONES.map((tone) => {
69
+ const color = palette.tone(tone);
70
+ return refPaletteVar(paletteName, tone, color);
71
+ }).join(" ");
72
+ }
73
+ function generateTonalVars() {
74
+ return Object.entries(allPalettes).map(
75
+ ([name, palette]) => generateTonalPaletteVars(kebabCase(name), palette)
76
+ ).join(" ");
77
+ }
78
+ const refPaletteLookup = buildRefPaletteLookup();
79
+ const lightVars = toCssVars(mergedColorsLight, refPaletteLookup);
80
+ const darkVars = toCssVars(mergedColorsDark, refPaletteLookup);
81
+ const tonalVars = generateTonalVars();
82
+ return `
83
+ :root { ${lightVars} ${tonalVars} }
84
+ .dark { ${darkVars} ${tonalVars} }
85
+ `;
86
+ }
87
+
88
+ // src/lib/builder.figma.ts
89
+ import {
90
+ blueFromArgb,
91
+ greenFromArgb,
92
+ hexFromArgb as hexFromArgb2,
93
+ redFromArgb
94
+ } from "@material/material-color-utilities";
95
+ import { kebabCase as kebabCase2, startCase } from "lodash-es";
96
+ function buildFigmaVariables(ctx) {
97
+ const {
98
+ allPalettes,
99
+ mergedColorsLight,
100
+ mergedColorsDark,
101
+ tokenToPalette,
102
+ allPaletteNamesKebab
103
+ } = ctx;
104
+ const variables = [];
105
+ const paletteHexMap = {};
106
+ for (const [name, palette] of Object.entries(allPalettes)) {
107
+ const paletteName = startCase(name);
108
+ paletteHexMap[paletteName] = {};
109
+ for (const tone of STANDARD_TONES) {
110
+ const argb = palette.tone(tone);
111
+ const path = `ref/palette/${paletteName}/${tone}`;
112
+ const hex = hexFromArgb2(argb).toUpperCase();
113
+ paletteHexMap[paletteName][hex] = path;
114
+ const color = {
115
+ r: redFromArgb(argb) / 255,
116
+ g: greenFromArgb(argb) / 255,
117
+ b: blueFromArgb(argb) / 255,
118
+ a: 1
119
+ };
120
+ variables.push({
121
+ path,
122
+ scopes: ["ALL_SCOPES"],
123
+ values: { Light: color, Dark: color }
124
+ });
125
+ }
126
+ }
127
+ function findAlias(hex, tokenName) {
128
+ const preferredKebab = tokenToPalette[tokenName] ?? deriveCustomPaletteName(tokenName, allPaletteNamesKebab);
129
+ const preferred = preferredKebab ? startCase(preferredKebab) : void 0;
130
+ if (preferred && paletteHexMap[preferred]?.[hex]) {
131
+ return paletteHexMap[preferred][hex];
132
+ }
133
+ for (const palHexes of Object.values(paletteHexMap)) {
134
+ if (palHexes[hex]) return palHexes[hex];
135
+ }
136
+ return null;
137
+ }
138
+ function resolveValue(argb, tokenName) {
139
+ const hex = hexFromArgb2(argb).toUpperCase();
140
+ const aliasPath = findAlias(hex, tokenName);
141
+ if (aliasPath) return { alias: aliasPath };
142
+ return {
143
+ r: redFromArgb(argb) / 255,
144
+ g: greenFromArgb(argb) / 255,
145
+ b: blueFromArgb(argb) / 255,
146
+ a: 1
147
+ };
148
+ }
149
+ for (const [name, lightArgb] of Object.entries(mergedColorsLight)) {
150
+ const darkArgb = mergedColorsDark[name] ?? lightArgb;
151
+ const description = isTokenName(name) ? tokenDescriptions[name] : void 0;
152
+ variables.push({
153
+ path: `sys/color/${startCase(name)}`,
154
+ ...description ? { description } : {},
155
+ scopes: ["ALL_SCOPES"],
156
+ values: {
157
+ Light: resolveValue(lightArgb, name),
158
+ Dark: resolveValue(darkArgb, name)
159
+ }
160
+ });
161
+ }
162
+ return variables;
163
+ }
164
+ function buildFigmaTokens(ctx) {
165
+ const { prefix } = ctx;
166
+ const variables = buildFigmaVariables(ctx);
167
+ function rgbToHex(r, g, b) {
168
+ const toHex = (c) => Math.round(c * 255).toString(16).padStart(2, "0");
169
+ return `#${toHex(r)}${toHex(g)}${toHex(b)}`.toUpperCase();
170
+ }
171
+ function toDtcgValue(modeValue) {
172
+ if ("alias" in modeValue) {
173
+ return `{${modeValue.alias.replaceAll("/", ".")}}`;
174
+ }
175
+ return {
176
+ colorSpace: "srgb",
177
+ components: [modeValue.r, modeValue.g, modeValue.b],
178
+ alpha: modeValue.a,
179
+ hex: rgbToHex(modeValue.r, modeValue.g, modeValue.b)
180
+ };
181
+ }
182
+ function toDtcgExtensions(v) {
183
+ if (v.path.startsWith("ref/palette/")) {
184
+ return {
185
+ "com.figma.scopes": v.scopes ?? ["ALL_SCOPES"],
186
+ "com.figma.isOverride": true
187
+ };
188
+ }
189
+ const lastSegment = v.path.split("/").at(-1);
190
+ if (!lastSegment) return { "com.figma.scopes": v.scopes ?? ["ALL_SCOPES"] };
191
+ const tokenName = kebabCase2(lastSegment);
192
+ return {
193
+ "com.figma.scopes": v.scopes ?? ["ALL_SCOPES"],
194
+ "css.variable": `--${prefix}-sys-color-${tokenName}`
195
+ };
196
+ }
197
+ function buildToken(v, modeValue) {
198
+ return {
199
+ $type: "color",
200
+ $value: toDtcgValue(modeValue),
201
+ ...v.description ? { $description: v.description } : {},
202
+ $extensions: toDtcgExtensions(v)
203
+ };
204
+ }
205
+ function parsePath(path) {
206
+ const parts = path.split("/");
207
+ if (parts[0] === "ref" && parts[1] === "palette" && parts[2] && parts[3]) {
208
+ return {
209
+ kind: "palette",
210
+ paletteName: parts[2],
211
+ tone: parts[3]
212
+ };
213
+ }
214
+ if (parts[0] === "sys" && parts[1] === "color" && parts[2]) {
215
+ return { kind: "color", tokenName: parts[2] };
216
+ }
217
+ return null;
218
+ }
219
+ function buildModeFile(modeName) {
220
+ const palette = {};
221
+ const color = {};
222
+ for (const v of variables) {
223
+ const modeValue = v.values[modeName];
224
+ if (!modeValue) continue;
225
+ const parsed = parsePath(v.path);
226
+ if (!parsed) continue;
227
+ if (parsed.kind === "palette") {
228
+ const group = palette[parsed.paletteName] ??= {};
229
+ group[parsed.tone] = buildToken(v, modeValue);
230
+ } else {
231
+ color[parsed.tokenName] = buildToken(v, modeValue);
232
+ }
233
+ }
234
+ return {
235
+ $extensions: { "com.figma.modeName": modeName },
236
+ ref: { palette },
237
+ sys: { color }
238
+ };
239
+ }
240
+ return {
241
+ "Light.tokens.json": buildModeFile("Light"),
242
+ "Dark.tokens.json": buildModeFile("Dark")
243
+ };
244
+ }
245
+
246
+ // src/lib/builder.flutter.ts
247
+ import { hexFromArgb as hexFromArgb3 } from "@material/material-color-utilities";
248
+ import { upperFirst } from "lodash-es";
249
+ var FLUTTER_PROPERTIES = [
250
+ "primary",
251
+ "surfaceTint",
252
+ "onPrimary",
253
+ "primaryContainer",
254
+ "onPrimaryContainer",
255
+ "secondary",
256
+ "onSecondary",
257
+ "secondaryContainer",
258
+ "onSecondaryContainer",
259
+ "tertiary",
260
+ "onTertiary",
261
+ "tertiaryContainer",
262
+ "onTertiaryContainer",
263
+ "error",
264
+ "onError",
265
+ "errorContainer",
266
+ "onErrorContainer",
267
+ "background",
268
+ "onBackground",
269
+ "surface",
270
+ "onSurface",
271
+ "surfaceVariant",
272
+ "onSurfaceVariant",
273
+ "outline",
274
+ "outlineVariant",
275
+ "shadow",
276
+ "scrim",
277
+ "inverseSurface",
278
+ "inverseOnSurface",
279
+ "inversePrimary",
280
+ "primaryFixed",
281
+ "onPrimaryFixed",
282
+ "primaryFixedDim",
283
+ "onPrimaryFixedVariant",
284
+ "secondaryFixed",
285
+ "onSecondaryFixed",
286
+ "secondaryFixedDim",
287
+ "onSecondaryFixedVariant",
288
+ "tertiaryFixed",
289
+ "onTertiaryFixed",
290
+ "tertiaryFixedDim",
291
+ "onTertiaryFixedVariant",
292
+ "surfaceDim",
293
+ "surfaceBright",
294
+ "surfaceContainerLowest",
295
+ "surfaceContainerLow",
296
+ "surfaceContainer",
297
+ "surfaceContainerHigh",
298
+ "surfaceContainerHighest"
299
+ ];
300
+ var TOKEN_TO_FLUTTER = {
301
+ inverseOnSurface: "onInverseSurface"
302
+ };
303
+ function toFlutterColor(argb) {
304
+ const hex = hexFromArgb3(argb).replace("#", "").toUpperCase();
305
+ return `Color(0xFF${hex})`;
306
+ }
307
+ function flutterPropName(m3Token) {
308
+ return TOKEN_TO_FLUTTER[m3Token] ?? m3Token;
309
+ }
310
+ function buildFlutter(ctx) {
311
+ const { mergedColorsLight, mergedColorsDark, hexCustomColors } = ctx;
312
+ function buildColorScheme(name, brightness, colors) {
313
+ const lines = [];
314
+ lines.push(`const ${name} = ColorScheme(`);
315
+ lines.push(` brightness: Brightness.${brightness},`);
316
+ for (const token of FLUTTER_PROPERTIES) {
317
+ const argb = colors[token];
318
+ if (argb === void 0) continue;
319
+ lines.push(` ${flutterPropName(token)}: ${toFlutterColor(argb)},`);
320
+ }
321
+ lines.push(");");
322
+ return lines.join("\n");
323
+ }
324
+ function buildCustomColors() {
325
+ if (hexCustomColors.length === 0) return "";
326
+ const sections = [];
327
+ for (const cc of hexCustomColors) {
328
+ const ccName = cc.name;
329
+ const tokens = [
330
+ ccName,
331
+ `on${upperFirst(ccName)}`,
332
+ `${ccName}Container`,
333
+ `on${upperFirst(ccName)}Container`
334
+ ];
335
+ const lightLines = [];
336
+ const darkLines = [];
337
+ for (const token of tokens) {
338
+ const lightArgb = mergedColorsLight[token];
339
+ const darkArgb = mergedColorsDark[token];
340
+ if (lightArgb !== void 0) {
341
+ lightLines.push(
342
+ `const light${upperFirst(token)} = ${toFlutterColor(lightArgb)};`
343
+ );
344
+ }
345
+ if (darkArgb !== void 0) {
346
+ darkLines.push(
347
+ `const dark${upperFirst(token)} = ${toFlutterColor(darkArgb)};`
348
+ );
349
+ }
350
+ }
351
+ sections.push([...lightLines, ...darkLines].join("\n"));
352
+ }
353
+ return "\n\n" + sections.join("\n\n");
354
+ }
355
+ const header = "import 'package:flutter/material.dart';";
356
+ const light = buildColorScheme(
357
+ "lightColorScheme",
358
+ "light",
359
+ mergedColorsLight
360
+ );
361
+ const dark = buildColorScheme("darkColorScheme", "dark", mergedColorsDark);
362
+ const custom = buildCustomColors();
363
+ return `${header}
364
+
365
+ ${light}
366
+
367
+ ${dark}${custom}
368
+ `;
369
+ }
370
+
371
+ // src/lib/builder.json.ts
372
+ import {
373
+ argbFromHex,
374
+ DynamicScheme,
375
+ Hct,
376
+ hexFromArgb as hexFromArgb4,
377
+ MaterialDynamicColors,
22
378
  TonalPalette
23
379
  } from "@material/material-color-utilities";
24
- import { kebabCase, startCase, upperFirst } from "lodash-es";
380
+ var MTB_TONES = [
381
+ 0,
382
+ 5,
383
+ 10,
384
+ 15,
385
+ 20,
386
+ 25,
387
+ 30,
388
+ 35,
389
+ 40,
390
+ 50,
391
+ 60,
392
+ 70,
393
+ 80,
394
+ 90,
395
+ 95,
396
+ 98,
397
+ 99,
398
+ 100
399
+ ];
400
+ var FIXTURE_TOKEN_ORDER = [
401
+ "primary",
402
+ "surfaceTint",
403
+ "onPrimary",
404
+ "primaryContainer",
405
+ "onPrimaryContainer",
406
+ "secondary",
407
+ "onSecondary",
408
+ "secondaryContainer",
409
+ "onSecondaryContainer",
410
+ "tertiary",
411
+ "onTertiary",
412
+ "tertiaryContainer",
413
+ "onTertiaryContainer",
414
+ "error",
415
+ "onError",
416
+ "errorContainer",
417
+ "onErrorContainer",
418
+ "background",
419
+ "onBackground",
420
+ "surface",
421
+ "onSurface",
422
+ "surfaceVariant",
423
+ "onSurfaceVariant",
424
+ "outline",
425
+ "outlineVariant",
426
+ "shadow",
427
+ "scrim",
428
+ "inverseSurface",
429
+ "inverseOnSurface",
430
+ "inversePrimary",
431
+ "primaryFixed",
432
+ "onPrimaryFixed",
433
+ "primaryFixedDim",
434
+ "onPrimaryFixedVariant",
435
+ "secondaryFixed",
436
+ "onSecondaryFixed",
437
+ "secondaryFixedDim",
438
+ "onSecondaryFixedVariant",
439
+ "tertiaryFixed",
440
+ "onTertiaryFixed",
441
+ "tertiaryFixedDim",
442
+ "onTertiaryFixedVariant",
443
+ "surfaceDim",
444
+ "surfaceBright",
445
+ "surfaceContainerLowest",
446
+ "surfaceContainerLow",
447
+ "surfaceContainer",
448
+ "surfaceContainerHigh",
449
+ "surfaceContainerHighest"
450
+ ];
451
+ function buildJson(ctx) {
452
+ const {
453
+ hexSource,
454
+ sourceHct,
455
+ effectiveSourceArgb,
456
+ primaryHct,
457
+ SchemeClass,
458
+ scheme,
459
+ primary,
460
+ secondary,
461
+ tertiary,
462
+ error,
463
+ neutral,
464
+ neutralVariant,
465
+ hexCustomColors
466
+ } = ctx;
467
+ const neuHct = neutral ? Hct.fromInt(argbFromHex(neutral)) : sourceHct;
468
+ const nvHct = neutralVariant ? Hct.fromInt(argbFromHex(neutralVariant)) : sourceHct;
469
+ const rawPalettes = {
470
+ primary: TonalPalette.fromInt(effectiveSourceArgb),
471
+ secondary: secondary ? TonalPalette.fromInt(argbFromHex(secondary)) : TonalPalette.fromHueAndChroma(sourceHct.hue, sourceHct.chroma / 3),
472
+ tertiary: tertiary ? TonalPalette.fromInt(argbFromHex(tertiary)) : TonalPalette.fromHueAndChroma(
473
+ (sourceHct.hue + 60) % 360,
474
+ sourceHct.chroma / 2
475
+ ),
476
+ neutral: TonalPalette.fromHueAndChroma(
477
+ neuHct.hue,
478
+ Math.min(neuHct.chroma / 12, 4)
479
+ ),
480
+ "neutral-variant": TonalPalette.fromHueAndChroma(
481
+ nvHct.hue,
482
+ Math.min(nvHct.chroma / 6, 8)
483
+ )
484
+ };
485
+ function buildJsonSchemes() {
486
+ function extractSchemeColors(scheme2, backgroundScheme) {
487
+ const colors = {};
488
+ for (const tokenName of FIXTURE_TOKEN_ORDER) {
489
+ const dynamicColor = MaterialDynamicColors[tokenName];
490
+ const useScheme = backgroundScheme && (tokenName === "background" || tokenName === "onBackground") ? backgroundScheme : scheme2;
491
+ colors[tokenName] = hexFromArgb4(
492
+ dynamicColor.getArgb(useScheme)
493
+ ).toUpperCase();
494
+ }
495
+ return colors;
496
+ }
497
+ function resolveOverridePalette(hex, role) {
498
+ if (!hex) return null;
499
+ return new SchemeClass(Hct.fromInt(argbFromHex(hex)), false, 0)[role];
500
+ }
501
+ const secPalette = resolveOverridePalette(secondary, "primaryPalette");
502
+ const terPalette = resolveOverridePalette(tertiary, "primaryPalette");
503
+ const errPalette = resolveOverridePalette(error, "primaryPalette");
504
+ const neuPalette = resolveOverridePalette(neutral, "neutralPalette");
505
+ const nvPalette = resolveOverridePalette(
506
+ neutralVariant,
507
+ "neutralVariantPalette"
508
+ );
509
+ const jsonSchemes = {};
510
+ const jsonContrastLevels = [
511
+ { name: "light", isDark: false, contrast: 0 },
512
+ { name: "light-medium-contrast", isDark: false, contrast: 0.5 },
513
+ { name: "light-high-contrast", isDark: false, contrast: 1 },
514
+ { name: "dark", isDark: true, contrast: 0 },
515
+ { name: "dark-medium-contrast", isDark: true, contrast: 0.5 },
516
+ { name: "dark-high-contrast", isDark: true, contrast: 1 }
517
+ ];
518
+ for (const { name, isDark, contrast } of jsonContrastLevels) {
519
+ const baseScheme = new SchemeClass(primaryHct, isDark, contrast);
520
+ const composedScheme = new DynamicScheme({
521
+ sourceColorArgb: effectiveSourceArgb,
522
+ variant: schemeToVariant[scheme],
523
+ contrastLevel: contrast,
524
+ isDark,
525
+ primaryPalette: baseScheme.primaryPalette,
526
+ secondaryPalette: secPalette || baseScheme.secondaryPalette,
527
+ tertiaryPalette: terPalette || baseScheme.tertiaryPalette,
528
+ neutralPalette: neuPalette || baseScheme.neutralPalette,
529
+ neutralVariantPalette: nvPalette || baseScheme.neutralVariantPalette
530
+ });
531
+ if (errPalette) composedScheme.errorPalette = errPalette;
532
+ jsonSchemes[name] = extractSchemeColors(composedScheme, baseScheme);
533
+ }
534
+ return jsonSchemes;
535
+ }
536
+ function rawPalettesToJson() {
537
+ const jsonPalettes = {};
538
+ const RAW_PALETTE_NAMES = [
539
+ "primary",
540
+ "secondary",
541
+ "tertiary",
542
+ "neutral",
543
+ "neutral-variant"
544
+ ];
545
+ for (const name of RAW_PALETTE_NAMES) {
546
+ const palette = rawPalettes[name];
547
+ const tones = {};
548
+ for (const tone of MTB_TONES) {
549
+ tones[tone.toString()] = hexFromArgb4(palette.tone(tone)).toUpperCase();
550
+ }
551
+ jsonPalettes[name] = tones;
552
+ }
553
+ return jsonPalettes;
554
+ }
555
+ function buildCoreColors(opts) {
556
+ const colors = { primary: opts.primary };
557
+ if (opts.secondary) colors.secondary = opts.secondary.toUpperCase();
558
+ if (opts.tertiary) colors.tertiary = opts.tertiary.toUpperCase();
559
+ if (opts.error) colors.error = opts.error.toUpperCase();
560
+ if (opts.neutral) colors.neutral = opts.neutral.toUpperCase();
561
+ if (opts.neutralVariant)
562
+ colors.neutralVariant = opts.neutralVariant.toUpperCase();
563
+ return colors;
564
+ }
565
+ const seed = hexSource.toUpperCase();
566
+ const coreColors = buildCoreColors({
567
+ primary: (primary || hexSource).toUpperCase(),
568
+ secondary,
569
+ tertiary,
570
+ error,
571
+ neutral,
572
+ neutralVariant
573
+ });
574
+ const extendedColors = hexCustomColors.map((c) => ({
575
+ name: c.name,
576
+ color: c.hex.toUpperCase(),
577
+ description: "",
578
+ harmonized: c.blend ?? DEFAULT_BLEND
579
+ }));
580
+ return {
581
+ seed,
582
+ coreColors,
583
+ extendedColors,
584
+ schemes: buildJsonSchemes(),
585
+ palettes: rawPalettesToJson()
586
+ };
587
+ }
588
+
589
+ // src/lib/builder.tailwind.ts
590
+ import { kebabCase as kebabCase3 } from "lodash-es";
591
+ var SHADE_TO_TONE = [
592
+ [50, 95],
593
+ [100, 90],
594
+ [200, 80],
595
+ [300, 70],
596
+ [400, 60],
597
+ [500, 50],
598
+ [600, 40],
599
+ [700, 30],
600
+ [800, 20],
601
+ [900, 10],
602
+ [950, 5]
603
+ ];
604
+ var CORE_PALETTES = [
605
+ "primary",
606
+ "secondary",
607
+ "tertiary",
608
+ "error",
609
+ "neutral",
610
+ "neutral-variant"
611
+ ];
612
+ var SHADCN_MAPPING = [
613
+ ["--background", "surface"],
614
+ ["--foreground", "on-surface"],
615
+ ["--card", "surface-container-low"],
616
+ ["--card-foreground", "on-surface"],
617
+ ["--popover", "surface-container-high"],
618
+ ["--popover-foreground", "on-surface"],
619
+ ["--primary", "primary"],
620
+ ["--primary-foreground", "on-primary"],
621
+ ["--secondary", "secondary-container"],
622
+ ["--secondary-foreground", "on-secondary-container"],
623
+ ["--muted", "surface-container-highest"],
624
+ ["--muted-foreground", "on-surface-variant"],
625
+ ["--accent", "secondary-container"],
626
+ ["--accent-foreground", "on-secondary-container"],
627
+ ["--destructive", "error"],
628
+ ["--border", "outline-variant"],
629
+ ["--input", "outline"],
630
+ ["--ring", "primary"],
631
+ ["--chart-1", "primary-fixed"],
632
+ ["--chart-2", "secondary-fixed"],
633
+ ["--chart-3", "tertiary-fixed"],
634
+ ["--chart-4", "primary-fixed-dim"],
635
+ ["--chart-5", "secondary-fixed-dim"],
636
+ ["--sidebar", "surface-container-low"],
637
+ ["--sidebar-foreground", "on-surface"],
638
+ ["--sidebar-primary", "primary"],
639
+ ["--sidebar-primary-foreground", "on-primary"],
640
+ ["--sidebar-accent", "secondary-container"],
641
+ ["--sidebar-accent-foreground", "on-secondary-container"],
642
+ ["--sidebar-border", "outline-variant"],
643
+ ["--sidebar-ring", "primary"]
644
+ ];
645
+ function buildTailwind(ctx, options) {
646
+ const { prefix, mergedColorsLight, hexCustomColors } = ctx;
647
+ const lines = [];
648
+ for (const name of Object.keys(mergedColorsLight)) {
649
+ const kebab = kebabCase3(name);
650
+ lines.push(`--color-${kebab}: var(--${prefix}-sys-color-${kebab});`);
651
+ }
652
+ lines.push("");
653
+ lines.push("/* Shades */");
654
+ for (const palette of CORE_PALETTES) {
655
+ lines.push("");
656
+ for (const [shade, tone] of SHADE_TO_TONE) {
657
+ lines.push(
658
+ `--color-${palette}-${shade}: var(--${prefix}-ref-palette-${palette}-${tone});`
659
+ );
660
+ }
661
+ }
662
+ if (hexCustomColors.length > 0) {
663
+ for (const customColor of hexCustomColors) {
664
+ const kebab = kebabCase3(customColor.name);
665
+ lines.push("");
666
+ for (const [shade, tone] of SHADE_TO_TONE) {
667
+ lines.push(
668
+ `--color-${kebab}-${shade}: var(--${prefix}-ref-palette-${kebab}-${tone});`
669
+ );
670
+ }
671
+ }
672
+ }
673
+ let output = `@theme inline {
674
+ ${lines.join("\n ")}
675
+ }
676
+ `;
677
+ if (options?.shadcn) {
678
+ const shadcnLines = SHADCN_MAPPING.map(
679
+ ([shadcnVar, m3Token]) => `${shadcnVar}: var(--${prefix}-sys-color-${m3Token});`
680
+ );
681
+ output += `
682
+ :root,
683
+ .dark {
684
+ ${shadcnLines.join("\n ")}
685
+ }
686
+ `;
687
+ }
688
+ return output;
689
+ }
690
+
691
+ // src/lib/builder.ts
25
692
  var schemesMap = {
26
693
  tonalSpot: SchemeTonalSpot,
27
694
  monochrome: SchemeMonochrome,
@@ -66,26 +733,6 @@ var STANDARD_TONES = [
66
733
  99,
67
734
  100
68
735
  ];
69
- var MTB_TONES = [
70
- 0,
71
- 5,
72
- 10,
73
- 15,
74
- 20,
75
- 25,
76
- 30,
77
- 35,
78
- 40,
79
- 50,
80
- 60,
81
- 70,
82
- 80,
83
- 90,
84
- 95,
85
- 98,
86
- 99,
87
- 100
88
- ];
89
736
  var Variant = {
90
737
  MONOCHROME: 0,
91
738
  NEUTRAL: 1,
@@ -157,9 +804,21 @@ var tokenDescriptions = {
157
804
  tertiaryFixed: "Fixed tertiary color that stays the same in light and dark themes.",
158
805
  tertiaryFixedDim: "Dimmed variant of the fixed tertiary color for lower emphasis."
159
806
  };
160
- var tokenNames = Object.keys(
161
- tokenDescriptions
162
- );
807
+ function isTokenName(key) {
808
+ return key in tokenDescriptions;
809
+ }
810
+ var tokenNames = Object.keys(tokenDescriptions).filter(isTokenName);
811
+ function deriveCustomPaletteName(tokenName, allPaletteNamesKebab) {
812
+ let baseName = tokenName;
813
+ if (/^on[A-Z]/.test(baseName) && baseName.length > 2) {
814
+ baseName = baseName.charAt(2).toLowerCase() + baseName.slice(3);
815
+ }
816
+ if (baseName.endsWith("Container")) {
817
+ baseName = baseName.slice(0, -"Container".length);
818
+ }
819
+ const kebab = kebabCase4(baseName);
820
+ return allPaletteNamesKebab.has(kebab) ? kebab : void 0;
821
+ }
163
822
  function toRecord(arr, getEntry) {
164
823
  return Object.fromEntries(arr.map(getEntry));
165
824
  }
@@ -174,58 +833,55 @@ function getPalette(palettes, colorName) {
174
833
  }
175
834
  function mergeBaseAndCustomColors(scheme, customColors, colorPalettes) {
176
835
  const baseVars = toRecord(tokenNames, (tokenName) => {
177
- const dynamicColor = MaterialDynamicColors[tokenName];
836
+ const dynamicColor = MaterialDynamicColors2[tokenName];
178
837
  const argb = dynamicColor.getArgb(scheme);
179
838
  return [tokenName, argb];
180
839
  });
181
840
  const customVars = {};
182
841
  customColors.forEach((color) => {
183
842
  const colorname = color.name;
184
- const getPaletteForColor = (s) => getPalette(colorPalettes, colorname);
185
- const getTone = (baseTone) => (_s) => {
186
- return baseTone;
187
- };
843
+ const getPaletteForColor = () => getPalette(colorPalettes, colorname);
188
844
  const colorDynamicColor = new DynamicColor(
189
845
  colorname,
190
846
  getPaletteForColor,
191
- (s) => getTone(s.isDark ? 80 : 40)(s),
847
+ (s) => s.isDark ? 80 : 40,
192
848
  // Main color: lighter in dark mode, darker in light mode
193
849
  true
194
850
  // background
195
851
  );
196
852
  const onColorDynamicColor = new DynamicColor(
197
- `on${upperFirst(colorname)}`,
853
+ `on${upperFirst2(colorname)}`,
198
854
  getPaletteForColor,
199
- (s) => getTone(s.isDark ? 20 : 100)(s),
855
+ (s) => s.isDark ? 20 : 100,
200
856
  // Text on main color: high contrast (dark on light, light on dark)
201
857
  false
202
858
  );
203
859
  const containerDynamicColor = new DynamicColor(
204
860
  `${colorname}Container`,
205
861
  getPaletteForColor,
206
- (s) => getTone(s.isDark ? 30 : 90)(s),
862
+ (s) => s.isDark ? 30 : 90,
207
863
  // Container: subtle variant (darker in dark mode, lighter in light mode)
208
864
  true
209
865
  // background
210
866
  );
211
867
  const onContainerDynamicColor = new DynamicColor(
212
- `on${upperFirst(colorname)}Container`,
868
+ `on${upperFirst2(colorname)}Container`,
213
869
  getPaletteForColor,
214
- (s) => getTone(s.isDark ? 90 : 30)(s),
870
+ (s) => s.isDark ? 90 : 30,
215
871
  // Text on container: high contrast against container background
216
872
  false
217
873
  );
218
874
  customVars[colorname] = colorDynamicColor.getArgb(scheme);
219
- customVars[`on${upperFirst(colorname)}`] = onColorDynamicColor.getArgb(scheme);
875
+ customVars[`on${upperFirst2(colorname)}`] = onColorDynamicColor.getArgb(scheme);
220
876
  customVars[`${colorname}Container`] = containerDynamicColor.getArgb(scheme);
221
- customVars[`on${upperFirst(colorname)}Container`] = onContainerDynamicColor.getArgb(scheme);
877
+ customVars[`on${upperFirst2(colorname)}Container`] = onContainerDynamicColor.getArgb(scheme);
222
878
  });
223
879
  return { ...baseVars, ...customVars };
224
880
  }
225
881
  function createColorPalette(colorDef, baseScheme, effectiveSourceForHarmonization) {
226
- const colorArgb = argbFromHex(colorDef.hex);
882
+ const colorArgb = argbFromHex2(colorDef.hex);
227
883
  const harmonizedArgb = colorDef.blend ? Blend.harmonize(colorArgb, effectiveSourceForHarmonization) : colorArgb;
228
- const hct = Hct.fromInt(harmonizedArgb);
884
+ const hct = Hct2.fromInt(harmonizedArgb);
229
885
  let targetChroma;
230
886
  if (colorDef.core && colorDef.chromaSource) {
231
887
  if (colorDef.chromaSource === "neutral") {
@@ -238,7 +894,25 @@ function createColorPalette(colorDef, baseScheme, effectiveSourceForHarmonizatio
238
894
  } else {
239
895
  targetChroma = baseScheme.primaryPalette.chroma;
240
896
  }
241
- return TonalPalette.fromHueAndChroma(hct.hue, targetChroma);
897
+ return TonalPalette2.fromHueAndChroma(hct.hue, targetChroma);
898
+ }
899
+ function buildTokenToPaletteMap(schemePalettes, scheme) {
900
+ const result = {};
901
+ for (const propName of Object.getOwnPropertyNames(MaterialDynamicColors2)) {
902
+ const dc = Object.getOwnPropertyDescriptor(
903
+ MaterialDynamicColors2,
904
+ propName
905
+ )?.value;
906
+ if (!(dc instanceof DynamicColor)) continue;
907
+ const palette = dc.palette(scheme);
908
+ for (const [palName, pal] of schemePalettes) {
909
+ if (palette === pal) {
910
+ result[propName] = palName;
911
+ break;
912
+ }
913
+ }
914
+ }
915
+ return result;
242
916
  }
243
917
  function builder(hexSource, {
244
918
  scheme = DEFAULT_SCHEME,
@@ -252,13 +926,13 @@ function builder(hexSource, {
252
926
  customColors: hexCustomColors = DEFAULT_CUSTOM_COLORS,
253
927
  prefix = DEFAULT_PREFIX
254
928
  } = {}) {
255
- const sourceArgb = argbFromHex(hexSource);
256
- const sourceHct = Hct.fromInt(sourceArgb);
929
+ const sourceArgb = argbFromHex2(hexSource);
930
+ const sourceHct = Hct2.fromInt(sourceArgb);
257
931
  const effectiveSource = primary || hexSource;
258
- const effectiveSourceArgb = argbFromHex(effectiveSource);
259
- const effectiveSourceForHarmonization = primary ? argbFromHex(primary) : sourceArgb;
932
+ const effectiveSourceArgb = argbFromHex2(effectiveSource);
933
+ const effectiveSourceForHarmonization = primary ? argbFromHex2(primary) : sourceArgb;
260
934
  const SchemeClass = schemesMap[scheme];
261
- const primaryHct = Hct.fromInt(effectiveSourceArgb);
935
+ const primaryHct = Hct2.fromInt(effectiveSourceArgb);
262
936
  const baseScheme = new SchemeClass(primaryHct, false, contrast);
263
937
  const allColors = [
264
938
  // Core colors (hex may be undefined)
@@ -323,8 +997,8 @@ function builder(hexSource, {
323
997
  neutralPalette: colorPalettes["neutral"] || baseScheme.neutralPalette,
324
998
  neutralVariantPalette: colorPalettes["neutralVariant"] || baseScheme.neutralVariantPalette
325
999
  };
326
- const lightScheme = new DynamicScheme({ ...schemeConfig, isDark: false });
327
- const darkScheme = new DynamicScheme({ ...schemeConfig, isDark: true });
1000
+ const lightScheme = new DynamicScheme2({ ...schemeConfig, isDark: false });
1001
+ const darkScheme = new DynamicScheme2({ ...schemeConfig, isDark: true });
328
1002
  const errorPalette = colorPalettes["error"];
329
1003
  if (errorPalette) {
330
1004
  lightScheme.errorPalette = errorPalette;
@@ -345,7 +1019,7 @@ function builder(hexSource, {
345
1019
  const customColors = definedColors.filter((c) => !c.core).map((c) => ({
346
1020
  name: c.name,
347
1021
  blend: c.blend ?? DEFAULT_BLEND,
348
- value: argbFromHex(c.hex)
1022
+ value: argbFromHex2(c.hex)
349
1023
  }));
350
1024
  const mergedColorsLight = mergeBaseAndCustomColors(
351
1025
  lightScheme,
@@ -365,524 +1039,41 @@ function builder(hexSource, {
365
1039
  ["neutral", lightScheme.neutralPalette],
366
1040
  ["neutral-variant", lightScheme.neutralVariantPalette]
367
1041
  ];
368
- function buildTokenToPaletteMap(schemePalettes2, scheme2) {
369
- const result = {};
370
- for (const propName of Object.getOwnPropertyNames(MaterialDynamicColors)) {
371
- const dc = MaterialDynamicColors[propName];
372
- if (!(dc instanceof DynamicColor)) continue;
373
- const palette = dc.palette(scheme2);
374
- for (const [palName, pal] of schemePalettes2) {
375
- if (palette === pal) {
376
- result[propName] = palName;
377
- break;
378
- }
379
- }
380
- }
381
- return result;
382
- }
383
1042
  const tokenToPalette = buildTokenToPaletteMap(schemePalettes, lightScheme);
384
- const allPaletteNamesKebab = new Set(Object.keys(allPalettes).map(kebabCase));
385
- function deriveCustomPaletteName(tokenName) {
386
- let baseName = tokenName;
387
- if (/^on[A-Z]/.test(baseName) && baseName.length > 2) {
388
- baseName = baseName.charAt(2).toLowerCase() + baseName.slice(3);
389
- }
390
- if (baseName.endsWith("Container")) {
391
- baseName = baseName.slice(0, -"Container".length);
392
- }
393
- const kebab = kebabCase(baseName);
394
- return allPaletteNamesKebab.has(kebab) ? kebab : void 0;
395
- }
1043
+ const allPaletteNamesKebab = new Set(Object.keys(allPalettes).map(kebabCase4));
1044
+ const ctx = {
1045
+ hexSource,
1046
+ prefix,
1047
+ scheme,
1048
+ primary,
1049
+ secondary,
1050
+ tertiary,
1051
+ neutral,
1052
+ neutralVariant,
1053
+ error,
1054
+ hexCustomColors,
1055
+ sourceHct,
1056
+ effectiveSourceArgb,
1057
+ primaryHct,
1058
+ SchemeClass,
1059
+ allPalettes,
1060
+ mergedColorsLight,
1061
+ mergedColorsDark,
1062
+ tokenToPalette,
1063
+ allPaletteNamesKebab
1064
+ };
396
1065
  return {
397
- //
398
- // ██████ ███████ ███████
399
- // ██ ██ ██
400
- // ██ ███████ ███████
401
- // ██ ██ ██
402
- // ██████ ███████ ███████
403
- //
404
- toCss() {
405
- function buildRefPaletteLookup() {
406
- const lookup = {};
407
- for (const [name, palette] of Object.entries(allPalettes)) {
408
- const paletteName = kebabCase(name);
409
- for (const tone of STANDARD_TONES) {
410
- const hex = hexFromArgb(palette.tone(tone));
411
- if (!lookup[hex]) lookup[hex] = [];
412
- lookup[hex].push({ paletteName, tone });
413
- }
414
- }
415
- return lookup;
416
- }
417
- function sysColorVar(colorName, colorValue, lookup) {
418
- const name = `--${prefix}-sys-color-${kebabCase(colorName)}`;
419
- const hex = hexFromArgb(colorValue);
420
- const matches = lookup[hex];
421
- if (matches && matches.length > 0) {
422
- const preferred = tokenToPalette[colorName] ?? deriveCustomPaletteName(colorName);
423
- const match = (preferred ? matches.find((m) => m.paletteName === preferred) : void 0) ?? matches[0];
424
- return `${name}:var(--${prefix}-ref-palette-${match.paletteName}-${match.tone});`;
425
- }
426
- return `${name}:${hex};`;
427
- }
428
- function toCssVars(mergedColors, lookup) {
429
- return Object.entries(mergedColors).map(([name, value]) => sysColorVar(name, value, lookup)).join(" ");
430
- }
431
- function refPaletteVar(paletteName, tone, colorValue) {
432
- const name = `--${prefix}-ref-palette-${paletteName}-${tone}`;
433
- const value = hexFromArgb(colorValue);
434
- return `${name}:${value};`;
435
- }
436
- function generateTonalPaletteVars(paletteName, palette) {
437
- return STANDARD_TONES.map((tone) => {
438
- const color = palette.tone(tone);
439
- return refPaletteVar(paletteName, tone, color);
440
- }).join(" ");
441
- }
442
- function generateTonalVars() {
443
- return Object.entries(allPalettes).map(
444
- ([name, palette]) => generateTonalPaletteVars(kebabCase(name), palette)
445
- ).join(" ");
446
- }
447
- const refPaletteLookup = buildRefPaletteLookup();
448
- const lightVars = toCssVars(mergedColorsLight, refPaletteLookup);
449
- const darkVars = toCssVars(mergedColorsDark, refPaletteLookup);
450
- const tonalVars = generateTonalVars();
451
- return `
452
- :root { ${lightVars} ${tonalVars} }
453
- .dark { ${darkVars} ${tonalVars} }
454
- `;
455
- },
456
- //
457
- // ██ ███████ ██████ ███ ██
458
- // ██ ██ ██ ██ ████ ██
459
- // ██ ███████ ██ ██ ██ ██ ██
460
- // ██ ██ ██ ██ ██ ██ ██ ██
461
- // █████ ███████ ██████ ██ ████
462
- //
463
- toJson() {
464
- const fixtureTokenOrder = [
465
- "primary",
466
- "surfaceTint",
467
- "onPrimary",
468
- "primaryContainer",
469
- "onPrimaryContainer",
470
- "secondary",
471
- "onSecondary",
472
- "secondaryContainer",
473
- "onSecondaryContainer",
474
- "tertiary",
475
- "onTertiary",
476
- "tertiaryContainer",
477
- "onTertiaryContainer",
478
- "error",
479
- "onError",
480
- "errorContainer",
481
- "onErrorContainer",
482
- "background",
483
- "onBackground",
484
- "surface",
485
- "onSurface",
486
- "surfaceVariant",
487
- "onSurfaceVariant",
488
- "outline",
489
- "outlineVariant",
490
- "shadow",
491
- "scrim",
492
- "inverseSurface",
493
- "inverseOnSurface",
494
- "inversePrimary",
495
- "primaryFixed",
496
- "onPrimaryFixed",
497
- "primaryFixedDim",
498
- "onPrimaryFixedVariant",
499
- "secondaryFixed",
500
- "onSecondaryFixed",
501
- "secondaryFixedDim",
502
- "onSecondaryFixedVariant",
503
- "tertiaryFixed",
504
- "onTertiaryFixed",
505
- "tertiaryFixedDim",
506
- "onTertiaryFixedVariant",
507
- "surfaceDim",
508
- "surfaceBright",
509
- "surfaceContainerLowest",
510
- "surfaceContainerLow",
511
- "surfaceContainer",
512
- "surfaceContainerHigh",
513
- "surfaceContainerHighest"
514
- ];
515
- const neuHct = neutral ? Hct.fromInt(argbFromHex(neutral)) : sourceHct;
516
- const nvHct = neutralVariant ? Hct.fromInt(argbFromHex(neutralVariant)) : sourceHct;
517
- const rawPalettes = {
518
- primary: TonalPalette.fromInt(effectiveSourceArgb),
519
- secondary: secondary ? TonalPalette.fromInt(argbFromHex(secondary)) : TonalPalette.fromHueAndChroma(sourceHct.hue, sourceHct.chroma / 3),
520
- tertiary: tertiary ? TonalPalette.fromInt(argbFromHex(tertiary)) : TonalPalette.fromHueAndChroma(
521
- (sourceHct.hue + 60) % 360,
522
- sourceHct.chroma / 2
523
- ),
524
- neutral: TonalPalette.fromHueAndChroma(
525
- neuHct.hue,
526
- Math.min(neuHct.chroma / 12, 4)
527
- ),
528
- "neutral-variant": TonalPalette.fromHueAndChroma(
529
- nvHct.hue,
530
- Math.min(nvHct.chroma / 6, 8)
531
- )
532
- };
533
- function buildJsonSchemes() {
534
- function extractSchemeColors(scheme2, backgroundScheme) {
535
- const colors = {};
536
- for (const tokenName of fixtureTokenOrder) {
537
- const dynamicColor = MaterialDynamicColors[tokenName];
538
- const useScheme = backgroundScheme && (tokenName === "background" || tokenName === "onBackground") ? backgroundScheme : scheme2;
539
- colors[tokenName] = hexFromArgb(
540
- dynamicColor.getArgb(useScheme)
541
- ).toUpperCase();
542
- }
543
- return colors;
544
- }
545
- function resolveOverridePalette(hex, role) {
546
- if (!hex) return null;
547
- return new SchemeClass(Hct.fromInt(argbFromHex(hex)), false, 0)[role];
548
- }
549
- const secPalette = resolveOverridePalette(secondary, "primaryPalette");
550
- const terPalette = resolveOverridePalette(tertiary, "primaryPalette");
551
- const errPalette = resolveOverridePalette(error, "primaryPalette");
552
- const neuPalette = resolveOverridePalette(neutral, "neutralPalette");
553
- const nvPalette = resolveOverridePalette(
554
- neutralVariant,
555
- "neutralVariantPalette"
556
- );
557
- const jsonSchemes = {};
558
- const jsonContrastLevels = [
559
- { name: "light", isDark: false, contrast: 0 },
560
- { name: "light-medium-contrast", isDark: false, contrast: 0.5 },
561
- { name: "light-high-contrast", isDark: false, contrast: 1 },
562
- { name: "dark", isDark: true, contrast: 0 },
563
- { name: "dark-medium-contrast", isDark: true, contrast: 0.5 },
564
- { name: "dark-high-contrast", isDark: true, contrast: 1 }
565
- ];
566
- for (const { name, isDark, contrast: contrast2 } of jsonContrastLevels) {
567
- const baseScheme2 = new SchemeClass(primaryHct, isDark, contrast2);
568
- const composedScheme = new DynamicScheme({
569
- sourceColorArgb: effectiveSourceArgb,
570
- variant: schemeToVariant[scheme],
571
- contrastLevel: contrast2,
572
- isDark,
573
- primaryPalette: baseScheme2.primaryPalette,
574
- secondaryPalette: secPalette || baseScheme2.secondaryPalette,
575
- tertiaryPalette: terPalette || baseScheme2.tertiaryPalette,
576
- neutralPalette: neuPalette || baseScheme2.neutralPalette,
577
- neutralVariantPalette: nvPalette || baseScheme2.neutralVariantPalette
578
- });
579
- if (errPalette) composedScheme.errorPalette = errPalette;
580
- jsonSchemes[name] = extractSchemeColors(composedScheme, baseScheme2);
581
- }
582
- return jsonSchemes;
583
- }
584
- function rawPalettesToJson() {
585
- const jsonPalettes = {};
586
- const RAW_PALETTE_NAMES = [
587
- "primary",
588
- "secondary",
589
- "tertiary",
590
- "neutral",
591
- "neutral-variant"
592
- ];
593
- for (const name of RAW_PALETTE_NAMES) {
594
- const palette = rawPalettes[name];
595
- const tones = {};
596
- for (const tone of MTB_TONES) {
597
- tones[tone.toString()] = hexFromArgb(
598
- palette.tone(tone)
599
- ).toUpperCase();
600
- }
601
- jsonPalettes[name] = tones;
602
- }
603
- return jsonPalettes;
604
- }
605
- function buildCoreColors(opts) {
606
- const colors = { primary: opts.primary };
607
- if (opts.secondary) colors.secondary = opts.secondary.toUpperCase();
608
- if (opts.tertiary) colors.tertiary = opts.tertiary.toUpperCase();
609
- if (opts.error) colors.error = opts.error.toUpperCase();
610
- if (opts.neutral) colors.neutral = opts.neutral.toUpperCase();
611
- if (opts.neutralVariant)
612
- colors.neutralVariant = opts.neutralVariant.toUpperCase();
613
- return colors;
614
- }
615
- const seed = hexSource.toUpperCase();
616
- const coreColors = buildCoreColors({
617
- primary: (primary || hexSource).toUpperCase(),
618
- secondary,
619
- tertiary,
620
- error,
621
- neutral,
622
- neutralVariant
623
- });
624
- const extendedColors = hexCustomColors.map((c) => ({
625
- name: c.name,
626
- color: c.hex.toUpperCase(),
627
- description: "",
628
- harmonized: c.blend ?? DEFAULT_BLEND
629
- }));
630
- return {
631
- seed,
632
- coreColors,
633
- extendedColors,
634
- schemes: buildJsonSchemes(),
635
- palettes: rawPalettesToJson()
636
- };
637
- },
638
- //
639
- // ███████ ██ ██████ ███ ███ █████
640
- // ██ ██ ██ ████ ████ ██ ██
641
- // █████ ██ ██ ███ ██ ████ ██ ███████
642
- // ██ ██ ██ ██ ██ ██ ██ ██ ██
643
- // ██ ██ ██████ ██ ██ ██ ██
644
- //
645
- toFigmaTokens() {
646
- function argbToFigmaColorValue(argb) {
647
- return {
648
- colorSpace: "srgb",
649
- components: [
650
- redFromArgb(argb) / 255,
651
- greenFromArgb(argb) / 255,
652
- blueFromArgb(argb) / 255
653
- ],
654
- alpha: 1,
655
- hex: hexFromArgb(argb).toUpperCase()
656
- };
657
- }
658
- function figmaToken(argb) {
659
- return {
660
- $type: "color",
661
- $value: argbToFigmaColorValue(argb),
662
- $extensions: {
663
- "com.figma.scopes": ["ALL_SCOPES"],
664
- "com.figma.isOverride": true
665
- }
666
- };
667
- }
668
- function buildRefPaletteTokens() {
669
- const palettes = {};
670
- for (const [name, palette] of Object.entries(allPalettes)) {
671
- const tones = {};
672
- for (const tone of STANDARD_TONES) {
673
- const argb = palette.tone(tone);
674
- tones[tone.toString()] = figmaToken(argb);
675
- }
676
- palettes[startCase(name)] = tones;
677
- }
678
- return palettes;
679
- }
680
- function findToneInPalette(hex, paletteName, tones) {
681
- for (const [tone, token] of Object.entries(tones)) {
682
- if (token.$value.hex === hex) {
683
- return `{ref.palette.${paletteName}.${tone}}`;
684
- }
685
- }
686
- return null;
687
- }
688
- function findAlias(hex, tokenName, refPalettes2) {
689
- const preferredPaletteKebab = tokenToPalette[tokenName] ?? deriveCustomPaletteName(tokenName);
690
- const preferredPalette = preferredPaletteKebab ? startCase(preferredPaletteKebab) : void 0;
691
- if (preferredPalette && refPalettes2[preferredPalette]) {
692
- const match = findToneInPalette(
693
- hex,
694
- preferredPalette,
695
- refPalettes2[preferredPalette]
696
- );
697
- if (match) return match;
698
- }
699
- for (const [palName, tones] of Object.entries(refPalettes2)) {
700
- const match = findToneInPalette(hex, palName, tones);
701
- if (match) return match;
702
- }
703
- return null;
704
- }
705
- function resolveModeValue(argb, tokenName, refPalettes2) {
706
- const hex = hexFromArgb(argb).toUpperCase();
707
- return findAlias(hex, tokenName, refPalettes2) ?? argbToFigmaColorValue(argb);
708
- }
709
- function buildSysColorTokens(mergedColors, refPalettes2) {
710
- const tokens = {};
711
- for (const [name, argb] of Object.entries(mergedColors)) {
712
- const description = tokenDescriptions[name];
713
- const cssVar = `--${prefix}-sys-color-${kebabCase(name)}`;
714
- const value = resolveModeValue(argb, name, refPalettes2);
715
- tokens[startCase(name)] = {
716
- $type: "color",
717
- $value: value,
718
- ...description ? { $description: description } : {},
719
- $extensions: {
720
- "com.figma.scopes": ["ALL_SCOPES"],
721
- "css.variable": cssVar
722
- }
723
- };
724
- }
725
- return tokens;
726
- }
727
- const refPalettes = buildRefPaletteTokens();
728
- function buildModeFile(modeName, mergedColors) {
729
- return {
730
- ref: {
731
- palette: refPalettes
732
- },
733
- sys: {
734
- color: buildSysColorTokens(mergedColors, refPalettes)
735
- },
736
- $extensions: {
737
- "com.figma.modeName": modeName
738
- }
739
- };
740
- }
741
- return {
742
- "Light.tokens.json": buildModeFile("Light", mergedColorsLight),
743
- "Dark.tokens.json": buildModeFile("Dark", mergedColorsDark)
744
- };
745
- },
746
- //
747
- // API
748
- //
1066
+ toCss: () => buildCss(ctx),
1067
+ toJson: () => buildJson(ctx),
1068
+ toFigmaVariables: () => buildFigmaVariables(ctx),
1069
+ toFigmaTokens: () => buildFigmaTokens(ctx),
1070
+ toTailwind: (options) => buildTailwind(ctx, options),
1071
+ toFlutter: () => buildFlutter(ctx),
749
1072
  mergedColorsLight,
750
1073
  mergedColorsDark,
751
1074
  allPalettes
752
1075
  };
753
1076
  }
754
-
755
- // src/Mcu.tsx
756
- import { useMemo as useMemo2 } from "react";
757
-
758
- // src/Mcu.context.tsx
759
- import {
760
- hexFromArgb as hexFromArgb2
761
- } from "@material/material-color-utilities";
762
- import React, {
763
- useCallback,
764
- useInsertionEffect,
765
- useMemo,
766
- useState
767
- } from "react";
768
-
769
- // src/lib/createRequiredContext.ts
770
- import { createContext, useContext } from "react";
771
- var createRequiredContext = () => {
772
- const Ctx = createContext(null);
773
- const useCtx = () => {
774
- const contextValue = useContext(Ctx);
775
- if (contextValue === null) {
776
- throw new Error("Context value is null");
777
- }
778
- return contextValue;
779
- };
780
- return [useCtx, Ctx.Provider, Ctx];
781
- };
782
-
783
- // src/Mcu.context.tsx
784
- import { jsx } from "react/jsx-runtime";
785
- var [useMcu, Provider, McuContext] = createRequiredContext();
786
- var McuProvider = ({
787
- styleId,
788
- children,
789
- ...configProps
790
- }) => {
791
- const [initials] = useState(() => configProps);
792
- const [mcuConfig, setMcuConfig] = useState(initials);
793
- const configKey = JSON.stringify(configProps);
794
- React.useEffect(() => {
795
- setMcuConfig(configProps);
796
- }, [configKey]);
797
- const { css, mergedColorsLight, mergedColorsDark, allPalettes } = useMemo(() => {
798
- const { toCss, ...rest } = builder(mcuConfig.source, mcuConfig);
799
- return { css: toCss(), ...rest };
800
- }, [mcuConfig]);
801
- useInsertionEffect(() => {
802
- let tag = document.getElementById(styleId);
803
- if (!tag) {
804
- tag = document.createElement("style");
805
- tag.id = styleId;
806
- document.head.appendChild(tag);
807
- }
808
- tag.textContent = css;
809
- }, [css, styleId]);
810
- const getMcuColor = useCallback(
811
- (colorName, theme) => {
812
- const mergedColors = theme === "light" ? mergedColorsLight : mergedColorsDark;
813
- const colorValue = mergedColors[colorName];
814
- if (colorValue === void 0) {
815
- throw new Error(`Unknown MCU token '${colorName}'`);
816
- }
817
- return hexFromArgb2(colorValue);
818
- },
819
- [mergedColorsDark, mergedColorsLight]
820
- );
821
- const value = useMemo(
822
- () => ({
823
- initials,
824
- setMcuConfig,
825
- getMcuColor,
826
- allPalettes
827
- }),
828
- [getMcuColor, initials, allPalettes]
829
- );
830
- return /* @__PURE__ */ jsx(Provider, { value, children });
831
- };
832
-
833
- // src/Mcu.tsx
834
- import { jsx as jsx2 } from "react/jsx-runtime";
835
- var mcuStyleId = "mcu-styles";
836
- var DEFAULT_COLOR_MATCH = false;
837
- function Mcu({
838
- source,
839
- scheme = DEFAULT_SCHEME,
840
- contrast = DEFAULT_CONTRAST,
841
- primary,
842
- secondary,
843
- tertiary,
844
- neutral,
845
- neutralVariant,
846
- error,
847
- colorMatch = DEFAULT_COLOR_MATCH,
848
- customColors = DEFAULT_CUSTOM_COLORS,
849
- prefix = DEFAULT_PREFIX,
850
- children
851
- }) {
852
- const config = useMemo2(
853
- () => ({
854
- source,
855
- scheme,
856
- contrast,
857
- primary,
858
- secondary,
859
- tertiary,
860
- neutral,
861
- neutralVariant,
862
- error,
863
- colorMatch,
864
- customColors,
865
- prefix
866
- }),
867
- [
868
- contrast,
869
- customColors,
870
- scheme,
871
- source,
872
- primary,
873
- secondary,
874
- tertiary,
875
- neutral,
876
- neutralVariant,
877
- error,
878
- colorMatch,
879
- prefix
880
- ]
881
- );
882
- return /* @__PURE__ */ jsx2(McuProvider, { ...config, styleId: mcuStyleId, children });
883
- }
884
1077
  export {
885
- Mcu,
886
- builder,
887
- useMcu
1078
+ builder
888
1079
  };