@qw-ui/tokens 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,1182 @@
1
+ import { z } from 'zod';
2
+ import { rgb, parse, formatHex, oklch, clampChroma } from 'culori';
3
+
4
+ // src/seed/index.json
5
+ var seed_default = {
6
+ qw: {
7
+ seed: {
8
+ color: {
9
+ brand: { $value: { colorSpace: "srgb", components: [0, 0.0667, 1], alpha: 1 }, $type: "color" },
10
+ black: { $value: { colorSpace: "srgb", components: [0.1333, 0.1333, 0.1333], alpha: 1 }, $type: "color" },
11
+ white: { $value: { colorSpace: "srgb", components: [1, 1, 1], alpha: 1 }, $type: "color" },
12
+ gray: { $value: { colorSpace: "srgb", components: [0.6, 0.6, 0.6], alpha: 1 }, $type: "color" },
13
+ red: { $value: { colorSpace: "srgb", components: [1, 0.251, 0.251], alpha: 1 }, $type: "color" },
14
+ orange: { $value: { colorSpace: "srgb", components: [1, 0.4196, 0.2471], alpha: 1 }, $type: "color" },
15
+ yellow: { $value: { colorSpace: "srgb", components: [1, 0.8353, 0.4588], alpha: 1 }, $type: "color" },
16
+ green: { $value: { colorSpace: "srgb", components: [0.1216, 0.6, 0.2471], alpha: 1 }, $type: "color" },
17
+ cyan: { $value: { colorSpace: "srgb", components: [0.1608, 0.7451, 0.8], alpha: 1 }, $type: "color" },
18
+ blue: { $value: { colorSpace: "srgb", components: [0.051, 0.3255, 1], alpha: 1 }, $type: "color" },
19
+ purple: { $value: { colorSpace: "srgb", components: [0.2627, 0.1725, 0.8588], alpha: 1 }, $type: "color" },
20
+ brown: { $value: { colorSpace: "srgb", components: [0.7059, 0.3686, 0.0235], alpha: 1 }, $type: "color" }
21
+ },
22
+ size: {
23
+ spacing: {
24
+ step: { $value: { value: 4, unit: "px" }}
25
+ },
26
+ borderWidth: {
27
+ hairline: { $value: { value: 1, unit: "px" }}
28
+ },
29
+ radius: {
30
+ base: { $value: { value: 8, unit: "px" }},
31
+ full: { $value: { value: 9999, unit: "px" }}
32
+ },
33
+ controlSize: {
34
+ base: { $value: { value: 40, unit: "px" }}
35
+ },
36
+ iconSize: {
37
+ base: { $value: { value: 20, unit: "px" }}
38
+ },
39
+ opacity: {
40
+ disabled: { $value: 0.5},
41
+ alphaStep: { $value: 0.04}
42
+ },
43
+ zIndex: {
44
+ step: { $value: 10}
45
+ }
46
+ },
47
+ typography: {
48
+ fontFamily: {
49
+ text: { $value: ["system-ui", "-apple-system", "BlinkMacSystemFont", "Segoe UI", "Roboto", "Helvetica Neue", "Arial", "sans-serif"]},
50
+ number: { $value: ["PlusJakartaSans", "system-ui", "Segoe UI", "Roboto", "Helvetica Neue", "Arial", "sans-serif"]},
51
+ code: { $value: ["ui-monospace", "SFMono-Regular", "SF Mono", "Menlo", "Consolas", "Liberation Mono", "monospace"]},
52
+ textMacLatin: { $value: ["-apple-system", "BlinkMacSystemFont", "SF Pro Text", "system-ui", "Helvetica Neue", "Helvetica", "Arial", "sans-serif"]},
53
+ textMacZh: { $value: ["PingFang SC", "-apple-system", "BlinkMacSystemFont", "Hiragino Sans GB", "Hiragino Sans", "SF Pro Text", "system-ui", "Noto Sans SC", "Helvetica Neue", "Helvetica", "Arial", "sans-serif"]},
54
+ textMacJa: { $value: ["Hiragino Sans", "Hiragino Kaku Gothic ProN", "-apple-system", "BlinkMacSystemFont", "PingFang SC", "SF Pro Text", "system-ui", "Noto Sans JP", "Helvetica Neue", "Helvetica", "Arial", "sans-serif"]},
55
+ textWindowsLatin: { $value: ["Segoe UI", "system-ui", "Roboto", "Noto Sans", "Helvetica Neue", "Arial", "sans-serif"]},
56
+ textWindowsZh: { $value: ["Microsoft YaHei", "Segoe UI", "system-ui", "Roboto", "Noto Sans SC", "Helvetica Neue", "Arial", "sans-serif"]},
57
+ textWindowsJa: { $value: ["Meiryo", "Yu Gothic UI", "Segoe UI", "system-ui", "Roboto", "Noto Sans JP", "Helvetica Neue", "Arial", "sans-serif"]}
58
+ },
59
+ fontWeight: {
60
+ regular: { $value: 400},
61
+ medium: { $value: 500},
62
+ semibold: { $value: 600}
63
+ },
64
+ fontSize: {
65
+ base: { $value: { value: 14, unit: "px" }}
66
+ },
67
+ lineHeight: {
68
+ base: { $value: 1.5}
69
+ },
70
+ letterSpacing: {
71
+ base: { $value: { value: 0, unit: "px" }}
72
+ }
73
+ },
74
+ motion: {
75
+ duration: {
76
+ base: { $value: { value: 200, unit: "ms" }}
77
+ },
78
+ easing: {
79
+ standard: { $value: [0.16, 1, 0.3, 1]}
80
+ }
81
+ },
82
+ effect: {
83
+ shadow: {
84
+ base: {
85
+ $value: {
86
+ color: { colorSpace: "srgb", components: [0, 0, 0], alpha: 0.08 },
87
+ offsetX: { value: 0, unit: "px" },
88
+ offsetY: { value: 2, unit: "px" },
89
+ blur: { value: 4, unit: "px" },
90
+ spread: { value: 0, unit: "px" }
91
+ }}
92
+ }
93
+ }
94
+ }
95
+ }
96
+ };
97
+
98
+ // src/color-architecture.ts
99
+ var FIGMA_COLOR_COLLECTION = "Color";
100
+ var FIGMA_COLOR_PREFIX = "qw";
101
+ var T1_COLOR_KEYS = [
102
+ "brand",
103
+ "black",
104
+ "white",
105
+ "gray",
106
+ "red",
107
+ "orange",
108
+ "yellow",
109
+ "green",
110
+ "cyan",
111
+ "blue",
112
+ "purple",
113
+ "brown"
114
+ ];
115
+ var FIGMA_T1_SEED_HEX = {
116
+ brand: "#0011FF",
117
+ black: "#222222",
118
+ white: "#FFFFFF",
119
+ gray: "#999999",
120
+ red: "#FF4040",
121
+ orange: "#FF6B3F",
122
+ yellow: "#FFD575",
123
+ green: "#1F993F",
124
+ cyan: "#29BECC",
125
+ blue: "#0D53FF",
126
+ purple: "#432CDB",
127
+ brown: "#B45E06"
128
+ };
129
+ var T2_ALPHA_STEPS = [5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100];
130
+ var T2_ALPHA_KEYS = T2_ALPHA_STEPS.map((step) => `a${step}`);
131
+ var T2_OKLCH_STEPS = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900];
132
+ var FIGMA_T2_SOLID_SCALE = {
133
+ brand: {
134
+ 50: "#F2F6FF",
135
+ 100: "#E6ECFF",
136
+ 200: "#C4D8FF",
137
+ 300: "#9DBDFF",
138
+ 400: "#6C9AFF",
139
+ 500: "#426EFF",
140
+ 600: "#1B57FF",
141
+ 700: "#002CE8",
142
+ 800: "#001A99",
143
+ 900: "#000540"
144
+ },
145
+ black: {
146
+ 50: "#F6F6F6",
147
+ 100: "#EBEBEB",
148
+ 200: "#D7D7D7",
149
+ 300: "#BEBEBE",
150
+ 400: "#9E9E9E",
151
+ 500: "#868686",
152
+ 600: "#6F6F6F",
153
+ 700: "#555555",
154
+ 800: "#353535",
155
+ 900: "#121212"
156
+ },
157
+ white: {
158
+ 50: "#F6F6F6",
159
+ 100: "#EBEBEB",
160
+ 200: "#D7D7D7",
161
+ 300: "#BEBEBE",
162
+ 400: "#9E9E9E",
163
+ 500: "#868686",
164
+ 600: "#6F6F6F",
165
+ 700: "#555555",
166
+ 800: "#353535",
167
+ 900: "#121212"
168
+ },
169
+ gray: {
170
+ 50: "#F6F6F6",
171
+ 100: "#EEEEEE",
172
+ 200: "#E0E0E0",
173
+ 300: "#CCCCCC",
174
+ 400: "#A2A9B6",
175
+ 500: "#888E99",
176
+ 600: "#666666",
177
+ 700: "#3A3A3A",
178
+ 800: "#2D2D2D",
179
+ 900: "#202020"
180
+ },
181
+ red: {
182
+ 50: "#FFF3F1",
183
+ 100: "#FFE7E4",
184
+ 200: "#FFC8C2",
185
+ 300: "#FFA097",
186
+ 400: "#FF5745",
187
+ 500: "#FF4D4D",
188
+ 600: "#CF081E",
189
+ 700: "#A30013",
190
+ 800: "#6A0009",
191
+ 900: "#2A0001"
192
+ },
193
+ orange: {
194
+ 50: "#FFF3EF",
195
+ 100: "#FFE5DD",
196
+ 200: "#FFC9B9",
197
+ 300: "#FFA287",
198
+ 400: "#F76F47",
199
+ 500: "#FF764D",
200
+ 600: "#C03800",
201
+ 700: "#962A00",
202
+ 800: "#611800",
203
+ 900: "#260500"
204
+ },
205
+ yellow: {
206
+ 50: "#FFF5DF",
207
+ 100: "#FFE9B9",
208
+ 200: "#F4D38B",
209
+ 300: "#DCB96B",
210
+ 400: "#BE9940",
211
+ 500: "#A78013",
212
+ 600: "#8B6900",
213
+ 700: "#6C5100",
214
+ 800: "#453200",
215
+ 900: "#191000"
216
+ },
217
+ green: {
218
+ 50: "#E2FFE4",
219
+ 100: "#BCFFC3",
220
+ 200: "#9BEFA5",
221
+ 300: "#7BD688",
222
+ 400: "#52B764",
223
+ 500: "#2C9F47",
224
+ 600: "#068631",
225
+ 700: "#006823",
226
+ 800: "#004213",
227
+ 900: "#001704"
228
+ },
229
+ cyan: {
230
+ 50: "#E0FCFF",
231
+ 100: "#BAF8FF",
232
+ 200: "#91EAF2",
233
+ 300: "#65D0DC",
234
+ 400: "#2FB2BE",
235
+ 500: "#0098A4",
236
+ 600: "#007E88",
237
+ 700: "#006169",
238
+ 800: "#003D43",
239
+ 900: "#001518"
240
+ },
241
+ blue: {
242
+ 50: "#EBF5FF",
243
+ 100: "#E7F1FF",
244
+ 200: "#D6EBFF",
245
+ 300: "#9CBEFF",
246
+ 400: "#3086FF",
247
+ 500: "#1677FF",
248
+ 600: "#266FFF",
249
+ 700: "#003DB8",
250
+ 800: "#001D66",
251
+ 900: "#000A3A"
252
+ },
253
+ purple: {
254
+ 50: "#F3F5FF",
255
+ 100: "#E6EAFF",
256
+ 200: "#CDD5FF",
257
+ 300: "#A699FF",
258
+ 400: "#8692FF",
259
+ 500: "#6B71FF",
260
+ 600: "#5550F2",
261
+ 700: "#4135C9",
262
+ 800: "#280B96",
263
+ 900: "#0C0041"
264
+ },
265
+ brown: {
266
+ 50: "#FFF3EC",
267
+ 100: "#FFE6D5",
268
+ 200: "#FFCBA8",
269
+ 300: "#F8A971",
270
+ 400: "#DA8749",
271
+ 500: "#C36D24",
272
+ 600: "#A75600",
273
+ 700: "#824100",
274
+ 800: "#542800",
275
+ 900: "#200B00"
276
+ }
277
+ };
278
+ var FIGMA_T3_COLOR_ROLES = {
279
+ "surface.base": { light: "color.white.base", dark: "color.black.base" },
280
+ "surface.subtle": { light: "color.gray.50", dark: "color.gray.900" },
281
+ "surface.elevated": { light: "color.white.base", dark: "color.gray.800" },
282
+ "surface.header": { light: "color.gray.100", dark: "color.gray.700" },
283
+ "surface.brand-subtle": { light: "color.blue.50", dark: "color.blue.800" },
284
+ "content.primary": { light: "color.black.base", dark: "color.white.base" },
285
+ "content.secondary": { light: "color.gray.600", dark: "color.gray.base" },
286
+ "content.tertiary": { light: "color.gray.base", dark: "color.gray.600" },
287
+ "content.placeholder": { light: "color.gray.300", dark: "color.white.a30" },
288
+ "content.intro": { light: "color.gray.400", dark: "color.gray.500" },
289
+ "border.default": { light: "color.gray.100", dark: "color.gray.700" },
290
+ "border.strong": { light: "color.gray.300", dark: "color.gray.600" },
291
+ "border.focus": { light: "color.brand.base", dark: "color.brand.500" },
292
+ "fill.subtle": { light: "color.gray.50", dark: "color.white.a20" },
293
+ "fill.hover": { light: "color.gray.100", dark: "color.gray.800" },
294
+ "fill.active": { light: "color.blue.50", dark: "color.blue.800" },
295
+ "fill.disabled": { light: "color.gray.50", dark: "color.gray.900" },
296
+ "action.brand": { light: "color.brand.base", dark: "color.brand.500" },
297
+ "action.product": { light: "color.blue.base", dark: "color.blue.600" },
298
+ "action.selected": { light: "color.blue.a20", dark: "color.blue.a40" },
299
+ "action.inverse": { light: "color.white.base", dark: "color.black.base" },
300
+ "status.success": { light: "color.green.base", dark: "color.green.base" },
301
+ "status.warning": { light: "color.yellow.base", dark: "color.yellow.base" },
302
+ "status.danger": { light: "color.red.400", dark: "color.red.400" },
303
+ "status.info": { light: "color.blue.base", dark: "color.blue.600" },
304
+ "overlay.scrim": { light: "color.black.a50", dark: "color.black.a70" },
305
+ "overlay.guide": { light: "color.black.a70", dark: "color.black.a70" }
306
+ };
307
+
308
+ // src/seed/index.ts
309
+ var s = seed_default.qw.seed;
310
+ var px = (d) => `${d.value}${d.unit}`;
311
+ var color = (v) => v;
312
+ var defaultSeed = {
313
+ color: Object.fromEntries(T1_COLOR_KEYS.map((key) => [key, color(s.color[key].$value)])),
314
+ size: {
315
+ spacing: {
316
+ step: px(s.size.spacing.step.$value)
317
+ },
318
+ borderWidth: {
319
+ hairline: px(s.size.borderWidth.hairline.$value)
320
+ },
321
+ radius: {
322
+ base: px(s.size.radius.base.$value),
323
+ full: px(s.size.radius.full.$value)
324
+ },
325
+ controlSize: {
326
+ base: px(s.size.controlSize.base.$value)
327
+ },
328
+ iconSize: {
329
+ base: px(s.size.iconSize.base.$value)
330
+ },
331
+ opacity: {
332
+ disabled: s.size.opacity.disabled.$value,
333
+ alphaStep: s.size.opacity.alphaStep.$value
334
+ },
335
+ zIndex: {
336
+ step: s.size.zIndex.step.$value
337
+ }
338
+ },
339
+ typography: {
340
+ fontFamily: {
341
+ text: s.typography.fontFamily.text.$value,
342
+ number: s.typography.fontFamily.number.$value,
343
+ code: s.typography.fontFamily.code.$value,
344
+ textMacLatin: s.typography.fontFamily.textMacLatin.$value,
345
+ textMacZh: s.typography.fontFamily.textMacZh.$value,
346
+ textMacJa: s.typography.fontFamily.textMacJa.$value,
347
+ textWindowsLatin: s.typography.fontFamily.textWindowsLatin.$value,
348
+ textWindowsZh: s.typography.fontFamily.textWindowsZh.$value,
349
+ textWindowsJa: s.typography.fontFamily.textWindowsJa.$value
350
+ },
351
+ fontWeight: {
352
+ regular: s.typography.fontWeight.regular.$value,
353
+ medium: s.typography.fontWeight.medium.$value,
354
+ semibold: s.typography.fontWeight.semibold.$value
355
+ },
356
+ fontSize: {
357
+ base: px(s.typography.fontSize.base.$value)
358
+ },
359
+ lineHeight: {
360
+ base: s.typography.lineHeight.base.$value
361
+ },
362
+ letterSpacing: {
363
+ base: px(s.typography.letterSpacing.base.$value)
364
+ }
365
+ },
366
+ motion: {
367
+ duration: {
368
+ base: px(s.motion.duration.base.$value)
369
+ },
370
+ easing: {
371
+ standard: s.motion.easing.standard.$value
372
+ }
373
+ },
374
+ effect: {
375
+ shadow: {
376
+ base: {
377
+ color: color(s.effect.shadow.base.$value.color),
378
+ offsetX: px(s.effect.shadow.base.$value.offsetX),
379
+ offsetY: px(s.effect.shadow.base.$value.offsetY),
380
+ blur: px(s.effect.shadow.base.$value.blur),
381
+ spread: px(s.effect.shadow.base.$value.spread)
382
+ }
383
+ }
384
+ }
385
+ };
386
+ var seedColor = z.object({
387
+ colorSpace: z.enum(["srgb", "oklch"]),
388
+ components: z.tuple([z.number(), z.number(), z.number()]),
389
+ alpha: z.number().min(0).max(1)
390
+ }).superRefine((c, ctx) => {
391
+ if (c.colorSpace === "srgb") {
392
+ if (c.components.some((v) => v < 0 || v > 1)) {
393
+ ctx.addIssue({
394
+ code: "custom",
395
+ message: "srgb components \u5FC5\u987B\u662F 0\u20131\uFF08\u4E0D\u662F 0\u2013255\uFF09\uFF0C\u4F8B\u5982 #0011ff \u2192 [0, 0.0667, 1]"
396
+ });
397
+ }
398
+ } else {
399
+ const [l, chroma] = c.components;
400
+ if (l < 0 || l > 1 || chroma < 0) {
401
+ ctx.addIssue({ code: "custom", message: "oklch \u8981\u6C42 l \u2208 [0,1] \u4E14 c \u2265 0" });
402
+ }
403
+ }
404
+ });
405
+ var cubicBezier = z.tuple([z.number(), z.number(), z.number(), z.number()]);
406
+ var fontStack = z.array(z.string()).min(1);
407
+ var colorSeedShape = Object.fromEntries(T1_COLOR_KEYS.map((key) => [key, seedColor]));
408
+ var SeedSchema = z.object({
409
+ color: z.object(colorSeedShape),
410
+ size: z.object({
411
+ spacing: z.object({
412
+ step: z.string()
413
+ }),
414
+ borderWidth: z.object({
415
+ hairline: z.string()
416
+ }),
417
+ radius: z.object({
418
+ /** 控件基准圆角;Reference 派生 sm=×0.5 / md=×1 / lg=×1.75。 */
419
+ base: z.string(),
420
+ /** 药丸/圆形裁切基准(独立设计决策,不从 base 派生)。 */
421
+ full: z.string()
422
+ }),
423
+ controlSize: z.object({
424
+ /** md 控件高度锚点;sm/lg = base ∓ spacing.step × 2。 */
425
+ base: z.string()
426
+ }),
427
+ iconSize: z.object({
428
+ /** md 图标尺寸锚点;sm/lg = base ∓ spacing.step。 */
429
+ base: z.string()
430
+ }),
431
+ opacity: z.object({
432
+ disabled: z.number().min(0).max(1),
433
+ alphaStep: z.number().min(0).max(1)
434
+ }),
435
+ zIndex: z.object({
436
+ step: z.number().int().positive()
437
+ })
438
+ }),
439
+ typography: z.object({
440
+ fontFamily: z.object({
441
+ /** 通用正文栈(跨平台缺省)。 */
442
+ text: fontStack,
443
+ /** 数字/数据展示栈。 */
444
+ number: fontStack,
445
+ /** 代码等宽栈。 */
446
+ code: fontStack,
447
+ /** 平台/语言细分变体,供上层按 UA/lang 重映射 text 角色。 */
448
+ textMacLatin: fontStack,
449
+ textMacZh: fontStack,
450
+ textMacJa: fontStack,
451
+ textWindowsLatin: fontStack,
452
+ textWindowsZh: fontStack,
453
+ textWindowsJa: fontStack
454
+ }),
455
+ fontWeight: z.object({
456
+ regular: z.number(),
457
+ medium: z.number(),
458
+ semibold: z.number()
459
+ }),
460
+ fontSize: z.object({
461
+ base: z.string()
462
+ }),
463
+ lineHeight: z.object({
464
+ base: z.number().positive()
465
+ }),
466
+ letterSpacing: z.object({
467
+ base: z.string()
468
+ })
469
+ }),
470
+ motion: z.object({
471
+ duration: z.object({
472
+ base: z.string()
473
+ }),
474
+ easing: z.object({
475
+ standard: cubicBezier
476
+ })
477
+ }),
478
+ effect: z.object({
479
+ shadow: z.object({
480
+ base: z.object({
481
+ color: seedColor,
482
+ offsetX: z.string(),
483
+ offsetY: z.string(),
484
+ blur: z.string(),
485
+ spread: z.string()
486
+ })
487
+ })
488
+ })
489
+ });
490
+ function validateSeed(seed) {
491
+ const r = SeedSchema.safeParse(seed);
492
+ if (!r.success) {
493
+ console.error("[qw] invalid seed:", r.error.format());
494
+ throw new Error("invalid seed");
495
+ }
496
+ return r.data;
497
+ }
498
+ function toCulori(c) {
499
+ if (c.colorSpace === "srgb") {
500
+ return { mode: "rgb", r: c.components[0], g: c.components[1], b: c.components[2], alpha: c.alpha };
501
+ }
502
+ return { mode: "oklch", l: c.components[0], c: c.components[1], h: c.components[2], alpha: c.alpha };
503
+ }
504
+ var round6 = (n) => Math.round(n * 1e6) / 1e6;
505
+ function hexToSeedColor(hex) {
506
+ const parsed = rgb(parse(hex));
507
+ if (!parsed) throw new Error(`[qw] \u65E0\u6CD5\u89E3\u6790\u989C\u8272: ${hex}`);
508
+ return {
509
+ colorSpace: "srgb",
510
+ components: [round6(parsed.r), round6(parsed.g), round6(parsed.b)],
511
+ alpha: parsed.alpha ?? 1
512
+ };
513
+ }
514
+ function seedColorToHex(c) {
515
+ const converted = rgb(toCulori(c));
516
+ if (!converted) throw new Error(`[qw] \u65E0\u6CD5\u8F6C\u6362\u989C\u8272: ${JSON.stringify(c)}`);
517
+ return formatHex(converted) ?? "#000000";
518
+ }
519
+ function seedColorToCss(c) {
520
+ if (c.colorSpace === "oklch") {
521
+ const [l, ch, h] = c.components;
522
+ return c.alpha >= 1 ? `oklch(${l} ${ch} ${h})` : `oklch(${l} ${ch} ${h} / ${c.alpha})`;
523
+ }
524
+ if (c.alpha >= 1) return seedColorToHex(c);
525
+ const [r, g, b] = c.components.map((v) => Math.round(v * 255));
526
+ return `rgb(${r} ${g} ${b} / ${c.alpha})`;
527
+ }
528
+ var STEPS = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900];
529
+ var L_TARGETS = {
530
+ 50: 0.972,
531
+ 100: 0.94,
532
+ 200: 0.88,
533
+ 300: 0.8,
534
+ 400: 0.7,
535
+ 500: 0.62,
536
+ 600: 0.54,
537
+ 700: 0.45,
538
+ 800: 0.33,
539
+ 900: 0.18
540
+ };
541
+ function chromaFactor(l) {
542
+ const d = Math.abs(l - 0.6) / 0.6;
543
+ return 1 - 0.45 * Math.min(1, d);
544
+ }
545
+ function ramp(seedColor2) {
546
+ const input = typeof seedColor2 === "string" ? parse(seedColor2) : toCulori(seedColor2);
547
+ const base = oklch(input);
548
+ if (!base) throw new Error(`[qw] \u65E0\u6CD5\u89E3\u6790\u989C\u8272: ${JSON.stringify(seedColor2)}`);
549
+ const baseC = base.c ?? 0;
550
+ const baseH = base.h ?? 0;
551
+ const out = {};
552
+ for (const step of STEPS) {
553
+ const l = L_TARGETS[step];
554
+ const c = baseC * chromaFactor(l);
555
+ const inGamut = clampChroma({ mode: "oklch", l, c, h: baseH }, "oklch");
556
+ out[step] = formatHex(inGamut) ?? formatHex(base) ?? "#000000";
557
+ }
558
+ return out;
559
+ }
560
+ function relativeLuminance(hex) {
561
+ const srgb = parse(hex);
562
+ if (!srgb) return 0;
563
+ const lin = (v) => v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
564
+ return 0.2126 * lin(srgb.r) + 0.7152 * lin(srgb.g) + 0.0722 * lin(srgb.b);
565
+ }
566
+ function contrastRatio(fg, bg) {
567
+ const l1 = relativeLuminance(fg);
568
+ const l2 = relativeLuminance(bg);
569
+ const [hi, lo] = l1 > l2 ? [l1, l2] : [l2, l1];
570
+ return (hi + 0.05) / (lo + 0.05);
571
+ }
572
+
573
+ // src/derive/naming.ts
574
+ function kebab(segment) {
575
+ return segment.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
576
+ }
577
+ function toVar(layer, path) {
578
+ return `--qw-${layer}-${path.map(kebab).join("-")}`;
579
+ }
580
+
581
+ // src/derive/reference.ts
582
+ function seedValueAt(seed, dotted) {
583
+ let node = seed;
584
+ for (const seg of dotted.split(".")) {
585
+ if (node == null || typeof node !== "object") {
586
+ throw new Error(`[qw] Seed \u8DEF\u5F84\u4E0D\u5B58\u5728: ${dotted}`);
587
+ }
588
+ node = node[seg];
589
+ }
590
+ if (node === void 0) throw new Error(`[qw] Seed \u8DEF\u5F84\u4E0D\u5B58\u5728: ${dotted}`);
591
+ return node;
592
+ }
593
+ function parsePx(s2) {
594
+ const m = /^(-?\d+(?:\.\d+)?)(.*)$/.exec(s2.trim());
595
+ if (!m) throw new Error(`[qw] \u65E0\u6CD5\u89E3\u6790\u5C3A\u5BF8: ${s2}`);
596
+ return { value: Number(m[1]), unit: m[2] ?? "" };
597
+ }
598
+ var round2 = (n) => Math.round(n * 100) / 100;
599
+ function rgba(components, alpha) {
600
+ return `rgba(${components[0]}, ${components[1]}, ${components[2]}, ${round2(alpha)})`;
601
+ }
602
+ function hexRgb(hex) {
603
+ const m = /^#?([0-9a-f]{6})$/i.exec(hex);
604
+ if (!m) throw new Error(`[qw] \u65E0\u6CD5\u89E3\u6790 hex \u989C\u8272: ${hex}`);
605
+ const n = Number.parseInt(m[1], 16);
606
+ return [n >> 16 & 255, n >> 8 & 255, n & 255];
607
+ }
608
+ function seedAlphaCss(seedColor2, alpha) {
609
+ if (alpha >= 1) return seedColorToCss({ ...seedColor2, alpha: 1 });
610
+ return rgba(hexRgb(seedColorToHex(seedColor2)), alpha);
611
+ }
612
+ function formatFontFamily(list) {
613
+ return list.map((f) => /[\s./]/.test(f) ? `'${f}'` : f).join(", ");
614
+ }
615
+ function formatCubicBezier([a, b, c, d]) {
616
+ return `cubic-bezier(${a}, ${b}, ${c}, ${d})`;
617
+ }
618
+ var SHADOW_LEVELS = {
619
+ sm: { offset: 0.5, blur: 0.5, alphaMult: 2 },
620
+ md: { offset: 2, blur: 3, alphaMult: 3 },
621
+ lg: { offset: 4, blur: 6, alphaMult: 4 }
622
+ };
623
+ function shadowShapeOf(seed, level) {
624
+ const { offset, blur } = SHADOW_LEVELS[level];
625
+ const base = seed.effect.shadow.base;
626
+ const scale = (s2, f) => {
627
+ const { value, unit } = parsePx(s2);
628
+ return `${round2(value * f)}${unit}`;
629
+ };
630
+ return {
631
+ offsetX: scale(base.offsetX, offset),
632
+ offsetY: scale(base.offsetY, offset),
633
+ blur: scale(base.blur, blur),
634
+ spread: scale(base.spread, offset)
635
+ };
636
+ }
637
+ function evaluateDerivation(d, seed) {
638
+ switch (d.kind) {
639
+ case "alias": {
640
+ const v = seedValueAt(seed, d.seedRef);
641
+ if (v != null && typeof v === "object" && "colorSpace" in v) {
642
+ return seedColorToCss(v);
643
+ }
644
+ return typeof v === "number" ? String(v) : v;
645
+ }
646
+ case "scale": {
647
+ const { value, unit } = parsePx(seedValueAt(seed, d.seedRef));
648
+ const scaled = value * d.factor;
649
+ return `${d.round === "int" ? Math.round(scaled) : round2(scaled)}${unit}`;
650
+ }
651
+ case "scaleNumber":
652
+ return String(round2(seedValueAt(seed, d.seedRef) * d.factor));
653
+ case "offsetNumber":
654
+ return String(round2(seedValueAt(seed, d.seedRef) + d.delta));
655
+ case "offsetSteps": {
656
+ const base = parsePx(seedValueAt(seed, d.seedRef));
657
+ const step = parsePx(seedValueAt(seed, d.stepRef));
658
+ return `${round2(base.value + step.value * d.n)}${base.unit}`;
659
+ }
660
+ case "oklchRamp":
661
+ return ramp(seed.color[d.seedRef.split(".")[1]])[d.step];
662
+ case "figmaOklchScale":
663
+ return d.value;
664
+ case "seedAlpha":
665
+ return seedAlphaCss(seedValueAt(seed, d.seedRef), d.alpha);
666
+ case "alphaScale": {
667
+ const step = seedValueAt(seed, d.stepRef);
668
+ const channel = d.channel === "black" ? [0, 0, 0] : [255, 255, 255];
669
+ return rgba(channel, step * d.multiplier);
670
+ }
671
+ case "fontStack":
672
+ return formatFontFamily(seedValueAt(seed, d.seedRef));
673
+ case "cubicBezier":
674
+ return formatCubicBezier(seedValueAt(seed, d.seedRef));
675
+ case "literal":
676
+ return d.value;
677
+ case "shadowLayer": {
678
+ const { offsetX, offsetY, blur, spread } = shadowShapeOf(seed, d.level);
679
+ const color2 = rgba([0, 0, 0], seed.size.opacity.alphaStep * SHADOW_LEVELS[d.level].alphaMult);
680
+ return `${offsetX} ${offsetY} ${blur} ${spread} ${color2}`;
681
+ }
682
+ }
683
+ }
684
+ function seedRefsOf(d) {
685
+ switch (d.kind) {
686
+ case "alias":
687
+ case "scale":
688
+ case "scaleNumber":
689
+ case "offsetNumber":
690
+ case "oklchRamp":
691
+ case "figmaOklchScale":
692
+ case "seedAlpha":
693
+ case "fontStack":
694
+ case "cubicBezier":
695
+ return [d.seedRef];
696
+ case "offsetSteps":
697
+ return [d.seedRef, d.stepRef];
698
+ case "alphaScale":
699
+ return [d.stepRef];
700
+ case "literal":
701
+ return [];
702
+ case "shadowLayer":
703
+ return ["effect.shadow.base", "size.opacity.alphaStep"];
704
+ }
705
+ }
706
+ function formatDerivation(d) {
707
+ const sign = (n) => n >= 0 ? "+" : "\u2212";
708
+ switch (d.kind) {
709
+ case "alias":
710
+ case "fontStack":
711
+ case "cubicBezier":
712
+ return `= seed.${d.seedRef}`;
713
+ case "scale":
714
+ return `= seed.${d.seedRef} \xD7 ${d.factor}`;
715
+ case "scaleNumber":
716
+ return `= seed.${d.seedRef} \xD7 ${d.factor}`;
717
+ case "offsetNumber":
718
+ return `= seed.${d.seedRef} ${sign(d.delta)} ${Math.abs(d.delta)}`;
719
+ case "offsetSteps":
720
+ return `= seed.${d.seedRef} ${sign(d.n)} seed.${d.stepRef} \xD7 ${Math.abs(d.n)}`;
721
+ case "oklchRamp":
722
+ return `= oklch(seed.${d.seedRef}) @ L ${L_TARGETS[d.step]} \xB7 C \xD7 ${round2(chromaFactor(L_TARGETS[d.step]))}`;
723
+ case "figmaOklchScale":
724
+ return `= figma Color/qw/t2/${d.seedRef.split(".")[1]}/${d.step}\uFF08OKLCH \u8BBE\u8BA1\u6821\u51C6\uFF09`;
725
+ case "seedAlpha":
726
+ return `= seed.${d.seedRef} / ${round2(d.alpha * 100)}%`;
727
+ case "alphaScale":
728
+ return `= ${d.channel === "black" ? "\u9ED1" : "\u767D"} / seed.${d.stepRef} \xD7 ${d.multiplier}`;
729
+ case "literal":
730
+ return `= ${d.value}\uFF08\u8272\u5F69\u7A7A\u95F4\u7AEF\u70B9\uFF0C\u767D\u540D\u5355\u5B57\u9762\u91CF\uFF09`;
731
+ case "shadowLayer": {
732
+ const f = SHADOW_LEVELS[d.level];
733
+ return `= seed.effect.shadow.base \u5F62\u72B6 \xD7 {offset ${f.offset}, blur ${f.blur}} \xB7 \u8272 = \u9ED1 / alphaStep \xD7 ${f.alphaMult}`;
734
+ }
735
+ }
736
+ }
737
+ function ref(path, derivation) {
738
+ return { path, cssVar: toVar("ref", path), seedRefs: seedRefsOf(derivation), derivation };
739
+ }
740
+ var RAMP_COLORS = T1_COLOR_KEYS;
741
+ function buildColorRampRecipes() {
742
+ const out = [];
743
+ for (const name of RAMP_COLORS) {
744
+ const seedRef = `color.${name}`;
745
+ for (const alpha of T2_ALPHA_STEPS) {
746
+ out.push(ref(["color", name, `a${alpha}`], { kind: "seedAlpha", seedRef, alpha: alpha / 100 }));
747
+ }
748
+ for (const step of T2_OKLCH_STEPS) {
749
+ out.push(
750
+ ref(["color", name, String(step)], {
751
+ kind: "figmaOklchScale",
752
+ seedRef,
753
+ step,
754
+ value: FIGMA_T2_SOLID_SCALE[name][step]
755
+ })
756
+ );
757
+ }
758
+ out.push(ref(["color", name, "base"], { kind: "alias", seedRef }));
759
+ }
760
+ return out;
761
+ }
762
+ function buildSpacingRecipes() {
763
+ const out = [];
764
+ for (let n = 1; n <= 8; n++) {
765
+ out.push(ref(["size", "spacing", String(n)], { kind: "scale", seedRef: "size.spacing.step", factor: n }));
766
+ }
767
+ return out;
768
+ }
769
+ var RADIUS_FACTORS = { sm: 0.5, lg: 1.75 };
770
+ function buildRadiusRecipes() {
771
+ return [
772
+ ref(["size", "radius", "sm"], { kind: "scale", seedRef: "size.radius.base", factor: RADIUS_FACTORS.sm }),
773
+ ref(["size", "radius", "md"], { kind: "alias", seedRef: "size.radius.base" }),
774
+ ref(["size", "radius", "lg"], { kind: "scale", seedRef: "size.radius.base", factor: RADIUS_FACTORS.lg }),
775
+ ref(["size", "radius", "full"], { kind: "alias", seedRef: "size.radius.full" })
776
+ ];
777
+ }
778
+ function buildControlIconSizeRecipes() {
779
+ const step = "size.spacing.step";
780
+ return [
781
+ ref(["size", "controlSize", "sm"], { kind: "offsetSteps", seedRef: "size.controlSize.base", stepRef: step, n: -2 }),
782
+ ref(["size", "controlSize", "md"], { kind: "alias", seedRef: "size.controlSize.base" }),
783
+ ref(["size", "controlSize", "lg"], { kind: "offsetSteps", seedRef: "size.controlSize.base", stepRef: step, n: 2 }),
784
+ ref(["size", "iconSize", "sm"], { kind: "offsetSteps", seedRef: "size.iconSize.base", stepRef: step, n: -1 }),
785
+ ref(["size", "iconSize", "md"], { kind: "alias", seedRef: "size.iconSize.base" }),
786
+ ref(["size", "iconSize", "lg"], { kind: "offsetSteps", seedRef: "size.iconSize.base", stepRef: step, n: 1 })
787
+ ];
788
+ }
789
+ function buildBorderWidthRecipes() {
790
+ return [ref(["size", "borderWidth", "hairline"], { kind: "alias", seedRef: "size.borderWidth.hairline" })];
791
+ }
792
+ function buildLineHeightRecipes() {
793
+ return [
794
+ ref(["typography", "lineHeight", "tight"], { kind: "offsetNumber", seedRef: "typography.lineHeight.base", delta: -0.25 }),
795
+ ref(["typography", "lineHeight", "normal"], { kind: "alias", seedRef: "typography.lineHeight.base" }),
796
+ ref(["typography", "lineHeight", "relaxed"], { kind: "offsetNumber", seedRef: "typography.lineHeight.base", delta: 0.25 })
797
+ ];
798
+ }
799
+ function buildOpacityRecipes() {
800
+ return [ref(["size", "opacity", "disabled"], { kind: "alias", seedRef: "size.opacity.disabled" })];
801
+ }
802
+ function buildZIndexRecipes() {
803
+ return [1, 2, 3, 4].map(
804
+ (n) => ref(["size", "zIndex", String(n)], { kind: "scaleNumber", seedRef: "size.zIndex.step", factor: n })
805
+ );
806
+ }
807
+ var FONT_FAMILY_KEYS = [
808
+ "text",
809
+ "number",
810
+ "code",
811
+ "textMacLatin",
812
+ "textMacZh",
813
+ "textMacJa",
814
+ "textWindowsLatin",
815
+ "textWindowsZh",
816
+ "textWindowsJa"
817
+ ];
818
+ var FONT_SIZE_FACTORS = { sm: 0.857, lg: 1.143, xl: 1.429, "2xl": 1.714 };
819
+ function buildTypographyRecipes() {
820
+ const out = [];
821
+ for (const key of FONT_FAMILY_KEYS) {
822
+ out.push(ref(["typography", "fontFamily", key], { kind: "fontStack", seedRef: `typography.fontFamily.${key}` }));
823
+ }
824
+ for (const key of ["regular", "medium", "semibold"]) {
825
+ out.push(ref(["typography", "fontWeight", key], { kind: "alias", seedRef: `typography.fontWeight.${key}` }));
826
+ }
827
+ out.push(ref(["typography", "fontSize", "base"], { kind: "alias", seedRef: "typography.fontSize.base" }));
828
+ for (const [key, factor] of Object.entries(FONT_SIZE_FACTORS)) {
829
+ out.push(
830
+ ref(["typography", "fontSize", key], { kind: "scale", seedRef: "typography.fontSize.base", factor, round: "int" })
831
+ );
832
+ }
833
+ out.push(ref(["typography", "letterSpacing", "base"], { kind: "alias", seedRef: "typography.letterSpacing.base" }));
834
+ return out;
835
+ }
836
+ var DURATION_FACTORS = { fast: 0.5, slow: 1.6 };
837
+ function buildMotionRecipes() {
838
+ return [
839
+ ref(["motion", "duration", "fast"], { kind: "scale", seedRef: "motion.duration.base", factor: DURATION_FACTORS.fast }),
840
+ ref(["motion", "duration", "base"], { kind: "alias", seedRef: "motion.duration.base" }),
841
+ ref(["motion", "duration", "slow"], { kind: "scale", seedRef: "motion.duration.base", factor: DURATION_FACTORS.slow }),
842
+ ref(["motion", "easing", "standard"], { kind: "cubicBezier", seedRef: "motion.easing.standard" })
843
+ ];
844
+ }
845
+ function buildShadowRecipes() {
846
+ return ["sm", "md", "lg"].map((level) => ref(["effect", "shadow", level], { kind: "shadowLayer", level }));
847
+ }
848
+ function allReferenceRecipes() {
849
+ return [
850
+ ...buildColorRampRecipes(),
851
+ ...buildSpacingRecipes(),
852
+ ...buildRadiusRecipes(),
853
+ ...buildControlIconSizeRecipes(),
854
+ ...buildBorderWidthRecipes(),
855
+ ...buildLineHeightRecipes(),
856
+ ...buildOpacityRecipes(),
857
+ ...buildZIndexRecipes(),
858
+ ...buildTypographyRecipes(),
859
+ ...buildMotionRecipes(),
860
+ ...buildShadowRecipes()
861
+ ];
862
+ }
863
+ function buildReference(seed) {
864
+ const recipes = allReferenceRecipes();
865
+ const tokens = {};
866
+ for (const recipe of recipes) tokens[recipe.cssVar] = evaluateDerivation(recipe.derivation, seed);
867
+ return {
868
+ recipes,
869
+ tokens,
870
+ shapes: {
871
+ shadow: {
872
+ sm: shadowShapeOf(seed, "sm"),
873
+ md: shadowShapeOf(seed, "md"),
874
+ lg: shadowShapeOf(seed, "lg")
875
+ }
876
+ }
877
+ };
878
+ }
879
+
880
+ // src/derive/semantic.ts
881
+ function pick(tokens, dottedRefPath) {
882
+ const v = tokens[toVar("ref", dottedRefPath.split("."))];
883
+ if (v === void 0) throw new Error(`[qw] Semantic \u5F15\u7528\u4E86\u4E0D\u5B58\u5728\u7684 Reference token: ${dottedRefPath}`);
884
+ return v;
885
+ }
886
+ function semVar(path) {
887
+ return toVar("sem", path);
888
+ }
889
+ var RADIUS_ROLES = {
890
+ control: "size.radius.md",
891
+ card: "size.radius.lg",
892
+ pill: "size.radius.full",
893
+ full: "size.radius.full"
894
+ };
895
+ var CONTROL_HEIGHT_ROLES = {
896
+ sm: "size.controlSize.sm",
897
+ md: "size.controlSize.md",
898
+ lg: "size.controlSize.lg"
899
+ };
900
+ var ICON_SIZE_ROLES = {
901
+ sm: "size.iconSize.sm",
902
+ md: "size.iconSize.md",
903
+ lg: "size.iconSize.lg"
904
+ };
905
+ var INSET_STACK_ROLES = {
906
+ sm: "size.spacing.2",
907
+ md: "size.spacing.4",
908
+ lg: "size.spacing.6"
909
+ };
910
+ var Z_INDEX_ROLES = {
911
+ dropdown: "size.zIndex.1",
912
+ sticky: "size.zIndex.2",
913
+ overlay: "size.zIndex.3",
914
+ toast: "size.zIndex.4"
915
+ };
916
+ var MOTION_DURATION_ROLES = {
917
+ fast: "motion.duration.fast",
918
+ base: "motion.duration.base",
919
+ slow: "motion.duration.slow"
920
+ };
921
+ var FONT_FAMILY_ROLES = {
922
+ text: "typography.fontFamily.text",
923
+ number: "typography.fontFamily.number",
924
+ code: "typography.fontFamily.code"
925
+ };
926
+ var T_LETTER = "typography.letterSpacing.base";
927
+ var TYPOGRAPHY_ROLES = {
928
+ body: {
929
+ fontFamilyRef: "typography.fontFamily.text",
930
+ fontSizeRef: "typography.fontSize.base",
931
+ fontWeightRef: "typography.fontWeight.regular",
932
+ lineHeightRef: "typography.lineHeight.normal",
933
+ letterSpacingRef: T_LETTER
934
+ },
935
+ bodyStrong: {
936
+ fontFamilyRef: "typography.fontFamily.text",
937
+ fontSizeRef: "typography.fontSize.base",
938
+ fontWeightRef: "typography.fontWeight.medium",
939
+ lineHeightRef: "typography.lineHeight.normal",
940
+ letterSpacingRef: T_LETTER
941
+ },
942
+ headingSm: {
943
+ fontFamilyRef: "typography.fontFamily.text",
944
+ fontSizeRef: "typography.fontSize.lg",
945
+ fontWeightRef: "typography.fontWeight.semibold",
946
+ lineHeightRef: "typography.lineHeight.tight",
947
+ letterSpacingRef: T_LETTER
948
+ },
949
+ headingMd: {
950
+ fontFamilyRef: "typography.fontFamily.text",
951
+ fontSizeRef: "typography.fontSize.xl",
952
+ fontWeightRef: "typography.fontWeight.semibold",
953
+ lineHeightRef: "typography.lineHeight.tight",
954
+ letterSpacingRef: T_LETTER
955
+ },
956
+ headingLg: {
957
+ fontFamilyRef: "typography.fontFamily.text",
958
+ fontSizeRef: "typography.fontSize.2xl",
959
+ fontWeightRef: "typography.fontWeight.semibold",
960
+ lineHeightRef: "typography.lineHeight.tight",
961
+ letterSpacingRef: T_LETTER
962
+ },
963
+ caption: {
964
+ fontFamilyRef: "typography.fontFamily.text",
965
+ fontSizeRef: "typography.fontSize.sm",
966
+ fontWeightRef: "typography.fontWeight.regular",
967
+ lineHeightRef: "typography.lineHeight.normal",
968
+ letterSpacingRef: T_LETTER
969
+ },
970
+ code: {
971
+ fontFamilyRef: "typography.fontFamily.code",
972
+ fontSizeRef: "typography.fontSize.sm",
973
+ fontWeightRef: "typography.fontWeight.regular",
974
+ lineHeightRef: "typography.lineHeight.normal",
975
+ letterSpacingRef: T_LETTER
976
+ }
977
+ };
978
+ var COLOR_ROLES = FIGMA_T3_COLOR_ROLES;
979
+ var SHADOW_COMPOSITE_ROLES = {};
980
+ function semanticRoleEntries() {
981
+ const out = [];
982
+ const structural = (path, refPath) => out.push({ kind: "structural", path: path.join("."), cssVar: semVar(path), refPath });
983
+ for (const [role, refPath] of Object.entries(RADIUS_ROLES)) structural(["size", "radius", role], refPath);
984
+ for (const [role, refPath] of Object.entries(CONTROL_HEIGHT_ROLES)) structural(["size", "controlHeight", role], refPath);
985
+ for (const [role, refPath] of Object.entries(ICON_SIZE_ROLES)) structural(["size", "iconSize", role], refPath);
986
+ for (const [role, refPath] of Object.entries(INSET_STACK_ROLES)) {
987
+ structural(["size", "inset", role], refPath);
988
+ structural(["size", "stack", role], refPath);
989
+ }
990
+ structural(["size", "opacity", "disabled"], "size.opacity.disabled");
991
+ for (const [role, refPath] of Object.entries(Z_INDEX_ROLES)) structural(["size", "zIndex", role], refPath);
992
+ for (const [role, refPath] of Object.entries(FONT_FAMILY_ROLES)) structural(["typography", "fontFamily", role], refPath);
993
+ for (const [role, spec] of Object.entries(TYPOGRAPHY_ROLES)) {
994
+ structural(["typography", role, "fontFamily"], spec.fontFamilyRef);
995
+ structural(["typography", role, "fontSize"], spec.fontSizeRef);
996
+ structural(["typography", role, "fontWeight"], spec.fontWeightRef);
997
+ structural(["typography", role, "lineHeight"], spec.lineHeightRef);
998
+ structural(["typography", role, "letterSpacing"], spec.letterSpacingRef);
999
+ }
1000
+ for (const [role, refPath] of Object.entries(MOTION_DURATION_ROLES)) structural(["motion", "duration", role], refPath);
1001
+ structural(["motion", "easing", "standard"], "motion.easing.standard");
1002
+ for (const [path, refs] of Object.entries(COLOR_ROLES)) {
1003
+ const segs = ["color", ...path.split(".")];
1004
+ out.push({ kind: "color", path: segs.join("."), cssVar: semVar(segs), refPath: refs });
1005
+ }
1006
+ for (const [role, level] of Object.entries(SHADOW_COMPOSITE_ROLES)) {
1007
+ const segs = ["effect", "shadow", role];
1008
+ out.push({
1009
+ kind: "shadowComposite",
1010
+ path: segs.join("."),
1011
+ cssVar: semVar(segs),
1012
+ shapeRef: `effect.shadow.${level}`,
1013
+ colorRole: "color.shadow"
1014
+ });
1015
+ }
1016
+ return out;
1017
+ }
1018
+ function buildSemanticStructural(reference) {
1019
+ const out = {};
1020
+ const { tokens } = reference;
1021
+ for (const entry of semanticRoleEntries()) {
1022
+ if (entry.kind !== "structural") continue;
1023
+ out[entry.cssVar] = pick(tokens, entry.refPath);
1024
+ }
1025
+ return out;
1026
+ }
1027
+ function buildSemanticColor(reference, mode) {
1028
+ const out = {};
1029
+ const { tokens, shapes } = reference;
1030
+ for (const entry of semanticRoleEntries()) {
1031
+ if (entry.kind !== "color") continue;
1032
+ out[entry.cssVar] = pick(tokens, entry.refPath[mode]);
1033
+ }
1034
+ const shadowColor = out[semVar(["color", "shadow"])];
1035
+ for (const [role, level] of Object.entries(SHADOW_COMPOSITE_ROLES)) {
1036
+ const shape = shapes.shadow[level];
1037
+ out[semVar(["effect", "shadow", role])] = `${shape.offsetX} ${shape.offsetY} ${shape.blur} ${shape.spread} ${shadowColor}`;
1038
+ }
1039
+ return out;
1040
+ }
1041
+
1042
+ // src/derive/index.ts
1043
+ function derive(seed) {
1044
+ const reference = buildReference(seed);
1045
+ const structural = buildSemanticStructural(reference);
1046
+ const mk = (mode) => ({
1047
+ ...reference.tokens,
1048
+ ...structural,
1049
+ ...buildSemanticColor(reference, mode)
1050
+ });
1051
+ return { light: mk("light"), dark: mk("dark") };
1052
+ }
1053
+
1054
+ // src/derive/live-css.ts
1055
+ var round4 = (n) => Math.round(n * 1e4) / 1e4;
1056
+ function seedVar(dotted) {
1057
+ return toVar("seed", dotted.split("."));
1058
+ }
1059
+ function seedCssVars(seed) {
1060
+ const out = {};
1061
+ for (const [name, value] of Object.entries(seed.color)) {
1062
+ out[seedVar(`color.${name}`)] = seedColorToCss(value);
1063
+ }
1064
+ out[seedVar("size.spacing.step")] = seed.size.spacing.step;
1065
+ out[seedVar("size.borderWidth.hairline")] = seed.size.borderWidth.hairline;
1066
+ out[seedVar("size.radius.base")] = seed.size.radius.base;
1067
+ out[seedVar("size.radius.full")] = seed.size.radius.full;
1068
+ out[seedVar("size.controlSize.base")] = seed.size.controlSize.base;
1069
+ out[seedVar("size.iconSize.base")] = seed.size.iconSize.base;
1070
+ out[seedVar("size.opacity.disabled")] = String(seed.size.opacity.disabled);
1071
+ out[seedVar("size.opacity.alphaStep")] = String(seed.size.opacity.alphaStep);
1072
+ out[seedVar("size.zIndex.step")] = String(seed.size.zIndex.step);
1073
+ for (const key of FONT_FAMILY_KEYS) {
1074
+ out[seedVar(`typography.fontFamily.${key}`)] = formatFontFamily(seed.typography.fontFamily[key]);
1075
+ }
1076
+ out[seedVar("typography.fontWeight.regular")] = String(seed.typography.fontWeight.regular);
1077
+ out[seedVar("typography.fontWeight.medium")] = String(seed.typography.fontWeight.medium);
1078
+ out[seedVar("typography.fontWeight.semibold")] = String(seed.typography.fontWeight.semibold);
1079
+ out[seedVar("typography.fontSize.base")] = seed.typography.fontSize.base;
1080
+ out[seedVar("typography.lineHeight.base")] = String(seed.typography.lineHeight.base);
1081
+ out[seedVar("typography.letterSpacing.base")] = seed.typography.letterSpacing.base;
1082
+ out[seedVar("motion.duration.base")] = seed.motion.duration.base;
1083
+ const [a, b, c, d] = seed.motion.easing.standard;
1084
+ out[seedVar("motion.easing.standard")] = `cubic-bezier(${a}, ${b}, ${c}, ${d})`;
1085
+ out[seedVar("effect.shadow.base.offsetX")] = seed.effect.shadow.base.offsetX;
1086
+ out[seedVar("effect.shadow.base.offsetY")] = seed.effect.shadow.base.offsetY;
1087
+ out[seedVar("effect.shadow.base.blur")] = seed.effect.shadow.base.blur;
1088
+ out[seedVar("effect.shadow.base.spread")] = seed.effect.shadow.base.spread;
1089
+ return out;
1090
+ }
1091
+ function shadowShapeExprs(level) {
1092
+ const { offset, blur } = SHADOW_LEVELS[level];
1093
+ const scale = (field, f) => `calc(var(${seedVar(`effect.shadow.base.${field}`)}) * ${f})`;
1094
+ return {
1095
+ offsetX: scale("offsetX", offset),
1096
+ offsetY: scale("offsetY", offset),
1097
+ blur: scale("blur", blur),
1098
+ spread: scale("spread", offset)
1099
+ };
1100
+ }
1101
+ function derivationToCssExpr(d) {
1102
+ switch (d.kind) {
1103
+ case "alias":
1104
+ case "fontStack":
1105
+ case "cubicBezier":
1106
+ return `var(${seedVar(d.seedRef)})`;
1107
+ case "scale": {
1108
+ const expr = `calc(var(${seedVar(d.seedRef)}) * ${d.factor})`;
1109
+ return d.round === "int" ? `round(nearest, ${expr}, 1px)` : expr;
1110
+ }
1111
+ case "scaleNumber":
1112
+ return `calc(var(${seedVar(d.seedRef)}) * ${d.factor})`;
1113
+ case "offsetNumber":
1114
+ return `calc(var(${seedVar(d.seedRef)}) ${d.delta >= 0 ? "+" : "-"} ${Math.abs(d.delta)})`;
1115
+ case "offsetSteps":
1116
+ return `calc(var(${seedVar(d.seedRef)}) ${d.n >= 0 ? "+" : "-"} var(${seedVar(d.stepRef)}) * ${Math.abs(d.n)})`;
1117
+ case "oklchRamp": {
1118
+ const l = L_TARGETS[d.step];
1119
+ const f = round4(chromaFactor(l));
1120
+ return `oklch(from var(${seedVar(d.seedRef)}) ${l} calc(c * ${f}) h)`;
1121
+ }
1122
+ case "figmaOklchScale":
1123
+ return d.value;
1124
+ case "seedAlpha":
1125
+ return `rgb(from var(${seedVar(d.seedRef)}) r g b / ${round4(d.alpha)})`;
1126
+ case "alphaScale": {
1127
+ const channel = d.channel === "black" ? "0 0 0" : "255 255 255";
1128
+ return `rgb(${channel} / calc(var(${seedVar(d.stepRef)}) * ${d.multiplier}))`;
1129
+ }
1130
+ case "literal":
1131
+ return d.value;
1132
+ case "shadowLayer": {
1133
+ const s2 = shadowShapeExprs(d.level);
1134
+ const alpha = `calc(var(${seedVar("size.opacity.alphaStep")}) * ${SHADOW_LEVELS[d.level].alphaMult})`;
1135
+ return `${s2.offsetX} ${s2.offsetY} ${s2.blur} ${s2.spread} rgb(0 0 0 / ${alpha})`;
1136
+ }
1137
+ }
1138
+ }
1139
+ function block(selector, decls) {
1140
+ return `${selector} {
1141
+ ${decls.map(([k, v]) => ` ${k}: ${v};`).join("\n")}
1142
+ }
1143
+ `;
1144
+ }
1145
+ function buildLiveCss(seed, options = {}) {
1146
+ const selector = options.selector ?? ":root";
1147
+ const darkSelector = options.darkSelector ?? '[data-qw-mode="dark"]';
1148
+ const seedDecls = Object.entries(seedCssVars(seed));
1149
+ const refDecls = allReferenceRecipes().map((r) => [
1150
+ r.cssVar,
1151
+ derivationToCssExpr(r.derivation)
1152
+ ]);
1153
+ const semLight = [];
1154
+ const semDark = [];
1155
+ for (const entry of semanticRoleEntries()) {
1156
+ if (entry.kind === "structural") {
1157
+ semLight.push([entry.cssVar, `var(${toVar("ref", entry.refPath.split("."))})`]);
1158
+ } else if (entry.kind === "color") {
1159
+ semLight.push([entry.cssVar, `var(${toVar("ref", entry.refPath.light.split("."))})`]);
1160
+ if (entry.refPath.dark !== entry.refPath.light) {
1161
+ semDark.push([entry.cssVar, `var(${toVar("ref", entry.refPath.dark.split("."))})`]);
1162
+ }
1163
+ } else {
1164
+ const level = entry.shapeRef.split(".").pop();
1165
+ const s2 = shadowShapeExprs(level);
1166
+ semLight.push([
1167
+ entry.cssVar,
1168
+ `${s2.offsetX} ${s2.offsetY} ${s2.blur} ${s2.spread} var(${toVar("sem", entry.colorRole.split("."))})`
1169
+ ]);
1170
+ }
1171
+ }
1172
+ return [
1173
+ "/* @qw-ui/tokens live \u2014 Seed \u53D8\u91CF\u9A71\u52A8\u7684\u54CD\u5E94\u5F0F\u6D3E\u751F\u6811\uFF08relative color / calc\uFF09\uFF0C\u8BF7\u52FF\u624B\u6539\u3002",
1174
+ " \u6539 --qw-seed-* \u5373\u7EA7\u8054\u6574\u68F5 ref/sem \u6811\uFF1B\u9700\u8981\u73B0\u4EE3\u6D4F\u89C8\u5668\uFF0C\u7EC4\u4EF6\u5E93\u6D88\u8D39\u65B9\u8BF7\u7528\u9759\u6001 tokens.css\u3002 */",
1175
+ block(selector, [...seedDecls, ...refDecls, ...semLight]),
1176
+ block(darkSelector, semDark)
1177
+ ].join("\n");
1178
+ }
1179
+
1180
+ export { COLOR_ROLES, FIGMA_COLOR_COLLECTION, FIGMA_COLOR_PREFIX, FIGMA_T1_SEED_HEX, FIGMA_T2_SOLID_SCALE, FIGMA_T3_COLOR_ROLES, L_TARGETS, RAMP_COLORS, SHADOW_COMPOSITE_ROLES, STEPS, SeedSchema, T1_COLOR_KEYS, T2_ALPHA_KEYS, T2_ALPHA_STEPS, T2_OKLCH_STEPS, TYPOGRAPHY_ROLES, allReferenceRecipes, buildLiveCss, buildReference, buildSemanticColor, buildSemanticStructural, contrastRatio, defaultSeed, derivationToCssExpr, derive, evaluateDerivation, formatDerivation, hexToSeedColor, ramp, seedColorToCss, seedColorToHex, seedCssVars, seedRefsOf, seedValueAt, semanticRoleEntries, toVar, validateSeed };
1181
+ //# sourceMappingURL=index.js.map
1182
+ //# sourceMappingURL=index.js.map