material-theme-builder 5.0.0 → 5.1.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 +15 -3
- package/dist/cli.js +79 -112
- package/dist/index.d.ts +13 -3
- package/dist/index.js +77 -111
- package/dist/react.d.ts +6 -1
- package/dist/react.js +77 -111
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
[](https://www.chromatic.com/library?appId=695eb517cb602e59b4cc045c&branch=main)
|
|
3
3
|
[](https://main--695eb517cb602e59b4cc045c.chromatic.com)
|
|
4
4
|
|
|
5
|
-
Outputs [m3 colors](https://m3.material.io/styles/color/system/overview) `--md-sys-color
|
|
5
|
+
Outputs [m3 colors](https://m3.material.io/styles/color/system/overview) `--md-sys-color-*`, 1:1 with [Material Theme Builder](https://material-foundation.github.io/material-theme-builder/), and the `--md-ref-palette-*` tonal palettes they are drawn from, either:
|
|
6
6
|
|
|
7
7
|
- [programmatically](#programmatic-api)
|
|
8
8
|
- from [CLI](#cli)
|
|
@@ -19,8 +19,8 @@ Support for:
|
|
|
19
19
|
- [x] core-colors overrides: primary, secondary, tertiary, error, neutral,
|
|
20
20
|
neutralVariant
|
|
21
21
|
- [x] custom-colors (aka. "Extended colors")
|
|
22
|
-
- [x] Harmonization (aka. `blend
|
|
23
|
-
`primary` if defined
|
|
22
|
+
- [x] Harmonization (aka. `blend`, on by default) -- with effective color:
|
|
23
|
+
`source` or `primary` if defined
|
|
24
24
|
- [x] Shades (aka. "tonals")
|
|
25
25
|
- [ ] colorMatch
|
|
26
26
|
|
|
@@ -52,6 +52,18 @@ theme.toShadcnAliases();
|
|
|
52
52
|
theme.toShadcnRegistryItem({ fallback: true });
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
+
> [!NOTE]
|
|
56
|
+
>
|
|
57
|
+
> `toJson()` is shaped like Material Theme Builder's JSON export, and its
|
|
58
|
+
> `schemes` match it. Its `palettes`, though, are the reference palettes: the
|
|
59
|
+
> palettes the system colors are drawn from, the same ones, tones and values as
|
|
60
|
+
> the `--md-ref-palette-*` of `toCss()` (`error` and custom colors included, 28
|
|
61
|
+
> tones). Material Theme Builder's own export holds other palettes -- five, at
|
|
62
|
+
> 18 tones, which ignore the scheme variant and are not the palettes its
|
|
63
|
+
> `schemes` come from. They are not reproduced: Material Theme Builder's
|
|
64
|
+
> maintainers say they are only there as reference. See [ADR 0001](docs/adr/0001-reference-palettes-are-the-scheme-palettes.md)
|
|
65
|
+
> for why.
|
|
66
|
+
|
|
55
67
|
## CLI
|
|
56
68
|
|
|
57
69
|
```sh
|
package/dist/cli.js
CHANGED
|
@@ -27,19 +27,17 @@ import {
|
|
|
27
27
|
SchemeNeutral,
|
|
28
28
|
SchemeTonalSpot,
|
|
29
29
|
SchemeVibrant,
|
|
30
|
-
TonalPalette
|
|
30
|
+
TonalPalette
|
|
31
31
|
} from "@material/material-color-utilities";
|
|
32
32
|
import { kebabCase as kebabCase4, upperFirst as upperFirst2 } from "lodash-es";
|
|
33
33
|
|
|
34
34
|
// src/lib/builder.css.ts
|
|
35
|
-
import {
|
|
36
|
-
hexFromArgb
|
|
37
|
-
} from "@material/material-color-utilities";
|
|
35
|
+
import { hexFromArgb } from "@material/material-color-utilities";
|
|
38
36
|
import { kebabCase } from "lodash-es";
|
|
39
37
|
function buildCss(ctx) {
|
|
40
38
|
const {
|
|
41
39
|
prefix,
|
|
42
|
-
|
|
40
|
+
refPalettes,
|
|
43
41
|
mergedColorsLight,
|
|
44
42
|
mergedColorsDark,
|
|
45
43
|
tokenToPalette,
|
|
@@ -47,10 +45,9 @@ function buildCss(ctx) {
|
|
|
47
45
|
} = ctx;
|
|
48
46
|
function buildRefPaletteLookup() {
|
|
49
47
|
const lookup = {};
|
|
50
|
-
for (const [
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
const hex = hexFromArgb(palette.tone(tone));
|
|
48
|
+
for (const [paletteName, tones] of Object.entries(refPalettes)) {
|
|
49
|
+
for (const { tone, argb } of tones) {
|
|
50
|
+
const hex = hexFromArgb(argb);
|
|
54
51
|
if (!lookup[hex]) lookup[hex] = [];
|
|
55
52
|
lookup[hex].push({ paletteName, tone });
|
|
56
53
|
}
|
|
@@ -78,15 +75,12 @@ function buildCss(ctx) {
|
|
|
78
75
|
const value = hexFromArgb(colorValue);
|
|
79
76
|
return `${name}:${value};`;
|
|
80
77
|
}
|
|
81
|
-
function generateTonalPaletteVars(paletteName,
|
|
82
|
-
return
|
|
83
|
-
const color = palette.tone(tone);
|
|
84
|
-
return refPaletteVar(paletteName, tone, color);
|
|
85
|
-
}).join(" ");
|
|
78
|
+
function generateTonalPaletteVars(paletteName, tones) {
|
|
79
|
+
return tones.map(({ tone, argb }) => refPaletteVar(paletteName, tone, argb)).join(" ");
|
|
86
80
|
}
|
|
87
81
|
function generateTonalVars() {
|
|
88
|
-
return Object.entries(
|
|
89
|
-
([
|
|
82
|
+
return Object.entries(refPalettes).map(
|
|
83
|
+
([paletteName, tones]) => generateTonalPaletteVars(paletteName, tones)
|
|
90
84
|
).join(" ");
|
|
91
85
|
}
|
|
92
86
|
const refPaletteLookup = buildRefPaletteLookup();
|
|
@@ -388,29 +382,8 @@ import {
|
|
|
388
382
|
DynamicScheme,
|
|
389
383
|
Hct,
|
|
390
384
|
hexFromArgb as hexFromArgb4,
|
|
391
|
-
MaterialDynamicColors
|
|
392
|
-
TonalPalette
|
|
385
|
+
MaterialDynamicColors
|
|
393
386
|
} from "@material/material-color-utilities";
|
|
394
|
-
var MTB_TONES = [
|
|
395
|
-
0,
|
|
396
|
-
5,
|
|
397
|
-
10,
|
|
398
|
-
15,
|
|
399
|
-
20,
|
|
400
|
-
25,
|
|
401
|
-
30,
|
|
402
|
-
35,
|
|
403
|
-
40,
|
|
404
|
-
50,
|
|
405
|
-
60,
|
|
406
|
-
70,
|
|
407
|
-
80,
|
|
408
|
-
90,
|
|
409
|
-
95,
|
|
410
|
-
98,
|
|
411
|
-
99,
|
|
412
|
-
100
|
|
413
|
-
];
|
|
414
387
|
var FIXTURE_TOKEN_ORDER = [
|
|
415
388
|
"primary",
|
|
416
389
|
"surfaceTint",
|
|
@@ -465,7 +438,6 @@ var FIXTURE_TOKEN_ORDER = [
|
|
|
465
438
|
function buildJson(ctx) {
|
|
466
439
|
const {
|
|
467
440
|
hexSource,
|
|
468
|
-
sourceHct,
|
|
469
441
|
effectiveSourceArgb,
|
|
470
442
|
primaryHct,
|
|
471
443
|
SchemeClass,
|
|
@@ -476,34 +448,16 @@ function buildJson(ctx) {
|
|
|
476
448
|
error,
|
|
477
449
|
neutral,
|
|
478
450
|
neutralVariant,
|
|
479
|
-
hexCustomColors
|
|
451
|
+
hexCustomColors,
|
|
452
|
+
refPalettes
|
|
480
453
|
} = ctx;
|
|
481
|
-
const neuHct = neutral ? Hct.fromInt(argbFromHex(neutral)) : sourceHct;
|
|
482
|
-
const nvHct = neutralVariant ? Hct.fromInt(argbFromHex(neutralVariant)) : sourceHct;
|
|
483
|
-
const rawPalettes = {
|
|
484
|
-
primary: TonalPalette.fromInt(effectiveSourceArgb),
|
|
485
|
-
secondary: secondary ? TonalPalette.fromInt(argbFromHex(secondary)) : TonalPalette.fromHueAndChroma(sourceHct.hue, sourceHct.chroma / 3),
|
|
486
|
-
tertiary: tertiary ? TonalPalette.fromInt(argbFromHex(tertiary)) : TonalPalette.fromHueAndChroma(
|
|
487
|
-
(sourceHct.hue + 60) % 360,
|
|
488
|
-
sourceHct.chroma / 2
|
|
489
|
-
),
|
|
490
|
-
neutral: TonalPalette.fromHueAndChroma(
|
|
491
|
-
neuHct.hue,
|
|
492
|
-
Math.min(neuHct.chroma / 12, 4)
|
|
493
|
-
),
|
|
494
|
-
"neutral-variant": TonalPalette.fromHueAndChroma(
|
|
495
|
-
nvHct.hue,
|
|
496
|
-
Math.min(nvHct.chroma / 6, 8)
|
|
497
|
-
)
|
|
498
|
-
};
|
|
499
454
|
function buildJsonSchemes() {
|
|
500
|
-
function extractSchemeColors(scheme2
|
|
455
|
+
function extractSchemeColors(scheme2) {
|
|
501
456
|
const colors = {};
|
|
502
457
|
for (const tokenName of FIXTURE_TOKEN_ORDER) {
|
|
503
458
|
const dynamicColor = MaterialDynamicColors[tokenName];
|
|
504
|
-
const useScheme = backgroundScheme && (tokenName === "background" || tokenName === "onBackground") ? backgroundScheme : scheme2;
|
|
505
459
|
colors[tokenName] = hexFromArgb4(
|
|
506
|
-
dynamicColor.getArgb(
|
|
460
|
+
dynamicColor.getArgb(scheme2)
|
|
507
461
|
).toUpperCase();
|
|
508
462
|
}
|
|
509
463
|
return colors;
|
|
@@ -543,26 +497,18 @@ function buildJson(ctx) {
|
|
|
543
497
|
neutralVariantPalette: nvPalette || baseScheme.neutralVariantPalette
|
|
544
498
|
});
|
|
545
499
|
if (errPalette) composedScheme.errorPalette = errPalette;
|
|
546
|
-
jsonSchemes[name] = extractSchemeColors(composedScheme
|
|
500
|
+
jsonSchemes[name] = extractSchemeColors(composedScheme);
|
|
547
501
|
}
|
|
548
502
|
return jsonSchemes;
|
|
549
503
|
}
|
|
550
|
-
function
|
|
504
|
+
function refPalettesToJson() {
|
|
551
505
|
const jsonPalettes = {};
|
|
552
|
-
const
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
"neutral",
|
|
557
|
-
"neutral-variant"
|
|
558
|
-
];
|
|
559
|
-
for (const name of RAW_PALETTE_NAMES) {
|
|
560
|
-
const palette = rawPalettes[name];
|
|
561
|
-
const tones = {};
|
|
562
|
-
for (const tone of MTB_TONES) {
|
|
563
|
-
tones[tone.toString()] = hexFromArgb4(palette.tone(tone)).toUpperCase();
|
|
506
|
+
for (const [name, tones] of Object.entries(refPalettes)) {
|
|
507
|
+
const jsonTones = {};
|
|
508
|
+
for (const { tone, argb } of tones) {
|
|
509
|
+
jsonTones[tone.toString()] = hexFromArgb4(argb).toUpperCase();
|
|
564
510
|
}
|
|
565
|
-
jsonPalettes[name] =
|
|
511
|
+
jsonPalettes[name] = jsonTones;
|
|
566
512
|
}
|
|
567
513
|
return jsonPalettes;
|
|
568
514
|
}
|
|
@@ -589,14 +535,14 @@ function buildJson(ctx) {
|
|
|
589
535
|
name: c.name,
|
|
590
536
|
color: c.hex.toUpperCase(),
|
|
591
537
|
description: "",
|
|
592
|
-
harmonized: c.blend
|
|
538
|
+
harmonized: c.blend
|
|
593
539
|
}));
|
|
594
540
|
return {
|
|
595
541
|
seed,
|
|
596
542
|
coreColors,
|
|
597
543
|
extendedColors,
|
|
598
544
|
schemes: buildJsonSchemes(),
|
|
599
|
-
palettes:
|
|
545
|
+
palettes: refPalettesToJson()
|
|
600
546
|
};
|
|
601
547
|
}
|
|
602
548
|
|
|
@@ -945,51 +891,53 @@ function getPalette(palettes, colorName) {
|
|
|
945
891
|
}
|
|
946
892
|
return palette;
|
|
947
893
|
}
|
|
948
|
-
function
|
|
949
|
-
const
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
return [tokenName, argb];
|
|
953
|
-
});
|
|
954
|
-
const customVars = {};
|
|
955
|
-
customColors.forEach((color) => {
|
|
956
|
-
const colorname = color.name;
|
|
957
|
-
const getPaletteForColor = () => getPalette(colorPalettes, colorname);
|
|
958
|
-
const colorDynamicColor = new DynamicColor(
|
|
894
|
+
function buildCustomColorRoles(colorname, palette) {
|
|
895
|
+
const getPaletteForColor = () => palette;
|
|
896
|
+
return {
|
|
897
|
+
[colorname]: new DynamicColor(
|
|
959
898
|
colorname,
|
|
960
899
|
getPaletteForColor,
|
|
961
900
|
(s) => s.isDark ? 80 : 40,
|
|
962
901
|
// Main color: lighter in dark mode, darker in light mode
|
|
963
902
|
true
|
|
964
903
|
// background
|
|
965
|
-
)
|
|
966
|
-
|
|
904
|
+
),
|
|
905
|
+
[`on${upperFirst2(colorname)}`]: new DynamicColor(
|
|
967
906
|
`on${upperFirst2(colorname)}`,
|
|
968
907
|
getPaletteForColor,
|
|
969
908
|
(s) => s.isDark ? 20 : 100,
|
|
970
909
|
// Text on main color: high contrast (dark on light, light on dark)
|
|
971
910
|
false
|
|
972
|
-
)
|
|
973
|
-
|
|
911
|
+
),
|
|
912
|
+
[`${colorname}Container`]: new DynamicColor(
|
|
974
913
|
`${colorname}Container`,
|
|
975
914
|
getPaletteForColor,
|
|
976
915
|
(s) => s.isDark ? 30 : 90,
|
|
977
916
|
// Container: subtle variant (darker in dark mode, lighter in light mode)
|
|
978
917
|
true
|
|
979
918
|
// background
|
|
980
|
-
)
|
|
981
|
-
|
|
919
|
+
),
|
|
920
|
+
[`on${upperFirst2(colorname)}Container`]: new DynamicColor(
|
|
982
921
|
`on${upperFirst2(colorname)}Container`,
|
|
983
922
|
getPaletteForColor,
|
|
984
923
|
(s) => s.isDark ? 90 : 30,
|
|
985
924
|
// Text on container: high contrast against container background
|
|
986
925
|
false
|
|
987
|
-
)
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
926
|
+
)
|
|
927
|
+
};
|
|
928
|
+
}
|
|
929
|
+
function mergeBaseAndCustomColors(scheme, customColorRoles) {
|
|
930
|
+
const baseVars = toRecord(tokenNames, (tokenName) => {
|
|
931
|
+
const dynamicColor = MaterialDynamicColors2[tokenName];
|
|
932
|
+
const argb = dynamicColor.getArgb(scheme);
|
|
933
|
+
return [tokenName, argb];
|
|
992
934
|
});
|
|
935
|
+
const customVars = {};
|
|
936
|
+
for (const roles of Object.values(customColorRoles)) {
|
|
937
|
+
for (const [tokenName, dynamicColor] of Object.entries(roles)) {
|
|
938
|
+
customVars[tokenName] = dynamicColor.getArgb(scheme);
|
|
939
|
+
}
|
|
940
|
+
}
|
|
993
941
|
return { ...baseVars, ...customVars };
|
|
994
942
|
}
|
|
995
943
|
function createColorPalette(colorDef, baseScheme, effectiveSourceForHarmonization) {
|
|
@@ -1008,7 +956,17 @@ function createColorPalette(colorDef, baseScheme, effectiveSourceForHarmonizatio
|
|
|
1008
956
|
} else {
|
|
1009
957
|
targetChroma = baseScheme.primaryPalette.chroma;
|
|
1010
958
|
}
|
|
1011
|
-
return
|
|
959
|
+
return TonalPalette.fromHueAndChroma(hct.hue, targetChroma);
|
|
960
|
+
}
|
|
961
|
+
function buildRefPalettes(allPalettes) {
|
|
962
|
+
const refPalettes = {};
|
|
963
|
+
for (const [name, palette] of Object.entries(allPalettes)) {
|
|
964
|
+
refPalettes[kebabCase4(name)] = STANDARD_TONES.map((tone) => ({
|
|
965
|
+
tone,
|
|
966
|
+
argb: palette.tone(tone)
|
|
967
|
+
}));
|
|
968
|
+
}
|
|
969
|
+
return refPalettes;
|
|
1012
970
|
}
|
|
1013
971
|
function buildTokenToPaletteMap(schemePalettes, scheme) {
|
|
1014
972
|
const result = {};
|
|
@@ -1037,7 +995,7 @@ function builder(hexSource, {
|
|
|
1037
995
|
neutral,
|
|
1038
996
|
neutralVariant,
|
|
1039
997
|
error,
|
|
1040
|
-
customColors:
|
|
998
|
+
customColors: customColorInputs = DEFAULT_CUSTOM_COLORS,
|
|
1041
999
|
prefix = DEFAULT_PREFIX
|
|
1042
1000
|
} = {}) {
|
|
1043
1001
|
const cores = {
|
|
@@ -1048,9 +1006,12 @@ function builder(hexSource, {
|
|
|
1048
1006
|
neutral: optionalHex(neutral),
|
|
1049
1007
|
neutralVariant: optionalHex(neutralVariant)
|
|
1050
1008
|
};
|
|
1051
|
-
assertHexInputs(hexSource, cores,
|
|
1009
|
+
assertHexInputs(hexSource, cores, customColorInputs);
|
|
1010
|
+
const hexCustomColors = customColorInputs.map((c) => ({
|
|
1011
|
+
...c,
|
|
1012
|
+
blend: c.blend ?? DEFAULT_BLEND
|
|
1013
|
+
}));
|
|
1052
1014
|
const sourceArgb = argbFromHex2(hexSource);
|
|
1053
|
-
const sourceHct = Hct2.fromInt(sourceArgb);
|
|
1054
1015
|
const effectiveSource = cores.primary || hexSource;
|
|
1055
1016
|
const effectiveSourceArgb = argbFromHex2(effectiveSource);
|
|
1056
1017
|
const effectiveSourceForHarmonization = cores.primary ? argbFromHex2(cores.primary) : sourceArgb;
|
|
@@ -1141,18 +1102,21 @@ function builder(hexSource, {
|
|
|
1141
1102
|
};
|
|
1142
1103
|
const customColors = definedColors.filter((c) => !c.core).map((c) => ({
|
|
1143
1104
|
name: c.name,
|
|
1144
|
-
blend: c.blend ?? DEFAULT_BLEND,
|
|
1145
1105
|
value: argbFromHex2(c.hex)
|
|
1146
1106
|
}));
|
|
1107
|
+
const customColorRoles = Object.fromEntries(
|
|
1108
|
+
customColors.map((color) => [
|
|
1109
|
+
color.name,
|
|
1110
|
+
buildCustomColorRoles(color.name, getPalette(colorPalettes, color.name))
|
|
1111
|
+
])
|
|
1112
|
+
);
|
|
1147
1113
|
const mergedColorsLight = mergeBaseAndCustomColors(
|
|
1148
1114
|
lightScheme,
|
|
1149
|
-
|
|
1150
|
-
colorPalettes
|
|
1115
|
+
customColorRoles
|
|
1151
1116
|
);
|
|
1152
1117
|
const mergedColorsDark = mergeBaseAndCustomColors(
|
|
1153
1118
|
darkScheme,
|
|
1154
|
-
|
|
1155
|
-
colorPalettes
|
|
1119
|
+
customColorRoles
|
|
1156
1120
|
);
|
|
1157
1121
|
const schemePalettes = [
|
|
1158
1122
|
["primary", lightScheme.primaryPalette],
|
|
@@ -1163,6 +1127,7 @@ function builder(hexSource, {
|
|
|
1163
1127
|
["neutral-variant", lightScheme.neutralVariantPalette]
|
|
1164
1128
|
];
|
|
1165
1129
|
const tokenToPalette = buildTokenToPaletteMap(schemePalettes, lightScheme);
|
|
1130
|
+
const refPalettes = buildRefPalettes(allPalettes);
|
|
1166
1131
|
const allPaletteNamesKebab = new Set(Object.keys(allPalettes).map(kebabCase4));
|
|
1167
1132
|
const ctx = {
|
|
1168
1133
|
hexSource,
|
|
@@ -1175,11 +1140,11 @@ function builder(hexSource, {
|
|
|
1175
1140
|
neutralVariant,
|
|
1176
1141
|
error,
|
|
1177
1142
|
hexCustomColors,
|
|
1178
|
-
sourceHct,
|
|
1179
1143
|
effectiveSourceArgb,
|
|
1180
1144
|
primaryHct,
|
|
1181
1145
|
SchemeClass,
|
|
1182
1146
|
allPalettes,
|
|
1147
|
+
refPalettes,
|
|
1183
1148
|
mergedColorsLight,
|
|
1184
1149
|
mergedColorsDark,
|
|
1185
1150
|
tokenToPalette,
|
|
@@ -1197,7 +1162,8 @@ function builder(hexSource, {
|
|
|
1197
1162
|
toFlutter: () => buildFlutter(ctx),
|
|
1198
1163
|
mergedColorsLight,
|
|
1199
1164
|
mergedColorsDark,
|
|
1200
|
-
allPalettes
|
|
1165
|
+
allPalettes,
|
|
1166
|
+
customColorRoles
|
|
1201
1167
|
};
|
|
1202
1168
|
}
|
|
1203
1169
|
|
|
@@ -1310,7 +1276,8 @@ var customColorSchema = z.array(
|
|
|
1310
1276
|
isHexColor,
|
|
1311
1277
|
"must be a hex color \u2014 3, 6 or 8 hex digits, with or without '#' (e.g. #FF5733)"
|
|
1312
1278
|
),
|
|
1313
|
-
|
|
1279
|
+
// left to builder(), which applies DEFAULT_BLEND to an omitted `blend`
|
|
1280
|
+
blend: z.boolean().optional()
|
|
1314
1281
|
})
|
|
1315
1282
|
);
|
|
1316
1283
|
function writeFigmaTokens(theme, outputDir) {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CustomColor, TonalPalette } from '@material/material-color-utilities';
|
|
1
|
+
import { CustomColor, TonalPalette, DynamicColor } from '@material/material-color-utilities';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* shadcn CSS variable → M3 sys-color token mapping.
|
|
@@ -97,8 +97,13 @@ type TailwindOptions = {
|
|
|
97
97
|
};
|
|
98
98
|
|
|
99
99
|
/** A custom color defined with a hex string instead of an ARGB integer. */
|
|
100
|
-
type HexCustomColor = Omit<CustomColor, "value"> & {
|
|
100
|
+
type HexCustomColor = Omit<CustomColor, "value" | "blend"> & {
|
|
101
101
|
hex: string;
|
|
102
|
+
/**
|
|
103
|
+
* Harmonize the color with the source (or `primary`, when given) -- "Harmonize"
|
|
104
|
+
* in Material Theme Builder. Default: `DEFAULT_BLEND` (true).
|
|
105
|
+
*/
|
|
106
|
+
blend?: boolean;
|
|
102
107
|
};
|
|
103
108
|
/** Available Material You color scheme variants. */
|
|
104
109
|
declare const schemeNames: readonly ["tonalSpot", "monochrome", "neutral", "vibrant", "expressive", "fidelity", "content"];
|
|
@@ -164,7 +169,7 @@ type McuConfig = MtbConfig;
|
|
|
164
169
|
* const json = theme.toJson();
|
|
165
170
|
* ```
|
|
166
171
|
*/
|
|
167
|
-
declare function builder(hexSource: MtbConfig["source"], { scheme, contrast, primary, secondary, tertiary, neutral, neutralVariant, error, customColors:
|
|
172
|
+
declare function builder(hexSource: MtbConfig["source"], { scheme, contrast, primary, secondary, tertiary, neutral, neutralVariant, error, customColors: customColorInputs, prefix, }?: Omit<MtbConfig, "source">): {
|
|
168
173
|
toCss: () => string;
|
|
169
174
|
toJson: () => {
|
|
170
175
|
seed: string;
|
|
@@ -222,6 +227,11 @@ declare function builder(hexSource: MtbConfig["source"], { scheme, contrast, pri
|
|
|
222
227
|
neutral: TonalPalette;
|
|
223
228
|
"neutral-variant": TonalPalette;
|
|
224
229
|
};
|
|
230
|
+
customColorRoles: {
|
|
231
|
+
[k: string]: {
|
|
232
|
+
[x: string]: DynamicColor;
|
|
233
|
+
};
|
|
234
|
+
};
|
|
225
235
|
};
|
|
226
236
|
|
|
227
237
|
export { type McuConfig, type MtbConfig, type ShadcnRegistryItem, type ShadcnTheme, type ShadcnVarName, builder };
|
package/dist/index.js
CHANGED
|
@@ -13,19 +13,17 @@ import {
|
|
|
13
13
|
SchemeNeutral,
|
|
14
14
|
SchemeTonalSpot,
|
|
15
15
|
SchemeVibrant,
|
|
16
|
-
TonalPalette
|
|
16
|
+
TonalPalette
|
|
17
17
|
} from "@material/material-color-utilities";
|
|
18
18
|
import { kebabCase as kebabCase4, upperFirst as upperFirst2 } from "lodash-es";
|
|
19
19
|
|
|
20
20
|
// src/lib/builder.css.ts
|
|
21
|
-
import {
|
|
22
|
-
hexFromArgb
|
|
23
|
-
} from "@material/material-color-utilities";
|
|
21
|
+
import { hexFromArgb } from "@material/material-color-utilities";
|
|
24
22
|
import { kebabCase } from "lodash-es";
|
|
25
23
|
function buildCss(ctx) {
|
|
26
24
|
const {
|
|
27
25
|
prefix,
|
|
28
|
-
|
|
26
|
+
refPalettes,
|
|
29
27
|
mergedColorsLight,
|
|
30
28
|
mergedColorsDark,
|
|
31
29
|
tokenToPalette,
|
|
@@ -33,10 +31,9 @@ function buildCss(ctx) {
|
|
|
33
31
|
} = ctx;
|
|
34
32
|
function buildRefPaletteLookup() {
|
|
35
33
|
const lookup = {};
|
|
36
|
-
for (const [
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
const hex = hexFromArgb(palette.tone(tone));
|
|
34
|
+
for (const [paletteName, tones] of Object.entries(refPalettes)) {
|
|
35
|
+
for (const { tone, argb } of tones) {
|
|
36
|
+
const hex = hexFromArgb(argb);
|
|
40
37
|
if (!lookup[hex]) lookup[hex] = [];
|
|
41
38
|
lookup[hex].push({ paletteName, tone });
|
|
42
39
|
}
|
|
@@ -64,15 +61,12 @@ function buildCss(ctx) {
|
|
|
64
61
|
const value = hexFromArgb(colorValue);
|
|
65
62
|
return `${name}:${value};`;
|
|
66
63
|
}
|
|
67
|
-
function generateTonalPaletteVars(paletteName,
|
|
68
|
-
return
|
|
69
|
-
const color = palette.tone(tone);
|
|
70
|
-
return refPaletteVar(paletteName, tone, color);
|
|
71
|
-
}).join(" ");
|
|
64
|
+
function generateTonalPaletteVars(paletteName, tones) {
|
|
65
|
+
return tones.map(({ tone, argb }) => refPaletteVar(paletteName, tone, argb)).join(" ");
|
|
72
66
|
}
|
|
73
67
|
function generateTonalVars() {
|
|
74
|
-
return Object.entries(
|
|
75
|
-
([
|
|
68
|
+
return Object.entries(refPalettes).map(
|
|
69
|
+
([paletteName, tones]) => generateTonalPaletteVars(paletteName, tones)
|
|
76
70
|
).join(" ");
|
|
77
71
|
}
|
|
78
72
|
const refPaletteLookup = buildRefPaletteLookup();
|
|
@@ -374,29 +368,8 @@ import {
|
|
|
374
368
|
DynamicScheme,
|
|
375
369
|
Hct,
|
|
376
370
|
hexFromArgb as hexFromArgb4,
|
|
377
|
-
MaterialDynamicColors
|
|
378
|
-
TonalPalette
|
|
371
|
+
MaterialDynamicColors
|
|
379
372
|
} from "@material/material-color-utilities";
|
|
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
373
|
var FIXTURE_TOKEN_ORDER = [
|
|
401
374
|
"primary",
|
|
402
375
|
"surfaceTint",
|
|
@@ -451,7 +424,6 @@ var FIXTURE_TOKEN_ORDER = [
|
|
|
451
424
|
function buildJson(ctx) {
|
|
452
425
|
const {
|
|
453
426
|
hexSource,
|
|
454
|
-
sourceHct,
|
|
455
427
|
effectiveSourceArgb,
|
|
456
428
|
primaryHct,
|
|
457
429
|
SchemeClass,
|
|
@@ -462,34 +434,16 @@ function buildJson(ctx) {
|
|
|
462
434
|
error,
|
|
463
435
|
neutral,
|
|
464
436
|
neutralVariant,
|
|
465
|
-
hexCustomColors
|
|
437
|
+
hexCustomColors,
|
|
438
|
+
refPalettes
|
|
466
439
|
} = 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
440
|
function buildJsonSchemes() {
|
|
486
|
-
function extractSchemeColors(scheme2
|
|
441
|
+
function extractSchemeColors(scheme2) {
|
|
487
442
|
const colors = {};
|
|
488
443
|
for (const tokenName of FIXTURE_TOKEN_ORDER) {
|
|
489
444
|
const dynamicColor = MaterialDynamicColors[tokenName];
|
|
490
|
-
const useScheme = backgroundScheme && (tokenName === "background" || tokenName === "onBackground") ? backgroundScheme : scheme2;
|
|
491
445
|
colors[tokenName] = hexFromArgb4(
|
|
492
|
-
dynamicColor.getArgb(
|
|
446
|
+
dynamicColor.getArgb(scheme2)
|
|
493
447
|
).toUpperCase();
|
|
494
448
|
}
|
|
495
449
|
return colors;
|
|
@@ -529,26 +483,18 @@ function buildJson(ctx) {
|
|
|
529
483
|
neutralVariantPalette: nvPalette || baseScheme.neutralVariantPalette
|
|
530
484
|
});
|
|
531
485
|
if (errPalette) composedScheme.errorPalette = errPalette;
|
|
532
|
-
jsonSchemes[name] = extractSchemeColors(composedScheme
|
|
486
|
+
jsonSchemes[name] = extractSchemeColors(composedScheme);
|
|
533
487
|
}
|
|
534
488
|
return jsonSchemes;
|
|
535
489
|
}
|
|
536
|
-
function
|
|
490
|
+
function refPalettesToJson() {
|
|
537
491
|
const jsonPalettes = {};
|
|
538
|
-
const
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
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();
|
|
492
|
+
for (const [name, tones] of Object.entries(refPalettes)) {
|
|
493
|
+
const jsonTones = {};
|
|
494
|
+
for (const { tone, argb } of tones) {
|
|
495
|
+
jsonTones[tone.toString()] = hexFromArgb4(argb).toUpperCase();
|
|
550
496
|
}
|
|
551
|
-
jsonPalettes[name] =
|
|
497
|
+
jsonPalettes[name] = jsonTones;
|
|
552
498
|
}
|
|
553
499
|
return jsonPalettes;
|
|
554
500
|
}
|
|
@@ -575,14 +521,14 @@ function buildJson(ctx) {
|
|
|
575
521
|
name: c.name,
|
|
576
522
|
color: c.hex.toUpperCase(),
|
|
577
523
|
description: "",
|
|
578
|
-
harmonized: c.blend
|
|
524
|
+
harmonized: c.blend
|
|
579
525
|
}));
|
|
580
526
|
return {
|
|
581
527
|
seed,
|
|
582
528
|
coreColors,
|
|
583
529
|
extendedColors,
|
|
584
530
|
schemes: buildJsonSchemes(),
|
|
585
|
-
palettes:
|
|
531
|
+
palettes: refPalettesToJson()
|
|
586
532
|
};
|
|
587
533
|
}
|
|
588
534
|
|
|
@@ -922,51 +868,53 @@ function getPalette(palettes, colorName) {
|
|
|
922
868
|
}
|
|
923
869
|
return palette;
|
|
924
870
|
}
|
|
925
|
-
function
|
|
926
|
-
const
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
return [tokenName, argb];
|
|
930
|
-
});
|
|
931
|
-
const customVars = {};
|
|
932
|
-
customColors.forEach((color) => {
|
|
933
|
-
const colorname = color.name;
|
|
934
|
-
const getPaletteForColor = () => getPalette(colorPalettes, colorname);
|
|
935
|
-
const colorDynamicColor = new DynamicColor(
|
|
871
|
+
function buildCustomColorRoles(colorname, palette) {
|
|
872
|
+
const getPaletteForColor = () => palette;
|
|
873
|
+
return {
|
|
874
|
+
[colorname]: new DynamicColor(
|
|
936
875
|
colorname,
|
|
937
876
|
getPaletteForColor,
|
|
938
877
|
(s) => s.isDark ? 80 : 40,
|
|
939
878
|
// Main color: lighter in dark mode, darker in light mode
|
|
940
879
|
true
|
|
941
880
|
// background
|
|
942
|
-
)
|
|
943
|
-
|
|
881
|
+
),
|
|
882
|
+
[`on${upperFirst2(colorname)}`]: new DynamicColor(
|
|
944
883
|
`on${upperFirst2(colorname)}`,
|
|
945
884
|
getPaletteForColor,
|
|
946
885
|
(s) => s.isDark ? 20 : 100,
|
|
947
886
|
// Text on main color: high contrast (dark on light, light on dark)
|
|
948
887
|
false
|
|
949
|
-
)
|
|
950
|
-
|
|
888
|
+
),
|
|
889
|
+
[`${colorname}Container`]: new DynamicColor(
|
|
951
890
|
`${colorname}Container`,
|
|
952
891
|
getPaletteForColor,
|
|
953
892
|
(s) => s.isDark ? 30 : 90,
|
|
954
893
|
// Container: subtle variant (darker in dark mode, lighter in light mode)
|
|
955
894
|
true
|
|
956
895
|
// background
|
|
957
|
-
)
|
|
958
|
-
|
|
896
|
+
),
|
|
897
|
+
[`on${upperFirst2(colorname)}Container`]: new DynamicColor(
|
|
959
898
|
`on${upperFirst2(colorname)}Container`,
|
|
960
899
|
getPaletteForColor,
|
|
961
900
|
(s) => s.isDark ? 90 : 30,
|
|
962
901
|
// Text on container: high contrast against container background
|
|
963
902
|
false
|
|
964
|
-
)
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
903
|
+
)
|
|
904
|
+
};
|
|
905
|
+
}
|
|
906
|
+
function mergeBaseAndCustomColors(scheme, customColorRoles) {
|
|
907
|
+
const baseVars = toRecord(tokenNames, (tokenName) => {
|
|
908
|
+
const dynamicColor = MaterialDynamicColors2[tokenName];
|
|
909
|
+
const argb = dynamicColor.getArgb(scheme);
|
|
910
|
+
return [tokenName, argb];
|
|
969
911
|
});
|
|
912
|
+
const customVars = {};
|
|
913
|
+
for (const roles of Object.values(customColorRoles)) {
|
|
914
|
+
for (const [tokenName, dynamicColor] of Object.entries(roles)) {
|
|
915
|
+
customVars[tokenName] = dynamicColor.getArgb(scheme);
|
|
916
|
+
}
|
|
917
|
+
}
|
|
970
918
|
return { ...baseVars, ...customVars };
|
|
971
919
|
}
|
|
972
920
|
function createColorPalette(colorDef, baseScheme, effectiveSourceForHarmonization) {
|
|
@@ -985,7 +933,17 @@ function createColorPalette(colorDef, baseScheme, effectiveSourceForHarmonizatio
|
|
|
985
933
|
} else {
|
|
986
934
|
targetChroma = baseScheme.primaryPalette.chroma;
|
|
987
935
|
}
|
|
988
|
-
return
|
|
936
|
+
return TonalPalette.fromHueAndChroma(hct.hue, targetChroma);
|
|
937
|
+
}
|
|
938
|
+
function buildRefPalettes(allPalettes) {
|
|
939
|
+
const refPalettes = {};
|
|
940
|
+
for (const [name, palette] of Object.entries(allPalettes)) {
|
|
941
|
+
refPalettes[kebabCase4(name)] = STANDARD_TONES.map((tone) => ({
|
|
942
|
+
tone,
|
|
943
|
+
argb: palette.tone(tone)
|
|
944
|
+
}));
|
|
945
|
+
}
|
|
946
|
+
return refPalettes;
|
|
989
947
|
}
|
|
990
948
|
function buildTokenToPaletteMap(schemePalettes, scheme) {
|
|
991
949
|
const result = {};
|
|
@@ -1014,7 +972,7 @@ function builder(hexSource, {
|
|
|
1014
972
|
neutral,
|
|
1015
973
|
neutralVariant,
|
|
1016
974
|
error,
|
|
1017
|
-
customColors:
|
|
975
|
+
customColors: customColorInputs = DEFAULT_CUSTOM_COLORS,
|
|
1018
976
|
prefix = DEFAULT_PREFIX
|
|
1019
977
|
} = {}) {
|
|
1020
978
|
const cores = {
|
|
@@ -1025,9 +983,12 @@ function builder(hexSource, {
|
|
|
1025
983
|
neutral: optionalHex(neutral),
|
|
1026
984
|
neutralVariant: optionalHex(neutralVariant)
|
|
1027
985
|
};
|
|
1028
|
-
assertHexInputs(hexSource, cores,
|
|
986
|
+
assertHexInputs(hexSource, cores, customColorInputs);
|
|
987
|
+
const hexCustomColors = customColorInputs.map((c) => ({
|
|
988
|
+
...c,
|
|
989
|
+
blend: c.blend ?? DEFAULT_BLEND
|
|
990
|
+
}));
|
|
1029
991
|
const sourceArgb = argbFromHex2(hexSource);
|
|
1030
|
-
const sourceHct = Hct2.fromInt(sourceArgb);
|
|
1031
992
|
const effectiveSource = cores.primary || hexSource;
|
|
1032
993
|
const effectiveSourceArgb = argbFromHex2(effectiveSource);
|
|
1033
994
|
const effectiveSourceForHarmonization = cores.primary ? argbFromHex2(cores.primary) : sourceArgb;
|
|
@@ -1118,18 +1079,21 @@ function builder(hexSource, {
|
|
|
1118
1079
|
};
|
|
1119
1080
|
const customColors = definedColors.filter((c) => !c.core).map((c) => ({
|
|
1120
1081
|
name: c.name,
|
|
1121
|
-
blend: c.blend ?? DEFAULT_BLEND,
|
|
1122
1082
|
value: argbFromHex2(c.hex)
|
|
1123
1083
|
}));
|
|
1084
|
+
const customColorRoles = Object.fromEntries(
|
|
1085
|
+
customColors.map((color) => [
|
|
1086
|
+
color.name,
|
|
1087
|
+
buildCustomColorRoles(color.name, getPalette(colorPalettes, color.name))
|
|
1088
|
+
])
|
|
1089
|
+
);
|
|
1124
1090
|
const mergedColorsLight = mergeBaseAndCustomColors(
|
|
1125
1091
|
lightScheme,
|
|
1126
|
-
|
|
1127
|
-
colorPalettes
|
|
1092
|
+
customColorRoles
|
|
1128
1093
|
);
|
|
1129
1094
|
const mergedColorsDark = mergeBaseAndCustomColors(
|
|
1130
1095
|
darkScheme,
|
|
1131
|
-
|
|
1132
|
-
colorPalettes
|
|
1096
|
+
customColorRoles
|
|
1133
1097
|
);
|
|
1134
1098
|
const schemePalettes = [
|
|
1135
1099
|
["primary", lightScheme.primaryPalette],
|
|
@@ -1140,6 +1104,7 @@ function builder(hexSource, {
|
|
|
1140
1104
|
["neutral-variant", lightScheme.neutralVariantPalette]
|
|
1141
1105
|
];
|
|
1142
1106
|
const tokenToPalette = buildTokenToPaletteMap(schemePalettes, lightScheme);
|
|
1107
|
+
const refPalettes = buildRefPalettes(allPalettes);
|
|
1143
1108
|
const allPaletteNamesKebab = new Set(Object.keys(allPalettes).map(kebabCase4));
|
|
1144
1109
|
const ctx = {
|
|
1145
1110
|
hexSource,
|
|
@@ -1152,11 +1117,11 @@ function builder(hexSource, {
|
|
|
1152
1117
|
neutralVariant,
|
|
1153
1118
|
error,
|
|
1154
1119
|
hexCustomColors,
|
|
1155
|
-
sourceHct,
|
|
1156
1120
|
effectiveSourceArgb,
|
|
1157
1121
|
primaryHct,
|
|
1158
1122
|
SchemeClass,
|
|
1159
1123
|
allPalettes,
|
|
1124
|
+
refPalettes,
|
|
1160
1125
|
mergedColorsLight,
|
|
1161
1126
|
mergedColorsDark,
|
|
1162
1127
|
tokenToPalette,
|
|
@@ -1174,7 +1139,8 @@ function builder(hexSource, {
|
|
|
1174
1139
|
toFlutter: () => buildFlutter(ctx),
|
|
1175
1140
|
mergedColorsLight,
|
|
1176
1141
|
mergedColorsDark,
|
|
1177
|
-
allPalettes
|
|
1142
|
+
allPalettes,
|
|
1143
|
+
customColorRoles
|
|
1178
1144
|
};
|
|
1179
1145
|
}
|
|
1180
1146
|
export {
|
package/dist/react.d.ts
CHANGED
|
@@ -134,8 +134,13 @@ declare const tokenDescriptions: {
|
|
|
134
134
|
type TokenName = keyof typeof tokenDescriptions;
|
|
135
135
|
|
|
136
136
|
/** A custom color defined with a hex string instead of an ARGB integer. */
|
|
137
|
-
type HexCustomColor = Omit<CustomColor, "value"> & {
|
|
137
|
+
type HexCustomColor = Omit<CustomColor, "value" | "blend"> & {
|
|
138
138
|
hex: string;
|
|
139
|
+
/**
|
|
140
|
+
* Harmonize the color with the source (or `primary`, when given) -- "Harmonize"
|
|
141
|
+
* in Material Theme Builder. Default: `DEFAULT_BLEND` (true).
|
|
142
|
+
*/
|
|
143
|
+
blend?: boolean;
|
|
139
144
|
};
|
|
140
145
|
/** Available Material You color scheme variants. */
|
|
141
146
|
declare const schemeNames: readonly ["tonalSpot", "monochrome", "neutral", "vibrant", "expressive", "fidelity", "content"];
|
package/dist/react.js
CHANGED
|
@@ -3333,19 +3333,17 @@ import {
|
|
|
3333
3333
|
SchemeNeutral,
|
|
3334
3334
|
SchemeTonalSpot,
|
|
3335
3335
|
SchemeVibrant,
|
|
3336
|
-
TonalPalette
|
|
3336
|
+
TonalPalette
|
|
3337
3337
|
} from "@material/material-color-utilities";
|
|
3338
3338
|
import { kebabCase as kebabCase4, upperFirst as upperFirst2 } from "lodash-es";
|
|
3339
3339
|
|
|
3340
3340
|
// src/lib/builder.css.ts
|
|
3341
|
-
import {
|
|
3342
|
-
hexFromArgb
|
|
3343
|
-
} from "@material/material-color-utilities";
|
|
3341
|
+
import { hexFromArgb } from "@material/material-color-utilities";
|
|
3344
3342
|
import { kebabCase } from "lodash-es";
|
|
3345
3343
|
function buildCss(ctx) {
|
|
3346
3344
|
const {
|
|
3347
3345
|
prefix,
|
|
3348
|
-
|
|
3346
|
+
refPalettes,
|
|
3349
3347
|
mergedColorsLight,
|
|
3350
3348
|
mergedColorsDark,
|
|
3351
3349
|
tokenToPalette,
|
|
@@ -3353,10 +3351,9 @@ function buildCss(ctx) {
|
|
|
3353
3351
|
} = ctx;
|
|
3354
3352
|
function buildRefPaletteLookup() {
|
|
3355
3353
|
const lookup = {};
|
|
3356
|
-
for (const [
|
|
3357
|
-
const
|
|
3358
|
-
|
|
3359
|
-
const hex = hexFromArgb(palette.tone(tone));
|
|
3354
|
+
for (const [paletteName, tones] of Object.entries(refPalettes)) {
|
|
3355
|
+
for (const { tone, argb } of tones) {
|
|
3356
|
+
const hex = hexFromArgb(argb);
|
|
3360
3357
|
if (!lookup[hex]) lookup[hex] = [];
|
|
3361
3358
|
lookup[hex].push({ paletteName, tone });
|
|
3362
3359
|
}
|
|
@@ -3384,15 +3381,12 @@ function buildCss(ctx) {
|
|
|
3384
3381
|
const value = hexFromArgb(colorValue);
|
|
3385
3382
|
return `${name}:${value};`;
|
|
3386
3383
|
}
|
|
3387
|
-
function generateTonalPaletteVars(paletteName,
|
|
3388
|
-
return
|
|
3389
|
-
const color = palette.tone(tone);
|
|
3390
|
-
return refPaletteVar(paletteName, tone, color);
|
|
3391
|
-
}).join(" ");
|
|
3384
|
+
function generateTonalPaletteVars(paletteName, tones) {
|
|
3385
|
+
return tones.map(({ tone, argb }) => refPaletteVar(paletteName, tone, argb)).join(" ");
|
|
3392
3386
|
}
|
|
3393
3387
|
function generateTonalVars() {
|
|
3394
|
-
return Object.entries(
|
|
3395
|
-
([
|
|
3388
|
+
return Object.entries(refPalettes).map(
|
|
3389
|
+
([paletteName, tones]) => generateTonalPaletteVars(paletteName, tones)
|
|
3396
3390
|
).join(" ");
|
|
3397
3391
|
}
|
|
3398
3392
|
const refPaletteLookup = buildRefPaletteLookup();
|
|
@@ -3694,29 +3688,8 @@ import {
|
|
|
3694
3688
|
DynamicScheme,
|
|
3695
3689
|
Hct,
|
|
3696
3690
|
hexFromArgb as hexFromArgb4,
|
|
3697
|
-
MaterialDynamicColors
|
|
3698
|
-
TonalPalette
|
|
3691
|
+
MaterialDynamicColors
|
|
3699
3692
|
} from "@material/material-color-utilities";
|
|
3700
|
-
var MTB_TONES = [
|
|
3701
|
-
0,
|
|
3702
|
-
5,
|
|
3703
|
-
10,
|
|
3704
|
-
15,
|
|
3705
|
-
20,
|
|
3706
|
-
25,
|
|
3707
|
-
30,
|
|
3708
|
-
35,
|
|
3709
|
-
40,
|
|
3710
|
-
50,
|
|
3711
|
-
60,
|
|
3712
|
-
70,
|
|
3713
|
-
80,
|
|
3714
|
-
90,
|
|
3715
|
-
95,
|
|
3716
|
-
98,
|
|
3717
|
-
99,
|
|
3718
|
-
100
|
|
3719
|
-
];
|
|
3720
3693
|
var FIXTURE_TOKEN_ORDER = [
|
|
3721
3694
|
"primary",
|
|
3722
3695
|
"surfaceTint",
|
|
@@ -3771,7 +3744,6 @@ var FIXTURE_TOKEN_ORDER = [
|
|
|
3771
3744
|
function buildJson(ctx) {
|
|
3772
3745
|
const {
|
|
3773
3746
|
hexSource,
|
|
3774
|
-
sourceHct,
|
|
3775
3747
|
effectiveSourceArgb,
|
|
3776
3748
|
primaryHct,
|
|
3777
3749
|
SchemeClass,
|
|
@@ -3782,34 +3754,16 @@ function buildJson(ctx) {
|
|
|
3782
3754
|
error,
|
|
3783
3755
|
neutral,
|
|
3784
3756
|
neutralVariant,
|
|
3785
|
-
hexCustomColors
|
|
3757
|
+
hexCustomColors,
|
|
3758
|
+
refPalettes
|
|
3786
3759
|
} = ctx;
|
|
3787
|
-
const neuHct = neutral ? Hct.fromInt(argbFromHex(neutral)) : sourceHct;
|
|
3788
|
-
const nvHct = neutralVariant ? Hct.fromInt(argbFromHex(neutralVariant)) : sourceHct;
|
|
3789
|
-
const rawPalettes = {
|
|
3790
|
-
primary: TonalPalette.fromInt(effectiveSourceArgb),
|
|
3791
|
-
secondary: secondary ? TonalPalette.fromInt(argbFromHex(secondary)) : TonalPalette.fromHueAndChroma(sourceHct.hue, sourceHct.chroma / 3),
|
|
3792
|
-
tertiary: tertiary ? TonalPalette.fromInt(argbFromHex(tertiary)) : TonalPalette.fromHueAndChroma(
|
|
3793
|
-
(sourceHct.hue + 60) % 360,
|
|
3794
|
-
sourceHct.chroma / 2
|
|
3795
|
-
),
|
|
3796
|
-
neutral: TonalPalette.fromHueAndChroma(
|
|
3797
|
-
neuHct.hue,
|
|
3798
|
-
Math.min(neuHct.chroma / 12, 4)
|
|
3799
|
-
),
|
|
3800
|
-
"neutral-variant": TonalPalette.fromHueAndChroma(
|
|
3801
|
-
nvHct.hue,
|
|
3802
|
-
Math.min(nvHct.chroma / 6, 8)
|
|
3803
|
-
)
|
|
3804
|
-
};
|
|
3805
3760
|
function buildJsonSchemes() {
|
|
3806
|
-
function extractSchemeColors(scheme2
|
|
3761
|
+
function extractSchemeColors(scheme2) {
|
|
3807
3762
|
const colors = {};
|
|
3808
3763
|
for (const tokenName of FIXTURE_TOKEN_ORDER) {
|
|
3809
3764
|
const dynamicColor = MaterialDynamicColors[tokenName];
|
|
3810
|
-
const useScheme = backgroundScheme && (tokenName === "background" || tokenName === "onBackground") ? backgroundScheme : scheme2;
|
|
3811
3765
|
colors[tokenName] = hexFromArgb4(
|
|
3812
|
-
dynamicColor.getArgb(
|
|
3766
|
+
dynamicColor.getArgb(scheme2)
|
|
3813
3767
|
).toUpperCase();
|
|
3814
3768
|
}
|
|
3815
3769
|
return colors;
|
|
@@ -3849,26 +3803,18 @@ function buildJson(ctx) {
|
|
|
3849
3803
|
neutralVariantPalette: nvPalette || baseScheme.neutralVariantPalette
|
|
3850
3804
|
});
|
|
3851
3805
|
if (errPalette) composedScheme.errorPalette = errPalette;
|
|
3852
|
-
jsonSchemes[name] = extractSchemeColors(composedScheme
|
|
3806
|
+
jsonSchemes[name] = extractSchemeColors(composedScheme);
|
|
3853
3807
|
}
|
|
3854
3808
|
return jsonSchemes;
|
|
3855
3809
|
}
|
|
3856
|
-
function
|
|
3810
|
+
function refPalettesToJson() {
|
|
3857
3811
|
const jsonPalettes = {};
|
|
3858
|
-
const
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
"neutral",
|
|
3863
|
-
"neutral-variant"
|
|
3864
|
-
];
|
|
3865
|
-
for (const name of RAW_PALETTE_NAMES) {
|
|
3866
|
-
const palette = rawPalettes[name];
|
|
3867
|
-
const tones = {};
|
|
3868
|
-
for (const tone of MTB_TONES) {
|
|
3869
|
-
tones[tone.toString()] = hexFromArgb4(palette.tone(tone)).toUpperCase();
|
|
3812
|
+
for (const [name, tones] of Object.entries(refPalettes)) {
|
|
3813
|
+
const jsonTones = {};
|
|
3814
|
+
for (const { tone, argb } of tones) {
|
|
3815
|
+
jsonTones[tone.toString()] = hexFromArgb4(argb).toUpperCase();
|
|
3870
3816
|
}
|
|
3871
|
-
jsonPalettes[name] =
|
|
3817
|
+
jsonPalettes[name] = jsonTones;
|
|
3872
3818
|
}
|
|
3873
3819
|
return jsonPalettes;
|
|
3874
3820
|
}
|
|
@@ -3895,14 +3841,14 @@ function buildJson(ctx) {
|
|
|
3895
3841
|
name: c.name,
|
|
3896
3842
|
color: c.hex.toUpperCase(),
|
|
3897
3843
|
description: "",
|
|
3898
|
-
harmonized: c.blend
|
|
3844
|
+
harmonized: c.blend
|
|
3899
3845
|
}));
|
|
3900
3846
|
return {
|
|
3901
3847
|
seed,
|
|
3902
3848
|
coreColors,
|
|
3903
3849
|
extendedColors,
|
|
3904
3850
|
schemes: buildJsonSchemes(),
|
|
3905
|
-
palettes:
|
|
3851
|
+
palettes: refPalettesToJson()
|
|
3906
3852
|
};
|
|
3907
3853
|
}
|
|
3908
3854
|
|
|
@@ -4242,51 +4188,53 @@ function getPalette(palettes, colorName) {
|
|
|
4242
4188
|
}
|
|
4243
4189
|
return palette;
|
|
4244
4190
|
}
|
|
4245
|
-
function
|
|
4246
|
-
const
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
return [tokenName, argb];
|
|
4250
|
-
});
|
|
4251
|
-
const customVars = {};
|
|
4252
|
-
customColors.forEach((color) => {
|
|
4253
|
-
const colorname = color.name;
|
|
4254
|
-
const getPaletteForColor = () => getPalette(colorPalettes, colorname);
|
|
4255
|
-
const colorDynamicColor = new DynamicColor(
|
|
4191
|
+
function buildCustomColorRoles(colorname, palette) {
|
|
4192
|
+
const getPaletteForColor = () => palette;
|
|
4193
|
+
return {
|
|
4194
|
+
[colorname]: new DynamicColor(
|
|
4256
4195
|
colorname,
|
|
4257
4196
|
getPaletteForColor,
|
|
4258
4197
|
(s) => s.isDark ? 80 : 40,
|
|
4259
4198
|
// Main color: lighter in dark mode, darker in light mode
|
|
4260
4199
|
true
|
|
4261
4200
|
// background
|
|
4262
|
-
)
|
|
4263
|
-
|
|
4201
|
+
),
|
|
4202
|
+
[`on${upperFirst2(colorname)}`]: new DynamicColor(
|
|
4264
4203
|
`on${upperFirst2(colorname)}`,
|
|
4265
4204
|
getPaletteForColor,
|
|
4266
4205
|
(s) => s.isDark ? 20 : 100,
|
|
4267
4206
|
// Text on main color: high contrast (dark on light, light on dark)
|
|
4268
4207
|
false
|
|
4269
|
-
)
|
|
4270
|
-
|
|
4208
|
+
),
|
|
4209
|
+
[`${colorname}Container`]: new DynamicColor(
|
|
4271
4210
|
`${colorname}Container`,
|
|
4272
4211
|
getPaletteForColor,
|
|
4273
4212
|
(s) => s.isDark ? 30 : 90,
|
|
4274
4213
|
// Container: subtle variant (darker in dark mode, lighter in light mode)
|
|
4275
4214
|
true
|
|
4276
4215
|
// background
|
|
4277
|
-
)
|
|
4278
|
-
|
|
4216
|
+
),
|
|
4217
|
+
[`on${upperFirst2(colorname)}Container`]: new DynamicColor(
|
|
4279
4218
|
`on${upperFirst2(colorname)}Container`,
|
|
4280
4219
|
getPaletteForColor,
|
|
4281
4220
|
(s) => s.isDark ? 90 : 30,
|
|
4282
4221
|
// Text on container: high contrast against container background
|
|
4283
4222
|
false
|
|
4284
|
-
)
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4223
|
+
)
|
|
4224
|
+
};
|
|
4225
|
+
}
|
|
4226
|
+
function mergeBaseAndCustomColors(scheme, customColorRoles) {
|
|
4227
|
+
const baseVars = toRecord(tokenNames, (tokenName) => {
|
|
4228
|
+
const dynamicColor = MaterialDynamicColors2[tokenName];
|
|
4229
|
+
const argb = dynamicColor.getArgb(scheme);
|
|
4230
|
+
return [tokenName, argb];
|
|
4289
4231
|
});
|
|
4232
|
+
const customVars = {};
|
|
4233
|
+
for (const roles of Object.values(customColorRoles)) {
|
|
4234
|
+
for (const [tokenName, dynamicColor] of Object.entries(roles)) {
|
|
4235
|
+
customVars[tokenName] = dynamicColor.getArgb(scheme);
|
|
4236
|
+
}
|
|
4237
|
+
}
|
|
4290
4238
|
return { ...baseVars, ...customVars };
|
|
4291
4239
|
}
|
|
4292
4240
|
function createColorPalette(colorDef, baseScheme, effectiveSourceForHarmonization) {
|
|
@@ -4305,7 +4253,17 @@ function createColorPalette(colorDef, baseScheme, effectiveSourceForHarmonizatio
|
|
|
4305
4253
|
} else {
|
|
4306
4254
|
targetChroma = baseScheme.primaryPalette.chroma;
|
|
4307
4255
|
}
|
|
4308
|
-
return
|
|
4256
|
+
return TonalPalette.fromHueAndChroma(hct.hue, targetChroma);
|
|
4257
|
+
}
|
|
4258
|
+
function buildRefPalettes(allPalettes) {
|
|
4259
|
+
const refPalettes = {};
|
|
4260
|
+
for (const [name, palette] of Object.entries(allPalettes)) {
|
|
4261
|
+
refPalettes[kebabCase4(name)] = STANDARD_TONES.map((tone) => ({
|
|
4262
|
+
tone,
|
|
4263
|
+
argb: palette.tone(tone)
|
|
4264
|
+
}));
|
|
4265
|
+
}
|
|
4266
|
+
return refPalettes;
|
|
4309
4267
|
}
|
|
4310
4268
|
function buildTokenToPaletteMap(schemePalettes, scheme) {
|
|
4311
4269
|
const result = {};
|
|
@@ -4334,7 +4292,7 @@ function builder(hexSource, {
|
|
|
4334
4292
|
neutral,
|
|
4335
4293
|
neutralVariant,
|
|
4336
4294
|
error,
|
|
4337
|
-
customColors:
|
|
4295
|
+
customColors: customColorInputs = DEFAULT_CUSTOM_COLORS,
|
|
4338
4296
|
prefix = DEFAULT_PREFIX
|
|
4339
4297
|
} = {}) {
|
|
4340
4298
|
const cores = {
|
|
@@ -4345,9 +4303,12 @@ function builder(hexSource, {
|
|
|
4345
4303
|
neutral: optionalHex(neutral),
|
|
4346
4304
|
neutralVariant: optionalHex(neutralVariant)
|
|
4347
4305
|
};
|
|
4348
|
-
assertHexInputs(hexSource, cores,
|
|
4306
|
+
assertHexInputs(hexSource, cores, customColorInputs);
|
|
4307
|
+
const hexCustomColors = customColorInputs.map((c) => ({
|
|
4308
|
+
...c,
|
|
4309
|
+
blend: c.blend ?? DEFAULT_BLEND
|
|
4310
|
+
}));
|
|
4349
4311
|
const sourceArgb = argbFromHex2(hexSource);
|
|
4350
|
-
const sourceHct = Hct2.fromInt(sourceArgb);
|
|
4351
4312
|
const effectiveSource = cores.primary || hexSource;
|
|
4352
4313
|
const effectiveSourceArgb = argbFromHex2(effectiveSource);
|
|
4353
4314
|
const effectiveSourceForHarmonization = cores.primary ? argbFromHex2(cores.primary) : sourceArgb;
|
|
@@ -4438,18 +4399,21 @@ function builder(hexSource, {
|
|
|
4438
4399
|
};
|
|
4439
4400
|
const customColors = definedColors.filter((c) => !c.core).map((c) => ({
|
|
4440
4401
|
name: c.name,
|
|
4441
|
-
blend: c.blend ?? DEFAULT_BLEND,
|
|
4442
4402
|
value: argbFromHex2(c.hex)
|
|
4443
4403
|
}));
|
|
4404
|
+
const customColorRoles = Object.fromEntries(
|
|
4405
|
+
customColors.map((color) => [
|
|
4406
|
+
color.name,
|
|
4407
|
+
buildCustomColorRoles(color.name, getPalette(colorPalettes, color.name))
|
|
4408
|
+
])
|
|
4409
|
+
);
|
|
4444
4410
|
const mergedColorsLight = mergeBaseAndCustomColors(
|
|
4445
4411
|
lightScheme,
|
|
4446
|
-
|
|
4447
|
-
colorPalettes
|
|
4412
|
+
customColorRoles
|
|
4448
4413
|
);
|
|
4449
4414
|
const mergedColorsDark = mergeBaseAndCustomColors(
|
|
4450
4415
|
darkScheme,
|
|
4451
|
-
|
|
4452
|
-
colorPalettes
|
|
4416
|
+
customColorRoles
|
|
4453
4417
|
);
|
|
4454
4418
|
const schemePalettes = [
|
|
4455
4419
|
["primary", lightScheme.primaryPalette],
|
|
@@ -4460,6 +4424,7 @@ function builder(hexSource, {
|
|
|
4460
4424
|
["neutral-variant", lightScheme.neutralVariantPalette]
|
|
4461
4425
|
];
|
|
4462
4426
|
const tokenToPalette = buildTokenToPaletteMap(schemePalettes, lightScheme);
|
|
4427
|
+
const refPalettes = buildRefPalettes(allPalettes);
|
|
4463
4428
|
const allPaletteNamesKebab = new Set(Object.keys(allPalettes).map(kebabCase4));
|
|
4464
4429
|
const ctx = {
|
|
4465
4430
|
hexSource,
|
|
@@ -4472,11 +4437,11 @@ function builder(hexSource, {
|
|
|
4472
4437
|
neutralVariant,
|
|
4473
4438
|
error,
|
|
4474
4439
|
hexCustomColors,
|
|
4475
|
-
sourceHct,
|
|
4476
4440
|
effectiveSourceArgb,
|
|
4477
4441
|
primaryHct,
|
|
4478
4442
|
SchemeClass,
|
|
4479
4443
|
allPalettes,
|
|
4444
|
+
refPalettes,
|
|
4480
4445
|
mergedColorsLight,
|
|
4481
4446
|
mergedColorsDark,
|
|
4482
4447
|
tokenToPalette,
|
|
@@ -4494,7 +4459,8 @@ function builder(hexSource, {
|
|
|
4494
4459
|
toFlutter: () => buildFlutter(ctx),
|
|
4495
4460
|
mergedColorsLight,
|
|
4496
4461
|
mergedColorsDark,
|
|
4497
|
-
allPalettes
|
|
4462
|
+
allPalettes,
|
|
4463
|
+
customColorRoles
|
|
4498
4464
|
};
|
|
4499
4465
|
}
|
|
4500
4466
|
|