wensity 0.1.6 → 0.1.8
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 +3 -3
- package/dist/index.js +1286 -264
- package/package.json +10 -10
- package/LICENSE +0 -21
package/dist/index.js
CHANGED
|
@@ -4,10 +4,160 @@
|
|
|
4
4
|
import { mkdir as mkdir5, readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
|
|
5
5
|
import { dirname as dirname6, join as join6 } from "path";
|
|
6
6
|
|
|
7
|
+
// src/constants.ts
|
|
8
|
+
var CLI_NAME = "wensity";
|
|
9
|
+
var CLI_VERSION = "0.1.8";
|
|
10
|
+
var CONFIG_FILE_NAME = "wensity.json";
|
|
11
|
+
var DEFAULT_API_ORIGIN = "https://ui.wensity.com";
|
|
12
|
+
var DEFAULT_REGISTRY_PATH = "/api/registry";
|
|
13
|
+
var DEFAULT_COMPONENTS_DIR = "src/components/wensity";
|
|
14
|
+
var DEFAULT_UTILS_PATH = "src/lib/utils";
|
|
15
|
+
var DEFAULT_COMPONENTS_ALIAS = "@/components/wensity";
|
|
16
|
+
var DEFAULT_UTILS_ALIAS = "@/lib/utils";
|
|
17
|
+
var INIT_PRIMITIVE_CSS_SLUG = "button";
|
|
18
|
+
var HELP_TEXT = `Wensity CLI ${CLI_VERSION}
|
|
19
|
+
|
|
20
|
+
Usage:
|
|
21
|
+
wensity init [--preset <code>] [--preset-file <path>] [options]
|
|
22
|
+
wensity login [options]
|
|
23
|
+
wensity logout
|
|
24
|
+
wensity whoami [--json]
|
|
25
|
+
wensity list [--type component|block] [options]
|
|
26
|
+
wensity add <slug> [--type component|block] [options]
|
|
27
|
+
wensity update <slug> [--type component|block] [options]
|
|
28
|
+
wensity version
|
|
29
|
+
|
|
30
|
+
Commands:
|
|
31
|
+
init Create wensity.json and local helper files (optional --preset applies style + CSS)
|
|
32
|
+
login Save a Wensity API token for premium component access
|
|
33
|
+
logout Remove saved CLI credentials
|
|
34
|
+
whoami Verify the saved token and print the authenticated account
|
|
35
|
+
list List registry components or blocks
|
|
36
|
+
add Download a component or block source file into this project
|
|
37
|
+
update Re-download a component or block and overwrite the local copy
|
|
38
|
+
version Print the CLI version
|
|
39
|
+
|
|
40
|
+
Options:
|
|
41
|
+
--api-url <url> Override the Wensity app origin, defaults to ${DEFAULT_API_ORIGIN}
|
|
42
|
+
--registry <url> Override the registry endpoint
|
|
43
|
+
--type <type> Select component or block, defaults to component
|
|
44
|
+
--token <token> Provide a token non-interactively for login
|
|
45
|
+
--preset <code> Apply a shareable Wensity style preset (wsty1.\u2026); merges style when config exists
|
|
46
|
+
--preset-file <path> Read a preset code or JSON payload from a file
|
|
47
|
+
--force Overwrite generated files when adding or initializing
|
|
48
|
+
--no-install Write files without running the package manager
|
|
49
|
+
--dry-run Print planned writes and installs without changing files
|
|
50
|
+
--json Print machine-readable output where supported
|
|
51
|
+
--help Show help
|
|
52
|
+
--version Print the CLI version
|
|
53
|
+
|
|
54
|
+
Preset notes:
|
|
55
|
+
Generate codes at ${DEFAULT_API_ORIGIN}/docs/primitives/setup
|
|
56
|
+
Plain init refuses an existing wensity.json unless --force
|
|
57
|
+
init --preset merges style + primitive CSS; does not rewrite installed source
|
|
58
|
+
add/update read style.iconLibrary for UI primitives only (Tabler|Lucide)
|
|
59
|
+
Invalid/expired/unsupported codes exit non-zero with an actionable message
|
|
60
|
+
`;
|
|
61
|
+
|
|
62
|
+
// src/errors.ts
|
|
63
|
+
var CliError = class extends Error {
|
|
64
|
+
exitCode;
|
|
65
|
+
constructor(message, exitCode = 1) {
|
|
66
|
+
super(message);
|
|
67
|
+
this.name = "CliError";
|
|
68
|
+
this.exitCode = exitCode;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
function isNodeError(error) {
|
|
72
|
+
return error instanceof Error && "code" in error;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// src/args.ts
|
|
76
|
+
function parseArgs(argv) {
|
|
77
|
+
const positionals = [];
|
|
78
|
+
const options = /* @__PURE__ */ new Map();
|
|
79
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
80
|
+
const token = argv[index];
|
|
81
|
+
if (!token.startsWith("--")) {
|
|
82
|
+
positionals.push(token);
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
if (token === "--") {
|
|
86
|
+
positionals.push(...argv.slice(index + 1));
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
const inlineValueIndex = token.indexOf("=");
|
|
90
|
+
const rawName = inlineValueIndex > -1 ? token.slice(2, inlineValueIndex) : token.slice(2);
|
|
91
|
+
const name = normalizeOptionName(rawName);
|
|
92
|
+
if (!name) {
|
|
93
|
+
throw new CliError(`Invalid option: ${token}`);
|
|
94
|
+
}
|
|
95
|
+
if (inlineValueIndex > -1) {
|
|
96
|
+
options.set(name, token.slice(inlineValueIndex + 1));
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
const nextToken = argv[index + 1];
|
|
100
|
+
if (nextToken && !nextToken.startsWith("--") && expectsValue(name)) {
|
|
101
|
+
options.set(name, nextToken);
|
|
102
|
+
index += 1;
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
options.set(name, true);
|
|
106
|
+
}
|
|
107
|
+
return { positionals, options };
|
|
108
|
+
}
|
|
109
|
+
function getStringOption(args, name) {
|
|
110
|
+
const value = args.options.get(name);
|
|
111
|
+
if (value === void 0) return void 0;
|
|
112
|
+
if (typeof value === "boolean") {
|
|
113
|
+
throw new CliError(`--${name} expects a value.`);
|
|
114
|
+
}
|
|
115
|
+
return value;
|
|
116
|
+
}
|
|
117
|
+
function hasFlag(args, name) {
|
|
118
|
+
return args.options.get(name) === true;
|
|
119
|
+
}
|
|
120
|
+
function expectsValue(name) {
|
|
121
|
+
return ["api-url", "registry", "token", "type", "preset", "preset-file"].includes(name);
|
|
122
|
+
}
|
|
123
|
+
function normalizeOptionName(name) {
|
|
124
|
+
if (name === "dry") return "dry-run";
|
|
125
|
+
return name;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// src/config.ts
|
|
129
|
+
import { existsSync } from "fs";
|
|
130
|
+
import { access, mkdir, readFile, writeFile } from "fs/promises";
|
|
131
|
+
import { dirname as dirname2, join as join2, relative as relative2 } from "path";
|
|
132
|
+
|
|
7
133
|
// ../wensity-preset/src/constants.ts
|
|
8
134
|
var ICON_LIBRARIES = ["tabler", "lucide"];
|
|
9
135
|
var RADIUS_PRESETS = ["none", "small", "medium", "large"];
|
|
10
136
|
var BUILTIN_FONT_IDS = ["site", "system-sans", "system-mono"];
|
|
137
|
+
var BASE_COLOR_IDS = [
|
|
138
|
+
"inherit",
|
|
139
|
+
"neutral",
|
|
140
|
+
"zinc",
|
|
141
|
+
"slate",
|
|
142
|
+
"stone",
|
|
143
|
+
"taupe"
|
|
144
|
+
];
|
|
145
|
+
var THEME_COLOR_IDS = [
|
|
146
|
+
"ink",
|
|
147
|
+
"red",
|
|
148
|
+
"blue",
|
|
149
|
+
"violet",
|
|
150
|
+
"green",
|
|
151
|
+
"orange"
|
|
152
|
+
];
|
|
153
|
+
var CHART_PALETTE_IDS = [
|
|
154
|
+
"theme",
|
|
155
|
+
"warm",
|
|
156
|
+
"cool",
|
|
157
|
+
"mixed"
|
|
158
|
+
];
|
|
159
|
+
var HEADING_FONT_IDS = ["system", "playfair"];
|
|
160
|
+
var BODY_FONT_IDS = ["system", "inter"];
|
|
11
161
|
var RADIUS_PRESET_CSS = {
|
|
12
162
|
none: "0px",
|
|
13
163
|
small: "0.5rem",
|
|
@@ -27,12 +177,6 @@ var CONTROL_SOLID_COLOR_KEYS = [
|
|
|
27
177
|
"controlSolidActive",
|
|
28
178
|
"controlSolidForeground"
|
|
29
179
|
];
|
|
30
|
-
var CONTROL_SOLID_CSS_VARS = {
|
|
31
|
-
controlSolid: "--primitive-control-solid",
|
|
32
|
-
controlSolidHover: "--primitive-control-solid-hover",
|
|
33
|
-
controlSolidActive: "--primitive-control-solid-active",
|
|
34
|
-
controlSolidForeground: "--primitive-control-solid-foreground"
|
|
35
|
-
};
|
|
36
180
|
var STYLE_OBJECT_KEYS = [
|
|
37
181
|
"iconLibrary",
|
|
38
182
|
"radius",
|
|
@@ -40,6 +184,16 @@ var STYLE_OBJECT_KEYS = [
|
|
|
40
184
|
"colors",
|
|
41
185
|
"presetCode"
|
|
42
186
|
];
|
|
187
|
+
var STYLE_OBJECT_KEYS_CANONICAL = [
|
|
188
|
+
"baseColor",
|
|
189
|
+
"themeColor",
|
|
190
|
+
"chartPalette",
|
|
191
|
+
"headingFont",
|
|
192
|
+
"bodyFont",
|
|
193
|
+
"iconLibrary",
|
|
194
|
+
"radius",
|
|
195
|
+
"presetCode"
|
|
196
|
+
];
|
|
43
197
|
var FONT_ROLE_KEYS = ["sans", "display", "mono"];
|
|
44
198
|
var COLOR_MODE_KEYS = ["light", "dark"];
|
|
45
199
|
var HEX_COLOR_PATTERN = /^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;
|
|
@@ -62,6 +216,21 @@ function isFontRoleValue(value) {
|
|
|
62
216
|
if (isBuiltinFontId(value)) return true;
|
|
63
217
|
return value.startsWith(CUSTOM_FONT_PREFIX) && value.length > CUSTOM_FONT_PREFIX.length;
|
|
64
218
|
}
|
|
219
|
+
function isBaseColorId(value) {
|
|
220
|
+
return BASE_COLOR_IDS.includes(value);
|
|
221
|
+
}
|
|
222
|
+
function isThemeColorId(value) {
|
|
223
|
+
return THEME_COLOR_IDS.includes(value);
|
|
224
|
+
}
|
|
225
|
+
function isChartPaletteId(value) {
|
|
226
|
+
return CHART_PALETTE_IDS.includes(value);
|
|
227
|
+
}
|
|
228
|
+
function isHeadingFontId(value) {
|
|
229
|
+
return HEADING_FONT_IDS.includes(value);
|
|
230
|
+
}
|
|
231
|
+
function isBodyFontId(value) {
|
|
232
|
+
return BODY_FONT_IDS.includes(value);
|
|
233
|
+
}
|
|
65
234
|
|
|
66
235
|
// ../wensity-preset/src/defaults.ts
|
|
67
236
|
var DEFAULT_STYLE_FONTS = {
|
|
@@ -101,6 +270,26 @@ function createDefaultStyleConfig() {
|
|
|
101
270
|
}
|
|
102
271
|
};
|
|
103
272
|
}
|
|
273
|
+
var DEFAULT_STYLE_CONFIG_CANONICAL = {
|
|
274
|
+
baseColor: "inherit",
|
|
275
|
+
themeColor: "ink",
|
|
276
|
+
chartPalette: "theme",
|
|
277
|
+
headingFont: "system",
|
|
278
|
+
bodyFont: "system",
|
|
279
|
+
iconLibrary: "tabler",
|
|
280
|
+
radius: "medium"
|
|
281
|
+
};
|
|
282
|
+
function createDefaultStyleConfigCanonical() {
|
|
283
|
+
return {
|
|
284
|
+
baseColor: DEFAULT_STYLE_CONFIG_CANONICAL.baseColor,
|
|
285
|
+
themeColor: DEFAULT_STYLE_CONFIG_CANONICAL.themeColor,
|
|
286
|
+
chartPalette: DEFAULT_STYLE_CONFIG_CANONICAL.chartPalette,
|
|
287
|
+
headingFont: DEFAULT_STYLE_CONFIG_CANONICAL.headingFont,
|
|
288
|
+
bodyFont: DEFAULT_STYLE_CONFIG_CANONICAL.bodyFont,
|
|
289
|
+
iconLibrary: DEFAULT_STYLE_CONFIG_CANONICAL.iconLibrary,
|
|
290
|
+
radius: DEFAULT_STYLE_CONFIG_CANONICAL.radius
|
|
291
|
+
};
|
|
292
|
+
}
|
|
104
293
|
|
|
105
294
|
// ../wensity-preset/src/schema.ts
|
|
106
295
|
var fontRoleSchema = {
|
|
@@ -123,66 +312,53 @@ var controlSolidColorsSchema = {
|
|
|
123
312
|
])
|
|
124
313
|
)
|
|
125
314
|
};
|
|
126
|
-
var
|
|
127
|
-
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
128
|
-
$id: "https://ui.wensity.com/schema/wensity.json",
|
|
129
|
-
title: "Wensity CLI configuration",
|
|
315
|
+
var legacyStyleSchema = {
|
|
130
316
|
type: "object",
|
|
131
317
|
additionalProperties: false,
|
|
132
318
|
properties: {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
components: { type: "string", minLength: 1 },
|
|
137
|
-
utils: { type: "string", minLength: 1 },
|
|
138
|
-
tailwind: {
|
|
319
|
+
iconLibrary: { type: "string", enum: [...ICON_LIBRARIES] },
|
|
320
|
+
radius: { type: "string", enum: [...RADIUS_PRESETS] },
|
|
321
|
+
fonts: {
|
|
139
322
|
type: "object",
|
|
140
323
|
additionalProperties: false,
|
|
141
324
|
properties: {
|
|
142
|
-
|
|
143
|
-
|
|
325
|
+
sans: fontRoleSchema,
|
|
326
|
+
display: fontRoleSchema,
|
|
327
|
+
mono: fontRoleSchema
|
|
144
328
|
}
|
|
145
329
|
},
|
|
146
|
-
|
|
330
|
+
colors: {
|
|
147
331
|
type: "object",
|
|
148
332
|
additionalProperties: false,
|
|
149
333
|
properties: {
|
|
150
|
-
|
|
151
|
-
|
|
334
|
+
light: controlSolidColorsSchema,
|
|
335
|
+
dark: controlSolidColorsSchema
|
|
152
336
|
}
|
|
153
337
|
},
|
|
154
|
-
|
|
155
|
-
type: "
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
iconLibrary: { type: "string", enum: [...ICON_LIBRARIES] },
|
|
159
|
-
radius: { type: "string", enum: [...RADIUS_PRESETS] },
|
|
160
|
-
fonts: {
|
|
161
|
-
type: "object",
|
|
162
|
-
additionalProperties: false,
|
|
163
|
-
properties: {
|
|
164
|
-
sans: fontRoleSchema,
|
|
165
|
-
display: fontRoleSchema,
|
|
166
|
-
mono: fontRoleSchema
|
|
167
|
-
}
|
|
168
|
-
},
|
|
169
|
-
colors: {
|
|
170
|
-
type: "object",
|
|
171
|
-
additionalProperties: false,
|
|
172
|
-
properties: {
|
|
173
|
-
light: controlSolidColorsSchema,
|
|
174
|
-
dark: controlSolidColorsSchema
|
|
175
|
-
}
|
|
176
|
-
},
|
|
177
|
-
presetCode: {
|
|
178
|
-
type: "string",
|
|
179
|
-
minLength: 1,
|
|
180
|
-
maxLength: PRESET_CODEC_MAX_CODE_LENGTH
|
|
181
|
-
}
|
|
182
|
-
}
|
|
338
|
+
presetCode: {
|
|
339
|
+
type: "string",
|
|
340
|
+
minLength: 1,
|
|
341
|
+
maxLength: PRESET_CODEC_MAX_CODE_LENGTH
|
|
183
342
|
}
|
|
184
|
-
}
|
|
185
|
-
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
var canonicalStyleSchema = {
|
|
346
|
+
type: "object",
|
|
347
|
+
additionalProperties: false,
|
|
348
|
+
properties: {
|
|
349
|
+
baseColor: { type: "string", enum: [...BASE_COLOR_IDS] },
|
|
350
|
+
themeColor: { type: "string", enum: [...THEME_COLOR_IDS] },
|
|
351
|
+
chartPalette: { type: "string", enum: [...CHART_PALETTE_IDS] },
|
|
352
|
+
headingFont: { type: "string", enum: [...HEADING_FONT_IDS] },
|
|
353
|
+
bodyFont: { type: "string", enum: [...BODY_FONT_IDS] },
|
|
354
|
+
iconLibrary: { type: "string", enum: [...ICON_LIBRARIES] },
|
|
355
|
+
radius: { type: "string", enum: [...RADIUS_PRESETS] },
|
|
356
|
+
presetCode: {
|
|
357
|
+
type: "string",
|
|
358
|
+
minLength: 1,
|
|
359
|
+
maxLength: PRESET_CODEC_MAX_CODE_LENGTH
|
|
360
|
+
}
|
|
361
|
+
}
|
|
186
362
|
};
|
|
187
363
|
|
|
188
364
|
// ../wensity-preset/src/fonts.ts
|
|
@@ -420,6 +596,91 @@ function validateStyleConfigPartial(value) {
|
|
|
420
596
|
}
|
|
421
597
|
return result;
|
|
422
598
|
}
|
|
599
|
+
function validateStyleConfigCanonicalPartial(value) {
|
|
600
|
+
if (value === void 0 || value === null) return {};
|
|
601
|
+
assertPlainObject(value, "style");
|
|
602
|
+
assertAllowedKeys(value, STYLE_OBJECT_KEYS_CANONICAL, "style");
|
|
603
|
+
const result = {};
|
|
604
|
+
if ("baseColor" in value) {
|
|
605
|
+
if (typeof value.baseColor !== "string" || !isBaseColorId(value.baseColor)) {
|
|
606
|
+
throw new PresetValidationError(
|
|
607
|
+
"Invalid style.baseColor. Expected inherit | neutral | zinc | slate | stone | taupe.",
|
|
608
|
+
"style.baseColor"
|
|
609
|
+
);
|
|
610
|
+
}
|
|
611
|
+
result.baseColor = value.baseColor;
|
|
612
|
+
}
|
|
613
|
+
if ("themeColor" in value) {
|
|
614
|
+
if (typeof value.themeColor !== "string" || !isThemeColorId(value.themeColor)) {
|
|
615
|
+
throw new PresetValidationError(
|
|
616
|
+
"Invalid style.themeColor. Expected ink | red | blue | violet | green | orange.",
|
|
617
|
+
"style.themeColor"
|
|
618
|
+
);
|
|
619
|
+
}
|
|
620
|
+
result.themeColor = value.themeColor;
|
|
621
|
+
}
|
|
622
|
+
if ("chartPalette" in value) {
|
|
623
|
+
if (typeof value.chartPalette !== "string" || !isChartPaletteId(value.chartPalette)) {
|
|
624
|
+
throw new PresetValidationError(
|
|
625
|
+
"Invalid style.chartPalette. Expected theme | warm | cool | mixed.",
|
|
626
|
+
"style.chartPalette"
|
|
627
|
+
);
|
|
628
|
+
}
|
|
629
|
+
result.chartPalette = value.chartPalette;
|
|
630
|
+
}
|
|
631
|
+
if ("headingFont" in value) {
|
|
632
|
+
if (typeof value.headingFont !== "string" || !isHeadingFontId(value.headingFont)) {
|
|
633
|
+
throw new PresetValidationError(
|
|
634
|
+
"Invalid style.headingFont. Expected system | playfair.",
|
|
635
|
+
"style.headingFont"
|
|
636
|
+
);
|
|
637
|
+
}
|
|
638
|
+
result.headingFont = value.headingFont;
|
|
639
|
+
}
|
|
640
|
+
if ("bodyFont" in value) {
|
|
641
|
+
if (typeof value.bodyFont !== "string" || !isBodyFontId(value.bodyFont)) {
|
|
642
|
+
throw new PresetValidationError(
|
|
643
|
+
"Invalid style.bodyFont. Expected system | inter.",
|
|
644
|
+
"style.bodyFont"
|
|
645
|
+
);
|
|
646
|
+
}
|
|
647
|
+
result.bodyFont = value.bodyFont;
|
|
648
|
+
}
|
|
649
|
+
if ("iconLibrary" in value) {
|
|
650
|
+
if (typeof value.iconLibrary !== "string" || !isIconLibrary(value.iconLibrary)) {
|
|
651
|
+
throw new PresetValidationError(
|
|
652
|
+
"Invalid style.iconLibrary. Expected tabler | lucide.",
|
|
653
|
+
"style.iconLibrary"
|
|
654
|
+
);
|
|
655
|
+
}
|
|
656
|
+
result.iconLibrary = value.iconLibrary;
|
|
657
|
+
}
|
|
658
|
+
if ("radius" in value) {
|
|
659
|
+
if (typeof value.radius !== "string" || !isRadiusPreset(value.radius)) {
|
|
660
|
+
throw new PresetValidationError(
|
|
661
|
+
"Invalid style.radius. Expected none | small | medium | large.",
|
|
662
|
+
"style.radius"
|
|
663
|
+
);
|
|
664
|
+
}
|
|
665
|
+
result.radius = value.radius;
|
|
666
|
+
}
|
|
667
|
+
if ("presetCode" in value) {
|
|
668
|
+
if (typeof value.presetCode !== "string" || value.presetCode.length === 0) {
|
|
669
|
+
throw new PresetValidationError(
|
|
670
|
+
"Invalid style.presetCode. Expected a non-empty string.",
|
|
671
|
+
"style.presetCode"
|
|
672
|
+
);
|
|
673
|
+
}
|
|
674
|
+
if (value.presetCode.length > PRESET_CODEC_MAX_CODE_LENGTH) {
|
|
675
|
+
throw new PresetValidationError(
|
|
676
|
+
`Invalid style.presetCode. Exceeds ${PRESET_CODEC_MAX_CODE_LENGTH} characters.`,
|
|
677
|
+
"style.presetCode"
|
|
678
|
+
);
|
|
679
|
+
}
|
|
680
|
+
result.presetCode = value.presetCode;
|
|
681
|
+
}
|
|
682
|
+
return result;
|
|
683
|
+
}
|
|
423
684
|
|
|
424
685
|
// ../wensity-preset/src/normalize.ts
|
|
425
686
|
function mergeControlSolid(base, partial) {
|
|
@@ -460,9 +721,36 @@ function normalizeStyleConfig(partial) {
|
|
|
460
721
|
}
|
|
461
722
|
return normalized;
|
|
462
723
|
}
|
|
724
|
+
function normalizeStyleConfigCanonical(partial) {
|
|
725
|
+
const validated = validateStyleConfigCanonicalPartial(partial ?? void 0);
|
|
726
|
+
const defaults = createDefaultStyleConfigCanonical();
|
|
727
|
+
const normalized = {
|
|
728
|
+
baseColor: validated.baseColor ?? defaults.baseColor,
|
|
729
|
+
themeColor: validated.themeColor ?? defaults.themeColor,
|
|
730
|
+
chartPalette: validated.chartPalette ?? defaults.chartPalette,
|
|
731
|
+
headingFont: validated.headingFont ?? defaults.headingFont,
|
|
732
|
+
bodyFont: validated.bodyFont ?? defaults.bodyFont,
|
|
733
|
+
iconLibrary: validated.iconLibrary ?? defaults.iconLibrary,
|
|
734
|
+
radius: validated.radius ?? defaults.radius
|
|
735
|
+
};
|
|
736
|
+
if (validated.presetCode !== void 0) {
|
|
737
|
+
normalized.presetCode = validated.presetCode;
|
|
738
|
+
}
|
|
739
|
+
return normalized;
|
|
740
|
+
}
|
|
463
741
|
|
|
464
742
|
// ../wensity-preset/src/codec.ts
|
|
465
743
|
var CODEC_PAYLOAD_KEYS = ["v", "iconLibrary", "radius", "fonts", "colors"];
|
|
744
|
+
var CODEC_PAYLOAD_KEYS_CANONICAL = [
|
|
745
|
+
"v",
|
|
746
|
+
"baseColor",
|
|
747
|
+
"themeColor",
|
|
748
|
+
"chartPalette",
|
|
749
|
+
"headingFont",
|
|
750
|
+
"bodyFont",
|
|
751
|
+
"iconLibrary",
|
|
752
|
+
"radius"
|
|
753
|
+
];
|
|
466
754
|
function assertPlainObject2(value, path) {
|
|
467
755
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
468
756
|
throw new PresetValidationError(`Expected an object at ${path}.`, path);
|
|
@@ -481,6 +769,9 @@ function utf8ByteLength(text) {
|
|
|
481
769
|
return new TextEncoder().encode(text).byteLength;
|
|
482
770
|
}
|
|
483
771
|
var BASE64URL_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
772
|
+
var COMPACT_CANONICAL_PREFIX = "c";
|
|
773
|
+
var COMPACT_CANONICAL_BODY_LENGTH = 3;
|
|
774
|
+
var COMPACT_CANONICAL_ENCODED_LENGTH = COMPACT_CANONICAL_PREFIX.length + COMPACT_CANONICAL_BODY_LENGTH;
|
|
484
775
|
function toBase64Url(bytes) {
|
|
485
776
|
let out = "";
|
|
486
777
|
for (let i = 0; i < bytes.length; i += 3) {
|
|
@@ -520,6 +811,66 @@ function fromBase64Url(code) {
|
|
|
520
811
|
}
|
|
521
812
|
return outIndex === out.length ? out : out.subarray(0, outIndex);
|
|
522
813
|
}
|
|
814
|
+
function indexOfPresetValue(values, value, path) {
|
|
815
|
+
const index = values.indexOf(value);
|
|
816
|
+
if (index < 0) {
|
|
817
|
+
throw new PresetValidationError(`Invalid compact preset value at ${path}.`, path);
|
|
818
|
+
}
|
|
819
|
+
return index;
|
|
820
|
+
}
|
|
821
|
+
function readCompactChar(char) {
|
|
822
|
+
if (!char) return -1;
|
|
823
|
+
return BASE64URL_ALPHABET.indexOf(char);
|
|
824
|
+
}
|
|
825
|
+
function encodeCompactCanonicalPayload(payload) {
|
|
826
|
+
let value = indexOfPresetValue(BASE_COLOR_IDS, payload.baseColor, "preset.baseColor");
|
|
827
|
+
value = value << 3 | indexOfPresetValue(THEME_COLOR_IDS, payload.themeColor, "preset.themeColor");
|
|
828
|
+
value = value << 2 | indexOfPresetValue(CHART_PALETTE_IDS, payload.chartPalette, "preset.chartPalette");
|
|
829
|
+
value = value << 1 | indexOfPresetValue(HEADING_FONT_IDS, payload.headingFont, "preset.headingFont");
|
|
830
|
+
value = value << 1 | indexOfPresetValue(BODY_FONT_IDS, payload.bodyFont, "preset.bodyFont");
|
|
831
|
+
value = value << 1 | indexOfPresetValue(ICON_LIBRARIES, payload.iconLibrary, "preset.iconLibrary");
|
|
832
|
+
value = value << 2 | indexOfPresetValue(RADIUS_PRESETS, payload.radius, "preset.radius");
|
|
833
|
+
return `${COMPACT_CANONICAL_PREFIX}${BASE64URL_ALPHABET[value >> 12 & 63]}${BASE64URL_ALPHABET[value >> 6 & 63]}${BASE64URL_ALPHABET[value & 63]}`;
|
|
834
|
+
}
|
|
835
|
+
function decodeCompactCanonicalPayload(encoded) {
|
|
836
|
+
if (encoded.length !== COMPACT_CANONICAL_ENCODED_LENGTH || !encoded.startsWith(COMPACT_CANONICAL_PREFIX)) {
|
|
837
|
+
throw new PresetValidationError("Compact preset code has an invalid length.", "preset");
|
|
838
|
+
}
|
|
839
|
+
const a = readCompactChar(encoded[1]);
|
|
840
|
+
const b = readCompactChar(encoded[2]);
|
|
841
|
+
const c = readCompactChar(encoded[3]);
|
|
842
|
+
if (a < 0 || b < 0 || c < 0) {
|
|
843
|
+
throw new PresetValidationError("Compact preset code is not valid base64url.", "preset");
|
|
844
|
+
}
|
|
845
|
+
let value = a << 12 | b << 6 | c;
|
|
846
|
+
const radius = RADIUS_PRESETS[value & 3];
|
|
847
|
+
value >>= 2;
|
|
848
|
+
const iconLibrary = ICON_LIBRARIES[value & 1];
|
|
849
|
+
value >>= 1;
|
|
850
|
+
const bodyFont = BODY_FONT_IDS[value & 1];
|
|
851
|
+
value >>= 1;
|
|
852
|
+
const headingFont = HEADING_FONT_IDS[value & 1];
|
|
853
|
+
value >>= 1;
|
|
854
|
+
const chartPalette = CHART_PALETTE_IDS[value & 3];
|
|
855
|
+
value >>= 2;
|
|
856
|
+
const themeColor = THEME_COLOR_IDS[value & 7];
|
|
857
|
+
value >>= 3;
|
|
858
|
+
const baseColor = BASE_COLOR_IDS[value & 7];
|
|
859
|
+
value >>= 3;
|
|
860
|
+
if (value !== 0 || !baseColor || !themeColor || !chartPalette || !headingFont || !bodyFont || !iconLibrary || !radius) {
|
|
861
|
+
throw new PresetValidationError("Compact preset code contains an out-of-range value.", "preset");
|
|
862
|
+
}
|
|
863
|
+
return {
|
|
864
|
+
v: 2,
|
|
865
|
+
baseColor,
|
|
866
|
+
themeColor,
|
|
867
|
+
chartPalette,
|
|
868
|
+
headingFont,
|
|
869
|
+
bodyFont,
|
|
870
|
+
iconLibrary,
|
|
871
|
+
radius
|
|
872
|
+
};
|
|
873
|
+
}
|
|
523
874
|
function stableStringifyCodecPayload(payload) {
|
|
524
875
|
const parts = [
|
|
525
876
|
`"v":${payload.v}`,
|
|
@@ -675,7 +1026,104 @@ function pickDefinedColors(partial) {
|
|
|
675
1026
|
}
|
|
676
1027
|
return Object.keys(out).length > 0 ? out : void 0;
|
|
677
1028
|
}
|
|
678
|
-
|
|
1029
|
+
var CODEC_CANONICAL_REQUIRED_FIELDS = [
|
|
1030
|
+
"baseColor",
|
|
1031
|
+
"themeColor",
|
|
1032
|
+
"chartPalette",
|
|
1033
|
+
"headingFont",
|
|
1034
|
+
"bodyFont",
|
|
1035
|
+
"iconLibrary",
|
|
1036
|
+
"radius"
|
|
1037
|
+
];
|
|
1038
|
+
function validateCodecPayloadCanonical(value) {
|
|
1039
|
+
assertPlainObject2(value, "preset");
|
|
1040
|
+
assertAllowedKeys2(value, CODEC_PAYLOAD_KEYS_CANONICAL, "preset");
|
|
1041
|
+
if (value.v !== 2) {
|
|
1042
|
+
throw new PresetValidationError(
|
|
1043
|
+
typeof value.v === "number" ? `Unsupported preset codec version ${value.v}. Expected v: 2.` : "Preset payload missing v: 2.",
|
|
1044
|
+
"preset.v"
|
|
1045
|
+
);
|
|
1046
|
+
}
|
|
1047
|
+
for (const key of CODEC_CANONICAL_REQUIRED_FIELDS) {
|
|
1048
|
+
if (!(key in value)) {
|
|
1049
|
+
throw new PresetValidationError(`Preset payload missing ${key}.`, `preset.${key}`);
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
if (typeof value.baseColor !== "string" || !isBaseColorId(value.baseColor)) {
|
|
1053
|
+
throw new PresetValidationError(
|
|
1054
|
+
"Invalid preset.baseColor. Expected inherit | neutral | zinc | slate | stone | taupe.",
|
|
1055
|
+
"preset.baseColor"
|
|
1056
|
+
);
|
|
1057
|
+
}
|
|
1058
|
+
if (typeof value.themeColor !== "string" || !isThemeColorId(value.themeColor)) {
|
|
1059
|
+
throw new PresetValidationError(
|
|
1060
|
+
"Invalid preset.themeColor. Expected ink | red | blue | violet | green | orange.",
|
|
1061
|
+
"preset.themeColor"
|
|
1062
|
+
);
|
|
1063
|
+
}
|
|
1064
|
+
if (typeof value.chartPalette !== "string" || !isChartPaletteId(value.chartPalette)) {
|
|
1065
|
+
throw new PresetValidationError(
|
|
1066
|
+
"Invalid preset.chartPalette. Expected theme | warm | cool | mixed.",
|
|
1067
|
+
"preset.chartPalette"
|
|
1068
|
+
);
|
|
1069
|
+
}
|
|
1070
|
+
if (typeof value.headingFont !== "string" || !isHeadingFontId(value.headingFont)) {
|
|
1071
|
+
throw new PresetValidationError(
|
|
1072
|
+
"Invalid preset.headingFont. Expected system | playfair.",
|
|
1073
|
+
"preset.headingFont"
|
|
1074
|
+
);
|
|
1075
|
+
}
|
|
1076
|
+
if (typeof value.bodyFont !== "string" || !isBodyFontId(value.bodyFont)) {
|
|
1077
|
+
throw new PresetValidationError(
|
|
1078
|
+
"Invalid preset.bodyFont. Expected system | inter.",
|
|
1079
|
+
"preset.bodyFont"
|
|
1080
|
+
);
|
|
1081
|
+
}
|
|
1082
|
+
if (typeof value.iconLibrary !== "string" || !isIconLibrary(value.iconLibrary)) {
|
|
1083
|
+
throw new PresetValidationError(
|
|
1084
|
+
"Invalid preset.iconLibrary. Expected tabler | lucide.",
|
|
1085
|
+
"preset.iconLibrary"
|
|
1086
|
+
);
|
|
1087
|
+
}
|
|
1088
|
+
if (typeof value.radius !== "string" || !isRadiusPreset(value.radius)) {
|
|
1089
|
+
throw new PresetValidationError(
|
|
1090
|
+
"Invalid preset.radius. Expected none | small | medium | large.",
|
|
1091
|
+
"preset.radius"
|
|
1092
|
+
);
|
|
1093
|
+
}
|
|
1094
|
+
return {
|
|
1095
|
+
v: 2,
|
|
1096
|
+
baseColor: value.baseColor,
|
|
1097
|
+
themeColor: value.themeColor,
|
|
1098
|
+
chartPalette: value.chartPalette,
|
|
1099
|
+
headingFont: value.headingFont,
|
|
1100
|
+
bodyFont: value.bodyFont,
|
|
1101
|
+
iconLibrary: value.iconLibrary,
|
|
1102
|
+
radius: value.radius
|
|
1103
|
+
};
|
|
1104
|
+
}
|
|
1105
|
+
function encodePresetCanonical(style) {
|
|
1106
|
+
const normalized = normalizeStyleConfigCanonical(style);
|
|
1107
|
+
const payload = {
|
|
1108
|
+
v: 2,
|
|
1109
|
+
baseColor: normalized.baseColor,
|
|
1110
|
+
themeColor: normalized.themeColor,
|
|
1111
|
+
chartPalette: normalized.chartPalette,
|
|
1112
|
+
headingFont: normalized.headingFont,
|
|
1113
|
+
bodyFont: normalized.bodyFont,
|
|
1114
|
+
iconLibrary: normalized.iconLibrary,
|
|
1115
|
+
radius: normalized.radius
|
|
1116
|
+
};
|
|
1117
|
+
const code = `${PRESET_CODEC_PREFIX}.${encodeCompactCanonicalPayload(payload)}`;
|
|
1118
|
+
if (code.length > PRESET_CODEC_MAX_CODE_LENGTH) {
|
|
1119
|
+
throw new PresetValidationError(
|
|
1120
|
+
`Preset code exceeds ${PRESET_CODEC_MAX_CODE_LENGTH} characters.`,
|
|
1121
|
+
"preset"
|
|
1122
|
+
);
|
|
1123
|
+
}
|
|
1124
|
+
return code;
|
|
1125
|
+
}
|
|
1126
|
+
function decodePresetEnvelope(code) {
|
|
679
1127
|
if (typeof code !== "string" || code.length === 0) {
|
|
680
1128
|
throw new PresetValidationError("Preset code is required.", "preset");
|
|
681
1129
|
}
|
|
@@ -696,6 +1144,9 @@ function decodePreset(code) {
|
|
|
696
1144
|
if (!encoded) {
|
|
697
1145
|
throw new PresetValidationError("Preset code payload is empty.", "preset");
|
|
698
1146
|
}
|
|
1147
|
+
if (encoded.length === COMPACT_CANONICAL_ENCODED_LENGTH && encoded.startsWith(COMPACT_CANONICAL_PREFIX)) {
|
|
1148
|
+
return decodeCompactCanonicalPayload(encoded);
|
|
1149
|
+
}
|
|
699
1150
|
if (encoded.includes("=") || /[^A-Za-z0-9_-]/.test(encoded)) {
|
|
700
1151
|
throw new PresetValidationError("Preset code payload is not valid unpadded base64url.", "preset");
|
|
701
1152
|
}
|
|
@@ -727,7 +1178,26 @@ function decodePreset(code) {
|
|
|
727
1178
|
} catch {
|
|
728
1179
|
throw new PresetValidationError("Preset payload is not valid JSON.", "preset");
|
|
729
1180
|
}
|
|
730
|
-
return
|
|
1181
|
+
return parsed;
|
|
1182
|
+
}
|
|
1183
|
+
function formatUnsupportedPayloadVersion(v) {
|
|
1184
|
+
const label = v === void 0 ? "undefined" : String(v);
|
|
1185
|
+
return `Unsupported preset payload version ${label}. This preset may require a newer version of the Wensity CLI.`;
|
|
1186
|
+
}
|
|
1187
|
+
function decodeAnyPreset(code) {
|
|
1188
|
+
const parsed = decodePresetEnvelope(code);
|
|
1189
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
1190
|
+
throw new PresetValidationError("Expected an object at preset.", "preset");
|
|
1191
|
+
}
|
|
1192
|
+
assertNoForbiddenObjectKeys(parsed, "preset");
|
|
1193
|
+
const v = parsed.v;
|
|
1194
|
+
if (v === 1) {
|
|
1195
|
+
return validateCodecPayload(parsed);
|
|
1196
|
+
}
|
|
1197
|
+
if (v === 2) {
|
|
1198
|
+
return validateCodecPayloadCanonical(parsed);
|
|
1199
|
+
}
|
|
1200
|
+
throw new PresetValidationError(formatUnsupportedPayloadVersion(v), "preset.v");
|
|
731
1201
|
}
|
|
732
1202
|
|
|
733
1203
|
// ../wensity-preset/src/icon-map.ts
|
|
@@ -748,184 +1218,520 @@ var TABLER_TO_LUCIDE = {
|
|
|
748
1218
|
IconCalendar: "Calendar",
|
|
749
1219
|
IconCamera: "Camera",
|
|
750
1220
|
IconCheck: "Check",
|
|
751
|
-
IconChevronDown: "ChevronDown",
|
|
752
|
-
IconChevronLeft: "ChevronLeft",
|
|
753
|
-
IconChevronRight: "ChevronRight",
|
|
754
|
-
IconChevronUp: "ChevronUp",
|
|
755
|
-
IconChevronsLeft: "ChevronsLeft",
|
|
756
|
-
IconChevronsRight: "ChevronsRight",
|
|
757
|
-
IconCircleX: "CircleX",
|
|
758
|
-
IconClock: "Clock",
|
|
759
|
-
IconCornerDownLeft: "CornerDownLeft",
|
|
760
|
-
IconDots: "Ellipsis",
|
|
761
|
-
IconDownload: "Download",
|
|
762
|
-
IconFile: "File",
|
|
763
|
-
IconFileMusic: "FileAudio",
|
|
764
|
-
IconFileText: "FileText",
|
|
765
|
-
IconFileZip: "FileArchive",
|
|
766
|
-
IconInfoCircle: "Info",
|
|
767
|
-
IconLayoutSidebarLeftCollapse: "PanelLeftClose",
|
|
768
|
-
IconLayoutSidebarLeftExpand: "PanelLeftOpen",
|
|
769
|
-
IconMinus: "Minus",
|
|
770
|
-
IconPhoto: "Image",
|
|
771
|
-
IconPlus: "Plus",
|
|
772
|
-
IconRefresh: "RefreshCw",
|
|
773
|
-
IconSearch: "Search",
|
|
774
|
-
IconSelector: "ChevronsUpDown",
|
|
775
|
-
IconSlash: "Slash",
|
|
776
|
-
IconUser: "User",
|
|
777
|
-
IconVideo: "Video",
|
|
778
|
-
IconX: "X"
|
|
779
|
-
};
|
|
780
|
-
var EXCLUSION_SET = new Set(ICON_TRANSFORM_EXCLUSIONS);
|
|
781
|
-
function isIconTransformExclusion(name) {
|
|
782
|
-
return EXCLUSION_SET.has(name);
|
|
783
|
-
}
|
|
784
|
-
function isMappedTablerIcon(name) {
|
|
785
|
-
return Object.prototype.hasOwnProperty.call(TABLER_TO_LUCIDE, name);
|
|
786
|
-
}
|
|
787
|
-
function resolveLucideExport(tablerName) {
|
|
788
|
-
if (isIconTransformExclusion(tablerName)) {
|
|
789
|
-
throw new Error(
|
|
790
|
-
`Icon "${tablerName}" is a Phase 0 exclusion and must not be transformed. Use internal SVG/CSS geometry instead.`
|
|
791
|
-
);
|
|
792
|
-
}
|
|
793
|
-
if (!isMappedTablerIcon(tablerName)) {
|
|
794
|
-
throw new Error(
|
|
795
|
-
`No approved Lucide mapping for Tabler icon "${tablerName}". Add an audited map entry or convert it to internal geometry.`
|
|
796
|
-
);
|
|
797
|
-
}
|
|
798
|
-
return TABLER_TO_LUCIDE[tablerName];
|
|
799
|
-
}
|
|
800
|
-
var LUCIDE_TO_TABLER = Object.fromEntries(
|
|
801
|
-
Object.entries(TABLER_TO_LUCIDE).map(([tabler, lucide]) => [lucide, tabler])
|
|
802
|
-
);
|
|
803
|
-
|
|
804
|
-
// src/constants.ts
|
|
805
|
-
var CLI_NAME = "wensity";
|
|
806
|
-
var CLI_VERSION = "0.1.6";
|
|
807
|
-
var CONFIG_FILE_NAME = "wensity.json";
|
|
808
|
-
var DEFAULT_API_ORIGIN = "https://ui.wensity.com";
|
|
809
|
-
var DEFAULT_REGISTRY_PATH = "/api/registry";
|
|
810
|
-
var DEFAULT_COMPONENTS_DIR = "src/components/wensity";
|
|
811
|
-
var DEFAULT_UTILS_PATH = "src/lib/utils";
|
|
812
|
-
var DEFAULT_COMPONENTS_ALIAS = "@/components/wensity";
|
|
813
|
-
var DEFAULT_UTILS_ALIAS = "@/lib/utils";
|
|
814
|
-
var INIT_PRIMITIVE_CSS_SLUG = "button";
|
|
815
|
-
var HELP_TEXT = `Wensity CLI ${CLI_VERSION}
|
|
816
|
-
|
|
817
|
-
Usage:
|
|
818
|
-
wensity init [--preset <code>] [--preset-file <path>] [options]
|
|
819
|
-
wensity login [options]
|
|
820
|
-
wensity logout
|
|
821
|
-
wensity whoami [--json]
|
|
822
|
-
wensity list [--type component|block] [options]
|
|
823
|
-
wensity add <slug> [--type component|block] [options]
|
|
824
|
-
wensity update <slug> [--type component|block] [options]
|
|
825
|
-
wensity version
|
|
826
|
-
|
|
827
|
-
Commands:
|
|
828
|
-
init Create wensity.json and local helper files (optional --preset applies style + CSS)
|
|
829
|
-
login Save a Wensity API token for premium component access
|
|
830
|
-
logout Remove saved CLI credentials
|
|
831
|
-
whoami Verify the saved token and print the authenticated account
|
|
832
|
-
list List registry components or blocks
|
|
833
|
-
add Download a component or block source file into this project
|
|
834
|
-
update Re-download a component or block and overwrite the local copy
|
|
835
|
-
version Print the CLI version
|
|
836
|
-
|
|
837
|
-
Options:
|
|
838
|
-
--api-url <url> Override the Wensity app origin, defaults to ${DEFAULT_API_ORIGIN}
|
|
839
|
-
--registry <url> Override the registry endpoint
|
|
840
|
-
--type <type> Select component or block, defaults to component
|
|
841
|
-
--token <token> Provide a token non-interactively for login
|
|
842
|
-
--preset <code> Apply a shareable Wensity style preset (wsty1.\u2026); merges style when config exists
|
|
843
|
-
--preset-file <path> Read a preset code or JSON payload from a file
|
|
844
|
-
--force Overwrite generated files when adding or initializing
|
|
845
|
-
--no-install Write files without running the package manager
|
|
846
|
-
--dry-run Print planned writes and installs without changing files
|
|
847
|
-
--json Print machine-readable output where supported
|
|
848
|
-
--help Show help
|
|
849
|
-
--version Print the CLI version
|
|
850
|
-
|
|
851
|
-
Preset notes:
|
|
852
|
-
Generate codes at ${DEFAULT_API_ORIGIN}/docs/primitives/setup
|
|
853
|
-
Plain init refuses an existing wensity.json unless --force
|
|
854
|
-
init --preset merges style + primitive CSS; does not rewrite installed source
|
|
855
|
-
add/update read style.iconLibrary for UI primitives only (Tabler|Lucide)
|
|
856
|
-
Invalid/expired/unsupported codes exit non-zero with an actionable message
|
|
857
|
-
`;
|
|
858
|
-
|
|
859
|
-
// src/errors.ts
|
|
860
|
-
var CliError = class extends Error {
|
|
861
|
-
exitCode;
|
|
862
|
-
constructor(message, exitCode = 1) {
|
|
863
|
-
super(message);
|
|
864
|
-
this.name = "CliError";
|
|
865
|
-
this.exitCode = exitCode;
|
|
866
|
-
}
|
|
1221
|
+
IconChevronDown: "ChevronDown",
|
|
1222
|
+
IconChevronLeft: "ChevronLeft",
|
|
1223
|
+
IconChevronRight: "ChevronRight",
|
|
1224
|
+
IconChevronUp: "ChevronUp",
|
|
1225
|
+
IconChevronsLeft: "ChevronsLeft",
|
|
1226
|
+
IconChevronsRight: "ChevronsRight",
|
|
1227
|
+
IconCircleX: "CircleX",
|
|
1228
|
+
IconClock: "Clock",
|
|
1229
|
+
IconCornerDownLeft: "CornerDownLeft",
|
|
1230
|
+
IconDots: "Ellipsis",
|
|
1231
|
+
IconDownload: "Download",
|
|
1232
|
+
IconFile: "File",
|
|
1233
|
+
IconFileMusic: "FileAudio",
|
|
1234
|
+
IconFileText: "FileText",
|
|
1235
|
+
IconFileZip: "FileArchive",
|
|
1236
|
+
IconInfoCircle: "Info",
|
|
1237
|
+
IconLayoutSidebarLeftCollapse: "PanelLeftClose",
|
|
1238
|
+
IconLayoutSidebarLeftExpand: "PanelLeftOpen",
|
|
1239
|
+
IconMinus: "Minus",
|
|
1240
|
+
IconPhoto: "Image",
|
|
1241
|
+
IconPlus: "Plus",
|
|
1242
|
+
IconRefresh: "RefreshCw",
|
|
1243
|
+
IconSearch: "Search",
|
|
1244
|
+
IconSelector: "ChevronsUpDown",
|
|
1245
|
+
IconSlash: "Slash",
|
|
1246
|
+
IconUser: "User",
|
|
1247
|
+
IconVideo: "Video",
|
|
1248
|
+
IconX: "X"
|
|
867
1249
|
};
|
|
868
|
-
|
|
869
|
-
|
|
1250
|
+
var EXCLUSION_SET = new Set(ICON_TRANSFORM_EXCLUSIONS);
|
|
1251
|
+
function isIconTransformExclusion(name) {
|
|
1252
|
+
return EXCLUSION_SET.has(name);
|
|
1253
|
+
}
|
|
1254
|
+
function isMappedTablerIcon(name) {
|
|
1255
|
+
return Object.prototype.hasOwnProperty.call(TABLER_TO_LUCIDE, name);
|
|
1256
|
+
}
|
|
1257
|
+
function resolveLucideExport(tablerName) {
|
|
1258
|
+
if (isIconTransformExclusion(tablerName)) {
|
|
1259
|
+
throw new Error(
|
|
1260
|
+
`Icon "${tablerName}" is a Phase 0 exclusion and must not be transformed. Use internal SVG/CSS geometry instead.`
|
|
1261
|
+
);
|
|
1262
|
+
}
|
|
1263
|
+
if (!isMappedTablerIcon(tablerName)) {
|
|
1264
|
+
throw new Error(
|
|
1265
|
+
`No approved Lucide mapping for Tabler icon "${tablerName}". Add an audited map entry or convert it to internal geometry.`
|
|
1266
|
+
);
|
|
1267
|
+
}
|
|
1268
|
+
return TABLER_TO_LUCIDE[tablerName];
|
|
870
1269
|
}
|
|
1270
|
+
var LUCIDE_TO_TABLER = Object.fromEntries(
|
|
1271
|
+
Object.entries(TABLER_TO_LUCIDE).map(([tabler, lucide]) => [lucide, tabler])
|
|
1272
|
+
);
|
|
871
1273
|
|
|
872
|
-
// src/
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
1274
|
+
// ../wensity-preset/src/palettes.ts
|
|
1275
|
+
var BASE_COLOR_PALETTE = {
|
|
1276
|
+
zinc: {
|
|
1277
|
+
light: {
|
|
1278
|
+
surfaceElevated: "#ffffff",
|
|
1279
|
+
surfaceOverlay: "#ffffff",
|
|
1280
|
+
foreground: "#09090b",
|
|
1281
|
+
border: "rgba(9, 9, 11, 0.08)",
|
|
1282
|
+
mutedForeground: "#71717a"
|
|
1283
|
+
},
|
|
1284
|
+
dark: {
|
|
1285
|
+
surfaceElevated: "#18181b",
|
|
1286
|
+
surfaceOverlay: "#27272a",
|
|
1287
|
+
foreground: "#fafafa",
|
|
1288
|
+
border: "rgba(250, 250, 250, 0.10)",
|
|
1289
|
+
mutedForeground: "#a1a1aa"
|
|
881
1290
|
}
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
1291
|
+
},
|
|
1292
|
+
neutral: {
|
|
1293
|
+
light: {
|
|
1294
|
+
surfaceElevated: "#ffffff",
|
|
1295
|
+
surfaceOverlay: "#ffffff",
|
|
1296
|
+
foreground: "#171717",
|
|
1297
|
+
border: "rgba(23, 23, 23, 0.08)",
|
|
1298
|
+
mutedForeground: "#737373"
|
|
1299
|
+
},
|
|
1300
|
+
dark: {
|
|
1301
|
+
surfaceElevated: "#171717",
|
|
1302
|
+
surfaceOverlay: "#262626",
|
|
1303
|
+
foreground: "#fafafa",
|
|
1304
|
+
border: "rgba(250, 250, 250, 0.10)",
|
|
1305
|
+
mutedForeground: "#a3a3a3"
|
|
885
1306
|
}
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
1307
|
+
},
|
|
1308
|
+
slate: {
|
|
1309
|
+
light: {
|
|
1310
|
+
surfaceElevated: "#ffffff",
|
|
1311
|
+
surfaceOverlay: "#ffffff",
|
|
1312
|
+
foreground: "#0f172a",
|
|
1313
|
+
border: "rgba(15, 23, 42, 0.08)",
|
|
1314
|
+
mutedForeground: "#64748b"
|
|
1315
|
+
},
|
|
1316
|
+
dark: {
|
|
1317
|
+
surfaceElevated: "#0f172a",
|
|
1318
|
+
surfaceOverlay: "#1e293b",
|
|
1319
|
+
foreground: "#f8fafc",
|
|
1320
|
+
border: "rgba(248, 250, 252, 0.10)",
|
|
1321
|
+
mutedForeground: "#94a3b8"
|
|
891
1322
|
}
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
1323
|
+
},
|
|
1324
|
+
stone: {
|
|
1325
|
+
light: {
|
|
1326
|
+
surfaceElevated: "#ffffff",
|
|
1327
|
+
surfaceOverlay: "#ffffff",
|
|
1328
|
+
foreground: "#1c1917",
|
|
1329
|
+
border: "rgba(28, 25, 23, 0.08)",
|
|
1330
|
+
mutedForeground: "#78716c"
|
|
1331
|
+
},
|
|
1332
|
+
dark: {
|
|
1333
|
+
surfaceElevated: "#1c1917",
|
|
1334
|
+
surfaceOverlay: "#292524",
|
|
1335
|
+
foreground: "#fafaf9",
|
|
1336
|
+
border: "rgba(250, 250, 249, 0.10)",
|
|
1337
|
+
mutedForeground: "#a8a29e"
|
|
895
1338
|
}
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
1339
|
+
},
|
|
1340
|
+
taupe: {
|
|
1341
|
+
light: {
|
|
1342
|
+
surfaceElevated: "#faf8f5",
|
|
1343
|
+
surfaceOverlay: "#ffffff",
|
|
1344
|
+
foreground: "#3b342e",
|
|
1345
|
+
border: "rgba(59, 52, 46, 0.10)",
|
|
1346
|
+
mutedForeground: "#8a7f74"
|
|
1347
|
+
},
|
|
1348
|
+
dark: {
|
|
1349
|
+
surfaceElevated: "#1c1916",
|
|
1350
|
+
surfaceOverlay: "#2a2521",
|
|
1351
|
+
foreground: "#f5f0ea",
|
|
1352
|
+
border: "rgba(245, 240, 234, 0.10)",
|
|
1353
|
+
mutedForeground: "#a89f94"
|
|
901
1354
|
}
|
|
902
|
-
options.set(name, true);
|
|
903
1355
|
}
|
|
904
|
-
|
|
1356
|
+
};
|
|
1357
|
+
var THEME_COLOR_PALETTE = {
|
|
1358
|
+
ink: {
|
|
1359
|
+
light: { ...DEFAULT_CONTROL_SOLID_LIGHT },
|
|
1360
|
+
dark: { ...DEFAULT_CONTROL_SOLID_DARK }
|
|
1361
|
+
},
|
|
1362
|
+
//
|
|
1363
|
+
// Named hues stay the same true, saturated color family in both modes —
|
|
1364
|
+
// dark mode gets one step deeper (never a washed-out pastel tint of the
|
|
1365
|
+
// light-mode color). This mirrors how shadcn's own theme presets work:
|
|
1366
|
+
// e.g. its "red" theme ships `oklch(0.505 … 27.518)` (~Tailwind red-700)
|
|
1367
|
+
// for light and `oklch(0.444 … 26.899)` (~red-800, darker not lighter)
|
|
1368
|
+
// for dark, with a near-white foreground in both. Hex stops below are
|
|
1369
|
+
// Tailwind v4's red/blue/violet/green/orange 600/700/800/900/50 values.
|
|
1370
|
+
red: {
|
|
1371
|
+
light: {
|
|
1372
|
+
controlSolid: "#c10007",
|
|
1373
|
+
// red-700
|
|
1374
|
+
controlSolidHover: "#e7000b",
|
|
1375
|
+
// red-600 — brighter on hover
|
|
1376
|
+
controlSolidActive: "#9f0712",
|
|
1377
|
+
// red-800 — darker on press
|
|
1378
|
+
controlSolidForeground: "#fef2f2"
|
|
1379
|
+
// red-50
|
|
1380
|
+
},
|
|
1381
|
+
dark: {
|
|
1382
|
+
controlSolid: "#9f0712",
|
|
1383
|
+
// red-800
|
|
1384
|
+
controlSolidHover: "#c10007",
|
|
1385
|
+
// red-700 — brighter on hover
|
|
1386
|
+
controlSolidActive: "#82181a",
|
|
1387
|
+
// red-900 — darker on press
|
|
1388
|
+
controlSolidForeground: "#fef2f2"
|
|
1389
|
+
// red-50
|
|
1390
|
+
}
|
|
1391
|
+
},
|
|
1392
|
+
blue: {
|
|
1393
|
+
light: {
|
|
1394
|
+
controlSolid: "#1447e6",
|
|
1395
|
+
// blue-700
|
|
1396
|
+
controlSolidHover: "#155dfc",
|
|
1397
|
+
// blue-600
|
|
1398
|
+
controlSolidActive: "#193cb8",
|
|
1399
|
+
// blue-800
|
|
1400
|
+
controlSolidForeground: "#eff6ff"
|
|
1401
|
+
// blue-50
|
|
1402
|
+
},
|
|
1403
|
+
dark: {
|
|
1404
|
+
controlSolid: "#193cb8",
|
|
1405
|
+
// blue-800
|
|
1406
|
+
controlSolidHover: "#1447e6",
|
|
1407
|
+
// blue-700
|
|
1408
|
+
controlSolidActive: "#1c398e",
|
|
1409
|
+
// blue-900
|
|
1410
|
+
controlSolidForeground: "#eff6ff"
|
|
1411
|
+
// blue-50
|
|
1412
|
+
}
|
|
1413
|
+
},
|
|
1414
|
+
violet: {
|
|
1415
|
+
light: {
|
|
1416
|
+
controlSolid: "#7008e7",
|
|
1417
|
+
// violet-700
|
|
1418
|
+
controlSolidHover: "#7f22fe",
|
|
1419
|
+
// violet-600
|
|
1420
|
+
controlSolidActive: "#5d0ec0",
|
|
1421
|
+
// violet-800
|
|
1422
|
+
controlSolidForeground: "#f5f3ff"
|
|
1423
|
+
// violet-50
|
|
1424
|
+
},
|
|
1425
|
+
dark: {
|
|
1426
|
+
controlSolid: "#5d0ec0",
|
|
1427
|
+
// violet-800
|
|
1428
|
+
controlSolidHover: "#7008e7",
|
|
1429
|
+
// violet-700
|
|
1430
|
+
controlSolidActive: "#4d179a",
|
|
1431
|
+
// violet-900
|
|
1432
|
+
controlSolidForeground: "#f5f3ff"
|
|
1433
|
+
// violet-50
|
|
1434
|
+
}
|
|
1435
|
+
},
|
|
1436
|
+
green: {
|
|
1437
|
+
light: {
|
|
1438
|
+
controlSolid: "#008236",
|
|
1439
|
+
// green-700
|
|
1440
|
+
controlSolidHover: "#00a63e",
|
|
1441
|
+
// green-600
|
|
1442
|
+
controlSolidActive: "#016630",
|
|
1443
|
+
// green-800
|
|
1444
|
+
controlSolidForeground: "#f0fdf4"
|
|
1445
|
+
// green-50
|
|
1446
|
+
},
|
|
1447
|
+
dark: {
|
|
1448
|
+
controlSolid: "#016630",
|
|
1449
|
+
// green-800
|
|
1450
|
+
controlSolidHover: "#008236",
|
|
1451
|
+
// green-700
|
|
1452
|
+
controlSolidActive: "#0d542b",
|
|
1453
|
+
// green-900
|
|
1454
|
+
controlSolidForeground: "#f0fdf4"
|
|
1455
|
+
// green-50
|
|
1456
|
+
}
|
|
1457
|
+
},
|
|
1458
|
+
orange: {
|
|
1459
|
+
light: {
|
|
1460
|
+
controlSolid: "#ca3500",
|
|
1461
|
+
// orange-700
|
|
1462
|
+
controlSolidHover: "#f54900",
|
|
1463
|
+
// orange-600
|
|
1464
|
+
controlSolidActive: "#9f2d00",
|
|
1465
|
+
// orange-800
|
|
1466
|
+
controlSolidForeground: "#fff7ed"
|
|
1467
|
+
// orange-50
|
|
1468
|
+
},
|
|
1469
|
+
dark: {
|
|
1470
|
+
controlSolid: "#9f2d00",
|
|
1471
|
+
// orange-800
|
|
1472
|
+
controlSolidHover: "#ca3500",
|
|
1473
|
+
// orange-700
|
|
1474
|
+
controlSolidActive: "#7e2a0c",
|
|
1475
|
+
// orange-900
|
|
1476
|
+
controlSolidForeground: "#fff7ed"
|
|
1477
|
+
// orange-50
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
};
|
|
1481
|
+
var DEFAULT_CHART_STOPS = {
|
|
1482
|
+
light: [
|
|
1483
|
+
"#2a78d6",
|
|
1484
|
+
"#1baf7a",
|
|
1485
|
+
"#eda100",
|
|
1486
|
+
"#008300",
|
|
1487
|
+
"#4a3aa7",
|
|
1488
|
+
"#e34948"
|
|
1489
|
+
],
|
|
1490
|
+
dark: [
|
|
1491
|
+
"#3987e5",
|
|
1492
|
+
"#199e70",
|
|
1493
|
+
"#c98500",
|
|
1494
|
+
"#008300",
|
|
1495
|
+
"#9085e9",
|
|
1496
|
+
"#e66767"
|
|
1497
|
+
]
|
|
1498
|
+
};
|
|
1499
|
+
var CHART_PALETTES = {
|
|
1500
|
+
theme: {
|
|
1501
|
+
ink: DEFAULT_CHART_STOPS,
|
|
1502
|
+
red: {
|
|
1503
|
+
light: ["#e34948", "#f97316", "#eda100", "#db2777", "#b91c1c", "#9f1239"],
|
|
1504
|
+
dark: ["#e66767", "#fb923c", "#c98500", "#f472b6", "#f87171", "#fb7185"]
|
|
1505
|
+
},
|
|
1506
|
+
blue: {
|
|
1507
|
+
light: ["#2a78d6", "#0284c7", "#4a3aa7", "#0e7490", "#1d4ed8", "#0369a1"],
|
|
1508
|
+
dark: ["#3987e5", "#38bdf8", "#9085e9", "#22d3ee", "#60a5fa", "#7dd3fc"]
|
|
1509
|
+
},
|
|
1510
|
+
violet: {
|
|
1511
|
+
light: ["#4a3aa7", "#7c3aed", "#2a78d6", "#a21caf", "#6d28d9", "#db2777"],
|
|
1512
|
+
dark: ["#9085e9", "#a78bfa", "#3987e5", "#e879f9", "#c4b5fd", "#f472b6"]
|
|
1513
|
+
},
|
|
1514
|
+
green: {
|
|
1515
|
+
light: ["#1baf7a", "#008300", "#0d9488", "#2a78d6", "#047857", "#65a30d"],
|
|
1516
|
+
dark: ["#199e70", "#34d399", "#2dd4bf", "#3987e5", "#4ade80", "#a3e635"]
|
|
1517
|
+
},
|
|
1518
|
+
orange: {
|
|
1519
|
+
light: ["#eda100", "#f97316", "#e34948", "#ca8a04", "#c2410c", "#db2777"],
|
|
1520
|
+
dark: ["#c98500", "#fb923c", "#e66767", "#facc15", "#fdba74", "#f472b6"]
|
|
1521
|
+
}
|
|
1522
|
+
},
|
|
1523
|
+
warm: {
|
|
1524
|
+
light: ["#ea580c", "#d97706", "#e34948", "#db2777", "#ca8a04", "#c2410c"],
|
|
1525
|
+
dark: ["#fb923c", "#fbbf24", "#e66767", "#f472b6", "#facc15", "#fdba74"]
|
|
1526
|
+
},
|
|
1527
|
+
cool: {
|
|
1528
|
+
light: ["#2a78d6", "#0e7490", "#4a3aa7", "#0284c7", "#1d4ed8", "#0f766e"],
|
|
1529
|
+
dark: ["#3987e5", "#22d3ee", "#9085e9", "#38bdf8", "#60a5fa", "#2dd4bf"]
|
|
1530
|
+
},
|
|
1531
|
+
mixed: {
|
|
1532
|
+
light: ["#2a78d6", "#e34948", "#1baf7a", "#eda100", "#4a3aa7", "#db2777"],
|
|
1533
|
+
dark: ["#3987e5", "#e66767", "#199e70", "#c98500", "#9085e9", "#f472b6"]
|
|
1534
|
+
}
|
|
1535
|
+
};
|
|
1536
|
+
|
|
1537
|
+
// ../wensity-preset/src/curated-fonts.ts
|
|
1538
|
+
var HEADING_FONT_PACKAGES = {
|
|
1539
|
+
playfair: {
|
|
1540
|
+
packageName: "@fontsource/playfair-display",
|
|
1541
|
+
importSpecifier: "@fontsource/playfair-display",
|
|
1542
|
+
familyName: "Playfair Display"
|
|
1543
|
+
}
|
|
1544
|
+
};
|
|
1545
|
+
var BODY_FONT_PACKAGES = {
|
|
1546
|
+
inter: {
|
|
1547
|
+
packageName: "@fontsource/inter",
|
|
1548
|
+
importSpecifier: "@fontsource/inter",
|
|
1549
|
+
familyName: "Inter"
|
|
1550
|
+
}
|
|
1551
|
+
};
|
|
1552
|
+
var HEADING_FONT_CSS = {
|
|
1553
|
+
system: "var(--font-display)",
|
|
1554
|
+
playfair: "'Playfair Display', Georgia, 'Times New Roman', serif"
|
|
1555
|
+
};
|
|
1556
|
+
var BODY_FONT_CSS = {
|
|
1557
|
+
system: "var(--font-sans)",
|
|
1558
|
+
inter: "'Inter', ui-sans-serif, system-ui, sans-serif"
|
|
1559
|
+
};
|
|
1560
|
+
|
|
1561
|
+
// ../wensity-preset/src/resolve.ts
|
|
1562
|
+
var RESOLVED_TOKEN_CSS_VARS = {
|
|
1563
|
+
surfaceElevated: "--primitive-surface-elevated",
|
|
1564
|
+
surfaceOverlay: "--primitive-surface-overlay",
|
|
1565
|
+
surfaceHover: "--primitive-surface-hover",
|
|
1566
|
+
surfaceActive: "--primitive-surface-active",
|
|
1567
|
+
surfaceSelected: "--primitive-surface-selected",
|
|
1568
|
+
borderSubtle: "--primitive-border-subtle",
|
|
1569
|
+
ring: "--primitive-ring",
|
|
1570
|
+
textSecondary: "--primitive-text-secondary",
|
|
1571
|
+
textPlaceholder: "--primitive-text-placeholder",
|
|
1572
|
+
controlSolid: "--primitive-control-solid",
|
|
1573
|
+
controlSolidHover: "--primitive-control-solid-hover",
|
|
1574
|
+
controlSolidActive: "--primitive-control-solid-active",
|
|
1575
|
+
controlSolidForeground: "--primitive-control-solid-foreground",
|
|
1576
|
+
chart1: "--primitive-chart-1",
|
|
1577
|
+
chart2: "--primitive-chart-2",
|
|
1578
|
+
chart3: "--primitive-chart-3",
|
|
1579
|
+
chart4: "--primitive-chart-4",
|
|
1580
|
+
chart5: "--primitive-chart-5",
|
|
1581
|
+
chart6: "--primitive-chart-6",
|
|
1582
|
+
radius: "--primitive-radius",
|
|
1583
|
+
fontSans: "--primitive-font-sans",
|
|
1584
|
+
fontDisplay: "--primitive-font-display",
|
|
1585
|
+
fontMono: "--primitive-font-mono"
|
|
1586
|
+
};
|
|
1587
|
+
var INHERIT_BASE_EXPRESSIONS = {
|
|
1588
|
+
light: {
|
|
1589
|
+
surfaceElevated: "#ffffff",
|
|
1590
|
+
surfaceOverlay: "#ffffff",
|
|
1591
|
+
surfaceHover: "color-mix(in srgb, var(--foreground) 4%, transparent)",
|
|
1592
|
+
surfaceActive: "color-mix(in srgb, var(--foreground) 7%, transparent)",
|
|
1593
|
+
borderSubtle: "color-mix(in srgb, var(--border) 60%, transparent)",
|
|
1594
|
+
textSecondary: "color-mix(in srgb, var(--foreground) 72%, transparent)",
|
|
1595
|
+
textPlaceholder: "color-mix(in srgb, var(--muted-foreground) 85%, transparent)"
|
|
1596
|
+
},
|
|
1597
|
+
dark: {
|
|
1598
|
+
surfaceElevated: "#0f0f10",
|
|
1599
|
+
surfaceOverlay: "#141415",
|
|
1600
|
+
surfaceHover: "color-mix(in srgb, var(--foreground) 5%, transparent)",
|
|
1601
|
+
surfaceActive: "color-mix(in srgb, var(--foreground) 10%, transparent)",
|
|
1602
|
+
borderSubtle: "color-mix(in srgb, var(--border) 60%, transparent)",
|
|
1603
|
+
textSecondary: "color-mix(in srgb, var(--foreground) 72%, transparent)",
|
|
1604
|
+
textPlaceholder: "color-mix(in srgb, var(--muted-foreground) 85%, transparent)"
|
|
1605
|
+
}
|
|
1606
|
+
};
|
|
1607
|
+
var FIXED_RING = "color-mix(in srgb, var(--foreground) 45%, transparent)";
|
|
1608
|
+
var FIXED_SURFACE_SELECTED = {
|
|
1609
|
+
light: "color-mix(in srgb, var(--foreground) 6%, transparent)",
|
|
1610
|
+
dark: "color-mix(in srgb, var(--foreground) 8%, transparent)"
|
|
1611
|
+
};
|
|
1612
|
+
var COLORED_THEME_IDS = /* @__PURE__ */ new Set([
|
|
1613
|
+
"red",
|
|
1614
|
+
"blue",
|
|
1615
|
+
"violet",
|
|
1616
|
+
"green",
|
|
1617
|
+
"orange"
|
|
1618
|
+
]);
|
|
1619
|
+
function colorMix(source, percent) {
|
|
1620
|
+
return `color-mix(in srgb, ${source} ${percent}%, transparent)`;
|
|
905
1621
|
}
|
|
906
|
-
function
|
|
907
|
-
const
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
1622
|
+
function resolveControlSolid(partial, fallback) {
|
|
1623
|
+
const out = { ...fallback };
|
|
1624
|
+
for (const key of CONTROL_SOLID_COLOR_KEYS) {
|
|
1625
|
+
const value = partial?.[key];
|
|
1626
|
+
if (value !== void 0) out[key] = value;
|
|
911
1627
|
}
|
|
912
|
-
return
|
|
1628
|
+
return out;
|
|
913
1629
|
}
|
|
914
|
-
function
|
|
915
|
-
return
|
|
1630
|
+
function chartStopsToModeTokens(stops) {
|
|
1631
|
+
return {
|
|
1632
|
+
chart1: stops[0],
|
|
1633
|
+
chart2: stops[1],
|
|
1634
|
+
chart3: stops[2],
|
|
1635
|
+
chart4: stops[3],
|
|
1636
|
+
chart5: stops[4],
|
|
1637
|
+
chart6: stops[5]
|
|
1638
|
+
};
|
|
916
1639
|
}
|
|
917
|
-
function
|
|
918
|
-
return [
|
|
1640
|
+
function baseFromInherit(mode) {
|
|
1641
|
+
return { ...INHERIT_BASE_EXPRESSIONS[mode] };
|
|
919
1642
|
}
|
|
920
|
-
function
|
|
921
|
-
|
|
922
|
-
|
|
1643
|
+
function baseFromSeeds(seeds, mode) {
|
|
1644
|
+
const hoverPercent = mode === "light" ? 4 : 5;
|
|
1645
|
+
const activePercent = mode === "light" ? 7 : 10;
|
|
1646
|
+
return {
|
|
1647
|
+
surfaceElevated: seeds.surfaceElevated,
|
|
1648
|
+
surfaceOverlay: seeds.surfaceOverlay,
|
|
1649
|
+
surfaceHover: colorMix(seeds.foreground, hoverPercent),
|
|
1650
|
+
surfaceActive: colorMix(seeds.foreground, activePercent),
|
|
1651
|
+
borderSubtle: colorMix(seeds.border, 60),
|
|
1652
|
+
textSecondary: colorMix(seeds.foreground, 72),
|
|
1653
|
+
textPlaceholder: colorMix(seeds.mutedForeground, 85)
|
|
1654
|
+
};
|
|
1655
|
+
}
|
|
1656
|
+
function ringAndSelectedForInk(mode) {
|
|
1657
|
+
return {
|
|
1658
|
+
ring: FIXED_RING,
|
|
1659
|
+
surfaceSelected: FIXED_SURFACE_SELECTED[mode]
|
|
1660
|
+
};
|
|
1661
|
+
}
|
|
1662
|
+
function ringAndSelectedFromAccent(accent, mode) {
|
|
1663
|
+
return {
|
|
1664
|
+
ring: colorMix(accent, 45),
|
|
1665
|
+
surfaceSelected: colorMix(accent, mode === "light" ? 6 : 8)
|
|
1666
|
+
};
|
|
1667
|
+
}
|
|
1668
|
+
function buildModeTokens(args) {
|
|
1669
|
+
return {
|
|
1670
|
+
...args.base,
|
|
1671
|
+
...args.ringSelected,
|
|
1672
|
+
controlSolid: args.control.controlSolid,
|
|
1673
|
+
controlSolidHover: args.control.controlSolidHover,
|
|
1674
|
+
controlSolidActive: args.control.controlSolidActive,
|
|
1675
|
+
controlSolidForeground: args.control.controlSolidForeground,
|
|
1676
|
+
...chartStopsToModeTokens(args.charts)
|
|
1677
|
+
};
|
|
1678
|
+
}
|
|
1679
|
+
function resolveStyleConfig(style) {
|
|
1680
|
+
const lightControl = resolveControlSolid(
|
|
1681
|
+
style.colors?.light,
|
|
1682
|
+
DEFAULT_CONTROL_SOLID_LIGHT
|
|
1683
|
+
);
|
|
1684
|
+
const darkControl = resolveControlSolid(
|
|
1685
|
+
style.colors?.dark,
|
|
1686
|
+
DEFAULT_CONTROL_SOLID_DARK
|
|
1687
|
+
);
|
|
1688
|
+
return {
|
|
1689
|
+
iconLibrary: style.iconLibrary,
|
|
1690
|
+
radius: RADIUS_PRESET_CSS[style.radius],
|
|
1691
|
+
fontSans: expandFontRole(style.fonts.sans, "sans"),
|
|
1692
|
+
fontDisplay: expandFontRole(style.fonts.display, "display"),
|
|
1693
|
+
fontMono: expandFontRole(style.fonts.mono, "mono"),
|
|
1694
|
+
light: buildModeTokens({
|
|
1695
|
+
base: baseFromInherit("light"),
|
|
1696
|
+
control: lightControl,
|
|
1697
|
+
ringSelected: ringAndSelectedForInk("light"),
|
|
1698
|
+
charts: DEFAULT_CHART_STOPS.light
|
|
1699
|
+
}),
|
|
1700
|
+
dark: buildModeTokens({
|
|
1701
|
+
base: baseFromInherit("dark"),
|
|
1702
|
+
control: darkControl,
|
|
1703
|
+
ringSelected: ringAndSelectedForInk("dark"),
|
|
1704
|
+
charts: DEFAULT_CHART_STOPS.dark
|
|
1705
|
+
})
|
|
1706
|
+
};
|
|
1707
|
+
}
|
|
1708
|
+
function resolveChartStops(chartPalette, themeColor, mode) {
|
|
1709
|
+
if (chartPalette === "theme") {
|
|
1710
|
+
return CHART_PALETTES.theme[themeColor][mode];
|
|
1711
|
+
}
|
|
1712
|
+
return CHART_PALETTES[chartPalette][mode];
|
|
1713
|
+
}
|
|
1714
|
+
function resolveStyleConfigCanonical(style) {
|
|
1715
|
+
const theme = THEME_COLOR_PALETTE[style.themeColor];
|
|
1716
|
+
const useAccentRing = COLORED_THEME_IDS.has(style.themeColor);
|
|
1717
|
+
const resolveMode = (mode) => {
|
|
1718
|
+
const base = style.baseColor === "inherit" ? baseFromInherit(mode) : baseFromSeeds(BASE_COLOR_PALETTE[style.baseColor][mode], mode);
|
|
1719
|
+
const control = theme[mode];
|
|
1720
|
+
const ringSelected = useAccentRing ? ringAndSelectedFromAccent(control.controlSolid, mode) : ringAndSelectedForInk(mode);
|
|
1721
|
+
const charts = resolveChartStops(style.chartPalette, style.themeColor, mode);
|
|
1722
|
+
return buildModeTokens({ base, control, ringSelected, charts });
|
|
1723
|
+
};
|
|
1724
|
+
return {
|
|
1725
|
+
iconLibrary: style.iconLibrary,
|
|
1726
|
+
radius: RADIUS_PRESET_CSS[style.radius],
|
|
1727
|
+
fontSans: BODY_FONT_CSS[style.bodyFont],
|
|
1728
|
+
fontDisplay: HEADING_FONT_CSS[style.headingFont],
|
|
1729
|
+
// Canonical model has no mono field — lock to today's system-mono expansion.
|
|
1730
|
+
fontMono: FONT_ID_EXPANSIONS["system-mono"],
|
|
1731
|
+
light: resolveMode("light"),
|
|
1732
|
+
dark: resolveMode("dark")
|
|
1733
|
+
};
|
|
923
1734
|
}
|
|
924
|
-
|
|
925
|
-
// src/config.ts
|
|
926
|
-
import { existsSync } from "fs";
|
|
927
|
-
import { access, mkdir, readFile, writeFile } from "fs/promises";
|
|
928
|
-
import { dirname as dirname2, join as join2, relative as relative2 } from "path";
|
|
929
1735
|
|
|
930
1736
|
// src/paths.ts
|
|
931
1737
|
import { dirname, isAbsolute, relative, resolve, sep } from "path";
|
|
@@ -995,6 +1801,35 @@ function extensionlessPath(path) {
|
|
|
995
1801
|
return path.replace(/\.(tsx|ts|jsx|js)$/, "");
|
|
996
1802
|
}
|
|
997
1803
|
|
|
1804
|
+
// src/style-shape.ts
|
|
1805
|
+
function isCanonicalStyleShape(value) {
|
|
1806
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
1807
|
+
const record = value;
|
|
1808
|
+
return "baseColor" in record || "themeColor" in record || "chartPalette" in record || "headingFont" in record || "bodyFont" in record;
|
|
1809
|
+
}
|
|
1810
|
+
function normalizeProjectStyle(style) {
|
|
1811
|
+
if (isCanonicalStyleShape(style)) {
|
|
1812
|
+
return normalizeStyleConfigCanonical(style);
|
|
1813
|
+
}
|
|
1814
|
+
return normalizeStyleConfig(style);
|
|
1815
|
+
}
|
|
1816
|
+
function resolveTokensForStyle(style) {
|
|
1817
|
+
if (isCanonicalStyleShape(style)) {
|
|
1818
|
+
return resolveStyleConfigCanonical(normalizeStyleConfigCanonical(style));
|
|
1819
|
+
}
|
|
1820
|
+
return resolveStyleConfig(normalizeStyleConfig(style));
|
|
1821
|
+
}
|
|
1822
|
+
function curatedFontsFromStyle(style) {
|
|
1823
|
+
if (isCanonicalStyleShape(style)) {
|
|
1824
|
+
const normalized = normalizeStyleConfigCanonical(style);
|
|
1825
|
+
return {
|
|
1826
|
+
headingFont: normalized.headingFont,
|
|
1827
|
+
bodyFont: normalized.bodyFont
|
|
1828
|
+
};
|
|
1829
|
+
}
|
|
1830
|
+
return { headingFont: "system", bodyFont: "system" };
|
|
1831
|
+
}
|
|
1832
|
+
|
|
998
1833
|
// src/config.ts
|
|
999
1834
|
async function loadConfig(cwd, overrides = {}) {
|
|
1000
1835
|
const foundPath = await findUp(cwd, CONFIG_FILE_NAME);
|
|
@@ -1128,7 +1963,8 @@ function normalizeConfig(config, overrides) {
|
|
|
1128
1963
|
utils: config.aliases?.utils || DEFAULT_UTILS_ALIAS
|
|
1129
1964
|
},
|
|
1130
1965
|
// In-memory only: missing style fields resolve to defaults without rewriting disk.
|
|
1131
|
-
style
|
|
1966
|
+
// Accepts either legacy or canonical style shapes.
|
|
1967
|
+
style: normalizeProjectStyle(config.style)
|
|
1132
1968
|
};
|
|
1133
1969
|
} catch (error) {
|
|
1134
1970
|
if (error instanceof PresetValidationError) {
|
|
@@ -1257,6 +2093,122 @@ function requiredHome(env) {
|
|
|
1257
2093
|
throw new CliError("HOME is not set, so the CLI cannot locate ~/.config/wensity.");
|
|
1258
2094
|
}
|
|
1259
2095
|
|
|
2096
|
+
// src/font-install.ts
|
|
2097
|
+
var FONT_CSS_START_MARKER = "/* \u2500\u2500 Wensity Fonts";
|
|
2098
|
+
var FONT_CSS_END_MARKER = "/* \u2500\u2500 End Wensity Fonts \u2500\u2500 */";
|
|
2099
|
+
function planFontInstall(headingFont, bodyFont) {
|
|
2100
|
+
const packages = [];
|
|
2101
|
+
const importLines = [];
|
|
2102
|
+
const seenPackages = /* @__PURE__ */ new Set();
|
|
2103
|
+
const seenImports = /* @__PURE__ */ new Set();
|
|
2104
|
+
const pushFont = (meta) => {
|
|
2105
|
+
if (!meta) return;
|
|
2106
|
+
if (!seenPackages.has(meta.packageName)) {
|
|
2107
|
+
seenPackages.add(meta.packageName);
|
|
2108
|
+
packages.push(meta.packageName);
|
|
2109
|
+
}
|
|
2110
|
+
const line = `@import "${meta.importSpecifier}";`;
|
|
2111
|
+
if (!seenImports.has(line)) {
|
|
2112
|
+
seenImports.add(line);
|
|
2113
|
+
importLines.push(line);
|
|
2114
|
+
}
|
|
2115
|
+
};
|
|
2116
|
+
if (headingFont !== "system") {
|
|
2117
|
+
pushFont(HEADING_FONT_PACKAGES[headingFont]);
|
|
2118
|
+
}
|
|
2119
|
+
if (bodyFont !== "system") {
|
|
2120
|
+
pushFont(BODY_FONT_PACKAGES[bodyFont]);
|
|
2121
|
+
}
|
|
2122
|
+
packages.sort();
|
|
2123
|
+
if (importLines.length === 0) {
|
|
2124
|
+
return { packages: [], importLines: [], block: null };
|
|
2125
|
+
}
|
|
2126
|
+
const block = [
|
|
2127
|
+
`${FONT_CSS_START_MARKER} \u2500\u2500 */`,
|
|
2128
|
+
...importLines,
|
|
2129
|
+
FONT_CSS_END_MARKER
|
|
2130
|
+
].join("\n");
|
|
2131
|
+
return { packages, importLines, block };
|
|
2132
|
+
}
|
|
2133
|
+
function upsertFontImportBlock(existingCss, block) {
|
|
2134
|
+
const start = existingCss.indexOf(FONT_CSS_START_MARKER);
|
|
2135
|
+
const end = existingCss.indexOf(FONT_CSS_END_MARKER);
|
|
2136
|
+
if (start !== -1 || end !== -1) {
|
|
2137
|
+
if (start === -1 || end === -1 || end <= start) {
|
|
2138
|
+
throw new CliError(
|
|
2139
|
+
"Configured Tailwind CSS has a partial Wensity Fonts block. Remove the broken markers and re-run install."
|
|
2140
|
+
);
|
|
2141
|
+
}
|
|
2142
|
+
const before2 = existingCss.slice(0, start).replace(/\s*$/, "");
|
|
2143
|
+
const after2 = existingCss.slice(end + FONT_CSS_END_MARKER.length).replace(/^\s*/, "");
|
|
2144
|
+
if (!block) {
|
|
2145
|
+
const joined = [before2, after2].filter((part) => part.length > 0).join("\n\n");
|
|
2146
|
+
return joined ? `${joined.replace(/\n{3,}/g, "\n\n")}
|
|
2147
|
+
` : "";
|
|
2148
|
+
}
|
|
2149
|
+
const normalizedBlock2 = block.trim();
|
|
2150
|
+
const prefix2 = before2 ? `${before2}
|
|
2151
|
+
|
|
2152
|
+
` : "";
|
|
2153
|
+
const suffix2 = after2 ? `
|
|
2154
|
+
|
|
2155
|
+
${after2}` : "\n";
|
|
2156
|
+
return `${prefix2}${normalizedBlock2}${suffix2}`.replace(/\n{3,}/g, "\n\n");
|
|
2157
|
+
}
|
|
2158
|
+
if (!block) return existingCss;
|
|
2159
|
+
const normalizedBlock = block.trim();
|
|
2160
|
+
const insertAt = findFontBlockInsertIndex(existingCss);
|
|
2161
|
+
const before = existingCss.slice(0, insertAt).replace(/\s*$/, "");
|
|
2162
|
+
const after = existingCss.slice(insertAt).replace(/^\s*/, "");
|
|
2163
|
+
const prefix = before ? `${before}
|
|
2164
|
+
|
|
2165
|
+
` : "";
|
|
2166
|
+
const suffix = after ? `
|
|
2167
|
+
|
|
2168
|
+
${after}` : "\n";
|
|
2169
|
+
return `${prefix}${normalizedBlock}${suffix}`.replace(/\n{3,}/g, "\n\n");
|
|
2170
|
+
}
|
|
2171
|
+
function warnUnusedFontPackageMessage(headingFont, bodyFont, installedPackages) {
|
|
2172
|
+
const needed = new Set(planFontInstall(headingFont, bodyFont).packages);
|
|
2173
|
+
const curated = [
|
|
2174
|
+
...Object.values(HEADING_FONT_PACKAGES).map((entry) => entry.packageName),
|
|
2175
|
+
...Object.values(BODY_FONT_PACKAGES).map((entry) => entry.packageName)
|
|
2176
|
+
];
|
|
2177
|
+
const leftover = curated.filter(
|
|
2178
|
+
(pkg) => installedPackages.has(pkg) && !needed.has(pkg)
|
|
2179
|
+
);
|
|
2180
|
+
if (leftover.length === 0) return void 0;
|
|
2181
|
+
return `Project package.json still lists ${leftover.join(", ")} while curated fonts are set to heading="${headingFont}" body="${bodyFont}". Wensity removed the @import for unused fonts but will not uninstall ${leftover.join(", ")} (it may be used outside Wensity).`;
|
|
2182
|
+
}
|
|
2183
|
+
function findFontBlockInsertIndex(css) {
|
|
2184
|
+
let index = 0;
|
|
2185
|
+
const length = css.length;
|
|
2186
|
+
while (index < length) {
|
|
2187
|
+
while (index < length && /\s/.test(css[index])) index += 1;
|
|
2188
|
+
if (index >= length) break;
|
|
2189
|
+
if (css.startsWith("/*", index)) {
|
|
2190
|
+
const end = css.indexOf("*/", index + 2);
|
|
2191
|
+
if (end === -1) break;
|
|
2192
|
+
index = end + 2;
|
|
2193
|
+
continue;
|
|
2194
|
+
}
|
|
2195
|
+
if (css.startsWith("//", index)) {
|
|
2196
|
+
const end = css.indexOf("\n", index);
|
|
2197
|
+
if (end === -1) return length;
|
|
2198
|
+
index = end + 1;
|
|
2199
|
+
continue;
|
|
2200
|
+
}
|
|
2201
|
+
if (css.startsWith("@charset", index) || css.startsWith("@import", index)) {
|
|
2202
|
+
const end = css.indexOf(";", index);
|
|
2203
|
+
if (end === -1) break;
|
|
2204
|
+
index = end + 1;
|
|
2205
|
+
continue;
|
|
2206
|
+
}
|
|
2207
|
+
break;
|
|
2208
|
+
}
|
|
2209
|
+
return index;
|
|
2210
|
+
}
|
|
2211
|
+
|
|
1260
2212
|
// src/output.ts
|
|
1261
2213
|
import boxen from "boxen";
|
|
1262
2214
|
import Table from "cli-table3";
|
|
@@ -1807,19 +2759,13 @@ async function resolvePresetStyle(input) {
|
|
|
1807
2759
|
const trimmed = raw.trim();
|
|
1808
2760
|
if (trimmed.startsWith("{")) {
|
|
1809
2761
|
const parsed = JSON.parse(trimmed);
|
|
1810
|
-
|
|
1811
|
-
const payload = validateCodecPayload(parsed);
|
|
1812
|
-
const json = stableStringifyCodecPayload(payload);
|
|
1813
|
-
code = `${PRESET_CODEC_PREFIX}.${Buffer.from(json, "utf8").toString("base64url")}`;
|
|
1814
|
-
} else {
|
|
1815
|
-
code = encodePreset(parsed);
|
|
1816
|
-
}
|
|
2762
|
+
code = encodePresetFileJson(parsed);
|
|
1817
2763
|
} else {
|
|
1818
2764
|
code = trimmed;
|
|
1819
2765
|
}
|
|
1820
2766
|
} catch (error) {
|
|
1821
2767
|
if (error instanceof PresetValidationError) {
|
|
1822
|
-
throw
|
|
2768
|
+
throw toCliPresetError(error);
|
|
1823
2769
|
}
|
|
1824
2770
|
if (error instanceof SyntaxError) {
|
|
1825
2771
|
throw new CliError(`Preset file contains invalid JSON: ${error.message}`);
|
|
@@ -1834,19 +2780,76 @@ async function resolvePresetStyle(input) {
|
|
|
1834
2780
|
}
|
|
1835
2781
|
try {
|
|
1836
2782
|
const trimmed = code.trim();
|
|
1837
|
-
const payload =
|
|
1838
|
-
const style =
|
|
1839
|
-
...codecPayloadToStyleInput(payload),
|
|
1840
|
-
presetCode: trimmed
|
|
1841
|
-
});
|
|
2783
|
+
const payload = decodeAnyPreset(trimmed);
|
|
2784
|
+
const style = styleFromDecodedPayload(payload, trimmed);
|
|
1842
2785
|
return { style, presetCode: trimmed };
|
|
1843
2786
|
} catch (error) {
|
|
1844
2787
|
if (error instanceof PresetValidationError) {
|
|
1845
|
-
throw
|
|
2788
|
+
throw toCliPresetError(error);
|
|
1846
2789
|
}
|
|
1847
2790
|
throw error;
|
|
1848
2791
|
}
|
|
1849
2792
|
}
|
|
2793
|
+
function encodePresetFileJson(parsed) {
|
|
2794
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
2795
|
+
throw new PresetValidationError("Expected an object at preset.", "preset");
|
|
2796
|
+
}
|
|
2797
|
+
if ("v" in parsed) {
|
|
2798
|
+
const v = parsed.v;
|
|
2799
|
+
if (v === 1) {
|
|
2800
|
+
const payload = validateCodecPayload(parsed);
|
|
2801
|
+
const json = stableStringifyCodecPayload(payload);
|
|
2802
|
+
return `${PRESET_CODEC_PREFIX}.${Buffer.from(json, "utf8").toString("base64url")}`;
|
|
2803
|
+
}
|
|
2804
|
+
if (v === 2) {
|
|
2805
|
+
const payload = validateCodecPayloadCanonical(parsed);
|
|
2806
|
+
return encodePresetCanonical({
|
|
2807
|
+
baseColor: payload.baseColor,
|
|
2808
|
+
themeColor: payload.themeColor,
|
|
2809
|
+
chartPalette: payload.chartPalette,
|
|
2810
|
+
headingFont: payload.headingFont,
|
|
2811
|
+
bodyFont: payload.bodyFont,
|
|
2812
|
+
iconLibrary: payload.iconLibrary,
|
|
2813
|
+
radius: payload.radius
|
|
2814
|
+
});
|
|
2815
|
+
}
|
|
2816
|
+
throw new PresetValidationError(
|
|
2817
|
+
`Unsupported preset payload version ${String(v)}. This preset may require a newer version of the Wensity CLI.`,
|
|
2818
|
+
"preset.v"
|
|
2819
|
+
);
|
|
2820
|
+
}
|
|
2821
|
+
if ("baseColor" in parsed || "themeColor" in parsed || "chartPalette" in parsed || "headingFont" in parsed || "bodyFont" in parsed) {
|
|
2822
|
+
return encodePresetCanonical(parsed);
|
|
2823
|
+
}
|
|
2824
|
+
return encodePreset(parsed);
|
|
2825
|
+
}
|
|
2826
|
+
function styleFromDecodedPayload(payload, presetCode) {
|
|
2827
|
+
if (payload.v === 1) {
|
|
2828
|
+
return normalizeStyleConfig({
|
|
2829
|
+
...codecPayloadToStyleInput(payload),
|
|
2830
|
+
presetCode
|
|
2831
|
+
});
|
|
2832
|
+
}
|
|
2833
|
+
return normalizeStyleConfigCanonical({
|
|
2834
|
+
baseColor: payload.baseColor,
|
|
2835
|
+
themeColor: payload.themeColor,
|
|
2836
|
+
chartPalette: payload.chartPalette,
|
|
2837
|
+
headingFont: payload.headingFont,
|
|
2838
|
+
bodyFont: payload.bodyFont,
|
|
2839
|
+
iconLibrary: payload.iconLibrary,
|
|
2840
|
+
radius: payload.radius,
|
|
2841
|
+
presetCode
|
|
2842
|
+
});
|
|
2843
|
+
}
|
|
2844
|
+
function toCliPresetError(error) {
|
|
2845
|
+
const message = error.message;
|
|
2846
|
+
if (/Unsupported preset payload version/i.test(message)) {
|
|
2847
|
+
return new CliError(
|
|
2848
|
+
`Invalid preset: ${message} Upgrade the Wensity CLI (wensity@latest) and try again.`
|
|
2849
|
+
);
|
|
2850
|
+
}
|
|
2851
|
+
return new CliError(`Invalid preset: ${message}`);
|
|
2852
|
+
}
|
|
1850
2853
|
|
|
1851
2854
|
// src/preset-init-writes.ts
|
|
1852
2855
|
import { mkdir as mkdir3, writeFile as writeFile3 } from "fs/promises";
|
|
@@ -1878,34 +2881,29 @@ async function commitPresetInitWrites(input) {
|
|
|
1878
2881
|
// src/style-css.ts
|
|
1879
2882
|
var ROOT_SELECTOR = ":root";
|
|
1880
2883
|
var DARK_SELECTOR = ".dark";
|
|
1881
|
-
|
|
1882
|
-
|
|
2884
|
+
var SHARED_TOKEN_KEYS = ["radius", "fontSans", "fontDisplay", "fontMono"];
|
|
2885
|
+
var MODE_TOKEN_KEYS = Object.keys(RESOLVED_TOKEN_CSS_VARS).filter(
|
|
2886
|
+
(key) => !SHARED_TOKEN_KEYS.includes(key)
|
|
2887
|
+
);
|
|
2888
|
+
function applyResolvedTokensToPrimitiveCss(block, tokens) {
|
|
1883
2889
|
let next = block;
|
|
1884
|
-
const
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
const cssValue = expandFontRole(style.fonts[role], role);
|
|
1890
|
-
next = replaceDeclInSelector(next, ROOT_SELECTOR, cssVar, cssValue);
|
|
1891
|
-
next = replaceDeclInSelector(next, DARK_SELECTOR, cssVar, cssValue);
|
|
1892
|
-
}
|
|
1893
|
-
if (style.colors?.light) {
|
|
1894
|
-
for (const key of CONTROL_SOLID_COLOR_KEYS) {
|
|
1895
|
-
const value = style.colors.light[key];
|
|
1896
|
-
if (value === void 0) continue;
|
|
1897
|
-
next = replaceDeclInSelector(next, ROOT_SELECTOR, CONTROL_SOLID_CSS_VARS[key], value);
|
|
1898
|
-
}
|
|
2890
|
+
for (const key of SHARED_TOKEN_KEYS) {
|
|
2891
|
+
const cssVar = RESOLVED_TOKEN_CSS_VARS[key];
|
|
2892
|
+
const value = tokens[key];
|
|
2893
|
+
next = replaceDeclInSelector(next, ROOT_SELECTOR, cssVar, value);
|
|
2894
|
+
next = replaceDeclInSelector(next, DARK_SELECTOR, cssVar, value);
|
|
1899
2895
|
}
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
next = replaceDeclInSelector(next, DARK_SELECTOR, CONTROL_SOLID_CSS_VARS[key], value);
|
|
1905
|
-
}
|
|
2896
|
+
for (const key of MODE_TOKEN_KEYS) {
|
|
2897
|
+
const cssVar = RESOLVED_TOKEN_CSS_VARS[key];
|
|
2898
|
+
next = replaceDeclInSelector(next, ROOT_SELECTOR, cssVar, tokens.light[key]);
|
|
2899
|
+
next = replaceDeclInSelector(next, DARK_SELECTOR, cssVar, tokens.dark[key]);
|
|
1906
2900
|
}
|
|
1907
2901
|
return next;
|
|
1908
2902
|
}
|
|
2903
|
+
function applyStyleToPrimitiveCss(block, styleInput) {
|
|
2904
|
+
const style = normalizeProjectStyle(styleInput);
|
|
2905
|
+
return applyResolvedTokensToPrimitiveCss(block, resolveTokensForStyle(style));
|
|
2906
|
+
}
|
|
1909
2907
|
function replaceDeclInSelector(css, selector, property, value) {
|
|
1910
2908
|
const block = findTopLevelRule(css, selector);
|
|
1911
2909
|
if (!block) return css;
|
|
@@ -2131,7 +3129,7 @@ async function prepareInstall(projectRoot, config, payload, options = {}) {
|
|
|
2131
3129
|
const files = [];
|
|
2132
3130
|
const componentContents = [];
|
|
2133
3131
|
const iconSwaps = [];
|
|
2134
|
-
const style =
|
|
3132
|
+
const style = normalizeProjectStyle(config.style);
|
|
2135
3133
|
const isPrimitiveCategory = isPrimitivePayloadCategory(payload.category);
|
|
2136
3134
|
const payloadHelperNeeds = normalizePayloadHelperNeeds(
|
|
2137
3135
|
"helperNeeds" in payload ? payload.helperNeeds : void 0
|
|
@@ -2188,8 +3186,10 @@ async function prepareInstall(projectRoot, config, payload, options = {}) {
|
|
|
2188
3186
|
}
|
|
2189
3187
|
const iconDependencySwap = aggregateIconDependencySwaps(iconSwaps);
|
|
2190
3188
|
const declaredAfterSwap = applyIconDependencySwap(payload.dependencies ?? [], iconDependencySwap);
|
|
3189
|
+
const fonts = curatedFontsFromStyle(style);
|
|
3190
|
+
const fontPlan = planFontInstall(fonts.headingFont, fonts.bodyFont);
|
|
2191
3191
|
const dependencies = collectDependencies({
|
|
2192
|
-
declared: declaredAfterSwap,
|
|
3192
|
+
declared: [...declaredAfterSwap, ...fontPlan.packages],
|
|
2193
3193
|
source: componentContents.join("\n"),
|
|
2194
3194
|
needsUtility: helperNeeds.utils
|
|
2195
3195
|
});
|
|
@@ -2198,7 +3198,8 @@ async function prepareInstall(projectRoot, config, payload, options = {}) {
|
|
|
2198
3198
|
files,
|
|
2199
3199
|
dependencies,
|
|
2200
3200
|
...cssFile ? { cssFile } : {},
|
|
2201
|
-
...isPrimitiveCategory ? { iconDependencySwap } : {}
|
|
3201
|
+
...isPrimitiveCategory ? { iconDependencySwap } : {},
|
|
3202
|
+
...fontPlan.packages.length > 0 ? { fontPackages: fontPlan.packages } : {}
|
|
2202
3203
|
};
|
|
2203
3204
|
}
|
|
2204
3205
|
async function planPrimitiveCssFile(projectRoot, config, payload) {
|
|
@@ -2207,13 +3208,16 @@ async function planPrimitiveCssFile(projectRoot, config, payload) {
|
|
|
2207
3208
|
}
|
|
2208
3209
|
let primitiveCss = payload.primitiveCss.trim();
|
|
2209
3210
|
if (!primitiveCss) return void 0;
|
|
2210
|
-
const style =
|
|
3211
|
+
const style = normalizeProjectStyle(config.style);
|
|
2211
3212
|
primitiveCss = applyStyleToPrimitiveCss(primitiveCss, style).trim();
|
|
2212
3213
|
const cssRelative = config.tailwind?.css;
|
|
2213
3214
|
if (!cssRelative) return void 0;
|
|
2214
3215
|
const absolutePath = resolveInside(projectRoot, cssRelative);
|
|
2215
3216
|
const existing = await fileExists(absolutePath) ? await readFile4(absolutePath, "utf8") : "";
|
|
2216
|
-
const
|
|
3217
|
+
const withTokens = upsertPrimitiveCssBlock(existing, primitiveCss);
|
|
3218
|
+
const fonts = curatedFontsFromStyle(style);
|
|
3219
|
+
const fontPlan = planFontInstall(fonts.headingFont, fonts.bodyFont);
|
|
3220
|
+
const next = upsertFontImportBlock(withTokens, fontPlan.block);
|
|
2217
3221
|
if (next === existing) return void 0;
|
|
2218
3222
|
return {
|
|
2219
3223
|
absolutePath,
|
|
@@ -2489,6 +3493,9 @@ async function initWithPreset(context, options) {
|
|
|
2489
3493
|
presetCode: options.presetCode,
|
|
2490
3494
|
presetFile: options.presetFile
|
|
2491
3495
|
});
|
|
3496
|
+
const fonts = curatedFontsFromStyle(style);
|
|
3497
|
+
const fontPlan = planFontInstall(fonts.headingFont, fonts.bodyFont);
|
|
3498
|
+
const installDependencies = [...options.dependencies, ...fontPlan.packages];
|
|
2492
3499
|
const configPath = join6(context.cwd, CONFIG_FILE_NAME);
|
|
2493
3500
|
const configExists = await fileExists(configPath);
|
|
2494
3501
|
let config;
|
|
@@ -2531,8 +3538,11 @@ async function initWithPreset(context, options) {
|
|
|
2531
3538
|
}
|
|
2532
3539
|
const cssAbsolute = resolveInside(context.cwd, cssRelative);
|
|
2533
3540
|
const existingCss = await fileExists(cssAbsolute) ? await readFile5(cssAbsolute, "utf8") : "";
|
|
2534
|
-
const
|
|
3541
|
+
const withTokens = upsertPrimitiveCssBlock(existingCss, primitiveCss);
|
|
3542
|
+
const nextCss = upsertFontImportBlock(withTokens, fontPlan.block);
|
|
2535
3543
|
const cssChanged = nextCss !== existingCss;
|
|
3544
|
+
const installedPackages = readInstalledPackageNames(context.cwd);
|
|
3545
|
+
const unusedFontWarning = installedPackages ? warnUnusedFontPackageMessage(fonts.headingFont, fonts.bodyFont, installedPackages) : void 0;
|
|
2536
3546
|
if (options.dryRun) {
|
|
2537
3547
|
printTitle("Project initialization preview (preset)");
|
|
2538
3548
|
print(action("Would write:"));
|
|
@@ -2541,7 +3551,11 @@ async function initWithPreset(context, options) {
|
|
|
2541
3551
|
print(formatList(planned));
|
|
2542
3552
|
print(action(`Preset: ${presetCode.slice(0, 24)}\u2026`));
|
|
2543
3553
|
print(action(`Style: icon=${style.iconLibrary} radius=${style.radius}`));
|
|
2544
|
-
if (
|
|
3554
|
+
if (fontPlan.packages.length > 0) {
|
|
3555
|
+
print(action(`Fonts: ${fontPlan.packages.join(" ")}`));
|
|
3556
|
+
}
|
|
3557
|
+
if (options.install) print(action(`Would install: ${installDependencies.join(" ")}`));
|
|
3558
|
+
if (unusedFontWarning) warn(unusedFontWarning);
|
|
2545
3559
|
return;
|
|
2546
3560
|
}
|
|
2547
3561
|
const shouldWriteUtility = options.force || !await fileExists(utilityPath);
|
|
@@ -2562,7 +3576,7 @@ async function initWithPreset(context, options) {
|
|
|
2562
3576
|
}
|
|
2563
3577
|
});
|
|
2564
3578
|
if (options.install) {
|
|
2565
|
-
runInstall(context.cwd, missingDependencies(context.cwd,
|
|
3579
|
+
runInstall(context.cwd, missingDependencies(context.cwd, installDependencies));
|
|
2566
3580
|
}
|
|
2567
3581
|
printTitle("Project initialized");
|
|
2568
3582
|
const created = [
|
|
@@ -2576,7 +3590,11 @@ async function initWithPreset(context, options) {
|
|
|
2576
3590
|
} else {
|
|
2577
3591
|
created.push(action(`CSS tokens unchanged: ${toPosixPath(cssRelative)}`));
|
|
2578
3592
|
}
|
|
3593
|
+
if (fontPlan.packages.length > 0) {
|
|
3594
|
+
created.push(success(`fonts: ${fontPlan.packages.join(", ")}`));
|
|
3595
|
+
}
|
|
2579
3596
|
print(panel("Created", created));
|
|
3597
|
+
if (unusedFontWarning) warn(unusedFontWarning);
|
|
2580
3598
|
print(nextSteps([
|
|
2581
3599
|
"Browse available components: npx wensity list",
|
|
2582
3600
|
"Install a primitive: npx wensity add button"
|
|
@@ -2721,9 +3739,11 @@ Usage: wensity ${updateMode ? "update" : "add"} <slug>${resourceType === "block"
|
|
|
2721
3739
|
await assertNoConflicts(plannedInstallFiles, force || dryRun);
|
|
2722
3740
|
const plannedFiles = summarizeFiles(loaded.projectRoot, plannedInstallFiles);
|
|
2723
3741
|
const missing = missingDependencies(loaded.projectRoot, prepared.dependencies);
|
|
2724
|
-
const style =
|
|
3742
|
+
const style = normalizeProjectStyle(loaded.config.style);
|
|
3743
|
+
const fonts = curatedFontsFromStyle(style);
|
|
2725
3744
|
const installedPackages = readInstalledPackageNames(loaded.projectRoot);
|
|
2726
3745
|
const oppositeIconWarning = installedPackages && prepared.iconDependencySwap ? warnOppositeIconPackageMessage(style.iconLibrary, installedPackages) : void 0;
|
|
3746
|
+
const unusedFontWarning = installedPackages ? warnUnusedFontPackageMessage(fonts.headingFont, fonts.bodyFont, installedPackages) : void 0;
|
|
2727
3747
|
if (dryRun) {
|
|
2728
3748
|
printTitle(updateMode ? "Update preview" : "Install preview");
|
|
2729
3749
|
print(action("Would write:"));
|
|
@@ -2733,6 +3753,7 @@ Usage: wensity ${updateMode ? "update" : "add"} <slug>${resourceType === "block"
|
|
|
2733
3753
|
}
|
|
2734
3754
|
if (install && missing.length > 0) print(action(`Would install: ${missing.join(" ")}`));
|
|
2735
3755
|
if (oppositeIconWarning) warn(oppositeIconWarning);
|
|
3756
|
+
if (unusedFontWarning) warn(unusedFontWarning);
|
|
2736
3757
|
return;
|
|
2737
3758
|
}
|
|
2738
3759
|
await writePlannedFiles(plannedInstallFiles);
|
|
@@ -2745,6 +3766,7 @@ Usage: wensity ${updateMode ? "update" : "add"} <slug>${resourceType === "block"
|
|
|
2745
3766
|
...plannedFiles.map((file) => success(file))
|
|
2746
3767
|
]));
|
|
2747
3768
|
if (oppositeIconWarning) warn(oppositeIconWarning);
|
|
3769
|
+
if (unusedFontWarning) warn(unusedFontWarning);
|
|
2748
3770
|
if (!install && missing.length > 0) {
|
|
2749
3771
|
warn(`Dependencies were not installed: ${missing.join(" ")}`);
|
|
2750
3772
|
print(nextSteps([
|