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