@starterlib/tokens 0.9.1 → 0.10.1

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.
@@ -0,0 +1,2103 @@
1
+ const DEGRES_EN_RADIANS = Math.PI / 180;
2
+ function versSrgbLineaire({ l, c, h }) {
3
+ const a = c * Math.cos(h * DEGRES_EN_RADIANS);
4
+ const b = c * Math.sin(h * DEGRES_EN_RADIANS);
5
+ const l_ = l + .3963377774 * a + .2158037573 * b;
6
+ const m_ = l - .1055613458 * a - .0638541728 * b;
7
+ const s_ = l - .0894841775 * a - 1.291485548 * b;
8
+ const lc = l_ ** 3;
9
+ const mc = m_ ** 3;
10
+ const sc = s_ ** 3;
11
+ return [
12
+ 4.0767416621 * lc - 3.3077115913 * mc + .2309699292 * sc,
13
+ -1.2684380046 * lc + 2.6097574011 * mc - .3413193965 * sc,
14
+ -.0041960863 * lc - .7034186147 * mc + 1.707614701 * sc
15
+ ];
16
+ }
17
+ function dansLeGamut(lineaire) {
18
+ return lineaire.every((v) => v >= -1e-7 && v <= 1.0000001);
19
+ }
20
+ function encoderGamma(lineaire) {
21
+ const v = Math.min(1, Math.max(0, lineaire));
22
+ return v <= .0031308 ? 12.92 * v : 1.055 * v ** (1 / 2.4) - .055;
23
+ }
24
+ function decoderGamma(canal8bits) {
25
+ const c = canal8bits / 255;
26
+ return c <= .04045 ? c / 12.92 : ((c + .055) / 1.055) ** 2.4;
27
+ }
28
+ function enHex$2(lineaire) {
29
+ return `#${lineaire.map((v) => Math.round(encoderGamma(v) * 255).toString(16).padStart(2, "0")).join("")}`;
30
+ }
31
+ function oklchVersSrgb(couleur) {
32
+ if (!Number.isFinite(couleur.l) || !Number.isFinite(couleur.c) || !Number.isFinite(couleur.h)) throw new Error(`Couleur OKLCH invalide : ${JSON.stringify(couleur)}`);
33
+ const demandee = versSrgbLineaire(couleur);
34
+ if (dansLeGamut(demandee)) return {
35
+ hex: enHex$2(demandee),
36
+ rabattue: false,
37
+ chroma: couleur.c
38
+ };
39
+ let dedans = 0;
40
+ let dehors = couleur.c;
41
+ for (let pas = 0; pas < 40; pas++) {
42
+ const milieu = (dedans + dehors) / 2;
43
+ if (dansLeGamut(versSrgbLineaire({
44
+ ...couleur,
45
+ c: milieu
46
+ }))) dedans = milieu;
47
+ else dehors = milieu;
48
+ }
49
+ return {
50
+ hex: enHex$2(versSrgbLineaire({
51
+ ...couleur,
52
+ c: dedans
53
+ })),
54
+ rabattue: true,
55
+ chroma: dedans
56
+ };
57
+ }
58
+ function oklchVersHex(couleur) {
59
+ return oklchVersSrgb(couleur).hex;
60
+ }
61
+ function hexVersOklch(hex) {
62
+ const v = hex.trim().replace(/^#/, "");
63
+ const complet = v.length === 3 ? v.split("").map((c) => c + c).join("") : v;
64
+ if (!/^[0-9a-fA-F]{6}$/.test(complet)) throw new Error(`Couleur hexadecimale invalide : ${hex}`);
65
+ const [r, g, b] = [
66
+ 0,
67
+ 2,
68
+ 4
69
+ ].map((i) => decoderGamma(parseInt(complet.slice(i, i + 2), 16)));
70
+ const l_ = Math.cbrt(.4122214708 * r + .5363325363 * g + .0514459929 * b);
71
+ const m_ = Math.cbrt(.2119034982 * r + .6806995451 * g + .1073969566 * b);
72
+ const s_ = Math.cbrt(.0883024619 * r + .2817188376 * g + .6299787005 * b);
73
+ const l = .2104542553 * l_ + .793617785 * m_ - .0040720468 * s_;
74
+ const a = 1.9779984951 * l_ - 2.428592205 * m_ + .4505937099 * s_;
75
+ const bb = .0259040371 * l_ + .7827717662 * m_ - .808675766 * s_;
76
+ const c = Math.hypot(a, bb);
77
+ return {
78
+ l,
79
+ c,
80
+ h: c < 1e-4 ? 0 : (Math.atan2(bb, a) / DEGRES_EN_RADIANS + 360) % 360
81
+ };
82
+ }
83
+ function oklchEnCss({ l, c, h }) {
84
+ const arrondir = (v, chiffres) => Number(v.toFixed(chiffres)).toString();
85
+ return `oklch(${arrondir(l, 3)} ${arrondir(c, 3)} ${arrondir(h, 0)})`;
86
+ }
87
+ const PAS_DE_RAMPE = [
88
+ 50,
89
+ 100,
90
+ 200,
91
+ 300,
92
+ 400,
93
+ 500,
94
+ 600,
95
+ 700,
96
+ 800,
97
+ 900,
98
+ 950
99
+ ];
100
+ const PAS_NEUTRES = [
101
+ 0,
102
+ 50,
103
+ 100,
104
+ 150,
105
+ 200,
106
+ 300,
107
+ 400,
108
+ 500,
109
+ 600,
110
+ 700,
111
+ 800,
112
+ 900,
113
+ 950
114
+ ];
115
+ const RANGS_DE_SERIE = [
116
+ 1,
117
+ 2,
118
+ 3,
119
+ 4,
120
+ 5,
121
+ 6
122
+ ];
123
+ const L_PAS = {
124
+ 50: .97,
125
+ 100: .935,
126
+ 200: .88,
127
+ 300: .8,
128
+ 400: .7,
129
+ 500: .6,
130
+ 600: .5,
131
+ 700: .43,
132
+ 800: .36,
133
+ 900: .28,
134
+ 950: .2
135
+ };
136
+ const C_PAS = {
137
+ 50: .07,
138
+ 100: .15,
139
+ 200: .29,
140
+ 300: .5,
141
+ 400: .77,
142
+ 500: .95,
143
+ 600: 1,
144
+ 700: .88,
145
+ 800: .74,
146
+ 900: .58,
147
+ 950: .38
148
+ };
149
+ const FAMILLES = {
150
+ bleu: {
151
+ teinte: 262,
152
+ chromaMax: .18,
153
+ vocation: "marque, focus, selection"
154
+ },
155
+ azur: {
156
+ teinte: 232,
157
+ chromaMax: .095,
158
+ vocation: "information"
159
+ },
160
+ or: {
161
+ teinte: 85,
162
+ chromaMax: .098,
163
+ vocation: "accent (jamais un statut, jamais une action)"
164
+ },
165
+ vert: {
166
+ teinte: 152,
167
+ chromaMax: .125,
168
+ vocation: "succes et variation positive"
169
+ },
170
+ ambre: {
171
+ teinte: 58,
172
+ chromaMax: .115,
173
+ exception: { 600: .52 },
174
+ vocation: "avertissement"
175
+ },
176
+ rouge: {
177
+ teinte: 25,
178
+ chromaMax: .19,
179
+ vocation: "danger, erreur, action destructrice"
180
+ }
181
+ };
182
+ const NEUTRES = {
183
+ 0: {
184
+ l: 1,
185
+ c: 0,
186
+ h: 0
187
+ },
188
+ 50: {
189
+ l: .98,
190
+ c: .003,
191
+ h: 255
192
+ },
193
+ 100: {
194
+ l: .965,
195
+ c: .004,
196
+ h: 255
197
+ },
198
+ 150: {
199
+ l: .94,
200
+ c: .005,
201
+ h: 255
202
+ },
203
+ 200: {
204
+ l: .888,
205
+ c: .007,
206
+ h: 255
207
+ },
208
+ 300: {
209
+ l: .81,
210
+ c: .009,
211
+ h: 255
212
+ },
213
+ 400: {
214
+ l: .71,
215
+ c: .011,
216
+ h: 255
217
+ },
218
+ 500: {
219
+ l: .61,
220
+ c: .013,
221
+ h: 255
222
+ },
223
+ 600: {
224
+ l: .51,
225
+ c: .015,
226
+ h: 255
227
+ },
228
+ 700: {
229
+ l: .45,
230
+ c: .016,
231
+ h: 255
232
+ },
233
+ 800: {
234
+ l: .31,
235
+ c: .017,
236
+ h: 255
237
+ },
238
+ 900: {
239
+ l: .22,
240
+ c: .018,
241
+ h: 255
242
+ },
243
+ 950: {
244
+ l: .155,
245
+ c: .018,
246
+ h: 255
247
+ }
248
+ };
249
+ const SERIE = {
250
+ 1: {
251
+ l: .55,
252
+ c: .15,
253
+ h: 262
254
+ },
255
+ 2: {
256
+ l: .55,
257
+ c: .13,
258
+ h: 85
259
+ },
260
+ 3: {
261
+ l: .55,
262
+ c: .12,
263
+ h: 195
264
+ },
265
+ 4: {
266
+ l: .55,
267
+ c: .15,
268
+ h: 310
269
+ },
270
+ 5: {
271
+ l: .55,
272
+ c: .14,
273
+ h: 152
274
+ },
275
+ 6: {
276
+ l: .55,
277
+ c: .16,
278
+ h: 25
279
+ }
280
+ };
281
+ function definir(oklch) {
282
+ const { hex, rabattue } = oklchVersSrgb(oklch);
283
+ return {
284
+ oklch,
285
+ hex,
286
+ rabattue
287
+ };
288
+ }
289
+ function definitionDuPas(famille, pas) {
290
+ const f = FAMILLES[famille];
291
+ return {
292
+ l: f.exception?.[pas] ?? L_PAS[pas],
293
+ c: Number((f.chromaMax * C_PAS[pas]).toFixed(6)),
294
+ h: f.teinte
295
+ };
296
+ }
297
+ function engendrer(cles, definition) {
298
+ return Object.fromEntries(cles.map((cle) => [cle, definir(definition(cle))]));
299
+ }
300
+ function rampe(famille) {
301
+ return engendrer(PAS_DE_RAMPE, (pas) => definitionDuPas(famille, pas));
302
+ }
303
+ const definitionsDesPrimitives = {
304
+ neutre: engendrer(PAS_NEUTRES, (pas) => NEUTRES[pas]),
305
+ bleu: rampe("bleu"),
306
+ azur: rampe("azur"),
307
+ or: rampe("or"),
308
+ vert: rampe("vert"),
309
+ ambre: rampe("ambre"),
310
+ rouge: rampe("rouge"),
311
+ serie: engendrer(RANGS_DE_SERIE, (rang) => SERIE[rang])
312
+ };
313
+ function enHex$1(rampeDefinie) {
314
+ return Object.fromEntries(Object.entries(rampeDefinie).map(([cle, d]) => [cle, d.hex]));
315
+ }
316
+ const primitives = {
317
+ neutre: enHex$1(definitionsDesPrimitives.neutre),
318
+ bleu: enHex$1(definitionsDesPrimitives.bleu),
319
+ azur: enHex$1(definitionsDesPrimitives.azur),
320
+ or: enHex$1(definitionsDesPrimitives.or),
321
+ vert: enHex$1(definitionsDesPrimitives.vert),
322
+ ambre: enHex$1(definitionsDesPrimitives.ambre),
323
+ rouge: enHex$1(definitionsDesPrimitives.rouge),
324
+ serie: enHex$1(definitionsDesPrimitives.serie)
325
+ };
326
+ const espacement = {
327
+ "0": "0",
328
+ "1": "0.25rem",
329
+ "2": "0.5rem",
330
+ "3": "0.75rem",
331
+ "4": "1rem",
332
+ "5": "1.25rem",
333
+ "6": "1.5rem",
334
+ "8": "2rem",
335
+ "10": "2.5rem",
336
+ "12": "3rem",
337
+ "16": "4rem",
338
+ "20": "5rem",
339
+ "24": "6rem",
340
+ demi: "0.125rem",
341
+ "1-5": "0.375rem",
342
+ "2-5": "0.625rem",
343
+ "3-5": "0.875rem"
344
+ };
345
+ const rayon = {
346
+ none: "0",
347
+ xs: "0.125rem",
348
+ sm: "0.25rem",
349
+ md: "0.5rem",
350
+ lg: "0.75rem",
351
+ xl: "1rem",
352
+ pleine: "9999px"
353
+ };
354
+ const CLES_DE_TAILLE = [
355
+ "2xs",
356
+ "xs",
357
+ "sm",
358
+ "md",
359
+ "lg",
360
+ "xl",
361
+ "2xl",
362
+ "3xl",
363
+ "4xl",
364
+ "5xl",
365
+ "6xl"
366
+ ];
367
+ const typographie = {
368
+ famille: {
369
+ base: "'Inter Variable', 'Inter Repli', system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif",
370
+ mono: "'JetBrains Mono Variable', 'JetBrains Mono Repli', ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace"
371
+ },
372
+ taille: {
373
+ "2xs": "0.6875rem",
374
+ xs: "0.75rem",
375
+ sm: "0.875rem",
376
+ md: "1rem",
377
+ lg: "1.125rem",
378
+ xl: "1.25rem",
379
+ "2xl": "1.5rem",
380
+ "3xl": "2rem",
381
+ "4xl": "2.5rem",
382
+ "5xl": "3rem",
383
+ "6xl": "3.5rem"
384
+ },
385
+ interligne: {
386
+ "2xs": "0.875rem",
387
+ xs: "1rem",
388
+ sm: "1.25rem",
389
+ md: "1.5rem",
390
+ lg: "1.75rem",
391
+ xl: "1.75rem",
392
+ "2xl": "2rem",
393
+ "3xl": "2.5rem",
394
+ "4xl": "3rem",
395
+ "5xl": "3.5rem",
396
+ "6xl": "4rem"
397
+ },
398
+ graisse: {
399
+ normale: "400",
400
+ moyenne: "500",
401
+ semi: "600",
402
+ grasse: "700"
403
+ },
404
+ interlettrage: {
405
+ serre: "-0.01em",
406
+ normal: "normal",
407
+ large: "0.02em",
408
+ capitales: "0.05em",
409
+ etiquette: "0.04em",
410
+ surtitre: "0.1em"
411
+ },
412
+ approche: {
413
+ lg: "-0.005em",
414
+ xl: "-0.01em",
415
+ "2xl": "-0.015em",
416
+ "3xl": "-0.02em",
417
+ "4xl": "-0.025em",
418
+ "6xl": "-0.03em"
419
+ },
420
+ chiffres: {
421
+ alignes: "tabular-nums lining-nums",
422
+ references: "tabular-nums lining-nums slashed-zero"
423
+ }
424
+ };
425
+ const duree = {
426
+ instantane: "0ms",
427
+ rapide: "120ms",
428
+ normale: "200ms",
429
+ lente: "320ms",
430
+ longue: "480ms"
431
+ };
432
+ const deplacement = {
433
+ court: "0.25rem",
434
+ moyen: "0.5rem",
435
+ long: "1rem"
436
+ };
437
+ const cadence = {
438
+ vive: "900ms",
439
+ normale: "1400ms",
440
+ respiration: "1600ms"
441
+ };
442
+ const cadenceMinimale = "600ms";
443
+ const courbe = {
444
+ standard: "cubic-bezier(0.2, 0, 0, 1)",
445
+ entrant: "cubic-bezier(0, 0, 0, 1)",
446
+ sortant: "cubic-bezier(0.3, 0, 1, 1)"
447
+ };
448
+ const plan = {
449
+ base: "0",
450
+ contenuEleve: "10",
451
+ entete: "100",
452
+ superposition: "300",
453
+ notification: "600",
454
+ evitement: "700"
455
+ };
456
+ const cibleTactileMinimale = "44px";
457
+ const cibleMinimale = "24px";
458
+ const epaisseur = {
459
+ fine: "1px",
460
+ intermediaire: "1.5px",
461
+ moyenne: "2px",
462
+ forte: "3px",
463
+ epaisse: "4px"
464
+ };
465
+ const epaisseurCapillaire = {
466
+ base: "1px",
467
+ hauteDensite: "0.5px"
468
+ };
469
+ const largeur = {
470
+ etroite: "45ch",
471
+ normale: "70ch",
472
+ page: "90rem",
473
+ navigation: "16rem",
474
+ rail: "4.5rem",
475
+ "carte-auth": "28.125rem",
476
+ "dialogue-sm": "24rem",
477
+ "dialogue-md": "32rem",
478
+ "dialogue-lg": "48rem",
479
+ tiroir: "28rem",
480
+ menu: "12rem",
481
+ couche: "28rem",
482
+ "champ-sm": "8rem",
483
+ "champ-md": "12rem",
484
+ "champ-lg": "16rem",
485
+ colonne: "18rem"
486
+ };
487
+ const hauteurDeCommande = {
488
+ sm: "2rem",
489
+ md: "2.25rem",
490
+ lg: "2.5rem",
491
+ xl: "2.75rem",
492
+ "2xl": "3.25rem"
493
+ };
494
+ const MODES_DE_DENSITE = [
495
+ "confortable",
496
+ "dense",
497
+ "compacte"
498
+ ];
499
+ const densite = {
500
+ confortable: {
501
+ "hauteur-commande-defaut": "var(--st-hauteur-commande-xl)",
502
+ "densite-cellule-bloc": "var(--st-espacement-3)",
503
+ "densite-cellule-ligne": "var(--st-espacement-3)",
504
+ "densite-texte-taille": "var(--st-taille-md)",
505
+ "densite-texte-interligne": "var(--st-interligne-md)",
506
+ "densite-ligne": "var(--st-hauteur-commande-2xl)",
507
+ "calendrier-jour-defaut": "var(--st-hauteur-commande-xl)"
508
+ },
509
+ dense: {
510
+ "hauteur-commande-defaut": "var(--st-hauteur-commande-md)",
511
+ "densite-cellule-bloc": "var(--st-espacement-2)",
512
+ "densite-cellule-ligne": "var(--st-espacement-3)",
513
+ "densite-texte-taille": "var(--st-taille-sm)",
514
+ "densite-texte-interligne": "var(--st-interligne-sm)",
515
+ "densite-ligne": "var(--st-hauteur-commande-xl)",
516
+ "calendrier-jour-defaut": "var(--st-hauteur-commande-md)"
517
+ },
518
+ compacte: {
519
+ "hauteur-commande-defaut": "var(--st-hauteur-commande-sm)",
520
+ "densite-cellule-bloc": "var(--st-espacement-1)",
521
+ "densite-cellule-ligne": "var(--st-espacement-2)",
522
+ "densite-texte-taille": "var(--st-taille-xs)",
523
+ "densite-texte-interligne": "var(--st-interligne-xs)",
524
+ "densite-ligne": "var(--st-hauteur-commande-md)",
525
+ "calendrier-jour-defaut": "var(--st-hauteur-commande-sm)"
526
+ }
527
+ };
528
+ const focus = {
529
+ epaisseur: "var(--st-epaisseur-moyenne)",
530
+ decalage: "var(--st-epaisseur-moyenne)",
531
+ lisere: "var(--st-epaisseur-moyenne)"
532
+ };
533
+ function lireHex(texte) {
534
+ const v = texte.trim().replace(/^#/, "");
535
+ const complet = v.length === 3 ? v.split("").map((c) => c + c).join("") : v;
536
+ if (!/^[0-9a-fA-F]{6}$/.test(complet)) return null;
537
+ return {
538
+ r: parseInt(complet.slice(0, 2), 16),
539
+ g: parseInt(complet.slice(2, 4), 16),
540
+ b: parseInt(complet.slice(4, 6), 16)
541
+ };
542
+ }
543
+ function lireOpacite(texte) {
544
+ const v = texte.trim();
545
+ return v.endsWith("%") ? Number(v.slice(0, -1)) / 100 : Number(v);
546
+ }
547
+ function lireFonctionRgb(texte) {
548
+ const trouve = /^rgba?\(([^)]*)\)$/i.exec(texte.trim());
549
+ if (trouve === null) return null;
550
+ const [canaux = "", opaciteModerne] = (trouve[1] ?? "").split("/");
551
+ const morceaux = canaux.split(/[\s,]+/).map((m) => m.trim()).filter((m) => m !== "");
552
+ const opacite = opaciteModerne ?? (morceaux.length === 4 ? morceaux.pop() : void 0);
553
+ if (morceaux.length !== 3) return null;
554
+ const canal = (m) => Math.round(m.endsWith("%") ? Number(m.slice(0, -1)) * 255 / 100 : Number(m));
555
+ const [r, g, b] = morceaux.map(canal);
556
+ const a = opacite === void 0 ? 1 : lireOpacite(opacite);
557
+ if (![
558
+ r,
559
+ g,
560
+ b
561
+ ].every((c) => Number.isFinite(c) && c >= 0 && c <= 255) || !Number.isFinite(a) || a < 0 || a > 1) return null;
562
+ return {
563
+ r,
564
+ g,
565
+ b,
566
+ a
567
+ };
568
+ }
569
+ function lireCouleur(texte) {
570
+ const hex = lireHex(texte);
571
+ if (hex !== null) return {
572
+ ...hex,
573
+ a: 1
574
+ };
575
+ const fonction = lireFonctionRgb(texte);
576
+ if (fonction !== null) return fonction;
577
+ throw new Error(`Couleur invalide : ${texte}`);
578
+ }
579
+ function versRvb(couleur) {
580
+ const lue = lireCouleur(couleur);
581
+ if (lue.a < 1) throw new Error(`Couleur translucide (${couleur}) : la composer sur son fond avant d'en mesurer le contraste.`);
582
+ return {
583
+ r: lue.r,
584
+ g: lue.g,
585
+ b: lue.b
586
+ };
587
+ }
588
+ function enHex({ r, g, b }) {
589
+ return `#${[
590
+ r,
591
+ g,
592
+ b
593
+ ].map((c) => c.toString(16).padStart(2, "0")).join("")}`;
594
+ }
595
+ function composer(premierPlan, fond) {
596
+ const dessus = lireCouleur(premierPlan);
597
+ const dessous = versRvb(fond);
598
+ const melange = (c, d) => Math.round(c * dessus.a + d * (1 - dessus.a));
599
+ return enHex({
600
+ r: melange(dessus.r, dessous.r),
601
+ g: melange(dessus.g, dessous.g),
602
+ b: melange(dessus.b, dessous.b)
603
+ });
604
+ }
605
+ function canalLineaire(valeur8bits) {
606
+ const c = valeur8bits / 255;
607
+ return c <= .04045 ? c / 12.92 : Math.pow((c + .055) / 1.055, 2.4);
608
+ }
609
+ function luminanceRelative(couleur) {
610
+ const { r, g, b } = typeof couleur === "string" ? versRvb(couleur) : couleur;
611
+ return .2126 * canalLineaire(r) + .7152 * canalLineaire(g) + .0722 * canalLineaire(b);
612
+ }
613
+ function rapportDeContraste(a, b) {
614
+ const la = luminanceRelative(a);
615
+ const lb = luminanceRelative(b);
616
+ const clair = Math.max(la, lb);
617
+ const sombre = Math.min(la, lb);
618
+ return (clair + .05) / (sombre + .05);
619
+ }
620
+ function seuilExige(niveau, nature) {
621
+ if (nature === "composant") return 3;
622
+ if (niveau === "AAA") return nature === "grand" ? 4.5 : 7;
623
+ return nature === "grand" ? 3 : 4.5;
624
+ }
625
+ function respecteLeContraste(premierPlan, arrierePlan, niveau = "AA", nature = "courant") {
626
+ return rapportDeContraste(premierPlan, arrierePlan) >= seuilExige(niveau, nature);
627
+ }
628
+ const APCA = {
629
+ trc: 2.4,
630
+ rouge: .2126729,
631
+ vert: .7151522,
632
+ bleu: .072175,
633
+ normFond: .56,
634
+ normTexte: .57,
635
+ inverseTexte: .62,
636
+ inverseFond: .65,
637
+ seuilNoir: .022,
638
+ serrageNoir: 1.414,
639
+ echelle: 1.14,
640
+ decalage: .027,
641
+ deltaMin: 5e-4,
642
+ plancher: .1
643
+ };
644
+ function luminanceApca(couleur) {
645
+ const { r, g, b } = versRvb(couleur);
646
+ const y = APCA.rouge * (r / 255) ** APCA.trc + APCA.vert * (g / 255) ** APCA.trc + APCA.bleu * (b / 255) ** APCA.trc;
647
+ return y > APCA.seuilNoir ? y : y + (APCA.seuilNoir - y) ** APCA.serrageNoir;
648
+ }
649
+ function apca(texte, fond) {
650
+ const yTexte = luminanceApca(texte);
651
+ const yFond = luminanceApca(fond);
652
+ if (Math.abs(yFond - yTexte) < APCA.deltaMin) return 0;
653
+ if (yFond > yTexte) {
654
+ const brut = (yFond ** APCA.normFond - yTexte ** APCA.normTexte) * APCA.echelle;
655
+ return brut < APCA.plancher ? 0 : (brut - APCA.decalage) * 100;
656
+ }
657
+ const brut = (yFond ** APCA.inverseFond - yTexte ** APCA.inverseTexte) * APCA.echelle;
658
+ return brut > -APCA.plancher ? 0 : (brut + APCA.decalage) * 100;
659
+ }
660
+ const RENDU = {
661
+ fond: "#f8f9ff",
662
+ texte: "#161c24",
663
+ texteDiscret: "#434652",
664
+ texteAttenue: "#656874",
665
+ primaire: "#003181",
666
+ surfaceConteneurBas: "#eff4ff",
667
+ surfaceConteneur: "#e9eefa",
668
+ surfaceConteneurHaut: "#e3e8f4",
669
+ surfaceConteneurPlusHaut: "#dde3ee",
670
+ positif: "#005a2b",
671
+ primaireAttenue: "#dae2ff",
672
+ surPrimaireAttenue: "#001848"
673
+ };
674
+ const SOMBRE_CALCULE = {
675
+ surfaceConteneurBas: "#0e141c",
676
+ surfaceConteneurHaut: "#323941",
677
+ surfaceSurvolElevee: "#383f49",
678
+ surfaceActive: "#424851"
679
+ };
680
+ const { neutre, bleu, azur, or, vert, ambre, rouge } = primitives;
681
+ const themeClair = {
682
+ fond: RENDU.fond,
683
+ surface: neutre[0],
684
+ surfaceElevee: neutre[0],
685
+ surfaceEnfoncee: RENDU.surfaceConteneur,
686
+ surfaceConteneurBas: RENDU.surfaceConteneurBas,
687
+ surfaceConteneurHaut: RENDU.surfaceConteneurHaut,
688
+ surfaceSurvol: RENDU.surfaceConteneur,
689
+ surfaceSurvolElevee: RENDU.surfaceConteneur,
690
+ surfaceCouranteElevee: RENDU.surfaceConteneur,
691
+ surfaceActive: RENDU.surfaceConteneurPlusHaut,
692
+ surfaceSelection: bleu[50],
693
+ surfaceInverse: RENDU.texte,
694
+ surfaceMarque: bleu[950],
695
+ texte: RENDU.texte,
696
+ texteDiscret: RENDU.texteDiscret,
697
+ texteAttenue: RENDU.texteAttenue,
698
+ texteDesactive: neutre[400],
699
+ texteInverse: neutre[0],
700
+ textePrimaire: RENDU.primaire,
701
+ texteSurMarque: neutre[0],
702
+ texteSurMarqueDiscret: bleu[200],
703
+ bordure: neutre[200],
704
+ bordureForte: neutre[500],
705
+ bordureSelection: bleu[700],
706
+ anneauFocus: bleu[600],
707
+ lisereFocus: neutre[0],
708
+ selection: bleu[200],
709
+ surSelection: neutre[950],
710
+ primaire: RENDU.primaire,
711
+ primaireSurvol: bleu[700],
712
+ primaireActif: bleu[900],
713
+ surPrimaire: neutre[0],
714
+ primaireDiscret: bleu[50],
715
+ surPrimaireDiscret: bleu[900],
716
+ primaireAttenue: RENDU.primaireAttenue,
717
+ surPrimaireAttenue: RENDU.surPrimaireAttenue,
718
+ accent: or[600],
719
+ accentSurvol: or[700],
720
+ surAccent: neutre[0],
721
+ accentDiscret: or[100],
722
+ surAccentDiscret: or[900],
723
+ information: azur[600],
724
+ surInformation: neutre[0],
725
+ informationDiscret: azur[50],
726
+ surInformationDiscret: azur[900],
727
+ succes: vert[600],
728
+ surSucces: neutre[0],
729
+ succesDiscret: vert[50],
730
+ surSuccesDiscret: vert[900],
731
+ avertissement: ambre[600],
732
+ surAvertissement: neutre[0],
733
+ avertissementDiscret: ambre[50],
734
+ surAvertissementDiscret: ambre[900],
735
+ danger: rouge[600],
736
+ dangerSurvol: rouge[700],
737
+ dangerActif: rouge[800],
738
+ surDanger: neutre[0],
739
+ dangerDiscret: rouge[50],
740
+ surDangerDiscret: rouge[900],
741
+ dangerDiscretCourant: rouge[100],
742
+ positif: RENDU.positif,
743
+ negatif: RENDU.texte
744
+ };
745
+ const themeSombre = {
746
+ fond: neutre[950],
747
+ surface: neutre[900],
748
+ surfaceElevee: neutre[800],
749
+ surfaceEnfoncee: neutre[950],
750
+ surfaceConteneurBas: SOMBRE_CALCULE.surfaceConteneurBas,
751
+ surfaceConteneurHaut: SOMBRE_CALCULE.surfaceConteneurHaut,
752
+ surfaceSurvol: neutre[800],
753
+ surfaceSurvolElevee: SOMBRE_CALCULE.surfaceSurvolElevee,
754
+ surfaceCouranteElevee: neutre[700],
755
+ surfaceActive: SOMBRE_CALCULE.surfaceActive,
756
+ surfaceSelection: bleu[900],
757
+ surfaceInverse: neutre[100],
758
+ surfaceMarque: neutre[900],
759
+ texte: neutre[100],
760
+ texteDiscret: neutre[300],
761
+ texteAttenue: neutre[400],
762
+ texteDesactive: neutre[500],
763
+ texteInverse: neutre[950],
764
+ textePrimaire: bleu[300],
765
+ texteSurMarque: neutre[100],
766
+ texteSurMarqueDiscret: neutre[300],
767
+ bordure: neutre[700],
768
+ bordureForte: neutre[500],
769
+ bordureSelection: bleu[300],
770
+ anneauFocus: bleu[200],
771
+ lisereFocus: neutre[900],
772
+ selection: bleu[800],
773
+ surSelection: neutre[0],
774
+ primaire: bleu[300],
775
+ primaireSurvol: bleu[200],
776
+ primaireActif: bleu[100],
777
+ surPrimaire: neutre[950],
778
+ primaireDiscret: bleu[900],
779
+ surPrimaireDiscret: bleu[100],
780
+ primaireAttenue: bleu[800],
781
+ surPrimaireAttenue: bleu[100],
782
+ accent: or[300],
783
+ accentSurvol: or[200],
784
+ surAccent: neutre[950],
785
+ accentDiscret: or[900],
786
+ surAccentDiscret: or[100],
787
+ information: azur[300],
788
+ surInformation: neutre[950],
789
+ informationDiscret: azur[900],
790
+ surInformationDiscret: azur[100],
791
+ succes: vert[300],
792
+ surSucces: neutre[950],
793
+ succesDiscret: vert[900],
794
+ surSuccesDiscret: vert[100],
795
+ avertissement: ambre[300],
796
+ surAvertissement: neutre[950],
797
+ avertissementDiscret: ambre[900],
798
+ surAvertissementDiscret: ambre[100],
799
+ danger: rouge[300],
800
+ dangerSurvol: rouge[200],
801
+ dangerActif: rouge[100],
802
+ surDanger: neutre[950],
803
+ dangerDiscret: rouge[900],
804
+ surDangerDiscret: rouge[100],
805
+ dangerDiscretCourant: rouge[950],
806
+ positif: vert[300],
807
+ negatif: neutre[100]
808
+ };
809
+ const themes = {
810
+ clair: themeClair,
811
+ sombre: themeSombre
812
+ };
813
+ function surChacune(premierPlan, arrierePlans, nature = "courant") {
814
+ return arrierePlans.map((arrierePlan) => ({
815
+ premierPlan,
816
+ arrierePlan,
817
+ nature
818
+ }));
819
+ }
820
+ const SURFACES_DE_LECTURE = [
821
+ "fond",
822
+ "surface",
823
+ "surfaceElevee",
824
+ "surfaceEnfoncee",
825
+ "surfaceConteneurBas",
826
+ "surfaceConteneurHaut",
827
+ "surfaceSurvol",
828
+ "surfaceSelection"
829
+ ];
830
+ const SURFACES_DE_STATUT = [
831
+ "fond",
832
+ "surface",
833
+ "surfaceElevee",
834
+ "surfaceEnfoncee",
835
+ "surfaceSurvol"
836
+ ];
837
+ const pairesDeContraste = [
838
+ ...surChacune("texte", [
839
+ ...SURFACES_DE_LECTURE,
840
+ "surfaceSurvolElevee",
841
+ "surfaceCouranteElevee",
842
+ "surfaceActive"
843
+ ]),
844
+ ...surChacune("texteDiscret", [
845
+ ...SURFACES_DE_LECTURE,
846
+ "surfaceSurvolElevee",
847
+ "surfaceActive"
848
+ ]),
849
+ ...surChacune("texteAttenue", SURFACES_DE_LECTURE),
850
+ ...surChacune("textePrimaire", [
851
+ "fond",
852
+ "surface",
853
+ "surfaceElevee",
854
+ "surfaceConteneurBas",
855
+ "surfaceSelection",
856
+ "primaireDiscret"
857
+ ]),
858
+ {
859
+ premierPlan: "texteInverse",
860
+ arrierePlan: "surfaceInverse",
861
+ nature: "courant"
862
+ },
863
+ {
864
+ premierPlan: "texteInverse",
865
+ arrierePlan: "primaire",
866
+ nature: "courant"
867
+ },
868
+ {
869
+ premierPlan: "texteSurMarque",
870
+ arrierePlan: "surfaceMarque",
871
+ nature: "courant"
872
+ },
873
+ {
874
+ premierPlan: "texteSurMarqueDiscret",
875
+ arrierePlan: "surfaceMarque",
876
+ nature: "courant"
877
+ },
878
+ ...surChacune("bordureForte", [
879
+ "surface",
880
+ "fond",
881
+ "surfaceEnfoncee",
882
+ "surfaceConteneurBas"
883
+ ], "composant"),
884
+ ...surChacune("bordureSelection", ["surfaceSelection", "surface"], "composant"),
885
+ ...surChacune("anneauFocus", [
886
+ "surface",
887
+ "fond",
888
+ "surfaceElevee",
889
+ "lisereFocus",
890
+ "surfaceCouranteElevee",
891
+ "dangerDiscretCourant"
892
+ ], "composant"),
893
+ {
894
+ premierPlan: "surSelection",
895
+ arrierePlan: "selection",
896
+ nature: "courant"
897
+ },
898
+ ...surChacune("surPrimaire", [
899
+ "primaire",
900
+ "primaireSurvol",
901
+ "primaireActif"
902
+ ]),
903
+ {
904
+ premierPlan: "surPrimaireDiscret",
905
+ arrierePlan: "primaireDiscret",
906
+ nature: "courant"
907
+ },
908
+ {
909
+ premierPlan: "surPrimaireAttenue",
910
+ arrierePlan: "primaireAttenue",
911
+ nature: "courant"
912
+ },
913
+ ...surChacune("primaire", [
914
+ "surface",
915
+ "fond",
916
+ "surfaceElevee",
917
+ "primaireDiscret",
918
+ "surfaceSelection"
919
+ ]),
920
+ {
921
+ premierPlan: "primaire",
922
+ arrierePlan: "surfaceCouranteElevee",
923
+ nature: "composant"
924
+ },
925
+ ...surChacune("surAccent", ["accent", "accentSurvol"]),
926
+ {
927
+ premierPlan: "surAccentDiscret",
928
+ arrierePlan: "accentDiscret",
929
+ nature: "courant"
930
+ },
931
+ ...surChacune("accent", [
932
+ "surface",
933
+ "fond",
934
+ "accentDiscret"
935
+ ]),
936
+ {
937
+ premierPlan: "surInformation",
938
+ arrierePlan: "information",
939
+ nature: "courant"
940
+ },
941
+ {
942
+ premierPlan: "surInformationDiscret",
943
+ arrierePlan: "informationDiscret",
944
+ nature: "courant"
945
+ },
946
+ ...surChacune("information", [...SURFACES_DE_STATUT, "informationDiscret"]),
947
+ {
948
+ premierPlan: "surSucces",
949
+ arrierePlan: "succes",
950
+ nature: "courant"
951
+ },
952
+ {
953
+ premierPlan: "surSuccesDiscret",
954
+ arrierePlan: "succesDiscret",
955
+ nature: "courant"
956
+ },
957
+ ...surChacune("succes", [...SURFACES_DE_STATUT, "succesDiscret"]),
958
+ {
959
+ premierPlan: "surAvertissement",
960
+ arrierePlan: "avertissement",
961
+ nature: "courant"
962
+ },
963
+ {
964
+ premierPlan: "surAvertissementDiscret",
965
+ arrierePlan: "avertissementDiscret",
966
+ nature: "courant"
967
+ },
968
+ ...surChacune("avertissement", [...SURFACES_DE_STATUT, "avertissementDiscret"]),
969
+ ...surChacune("surDanger", [
970
+ "danger",
971
+ "dangerSurvol",
972
+ "dangerActif"
973
+ ]),
974
+ {
975
+ premierPlan: "surDangerDiscret",
976
+ arrierePlan: "dangerDiscret",
977
+ nature: "courant"
978
+ },
979
+ ...surChacune("danger", [
980
+ ...SURFACES_DE_STATUT,
981
+ "dangerDiscret",
982
+ "dangerDiscretCourant"
983
+ ]),
984
+ ...surChacune("positif", [
985
+ "surface",
986
+ "fond",
987
+ "surfaceConteneurBas"
988
+ ]),
989
+ ...surChacune("negatif", ["surface", "fond"])
990
+ ];
991
+ const exemptesDeContraste = [{
992
+ jeton: "bordure",
993
+ raison: "Separateur decoratif (bord de carte, filet de tableau). WCAG 1.4.11 ne s'applique qu'aux bordures porteuses d'information ; celle qui identifie un champ est `bordureForte`, elle, controlee a 3:1."
994
+ }, {
995
+ jeton: "texteDesactive",
996
+ raison: "WCAG 1.4.3 exempte explicitement les commandes desactivees. Le statut desactive n'est jamais porte par la seule couleur : l'attribut aria le dit."
997
+ }];
998
+ const pairesExclues = [
999
+ {
1000
+ premierPlan: "texteAttenue",
1001
+ arrierePlan: "surfaceActive",
1002
+ raison: "4,30:1 en clair (#656874 sur #dde3ee, D17), 3,59:1 en sombre. Sur une surface active, une aide se compose en `texteDiscret` (audit Claude Design §3.2 #3)."
1003
+ },
1004
+ {
1005
+ premierPlan: "texteAttenue",
1006
+ arrierePlan: "surfaceSurvolElevee",
1007
+ raison: "4,13:1 en sombre (#9da2a8 sur #383f49). Une entree de menu survolee garde son texte en `texte` ou `texteDiscret`."
1008
+ },
1009
+ {
1010
+ premierPlan: "texteDiscret",
1011
+ arrierePlan: "surfaceCouranteElevee",
1012
+ raison: "4,11:1 en sombre (#bdc1c7 sur #4f565e). L entree courante d un menu passe son texte en `texte` (6,74:1), son suffixe aussi en sombre."
1013
+ }
1014
+ ];
1015
+ const SEUIL_DE_PERCEPTIBILITE = 1.2;
1016
+ const ecartsDeSurface = [
1017
+ {
1018
+ devant: "surfaceEnfoncee",
1019
+ derriere: "surface",
1020
+ minimum: 1.12,
1021
+ pourquoi: "le creux (champ en lecture seule, puits) se voit sur une carte"
1022
+ },
1023
+ {
1024
+ devant: "surfaceSurvol",
1025
+ derriere: "surface",
1026
+ minimum: 1.12,
1027
+ pourquoi: "une ligne survolee se distingue de ses voisines"
1028
+ },
1029
+ {
1030
+ devant: "surfaceSurvolElevee",
1031
+ derriere: "surfaceElevee",
1032
+ minimum: 1.15,
1033
+ pourquoi: "une entree de menu survolee se voit dans les deux themes (D1)"
1034
+ },
1035
+ {
1036
+ devant: "surfaceCouranteElevee",
1037
+ derriere: "surfaceElevee",
1038
+ minimum: 1.15,
1039
+ pourquoi: "l'entree courante d'un menu se voit dans les deux themes (lot 231)"
1040
+ },
1041
+ {
1042
+ devant: "dangerDiscretCourant",
1043
+ derriere: "surfaceElevee",
1044
+ minimum: 1.2,
1045
+ pourquoi: "l'entree danger courante d'un menu se voit dans les deux themes (lot 231)"
1046
+ },
1047
+ {
1048
+ devant: "surfaceActive",
1049
+ derriere: "surfaceSurvol",
1050
+ minimum: 1.1,
1051
+ pourquoi: "l'etat enfonce differe du survol"
1052
+ },
1053
+ {
1054
+ devant: "surfaceConteneurHaut",
1055
+ derriere: "surfaceConteneurBas",
1056
+ minimum: 1.1,
1057
+ pourquoi: "le survol d un lien de navigation se voit sur son panneau"
1058
+ },
1059
+ {
1060
+ devant: "surfaceConteneurBas",
1061
+ derriere: "surface",
1062
+ minimum: 1.05,
1063
+ pourquoi: "un en-tete de tableau ou un pied se detache de la carte qui le porte"
1064
+ }
1065
+ ];
1066
+ const surfacesDuFocus = [
1067
+ "surface",
1068
+ "fond",
1069
+ "surfaceElevee",
1070
+ "surfaceEnfoncee",
1071
+ "surfaceConteneurBas",
1072
+ "surfaceConteneurHaut",
1073
+ "surfaceSelection",
1074
+ "surfaceActive",
1075
+ "surfaceMarque",
1076
+ "surfaceInverse",
1077
+ "primaire",
1078
+ "primaireSurvol",
1079
+ "danger",
1080
+ "accent",
1081
+ "succes",
1082
+ "information",
1083
+ "avertissement"
1084
+ ];
1085
+ const COUCHES = [
1086
+ "repos",
1087
+ "survol",
1088
+ "surelevee",
1089
+ "flottante",
1090
+ "modale"
1091
+ ];
1092
+ function memeCouleur(couleur) {
1093
+ return {
1094
+ clair: couleur,
1095
+ sombre: couleur
1096
+ };
1097
+ }
1098
+ const ombres = {
1099
+ repos: [{
1100
+ geometrie: "0 1px 2px 0",
1101
+ couleur: memeCouleur("rgb(0 0 0 / 0.05)")
1102
+ }],
1103
+ survol: [{
1104
+ geometrie: "0 4px 6px -1px",
1105
+ couleur: memeCouleur("rgb(0 0 0 / 0.1)")
1106
+ }, {
1107
+ geometrie: "0 2px 4px -2px",
1108
+ couleur: memeCouleur("rgb(0 0 0 / 0.1)")
1109
+ }],
1110
+ surelevee: [{
1111
+ geometrie: "0 10px 15px -3px",
1112
+ couleur: memeCouleur("rgb(0 0 0 / 0.1)")
1113
+ }, {
1114
+ geometrie: "0 4px 6px -4px",
1115
+ couleur: memeCouleur("rgb(0 0 0 / 0.1)")
1116
+ }],
1117
+ flottante: [{
1118
+ geometrie: "0 20px 25px -5px",
1119
+ couleur: memeCouleur("rgb(0 0 0 / 0.1)")
1120
+ }, {
1121
+ geometrie: "0 8px 10px -6px",
1122
+ couleur: memeCouleur("rgb(0 0 0 / 0.1)")
1123
+ }],
1124
+ modale: [{
1125
+ geometrie: "0 16px 32px -8px",
1126
+ couleur: {
1127
+ clair: "rgb(7 13 20 / 0.14)",
1128
+ sombre: "rgb(0 0 0 / 0.48)"
1129
+ }
1130
+ }, {
1131
+ geometrie: "0 32px 64px -16px",
1132
+ couleur: {
1133
+ clair: "rgb(7 13 20 / 0.2)",
1134
+ sombre: "rgb(0 0 0 / 0.56)"
1135
+ }
1136
+ }]
1137
+ };
1138
+ const voile = {
1139
+ clair: "rgb(7 13 20 / 0.48)",
1140
+ sombre: "rgb(0 0 0 / 0.64)"
1141
+ };
1142
+ const couleurDOmbre = {
1143
+ clair: "rgb(0 0 0 / 0.2)",
1144
+ sombre: "rgb(0 0 0 / 0.6)"
1145
+ };
1146
+ function ombreDuTheme(couche, theme) {
1147
+ return ombres[couche].map((c) => `${c.geometrie} ${c.couleur[theme]}`).join(", ");
1148
+ }
1149
+ function rolesDesPrimitives() {
1150
+ const roles = /* @__PURE__ */ new Map();
1151
+ for (const nomDeTheme of ["clair", "sombre"]) {
1152
+ const entrees = Object.entries(themes[nomDeTheme]);
1153
+ for (const [jeton, valeur] of entrees) {
1154
+ const liste = roles.get(valeur) ?? [];
1155
+ liste.push(`${jeton} (${nomDeTheme})`);
1156
+ roles.set(valeur, liste);
1157
+ }
1158
+ }
1159
+ return roles;
1160
+ }
1161
+ const stylesTypographiques = {
1162
+ corps: {
1163
+ taille: "md",
1164
+ graisse: "normale",
1165
+ interlettrage: "normal",
1166
+ usage: "texte courant"
1167
+ },
1168
+ "corps-petit": {
1169
+ taille: "sm",
1170
+ graisse: "normale",
1171
+ interlettrage: "normal",
1172
+ usage: "texte secondaire"
1173
+ },
1174
+ "corps-fort": {
1175
+ taille: "md",
1176
+ graisse: "semi",
1177
+ interlettrage: "normal",
1178
+ usage: "intitule de ligne, valeur secondaire (D5)"
1179
+ },
1180
+ "corps-grand": {
1181
+ taille: "lg",
1182
+ graisse: "normale",
1183
+ interlettrage: "normal",
1184
+ usage: "texte d introduction, mention juridique (18/28, DESIGN.md body-lg)"
1185
+ },
1186
+ legende: {
1187
+ taille: "xs",
1188
+ graisse: "moyenne",
1189
+ interlettrage: "large",
1190
+ usage: "legende, etiquette de badge"
1191
+ },
1192
+ libelle: {
1193
+ taille: "sm",
1194
+ graisse: "moyenne",
1195
+ interlettrage: "normal",
1196
+ usage: "libelle de champ, onglet (D18 : 14/500)"
1197
+ },
1198
+ commande: {
1199
+ taille: "sm",
1200
+ graisse: "semi",
1201
+ interlettrage: "normal",
1202
+ usage: "libelle de bouton de 44 px (14/20 600, majorite des planches)"
1203
+ },
1204
+ etiquette: {
1205
+ taille: "xs",
1206
+ graisse: "semi",
1207
+ interlettrage: "etiquette",
1208
+ usage: "en-tete de colonne, etiquette de statut (12/16 600, DESIGN.md label-md)"
1209
+ },
1210
+ "micro-capitales": {
1211
+ taille: "2xs",
1212
+ graisse: "semi",
1213
+ interlettrage: "capitales",
1214
+ capitales: true,
1215
+ usage: "en-tete de colonne, terme de liste, statut en capitales (seul lecteur de 2xs)"
1216
+ },
1217
+ surtitre: {
1218
+ taille: "2xs",
1219
+ graisse: "semi",
1220
+ interlettrage: "surtitre",
1221
+ capitales: true,
1222
+ usage: "surtitre de page ou de section, en capitales espacees"
1223
+ },
1224
+ "titre-4": {
1225
+ taille: "lg",
1226
+ interligne: "md",
1227
+ graisse: "semi",
1228
+ interlettrage: "approche",
1229
+ usage: "intertitre, titre de dialogue et de carte (18/24)"
1230
+ },
1231
+ "titre-3": {
1232
+ taille: "xl",
1233
+ graisse: "semi",
1234
+ interlettrage: "approche",
1235
+ usage: "titre de section"
1236
+ },
1237
+ "titre-2": {
1238
+ taille: "2xl",
1239
+ graisse: "semi",
1240
+ interlettrage: "approche",
1241
+ usage: "titre de bloc majeur"
1242
+ },
1243
+ "titre-1": {
1244
+ taille: "3xl",
1245
+ graisse: "semi",
1246
+ interlettrage: "approche",
1247
+ usage: "titre de page (h1 de 32 px, D18)"
1248
+ },
1249
+ affichage: {
1250
+ taille: "4xl",
1251
+ graisse: "semi",
1252
+ interlettrage: "approche",
1253
+ usage: "annonce, titre d ecran de marque"
1254
+ },
1255
+ "affichage-grand": {
1256
+ taille: "6xl",
1257
+ graisse: "semi",
1258
+ interlettrage: "approche",
1259
+ usage: "grand chiffre de tableau de bord (56/64, DESIGN.md display-lg)"
1260
+ },
1261
+ "chiffre-cle": {
1262
+ taille: "3xl",
1263
+ graisse: "semi",
1264
+ interlettrage: "approche",
1265
+ chiffres: "alignes",
1266
+ usage: "valeur de st-stat"
1267
+ },
1268
+ montant: {
1269
+ taille: "md",
1270
+ graisse: "moyenne",
1271
+ interlettrage: "normal",
1272
+ chiffres: "alignes",
1273
+ usage: "st-money, cellule numerique"
1274
+ },
1275
+ "montant-hero": {
1276
+ taille: "4xl",
1277
+ graisse: "semi",
1278
+ interlettrage: "approche",
1279
+ chiffres: "alignes",
1280
+ usage: "solde de compte (40/48, planche 2)"
1281
+ },
1282
+ reference: {
1283
+ taille: "sm",
1284
+ graisse: "normale",
1285
+ interlettrage: "large",
1286
+ chiffres: "references",
1287
+ famille: "mono",
1288
+ usage: "IBAN, identifiant, reference de virement"
1289
+ },
1290
+ code: {
1291
+ taille: "sm",
1292
+ graisse: "normale",
1293
+ interlettrage: "normal",
1294
+ chiffres: "references",
1295
+ famille: "mono",
1296
+ usage: "st-code"
1297
+ }
1298
+ };
1299
+ function interlettrageEnCss(style) {
1300
+ if (style.interlettrage !== "approche") return `var(--st-interlettrage-${style.interlettrage})`;
1301
+ if (!(style.taille in typographie.approche)) throw new Error(`Aucune approche de titre pour la taille ${style.taille}.`);
1302
+ return `var(--st-approche-${style.taille})`;
1303
+ }
1304
+ function interlettrageDuStyle(nom) {
1305
+ const style = stylesTypographiques[nom];
1306
+ if (style.interlettrage !== "approche") return typographie.interlettrage[style.interlettrage];
1307
+ return typographie.approche[style.taille] ?? "normal";
1308
+ }
1309
+ function declarationsDuStyle(nom) {
1310
+ const style = stylesTypographiques[nom];
1311
+ return [
1312
+ ...style.famille === "mono" ? ["font-family: var(--st-police-mono);"] : [],
1313
+ `font-size: var(--st-taille-${style.taille});`,
1314
+ `line-height: var(--st-interligne-${style.interligne ?? style.taille});`,
1315
+ `font-weight: var(--st-graisse-${style.graisse});`,
1316
+ `letter-spacing: ${interlettrageEnCss(style)};`,
1317
+ ...style.chiffres === void 0 ? [] : [`font-variant-numeric: var(--st-chiffres-${style.chiffres});`],
1318
+ ...style.capitales === true ? ["text-transform: uppercase;"] : []
1319
+ ];
1320
+ }
1321
+ function partielDeTypographie() {
1322
+ const noms = Object.keys(stylesTypographiques);
1323
+ const branches = noms.map((nom, i) => {
1324
+ return ` ${i === 0 ? "@if" : "} @else if"} $nom == '${nom}' {\n${declarationsDuStyle(nom).map((d) => ` ${d}`).join("\n")}\n`;
1325
+ });
1326
+ return `// Engendre par @starterlib/tokens \u2014 ne pas modifier a la main.
1327
+ // Regenerer : pnpm tokens:css
1328
+ //
1329
+ // Styles typographiques composites : taille, interligne, graisse, interlettrage et
1330
+ // chiffres, jamais de couleur. Une seule notation : \`@include style('titre-2')\`.
1331
+ // Les valeurs sont LUES dans la feuille de jetons (var(--st-*)) : l'impression, qui
1332
+ // passe les tailles en points, et la densite s'appliquent aux styles aussi.
1333
+
1334
+ $styles: (${noms.map((n) => `'${n}'`).join(", ")});
1335
+
1336
+ @mixin style($nom) {
1337
+ ${branches.join("")} } @else {
1338
+ @error "Style typographique inconnu : #{$nom}. Admis : #{$styles}.";
1339
+ }
1340
+ }
1341
+ `;
1342
+ }
1343
+ const LATIN = "U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD";
1344
+ const LATIN_ETENDU = "U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF";
1345
+ const policesDuSocle = [{
1346
+ famille: "Inter Variable",
1347
+ graisses: "100 900",
1348
+ paquet: "@fontsource-variable/inter",
1349
+ fichiers: [{
1350
+ fichier: "inter-latin-ext-wght-normal.woff2",
1351
+ unicodeRange: LATIN_ETENDU,
1352
+ aPrecharger: false
1353
+ }, {
1354
+ fichier: "inter-latin-wght-normal.woff2",
1355
+ unicodeRange: LATIN,
1356
+ aPrecharger: true
1357
+ }],
1358
+ metriques: {
1359
+ unitesParEm: 2048,
1360
+ ascendante: 1984,
1361
+ descendante: 494,
1362
+ interligneAjoute: 0,
1363
+ chasseMoyenne: 969.74
1364
+ },
1365
+ repli: {
1366
+ famille: "Inter Repli",
1367
+ locales: [
1368
+ "Arial",
1369
+ "ArialMT",
1370
+ "Liberation Sans",
1371
+ "Arimo"
1372
+ ],
1373
+ metriques: {
1374
+ unitesParEm: 2048,
1375
+ ascendante: 1854,
1376
+ descendante: 434,
1377
+ interligneAjoute: 67,
1378
+ chasseMoyenne: 904
1379
+ }
1380
+ }
1381
+ }, {
1382
+ famille: "JetBrains Mono Variable",
1383
+ graisses: "100 800",
1384
+ paquet: "@fontsource-variable/jetbrains-mono",
1385
+ fichiers: [{
1386
+ fichier: "jetbrains-mono-latin-ext-wght-normal.woff2",
1387
+ unicodeRange: LATIN_ETENDU,
1388
+ aPrecharger: false
1389
+ }, {
1390
+ fichier: "jetbrains-mono-latin-wght-normal.woff2",
1391
+ unicodeRange: LATIN,
1392
+ aPrecharger: false
1393
+ }],
1394
+ metriques: {
1395
+ unitesParEm: 1e3,
1396
+ ascendante: 1020,
1397
+ descendante: 300,
1398
+ interligneAjoute: 0,
1399
+ chasseMoyenne: 600
1400
+ },
1401
+ repli: {
1402
+ famille: "JetBrains Mono Repli",
1403
+ locales: [
1404
+ "Courier New",
1405
+ "CourierNewPSMT",
1406
+ "Liberation Mono",
1407
+ "Cousine"
1408
+ ],
1409
+ metriques: {
1410
+ unitesParEm: 2048,
1411
+ ascendante: 1705,
1412
+ descendante: 615,
1413
+ interligneAjoute: 0,
1414
+ chasseMoyenne: 1229
1415
+ }
1416
+ }
1417
+ }];
1418
+ function pourcent(valeur) {
1419
+ return `${(Math.round(valeur * 1e4) / 100).toFixed(2)}%`;
1420
+ }
1421
+ function surchargesDuRepli(police) {
1422
+ const p = police.metriques;
1423
+ const r = police.repli.metriques;
1424
+ const agrandissement = p.chasseMoyenne / p.unitesParEm / (r.chasseMoyenne / r.unitesParEm);
1425
+ return {
1426
+ sizeAdjust: pourcent(agrandissement),
1427
+ ascentOverride: pourcent(p.ascendante / p.unitesParEm / agrandissement),
1428
+ descentOverride: pourcent(p.descendante / p.unitesParEm / agrandissement),
1429
+ lineGapOverride: pourcent(p.interligneAjoute / p.unitesParEm / agrandissement)
1430
+ };
1431
+ }
1432
+ function fichiersAPrecharger() {
1433
+ return policesDuSocle.flatMap((p) => p.fichiers.filter((f) => f.aPrecharger).map((f) => f.fichier));
1434
+ }
1435
+ function feuilleDesPolices() {
1436
+ const blocs = policesDuSocle.flatMap((police) => {
1437
+ const faces = police.fichiers.map((f) => `@font-face {
1438
+ font-family: '${police.famille}';
1439
+ font-style: normal;
1440
+ font-weight: ${police.graisses};
1441
+ font-display: optional;
1442
+ src: url('./polices/${f.fichier}') format('woff2');
1443
+ unicode-range: ${f.unicodeRange};
1444
+ }`);
1445
+ const s = surchargesDuRepli(police);
1446
+ const repli = `@font-face {
1447
+ font-family: '${police.repli.famille}';
1448
+ src: ${police.repli.locales.map((l) => `local('${l}')`).join(", ")};
1449
+ size-adjust: ${s.sizeAdjust};
1450
+ ascent-override: ${s.ascentOverride};
1451
+ descent-override: ${s.descentOverride};
1452
+ line-gap-override: ${s.lineGapOverride};
1453
+ }`;
1454
+ return [...faces, repli];
1455
+ });
1456
+ return `/* Engendre par @starterlib/tokens \u2014 ne pas modifier a la main.
1457
+ Regenerer : pnpm tokens:css
1458
+
1459
+ Polices du socle, auto-hebergees (SIL OFL 1.1, voir polices/LICENSE-*.txt).
1460
+ Recette : docs/recettes/police.md. A precharger par l'hote :
1461
+ ${fichiersAPrecharger().map((f) => ` <link rel="preload" href="\u2026/polices/${f}" as="font" type="font/woff2" crossorigin>`).join("\n")}
1462
+ Repli METRISE : memes hauteur de ligne et chasse moyenne que la police, calculees
1463
+ sur le fichier livre (tools/verifier-police.mjs). */
1464
+
1465
+ ${blocs.join("\n\n")}
1466
+ `;
1467
+ }
1468
+ const jetonsDeComposant = [
1469
+ {
1470
+ nom: "--st-commande-hauteur",
1471
+ repli: "var(--st-hauteur-commande-defaut)",
1472
+ role: "Hauteur MINIMALE commune des boutons, champs et listes deroulantes. Une seule valeur pour tous : une ligne ou le champ fait 44 px et le bouton 40 se voit tout de suite. Le repli suit la densite (44 / 36 / 32, 44 au doigt). Un reglage plus court ne descend jamais sous le plancher des commandes (D4) : 32 px au pointeur fin, 44 au doigt.",
1473
+ lecteurs: [
1474
+ "st-button",
1475
+ "st-icon-button",
1476
+ "_champ-natif"
1477
+ ]
1478
+ },
1479
+ {
1480
+ nom: "--st-commande-rayon",
1481
+ repli: "var(--st-rayon-md)",
1482
+ role: "Rayon des commandes. C'est le reglage d'identite le plus demande.",
1483
+ lecteurs: [
1484
+ "st-button",
1485
+ "st-icon-button",
1486
+ "_champ-natif"
1487
+ ]
1488
+ },
1489
+ {
1490
+ nom: "--st-surface-rayon",
1491
+ repli: "var(--st-rayon-md)",
1492
+ role: "Rayon des surfaces flottantes qui portent du contenu : menu, popover, dialogue, message.",
1493
+ lecteurs: [
1494
+ "st-menu",
1495
+ "st-popover",
1496
+ "st-dialog-container",
1497
+ "st-toast-message"
1498
+ ]
1499
+ },
1500
+ {
1501
+ nom: "--st-carte-rayon",
1502
+ repli: "var(--st-rayon-lg)",
1503
+ role: "Rayon de la carte, la surface la plus chartee : 12 px, distinct des surfaces flottantes.",
1504
+ lecteurs: ["st-card"]
1505
+ },
1506
+ {
1507
+ nom: "--st-tableau-cellule-bloc",
1508
+ repli: "var(--st-espacement-0)",
1509
+ role: "Respiration verticale d'une cellule ; aucune par defaut : la hauteur de ligne du mode fait le rythme (D29).",
1510
+ lecteurs: ["st-data-table"]
1511
+ },
1512
+ {
1513
+ nom: "--st-tableau-cellule-ligne",
1514
+ repli: "calc(var(--st-densite-cellule-ligne) + var(--st-espacement-1))",
1515
+ role: "Respiration horizontale d'une cellule ; le repli suit la densite (16 / 16 / 12 px).",
1516
+ lecteurs: ["st-data-table"]
1517
+ },
1518
+ {
1519
+ nom: "--st-tableau-largeur-case",
1520
+ repli: "var(--st-espacement-12)",
1521
+ role: "Largeur de la colonne des cases a cocher ; la colonne figee suivante se decale d autant.",
1522
+ lecteurs: ["st-data-table"]
1523
+ },
1524
+ {
1525
+ nom: "--st-calendrier-jour-taille",
1526
+ repli: "var(--st-calendrier-jour-defaut)",
1527
+ role: "Cote d une case de jour. Un calendrier dense reste au-dessus de la cible minimale.",
1528
+ lecteurs: ["st-calendar"]
1529
+ },
1530
+ {
1531
+ nom: "--st-anim-chargement",
1532
+ repli: "var(--st-cadence-vive) ou var(--st-cadence-normale)",
1533
+ role: "Rythme d'un indicateur d'activite. ⚠️ Hors de l'echelle des durees, qui passe a zero sous mouvement reduit : un indicateur fige ferait croire a un ecran bloque. Borne par --st-cadence-min : on ralentit une boucle, on ne l eteint pas.",
1534
+ lecteurs: [
1535
+ "st-spinner",
1536
+ "st-progress",
1537
+ "st-skeleton"
1538
+ ]
1539
+ },
1540
+ {
1541
+ nom: "--st-anim-respiration",
1542
+ repli: "var(--st-cadence-respiration)",
1543
+ role: "Rythme de la respiration qui remplace le mouvement sous mouvement reduit. Borne par --st-cadence-min.",
1544
+ lecteurs: [
1545
+ "st-spinner",
1546
+ "st-progress",
1547
+ "st-skeleton"
1548
+ ]
1549
+ },
1550
+ {
1551
+ nom: "--st-coquille-largeur-navigation",
1552
+ repli: "var(--st-largeur-navigation)",
1553
+ role: "Largeur de la navigation laterale de la coquille : un reglage de coquille legitime.",
1554
+ lecteurs: ["st-app-shell"]
1555
+ },
1556
+ {
1557
+ nom: "--st-separateur-marge",
1558
+ repli: "var(--st-espacement-4)",
1559
+ role: "Marge d'un separateur : le reglage de rythme vertical le plus pose par une SPA.",
1560
+ lecteurs: ["st-divider"]
1561
+ },
1562
+ {
1563
+ nom: "--st-champ-largeur-libelle",
1564
+ repli: "var(--st-largeur-champ-md)",
1565
+ role: "Largeur de la colonne des libelles d un formulaire en ligne (libelle a gauche du champ).",
1566
+ lecteurs: ["st-form-field"]
1567
+ },
1568
+ {
1569
+ nom: "--st-liste-hauteur-max",
1570
+ repli: "18rem",
1571
+ role: "Hauteur maximale d une liste deroulante avant defilement (combobox, choix multiple).",
1572
+ lecteurs: ["_liste"]
1573
+ }
1574
+ ];
1575
+ const contratsDHote = [
1576
+ "--st-hauteur-entete",
1577
+ "--st-form-actions-hauteur",
1578
+ "--st-choix-interligne",
1579
+ "--st-choix-graisse",
1580
+ "--st-choix-couleur",
1581
+ "--st-menu-curseur",
1582
+ "--st-switch-rail",
1583
+ "--st-switch-curseur"
1584
+ ];
1585
+ const variablesInternes = [
1586
+ "--st-icone-taille",
1587
+ "--st-avatar-taille",
1588
+ "--st-spinner-taille",
1589
+ "--st-logo-hauteur",
1590
+ "--st-progress-part",
1591
+ "--st-text-lignes",
1592
+ "--st-arbre-niveau",
1593
+ "--st-tableau-plan-figee",
1594
+ "--st-tableau-plan-entete",
1595
+ "--st-tableau-plan-coin",
1596
+ "--st-skeleton-derniere"
1597
+ ];
1598
+ function estJetonDeComposant(nom) {
1599
+ return jetonsDeComposant.some((jeton) => jeton.nom === nom);
1600
+ }
1601
+ const PREFIXE = "--st";
1602
+ function enKebab(valeur) {
1603
+ return valeur.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
1604
+ }
1605
+ function aplatir(prefixe, valeurs) {
1606
+ return Object.entries(valeurs).map(([cle, valeur]) => ` ${prefixe}-${enKebab(cle)}: ${valeur};`);
1607
+ }
1608
+ function selonLeTheme(clair, sombre) {
1609
+ return clair === sombre ? clair : `light-dark(${clair}, ${sombre})`;
1610
+ }
1611
+ function nomDeCouleur(jeton) {
1612
+ return `${PREFIXE}-couleur-${enKebab(jeton)}`;
1613
+ }
1614
+ function couleursEnCss() {
1615
+ return Object.keys(themeClair).map((jeton) => ` ${nomDeCouleur(jeton)}: ${selonLeTheme(themeClair[jeton], themeSombre[jeton])};`);
1616
+ }
1617
+ function ombresEnCss() {
1618
+ return [
1619
+ ` ${PREFIXE}-ombre-none: none;`,
1620
+ ...COUCHES.map((couche) => {
1621
+ const valeur = ombres[couche].map((c) => `${c.geometrie} ${selonLeTheme(c.couleur.clair, c.couleur.sombre)}`).join(", ");
1622
+ return ` ${PREFIXE}-ombre-${couche}: ${valeur};`;
1623
+ }),
1624
+ ` ${PREFIXE}-voile: ${selonLeTheme(voile.clair, voile.sombre)};`,
1625
+ ` ${PREFIXE}-couleur-ombre: ${selonLeTheme(couleurDOmbre.clair, couleurDOmbre.sombre)};`
1626
+ ];
1627
+ }
1628
+ function cssDesEchelles() {
1629
+ return [
1630
+ ...aplatir(`${PREFIXE}-espacement`, espacement),
1631
+ ...aplatir(`${PREFIXE}-rayon`, rayon),
1632
+ ...aplatir(`${PREFIXE}-duree`, duree),
1633
+ ...aplatir(`${PREFIXE}-courbe`, courbe),
1634
+ ...aplatir(`${PREFIXE}-deplacement`, deplacement),
1635
+ ...aplatir(`${PREFIXE}-cadence`, cadence),
1636
+ ` ${PREFIXE}-cadence-min: ${cadenceMinimale};`,
1637
+ ...aplatir(`${PREFIXE}-plan`, plan),
1638
+ ...aplatir(`${PREFIXE}-police`, typographie.famille),
1639
+ ...aplatir(`${PREFIXE}-taille`, typographie.taille),
1640
+ ...aplatir(`${PREFIXE}-interligne`, typographie.interligne),
1641
+ ...aplatir(`${PREFIXE}-graisse`, typographie.graisse),
1642
+ ...aplatir(`${PREFIXE}-interlettrage`, typographie.interlettrage),
1643
+ ...aplatir(`${PREFIXE}-approche`, typographie.approche),
1644
+ ...aplatir(`${PREFIXE}-chiffres`, typographie.chiffres),
1645
+ ...aplatir(`${PREFIXE}-epaisseur`, epaisseur),
1646
+ ` ${PREFIXE}-epaisseur-capillaire: ${epaisseurCapillaire.base};`,
1647
+ ...aplatir(`${PREFIXE}-largeur`, largeur),
1648
+ ...aplatir(`${PREFIXE}-hauteur-commande`, hauteurDeCommande),
1649
+ ...aplatir(`${PREFIXE}-focus`, focus),
1650
+ ` ${PREFIXE}-cible-tactile-min: ${cibleTactileMinimale};`,
1651
+ ` ${PREFIXE}-cible-min: ${cibleMinimale};`
1652
+ ].join("\n");
1653
+ }
1654
+ function cssDuTheme() {
1655
+ return [...couleursEnCss(), ...ombresEnCss()].join("\n");
1656
+ }
1657
+ function variablesDeDensite(mode, retrait = " ") {
1658
+ return Object.entries(densite[mode]).map(([nom, valeur]) => `${retrait}${PREFIXE}-${nom}: ${valeur};`).join("\n");
1659
+ }
1660
+ function catalogueDesComposants() {
1661
+ return `/* Reglages de composant, a poser par l'application la ou elle veut :
1662
+ ${jetonsDeComposant.map((jeton) => ` ${jeton.nom} (defaut : ${jeton.repli})`).join("\n")}
1663
+ Voir le README de @starterlib/tokens. */`;
1664
+ }
1665
+ function dureesAEteindre() {
1666
+ return Object.fromEntries(Object.entries(duree).filter(([, valeur]) => Number.parseFloat(valeur) !== 0).map(([cle]) => [`${PREFIXE}-duree-${enKebab(cle)}`, "0ms"]));
1667
+ }
1668
+ const mouvementReduit = {
1669
+ ...dureesAEteindre(),
1670
+ ...Object.fromEntries(Object.keys(deplacement).map((cle) => [`${PREFIXE}-deplacement-${enKebab(cle)}`, "0rem"]))
1671
+ };
1672
+ const mouvementGele = dureesAEteindre();
1673
+ const aliasDeContrasteRenforceParJeton = {
1674
+ bordure: "bordureForte",
1675
+ bordureForte: "texteDiscret",
1676
+ texteDiscret: "texte",
1677
+ texteAttenue: "texteDiscret",
1678
+ texteDesactive: "texteAttenue",
1679
+ surfaceSurvol: "surfaceActive",
1680
+ surfaceSurvolElevee: "surfaceActive",
1681
+ surfaceCouranteElevee: "bordure",
1682
+ surfaceConteneurHaut: "surfaceActive"
1683
+ };
1684
+ const encresDeContrasteRenforce = {
1685
+ succes: {
1686
+ clair: primitives.vert[700],
1687
+ sombre: themeSombre.succes
1688
+ },
1689
+ avertissement: {
1690
+ clair: primitives.ambre[700],
1691
+ sombre: themeSombre.avertissement
1692
+ }
1693
+ };
1694
+ function themeSousContrasteRenforce(theme) {
1695
+ const base = theme === "clair" ? themeClair : themeSombre;
1696
+ const rendu = { ...base };
1697
+ for (const [jeton, cible] of Object.entries(aliasDeContrasteRenforceParJeton)) rendu[jeton] = base[cible];
1698
+ for (const [jeton, encres] of Object.entries(encresDeContrasteRenforce)) rendu[jeton] = encres[theme];
1699
+ return rendu;
1700
+ }
1701
+ const aliasDeContrasteRenforce = {
1702
+ ...Object.fromEntries(Object.entries(aliasDeContrasteRenforceParJeton).map(([jeton, cible]) => [nomDeCouleur(jeton), selonLeTheme(themeClair[cible], themeSombre[cible])])),
1703
+ ...Object.fromEntries(Object.entries(encresDeContrasteRenforce).map(([jeton, encres]) => [nomDeCouleur(jeton), selonLeTheme(encres.clair, encres.sombre)])),
1704
+ [`${PREFIXE}-focus-epaisseur`]: `var(${PREFIXE}-epaisseur-forte)`
1705
+ };
1706
+ const couleursSysteme = {
1707
+ Canvas: [
1708
+ "fond",
1709
+ "surface",
1710
+ "surfaceElevee",
1711
+ "surfaceEnfoncee",
1712
+ "surfaceConteneurBas",
1713
+ "surfaceConteneurHaut",
1714
+ "surfaceSurvol",
1715
+ "surfaceSurvolElevee",
1716
+ "surfaceCouranteElevee",
1717
+ "surfaceActive",
1718
+ "surfaceSelection",
1719
+ "surfaceInverse",
1720
+ "surfaceMarque",
1721
+ "lisereFocus",
1722
+ "primaireDiscret",
1723
+ "primaireAttenue",
1724
+ "accentDiscret",
1725
+ "informationDiscret",
1726
+ "succesDiscret",
1727
+ "avertissementDiscret",
1728
+ "dangerDiscret",
1729
+ "dangerDiscretCourant"
1730
+ ],
1731
+ CanvasText: [
1732
+ "texte",
1733
+ "texteDiscret",
1734
+ "texteAttenue",
1735
+ "texteInverse",
1736
+ "texteSurMarque",
1737
+ "texteSurMarqueDiscret",
1738
+ "negatif",
1739
+ "bordure",
1740
+ "bordureForte",
1741
+ "accent",
1742
+ "accentSurvol",
1743
+ "information",
1744
+ "succes",
1745
+ "avertissement",
1746
+ "danger",
1747
+ "dangerSurvol",
1748
+ "dangerActif",
1749
+ "positif",
1750
+ "surPrimaireDiscret",
1751
+ "surPrimaireAttenue",
1752
+ "surAccentDiscret",
1753
+ "surInformationDiscret",
1754
+ "surSuccesDiscret",
1755
+ "surAvertissementDiscret",
1756
+ "surDangerDiscret"
1757
+ ],
1758
+ GrayText: ["texteDesactive"],
1759
+ LinkText: [
1760
+ "primaire",
1761
+ "primaireSurvol",
1762
+ "primaireActif",
1763
+ "textePrimaire"
1764
+ ],
1765
+ Highlight: [
1766
+ "selection",
1767
+ "bordureSelection",
1768
+ "anneauFocus"
1769
+ ],
1770
+ HighlightText: ["surSelection"]
1771
+ };
1772
+ const encresDAplat = [
1773
+ "surPrimaire",
1774
+ "surAccent",
1775
+ "surInformation",
1776
+ "surSucces",
1777
+ "surAvertissement",
1778
+ "surDanger"
1779
+ ];
1780
+ const derogationsDImpression = {
1781
+ fond: "#ffffff",
1782
+ surfaceSurvol: "#ffffff",
1783
+ surfaceActive: "#ffffff",
1784
+ surfaceSelection: "#ffffff",
1785
+ surfaceConteneurBas: "#ffffff",
1786
+ surfaceConteneurHaut: "#ffffff",
1787
+ texte: "#070d14",
1788
+ bordure: "#9da2a8",
1789
+ bordureForte: "#60676f",
1790
+ succes: "#07602f",
1791
+ avertissement: "#783f03",
1792
+ danger: "#960c19",
1793
+ information: "#0b5776",
1794
+ primaireDiscret: "#ffffff",
1795
+ primaireAttenue: "#ffffff",
1796
+ accentDiscret: "#ffffff",
1797
+ informationDiscret: "#ffffff",
1798
+ succesDiscret: "#ffffff",
1799
+ avertissementDiscret: "#ffffff",
1800
+ dangerDiscret: "#ffffff"
1801
+ };
1802
+ const taillesDImpression = {
1803
+ "2xs": "8pt",
1804
+ xs: "8pt",
1805
+ sm: "9pt",
1806
+ md: "10.5pt",
1807
+ lg: "12pt",
1808
+ xl: "13pt",
1809
+ "2xl": "15pt",
1810
+ "3xl": "18pt",
1811
+ "4xl": "22pt",
1812
+ "5xl": "28pt",
1813
+ "6xl": "32pt"
1814
+ };
1815
+ function declarations(valeurs, retrait) {
1816
+ return Object.entries(valeurs).map(([nom, valeur]) => `${retrait}${nom}: ${valeur};`).join("\n");
1817
+ }
1818
+ function blocContrasteForce() {
1819
+ const alias = {};
1820
+ for (const [systeme, jetons] of Object.entries(couleursSysteme)) for (const jeton of jetons) alias[nomDeCouleur(jeton)] = systeme;
1821
+ for (const couche of ["none", ...COUCHES]) alias[`${PREFIXE}-ombre-${couche}`] = "none";
1822
+ alias[`${PREFIXE}-epaisseur-capillaire`] = epaisseurCapillaire.base;
1823
+ return declarations(alias, " ");
1824
+ }
1825
+ function blocImpression() {
1826
+ const valeurs = {};
1827
+ for (const [jeton, valeur] of Object.entries(derogationsDImpression)) valeurs[nomDeCouleur(jeton)] = valeur;
1828
+ for (const couche of COUCHES) valeurs[`${PREFIXE}-ombre-${couche}`] = "none";
1829
+ valeurs[`${PREFIXE}-voile`] = "transparent";
1830
+ valeurs[`${PREFIXE}-epaisseur-capillaire`] = epaisseurCapillaire.base;
1831
+ for (const [cle, taille] of Object.entries(taillesDImpression)) valeurs[`${PREFIXE}-taille-${cle}`] = taille;
1832
+ return declarations(valeurs, " ");
1833
+ }
1834
+ function affichageSelonLeTheme(theme, retrait = " ") {
1835
+ const visible = "inline";
1836
+ return [`${retrait}${PREFIXE}-affichage-si-clair: ${theme === "clair" ? visible : "none"};`, `${retrait}${PREFIXE}-affichage-si-sombre: ${theme === "sombre" ? visible : "none"};`].join("\n");
1837
+ }
1838
+ function feuilleDeJetons() {
1839
+ return `/* Engendre par @starterlib/tokens \u2014 ne pas modifier a la main.
1840
+ Regenerer : pnpm tokens:css */
1841
+
1842
+ ${catalogueDesComposants()}
1843
+
1844
+ :root {
1845
+ color-scheme: light;
1846
+ ${affichageSelonLeTheme("clair")}
1847
+ ${cssDesEchelles()}
1848
+ ${cssDuTheme()}
1849
+ ${variablesDeDensite("confortable")}
1850
+ }
1851
+
1852
+ /* Theme : la preference du systeme, puis l'attribut, qui l'emporte dans les deux
1853
+ sens. Sur la racine comme sur un conteneur : un ilot [data-theme] rend ses
1854
+ descendants dans son theme. */
1855
+ @media (prefers-color-scheme: dark) {
1856
+ :root {
1857
+ color-scheme: dark;
1858
+ ${affichageSelonLeTheme("sombre", " ")}
1859
+ }
1860
+ }
1861
+
1862
+ [data-theme='sombre'] {
1863
+ color-scheme: dark;
1864
+ ${affichageSelonLeTheme("sombre")}
1865
+ }
1866
+
1867
+ [data-theme='clair'] {
1868
+ color-scheme: light;
1869
+ ${affichageSelonLeTheme("clair")}
1870
+ }
1871
+
1872
+ /* Un ilot re-pose la couleur du texte : \`color\` s'herite RESOLUE, et le texte d'un
1873
+ ilot sombre heriterait sinon l'encre claire de la page. */
1874
+ :where([data-theme]):not(:root) {
1875
+ color: var(${PREFIXE}-couleur-texte);
1876
+ }
1877
+
1878
+ ::selection {
1879
+ color: var(${nomDeCouleur("surSelection")});
1880
+ background: var(${nomDeCouleur("selection")});
1881
+ }
1882
+
1883
+ /* Densite : un MODE, sur la racine ou sur une zone. Aucune densite ne descend
1884
+ sous la cible tactile sur un ecran tactile. */
1885
+ [data-densite='confortable'] {
1886
+ ${variablesDeDensite("confortable")}
1887
+ }
1888
+
1889
+ [data-densite='dense'] {
1890
+ ${variablesDeDensite("dense")}
1891
+ }
1892
+
1893
+ [data-densite='compacte'] {
1894
+ ${variablesDeDensite("compacte")}
1895
+ }
1896
+
1897
+ @media (pointer: coarse) {
1898
+ :root,
1899
+ [data-densite] {
1900
+ ${PREFIXE}-hauteur-commande-defaut: var(${PREFIXE}-hauteur-commande-xl);
1901
+ ${PREFIXE}-calendrier-jour-defaut: var(${PREFIXE}-cible-tactile-min);
1902
+ }
1903
+ }
1904
+
1905
+ /* Un filet d'un vrai pixel d'ecran sur les dalles haute densite. */
1906
+ @media (min-resolution: 2dppx) {
1907
+ :root {
1908
+ ${PREFIXE}-epaisseur-capillaire: ${epaisseurCapillaire.hauteDensite};
1909
+ }
1910
+ }
1911
+
1912
+ /* Mouvement reduit (01 \u00a76, 03 P5) : la preference du systeme, sauf quand la
1913
+ personne a choisi le mouvement complet (data-mouvement sur <html>, pose par
1914
+ StMouvement) ; puis l'attribut, qui l'impose \u2014 sur la racine ou sur une zone.
1915
+ Durees et deplacements a zero ; les cadences restent, un indicateur d'attente
1916
+ ne se fige jamais. \`:where(:root)\` : la regle pese (0,1,0), comme les autres. */
1917
+ @media (prefers-reduced-motion: reduce) {
1918
+ :where(:root):not([data-mouvement='complet']) {
1919
+ ${declarations(mouvementReduit, " ")}
1920
+ }
1921
+ }
1922
+
1923
+ [data-mouvement='reduit'] {
1924
+ ${declarations(mouvementReduit, " ")}
1925
+ }
1926
+
1927
+ /* Gel d'une image : au changement de theme ou de langue, rien ne transite le temps
1928
+ d'un rendu (StTheme et StLangue posent data-gel sur <html>). Place apres le
1929
+ mouvement : un mouvement complet choisi ne leve pas le gel. */
1930
+ [data-gel] {
1931
+ ${declarations(mouvementGele, " ")}
1932
+ }
1933
+
1934
+ /* WCAG 2.4.11 : un arret de tabulation ne remonte jamais sous l'en-tete collant.
1935
+ \`${PREFIXE}-hauteur-entete\` est posee sur <html> par st-app-shell, qui mesure
1936
+ son en-tete ; sans coquille, le repli vaut zero et rien ne change. */
1937
+ html {
1938
+ scroll-padding-block-start: var(${PREFIXE}-hauteur-entete, 0px);
1939
+ }
1940
+
1941
+ /* Rythme vertical d'un formulaire, porte par le CONTENEUR (lot 200) : les champs du
1942
+ socle n'ont plus de marge externe, pour qu'un champ pose dans une ligne de
1943
+ reglage ou un popover ne traine pas 20 px qu'il n'a pas choisis. */
1944
+ .st-formulaire {
1945
+ display: grid;
1946
+ gap: var(${PREFIXE}-espacement-5);
1947
+ }
1948
+
1949
+ /* Texte pour les seuls lecteurs d'ecran (\u00ab , 5 non lus \u00bb d'un lien de navigation) : la classe
1950
+ est PUBLIEE ici, dans la feuille que l'hote charge deja. Emise dans la portee emulee de chaque
1951
+ composant, elle n'atteignait jamais un element ecrit dans le gabarit de l'APPELANT, dont le
1952
+ texte s'affichait en clair (constats A1099, A1082, lot 156). \`.st-vh-focalisable\` : masquee
1953
+ tant qu'elle ne contient pas le focus (un lien d'evitement) ; \`:where()\` garde le poids d'une
1954
+ classe, comme toute la feuille. */
1955
+ .st-vh,
1956
+ .st-vh-focalisable:where(:not(:focus-within)) {
1957
+ position: absolute;
1958
+ width: 1px;
1959
+ height: 1px;
1960
+ padding: 0;
1961
+ margin: -1px;
1962
+ overflow: hidden;
1963
+ clip-path: inset(50%);
1964
+ white-space: nowrap;
1965
+ border: 0;
1966
+ }
1967
+
1968
+ /* Contrat avec le CDK : ses surfaces (menus, popovers, infobulles, tiroirs,
1969
+ dialogues) s'empilent par l'ordre du DOM dans ce conteneur, qui lit le plan. */
1970
+ .cdk-overlay-container {
1971
+ z-index: var(${PREFIXE}-plan-superposition);
1972
+ }
1973
+
1974
+ /* Contraste renforce : alias du theme courant, clair ou sombre (01 \u00a77.1). */
1975
+ @media (prefers-contrast: more) {
1976
+ :root {
1977
+ ${declarations(aliasDeContrasteRenforce, " ")}
1978
+ }
1979
+ }
1980
+
1981
+ /* Contraste force : les roles vers les couleurs systeme, aucune ombre (01 \u00a77.2). */
1982
+ @media (forced-colors: active) {
1983
+ :root {
1984
+ ${blocContrasteForce()}
1985
+ }
1986
+ }
1987
+
1988
+ /* Impression : le theme clair et son encre, quel que soit le theme a l'ecran ou
1989
+ dans un ilot (01 \u00a77.3). Un fond sombre imprime est une page noire. */
1990
+ @media print {
1991
+ :root,
1992
+ [data-theme] {
1993
+ color-scheme: light;
1994
+ ${affichageSelonLeTheme("clair", " ")}
1995
+ }
1996
+
1997
+ :root {
1998
+ ${blocImpression()}
1999
+ }
2000
+
2001
+ .st-hors-impression {
2002
+ display: none !important;
2003
+ }
2004
+
2005
+ /* Impression EXCLUSIVE (lot 263) : un composant qui la demande (les codes de secours) pose
2006
+ l'attribut sur <html> le temps du dialogue, et seule sa region s'imprime ; tout ce qui n'est
2007
+ ni elle, ni dedans, ni l'un de ses ancetres disparait. Poids nul (:where) comme le reste de
2008
+ la feuille ; !important l'emporte sur l'affichage des composants. */
2009
+ :where(
2010
+ :root[data-st-impression-exclusive]
2011
+ body
2012
+ *:not([data-st-imprimable], [data-st-imprimable] *, :has([data-st-imprimable]))
2013
+ ) {
2014
+ display: none !important;
2015
+ }
2016
+ }
2017
+
2018
+ @media not print {
2019
+ .st-impression-seulement {
2020
+ display: none !important;
2021
+ }
2022
+ }
2023
+
2024
+ @page {
2025
+ margin: 16mm 14mm;
2026
+ }
2027
+ `;
2028
+ }
2029
+ function nombreDeJetonsDeCouleur(jetons = themeClair) {
2030
+ return Object.keys(jetons).length;
2031
+ }
2032
+ function jetonsDtcg() {
2033
+ const jetons = {
2034
+ $description: "Jetons de @starterlib/tokens au format DTCG 2025.10. Engendre par tools/generer-css.mjs : ne pas modifier.",
2035
+ couleur: {
2036
+ clair: couleurs(themeClair),
2037
+ sombre: couleurs(themeSombre)
2038
+ },
2039
+ espacement: dimensions(espacement),
2040
+ rayon: dimensions(rayon),
2041
+ taille: dimensions(typographie.taille),
2042
+ interligne: dimensions(typographie.interligne),
2043
+ graisse: Object.fromEntries(Object.entries(typographie.graisse).map(([cle, valeur]) => [cle, {
2044
+ $type: "fontWeight",
2045
+ $value: Number(valeur)
2046
+ }])),
2047
+ police: Object.fromEntries(Object.entries(typographie.famille).map(([cle, pile]) => [cle, {
2048
+ $type: "fontFamily",
2049
+ $value: familles(pile)
2050
+ }])),
2051
+ duree: Object.fromEntries(Object.entries(duree).map(([cle, valeur]) => [cle, {
2052
+ $type: "duration",
2053
+ $value: {
2054
+ value: Number.parseFloat(valeur),
2055
+ unit: "ms"
2056
+ }
2057
+ }]))
2058
+ };
2059
+ return `${JSON.stringify(jetons, null, 2)}\n`;
2060
+ }
2061
+ function couleurs(theme) {
2062
+ const noms = Object.keys(theme);
2063
+ return Object.fromEntries(noms.map((nom) => [nom, {
2064
+ $type: "color",
2065
+ $value: couleur(theme[nom])
2066
+ }]));
2067
+ }
2068
+ function couleur(hex) {
2069
+ return {
2070
+ colorSpace: "srgb",
2071
+ components: [
2072
+ 1,
2073
+ 3,
2074
+ 5
2075
+ ].map((debut) => Number.parseInt(hex.slice(debut, debut + 2), 16) / 255).map((canal) => Number(canal.toFixed(4))),
2076
+ alpha: 1,
2077
+ hex
2078
+ };
2079
+ }
2080
+ function dimensions(valeurs) {
2081
+ return Object.fromEntries(Object.entries(valeurs).map(([cle, valeur]) => [cle, {
2082
+ $type: "dimension",
2083
+ $value: dimension(valeur)
2084
+ }]));
2085
+ }
2086
+ function dimension(valeur) {
2087
+ if (valeur === "0") return {
2088
+ value: 0,
2089
+ unit: "px"
2090
+ };
2091
+ const lu = /^(-?\d*\.?\d+)(px|rem)$/.exec(valeur);
2092
+ if (lu === null) throw new Error(`Dimension hors du format DTCG (px ou rem) : ${valeur}`);
2093
+ return {
2094
+ value: Number(lu[1]),
2095
+ unit: lu[2]
2096
+ };
2097
+ }
2098
+ function familles(pile) {
2099
+ return pile.split(",").map((famille) => famille.trim().replace(/^'(.*)'$/, "$1"));
2100
+ }
2101
+ export { CLES_DE_TAILLE, COUCHES, C_PAS, FAMILLES, L_PAS, MODES_DE_DENSITE, PAS_DE_RAMPE, PAS_NEUTRES, PREFIXE, RANGS_DE_SERIE, SEUIL_DE_PERCEPTIBILITE, aliasDeContrasteRenforce, aliasDeContrasteRenforceParJeton, apca, cadence, cadenceMinimale, cibleMinimale, cibleTactileMinimale, composer, contratsDHote, couleurDOmbre, couleursSysteme, courbe, cssDesEchelles, cssDuTheme, declarationsDuStyle, definitionDuPas, definitionsDesPrimitives, densite, deplacement, derogationsDImpression, duree, ecartsDeSurface, enKebab, encresDAplat, encresDeContrasteRenforce, epaisseur, epaisseurCapillaire, espacement, estJetonDeComposant, exemptesDeContraste, feuilleDeJetons, feuilleDesPolices, fichiersAPrecharger, focus, hauteurDeCommande, hexVersOklch, interlettrageDuStyle, jetonsDeComposant, jetonsDtcg, largeur, lireCouleur, luminanceRelative, mouvementGele, mouvementReduit, nomDeCouleur, nombreDeJetonsDeCouleur, oklchEnCss, oklchVersHex, oklchVersSrgb, ombreDuTheme, ombres, pairesDeContraste, pairesExclues, partielDeTypographie, plan, policesDuSocle, primitives, rapportDeContraste, rayon, respecteLeContraste, rolesDesPrimitives, seuilExige, stylesTypographiques, surchargesDuRepli, surfacesDuFocus, taillesDImpression, themeClair, themeSombre, themeSousContrasteRenforce, themes, typographie, variablesInternes, versRvb, voile };
2102
+
2103
+ //# sourceMappingURL=starterlib-tokens-moteur.mjs.map