wensity 0.1.7 → 0.1.9
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 +5 -4
- package/dist/index.js +1626 -167
- package/package.json +10 -10
- package/LICENSE +0 -21
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/commands.ts
|
|
4
|
-
import { mkdir as
|
|
5
|
-
import { dirname as
|
|
4
|
+
import { mkdir as mkdir6, readFile as readFile6, writeFile as writeFile6 } from "fs/promises";
|
|
5
|
+
import { dirname as dirname7, join as join7 } from "path";
|
|
6
6
|
|
|
7
7
|
// src/constants.ts
|
|
8
8
|
var CLI_NAME = "wensity";
|
|
9
|
-
var CLI_VERSION = "0.1.
|
|
9
|
+
var CLI_VERSION = "0.1.9";
|
|
10
10
|
var CONFIG_FILE_NAME = "wensity.json";
|
|
11
11
|
var DEFAULT_API_ORIGIN = "https://ui.wensity.com";
|
|
12
12
|
var DEFAULT_REGISTRY_PATH = "/api/registry";
|
|
@@ -18,7 +18,9 @@ var INIT_PRIMITIVE_CSS_SLUG = "button";
|
|
|
18
18
|
var HELP_TEXT = `Wensity CLI ${CLI_VERSION}
|
|
19
19
|
|
|
20
20
|
Usage:
|
|
21
|
-
wensity init [--preset <code>] [--preset-file <path>] [options]
|
|
21
|
+
wensity init [--preset <code>] [--preset-file <path>] [--template next|vite|astro|react-router] [options]
|
|
22
|
+
wensity apply --preset <code> [options]
|
|
23
|
+
wensity preset inspect <code> [--json]
|
|
22
24
|
wensity login [options]
|
|
23
25
|
wensity logout
|
|
24
26
|
wensity whoami [--json]
|
|
@@ -28,7 +30,9 @@ Usage:
|
|
|
28
30
|
wensity version
|
|
29
31
|
|
|
30
32
|
Commands:
|
|
31
|
-
init Create wensity.json and local helper files (optional --preset applies style + CSS)
|
|
33
|
+
init Create wensity.json and local helper files (optional --preset applies style + CSS; optional --template scaffolds an app)
|
|
34
|
+
apply Apply a preset to an existing Wensity project
|
|
35
|
+
preset Inspect or work with shareable Wensity style presets
|
|
32
36
|
login Save a Wensity API token for premium component access
|
|
33
37
|
logout Remove saved CLI credentials
|
|
34
38
|
whoami Verify the saved token and print the authenticated account
|
|
@@ -44,6 +48,7 @@ Options:
|
|
|
44
48
|
--token <token> Provide a token non-interactively for login
|
|
45
49
|
--preset <code> Apply a shareable Wensity style preset (wsty1.\u2026); merges style when config exists
|
|
46
50
|
--preset-file <path> Read a preset code or JSON payload from a file
|
|
51
|
+
--template <name> Scaffold a new app before init: next, vite, astro, react-router
|
|
47
52
|
--force Overwrite generated files when adding or initializing
|
|
48
53
|
--no-install Write files without running the package manager
|
|
49
54
|
--dry-run Print planned writes and installs without changing files
|
|
@@ -53,8 +58,11 @@ Options:
|
|
|
53
58
|
|
|
54
59
|
Preset notes:
|
|
55
60
|
Generate codes at ${DEFAULT_API_ORIGIN}/docs/primitives/setup
|
|
61
|
+
preset inspect decodes the token, font packages, and resolved primitive tokens
|
|
62
|
+
apply --preset updates existing style + primitive CSS without scaffolding helper files
|
|
56
63
|
Plain init refuses an existing wensity.json unless --force
|
|
57
64
|
init --preset merges style + primitive CSS; does not rewrite installed source
|
|
65
|
+
init --template writes a minimal app scaffold in the current directory before Wensity files
|
|
58
66
|
add/update read style.iconLibrary for UI primitives only (Tabler|Lucide)
|
|
59
67
|
Invalid/expired/unsupported codes exit non-zero with an actionable message
|
|
60
68
|
`;
|
|
@@ -118,7 +126,7 @@ function hasFlag(args, name) {
|
|
|
118
126
|
return args.options.get(name) === true;
|
|
119
127
|
}
|
|
120
128
|
function expectsValue(name) {
|
|
121
|
-
return ["api-url", "registry", "token", "type", "preset", "preset-file"].includes(name);
|
|
129
|
+
return ["api-url", "registry", "token", "type", "preset", "preset-file", "template"].includes(name);
|
|
122
130
|
}
|
|
123
131
|
function normalizeOptionName(name) {
|
|
124
132
|
if (name === "dry") return "dry-run";
|
|
@@ -138,9 +146,14 @@ var BASE_COLOR_IDS = [
|
|
|
138
146
|
"inherit",
|
|
139
147
|
"neutral",
|
|
140
148
|
"zinc",
|
|
149
|
+
"gray",
|
|
141
150
|
"slate",
|
|
151
|
+
"cool-gray",
|
|
142
152
|
"stone",
|
|
143
|
-
"taupe"
|
|
153
|
+
"taupe",
|
|
154
|
+
"mauve",
|
|
155
|
+
"olive",
|
|
156
|
+
"mist"
|
|
144
157
|
];
|
|
145
158
|
var THEME_COLOR_IDS = [
|
|
146
159
|
"ink",
|
|
@@ -148,16 +161,68 @@ var THEME_COLOR_IDS = [
|
|
|
148
161
|
"blue",
|
|
149
162
|
"violet",
|
|
150
163
|
"green",
|
|
151
|
-
"orange"
|
|
164
|
+
"orange",
|
|
165
|
+
"amber",
|
|
166
|
+
"cyan",
|
|
167
|
+
"emerald",
|
|
168
|
+
"indigo",
|
|
169
|
+
"pink",
|
|
170
|
+
"purple",
|
|
171
|
+
"rose",
|
|
172
|
+
"sky",
|
|
173
|
+
"teal",
|
|
174
|
+
"yellow",
|
|
175
|
+
"fuchsia",
|
|
176
|
+
"lime"
|
|
152
177
|
];
|
|
153
178
|
var CHART_PALETTE_IDS = [
|
|
154
179
|
"theme",
|
|
155
180
|
"warm",
|
|
156
181
|
"cool",
|
|
157
|
-
"mixed"
|
|
182
|
+
"mixed",
|
|
183
|
+
"neutral",
|
|
184
|
+
"zinc",
|
|
185
|
+
"stone",
|
|
186
|
+
"gray",
|
|
187
|
+
"amber",
|
|
188
|
+
"cyan",
|
|
189
|
+
"emerald",
|
|
190
|
+
"indigo",
|
|
191
|
+
"lime",
|
|
192
|
+
"pink",
|
|
193
|
+
"purple",
|
|
194
|
+
"rose",
|
|
195
|
+
"sky",
|
|
196
|
+
"teal",
|
|
197
|
+
"yellow",
|
|
198
|
+
"taupe"
|
|
199
|
+
];
|
|
200
|
+
var HEADING_FONT_IDS = [
|
|
201
|
+
"system",
|
|
202
|
+
"playfair",
|
|
203
|
+
"instrument-serif",
|
|
204
|
+
"fraunces",
|
|
205
|
+
"space-grotesk",
|
|
206
|
+
"noto-serif",
|
|
207
|
+
"eb-garamond",
|
|
208
|
+
"lora",
|
|
209
|
+
"montserrat",
|
|
210
|
+
"manrope",
|
|
211
|
+
"inter"
|
|
212
|
+
];
|
|
213
|
+
var BODY_FONT_IDS = [
|
|
214
|
+
"system",
|
|
215
|
+
"inter",
|
|
216
|
+
"geist",
|
|
217
|
+
"dm-sans",
|
|
218
|
+
"plus-jakarta-sans",
|
|
219
|
+
"figtree",
|
|
220
|
+
"noto-sans",
|
|
221
|
+
"public-sans",
|
|
222
|
+
"outfit",
|
|
223
|
+
"manrope",
|
|
224
|
+
"ibm-plex-sans"
|
|
158
225
|
];
|
|
159
|
-
var HEADING_FONT_IDS = ["system", "playfair"];
|
|
160
|
-
var BODY_FONT_IDS = ["system", "inter"];
|
|
161
226
|
var RADIUS_PRESET_CSS = {
|
|
162
227
|
none: "0px",
|
|
163
228
|
small: "0.5rem",
|
|
@@ -274,8 +339,8 @@ var DEFAULT_STYLE_CONFIG_CANONICAL = {
|
|
|
274
339
|
baseColor: "inherit",
|
|
275
340
|
themeColor: "ink",
|
|
276
341
|
chartPalette: "theme",
|
|
277
|
-
headingFont: "
|
|
278
|
-
bodyFont: "
|
|
342
|
+
headingFont: "inter",
|
|
343
|
+
bodyFont: "inter",
|
|
279
344
|
iconLibrary: "tabler",
|
|
280
345
|
radius: "medium"
|
|
281
346
|
};
|
|
@@ -604,7 +669,7 @@ function validateStyleConfigCanonicalPartial(value) {
|
|
|
604
669
|
if ("baseColor" in value) {
|
|
605
670
|
if (typeof value.baseColor !== "string" || !isBaseColorId(value.baseColor)) {
|
|
606
671
|
throw new PresetValidationError(
|
|
607
|
-
"Invalid style.baseColor. Expected inherit | neutral | zinc | slate | stone | taupe.",
|
|
672
|
+
"Invalid style.baseColor. Expected inherit | neutral | zinc | gray | slate | cool-gray | stone | taupe.",
|
|
608
673
|
"style.baseColor"
|
|
609
674
|
);
|
|
610
675
|
}
|
|
@@ -613,7 +678,7 @@ function validateStyleConfigCanonicalPartial(value) {
|
|
|
613
678
|
if ("themeColor" in value) {
|
|
614
679
|
if (typeof value.themeColor !== "string" || !isThemeColorId(value.themeColor)) {
|
|
615
680
|
throw new PresetValidationError(
|
|
616
|
-
"Invalid style.themeColor. Expected
|
|
681
|
+
"Invalid style.themeColor. Expected a supported theme color id.",
|
|
617
682
|
"style.themeColor"
|
|
618
683
|
);
|
|
619
684
|
}
|
|
@@ -622,7 +687,7 @@ function validateStyleConfigCanonicalPartial(value) {
|
|
|
622
687
|
if ("chartPalette" in value) {
|
|
623
688
|
if (typeof value.chartPalette !== "string" || !isChartPaletteId(value.chartPalette)) {
|
|
624
689
|
throw new PresetValidationError(
|
|
625
|
-
"Invalid style.chartPalette. Expected
|
|
690
|
+
"Invalid style.chartPalette. Expected a supported chart palette id.",
|
|
626
691
|
"style.chartPalette"
|
|
627
692
|
);
|
|
628
693
|
}
|
|
@@ -631,7 +696,7 @@ function validateStyleConfigCanonicalPartial(value) {
|
|
|
631
696
|
if ("headingFont" in value) {
|
|
632
697
|
if (typeof value.headingFont !== "string" || !isHeadingFontId(value.headingFont)) {
|
|
633
698
|
throw new PresetValidationError(
|
|
634
|
-
"Invalid style.headingFont. Expected
|
|
699
|
+
"Invalid style.headingFont. Expected a supported heading font id.",
|
|
635
700
|
"style.headingFont"
|
|
636
701
|
);
|
|
637
702
|
}
|
|
@@ -640,7 +705,7 @@ function validateStyleConfigCanonicalPartial(value) {
|
|
|
640
705
|
if ("bodyFont" in value) {
|
|
641
706
|
if (typeof value.bodyFont !== "string" || !isBodyFontId(value.bodyFont)) {
|
|
642
707
|
throw new PresetValidationError(
|
|
643
|
-
"Invalid style.bodyFont. Expected
|
|
708
|
+
"Invalid style.bodyFont. Expected a supported body font id.",
|
|
644
709
|
"style.bodyFont"
|
|
645
710
|
);
|
|
646
711
|
}
|
|
@@ -769,6 +834,29 @@ function utf8ByteLength(text) {
|
|
|
769
834
|
return new TextEncoder().encode(text).byteLength;
|
|
770
835
|
}
|
|
771
836
|
var BASE64URL_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
837
|
+
var COMPACT_CANONICAL_LEGACY_PREFIX = "c";
|
|
838
|
+
var COMPACT_CANONICAL_PREFIX = "d";
|
|
839
|
+
var COMPACT_CANONICAL_EXPANDED_PREFIX = "e";
|
|
840
|
+
var COMPACT_CANONICAL_CHART_PREFIX = "f";
|
|
841
|
+
var COMPACT_CANONICAL_THEME_PREFIX = "g";
|
|
842
|
+
var COMPACT_CANONICAL_BASE_PREFIX = "h";
|
|
843
|
+
var COMPACT_CANONICAL_BODY_LENGTH = 3;
|
|
844
|
+
var COMPACT_CANONICAL_ENCODED_LENGTH = COMPACT_CANONICAL_PREFIX.length + COMPACT_CANONICAL_BODY_LENGTH;
|
|
845
|
+
var COMPACT_CANONICAL_EXPANDED_BODY_LENGTH = 4;
|
|
846
|
+
var COMPACT_CANONICAL_EXPANDED_ENCODED_LENGTH = COMPACT_CANONICAL_EXPANDED_PREFIX.length + COMPACT_CANONICAL_EXPANDED_BODY_LENGTH;
|
|
847
|
+
var COMPACT_CANONICAL_CHART_ENCODED_LENGTH = COMPACT_CANONICAL_CHART_PREFIX.length + COMPACT_CANONICAL_EXPANDED_BODY_LENGTH;
|
|
848
|
+
var COMPACT_CANONICAL_THEME_ENCODED_LENGTH = COMPACT_CANONICAL_THEME_PREFIX.length + COMPACT_CANONICAL_EXPANDED_BODY_LENGTH;
|
|
849
|
+
var COMPACT_CANONICAL_BASE_BODY_LENGTH = 5;
|
|
850
|
+
var COMPACT_CANONICAL_BASE_ENCODED_LENGTH = COMPACT_CANONICAL_BASE_PREFIX.length + COMPACT_CANONICAL_BASE_BODY_LENGTH;
|
|
851
|
+
var COMPACT_CANONICAL_LEGACY_BASE_MAX_INDEX = 7;
|
|
852
|
+
var COMPACT_CANONICAL_LEGACY_THEME_MAX_INDEX = 5;
|
|
853
|
+
var COMPACT_CANONICAL_LEGACY_CHART_MAX_INDEX = 3;
|
|
854
|
+
var COMPACT_CANONICAL_LEGACY_FONT_MAX_INDEX = 1;
|
|
855
|
+
var COMPACT_CANONICAL_FONT_MAX_INDEX = 7;
|
|
856
|
+
var COMPACT_CANONICAL_EXPANDED_FONT_MAX_INDEX = 15;
|
|
857
|
+
var COMPACT_CANONICAL_EXPANDED_CHART_MAX_INDEX = 31;
|
|
858
|
+
var COMPACT_CANONICAL_EXPANDED_THEME_MAX_INDEX = 31;
|
|
859
|
+
var COMPACT_CANONICAL_EXPANDED_BASE_MAX_INDEX = 31;
|
|
772
860
|
function toBase64Url(bytes) {
|
|
773
861
|
let out = "";
|
|
774
862
|
for (let i = 0; i < bytes.length; i += 3) {
|
|
@@ -808,6 +896,242 @@ function fromBase64Url(code) {
|
|
|
808
896
|
}
|
|
809
897
|
return outIndex === out.length ? out : out.subarray(0, outIndex);
|
|
810
898
|
}
|
|
899
|
+
function indexOfPresetValue(values, value, path) {
|
|
900
|
+
const index = values.indexOf(value);
|
|
901
|
+
if (index < 0) {
|
|
902
|
+
throw new PresetValidationError(`Invalid compact preset value at ${path}.`, path);
|
|
903
|
+
}
|
|
904
|
+
return index;
|
|
905
|
+
}
|
|
906
|
+
function readCompactChar(char) {
|
|
907
|
+
if (!char) return -1;
|
|
908
|
+
return BASE64URL_ALPHABET.indexOf(char);
|
|
909
|
+
}
|
|
910
|
+
function encodeCompactCanonicalPayload(payload) {
|
|
911
|
+
const baseColorIndex = indexOfPresetValue(BASE_COLOR_IDS, payload.baseColor, "preset.baseColor");
|
|
912
|
+
const themeColorIndex = indexOfPresetValue(
|
|
913
|
+
THEME_COLOR_IDS,
|
|
914
|
+
payload.themeColor,
|
|
915
|
+
"preset.themeColor"
|
|
916
|
+
);
|
|
917
|
+
const chartPaletteIndex = indexOfPresetValue(
|
|
918
|
+
CHART_PALETTE_IDS,
|
|
919
|
+
payload.chartPalette,
|
|
920
|
+
"preset.chartPalette"
|
|
921
|
+
);
|
|
922
|
+
const headingFontIndex = indexOfPresetValue(
|
|
923
|
+
HEADING_FONT_IDS,
|
|
924
|
+
payload.headingFont,
|
|
925
|
+
"preset.headingFont"
|
|
926
|
+
);
|
|
927
|
+
const bodyFontIndex = indexOfPresetValue(BODY_FONT_IDS, payload.bodyFont, "preset.bodyFont");
|
|
928
|
+
const iconLibraryIndex = indexOfPresetValue(
|
|
929
|
+
ICON_LIBRARIES,
|
|
930
|
+
payload.iconLibrary,
|
|
931
|
+
"preset.iconLibrary"
|
|
932
|
+
);
|
|
933
|
+
const radiusIndex = indexOfPresetValue(RADIUS_PRESETS, payload.radius, "preset.radius");
|
|
934
|
+
if (baseColorIndex > 7) {
|
|
935
|
+
if (baseColorIndex > COMPACT_CANONICAL_EXPANDED_BASE_MAX_INDEX) {
|
|
936
|
+
throw new PresetValidationError(
|
|
937
|
+
"Too many curated base colors for compact preset encoding.",
|
|
938
|
+
"preset.baseColor"
|
|
939
|
+
);
|
|
940
|
+
}
|
|
941
|
+
if (themeColorIndex > COMPACT_CANONICAL_EXPANDED_THEME_MAX_INDEX) {
|
|
942
|
+
throw new PresetValidationError(
|
|
943
|
+
"Too many curated theme colors for compact preset encoding.",
|
|
944
|
+
"preset.themeColor"
|
|
945
|
+
);
|
|
946
|
+
}
|
|
947
|
+
if (chartPaletteIndex > COMPACT_CANONICAL_EXPANDED_CHART_MAX_INDEX) {
|
|
948
|
+
throw new PresetValidationError(
|
|
949
|
+
"Too many curated chart palettes for compact preset encoding.",
|
|
950
|
+
"preset.chartPalette"
|
|
951
|
+
);
|
|
952
|
+
}
|
|
953
|
+
if (headingFontIndex > COMPACT_CANONICAL_EXPANDED_FONT_MAX_INDEX || bodyFontIndex > COMPACT_CANONICAL_EXPANDED_FONT_MAX_INDEX) {
|
|
954
|
+
throw new PresetValidationError(
|
|
955
|
+
"Too many curated fonts for compact preset encoding.",
|
|
956
|
+
"preset.headingFont"
|
|
957
|
+
);
|
|
958
|
+
}
|
|
959
|
+
let baseValue = baseColorIndex;
|
|
960
|
+
baseValue = baseValue << 5 | themeColorIndex;
|
|
961
|
+
baseValue = baseValue << 5 | chartPaletteIndex;
|
|
962
|
+
baseValue = baseValue << 4 | headingFontIndex;
|
|
963
|
+
baseValue = baseValue << 4 | bodyFontIndex;
|
|
964
|
+
baseValue = baseValue << 1 | iconLibraryIndex;
|
|
965
|
+
baseValue = baseValue << 2 | radiusIndex;
|
|
966
|
+
return encodeCompactCanonicalValue(
|
|
967
|
+
COMPACT_CANONICAL_BASE_PREFIX,
|
|
968
|
+
baseValue,
|
|
969
|
+
COMPACT_CANONICAL_BASE_BODY_LENGTH
|
|
970
|
+
);
|
|
971
|
+
}
|
|
972
|
+
if (themeColorIndex > 7) {
|
|
973
|
+
if (themeColorIndex > COMPACT_CANONICAL_EXPANDED_THEME_MAX_INDEX) {
|
|
974
|
+
throw new PresetValidationError(
|
|
975
|
+
"Too many curated theme colors for compact preset encoding.",
|
|
976
|
+
"preset.themeColor"
|
|
977
|
+
);
|
|
978
|
+
}
|
|
979
|
+
if (chartPaletteIndex > COMPACT_CANONICAL_EXPANDED_CHART_MAX_INDEX) {
|
|
980
|
+
throw new PresetValidationError(
|
|
981
|
+
"Too many curated chart palettes for compact preset encoding.",
|
|
982
|
+
"preset.chartPalette"
|
|
983
|
+
);
|
|
984
|
+
}
|
|
985
|
+
if (headingFontIndex > COMPACT_CANONICAL_EXPANDED_FONT_MAX_INDEX || bodyFontIndex > COMPACT_CANONICAL_EXPANDED_FONT_MAX_INDEX) {
|
|
986
|
+
throw new PresetValidationError(
|
|
987
|
+
"Too many curated fonts for compact preset encoding.",
|
|
988
|
+
"preset.headingFont"
|
|
989
|
+
);
|
|
990
|
+
}
|
|
991
|
+
let themeValue = baseColorIndex;
|
|
992
|
+
themeValue = themeValue << 5 | themeColorIndex;
|
|
993
|
+
themeValue = themeValue << 5 | chartPaletteIndex;
|
|
994
|
+
themeValue = themeValue << 4 | headingFontIndex;
|
|
995
|
+
themeValue = themeValue << 4 | bodyFontIndex;
|
|
996
|
+
themeValue = themeValue << 1 | iconLibraryIndex;
|
|
997
|
+
themeValue = themeValue << 2 | radiusIndex;
|
|
998
|
+
return encodeCompactCanonicalValue(
|
|
999
|
+
COMPACT_CANONICAL_THEME_PREFIX,
|
|
1000
|
+
themeValue,
|
|
1001
|
+
COMPACT_CANONICAL_EXPANDED_BODY_LENGTH
|
|
1002
|
+
);
|
|
1003
|
+
}
|
|
1004
|
+
if (baseColorIndex <= COMPACT_CANONICAL_LEGACY_BASE_MAX_INDEX && themeColorIndex <= COMPACT_CANONICAL_LEGACY_THEME_MAX_INDEX && chartPaletteIndex <= COMPACT_CANONICAL_LEGACY_CHART_MAX_INDEX && headingFontIndex <= COMPACT_CANONICAL_LEGACY_FONT_MAX_INDEX && bodyFontIndex <= COMPACT_CANONICAL_LEGACY_FONT_MAX_INDEX) {
|
|
1005
|
+
let legacyValue = baseColorIndex;
|
|
1006
|
+
legacyValue = legacyValue << 3 | themeColorIndex;
|
|
1007
|
+
legacyValue = legacyValue << 2 | chartPaletteIndex;
|
|
1008
|
+
legacyValue = legacyValue << 1 | headingFontIndex;
|
|
1009
|
+
legacyValue = legacyValue << 1 | bodyFontIndex;
|
|
1010
|
+
legacyValue = legacyValue << 1 | iconLibraryIndex;
|
|
1011
|
+
legacyValue = legacyValue << 2 | radiusIndex;
|
|
1012
|
+
return encodeCompactCanonicalValue(COMPACT_CANONICAL_LEGACY_PREFIX, legacyValue);
|
|
1013
|
+
}
|
|
1014
|
+
if (chartPaletteIndex > 3) {
|
|
1015
|
+
if (chartPaletteIndex > COMPACT_CANONICAL_EXPANDED_CHART_MAX_INDEX) {
|
|
1016
|
+
throw new PresetValidationError(
|
|
1017
|
+
"Too many curated chart palettes for compact preset encoding.",
|
|
1018
|
+
"preset.chartPalette"
|
|
1019
|
+
);
|
|
1020
|
+
}
|
|
1021
|
+
if (headingFontIndex > COMPACT_CANONICAL_EXPANDED_FONT_MAX_INDEX || bodyFontIndex > COMPACT_CANONICAL_EXPANDED_FONT_MAX_INDEX) {
|
|
1022
|
+
throw new PresetValidationError(
|
|
1023
|
+
"Too many curated fonts for compact preset encoding.",
|
|
1024
|
+
"preset.headingFont"
|
|
1025
|
+
);
|
|
1026
|
+
}
|
|
1027
|
+
let chartValue = baseColorIndex;
|
|
1028
|
+
chartValue = chartValue << 3 | themeColorIndex;
|
|
1029
|
+
chartValue = chartValue << 5 | chartPaletteIndex;
|
|
1030
|
+
chartValue = chartValue << 4 | headingFontIndex;
|
|
1031
|
+
chartValue = chartValue << 4 | bodyFontIndex;
|
|
1032
|
+
chartValue = chartValue << 1 | iconLibraryIndex;
|
|
1033
|
+
chartValue = chartValue << 2 | radiusIndex;
|
|
1034
|
+
return encodeCompactCanonicalValue(
|
|
1035
|
+
COMPACT_CANONICAL_CHART_PREFIX,
|
|
1036
|
+
chartValue,
|
|
1037
|
+
COMPACT_CANONICAL_EXPANDED_BODY_LENGTH
|
|
1038
|
+
);
|
|
1039
|
+
}
|
|
1040
|
+
if (headingFontIndex > COMPACT_CANONICAL_FONT_MAX_INDEX || bodyFontIndex > COMPACT_CANONICAL_FONT_MAX_INDEX) {
|
|
1041
|
+
if (headingFontIndex > COMPACT_CANONICAL_EXPANDED_FONT_MAX_INDEX || bodyFontIndex > COMPACT_CANONICAL_EXPANDED_FONT_MAX_INDEX) {
|
|
1042
|
+
throw new PresetValidationError(
|
|
1043
|
+
"Too many curated fonts for compact preset encoding.",
|
|
1044
|
+
"preset.headingFont"
|
|
1045
|
+
);
|
|
1046
|
+
}
|
|
1047
|
+
let expandedValue = baseColorIndex;
|
|
1048
|
+
expandedValue = expandedValue << 3 | themeColorIndex;
|
|
1049
|
+
expandedValue = expandedValue << 2 | chartPaletteIndex;
|
|
1050
|
+
expandedValue = expandedValue << 4 | headingFontIndex;
|
|
1051
|
+
expandedValue = expandedValue << 4 | bodyFontIndex;
|
|
1052
|
+
expandedValue = expandedValue << 1 | iconLibraryIndex;
|
|
1053
|
+
expandedValue = expandedValue << 2 | radiusIndex;
|
|
1054
|
+
return encodeCompactCanonicalValue(
|
|
1055
|
+
COMPACT_CANONICAL_EXPANDED_PREFIX,
|
|
1056
|
+
expandedValue,
|
|
1057
|
+
COMPACT_CANONICAL_EXPANDED_BODY_LENGTH
|
|
1058
|
+
);
|
|
1059
|
+
}
|
|
1060
|
+
let value = baseColorIndex;
|
|
1061
|
+
value = value << 3 | themeColorIndex;
|
|
1062
|
+
value = value << 2 | chartPaletteIndex;
|
|
1063
|
+
value = value << 3 | headingFontIndex;
|
|
1064
|
+
value = value << 3 | bodyFontIndex;
|
|
1065
|
+
value = value << 1 | iconLibraryIndex;
|
|
1066
|
+
value = value << 2 | radiusIndex;
|
|
1067
|
+
return encodeCompactCanonicalValue(
|
|
1068
|
+
COMPACT_CANONICAL_PREFIX,
|
|
1069
|
+
value,
|
|
1070
|
+
COMPACT_CANONICAL_BODY_LENGTH
|
|
1071
|
+
);
|
|
1072
|
+
}
|
|
1073
|
+
function encodeCompactCanonicalValue(prefix, value, bodyLength = 3) {
|
|
1074
|
+
let out = prefix;
|
|
1075
|
+
for (let shift = (bodyLength - 1) * 6; shift >= 0; shift -= 6) {
|
|
1076
|
+
out += BASE64URL_ALPHABET[value >> shift & 63];
|
|
1077
|
+
}
|
|
1078
|
+
return out;
|
|
1079
|
+
}
|
|
1080
|
+
function decodeCompactCanonicalPayload(encoded) {
|
|
1081
|
+
const isLegacyCompact = encoded.startsWith(COMPACT_CANONICAL_LEGACY_PREFIX);
|
|
1082
|
+
const isCurrentCompact = encoded.startsWith(COMPACT_CANONICAL_PREFIX);
|
|
1083
|
+
const isExpandedCompact = encoded.startsWith(COMPACT_CANONICAL_EXPANDED_PREFIX);
|
|
1084
|
+
const isChartCompact = encoded.startsWith(COMPACT_CANONICAL_CHART_PREFIX);
|
|
1085
|
+
const isThemeCompact = encoded.startsWith(COMPACT_CANONICAL_THEME_PREFIX);
|
|
1086
|
+
const isBaseCompact = encoded.startsWith(COMPACT_CANONICAL_BASE_PREFIX);
|
|
1087
|
+
const expectedLength = isExpandedCompact ? COMPACT_CANONICAL_EXPANDED_ENCODED_LENGTH : isChartCompact ? COMPACT_CANONICAL_CHART_ENCODED_LENGTH : isThemeCompact ? COMPACT_CANONICAL_THEME_ENCODED_LENGTH : isBaseCompact ? COMPACT_CANONICAL_BASE_ENCODED_LENGTH : COMPACT_CANONICAL_ENCODED_LENGTH;
|
|
1088
|
+
if (encoded.length !== expectedLength || !isCurrentCompact && !isLegacyCompact && !isExpandedCompact && !isChartCompact && !isThemeCompact && !isBaseCompact) {
|
|
1089
|
+
throw new PresetValidationError("Compact preset code has an invalid length.", "preset");
|
|
1090
|
+
}
|
|
1091
|
+
let value = 0;
|
|
1092
|
+
for (let i = 1; i < encoded.length; i += 1) {
|
|
1093
|
+
const char = readCompactChar(encoded[i]);
|
|
1094
|
+
if (char < 0) {
|
|
1095
|
+
throw new PresetValidationError("Compact preset code is not valid base64url.", "preset");
|
|
1096
|
+
}
|
|
1097
|
+
value = value << 6 | char;
|
|
1098
|
+
}
|
|
1099
|
+
const radius = RADIUS_PRESETS[value & 3];
|
|
1100
|
+
value >>= 2;
|
|
1101
|
+
const iconLibrary = ICON_LIBRARIES[value & 1];
|
|
1102
|
+
value >>= 1;
|
|
1103
|
+
const fontMask = isLegacyCompact ? 1 : isExpandedCompact || isChartCompact || isThemeCompact || isBaseCompact ? 15 : 7;
|
|
1104
|
+
const fontShift = isLegacyCompact ? 1 : isExpandedCompact || isChartCompact || isThemeCompact || isBaseCompact ? 4 : 3;
|
|
1105
|
+
const bodyFont = BODY_FONT_IDS[value & fontMask];
|
|
1106
|
+
value >>= fontShift;
|
|
1107
|
+
const headingFont = HEADING_FONT_IDS[value & fontMask];
|
|
1108
|
+
value >>= fontShift;
|
|
1109
|
+
const chartMask = isChartCompact || isThemeCompact || isBaseCompact ? 31 : 3;
|
|
1110
|
+
const chartShift = isChartCompact || isThemeCompact || isBaseCompact ? 5 : 2;
|
|
1111
|
+
const chartPalette = CHART_PALETTE_IDS[value & chartMask];
|
|
1112
|
+
value >>= chartShift;
|
|
1113
|
+
const themeMask = isThemeCompact || isBaseCompact ? 31 : 7;
|
|
1114
|
+
const themeShift = isThemeCompact || isBaseCompact ? 5 : 3;
|
|
1115
|
+
const themeColor = THEME_COLOR_IDS[value & themeMask];
|
|
1116
|
+
value >>= themeShift;
|
|
1117
|
+
const baseMask = isBaseCompact ? 31 : 7;
|
|
1118
|
+
const baseShift = isBaseCompact ? 5 : 3;
|
|
1119
|
+
const baseColor = BASE_COLOR_IDS[value & baseMask];
|
|
1120
|
+
value >>= baseShift;
|
|
1121
|
+
if (value !== 0 || !baseColor || !themeColor || !chartPalette || !headingFont || !bodyFont || !iconLibrary || !radius) {
|
|
1122
|
+
throw new PresetValidationError("Compact preset code contains an out-of-range value.", "preset");
|
|
1123
|
+
}
|
|
1124
|
+
return {
|
|
1125
|
+
v: 2,
|
|
1126
|
+
baseColor,
|
|
1127
|
+
themeColor,
|
|
1128
|
+
chartPalette,
|
|
1129
|
+
headingFont,
|
|
1130
|
+
bodyFont,
|
|
1131
|
+
iconLibrary,
|
|
1132
|
+
radius
|
|
1133
|
+
};
|
|
1134
|
+
}
|
|
811
1135
|
function stableStringifyCodecPayload(payload) {
|
|
812
1136
|
const parts = [
|
|
813
1137
|
`"v":${payload.v}`,
|
|
@@ -994,25 +1318,25 @@ function validateCodecPayloadCanonical(value) {
|
|
|
994
1318
|
}
|
|
995
1319
|
if (typeof value.themeColor !== "string" || !isThemeColorId(value.themeColor)) {
|
|
996
1320
|
throw new PresetValidationError(
|
|
997
|
-
"Invalid preset.themeColor. Expected
|
|
1321
|
+
"Invalid preset.themeColor. Expected a supported theme color id.",
|
|
998
1322
|
"preset.themeColor"
|
|
999
1323
|
);
|
|
1000
1324
|
}
|
|
1001
1325
|
if (typeof value.chartPalette !== "string" || !isChartPaletteId(value.chartPalette)) {
|
|
1002
1326
|
throw new PresetValidationError(
|
|
1003
|
-
"Invalid preset.chartPalette. Expected
|
|
1327
|
+
"Invalid preset.chartPalette. Expected a supported chart palette id.",
|
|
1004
1328
|
"preset.chartPalette"
|
|
1005
1329
|
);
|
|
1006
1330
|
}
|
|
1007
1331
|
if (typeof value.headingFont !== "string" || !isHeadingFontId(value.headingFont)) {
|
|
1008
1332
|
throw new PresetValidationError(
|
|
1009
|
-
"Invalid preset.headingFont. Expected
|
|
1333
|
+
"Invalid preset.headingFont. Expected a supported heading font id.",
|
|
1010
1334
|
"preset.headingFont"
|
|
1011
1335
|
);
|
|
1012
1336
|
}
|
|
1013
1337
|
if (typeof value.bodyFont !== "string" || !isBodyFontId(value.bodyFont)) {
|
|
1014
1338
|
throw new PresetValidationError(
|
|
1015
|
-
"Invalid preset.bodyFont. Expected
|
|
1339
|
+
"Invalid preset.bodyFont. Expected a supported body font id.",
|
|
1016
1340
|
"preset.bodyFont"
|
|
1017
1341
|
);
|
|
1018
1342
|
}
|
|
@@ -1039,18 +1363,6 @@ function validateCodecPayloadCanonical(value) {
|
|
|
1039
1363
|
radius: value.radius
|
|
1040
1364
|
};
|
|
1041
1365
|
}
|
|
1042
|
-
function stableStringifyCodecPayloadCanonical(payload) {
|
|
1043
|
-
return `{${[
|
|
1044
|
-
`"v":${payload.v}`,
|
|
1045
|
-
`"baseColor":${JSON.stringify(payload.baseColor)}`,
|
|
1046
|
-
`"themeColor":${JSON.stringify(payload.themeColor)}`,
|
|
1047
|
-
`"chartPalette":${JSON.stringify(payload.chartPalette)}`,
|
|
1048
|
-
`"headingFont":${JSON.stringify(payload.headingFont)}`,
|
|
1049
|
-
`"bodyFont":${JSON.stringify(payload.bodyFont)}`,
|
|
1050
|
-
`"iconLibrary":${JSON.stringify(payload.iconLibrary)}`,
|
|
1051
|
-
`"radius":${JSON.stringify(payload.radius)}`
|
|
1052
|
-
].join(",")}}`;
|
|
1053
|
-
}
|
|
1054
1366
|
function encodePresetCanonical(style) {
|
|
1055
1367
|
const normalized = normalizeStyleConfigCanonical(style);
|
|
1056
1368
|
const payload = {
|
|
@@ -1063,15 +1375,7 @@ function encodePresetCanonical(style) {
|
|
|
1063
1375
|
iconLibrary: normalized.iconLibrary,
|
|
1064
1376
|
radius: normalized.radius
|
|
1065
1377
|
};
|
|
1066
|
-
const
|
|
1067
|
-
const bytes = new TextEncoder().encode(json);
|
|
1068
|
-
if (bytes.byteLength > PRESET_CODEC_MAX_DECODED_JSON_BYTES) {
|
|
1069
|
-
throw new PresetValidationError(
|
|
1070
|
-
`Preset JSON exceeds ${PRESET_CODEC_MAX_DECODED_JSON_BYTES} bytes.`,
|
|
1071
|
-
"preset"
|
|
1072
|
-
);
|
|
1073
|
-
}
|
|
1074
|
-
const code = `${PRESET_CODEC_PREFIX}.${toBase64Url(bytes)}`;
|
|
1378
|
+
const code = `${PRESET_CODEC_PREFIX}.${encodeCompactCanonicalPayload(payload)}`;
|
|
1075
1379
|
if (code.length > PRESET_CODEC_MAX_CODE_LENGTH) {
|
|
1076
1380
|
throw new PresetValidationError(
|
|
1077
1381
|
`Preset code exceeds ${PRESET_CODEC_MAX_CODE_LENGTH} characters.`,
|
|
@@ -1101,6 +1405,9 @@ function decodePresetEnvelope(code) {
|
|
|
1101
1405
|
if (!encoded) {
|
|
1102
1406
|
throw new PresetValidationError("Preset code payload is empty.", "preset");
|
|
1103
1407
|
}
|
|
1408
|
+
if ((encoded.length === COMPACT_CANONICAL_ENCODED_LENGTH || encoded.length === COMPACT_CANONICAL_EXPANDED_ENCODED_LENGTH || encoded.length === COMPACT_CANONICAL_CHART_ENCODED_LENGTH || encoded.length === COMPACT_CANONICAL_THEME_ENCODED_LENGTH || encoded.length === COMPACT_CANONICAL_BASE_ENCODED_LENGTH) && (encoded.startsWith(COMPACT_CANONICAL_PREFIX) || encoded.startsWith(COMPACT_CANONICAL_LEGACY_PREFIX) || encoded.startsWith(COMPACT_CANONICAL_EXPANDED_PREFIX) || encoded.startsWith(COMPACT_CANONICAL_CHART_PREFIX) || encoded.startsWith(COMPACT_CANONICAL_THEME_PREFIX) || encoded.startsWith(COMPACT_CANONICAL_BASE_PREFIX))) {
|
|
1409
|
+
return decodeCompactCanonicalPayload(encoded);
|
|
1410
|
+
}
|
|
1104
1411
|
if (encoded.includes("=") || /[^A-Za-z0-9_-]/.test(encoded)) {
|
|
1105
1412
|
throw new PresetValidationError("Preset code payload is not valid unpadded base64url.", "preset");
|
|
1106
1413
|
}
|
|
@@ -1229,8 +1536,8 @@ var LUCIDE_TO_TABLER = Object.fromEntries(
|
|
|
1229
1536
|
var BASE_COLOR_PALETTE = {
|
|
1230
1537
|
zinc: {
|
|
1231
1538
|
light: {
|
|
1232
|
-
surfaceElevated: "#
|
|
1233
|
-
surfaceOverlay: "#
|
|
1539
|
+
surfaceElevated: "#fafafa",
|
|
1540
|
+
surfaceOverlay: "#f4f4f5",
|
|
1234
1541
|
foreground: "#09090b",
|
|
1235
1542
|
border: "rgba(9, 9, 11, 0.08)",
|
|
1236
1543
|
mutedForeground: "#71717a"
|
|
@@ -1245,8 +1552,8 @@ var BASE_COLOR_PALETTE = {
|
|
|
1245
1552
|
},
|
|
1246
1553
|
neutral: {
|
|
1247
1554
|
light: {
|
|
1248
|
-
surfaceElevated: "#
|
|
1249
|
-
surfaceOverlay: "#
|
|
1555
|
+
surfaceElevated: "#fafafa",
|
|
1556
|
+
surfaceOverlay: "#f5f5f5",
|
|
1250
1557
|
foreground: "#171717",
|
|
1251
1558
|
border: "rgba(23, 23, 23, 0.08)",
|
|
1252
1559
|
mutedForeground: "#737373"
|
|
@@ -1259,10 +1566,26 @@ var BASE_COLOR_PALETTE = {
|
|
|
1259
1566
|
mutedForeground: "#a3a3a3"
|
|
1260
1567
|
}
|
|
1261
1568
|
},
|
|
1569
|
+
gray: {
|
|
1570
|
+
light: {
|
|
1571
|
+
surfaceElevated: "#f9fafb",
|
|
1572
|
+
surfaceOverlay: "#f3f4f6",
|
|
1573
|
+
foreground: "#111827",
|
|
1574
|
+
border: "rgba(17, 24, 39, 0.08)",
|
|
1575
|
+
mutedForeground: "#6b7280"
|
|
1576
|
+
},
|
|
1577
|
+
dark: {
|
|
1578
|
+
surfaceElevated: "#1a1f2b",
|
|
1579
|
+
surfaceOverlay: "#262c3a",
|
|
1580
|
+
foreground: "#f9fafb",
|
|
1581
|
+
border: "rgba(249, 250, 251, 0.10)",
|
|
1582
|
+
mutedForeground: "#9ca3af"
|
|
1583
|
+
}
|
|
1584
|
+
},
|
|
1262
1585
|
slate: {
|
|
1263
1586
|
light: {
|
|
1264
|
-
surfaceElevated: "#
|
|
1265
|
-
surfaceOverlay: "#
|
|
1587
|
+
surfaceElevated: "#f8fafc",
|
|
1588
|
+
surfaceOverlay: "#f1f5f9",
|
|
1266
1589
|
foreground: "#0f172a",
|
|
1267
1590
|
border: "rgba(15, 23, 42, 0.08)",
|
|
1268
1591
|
mutedForeground: "#64748b"
|
|
@@ -1275,10 +1598,26 @@ var BASE_COLOR_PALETTE = {
|
|
|
1275
1598
|
mutedForeground: "#94a3b8"
|
|
1276
1599
|
}
|
|
1277
1600
|
},
|
|
1601
|
+
"cool-gray": {
|
|
1602
|
+
light: {
|
|
1603
|
+
surfaceElevated: "#f6fafb",
|
|
1604
|
+
surfaceOverlay: "#eaf3f4",
|
|
1605
|
+
foreground: "#13343b",
|
|
1606
|
+
border: "rgba(19, 52, 59, 0.08)",
|
|
1607
|
+
mutedForeground: "#5f7d84"
|
|
1608
|
+
},
|
|
1609
|
+
dark: {
|
|
1610
|
+
surfaceElevated: "#101c1f",
|
|
1611
|
+
surfaceOverlay: "#1b2d31",
|
|
1612
|
+
foreground: "#eef6f7",
|
|
1613
|
+
border: "rgba(238, 246, 247, 0.10)",
|
|
1614
|
+
mutedForeground: "#9db3b8"
|
|
1615
|
+
}
|
|
1616
|
+
},
|
|
1278
1617
|
stone: {
|
|
1279
1618
|
light: {
|
|
1280
|
-
surfaceElevated: "#
|
|
1281
|
-
surfaceOverlay: "#
|
|
1619
|
+
surfaceElevated: "#fafaf9",
|
|
1620
|
+
surfaceOverlay: "#f5f5f4",
|
|
1282
1621
|
foreground: "#1c1917",
|
|
1283
1622
|
border: "rgba(28, 25, 23, 0.08)",
|
|
1284
1623
|
mutedForeground: "#78716c"
|
|
@@ -1294,7 +1633,7 @@ var BASE_COLOR_PALETTE = {
|
|
|
1294
1633
|
taupe: {
|
|
1295
1634
|
light: {
|
|
1296
1635
|
surfaceElevated: "#faf8f5",
|
|
1297
|
-
surfaceOverlay: "#
|
|
1636
|
+
surfaceOverlay: "#f3ede6",
|
|
1298
1637
|
foreground: "#3b342e",
|
|
1299
1638
|
border: "rgba(59, 52, 46, 0.10)",
|
|
1300
1639
|
mutedForeground: "#8a7f74"
|
|
@@ -1306,6 +1645,54 @@ var BASE_COLOR_PALETTE = {
|
|
|
1306
1645
|
border: "rgba(245, 240, 234, 0.10)",
|
|
1307
1646
|
mutedForeground: "#a89f94"
|
|
1308
1647
|
}
|
|
1648
|
+
},
|
|
1649
|
+
mauve: {
|
|
1650
|
+
light: {
|
|
1651
|
+
surfaceElevated: "#fbf8fb",
|
|
1652
|
+
surfaceOverlay: "#f4eef5",
|
|
1653
|
+
foreground: "#34283a",
|
|
1654
|
+
border: "rgba(52, 40, 58, 0.10)",
|
|
1655
|
+
mutedForeground: "#837388"
|
|
1656
|
+
},
|
|
1657
|
+
dark: {
|
|
1658
|
+
surfaceElevated: "#1b151f",
|
|
1659
|
+
surfaceOverlay: "#2a2130",
|
|
1660
|
+
foreground: "#f5eef7",
|
|
1661
|
+
border: "rgba(245, 238, 247, 0.10)",
|
|
1662
|
+
mutedForeground: "#b3a5b8"
|
|
1663
|
+
}
|
|
1664
|
+
},
|
|
1665
|
+
olive: {
|
|
1666
|
+
light: {
|
|
1667
|
+
surfaceElevated: "#fafbf4",
|
|
1668
|
+
surfaceOverlay: "#f0f3e4",
|
|
1669
|
+
foreground: "#2d331f",
|
|
1670
|
+
border: "rgba(45, 51, 31, 0.10)",
|
|
1671
|
+
mutedForeground: "#747b61"
|
|
1672
|
+
},
|
|
1673
|
+
dark: {
|
|
1674
|
+
surfaceElevated: "#171a12",
|
|
1675
|
+
surfaceOverlay: "#24291b",
|
|
1676
|
+
foreground: "#f2f5e8",
|
|
1677
|
+
border: "rgba(242, 245, 232, 0.10)",
|
|
1678
|
+
mutedForeground: "#abb196"
|
|
1679
|
+
}
|
|
1680
|
+
},
|
|
1681
|
+
mist: {
|
|
1682
|
+
light: {
|
|
1683
|
+
surfaceElevated: "#f7fbfb",
|
|
1684
|
+
surfaceOverlay: "#edf5f5",
|
|
1685
|
+
foreground: "#253638",
|
|
1686
|
+
border: "rgba(37, 54, 56, 0.10)",
|
|
1687
|
+
mutedForeground: "#697d80"
|
|
1688
|
+
},
|
|
1689
|
+
dark: {
|
|
1690
|
+
surfaceElevated: "#111b1d",
|
|
1691
|
+
surfaceOverlay: "#1d2b2e",
|
|
1692
|
+
foreground: "#edf7f8",
|
|
1693
|
+
border: "rgba(237, 247, 248, 0.10)",
|
|
1694
|
+
mutedForeground: "#9fb5b8"
|
|
1695
|
+
}
|
|
1309
1696
|
}
|
|
1310
1697
|
};
|
|
1311
1698
|
var THEME_COLOR_PALETTE = {
|
|
@@ -1313,74 +1700,290 @@ var THEME_COLOR_PALETTE = {
|
|
|
1313
1700
|
light: { ...DEFAULT_CONTROL_SOLID_LIGHT },
|
|
1314
1701
|
dark: { ...DEFAULT_CONTROL_SOLID_DARK }
|
|
1315
1702
|
},
|
|
1703
|
+
//
|
|
1704
|
+
// Named hues stay the same true, saturated color family in both modes —
|
|
1705
|
+
// dark mode gets one step deeper (never a washed-out pastel tint of the
|
|
1706
|
+
// light-mode color). This mirrors how shadcn's own theme presets work:
|
|
1707
|
+
// e.g. its "red" theme ships `oklch(0.505 … 27.518)` (~Tailwind red-700)
|
|
1708
|
+
// for light and `oklch(0.444 … 26.899)` (~red-800, darker not lighter)
|
|
1709
|
+
// for dark, with a near-white foreground in both. Hex stops below are
|
|
1710
|
+
// Tailwind v4's red/blue/violet/green/orange 600/700/800/900/50 values.
|
|
1316
1711
|
red: {
|
|
1317
1712
|
light: {
|
|
1318
|
-
controlSolid: "#
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1713
|
+
controlSolid: "#c10007",
|
|
1714
|
+
// red-700
|
|
1715
|
+
controlSolidHover: "#e7000b",
|
|
1716
|
+
// red-600 — brighter on hover
|
|
1717
|
+
controlSolidActive: "#9f0712",
|
|
1718
|
+
// red-800 — darker on press
|
|
1719
|
+
controlSolidForeground: "#fef2f2"
|
|
1720
|
+
// red-50
|
|
1322
1721
|
},
|
|
1323
1722
|
dark: {
|
|
1324
|
-
controlSolid: "#
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1723
|
+
controlSolid: "#9f0712",
|
|
1724
|
+
// red-800
|
|
1725
|
+
controlSolidHover: "#c10007",
|
|
1726
|
+
// red-700 — brighter on hover
|
|
1727
|
+
controlSolidActive: "#82181a",
|
|
1728
|
+
// red-900 — darker on press
|
|
1729
|
+
controlSolidForeground: "#fef2f2"
|
|
1730
|
+
// red-50
|
|
1328
1731
|
}
|
|
1329
1732
|
},
|
|
1330
1733
|
blue: {
|
|
1331
1734
|
light: {
|
|
1332
|
-
controlSolid: "#
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1735
|
+
controlSolid: "#1447e6",
|
|
1736
|
+
// blue-700
|
|
1737
|
+
controlSolidHover: "#155dfc",
|
|
1738
|
+
// blue-600
|
|
1739
|
+
controlSolidActive: "#193cb8",
|
|
1740
|
+
// blue-800
|
|
1741
|
+
controlSolidForeground: "#eff6ff"
|
|
1742
|
+
// blue-50
|
|
1336
1743
|
},
|
|
1337
1744
|
dark: {
|
|
1338
|
-
controlSolid: "#
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1745
|
+
controlSolid: "#193cb8",
|
|
1746
|
+
// blue-800
|
|
1747
|
+
controlSolidHover: "#1447e6",
|
|
1748
|
+
// blue-700
|
|
1749
|
+
controlSolidActive: "#1c398e",
|
|
1750
|
+
// blue-900
|
|
1751
|
+
controlSolidForeground: "#eff6ff"
|
|
1752
|
+
// blue-50
|
|
1342
1753
|
}
|
|
1343
1754
|
},
|
|
1344
1755
|
violet: {
|
|
1345
1756
|
light: {
|
|
1346
|
-
controlSolid: "#
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1757
|
+
controlSolid: "#7008e7",
|
|
1758
|
+
// violet-700
|
|
1759
|
+
controlSolidHover: "#7f22fe",
|
|
1760
|
+
// violet-600
|
|
1761
|
+
controlSolidActive: "#5d0ec0",
|
|
1762
|
+
// violet-800
|
|
1763
|
+
controlSolidForeground: "#f5f3ff"
|
|
1764
|
+
// violet-50
|
|
1350
1765
|
},
|
|
1351
1766
|
dark: {
|
|
1352
|
-
controlSolid: "#
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1767
|
+
controlSolid: "#5d0ec0",
|
|
1768
|
+
// violet-800
|
|
1769
|
+
controlSolidHover: "#7008e7",
|
|
1770
|
+
// violet-700
|
|
1771
|
+
controlSolidActive: "#4d179a",
|
|
1772
|
+
// violet-900
|
|
1773
|
+
controlSolidForeground: "#f5f3ff"
|
|
1774
|
+
// violet-50
|
|
1356
1775
|
}
|
|
1357
1776
|
},
|
|
1358
1777
|
green: {
|
|
1778
|
+
light: {
|
|
1779
|
+
controlSolid: "#008236",
|
|
1780
|
+
// green-700
|
|
1781
|
+
controlSolidHover: "#00a63e",
|
|
1782
|
+
// green-600
|
|
1783
|
+
controlSolidActive: "#016630",
|
|
1784
|
+
// green-800
|
|
1785
|
+
controlSolidForeground: "#f0fdf4"
|
|
1786
|
+
// green-50
|
|
1787
|
+
},
|
|
1788
|
+
dark: {
|
|
1789
|
+
controlSolid: "#016630",
|
|
1790
|
+
// green-800
|
|
1791
|
+
controlSolidHover: "#008236",
|
|
1792
|
+
// green-700
|
|
1793
|
+
controlSolidActive: "#0d542b",
|
|
1794
|
+
// green-900
|
|
1795
|
+
controlSolidForeground: "#f0fdf4"
|
|
1796
|
+
// green-50
|
|
1797
|
+
}
|
|
1798
|
+
},
|
|
1799
|
+
orange: {
|
|
1800
|
+
light: {
|
|
1801
|
+
controlSolid: "#ca3500",
|
|
1802
|
+
// orange-700
|
|
1803
|
+
controlSolidHover: "#f54900",
|
|
1804
|
+
// orange-600
|
|
1805
|
+
controlSolidActive: "#9f2d00",
|
|
1806
|
+
// orange-800
|
|
1807
|
+
controlSolidForeground: "#fff7ed"
|
|
1808
|
+
// orange-50
|
|
1809
|
+
},
|
|
1810
|
+
dark: {
|
|
1811
|
+
controlSolid: "#9f2d00",
|
|
1812
|
+
// orange-800
|
|
1813
|
+
controlSolidHover: "#ca3500",
|
|
1814
|
+
// orange-700
|
|
1815
|
+
controlSolidActive: "#7e2a0c",
|
|
1816
|
+
// orange-900
|
|
1817
|
+
controlSolidForeground: "#fff7ed"
|
|
1818
|
+
// orange-50
|
|
1819
|
+
}
|
|
1820
|
+
},
|
|
1821
|
+
amber: {
|
|
1822
|
+
light: {
|
|
1823
|
+
controlSolid: "#b45309",
|
|
1824
|
+
controlSolidHover: "#d97706",
|
|
1825
|
+
controlSolidActive: "#92400e",
|
|
1826
|
+
controlSolidForeground: "#fffbeb"
|
|
1827
|
+
},
|
|
1828
|
+
dark: {
|
|
1829
|
+
controlSolid: "#92400e",
|
|
1830
|
+
controlSolidHover: "#b45309",
|
|
1831
|
+
controlSolidActive: "#78350f",
|
|
1832
|
+
controlSolidForeground: "#fffbeb"
|
|
1833
|
+
}
|
|
1834
|
+
},
|
|
1835
|
+
cyan: {
|
|
1836
|
+
light: {
|
|
1837
|
+
controlSolid: "#0e7490",
|
|
1838
|
+
controlSolidHover: "#0891b2",
|
|
1839
|
+
controlSolidActive: "#155e75",
|
|
1840
|
+
controlSolidForeground: "#ecfeff"
|
|
1841
|
+
},
|
|
1842
|
+
dark: {
|
|
1843
|
+
controlSolid: "#155e75",
|
|
1844
|
+
controlSolidHover: "#0e7490",
|
|
1845
|
+
controlSolidActive: "#164e63",
|
|
1846
|
+
controlSolidForeground: "#ecfeff"
|
|
1847
|
+
}
|
|
1848
|
+
},
|
|
1849
|
+
emerald: {
|
|
1359
1850
|
light: {
|
|
1360
1851
|
controlSolid: "#047857",
|
|
1361
1852
|
controlSolidHover: "#059669",
|
|
1362
1853
|
controlSolidActive: "#065f46",
|
|
1363
|
-
controlSolidForeground: "#
|
|
1854
|
+
controlSolidForeground: "#ecfdf5"
|
|
1364
1855
|
},
|
|
1365
1856
|
dark: {
|
|
1366
|
-
controlSolid: "#
|
|
1367
|
-
controlSolidHover: "#
|
|
1368
|
-
controlSolidActive: "#
|
|
1369
|
-
controlSolidForeground: "#
|
|
1857
|
+
controlSolid: "#065f46",
|
|
1858
|
+
controlSolidHover: "#047857",
|
|
1859
|
+
controlSolidActive: "#064e3b",
|
|
1860
|
+
controlSolidForeground: "#ecfdf5"
|
|
1370
1861
|
}
|
|
1371
1862
|
},
|
|
1372
|
-
|
|
1863
|
+
indigo: {
|
|
1864
|
+
light: {
|
|
1865
|
+
controlSolid: "#4338ca",
|
|
1866
|
+
controlSolidHover: "#4f46e5",
|
|
1867
|
+
controlSolidActive: "#3730a3",
|
|
1868
|
+
controlSolidForeground: "#eef2ff"
|
|
1869
|
+
},
|
|
1870
|
+
dark: {
|
|
1871
|
+
controlSolid: "#3730a3",
|
|
1872
|
+
controlSolidHover: "#4338ca",
|
|
1873
|
+
controlSolidActive: "#312e81",
|
|
1874
|
+
controlSolidForeground: "#eef2ff"
|
|
1875
|
+
}
|
|
1876
|
+
},
|
|
1877
|
+
pink: {
|
|
1373
1878
|
light: {
|
|
1374
|
-
controlSolid: "#
|
|
1375
|
-
controlSolidHover: "#
|
|
1376
|
-
controlSolidActive: "#
|
|
1377
|
-
controlSolidForeground: "#
|
|
1879
|
+
controlSolid: "#be185d",
|
|
1880
|
+
controlSolidHover: "#db2777",
|
|
1881
|
+
controlSolidActive: "#9d174d",
|
|
1882
|
+
controlSolidForeground: "#fdf2f8"
|
|
1378
1883
|
},
|
|
1379
1884
|
dark: {
|
|
1380
|
-
controlSolid: "#
|
|
1381
|
-
controlSolidHover: "#
|
|
1382
|
-
controlSolidActive: "#
|
|
1383
|
-
controlSolidForeground: "#
|
|
1885
|
+
controlSolid: "#9d174d",
|
|
1886
|
+
controlSolidHover: "#be185d",
|
|
1887
|
+
controlSolidActive: "#831843",
|
|
1888
|
+
controlSolidForeground: "#fdf2f8"
|
|
1889
|
+
}
|
|
1890
|
+
},
|
|
1891
|
+
purple: {
|
|
1892
|
+
light: {
|
|
1893
|
+
controlSolid: "#7e22ce",
|
|
1894
|
+
controlSolidHover: "#9333ea",
|
|
1895
|
+
controlSolidActive: "#6b21a8",
|
|
1896
|
+
controlSolidForeground: "#faf5ff"
|
|
1897
|
+
},
|
|
1898
|
+
dark: {
|
|
1899
|
+
controlSolid: "#6b21a8",
|
|
1900
|
+
controlSolidHover: "#7e22ce",
|
|
1901
|
+
controlSolidActive: "#581c87",
|
|
1902
|
+
controlSolidForeground: "#faf5ff"
|
|
1903
|
+
}
|
|
1904
|
+
},
|
|
1905
|
+
rose: {
|
|
1906
|
+
light: {
|
|
1907
|
+
controlSolid: "#be123c",
|
|
1908
|
+
controlSolidHover: "#e11d48",
|
|
1909
|
+
controlSolidActive: "#9f1239",
|
|
1910
|
+
controlSolidForeground: "#fff1f2"
|
|
1911
|
+
},
|
|
1912
|
+
dark: {
|
|
1913
|
+
controlSolid: "#9f1239",
|
|
1914
|
+
controlSolidHover: "#be123c",
|
|
1915
|
+
controlSolidActive: "#881337",
|
|
1916
|
+
controlSolidForeground: "#fff1f2"
|
|
1917
|
+
}
|
|
1918
|
+
},
|
|
1919
|
+
sky: {
|
|
1920
|
+
light: {
|
|
1921
|
+
controlSolid: "#0369a1",
|
|
1922
|
+
controlSolidHover: "#0284c7",
|
|
1923
|
+
controlSolidActive: "#075985",
|
|
1924
|
+
controlSolidForeground: "#f0f9ff"
|
|
1925
|
+
},
|
|
1926
|
+
dark: {
|
|
1927
|
+
controlSolid: "#075985",
|
|
1928
|
+
controlSolidHover: "#0369a1",
|
|
1929
|
+
controlSolidActive: "#0c4a6e",
|
|
1930
|
+
controlSolidForeground: "#f0f9ff"
|
|
1931
|
+
}
|
|
1932
|
+
},
|
|
1933
|
+
teal: {
|
|
1934
|
+
light: {
|
|
1935
|
+
controlSolid: "#0f766e",
|
|
1936
|
+
controlSolidHover: "#0d9488",
|
|
1937
|
+
controlSolidActive: "#115e59",
|
|
1938
|
+
controlSolidForeground: "#f0fdfa"
|
|
1939
|
+
},
|
|
1940
|
+
dark: {
|
|
1941
|
+
controlSolid: "#115e59",
|
|
1942
|
+
controlSolidHover: "#0f766e",
|
|
1943
|
+
controlSolidActive: "#134e4a",
|
|
1944
|
+
controlSolidForeground: "#f0fdfa"
|
|
1945
|
+
}
|
|
1946
|
+
},
|
|
1947
|
+
yellow: {
|
|
1948
|
+
light: {
|
|
1949
|
+
controlSolid: "#a16207",
|
|
1950
|
+
controlSolidHover: "#ca8a04",
|
|
1951
|
+
controlSolidActive: "#854d0e",
|
|
1952
|
+
controlSolidForeground: "#fefce8"
|
|
1953
|
+
},
|
|
1954
|
+
dark: {
|
|
1955
|
+
controlSolid: "#854d0e",
|
|
1956
|
+
controlSolidHover: "#a16207",
|
|
1957
|
+
controlSolidActive: "#713f12",
|
|
1958
|
+
controlSolidForeground: "#fefce8"
|
|
1959
|
+
}
|
|
1960
|
+
},
|
|
1961
|
+
fuchsia: {
|
|
1962
|
+
light: {
|
|
1963
|
+
controlSolid: "#a21caf",
|
|
1964
|
+
controlSolidHover: "#c026d3",
|
|
1965
|
+
controlSolidActive: "#86198f",
|
|
1966
|
+
controlSolidForeground: "#fdf4ff"
|
|
1967
|
+
},
|
|
1968
|
+
dark: {
|
|
1969
|
+
controlSolid: "#86198f",
|
|
1970
|
+
controlSolidHover: "#a21caf",
|
|
1971
|
+
controlSolidActive: "#701a75",
|
|
1972
|
+
controlSolidForeground: "#fdf4ff"
|
|
1973
|
+
}
|
|
1974
|
+
},
|
|
1975
|
+
lime: {
|
|
1976
|
+
light: {
|
|
1977
|
+
controlSolid: "#4d7c0f",
|
|
1978
|
+
controlSolidHover: "#65a30d",
|
|
1979
|
+
controlSolidActive: "#3f6212",
|
|
1980
|
+
controlSolidForeground: "#f7fee7"
|
|
1981
|
+
},
|
|
1982
|
+
dark: {
|
|
1983
|
+
controlSolid: "#3f6212",
|
|
1984
|
+
controlSolidHover: "#4d7c0f",
|
|
1985
|
+
controlSolidActive: "#365314",
|
|
1986
|
+
controlSolidForeground: "#f7fee7"
|
|
1384
1987
|
}
|
|
1385
1988
|
}
|
|
1386
1989
|
};
|
|
@@ -1424,6 +2027,54 @@ var CHART_PALETTES = {
|
|
|
1424
2027
|
orange: {
|
|
1425
2028
|
light: ["#eda100", "#f97316", "#e34948", "#ca8a04", "#c2410c", "#db2777"],
|
|
1426
2029
|
dark: ["#c98500", "#fb923c", "#e66767", "#facc15", "#fdba74", "#f472b6"]
|
|
2030
|
+
},
|
|
2031
|
+
amber: {
|
|
2032
|
+
light: ["#d97706", "#f59e0b", "#b45309", "#fbbf24", "#92400e", "#f97316"],
|
|
2033
|
+
dark: ["#fbbf24", "#f59e0b", "#fcd34d", "#d97706", "#fde68a", "#fb923c"]
|
|
2034
|
+
},
|
|
2035
|
+
cyan: {
|
|
2036
|
+
light: ["#0891b2", "#06b6d4", "#0e7490", "#22d3ee", "#155e75", "#0284c7"],
|
|
2037
|
+
dark: ["#22d3ee", "#67e8f9", "#06b6d4", "#38bdf8", "#a5f3fc", "#0891b2"]
|
|
2038
|
+
},
|
|
2039
|
+
emerald: {
|
|
2040
|
+
light: ["#059669", "#10b981", "#047857", "#34d399", "#065f46", "#0d9488"],
|
|
2041
|
+
dark: ["#34d399", "#6ee7b7", "#10b981", "#2dd4bf", "#a7f3d0", "#059669"]
|
|
2042
|
+
},
|
|
2043
|
+
indigo: {
|
|
2044
|
+
light: ["#4f46e5", "#6366f1", "#4338ca", "#818cf8", "#3730a3", "#7c3aed"],
|
|
2045
|
+
dark: ["#818cf8", "#a5b4fc", "#6366f1", "#a78bfa", "#c7d2fe", "#4f46e5"]
|
|
2046
|
+
},
|
|
2047
|
+
pink: {
|
|
2048
|
+
light: ["#db2777", "#ec4899", "#be185d", "#f472b6", "#9d174d", "#e11d48"],
|
|
2049
|
+
dark: ["#f472b6", "#f9a8d4", "#ec4899", "#fb7185", "#fbcfe8", "#db2777"]
|
|
2050
|
+
},
|
|
2051
|
+
purple: {
|
|
2052
|
+
light: ["#9333ea", "#a855f7", "#7e22ce", "#c084fc", "#6b21a8", "#7c3aed"],
|
|
2053
|
+
dark: ["#c084fc", "#d8b4fe", "#a855f7", "#a78bfa", "#e9d5ff", "#9333ea"]
|
|
2054
|
+
},
|
|
2055
|
+
rose: {
|
|
2056
|
+
light: ["#e11d48", "#f43f5e", "#be123c", "#fb7185", "#9f1239", "#db2777"],
|
|
2057
|
+
dark: ["#fb7185", "#fda4af", "#f43f5e", "#f472b6", "#ffe4e6", "#e11d48"]
|
|
2058
|
+
},
|
|
2059
|
+
sky: {
|
|
2060
|
+
light: ["#0284c7", "#0ea5e9", "#0369a1", "#38bdf8", "#075985", "#2563eb"],
|
|
2061
|
+
dark: ["#38bdf8", "#7dd3fc", "#0ea5e9", "#60a5fa", "#bae6fd", "#0284c7"]
|
|
2062
|
+
},
|
|
2063
|
+
teal: {
|
|
2064
|
+
light: ["#0d9488", "#14b8a6", "#0f766e", "#2dd4bf", "#115e59", "#0891b2"],
|
|
2065
|
+
dark: ["#2dd4bf", "#5eead4", "#14b8a6", "#22d3ee", "#99f6e4", "#0d9488"]
|
|
2066
|
+
},
|
|
2067
|
+
yellow: {
|
|
2068
|
+
light: ["#ca8a04", "#eab308", "#a16207", "#facc15", "#854d0e", "#f59e0b"],
|
|
2069
|
+
dark: ["#facc15", "#fde047", "#eab308", "#fbbf24", "#fef08a", "#ca8a04"]
|
|
2070
|
+
},
|
|
2071
|
+
fuchsia: {
|
|
2072
|
+
light: ["#c026d3", "#d946ef", "#a21caf", "#e879f9", "#86198f", "#db2777"],
|
|
2073
|
+
dark: ["#e879f9", "#f0abfc", "#d946ef", "#f472b6", "#fae8ff", "#c026d3"]
|
|
2074
|
+
},
|
|
2075
|
+
lime: {
|
|
2076
|
+
light: ["#65a30d", "#84cc16", "#4d7c0f", "#a3e635", "#3f6212", "#16a34a"],
|
|
2077
|
+
dark: ["#a3e635", "#bef264", "#84cc16", "#4ade80", "#d9f99d", "#65a30d"]
|
|
1427
2078
|
}
|
|
1428
2079
|
},
|
|
1429
2080
|
warm: {
|
|
@@ -1437,6 +2088,70 @@ var CHART_PALETTES = {
|
|
|
1437
2088
|
mixed: {
|
|
1438
2089
|
light: ["#2a78d6", "#e34948", "#1baf7a", "#eda100", "#4a3aa7", "#db2777"],
|
|
1439
2090
|
dark: ["#3987e5", "#e66767", "#199e70", "#c98500", "#9085e9", "#f472b6"]
|
|
2091
|
+
},
|
|
2092
|
+
neutral: {
|
|
2093
|
+
light: ["#404040", "#737373", "#a3a3a3", "#525252", "#262626", "#d4d4d4"],
|
|
2094
|
+
dark: ["#d4d4d4", "#a3a3a3", "#737373", "#e5e5e5", "#f5f5f5", "#525252"]
|
|
2095
|
+
},
|
|
2096
|
+
zinc: {
|
|
2097
|
+
light: ["#3f3f46", "#71717a", "#a1a1aa", "#52525b", "#27272a", "#d4d4d8"],
|
|
2098
|
+
dark: ["#d4d4d8", "#a1a1aa", "#71717a", "#e4e4e7", "#f4f4f5", "#52525b"]
|
|
2099
|
+
},
|
|
2100
|
+
stone: {
|
|
2101
|
+
light: ["#44403c", "#78716c", "#a8a29e", "#57534e", "#292524", "#d6d3d1"],
|
|
2102
|
+
dark: ["#d6d3d1", "#a8a29e", "#78716c", "#e7e5e4", "#fafaf9", "#57534e"]
|
|
2103
|
+
},
|
|
2104
|
+
gray: {
|
|
2105
|
+
light: ["#374151", "#6b7280", "#9ca3af", "#4b5563", "#1f2937", "#d1d5db"],
|
|
2106
|
+
dark: ["#d1d5db", "#9ca3af", "#6b7280", "#e5e7eb", "#f9fafb", "#4b5563"]
|
|
2107
|
+
},
|
|
2108
|
+
amber: {
|
|
2109
|
+
light: ["#d97706", "#f59e0b", "#b45309", "#fbbf24", "#92400e", "#f97316"],
|
|
2110
|
+
dark: ["#fbbf24", "#f59e0b", "#fcd34d", "#d97706", "#fde68a", "#fb923c"]
|
|
2111
|
+
},
|
|
2112
|
+
cyan: {
|
|
2113
|
+
light: ["#0891b2", "#06b6d4", "#0e7490", "#22d3ee", "#155e75", "#0284c7"],
|
|
2114
|
+
dark: ["#22d3ee", "#67e8f9", "#06b6d4", "#38bdf8", "#a5f3fc", "#0891b2"]
|
|
2115
|
+
},
|
|
2116
|
+
emerald: {
|
|
2117
|
+
light: ["#059669", "#10b981", "#047857", "#34d399", "#065f46", "#0d9488"],
|
|
2118
|
+
dark: ["#34d399", "#6ee7b7", "#10b981", "#2dd4bf", "#a7f3d0", "#059669"]
|
|
2119
|
+
},
|
|
2120
|
+
indigo: {
|
|
2121
|
+
light: ["#4f46e5", "#6366f1", "#4338ca", "#818cf8", "#3730a3", "#7c3aed"],
|
|
2122
|
+
dark: ["#818cf8", "#a5b4fc", "#6366f1", "#a78bfa", "#c7d2fe", "#4f46e5"]
|
|
2123
|
+
},
|
|
2124
|
+
lime: {
|
|
2125
|
+
light: ["#65a30d", "#84cc16", "#4d7c0f", "#a3e635", "#3f6212", "#16a34a"],
|
|
2126
|
+
dark: ["#a3e635", "#bef264", "#84cc16", "#4ade80", "#d9f99d", "#65a30d"]
|
|
2127
|
+
},
|
|
2128
|
+
pink: {
|
|
2129
|
+
light: ["#db2777", "#ec4899", "#be185d", "#f472b6", "#9d174d", "#e11d48"],
|
|
2130
|
+
dark: ["#f472b6", "#f9a8d4", "#ec4899", "#fb7185", "#fbcfe8", "#db2777"]
|
|
2131
|
+
},
|
|
2132
|
+
purple: {
|
|
2133
|
+
light: ["#9333ea", "#a855f7", "#7e22ce", "#c084fc", "#6b21a8", "#7c3aed"],
|
|
2134
|
+
dark: ["#c084fc", "#d8b4fe", "#a855f7", "#a78bfa", "#e9d5ff", "#9333ea"]
|
|
2135
|
+
},
|
|
2136
|
+
rose: {
|
|
2137
|
+
light: ["#e11d48", "#f43f5e", "#be123c", "#fb7185", "#9f1239", "#db2777"],
|
|
2138
|
+
dark: ["#fb7185", "#fda4af", "#f43f5e", "#f472b6", "#ffe4e6", "#e11d48"]
|
|
2139
|
+
},
|
|
2140
|
+
sky: {
|
|
2141
|
+
light: ["#0284c7", "#0ea5e9", "#0369a1", "#38bdf8", "#075985", "#2563eb"],
|
|
2142
|
+
dark: ["#38bdf8", "#7dd3fc", "#0ea5e9", "#60a5fa", "#bae6fd", "#0284c7"]
|
|
2143
|
+
},
|
|
2144
|
+
teal: {
|
|
2145
|
+
light: ["#0d9488", "#14b8a6", "#0f766e", "#2dd4bf", "#115e59", "#0891b2"],
|
|
2146
|
+
dark: ["#2dd4bf", "#5eead4", "#14b8a6", "#22d3ee", "#99f6e4", "#0d9488"]
|
|
2147
|
+
},
|
|
2148
|
+
yellow: {
|
|
2149
|
+
light: ["#ca8a04", "#eab308", "#a16207", "#facc15", "#854d0e", "#f59e0b"],
|
|
2150
|
+
dark: ["#facc15", "#fde047", "#eab308", "#fbbf24", "#fef08a", "#ca8a04"]
|
|
2151
|
+
},
|
|
2152
|
+
taupe: {
|
|
2153
|
+
light: ["#8a6f55", "#a78b71", "#6f5a46", "#c4aa8f", "#4f4034", "#d97706"],
|
|
2154
|
+
dark: ["#c4aa8f", "#dcc8b2", "#a78b71", "#f3ede6", "#8a6f55", "#fbbf24"]
|
|
1440
2155
|
}
|
|
1441
2156
|
};
|
|
1442
2157
|
|
|
@@ -1446,6 +2161,51 @@ var HEADING_FONT_PACKAGES = {
|
|
|
1446
2161
|
packageName: "@fontsource/playfair-display",
|
|
1447
2162
|
importSpecifier: "@fontsource/playfair-display",
|
|
1448
2163
|
familyName: "Playfair Display"
|
|
2164
|
+
},
|
|
2165
|
+
"instrument-serif": {
|
|
2166
|
+
packageName: "@fontsource/instrument-serif",
|
|
2167
|
+
importSpecifier: "@fontsource/instrument-serif",
|
|
2168
|
+
familyName: "Instrument Serif"
|
|
2169
|
+
},
|
|
2170
|
+
fraunces: {
|
|
2171
|
+
packageName: "@fontsource/fraunces",
|
|
2172
|
+
importSpecifier: "@fontsource/fraunces",
|
|
2173
|
+
familyName: "Fraunces"
|
|
2174
|
+
},
|
|
2175
|
+
"space-grotesk": {
|
|
2176
|
+
packageName: "@fontsource/space-grotesk",
|
|
2177
|
+
importSpecifier: "@fontsource/space-grotesk",
|
|
2178
|
+
familyName: "Space Grotesk"
|
|
2179
|
+
},
|
|
2180
|
+
"noto-serif": {
|
|
2181
|
+
packageName: "@fontsource/noto-serif",
|
|
2182
|
+
importSpecifier: "@fontsource/noto-serif",
|
|
2183
|
+
familyName: "Noto Serif"
|
|
2184
|
+
},
|
|
2185
|
+
"eb-garamond": {
|
|
2186
|
+
packageName: "@fontsource/eb-garamond",
|
|
2187
|
+
importSpecifier: "@fontsource/eb-garamond",
|
|
2188
|
+
familyName: "EB Garamond"
|
|
2189
|
+
},
|
|
2190
|
+
lora: {
|
|
2191
|
+
packageName: "@fontsource/lora",
|
|
2192
|
+
importSpecifier: "@fontsource/lora",
|
|
2193
|
+
familyName: "Lora"
|
|
2194
|
+
},
|
|
2195
|
+
montserrat: {
|
|
2196
|
+
packageName: "@fontsource/montserrat",
|
|
2197
|
+
importSpecifier: "@fontsource/montserrat",
|
|
2198
|
+
familyName: "Montserrat"
|
|
2199
|
+
},
|
|
2200
|
+
manrope: {
|
|
2201
|
+
packageName: "@fontsource/manrope",
|
|
2202
|
+
importSpecifier: "@fontsource/manrope",
|
|
2203
|
+
familyName: "Manrope"
|
|
2204
|
+
},
|
|
2205
|
+
inter: {
|
|
2206
|
+
packageName: "@fontsource/inter",
|
|
2207
|
+
importSpecifier: "@fontsource/inter",
|
|
2208
|
+
familyName: "Inter"
|
|
1449
2209
|
}
|
|
1450
2210
|
};
|
|
1451
2211
|
var BODY_FONT_PACKAGES = {
|
|
@@ -1453,15 +2213,78 @@ var BODY_FONT_PACKAGES = {
|
|
|
1453
2213
|
packageName: "@fontsource/inter",
|
|
1454
2214
|
importSpecifier: "@fontsource/inter",
|
|
1455
2215
|
familyName: "Inter"
|
|
2216
|
+
},
|
|
2217
|
+
geist: {
|
|
2218
|
+
packageName: "@fontsource/geist",
|
|
2219
|
+
importSpecifier: "@fontsource/geist",
|
|
2220
|
+
familyName: "Geist"
|
|
2221
|
+
},
|
|
2222
|
+
"dm-sans": {
|
|
2223
|
+
packageName: "@fontsource/dm-sans",
|
|
2224
|
+
importSpecifier: "@fontsource/dm-sans",
|
|
2225
|
+
familyName: "DM Sans"
|
|
2226
|
+
},
|
|
2227
|
+
"plus-jakarta-sans": {
|
|
2228
|
+
packageName: "@fontsource/plus-jakarta-sans",
|
|
2229
|
+
importSpecifier: "@fontsource/plus-jakarta-sans",
|
|
2230
|
+
familyName: "Plus Jakarta Sans"
|
|
2231
|
+
},
|
|
2232
|
+
figtree: {
|
|
2233
|
+
packageName: "@fontsource/figtree",
|
|
2234
|
+
importSpecifier: "@fontsource/figtree",
|
|
2235
|
+
familyName: "Figtree"
|
|
2236
|
+
},
|
|
2237
|
+
"noto-sans": {
|
|
2238
|
+
packageName: "@fontsource/noto-sans",
|
|
2239
|
+
importSpecifier: "@fontsource/noto-sans",
|
|
2240
|
+
familyName: "Noto Sans"
|
|
2241
|
+
},
|
|
2242
|
+
"public-sans": {
|
|
2243
|
+
packageName: "@fontsource/public-sans",
|
|
2244
|
+
importSpecifier: "@fontsource/public-sans",
|
|
2245
|
+
familyName: "Public Sans"
|
|
2246
|
+
},
|
|
2247
|
+
outfit: {
|
|
2248
|
+
packageName: "@fontsource/outfit",
|
|
2249
|
+
importSpecifier: "@fontsource/outfit",
|
|
2250
|
+
familyName: "Outfit"
|
|
2251
|
+
},
|
|
2252
|
+
manrope: {
|
|
2253
|
+
packageName: "@fontsource/manrope",
|
|
2254
|
+
importSpecifier: "@fontsource/manrope",
|
|
2255
|
+
familyName: "Manrope"
|
|
2256
|
+
},
|
|
2257
|
+
"ibm-plex-sans": {
|
|
2258
|
+
packageName: "@fontsource/ibm-plex-sans",
|
|
2259
|
+
importSpecifier: "@fontsource/ibm-plex-sans",
|
|
2260
|
+
familyName: "IBM Plex Sans"
|
|
1456
2261
|
}
|
|
1457
2262
|
};
|
|
1458
2263
|
var HEADING_FONT_CSS = {
|
|
1459
2264
|
system: "var(--font-display)",
|
|
1460
|
-
playfair: "'Playfair Display', Georgia, 'Times New Roman', serif"
|
|
2265
|
+
playfair: "'Playfair Display', Georgia, 'Times New Roman', serif",
|
|
2266
|
+
"instrument-serif": "'Instrument Serif', Georgia, 'Times New Roman', serif",
|
|
2267
|
+
fraunces: "'Fraunces', Georgia, 'Times New Roman', serif",
|
|
2268
|
+
"space-grotesk": "'Space Grotesk', ui-sans-serif, system-ui, sans-serif",
|
|
2269
|
+
"noto-serif": "'Noto Serif', Georgia, 'Times New Roman', serif",
|
|
2270
|
+
"eb-garamond": "'EB Garamond', Georgia, 'Times New Roman', serif",
|
|
2271
|
+
lora: "'Lora', Georgia, 'Times New Roman', serif",
|
|
2272
|
+
montserrat: "'Montserrat', ui-sans-serif, system-ui, sans-serif",
|
|
2273
|
+
manrope: "'Manrope', ui-sans-serif, system-ui, sans-serif",
|
|
2274
|
+
inter: "'Inter', ui-sans-serif, system-ui, sans-serif"
|
|
1461
2275
|
};
|
|
1462
2276
|
var BODY_FONT_CSS = {
|
|
1463
2277
|
system: "var(--font-sans)",
|
|
1464
|
-
inter: "'Inter', ui-sans-serif, system-ui, sans-serif"
|
|
2278
|
+
inter: "'Inter', ui-sans-serif, system-ui, sans-serif",
|
|
2279
|
+
geist: "'Geist', ui-sans-serif, system-ui, sans-serif",
|
|
2280
|
+
"dm-sans": "'DM Sans', ui-sans-serif, system-ui, sans-serif",
|
|
2281
|
+
"plus-jakarta-sans": "'Plus Jakarta Sans', ui-sans-serif, system-ui, sans-serif",
|
|
2282
|
+
figtree: "'Figtree', ui-sans-serif, system-ui, sans-serif",
|
|
2283
|
+
"noto-sans": "'Noto Sans', ui-sans-serif, system-ui, sans-serif",
|
|
2284
|
+
"public-sans": "'Public Sans', ui-sans-serif, system-ui, sans-serif",
|
|
2285
|
+
outfit: "'Outfit', ui-sans-serif, system-ui, sans-serif",
|
|
2286
|
+
manrope: "'Manrope', ui-sans-serif, system-ui, sans-serif",
|
|
2287
|
+
"ibm-plex-sans": "'IBM Plex Sans', ui-sans-serif, system-ui, sans-serif"
|
|
1465
2288
|
};
|
|
1466
2289
|
|
|
1467
2290
|
// ../wensity-preset/src/resolve.ts
|
|
@@ -1520,7 +2343,19 @@ var COLORED_THEME_IDS = /* @__PURE__ */ new Set([
|
|
|
1520
2343
|
"blue",
|
|
1521
2344
|
"violet",
|
|
1522
2345
|
"green",
|
|
1523
|
-
"orange"
|
|
2346
|
+
"orange",
|
|
2347
|
+
"amber",
|
|
2348
|
+
"cyan",
|
|
2349
|
+
"emerald",
|
|
2350
|
+
"indigo",
|
|
2351
|
+
"pink",
|
|
2352
|
+
"purple",
|
|
2353
|
+
"rose",
|
|
2354
|
+
"sky",
|
|
2355
|
+
"teal",
|
|
2356
|
+
"yellow",
|
|
2357
|
+
"fuchsia",
|
|
2358
|
+
"lime"
|
|
1524
2359
|
]);
|
|
1525
2360
|
function colorMix(source, percent) {
|
|
1526
2361
|
return `color-mix(in srgb, ${source} ${percent}%, transparent)`;
|
|
@@ -1638,6 +2473,34 @@ function resolveStyleConfigCanonical(style) {
|
|
|
1638
2473
|
dark: resolveMode("dark")
|
|
1639
2474
|
};
|
|
1640
2475
|
}
|
|
2476
|
+
function resolvedTokensToCssVars(tokens, mode) {
|
|
2477
|
+
const modeTokens = tokens[mode];
|
|
2478
|
+
return {
|
|
2479
|
+
[RESOLVED_TOKEN_CSS_VARS.surfaceElevated]: modeTokens.surfaceElevated,
|
|
2480
|
+
[RESOLVED_TOKEN_CSS_VARS.surfaceOverlay]: modeTokens.surfaceOverlay,
|
|
2481
|
+
[RESOLVED_TOKEN_CSS_VARS.surfaceHover]: modeTokens.surfaceHover,
|
|
2482
|
+
[RESOLVED_TOKEN_CSS_VARS.surfaceActive]: modeTokens.surfaceActive,
|
|
2483
|
+
[RESOLVED_TOKEN_CSS_VARS.surfaceSelected]: modeTokens.surfaceSelected,
|
|
2484
|
+
[RESOLVED_TOKEN_CSS_VARS.borderSubtle]: modeTokens.borderSubtle,
|
|
2485
|
+
[RESOLVED_TOKEN_CSS_VARS.ring]: modeTokens.ring,
|
|
2486
|
+
[RESOLVED_TOKEN_CSS_VARS.textSecondary]: modeTokens.textSecondary,
|
|
2487
|
+
[RESOLVED_TOKEN_CSS_VARS.textPlaceholder]: modeTokens.textPlaceholder,
|
|
2488
|
+
[RESOLVED_TOKEN_CSS_VARS.controlSolid]: modeTokens.controlSolid,
|
|
2489
|
+
[RESOLVED_TOKEN_CSS_VARS.controlSolidHover]: modeTokens.controlSolidHover,
|
|
2490
|
+
[RESOLVED_TOKEN_CSS_VARS.controlSolidActive]: modeTokens.controlSolidActive,
|
|
2491
|
+
[RESOLVED_TOKEN_CSS_VARS.controlSolidForeground]: modeTokens.controlSolidForeground,
|
|
2492
|
+
[RESOLVED_TOKEN_CSS_VARS.chart1]: modeTokens.chart1,
|
|
2493
|
+
[RESOLVED_TOKEN_CSS_VARS.chart2]: modeTokens.chart2,
|
|
2494
|
+
[RESOLVED_TOKEN_CSS_VARS.chart3]: modeTokens.chart3,
|
|
2495
|
+
[RESOLVED_TOKEN_CSS_VARS.chart4]: modeTokens.chart4,
|
|
2496
|
+
[RESOLVED_TOKEN_CSS_VARS.chart5]: modeTokens.chart5,
|
|
2497
|
+
[RESOLVED_TOKEN_CSS_VARS.chart6]: modeTokens.chart6,
|
|
2498
|
+
[RESOLVED_TOKEN_CSS_VARS.radius]: tokens.radius,
|
|
2499
|
+
[RESOLVED_TOKEN_CSS_VARS.fontSans]: tokens.fontSans,
|
|
2500
|
+
[RESOLVED_TOKEN_CSS_VARS.fontDisplay]: tokens.fontDisplay,
|
|
2501
|
+
[RESOLVED_TOKEN_CSS_VARS.fontMono]: tokens.fontMono
|
|
2502
|
+
};
|
|
2503
|
+
}
|
|
1641
2504
|
|
|
1642
2505
|
// src/paths.ts
|
|
1643
2506
|
import { dirname, isAbsolute, relative, resolve, sep } from "path";
|
|
@@ -2608,13 +3471,13 @@ function missingDependencies(projectRoot, dependencies) {
|
|
|
2608
3471
|
function readInstalledPackageNames(projectRoot) {
|
|
2609
3472
|
const packageJsonPath = join4(projectRoot, "package.json");
|
|
2610
3473
|
if (!existsSync2(packageJsonPath)) return void 0;
|
|
2611
|
-
const
|
|
3474
|
+
const packageJson2 = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
2612
3475
|
return new Set(
|
|
2613
3476
|
Object.keys({
|
|
2614
|
-
...
|
|
2615
|
-
...
|
|
2616
|
-
...
|
|
2617
|
-
...
|
|
3477
|
+
...packageJson2.dependencies,
|
|
3478
|
+
...packageJson2.devDependencies,
|
|
3479
|
+
...packageJson2.peerDependencies,
|
|
3480
|
+
...packageJson2.optionalDependencies
|
|
2618
3481
|
})
|
|
2619
3482
|
);
|
|
2620
3483
|
}
|
|
@@ -2709,8 +3572,15 @@ function encodePresetFileJson(parsed) {
|
|
|
2709
3572
|
}
|
|
2710
3573
|
if (v === 2) {
|
|
2711
3574
|
const payload = validateCodecPayloadCanonical(parsed);
|
|
2712
|
-
|
|
2713
|
-
|
|
3575
|
+
return encodePresetCanonical({
|
|
3576
|
+
baseColor: payload.baseColor,
|
|
3577
|
+
themeColor: payload.themeColor,
|
|
3578
|
+
chartPalette: payload.chartPalette,
|
|
3579
|
+
headingFont: payload.headingFont,
|
|
3580
|
+
bodyFont: payload.bodyFont,
|
|
3581
|
+
iconLibrary: payload.iconLibrary,
|
|
3582
|
+
radius: payload.radius
|
|
3583
|
+
});
|
|
2714
3584
|
}
|
|
2715
3585
|
throw new PresetValidationError(
|
|
2716
3586
|
`Unsupported preset payload version ${String(v)}. This preset may require a newer version of the Wensity CLI.`,
|
|
@@ -2744,12 +3614,115 @@ function toCliPresetError(error) {
|
|
|
2744
3614
|
const message = error.message;
|
|
2745
3615
|
if (/Unsupported preset payload version/i.test(message)) {
|
|
2746
3616
|
return new CliError(
|
|
2747
|
-
`Invalid preset: ${message} Upgrade the Wensity CLI (wensity@
|
|
3617
|
+
`Invalid preset: ${message} Upgrade the Wensity CLI (wensity@latest) and try again.`
|
|
2748
3618
|
);
|
|
2749
3619
|
}
|
|
2750
3620
|
return new CliError(`Invalid preset: ${message}`);
|
|
2751
3621
|
}
|
|
2752
3622
|
|
|
3623
|
+
// src/preset-inspect.ts
|
|
3624
|
+
function createPresetInspectSummary(input) {
|
|
3625
|
+
const tokens = resolveTokensForStyle(input.style);
|
|
3626
|
+
const fontPlan = fontPlanForStyle(input.style);
|
|
3627
|
+
return {
|
|
3628
|
+
presetCode: input.presetCode,
|
|
3629
|
+
kind: isCanonicalStyleShape(input.style) ? "canonical" : "legacy",
|
|
3630
|
+
style: input.style,
|
|
3631
|
+
fontPackages: fontPlan.packages,
|
|
3632
|
+
fontImports: fontPlan.importLines,
|
|
3633
|
+
tokens: {
|
|
3634
|
+
radius: tokens.radius,
|
|
3635
|
+
fonts: {
|
|
3636
|
+
sans: tokens.fontSans,
|
|
3637
|
+
display: tokens.fontDisplay,
|
|
3638
|
+
mono: tokens.fontMono
|
|
3639
|
+
},
|
|
3640
|
+
light: summarizeMode(tokens, "light"),
|
|
3641
|
+
dark: summarizeMode(tokens, "dark")
|
|
3642
|
+
}
|
|
3643
|
+
};
|
|
3644
|
+
}
|
|
3645
|
+
function formatPresetInspectSummary(summary) {
|
|
3646
|
+
return [
|
|
3647
|
+
panel("Preset", [
|
|
3648
|
+
`Code: ${summary.presetCode}`,
|
|
3649
|
+
`Shape: ${summary.kind}`,
|
|
3650
|
+
`Icon library: ${summary.style.iconLibrary}`,
|
|
3651
|
+
`Radius: ${summary.style.radius} (${summary.tokens.radius})`
|
|
3652
|
+
]),
|
|
3653
|
+
formatStylePanel(summary),
|
|
3654
|
+
formatFontPanel(summary),
|
|
3655
|
+
formatTokenPanel(summary)
|
|
3656
|
+
].join("\n");
|
|
3657
|
+
}
|
|
3658
|
+
function fontPlanForStyle(style) {
|
|
3659
|
+
if (!isCanonicalStyleShape(style)) {
|
|
3660
|
+
return { packages: [], importLines: [], block: null };
|
|
3661
|
+
}
|
|
3662
|
+
return planFontInstall(style.headingFont, style.bodyFont);
|
|
3663
|
+
}
|
|
3664
|
+
function summarizeMode(tokens, mode) {
|
|
3665
|
+
const cssVars = resolvedTokensToCssVars(tokens, mode);
|
|
3666
|
+
return {
|
|
3667
|
+
controlSolid: cssVars["--primitive-control-solid"] ?? tokens[mode].controlSolid,
|
|
3668
|
+
ring: cssVars["--primitive-ring"] ?? tokens[mode].ring,
|
|
3669
|
+
surfaceSelected: cssVars["--primitive-surface-selected"] ?? tokens[mode].surfaceSelected,
|
|
3670
|
+
chart: [
|
|
3671
|
+
cssVars["--primitive-chart-1"] ?? tokens[mode].chart1,
|
|
3672
|
+
cssVars["--primitive-chart-2"] ?? tokens[mode].chart2,
|
|
3673
|
+
cssVars["--primitive-chart-3"] ?? tokens[mode].chart3,
|
|
3674
|
+
cssVars["--primitive-chart-4"] ?? tokens[mode].chart4,
|
|
3675
|
+
cssVars["--primitive-chart-5"] ?? tokens[mode].chart5,
|
|
3676
|
+
cssVars["--primitive-chart-6"] ?? tokens[mode].chart6
|
|
3677
|
+
]
|
|
3678
|
+
};
|
|
3679
|
+
}
|
|
3680
|
+
function formatStylePanel(summary) {
|
|
3681
|
+
if (isCanonicalStyleShape(summary.style)) {
|
|
3682
|
+
return panel("Style", [
|
|
3683
|
+
`Base color: ${summary.style.baseColor}`,
|
|
3684
|
+
`Theme color: ${summary.style.themeColor}`,
|
|
3685
|
+
`Chart palette: ${summary.style.chartPalette}`,
|
|
3686
|
+
`Heading font: ${summary.style.headingFont}`,
|
|
3687
|
+
`Body font: ${summary.style.bodyFont}`
|
|
3688
|
+
]);
|
|
3689
|
+
}
|
|
3690
|
+
return panel("Style", [
|
|
3691
|
+
"Legacy payload",
|
|
3692
|
+
`Font sans: ${summary.style.fonts.sans}`,
|
|
3693
|
+
`Font display: ${summary.style.fonts.display}`,
|
|
3694
|
+
`Font mono: ${summary.style.fonts.mono}`
|
|
3695
|
+
]);
|
|
3696
|
+
}
|
|
3697
|
+
function formatFontPanel(summary) {
|
|
3698
|
+
const rows = [
|
|
3699
|
+
`--primitive-font-sans: ${summary.tokens.fonts.sans}`,
|
|
3700
|
+
`--primitive-font-display: ${summary.tokens.fonts.display}`,
|
|
3701
|
+
`--primitive-font-mono: ${summary.tokens.fonts.mono}`
|
|
3702
|
+
];
|
|
3703
|
+
const install = summary.fontPackages.length ? [
|
|
3704
|
+
"",
|
|
3705
|
+
action(`Install packages: ${summary.fontPackages.join(" ")}`),
|
|
3706
|
+
action(`CSS imports: ${summary.fontImports.join(" ")}`)
|
|
3707
|
+
].join("\n") : ["", action("No Fontsource packages required.")].join("\n");
|
|
3708
|
+
return `${panel("Fonts", rows)}${install}`;
|
|
3709
|
+
}
|
|
3710
|
+
function formatTokenPanel(summary) {
|
|
3711
|
+
return panel("Resolved primitive tokens", [
|
|
3712
|
+
"Light",
|
|
3713
|
+
` control: ${summary.tokens.light.controlSolid}`,
|
|
3714
|
+
` ring: ${summary.tokens.light.ring}`,
|
|
3715
|
+
` selected: ${summary.tokens.light.surfaceSelected}`,
|
|
3716
|
+
` chart: ${summary.tokens.light.chart.join(", ")}`,
|
|
3717
|
+
"",
|
|
3718
|
+
"Dark",
|
|
3719
|
+
` control: ${summary.tokens.dark.controlSolid}`,
|
|
3720
|
+
` ring: ${summary.tokens.dark.ring}`,
|
|
3721
|
+
` selected: ${summary.tokens.dark.surfaceSelected}`,
|
|
3722
|
+
` chart: ${summary.tokens.dark.chart.join(", ")}`
|
|
3723
|
+
]);
|
|
3724
|
+
}
|
|
3725
|
+
|
|
2753
3726
|
// src/preset-init-writes.ts
|
|
2754
3727
|
import { mkdir as mkdir3, writeFile as writeFile3 } from "fs/promises";
|
|
2755
3728
|
import { dirname as dirname4 } from "path";
|
|
@@ -2777,6 +3750,351 @@ async function commitPresetInitWrites(input) {
|
|
|
2777
3750
|
}
|
|
2778
3751
|
}
|
|
2779
3752
|
|
|
3753
|
+
// src/project-templates.ts
|
|
3754
|
+
import { mkdir as mkdir4, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
|
|
3755
|
+
import { dirname as dirname5, join as join5 } from "path";
|
|
3756
|
+
var PROJECT_TEMPLATE_IDS = ["next", "vite", "astro", "react-router"];
|
|
3757
|
+
function parseProjectTemplate(value) {
|
|
3758
|
+
if (!value) return void 0;
|
|
3759
|
+
const normalized = value.toLowerCase();
|
|
3760
|
+
if (normalized === "nextjs" || normalized === "next.js") return "next";
|
|
3761
|
+
if (normalized === "reactrouter" || normalized === "react-router") return "react-router";
|
|
3762
|
+
if (isProjectTemplateId(normalized)) return normalized;
|
|
3763
|
+
throw new CliError(
|
|
3764
|
+
`Unsupported template "${value}". Use one of: ${PROJECT_TEMPLATE_IDS.join(", ")}.`
|
|
3765
|
+
);
|
|
3766
|
+
}
|
|
3767
|
+
function getProjectTemplateDefinition(id) {
|
|
3768
|
+
return templateDefinitions[id];
|
|
3769
|
+
}
|
|
3770
|
+
function applyTemplateToConfig(config, template) {
|
|
3771
|
+
return {
|
|
3772
|
+
...config,
|
|
3773
|
+
tailwind: {
|
|
3774
|
+
...config.tailwind,
|
|
3775
|
+
css: template.cssPath
|
|
3776
|
+
}
|
|
3777
|
+
};
|
|
3778
|
+
}
|
|
3779
|
+
async function scaffoldProjectTemplate(projectRoot, template, options) {
|
|
3780
|
+
const planned = template.files.map((file) => file.path);
|
|
3781
|
+
if (!options.force) {
|
|
3782
|
+
const conflicts = [];
|
|
3783
|
+
for (const file of template.files) {
|
|
3784
|
+
if (await fileExists(join5(projectRoot, file.path))) {
|
|
3785
|
+
conflicts.push(file.path);
|
|
3786
|
+
}
|
|
3787
|
+
}
|
|
3788
|
+
if (conflicts.length > 0) {
|
|
3789
|
+
throw new CliError(
|
|
3790
|
+
`Template "${template.id}" would overwrite existing files: ${conflicts.join(", ")}. Use --force to overwrite.`
|
|
3791
|
+
);
|
|
3792
|
+
}
|
|
3793
|
+
}
|
|
3794
|
+
if (options.dryRun) return planned;
|
|
3795
|
+
for (const file of template.files) {
|
|
3796
|
+
await writeTemplateFile(projectRoot, file);
|
|
3797
|
+
}
|
|
3798
|
+
return planned;
|
|
3799
|
+
}
|
|
3800
|
+
async function writeTemplateFile(projectRoot, file) {
|
|
3801
|
+
const absolute = join5(projectRoot, file.path);
|
|
3802
|
+
await mkdir4(dirname5(absolute), { recursive: true });
|
|
3803
|
+
if (file.path === "package.json" && await fileExists(absolute)) {
|
|
3804
|
+
const existing = JSON.parse(await readFile4(absolute, "utf8"));
|
|
3805
|
+
const next = JSON.parse(file.content);
|
|
3806
|
+
await writeFile4(
|
|
3807
|
+
absolute,
|
|
3808
|
+
`${JSON.stringify(mergePackageJson(existing, next), null, 2)}
|
|
3809
|
+
`,
|
|
3810
|
+
"utf8"
|
|
3811
|
+
);
|
|
3812
|
+
return;
|
|
3813
|
+
}
|
|
3814
|
+
await writeFile4(absolute, file.content, "utf8");
|
|
3815
|
+
}
|
|
3816
|
+
function mergePackageJson(existing, next) {
|
|
3817
|
+
return {
|
|
3818
|
+
...existing,
|
|
3819
|
+
...next,
|
|
3820
|
+
scripts: {
|
|
3821
|
+
...isRecord(existing.scripts) ? existing.scripts : {},
|
|
3822
|
+
...isRecord(next.scripts) ? next.scripts : {}
|
|
3823
|
+
},
|
|
3824
|
+
dependencies: {
|
|
3825
|
+
...isRecord(existing.dependencies) ? existing.dependencies : {},
|
|
3826
|
+
...isRecord(next.dependencies) ? next.dependencies : {}
|
|
3827
|
+
},
|
|
3828
|
+
devDependencies: {
|
|
3829
|
+
...isRecord(existing.devDependencies) ? existing.devDependencies : {},
|
|
3830
|
+
...isRecord(next.devDependencies) ? next.devDependencies : {}
|
|
3831
|
+
}
|
|
3832
|
+
};
|
|
3833
|
+
}
|
|
3834
|
+
function isRecord(value) {
|
|
3835
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3836
|
+
}
|
|
3837
|
+
function isProjectTemplateId(value) {
|
|
3838
|
+
return PROJECT_TEMPLATE_IDS.includes(value);
|
|
3839
|
+
}
|
|
3840
|
+
function packageJson(name, input) {
|
|
3841
|
+
return `${JSON.stringify({
|
|
3842
|
+
name,
|
|
3843
|
+
private: true,
|
|
3844
|
+
version: "0.1.0",
|
|
3845
|
+
type: "module",
|
|
3846
|
+
scripts: input.scripts,
|
|
3847
|
+
dependencies: input.dependencies,
|
|
3848
|
+
devDependencies: input.devDependencies ?? {}
|
|
3849
|
+
}, null, 2)}
|
|
3850
|
+
`;
|
|
3851
|
+
}
|
|
3852
|
+
var templateDefinitions = {
|
|
3853
|
+
next: {
|
|
3854
|
+
id: "next",
|
|
3855
|
+
label: "Next.js",
|
|
3856
|
+
cssPath: "src/app/globals.css",
|
|
3857
|
+
files: [
|
|
3858
|
+
{
|
|
3859
|
+
path: "package.json",
|
|
3860
|
+
content: packageJson("wensity-next-app", {
|
|
3861
|
+
scripts: {
|
|
3862
|
+
dev: "next dev",
|
|
3863
|
+
build: "next build",
|
|
3864
|
+
start: "next start"
|
|
3865
|
+
},
|
|
3866
|
+
dependencies: {
|
|
3867
|
+
"next": "^16.2.4",
|
|
3868
|
+
"react": "^19.2.4",
|
|
3869
|
+
"react-dom": "^19.2.4"
|
|
3870
|
+
},
|
|
3871
|
+
devDependencies: {
|
|
3872
|
+
"@types/node": "^22.10.2",
|
|
3873
|
+
"@types/react": "^19.0.0",
|
|
3874
|
+
"@types/react-dom": "^19.0.0",
|
|
3875
|
+
"tailwindcss": "^4.0.0",
|
|
3876
|
+
"typescript": "^5.7.2"
|
|
3877
|
+
}
|
|
3878
|
+
})
|
|
3879
|
+
},
|
|
3880
|
+
{ path: "src/app/globals.css", content: '@import "tailwindcss";\n' },
|
|
3881
|
+
{
|
|
3882
|
+
path: "src/app/layout.tsx",
|
|
3883
|
+
content: `import type { ReactNode } from "react";
|
|
3884
|
+
import "./globals.css";
|
|
3885
|
+
|
|
3886
|
+
export default function RootLayout({ children }: { children: ReactNode }) {
|
|
3887
|
+
return (
|
|
3888
|
+
<html lang="en">
|
|
3889
|
+
<body>{children}</body>
|
|
3890
|
+
</html>
|
|
3891
|
+
);
|
|
3892
|
+
}
|
|
3893
|
+
`
|
|
3894
|
+
},
|
|
3895
|
+
{
|
|
3896
|
+
path: "src/app/page.tsx",
|
|
3897
|
+
content: `export default function Page() {
|
|
3898
|
+
return <main className="min-h-screen bg-background text-foreground" />;
|
|
3899
|
+
}
|
|
3900
|
+
`
|
|
3901
|
+
},
|
|
3902
|
+
{
|
|
3903
|
+
path: "tsconfig.json",
|
|
3904
|
+
content: `${JSON.stringify({
|
|
3905
|
+
compilerOptions: {
|
|
3906
|
+
target: "ES2017",
|
|
3907
|
+
lib: ["dom", "dom.iterable", "esnext"],
|
|
3908
|
+
allowJs: true,
|
|
3909
|
+
skipLibCheck: true,
|
|
3910
|
+
strict: true,
|
|
3911
|
+
noEmit: true,
|
|
3912
|
+
esModuleInterop: true,
|
|
3913
|
+
module: "esnext",
|
|
3914
|
+
moduleResolution: "bundler",
|
|
3915
|
+
resolveJsonModule: true,
|
|
3916
|
+
isolatedModules: true,
|
|
3917
|
+
jsx: "preserve",
|
|
3918
|
+
incremental: true,
|
|
3919
|
+
paths: { "@/*": ["./src/*"] }
|
|
3920
|
+
},
|
|
3921
|
+
include: ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
|
3922
|
+
exclude: ["node_modules"]
|
|
3923
|
+
}, null, 2)}
|
|
3924
|
+
`
|
|
3925
|
+
}
|
|
3926
|
+
]
|
|
3927
|
+
},
|
|
3928
|
+
vite: {
|
|
3929
|
+
id: "vite",
|
|
3930
|
+
label: "Vite",
|
|
3931
|
+
cssPath: "src/index.css",
|
|
3932
|
+
files: [
|
|
3933
|
+
{
|
|
3934
|
+
path: "package.json",
|
|
3935
|
+
content: packageJson("wensity-vite-app", {
|
|
3936
|
+
scripts: {
|
|
3937
|
+
dev: "vite",
|
|
3938
|
+
build: "vite build",
|
|
3939
|
+
preview: "vite preview"
|
|
3940
|
+
},
|
|
3941
|
+
dependencies: {
|
|
3942
|
+
"vite": "^7.3.0",
|
|
3943
|
+
"react": "^19.2.4",
|
|
3944
|
+
"react-dom": "^19.2.4"
|
|
3945
|
+
},
|
|
3946
|
+
devDependencies: {
|
|
3947
|
+
"@vitejs/plugin-react": "^5.1.2",
|
|
3948
|
+
"@types/react": "^19.0.0",
|
|
3949
|
+
"@types/react-dom": "^19.0.0",
|
|
3950
|
+
"tailwindcss": "^4.0.0",
|
|
3951
|
+
"typescript": "^5.7.2"
|
|
3952
|
+
}
|
|
3953
|
+
})
|
|
3954
|
+
},
|
|
3955
|
+
{ path: "index.html", content: '<div id="root"></div><script type="module" src="/src/main.tsx"></script>\n' },
|
|
3956
|
+
{ path: "src/index.css", content: '@import "tailwindcss";\n' },
|
|
3957
|
+
{
|
|
3958
|
+
path: "src/main.tsx",
|
|
3959
|
+
content: `import { createRoot } from "react-dom/client";
|
|
3960
|
+
import "./index.css";
|
|
3961
|
+
|
|
3962
|
+
createRoot(document.getElementById("root")!).render(
|
|
3963
|
+
<main className="min-h-screen bg-background text-foreground" />,
|
|
3964
|
+
);
|
|
3965
|
+
`
|
|
3966
|
+
},
|
|
3967
|
+
{
|
|
3968
|
+
path: "vite.config.ts",
|
|
3969
|
+
content: `import { defineConfig } from "vite";
|
|
3970
|
+
import react from "@vitejs/plugin-react";
|
|
3971
|
+
|
|
3972
|
+
export default defineConfig({
|
|
3973
|
+
plugins: [react()],
|
|
3974
|
+
resolve: {
|
|
3975
|
+
alias: {
|
|
3976
|
+
"@": new URL("./src", import.meta.url).pathname,
|
|
3977
|
+
},
|
|
3978
|
+
},
|
|
3979
|
+
});
|
|
3980
|
+
`
|
|
3981
|
+
}
|
|
3982
|
+
]
|
|
3983
|
+
},
|
|
3984
|
+
astro: {
|
|
3985
|
+
id: "astro",
|
|
3986
|
+
label: "Astro",
|
|
3987
|
+
cssPath: "src/styles/global.css",
|
|
3988
|
+
files: [
|
|
3989
|
+
{
|
|
3990
|
+
path: "package.json",
|
|
3991
|
+
content: packageJson("wensity-astro-app", {
|
|
3992
|
+
scripts: {
|
|
3993
|
+
dev: "astro dev",
|
|
3994
|
+
build: "astro build",
|
|
3995
|
+
preview: "astro preview"
|
|
3996
|
+
},
|
|
3997
|
+
dependencies: {
|
|
3998
|
+
"@astrojs/react": "^4.4.0",
|
|
3999
|
+
"astro": "^5.16.0",
|
|
4000
|
+
"react": "^19.2.4",
|
|
4001
|
+
"react-dom": "^19.2.4"
|
|
4002
|
+
},
|
|
4003
|
+
devDependencies: {
|
|
4004
|
+
"tailwindcss": "^4.0.0",
|
|
4005
|
+
"typescript": "^5.7.2"
|
|
4006
|
+
}
|
|
4007
|
+
})
|
|
4008
|
+
},
|
|
4009
|
+
{ path: "src/styles/global.css", content: '@import "tailwindcss";\n' },
|
|
4010
|
+
{
|
|
4011
|
+
path: "astro.config.mjs",
|
|
4012
|
+
content: `import { defineConfig } from "astro/config";
|
|
4013
|
+
import react from "@astrojs/react";
|
|
4014
|
+
|
|
4015
|
+
export default defineConfig({
|
|
4016
|
+
integrations: [react()],
|
|
4017
|
+
});
|
|
4018
|
+
`
|
|
4019
|
+
},
|
|
4020
|
+
{
|
|
4021
|
+
path: "src/pages/index.astro",
|
|
4022
|
+
content: `---
|
|
4023
|
+
import "../styles/global.css";
|
|
4024
|
+
---
|
|
4025
|
+
|
|
4026
|
+
<main class="min-h-screen bg-background text-foreground"></main>
|
|
4027
|
+
`
|
|
4028
|
+
}
|
|
4029
|
+
]
|
|
4030
|
+
},
|
|
4031
|
+
"react-router": {
|
|
4032
|
+
id: "react-router",
|
|
4033
|
+
label: "React Router",
|
|
4034
|
+
cssPath: "src/app/globals.css",
|
|
4035
|
+
files: [
|
|
4036
|
+
{
|
|
4037
|
+
path: "package.json",
|
|
4038
|
+
content: packageJson("wensity-react-router-app", {
|
|
4039
|
+
scripts: {
|
|
4040
|
+
dev: "vite",
|
|
4041
|
+
build: "vite build",
|
|
4042
|
+
preview: "vite preview"
|
|
4043
|
+
},
|
|
4044
|
+
dependencies: {
|
|
4045
|
+
"vite": "^7.3.0",
|
|
4046
|
+
"react": "^19.2.4",
|
|
4047
|
+
"react-dom": "^19.2.4",
|
|
4048
|
+
"react-router": "^7.12.0"
|
|
4049
|
+
},
|
|
4050
|
+
devDependencies: {
|
|
4051
|
+
"@vitejs/plugin-react": "^5.1.2",
|
|
4052
|
+
"@types/react": "^19.0.0",
|
|
4053
|
+
"@types/react-dom": "^19.0.0",
|
|
4054
|
+
"tailwindcss": "^4.0.0",
|
|
4055
|
+
"typescript": "^5.7.2"
|
|
4056
|
+
}
|
|
4057
|
+
})
|
|
4058
|
+
},
|
|
4059
|
+
{ path: "index.html", content: '<div id="root"></div><script type="module" src="/src/main.tsx"></script>\n' },
|
|
4060
|
+
{ path: "src/app/globals.css", content: '@import "tailwindcss";\n' },
|
|
4061
|
+
{
|
|
4062
|
+
path: "src/main.tsx",
|
|
4063
|
+
content: `import { createRoot } from "react-dom/client";
|
|
4064
|
+
import { BrowserRouter, Route, Routes } from "react-router";
|
|
4065
|
+
import "./app/globals.css";
|
|
4066
|
+
|
|
4067
|
+
createRoot(document.getElementById("root")!).render(
|
|
4068
|
+
<BrowserRouter>
|
|
4069
|
+
<Routes>
|
|
4070
|
+
<Route path="/" element={<main className="min-h-screen bg-background text-foreground" />} />
|
|
4071
|
+
</Routes>
|
|
4072
|
+
</BrowserRouter>,
|
|
4073
|
+
);
|
|
4074
|
+
`
|
|
4075
|
+
},
|
|
4076
|
+
{
|
|
4077
|
+
path: "vite.config.ts",
|
|
4078
|
+
content: `import { defineConfig } from "vite";
|
|
4079
|
+
import react from "@vitejs/plugin-react";
|
|
4080
|
+
|
|
4081
|
+
export default defineConfig({
|
|
4082
|
+
plugins: [react()],
|
|
4083
|
+
resolve: {
|
|
4084
|
+
alias: {
|
|
4085
|
+
"@": new URL("./src", import.meta.url).pathname,
|
|
4086
|
+
},
|
|
4087
|
+
},
|
|
4088
|
+
});
|
|
4089
|
+
`
|
|
4090
|
+
}
|
|
4091
|
+
]
|
|
4092
|
+
}
|
|
4093
|
+
};
|
|
4094
|
+
function formatTemplateFiles(files) {
|
|
4095
|
+
return files.map(toPosixPath);
|
|
4096
|
+
}
|
|
4097
|
+
|
|
2780
4098
|
// src/style-css.ts
|
|
2781
4099
|
var ROOT_SELECTOR = ":root";
|
|
2782
4100
|
var DARK_SELECTOR = ".dark";
|
|
@@ -2862,8 +4180,8 @@ function escapeRegExp(value) {
|
|
|
2862
4180
|
}
|
|
2863
4181
|
|
|
2864
4182
|
// src/component-install.ts
|
|
2865
|
-
import { mkdir as
|
|
2866
|
-
import { dirname as
|
|
4183
|
+
import { mkdir as mkdir5, readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
|
|
4184
|
+
import { dirname as dirname6, join as join6, relative as relative3 } from "path";
|
|
2867
4185
|
|
|
2868
4186
|
// src/templates.ts
|
|
2869
4187
|
function cnUtilityTemplate() {
|
|
@@ -3071,7 +4389,7 @@ async function prepareInstall(projectRoot, config, payload, options = {}) {
|
|
|
3071
4389
|
}
|
|
3072
4390
|
}
|
|
3073
4391
|
if (!hasGraphHelperFiles && helperNeeds.primitives) {
|
|
3074
|
-
const primitivesPath = toPosixPath(
|
|
4392
|
+
const primitivesPath = toPosixPath(join6(config.components, "primitives.tsx"));
|
|
3075
4393
|
if (!await fileExists(resolveInside(projectRoot, primitivesPath))) {
|
|
3076
4394
|
const primitives = primitivesTemplate(config.aliases.utils);
|
|
3077
4395
|
files.push({
|
|
@@ -3112,7 +4430,7 @@ async function planPrimitiveCssFile(projectRoot, config, payload) {
|
|
|
3112
4430
|
const cssRelative = config.tailwind?.css;
|
|
3113
4431
|
if (!cssRelative) return void 0;
|
|
3114
4432
|
const absolutePath = resolveInside(projectRoot, cssRelative);
|
|
3115
|
-
const existing = await fileExists(absolutePath) ? await
|
|
4433
|
+
const existing = await fileExists(absolutePath) ? await readFile5(absolutePath, "utf8") : "";
|
|
3116
4434
|
const withTokens = upsertPrimitiveCssBlock(existing, primitiveCss);
|
|
3117
4435
|
const fonts = curatedFontsFromStyle(style);
|
|
3118
4436
|
const fontPlan = planFontInstall(fonts.headingFont, fonts.bodyFont);
|
|
@@ -3161,8 +4479,8 @@ ${conflicts.map((path) => ` - ${path}`).join("\n")}`);
|
|
|
3161
4479
|
}
|
|
3162
4480
|
async function writePlannedFiles(files) {
|
|
3163
4481
|
for (const file of files) {
|
|
3164
|
-
await
|
|
3165
|
-
await
|
|
4482
|
+
await mkdir5(dirname6(file.absolutePath), { recursive: true });
|
|
4483
|
+
await writeFile5(file.absolutePath, file.content, "utf8");
|
|
3166
4484
|
}
|
|
3167
4485
|
}
|
|
3168
4486
|
function summarizeFiles(projectRoot, files) {
|
|
@@ -3187,13 +4505,13 @@ function getPayloadFileKind(payloadFile) {
|
|
|
3187
4505
|
}
|
|
3188
4506
|
function getPayloadOutputPath(payloadFile, fallbackFileName, config) {
|
|
3189
4507
|
if (isUtilsHelperFile(payloadFile)) return withSourceExtension(config.utils, "ts");
|
|
3190
|
-
if (isOverlayHelperFile(payloadFile)) return toPosixPath(
|
|
3191
|
-
if (isPrimitivesHelperFile(payloadFile)) return toPosixPath(
|
|
4508
|
+
if (isOverlayHelperFile(payloadFile)) return toPosixPath(join6(config.components, "overlay.tsx"));
|
|
4509
|
+
if (isPrimitivesHelperFile(payloadFile)) return toPosixPath(join6(config.components, "primitives.tsx"));
|
|
3192
4510
|
if (payloadFile.kind === "helper") {
|
|
3193
4511
|
throw new CliError(`Unsupported registry helper file path: ${payloadFile.path}`);
|
|
3194
4512
|
}
|
|
3195
4513
|
const safePayloadPath = sanitizePayloadPath(payloadFile.path, fallbackFileName);
|
|
3196
|
-
return toPosixPath(
|
|
4514
|
+
return toPosixPath(join6(config.components, safePayloadPath));
|
|
3197
4515
|
}
|
|
3198
4516
|
function isGraphHelperFile(payloadFile) {
|
|
3199
4517
|
return isUtilsHelperFile(payloadFile) || isOverlayHelperFile(payloadFile) || isPrimitivesHelperFile(payloadFile);
|
|
@@ -3290,7 +4608,7 @@ function normalizePackageName(specifier) {
|
|
|
3290
4608
|
function withSourceExtension(path, extension) {
|
|
3291
4609
|
const directory = parentDirectory(path);
|
|
3292
4610
|
const fileName = extensionlessPath(path.split("/").at(-1) ?? path);
|
|
3293
|
-
return toPosixPath(
|
|
4611
|
+
return toPosixPath(join6(directory === "." ? "" : directory, `${fileName}.${extension}`));
|
|
3294
4612
|
}
|
|
3295
4613
|
|
|
3296
4614
|
// src/commands.ts
|
|
@@ -3309,6 +4627,12 @@ async function run(context) {
|
|
|
3309
4627
|
case "init":
|
|
3310
4628
|
await initCommand(context, parsed);
|
|
3311
4629
|
return;
|
|
4630
|
+
case "apply":
|
|
4631
|
+
await applyCommand(context, parsed);
|
|
4632
|
+
return;
|
|
4633
|
+
case "preset":
|
|
4634
|
+
await presetCommand(context, parsed, positionals);
|
|
4635
|
+
return;
|
|
3312
4636
|
case "login":
|
|
3313
4637
|
await loginCommand(context, parsed);
|
|
3314
4638
|
return;
|
|
@@ -3336,6 +4660,35 @@ async function run(context) {
|
|
|
3336
4660
|
${HELP_TEXT.trimEnd()}`);
|
|
3337
4661
|
}
|
|
3338
4662
|
}
|
|
4663
|
+
async function presetCommand(_context, parsed, positionals) {
|
|
4664
|
+
const [subcommand, positionalCode, ...extra] = positionals;
|
|
4665
|
+
if (subcommand !== "inspect") {
|
|
4666
|
+
throw new CliError(
|
|
4667
|
+
`Unknown preset command: ${subcommand ?? ""}
|
|
4668
|
+
|
|
4669
|
+
Usage: wensity preset inspect <code> [--json]`
|
|
4670
|
+
);
|
|
4671
|
+
}
|
|
4672
|
+
if (extra.length > 0) {
|
|
4673
|
+
throw new CliError("Too many arguments.\n\nUsage: wensity preset inspect <code> [--json]");
|
|
4674
|
+
}
|
|
4675
|
+
const optionCode = getStringOption(parsed, "preset");
|
|
4676
|
+
const presetFile = getStringOption(parsed, "preset-file");
|
|
4677
|
+
if (positionalCode && optionCode) {
|
|
4678
|
+
throw new CliError("Use either a positional preset code or --preset <code>, not both.");
|
|
4679
|
+
}
|
|
4680
|
+
const { style, presetCode } = await resolvePresetStyle({
|
|
4681
|
+
presetCode: optionCode ?? positionalCode,
|
|
4682
|
+
presetFile
|
|
4683
|
+
});
|
|
4684
|
+
const summary = createPresetInspectSummary({ presetCode, style });
|
|
4685
|
+
if (hasFlag(parsed, "json")) {
|
|
4686
|
+
printJson(summary);
|
|
4687
|
+
return;
|
|
4688
|
+
}
|
|
4689
|
+
printTitle("Preset inspection");
|
|
4690
|
+
print(formatPresetInspectSummary(summary));
|
|
4691
|
+
}
|
|
3339
4692
|
async function initCommand(context, parsed) {
|
|
3340
4693
|
const dryRun = hasFlag(parsed, "dry-run");
|
|
3341
4694
|
const force = hasFlag(parsed, "force");
|
|
@@ -3343,6 +4696,8 @@ async function initCommand(context, parsed) {
|
|
|
3343
4696
|
const apiUrl = getStringOption(parsed, "api-url") ?? context.env.WENSITY_API_URL ?? DEFAULT_API_ORIGIN;
|
|
3344
4697
|
const presetCode = getStringOption(parsed, "preset");
|
|
3345
4698
|
const presetFile = getStringOption(parsed, "preset-file");
|
|
4699
|
+
const templateId = parseProjectTemplate(getStringOption(parsed, "template"));
|
|
4700
|
+
const template = templateId ? getProjectTemplateDefinition(templateId) : void 0;
|
|
3346
4701
|
const hasPreset = Boolean(presetCode || presetFile);
|
|
3347
4702
|
const dependencies = ["clsx", "tailwind-merge"];
|
|
3348
4703
|
if (hasPreset) {
|
|
@@ -3353,18 +4708,21 @@ async function initCommand(context, parsed) {
|
|
|
3353
4708
|
apiUrl,
|
|
3354
4709
|
presetCode,
|
|
3355
4710
|
presetFile,
|
|
3356
|
-
dependencies
|
|
4711
|
+
dependencies,
|
|
4712
|
+
template
|
|
3357
4713
|
});
|
|
3358
4714
|
return;
|
|
3359
4715
|
}
|
|
3360
|
-
const
|
|
3361
|
-
const
|
|
4716
|
+
const templateFiles = template ? await scaffoldProjectTemplate(context.cwd, template, { dryRun, force }) : [];
|
|
4717
|
+
const config = template ? applyTemplateToConfig(createDefaultConfig(context.cwd, apiUrl), template) : createDefaultConfig(context.cwd, apiUrl);
|
|
4718
|
+
const configPath = join7(context.cwd, CONFIG_FILE_NAME);
|
|
3362
4719
|
const utilityPath = resolveConfiguredFilePath(context.cwd, config.utils);
|
|
3363
4720
|
const utilityRelativePath = toPosixPath(config.utils.endsWith(".ts") ? config.utils : `${config.utils}.ts`);
|
|
3364
4721
|
if (dryRun) {
|
|
3365
4722
|
printTitle("Project initialization preview");
|
|
3366
4723
|
print(action("Would write:"));
|
|
3367
|
-
print(formatList([CONFIG_FILE_NAME, utilityRelativePath]));
|
|
4724
|
+
print(formatList([...formatTemplateFiles(templateFiles), CONFIG_FILE_NAME, utilityRelativePath]));
|
|
4725
|
+
if (template) print(action(`Template: ${template.label}`));
|
|
3368
4726
|
if (install) print(action(`Would install: ${dependencies.join(" ")}`));
|
|
3369
4727
|
return;
|
|
3370
4728
|
}
|
|
@@ -3392,13 +4750,17 @@ async function initWithPreset(context, options) {
|
|
|
3392
4750
|
presetCode: options.presetCode,
|
|
3393
4751
|
presetFile: options.presetFile
|
|
3394
4752
|
});
|
|
3395
|
-
const
|
|
3396
|
-
const fontPlan = planFontInstall(fonts.headingFont, fonts.bodyFont);
|
|
3397
|
-
const installDependencies = [...options.dependencies, ...fontPlan.packages];
|
|
3398
|
-
const configPath = join6(context.cwd, CONFIG_FILE_NAME);
|
|
4753
|
+
const configPath = join7(context.cwd, CONFIG_FILE_NAME);
|
|
3399
4754
|
const configExists = await fileExists(configPath);
|
|
4755
|
+
const templateFiles = options.template ? await scaffoldProjectTemplate(context.cwd, options.template, {
|
|
4756
|
+
dryRun: options.dryRun,
|
|
4757
|
+
force: options.force
|
|
4758
|
+
}) : [];
|
|
3400
4759
|
let config;
|
|
3401
4760
|
if (configExists && !options.force) {
|
|
4761
|
+
if (options.template) {
|
|
4762
|
+
throw new CliError(`${CONFIG_FILE_NAME} already exists. Omit --template for existing projects or use --force.`);
|
|
4763
|
+
}
|
|
3402
4764
|
const loaded = await loadConfig(context.cwd, { apiUrl: options.apiUrl });
|
|
3403
4765
|
config = {
|
|
3404
4766
|
...loaded.config,
|
|
@@ -3406,63 +4768,36 @@ async function initWithPreset(context, options) {
|
|
|
3406
4768
|
};
|
|
3407
4769
|
} else {
|
|
3408
4770
|
config = {
|
|
3409
|
-
...createDefaultConfig(context.cwd, options.apiUrl),
|
|
4771
|
+
...options.template ? applyTemplateToConfig(createDefaultConfig(context.cwd, options.apiUrl), options.template) : createDefaultConfig(context.cwd, options.apiUrl),
|
|
3410
4772
|
style
|
|
3411
4773
|
};
|
|
3412
4774
|
}
|
|
3413
4775
|
const utilityPath = resolveConfiguredFilePath(context.cwd, config.utils);
|
|
3414
4776
|
const utilityRelativePath = toPosixPath(config.utils.endsWith(".ts") ? config.utils : `${config.utils}.ts`);
|
|
3415
|
-
const
|
|
3416
|
-
|
|
3417
|
-
try {
|
|
3418
|
-
const payload = await withSpinner(
|
|
3419
|
-
`Fetching primitive tokens (${INIT_PRIMITIVE_CSS_SLUG})`,
|
|
3420
|
-
() => fetchComponentPayload({ slug: INIT_PRIMITIVE_CSS_SLUG, registry }),
|
|
3421
|
-
"Fetched primitive tokens"
|
|
3422
|
-
);
|
|
3423
|
-
if (typeof payload.primitiveCss !== "string" || !payload.primitiveCss.trim()) {
|
|
3424
|
-
throw new CliError(
|
|
3425
|
-
`Pinned slug "${INIT_PRIMITIVE_CSS_SLUG}" did not return primitiveCss. Cannot apply preset styles.`
|
|
3426
|
-
);
|
|
3427
|
-
}
|
|
3428
|
-
primitiveCss = applyStyleToPrimitiveCss(payload.primitiveCss, style).trim();
|
|
3429
|
-
} catch (error) {
|
|
3430
|
-
if (error instanceof CliError) throw error;
|
|
3431
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
3432
|
-
throw new CliError(`Failed to fetch primitive CSS for preset init: ${message}`);
|
|
3433
|
-
}
|
|
3434
|
-
const cssRelative = config.tailwind?.css;
|
|
3435
|
-
if (!cssRelative) {
|
|
3436
|
-
throw new CliError("No Tailwind CSS path configured. Set tailwind.css in wensity.json.");
|
|
3437
|
-
}
|
|
3438
|
-
const cssAbsolute = resolveInside(context.cwd, cssRelative);
|
|
3439
|
-
const existingCss = await fileExists(cssAbsolute) ? await readFile5(cssAbsolute, "utf8") : "";
|
|
3440
|
-
const withTokens = upsertPrimitiveCssBlock(existingCss, primitiveCss);
|
|
3441
|
-
const nextCss = upsertFontImportBlock(withTokens, fontPlan.block);
|
|
3442
|
-
const cssChanged = nextCss !== existingCss;
|
|
3443
|
-
const installedPackages = readInstalledPackageNames(context.cwd);
|
|
3444
|
-
const unusedFontWarning = installedPackages ? warnUnusedFontPackageMessage(fonts.headingFont, fonts.bodyFont, installedPackages) : void 0;
|
|
4777
|
+
const prepared = await preparePresetStyleApplication(context.cwd, config, style, "preset init");
|
|
4778
|
+
const installDependencies = [...options.dependencies, ...prepared.fontPlan.packages];
|
|
3445
4779
|
if (options.dryRun) {
|
|
3446
4780
|
printTitle("Project initialization preview (preset)");
|
|
3447
4781
|
print(action("Would write:"));
|
|
3448
|
-
const planned = [CONFIG_FILE_NAME, utilityRelativePath];
|
|
3449
|
-
if (cssChanged) planned.push(toPosixPath(cssRelative));
|
|
4782
|
+
const planned = [...formatTemplateFiles(templateFiles), CONFIG_FILE_NAME, utilityRelativePath];
|
|
4783
|
+
if (prepared.cssChanged) planned.push(toPosixPath(prepared.cssRelative));
|
|
3450
4784
|
print(formatList(planned));
|
|
4785
|
+
if (options.template) print(action(`Template: ${options.template.label}`));
|
|
3451
4786
|
print(action(`Preset: ${presetCode.slice(0, 24)}\u2026`));
|
|
3452
4787
|
print(action(`Style: icon=${style.iconLibrary} radius=${style.radius}`));
|
|
3453
|
-
if (fontPlan.packages.length > 0) {
|
|
3454
|
-
print(action(`Fonts: ${fontPlan.packages.join(" ")}`));
|
|
4788
|
+
if (prepared.fontPlan.packages.length > 0) {
|
|
4789
|
+
print(action(`Fonts: ${prepared.fontPlan.packages.join(" ")}`));
|
|
3455
4790
|
}
|
|
3456
4791
|
if (options.install) print(action(`Would install: ${installDependencies.join(" ")}`));
|
|
3457
|
-
if (unusedFontWarning) warn(unusedFontWarning);
|
|
4792
|
+
if (prepared.unusedFontWarning) warn(prepared.unusedFontWarning);
|
|
3458
4793
|
return;
|
|
3459
4794
|
}
|
|
3460
4795
|
const shouldWriteUtility = options.force || !await fileExists(utilityPath);
|
|
3461
4796
|
await commitPresetInitWrites({
|
|
3462
|
-
cssAbsolute,
|
|
3463
|
-
existingCss,
|
|
3464
|
-
nextCss,
|
|
3465
|
-
cssChanged,
|
|
4797
|
+
cssAbsolute: prepared.cssAbsolute,
|
|
4798
|
+
existingCss: prepared.existingCss,
|
|
4799
|
+
nextCss: prepared.nextCss,
|
|
4800
|
+
cssChanged: prepared.cssChanged,
|
|
3466
4801
|
writeUtility: shouldWriteUtility,
|
|
3467
4802
|
utilityAbsolutePath: utilityPath,
|
|
3468
4803
|
utilityContent: cnUtilityTemplate(),
|
|
@@ -3479,26 +4814,150 @@ async function initWithPreset(context, options) {
|
|
|
3479
4814
|
}
|
|
3480
4815
|
printTitle("Project initialized");
|
|
3481
4816
|
const created = [
|
|
4817
|
+
...options.template ? [success(`template: ${options.template.label}`)] : [],
|
|
3482
4818
|
success(CONFIG_FILE_NAME),
|
|
3483
4819
|
success(utilityRelativePath),
|
|
3484
4820
|
success(`registry: ${options.apiUrl}`),
|
|
3485
4821
|
success(`preset applied (${style.iconLibrary}, radius=${style.radius})`)
|
|
3486
4822
|
];
|
|
3487
|
-
if (cssChanged) {
|
|
3488
|
-
created.push(success(`CSS tokens: ${toPosixPath(cssRelative)}`));
|
|
4823
|
+
if (prepared.cssChanged) {
|
|
4824
|
+
created.push(success(`CSS tokens: ${toPosixPath(prepared.cssRelative)}`));
|
|
3489
4825
|
} else {
|
|
3490
|
-
created.push(action(`CSS tokens unchanged: ${toPosixPath(cssRelative)}`));
|
|
4826
|
+
created.push(action(`CSS tokens unchanged: ${toPosixPath(prepared.cssRelative)}`));
|
|
3491
4827
|
}
|
|
3492
|
-
if (fontPlan.packages.length > 0) {
|
|
3493
|
-
created.push(success(`fonts: ${fontPlan.packages.join(", ")}`));
|
|
4828
|
+
if (prepared.fontPlan.packages.length > 0) {
|
|
4829
|
+
created.push(success(`fonts: ${prepared.fontPlan.packages.join(", ")}`));
|
|
3494
4830
|
}
|
|
3495
4831
|
print(panel("Created", created));
|
|
3496
|
-
if (unusedFontWarning) warn(unusedFontWarning);
|
|
4832
|
+
if (prepared.unusedFontWarning) warn(prepared.unusedFontWarning);
|
|
3497
4833
|
print(nextSteps([
|
|
3498
4834
|
"Browse available components: npx wensity list",
|
|
3499
4835
|
"Install a primitive: npx wensity add button"
|
|
3500
4836
|
]));
|
|
3501
4837
|
}
|
|
4838
|
+
async function applyCommand(context, parsed) {
|
|
4839
|
+
const dryRun = hasFlag(parsed, "dry-run");
|
|
4840
|
+
const install = !hasFlag(parsed, "no-install");
|
|
4841
|
+
const apiUrl = getStringOption(parsed, "api-url") ?? context.env.WENSITY_API_URL;
|
|
4842
|
+
const registryOverride = getStringOption(parsed, "registry");
|
|
4843
|
+
const presetCodeInput = getStringOption(parsed, "preset");
|
|
4844
|
+
const presetFile = getStringOption(parsed, "preset-file");
|
|
4845
|
+
if (!presetCodeInput && !presetFile) {
|
|
4846
|
+
throw new CliError("Missing preset. Pass --preset <code> or --preset-file <path>.");
|
|
4847
|
+
}
|
|
4848
|
+
const loaded = await loadConfig(context.cwd, { registry: registryOverride, apiUrl });
|
|
4849
|
+
if (!loaded.exists) {
|
|
4850
|
+
throw new CliError(`${CONFIG_FILE_NAME} not found. Run "wensity init" first, then "wensity apply --preset <code>".`);
|
|
4851
|
+
}
|
|
4852
|
+
const { style, presetCode } = await resolvePresetStyle({
|
|
4853
|
+
presetCode: presetCodeInput,
|
|
4854
|
+
presetFile
|
|
4855
|
+
});
|
|
4856
|
+
const prepared = await preparePresetStyleApplication(
|
|
4857
|
+
loaded.projectRoot,
|
|
4858
|
+
{
|
|
4859
|
+
...loaded.config,
|
|
4860
|
+
style
|
|
4861
|
+
},
|
|
4862
|
+
style,
|
|
4863
|
+
"preset apply"
|
|
4864
|
+
);
|
|
4865
|
+
const installDependencies = prepared.fontPlan.packages;
|
|
4866
|
+
if (dryRun) {
|
|
4867
|
+
printTitle("Preset apply preview");
|
|
4868
|
+
print(action("Would write:"));
|
|
4869
|
+
const planned = [CONFIG_FILE_NAME];
|
|
4870
|
+
if (prepared.cssChanged) planned.push(toPosixPath(prepared.cssRelative));
|
|
4871
|
+
print(formatList(planned));
|
|
4872
|
+
print(action(`Preset: ${presetCode.slice(0, 24)}\u2026`));
|
|
4873
|
+
print(action(`Style: icon=${style.iconLibrary} radius=${style.radius}`));
|
|
4874
|
+
if (prepared.fontPlan.packages.length > 0) {
|
|
4875
|
+
print(action(`Fonts: ${prepared.fontPlan.packages.join(" ")}`));
|
|
4876
|
+
}
|
|
4877
|
+
if (install && installDependencies.length > 0) {
|
|
4878
|
+
print(action(`Would install: ${installDependencies.join(" ")}`));
|
|
4879
|
+
}
|
|
4880
|
+
if (prepared.unusedFontWarning) warn(prepared.unusedFontWarning);
|
|
4881
|
+
return;
|
|
4882
|
+
}
|
|
4883
|
+
await commitPresetInitWrites({
|
|
4884
|
+
cssAbsolute: prepared.cssAbsolute,
|
|
4885
|
+
existingCss: prepared.existingCss,
|
|
4886
|
+
nextCss: prepared.nextCss,
|
|
4887
|
+
cssChanged: prepared.cssChanged,
|
|
4888
|
+
writeUtility: false,
|
|
4889
|
+
utilityAbsolutePath: resolveConfiguredFilePath(loaded.projectRoot, loaded.config.utils),
|
|
4890
|
+
utilityContent: cnUtilityTemplate(),
|
|
4891
|
+
commitConfig: async () => {
|
|
4892
|
+
await mergeStyleIntoConfigFile(loaded.configPath, style);
|
|
4893
|
+
}
|
|
4894
|
+
});
|
|
4895
|
+
if (install && installDependencies.length > 0) {
|
|
4896
|
+
runInstall(loaded.projectRoot, missingDependencies(loaded.projectRoot, installDependencies));
|
|
4897
|
+
}
|
|
4898
|
+
printTitle("Preset applied");
|
|
4899
|
+
const applied = [
|
|
4900
|
+
success(CONFIG_FILE_NAME),
|
|
4901
|
+
success(`preset applied (${style.iconLibrary}, radius=${style.radius})`)
|
|
4902
|
+
];
|
|
4903
|
+
if (prepared.cssChanged) {
|
|
4904
|
+
applied.push(success(`CSS tokens: ${toPosixPath(prepared.cssRelative)}`));
|
|
4905
|
+
} else {
|
|
4906
|
+
applied.push(action(`CSS tokens unchanged: ${toPosixPath(prepared.cssRelative)}`));
|
|
4907
|
+
}
|
|
4908
|
+
if (prepared.fontPlan.packages.length > 0) {
|
|
4909
|
+
applied.push(success(`fonts: ${prepared.fontPlan.packages.join(", ")}`));
|
|
4910
|
+
}
|
|
4911
|
+
print(panel("Updated", applied));
|
|
4912
|
+
if (prepared.unusedFontWarning) warn(prepared.unusedFontWarning);
|
|
4913
|
+
print(nextSteps([
|
|
4914
|
+
"Review your changed CSS tokens",
|
|
4915
|
+
"Run your app to verify the updated primitive theme"
|
|
4916
|
+
]));
|
|
4917
|
+
}
|
|
4918
|
+
async function preparePresetStyleApplication(projectRoot, config, style, operation) {
|
|
4919
|
+
const fonts = curatedFontsFromStyle(style);
|
|
4920
|
+
const fontPlan = planFontInstall(fonts.headingFont, fonts.bodyFont);
|
|
4921
|
+
const registry = config.registry;
|
|
4922
|
+
let primitiveCss;
|
|
4923
|
+
try {
|
|
4924
|
+
const payload = await withSpinner(
|
|
4925
|
+
`Fetching primitive tokens (${INIT_PRIMITIVE_CSS_SLUG})`,
|
|
4926
|
+
() => fetchComponentPayload({ slug: INIT_PRIMITIVE_CSS_SLUG, registry }),
|
|
4927
|
+
"Fetched primitive tokens"
|
|
4928
|
+
);
|
|
4929
|
+
if (typeof payload.primitiveCss !== "string" || !payload.primitiveCss.trim()) {
|
|
4930
|
+
throw new CliError(
|
|
4931
|
+
`Pinned slug "${INIT_PRIMITIVE_CSS_SLUG}" did not return primitiveCss. Cannot apply preset styles.`
|
|
4932
|
+
);
|
|
4933
|
+
}
|
|
4934
|
+
primitiveCss = applyStyleToPrimitiveCss(payload.primitiveCss, style).trim();
|
|
4935
|
+
} catch (error) {
|
|
4936
|
+
if (error instanceof CliError) throw error;
|
|
4937
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4938
|
+
throw new CliError(`Failed to fetch primitive CSS for ${operation}: ${message}`);
|
|
4939
|
+
}
|
|
4940
|
+
const cssRelative = config.tailwind?.css;
|
|
4941
|
+
if (!cssRelative) {
|
|
4942
|
+
throw new CliError("No Tailwind CSS path configured. Set tailwind.css in wensity.json.");
|
|
4943
|
+
}
|
|
4944
|
+
const cssAbsolute = resolveInside(projectRoot, cssRelative);
|
|
4945
|
+
const existingCss = await fileExists(cssAbsolute) ? await readFile6(cssAbsolute, "utf8") : "";
|
|
4946
|
+
const withTokens = upsertPrimitiveCssBlock(existingCss, primitiveCss);
|
|
4947
|
+
const nextCss = upsertFontImportBlock(withTokens, fontPlan.block);
|
|
4948
|
+
const cssChanged = nextCss !== existingCss;
|
|
4949
|
+
const installedPackages = readInstalledPackageNames(projectRoot);
|
|
4950
|
+
const unusedFontWarning = installedPackages ? warnUnusedFontPackageMessage(fonts.headingFont, fonts.bodyFont, installedPackages) : void 0;
|
|
4951
|
+
return {
|
|
4952
|
+
fontPlan,
|
|
4953
|
+
cssRelative,
|
|
4954
|
+
cssAbsolute,
|
|
4955
|
+
existingCss,
|
|
4956
|
+
nextCss,
|
|
4957
|
+
cssChanged,
|
|
4958
|
+
unusedFontWarning
|
|
4959
|
+
};
|
|
4960
|
+
}
|
|
3502
4961
|
async function loginCommand(context, parsed) {
|
|
3503
4962
|
const apiUrl = getStringOption(parsed, "api-url") ?? context.env.WENSITY_API_URL ?? DEFAULT_API_ORIGIN;
|
|
3504
4963
|
const apiBaseUrl = normalizeUrlOrigin(apiUrl);
|
|
@@ -3788,8 +5247,8 @@ function formatAccountPanel(whoami, savedPath) {
|
|
|
3788
5247
|
return panel(isPro ? "Wensity Pro" : "Wensity Free", lines);
|
|
3789
5248
|
}
|
|
3790
5249
|
async function writeTextFile(path, content) {
|
|
3791
|
-
await
|
|
3792
|
-
await
|
|
5250
|
+
await mkdir6(dirname7(path), { recursive: true });
|
|
5251
|
+
await writeFile6(path, content, "utf8");
|
|
3793
5252
|
}
|
|
3794
5253
|
|
|
3795
5254
|
// src/index.ts
|