@nxds/core 0.12.0 → 0.13.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.
@@ -1,381 +1,57 @@
1
- // tokens/primitives/typography/typography-default.json
2
- var typography_default_default = {
3
- family: {
4
- "font-sans": {
5
- $value: "ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif",
6
- $type: "fontFamily",
7
- $extensions: {
8
- "nx-font-source": {
9
- type: "system"
10
- }
11
- }
12
- },
13
- "font-heading": {
14
- $value: "ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif",
15
- $type: "fontFamily",
16
- $extensions: {
17
- "nx-font-source": {
18
- type: "system"
19
- }
20
- }
21
- },
22
- "font-serif": {
23
- $value: "Georgia",
24
- $type: "fontFamily",
25
- $extensions: {
26
- "nx-font-source": {
27
- type: "system"
28
- }
29
- }
30
- },
31
- "font-mono": {
32
- $value: "ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace",
33
- $type: "fontFamily",
34
- $extensions: {
35
- "nx-font-source": {
36
- type: "system"
37
- }
38
- }
39
- }
40
- },
41
- size: {
42
- xxs: {
43
- $value: {
44
- value: 11,
45
- unit: "px"
46
- },
47
- $type: "dimension"
48
- },
49
- xs: {
50
- $value: {
51
- value: 12,
52
- unit: "px"
53
- },
54
- $type: "dimension"
55
- },
56
- sm: {
57
- $value: {
58
- value: 14,
59
- unit: "px"
60
- },
61
- $type: "dimension"
62
- },
63
- base: {
64
- $value: {
65
- value: 16,
66
- unit: "px"
67
- },
68
- $type: "dimension"
69
- },
70
- lg: {
71
- $value: {
72
- value: 18,
73
- unit: "px"
74
- },
75
- $type: "dimension"
76
- },
77
- xl: {
78
- $value: {
79
- value: 20,
80
- unit: "px"
81
- },
82
- $type: "dimension"
83
- },
84
- "2xl": {
85
- $value: {
86
- value: 24,
87
- unit: "px"
88
- },
89
- $type: "dimension"
90
- },
91
- "3xl": {
92
- $value: {
93
- value: 30,
94
- unit: "px"
95
- },
96
- $type: "dimension"
97
- },
98
- "4xl": {
99
- $value: {
100
- value: 36,
101
- unit: "px"
102
- },
103
- $type: "dimension"
104
- },
105
- "5xl": {
106
- $value: {
107
- value: 48,
108
- unit: "px"
109
- },
110
- $type: "dimension"
111
- },
112
- "6xl": {
113
- $value: {
114
- value: 60,
115
- unit: "px"
116
- },
117
- $type: "dimension"
118
- },
119
- "7xl": {
120
- $value: {
121
- value: 72,
122
- unit: "px"
123
- },
124
- $type: "dimension"
125
- },
126
- "8xl": {
127
- $value: {
128
- value: 96,
129
- unit: "px"
130
- },
131
- $type: "dimension"
132
- },
133
- "9xl": {
134
- $value: {
135
- value: 128,
136
- unit: "px"
137
- },
138
- $type: "dimension"
1
+ // src/lib/contrast.ts
2
+ import { APCAcontrast as APCAcontrast2, sRGBtoY as sRGBtoY2 } from "apca-w3";
3
+ import { clampChroma as clampChroma4 } from "culori";
4
+
5
+ // src/lib/apca.ts
6
+ import { APCAcontrast, sRGBtoY } from "apca-w3";
7
+ import { clampChroma, converter, oklch, parse } from "culori";
8
+ var toRgb = converter("rgb");
9
+ function channel(value) {
10
+ return Math.max(0, Math.min(255, Math.round(value * 255)));
11
+ }
12
+ function toSrgbInts(input) {
13
+ const parsed = parse(input);
14
+ if (!parsed) throw new Error(`apca: cannot parse color '${input}'`);
15
+ const converted = oklch(parsed);
16
+ if (!converted) throw new Error(`apca: cannot convert '${input}' to OKLCH`);
17
+ const rgb = toRgb(clampChroma(converted, "oklch", "rgb"));
18
+ return [channel(rgb.r), channel(rgb.g), channel(rgb.b)];
19
+ }
20
+ function blendAlphaOver(hex8, bgInts) {
21
+ const h = hex8.slice(1);
22
+ const a = parseInt(h.slice(6, 8), 16) / 255;
23
+ const [bgR, bgG, bgB] = bgInts;
24
+ const mix = (fg, bg) => Math.round(fg * a + bg * (1 - a));
25
+ return [
26
+ mix(parseInt(h.slice(0, 2), 16), bgR),
27
+ mix(parseInt(h.slice(2, 4), 16), bgG),
28
+ mix(parseInt(h.slice(4, 6), 16), bgB)
29
+ ];
30
+ }
31
+ function resolveToSrgbInts(value, bgInts) {
32
+ if (typeof value !== "string") {
33
+ throw new Error(`apca: expected string color value, got ${typeof value}`);
34
+ }
35
+ if (/^#[0-9a-fA-F]{8}$/.test(value)) {
36
+ if (!bgInts) {
37
+ throw new Error(
38
+ `apca: alpha color "${value}" needs a backdrop to composite against`
39
+ );
139
40
  }
140
- },
141
- weight: {
142
- thin: {
143
- $value: 100,
144
- $type: "fontWeight"
145
- },
146
- extralight: {
147
- $value: 200,
148
- $type: "fontWeight"
149
- },
150
- light: {
151
- $value: 300,
152
- $type: "fontWeight"
153
- },
154
- normal: {
155
- $value: 400,
156
- $type: "fontWeight"
157
- },
158
- medium: {
159
- $value: 500,
160
- $type: "fontWeight"
161
- },
162
- semibold: {
163
- $value: 600,
164
- $type: "fontWeight"
165
- },
166
- bold: {
167
- $value: 700,
168
- $type: "fontWeight"
169
- },
170
- extrabold: {
171
- $value: 800,
172
- $type: "fontWeight"
173
- },
174
- black: {
175
- $value: 900,
176
- $type: "fontWeight"
177
- }
178
- },
179
- "line-height": {
180
- xxs: {
181
- $value: {
182
- value: 12,
183
- unit: "px"
184
- },
185
- $type: "dimension"
186
- },
187
- xs: {
188
- $value: {
189
- value: 16,
190
- unit: "px"
191
- },
192
- $type: "dimension"
193
- },
194
- sm: {
195
- $value: {
196
- value: 20,
197
- unit: "px"
198
- },
199
- $type: "dimension"
200
- },
201
- base: {
202
- $value: {
203
- value: 24,
204
- unit: "px"
205
- },
206
- $type: "dimension"
207
- },
208
- lg: {
209
- $value: {
210
- value: 28,
211
- unit: "px"
212
- },
213
- $type: "dimension"
214
- },
215
- xl: {
216
- $value: {
217
- value: 28,
218
- unit: "px"
219
- },
220
- $type: "dimension"
221
- },
222
- "2xl": {
223
- $value: {
224
- value: 32,
225
- unit: "px"
226
- },
227
- $type: "dimension"
228
- },
229
- "3xl": {
230
- $value: {
231
- value: 36,
232
- unit: "px"
233
- },
234
- $type: "dimension"
235
- },
236
- "4xl": {
237
- $value: {
238
- value: 48,
239
- unit: "px"
240
- },
241
- $type: "dimension"
242
- },
243
- "5xl": {
244
- $value: {
245
- value: 48,
246
- unit: "px"
247
- },
248
- $type: "dimension"
249
- },
250
- "6xl": {
251
- $value: {
252
- value: 60,
253
- unit: "px"
254
- },
255
- $type: "dimension"
256
- },
257
- "7xl": {
258
- $value: {
259
- value: 72,
260
- unit: "px"
261
- },
262
- $type: "dimension"
263
- },
264
- "8xl": {
265
- $value: {
266
- value: 96,
267
- unit: "px"
268
- },
269
- $type: "dimension"
270
- },
271
- "9xl": {
272
- $value: {
273
- value: 128,
274
- unit: "px"
275
- },
276
- $type: "dimension"
277
- }
278
- },
279
- letterspacing: {
280
- tighter: {
281
- $value: {
282
- value: -0.800000011920929,
283
- unit: "px"
284
- },
285
- $type: "dimension"
286
- },
287
- tight: {
288
- $value: {
289
- value: -0.4000000059604645,
290
- unit: "px"
291
- },
292
- $type: "dimension"
293
- },
294
- normal: {
295
- $value: {
296
- value: 0,
297
- unit: "px"
298
- },
299
- $type: "dimension"
300
- },
301
- wide: {
302
- $value: {
303
- value: 0.4000000059604645,
304
- unit: "px"
305
- },
306
- $type: "dimension"
307
- },
308
- wider: {
309
- $value: {
310
- value: 0.800000011920929,
311
- unit: "px"
312
- },
313
- $type: "dimension"
314
- },
315
- widest: {
316
- $value: {
317
- value: 1.600000023841858,
318
- unit: "px"
319
- },
320
- $type: "dimension"
321
- }
322
- }
323
- };
324
-
325
- // src/lib/contrast.ts
326
- import { APCAcontrast as APCAcontrast2, sRGBtoY as sRGBtoY2 } from "apca-w3";
327
- import { clampChroma as clampChroma4 } from "culori";
328
-
329
- // src/lib/apca.ts
330
- import { APCAcontrast, sRGBtoY } from "apca-w3";
331
- import { clampChroma, converter, oklch, parse } from "culori";
332
- var toRgb = converter("rgb");
333
- function channel(value) {
334
- return Math.max(0, Math.min(255, Math.round(value * 255)));
335
- }
336
- function toSrgbInts(input) {
337
- const parsed = parse(input);
338
- if (!parsed) throw new Error(`apca: cannot parse color '${input}'`);
339
- const converted = oklch(parsed);
340
- if (!converted) throw new Error(`apca: cannot convert '${input}' to OKLCH`);
341
- const rgb = toRgb(clampChroma(converted, "oklch", "rgb"));
342
- return [channel(rgb.r), channel(rgb.g), channel(rgb.b)];
343
- }
344
- function blendAlphaOver(hex8, bgInts) {
345
- const h = hex8.slice(1);
346
- const a = parseInt(h.slice(6, 8), 16) / 255;
347
- const [bgR, bgG, bgB] = bgInts;
348
- const mix = (fg, bg) => Math.round(fg * a + bg * (1 - a));
349
- return [
350
- mix(parseInt(h.slice(0, 2), 16), bgR),
351
- mix(parseInt(h.slice(2, 4), 16), bgG),
352
- mix(parseInt(h.slice(4, 6), 16), bgB)
353
- ];
354
- }
355
- function resolveToSrgbInts(value, bgInts) {
356
- if (typeof value !== "string") {
357
- throw new Error(`apca: expected string color value, got ${typeof value}`);
358
- }
359
- if (/^#[0-9a-fA-F]{8}$/.test(value)) {
360
- if (!bgInts) {
361
- throw new Error(
362
- `apca: alpha color "${value}" needs a backdrop to composite against`
363
- );
364
- }
365
- return blendAlphaOver(value, bgInts);
366
- }
367
- const parsed = parse(value);
368
- if (!parsed) throw new Error(`apca: cannot parse color '${value}'`);
369
- const converted = oklch(parsed);
370
- if (!converted) throw new Error(`apca: cannot convert '${value}'`);
371
- const rgb = toRgb(clampChroma(converted, "oklch", "rgb"));
372
- const alpha = rgb.alpha ?? 1;
373
- const ints = [channel(rgb.r), channel(rgb.g), channel(rgb.b)];
374
- if (alpha < 1) {
375
- if (!bgInts) {
376
- throw new Error(
377
- `apca: alpha color "${value}" needs a backdrop to composite against`
378
- );
41
+ return blendAlphaOver(value, bgInts);
42
+ }
43
+ const parsed = parse(value);
44
+ if (!parsed) throw new Error(`apca: cannot parse color '${value}'`);
45
+ const converted = oklch(parsed);
46
+ if (!converted) throw new Error(`apca: cannot convert '${value}'`);
47
+ const rgb = toRgb(clampChroma(converted, "oklch", "rgb"));
48
+ const alpha = rgb.alpha ?? 1;
49
+ const ints = [channel(rgb.r), channel(rgb.g), channel(rgb.b)];
50
+ if (alpha < 1) {
51
+ if (!bgInts) {
52
+ throw new Error(
53
+ `apca: alpha color "${value}" needs a backdrop to composite against`
54
+ );
379
55
  }
380
56
  return [
381
57
  Math.round(ints[0] * alpha + bgInts[0] * (1 - alpha)),
@@ -797,251 +473,607 @@ var perceptual_grid_hue_default = {
797
473
  "900": 0.32,
798
474
  "950": 0.24
799
475
  },
800
- fuchsia: {
801
- "50": 0.97,
802
- "100": 0.94,
803
- "200": 0.89,
804
- "300": 0.81,
805
- "400": 0.71,
806
- "500": 0.63,
807
- "600": 0.56,
808
- "700": 0.49,
809
- "800": 0.41,
810
- "900": 0.33,
811
- "950": 0.25
476
+ fuchsia: {
477
+ "50": 0.97,
478
+ "100": 0.94,
479
+ "200": 0.89,
480
+ "300": 0.81,
481
+ "400": 0.71,
482
+ "500": 0.63,
483
+ "600": 0.56,
484
+ "700": 0.49,
485
+ "800": 0.41,
486
+ "900": 0.33,
487
+ "950": 0.25
488
+ },
489
+ pink: {
490
+ "50": 0.97,
491
+ "100": 0.94,
492
+ "200": 0.89,
493
+ "300": 0.82,
494
+ "400": 0.72,
495
+ "500": 0.64,
496
+ "600": 0.57,
497
+ "700": 0.5,
498
+ "800": 0.42,
499
+ "900": 0.34,
500
+ "950": 0.25
501
+ }
502
+ };
503
+
504
+ // src/token-source/perceptual-grid.ts
505
+ var EMIT_GAMUT = "p3";
506
+ var toRgb2 = converter2("rgb");
507
+ var PERCEPTUAL_L_GRID = Object.freeze(perceptual_grid_default);
508
+ var PERCEPTUAL_L_GRID_HUE = Object.freeze(
509
+ Object.fromEntries(
510
+ Object.entries(perceptual_grid_hue_default).map(([name, curve]) => [name, Object.freeze(curve)])
511
+ )
512
+ );
513
+ var CUSP_FRACTION = 0.95;
514
+ var SHADE_KEY_RE = /^(50|100|200|300|400|500|600|700|800|900|950)$/;
515
+ function isPaletteShadeKey(key) {
516
+ return typeof key === "string" && SHADE_KEY_RE.test(key);
517
+ }
518
+ function round2(value, decimals) {
519
+ const factor = 10 ** decimals;
520
+ return Math.round(value * factor) / factor;
521
+ }
522
+ function formatPaletteOklch({ l, c, h, alpha }) {
523
+ const finite = (v) => v !== void 0 && Number.isFinite(v) ? v : 0;
524
+ const lRounded = round2(finite(l), 4);
525
+ const cRounded = round2(finite(c), 4);
526
+ const hRounded = c && h !== void 0 ? round2(finite(h), 3) : 0;
527
+ const base = `oklch(${lRounded} ${cRounded} ${hRounded}`;
528
+ if (alpha !== void 0 && alpha < 1) {
529
+ return `${base} / ${round2(alpha, 4)})`;
530
+ }
531
+ return `${base})`;
532
+ }
533
+ function parseToOklch(hex) {
534
+ const parsed = parse3(hex);
535
+ if (!parsed) {
536
+ throw new Error(`palette: cannot parse color "${hex}"`);
537
+ }
538
+ return oklch3(parsed);
539
+ }
540
+ function computePinnedOklch(hex, shade, palette, reportGamutClip) {
541
+ const hueCurve = palette ? PERCEPTUAL_L_GRID_HUE[palette] : void 0;
542
+ const pinnedL = isPaletteShadeKey(shade) ? (hueCurve ?? PERCEPTUAL_L_GRID)[shade] : void 0;
543
+ if (pinnedL === void 0) {
544
+ throw new Error(`palette: unknown shade "${shade}" for ${hex}`);
545
+ }
546
+ const source = parseToOklch(hex);
547
+ let chroma = source.c ?? 0;
548
+ if (hueCurve) {
549
+ const cuspC = clampChroma2(
550
+ { mode: "oklch", l: pinnedL, c: 0.5, h: source.h },
551
+ "oklch",
552
+ EMIT_GAMUT
553
+ ).c ?? 0;
554
+ chroma = cuspC * CUSP_FRACTION;
555
+ }
556
+ const target = {
557
+ mode: "oklch",
558
+ l: pinnedL,
559
+ c: chroma,
560
+ h: source.h,
561
+ ...source.alpha !== void 0 ? { alpha: source.alpha } : {}
562
+ };
563
+ const clamped = clampChroma2(target, "oklch", EMIT_GAMUT);
564
+ if (!hueCurve) {
565
+ const originalC = target.c;
566
+ const clampedC = clamped.c ?? 0;
567
+ if (originalC > 0 && (originalC - clampedC) / originalC > 0.2) {
568
+ reportGamutClip?.(
569
+ `palette: P3 gamut clip on ${hex} at shade ${shade} \u2014 C ${originalC.toFixed(4)} \u2192 ${clampedC.toFixed(4)}`
570
+ );
571
+ }
572
+ }
573
+ return clamped;
574
+ }
575
+ function hexToOklchPinned(hex, shade, palette, reportGamutClip) {
576
+ return formatPaletteOklch(
577
+ computePinnedOklch(hex, shade, palette, reportGamutClip)
578
+ );
579
+ }
580
+ function hexToOklchMechanical(hex) {
581
+ return formatPaletteOklch(parseToOklch(hex));
582
+ }
583
+
584
+ // src/lib/perceptual-ramp.ts
585
+ var EMIT_GAMUT2 = "p3";
586
+ var CUSP_FRACTION2 = 0.95;
587
+ function seedOklch(input) {
588
+ const parsed = parse4(input);
589
+ if (!parsed)
590
+ throw new Error(`perceptual-ramp: cannot parse color '${input}'`);
591
+ const converted = oklch4(parsed);
592
+ if (!converted)
593
+ throw new Error(`perceptual-ramp: cannot convert '${input}' to OKLCH`);
594
+ return converted;
595
+ }
596
+ function pinnedOklch(seedHex, shade, options = {}) {
597
+ const { capAtSeedChroma = true } = options;
598
+ const seed = seedOklch(seedHex);
599
+ const l = PERCEPTUAL_L_GRID[shade];
600
+ const hue = seed.h ?? 0;
601
+ const seedC = seed.c ?? 0;
602
+ const cuspC = clampChroma3({ mode: "oklch", l, c: 0.5, h: hue }, "oklch", EMIT_GAMUT2).c ?? 0;
603
+ let chroma = cuspC * CUSP_FRACTION2;
604
+ if (capAtSeedChroma) chroma = Math.min(chroma, seedC);
605
+ const target = { mode: "oklch", l, c: chroma, h: hue };
606
+ return formatOklch(clampChroma3(target, "oklch", EMIT_GAMUT2));
607
+ }
608
+ function rampFromSeed(seedHex, options = {}) {
609
+ const ramp = {};
610
+ for (const shade of SHADES)
611
+ ramp[shade] = pinnedOklch(seedHex, shade, options);
612
+ return ramp;
613
+ }
614
+
615
+ // src/lib/contrast.ts
616
+ var CONTRAST_MIN = 0;
617
+ var CONTRAST_MAX = 100;
618
+ function normalizeContrast(value, fallback = 50) {
619
+ return typeof value === "number" && Number.isFinite(value) ? Math.round(Math.max(CONTRAST_MIN, Math.min(CONTRAST_MAX, value))) : fallback;
620
+ }
621
+ function contrastTarget(tier, contrast) {
622
+ return TIER_THRESHOLDS[tier] + 15 * contrast / 100;
623
+ }
624
+ var BISECT_STEPS = 12;
625
+ function bisect(fail, pass, passes) {
626
+ for (let i = 0; i < BISECT_STEPS; i++) {
627
+ const middle = (fail + pass) / 2;
628
+ if (passes(middle)) pass = middle;
629
+ else fail = middle;
630
+ }
631
+ return pass;
632
+ }
633
+ var token = (map, name) => {
634
+ const value = map[`--nx-color-${name}`];
635
+ if (value === void 0) throw new Error(`contrast: missing ${name}`);
636
+ return value;
637
+ };
638
+ function pairBackground(map, pair) {
639
+ const backdrop = pair.backdrop ? resolveToSrgbInts(
640
+ pair.backdrop.startsWith("#") ? pair.backdrop : token(map, pair.backdrop)
641
+ ) : void 0;
642
+ return resolveToSrgbInts(token(map, pair.bg), backdrop);
643
+ }
644
+ var luminance = (color) => sRGBtoY2(resolveToSrgbInts(color));
645
+ var score = (foregroundY, backgroundY) => Math.abs(APCAcontrast2(foregroundY, backgroundY));
646
+ function constraintsFor(map, pairs, contrast, endpointY) {
647
+ const constraints = [];
648
+ for (const pair of pairs) {
649
+ const backgroundY = sRGBtoY2(pairBackground(map, pair));
650
+ const reachable = score(endpointY, backgroundY);
651
+ if (reachable < TIER_THRESHOLDS[pair.tier]) return void 0;
652
+ const target = contrastTarget(pair.tier, contrast) + (pair.offset ?? 0);
653
+ constraints.push({ backgroundY, target: Math.min(target, reachable) });
654
+ }
655
+ return constraints;
656
+ }
657
+ var keepsTextSeed = (mode, kind) => mode === "light" && kind === "text";
658
+ function solveForeground(seed, constraints, endpoint, keepSeed) {
659
+ const passes = (color) => {
660
+ const y = luminance(color);
661
+ return constraints.every((c) => score(y, c.backgroundY) >= c.target);
662
+ };
663
+ if (keepSeed && passes(seed)) return seed;
664
+ const parsed = seedOklch(seed);
665
+ const at = (l) => formatOklch(clampChroma4({ ...parsed, l, alpha: 1 }, "oklch", "p3"));
666
+ return at(
667
+ bisect(keepSeed ? parsed.l : 1 - endpoint, endpoint, (l) => passes(at(l)))
668
+ );
669
+ }
670
+ var SOLVE_GROUPS = /* @__PURE__ */ new Map();
671
+ for (const pair of APCA_PAIRS) {
672
+ const key = pair.solveAs ?? pair.fg;
673
+ const group = SOLVE_GROUPS.get(key);
674
+ if (!group) {
675
+ SOLVE_GROUPS.set(key, { kind: pair.kind, pairs: [pair] });
676
+ continue;
677
+ }
678
+ if (group.kind !== pair.kind)
679
+ throw new Error(
680
+ `contrast: ${pair.fg} is '${pair.kind}' but joins '${group.kind}' group ${key}`
681
+ );
682
+ group.pairs.push(pair);
683
+ }
684
+ function constrainFamilyFills(map, name, pairs) {
685
+ const basePair = pairs[0];
686
+ if (!basePair) throw new Error(`contrast: missing pairs for ${name}`);
687
+ const baseY = luminance(token(map, basePair.bg));
688
+ const endpoint = score(1, baseY) >= score(0, baseY) ? 1 : 0;
689
+ map[`--nx-color-${name}`] = `oklch(${endpoint} 0 0)`;
690
+ for (const pair of pairs) {
691
+ const floor = TIER_THRESHOLDS[pair.tier];
692
+ const value = token(map, pair.bg);
693
+ if (score(endpoint, luminance(value)) >= floor) continue;
694
+ const fill = seedOklch(value);
695
+ const at = (l) => formatOklch(clampChroma4({ ...fill, l }, "oklch", "p3"));
696
+ const readable = (l) => score(endpoint, luminance(at(l))) >= floor;
697
+ map[`--nx-color-${pair.bg}`] = at(bisect(fill.l, 1 - endpoint, readable));
698
+ }
699
+ }
700
+ function constrainColors(map, mode, contrast) {
701
+ for (const [name, { kind, pairs }] of SOLVE_GROUPS)
702
+ if (kind === "label") constrainFamilyFills(map, name, pairs);
703
+ const endpoint = mode === "dark" ? 1 : 0;
704
+ const endpointY = luminance(`oklch(${endpoint} 0 0)`);
705
+ for (const [name, { kind, pairs }] of SOLVE_GROUPS) {
706
+ if (kind === "label") continue;
707
+ const constraints = constraintsFor(map, pairs, contrast, endpointY);
708
+ if (constraints === void 0)
709
+ throw new Error(`contrast: no readable ${name} in ${mode}`);
710
+ const solved = solveForeground(
711
+ token(map, name),
712
+ constraints,
713
+ endpoint,
714
+ keepsTextSeed(mode, kind)
715
+ );
716
+ for (const fg of new Set(pairs.map((pair) => pair.fg).concat(name)))
717
+ map[`--nx-color-${fg}`] = solved;
718
+ }
719
+ return map;
720
+ }
721
+
722
+ // tokens/primitives/typography/typography-default.json
723
+ var typography_default_default = {
724
+ family: {
725
+ "font-sans": {
726
+ $value: "ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif",
727
+ $type: "fontFamily",
728
+ $extensions: {
729
+ "nx-font-source": {
730
+ type: "system"
731
+ }
732
+ }
733
+ },
734
+ "font-heading": {
735
+ $value: "ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif",
736
+ $type: "fontFamily",
737
+ $extensions: {
738
+ "nx-font-source": {
739
+ type: "system"
740
+ }
741
+ }
742
+ },
743
+ "font-serif": {
744
+ $value: "Georgia",
745
+ $type: "fontFamily",
746
+ $extensions: {
747
+ "nx-font-source": {
748
+ type: "system"
749
+ }
750
+ }
751
+ },
752
+ "font-mono": {
753
+ $value: "ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace",
754
+ $type: "fontFamily",
755
+ $extensions: {
756
+ "nx-font-source": {
757
+ type: "system"
758
+ }
759
+ }
760
+ }
761
+ },
762
+ size: {
763
+ xxs: {
764
+ $value: {
765
+ value: 11,
766
+ unit: "px"
767
+ },
768
+ $type: "dimension"
769
+ },
770
+ xs: {
771
+ $value: {
772
+ value: 12,
773
+ unit: "px"
774
+ },
775
+ $type: "dimension"
776
+ },
777
+ sm: {
778
+ $value: {
779
+ value: 14,
780
+ unit: "px"
781
+ },
782
+ $type: "dimension"
783
+ },
784
+ base: {
785
+ $value: {
786
+ value: 16,
787
+ unit: "px"
788
+ },
789
+ $type: "dimension"
790
+ },
791
+ lg: {
792
+ $value: {
793
+ value: 18,
794
+ unit: "px"
795
+ },
796
+ $type: "dimension"
797
+ },
798
+ xl: {
799
+ $value: {
800
+ value: 20,
801
+ unit: "px"
802
+ },
803
+ $type: "dimension"
804
+ },
805
+ "2xl": {
806
+ $value: {
807
+ value: 24,
808
+ unit: "px"
809
+ },
810
+ $type: "dimension"
811
+ },
812
+ "3xl": {
813
+ $value: {
814
+ value: 30,
815
+ unit: "px"
816
+ },
817
+ $type: "dimension"
818
+ },
819
+ "4xl": {
820
+ $value: {
821
+ value: 36,
822
+ unit: "px"
823
+ },
824
+ $type: "dimension"
825
+ },
826
+ "5xl": {
827
+ $value: {
828
+ value: 48,
829
+ unit: "px"
830
+ },
831
+ $type: "dimension"
832
+ },
833
+ "6xl": {
834
+ $value: {
835
+ value: 60,
836
+ unit: "px"
837
+ },
838
+ $type: "dimension"
839
+ },
840
+ "7xl": {
841
+ $value: {
842
+ value: 72,
843
+ unit: "px"
844
+ },
845
+ $type: "dimension"
846
+ },
847
+ "8xl": {
848
+ $value: {
849
+ value: 96,
850
+ unit: "px"
851
+ },
852
+ $type: "dimension"
853
+ },
854
+ "9xl": {
855
+ $value: {
856
+ value: 128,
857
+ unit: "px"
858
+ },
859
+ $type: "dimension"
860
+ },
861
+ code: {
862
+ $value: {
863
+ value: 12,
864
+ unit: "px"
865
+ },
866
+ $type: "dimension"
867
+ }
868
+ },
869
+ weight: {
870
+ thin: {
871
+ $value: 100,
872
+ $type: "fontWeight"
873
+ },
874
+ extralight: {
875
+ $value: 200,
876
+ $type: "fontWeight"
877
+ },
878
+ light: {
879
+ $value: 300,
880
+ $type: "fontWeight"
881
+ },
882
+ normal: {
883
+ $value: 400,
884
+ $type: "fontWeight"
885
+ },
886
+ medium: {
887
+ $value: 500,
888
+ $type: "fontWeight"
889
+ },
890
+ semibold: {
891
+ $value: 600,
892
+ $type: "fontWeight"
893
+ },
894
+ bold: {
895
+ $value: 700,
896
+ $type: "fontWeight"
897
+ },
898
+ extrabold: {
899
+ $value: 800,
900
+ $type: "fontWeight"
901
+ },
902
+ black: {
903
+ $value: 900,
904
+ $type: "fontWeight"
905
+ }
812
906
  },
813
- pink: {
814
- "50": 0.97,
815
- "100": 0.94,
816
- "200": 0.89,
817
- "300": 0.82,
818
- "400": 0.72,
819
- "500": 0.64,
820
- "600": 0.57,
821
- "700": 0.5,
822
- "800": 0.42,
823
- "900": 0.34,
824
- "950": 0.25
825
- }
826
- };
827
-
828
- // src/token-source/perceptual-grid.ts
829
- var EMIT_GAMUT = "p3";
830
- var toRgb2 = converter2("rgb");
831
- var PERCEPTUAL_L_GRID = Object.freeze(perceptual_grid_default);
832
- var PERCEPTUAL_L_GRID_HUE = Object.freeze(
833
- Object.fromEntries(
834
- Object.entries(perceptual_grid_hue_default).map(([name, curve]) => [name, Object.freeze(curve)])
835
- )
836
- );
837
- var CUSP_FRACTION = 0.95;
838
- var SHADE_KEY_RE = /^(50|100|200|300|400|500|600|700|800|900|950)$/;
839
- function isPaletteShadeKey(key) {
840
- return typeof key === "string" && SHADE_KEY_RE.test(key);
841
- }
842
- function round2(value, decimals) {
843
- const factor = 10 ** decimals;
844
- return Math.round(value * factor) / factor;
845
- }
846
- function formatPaletteOklch({ l, c, h, alpha }) {
847
- const finite = (v) => v !== void 0 && Number.isFinite(v) ? v : 0;
848
- const lRounded = round2(finite(l), 4);
849
- const cRounded = round2(finite(c), 4);
850
- const hRounded = c && h !== void 0 ? round2(finite(h), 3) : 0;
851
- const base = `oklch(${lRounded} ${cRounded} ${hRounded}`;
852
- if (alpha !== void 0 && alpha < 1) {
853
- return `${base} / ${round2(alpha, 4)})`;
854
- }
855
- return `${base})`;
856
- }
857
- function parseToOklch(hex) {
858
- const parsed = parse3(hex);
859
- if (!parsed) {
860
- throw new Error(`palette: cannot parse color "${hex}"`);
861
- }
862
- return oklch3(parsed);
863
- }
864
- function computePinnedOklch(hex, shade, palette, reportGamutClip) {
865
- const hueCurve = palette ? PERCEPTUAL_L_GRID_HUE[palette] : void 0;
866
- const pinnedL = isPaletteShadeKey(shade) ? (hueCurve ?? PERCEPTUAL_L_GRID)[shade] : void 0;
867
- if (pinnedL === void 0) {
868
- throw new Error(`palette: unknown shade "${shade}" for ${hex}`);
869
- }
870
- const source = parseToOklch(hex);
871
- let chroma = source.c ?? 0;
872
- if (hueCurve) {
873
- const cuspC = clampChroma2(
874
- { mode: "oklch", l: pinnedL, c: 0.5, h: source.h },
875
- "oklch",
876
- EMIT_GAMUT
877
- ).c ?? 0;
878
- chroma = cuspC * CUSP_FRACTION;
879
- }
880
- const target = {
881
- mode: "oklch",
882
- l: pinnedL,
883
- c: chroma,
884
- h: source.h,
885
- ...source.alpha !== void 0 ? { alpha: source.alpha } : {}
886
- };
887
- const clamped = clampChroma2(target, "oklch", EMIT_GAMUT);
888
- if (!hueCurve) {
889
- const originalC = target.c;
890
- const clampedC = clamped.c ?? 0;
891
- if (originalC > 0 && (originalC - clampedC) / originalC > 0.2) {
892
- reportGamutClip?.(
893
- `palette: P3 gamut clip on ${hex} at shade ${shade} \u2014 C ${originalC.toFixed(4)} \u2192 ${clampedC.toFixed(4)}`
894
- );
907
+ "line-height": {
908
+ xxs: {
909
+ $value: {
910
+ value: 12,
911
+ unit: "px"
912
+ },
913
+ $type: "dimension"
914
+ },
915
+ xs: {
916
+ $value: {
917
+ value: 16,
918
+ unit: "px"
919
+ },
920
+ $type: "dimension"
921
+ },
922
+ sm: {
923
+ $value: {
924
+ value: 20,
925
+ unit: "px"
926
+ },
927
+ $type: "dimension"
928
+ },
929
+ base: {
930
+ $value: {
931
+ value: 24,
932
+ unit: "px"
933
+ },
934
+ $type: "dimension"
935
+ },
936
+ lg: {
937
+ $value: {
938
+ value: 28,
939
+ unit: "px"
940
+ },
941
+ $type: "dimension"
942
+ },
943
+ xl: {
944
+ $value: {
945
+ value: 28,
946
+ unit: "px"
947
+ },
948
+ $type: "dimension"
949
+ },
950
+ "2xl": {
951
+ $value: {
952
+ value: 32,
953
+ unit: "px"
954
+ },
955
+ $type: "dimension"
956
+ },
957
+ "3xl": {
958
+ $value: {
959
+ value: 36,
960
+ unit: "px"
961
+ },
962
+ $type: "dimension"
963
+ },
964
+ "4xl": {
965
+ $value: {
966
+ value: 48,
967
+ unit: "px"
968
+ },
969
+ $type: "dimension"
970
+ },
971
+ "5xl": {
972
+ $value: {
973
+ value: 48,
974
+ unit: "px"
975
+ },
976
+ $type: "dimension"
977
+ },
978
+ "6xl": {
979
+ $value: {
980
+ value: 60,
981
+ unit: "px"
982
+ },
983
+ $type: "dimension"
984
+ },
985
+ "7xl": {
986
+ $value: {
987
+ value: 72,
988
+ unit: "px"
989
+ },
990
+ $type: "dimension"
991
+ },
992
+ "8xl": {
993
+ $value: {
994
+ value: 96,
995
+ unit: "px"
996
+ },
997
+ $type: "dimension"
998
+ },
999
+ "9xl": {
1000
+ $value: {
1001
+ value: 128,
1002
+ unit: "px"
1003
+ },
1004
+ $type: "dimension"
1005
+ }
1006
+ },
1007
+ letterspacing: {
1008
+ tighter: {
1009
+ $value: {
1010
+ value: -0.800000011920929,
1011
+ unit: "px"
1012
+ },
1013
+ $type: "dimension"
1014
+ },
1015
+ tight: {
1016
+ $value: {
1017
+ value: -0.4000000059604645,
1018
+ unit: "px"
1019
+ },
1020
+ $type: "dimension"
1021
+ },
1022
+ normal: {
1023
+ $value: {
1024
+ value: 0,
1025
+ unit: "px"
1026
+ },
1027
+ $type: "dimension"
1028
+ },
1029
+ wide: {
1030
+ $value: {
1031
+ value: 0.4000000059604645,
1032
+ unit: "px"
1033
+ },
1034
+ $type: "dimension"
1035
+ },
1036
+ wider: {
1037
+ $value: {
1038
+ value: 0.800000011920929,
1039
+ unit: "px"
1040
+ },
1041
+ $type: "dimension"
1042
+ },
1043
+ widest: {
1044
+ $value: {
1045
+ value: 1.600000023841858,
1046
+ unit: "px"
1047
+ },
1048
+ $type: "dimension"
895
1049
  }
896
1050
  }
897
- return clamped;
898
- }
899
- function hexToOklchPinned(hex, shade, palette, reportGamutClip) {
900
- return formatPaletteOklch(
901
- computePinnedOklch(hex, shade, palette, reportGamutClip)
902
- );
903
- }
904
- function hexToOklchMechanical(hex) {
905
- return formatPaletteOklch(parseToOklch(hex));
906
- }
907
-
908
- // src/lib/perceptual-ramp.ts
909
- var EMIT_GAMUT2 = "p3";
910
- var CUSP_FRACTION2 = 0.95;
911
- function seedOklch(input) {
912
- const parsed = parse4(input);
913
- if (!parsed)
914
- throw new Error(`perceptual-ramp: cannot parse color '${input}'`);
915
- const converted = oklch4(parsed);
916
- if (!converted)
917
- throw new Error(`perceptual-ramp: cannot convert '${input}' to OKLCH`);
918
- return converted;
919
- }
920
- function pinnedOklch(seedHex, shade, options = {}) {
921
- const { capAtSeedChroma = true } = options;
922
- const seed = seedOklch(seedHex);
923
- const l = PERCEPTUAL_L_GRID[shade];
924
- const hue = seed.h ?? 0;
925
- const seedC = seed.c ?? 0;
926
- const cuspC = clampChroma3({ mode: "oklch", l, c: 0.5, h: hue }, "oklch", EMIT_GAMUT2).c ?? 0;
927
- let chroma = cuspC * CUSP_FRACTION2;
928
- if (capAtSeedChroma) chroma = Math.min(chroma, seedC);
929
- const target = { mode: "oklch", l, c: chroma, h: hue };
930
- return formatOklch(clampChroma3(target, "oklch", EMIT_GAMUT2));
931
- }
932
- function rampFromSeed(seedHex, options = {}) {
933
- const ramp = {};
934
- for (const shade of SHADES)
935
- ramp[shade] = pinnedOklch(seedHex, shade, options);
936
- return ramp;
937
- }
938
-
939
- // src/lib/contrast.ts
940
- var CONTRAST_MIN = 0;
941
- var CONTRAST_MAX = 100;
942
- function normalizeContrast(value, fallback = 50) {
943
- return typeof value === "number" && Number.isFinite(value) ? Math.round(Math.max(CONTRAST_MIN, Math.min(CONTRAST_MAX, value))) : fallback;
944
- }
945
- function contrastTarget(tier, contrast) {
946
- return TIER_THRESHOLDS[tier] + 15 * contrast / 100;
947
- }
948
- var BISECT_STEPS = 12;
949
- function bisect(fail, pass, passes) {
950
- for (let i = 0; i < BISECT_STEPS; i++) {
951
- const middle = (fail + pass) / 2;
952
- if (passes(middle)) pass = middle;
953
- else fail = middle;
954
- }
955
- return pass;
956
- }
957
- var token = (map, name) => {
958
- const value = map[`--nx-color-${name}`];
959
- if (value === void 0) throw new Error(`contrast: missing ${name}`);
960
- return value;
961
1051
  };
962
- function pairBackground(map, pair) {
963
- const backdrop = pair.backdrop ? resolveToSrgbInts(
964
- pair.backdrop.startsWith("#") ? pair.backdrop : token(map, pair.backdrop)
965
- ) : void 0;
966
- return resolveToSrgbInts(token(map, pair.bg), backdrop);
967
- }
968
- var luminance = (color) => sRGBtoY2(resolveToSrgbInts(color));
969
- var score = (foregroundY, backgroundY) => Math.abs(APCAcontrast2(foregroundY, backgroundY));
970
- function constraintsFor(map, pairs, contrast, endpointY) {
971
- const constraints = [];
972
- for (const pair of pairs) {
973
- const backgroundY = sRGBtoY2(pairBackground(map, pair));
974
- const reachable = score(endpointY, backgroundY);
975
- if (reachable < TIER_THRESHOLDS[pair.tier]) return void 0;
976
- const target = contrastTarget(pair.tier, contrast) + (pair.offset ?? 0);
977
- constraints.push({ backgroundY, target: Math.min(target, reachable) });
978
- }
979
- return constraints;
980
- }
981
- var keepsTextSeed = (mode, kind) => mode === "light" && kind === "text";
982
- function solveForeground(seed, constraints, endpoint, keepSeed) {
983
- const passes = (color) => {
984
- const y = luminance(color);
985
- return constraints.every((c) => score(y, c.backgroundY) >= c.target);
986
- };
987
- if (keepSeed && passes(seed)) return seed;
988
- const parsed = seedOklch(seed);
989
- const at = (l) => formatOklch(clampChroma4({ ...parsed, l, alpha: 1 }, "oklch", "p3"));
990
- return at(
991
- bisect(keepSeed ? parsed.l : 1 - endpoint, endpoint, (l) => passes(at(l)))
992
- );
993
- }
994
- var SOLVE_GROUPS = /* @__PURE__ */ new Map();
995
- for (const pair of APCA_PAIRS) {
996
- const key = pair.solveAs ?? pair.fg;
997
- const group = SOLVE_GROUPS.get(key);
998
- if (!group) {
999
- SOLVE_GROUPS.set(key, { kind: pair.kind, pairs: [pair] });
1000
- continue;
1001
- }
1002
- if (group.kind !== pair.kind)
1003
- throw new Error(
1004
- `contrast: ${pair.fg} is '${pair.kind}' but joins '${group.kind}' group ${key}`
1005
- );
1006
- group.pairs.push(pair);
1007
- }
1008
- function constrainFamilyFills(map, name, pairs) {
1009
- const basePair = pairs[0];
1010
- if (!basePair) throw new Error(`contrast: missing pairs for ${name}`);
1011
- const baseY = luminance(token(map, basePair.bg));
1012
- const endpoint = score(1, baseY) >= score(0, baseY) ? 1 : 0;
1013
- map[`--nx-color-${name}`] = `oklch(${endpoint} 0 0)`;
1014
- for (const pair of pairs) {
1015
- const floor = TIER_THRESHOLDS[pair.tier];
1016
- const value = token(map, pair.bg);
1017
- if (score(endpoint, luminance(value)) >= floor) continue;
1018
- const fill = seedOklch(value);
1019
- const at = (l) => formatOklch(clampChroma4({ ...fill, l }, "oklch", "p3"));
1020
- const readable = (l) => score(endpoint, luminance(at(l))) >= floor;
1021
- map[`--nx-color-${pair.bg}`] = at(bisect(fill.l, 1 - endpoint, readable));
1022
- }
1052
+
1053
+ // src/lib/typography-scale.ts
1054
+ var TYPOGRAPHY_BASE_PX = 14;
1055
+ function formatPx(value) {
1056
+ return `${Number(value.toFixed(4))}px`;
1023
1057
  }
1024
- function constrainColors(map, mode, contrast) {
1025
- for (const [name, { kind, pairs }] of SOLVE_GROUPS)
1026
- if (kind === "label") constrainFamilyFills(map, name, pairs);
1027
- const endpoint = mode === "dark" ? 1 : 0;
1028
- const endpointY = luminance(`oklch(${endpoint} 0 0)`);
1029
- for (const [name, { kind, pairs }] of SOLVE_GROUPS) {
1030
- if (kind === "label") continue;
1031
- const constraints = constraintsFor(map, pairs, contrast, endpointY);
1032
- if (constraints === void 0)
1033
- throw new Error(`contrast: no readable ${name} in ${mode}`);
1034
- const solved = solveForeground(
1035
- token(map, name),
1036
- constraints,
1037
- endpoint,
1038
- keepsTextSeed(mode, kind)
1039
- );
1040
- for (const fg of new Set(pairs.map((pair) => pair.fg).concat(name)))
1041
- map[`--nx-color-${fg}`] = solved;
1042
- }
1043
- return map;
1058
+ var CODE_SIZE = "code";
1059
+ function typographyScale(uiPx, codePx) {
1060
+ const scale = uiPx / TYPOGRAPHY_BASE_PX;
1061
+ return new Map([
1062
+ ...Object.entries(typography_default_default.size).map(
1063
+ ([name, token2]) => [
1064
+ `--nx-typography-size-${name}`,
1065
+ formatPx(name === CODE_SIZE ? codePx : token2.$value.value * scale)
1066
+ ]
1067
+ ),
1068
+ ...Object.entries(typography_default_default["line-height"]).map(
1069
+ ([name, token2]) => [
1070
+ `--nx-typography-line-height-${name}`,
1071
+ formatPx(token2.$value.value * scale)
1072
+ ]
1073
+ )
1074
+ ]);
1044
1075
  }
1076
+ var isCodeSize = (path) => path[0] === "size" && path[1] === CODE_SIZE;
1045
1077
 
1046
1078
  // src/lib/appearance-model.ts
1047
1079
  var DEFAULT_BRAND_COLOR = "#0a0a0a";
@@ -1115,7 +1147,7 @@ var DEFAULT_NXDS_APPEARANCE = {
1115
1147
  uiFont: '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
1116
1148
  headingFont: null,
1117
1149
  codeFont: 'ui-monospace, "SF Mono", Menlo, monospace',
1118
- uiFontSize: 14,
1150
+ uiFontSize: TYPOGRAPHY_BASE_PX,
1119
1151
  codeFontSize: 12,
1120
1152
  reduceMotion: false,
1121
1153
  pointerCursors: false,
@@ -11003,7 +11035,7 @@ var typography_default = {
11003
11035
  $type: "typography",
11004
11036
  $value: {
11005
11037
  fontFamily: "{family.font-mono}",
11006
- fontSize: "{size.sm}",
11038
+ fontSize: "{size.code}",
11007
11039
  fontWeight: "{weight.normal}",
11008
11040
  lineHeight: "{line-height.sm}",
11009
11041
  letterSpacing: {
@@ -11016,7 +11048,7 @@ var typography_default = {
11016
11048
  $type: "typography",
11017
11049
  $value: {
11018
11050
  fontFamily: "{family.font-mono}",
11019
- fontSize: "{size.sm}",
11051
+ fontSize: "{size.code}",
11020
11052
  fontWeight: "{weight.semibold}",
11021
11053
  lineHeight: "auto",
11022
11054
  letterSpacing: {
@@ -11086,6 +11118,7 @@ var PRESET_CONTROLS = {
11086
11118
  };
11087
11119
  function typographyControl(path) {
11088
11120
  const [group, key] = path;
11121
+ if (isCodeSize(path)) return { kind: "pref", field: "codeFontSize" };
11089
11122
  if (group === "size" || group === "line-height") {
11090
11123
  return { kind: "pref", field: "uiFontSize" };
11091
11124
  }
@@ -11252,7 +11285,7 @@ function primitiveAliases(family, path) {
11252
11285
  }
11253
11286
  return [];
11254
11287
  }
11255
- function primitiveEntry(lookup) {
11288
+ function primitiveEntry(lookup, scaled) {
11256
11289
  return ({ family, leaf }) => {
11257
11290
  const name = primitiveName(family, leaf.path);
11258
11291
  const reference = leaf.path.join(".");
@@ -11266,7 +11299,7 @@ function primitiveEntry(lookup) {
11266
11299
  declarations: [
11267
11300
  {
11268
11301
  property: name,
11269
- value: resolveValue(leaf.value, lookup, leaf.type, leaf.path)
11302
+ value: scaled.get(name) ?? resolveValue(leaf.value, lookup, leaf.type, leaf.path)
11270
11303
  }
11271
11304
  ]
11272
11305
  };
@@ -11368,13 +11401,6 @@ function styleLeaves(family, file) {
11368
11401
  ({ leaf }) => leaf.type === family
11369
11402
  );
11370
11403
  }
11371
- function runtimeAppearance(mode) {
11372
- return {
11373
- ...DEFAULT_NXDS_APPEARANCE,
11374
- prefs: { ...DEFAULT_NXDS_APPEARANCE.prefs },
11375
- mode
11376
- };
11377
- }
11378
11404
  function runtimeColorAliases(name) {
11379
11405
  const aliases = [cssVariable(`--color-${name}`)];
11380
11406
  const borderName = borderColorAliasName(name);
@@ -11383,15 +11409,14 @@ function runtimeColorAliases(name) {
11383
11409
  }
11384
11410
  return aliases;
11385
11411
  }
11386
- function runtimeColorTokens() {
11387
- const themes = RUNTIME_MODES.map((mode) => {
11388
- const appearance = runtimeAppearance(mode);
11389
- return {
11390
- mode,
11391
- appearance,
11392
- values: deriveThemeMode(createNxdsThemeContract(appearance), mode)
11393
- };
11394
- });
11412
+ function runtimeColorTokens(appearance) {
11413
+ const { brandColor, surfaceTone, lightContrast, darkContrast } = appearance;
11414
+ const colors = { brandColor, surfaceTone, lightContrast, darkContrast };
11415
+ const themes = RUNTIME_MODES.map((mode) => ({
11416
+ mode,
11417
+ appearance: { ...colors, mode },
11418
+ values: deriveThemeMode(createNxdsThemeContract(colors), mode)
11419
+ }));
11395
11420
  return SEMANTIC_TOKEN_REGISTRY.map(({ name, category }) => {
11396
11421
  const property = `--nx-color-${name}`;
11397
11422
  return {
@@ -11402,7 +11427,7 @@ function runtimeColorTokens() {
11402
11427
  description: RUNTIME_COLOR_DESCRIPTIONS[name] ?? null,
11403
11428
  aliases: runtimeColorAliases(name),
11404
11429
  control: null,
11405
- variants: themes.map(({ mode, appearance, values }) => {
11430
+ variants: themes.map(({ mode, appearance: appearance2, values }) => {
11406
11431
  const value = values[property];
11407
11432
  if (value === void 0) {
11408
11433
  throw new Error(`catalogue: deriveTheme emitted no ${property}`);
@@ -11411,7 +11436,7 @@ function runtimeColorTokens() {
11411
11436
  mode,
11412
11437
  preset: null,
11413
11438
  source: null,
11414
- appearance,
11439
+ appearance: appearance2,
11415
11440
  authoredValue: null,
11416
11441
  declarations: [{ property, value }],
11417
11442
  references: []
@@ -11420,7 +11445,7 @@ function runtimeColorTokens() {
11420
11445
  };
11421
11446
  });
11422
11447
  }
11423
- function createTokenCatalogue() {
11448
+ function createTokenCatalogue(appearance = DEFAULT_NXDS_APPEARANCE) {
11424
11449
  const primitives = PRIMITIVE_FAMILIES.flatMap(primitiveLeaves);
11425
11450
  const lookup = primitiveLookup(primitives);
11426
11451
  const shadowLayers = primitives.filter(({ family }) => family === "shadow");
@@ -11428,9 +11453,15 @@ function createTokenCatalogue() {
11428
11453
  ...authoredTokens(
11429
11454
  primitives.filter((leaf) => leaf.family !== "shadow"),
11430
11455
  lookup,
11431
- primitiveEntry(lookup)
11456
+ primitiveEntry(
11457
+ lookup,
11458
+ typographyScale(
11459
+ appearance.prefs.uiFontSize,
11460
+ appearance.prefs.codeFontSize
11461
+ )
11462
+ )
11432
11463
  ),
11433
- ...runtimeColorTokens(),
11464
+ ...runtimeColorTokens(appearance),
11434
11465
  ...authoredTokens(spacingLeaves(), lookup, spacingEntry),
11435
11466
  ...authoredTokens(
11436
11467
  fileLeaves("z-index", Z_INDEX_FILE, SINGLE_SOURCE),