@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
|
@@ -27,384 +27,60 @@ __export(catalogue_exports, {
|
|
|
27
27
|
});
|
|
28
28
|
module.exports = __toCommonJS(catalogue_exports);
|
|
29
29
|
|
|
30
|
-
//
|
|
31
|
-
var
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
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,249 +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
|
-
|
|
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
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
"
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
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
|
-
function normalizeContrast(value, fallback = 50) {
|
|
970
|
-
return typeof value === "number" && Number.isFinite(value) ? Math.round(Math.max(0, Math.min(100, value))) : fallback;
|
|
971
|
-
}
|
|
972
|
-
function contrastTarget(tier, contrast) {
|
|
973
|
-
return TIER_THRESHOLDS[tier] + 15 * contrast / 100;
|
|
974
|
-
}
|
|
975
|
-
var BISECT_STEPS = 12;
|
|
976
|
-
function bisect(fail, pass, passes) {
|
|
977
|
-
for (let i = 0; i < BISECT_STEPS; i++) {
|
|
978
|
-
const middle = (fail + pass) / 2;
|
|
979
|
-
if (passes(middle)) pass = middle;
|
|
980
|
-
else fail = middle;
|
|
981
|
-
}
|
|
982
|
-
return pass;
|
|
983
|
-
}
|
|
984
|
-
var token = (map, name) => {
|
|
985
|
-
const value = map[`--nx-color-${name}`];
|
|
986
|
-
if (value === void 0) throw new Error(`contrast: missing ${name}`);
|
|
987
|
-
return value;
|
|
988
1080
|
};
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
return
|
|
994
|
-
}
|
|
995
|
-
var luminance = (color) => (0, import_apca_w32.sRGBtoY)(resolveToSrgbInts(color));
|
|
996
|
-
var score = (foregroundY, backgroundY) => Math.abs((0, import_apca_w32.APCAcontrast)(foregroundY, backgroundY));
|
|
997
|
-
function constraintsFor(map, pairs, contrast, endpointY) {
|
|
998
|
-
const constraints = [];
|
|
999
|
-
for (const pair of pairs) {
|
|
1000
|
-
const backgroundY = (0, import_apca_w32.sRGBtoY)(pairBackground(map, pair));
|
|
1001
|
-
const reachable = score(endpointY, backgroundY);
|
|
1002
|
-
if (reachable < TIER_THRESHOLDS[pair.tier]) return void 0;
|
|
1003
|
-
const target = contrastTarget(pair.tier, contrast) + (pair.offset ?? 0);
|
|
1004
|
-
constraints.push({ backgroundY, target: Math.min(target, reachable) });
|
|
1005
|
-
}
|
|
1006
|
-
return constraints;
|
|
1007
|
-
}
|
|
1008
|
-
var keepsTextSeed = (mode, kind) => mode === "light" && kind === "text";
|
|
1009
|
-
function solveForeground(seed, constraints, endpoint, keepSeed) {
|
|
1010
|
-
const passes = (color) => {
|
|
1011
|
-
const y = luminance(color);
|
|
1012
|
-
return constraints.every((c) => score(y, c.backgroundY) >= c.target);
|
|
1013
|
-
};
|
|
1014
|
-
if (keepSeed && passes(seed)) return seed;
|
|
1015
|
-
const parsed = seedOklch(seed);
|
|
1016
|
-
const at = (l) => formatOklch((0, import_culori5.clampChroma)({ ...parsed, l, alpha: 1 }, "oklch", "p3"));
|
|
1017
|
-
return at(
|
|
1018
|
-
bisect(keepSeed ? parsed.l : 1 - endpoint, endpoint, (l) => passes(at(l)))
|
|
1019
|
-
);
|
|
1020
|
-
}
|
|
1021
|
-
var SOLVE_GROUPS = /* @__PURE__ */ new Map();
|
|
1022
|
-
for (const pair of APCA_PAIRS) {
|
|
1023
|
-
const key = pair.solveAs ?? pair.fg;
|
|
1024
|
-
const group = SOLVE_GROUPS.get(key);
|
|
1025
|
-
if (!group) {
|
|
1026
|
-
SOLVE_GROUPS.set(key, { kind: pair.kind, pairs: [pair] });
|
|
1027
|
-
continue;
|
|
1028
|
-
}
|
|
1029
|
-
if (group.kind !== pair.kind)
|
|
1030
|
-
throw new Error(
|
|
1031
|
-
`contrast: ${pair.fg} is '${pair.kind}' but joins '${group.kind}' group ${key}`
|
|
1032
|
-
);
|
|
1033
|
-
group.pairs.push(pair);
|
|
1034
|
-
}
|
|
1035
|
-
function constrainFamilyFills(map, name, pairs) {
|
|
1036
|
-
const basePair = pairs[0];
|
|
1037
|
-
if (!basePair) throw new Error(`contrast: missing pairs for ${name}`);
|
|
1038
|
-
const baseY = luminance(token(map, basePair.bg));
|
|
1039
|
-
const endpoint = score(1, baseY) >= score(0, baseY) ? 1 : 0;
|
|
1040
|
-
map[`--nx-color-${name}`] = `oklch(${endpoint} 0 0)`;
|
|
1041
|
-
for (const pair of pairs) {
|
|
1042
|
-
const floor = TIER_THRESHOLDS[pair.tier];
|
|
1043
|
-
const value = token(map, pair.bg);
|
|
1044
|
-
if (score(endpoint, luminance(value)) >= floor) continue;
|
|
1045
|
-
const fill = seedOklch(value);
|
|
1046
|
-
const at = (l) => formatOklch((0, import_culori5.clampChroma)({ ...fill, l }, "oklch", "p3"));
|
|
1047
|
-
const readable = (l) => score(endpoint, luminance(at(l))) >= floor;
|
|
1048
|
-
map[`--nx-color-${pair.bg}`] = at(bisect(fill.l, 1 - endpoint, readable));
|
|
1049
|
-
}
|
|
1081
|
+
|
|
1082
|
+
// src/lib/typography-scale.ts
|
|
1083
|
+
var TYPOGRAPHY_BASE_PX = 14;
|
|
1084
|
+
function formatPx(value) {
|
|
1085
|
+
return `${Number(value.toFixed(4))}px`;
|
|
1050
1086
|
}
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
)
|
|
1067
|
-
|
|
1068
|
-
map[`--nx-color-${fg}`] = solved;
|
|
1069
|
-
}
|
|
1070
|
-
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
|
+
]);
|
|
1071
1104
|
}
|
|
1105
|
+
var isCodeSize = (path) => path[0] === "size" && path[1] === CODE_SIZE;
|
|
1072
1106
|
|
|
1073
1107
|
// src/lib/appearance-model.ts
|
|
1074
1108
|
var DEFAULT_BRAND_COLOR = "#0a0a0a";
|
|
@@ -1140,8 +1174,9 @@ var DEFAULT_NXDS_APPEARANCE = {
|
|
|
1140
1174
|
stroke: "normal",
|
|
1141
1175
|
prefs: {
|
|
1142
1176
|
uiFont: '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
|
|
1177
|
+
headingFont: null,
|
|
1143
1178
|
codeFont: 'ui-monospace, "SF Mono", Menlo, monospace',
|
|
1144
|
-
uiFontSize:
|
|
1179
|
+
uiFontSize: TYPOGRAPHY_BASE_PX,
|
|
1145
1180
|
codeFontSize: 12,
|
|
1146
1181
|
reduceMotion: false,
|
|
1147
1182
|
pointerCursors: false,
|
|
@@ -3283,7 +3318,7 @@ function formatTypographyDeclarations(tokenPath, value, primitiveMap) {
|
|
|
3283
3318
|
const css = fieldValue === "auto" ? "normal" : resolveValue(fieldValue, primitiveMap);
|
|
3284
3319
|
declarations.push({ property, value: css });
|
|
3285
3320
|
}
|
|
3286
|
-
if (tokenPath[0] === "heading") {
|
|
3321
|
+
if (tokenPath[0] === "display" || tokenPath[0] === "heading") {
|
|
3287
3322
|
declarations.push({ property: "text-wrap", value: "balance" });
|
|
3288
3323
|
}
|
|
3289
3324
|
if (tokenPath[0] === "body") {
|
|
@@ -10862,6 +10897,41 @@ var shadows_default = {
|
|
|
10862
10897
|
|
|
10863
10898
|
// tokens/styles/typography.json
|
|
10864
10899
|
var typography_default = {
|
|
10900
|
+
display: {
|
|
10901
|
+
large: {
|
|
10902
|
+
$type: "typography",
|
|
10903
|
+
$value: {
|
|
10904
|
+
fontFamily: "{family.font-heading}",
|
|
10905
|
+
fontSize: "{size.5xl}",
|
|
10906
|
+
fontWeight: "{weight.semibold}",
|
|
10907
|
+
lineHeight: "{line-height.5xl}",
|
|
10908
|
+
letterSpacing: "{letterspacing.tighter}"
|
|
10909
|
+
},
|
|
10910
|
+
$description: "Largest display title \u2014 hero and landing-page section titles"
|
|
10911
|
+
},
|
|
10912
|
+
medium: {
|
|
10913
|
+
$type: "typography",
|
|
10914
|
+
$value: {
|
|
10915
|
+
fontFamily: "{family.font-heading}",
|
|
10916
|
+
fontSize: "{size.4xl}",
|
|
10917
|
+
fontWeight: "{weight.semibold}",
|
|
10918
|
+
lineHeight: "{line-height.4xl}",
|
|
10919
|
+
letterSpacing: "{letterspacing.tighter}"
|
|
10920
|
+
},
|
|
10921
|
+
$description: "Display title one step below display-large, for page sections"
|
|
10922
|
+
},
|
|
10923
|
+
small: {
|
|
10924
|
+
$type: "typography",
|
|
10925
|
+
$value: {
|
|
10926
|
+
fontFamily: "{family.font-heading}",
|
|
10927
|
+
fontSize: "{size.3xl}",
|
|
10928
|
+
fontWeight: "{weight.semibold}",
|
|
10929
|
+
lineHeight: "{line-height.3xl}",
|
|
10930
|
+
letterSpacing: "{letterspacing.tighter}"
|
|
10931
|
+
},
|
|
10932
|
+
$description: "Smallest display title \u2014 page-section titles in narrow layouts"
|
|
10933
|
+
}
|
|
10934
|
+
},
|
|
10865
10935
|
heading: {
|
|
10866
10936
|
large: {
|
|
10867
10937
|
$type: "typography",
|
|
@@ -10994,7 +11064,7 @@ var typography_default = {
|
|
|
10994
11064
|
$type: "typography",
|
|
10995
11065
|
$value: {
|
|
10996
11066
|
fontFamily: "{family.font-mono}",
|
|
10997
|
-
fontSize: "{size.
|
|
11067
|
+
fontSize: "{size.code}",
|
|
10998
11068
|
fontWeight: "{weight.normal}",
|
|
10999
11069
|
lineHeight: "{line-height.sm}",
|
|
11000
11070
|
letterSpacing: {
|
|
@@ -11007,7 +11077,7 @@ var typography_default = {
|
|
|
11007
11077
|
$type: "typography",
|
|
11008
11078
|
$value: {
|
|
11009
11079
|
fontFamily: "{family.font-mono}",
|
|
11010
|
-
fontSize: "{size.
|
|
11080
|
+
fontSize: "{size.code}",
|
|
11011
11081
|
fontWeight: "{weight.semibold}",
|
|
11012
11082
|
lineHeight: "auto",
|
|
11013
11083
|
letterSpacing: {
|
|
@@ -11077,11 +11147,13 @@ var PRESET_CONTROLS = {
|
|
|
11077
11147
|
};
|
|
11078
11148
|
function typographyControl(path) {
|
|
11079
11149
|
const [group, key] = path;
|
|
11150
|
+
if (isCodeSize(path)) return { kind: "pref", field: "codeFontSize" };
|
|
11080
11151
|
if (group === "size" || group === "line-height") {
|
|
11081
11152
|
return { kind: "pref", field: "uiFontSize" };
|
|
11082
11153
|
}
|
|
11083
11154
|
if (group !== "family") return null;
|
|
11084
11155
|
if (key === "font-sans") return { kind: "pref", field: "uiFont" };
|
|
11156
|
+
if (key === "font-heading") return { kind: "pref", field: "headingFont" };
|
|
11085
11157
|
if (key === "font-mono") return { kind: "pref", field: "codeFont" };
|
|
11086
11158
|
return null;
|
|
11087
11159
|
}
|
|
@@ -11242,7 +11314,7 @@ function primitiveAliases(family, path) {
|
|
|
11242
11314
|
}
|
|
11243
11315
|
return [];
|
|
11244
11316
|
}
|
|
11245
|
-
function primitiveEntry(lookup) {
|
|
11317
|
+
function primitiveEntry(lookup, scaled) {
|
|
11246
11318
|
return ({ family, leaf }) => {
|
|
11247
11319
|
const name = primitiveName(family, leaf.path);
|
|
11248
11320
|
const reference = leaf.path.join(".");
|
|
@@ -11256,7 +11328,7 @@ function primitiveEntry(lookup) {
|
|
|
11256
11328
|
declarations: [
|
|
11257
11329
|
{
|
|
11258
11330
|
property: name,
|
|
11259
|
-
value: resolveValue(leaf.value, lookup, leaf.type, leaf.path)
|
|
11331
|
+
value: scaled.get(name) ?? resolveValue(leaf.value, lookup, leaf.type, leaf.path)
|
|
11260
11332
|
}
|
|
11261
11333
|
]
|
|
11262
11334
|
};
|
|
@@ -11358,13 +11430,6 @@ function styleLeaves(family, file) {
|
|
|
11358
11430
|
({ leaf }) => leaf.type === family
|
|
11359
11431
|
);
|
|
11360
11432
|
}
|
|
11361
|
-
function runtimeAppearance(mode) {
|
|
11362
|
-
return {
|
|
11363
|
-
...DEFAULT_NXDS_APPEARANCE,
|
|
11364
|
-
prefs: { ...DEFAULT_NXDS_APPEARANCE.prefs },
|
|
11365
|
-
mode
|
|
11366
|
-
};
|
|
11367
|
-
}
|
|
11368
11433
|
function runtimeColorAliases(name) {
|
|
11369
11434
|
const aliases = [cssVariable(`--color-${name}`)];
|
|
11370
11435
|
const borderName = borderColorAliasName(name);
|
|
@@ -11373,15 +11438,14 @@ function runtimeColorAliases(name) {
|
|
|
11373
11438
|
}
|
|
11374
11439
|
return aliases;
|
|
11375
11440
|
}
|
|
11376
|
-
function runtimeColorTokens() {
|
|
11377
|
-
const
|
|
11378
|
-
|
|
11379
|
-
|
|
11380
|
-
|
|
11381
|
-
|
|
11382
|
-
|
|
11383
|
-
|
|
11384
|
-
});
|
|
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
|
+
}));
|
|
11385
11449
|
return SEMANTIC_TOKEN_REGISTRY.map(({ name, category }) => {
|
|
11386
11450
|
const property = `--nx-color-${name}`;
|
|
11387
11451
|
return {
|
|
@@ -11392,7 +11456,7 @@ function runtimeColorTokens() {
|
|
|
11392
11456
|
description: RUNTIME_COLOR_DESCRIPTIONS[name] ?? null,
|
|
11393
11457
|
aliases: runtimeColorAliases(name),
|
|
11394
11458
|
control: null,
|
|
11395
|
-
variants: themes.map(({ mode, appearance, values }) => {
|
|
11459
|
+
variants: themes.map(({ mode, appearance: appearance2, values }) => {
|
|
11396
11460
|
const value = values[property];
|
|
11397
11461
|
if (value === void 0) {
|
|
11398
11462
|
throw new Error(`catalogue: deriveTheme emitted no ${property}`);
|
|
@@ -11401,7 +11465,7 @@ function runtimeColorTokens() {
|
|
|
11401
11465
|
mode,
|
|
11402
11466
|
preset: null,
|
|
11403
11467
|
source: null,
|
|
11404
|
-
appearance,
|
|
11468
|
+
appearance: appearance2,
|
|
11405
11469
|
authoredValue: null,
|
|
11406
11470
|
declarations: [{ property, value }],
|
|
11407
11471
|
references: []
|
|
@@ -11410,7 +11474,7 @@ function runtimeColorTokens() {
|
|
|
11410
11474
|
};
|
|
11411
11475
|
});
|
|
11412
11476
|
}
|
|
11413
|
-
function createTokenCatalogue() {
|
|
11477
|
+
function createTokenCatalogue(appearance = DEFAULT_NXDS_APPEARANCE) {
|
|
11414
11478
|
const primitives = PRIMITIVE_FAMILIES.flatMap(primitiveLeaves);
|
|
11415
11479
|
const lookup = primitiveLookup(primitives);
|
|
11416
11480
|
const shadowLayers = primitives.filter(({ family }) => family === "shadow");
|
|
@@ -11418,9 +11482,15 @@ function createTokenCatalogue() {
|
|
|
11418
11482
|
...authoredTokens(
|
|
11419
11483
|
primitives.filter((leaf) => leaf.family !== "shadow"),
|
|
11420
11484
|
lookup,
|
|
11421
|
-
primitiveEntry(
|
|
11485
|
+
primitiveEntry(
|
|
11486
|
+
lookup,
|
|
11487
|
+
typographyScale(
|
|
11488
|
+
appearance.prefs.uiFontSize,
|
|
11489
|
+
appearance.prefs.codeFontSize
|
|
11490
|
+
)
|
|
11491
|
+
)
|
|
11422
11492
|
),
|
|
11423
|
-
...runtimeColorTokens(),
|
|
11493
|
+
...runtimeColorTokens(appearance),
|
|
11424
11494
|
...authoredTokens(spacingLeaves(), lookup, spacingEntry),
|
|
11425
11495
|
...authoredTokens(
|
|
11426
11496
|
fileLeaves("z-index", Z_INDEX_FILE, SINGLE_SOURCE),
|