@nice2dev/design-tokens 1.0.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,3880 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ ENHANCED_ACCESSIBILITY: () => ENHANCED_ACCESSIBILITY,
34
+ ENHANCED_FOCUS: () => ENHANCED_FOCUS,
35
+ ENHANCED_TYPOGRAPHY: () => ENHANCED_TYPOGRAPHY,
36
+ HIGH_CONTRAST: () => HIGH_CONTRAST,
37
+ HIGH_CONTRAST_DARK: () => HIGH_CONTRAST_DARK,
38
+ HIGH_VISIBILITY_FOCUS: () => HIGH_VISIBILITY_FOCUS,
39
+ MAXIMUM_ACCESSIBILITY: () => MAXIMUM_ACCESSIBILITY,
40
+ MAXIMUM_READABILITY_TYPOGRAPHY: () => MAXIMUM_READABILITY_TYPOGRAPHY,
41
+ MINIMAL_MOTION: () => MINIMAL_MOTION,
42
+ PRESETS: () => PRESETS,
43
+ REDUCED_MOTION: () => REDUCED_MOTION,
44
+ STANDARD_ACCESSIBILITY: () => STANDARD_ACCESSIBILITY,
45
+ STANDARD_CONTRAST: () => STANDARD_CONTRAST,
46
+ STANDARD_FOCUS: () => STANDARD_FOCUS,
47
+ STANDARD_MOTION: () => STANDARD_MOTION,
48
+ STANDARD_TYPOGRAPHY: () => STANDARD_TYPOGRAPHY,
49
+ TokenGenerator: () => TokenGenerator,
50
+ analyzeColor: () => analyzeColor,
51
+ buildTokenObject: () => buildTokenObject,
52
+ checkCircularReferences: () => checkCircularReferences,
53
+ checkContrast: () => checkContrast,
54
+ createGenerator: () => createGenerator,
55
+ createTheme: () => createTheme,
56
+ createTokenCollection: () => createTokenCollection,
57
+ cubicBezierToCss: () => cubicBezierToCss,
58
+ darkenColor: () => darkenColor,
59
+ defaultOptions: () => defaultOptions,
60
+ defaultThemes: () => defaultThemes,
61
+ durationToMs: () => durationToMs,
62
+ extractReferencePath: () => extractReferencePath,
63
+ filterTokensByPath: () => filterTokensByPath,
64
+ filterTokensByType: () => filterTokensByType,
65
+ findReferences: () => findReferences,
66
+ flattenTokens: () => flattenTokens,
67
+ fontWeightToNumber: () => fontWeightToNumber,
68
+ generateAccessibilityCss: () => generateAccessibilityCss,
69
+ generateBrandKit: () => generateBrandKit,
70
+ generateColorScale: () => generateColorScale2,
71
+ generateColorScaleAsync: () => generateColorScale,
72
+ generateCompleteStylesheet: () => generateCompleteStylesheet,
73
+ generateComponentStyles: () => generateComponentStyles,
74
+ generateDarkModeTokens: () => generateDarkModeTokens,
75
+ generateFocusCss: () => generateFocusCss,
76
+ generateHighContrastCss: () => generateHighContrastCss,
77
+ generateHighContrastTokens: () => generateHighContrastTokens,
78
+ generateReactThemeContext: () => generateReactThemeContext,
79
+ generateReducedMotionCss: () => generateReducedMotionCss,
80
+ generateThemeSwitcher: () => generateThemeSwitcher,
81
+ generateThemesCss: () => generateThemesCss,
82
+ generateTokenTypes: () => generateTokenTypes,
83
+ generateTokens: () => generateTokens,
84
+ getAccessibleTextColor: () => getAccessibleTextColor,
85
+ getAllCategories: () => getAllCategories,
86
+ getCategories: () => getCategories,
87
+ getContrastRatio: () => getContrastRatio2,
88
+ getContrastRatioAsync: () => getContrastRatio,
89
+ getDependencyGraph: () => getDependencyGraph,
90
+ getPresetByName: () => getPresetByName,
91
+ getPresetsByCategory: () => getPresetsByCategory,
92
+ getTokenByPath: () => getTokenByPath,
93
+ hexToHsl: () => hexToHsl,
94
+ hexToOklch: () => hexToOklch,
95
+ hexToRgb: () => hexToRgb,
96
+ industryBrandKit: () => industryBrandKit,
97
+ isDesignToken: () => isDesignToken,
98
+ isReference: () => isReference,
99
+ isTokenGroup: () => isTokenGroup,
100
+ lightenColor: () => lightenColor,
101
+ mergeTokenFiles: () => mergeTokenFiles,
102
+ parseTokenDirectory: () => parseTokenDirectory,
103
+ parseTokenFile: () => parseTokenFile,
104
+ parseTokenFiles: () => parseTokenFiles,
105
+ pathToCssVariable: () => pathToCssVariable,
106
+ pathToString: () => pathToString,
107
+ presetToCss: () => presetToCss,
108
+ presetToCssVariables: () => presetToCssVariables,
109
+ presetToTokens: () => presetToTokens,
110
+ pxToEm: () => pxToEm,
111
+ pxToRem: () => pxToRem,
112
+ quickBrandKit: () => quickBrandKit,
113
+ remToPx: () => remToPx,
114
+ resolveToVariable: () => resolveToVariable,
115
+ resolveTokenValue: () => resolveTokenValue,
116
+ resolveTokens: () => resolveTokens,
117
+ sortTokensByDependencies: () => sortTokensByDependencies,
118
+ suggestAccessibleColor: () => suggestAccessibleColor,
119
+ tokensToCssVariables: () => tokensToCssVariables,
120
+ transformToCss: () => transformToCss,
121
+ transformToJs: () => transformToJs,
122
+ transformToScss: () => transformToScss,
123
+ transformToTailwind: () => transformToTailwind,
124
+ transformToTs: () => transformToTs
125
+ });
126
+ module.exports = __toCommonJS(index_exports);
127
+
128
+ // src/parser.ts
129
+ var fs = __toESM(require("fs"), 1);
130
+ var path = __toESM(require("path"), 1);
131
+ function isDesignToken(obj) {
132
+ return typeof obj === "object" && obj !== null && "$value" in obj && obj.$value !== void 0;
133
+ }
134
+ function isTokenGroup(obj) {
135
+ if (typeof obj !== "object" || obj === null) {
136
+ return false;
137
+ }
138
+ if (isDesignToken(obj)) {
139
+ return false;
140
+ }
141
+ return Object.keys(obj).some((key) => !key.startsWith("$"));
142
+ }
143
+ function isReference(value) {
144
+ if (typeof value !== "string") {
145
+ return false;
146
+ }
147
+ return /^\{[\w.]+\}$/.test(value);
148
+ }
149
+ function extractReferencePath(ref) {
150
+ const match = ref.match(/^\{([\w.]+)\}$/);
151
+ if (!match) {
152
+ throw new Error(`Invalid reference: ${ref}`);
153
+ }
154
+ return match[1].split(".");
155
+ }
156
+ function pathToCssVariable(path3, prefix = "nice") {
157
+ return `--${prefix}-${path3.join("-")}`;
158
+ }
159
+ function pathToString(path3) {
160
+ return path3.join(".");
161
+ }
162
+ function parseTokenFile(filePath) {
163
+ const content = fs.readFileSync(filePath, "utf-8");
164
+ const parsed = JSON.parse(content);
165
+ return parsed;
166
+ }
167
+ function parseTokenFiles(filePaths) {
168
+ const merged = {};
169
+ for (const filePath of filePaths) {
170
+ const tokens = parseTokenFile(filePath);
171
+ mergeTokenFiles(merged, tokens);
172
+ }
173
+ return merged;
174
+ }
175
+ function mergeTokenFiles(target, source) {
176
+ for (const [key, value] of Object.entries(source)) {
177
+ if (key.startsWith("$")) {
178
+ if (!(key in target)) {
179
+ target[key] = value;
180
+ }
181
+ } else if (typeof value === "object" && value !== null) {
182
+ if (!(key in target)) {
183
+ target[key] = {};
184
+ }
185
+ const targetValue = target[key];
186
+ if (typeof targetValue === "object" && targetValue !== null) {
187
+ mergeTokenFiles(targetValue, value);
188
+ }
189
+ } else {
190
+ target[key] = value;
191
+ }
192
+ }
193
+ }
194
+ function flattenTokens(tokenFile, prefix = [], inheritedType) {
195
+ const tokens = [];
196
+ const currentType = tokenFile.$type ?? inheritedType;
197
+ for (const [key, value] of Object.entries(tokenFile)) {
198
+ if (key.startsWith("$")) {
199
+ continue;
200
+ }
201
+ const currentPath = [...prefix, key];
202
+ if (isDesignToken(value)) {
203
+ const token = value;
204
+ const tokenType = token.$type ?? currentType;
205
+ const references = [];
206
+ findReferences(token.$value, references);
207
+ tokens.push({
208
+ path: currentPath,
209
+ name: key,
210
+ value: token.$value,
211
+ resolvedValue: "",
212
+ // Will be populated by resolver
213
+ type: tokenType,
214
+ description: token.$description,
215
+ cssVariable: pathToCssVariable(currentPath),
216
+ references: references.length > 0 ? references : void 0
217
+ });
218
+ } else if (isTokenGroup(value)) {
219
+ const group = value;
220
+ const groupType = group.$type ?? currentType;
221
+ tokens.push(...flattenTokens(group, currentPath, groupType));
222
+ }
223
+ }
224
+ return tokens;
225
+ }
226
+ function findReferences(value, refs) {
227
+ if (typeof value === "string" && isReference(value)) {
228
+ refs.push(extractReferencePath(value).join("."));
229
+ } else if (typeof value === "object" && value !== null) {
230
+ if (Array.isArray(value)) {
231
+ for (const item of value) {
232
+ findReferences(item, refs);
233
+ }
234
+ } else {
235
+ for (const v of Object.values(value)) {
236
+ findReferences(v, refs);
237
+ }
238
+ }
239
+ }
240
+ }
241
+ function createTokenCollection(tokens) {
242
+ const byPath = /* @__PURE__ */ new Map();
243
+ const byName = /* @__PURE__ */ new Map();
244
+ for (const token of tokens) {
245
+ const pathStr = pathToString(token.path);
246
+ byPath.set(pathStr, token);
247
+ const existing = byName.get(token.name);
248
+ if (!existing || token.path.length > existing.path.length) {
249
+ byName.set(token.name, token);
250
+ }
251
+ }
252
+ return { tokens, byPath, byName };
253
+ }
254
+ function parseTokenDirectory(dirPath, pattern = "*.json") {
255
+ const glob = require("fast-glob");
256
+ const files = glob.sync(path.join(dirPath, pattern));
257
+ const tokenFile = parseTokenFiles(files);
258
+ const flatTokens = flattenTokens(tokenFile);
259
+ return createTokenCollection(flatTokens);
260
+ }
261
+ function getTokenByPath(collection, path3) {
262
+ const pathStr = Array.isArray(path3) ? pathToString(path3) : path3;
263
+ return collection.byPath.get(pathStr);
264
+ }
265
+ function filterTokensByType(collection, type) {
266
+ return collection.tokens.filter((token) => token.type === type);
267
+ }
268
+ function filterTokensByPath(collection, prefix) {
269
+ return collection.tokens.filter((token) => pathToString(token.path).startsWith(prefix));
270
+ }
271
+ function getCategories(collection) {
272
+ const categories = /* @__PURE__ */ new Set();
273
+ for (const token of collection.tokens) {
274
+ if (token.path.length > 0) {
275
+ categories.add(token.path[0]);
276
+ }
277
+ }
278
+ return Array.from(categories);
279
+ }
280
+
281
+ // src/generator.ts
282
+ var fs2 = __toESM(require("fs"), 1);
283
+ var path2 = __toESM(require("path"), 1);
284
+
285
+ // src/resolver.ts
286
+ var MAX_RESOLUTION_DEPTH = 10;
287
+ function resolveTokens(collection) {
288
+ const resolvedTokens = collection.tokens.map((token) => {
289
+ const resolved = { ...token };
290
+ resolved.resolvedValue = resolveTokenValue(token.value, collection, 0);
291
+ return resolved;
292
+ });
293
+ return {
294
+ tokens: resolvedTokens,
295
+ byPath: new Map(resolvedTokens.map((t) => [pathToString(t.path), t])),
296
+ byName: new Map(resolvedTokens.map((t) => [t.name, t]))
297
+ };
298
+ }
299
+ function resolveTokenValue(value, collection, depth) {
300
+ if (depth > MAX_RESOLUTION_DEPTH) {
301
+ throw new Error(`Maximum reference depth exceeded while resolving token`);
302
+ }
303
+ if (typeof value === "string") {
304
+ if (isReference(value)) {
305
+ const refPath = extractReferencePath(value);
306
+ const refPathStr = pathToString(refPath);
307
+ const refToken = collection.byPath.get(refPathStr);
308
+ if (!refToken) {
309
+ console.warn(`Reference not found: ${value}`);
310
+ return value;
311
+ }
312
+ return resolveTokenValue(refToken.value, collection, depth + 1);
313
+ }
314
+ return value;
315
+ }
316
+ if (typeof value === "number") {
317
+ return String(value);
318
+ }
319
+ if (Array.isArray(value)) {
320
+ return value.map((v) => {
321
+ if (typeof v === "string") {
322
+ return v.includes(" ") ? `"${v}"` : v;
323
+ }
324
+ return String(v);
325
+ }).join(", ");
326
+ }
327
+ if (isShadowValue(value)) {
328
+ return resolveShadowValue(value, collection, depth);
329
+ }
330
+ if (Array.isArray(value) && value.length > 0 && isShadowValue(value[0])) {
331
+ return value.map((s) => resolveShadowValue(s, collection, depth)).join(", ");
332
+ }
333
+ if (isTypographyValue(value)) {
334
+ return resolveTypographyValue(value, collection, depth);
335
+ }
336
+ if (isBorderValue(value)) {
337
+ return resolveBorderValue(value, collection, depth);
338
+ }
339
+ return JSON.stringify(value);
340
+ }
341
+ function isShadowValue(value) {
342
+ if (typeof value !== "object" || value === null) {
343
+ return false;
344
+ }
345
+ return "offsetX" in value && "offsetY" in value && "blur" in value;
346
+ }
347
+ function resolveShadowValue(shadow, collection, depth) {
348
+ const offsetX = resolveTokenValue(shadow.offsetX, collection, depth);
349
+ const offsetY = resolveTokenValue(shadow.offsetY, collection, depth);
350
+ const blur = resolveTokenValue(shadow.blur, collection, depth);
351
+ const spread = resolveTokenValue(shadow.spread, collection, depth);
352
+ const color = resolveTokenValue(shadow.color, collection, depth);
353
+ const inset = shadow.inset ? "inset " : "";
354
+ return `${inset}${offsetX} ${offsetY} ${blur} ${spread} ${color}`;
355
+ }
356
+ function isTypographyValue(value) {
357
+ if (typeof value !== "object" || value === null) {
358
+ return false;
359
+ }
360
+ return "fontFamily" in value && "fontSize" in value;
361
+ }
362
+ function resolveTypographyValue(typography, collection, depth) {
363
+ const fontFamily = resolveTokenValue(typography.fontFamily, collection, depth);
364
+ const fontSize = resolveTokenValue(typography.fontSize, collection, depth);
365
+ const fontWeight = resolveTokenValue(typography.fontWeight, collection, depth);
366
+ const lineHeight = typography.lineHeight ? resolveTokenValue(typography.lineHeight, collection, depth) : "normal";
367
+ const fontStyle = typography.fontStyle || "normal";
368
+ return `${fontStyle} ${fontWeight} ${fontSize}/${lineHeight} ${fontFamily}`;
369
+ }
370
+ function isBorderValue(value) {
371
+ if (typeof value !== "object" || value === null) {
372
+ return false;
373
+ }
374
+ return "color" in value && "width" in value && "style" in value;
375
+ }
376
+ function resolveBorderValue(border, collection, depth) {
377
+ const width = resolveTokenValue(border.width, collection, depth);
378
+ const style = resolveTokenValue(border.style, collection, depth);
379
+ const color = resolveTokenValue(border.color, collection, depth);
380
+ return `${width} ${style} ${color}`;
381
+ }
382
+ function resolveToVariable(value, collection, _prefix = "nice") {
383
+ if (typeof value === "string" && isReference(value)) {
384
+ const refPath = extractReferencePath(value);
385
+ const refPathStr = pathToString(refPath);
386
+ const refToken = collection.byPath.get(refPathStr);
387
+ if (refToken) {
388
+ return `var(${refToken.cssVariable})`;
389
+ }
390
+ }
391
+ return resolveTokenValue(value, collection, 0);
392
+ }
393
+ function getDependencyGraph(collection) {
394
+ const graph = /* @__PURE__ */ new Map();
395
+ for (const token of collection.tokens) {
396
+ const pathStr = pathToString(token.path);
397
+ const deps = /* @__PURE__ */ new Set();
398
+ if (token.references) {
399
+ for (const ref of token.references) {
400
+ deps.add(ref);
401
+ }
402
+ }
403
+ graph.set(pathStr, deps);
404
+ }
405
+ return graph;
406
+ }
407
+ function sortTokensByDependencies(collection) {
408
+ const graph = getDependencyGraph(collection);
409
+ const visited = /* @__PURE__ */ new Set();
410
+ const sorted = [];
411
+ function visit(pathStr) {
412
+ if (visited.has(pathStr)) {
413
+ return;
414
+ }
415
+ visited.add(pathStr);
416
+ const deps = graph.get(pathStr);
417
+ if (deps) {
418
+ for (const dep of deps) {
419
+ visit(dep);
420
+ }
421
+ }
422
+ const token = collection.byPath.get(pathStr);
423
+ if (token) {
424
+ sorted.push(token);
425
+ }
426
+ }
427
+ for (const token of collection.tokens) {
428
+ visit(pathToString(token.path));
429
+ }
430
+ return sorted;
431
+ }
432
+ function checkCircularReferences(collection) {
433
+ const graph = getDependencyGraph(collection);
434
+ const circles = [];
435
+ const visiting = /* @__PURE__ */ new Set();
436
+ const visited = /* @__PURE__ */ new Set();
437
+ function visit(pathStr, path3) {
438
+ if (visited.has(pathStr)) {
439
+ return false;
440
+ }
441
+ if (visiting.has(pathStr)) {
442
+ const circleStart = path3.indexOf(pathStr);
443
+ circles.push(path3.slice(circleStart));
444
+ return true;
445
+ }
446
+ visiting.add(pathStr);
447
+ path3.push(pathStr);
448
+ const deps = graph.get(pathStr);
449
+ if (deps) {
450
+ for (const dep of deps) {
451
+ if (visit(dep, [...path3])) {
452
+ return true;
453
+ }
454
+ }
455
+ }
456
+ visiting.delete(pathStr);
457
+ visited.add(pathStr);
458
+ return false;
459
+ }
460
+ for (const token of collection.tokens) {
461
+ const pathStr = pathToString(token.path);
462
+ if (!visited.has(pathStr)) {
463
+ visit(pathStr, []);
464
+ }
465
+ }
466
+ return circles;
467
+ }
468
+
469
+ // src/transforms.ts
470
+ var chroma = null;
471
+ async function getChroma() {
472
+ if (!chroma) {
473
+ chroma = (await import("chroma-js")).default;
474
+ }
475
+ return chroma;
476
+ }
477
+ async function hexToRgb(hex) {
478
+ const c = await getChroma();
479
+ const [r, g, b] = c(hex).rgb();
480
+ return `rgb(${r}, ${g}, ${b})`;
481
+ }
482
+ async function hexToHsl(hex) {
483
+ const c = await getChroma();
484
+ const [h, s, l] = c(hex).hsl();
485
+ return `hsl(${Math.round(h)}deg ${Math.round(s * 100)}% ${Math.round(l * 100)}%)`;
486
+ }
487
+ async function hexToOklch(hex) {
488
+ const c = await getChroma();
489
+ const [l, a, b] = c(hex).lab();
490
+ const L = l / 100;
491
+ const C = Math.sqrt(a * a + b * b) / 125;
492
+ const H = Math.atan2(b, a) * 180 / Math.PI;
493
+ return `oklch(${(L * 100).toFixed(1)}% ${C.toFixed(3)} ${H < 0 ? H + 360 : H}deg)`;
494
+ }
495
+ async function lightenColor(hex, amount) {
496
+ const c = await getChroma();
497
+ return c(hex).brighten(amount).hex();
498
+ }
499
+ async function darkenColor(hex, amount) {
500
+ const c = await getChroma();
501
+ return c(hex).darken(amount).hex();
502
+ }
503
+ async function getContrastRatio(fg, bg) {
504
+ const c = await getChroma();
505
+ return c.contrast(fg, bg);
506
+ }
507
+ async function getAccessibleTextColor(bgColor) {
508
+ const c = await getChroma();
509
+ const contrastWhite = c.contrast(bgColor, "white");
510
+ const contrastBlack = c.contrast(bgColor, "black");
511
+ return contrastWhite > contrastBlack ? "#ffffff" : "#000000";
512
+ }
513
+ async function generateColorScale(baseColor, steps = 10) {
514
+ const c = await getChroma();
515
+ const scale = {};
516
+ const labels = ["50", "100", "200", "300", "400", "500", "600", "700", "800", "900", "950"];
517
+ const colors = c.scale(["white", baseColor, "black"]).mode("lab").colors(steps + 2);
518
+ for (let i = 0; i < Math.min(labels.length, colors.length - 1); i++) {
519
+ const index = Math.floor(i / (labels.length - 1) * (colors.length - 1));
520
+ scale[labels[i]] = colors[index];
521
+ }
522
+ return scale;
523
+ }
524
+ function pxToRem(px, baseFontSize = 16) {
525
+ const value = typeof px === "string" ? parseFloat(px) : px;
526
+ return `${value / baseFontSize}rem`;
527
+ }
528
+ function remToPx(rem, baseFontSize = 16) {
529
+ const value = typeof rem === "string" ? parseFloat(rem) : rem;
530
+ return `${value * baseFontSize}px`;
531
+ }
532
+ function pxToEm(px, context = 16) {
533
+ const value = typeof px === "string" ? parseFloat(px) : px;
534
+ return `${value / context}em`;
535
+ }
536
+ function fontWeightToNumber(weight) {
537
+ const weights = {
538
+ thin: 100,
539
+ hairline: 100,
540
+ extralight: 200,
541
+ ultralight: 200,
542
+ light: 300,
543
+ normal: 400,
544
+ regular: 400,
545
+ medium: 500,
546
+ semibold: 600,
547
+ demibold: 600,
548
+ bold: 700,
549
+ extrabold: 800,
550
+ ultrabold: 800,
551
+ black: 900,
552
+ heavy: 900
553
+ };
554
+ return (weights[weight.toLowerCase()] ?? parseInt(weight, 10)) || 400;
555
+ }
556
+ function cubicBezierToCss(values) {
557
+ if (values.length !== 4) {
558
+ throw new Error("Cubic bezier must have exactly 4 values");
559
+ }
560
+ return `cubic-bezier(${values.join(", ")})`;
561
+ }
562
+ function durationToMs(duration) {
563
+ if (duration.endsWith("ms")) {
564
+ return parseFloat(duration);
565
+ }
566
+ if (duration.endsWith("s")) {
567
+ return parseFloat(duration) * 1e3;
568
+ }
569
+ return parseFloat(duration);
570
+ }
571
+ function transformToCss(collection, prefix = "nice") {
572
+ const lines = [];
573
+ for (const token of collection.tokens) {
574
+ const varName = `--${prefix}-${token.path.join("-")}`;
575
+ lines.push(` ${varName}: ${token.resolvedValue};`);
576
+ }
577
+ return `:root {
578
+ ${lines.join("\n")}
579
+ }`;
580
+ }
581
+ function transformToScss(collection, prefix = "nice") {
582
+ const lines = [];
583
+ for (const token of collection.tokens) {
584
+ const varName = `$${prefix}-${token.path.join("-")}`;
585
+ lines.push(`${varName}: ${token.resolvedValue};`);
586
+ }
587
+ return lines.join("\n");
588
+ }
589
+ function transformToJs(collection, variableName = "tokens") {
590
+ const obj = buildTokenObject(collection);
591
+ return `export const ${variableName} = ${JSON.stringify(obj, null, 2)};`;
592
+ }
593
+ function transformToTs(collection, variableName = "tokens") {
594
+ const obj = buildTokenObject(collection);
595
+ const types = generateTokenTypes(collection);
596
+ return `${types}
597
+
598
+ export const ${variableName}: Tokens = ${JSON.stringify(obj, null, 2)};`;
599
+ }
600
+ function buildTokenObject(collection) {
601
+ const result = {};
602
+ for (const token of collection.tokens) {
603
+ let current = result;
604
+ for (let i = 0; i < token.path.length - 1; i++) {
605
+ const key = token.path[i];
606
+ if (!(key in current)) {
607
+ current[key] = {};
608
+ }
609
+ current = current[key];
610
+ }
611
+ const lastKey = token.path[token.path.length - 1];
612
+ current[lastKey] = token.resolvedValue;
613
+ }
614
+ return result;
615
+ }
616
+ function generateTokenTypes(collection) {
617
+ const typeObj = buildTypeStructure(collection);
618
+ return `interface Tokens ${formatTypeStructure(typeObj)}`;
619
+ }
620
+ function buildTypeStructure(collection) {
621
+ const result = {};
622
+ for (const token of collection.tokens) {
623
+ let current = result;
624
+ for (let i = 0; i < token.path.length - 1; i++) {
625
+ const key = token.path[i];
626
+ if (!(key in current)) {
627
+ current[key] = {};
628
+ }
629
+ current = current[key];
630
+ }
631
+ const lastKey = token.path[token.path.length - 1];
632
+ current[lastKey] = "string";
633
+ }
634
+ return result;
635
+ }
636
+ function formatTypeStructure(obj, indent = 0) {
637
+ const spaces = " ".repeat(indent);
638
+ const lines = ["{"];
639
+ for (const [key, value] of Object.entries(obj)) {
640
+ const safeKey = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key) ? key : `'${key}'`;
641
+ if (typeof value === "string") {
642
+ lines.push(`${spaces} ${safeKey}: ${value};`);
643
+ } else {
644
+ lines.push(
645
+ `${spaces} ${safeKey}: ${formatTypeStructure(value, indent + 1)};`
646
+ );
647
+ }
648
+ }
649
+ lines.push(`${spaces}}`);
650
+ return lines.join("\n");
651
+ }
652
+ function transformToTailwind(collection) {
653
+ const colors = {};
654
+ const spacing = {};
655
+ const fontSize = {};
656
+ const fontFamily = {};
657
+ const borderRadius = {};
658
+ const boxShadow = {};
659
+ for (const token of collection.tokens) {
660
+ const path3 = token.path;
661
+ const value = token.resolvedValue;
662
+ if (path3[0] === "color" || path3[0] === "colors") {
663
+ setNestedValue(colors, path3.slice(1), value);
664
+ } else if (path3[0] === "spacing") {
665
+ spacing[path3.slice(1).join("-")] = value;
666
+ } else if (path3[0] === "typography" && path3[1] === "fontSize") {
667
+ fontSize[path3[2]] = value;
668
+ } else if (path3[0] === "typography" && path3[1] === "fontFamily") {
669
+ fontFamily[path3[2]] = value.split(",").map((f) => f.trim());
670
+ } else if (path3[0] === "effects" && path3[1] === "radius") {
671
+ borderRadius[path3[2]] = value;
672
+ } else if (path3[0] === "effects" && path3[1] === "shadow") {
673
+ boxShadow[path3[2]] = value;
674
+ }
675
+ }
676
+ const config = {
677
+ theme: {
678
+ extend: {
679
+ colors,
680
+ spacing,
681
+ fontSize,
682
+ fontFamily,
683
+ borderRadius,
684
+ boxShadow
685
+ }
686
+ }
687
+ };
688
+ return `module.exports = ${JSON.stringify(config, null, 2)};`;
689
+ }
690
+ function setNestedValue(obj, path3, value) {
691
+ let current = obj;
692
+ for (let i = 0; i < path3.length - 1; i++) {
693
+ const key = path3[i];
694
+ if (!(key in current)) {
695
+ current[key] = {};
696
+ }
697
+ current = current[key];
698
+ }
699
+ current[path3[path3.length - 1]] = value;
700
+ }
701
+ function applyThemeOverrides(baseCollection, overrides) {
702
+ const mergedTokens = [...baseCollection.tokens];
703
+ for (const override of overrides.tokens) {
704
+ const pathStr = pathToString(override.path);
705
+ const existingIndex = mergedTokens.findIndex((t) => pathToString(t.path) === pathStr);
706
+ if (existingIndex >= 0) {
707
+ mergedTokens[existingIndex] = { ...mergedTokens[existingIndex], ...override };
708
+ } else {
709
+ mergedTokens.push(override);
710
+ }
711
+ }
712
+ return {
713
+ tokens: mergedTokens,
714
+ byPath: new Map(mergedTokens.map((t) => [pathToString(t.path), t])),
715
+ byName: new Map(mergedTokens.map((t) => [t.name, t]))
716
+ };
717
+ }
718
+
719
+ // src/themes.ts
720
+ var defaultThemes = {
721
+ light: {
722
+ name: "light",
723
+ displayName: "Light",
724
+ mode: "light",
725
+ selector: ':root, [data-theme="light"]'
726
+ },
727
+ dark: {
728
+ name: "dark",
729
+ displayName: "Dark",
730
+ mode: "dark",
731
+ selector: '[data-theme="dark"]',
732
+ mediaQuery: "(prefers-color-scheme: dark)",
733
+ extends: "light"
734
+ },
735
+ "high-contrast": {
736
+ name: "high-contrast",
737
+ displayName: "High Contrast",
738
+ mode: "high-contrast",
739
+ selector: '[data-theme="high-contrast"]',
740
+ mediaQuery: "(prefers-contrast: more)",
741
+ extends: "light"
742
+ },
743
+ "high-contrast-dark": {
744
+ name: "high-contrast-dark",
745
+ displayName: "High Contrast Dark",
746
+ mode: "high-contrast-dark",
747
+ selector: '[data-theme="high-contrast-dark"]',
748
+ extends: "dark"
749
+ },
750
+ dim: {
751
+ name: "dim",
752
+ displayName: "Dim",
753
+ mode: "dim",
754
+ selector: '[data-theme="dim"]',
755
+ extends: "dark"
756
+ }
757
+ };
758
+ function createTheme(name, baseTokens, overrideTokens, config) {
759
+ const tokens = overrideTokens ? applyThemeOverrides(baseTokens, overrideTokens) : baseTokens;
760
+ const resolvedTokens = resolveTokens(tokens);
761
+ const themeConfig = { ...defaultThemes.light, ...config, name };
762
+ return {
763
+ name,
764
+ tokens: resolvedTokens,
765
+ extends: themeConfig.extends,
766
+ selector: themeConfig.selector,
767
+ mediaQuery: themeConfig.mediaQuery
768
+ };
769
+ }
770
+ function generateThemesCss(themes, prefix = "nice") {
771
+ const sections = [];
772
+ for (const theme of themes) {
773
+ const vars = generateThemeVariables(theme, prefix);
774
+ sections.push(`${theme.selector} {
775
+ ${vars}
776
+ }`);
777
+ if (theme.mediaQuery) {
778
+ sections.push(
779
+ `@media ${theme.mediaQuery} {
780
+ :root {
781
+ ${vars.split("\n").map((l) => ` ${l}`).join("\n")}
782
+ }
783
+ }`
784
+ );
785
+ }
786
+ }
787
+ return sections.join("\n\n");
788
+ }
789
+ function generateThemeVariables(theme, prefix) {
790
+ const lines = [];
791
+ for (const token of theme.tokens.tokens) {
792
+ const varName = `--${prefix}-${token.path.join("-")}`;
793
+ lines.push(` ${varName}: ${token.resolvedValue};`);
794
+ }
795
+ return lines.join("\n");
796
+ }
797
+ function generateThemeSwitcher() {
798
+ return `
799
+ /**
800
+ * Nice2Dev Theme Switcher
801
+ * Auto-generated by @nice2dev/design-tokens
802
+ */
803
+
804
+ const THEME_KEY = 'nice-theme';
805
+ const THEMES = ['light', 'dark', 'high-contrast', 'high-contrast-dark', 'dim'];
806
+
807
+ /**
808
+ * Get current theme
809
+ */
810
+ function getTheme() {
811
+ return document.documentElement.getAttribute('data-theme') || 'light';
812
+ }
813
+
814
+ /**
815
+ * Set theme
816
+ */
817
+ function setTheme(theme) {
818
+ if (!THEMES.includes(theme)) {
819
+ console.warn(\`Invalid theme: \${theme}\`);
820
+ return;
821
+ }
822
+
823
+ document.documentElement.setAttribute('data-theme', theme);
824
+ localStorage.setItem(THEME_KEY, theme);
825
+
826
+ // Dispatch event
827
+ window.dispatchEvent(new CustomEvent('nice-theme-change', { detail: { theme } }));
828
+ }
829
+
830
+ /**
831
+ * Toggle between light and dark
832
+ */
833
+ function toggleTheme() {
834
+ const current = getTheme();
835
+ const next = current === 'dark' ? 'light' : 'dark';
836
+ setTheme(next);
837
+ return next;
838
+ }
839
+
840
+ /**
841
+ * Use system preference
842
+ */
843
+ function useSystemTheme() {
844
+ const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
845
+ const prefersHighContrast = window.matchMedia('(prefers-contrast: more)').matches;
846
+
847
+ let theme = 'light';
848
+ if (prefersDark && prefersHighContrast) {
849
+ theme = 'high-contrast-dark';
850
+ } else if (prefersDark) {
851
+ theme = 'dark';
852
+ } else if (prefersHighContrast) {
853
+ theme = 'high-contrast';
854
+ }
855
+
856
+ setTheme(theme);
857
+ return theme;
858
+ }
859
+
860
+ /**
861
+ * Initialize theme on page load
862
+ */
863
+ function initTheme() {
864
+ const saved = localStorage.getItem(THEME_KEY);
865
+
866
+ if (saved && THEMES.includes(saved)) {
867
+ setTheme(saved);
868
+ } else {
869
+ useSystemTheme();
870
+ }
871
+
872
+ // Listen for system changes
873
+ window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
874
+ if (!localStorage.getItem(THEME_KEY)) {
875
+ useSystemTheme();
876
+ }
877
+ });
878
+ }
879
+
880
+ // Auto-init
881
+ if (typeof document !== 'undefined') {
882
+ if (document.readyState === 'loading') {
883
+ document.addEventListener('DOMContentLoaded', initTheme);
884
+ } else {
885
+ initTheme();
886
+ }
887
+ }
888
+
889
+ export { getTheme, setTheme, toggleTheme, useSystemTheme, initTheme, THEMES };
890
+ `.trim();
891
+ }
892
+ function generateReactThemeContext() {
893
+ return `
894
+ 'use client';
895
+
896
+ import React, { createContext, useContext, useEffect, useState, useCallback } from 'react';
897
+
898
+ type Theme = 'light' | 'dark' | 'high-contrast' | 'high-contrast-dark' | 'dim';
899
+
900
+ interface ThemeContextValue {
901
+ theme: Theme;
902
+ setTheme: (theme: Theme) => void;
903
+ toggleTheme: () => void;
904
+ useSystemTheme: () => void;
905
+ }
906
+
907
+ const ThemeContext = createContext<ThemeContextValue | undefined>(undefined);
908
+
909
+ const THEME_KEY = 'nice-theme';
910
+ const THEMES: Theme[] = ['light', 'dark', 'high-contrast', 'high-contrast-dark', 'dim'];
911
+
912
+ interface ThemeProviderProps {
913
+ children: React.ReactNode;
914
+ defaultTheme?: Theme;
915
+ }
916
+
917
+ export function ThemeProvider({ children, defaultTheme = 'light' }: ThemeProviderProps) {
918
+ const [theme, setThemeState] = useState<Theme>(defaultTheme);
919
+
920
+ useEffect(() => {
921
+ const saved = localStorage.getItem(THEME_KEY) as Theme | null;
922
+ if (saved && THEMES.includes(saved)) {
923
+ setThemeState(saved);
924
+ document.documentElement.setAttribute('data-theme', saved);
925
+ } else {
926
+ const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
927
+ const initial = prefersDark ? 'dark' : 'light';
928
+ setThemeState(initial);
929
+ document.documentElement.setAttribute('data-theme', initial);
930
+ }
931
+ }, []);
932
+
933
+ const setTheme = useCallback((newTheme: Theme) => {
934
+ setThemeState(newTheme);
935
+ document.documentElement.setAttribute('data-theme', newTheme);
936
+ localStorage.setItem(THEME_KEY, newTheme);
937
+ }, []);
938
+
939
+ const toggleTheme = useCallback(() => {
940
+ setTheme(theme === 'dark' ? 'light' : 'dark');
941
+ }, [theme, setTheme]);
942
+
943
+ const useSystemTheme = useCallback(() => {
944
+ const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
945
+ const prefersHighContrast = window.matchMedia('(prefers-contrast: more)').matches;
946
+
947
+ let systemTheme: Theme = 'light';
948
+ if (prefersDark && prefersHighContrast) {
949
+ systemTheme = 'high-contrast-dark';
950
+ } else if (prefersDark) {
951
+ systemTheme = 'dark';
952
+ } else if (prefersHighContrast) {
953
+ systemTheme = 'high-contrast';
954
+ }
955
+
956
+ setTheme(systemTheme);
957
+ localStorage.removeItem(THEME_KEY);
958
+ }, [setTheme]);
959
+
960
+ return (
961
+ <ThemeContext.Provider value={{ theme, setTheme, toggleTheme, useSystemTheme }}>
962
+ {children}
963
+ </ThemeContext.Provider>
964
+ );
965
+ }
966
+
967
+ export function useTheme(): ThemeContextValue {
968
+ const context = useContext(ThemeContext);
969
+ if (!context) {
970
+ throw new Error('useTheme must be used within a ThemeProvider');
971
+ }
972
+ return context;
973
+ }
974
+
975
+ export { THEMES };
976
+ export type { Theme };
977
+ `.trim();
978
+ }
979
+ async function generateDarkModeTokens(lightTokens) {
980
+ const darkTokens = [];
981
+ const chroma2 = (await import("chroma-js")).default;
982
+ for (const token of lightTokens.tokens) {
983
+ if (token.type !== "color" || !token.path.includes("semantic")) {
984
+ continue;
985
+ }
986
+ const pathStr = pathToString(token.path);
987
+ if (pathStr.includes("dark")) {
988
+ continue;
989
+ }
990
+ try {
991
+ const color = chroma2(token.resolvedValue);
992
+ let darkValue;
993
+ if (token.name.includes("background") || token.name.includes("bg")) {
994
+ const [h, s, l] = color.hsl();
995
+ darkValue = chroma2.hsl(h, s, 1 - l).hex();
996
+ } else if (token.name.includes("text") || token.name.includes("foreground")) {
997
+ const [h, s, l] = color.hsl();
998
+ darkValue = chroma2.hsl(h, s, 1 - l).hex();
999
+ } else if (token.name.includes("border")) {
1000
+ darkValue = color.brighten(0.5).hex();
1001
+ } else {
1002
+ const [h, s, l] = color.hsl();
1003
+ darkValue = chroma2.hsl(h, Math.min(s * 1.1, 1), Math.min(l * 1.2, 0.9)).hex();
1004
+ }
1005
+ darkTokens.push({
1006
+ ...token,
1007
+ value: darkValue,
1008
+ resolvedValue: darkValue
1009
+ });
1010
+ } catch {
1011
+ }
1012
+ }
1013
+ return darkTokens;
1014
+ }
1015
+ async function generateHighContrastTokens(baseTokens, _minContrast = 7) {
1016
+ const contrastTokens = [];
1017
+ const chroma2 = (await import("chroma-js")).default;
1018
+ for (const token of baseTokens.tokens) {
1019
+ if (token.type !== "color") {
1020
+ continue;
1021
+ }
1022
+ try {
1023
+ const color = chroma2(token.resolvedValue);
1024
+ const [, s, l] = color.hsl();
1025
+ let newL = l;
1026
+ if (l > 0.5) {
1027
+ newL = Math.min(l * 1.2, 1);
1028
+ } else {
1029
+ newL = Math.max(l * 0.8, 0);
1030
+ }
1031
+ const newS = Math.min(s * 1.3, 1);
1032
+ const newColor = chroma2.hsl(color.get("hsl.h"), newS, newL);
1033
+ contrastTokens.push({
1034
+ ...token,
1035
+ value: newColor.hex(),
1036
+ resolvedValue: newColor.hex()
1037
+ });
1038
+ } catch {
1039
+ }
1040
+ }
1041
+ return contrastTokens;
1042
+ }
1043
+
1044
+ // src/generator.ts
1045
+ var defaultOptions = {
1046
+ formats: ["css"],
1047
+ outputDir: "./dist",
1048
+ prefix: "nice",
1049
+ includePrimitives: true,
1050
+ separateFiles: false,
1051
+ includeDarkMode: true,
1052
+ includeComponents: true
1053
+ };
1054
+ var TokenGenerator = class {
1055
+ constructor(options = {}) {
1056
+ this.plugins = [];
1057
+ this.collection = null;
1058
+ this.themes = [];
1059
+ this.options = { ...defaultOptions, ...options };
1060
+ }
1061
+ /**
1062
+ * Add plugin
1063
+ */
1064
+ use(plugin) {
1065
+ this.plugins.push(plugin);
1066
+ return this;
1067
+ }
1068
+ /**
1069
+ * Load tokens from files
1070
+ */
1071
+ load(files) {
1072
+ const tokenFile = parseTokenFiles(files);
1073
+ let processedTokens = [tokenFile];
1074
+ for (const plugin of this.plugins) {
1075
+ if (plugin.beforeResolve) {
1076
+ processedTokens = plugin.beforeResolve(processedTokens);
1077
+ }
1078
+ }
1079
+ const flatTokens = flattenTokens(processedTokens[0]);
1080
+ let collection = createTokenCollection(flatTokens);
1081
+ collection = resolveTokens(collection);
1082
+ for (const plugin of this.plugins) {
1083
+ if (plugin.afterResolve) {
1084
+ collection = plugin.afterResolve(collection);
1085
+ }
1086
+ }
1087
+ this.collection = collection;
1088
+ return this;
1089
+ }
1090
+ /**
1091
+ * Load tokens from directory
1092
+ */
1093
+ loadDirectory(dir, pattern = "**/*.json") {
1094
+ const glob = require("fast-glob");
1095
+ const files = glob.sync(path2.join(dir, pattern));
1096
+ return this.load(files);
1097
+ }
1098
+ /**
1099
+ * Add theme
1100
+ */
1101
+ addTheme(name, overrideTokens) {
1102
+ if (!this.collection) {
1103
+ throw new Error("Load tokens first before adding themes");
1104
+ }
1105
+ const theme = createTheme(name, this.collection, overrideTokens);
1106
+ this.themes.push(theme);
1107
+ return this;
1108
+ }
1109
+ /**
1110
+ * Generate output files
1111
+ */
1112
+ async generate() {
1113
+ if (!this.collection) {
1114
+ throw new Error("No tokens loaded");
1115
+ }
1116
+ fs2.mkdirSync(this.options.outputDir, { recursive: true });
1117
+ for (const format of this.options.formats) {
1118
+ await this.generateFormat(format);
1119
+ }
1120
+ if (this.themes.length > 0) {
1121
+ await this.generateThemeFiles();
1122
+ }
1123
+ }
1124
+ /**
1125
+ * Generate single format
1126
+ */
1127
+ async generateFormat(format) {
1128
+ if (!this.collection) {
1129
+ return;
1130
+ }
1131
+ for (const plugin of this.plugins) {
1132
+ if (plugin.customFormat) {
1133
+ const output = plugin.customFormat(this.collection, this.options);
1134
+ if (output) {
1135
+ const ext = this.getExtension(format);
1136
+ fs2.writeFileSync(
1137
+ path2.join(this.options.outputDir, `tokens.${plugin.name}.${ext}`),
1138
+ output
1139
+ );
1140
+ }
1141
+ }
1142
+ }
1143
+ if (this.options.separateFiles) {
1144
+ await this.generateSeparateFiles(format);
1145
+ } else {
1146
+ await this.generateSingleFile(format);
1147
+ }
1148
+ }
1149
+ /**
1150
+ * Generate single output file
1151
+ */
1152
+ async generateSingleFile(format) {
1153
+ if (!this.collection) {
1154
+ return;
1155
+ }
1156
+ const content = this.transform(this.collection, format);
1157
+ const filename = `tokens.${this.getExtension(format)}`;
1158
+ const filepath = path2.join(this.options.outputDir, filename);
1159
+ fs2.writeFileSync(filepath, content);
1160
+ console.log(`Generated: ${filepath}`);
1161
+ }
1162
+ /**
1163
+ * Generate separate files by category
1164
+ */
1165
+ async generateSeparateFiles(format) {
1166
+ if (!this.collection) {
1167
+ return;
1168
+ }
1169
+ const categories = getCategories(this.collection);
1170
+ const ext = this.getExtension(format);
1171
+ for (const category of categories) {
1172
+ const tokens = this.collection.tokens.filter((t) => t.path[0] === category);
1173
+ const catCollection = {
1174
+ tokens,
1175
+ byPath: new Map(tokens.map((t) => [t.path.join("."), t])),
1176
+ byName: new Map(tokens.map((t) => [t.name, t]))
1177
+ };
1178
+ const content = this.transform(catCollection, format);
1179
+ const filename = `${category}.${ext}`;
1180
+ const filepath = path2.join(this.options.outputDir, filename);
1181
+ fs2.writeFileSync(filepath, content);
1182
+ console.log(`Generated: ${filepath}`);
1183
+ }
1184
+ this.generateIndexFile(categories, format);
1185
+ }
1186
+ /**
1187
+ * Generate index file for separated files
1188
+ */
1189
+ generateIndexFile(categories, format) {
1190
+ const ext = this.getExtension(format);
1191
+ let content = "";
1192
+ switch (format) {
1193
+ case "css":
1194
+ content = categories.map((c) => `@import './${c}.css';`).join("\n");
1195
+ break;
1196
+ case "scss":
1197
+ content = categories.map((c) => `@import './${c}';`).join("\n");
1198
+ break;
1199
+ case "js":
1200
+ case "ts":
1201
+ content = categories.map((c) => `export * from './${c}';`).join("\n");
1202
+ break;
1203
+ default:
1204
+ return;
1205
+ }
1206
+ const filepath = path2.join(this.options.outputDir, `index.${ext}`);
1207
+ fs2.writeFileSync(filepath, content);
1208
+ console.log(`Generated: ${filepath}`);
1209
+ }
1210
+ /**
1211
+ * Transform collection to format
1212
+ */
1213
+ transform(collection, format) {
1214
+ const prefix = this.options.prefix ?? "nice";
1215
+ switch (format) {
1216
+ case "css":
1217
+ return transformToCss(collection, prefix);
1218
+ case "scss":
1219
+ return transformToScss(collection, prefix);
1220
+ case "js":
1221
+ return transformToJs(collection);
1222
+ case "ts":
1223
+ return transformToTs(collection);
1224
+ case "json":
1225
+ return JSON.stringify(this.buildNestedObject(collection), null, 2);
1226
+ case "tailwind":
1227
+ return transformToTailwind(collection);
1228
+ default:
1229
+ throw new Error(`Unsupported format: ${format}`);
1230
+ }
1231
+ }
1232
+ /**
1233
+ * Build nested object from flat tokens
1234
+ */
1235
+ buildNestedObject(collection) {
1236
+ const result = {};
1237
+ for (const token of collection.tokens) {
1238
+ let current = result;
1239
+ for (let i = 0; i < token.path.length - 1; i++) {
1240
+ const key = token.path[i];
1241
+ if (!(key in current)) {
1242
+ current[key] = {};
1243
+ }
1244
+ current = current[key];
1245
+ }
1246
+ current[token.path[token.path.length - 1]] = token.resolvedValue;
1247
+ }
1248
+ return result;
1249
+ }
1250
+ /**
1251
+ * Get file extension for format
1252
+ */
1253
+ getExtension(format) {
1254
+ switch (format) {
1255
+ case "css":
1256
+ return "css";
1257
+ case "scss":
1258
+ return "scss";
1259
+ case "js":
1260
+ return "js";
1261
+ case "ts":
1262
+ return "ts";
1263
+ case "json":
1264
+ return "json";
1265
+ case "tailwind":
1266
+ return "tailwind.js";
1267
+ default:
1268
+ return "txt";
1269
+ }
1270
+ }
1271
+ /**
1272
+ * Generate theme-related files
1273
+ */
1274
+ async generateThemeFiles() {
1275
+ const prefix = this.options.prefix ?? "nice";
1276
+ const themesCss = generateThemesCss(this.themes, prefix);
1277
+ fs2.writeFileSync(path2.join(this.options.outputDir, "themes.css"), themesCss);
1278
+ console.log(`Generated: themes.css`);
1279
+ const switcherJs = generateThemeSwitcher();
1280
+ fs2.writeFileSync(path2.join(this.options.outputDir, "theme-switcher.js"), switcherJs);
1281
+ console.log(`Generated: theme-switcher.js`);
1282
+ const reactContext = generateReactThemeContext();
1283
+ fs2.writeFileSync(path2.join(this.options.outputDir, "ThemeContext.tsx"), reactContext);
1284
+ console.log(`Generated: ThemeContext.tsx`);
1285
+ }
1286
+ /**
1287
+ * Get generated token collection
1288
+ */
1289
+ getCollection() {
1290
+ return this.collection;
1291
+ }
1292
+ /**
1293
+ * Get generated themes
1294
+ */
1295
+ getThemes() {
1296
+ return this.themes;
1297
+ }
1298
+ };
1299
+ function createGenerator(options) {
1300
+ return new TokenGenerator(options);
1301
+ }
1302
+ async function generateTokens(tokenDir, outputDir, options) {
1303
+ const generator = createGenerator({
1304
+ ...options,
1305
+ outputDir
1306
+ });
1307
+ generator.loadDirectory(tokenDir);
1308
+ await generator.generate();
1309
+ }
1310
+
1311
+ // src/presets.ts
1312
+ function generateColorScale2(baseColor) {
1313
+ return {
1314
+ 50: lighten(baseColor, 0.95),
1315
+ 100: lighten(baseColor, 0.9),
1316
+ 200: lighten(baseColor, 0.75),
1317
+ 300: lighten(baseColor, 0.6),
1318
+ 400: lighten(baseColor, 0.3),
1319
+ 500: baseColor,
1320
+ 600: darken(baseColor, 0.1),
1321
+ 700: darken(baseColor, 0.25),
1322
+ 800: darken(baseColor, 0.4),
1323
+ 900: darken(baseColor, 0.55),
1324
+ 950: darken(baseColor, 0.7)
1325
+ };
1326
+ }
1327
+ function hexToHsl2(hex) {
1328
+ const r = parseInt(hex.slice(1, 3), 16) / 255;
1329
+ const g = parseInt(hex.slice(3, 5), 16) / 255;
1330
+ const b = parseInt(hex.slice(5, 7), 16) / 255;
1331
+ const max = Math.max(r, g, b);
1332
+ const min = Math.min(r, g, b);
1333
+ let h = 0;
1334
+ let s = 0;
1335
+ const l = (max + min) / 2;
1336
+ if (max !== min) {
1337
+ const d = max - min;
1338
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
1339
+ switch (max) {
1340
+ case r:
1341
+ h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
1342
+ break;
1343
+ case g:
1344
+ h = ((b - r) / d + 2) / 6;
1345
+ break;
1346
+ case b:
1347
+ h = ((r - g) / d + 4) / 6;
1348
+ break;
1349
+ }
1350
+ }
1351
+ return [h * 360, s * 100, l * 100];
1352
+ }
1353
+ function hslToHex(h, s, l) {
1354
+ h /= 360;
1355
+ s /= 100;
1356
+ l /= 100;
1357
+ const hue2rgb = (p, q, t) => {
1358
+ if (t < 0) {
1359
+ t += 1;
1360
+ }
1361
+ if (t > 1) {
1362
+ t -= 1;
1363
+ }
1364
+ if (t < 1 / 6) {
1365
+ return p + (q - p) * 6 * t;
1366
+ }
1367
+ if (t < 1 / 2) {
1368
+ return q;
1369
+ }
1370
+ if (t < 2 / 3) {
1371
+ return p + (q - p) * (2 / 3 - t) * 6;
1372
+ }
1373
+ return p;
1374
+ };
1375
+ let r, g, b;
1376
+ if (s === 0) {
1377
+ r = g = b = l;
1378
+ } else {
1379
+ const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
1380
+ const p = 2 * l - q;
1381
+ r = hue2rgb(p, q, h + 1 / 3);
1382
+ g = hue2rgb(p, q, h);
1383
+ b = hue2rgb(p, q, h - 1 / 3);
1384
+ }
1385
+ const toHex = (n) => Math.round(n * 255).toString(16).padStart(2, "0");
1386
+ return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
1387
+ }
1388
+ function lighten(hex, amount) {
1389
+ const [h, s, l] = hexToHsl2(hex);
1390
+ return hslToHex(h, s, Math.min(100, l + (100 - l) * amount));
1391
+ }
1392
+ function darken(hex, amount) {
1393
+ const [h, s, l] = hexToHsl2(hex);
1394
+ return hslToHex(h, s, Math.max(0, l * (1 - amount)));
1395
+ }
1396
+ var GRAY_NEUTRAL = {
1397
+ 50: "#f9fafb",
1398
+ 100: "#f3f4f6",
1399
+ 200: "#e5e7eb",
1400
+ 300: "#d1d5db",
1401
+ 400: "#9ca3af",
1402
+ 500: "#6b7280",
1403
+ 600: "#4b5563",
1404
+ 700: "#374151",
1405
+ 800: "#1f2937",
1406
+ 900: "#111827",
1407
+ 950: "#030712"
1408
+ };
1409
+ var SLATE_NEUTRAL = {
1410
+ 50: "#f8fafc",
1411
+ 100: "#f1f5f9",
1412
+ 200: "#e2e8f0",
1413
+ 300: "#cbd5e1",
1414
+ 400: "#94a3b8",
1415
+ 500: "#64748b",
1416
+ 600: "#475569",
1417
+ 700: "#334155",
1418
+ 800: "#1e293b",
1419
+ 900: "#0f172a",
1420
+ 950: "#020617"
1421
+ };
1422
+ var ZINC_NEUTRAL = {
1423
+ 50: "#fafafa",
1424
+ 100: "#f4f4f5",
1425
+ 200: "#e4e4e7",
1426
+ 300: "#d4d4d8",
1427
+ 400: "#a1a1aa",
1428
+ 500: "#71717a",
1429
+ 600: "#52525b",
1430
+ 700: "#3f3f46",
1431
+ 800: "#27272a",
1432
+ 900: "#18181b",
1433
+ 950: "#09090b"
1434
+ };
1435
+ var WARM_NEUTRAL = {
1436
+ 50: "#faf5f0",
1437
+ 100: "#f0e8dd",
1438
+ 200: "#e0d0bb",
1439
+ 300: "#cdb899",
1440
+ 400: "#b89d77",
1441
+ 500: "#9a7f5a",
1442
+ 600: "#7d6548",
1443
+ 700: "#604c37",
1444
+ 800: "#443527",
1445
+ 900: "#2a1f18",
1446
+ 950: "#150f0c"
1447
+ };
1448
+ var PRESETS = [
1449
+ // ─────────────────────────────────────────────────────────────────────────
1450
+ // BRAND COLORS
1451
+ // ─────────────────────────────────────────────────────────────────────────
1452
+ {
1453
+ name: "ocean-blue",
1454
+ displayName: "Ocean Blue",
1455
+ description: "Deep blue tones inspired by the ocean",
1456
+ category: "brand",
1457
+ colors: {
1458
+ primary: generateColorScale2("#0077b6"),
1459
+ secondary: generateColorScale2("#00b4d8"),
1460
+ neutral: SLATE_NEUTRAL,
1461
+ success: "#22c55e",
1462
+ warning: "#f59e0b",
1463
+ error: "#ef4444",
1464
+ info: "#3b82f6"
1465
+ }
1466
+ },
1467
+ {
1468
+ name: "forest-green",
1469
+ displayName: "Forest Green",
1470
+ description: "Natural green tones inspired by forests",
1471
+ category: "brand",
1472
+ colors: {
1473
+ primary: generateColorScale2("#15803d"),
1474
+ secondary: generateColorScale2("#84cc16"),
1475
+ neutral: GRAY_NEUTRAL,
1476
+ success: "#22c55e",
1477
+ warning: "#f59e0b",
1478
+ error: "#ef4444",
1479
+ info: "#3b82f6"
1480
+ }
1481
+ },
1482
+ {
1483
+ name: "sunset-orange",
1484
+ displayName: "Sunset Orange",
1485
+ description: "Warm orange and coral tones",
1486
+ category: "brand",
1487
+ colors: {
1488
+ primary: generateColorScale2("#ea580c"),
1489
+ secondary: generateColorScale2("#facc15"),
1490
+ neutral: WARM_NEUTRAL,
1491
+ success: "#22c55e",
1492
+ warning: "#f59e0b",
1493
+ error: "#dc2626",
1494
+ info: "#0ea5e9"
1495
+ }
1496
+ },
1497
+ {
1498
+ name: "royal-purple",
1499
+ displayName: "Royal Purple",
1500
+ description: "Elegant purple and violet tones",
1501
+ category: "brand",
1502
+ colors: {
1503
+ primary: generateColorScale2("#7c3aed"),
1504
+ secondary: generateColorScale2("#c026d3"),
1505
+ neutral: SLATE_NEUTRAL,
1506
+ success: "#22c55e",
1507
+ warning: "#f59e0b",
1508
+ error: "#ef4444",
1509
+ info: "#3b82f6"
1510
+ }
1511
+ },
1512
+ {
1513
+ name: "cherry-red",
1514
+ displayName: "Cherry Red",
1515
+ description: "Bold red with dark accents",
1516
+ category: "bold",
1517
+ colors: {
1518
+ primary: generateColorScale2("#dc2626"),
1519
+ secondary: generateColorScale2("#1f2937"),
1520
+ neutral: ZINC_NEUTRAL,
1521
+ success: "#22c55e",
1522
+ warning: "#f59e0b",
1523
+ error: "#b91c1c",
1524
+ info: "#3b82f6"
1525
+ }
1526
+ },
1527
+ {
1528
+ name: "rose-gold",
1529
+ displayName: "Rose Gold",
1530
+ description: "Elegant rose and gold combination",
1531
+ category: "brand",
1532
+ colors: {
1533
+ primary: generateColorScale2("#f43f5e"),
1534
+ secondary: generateColorScale2("#d4a574"),
1535
+ neutral: WARM_NEUTRAL,
1536
+ success: "#22c55e",
1537
+ warning: "#f59e0b",
1538
+ error: "#e11d48",
1539
+ info: "#3b82f6"
1540
+ }
1541
+ },
1542
+ {
1543
+ name: "midnight",
1544
+ displayName: "Midnight",
1545
+ description: "Dark blue with cyan accents",
1546
+ category: "professional",
1547
+ colors: {
1548
+ primary: generateColorScale2("#1e3a5f"),
1549
+ secondary: generateColorScale2("#06b6d4"),
1550
+ neutral: SLATE_NEUTRAL,
1551
+ success: "#22c55e",
1552
+ warning: "#f59e0b",
1553
+ error: "#ef4444",
1554
+ info: "#0ea5e9"
1555
+ }
1556
+ },
1557
+ {
1558
+ name: "teal-modern",
1559
+ displayName: "Teal Modern",
1560
+ description: "Modern teal with warm accents",
1561
+ category: "technology",
1562
+ colors: {
1563
+ primary: generateColorScale2("#0d9488"),
1564
+ secondary: generateColorScale2("#f97316"),
1565
+ neutral: GRAY_NEUTRAL,
1566
+ success: "#22c55e",
1567
+ warning: "#f59e0b",
1568
+ error: "#ef4444",
1569
+ info: "#14b8a6"
1570
+ }
1571
+ },
1572
+ // ─────────────────────────────────────────────────────────────────────────
1573
+ // HEALTHCARE
1574
+ // ─────────────────────────────────────────────────────────────────────────
1575
+ {
1576
+ name: "healthcare-trust",
1577
+ displayName: "Healthcare Trust",
1578
+ description: "Trustworthy blue for medical applications",
1579
+ category: "healthcare",
1580
+ colors: {
1581
+ primary: generateColorScale2("#0077b6"),
1582
+ secondary: generateColorScale2("#48cae4"),
1583
+ neutral: SLATE_NEUTRAL,
1584
+ success: "#22c55e",
1585
+ warning: "#f59e0b",
1586
+ error: "#ef4444",
1587
+ info: "#3b82f6"
1588
+ },
1589
+ typography: {
1590
+ fontFamily: "Inter, system-ui, sans-serif"
1591
+ },
1592
+ borderRadius: "md"
1593
+ },
1594
+ {
1595
+ name: "healthcare-calm",
1596
+ displayName: "Healthcare Calm",
1597
+ description: "Soothing green for wellness apps",
1598
+ category: "healthcare",
1599
+ colors: {
1600
+ primary: generateColorScale2("#059669"),
1601
+ secondary: generateColorScale2("#a7f3d0"),
1602
+ neutral: GRAY_NEUTRAL,
1603
+ success: "#22c55e",
1604
+ warning: "#f59e0b",
1605
+ error: "#ef4444",
1606
+ info: "#3b82f6"
1607
+ },
1608
+ borderRadius: "lg"
1609
+ },
1610
+ {
1611
+ name: "healthcare-clean",
1612
+ displayName: "Healthcare Clean",
1613
+ description: "Clean, minimal healthcare theme",
1614
+ category: "healthcare",
1615
+ colors: {
1616
+ primary: generateColorScale2("#0284c7"),
1617
+ secondary: generateColorScale2("#e0f2fe"),
1618
+ neutral: SLATE_NEUTRAL,
1619
+ success: "#16a34a",
1620
+ warning: "#ca8a04",
1621
+ error: "#dc2626",
1622
+ info: "#0284c7"
1623
+ },
1624
+ borderRadius: "sm",
1625
+ shadows: "sm"
1626
+ },
1627
+ // ─────────────────────────────────────────────────────────────────────────
1628
+ // FINANCE
1629
+ // ─────────────────────────────────────────────────────────────────────────
1630
+ {
1631
+ name: "finance-corporate",
1632
+ displayName: "Finance Corporate",
1633
+ description: "Professional corporate finance theme",
1634
+ category: "finance",
1635
+ colors: {
1636
+ primary: generateColorScale2("#1e40af"),
1637
+ secondary: generateColorScale2("#047857"),
1638
+ neutral: SLATE_NEUTRAL,
1639
+ success: "#22c55e",
1640
+ warning: "#f59e0b",
1641
+ error: "#dc2626",
1642
+ info: "#3b82f6"
1643
+ },
1644
+ typography: {
1645
+ fontFamily: "Inter, system-ui, sans-serif",
1646
+ headingFontFamily: "Inter, system-ui, sans-serif"
1647
+ },
1648
+ borderRadius: "sm"
1649
+ },
1650
+ {
1651
+ name: "finance-modern",
1652
+ displayName: "Finance Modern",
1653
+ description: "Modern fintech startup theme",
1654
+ category: "finance",
1655
+ colors: {
1656
+ primary: generateColorScale2("#4f46e5"),
1657
+ secondary: generateColorScale2("#10b981"),
1658
+ neutral: ZINC_NEUTRAL,
1659
+ success: "#10b981",
1660
+ warning: "#f59e0b",
1661
+ error: "#ef4444",
1662
+ info: "#6366f1"
1663
+ },
1664
+ borderRadius: "lg"
1665
+ },
1666
+ {
1667
+ name: "finance-luxury",
1668
+ displayName: "Finance Luxury",
1669
+ description: "Premium private banking theme",
1670
+ category: "finance",
1671
+ colors: {
1672
+ primary: generateColorScale2("#1f2937"),
1673
+ secondary: generateColorScale2("#b8860b"),
1674
+ accent: generateColorScale2("#c4a35a"),
1675
+ neutral: ZINC_NEUTRAL,
1676
+ success: "#16a34a",
1677
+ warning: "#d97706",
1678
+ error: "#b91c1c",
1679
+ info: "#1d4ed8"
1680
+ },
1681
+ borderRadius: "none"
1682
+ },
1683
+ {
1684
+ name: "finance-crypto",
1685
+ displayName: "Finance Crypto",
1686
+ description: "Dark theme for crypto trading",
1687
+ category: "finance",
1688
+ colors: {
1689
+ primary: generateColorScale2("#f7931a"),
1690
+ secondary: generateColorScale2("#627eea"),
1691
+ neutral: {
1692
+ 50: "#0a0a0a",
1693
+ 100: "#171717",
1694
+ 200: "#262626",
1695
+ 300: "#404040",
1696
+ 400: "#525252",
1697
+ 500: "#737373",
1698
+ 600: "#a3a3a3",
1699
+ 700: "#d4d4d4",
1700
+ 800: "#e5e5e5",
1701
+ 900: "#f5f5f5",
1702
+ 950: "#fafafa"
1703
+ },
1704
+ success: "#22c55e",
1705
+ warning: "#f59e0b",
1706
+ error: "#ef4444",
1707
+ info: "#3b82f6"
1708
+ },
1709
+ borderRadius: "md"
1710
+ },
1711
+ // ─────────────────────────────────────────────────────────────────────────
1712
+ // EDUCATION
1713
+ // ─────────────────────────────────────────────────────────────────────────
1714
+ {
1715
+ name: "education-academic",
1716
+ displayName: "Education Academic",
1717
+ description: "Traditional academic institution theme",
1718
+ category: "education",
1719
+ colors: {
1720
+ primary: generateColorScale2("#1e3a8a"),
1721
+ secondary: generateColorScale2("#991b1b"),
1722
+ neutral: GRAY_NEUTRAL,
1723
+ success: "#22c55e",
1724
+ warning: "#f59e0b",
1725
+ error: "#dc2626",
1726
+ info: "#3b82f6"
1727
+ },
1728
+ typography: {
1729
+ fontFamily: "Georgia, serif",
1730
+ headingFontFamily: "Georgia, serif"
1731
+ },
1732
+ borderRadius: "sm"
1733
+ },
1734
+ {
1735
+ name: "education-modern",
1736
+ displayName: "Education Modern",
1737
+ description: "Modern e-learning platform theme",
1738
+ category: "education",
1739
+ colors: {
1740
+ primary: generateColorScale2("#4f46e5"),
1741
+ secondary: generateColorScale2("#f97316"),
1742
+ neutral: SLATE_NEUTRAL,
1743
+ success: "#22c55e",
1744
+ warning: "#f59e0b",
1745
+ error: "#ef4444",
1746
+ info: "#6366f1"
1747
+ },
1748
+ borderRadius: "lg"
1749
+ },
1750
+ {
1751
+ name: "education-kids",
1752
+ displayName: "Education Kids",
1753
+ description: "Fun, colorful theme for children",
1754
+ category: "education",
1755
+ colors: {
1756
+ primary: generateColorScale2("#8b5cf6"),
1757
+ secondary: generateColorScale2("#ec4899"),
1758
+ accent: generateColorScale2("#fbbf24"),
1759
+ neutral: GRAY_NEUTRAL,
1760
+ success: "#22c55e",
1761
+ warning: "#f59e0b",
1762
+ error: "#ef4444",
1763
+ info: "#3b82f6"
1764
+ },
1765
+ borderRadius: "full"
1766
+ },
1767
+ // ─────────────────────────────────────────────────────────────────────────
1768
+ // TECHNOLOGY
1769
+ // ─────────────────────────────────────────────────────────────────────────
1770
+ {
1771
+ name: "tech-startup",
1772
+ displayName: "Tech Startup",
1773
+ description: "Modern tech startup theme",
1774
+ category: "technology",
1775
+ colors: {
1776
+ primary: generateColorScale2("#2563eb"),
1777
+ secondary: generateColorScale2("#7c3aed"),
1778
+ neutral: SLATE_NEUTRAL,
1779
+ success: "#22c55e",
1780
+ warning: "#f59e0b",
1781
+ error: "#ef4444",
1782
+ info: "#3b82f6"
1783
+ },
1784
+ borderRadius: "lg"
1785
+ },
1786
+ {
1787
+ name: "tech-saas",
1788
+ displayName: "Tech SaaS",
1789
+ description: "Clean SaaS product theme",
1790
+ category: "technology",
1791
+ colors: {
1792
+ primary: generateColorScale2("#0ea5e9"),
1793
+ secondary: generateColorScale2("#8b5cf6"),
1794
+ neutral: GRAY_NEUTRAL,
1795
+ success: "#22c55e",
1796
+ warning: "#f59e0b",
1797
+ error: "#ef4444",
1798
+ info: "#0ea5e9"
1799
+ },
1800
+ borderRadius: "md"
1801
+ },
1802
+ {
1803
+ name: "tech-dark",
1804
+ displayName: "Tech Dark",
1805
+ description: "Developer-focused dark theme",
1806
+ category: "technology",
1807
+ colors: {
1808
+ primary: generateColorScale2("#22d3ee"),
1809
+ secondary: generateColorScale2("#a78bfa"),
1810
+ neutral: {
1811
+ 50: "#030712",
1812
+ 100: "#0a0f1a",
1813
+ 200: "#1f2937",
1814
+ 300: "#374151",
1815
+ 400: "#6b7280",
1816
+ 500: "#9ca3af",
1817
+ 600: "#d1d5db",
1818
+ 700: "#e5e7eb",
1819
+ 800: "#f3f4f6",
1820
+ 900: "#f9fafb",
1821
+ 950: "#ffffff"
1822
+ },
1823
+ success: "#4ade80",
1824
+ warning: "#fbbf24",
1825
+ error: "#f87171",
1826
+ info: "#38bdf8"
1827
+ }
1828
+ },
1829
+ {
1830
+ name: "tech-github",
1831
+ displayName: "GitHub Style",
1832
+ description: "GitHub-inspired developer theme",
1833
+ category: "technology",
1834
+ colors: {
1835
+ primary: generateColorScale2("#238636"),
1836
+ secondary: generateColorScale2("#1f6feb"),
1837
+ neutral: ZINC_NEUTRAL,
1838
+ success: "#238636",
1839
+ warning: "#d29922",
1840
+ error: "#da3633",
1841
+ info: "#58a6ff"
1842
+ },
1843
+ borderRadius: "md"
1844
+ },
1845
+ // ─────────────────────────────────────────────────────────────────────────
1846
+ // E-COMMERCE
1847
+ // ─────────────────────────────────────────────────────────────────────────
1848
+ {
1849
+ name: "ecommerce-modern",
1850
+ displayName: "E-commerce Modern",
1851
+ description: "Clean modern e-commerce theme",
1852
+ category: "ecommerce",
1853
+ colors: {
1854
+ primary: generateColorScale2("#111827"),
1855
+ secondary: generateColorScale2("#6366f1"),
1856
+ neutral: GRAY_NEUTRAL,
1857
+ success: "#22c55e",
1858
+ warning: "#f59e0b",
1859
+ error: "#ef4444",
1860
+ info: "#3b82f6"
1861
+ },
1862
+ borderRadius: "md"
1863
+ },
1864
+ {
1865
+ name: "ecommerce-fashion",
1866
+ displayName: "E-commerce Fashion",
1867
+ description: "Stylish fashion e-commerce theme",
1868
+ category: "ecommerce",
1869
+ colors: {
1870
+ primary: generateColorScale2("#000000"),
1871
+ secondary: generateColorScale2("#c4a35a"),
1872
+ neutral: ZINC_NEUTRAL,
1873
+ success: "#22c55e",
1874
+ warning: "#f59e0b",
1875
+ error: "#ef4444",
1876
+ info: "#3b82f6"
1877
+ },
1878
+ borderRadius: "none"
1879
+ },
1880
+ {
1881
+ name: "ecommerce-organic",
1882
+ displayName: "E-commerce Organic",
1883
+ description: "Natural products theme",
1884
+ category: "ecommerce",
1885
+ colors: {
1886
+ primary: generateColorScale2("#166534"),
1887
+ secondary: generateColorScale2("#92400e"),
1888
+ neutral: WARM_NEUTRAL,
1889
+ success: "#22c55e",
1890
+ warning: "#f59e0b",
1891
+ error: "#dc2626",
1892
+ info: "#0284c7"
1893
+ },
1894
+ borderRadius: "lg"
1895
+ },
1896
+ // ─────────────────────────────────────────────────────────────────────────
1897
+ // ENTERTAINMENT
1898
+ // ─────────────────────────────────────────────────────────────────────────
1899
+ {
1900
+ name: "entertainment-streaming",
1901
+ displayName: "Streaming Service",
1902
+ description: "Dark streaming platform theme",
1903
+ category: "entertainment",
1904
+ colors: {
1905
+ primary: generateColorScale2("#e50914"),
1906
+ secondary: generateColorScale2("#ffffff"),
1907
+ neutral: {
1908
+ 50: "#0a0a0a",
1909
+ 100: "#141414",
1910
+ 200: "#1f1f1f",
1911
+ 300: "#2d2d2d",
1912
+ 400: "#525252",
1913
+ 500: "#737373",
1914
+ 600: "#a3a3a3",
1915
+ 700: "#d4d4d4",
1916
+ 800: "#e5e5e5",
1917
+ 900: "#f5f5f5",
1918
+ 950: "#fafafa"
1919
+ },
1920
+ success: "#22c55e",
1921
+ warning: "#f59e0b",
1922
+ error: "#e50914",
1923
+ info: "#3b82f6"
1924
+ }
1925
+ },
1926
+ {
1927
+ name: "entertainment-gaming",
1928
+ displayName: "Gaming",
1929
+ description: "Vibrant gaming theme",
1930
+ category: "entertainment",
1931
+ colors: {
1932
+ primary: generateColorScale2("#9333ea"),
1933
+ secondary: generateColorScale2("#22d3ee"),
1934
+ accent: generateColorScale2("#f43f5e"),
1935
+ neutral: {
1936
+ 50: "#09090b",
1937
+ 100: "#18181b",
1938
+ 200: "#27272a",
1939
+ 300: "#3f3f46",
1940
+ 400: "#52525b",
1941
+ 500: "#71717a",
1942
+ 600: "#a1a1aa",
1943
+ 700: "#d4d4d8",
1944
+ 800: "#e4e4e7",
1945
+ 900: "#f4f4f5",
1946
+ 950: "#fafafa"
1947
+ },
1948
+ success: "#4ade80",
1949
+ warning: "#fbbf24",
1950
+ error: "#f43f5e",
1951
+ info: "#22d3ee"
1952
+ },
1953
+ borderRadius: "md"
1954
+ },
1955
+ {
1956
+ name: "entertainment-music",
1957
+ displayName: "Music",
1958
+ description: "Music streaming theme",
1959
+ category: "entertainment",
1960
+ colors: {
1961
+ primary: generateColorScale2("#1db954"),
1962
+ secondary: generateColorScale2("#ffffff"),
1963
+ neutral: {
1964
+ 50: "#121212",
1965
+ 100: "#181818",
1966
+ 200: "#282828",
1967
+ 300: "#3d3d3d",
1968
+ 400: "#535353",
1969
+ 500: "#7a7a7a",
1970
+ 600: "#b3b3b3",
1971
+ 700: "#d9d9d9",
1972
+ 800: "#ebebeb",
1973
+ 900: "#f5f5f5",
1974
+ 950: "#ffffff"
1975
+ },
1976
+ success: "#1db954",
1977
+ warning: "#f59e0b",
1978
+ error: "#e91429",
1979
+ info: "#1e90ff"
1980
+ }
1981
+ },
1982
+ // ─────────────────────────────────────────────────────────────────────────
1983
+ // GOVERNMENT
1984
+ // ─────────────────────────────────────────────────────────────────────────
1985
+ {
1986
+ name: "government-official",
1987
+ displayName: "Government Official",
1988
+ description: "Official government portal theme",
1989
+ category: "government",
1990
+ colors: {
1991
+ primary: generateColorScale2("#1e3a8a"),
1992
+ secondary: generateColorScale2("#991b1b"),
1993
+ neutral: SLATE_NEUTRAL,
1994
+ success: "#16a34a",
1995
+ warning: "#ca8a04",
1996
+ error: "#b91c1c",
1997
+ info: "#1e40af"
1998
+ },
1999
+ borderRadius: "sm",
2000
+ shadows: "sm"
2001
+ },
2002
+ {
2003
+ name: "government-accessible",
2004
+ displayName: "Government Accessible",
2005
+ description: "High contrast accessible theme",
2006
+ category: "government",
2007
+ colors: {
2008
+ primary: generateColorScale2("#0f172a"),
2009
+ secondary: generateColorScale2("#1e40af"),
2010
+ neutral: SLATE_NEUTRAL,
2011
+ success: "#15803d",
2012
+ warning: "#a16207",
2013
+ error: "#b91c1c",
2014
+ info: "#1d4ed8"
2015
+ },
2016
+ borderRadius: "none"
2017
+ },
2018
+ // ─────────────────────────────────────────────────────────────────────────
2019
+ // NATURE / ORGANIC
2020
+ // ─────────────────────────────────────────────────────────────────────────
2021
+ {
2022
+ name: "nature-earth",
2023
+ displayName: "Earth Tones",
2024
+ description: "Warm earthy natural tones",
2025
+ category: "nature",
2026
+ colors: {
2027
+ primary: generateColorScale2("#78350f"),
2028
+ secondary: generateColorScale2("#166534"),
2029
+ neutral: WARM_NEUTRAL,
2030
+ success: "#22c55e",
2031
+ warning: "#f59e0b",
2032
+ error: "#dc2626",
2033
+ info: "#0284c7"
2034
+ },
2035
+ borderRadius: "lg"
2036
+ },
2037
+ {
2038
+ name: "nature-ocean",
2039
+ displayName: "Ocean",
2040
+ description: "Ocean-inspired blues and teals",
2041
+ category: "nature",
2042
+ colors: {
2043
+ primary: generateColorScale2("#0369a1"),
2044
+ secondary: generateColorScale2("#0d9488"),
2045
+ neutral: SLATE_NEUTRAL,
2046
+ success: "#22c55e",
2047
+ warning: "#f59e0b",
2048
+ error: "#ef4444",
2049
+ info: "#0ea5e9"
2050
+ },
2051
+ borderRadius: "md"
2052
+ },
2053
+ {
2054
+ name: "nature-forest",
2055
+ displayName: "Forest",
2056
+ description: "Deep forest greens",
2057
+ category: "nature",
2058
+ colors: {
2059
+ primary: generateColorScale2("#14532d"),
2060
+ secondary: generateColorScale2("#365314"),
2061
+ neutral: GRAY_NEUTRAL,
2062
+ success: "#22c55e",
2063
+ warning: "#f59e0b",
2064
+ error: "#dc2626",
2065
+ info: "#3b82f6"
2066
+ },
2067
+ borderRadius: "md"
2068
+ },
2069
+ {
2070
+ name: "nature-sunset",
2071
+ displayName: "Sunset",
2072
+ description: "Warm sunset gradient colors",
2073
+ category: "nature",
2074
+ colors: {
2075
+ primary: generateColorScale2("#ea580c"),
2076
+ secondary: generateColorScale2("#be185d"),
2077
+ neutral: WARM_NEUTRAL,
2078
+ success: "#22c55e",
2079
+ warning: "#f59e0b",
2080
+ error: "#dc2626",
2081
+ info: "#0ea5e9"
2082
+ },
2083
+ borderRadius: "lg"
2084
+ },
2085
+ // ─────────────────────────────────────────────────────────────────────────
2086
+ // MINIMAL
2087
+ // ─────────────────────────────────────────────────────────────────────────
2088
+ {
2089
+ name: "minimal-mono",
2090
+ displayName: "Monochrome",
2091
+ description: "Pure black and white minimal",
2092
+ category: "minimal",
2093
+ colors: {
2094
+ primary: generateColorScale2("#000000"),
2095
+ neutral: ZINC_NEUTRAL,
2096
+ success: "#22c55e",
2097
+ warning: "#f59e0b",
2098
+ error: "#ef4444",
2099
+ info: "#3b82f6"
2100
+ },
2101
+ borderRadius: "none",
2102
+ shadows: "none"
2103
+ },
2104
+ {
2105
+ name: "minimal-soft",
2106
+ displayName: "Minimal Soft",
2107
+ description: "Soft grays with subtle accents",
2108
+ category: "minimal",
2109
+ colors: {
2110
+ primary: generateColorScale2("#4b5563"),
2111
+ secondary: generateColorScale2("#6366f1"),
2112
+ neutral: GRAY_NEUTRAL,
2113
+ success: "#22c55e",
2114
+ warning: "#f59e0b",
2115
+ error: "#ef4444",
2116
+ info: "#3b82f6"
2117
+ },
2118
+ borderRadius: "sm",
2119
+ shadows: "sm"
2120
+ },
2121
+ {
2122
+ name: "minimal-paper",
2123
+ displayName: "Paper",
2124
+ description: "Clean paper-like minimal theme",
2125
+ category: "minimal",
2126
+ colors: {
2127
+ primary: generateColorScale2("#525252"),
2128
+ neutral: {
2129
+ 50: "#fefefe",
2130
+ 100: "#fafafa",
2131
+ 200: "#f5f5f5",
2132
+ 300: "#e5e5e5",
2133
+ 400: "#d4d4d4",
2134
+ 500: "#a3a3a3",
2135
+ 600: "#737373",
2136
+ 700: "#525252",
2137
+ 800: "#404040",
2138
+ 900: "#262626",
2139
+ 950: "#171717"
2140
+ },
2141
+ success: "#16a34a",
2142
+ warning: "#ca8a04",
2143
+ error: "#dc2626",
2144
+ info: "#2563eb"
2145
+ },
2146
+ borderRadius: "sm",
2147
+ shadows: "sm"
2148
+ },
2149
+ // ─────────────────────────────────────────────────────────────────────────
2150
+ // BOLD
2151
+ // ─────────────────────────────────────────────────────────────────────────
2152
+ {
2153
+ name: "bold-neon",
2154
+ displayName: "Neon",
2155
+ description: "Vibrant neon colors on dark",
2156
+ category: "bold",
2157
+ colors: {
2158
+ primary: generateColorScale2("#f0abfc"),
2159
+ secondary: generateColorScale2("#22d3ee"),
2160
+ accent: generateColorScale2("#a3e635"),
2161
+ neutral: {
2162
+ 50: "#0a0a0a",
2163
+ 100: "#171717",
2164
+ 200: "#262626",
2165
+ 300: "#404040",
2166
+ 400: "#525252",
2167
+ 500: "#737373",
2168
+ 600: "#a3a3a3",
2169
+ 700: "#d4d4d4",
2170
+ 800: "#e5e5e5",
2171
+ 900: "#f5f5f5",
2172
+ 950: "#fafafa"
2173
+ },
2174
+ success: "#a3e635",
2175
+ warning: "#fbbf24",
2176
+ error: "#f87171",
2177
+ info: "#38bdf8"
2178
+ },
2179
+ borderRadius: "full"
2180
+ },
2181
+ {
2182
+ name: "bold-gradient",
2183
+ displayName: "Gradient Bold",
2184
+ description: "Bold gradient-ready colors",
2185
+ category: "bold",
2186
+ colors: {
2187
+ primary: generateColorScale2("#ec4899"),
2188
+ secondary: generateColorScale2("#8b5cf6"),
2189
+ accent: generateColorScale2("#06b6d4"),
2190
+ neutral: ZINC_NEUTRAL,
2191
+ success: "#22c55e",
2192
+ warning: "#f59e0b",
2193
+ error: "#ef4444",
2194
+ info: "#3b82f6"
2195
+ },
2196
+ borderRadius: "lg"
2197
+ },
2198
+ // ─────────────────────────────────────────────────────────────────────────
2199
+ // PLAYFUL
2200
+ // ─────────────────────────────────────────────────────────────────────────
2201
+ {
2202
+ name: "playful-candy",
2203
+ displayName: "Candy",
2204
+ description: "Sweet candy-inspired colors",
2205
+ category: "playful",
2206
+ colors: {
2207
+ primary: generateColorScale2("#ec4899"),
2208
+ secondary: generateColorScale2("#a855f7"),
2209
+ accent: generateColorScale2("#22d3ee"),
2210
+ neutral: GRAY_NEUTRAL,
2211
+ success: "#22c55e",
2212
+ warning: "#fbbf24",
2213
+ error: "#f43f5e",
2214
+ info: "#3b82f6"
2215
+ },
2216
+ borderRadius: "full"
2217
+ },
2218
+ {
2219
+ name: "playful-retro",
2220
+ displayName: "Retro",
2221
+ description: "Retro 80s inspired colors",
2222
+ category: "playful",
2223
+ colors: {
2224
+ primary: generateColorScale2("#f472b6"),
2225
+ secondary: generateColorScale2("#38bdf8"),
2226
+ accent: generateColorScale2("#facc15"),
2227
+ neutral: ZINC_NEUTRAL,
2228
+ success: "#4ade80",
2229
+ warning: "#fbbf24",
2230
+ error: "#f87171",
2231
+ info: "#38bdf8"
2232
+ },
2233
+ borderRadius: "lg"
2234
+ },
2235
+ {
2236
+ name: "playful-pastel",
2237
+ displayName: "Pastel",
2238
+ description: "Soft pastel colors",
2239
+ category: "playful",
2240
+ colors: {
2241
+ primary: generateColorScale2("#93c5fd"),
2242
+ secondary: generateColorScale2("#fda4af"),
2243
+ accent: generateColorScale2("#fde047"),
2244
+ neutral: GRAY_NEUTRAL,
2245
+ success: "#86efac",
2246
+ warning: "#fde047",
2247
+ error: "#fda4af",
2248
+ info: "#93c5fd"
2249
+ },
2250
+ borderRadius: "full"
2251
+ },
2252
+ // ─────────────────────────────────────────────────────────────────────────
2253
+ // PROFESSIONAL
2254
+ // ─────────────────────────────────────────────────────────────────────────
2255
+ {
2256
+ name: "professional-corporate",
2257
+ displayName: "Corporate",
2258
+ description: "Traditional corporate blue",
2259
+ category: "professional",
2260
+ colors: {
2261
+ primary: generateColorScale2("#1e40af"),
2262
+ secondary: generateColorScale2("#0f766e"),
2263
+ neutral: SLATE_NEUTRAL,
2264
+ success: "#22c55e",
2265
+ warning: "#f59e0b",
2266
+ error: "#dc2626",
2267
+ info: "#3b82f6"
2268
+ },
2269
+ borderRadius: "sm"
2270
+ },
2271
+ {
2272
+ name: "professional-law",
2273
+ displayName: "Legal",
2274
+ description: "Serious legal/consulting theme",
2275
+ category: "professional",
2276
+ colors: {
2277
+ primary: generateColorScale2("#1f2937"),
2278
+ secondary: generateColorScale2("#7c2d12"),
2279
+ neutral: GRAY_NEUTRAL,
2280
+ success: "#16a34a",
2281
+ warning: "#ca8a04",
2282
+ error: "#b91c1c",
2283
+ info: "#1d4ed8"
2284
+ },
2285
+ typography: {
2286
+ fontFamily: "Georgia, serif",
2287
+ headingFontFamily: "Georgia, serif"
2288
+ },
2289
+ borderRadius: "none"
2290
+ },
2291
+ {
2292
+ name: "professional-consulting",
2293
+ displayName: "Consulting",
2294
+ description: "Clean consulting firm theme",
2295
+ category: "professional",
2296
+ colors: {
2297
+ primary: generateColorScale2("#0f172a"),
2298
+ secondary: generateColorScale2("#0369a1"),
2299
+ neutral: SLATE_NEUTRAL,
2300
+ success: "#22c55e",
2301
+ warning: "#f59e0b",
2302
+ error: "#dc2626",
2303
+ info: "#0284c7"
2304
+ },
2305
+ borderRadius: "sm"
2306
+ }
2307
+ ];
2308
+ function getPresetsByCategory(category) {
2309
+ return PRESETS.filter((p) => p.category === category);
2310
+ }
2311
+ function getPresetByName(name) {
2312
+ return PRESETS.find((p) => p.name === name);
2313
+ }
2314
+ function getAllCategories() {
2315
+ return Array.from(new Set(PRESETS.map((p) => p.category)));
2316
+ }
2317
+ function presetToCssVariables(preset, prefix = "nice") {
2318
+ const lines = [];
2319
+ for (const [shade, value] of Object.entries(preset.colors.primary)) {
2320
+ lines.push(` --${prefix}-color-primary-${shade}: ${value};`);
2321
+ }
2322
+ if (preset.colors.secondary) {
2323
+ for (const [shade, value] of Object.entries(preset.colors.secondary)) {
2324
+ lines.push(` --${prefix}-color-secondary-${shade}: ${value};`);
2325
+ }
2326
+ }
2327
+ if (preset.colors.accent) {
2328
+ for (const [shade, value] of Object.entries(preset.colors.accent)) {
2329
+ lines.push(` --${prefix}-color-accent-${shade}: ${value};`);
2330
+ }
2331
+ }
2332
+ for (const [shade, value] of Object.entries(preset.colors.neutral)) {
2333
+ lines.push(` --${prefix}-color-neutral-${shade}: ${value};`);
2334
+ }
2335
+ lines.push(` --${prefix}-color-success: ${preset.colors.success};`);
2336
+ lines.push(` --${prefix}-color-warning: ${preset.colors.warning};`);
2337
+ lines.push(` --${prefix}-color-error: ${preset.colors.error};`);
2338
+ lines.push(` --${prefix}-color-info: ${preset.colors.info};`);
2339
+ return `:root {
2340
+ ${lines.join("\n")}
2341
+ }`;
2342
+ }
2343
+ function presetToTokens(preset) {
2344
+ const colorToToken = (value) => ({ $value: value, $type: "color" });
2345
+ const scaleToTokens = (scale) => {
2346
+ const tokens = {};
2347
+ for (const [shade, value] of Object.entries(scale)) {
2348
+ tokens[shade] = colorToToken(value);
2349
+ }
2350
+ return tokens;
2351
+ };
2352
+ return {
2353
+ $name: preset.displayName,
2354
+ $description: preset.description,
2355
+ color: {
2356
+ primary: scaleToTokens(preset.colors.primary),
2357
+ secondary: preset.colors.secondary ? scaleToTokens(preset.colors.secondary) : void 0,
2358
+ accent: preset.colors.accent ? scaleToTokens(preset.colors.accent) : void 0,
2359
+ neutral: scaleToTokens(preset.colors.neutral),
2360
+ semantic: {
2361
+ success: colorToToken(preset.colors.success),
2362
+ warning: colorToToken(preset.colors.warning),
2363
+ error: colorToToken(preset.colors.error),
2364
+ info: colorToToken(preset.colors.info)
2365
+ }
2366
+ }
2367
+ };
2368
+ }
2369
+
2370
+ // src/brand-kit.ts
2371
+ function analyzeColor(hex) {
2372
+ const rgb = hexToRgb2(hex);
2373
+ const hsl = rgbToHsl(rgb);
2374
+ const luminance = calculateLuminance(rgb);
2375
+ return {
2376
+ hsl,
2377
+ rgb,
2378
+ luminance,
2379
+ isLight: luminance > 0.5,
2380
+ complementary: hslToHex2((hsl[0] + 180) % 360, hsl[1], hsl[2]),
2381
+ analogous: [
2382
+ hslToHex2((hsl[0] + 30) % 360, hsl[1], hsl[2]),
2383
+ hslToHex2((hsl[0] - 30 + 360) % 360, hsl[1], hsl[2])
2384
+ ],
2385
+ triadic: [
2386
+ hslToHex2((hsl[0] + 120) % 360, hsl[1], hsl[2]),
2387
+ hslToHex2((hsl[0] + 240) % 360, hsl[1], hsl[2])
2388
+ ],
2389
+ splitComplementary: [
2390
+ hslToHex2((hsl[0] + 150) % 360, hsl[1], hsl[2]),
2391
+ hslToHex2((hsl[0] + 210) % 360, hsl[1], hsl[2])
2392
+ ]
2393
+ };
2394
+ }
2395
+ function hexToRgb2(hex) {
2396
+ const r = parseInt(hex.slice(1, 3), 16);
2397
+ const g = parseInt(hex.slice(3, 5), 16);
2398
+ const b = parseInt(hex.slice(5, 7), 16);
2399
+ return [r, g, b];
2400
+ }
2401
+ function rgbToHsl([r, g, b]) {
2402
+ r /= 255;
2403
+ g /= 255;
2404
+ b /= 255;
2405
+ const max = Math.max(r, g, b);
2406
+ const min = Math.min(r, g, b);
2407
+ let h = 0;
2408
+ let s = 0;
2409
+ const l = (max + min) / 2;
2410
+ if (max !== min) {
2411
+ const d = max - min;
2412
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
2413
+ switch (max) {
2414
+ case r:
2415
+ h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
2416
+ break;
2417
+ case g:
2418
+ h = ((b - r) / d + 2) / 6;
2419
+ break;
2420
+ case b:
2421
+ h = ((r - g) / d + 4) / 6;
2422
+ break;
2423
+ }
2424
+ }
2425
+ return [h * 360, s * 100, l * 100];
2426
+ }
2427
+ function hslToHex2(h, s, l) {
2428
+ s /= 100;
2429
+ l /= 100;
2430
+ h /= 360;
2431
+ const hue2rgb = (p, q, t) => {
2432
+ if (t < 0) {
2433
+ t += 1;
2434
+ }
2435
+ if (t > 1) {
2436
+ t -= 1;
2437
+ }
2438
+ if (t < 1 / 6) {
2439
+ return p + (q - p) * 6 * t;
2440
+ }
2441
+ if (t < 1 / 2) {
2442
+ return q;
2443
+ }
2444
+ if (t < 2 / 3) {
2445
+ return p + (q - p) * (2 / 3 - t) * 6;
2446
+ }
2447
+ return p;
2448
+ };
2449
+ let r, g, b;
2450
+ if (s === 0) {
2451
+ r = g = b = l;
2452
+ } else {
2453
+ const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
2454
+ const p = 2 * l - q;
2455
+ r = hue2rgb(p, q, h + 1 / 3);
2456
+ g = hue2rgb(p, q, h);
2457
+ b = hue2rgb(p, q, h - 1 / 3);
2458
+ }
2459
+ const toHex = (n) => Math.round(n * 255).toString(16).padStart(2, "0");
2460
+ return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
2461
+ }
2462
+ function calculateLuminance([r, g, b]) {
2463
+ const [rs, gs, bs] = [r, g, b].map((c) => {
2464
+ c /= 255;
2465
+ return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
2466
+ });
2467
+ return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs;
2468
+ }
2469
+ var INDUSTRY_DEFAULTS = {
2470
+ technology: {
2471
+ typography: "modern-sans",
2472
+ borderRadius: "lg",
2473
+ shadows: "md",
2474
+ style: "modern"
2475
+ },
2476
+ healthcare: {
2477
+ typography: "modern-sans",
2478
+ borderRadius: "md",
2479
+ shadows: "sm",
2480
+ style: "professional"
2481
+ },
2482
+ finance: {
2483
+ typography: "classic-serif",
2484
+ borderRadius: "sm",
2485
+ shadows: "sm",
2486
+ style: "professional"
2487
+ },
2488
+ education: {
2489
+ typography: "modern-sans",
2490
+ borderRadius: "md",
2491
+ shadows: "md",
2492
+ style: "modern"
2493
+ },
2494
+ retail: {
2495
+ typography: "modern-sans",
2496
+ borderRadius: "md",
2497
+ shadows: "md",
2498
+ style: "modern"
2499
+ },
2500
+ hospitality: {
2501
+ typography: "classic-serif",
2502
+ borderRadius: "lg",
2503
+ shadows: "md",
2504
+ style: "luxury"
2505
+ },
2506
+ manufacturing: {
2507
+ typography: "modern-sans",
2508
+ borderRadius: "sm",
2509
+ shadows: "sm",
2510
+ style: "professional"
2511
+ },
2512
+ creative: {
2513
+ typography: "geometric",
2514
+ borderRadius: "lg",
2515
+ shadows: "lg",
2516
+ style: "bold"
2517
+ },
2518
+ nonprofit: {
2519
+ typography: "modern-sans",
2520
+ borderRadius: "md",
2521
+ shadows: "sm",
2522
+ style: "organic"
2523
+ },
2524
+ government: {
2525
+ typography: "modern-sans",
2526
+ borderRadius: "none",
2527
+ shadows: "sm",
2528
+ style: "professional"
2529
+ }
2530
+ };
2531
+ var TYPOGRAPHY_STACKS = {
2532
+ "modern-sans": {
2533
+ body: "Inter, system-ui, -apple-system, sans-serif",
2534
+ heading: "Inter, system-ui, -apple-system, sans-serif"
2535
+ },
2536
+ "classic-serif": {
2537
+ body: 'Georgia, Cambria, "Times New Roman", serif',
2538
+ heading: 'Georgia, Cambria, "Times New Roman", serif'
2539
+ },
2540
+ geometric: {
2541
+ body: 'Poppins, "Segoe UI", Roboto, sans-serif',
2542
+ heading: 'Poppins, "Segoe UI", Roboto, sans-serif'
2543
+ },
2544
+ rounded: {
2545
+ body: 'Nunito, "Segoe UI", Roboto, sans-serif',
2546
+ heading: 'Nunito, "Segoe UI", Roboto, sans-serif'
2547
+ },
2548
+ monospace: {
2549
+ body: '"JetBrains Mono", "Fira Code", Consolas, monospace',
2550
+ heading: '"JetBrains Mono", "Fira Code", Consolas, monospace'
2551
+ }
2552
+ };
2553
+ function generateNeutralPalette(primaryColor) {
2554
+ const analysis = analyzeColor(primaryColor);
2555
+ const [h] = analysis.hsl;
2556
+ return {
2557
+ 50: hslToHex2(h, 5, 98),
2558
+ 100: hslToHex2(h, 5, 96),
2559
+ 200: hslToHex2(h, 5, 90),
2560
+ 300: hslToHex2(h, 5, 83),
2561
+ 400: hslToHex2(h, 5, 64),
2562
+ 500: hslToHex2(h, 5, 45),
2563
+ 600: hslToHex2(h, 5, 32),
2564
+ 700: hslToHex2(h, 5, 25),
2565
+ 800: hslToHex2(h, 5, 15),
2566
+ 900: hslToHex2(h, 5, 9),
2567
+ 950: hslToHex2(h, 5, 4)
2568
+ };
2569
+ }
2570
+ function generateBrandKit(config) {
2571
+ const defaults = config.industry ? INDUSTRY_DEFAULTS[config.industry] : {};
2572
+ const mergedConfig = { ...defaults, ...config };
2573
+ const primaryAnalysis = analyzeColor(config.primaryColor);
2574
+ const secondaryColor = config.secondaryColor || primaryAnalysis.complementary;
2575
+ const accentColor = config.accentColor || primaryAnalysis.analogous[0];
2576
+ const primaryScale = generateColorScale2(config.primaryColor);
2577
+ const secondaryScale = generateColorScale2(secondaryColor);
2578
+ const accentScale = generateColorScale2(accentColor);
2579
+ const neutralScale = generateNeutralPalette(config.primaryColor);
2580
+ const semanticColors = generateSemanticColors(mergedConfig.style || "modern");
2581
+ const preset = {
2582
+ name: `brand-${config.brandName.toLowerCase().replace(/\s+/g, "-")}`,
2583
+ displayName: config.brandName,
2584
+ description: `Custom brand theme for ${config.brandName}`,
2585
+ category: "brand",
2586
+ colors: {
2587
+ primary: primaryScale,
2588
+ secondary: secondaryScale,
2589
+ accent: accentScale,
2590
+ neutral: neutralScale,
2591
+ ...semanticColors
2592
+ },
2593
+ typography: {
2594
+ fontFamily: TYPOGRAPHY_STACKS[mergedConfig.typography || "modern-sans"].body,
2595
+ headingFontFamily: TYPOGRAPHY_STACKS[mergedConfig.typography || "modern-sans"].heading
2596
+ },
2597
+ borderRadius: mergedConfig.borderRadius,
2598
+ shadows: mergedConfig.shadows
2599
+ };
2600
+ const darkMode = generateDarkModePreset(preset);
2601
+ const css = generateCssFromPreset(preset);
2602
+ const tokens = generateTokensFromPreset(preset);
2603
+ const assets = generateBrandAssets(preset, mergedConfig);
2604
+ return {
2605
+ preset,
2606
+ css,
2607
+ tokens,
2608
+ darkMode,
2609
+ assets
2610
+ };
2611
+ }
2612
+ function generateSemanticColors(style) {
2613
+ const semantics = {
2614
+ professional: { success: "#16a34a", warning: "#ca8a04", error: "#dc2626", info: "#2563eb" },
2615
+ modern: { success: "#22c55e", warning: "#f59e0b", error: "#ef4444", info: "#3b82f6" },
2616
+ playful: { success: "#4ade80", warning: "#fbbf24", error: "#f87171", info: "#60a5fa" },
2617
+ minimal: { success: "#22c55e", warning: "#f59e0b", error: "#ef4444", info: "#3b82f6" },
2618
+ bold: { success: "#22c55e", warning: "#f59e0b", error: "#ef4444", info: "#3b82f6" },
2619
+ luxury: { success: "#15803d", warning: "#a16207", error: "#b91c1c", info: "#1e40af" },
2620
+ organic: { success: "#16a34a", warning: "#d97706", error: "#dc2626", info: "#0284c7" }
2621
+ };
2622
+ return semantics[style];
2623
+ }
2624
+ function generateDarkModePreset(lightPreset) {
2625
+ const invertedNeutral = {
2626
+ 50: lightPreset.colors.neutral[950],
2627
+ 100: lightPreset.colors.neutral[900],
2628
+ 200: lightPreset.colors.neutral[800],
2629
+ 300: lightPreset.colors.neutral[700],
2630
+ 400: lightPreset.colors.neutral[600],
2631
+ 500: lightPreset.colors.neutral[500],
2632
+ 600: lightPreset.colors.neutral[400],
2633
+ 700: lightPreset.colors.neutral[300],
2634
+ 800: lightPreset.colors.neutral[200],
2635
+ 900: lightPreset.colors.neutral[100],
2636
+ 950: lightPreset.colors.neutral[50]
2637
+ };
2638
+ return {
2639
+ ...lightPreset,
2640
+ name: `${lightPreset.name}-dark`,
2641
+ displayName: `${lightPreset.displayName} (Dark)`,
2642
+ colors: {
2643
+ ...lightPreset.colors,
2644
+ neutral: invertedNeutral
2645
+ }
2646
+ };
2647
+ }
2648
+ function generateCssFromPreset(preset) {
2649
+ const lines = [
2650
+ `/* ${preset.displayName} Theme */`,
2651
+ `/* Generated by Nice2Dev Brand Kit */`,
2652
+ "",
2653
+ ":root {"
2654
+ ];
2655
+ for (const [shade, value] of Object.entries(preset.colors.primary)) {
2656
+ lines.push(` --nice-color-primary-${shade}: ${value};`);
2657
+ }
2658
+ if (preset.colors.secondary) {
2659
+ for (const [shade, value] of Object.entries(preset.colors.secondary)) {
2660
+ lines.push(` --nice-color-secondary-${shade}: ${value};`);
2661
+ }
2662
+ }
2663
+ if (preset.colors.accent) {
2664
+ for (const [shade, value] of Object.entries(preset.colors.accent)) {
2665
+ lines.push(` --nice-color-accent-${shade}: ${value};`);
2666
+ }
2667
+ }
2668
+ for (const [shade, value] of Object.entries(preset.colors.neutral)) {
2669
+ lines.push(` --nice-color-neutral-${shade}: ${value};`);
2670
+ }
2671
+ lines.push(` --nice-color-success: ${preset.colors.success};`);
2672
+ lines.push(` --nice-color-warning: ${preset.colors.warning};`);
2673
+ lines.push(` --nice-color-error: ${preset.colors.error};`);
2674
+ lines.push(` --nice-color-info: ${preset.colors.info};`);
2675
+ if (preset.typography) {
2676
+ lines.push(` --nice-font-family-body: ${preset.typography.fontFamily};`);
2677
+ lines.push(
2678
+ ` --nice-font-family-heading: ${preset.typography.headingFontFamily || preset.typography.fontFamily};`
2679
+ );
2680
+ }
2681
+ const radiusMap = { none: "0", sm: "0.25rem", md: "0.5rem", lg: "1rem", full: "9999px" };
2682
+ if (preset.borderRadius) {
2683
+ lines.push(` --nice-radius-base: ${radiusMap[preset.borderRadius]};`);
2684
+ }
2685
+ lines.push("}");
2686
+ return lines.join("\n");
2687
+ }
2688
+ function generateTokensFromPreset(preset) {
2689
+ const colorToToken = (value) => ({ $value: value, $type: "color" });
2690
+ const scaleToTokens = (scale) => {
2691
+ const tokens = {};
2692
+ for (const [shade, value] of Object.entries(scale)) {
2693
+ tokens[shade] = colorToToken(value);
2694
+ }
2695
+ return tokens;
2696
+ };
2697
+ return {
2698
+ $name: preset.displayName,
2699
+ $description: preset.description,
2700
+ color: {
2701
+ primary: scaleToTokens(preset.colors.primary),
2702
+ secondary: preset.colors.secondary ? scaleToTokens(preset.colors.secondary) : void 0,
2703
+ accent: preset.colors.accent ? scaleToTokens(preset.colors.accent) : void 0,
2704
+ neutral: scaleToTokens(preset.colors.neutral),
2705
+ semantic: {
2706
+ success: colorToToken(preset.colors.success),
2707
+ warning: colorToToken(preset.colors.warning),
2708
+ error: colorToToken(preset.colors.error),
2709
+ info: colorToToken(preset.colors.info)
2710
+ }
2711
+ },
2712
+ typography: preset.typography ? {
2713
+ fontFamily: {
2714
+ body: { $value: [preset.typography.fontFamily], $type: "fontFamily" },
2715
+ heading: {
2716
+ $value: [preset.typography.headingFontFamily || preset.typography.fontFamily],
2717
+ $type: "fontFamily"
2718
+ }
2719
+ }
2720
+ } : void 0
2721
+ };
2722
+ }
2723
+ function generateBrandAssets(preset, config) {
2724
+ const colorPalette = [
2725
+ {
2726
+ name: "Primary",
2727
+ colors: Object.entries(preset.colors.primary).map(([shade, hex]) => ({
2728
+ shade,
2729
+ hex,
2730
+ usage: shade === "500" ? "Main brand color" : shade === "600" ? "Hover states" : shade === "700" ? "Active states" : "Supporting"
2731
+ }))
2732
+ }
2733
+ ];
2734
+ if (preset.colors.secondary) {
2735
+ colorPalette.push({
2736
+ name: "Secondary",
2737
+ colors: Object.entries(preset.colors.secondary).map(([shade, hex]) => ({
2738
+ shade,
2739
+ hex,
2740
+ usage: shade === "500" ? "Secondary actions" : "Supporting"
2741
+ }))
2742
+ });
2743
+ }
2744
+ const typographyScale = [
2745
+ {
2746
+ name: "Display",
2747
+ size: "3.75rem",
2748
+ weight: 700,
2749
+ lineHeight: 1,
2750
+ usage: "Hero sections, large headings"
2751
+ },
2752
+ { name: "H1", size: "2.25rem", weight: 700, lineHeight: 1.2, usage: "Page titles" },
2753
+ { name: "H2", size: "1.875rem", weight: 600, lineHeight: 1.3, usage: "Section headings" },
2754
+ { name: "H3", size: "1.5rem", weight: 600, lineHeight: 1.4, usage: "Card titles" },
2755
+ { name: "H4", size: "1.25rem", weight: 600, lineHeight: 1.4, usage: "Subsections" },
2756
+ {
2757
+ name: "Body Large",
2758
+ size: "1.125rem",
2759
+ weight: 400,
2760
+ lineHeight: 1.6,
2761
+ usage: "Lead paragraphs"
2762
+ },
2763
+ { name: "Body", size: "1rem", weight: 400, lineHeight: 1.5, usage: "Main content" },
2764
+ { name: "Body Small", size: "0.875rem", weight: 400, lineHeight: 1.5, usage: "Secondary text" },
2765
+ { name: "Caption", size: "0.75rem", weight: 400, lineHeight: 1.4, usage: "Labels, hints" }
2766
+ ];
2767
+ const spacingScale = [
2768
+ { name: "xs", value: "0.25rem", usage: "Tight spacing" },
2769
+ { name: "sm", value: "0.5rem", usage: "Compact elements" },
2770
+ { name: "md", value: "1rem", usage: "Standard spacing" },
2771
+ { name: "lg", value: "1.5rem", usage: "Section spacing" },
2772
+ { name: "xl", value: "2rem", usage: "Large gaps" },
2773
+ { name: "2xl", value: "3rem", usage: "Section dividers" }
2774
+ ];
2775
+ const logoUsageGuidelines = `
2776
+ # ${config.brandName || "Brand"} Logo Usage Guidelines
2777
+
2778
+ ## Minimum Size
2779
+ - Digital: 24px height minimum
2780
+ - Print: 12mm height minimum
2781
+
2782
+ ## Clear Space
2783
+ - Maintain clear space equal to the height of the logo mark
2784
+
2785
+ ## Color Variations
2786
+ - Primary: Use on light backgrounds (${preset.colors.primary[500]})
2787
+ - Reversed: Use on dark backgrounds (white or ${preset.colors.neutral[50]})
2788
+ - Monochrome: For limited color applications
2789
+
2790
+ ## Don'ts
2791
+ - Don't stretch or distort
2792
+ - Don't rotate
2793
+ - Don't apply effects or shadows
2794
+ - Don't change colors outside brand palette
2795
+ - Don't place on busy backgrounds
2796
+ `.trim();
2797
+ return {
2798
+ colorPalette,
2799
+ typographyScale,
2800
+ spacingScale,
2801
+ logoUsageGuidelines
2802
+ };
2803
+ }
2804
+ function quickBrandKit(primaryColor, brandName = "My Brand") {
2805
+ return generateBrandKit({
2806
+ primaryColor,
2807
+ brandName,
2808
+ industry: "technology",
2809
+ style: "modern"
2810
+ });
2811
+ }
2812
+ function industryBrandKit(primaryColor, brandName, industry) {
2813
+ return generateBrandKit({
2814
+ primaryColor,
2815
+ brandName,
2816
+ industry
2817
+ });
2818
+ }
2819
+
2820
+ // src/accessibility.ts
2821
+ var STANDARD_MOTION = {
2822
+ duration: {
2823
+ instant: "0ms",
2824
+ fast: "100ms",
2825
+ normal: "200ms",
2826
+ slow: "300ms",
2827
+ slower: "500ms",
2828
+ slowest: "1000ms"
2829
+ },
2830
+ easing: {
2831
+ linear: "linear",
2832
+ easeIn: "cubic-bezier(0.4, 0, 1, 1)",
2833
+ easeOut: "cubic-bezier(0, 0, 0.2, 1)",
2834
+ easeInOut: "cubic-bezier(0.4, 0, 0.2, 1)",
2835
+ spring: "cubic-bezier(0.175, 0.885, 0.32, 1.275)",
2836
+ bounce: "cubic-bezier(0.68, -0.55, 0.265, 1.55)"
2837
+ },
2838
+ transition: {
2839
+ none: "none",
2840
+ all: "all 200ms cubic-bezier(0.4, 0, 0.2, 1)",
2841
+ colors: "color, background-color, border-color 200ms cubic-bezier(0.4, 0, 0.2, 1)",
2842
+ opacity: "opacity 200ms cubic-bezier(0.4, 0, 0.2, 1)",
2843
+ transform: "transform 200ms cubic-bezier(0.4, 0, 0.2, 1)",
2844
+ shadow: "box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1)"
2845
+ }
2846
+ };
2847
+ var REDUCED_MOTION = {
2848
+ duration: {
2849
+ instant: "0ms",
2850
+ fast: "0ms",
2851
+ normal: "0ms",
2852
+ slow: "0ms",
2853
+ slower: "0ms",
2854
+ slowest: "0ms"
2855
+ },
2856
+ easing: {
2857
+ linear: "linear",
2858
+ easeIn: "linear",
2859
+ easeOut: "linear",
2860
+ easeInOut: "linear",
2861
+ spring: "linear",
2862
+ bounce: "linear"
2863
+ },
2864
+ transition: {
2865
+ none: "none",
2866
+ all: "none",
2867
+ colors: "none",
2868
+ opacity: "opacity 0ms linear",
2869
+ transform: "none",
2870
+ shadow: "none"
2871
+ }
2872
+ };
2873
+ var MINIMAL_MOTION = {
2874
+ duration: {
2875
+ instant: "0ms",
2876
+ fast: "50ms",
2877
+ normal: "100ms",
2878
+ slow: "150ms",
2879
+ slower: "200ms",
2880
+ slowest: "300ms"
2881
+ },
2882
+ easing: {
2883
+ linear: "linear",
2884
+ easeIn: "linear",
2885
+ easeOut: "linear",
2886
+ easeInOut: "linear",
2887
+ spring: "linear",
2888
+ bounce: "linear"
2889
+ },
2890
+ transition: {
2891
+ none: "none",
2892
+ all: "opacity 100ms linear",
2893
+ colors: "color, background-color 100ms linear",
2894
+ opacity: "opacity 100ms linear",
2895
+ transform: "none",
2896
+ shadow: "none"
2897
+ }
2898
+ };
2899
+ var STANDARD_FOCUS = {
2900
+ ring: {
2901
+ width: "2px",
2902
+ offset: "2px",
2903
+ color: "var(--nice-color-primary-500)",
2904
+ style: "solid"
2905
+ },
2906
+ outline: {
2907
+ width: "2px",
2908
+ style: "solid",
2909
+ color: "var(--nice-color-primary-500)",
2910
+ offset: "2px"
2911
+ }
2912
+ };
2913
+ var ENHANCED_FOCUS = {
2914
+ ring: {
2915
+ width: "3px",
2916
+ offset: "3px",
2917
+ color: "var(--nice-color-primary-600)",
2918
+ style: "solid"
2919
+ },
2920
+ outline: {
2921
+ width: "3px",
2922
+ style: "solid",
2923
+ color: "var(--nice-color-primary-600)",
2924
+ offset: "3px"
2925
+ }
2926
+ };
2927
+ var HIGH_VISIBILITY_FOCUS = {
2928
+ ring: {
2929
+ width: "4px",
2930
+ offset: "4px",
2931
+ color: "#000000",
2932
+ style: "solid"
2933
+ },
2934
+ outline: {
2935
+ width: "4px",
2936
+ style: "solid",
2937
+ color: "#000000",
2938
+ offset: "4px"
2939
+ }
2940
+ };
2941
+ var STANDARD_CONTRAST = {
2942
+ text: {
2943
+ primary: "#111827",
2944
+ secondary: "#374151",
2945
+ tertiary: "#6b7280",
2946
+ disabled: "#9ca3af",
2947
+ inverse: "#ffffff"
2948
+ },
2949
+ background: {
2950
+ primary: "#ffffff",
2951
+ secondary: "#f9fafb",
2952
+ tertiary: "#f3f4f6",
2953
+ elevated: "#ffffff",
2954
+ overlay: "rgba(0, 0, 0, 0.5)"
2955
+ },
2956
+ border: {
2957
+ default: "#e5e7eb",
2958
+ strong: "#d1d5db",
2959
+ focus: "#3b82f6"
2960
+ }
2961
+ };
2962
+ var HIGH_CONTRAST = {
2963
+ text: {
2964
+ primary: "#000000",
2965
+ secondary: "#1a1a1a",
2966
+ tertiary: "#333333",
2967
+ disabled: "#666666",
2968
+ inverse: "#ffffff"
2969
+ },
2970
+ background: {
2971
+ primary: "#ffffff",
2972
+ secondary: "#f5f5f5",
2973
+ tertiary: "#ebebeb",
2974
+ elevated: "#ffffff",
2975
+ overlay: "rgba(0, 0, 0, 0.7)"
2976
+ },
2977
+ border: {
2978
+ default: "#000000",
2979
+ strong: "#000000",
2980
+ focus: "#0000cc"
2981
+ }
2982
+ };
2983
+ var HIGH_CONTRAST_DARK = {
2984
+ text: {
2985
+ primary: "#ffffff",
2986
+ secondary: "#f0f0f0",
2987
+ tertiary: "#e0e0e0",
2988
+ disabled: "#999999",
2989
+ inverse: "#000000"
2990
+ },
2991
+ background: {
2992
+ primary: "#000000",
2993
+ secondary: "#0a0a0a",
2994
+ tertiary: "#141414",
2995
+ elevated: "#1a1a1a",
2996
+ overlay: "rgba(255, 255, 255, 0.3)"
2997
+ },
2998
+ border: {
2999
+ default: "#ffffff",
3000
+ strong: "#ffffff",
3001
+ focus: "#ffff00"
3002
+ }
3003
+ };
3004
+ var STANDARD_TYPOGRAPHY = {
3005
+ minSize: "1rem",
3006
+ lineHeight: "1.5",
3007
+ letterSpacing: "normal",
3008
+ wordSpacing: "normal"
3009
+ };
3010
+ var ENHANCED_TYPOGRAPHY = {
3011
+ minSize: "1.125rem",
3012
+ lineHeight: "1.75",
3013
+ letterSpacing: "0.02em",
3014
+ wordSpacing: "0.05em"
3015
+ };
3016
+ var MAXIMUM_READABILITY_TYPOGRAPHY = {
3017
+ minSize: "1.25rem",
3018
+ lineHeight: "2",
3019
+ letterSpacing: "0.05em",
3020
+ wordSpacing: "0.1em"
3021
+ };
3022
+ function generateReducedMotionCss(config = {}) {
3023
+ const motion = config.allowReducedAnimations ? MINIMAL_MOTION : REDUCED_MOTION;
3024
+ return `
3025
+ /* Reduced Motion Styles */
3026
+ @media (prefers-reduced-motion: reduce) {
3027
+ *,
3028
+ *::before,
3029
+ *::after {
3030
+ animation-duration: ${motion.duration.instant} !important;
3031
+ animation-iteration-count: 1 !important;
3032
+ transition-duration: ${motion.duration.instant} !important;
3033
+ scroll-behavior: auto !important;
3034
+ }
3035
+
3036
+ /* Preserve essential state changes */
3037
+ [data-state] {
3038
+ transition: opacity ${config.allowReducedAnimations ? "100ms" : "0ms"} linear !important;
3039
+ }
3040
+ }
3041
+
3042
+ /* Reduced motion utility classes */
3043
+ .reduce-motion {
3044
+ animation: none !important;
3045
+ transition: none !important;
3046
+ }
3047
+
3048
+ .reduce-motion-safe {
3049
+ animation-duration: ${motion.duration.normal} !important;
3050
+ transition-duration: ${motion.duration.normal} !important;
3051
+ }
3052
+
3053
+ ${config.disableParallax ? `
3054
+ /* Disable parallax */
3055
+ .parallax,
3056
+ [data-parallax] {
3057
+ transform: none !important;
3058
+ position: relative !important;
3059
+ }
3060
+ ` : ""}
3061
+
3062
+ ${config.disableAutoPlay ? `
3063
+ /* Disable autoplay */
3064
+ video[autoplay],
3065
+ [data-autoplay] {
3066
+ animation-play-state: paused !important;
3067
+ }
3068
+ ` : ""}
3069
+ `.trim();
3070
+ }
3071
+ function generateFocusCss(tokens = ENHANCED_FOCUS) {
3072
+ return `
3073
+ /* Enhanced Focus Styles */
3074
+ :focus-visible {
3075
+ outline: ${tokens.outline.width} ${tokens.outline.style} ${tokens.outline.color};
3076
+ outline-offset: ${tokens.outline.offset};
3077
+ }
3078
+
3079
+ /* Focus ring utility */
3080
+ .focus-ring:focus-visible {
3081
+ box-shadow: 0 0 0 ${tokens.ring.offset} var(--nice-color-background, #fff),
3082
+ 0 0 0 calc(${tokens.ring.offset} + ${tokens.ring.width}) ${tokens.ring.color};
3083
+ }
3084
+
3085
+ /* Skip links */
3086
+ .skip-link {
3087
+ position: absolute;
3088
+ top: -40px;
3089
+ left: 0;
3090
+ padding: 8px 16px;
3091
+ background: ${tokens.ring.color};
3092
+ color: white;
3093
+ z-index: 100;
3094
+ transition: top 200ms ease;
3095
+ }
3096
+
3097
+ .skip-link:focus {
3098
+ top: 0;
3099
+ }
3100
+ `.trim();
3101
+ }
3102
+ function generateHighContrastCss(tokens = HIGH_CONTRAST) {
3103
+ return `
3104
+ /* High Contrast Mode */
3105
+ @media (prefers-contrast: more) {
3106
+ :root {
3107
+ --nice-text-primary: ${tokens.text.primary};
3108
+ --nice-text-secondary: ${tokens.text.secondary};
3109
+ --nice-text-tertiary: ${tokens.text.tertiary};
3110
+ --nice-text-disabled: ${tokens.text.disabled};
3111
+ --nice-bg-primary: ${tokens.background.primary};
3112
+ --nice-bg-secondary: ${tokens.background.secondary};
3113
+ --nice-bg-tertiary: ${tokens.background.tertiary};
3114
+ --nice-border-default: ${tokens.border.default};
3115
+ --nice-border-strong: ${tokens.border.strong};
3116
+ --nice-border-focus: ${tokens.border.focus};
3117
+ }
3118
+
3119
+ /* Ensure minimum contrast */
3120
+ * {
3121
+ border-color: ${tokens.border.default} !important;
3122
+ }
3123
+
3124
+ /* No transparent backgrounds */
3125
+ button,
3126
+ input,
3127
+ select,
3128
+ textarea {
3129
+ background-color: ${tokens.background.primary} !important;
3130
+ border: 2px solid ${tokens.border.default} !important;
3131
+ }
3132
+ }
3133
+
3134
+ /* High contrast utility classes */
3135
+ .high-contrast {
3136
+ --nice-text-primary: ${tokens.text.primary};
3137
+ --nice-bg-primary: ${tokens.background.primary};
3138
+ --nice-border-default: ${tokens.border.default};
3139
+ }
3140
+ `.trim();
3141
+ }
3142
+ function generateAccessibilityCss(options = {}) {
3143
+ const sections = [];
3144
+ sections.push(generateReducedMotionCss(options.reducedMotion));
3145
+ sections.push(generateFocusCss(options.focus));
3146
+ sections.push(generateHighContrastCss(options.contrast));
3147
+ if (options.typography) {
3148
+ sections.push(
3149
+ `
3150
+ /* Enhanced Typography */
3151
+ .enhanced-readability {
3152
+ font-size: ${options.typography.minSize};
3153
+ line-height: ${options.typography.lineHeight};
3154
+ letter-spacing: ${options.typography.letterSpacing};
3155
+ word-spacing: ${options.typography.wordSpacing};
3156
+ }
3157
+ `.trim()
3158
+ );
3159
+ }
3160
+ return sections.join("\n\n");
3161
+ }
3162
+ var STANDARD_ACCESSIBILITY = {
3163
+ motion: STANDARD_MOTION,
3164
+ focus: STANDARD_FOCUS,
3165
+ contrast: STANDARD_CONTRAST,
3166
+ typography: STANDARD_TYPOGRAPHY
3167
+ };
3168
+ var ENHANCED_ACCESSIBILITY = {
3169
+ motion: MINIMAL_MOTION,
3170
+ focus: ENHANCED_FOCUS,
3171
+ contrast: STANDARD_CONTRAST,
3172
+ typography: ENHANCED_TYPOGRAPHY
3173
+ };
3174
+ var MAXIMUM_ACCESSIBILITY = {
3175
+ motion: REDUCED_MOTION,
3176
+ focus: HIGH_VISIBILITY_FOCUS,
3177
+ contrast: HIGH_CONTRAST,
3178
+ typography: MAXIMUM_READABILITY_TYPOGRAPHY
3179
+ };
3180
+ function getLuminance(hex) {
3181
+ const rgb = hex.slice(1).match(/.{2}/g).map((c) => parseInt(c, 16) / 255).map((c) => c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4));
3182
+ return 0.2126 * rgb[0] + 0.7152 * rgb[1] + 0.0722 * rgb[2];
3183
+ }
3184
+ function getContrastRatio2(color1, color2) {
3185
+ const l1 = getLuminance(color1);
3186
+ const l2 = getLuminance(color2);
3187
+ const lighter = Math.max(l1, l2);
3188
+ const darker = Math.min(l1, l2);
3189
+ return (lighter + 0.05) / (darker + 0.05);
3190
+ }
3191
+ function checkContrast(foreground, background, level = "AA", isLargeText = false) {
3192
+ const ratio = getContrastRatio2(foreground, background);
3193
+ let required;
3194
+ if (level === "AAA") {
3195
+ required = isLargeText ? 4.5 : 7;
3196
+ } else {
3197
+ required = isLargeText ? 3 : 4.5;
3198
+ }
3199
+ return {
3200
+ passes: ratio >= required,
3201
+ ratio: Math.round(ratio * 100) / 100,
3202
+ required
3203
+ };
3204
+ }
3205
+ function suggestAccessibleColor(color, background, targetRatio = 4.5) {
3206
+ const currentRatio = getContrastRatio2(color, background);
3207
+ if (currentRatio >= targetRatio) {
3208
+ return color;
3209
+ }
3210
+ const r = parseInt(color.slice(1, 3), 16);
3211
+ const g = parseInt(color.slice(3, 5), 16);
3212
+ const b = parseInt(color.slice(5, 7), 16);
3213
+ const bgLuminance = getLuminance(background);
3214
+ const shouldDarken = bgLuminance > 0.5;
3215
+ const factor = shouldDarken ? 0.9 : 1.1;
3216
+ let adjustedR = r, adjustedG = g, adjustedB = b;
3217
+ for (let i = 0; i < 50; i++) {
3218
+ if (shouldDarken) {
3219
+ adjustedR = Math.max(0, Math.floor(adjustedR * factor));
3220
+ adjustedG = Math.max(0, Math.floor(adjustedG * factor));
3221
+ adjustedB = Math.max(0, Math.floor(adjustedB * factor));
3222
+ } else {
3223
+ adjustedR = Math.min(255, Math.floor(adjustedR * factor));
3224
+ adjustedG = Math.min(255, Math.floor(adjustedG * factor));
3225
+ adjustedB = Math.min(255, Math.floor(adjustedB * factor));
3226
+ }
3227
+ const adjusted = `#${adjustedR.toString(16).padStart(2, "0")}${adjustedG.toString(16).padStart(2, "0")}${adjustedB.toString(16).padStart(2, "0")}`;
3228
+ if (getContrastRatio2(adjusted, background) >= targetRatio) {
3229
+ return adjusted;
3230
+ }
3231
+ }
3232
+ return shouldDarken ? "#000000" : "#ffffff";
3233
+ }
3234
+
3235
+ // src/css-only.ts
3236
+ function tokensToCssVariables(tokens, config = {}) {
3237
+ const prefix = config.prefix || "nice";
3238
+ const flatTokens = flattenTokensToVariables(tokens.tokens, prefix);
3239
+ const rootLines = [":root {", ...flatTokens.map((t) => ` ${t.variable}: ${t.value};`), "}"];
3240
+ const root = rootLines.join("\n");
3241
+ let dark;
3242
+ if (config.includeDarkMode && tokens.themes?.dark) {
3243
+ const darkTokens = flattenTokensToVariables(tokens.themes.dark, prefix);
3244
+ dark = [
3245
+ "@media (prefers-color-scheme: dark) {",
3246
+ " :root {",
3247
+ ...darkTokens.map((t) => ` ${t.variable}: ${t.value};`),
3248
+ " }",
3249
+ "}",
3250
+ "",
3251
+ '[data-theme="dark"] {',
3252
+ ...darkTokens.map((t) => ` ${t.variable}: ${t.value};`),
3253
+ "}"
3254
+ ].join("\n");
3255
+ }
3256
+ let highContrast;
3257
+ if (config.includeHighContrast && tokens.themes?.["high-contrast"]) {
3258
+ const hcTokens = flattenTokensToVariables(tokens.themes["high-contrast"], prefix);
3259
+ highContrast = [
3260
+ "@media (prefers-contrast: more) {",
3261
+ " :root {",
3262
+ ...hcTokens.map((t) => ` ${t.variable}: ${t.value};`),
3263
+ " }",
3264
+ "}",
3265
+ "",
3266
+ '[data-theme="high-contrast"] {',
3267
+ ...hcTokens.map((t) => ` ${t.variable}: ${t.value};`),
3268
+ "}"
3269
+ ].join("\n");
3270
+ }
3271
+ let reducedMotion;
3272
+ if (config.includeReducedMotion) {
3273
+ reducedMotion = generateReducedMotionStyles(prefix);
3274
+ }
3275
+ const utilities = generateUtilityClasses(prefix);
3276
+ const reset = generateMinimalReset(prefix);
3277
+ const sections = [root];
3278
+ if (dark) {
3279
+ sections.push(dark);
3280
+ }
3281
+ if (highContrast) {
3282
+ sections.push(highContrast);
3283
+ }
3284
+ if (reducedMotion) {
3285
+ sections.push(reducedMotion);
3286
+ }
3287
+ if (reset) {
3288
+ sections.push(reset);
3289
+ }
3290
+ if (utilities) {
3291
+ sections.push(utilities);
3292
+ }
3293
+ let combined = sections.join("\n\n");
3294
+ if (config.useLayers) {
3295
+ combined = wrapInLayers(combined);
3296
+ }
3297
+ return {
3298
+ root,
3299
+ dark,
3300
+ highContrast,
3301
+ reducedMotion,
3302
+ utilities,
3303
+ reset,
3304
+ combined
3305
+ };
3306
+ }
3307
+ function flattenTokensToVariables(input, prefix, path3 = []) {
3308
+ const result = [];
3309
+ if (Array.isArray(input)) {
3310
+ for (const token of input) {
3311
+ result.push({
3312
+ variable: token.cssVariable || `--${prefix}-${token.path.join("-")}`,
3313
+ value: token.resolvedValue,
3314
+ path: token.path.join(".")
3315
+ });
3316
+ }
3317
+ return result;
3318
+ }
3319
+ for (const [key, value] of Object.entries(input)) {
3320
+ const currentPath = [...path3, key];
3321
+ if (typeof value === "object" && value !== null && "$value" in value) {
3322
+ const token = value;
3323
+ const variable = `--${prefix}-${currentPath.join("-")}`;
3324
+ result.push({
3325
+ variable,
3326
+ value: formatTokenValue(token.$value, token.$type),
3327
+ path: currentPath.join(".")
3328
+ });
3329
+ } else if (typeof value === "object" && value !== null) {
3330
+ result.push(
3331
+ ...flattenTokensToVariables(value, prefix, currentPath)
3332
+ );
3333
+ }
3334
+ }
3335
+ return result;
3336
+ }
3337
+ function formatTokenValue(value, type) {
3338
+ if (typeof value === "string") {
3339
+ if (value.startsWith("{") && value.endsWith("}")) {
3340
+ const path3 = value.slice(1, -1).replace(/\./g, "-");
3341
+ return `var(--nice-${path3})`;
3342
+ }
3343
+ return value;
3344
+ }
3345
+ if (typeof value === "number") {
3346
+ if (type === "dimension") {
3347
+ return `${value}px`;
3348
+ }
3349
+ return String(value);
3350
+ }
3351
+ if (Array.isArray(value)) {
3352
+ if (type === "fontFamily") {
3353
+ return value.join(", ");
3354
+ }
3355
+ return value.join(" ");
3356
+ }
3357
+ if (typeof value === "object" && value !== null) {
3358
+ const obj = value;
3359
+ if (type === "shadow") {
3360
+ const offsetX = obj.offsetX || "0";
3361
+ const offsetY = obj.offsetY || "0";
3362
+ const blur = obj.blur || "0";
3363
+ const spread = obj.spread || "0";
3364
+ const color = obj.color || "rgba(0,0,0,0.1)";
3365
+ return `${offsetX} ${offsetY} ${blur} ${spread} ${color}`;
3366
+ }
3367
+ if (type === "typography") {
3368
+ const fontSize = obj.fontSize || "1rem";
3369
+ const fontWeight = obj.fontWeight || "400";
3370
+ const lineHeight = obj.lineHeight || "1.5";
3371
+ const fontFamily = Array.isArray(obj.fontFamily) ? obj.fontFamily.join(", ") : obj.fontFamily || "inherit";
3372
+ return `${fontWeight} ${fontSize}/${lineHeight} ${fontFamily}`;
3373
+ }
3374
+ }
3375
+ return String(value);
3376
+ }
3377
+ function presetToCss(preset, config = {}) {
3378
+ const prefix = config.prefix || "nice";
3379
+ const lines = [];
3380
+ lines.push(`/* ${preset.displayName} Theme */`);
3381
+ lines.push(`/* Generated by Nice2Dev Design Tokens */`);
3382
+ lines.push("");
3383
+ lines.push(":root {");
3384
+ for (const [colorName, colorValue] of Object.entries(preset.colors)) {
3385
+ if (typeof colorValue === "string") {
3386
+ lines.push(` --${prefix}-color-${colorName}: ${colorValue};`);
3387
+ } else if (typeof colorValue === "object" && colorValue !== null) {
3388
+ const scale = colorValue;
3389
+ for (const [shade, hex] of Object.entries(scale)) {
3390
+ lines.push(` --${prefix}-color-${colorName}-${shade}: ${hex};`);
3391
+ }
3392
+ }
3393
+ }
3394
+ if (preset.typography) {
3395
+ lines.push(` --${prefix}-font-body: ${preset.typography.fontFamily};`);
3396
+ if (preset.typography.headingFontFamily) {
3397
+ lines.push(` --${prefix}-font-heading: ${preset.typography.headingFontFamily};`);
3398
+ }
3399
+ }
3400
+ if (preset.borderRadius) {
3401
+ const radii = {
3402
+ none: "0",
3403
+ sm: "0.25rem",
3404
+ md: "0.5rem",
3405
+ lg: "1rem",
3406
+ full: "9999px"
3407
+ };
3408
+ lines.push(` --${prefix}-radius: ${radii[preset.borderRadius]};`);
3409
+ }
3410
+ if (preset.shadows) {
3411
+ const shadowMap = {
3412
+ none: { sm: "none", md: "none", lg: "none" },
3413
+ sm: {
3414
+ sm: "0 1px 2px rgba(0,0,0,0.05)",
3415
+ md: "0 2px 4px rgba(0,0,0,0.05)",
3416
+ lg: "0 4px 8px rgba(0,0,0,0.05)"
3417
+ },
3418
+ md: {
3419
+ sm: "0 1px 3px rgba(0,0,0,0.1)",
3420
+ md: "0 4px 6px rgba(0,0,0,0.1)",
3421
+ lg: "0 10px 15px rgba(0,0,0,0.1)"
3422
+ },
3423
+ lg: {
3424
+ sm: "0 2px 4px rgba(0,0,0,0.15)",
3425
+ md: "0 8px 16px rgba(0,0,0,0.15)",
3426
+ lg: "0 20px 40px rgba(0,0,0,0.15)"
3427
+ }
3428
+ };
3429
+ const shadows = shadowMap[preset.shadows];
3430
+ lines.push(` --${prefix}-shadow-sm: ${shadows.sm};`);
3431
+ lines.push(` --${prefix}-shadow-md: ${shadows.md};`);
3432
+ lines.push(` --${prefix}-shadow-lg: ${shadows.lg};`);
3433
+ }
3434
+ lines.push("}");
3435
+ return lines.join("\n");
3436
+ }
3437
+ function generateUtilityClasses(prefix) {
3438
+ return `
3439
+ /* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
3440
+ UTILITY CLASSES
3441
+ Generated CSS utilities using CSS variables
3442
+ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */
3443
+
3444
+ /* Colors */
3445
+ .text-primary { color: var(--${prefix}-color-primary-500); }
3446
+ .text-secondary { color: var(--${prefix}-color-secondary-500); }
3447
+ .text-accent { color: var(--${prefix}-color-accent-500); }
3448
+ .text-success { color: var(--${prefix}-color-success); }
3449
+ .text-warning { color: var(--${prefix}-color-warning); }
3450
+ .text-error { color: var(--${prefix}-color-error); }
3451
+ .text-info { color: var(--${prefix}-color-info); }
3452
+
3453
+ .bg-primary { background-color: var(--${prefix}-color-primary-500); }
3454
+ .bg-secondary { background-color: var(--${prefix}-color-secondary-500); }
3455
+ .bg-accent { background-color: var(--${prefix}-color-accent-500); }
3456
+ .bg-success { background-color: var(--${prefix}-color-success); }
3457
+ .bg-warning { background-color: var(--${prefix}-color-warning); }
3458
+ .bg-error { background-color: var(--${prefix}-color-error); }
3459
+ .bg-info { background-color: var(--${prefix}-color-info); }
3460
+
3461
+ /* Border */
3462
+ .border-primary { border-color: var(--${prefix}-color-primary-500); }
3463
+ .rounded { border-radius: var(--${prefix}-radius); }
3464
+ .rounded-sm { border-radius: calc(var(--${prefix}-radius) * 0.5); }
3465
+ .rounded-lg { border-radius: calc(var(--${prefix}-radius) * 2); }
3466
+ .rounded-full { border-radius: 9999px; }
3467
+
3468
+ /* Shadows */
3469
+ .shadow-sm { box-shadow: var(--${prefix}-shadow-sm); }
3470
+ .shadow-md { box-shadow: var(--${prefix}-shadow-md); }
3471
+ .shadow-lg { box-shadow: var(--${prefix}-shadow-lg); }
3472
+ .shadow-none { box-shadow: none; }
3473
+
3474
+ /* Typography */
3475
+ .font-body { font-family: var(--${prefix}-font-body); }
3476
+ .font-heading { font-family: var(--${prefix}-font-heading, var(--${prefix}-font-body)); }
3477
+
3478
+ /* Focus */
3479
+ .focus-ring:focus-visible {
3480
+ outline: 2px solid var(--${prefix}-color-primary-500);
3481
+ outline-offset: 2px;
3482
+ }
3483
+ `.trim();
3484
+ }
3485
+ function generateMinimalReset(prefix) {
3486
+ return `
3487
+ /* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
3488
+ MINIMAL RESET
3489
+ Component-ready CSS reset using design tokens
3490
+ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */
3491
+
3492
+ *, *::before, *::after {
3493
+ box-sizing: border-box;
3494
+ margin: 0;
3495
+ padding: 0;
3496
+ }
3497
+
3498
+ html {
3499
+ font-family: var(--${prefix}-font-body, system-ui, sans-serif);
3500
+ line-height: 1.5;
3501
+ -webkit-text-size-adjust: 100%;
3502
+ -webkit-font-smoothing: antialiased;
3503
+ -moz-osx-font-smoothing: grayscale;
3504
+ }
3505
+
3506
+ body {
3507
+ min-height: 100vh;
3508
+ color: var(--${prefix}-color-neutral-900);
3509
+ background-color: var(--${prefix}-color-neutral-50);
3510
+ }
3511
+
3512
+ h1, h2, h3, h4, h5, h6 {
3513
+ font-family: var(--${prefix}-font-heading, var(--${prefix}-font-body));
3514
+ font-weight: 600;
3515
+ line-height: 1.25;
3516
+ }
3517
+
3518
+ a {
3519
+ color: var(--${prefix}-color-primary-500);
3520
+ text-decoration: none;
3521
+ }
3522
+
3523
+ a:hover {
3524
+ color: var(--${prefix}-color-primary-600);
3525
+ text-decoration: underline;
3526
+ }
3527
+
3528
+ button, input, select, textarea {
3529
+ font-family: inherit;
3530
+ font-size: inherit;
3531
+ line-height: inherit;
3532
+ }
3533
+
3534
+ button {
3535
+ cursor: pointer;
3536
+ border: none;
3537
+ background: transparent;
3538
+ }
3539
+
3540
+ img, svg, video {
3541
+ display: block;
3542
+ max-width: 100%;
3543
+ height: auto;
3544
+ }
3545
+ `.trim();
3546
+ }
3547
+ function generateReducedMotionStyles(prefix) {
3548
+ return `
3549
+ /* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
3550
+ REDUCED MOTION
3551
+ Respect user preferences for reduced motion
3552
+ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */
3553
+
3554
+ @media (prefers-reduced-motion: reduce) {
3555
+ *, *::before, *::after {
3556
+ animation-duration: 0.01ms !important;
3557
+ animation-iteration-count: 1 !important;
3558
+ transition-duration: 0.01ms !important;
3559
+ scroll-behavior: auto !important;
3560
+ }
3561
+ }
3562
+
3563
+ /* Motion-safe utilities */
3564
+ @media (prefers-reduced-motion: no-preference) {
3565
+ .animate-fade-in {
3566
+ animation: ${prefix}-fade-in 200ms ease-out;
3567
+ }
3568
+
3569
+ .animate-slide-up {
3570
+ animation: ${prefix}-slide-up 200ms ease-out;
3571
+ }
3572
+
3573
+ .animate-scale-in {
3574
+ animation: ${prefix}-scale-in 200ms ease-out;
3575
+ }
3576
+ }
3577
+
3578
+ @keyframes ${prefix}-fade-in {
3579
+ from { opacity: 0; }
3580
+ to { opacity: 1; }
3581
+ }
3582
+
3583
+ @keyframes ${prefix}-slide-up {
3584
+ from { opacity: 0; transform: translateY(10px); }
3585
+ to { opacity: 1; transform: translateY(0); }
3586
+ }
3587
+
3588
+ @keyframes ${prefix}-scale-in {
3589
+ from { opacity: 0; transform: scale(0.95); }
3590
+ to { opacity: 1; transform: scale(1); }
3591
+ }
3592
+ `.trim();
3593
+ }
3594
+ function wrapInLayers(css) {
3595
+ return `
3596
+ /* Define layer order */
3597
+ @layer reset, tokens, utilities, components;
3598
+
3599
+ @layer tokens {
3600
+ ${css.split("\n").map((l) => ` ${l}`).join("\n")}
3601
+ }
3602
+ `.trim();
3603
+ }
3604
+ function generateComponentStyles(prefix = "nice") {
3605
+ return `
3606
+ /* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
3607
+ CSS-ONLY COMPONENT STYLES
3608
+ No CSS-in-JS required \u2014 pure CSS variables approach
3609
+ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */
3610
+
3611
+ /* Button */
3612
+ .${prefix}-button {
3613
+ display: inline-flex;
3614
+ align-items: center;
3615
+ justify-content: center;
3616
+ gap: 0.5rem;
3617
+ padding: 0.5rem 1rem;
3618
+ font-weight: 500;
3619
+ border-radius: var(--${prefix}-radius, 0.5rem);
3620
+ transition: all 150ms ease;
3621
+ }
3622
+
3623
+ .${prefix}-button--primary {
3624
+ background-color: var(--${prefix}-color-primary-500);
3625
+ color: white;
3626
+ }
3627
+
3628
+ .${prefix}-button--primary:hover {
3629
+ background-color: var(--${prefix}-color-primary-600);
3630
+ }
3631
+
3632
+ .${prefix}-button--secondary {
3633
+ background-color: var(--${prefix}-color-neutral-100);
3634
+ color: var(--${prefix}-color-neutral-900);
3635
+ }
3636
+
3637
+ .${prefix}-button--secondary:hover {
3638
+ background-color: var(--${prefix}-color-neutral-200);
3639
+ }
3640
+
3641
+ .${prefix}-button--outline {
3642
+ border: 1px solid var(--${prefix}-color-primary-500);
3643
+ color: var(--${prefix}-color-primary-500);
3644
+ background: transparent;
3645
+ }
3646
+
3647
+ .${prefix}-button--outline:hover {
3648
+ background-color: var(--${prefix}-color-primary-50);
3649
+ }
3650
+
3651
+ .${prefix}-button:disabled {
3652
+ opacity: 0.5;
3653
+ cursor: not-allowed;
3654
+ }
3655
+
3656
+ /* Input */
3657
+ .${prefix}-input {
3658
+ width: 100%;
3659
+ padding: 0.5rem 0.75rem;
3660
+ border: 1px solid var(--${prefix}-color-neutral-300);
3661
+ border-radius: var(--${prefix}-radius, 0.5rem);
3662
+ background-color: var(--${prefix}-color-neutral-50);
3663
+ transition: border-color 150ms ease, box-shadow 150ms ease;
3664
+ }
3665
+
3666
+ .${prefix}-input:focus {
3667
+ outline: none;
3668
+ border-color: var(--${prefix}-color-primary-500);
3669
+ box-shadow: 0 0 0 3px var(--${prefix}-color-primary-100);
3670
+ }
3671
+
3672
+ .${prefix}-input:disabled {
3673
+ opacity: 0.5;
3674
+ cursor: not-allowed;
3675
+ }
3676
+
3677
+ .${prefix}-input--error {
3678
+ border-color: var(--${prefix}-color-error);
3679
+ }
3680
+
3681
+ /* Card */
3682
+ .${prefix}-card {
3683
+ background-color: var(--${prefix}-color-neutral-50);
3684
+ border: 1px solid var(--${prefix}-color-neutral-200);
3685
+ border-radius: var(--${prefix}-radius, 0.5rem);
3686
+ box-shadow: var(--${prefix}-shadow-sm);
3687
+ }
3688
+
3689
+ .${prefix}-card__header {
3690
+ padding: 1rem 1.5rem;
3691
+ border-bottom: 1px solid var(--${prefix}-color-neutral-200);
3692
+ }
3693
+
3694
+ .${prefix}-card__body {
3695
+ padding: 1.5rem;
3696
+ }
3697
+
3698
+ .${prefix}-card__footer {
3699
+ padding: 1rem 1.5rem;
3700
+ border-top: 1px solid var(--${prefix}-color-neutral-200);
3701
+ }
3702
+
3703
+ /* Badge */
3704
+ .${prefix}-badge {
3705
+ display: inline-flex;
3706
+ align-items: center;
3707
+ padding: 0.25rem 0.5rem;
3708
+ font-size: 0.75rem;
3709
+ font-weight: 500;
3710
+ border-radius: 9999px;
3711
+ }
3712
+
3713
+ .${prefix}-badge--primary {
3714
+ background-color: var(--${prefix}-color-primary-100);
3715
+ color: var(--${prefix}-color-primary-700);
3716
+ }
3717
+
3718
+ .${prefix}-badge--success {
3719
+ background-color: #dcfce7;
3720
+ color: #166534;
3721
+ }
3722
+
3723
+ .${prefix}-badge--warning {
3724
+ background-color: #fef3c7;
3725
+ color: #92400e;
3726
+ }
3727
+
3728
+ .${prefix}-badge--error {
3729
+ background-color: #fee2e2;
3730
+ color: #991b1b;
3731
+ }
3732
+
3733
+ /* Alert */
3734
+ .${prefix}-alert {
3735
+ display: flex;
3736
+ gap: 0.75rem;
3737
+ padding: 1rem;
3738
+ border-radius: var(--${prefix}-radius, 0.5rem);
3739
+ }
3740
+
3741
+ .${prefix}-alert--info {
3742
+ background-color: #eff6ff;
3743
+ border: 1px solid #bfdbfe;
3744
+ color: #1e40af;
3745
+ }
3746
+
3747
+ .${prefix}-alert--success {
3748
+ background-color: #f0fdf4;
3749
+ border: 1px solid #bbf7d0;
3750
+ color: #166534;
3751
+ }
3752
+
3753
+ .${prefix}-alert--warning {
3754
+ background-color: #fffbeb;
3755
+ border: 1px solid #fde68a;
3756
+ color: #92400e;
3757
+ }
3758
+
3759
+ .${prefix}-alert--error {
3760
+ background-color: #fef2f2;
3761
+ border: 1px solid #fecaca;
3762
+ color: #991b1b;
3763
+ }
3764
+ `.trim();
3765
+ }
3766
+ function generateCompleteStylesheet(preset, config = {}) {
3767
+ const prefix = config.prefix || "nice";
3768
+ const sections = [];
3769
+ sections.push(`/**
3770
+ * ${preset.displayName} Theme Stylesheet
3771
+ * Generated by Nice2Dev Design Tokens
3772
+ * CSS-only approach \u2014 no CSS-in-JS runtime
3773
+ */`);
3774
+ if (config.useLayers) {
3775
+ sections.push("@layer reset, tokens, utilities, components;");
3776
+ }
3777
+ sections.push(presetToCss(preset, config));
3778
+ sections.push(generateMinimalReset(prefix));
3779
+ sections.push(generateUtilityClasses(prefix));
3780
+ sections.push(generateComponentStyles(prefix));
3781
+ if (config.includeReducedMotion) {
3782
+ sections.push(generateReducedMotionStyles(prefix));
3783
+ }
3784
+ return sections.join("\n\n");
3785
+ }
3786
+ // Annotate the CommonJS export names for ESM import in node:
3787
+ 0 && (module.exports = {
3788
+ ENHANCED_ACCESSIBILITY,
3789
+ ENHANCED_FOCUS,
3790
+ ENHANCED_TYPOGRAPHY,
3791
+ HIGH_CONTRAST,
3792
+ HIGH_CONTRAST_DARK,
3793
+ HIGH_VISIBILITY_FOCUS,
3794
+ MAXIMUM_ACCESSIBILITY,
3795
+ MAXIMUM_READABILITY_TYPOGRAPHY,
3796
+ MINIMAL_MOTION,
3797
+ PRESETS,
3798
+ REDUCED_MOTION,
3799
+ STANDARD_ACCESSIBILITY,
3800
+ STANDARD_CONTRAST,
3801
+ STANDARD_FOCUS,
3802
+ STANDARD_MOTION,
3803
+ STANDARD_TYPOGRAPHY,
3804
+ TokenGenerator,
3805
+ analyzeColor,
3806
+ buildTokenObject,
3807
+ checkCircularReferences,
3808
+ checkContrast,
3809
+ createGenerator,
3810
+ createTheme,
3811
+ createTokenCollection,
3812
+ cubicBezierToCss,
3813
+ darkenColor,
3814
+ defaultOptions,
3815
+ defaultThemes,
3816
+ durationToMs,
3817
+ extractReferencePath,
3818
+ filterTokensByPath,
3819
+ filterTokensByType,
3820
+ findReferences,
3821
+ flattenTokens,
3822
+ fontWeightToNumber,
3823
+ generateAccessibilityCss,
3824
+ generateBrandKit,
3825
+ generateColorScale,
3826
+ generateColorScaleAsync,
3827
+ generateCompleteStylesheet,
3828
+ generateComponentStyles,
3829
+ generateDarkModeTokens,
3830
+ generateFocusCss,
3831
+ generateHighContrastCss,
3832
+ generateHighContrastTokens,
3833
+ generateReactThemeContext,
3834
+ generateReducedMotionCss,
3835
+ generateThemeSwitcher,
3836
+ generateThemesCss,
3837
+ generateTokenTypes,
3838
+ generateTokens,
3839
+ getAccessibleTextColor,
3840
+ getAllCategories,
3841
+ getCategories,
3842
+ getContrastRatio,
3843
+ getContrastRatioAsync,
3844
+ getDependencyGraph,
3845
+ getPresetByName,
3846
+ getPresetsByCategory,
3847
+ getTokenByPath,
3848
+ hexToHsl,
3849
+ hexToOklch,
3850
+ hexToRgb,
3851
+ industryBrandKit,
3852
+ isDesignToken,
3853
+ isReference,
3854
+ isTokenGroup,
3855
+ lightenColor,
3856
+ mergeTokenFiles,
3857
+ parseTokenDirectory,
3858
+ parseTokenFile,
3859
+ parseTokenFiles,
3860
+ pathToCssVariable,
3861
+ pathToString,
3862
+ presetToCss,
3863
+ presetToCssVariables,
3864
+ presetToTokens,
3865
+ pxToEm,
3866
+ pxToRem,
3867
+ quickBrandKit,
3868
+ remToPx,
3869
+ resolveToVariable,
3870
+ resolveTokenValue,
3871
+ resolveTokens,
3872
+ sortTokensByDependencies,
3873
+ suggestAccessibleColor,
3874
+ tokensToCssVariables,
3875
+ transformToCss,
3876
+ transformToJs,
3877
+ transformToScss,
3878
+ transformToTailwind,
3879
+ transformToTs
3880
+ });