@nxds/core 0.11.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.
- package/README.md +9 -0
- package/dist/runtime/catalogue.cjs +711 -641
- package/dist/runtime/catalogue.cjs.map +1 -1
- package/dist/runtime/catalogue.d.cts +22 -8
- package/dist/runtime/catalogue.d.ts +22 -8
- package/dist/runtime/catalogue.js +711 -641
- package/dist/runtime/catalogue.js.map +1 -1
- package/dist/runtime/index.cjs +803 -430
- package/dist/runtime/index.cjs.map +1 -1
- package/dist/runtime/index.d.cts +192 -3
- package/dist/runtime/index.d.ts +192 -3
- package/dist/runtime/index.js +792 -430
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/{surface-ladder-B950TU4_.d.ts → surface-ladder-Cqo5DfZW.d.ts} +9 -2
- package/dist/runtime/{surface-ladder-C8HTwT7z.d.cts → surface-ladder-DZQFqJvm.d.cts} +9 -2
- package/package.json +1 -1
|
@@ -1,381 +1,57 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
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,249 +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
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
}
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
"
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
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
|
-
function normalizeContrast(value, fallback = 50) {
|
|
941
|
-
return typeof value === "number" && Number.isFinite(value) ? Math.round(Math.max(0, Math.min(100, value))) : fallback;
|
|
942
|
-
}
|
|
943
|
-
function contrastTarget(tier, contrast) {
|
|
944
|
-
return TIER_THRESHOLDS[tier] + 15 * contrast / 100;
|
|
945
|
-
}
|
|
946
|
-
var BISECT_STEPS = 12;
|
|
947
|
-
function bisect(fail, pass, passes) {
|
|
948
|
-
for (let i = 0; i < BISECT_STEPS; i++) {
|
|
949
|
-
const middle = (fail + pass) / 2;
|
|
950
|
-
if (passes(middle)) pass = middle;
|
|
951
|
-
else fail = middle;
|
|
952
|
-
}
|
|
953
|
-
return pass;
|
|
954
|
-
}
|
|
955
|
-
var token = (map, name) => {
|
|
956
|
-
const value = map[`--nx-color-${name}`];
|
|
957
|
-
if (value === void 0) throw new Error(`contrast: missing ${name}`);
|
|
958
|
-
return value;
|
|
959
1051
|
};
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
return
|
|
965
|
-
}
|
|
966
|
-
var luminance = (color) => sRGBtoY2(resolveToSrgbInts(color));
|
|
967
|
-
var score = (foregroundY, backgroundY) => Math.abs(APCAcontrast2(foregroundY, backgroundY));
|
|
968
|
-
function constraintsFor(map, pairs, contrast, endpointY) {
|
|
969
|
-
const constraints = [];
|
|
970
|
-
for (const pair of pairs) {
|
|
971
|
-
const backgroundY = sRGBtoY2(pairBackground(map, pair));
|
|
972
|
-
const reachable = score(endpointY, backgroundY);
|
|
973
|
-
if (reachable < TIER_THRESHOLDS[pair.tier]) return void 0;
|
|
974
|
-
const target = contrastTarget(pair.tier, contrast) + (pair.offset ?? 0);
|
|
975
|
-
constraints.push({ backgroundY, target: Math.min(target, reachable) });
|
|
976
|
-
}
|
|
977
|
-
return constraints;
|
|
978
|
-
}
|
|
979
|
-
var keepsTextSeed = (mode, kind) => mode === "light" && kind === "text";
|
|
980
|
-
function solveForeground(seed, constraints, endpoint, keepSeed) {
|
|
981
|
-
const passes = (color) => {
|
|
982
|
-
const y = luminance(color);
|
|
983
|
-
return constraints.every((c) => score(y, c.backgroundY) >= c.target);
|
|
984
|
-
};
|
|
985
|
-
if (keepSeed && passes(seed)) return seed;
|
|
986
|
-
const parsed = seedOklch(seed);
|
|
987
|
-
const at = (l) => formatOklch(clampChroma4({ ...parsed, l, alpha: 1 }, "oklch", "p3"));
|
|
988
|
-
return at(
|
|
989
|
-
bisect(keepSeed ? parsed.l : 1 - endpoint, endpoint, (l) => passes(at(l)))
|
|
990
|
-
);
|
|
991
|
-
}
|
|
992
|
-
var SOLVE_GROUPS = /* @__PURE__ */ new Map();
|
|
993
|
-
for (const pair of APCA_PAIRS) {
|
|
994
|
-
const key = pair.solveAs ?? pair.fg;
|
|
995
|
-
const group = SOLVE_GROUPS.get(key);
|
|
996
|
-
if (!group) {
|
|
997
|
-
SOLVE_GROUPS.set(key, { kind: pair.kind, pairs: [pair] });
|
|
998
|
-
continue;
|
|
999
|
-
}
|
|
1000
|
-
if (group.kind !== pair.kind)
|
|
1001
|
-
throw new Error(
|
|
1002
|
-
`contrast: ${pair.fg} is '${pair.kind}' but joins '${group.kind}' group ${key}`
|
|
1003
|
-
);
|
|
1004
|
-
group.pairs.push(pair);
|
|
1005
|
-
}
|
|
1006
|
-
function constrainFamilyFills(map, name, pairs) {
|
|
1007
|
-
const basePair = pairs[0];
|
|
1008
|
-
if (!basePair) throw new Error(`contrast: missing pairs for ${name}`);
|
|
1009
|
-
const baseY = luminance(token(map, basePair.bg));
|
|
1010
|
-
const endpoint = score(1, baseY) >= score(0, baseY) ? 1 : 0;
|
|
1011
|
-
map[`--nx-color-${name}`] = `oklch(${endpoint} 0 0)`;
|
|
1012
|
-
for (const pair of pairs) {
|
|
1013
|
-
const floor = TIER_THRESHOLDS[pair.tier];
|
|
1014
|
-
const value = token(map, pair.bg);
|
|
1015
|
-
if (score(endpoint, luminance(value)) >= floor) continue;
|
|
1016
|
-
const fill = seedOklch(value);
|
|
1017
|
-
const at = (l) => formatOklch(clampChroma4({ ...fill, l }, "oklch", "p3"));
|
|
1018
|
-
const readable = (l) => score(endpoint, luminance(at(l))) >= floor;
|
|
1019
|
-
map[`--nx-color-${pair.bg}`] = at(bisect(fill.l, 1 - endpoint, readable));
|
|
1020
|
-
}
|
|
1052
|
+
|
|
1053
|
+
// src/lib/typography-scale.ts
|
|
1054
|
+
var TYPOGRAPHY_BASE_PX = 14;
|
|
1055
|
+
function formatPx(value) {
|
|
1056
|
+
return `${Number(value.toFixed(4))}px`;
|
|
1021
1057
|
}
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
)
|
|
1038
|
-
|
|
1039
|
-
map[`--nx-color-${fg}`] = solved;
|
|
1040
|
-
}
|
|
1041
|
-
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
|
+
]);
|
|
1042
1075
|
}
|
|
1076
|
+
var isCodeSize = (path) => path[0] === "size" && path[1] === CODE_SIZE;
|
|
1043
1077
|
|
|
1044
1078
|
// src/lib/appearance-model.ts
|
|
1045
1079
|
var DEFAULT_BRAND_COLOR = "#0a0a0a";
|
|
@@ -1111,8 +1145,9 @@ var DEFAULT_NXDS_APPEARANCE = {
|
|
|
1111
1145
|
stroke: "normal",
|
|
1112
1146
|
prefs: {
|
|
1113
1147
|
uiFont: '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
|
|
1148
|
+
headingFont: null,
|
|
1114
1149
|
codeFont: 'ui-monospace, "SF Mono", Menlo, monospace',
|
|
1115
|
-
uiFontSize:
|
|
1150
|
+
uiFontSize: TYPOGRAPHY_BASE_PX,
|
|
1116
1151
|
codeFontSize: 12,
|
|
1117
1152
|
reduceMotion: false,
|
|
1118
1153
|
pointerCursors: false,
|
|
@@ -3254,7 +3289,7 @@ function formatTypographyDeclarations(tokenPath, value, primitiveMap) {
|
|
|
3254
3289
|
const css = fieldValue === "auto" ? "normal" : resolveValue(fieldValue, primitiveMap);
|
|
3255
3290
|
declarations.push({ property, value: css });
|
|
3256
3291
|
}
|
|
3257
|
-
if (tokenPath[0] === "heading") {
|
|
3292
|
+
if (tokenPath[0] === "display" || tokenPath[0] === "heading") {
|
|
3258
3293
|
declarations.push({ property: "text-wrap", value: "balance" });
|
|
3259
3294
|
}
|
|
3260
3295
|
if (tokenPath[0] === "body") {
|
|
@@ -10833,6 +10868,41 @@ var shadows_default = {
|
|
|
10833
10868
|
|
|
10834
10869
|
// tokens/styles/typography.json
|
|
10835
10870
|
var typography_default = {
|
|
10871
|
+
display: {
|
|
10872
|
+
large: {
|
|
10873
|
+
$type: "typography",
|
|
10874
|
+
$value: {
|
|
10875
|
+
fontFamily: "{family.font-heading}",
|
|
10876
|
+
fontSize: "{size.5xl}",
|
|
10877
|
+
fontWeight: "{weight.semibold}",
|
|
10878
|
+
lineHeight: "{line-height.5xl}",
|
|
10879
|
+
letterSpacing: "{letterspacing.tighter}"
|
|
10880
|
+
},
|
|
10881
|
+
$description: "Largest display title \u2014 hero and landing-page section titles"
|
|
10882
|
+
},
|
|
10883
|
+
medium: {
|
|
10884
|
+
$type: "typography",
|
|
10885
|
+
$value: {
|
|
10886
|
+
fontFamily: "{family.font-heading}",
|
|
10887
|
+
fontSize: "{size.4xl}",
|
|
10888
|
+
fontWeight: "{weight.semibold}",
|
|
10889
|
+
lineHeight: "{line-height.4xl}",
|
|
10890
|
+
letterSpacing: "{letterspacing.tighter}"
|
|
10891
|
+
},
|
|
10892
|
+
$description: "Display title one step below display-large, for page sections"
|
|
10893
|
+
},
|
|
10894
|
+
small: {
|
|
10895
|
+
$type: "typography",
|
|
10896
|
+
$value: {
|
|
10897
|
+
fontFamily: "{family.font-heading}",
|
|
10898
|
+
fontSize: "{size.3xl}",
|
|
10899
|
+
fontWeight: "{weight.semibold}",
|
|
10900
|
+
lineHeight: "{line-height.3xl}",
|
|
10901
|
+
letterSpacing: "{letterspacing.tighter}"
|
|
10902
|
+
},
|
|
10903
|
+
$description: "Smallest display title \u2014 page-section titles in narrow layouts"
|
|
10904
|
+
}
|
|
10905
|
+
},
|
|
10836
10906
|
heading: {
|
|
10837
10907
|
large: {
|
|
10838
10908
|
$type: "typography",
|
|
@@ -10965,7 +11035,7 @@ var typography_default = {
|
|
|
10965
11035
|
$type: "typography",
|
|
10966
11036
|
$value: {
|
|
10967
11037
|
fontFamily: "{family.font-mono}",
|
|
10968
|
-
fontSize: "{size.
|
|
11038
|
+
fontSize: "{size.code}",
|
|
10969
11039
|
fontWeight: "{weight.normal}",
|
|
10970
11040
|
lineHeight: "{line-height.sm}",
|
|
10971
11041
|
letterSpacing: {
|
|
@@ -10978,7 +11048,7 @@ var typography_default = {
|
|
|
10978
11048
|
$type: "typography",
|
|
10979
11049
|
$value: {
|
|
10980
11050
|
fontFamily: "{family.font-mono}",
|
|
10981
|
-
fontSize: "{size.
|
|
11051
|
+
fontSize: "{size.code}",
|
|
10982
11052
|
fontWeight: "{weight.semibold}",
|
|
10983
11053
|
lineHeight: "auto",
|
|
10984
11054
|
letterSpacing: {
|
|
@@ -11048,11 +11118,13 @@ var PRESET_CONTROLS = {
|
|
|
11048
11118
|
};
|
|
11049
11119
|
function typographyControl(path) {
|
|
11050
11120
|
const [group, key] = path;
|
|
11121
|
+
if (isCodeSize(path)) return { kind: "pref", field: "codeFontSize" };
|
|
11051
11122
|
if (group === "size" || group === "line-height") {
|
|
11052
11123
|
return { kind: "pref", field: "uiFontSize" };
|
|
11053
11124
|
}
|
|
11054
11125
|
if (group !== "family") return null;
|
|
11055
11126
|
if (key === "font-sans") return { kind: "pref", field: "uiFont" };
|
|
11127
|
+
if (key === "font-heading") return { kind: "pref", field: "headingFont" };
|
|
11056
11128
|
if (key === "font-mono") return { kind: "pref", field: "codeFont" };
|
|
11057
11129
|
return null;
|
|
11058
11130
|
}
|
|
@@ -11213,7 +11285,7 @@ function primitiveAliases(family, path) {
|
|
|
11213
11285
|
}
|
|
11214
11286
|
return [];
|
|
11215
11287
|
}
|
|
11216
|
-
function primitiveEntry(lookup) {
|
|
11288
|
+
function primitiveEntry(lookup, scaled) {
|
|
11217
11289
|
return ({ family, leaf }) => {
|
|
11218
11290
|
const name = primitiveName(family, leaf.path);
|
|
11219
11291
|
const reference = leaf.path.join(".");
|
|
@@ -11227,7 +11299,7 @@ function primitiveEntry(lookup) {
|
|
|
11227
11299
|
declarations: [
|
|
11228
11300
|
{
|
|
11229
11301
|
property: name,
|
|
11230
|
-
value: resolveValue(leaf.value, lookup, leaf.type, leaf.path)
|
|
11302
|
+
value: scaled.get(name) ?? resolveValue(leaf.value, lookup, leaf.type, leaf.path)
|
|
11231
11303
|
}
|
|
11232
11304
|
]
|
|
11233
11305
|
};
|
|
@@ -11329,13 +11401,6 @@ function styleLeaves(family, file) {
|
|
|
11329
11401
|
({ leaf }) => leaf.type === family
|
|
11330
11402
|
);
|
|
11331
11403
|
}
|
|
11332
|
-
function runtimeAppearance(mode) {
|
|
11333
|
-
return {
|
|
11334
|
-
...DEFAULT_NXDS_APPEARANCE,
|
|
11335
|
-
prefs: { ...DEFAULT_NXDS_APPEARANCE.prefs },
|
|
11336
|
-
mode
|
|
11337
|
-
};
|
|
11338
|
-
}
|
|
11339
11404
|
function runtimeColorAliases(name) {
|
|
11340
11405
|
const aliases = [cssVariable(`--color-${name}`)];
|
|
11341
11406
|
const borderName = borderColorAliasName(name);
|
|
@@ -11344,15 +11409,14 @@ function runtimeColorAliases(name) {
|
|
|
11344
11409
|
}
|
|
11345
11410
|
return aliases;
|
|
11346
11411
|
}
|
|
11347
|
-
function runtimeColorTokens() {
|
|
11348
|
-
const
|
|
11349
|
-
|
|
11350
|
-
|
|
11351
|
-
|
|
11352
|
-
|
|
11353
|
-
|
|
11354
|
-
|
|
11355
|
-
});
|
|
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
|
+
}));
|
|
11356
11420
|
return SEMANTIC_TOKEN_REGISTRY.map(({ name, category }) => {
|
|
11357
11421
|
const property = `--nx-color-${name}`;
|
|
11358
11422
|
return {
|
|
@@ -11363,7 +11427,7 @@ function runtimeColorTokens() {
|
|
|
11363
11427
|
description: RUNTIME_COLOR_DESCRIPTIONS[name] ?? null,
|
|
11364
11428
|
aliases: runtimeColorAliases(name),
|
|
11365
11429
|
control: null,
|
|
11366
|
-
variants: themes.map(({ mode, appearance, values }) => {
|
|
11430
|
+
variants: themes.map(({ mode, appearance: appearance2, values }) => {
|
|
11367
11431
|
const value = values[property];
|
|
11368
11432
|
if (value === void 0) {
|
|
11369
11433
|
throw new Error(`catalogue: deriveTheme emitted no ${property}`);
|
|
@@ -11372,7 +11436,7 @@ function runtimeColorTokens() {
|
|
|
11372
11436
|
mode,
|
|
11373
11437
|
preset: null,
|
|
11374
11438
|
source: null,
|
|
11375
|
-
appearance,
|
|
11439
|
+
appearance: appearance2,
|
|
11376
11440
|
authoredValue: null,
|
|
11377
11441
|
declarations: [{ property, value }],
|
|
11378
11442
|
references: []
|
|
@@ -11381,7 +11445,7 @@ function runtimeColorTokens() {
|
|
|
11381
11445
|
};
|
|
11382
11446
|
});
|
|
11383
11447
|
}
|
|
11384
|
-
function createTokenCatalogue() {
|
|
11448
|
+
function createTokenCatalogue(appearance = DEFAULT_NXDS_APPEARANCE) {
|
|
11385
11449
|
const primitives = PRIMITIVE_FAMILIES.flatMap(primitiveLeaves);
|
|
11386
11450
|
const lookup = primitiveLookup(primitives);
|
|
11387
11451
|
const shadowLayers = primitives.filter(({ family }) => family === "shadow");
|
|
@@ -11389,9 +11453,15 @@ function createTokenCatalogue() {
|
|
|
11389
11453
|
...authoredTokens(
|
|
11390
11454
|
primitives.filter((leaf) => leaf.family !== "shadow"),
|
|
11391
11455
|
lookup,
|
|
11392
|
-
primitiveEntry(
|
|
11456
|
+
primitiveEntry(
|
|
11457
|
+
lookup,
|
|
11458
|
+
typographyScale(
|
|
11459
|
+
appearance.prefs.uiFontSize,
|
|
11460
|
+
appearance.prefs.codeFontSize
|
|
11461
|
+
)
|
|
11462
|
+
)
|
|
11393
11463
|
),
|
|
11394
|
-
...runtimeColorTokens(),
|
|
11464
|
+
...runtimeColorTokens(appearance),
|
|
11395
11465
|
...authoredTokens(spacingLeaves(), lookup, spacingEntry),
|
|
11396
11466
|
...authoredTokens(
|
|
11397
11467
|
fileLeaves("z-index", Z_INDEX_FILE, SINGLE_SOURCE),
|