@starterlib/ui 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,9 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, LOCALE_ID, signal, input, computed, ChangeDetectionStrategy, Component, booleanAttribute, ElementRef, DestroyRef, output, model, afterNextRender, TemplateRef, Directive, contentChild, linkedSignal, effect, isDevMode } from '@angular/core';
3
- import { masquerIban, masquerTelephone, masquerCarte, quatreDerniers, formaterIban, formaterMontant } from '@starterlib/util';
2
+ import { InjectionToken, inject, LOCALE_ID, signal, input, computed, ChangeDetectionStrategy, Component, booleanAttribute, ElementRef, DestroyRef, output, model, afterNextRender, viewChild, Directive, effect, Injector, linkedSignal, TemplateRef, contentChild, isDevMode } from '@angular/core';
3
+ import { masquerIban, masquerTelephone, masquerCarte, quatreDerniers, formaterIban, formaterMontant, formaterTaille, formaterDateLongue, montant, decimalesDe, motifDeDate, formaterDateSaisie, ibanEstValide, normaliserTelephone, typeDeFichierAccepte, normaliserIban, bornerDate, premierJourDeLaSemaine, ajouterJours, semainesDuMois, ajouterMois, jourDeLaSemaine, CHOIX_DE_THEME, LANGUES } from '@starterlib/util';
4
4
  export { ETATS_DE_BLOC } from '@starterlib/util';
5
5
  import { DOCUMENT, NgTemplateOutlet } from '@angular/common';
6
+ import { RouterLink } from '@angular/router';
6
7
 
7
8
  /**
8
9
  * Defaut francais, identique mot pour mot aux textes ecrits en dur jusqu'a la
@@ -13,25 +14,111 @@ import { DOCUMENT, NgTemplateOutlet } from '@angular/common';
13
14
  * sous forme de signal — sinon la moitie de l'interface reste en francais quand
14
15
  * l'utilisateur passe a l'anglais, et rien ne le signale.
15
16
  */
17
+ /**
18
+ * ⚠️ Les textes AFFICHES portent leurs accents. La regle « sans accents » du
19
+ * depot vise la documentation et les commentaires, jamais ce que lit la
20
+ * personne qui utilise l'application : « Reessayer » ou « Aucun resultat » sont
21
+ * des fautes a l'ecran, et une synthese vocale les prononce de travers. La 0.2.0
22
+ * les a livres ainsi. Les accents s'ecrivent en sequence d'echappement, comme
23
+ * l'apostrophe typographique, pour garder la source en ASCII.
24
+ */
16
25
  const LIBELLES_FR = {
17
26
  chargementEnCours: 'Chargement en cours',
18
27
  erreurSurvenue: 'Une erreur est survenue',
19
- aucunResultat: 'Aucun resultat',
28
+ aucunResultat: 'Aucun r\u00e9sultat',
20
29
  horsConnexion: 'Hors connexion',
21
- reessayer: 'Reessayer',
30
+ reessayer: 'R\u00e9essayer',
22
31
  identifiantDeTrace: 'Identifiant de trace',
23
32
  codeTechnique: 'Code',
24
33
  copier: 'Copier',
25
- copieEffectuee: 'Copie',
34
+ copieEffectuee: 'Copi\u00e9',
35
+ copieImpossible: 'Copie impossible. S\u00e9lectionnez le texte pour le copier.',
26
36
  afficher: 'Afficher',
27
37
  masquer: 'Masquer',
28
- valeurMasqueeANouveau: 'Valeur masquee a nouveau',
38
+ valeurMasqueeANouveau: 'Valeur masqu\u00e9e \u00e0 nouveau',
29
39
  natureIban: 'IBAN',
30
40
  natureCarte: 'carte',
31
- natureTelephone: 'numero',
41
+ natureTelephone: 'num\u00e9ro',
32
42
  seTerminantPar: (nature, quatreDerniers) => `${nature} se terminant par ${quatreDerniers}`,
33
- nouvelleFenetre: '(nouvelle fenetre)',
43
+ nouvelleFenetre: '(nouvelle fen\u00eatre)',
34
44
  retirer: 'Retirer',
45
+ filDAriane: 'Fil d\u2019Ariane',
46
+ allerAuContenu: 'Aller au contenu',
47
+ navigationPrincipale: 'Navigation principale',
48
+ theme: 'Th\u00e8me',
49
+ themeSysteme: 'Syst\u00e8me',
50
+ themeClair: 'Clair',
51
+ themeSombre: 'Sombre',
52
+ langue: 'Langue',
53
+ reessayerDans: (duree) => `Nouvel essai possible dans ${duree}`,
54
+ reessayerMaintenant: 'Vous pouvez r\u00e9essayer.',
55
+ sessionBientotExpiree: 'Votre session va expirer',
56
+ sessionExpireDans: (duree) => `Sans activit\u00e9 de votre part, la session sera ferm\u00e9e dans ${duree}.`,
57
+ resterConnecte: 'Rester connect\u00e9',
58
+ seDeconnecter: 'Se d\u00e9connecter',
59
+ obligatoire: '(obligatoire)',
60
+ champObligatoire: 'Ce champ est obligatoire.',
61
+ valeurInvalide: 'Cette valeur n\u2019est pas valide.',
62
+ adresseInvalide: 'Saisissez une adresse \u00e9lectronique, par exemple nom@exemple.fr.',
63
+ formatInvalide: 'Le format n\u2019est pas valide.',
64
+ longueurMinimale: (minimum) => `Saisissez au moins ${String(minimum)} caract\u00e8res.`,
65
+ longueurMaximale: (maximum) => `Saisissez au plus ${String(maximum)} caract\u00e8res.`,
66
+ valeurMinimale: (minimum) => `La valeur doit \u00eatre au moins ${minimum}.`,
67
+ valeurMaximale: (maximum) => `La valeur doit \u00eatre au plus ${maximum}.`,
68
+ caracteresRestants: (restants) => restants <= 1
69
+ ? `${String(restants)} caract\u00e8re restant`
70
+ : `${String(restants)} caract\u00e8res restants`,
71
+ caracteresEnTrop: (enTrop) => enTrop === 1 ? '1 caract\u00e8re en trop' : `${String(enTrop)} caract\u00e8res en trop`,
72
+ erreursACorriger: (nombre) => nombre === 1 ? 'Une erreur \u00e0 corriger' : `${String(nombre)} erreurs \u00e0 corriger`,
73
+ afficherLeMotDePasse: 'Afficher le mot de passe',
74
+ codeAChiffres: (longueur) => `Code \u00e0 ${String(longueur)} chiffres.`,
75
+ ibanInvalide: 'Saisissez un IBAN valide.',
76
+ telephoneInvalide: 'Saisissez un num\u00e9ro de t\u00e9l\u00e9phone en chiffres, avec l\u2019indicatif du pays pour un num\u00e9ro \u00e9tranger.',
77
+ exempleDIban: 'Par exemple FR76 3000 6000 0112 3456 7890 189.',
78
+ rechercher: 'Rechercher',
79
+ fermerLeMessage: 'Fermer le message',
80
+ montantIllisible: (exemple) => `Saisissez un montant en chiffres, par exemple ${exemple}.`,
81
+ tropDeDecimales: (decimales) => decimales === 0
82
+ ? 'Saisissez un montant sans d\u00e9cimales.'
83
+ : `Saisissez au plus ${String(decimales)} d\u00e9cimale${decimales > 1 ? 's' : ''}.`,
84
+ deviseDuMontant: (devise) => `Devise\u00a0: ${devise}.`,
85
+ lettreDuJour: 'jj',
86
+ lettreDuMois: 'mm',
87
+ lettreDeLAnnee: 'aaaa',
88
+ formatDeDate: (motif, exemple) => `Au format ${motif}, par exemple ${exemple}.`,
89
+ dateIllisible: (motif, exemple) => `Saisissez une date qui existe, au format ${motif}, par exemple ${exemple}.`,
90
+ dateTropTot: (date) => `Saisissez une date \u00e0 partir du ${date}.`,
91
+ dateTropTard: (date) => `Saisissez une date jusqu\u2019au ${date}.`,
92
+ finAvantDebut: 'La date de fin ne peut pas pr\u00e9c\u00e9der la date de d\u00e9but.',
93
+ dateDeDebut: 'Date de d\u00e9but',
94
+ dateDeFin: 'Date de fin',
95
+ choisirDansLeCalendrier: (champ) => `${champ}\u00a0: choisir dans le calendrier`,
96
+ moisPrecedent: 'Mois pr\u00e9c\u00e9dent',
97
+ moisSuivant: 'Mois suivant',
98
+ aideDuCalendrier: 'Fl\u00e8ches pour changer de jour, Page pr\u00e9c\u00e9dente et Page suivante pour changer de mois, \u00c9chap pour fermer.',
99
+ choisir: 'Choisir\u2026',
100
+ nombreDeResultats: (nombre) => nombre === 0
101
+ ? 'Aucun r\u00e9sultat'
102
+ : `${String(nombre)} r\u00e9sultat${nombre > 1 ? 's' : ''}`,
103
+ nombreDeSelections: (nombre) => (nombre === 0 ? 'Aucun choix' : `${String(nombre)} choix`),
104
+ retirerLeChoix: (choix) => `Retirer ${choix}`,
105
+ afficherLesChoix: (champ) => `${champ}\u00a0: afficher les choix`,
106
+ choisirDesFichiers: 'Choisir des fichiers',
107
+ choisirUnFichier: 'Choisir un fichier',
108
+ ouDeposerIci: 'ou d\u00e9posez-les ici',
109
+ aucunFichier: 'Aucun fichier choisi.',
110
+ nombreDeFichiers: (nombre) => nombre === 0
111
+ ? 'Aucun fichier choisi.'
112
+ : `${String(nombre)} fichier${nombre > 1 ? 's' : ''} choisi${nombre > 1 ? 's' : ''}.`,
113
+ retirerLeFichier: (fichier) => `Retirer ${fichier}`,
114
+ fichierTropVolumineux: (fichier, taille) => `${fichier} d\u00e9passe ${taille}.`,
115
+ typeDeFichierRefuse: (fichier) => `${fichier} n\u2019est pas d\u2019un type accept\u00e9.`,
116
+ tropDeFichiers: (nombre) => `Choisissez au plus ${String(nombre)} fichier${nombre > 1 ? 's' : ''}.`,
117
+ typesAcceptes: (types) => `Types accept\u00e9s\u00a0: ${types}.`,
118
+ tailleMaximale: (taille) => `${taille} au plus par fichier.`,
119
+ confirmer: 'Confirmer',
120
+ annuler: 'Annuler',
121
+ recopierPourConfirmer: (texte) => `Pour confirmer, recopiez \u00ab\u202f${texte}\u202f\u00bb`,
35
122
  aLInstant: "a l'instant",
36
123
  };
37
124
  /** Traduction anglaise du meme dictionnaire. La paire est obligatoire. */
@@ -45,6 +132,7 @@ const LIBELLES_EN = {
45
132
  codeTechnique: 'Code',
46
133
  copier: 'Copy',
47
134
  copieEffectuee: 'Copied',
135
+ copieImpossible: 'Could not copy. Select the text to copy it.',
48
136
  afficher: 'Show',
49
137
  masquer: 'Hide',
50
138
  valeurMasqueeANouveau: 'Value hidden again',
@@ -54,6 +142,77 @@ const LIBELLES_EN = {
54
142
  seTerminantPar: (nature, quatreDerniers) => `${nature} ending in ${quatreDerniers}`,
55
143
  nouvelleFenetre: '(opens in a new window)',
56
144
  retirer: 'Remove',
145
+ filDAriane: 'Breadcrumb',
146
+ allerAuContenu: 'Skip to content',
147
+ navigationPrincipale: 'Main navigation',
148
+ theme: 'Theme',
149
+ themeSysteme: 'System',
150
+ themeClair: 'Light',
151
+ themeSombre: 'Dark',
152
+ langue: 'Language',
153
+ reessayerDans: (duree) => `You can try again in ${duree}`,
154
+ reessayerMaintenant: 'You can try again now.',
155
+ sessionBientotExpiree: 'Your session is about to expire',
156
+ sessionExpireDans: (duree) => `Without any activity, you will be signed out in ${duree}.`,
157
+ resterConnecte: 'Stay signed in',
158
+ seDeconnecter: 'Sign out',
159
+ obligatoire: '(required)',
160
+ champObligatoire: 'This field is required.',
161
+ valeurInvalide: 'This value is not valid.',
162
+ adresseInvalide: 'Enter an email address, like name@example.com.',
163
+ formatInvalide: 'The format is not valid.',
164
+ longueurMinimale: (minimum) => `Enter at least ${String(minimum)} characters.`,
165
+ longueurMaximale: (maximum) => `Enter no more than ${String(maximum)} characters.`,
166
+ valeurMinimale: (minimum) => `The value must be at least ${minimum}.`,
167
+ valeurMaximale: (maximum) => `The value must be at most ${maximum}.`,
168
+ caracteresRestants: (restants) => restants === 1 ? '1 character remaining' : `${String(restants)} characters remaining`,
169
+ caracteresEnTrop: (enTrop) => enTrop === 1 ? '1 character too many' : `${String(enTrop)} characters too many`,
170
+ erreursACorriger: (nombre) => nombre === 1 ? 'There is 1 problem to fix' : `There are ${String(nombre)} problems to fix`,
171
+ afficherLeMotDePasse: 'Show password',
172
+ codeAChiffres: (longueur) => `${String(longueur)}-digit code.`,
173
+ ibanInvalide: 'Enter a valid IBAN.',
174
+ telephoneInvalide: 'Enter a phone number using digits, with the country code for a number abroad.',
175
+ exempleDIban: 'For example FR76 3000 6000 0112 3456 7890 189.',
176
+ rechercher: 'Search',
177
+ fermerLeMessage: 'Dismiss message',
178
+ montantIllisible: (exemple) => `Enter an amount in figures, like ${exemple}.`,
179
+ tropDeDecimales: (decimales) => decimales === 0
180
+ ? 'Enter an amount without decimals.'
181
+ : `Enter no more than ${String(decimales)} decimal place${decimales > 1 ? 's' : ''}.`,
182
+ deviseDuMontant: (devise) => `Currency: ${devise}.`,
183
+ lettreDuJour: 'dd',
184
+ lettreDuMois: 'mm',
185
+ lettreDeLAnnee: 'yyyy',
186
+ formatDeDate: (motif, exemple) => `Use the format ${motif}, like ${exemple}.`,
187
+ dateIllisible: (motif, exemple) => `Enter a real date in the format ${motif}, like ${exemple}.`,
188
+ dateTropTot: (date) => `Enter a date on or after ${date}.`,
189
+ dateTropTard: (date) => `Enter a date on or before ${date}.`,
190
+ finAvantDebut: 'The end date cannot be before the start date.',
191
+ dateDeDebut: 'Start date',
192
+ dateDeFin: 'End date',
193
+ choisirDansLeCalendrier: (champ) => `${champ}: choose from calendar`,
194
+ moisPrecedent: 'Previous month',
195
+ moisSuivant: 'Next month',
196
+ aideDuCalendrier: 'Arrow keys to change day, Page Up and Page Down to change month, Escape to close.',
197
+ choisir: 'Choose\u2026',
198
+ nombreDeResultats: (nombre) => nombre === 0 ? 'No results' : `${String(nombre)} result${nombre > 1 ? 's' : ''}`,
199
+ nombreDeSelections: (nombre) => nombre === 0 ? 'Nothing selected' : `${String(nombre)} selected`,
200
+ retirerLeChoix: (choix) => `Remove ${choix}`,
201
+ afficherLesChoix: (champ) => `${champ}: show options`,
202
+ choisirDesFichiers: 'Choose files',
203
+ choisirUnFichier: 'Choose a file',
204
+ ouDeposerIci: 'or drop them here',
205
+ aucunFichier: 'No file chosen.',
206
+ nombreDeFichiers: (nombre) => nombre === 0 ? 'No file chosen.' : `${String(nombre)} file${nombre > 1 ? 's' : ''} chosen.`,
207
+ retirerLeFichier: (fichier) => `Remove ${fichier}`,
208
+ fichierTropVolumineux: (fichier, taille) => `${fichier} is larger than ${taille}.`,
209
+ typeDeFichierRefuse: (fichier) => `${fichier} is not an accepted file type.`,
210
+ tropDeFichiers: (nombre) => `Choose no more than ${String(nombre)} file${nombre > 1 ? 's' : ''}.`,
211
+ typesAcceptes: (types) => `Accepted types: ${types}.`,
212
+ tailleMaximale: (taille) => `${taille} maximum per file.`,
213
+ confirmer: 'Confirm',
214
+ annuler: 'Cancel',
215
+ recopierPourConfirmer: (texte) => `To confirm, type \u201c${texte}\u201d`,
57
216
  aLInstant: 'just now',
58
217
  };
59
218
 
@@ -173,6 +332,108 @@ const FUSEAU_PAR_DEFAUT = new InjectionToken('st.fuseau-par-defaut', {
173
332
  * seul import necessaire a qui n'ecrit que de l'interface.
174
333
  */
175
334
 
335
+ /**
336
+ * Meme raison que `StAnnonceur` du noyau, qu'`ui` ne peut pas importer : la
337
+ * region doit etre observee avant de recevoir son texte, et un texte identique
338
+ * repose dans la meme tache ne produit aucune mutation, donc aucune annonce.
339
+ */
340
+ const DELAI_D_ANNONCE_MS = 120;
341
+ /** Au-dela, le message est retire : relu plus tard hors contexte, il tromperait. */
342
+ const DUREE_D_AFFICHAGE_MS = 3000;
343
+ /**
344
+ * Texte d'une petite region vivante propre a un composant.
345
+ *
346
+ * ```ts
347
+ * protected readonly annonce = new AnnonceLocale(inject(DestroyRef));
348
+ * // gabarit : <span class="st-vh" aria-live="polite">{{ annonce.texte() }}</span>
349
+ * ```
350
+ *
351
+ * ⚠️ La region doit exister VIDE dans le gabarit des la creation du composant ;
352
+ * cette classe ne gere que son texte.
353
+ *
354
+ * ⚠️ Nee de deux defauts de `st-code` en 0.2.0 : un `onDestroy` enregistre a
355
+ * chaque clic, et une confirmation identique reposee dans la meme tache — la
356
+ * seconde copie n'etait jamais annoncee.
357
+ */
358
+ class AnnonceLocale {
359
+ contenu = signal('', /* @ts-ignore */
360
+ ...(ngDevMode ? [{ debugName: "contenu" }] : /* istanbul ignore next */ []));
361
+ minuteries = [];
362
+ texte = this.contenu.asReadonly();
363
+ constructor(destruction) {
364
+ destruction.onDestroy(() => {
365
+ this.arreter();
366
+ });
367
+ }
368
+ annoncer(message) {
369
+ this.arreter();
370
+ this.contenu.set('');
371
+ this.minuteries.push(setTimeout(() => {
372
+ this.contenu.set(message);
373
+ this.minuteries.push(setTimeout(() => {
374
+ this.contenu.set('');
375
+ }, DUREE_D_AFFICHAGE_MS));
376
+ }, DELAI_D_ANNONCE_MS));
377
+ }
378
+ arreter() {
379
+ for (const minuterie of this.minuteries)
380
+ clearTimeout(minuterie);
381
+ this.minuteries = [];
382
+ }
383
+ }
384
+
385
+ /**
386
+ * Ecrit un texte dans le presse-papiers.
387
+ *
388
+ * ⚠️ Trois issues, et non deux. `navigator.clipboard` n'existe qu'en contexte
389
+ * securise (HTTPS, ou `localhost`) : absent, c'est `indisponible`. Present, il
390
+ * peut encore refuser — permission, document sans focus — et c'est `refusee`.
391
+ * Confondre les deux conduit a cacher un bouton qui aurait fonctionne au clic
392
+ * suivant, ou a laisser croire qu'une copie a eu lieu.
393
+ *
394
+ * ⚠️ Ce qui entre dans le presse-papiers en sort difficilement : les
395
+ * gestionnaires d'historique le conservent, et la synchronisation entre
396
+ * appareils le propage. Jamais de secret — mot de passe, jeton, code a usage
397
+ * unique — et une donnee sensible seulement a la demande explicite de la
398
+ * personne.
399
+ */
400
+ async function copierDansLePressePapiers(document, texte) {
401
+ const presse = document.defaultView?.navigator.clipboard;
402
+ if (presse === undefined)
403
+ return 'indisponible';
404
+ try {
405
+ await presse.writeText(texte);
406
+ return 'copie';
407
+ }
408
+ catch {
409
+ return 'refusee';
410
+ }
411
+ }
412
+ /** Vrai si le navigateur expose un presse-papiers ecrivable par script. */
413
+ function pressePapiersDisponible(document) {
414
+ return document.defaultView?.navigator.clipboard !== undefined;
415
+ }
416
+
417
+ /**
418
+ * Formate une duree en secondes : « 45 s », « 2 min 05 s ».
419
+ *
420
+ * Unites courtes de la langue donnee, par `Intl.NumberFormat` : l'ordre, les
421
+ * espaces et les abreviations suivent la locale, sans table maison.
422
+ */
423
+ function formaterDuree(totalEnSecondes, locale) {
424
+ const total = Math.max(0, Math.round(totalEnSecondes));
425
+ const unite = (valeur, nom) => new Intl.NumberFormat(locale, {
426
+ style: 'unit',
427
+ unit: nom,
428
+ unitDisplay: 'short',
429
+ // « 2 min 05 s » : les secondes sur deux chiffres quand des minutes precedent.
430
+ minimumIntegerDigits: nom === 'second' && total >= 60 ? 2 : 1,
431
+ }).format(valeur);
432
+ if (total < 60)
433
+ return unite(total, 'second');
434
+ return `${unite(Math.floor(total / 60), 'minute')} ${unite(total % 60, 'second')}`;
435
+ }
436
+
176
437
  /**
177
438
  * Icone tiree d'un sprite SVG servi en meme origine.
178
439
  *
@@ -201,7 +462,7 @@ class StIcon {
201
462
  reference = computed(() => `${this.cheminDuSprite}#${this.nom()}`, /* @ts-ignore */
202
463
  ...(ngDevMode ? [{ debugName: "reference" }] : /* istanbul ignore next */ []));
203
464
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StIcon, deps: [], target: i0.ɵɵFactoryTarget.Component });
204
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StIcon, isStandalone: true, selector: "st-icon", inputs: { nom: { classPropertyName: "nom", publicName: "nom", isSignal: true, isRequired: true, transformFunction: null }, taille: { classPropertyName: "taille", publicName: "taille", isSignal: true, isRequired: false, transformFunction: null }, ton: { classPropertyName: "ton", publicName: "ton", isSignal: true, isRequired: false, transformFunction: null }, etiquette: { classPropertyName: "etiquette", publicName: "etiquette", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-taille": "taille()", "attr.data-ton": "ton()" }, classAttribute: "st-icon" }, ngImport: i0, template: "<svg\n [attr.aria-hidden]=\"estDecorative() ? 'true' : null\"\n [attr.role]=\"estDecorative() ? null : 'img'\"\n [attr.aria-label]=\"etiquette()\"\n focusable=\"false\"\n>\n <use [attr.href]=\"reference()\" />\n</svg>\n", styles: [":host{display:inline-flex;flex:none;vertical-align:-.125em;color:inherit}svg{inline-size:var(--st-icone-taille, 1.25em);block-size:var(--st-icone-taille, 1.25em)}:host([data-taille=xs]) svg{--st-icone-taille: .75em}:host([data-taille=sm]) svg{--st-icone-taille: 1em}:host([data-taille=lg]) svg{--st-icone-taille: 1.5em}:host([data-taille=xl]) svg{--st-icone-taille: 2em}:host([data-ton=discret]){color:var(--st-couleur-texte-discret)}:host([data-ton=primaire]){color:var(--st-couleur-primaire)}:host([data-ton=succes]){color:var(--st-couleur-succes)}:host([data-ton=avertissement]){color:var(--st-couleur-avertissement)}:host([data-ton=danger]){color:var(--st-couleur-danger)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
465
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StIcon, isStandalone: true, selector: "st-icon", inputs: { nom: { classPropertyName: "nom", publicName: "nom", isSignal: true, isRequired: true, transformFunction: null }, taille: { classPropertyName: "taille", publicName: "taille", isSignal: true, isRequired: false, transformFunction: null }, ton: { classPropertyName: "ton", publicName: "ton", isSignal: true, isRequired: false, transformFunction: null }, etiquette: { classPropertyName: "etiquette", publicName: "etiquette", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-taille": "taille()", "attr.data-ton": "ton()" }, classAttribute: "st-icon" }, ngImport: i0, template: "<svg\n [attr.aria-hidden]=\"estDecorative() ? 'true' : null\"\n [attr.role]=\"estDecorative() ? null : 'img'\"\n [attr.aria-label]=\"etiquette()\"\n focusable=\"false\"\n>\n <use [attr.href]=\"reference()\" />\n</svg>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:inline-flex;flex:none;vertical-align:-.125em;color:inherit}svg{inline-size:var(--st-icone-taille, 1.25em);block-size:var(--st-icone-taille, 1.25em)}:host([data-taille=xs]) svg{--st-icone-taille: .75em}:host([data-taille=sm]) svg{--st-icone-taille: 1em}:host([data-taille=lg]) svg{--st-icone-taille: 1.5em}:host([data-taille=xl]) svg{--st-icone-taille: 2em}:host([data-ton=discret]){color:var(--st-couleur-texte-discret)}:host([data-ton=primaire]){color:var(--st-couleur-primaire)}:host([data-ton=succes]){color:var(--st-couleur-succes)}:host([data-ton=avertissement]){color:var(--st-couleur-avertissement)}:host([data-ton=danger]){color:var(--st-couleur-danger)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
205
466
  }
206
467
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StIcon, decorators: [{
207
468
  type: Component,
@@ -209,7 +470,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
209
470
  class: 'st-icon',
210
471
  '[attr.data-taille]': 'taille()',
211
472
  '[attr.data-ton]': 'ton()',
212
- }, template: "<svg\n [attr.aria-hidden]=\"estDecorative() ? 'true' : null\"\n [attr.role]=\"estDecorative() ? null : 'img'\"\n [attr.aria-label]=\"etiquette()\"\n focusable=\"false\"\n>\n <use [attr.href]=\"reference()\" />\n</svg>\n", styles: [":host{display:inline-flex;flex:none;vertical-align:-.125em;color:inherit}svg{inline-size:var(--st-icone-taille, 1.25em);block-size:var(--st-icone-taille, 1.25em)}:host([data-taille=xs]) svg{--st-icone-taille: .75em}:host([data-taille=sm]) svg{--st-icone-taille: 1em}:host([data-taille=lg]) svg{--st-icone-taille: 1.5em}:host([data-taille=xl]) svg{--st-icone-taille: 2em}:host([data-ton=discret]){color:var(--st-couleur-texte-discret)}:host([data-ton=primaire]){color:var(--st-couleur-primaire)}:host([data-ton=succes]){color:var(--st-couleur-succes)}:host([data-ton=avertissement]){color:var(--st-couleur-avertissement)}:host([data-ton=danger]){color:var(--st-couleur-danger)}\n"] }]
473
+ }, template: "<svg\n [attr.aria-hidden]=\"estDecorative() ? 'true' : null\"\n [attr.role]=\"estDecorative() ? null : 'img'\"\n [attr.aria-label]=\"etiquette()\"\n focusable=\"false\"\n>\n <use [attr.href]=\"reference()\" />\n</svg>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:inline-flex;flex:none;vertical-align:-.125em;color:inherit}svg{inline-size:var(--st-icone-taille, 1.25em);block-size:var(--st-icone-taille, 1.25em)}:host([data-taille=xs]) svg{--st-icone-taille: .75em}:host([data-taille=sm]) svg{--st-icone-taille: 1em}:host([data-taille=lg]) svg{--st-icone-taille: 1.5em}:host([data-taille=xl]) svg{--st-icone-taille: 2em}:host([data-ton=discret]){color:var(--st-couleur-texte-discret)}:host([data-ton=primaire]){color:var(--st-couleur-primaire)}:host([data-ton=succes]){color:var(--st-couleur-succes)}:host([data-ton=avertissement]){color:var(--st-couleur-avertissement)}:host([data-ton=danger]){color:var(--st-couleur-danger)}\n"] }]
213
474
  }], propDecorators: { nom: [{ type: i0.Input, args: [{ isSignal: true, alias: "nom", required: true }] }], taille: [{ type: i0.Input, args: [{ isSignal: true, alias: "taille", required: false }] }], ton: [{ type: i0.Input, args: [{ isSignal: true, alias: "ton", required: false }] }], etiquette: [{ type: i0.Input, args: [{ isSignal: true, alias: "etiquette", required: false }] }] } });
214
475
 
215
476
  /**
@@ -222,6 +483,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
222
483
  */
223
484
  const NOMS_DICONE = [
224
485
  'boite-vide',
486
+ 'calendrier',
225
487
  'cercle',
226
488
  'cercle-coche',
227
489
  'cercle-croix',
@@ -234,6 +496,7 @@ const NOMS_DICONE = [
234
496
  'copie',
235
497
  'corbeille',
236
498
  'croix',
499
+ 'fichier',
237
500
  'hors-ligne',
238
501
  'lien-externe',
239
502
  'menu',
@@ -243,6 +506,7 @@ const NOMS_DICONE = [
243
506
  'rafraichir',
244
507
  'recherche',
245
508
  'serveur',
509
+ 'televerser',
246
510
  'triangle-alerte',
247
511
  'utilisateur',
248
512
  ];
@@ -269,7 +533,7 @@ class StText {
269
533
  tronquerA = input(null, /* @ts-ignore */
270
534
  ...(ngDevMode ? [{ debugName: "tronquerA" }] : /* istanbul ignore next */ []));
271
535
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StText, deps: [], target: i0.ɵɵFactoryTarget.Component });
272
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StText, isStandalone: true, selector: "st-text", inputs: { variante: { classPropertyName: "variante", publicName: "variante", isSignal: true, isRequired: false, transformFunction: null }, graisse: { classPropertyName: "graisse", publicName: "graisse", isSignal: true, isRequired: false, transformFunction: null }, enLigne: { classPropertyName: "enLigne", publicName: "enLigne", isSignal: true, isRequired: false, transformFunction: null }, tronquerA: { classPropertyName: "tronquerA", publicName: "tronquerA", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-variante": "variante()", "attr.data-graisse": "graisse()", "attr.data-en-ligne": "enLigne() ? \"\" : null", "attr.data-tronque": "tronquerA() === null ? null : \"\"", "style.--st-text-lignes": "tronquerA()" }, classAttribute: "st-text" }, ngImport: i0, template: "<ng-content />\n", styles: [":host{display:block;margin:0;font-family:var(--st-police-base);font-size:var(--st-taille-md);font-weight:var(--st-graisse-normale);line-height:var(--st-interligne-normal);color:var(--st-couleur-texte);max-inline-size:70ch}:host([data-en-ligne]){display:inline;max-inline-size:none}:host([data-variante=corps-sm]){font-size:var(--st-taille-sm)}:host([data-variante=discret]){color:var(--st-couleur-texte-discret)}:host([data-variante=legende]){font-size:var(--st-taille-xs);color:var(--st-couleur-texte-discret)}:host([data-variante=mono]){font-family:var(--st-police-mono);font-size:var(--st-taille-sm)}:host([data-graisse=moyenne]){font-weight:var(--st-graisse-moyenne)}:host([data-graisse=semi]){font-weight:var(--st-graisse-semi)}:host([data-tronque]){display:-webkit-box;overflow:hidden;-webkit-box-orient:vertical;-webkit-line-clamp:var(--st-text-lignes, 2);line-clamp:var(--st-text-lignes, 2)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
536
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StText, isStandalone: true, selector: "st-text", inputs: { variante: { classPropertyName: "variante", publicName: "variante", isSignal: true, isRequired: false, transformFunction: null }, graisse: { classPropertyName: "graisse", publicName: "graisse", isSignal: true, isRequired: false, transformFunction: null }, enLigne: { classPropertyName: "enLigne", publicName: "enLigne", isSignal: true, isRequired: false, transformFunction: null }, tronquerA: { classPropertyName: "tronquerA", publicName: "tronquerA", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-variante": "variante()", "attr.data-graisse": "graisse()", "attr.data-en-ligne": "enLigne() ? \"\" : null", "attr.data-tronque": "tronquerA() === null ? null : \"\"", "style.--st-text-lignes": "tronquerA()" }, classAttribute: "st-text" }, ngImport: i0, template: "<ng-content />\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block;margin:0;font-family:var(--st-police-base);font-size:var(--st-taille-md);font-weight:var(--st-graisse-normale);line-height:var(--st-interligne-normal);color:var(--st-couleur-texte);max-inline-size:70ch}:host([data-en-ligne]){display:inline;max-inline-size:none}:host([data-variante=corps-sm]){font-size:var(--st-taille-sm)}:host([data-variante=discret]){color:var(--st-couleur-texte-discret)}:host([data-variante=legende]){font-size:var(--st-taille-xs);color:var(--st-couleur-texte-discret)}:host([data-variante=mono]){font-family:var(--st-police-mono);font-size:var(--st-taille-sm)}:host([data-graisse=moyenne]){font-weight:var(--st-graisse-moyenne)}:host([data-graisse=semi]){font-weight:var(--st-graisse-semi)}:host([data-tronque]){display:-webkit-box;overflow:hidden;-webkit-box-orient:vertical;-webkit-line-clamp:var(--st-text-lignes, 2);line-clamp:var(--st-text-lignes, 2)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
273
537
  }
274
538
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StText, decorators: [{
275
539
  type: Component,
@@ -280,7 +544,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
280
544
  '[attr.data-en-ligne]': 'enLigne() ? "" : null',
281
545
  '[attr.data-tronque]': 'tronquerA() === null ? null : ""',
282
546
  '[style.--st-text-lignes]': 'tronquerA()',
283
- }, template: "<ng-content />\n", styles: [":host{display:block;margin:0;font-family:var(--st-police-base);font-size:var(--st-taille-md);font-weight:var(--st-graisse-normale);line-height:var(--st-interligne-normal);color:var(--st-couleur-texte);max-inline-size:70ch}:host([data-en-ligne]){display:inline;max-inline-size:none}:host([data-variante=corps-sm]){font-size:var(--st-taille-sm)}:host([data-variante=discret]){color:var(--st-couleur-texte-discret)}:host([data-variante=legende]){font-size:var(--st-taille-xs);color:var(--st-couleur-texte-discret)}:host([data-variante=mono]){font-family:var(--st-police-mono);font-size:var(--st-taille-sm)}:host([data-graisse=moyenne]){font-weight:var(--st-graisse-moyenne)}:host([data-graisse=semi]){font-weight:var(--st-graisse-semi)}:host([data-tronque]){display:-webkit-box;overflow:hidden;-webkit-box-orient:vertical;-webkit-line-clamp:var(--st-text-lignes, 2);line-clamp:var(--st-text-lignes, 2)}\n"] }]
547
+ }, template: "<ng-content />\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block;margin:0;font-family:var(--st-police-base);font-size:var(--st-taille-md);font-weight:var(--st-graisse-normale);line-height:var(--st-interligne-normal);color:var(--st-couleur-texte);max-inline-size:70ch}:host([data-en-ligne]){display:inline;max-inline-size:none}:host([data-variante=corps-sm]){font-size:var(--st-taille-sm)}:host([data-variante=discret]){color:var(--st-couleur-texte-discret)}:host([data-variante=legende]){font-size:var(--st-taille-xs);color:var(--st-couleur-texte-discret)}:host([data-variante=mono]){font-family:var(--st-police-mono);font-size:var(--st-taille-sm)}:host([data-graisse=moyenne]){font-weight:var(--st-graisse-moyenne)}:host([data-graisse=semi]){font-weight:var(--st-graisse-semi)}:host([data-tronque]){display:-webkit-box;overflow:hidden;-webkit-box-orient:vertical;-webkit-line-clamp:var(--st-text-lignes, 2);line-clamp:var(--st-text-lignes, 2)}\n"] }]
284
548
  }], propDecorators: { variante: [{ type: i0.Input, args: [{ isSignal: true, alias: "variante", required: false }] }], graisse: [{ type: i0.Input, args: [{ isSignal: true, alias: "graisse", required: false }] }], enLigne: [{ type: i0.Input, args: [{ isSignal: true, alias: "enLigne", required: false }] }], tronquerA: [{ type: i0.Input, args: [{ isSignal: true, alias: "tronquerA", required: false }] }] } });
285
549
 
286
550
  const TAILLE_PAR_NIVEAU = {
@@ -314,7 +578,7 @@ class StHeading {
314
578
  tailleEffective = computed(() => this.taille() ?? TAILLE_PAR_NIVEAU[this.niveau()], /* @ts-ignore */
315
579
  ...(ngDevMode ? [{ debugName: "tailleEffective" }] : /* istanbul ignore next */ []));
316
580
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StHeading, deps: [], target: i0.ɵɵFactoryTarget.Component });
317
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StHeading, isStandalone: true, selector: "st-heading", inputs: { niveau: { classPropertyName: "niveau", publicName: "niveau", isSignal: true, isRequired: true, transformFunction: null }, taille: { classPropertyName: "taille", publicName: "taille", isSignal: true, isRequired: false, transformFunction: null }, identifiant: { classPropertyName: "identifiant", publicName: "identifiant", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "heading" }, properties: { "attr.aria-level": "niveau()", "attr.id": "identifiant()", "attr.data-taille": "tailleEffective()" }, classAttribute: "st-heading" }, ngImport: i0, template: "<ng-content />\n", styles: [":host{display:block;margin:0 0 var(--st-espacement-3);font-family:var(--st-police-base);font-weight:var(--st-graisse-semi);line-height:var(--st-interligne-serre);color:var(--st-couleur-texte);text-wrap:balance}:host([data-taille=lg]){font-size:var(--st-taille-lg)}:host([data-taille=xl]){font-size:var(--st-taille-xl)}:host([data-taille=\"2xl\"]){font-size:var(--st-taille-2xl)}:host([data-taille=\"3xl\"]){font-size:var(--st-taille-3xl)}:host([data-taille=\"4xl\"]){font-size:var(--st-taille-4xl)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
581
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StHeading, isStandalone: true, selector: "st-heading", inputs: { niveau: { classPropertyName: "niveau", publicName: "niveau", isSignal: true, isRequired: true, transformFunction: null }, taille: { classPropertyName: "taille", publicName: "taille", isSignal: true, isRequired: false, transformFunction: null }, identifiant: { classPropertyName: "identifiant", publicName: "identifiant", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "heading" }, properties: { "attr.aria-level": "niveau()", "attr.id": "identifiant()", "attr.data-taille": "tailleEffective()" }, classAttribute: "st-heading" }, ngImport: i0, template: "<ng-content />\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block;margin:0 0 var(--st-espacement-3);font-family:var(--st-police-base);font-weight:var(--st-graisse-semi);line-height:var(--st-interligne-serre);color:var(--st-couleur-texte);text-wrap:balance}:host([data-taille=lg]){font-size:var(--st-taille-lg)}:host([data-taille=xl]){font-size:var(--st-taille-xl)}:host([data-taille=\"2xl\"]){font-size:var(--st-taille-2xl)}:host([data-taille=\"3xl\"]){font-size:var(--st-taille-3xl)}:host([data-taille=\"4xl\"]){font-size:var(--st-taille-4xl)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
318
582
  }
319
583
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StHeading, decorators: [{
320
584
  type: Component,
@@ -324,7 +588,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
324
588
  '[attr.aria-level]': 'niveau()',
325
589
  '[attr.id]': 'identifiant()',
326
590
  '[attr.data-taille]': 'tailleEffective()',
327
- }, template: "<ng-content />\n", styles: [":host{display:block;margin:0 0 var(--st-espacement-3);font-family:var(--st-police-base);font-weight:var(--st-graisse-semi);line-height:var(--st-interligne-serre);color:var(--st-couleur-texte);text-wrap:balance}:host([data-taille=lg]){font-size:var(--st-taille-lg)}:host([data-taille=xl]){font-size:var(--st-taille-xl)}:host([data-taille=\"2xl\"]){font-size:var(--st-taille-2xl)}:host([data-taille=\"3xl\"]){font-size:var(--st-taille-3xl)}:host([data-taille=\"4xl\"]){font-size:var(--st-taille-4xl)}\n"] }]
591
+ }, template: "<ng-content />\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block;margin:0 0 var(--st-espacement-3);font-family:var(--st-police-base);font-weight:var(--st-graisse-semi);line-height:var(--st-interligne-serre);color:var(--st-couleur-texte);text-wrap:balance}:host([data-taille=lg]){font-size:var(--st-taille-lg)}:host([data-taille=xl]){font-size:var(--st-taille-xl)}:host([data-taille=\"2xl\"]){font-size:var(--st-taille-2xl)}:host([data-taille=\"3xl\"]){font-size:var(--st-taille-3xl)}:host([data-taille=\"4xl\"]){font-size:var(--st-taille-4xl)}\n"] }]
328
592
  }], propDecorators: { niveau: [{ type: i0.Input, args: [{ isSignal: true, alias: "niveau", required: true }] }], taille: [{ type: i0.Input, args: [{ isSignal: true, alias: "taille", required: false }] }], identifiant: [{ type: i0.Input, args: [{ isSignal: true, alias: "identifiant", required: false }] }] } });
329
593
 
330
594
  /**
@@ -355,7 +619,7 @@ class StSpinner {
355
619
  sAnnonce = computed(() => this.regionParente === null, /* @ts-ignore */
356
620
  ...(ngDevMode ? [{ debugName: "sAnnonce" }] : /* istanbul ignore next */ []));
357
621
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StSpinner, deps: [], target: i0.ɵɵFactoryTarget.Component });
358
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StSpinner, isStandalone: true, selector: "st-spinner", inputs: { taille: { classPropertyName: "taille", publicName: "taille", isSignal: true, isRequired: false, transformFunction: null }, ton: { classPropertyName: "ton", publicName: "ton", isSignal: true, isRequired: false, transformFunction: null }, etiquette: { classPropertyName: "etiquette", publicName: "etiquette", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-taille": "taille()", "attr.data-ton": "ton()", "attr.role": "sAnnonce() ? \"status\" : null", "attr.aria-label": "sAnnonce() ? etiquetteLue() : null" }, classAttribute: "st-spinner" }, ngImport: i0, template: "<svg viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\">\n <circle class=\"st-spinner__piste\" cx=\"12\" cy=\"12\" r=\"10\" />\n <circle class=\"st-spinner__arc\" cx=\"12\" cy=\"12\" r=\"10\" />\n</svg>\n", styles: [":host{display:inline-flex;flex:none;color:var(--st-couleur-primaire)}svg{inline-size:var(--st-spinner-taille, 1.5rem);block-size:var(--st-spinner-taille, 1.5rem);fill:none;stroke-width:2.5;transform-origin:center;animation:st-spinner-rotation var(--st-anim-chargement, .9s) linear infinite}.st-spinner__piste{stroke:var(--st-couleur-bordure)}.st-spinner__arc{stroke:currentcolor;stroke-linecap:round;stroke-dasharray:16 47}@keyframes st-spinner-rotation{to{transform:rotate(1turn)}}@keyframes st-spinner-pulsation{0%,to{opacity:1}50%{opacity:.35}}@media(prefers-reduced-motion:reduce){svg{animation:st-spinner-pulsation 1.6s ease-in-out infinite}.st-spinner__arc{stroke-dasharray:none}}:host([data-taille=sm]) svg{--st-spinner-taille: 1rem}:host([data-taille=lg]) svg{--st-spinner-taille: 2.5rem}:host([data-ton=neutre]){color:currentcolor}:host([data-ton=inverse]){color:var(--st-couleur-sur-primaire)}:host([data-ton=inverse]) .st-spinner__piste{stroke:color-mix(in srgb,var(--st-couleur-sur-primaire) 30%,transparent)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
622
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StSpinner, isStandalone: true, selector: "st-spinner", inputs: { taille: { classPropertyName: "taille", publicName: "taille", isSignal: true, isRequired: false, transformFunction: null }, ton: { classPropertyName: "ton", publicName: "ton", isSignal: true, isRequired: false, transformFunction: null }, etiquette: { classPropertyName: "etiquette", publicName: "etiquette", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-taille": "taille()", "attr.data-ton": "ton()", "attr.role": "sAnnonce() ? \"status\" : null", "attr.aria-label": "sAnnonce() ? etiquetteLue() : null" }, classAttribute: "st-spinner" }, ngImport: i0, template: "<svg viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\">\n <circle class=\"st-spinner__piste\" cx=\"12\" cy=\"12\" r=\"10\" />\n <circle class=\"st-spinner__arc\" cx=\"12\" cy=\"12\" r=\"10\" />\n</svg>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:inline-flex;flex:none;color:var(--st-couleur-primaire)}svg{inline-size:var(--st-spinner-taille, 1.5rem);block-size:var(--st-spinner-taille, 1.5rem);fill:none;stroke-width:2.5;transform-origin:center;animation:st-spinner-rotation var(--st-anim-chargement, .9s) linear infinite}.st-spinner__piste{stroke:var(--st-couleur-bordure)}.st-spinner__arc{stroke:currentcolor;stroke-linecap:round;stroke-dasharray:16 47}@keyframes st-spinner-rotation{to{transform:rotate(1turn)}}@keyframes st-spinner-pulsation{0%,to{opacity:1}50%{opacity:.35}}@media(prefers-reduced-motion:reduce){svg{animation:st-spinner-pulsation 1.6s ease-in-out infinite}.st-spinner__arc{stroke-dasharray:none}}:host([data-taille=sm]) svg{--st-spinner-taille: 1rem}:host([data-taille=lg]) svg{--st-spinner-taille: 2.5rem}:host([data-ton=neutre]){color:currentcolor}:host([data-ton=inverse]){color:var(--st-couleur-sur-primaire)}:host([data-ton=inverse]) .st-spinner__piste{stroke:color-mix(in srgb,var(--st-couleur-sur-primaire) 30%,transparent)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
359
623
  }
360
624
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StSpinner, decorators: [{
361
625
  type: Component,
@@ -365,7 +629,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
365
629
  '[attr.data-ton]': 'ton()',
366
630
  '[attr.role]': 'sAnnonce() ? "status" : null',
367
631
  '[attr.aria-label]': 'sAnnonce() ? etiquetteLue() : null',
368
- }, template: "<svg viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\">\n <circle class=\"st-spinner__piste\" cx=\"12\" cy=\"12\" r=\"10\" />\n <circle class=\"st-spinner__arc\" cx=\"12\" cy=\"12\" r=\"10\" />\n</svg>\n", styles: [":host{display:inline-flex;flex:none;color:var(--st-couleur-primaire)}svg{inline-size:var(--st-spinner-taille, 1.5rem);block-size:var(--st-spinner-taille, 1.5rem);fill:none;stroke-width:2.5;transform-origin:center;animation:st-spinner-rotation var(--st-anim-chargement, .9s) linear infinite}.st-spinner__piste{stroke:var(--st-couleur-bordure)}.st-spinner__arc{stroke:currentcolor;stroke-linecap:round;stroke-dasharray:16 47}@keyframes st-spinner-rotation{to{transform:rotate(1turn)}}@keyframes st-spinner-pulsation{0%,to{opacity:1}50%{opacity:.35}}@media(prefers-reduced-motion:reduce){svg{animation:st-spinner-pulsation 1.6s ease-in-out infinite}.st-spinner__arc{stroke-dasharray:none}}:host([data-taille=sm]) svg{--st-spinner-taille: 1rem}:host([data-taille=lg]) svg{--st-spinner-taille: 2.5rem}:host([data-ton=neutre]){color:currentcolor}:host([data-ton=inverse]){color:var(--st-couleur-sur-primaire)}:host([data-ton=inverse]) .st-spinner__piste{stroke:color-mix(in srgb,var(--st-couleur-sur-primaire) 30%,transparent)}\n"] }]
632
+ }, template: "<svg viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\">\n <circle class=\"st-spinner__piste\" cx=\"12\" cy=\"12\" r=\"10\" />\n <circle class=\"st-spinner__arc\" cx=\"12\" cy=\"12\" r=\"10\" />\n</svg>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:inline-flex;flex:none;color:var(--st-couleur-primaire)}svg{inline-size:var(--st-spinner-taille, 1.5rem);block-size:var(--st-spinner-taille, 1.5rem);fill:none;stroke-width:2.5;transform-origin:center;animation:st-spinner-rotation var(--st-anim-chargement, .9s) linear infinite}.st-spinner__piste{stroke:var(--st-couleur-bordure)}.st-spinner__arc{stroke:currentcolor;stroke-linecap:round;stroke-dasharray:16 47}@keyframes st-spinner-rotation{to{transform:rotate(1turn)}}@keyframes st-spinner-pulsation{0%,to{opacity:1}50%{opacity:.35}}@media(prefers-reduced-motion:reduce){svg{animation:st-spinner-pulsation 1.6s ease-in-out infinite}.st-spinner__arc{stroke-dasharray:none}}:host([data-taille=sm]) svg{--st-spinner-taille: 1rem}:host([data-taille=lg]) svg{--st-spinner-taille: 2.5rem}:host([data-ton=neutre]){color:currentcolor}:host([data-ton=inverse]){color:var(--st-couleur-sur-primaire)}:host([data-ton=inverse]) .st-spinner__piste{stroke:color-mix(in srgb,var(--st-couleur-sur-primaire) 30%,transparent)}\n"] }]
369
633
  }], propDecorators: { taille: [{ type: i0.Input, args: [{ isSignal: true, alias: "taille", required: false }] }], ton: [{ type: i0.Input, args: [{ isSignal: true, alias: "ton", required: false }] }], etiquette: [{ type: i0.Input, args: [{ isSignal: true, alias: "etiquette", required: false }] }] } });
370
634
 
371
635
  /**
@@ -406,7 +670,7 @@ class StProgress {
406
670
  }, /* @ts-ignore */
407
671
  ...(ngDevMode ? [{ debugName: "pourcentage" }] : /* istanbul ignore next */ []));
408
672
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StProgress, deps: [], target: i0.ɵɵFactoryTarget.Component });
409
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StProgress, isStandalone: true, selector: "st-progress", inputs: { valeur: { classPropertyName: "valeur", publicName: "valeur", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, etiquette: { classPropertyName: "etiquette", publicName: "etiquette", isSignal: true, isRequired: true, transformFunction: null }, ton: { classPropertyName: "ton", publicName: "ton", isSignal: true, isRequired: false, transformFunction: null }, texteDeValeur: { classPropertyName: "texteDeValeur", publicName: "texteDeValeur", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "progressbar" }, properties: { "attr.data-ton": "ton()", "attr.data-indetermine": "estIndeterminee() ? \"\" : null", "attr.aria-label": "etiquette()", "attr.aria-valuemin": "0", "attr.aria-valuemax": "max()", "attr.aria-valuenow": "valeurAnnoncee()", "attr.aria-valuetext": "texteDeValeur()", "style.--st-progress-part.%": "pourcentage()" }, classAttribute: "st-progress" }, ngImport: i0, template: "<span class=\"st-progress__barre\"></span>\n", styles: [":host{display:block;block-size:.5rem;overflow:hidden;background:var(--st-couleur-surface-enfoncee);border-radius:var(--st-rayon-pleine)}.st-progress__barre{display:block;block-size:100%;inline-size:var(--st-progress-part, 0%);background:var(--st-couleur-primaire);border-radius:inherit;transition:inline-size var(--st-duree-normale) var(--st-courbe-standard)}:host([data-ton=succes]) .st-progress__barre{background:var(--st-couleur-succes)}:host([data-ton=danger]) .st-progress__barre{background:var(--st-couleur-danger)}:host([data-indetermine]) .st-progress__barre{inline-size:35%;animation:st-progress-va-et-vient var(--st-anim-chargement, 1.4s) ease-in-out infinite}@keyframes st-progress-va-et-vient{0%{transform:translate(-100%)}to{transform:translate(calc(100cqi + 100%))}}@keyframes st-progress-pulsation{0%,to{opacity:1}50%{opacity:.4}}@media(prefers-reduced-motion:reduce){:host([data-indetermine]) .st-progress__barre{inline-size:100%;transform:none;animation:st-progress-pulsation 1.6s ease-in-out infinite}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
673
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StProgress, isStandalone: true, selector: "st-progress", inputs: { valeur: { classPropertyName: "valeur", publicName: "valeur", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, etiquette: { classPropertyName: "etiquette", publicName: "etiquette", isSignal: true, isRequired: true, transformFunction: null }, ton: { classPropertyName: "ton", publicName: "ton", isSignal: true, isRequired: false, transformFunction: null }, texteDeValeur: { classPropertyName: "texteDeValeur", publicName: "texteDeValeur", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "progressbar" }, properties: { "attr.data-ton": "ton()", "attr.data-indetermine": "estIndeterminee() ? \"\" : null", "attr.aria-label": "etiquette()", "attr.aria-valuemin": "0", "attr.aria-valuemax": "max()", "attr.aria-valuenow": "valeurAnnoncee()", "attr.aria-valuetext": "texteDeValeur()", "style.--st-progress-part.%": "pourcentage()" }, classAttribute: "st-progress" }, ngImport: i0, template: "<span class=\"st-progress__barre\"></span>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block;block-size:.5rem;overflow:hidden;background:var(--st-couleur-surface-enfoncee);border-radius:var(--st-rayon-pleine)}.st-progress__barre{display:block;block-size:100%;inline-size:var(--st-progress-part, 0%);background:var(--st-couleur-primaire);border-radius:inherit;transition:inline-size var(--st-duree-normale) var(--st-courbe-standard)}:host([data-ton=succes]) .st-progress__barre{background:var(--st-couleur-succes)}:host([data-ton=danger]) .st-progress__barre{background:var(--st-couleur-danger)}:host([data-indetermine]) .st-progress__barre{inline-size:35%;animation:st-progress-va-et-vient var(--st-anim-chargement, 1.4s) ease-in-out infinite}@keyframes st-progress-va-et-vient{0%{transform:translate(-100%)}to{transform:translate(calc(100cqi + 100%))}}@keyframes st-progress-pulsation{0%,to{opacity:1}50%{opacity:.4}}@media(prefers-reduced-motion:reduce){:host([data-indetermine]) .st-progress__barre{inline-size:100%;transform:none;animation:st-progress-pulsation 1.6s ease-in-out infinite}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
410
674
  }
411
675
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StProgress, decorators: [{
412
676
  type: Component,
@@ -421,7 +685,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
421
685
  '[attr.aria-valuenow]': 'valeurAnnoncee()',
422
686
  '[attr.aria-valuetext]': 'texteDeValeur()',
423
687
  '[style.--st-progress-part.%]': 'pourcentage()',
424
- }, template: "<span class=\"st-progress__barre\"></span>\n", styles: [":host{display:block;block-size:.5rem;overflow:hidden;background:var(--st-couleur-surface-enfoncee);border-radius:var(--st-rayon-pleine)}.st-progress__barre{display:block;block-size:100%;inline-size:var(--st-progress-part, 0%);background:var(--st-couleur-primaire);border-radius:inherit;transition:inline-size var(--st-duree-normale) var(--st-courbe-standard)}:host([data-ton=succes]) .st-progress__barre{background:var(--st-couleur-succes)}:host([data-ton=danger]) .st-progress__barre{background:var(--st-couleur-danger)}:host([data-indetermine]) .st-progress__barre{inline-size:35%;animation:st-progress-va-et-vient var(--st-anim-chargement, 1.4s) ease-in-out infinite}@keyframes st-progress-va-et-vient{0%{transform:translate(-100%)}to{transform:translate(calc(100cqi + 100%))}}@keyframes st-progress-pulsation{0%,to{opacity:1}50%{opacity:.4}}@media(prefers-reduced-motion:reduce){:host([data-indetermine]) .st-progress__barre{inline-size:100%;transform:none;animation:st-progress-pulsation 1.6s ease-in-out infinite}}\n"] }]
688
+ }, template: "<span class=\"st-progress__barre\"></span>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block;block-size:.5rem;overflow:hidden;background:var(--st-couleur-surface-enfoncee);border-radius:var(--st-rayon-pleine)}.st-progress__barre{display:block;block-size:100%;inline-size:var(--st-progress-part, 0%);background:var(--st-couleur-primaire);border-radius:inherit;transition:inline-size var(--st-duree-normale) var(--st-courbe-standard)}:host([data-ton=succes]) .st-progress__barre{background:var(--st-couleur-succes)}:host([data-ton=danger]) .st-progress__barre{background:var(--st-couleur-danger)}:host([data-indetermine]) .st-progress__barre{inline-size:35%;animation:st-progress-va-et-vient var(--st-anim-chargement, 1.4s) ease-in-out infinite}@keyframes st-progress-va-et-vient{0%{transform:translate(-100%)}to{transform:translate(calc(100cqi + 100%))}}@keyframes st-progress-pulsation{0%,to{opacity:1}50%{opacity:.4}}@media(prefers-reduced-motion:reduce){:host([data-indetermine]) .st-progress__barre{inline-size:100%;transform:none;animation:st-progress-pulsation 1.6s ease-in-out infinite}}\n"] }]
425
689
  }], propDecorators: { valeur: [{ type: i0.Input, args: [{ isSignal: true, alias: "valeur", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], etiquette: [{ type: i0.Input, args: [{ isSignal: true, alias: "etiquette", required: true }] }], ton: [{ type: i0.Input, args: [{ isSignal: true, alias: "ton", required: false }] }], texteDeValeur: [{ type: i0.Input, args: [{ isSignal: true, alias: "texteDeValeur", required: false }] }] } });
426
690
 
427
691
  /**
@@ -447,7 +711,7 @@ class StSkeleton {
447
711
  indicesDeColonne = computed(() => Array.from({ length: Math.max(1, this.colonnes()) }, (_, index) => index), /* @ts-ignore */
448
712
  ...(ngDevMode ? [{ debugName: "indicesDeColonne" }] : /* istanbul ignore next */ []));
449
713
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StSkeleton, deps: [], target: i0.ɵɵFactoryTarget.Component });
450
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StSkeleton, isStandalone: true, selector: "st-skeleton", inputs: { variante: { classPropertyName: "variante", publicName: "variante", isSignal: true, isRequired: false, transformFunction: null }, lignes: { classPropertyName: "lignes", publicName: "lignes", isSignal: true, isRequired: false, transformFunction: null }, colonnes: { classPropertyName: "colonnes", publicName: "colonnes", isSignal: true, isRequired: false, transformFunction: null }, anime: { classPropertyName: "anime", publicName: "anime", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "aria-hidden": "true" }, properties: { "attr.data-variante": "variante()", "attr.data-anime": "anime() ? \"\" : null" }, classAttribute: "st-skeleton" }, ngImport: i0, template: "@switch (variante()) {\n @case ('tableau') {\n @for (ligne of indicesDeLigne(); track ligne) {\n <div class=\"st-skeleton__rangee\">\n @for (colonne of indicesDeColonne(); track colonne) {\n <span class=\"st-skeleton__cellule\"></span>\n }\n </div>\n }\n }\n @case ('carte') {\n <span class=\"st-skeleton__media\"></span>\n @for (ligne of indicesDeLigne(); track ligne) {\n <span class=\"st-skeleton__ligne\"></span>\n }\n }\n @default {\n @for (ligne of indicesDeLigne(); track ligne) {\n <span class=\"st-skeleton__ligne\"></span>\n }\n }\n}\n", styles: [":host{display:flex;flex-direction:column;gap:var(--st-espacement-2)}.st-skeleton__media,.st-skeleton__cellule,.st-skeleton__ligne{display:block;background:var(--st-couleur-surface-enfoncee);border-radius:var(--st-rayon-sm)}.st-skeleton__ligne{block-size:calc(1em * var(--st-interligne-normal))}.st-skeleton__ligne:last-child{inline-size:60%}.st-skeleton__rangee{display:flex;gap:var(--st-espacement-3)}.st-skeleton__cellule{flex:1;block-size:calc(1em * var(--st-interligne-normal))}.st-skeleton__media{block-size:8rem;border-radius:var(--st-rayon-md)}:host([data-anime]) .st-skeleton__ligne,:host([data-anime]) .st-skeleton__cellule,:host([data-anime]) .st-skeleton__media{background:linear-gradient(90deg,var(--st-couleur-surface-enfoncee) 25%,var(--st-couleur-surface-survol) 50%,var(--st-couleur-surface-enfoncee) 75%);background-size:200% 100%;animation:st-skeleton-miroitement var(--st-anim-chargement, 1.4s) linear infinite}@keyframes st-skeleton-miroitement{to{background-position:-200% 0}}@keyframes st-skeleton-pulsation{0%,to{opacity:1}50%{opacity:.5}}@media(prefers-reduced-motion:reduce){:host([data-anime]) .st-skeleton__ligne,:host([data-anime]) .st-skeleton__cellule,:host([data-anime]) .st-skeleton__media{background:var(--st-couleur-surface-enfoncee);animation:st-skeleton-pulsation 1.8s ease-in-out infinite}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
714
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StSkeleton, isStandalone: true, selector: "st-skeleton", inputs: { variante: { classPropertyName: "variante", publicName: "variante", isSignal: true, isRequired: false, transformFunction: null }, lignes: { classPropertyName: "lignes", publicName: "lignes", isSignal: true, isRequired: false, transformFunction: null }, colonnes: { classPropertyName: "colonnes", publicName: "colonnes", isSignal: true, isRequired: false, transformFunction: null }, anime: { classPropertyName: "anime", publicName: "anime", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "aria-hidden": "true" }, properties: { "attr.data-variante": "variante()", "attr.data-anime": "anime() ? \"\" : null" }, classAttribute: "st-skeleton" }, ngImport: i0, template: "@switch (variante()) {\n @case ('tableau') {\n @for (ligne of indicesDeLigne(); track ligne) {\n <div class=\"st-skeleton__rangee\">\n @for (colonne of indicesDeColonne(); track colonne) {\n <span class=\"st-skeleton__cellule\"></span>\n }\n </div>\n }\n }\n @case ('carte') {\n <span class=\"st-skeleton__media\"></span>\n @for (ligne of indicesDeLigne(); track ligne) {\n <span class=\"st-skeleton__ligne\"></span>\n }\n }\n @default {\n @for (ligne of indicesDeLigne(); track ligne) {\n <span class=\"st-skeleton__ligne\"></span>\n }\n }\n}\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:flex;flex-direction:column;gap:var(--st-espacement-2)}.st-skeleton__media,.st-skeleton__cellule,.st-skeleton__ligne{display:block;background:var(--st-couleur-surface-enfoncee);border-radius:var(--st-rayon-sm)}.st-skeleton__ligne{block-size:calc(1em * var(--st-interligne-normal))}.st-skeleton__ligne:last-child{inline-size:60%}.st-skeleton__rangee{display:flex;gap:var(--st-espacement-3)}.st-skeleton__cellule{flex:1;block-size:calc(1em * var(--st-interligne-normal))}.st-skeleton__media{block-size:8rem;border-radius:var(--st-rayon-md)}:host([data-anime]) .st-skeleton__ligne,:host([data-anime]) .st-skeleton__cellule,:host([data-anime]) .st-skeleton__media{background:linear-gradient(90deg,var(--st-couleur-surface-enfoncee) 25%,var(--st-couleur-surface-survol) 50%,var(--st-couleur-surface-enfoncee) 75%);background-size:200% 100%;animation:st-skeleton-miroitement var(--st-anim-chargement, 1.4s) linear infinite}@keyframes st-skeleton-miroitement{to{background-position:-200% 0}}@keyframes st-skeleton-pulsation{0%,to{opacity:1}50%{opacity:.5}}@media(prefers-reduced-motion:reduce){:host([data-anime]) .st-skeleton__ligne,:host([data-anime]) .st-skeleton__cellule,:host([data-anime]) .st-skeleton__media{background:var(--st-couleur-surface-enfoncee);animation:st-skeleton-pulsation 1.8s ease-in-out infinite}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
451
715
  }
452
716
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StSkeleton, decorators: [{
453
717
  type: Component,
@@ -456,7 +720,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
456
720
  'aria-hidden': 'true',
457
721
  '[attr.data-variante]': 'variante()',
458
722
  '[attr.data-anime]': 'anime() ? "" : null',
459
- }, template: "@switch (variante()) {\n @case ('tableau') {\n @for (ligne of indicesDeLigne(); track ligne) {\n <div class=\"st-skeleton__rangee\">\n @for (colonne of indicesDeColonne(); track colonne) {\n <span class=\"st-skeleton__cellule\"></span>\n }\n </div>\n }\n }\n @case ('carte') {\n <span class=\"st-skeleton__media\"></span>\n @for (ligne of indicesDeLigne(); track ligne) {\n <span class=\"st-skeleton__ligne\"></span>\n }\n }\n @default {\n @for (ligne of indicesDeLigne(); track ligne) {\n <span class=\"st-skeleton__ligne\"></span>\n }\n }\n}\n", styles: [":host{display:flex;flex-direction:column;gap:var(--st-espacement-2)}.st-skeleton__media,.st-skeleton__cellule,.st-skeleton__ligne{display:block;background:var(--st-couleur-surface-enfoncee);border-radius:var(--st-rayon-sm)}.st-skeleton__ligne{block-size:calc(1em * var(--st-interligne-normal))}.st-skeleton__ligne:last-child{inline-size:60%}.st-skeleton__rangee{display:flex;gap:var(--st-espacement-3)}.st-skeleton__cellule{flex:1;block-size:calc(1em * var(--st-interligne-normal))}.st-skeleton__media{block-size:8rem;border-radius:var(--st-rayon-md)}:host([data-anime]) .st-skeleton__ligne,:host([data-anime]) .st-skeleton__cellule,:host([data-anime]) .st-skeleton__media{background:linear-gradient(90deg,var(--st-couleur-surface-enfoncee) 25%,var(--st-couleur-surface-survol) 50%,var(--st-couleur-surface-enfoncee) 75%);background-size:200% 100%;animation:st-skeleton-miroitement var(--st-anim-chargement, 1.4s) linear infinite}@keyframes st-skeleton-miroitement{to{background-position:-200% 0}}@keyframes st-skeleton-pulsation{0%,to{opacity:1}50%{opacity:.5}}@media(prefers-reduced-motion:reduce){:host([data-anime]) .st-skeleton__ligne,:host([data-anime]) .st-skeleton__cellule,:host([data-anime]) .st-skeleton__media{background:var(--st-couleur-surface-enfoncee);animation:st-skeleton-pulsation 1.8s ease-in-out infinite}}\n"] }]
723
+ }, template: "@switch (variante()) {\n @case ('tableau') {\n @for (ligne of indicesDeLigne(); track ligne) {\n <div class=\"st-skeleton__rangee\">\n @for (colonne of indicesDeColonne(); track colonne) {\n <span class=\"st-skeleton__cellule\"></span>\n }\n </div>\n }\n }\n @case ('carte') {\n <span class=\"st-skeleton__media\"></span>\n @for (ligne of indicesDeLigne(); track ligne) {\n <span class=\"st-skeleton__ligne\"></span>\n }\n }\n @default {\n @for (ligne of indicesDeLigne(); track ligne) {\n <span class=\"st-skeleton__ligne\"></span>\n }\n }\n}\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:flex;flex-direction:column;gap:var(--st-espacement-2)}.st-skeleton__media,.st-skeleton__cellule,.st-skeleton__ligne{display:block;background:var(--st-couleur-surface-enfoncee);border-radius:var(--st-rayon-sm)}.st-skeleton__ligne{block-size:calc(1em * var(--st-interligne-normal))}.st-skeleton__ligne:last-child{inline-size:60%}.st-skeleton__rangee{display:flex;gap:var(--st-espacement-3)}.st-skeleton__cellule{flex:1;block-size:calc(1em * var(--st-interligne-normal))}.st-skeleton__media{block-size:8rem;border-radius:var(--st-rayon-md)}:host([data-anime]) .st-skeleton__ligne,:host([data-anime]) .st-skeleton__cellule,:host([data-anime]) .st-skeleton__media{background:linear-gradient(90deg,var(--st-couleur-surface-enfoncee) 25%,var(--st-couleur-surface-survol) 50%,var(--st-couleur-surface-enfoncee) 75%);background-size:200% 100%;animation:st-skeleton-miroitement var(--st-anim-chargement, 1.4s) linear infinite}@keyframes st-skeleton-miroitement{to{background-position:-200% 0}}@keyframes st-skeleton-pulsation{0%,to{opacity:1}50%{opacity:.5}}@media(prefers-reduced-motion:reduce){:host([data-anime]) .st-skeleton__ligne,:host([data-anime]) .st-skeleton__cellule,:host([data-anime]) .st-skeleton__media{background:var(--st-couleur-surface-enfoncee);animation:st-skeleton-pulsation 1.8s ease-in-out infinite}}\n"] }]
460
724
  }], propDecorators: { variante: [{ type: i0.Input, args: [{ isSignal: true, alias: "variante", required: false }] }], lignes: [{ type: i0.Input, args: [{ isSignal: true, alias: "lignes", required: false }] }], colonnes: [{ type: i0.Input, args: [{ isSignal: true, alias: "colonnes", required: false }] }], anime: [{ type: i0.Input, args: [{ isSignal: true, alias: "anime", required: false }] }] } });
461
725
 
462
726
  /**
@@ -494,6 +758,17 @@ class StButton {
494
758
  * soumission, pas a l'arrivee de la reponse.
495
759
  */
496
760
  chargement = input(false, { ...(ngDevMode ? { debugName: "chargement" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
761
+ /**
762
+ * L'action existe mais n'est pas disponible : une condition n'est pas encore
763
+ * remplie.
764
+ *
765
+ * ⚠️ `aria-disabled` et NON l'attribut natif `disabled`, qui retire le bouton
766
+ * de l'ordre de tabulation. Une personne au clavier ne l'atteindrait plus, et
767
+ * ne decouvrirait donc jamais la condition qui le bloque — le bouton aurait
768
+ * simplement disparu de son parcours. Ici il reste atteignable, annonce comme
769
+ * indisponible, et ses clics sont avales.
770
+ */
771
+ indisponible = input(false, { ...(ngDevMode ? { debugName: "indisponible" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
497
772
  /**
498
773
  * Le ton suit le FOND du bouton, et non le bouton en general : sur une
499
774
  * variante posee sur la surface (`secondaire`, qui est le defaut, et
@@ -504,7 +779,7 @@ class StButton {
504
779
  constructor() {
505
780
  const element = inject(ElementRef).nativeElement;
506
781
  const garde = (evenement) => {
507
- if (!this.chargement())
782
+ if (!this.chargement() && !this.indisponible())
508
783
  return;
509
784
  evenement.preventDefault();
510
785
  // `stopImmediatePropagation` et non `stopPropagation` : il faut barrer
@@ -523,7 +798,7 @@ class StButton {
523
798
  });
524
799
  }
525
800
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StButton, deps: [], target: i0.ɵɵFactoryTarget.Component });
526
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StButton, isStandalone: true, selector: "button[stButton]", inputs: { variante: { classPropertyName: "variante", publicName: "variante", isSignal: true, isRequired: false, transformFunction: null }, taille: { classPropertyName: "taille", publicName: "taille", isSignal: true, isRequired: false, transformFunction: null }, pleineLargeur: { classPropertyName: "pleineLargeur", publicName: "pleineLargeur", isSignal: true, isRequired: false, transformFunction: null }, iconeAvant: { classPropertyName: "iconeAvant", publicName: "iconeAvant", isSignal: true, isRequired: false, transformFunction: null }, iconeApres: { classPropertyName: "iconeApres", publicName: "iconeApres", isSignal: true, isRequired: false, transformFunction: null }, chargement: { classPropertyName: "chargement", publicName: "chargement", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-variante": "variante()", "attr.data-taille": "taille()", "attr.data-pleine-largeur": "pleineLargeur() ? \"\" : null", "attr.aria-disabled": "chargement() ? \"true\" : null", "attr.aria-busy": "chargement() ? \"true\" : null" }, classAttribute: "st-button" }, ngImport: i0, template: "@if (iconeAvant(); as icone) {\n <st-icon [nom]=\"icone\" taille=\"sm\" />\n}\n\n<span class=\"st-button__libelle\"><ng-content /></span>\n\n@if (iconeApres(); as icone) {\n <st-icon [nom]=\"icone\" taille=\"sm\" />\n}\n\n@if (chargement()) {\n <st-spinner\n class=\"st-button__chargement\"\n taille=\"sm\"\n [ton]=\"tonDuChargement()\"\n aria-hidden=\"true\"\n />\n}\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host{position:relative;display:inline-flex;gap:var(--st-espacement-2);align-items:center;justify-content:center;min-block-size:var(--st-cible-tactile-min);padding-block:var(--st-espacement-2);padding-inline:var(--st-espacement-4);font-family:var(--st-police-base);font-size:var(--st-taille-md);font-weight:var(--st-graisse-moyenne);line-height:var(--st-interligne-serre);color:var(--st-couleur-texte);cursor:pointer;background:var(--st-couleur-surface);border:1px solid var(--st-couleur-bordure-forte);border-radius:var(--st-rayon-md);transition:background-color var(--st-duree-rapide) var(--st-courbe-standard),border-color var(--st-duree-rapide) var(--st-courbe-standard)}:host:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}:host:hover:not([aria-disabled=true],:disabled){background:var(--st-couleur-surface-survol)}:host:disabled{color:var(--st-couleur-texte-desactive);cursor:not-allowed;border-color:var(--st-couleur-bordure)}:host[aria-disabled=true]{cursor:progress}.st-button__libelle{white-space:normal}:host([aria-busy=true])>:not(.st-button__chargement){opacity:0}.st-button__chargement{position:absolute;inset:0;margin:auto}:host([data-variante=primaire]){color:var(--st-couleur-sur-primaire);background:var(--st-couleur-primaire);border-color:transparent}:host([data-variante=primaire]):focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px;box-shadow:0 0 0 2px var(--st-couleur-surface)}:host([data-variante=primaire]):hover:not([aria-disabled=true],:disabled){background:var(--st-couleur-primaire-survol)}:host([data-variante=danger]){color:var(--st-couleur-sur-danger);background:var(--st-couleur-danger);border-color:transparent}:host([data-variante=danger]):focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px;box-shadow:0 0 0 2px var(--st-couleur-surface)}:host([data-variante=danger]):hover:not([aria-disabled=true],:disabled){background:var(--st-couleur-danger-survol)}:host([data-variante=discret]){color:var(--st-couleur-primaire);background:transparent;border-color:transparent}:host([data-variante=discret]):hover:not([aria-disabled=true],:disabled){background:var(--st-couleur-surface-survol)}:host([data-taille=sm]){min-block-size:2.25rem;padding-inline:var(--st-espacement-3);font-size:var(--st-taille-sm)}@media(pointer:coarse){:host([data-taille=sm]){min-block-size:var(--st-cible-tactile-min)}}:host([data-taille=lg]){min-block-size:3.25rem;padding-inline:var(--st-espacement-6);font-size:var(--st-taille-lg)}:host([data-pleine-largeur]){display:flex;inline-size:100%}\n"], dependencies: [{ kind: "component", type: StIcon, selector: "st-icon", inputs: ["nom", "taille", "ton", "etiquette"] }, { kind: "component", type: StSpinner, selector: "st-spinner", inputs: ["taille", "ton", "etiquette"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
801
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StButton, isStandalone: true, selector: "button[stButton]", inputs: { variante: { classPropertyName: "variante", publicName: "variante", isSignal: true, isRequired: false, transformFunction: null }, taille: { classPropertyName: "taille", publicName: "taille", isSignal: true, isRequired: false, transformFunction: null }, pleineLargeur: { classPropertyName: "pleineLargeur", publicName: "pleineLargeur", isSignal: true, isRequired: false, transformFunction: null }, iconeAvant: { classPropertyName: "iconeAvant", publicName: "iconeAvant", isSignal: true, isRequired: false, transformFunction: null }, iconeApres: { classPropertyName: "iconeApres", publicName: "iconeApres", isSignal: true, isRequired: false, transformFunction: null }, chargement: { classPropertyName: "chargement", publicName: "chargement", isSignal: true, isRequired: false, transformFunction: null }, indisponible: { classPropertyName: "indisponible", publicName: "indisponible", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-variante": "variante()", "attr.data-taille": "taille()", "attr.data-pleine-largeur": "pleineLargeur() ? \"\" : null", "attr.aria-disabled": "chargement() || indisponible() ? \"true\" : null", "attr.aria-busy": "chargement() ? \"true\" : null" }, classAttribute: "st-button" }, ngImport: i0, template: "@if (iconeAvant(); as icone) {\n <st-icon [nom]=\"icone\" taille=\"sm\" />\n}\n\n<span class=\"st-button__libelle\"><ng-content /></span>\n\n@if (iconeApres(); as icone) {\n <st-icon [nom]=\"icone\" taille=\"sm\" />\n}\n\n@if (chargement()) {\n <st-spinner\n class=\"st-button__chargement\"\n taille=\"sm\"\n [ton]=\"tonDuChargement()\"\n aria-hidden=\"true\"\n />\n}\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{position:relative;display:inline-flex;gap:var(--st-espacement-2);align-items:center;justify-content:center;min-block-size:var(--st-cible-tactile-min);padding-block:var(--st-espacement-2);padding-inline:var(--st-espacement-4);font-family:var(--st-police-base);font-size:var(--st-taille-md);font-weight:var(--st-graisse-moyenne);line-height:var(--st-interligne-serre);color:var(--st-couleur-texte);cursor:pointer;background:var(--st-couleur-surface);border:1px solid var(--st-couleur-bordure-forte);border-radius:var(--st-rayon-md);transition:background-color var(--st-duree-rapide) var(--st-courbe-standard),border-color var(--st-duree-rapide) var(--st-courbe-standard)}:host:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}:host:hover:not([aria-disabled=true],:disabled){background:var(--st-couleur-surface-survol)}:host:disabled{color:var(--st-couleur-texte-desactive);cursor:not-allowed;border-color:var(--st-couleur-bordure)}:host[aria-disabled=true]{cursor:progress}.st-button__libelle{white-space:normal}:host([aria-busy=true])>:not(.st-button__chargement){opacity:0}.st-button__chargement{position:absolute;inset:0;margin:auto}:host([data-variante=primaire]){color:var(--st-couleur-sur-primaire);background:var(--st-couleur-primaire);border-color:transparent}:host([data-variante=primaire]):focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px;box-shadow:0 0 0 2px var(--st-couleur-surface)}:host([data-variante=primaire]):hover:not([aria-disabled=true],:disabled){background:var(--st-couleur-primaire-survol)}:host([data-variante=danger]){color:var(--st-couleur-sur-danger);background:var(--st-couleur-danger);border-color:transparent}:host([data-variante=danger]):focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px;box-shadow:0 0 0 2px var(--st-couleur-surface)}:host([data-variante=danger]):hover:not([aria-disabled=true],:disabled){background:var(--st-couleur-danger-survol)}:host([data-variante=discret]){color:var(--st-couleur-primaire);background:transparent;border-color:transparent}:host([data-variante=discret]):hover:not([aria-disabled=true],:disabled){background:var(--st-couleur-surface-survol)}:host([data-taille=sm]){min-block-size:2.25rem;padding-inline:var(--st-espacement-3);font-size:var(--st-taille-sm)}@media(pointer:coarse){:host([data-taille=sm]){min-block-size:var(--st-cible-tactile-min)}}:host([data-taille=lg]){min-block-size:3.25rem;padding-inline:var(--st-espacement-6);font-size:var(--st-taille-lg)}:host([data-pleine-largeur]){display:flex;inline-size:100%}\n"], dependencies: [{ kind: "component", type: StIcon, selector: "st-icon", inputs: ["nom", "taille", "ton", "etiquette"] }, { kind: "component", type: StSpinner, selector: "st-spinner", inputs: ["taille", "ton", "etiquette"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
527
802
  }
528
803
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StButton, decorators: [{
529
804
  type: Component,
@@ -532,10 +807,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
532
807
  '[attr.data-variante]': 'variante()',
533
808
  '[attr.data-taille]': 'taille()',
534
809
  '[attr.data-pleine-largeur]': 'pleineLargeur() ? "" : null',
535
- '[attr.aria-disabled]': 'chargement() ? "true" : null',
810
+ '[attr.aria-disabled]': 'chargement() || indisponible() ? "true" : null',
536
811
  '[attr.aria-busy]': 'chargement() ? "true" : null',
537
- }, template: "@if (iconeAvant(); as icone) {\n <st-icon [nom]=\"icone\" taille=\"sm\" />\n}\n\n<span class=\"st-button__libelle\"><ng-content /></span>\n\n@if (iconeApres(); as icone) {\n <st-icon [nom]=\"icone\" taille=\"sm\" />\n}\n\n@if (chargement()) {\n <st-spinner\n class=\"st-button__chargement\"\n taille=\"sm\"\n [ton]=\"tonDuChargement()\"\n aria-hidden=\"true\"\n />\n}\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host{position:relative;display:inline-flex;gap:var(--st-espacement-2);align-items:center;justify-content:center;min-block-size:var(--st-cible-tactile-min);padding-block:var(--st-espacement-2);padding-inline:var(--st-espacement-4);font-family:var(--st-police-base);font-size:var(--st-taille-md);font-weight:var(--st-graisse-moyenne);line-height:var(--st-interligne-serre);color:var(--st-couleur-texte);cursor:pointer;background:var(--st-couleur-surface);border:1px solid var(--st-couleur-bordure-forte);border-radius:var(--st-rayon-md);transition:background-color var(--st-duree-rapide) var(--st-courbe-standard),border-color var(--st-duree-rapide) var(--st-courbe-standard)}:host:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}:host:hover:not([aria-disabled=true],:disabled){background:var(--st-couleur-surface-survol)}:host:disabled{color:var(--st-couleur-texte-desactive);cursor:not-allowed;border-color:var(--st-couleur-bordure)}:host[aria-disabled=true]{cursor:progress}.st-button__libelle{white-space:normal}:host([aria-busy=true])>:not(.st-button__chargement){opacity:0}.st-button__chargement{position:absolute;inset:0;margin:auto}:host([data-variante=primaire]){color:var(--st-couleur-sur-primaire);background:var(--st-couleur-primaire);border-color:transparent}:host([data-variante=primaire]):focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px;box-shadow:0 0 0 2px var(--st-couleur-surface)}:host([data-variante=primaire]):hover:not([aria-disabled=true],:disabled){background:var(--st-couleur-primaire-survol)}:host([data-variante=danger]){color:var(--st-couleur-sur-danger);background:var(--st-couleur-danger);border-color:transparent}:host([data-variante=danger]):focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px;box-shadow:0 0 0 2px var(--st-couleur-surface)}:host([data-variante=danger]):hover:not([aria-disabled=true],:disabled){background:var(--st-couleur-danger-survol)}:host([data-variante=discret]){color:var(--st-couleur-primaire);background:transparent;border-color:transparent}:host([data-variante=discret]):hover:not([aria-disabled=true],:disabled){background:var(--st-couleur-surface-survol)}:host([data-taille=sm]){min-block-size:2.25rem;padding-inline:var(--st-espacement-3);font-size:var(--st-taille-sm)}@media(pointer:coarse){:host([data-taille=sm]){min-block-size:var(--st-cible-tactile-min)}}:host([data-taille=lg]){min-block-size:3.25rem;padding-inline:var(--st-espacement-6);font-size:var(--st-taille-lg)}:host([data-pleine-largeur]){display:flex;inline-size:100%}\n"] }]
538
- }], ctorParameters: () => [], propDecorators: { variante: [{ type: i0.Input, args: [{ isSignal: true, alias: "variante", required: false }] }], taille: [{ type: i0.Input, args: [{ isSignal: true, alias: "taille", required: false }] }], pleineLargeur: [{ type: i0.Input, args: [{ isSignal: true, alias: "pleineLargeur", required: false }] }], iconeAvant: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconeAvant", required: false }] }], iconeApres: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconeApres", required: false }] }], chargement: [{ type: i0.Input, args: [{ isSignal: true, alias: "chargement", required: false }] }] } });
812
+ }, template: "@if (iconeAvant(); as icone) {\n <st-icon [nom]=\"icone\" taille=\"sm\" />\n}\n\n<span class=\"st-button__libelle\"><ng-content /></span>\n\n@if (iconeApres(); as icone) {\n <st-icon [nom]=\"icone\" taille=\"sm\" />\n}\n\n@if (chargement()) {\n <st-spinner\n class=\"st-button__chargement\"\n taille=\"sm\"\n [ton]=\"tonDuChargement()\"\n aria-hidden=\"true\"\n />\n}\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{position:relative;display:inline-flex;gap:var(--st-espacement-2);align-items:center;justify-content:center;min-block-size:var(--st-cible-tactile-min);padding-block:var(--st-espacement-2);padding-inline:var(--st-espacement-4);font-family:var(--st-police-base);font-size:var(--st-taille-md);font-weight:var(--st-graisse-moyenne);line-height:var(--st-interligne-serre);color:var(--st-couleur-texte);cursor:pointer;background:var(--st-couleur-surface);border:1px solid var(--st-couleur-bordure-forte);border-radius:var(--st-rayon-md);transition:background-color var(--st-duree-rapide) var(--st-courbe-standard),border-color var(--st-duree-rapide) var(--st-courbe-standard)}:host:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}:host:hover:not([aria-disabled=true],:disabled){background:var(--st-couleur-surface-survol)}:host:disabled{color:var(--st-couleur-texte-desactive);cursor:not-allowed;border-color:var(--st-couleur-bordure)}:host[aria-disabled=true]{cursor:progress}.st-button__libelle{white-space:normal}:host([aria-busy=true])>:not(.st-button__chargement){opacity:0}.st-button__chargement{position:absolute;inset:0;margin:auto}:host([data-variante=primaire]){color:var(--st-couleur-sur-primaire);background:var(--st-couleur-primaire);border-color:transparent}:host([data-variante=primaire]):focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px;box-shadow:0 0 0 2px var(--st-couleur-surface)}:host([data-variante=primaire]):hover:not([aria-disabled=true],:disabled){background:var(--st-couleur-primaire-survol)}:host([data-variante=danger]){color:var(--st-couleur-sur-danger);background:var(--st-couleur-danger);border-color:transparent}:host([data-variante=danger]):focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px;box-shadow:0 0 0 2px var(--st-couleur-surface)}:host([data-variante=danger]):hover:not([aria-disabled=true],:disabled){background:var(--st-couleur-danger-survol)}:host([data-variante=discret]){color:var(--st-couleur-primaire);background:transparent;border-color:transparent}:host([data-variante=discret]):hover:not([aria-disabled=true],:disabled){background:var(--st-couleur-surface-survol)}:host([data-taille=sm]){min-block-size:2.25rem;padding-inline:var(--st-espacement-3);font-size:var(--st-taille-sm)}@media(pointer:coarse){:host([data-taille=sm]){min-block-size:var(--st-cible-tactile-min)}}:host([data-taille=lg]){min-block-size:3.25rem;padding-inline:var(--st-espacement-6);font-size:var(--st-taille-lg)}:host([data-pleine-largeur]){display:flex;inline-size:100%}\n"] }]
813
+ }], ctorParameters: () => [], propDecorators: { variante: [{ type: i0.Input, args: [{ isSignal: true, alias: "variante", required: false }] }], taille: [{ type: i0.Input, args: [{ isSignal: true, alias: "taille", required: false }] }], pleineLargeur: [{ type: i0.Input, args: [{ isSignal: true, alias: "pleineLargeur", required: false }] }], iconeAvant: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconeAvant", required: false }] }], iconeApres: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconeApres", required: false }] }], chargement: [{ type: i0.Input, args: [{ isSignal: true, alias: "chargement", required: false }] }], indisponible: [{ type: i0.Input, args: [{ isSignal: true, alias: "indisponible", required: false }] }] } });
539
814
 
540
815
  /**
541
816
  * Bouton reduit a une icone, pose en attribut sur un `<button>` natif.
@@ -565,7 +840,7 @@ class StIconButton {
565
840
  enfonce = input(null, /* @ts-ignore */
566
841
  ...(ngDevMode ? [{ debugName: "enfonce" }] : /* istanbul ignore next */ []));
567
842
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StIconButton, deps: [], target: i0.ɵɵFactoryTarget.Component });
568
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StIconButton, isStandalone: true, selector: "button[stIconButton]", inputs: { icone: { classPropertyName: "icone", publicName: "icone", isSignal: true, isRequired: true, transformFunction: null }, etiquette: { classPropertyName: "etiquette", publicName: "etiquette", isSignal: true, isRequired: true, transformFunction: null }, variante: { classPropertyName: "variante", publicName: "variante", isSignal: true, isRequired: false, transformFunction: null }, taille: { classPropertyName: "taille", publicName: "taille", isSignal: true, isRequired: false, transformFunction: null }, enfonce: { classPropertyName: "enfonce", publicName: "enfonce", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-variante": "variante()", "attr.data-taille": "taille()", "attr.aria-label": "etiquette()", "attr.aria-pressed": "enfonce() === null ? null : enfonce()" }, classAttribute: "st-icon-button" }, ngImport: i0, template: "<st-icon [nom]=\"icone()\" [taille]=\"taille() === 'sm' ? 'sm' : 'md'\" />\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host{display:inline-flex;flex:none;align-items:center;justify-content:center;min-inline-size:var(--st-cible-tactile-min);min-block-size:var(--st-cible-tactile-min);color:var(--st-couleur-texte);cursor:pointer;background:transparent;border:1px solid transparent;border-radius:var(--st-rayon-md);transition:background-color var(--st-duree-rapide) var(--st-courbe-standard)}:host:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}:host:hover:not(:disabled){background:var(--st-couleur-surface-survol)}:host:disabled{color:var(--st-couleur-texte-desactive);cursor:not-allowed}:host[aria-pressed=true]{background:var(--st-couleur-surface-enfoncee)}:host([data-variante=secondaire]){background:var(--st-couleur-surface);border-color:var(--st-couleur-bordure-forte)}:host([data-variante=danger]){color:var(--st-couleur-danger)}:host([data-variante=danger]):hover:not(:disabled){background:var(--st-couleur-danger-discret)}\n"], dependencies: [{ kind: "component", type: StIcon, selector: "st-icon", inputs: ["nom", "taille", "ton", "etiquette"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
843
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StIconButton, isStandalone: true, selector: "button[stIconButton]", inputs: { icone: { classPropertyName: "icone", publicName: "icone", isSignal: true, isRequired: true, transformFunction: null }, etiquette: { classPropertyName: "etiquette", publicName: "etiquette", isSignal: true, isRequired: true, transformFunction: null }, variante: { classPropertyName: "variante", publicName: "variante", isSignal: true, isRequired: false, transformFunction: null }, taille: { classPropertyName: "taille", publicName: "taille", isSignal: true, isRequired: false, transformFunction: null }, enfonce: { classPropertyName: "enfonce", publicName: "enfonce", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-variante": "variante()", "attr.data-taille": "taille()", "attr.aria-label": "etiquette()", "attr.aria-pressed": "enfonce() === null ? null : enfonce()" }, classAttribute: "st-icon-button" }, ngImport: i0, template: "<st-icon [nom]=\"icone()\" [taille]=\"taille() === 'sm' ? 'sm' : 'md'\" />\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:inline-flex;flex:none;align-items:center;justify-content:center;min-inline-size:var(--st-cible-tactile-min);min-block-size:var(--st-cible-tactile-min);color:var(--st-couleur-texte);cursor:pointer;background:transparent;border:1px solid transparent;border-radius:var(--st-rayon-md);transition:background-color var(--st-duree-rapide) var(--st-courbe-standard)}:host:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}:host:hover:not(:disabled){background:var(--st-couleur-surface-survol)}:host:disabled{color:var(--st-couleur-texte-desactive);cursor:not-allowed}:host[aria-pressed=true]{background:var(--st-couleur-surface-enfoncee)}:host([data-variante=secondaire]){background:var(--st-couleur-surface);border-color:var(--st-couleur-bordure-forte)}:host([data-variante=danger]){color:var(--st-couleur-danger)}:host([data-variante=danger]):hover:not(:disabled){background:var(--st-couleur-danger-discret)}\n"], dependencies: [{ kind: "component", type: StIcon, selector: "st-icon", inputs: ["nom", "taille", "ton", "etiquette"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
569
844
  }
570
845
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StIconButton, decorators: [{
571
846
  type: Component,
@@ -575,7 +850,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
575
850
  '[attr.data-taille]': 'taille()',
576
851
  '[attr.aria-label]': 'etiquette()',
577
852
  '[attr.aria-pressed]': 'enfonce() === null ? null : enfonce()',
578
- }, template: "<st-icon [nom]=\"icone()\" [taille]=\"taille() === 'sm' ? 'sm' : 'md'\" />\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host{display:inline-flex;flex:none;align-items:center;justify-content:center;min-inline-size:var(--st-cible-tactile-min);min-block-size:var(--st-cible-tactile-min);color:var(--st-couleur-texte);cursor:pointer;background:transparent;border:1px solid transparent;border-radius:var(--st-rayon-md);transition:background-color var(--st-duree-rapide) var(--st-courbe-standard)}:host:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}:host:hover:not(:disabled){background:var(--st-couleur-surface-survol)}:host:disabled{color:var(--st-couleur-texte-desactive);cursor:not-allowed}:host[aria-pressed=true]{background:var(--st-couleur-surface-enfoncee)}:host([data-variante=secondaire]){background:var(--st-couleur-surface);border-color:var(--st-couleur-bordure-forte)}:host([data-variante=danger]){color:var(--st-couleur-danger)}:host([data-variante=danger]):hover:not(:disabled){background:var(--st-couleur-danger-discret)}\n"] }]
853
+ }, template: "<st-icon [nom]=\"icone()\" [taille]=\"taille() === 'sm' ? 'sm' : 'md'\" />\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:inline-flex;flex:none;align-items:center;justify-content:center;min-inline-size:var(--st-cible-tactile-min);min-block-size:var(--st-cible-tactile-min);color:var(--st-couleur-texte);cursor:pointer;background:transparent;border:1px solid transparent;border-radius:var(--st-rayon-md);transition:background-color var(--st-duree-rapide) var(--st-courbe-standard)}:host:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}:host:hover:not(:disabled){background:var(--st-couleur-surface-survol)}:host:disabled{color:var(--st-couleur-texte-desactive);cursor:not-allowed}:host[aria-pressed=true]{background:var(--st-couleur-surface-enfoncee)}:host([data-variante=secondaire]){background:var(--st-couleur-surface);border-color:var(--st-couleur-bordure-forte)}:host([data-variante=danger]){color:var(--st-couleur-danger)}:host([data-variante=danger]):hover:not(:disabled){background:var(--st-couleur-danger-discret)}\n"] }]
579
854
  }], propDecorators: { icone: [{ type: i0.Input, args: [{ isSignal: true, alias: "icone", required: true }] }], etiquette: [{ type: i0.Input, args: [{ isSignal: true, alias: "etiquette", required: true }] }], variante: [{ type: i0.Input, args: [{ isSignal: true, alias: "variante", required: false }] }], taille: [{ type: i0.Input, args: [{ isSignal: true, alias: "taille", required: false }] }], enfonce: [{ type: i0.Input, args: [{ isSignal: true, alias: "enfonce", required: false }] }] } });
580
855
 
581
856
  /**
@@ -603,7 +878,7 @@ class StLink {
603
878
  mentionExterneLue = computed(() => this.mentionExterne() ?? this.libelles().nouvelleFenetre, /* @ts-ignore */
604
879
  ...(ngDevMode ? [{ debugName: "mentionExterneLue" }] : /* istanbul ignore next */ []));
605
880
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StLink, deps: [], target: i0.ɵɵFactoryTarget.Component });
606
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StLink, isStandalone: true, selector: "a[stLink]", inputs: { variante: { classPropertyName: "variante", publicName: "variante", isSignal: true, isRequired: false, transformFunction: null }, externe: { classPropertyName: "externe", publicName: "externe", isSignal: true, isRequired: false, transformFunction: null }, mentionExterne: { classPropertyName: "mentionExterne", publicName: "mentionExterne", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-variante": "variante()", "attr.target": "externe() ? \"_blank\" : null", "attr.rel": "externe() ? \"noopener noreferrer\" : null" }, classAttribute: "st-link" }, ngImport: i0, template: "<ng-content />\n@if (externe()) {\n <st-icon nom=\"lien-externe\" taille=\"xs\" />\n <span class=\"st-vh\">{{ mentionExterneLue() }}</span>\n}\n", styles: [":host{display:inline;gap:var(--st-espacement-1);color:var(--st-couleur-primaire);text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px;border-radius:var(--st-rayon-xs)}:host:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}:host:hover{color:var(--st-couleur-primaire-survol)}:host([data-variante=discret]){color:var(--st-couleur-texte-discret)}:host([data-variante=autonome]){display:inline-flex;gap:var(--st-espacement-1);align-items:center;min-block-size:var(--st-cible-tactile-min);text-decoration:none}:host([data-variante=autonome]):hover{text-decoration:underline}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "component", type: StIcon, selector: "st-icon", inputs: ["nom", "taille", "ton", "etiquette"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
881
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StLink, isStandalone: true, selector: "a[stLink]", inputs: { variante: { classPropertyName: "variante", publicName: "variante", isSignal: true, isRequired: false, transformFunction: null }, externe: { classPropertyName: "externe", publicName: "externe", isSignal: true, isRequired: false, transformFunction: null }, mentionExterne: { classPropertyName: "mentionExterne", publicName: "mentionExterne", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-variante": "variante()", "attr.target": "externe() ? \"_blank\" : null", "attr.rel": "externe() ? \"noopener noreferrer\" : null" }, classAttribute: "st-link" }, ngImport: i0, template: "<ng-content />\n@if (externe()) {\n <st-icon nom=\"lien-externe\" taille=\"xs\" />\n <span class=\"st-vh\">{{ mentionExterneLue() }}</span>\n}\n", styles: [":host([hidden]){display:none!important}:host{display:inline;gap:var(--st-espacement-1);color:var(--st-couleur-primaire);text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px;border-radius:var(--st-rayon-xs)}:host:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}:host:hover{color:var(--st-couleur-primaire-survol)}:host([data-variante=discret]){color:var(--st-couleur-texte-discret)}:host([data-variante=autonome]){display:inline-flex;gap:var(--st-espacement-1);align-items:center;min-block-size:var(--st-cible-tactile-min);text-decoration:none}:host([data-variante=autonome]):hover{text-decoration:underline}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "component", type: StIcon, selector: "st-icon", inputs: ["nom", "taille", "ton", "etiquette"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
607
882
  }
608
883
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StLink, decorators: [{
609
884
  type: Component,
@@ -612,7 +887,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
612
887
  '[attr.data-variante]': 'variante()',
613
888
  '[attr.target]': 'externe() ? "_blank" : null',
614
889
  '[attr.rel]': 'externe() ? "noopener noreferrer" : null',
615
- }, template: "<ng-content />\n@if (externe()) {\n <st-icon nom=\"lien-externe\" taille=\"xs\" />\n <span class=\"st-vh\">{{ mentionExterneLue() }}</span>\n}\n", styles: [":host{display:inline;gap:var(--st-espacement-1);color:var(--st-couleur-primaire);text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px;border-radius:var(--st-rayon-xs)}:host:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}:host:hover{color:var(--st-couleur-primaire-survol)}:host([data-variante=discret]){color:var(--st-couleur-texte-discret)}:host([data-variante=autonome]){display:inline-flex;gap:var(--st-espacement-1);align-items:center;min-block-size:var(--st-cible-tactile-min);text-decoration:none}:host([data-variante=autonome]):hover{text-decoration:underline}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"] }]
890
+ }, template: "<ng-content />\n@if (externe()) {\n <st-icon nom=\"lien-externe\" taille=\"xs\" />\n <span class=\"st-vh\">{{ mentionExterneLue() }}</span>\n}\n", styles: [":host([hidden]){display:none!important}:host{display:inline;gap:var(--st-espacement-1);color:var(--st-couleur-primaire);text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px;border-radius:var(--st-rayon-xs)}:host:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}:host:hover{color:var(--st-couleur-primaire-survol)}:host([data-variante=discret]){color:var(--st-couleur-texte-discret)}:host([data-variante=autonome]){display:inline-flex;gap:var(--st-espacement-1);align-items:center;min-block-size:var(--st-cible-tactile-min);text-decoration:none}:host([data-variante=autonome]):hover{text-decoration:underline}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"] }]
616
891
  }], propDecorators: { variante: [{ type: i0.Input, args: [{ isSignal: true, alias: "variante", required: false }] }], externe: [{ type: i0.Input, args: [{ isSignal: true, alias: "externe", required: false }] }], mentionExterne: [{ type: i0.Input, args: [{ isSignal: true, alias: "mentionExterne", required: false }] }] } });
617
892
 
618
893
  /**
@@ -632,7 +907,7 @@ class StButtonGroup {
632
907
  /** Boutons jointifs, rayons fusionnes. */
633
908
  attache = input(false, { ...(ngDevMode ? { debugName: "attache" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
634
909
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StButtonGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
635
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StButtonGroup, isStandalone: true, selector: "st-button-group", inputs: { etiquette: { classPropertyName: "etiquette", publicName: "etiquette", isSignal: true, isRequired: true, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, attache: { classPropertyName: "attache", publicName: "attache", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "group" }, properties: { "attr.aria-label": "etiquette()", "attr.data-orientation": "orientation()", "attr.data-attache": "attache() ? \"\" : null" }, classAttribute: "st-button-group" }, ngImport: i0, template: "<ng-content />\n", styles: [":host{display:flex;flex-wrap:wrap;gap:var(--st-espacement-2);align-items:center}:host([data-orientation=verticale]){flex-direction:column;align-items:stretch}:host([data-attache]){flex-wrap:nowrap;gap:0}:host([data-attache]) ::ng-deep>.st-button:not(:first-child){border-start-start-radius:0;border-end-start-radius:0}:host([data-attache]) ::ng-deep>.st-button:not(:last-child){border-start-end-radius:0;border-end-end-radius:0;border-inline-end-width:0}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
910
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StButtonGroup, isStandalone: true, selector: "st-button-group", inputs: { etiquette: { classPropertyName: "etiquette", publicName: "etiquette", isSignal: true, isRequired: true, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, attache: { classPropertyName: "attache", publicName: "attache", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "group" }, properties: { "attr.aria-label": "etiquette()", "attr.data-orientation": "orientation()", "attr.data-attache": "attache() ? \"\" : null" }, classAttribute: "st-button-group" }, ngImport: i0, template: "<ng-content />\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:flex;flex-wrap:wrap;gap:var(--st-espacement-2);align-items:center}:host([data-orientation=verticale]){flex-direction:column;align-items:stretch}:host([data-attache]){flex-wrap:nowrap;gap:0}:host([data-attache]) ::ng-deep>.st-button:not(:first-child){border-start-start-radius:0;border-end-start-radius:0}:host([data-attache]) ::ng-deep>.st-button:not(:last-child){border-start-end-radius:0;border-end-end-radius:0;border-inline-end-width:0}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
636
911
  }
637
912
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StButtonGroup, decorators: [{
638
913
  type: Component,
@@ -642,7 +917,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
642
917
  '[attr.aria-label]': 'etiquette()',
643
918
  '[attr.data-orientation]': 'orientation()',
644
919
  '[attr.data-attache]': 'attache() ? "" : null',
645
- }, template: "<ng-content />\n", styles: [":host{display:flex;flex-wrap:wrap;gap:var(--st-espacement-2);align-items:center}:host([data-orientation=verticale]){flex-direction:column;align-items:stretch}:host([data-attache]){flex-wrap:nowrap;gap:0}:host([data-attache]) ::ng-deep>.st-button:not(:first-child){border-start-start-radius:0;border-end-start-radius:0}:host([data-attache]) ::ng-deep>.st-button:not(:last-child){border-start-end-radius:0;border-end-end-radius:0;border-inline-end-width:0}\n"] }]
920
+ }, template: "<ng-content />\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:flex;flex-wrap:wrap;gap:var(--st-espacement-2);align-items:center}:host([data-orientation=verticale]){flex-direction:column;align-items:stretch}:host([data-attache]){flex-wrap:nowrap;gap:0}:host([data-attache]) ::ng-deep>.st-button:not(:first-child){border-start-start-radius:0;border-end-start-radius:0}:host([data-attache]) ::ng-deep>.st-button:not(:last-child){border-start-end-radius:0;border-end-end-radius:0;border-inline-end-width:0}\n"] }]
646
921
  }], propDecorators: { etiquette: [{ type: i0.Input, args: [{ isSignal: true, alias: "etiquette", required: true }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], attache: [{ type: i0.Input, args: [{ isSignal: true, alias: "attache", required: false }] }] } });
647
922
 
648
923
  /**
@@ -656,7 +931,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
656
931
  */
657
932
  class StCode {
658
933
  document = inject(DOCUMENT);
659
- destruction = inject(DestroyRef);
660
934
  libelles = inject(ST_LIBELLES);
661
935
  valeur = input.required(/* @ts-ignore */
662
936
  ...(ngDevMode ? [{ debugName: "valeur" }] : /* istanbul ignore next */ []));
@@ -673,53 +947,31 @@ class StCode {
673
947
  libelleCopierLu = computed(() => this.libelleCopier() ?? this.libelles().copier, /* @ts-ignore */
674
948
  ...(ngDevMode ? [{ debugName: "libelleCopierLu" }] : /* istanbul ignore next */ []));
675
949
  copie = output();
676
- confirmation = signal('', /* @ts-ignore */
677
- ...(ngDevMode ? [{ debugName: "confirmation" }] : /* istanbul ignore next */ []));
678
- minuterie = null;
679
- texteDeConfirmation = this.confirmation.asReadonly();
950
+ annonce = new AnnonceLocale(inject(DestroyRef));
680
951
  /**
681
952
  * Le bouton n'apparait que si le navigateur sait copier. Sans presse-papiers,
682
953
  * un bouton qui ne fait rien vaut moins que la selection manuelle, que la
683
954
  * feuille garde possible (`user-select: all`).
684
955
  */
685
- copiePossible = computed(() => {
686
- if (!this.copiable())
687
- return false;
688
- const fenetre = this.document.defaultView;
689
- return fenetre?.navigator.clipboard !== undefined;
690
- }, /* @ts-ignore */
956
+ copiePossible = computed(() => this.copiable() && pressePapiersDisponible(this.document), /* @ts-ignore */
691
957
  ...(ngDevMode ? [{ debugName: "copiePossible" }] : /* istanbul ignore next */ []));
692
958
  async auClicDeCopie() {
693
- const presse = this.document.defaultView?.navigator.clipboard;
694
- if (presse === undefined)
695
- return;
696
- try {
697
- await presse.writeText(this.valeur());
959
+ const issue = await copierDansLePressePapiers(this.document, this.valeur());
960
+ if (issue === 'copie') {
961
+ this.copie.emit(this.valeur());
962
+ this.annonce.annoncer(this.messageDeConfirmation() ?? this.libelles().copieEffectuee);
698
963
  }
699
- catch {
700
- // Le refus du presse-papiers n'est pas une erreur applicative : la
701
- // valeur reste selectionnable a la main.
702
- return;
964
+ else if (issue === 'refusee') {
965
+ // Un refus se DIT : se taire laisserait croire que la copie a eu lieu.
966
+ this.annonce.annoncer(this.libelles().copieImpossible);
703
967
  }
704
- this.copie.emit(this.valeur());
705
- this.confirmation.set(this.messageDeConfirmation() ?? this.libelles().copieEffectuee);
706
- if (this.minuterie !== null)
707
- clearTimeout(this.minuterie);
708
- this.minuterie = setTimeout(() => {
709
- this.confirmation.set('');
710
- this.minuterie = null;
711
- }, 3000);
712
- this.destruction.onDestroy(() => {
713
- if (this.minuterie !== null)
714
- clearTimeout(this.minuterie);
715
- });
716
968
  }
717
969
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StCode, deps: [], target: i0.ɵɵFactoryTarget.Component });
718
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StCode, isStandalone: true, selector: "st-code", inputs: { valeur: { classPropertyName: "valeur", publicName: "valeur", isSignal: true, isRequired: true, transformFunction: null }, copiable: { classPropertyName: "copiable", publicName: "copiable", isSignal: true, isRequired: false, transformFunction: null }, etiquette: { classPropertyName: "etiquette", publicName: "etiquette", isSignal: true, isRequired: false, transformFunction: null }, libelleCopier: { classPropertyName: "libelleCopier", publicName: "libelleCopier", isSignal: true, isRequired: false, transformFunction: null }, messageDeConfirmation: { classPropertyName: "messageDeConfirmation", publicName: "messageDeConfirmation", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { copie: "copie" }, host: { classAttribute: "st-code" }, ngImport: i0, template: "<code aria-hidden=\"true\">{{ valeur() }}</code>\n<span class=\"st-vh\">{{ etiquetteLue() + ' ' + valeur() }}</span>\n\n@if (copiePossible()) {\n <!-- eslint-disable-next-line @angular-eslint/template/elements-content --\n Le contenu vient du gabarit de stIconButton. Le nom accessible est\n impose par le type (`etiquette` est requis) et verifie par axe. -->\n <button\n stIconButton\n type=\"button\"\n icone=\"copie\"\n taille=\"sm\"\n [etiquette]=\"libelleCopierLu()\"\n (click)=\"auClicDeCopie()\"\n ></button>\n}\n\n<span class=\"st-vh\" aria-live=\"polite\">{{ texteDeConfirmation() }}</span>\n", styles: [":host{display:inline-flex;gap:var(--st-espacement-1);align-items:center}code{padding-block:var(--st-espacement-1);padding-inline:var(--st-espacement-2);font-family:var(--st-police-mono);font-size:var(--st-taille-sm);color:var(--st-couleur-texte);background:var(--st-couleur-surface-enfoncee);border:1px solid var(--st-couleur-bordure);border-radius:var(--st-rayon-sm);overflow-wrap:anywhere;-webkit-user-select:all;user-select:all}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "component", type: StIconButton, selector: "button[stIconButton]", inputs: ["icone", "etiquette", "variante", "taille", "enfonce"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
970
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StCode, isStandalone: true, selector: "st-code", inputs: { valeur: { classPropertyName: "valeur", publicName: "valeur", isSignal: true, isRequired: true, transformFunction: null }, copiable: { classPropertyName: "copiable", publicName: "copiable", isSignal: true, isRequired: false, transformFunction: null }, etiquette: { classPropertyName: "etiquette", publicName: "etiquette", isSignal: true, isRequired: false, transformFunction: null }, libelleCopier: { classPropertyName: "libelleCopier", publicName: "libelleCopier", isSignal: true, isRequired: false, transformFunction: null }, messageDeConfirmation: { classPropertyName: "messageDeConfirmation", publicName: "messageDeConfirmation", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { copie: "copie" }, host: { classAttribute: "st-code" }, ngImport: i0, template: "<code aria-hidden=\"true\">{{ valeur() }}</code>\n<span class=\"st-vh\">{{ etiquetteLue() + ' ' + valeur() }}</span>\n\n@if (copiePossible()) {\n <!-- eslint-disable-next-line @angular-eslint/template/elements-content --\n Le contenu vient du gabarit de stIconButton. Le nom accessible est\n impose par le type (`etiquette` est requis) et verifie par axe. -->\n <button\n stIconButton\n type=\"button\"\n icone=\"copie\"\n taille=\"sm\"\n [etiquette]=\"libelleCopierLu()\"\n (click)=\"auClicDeCopie()\"\n ></button>\n}\n\n<span class=\"st-vh\" aria-live=\"polite\">{{ annonce.texte() }}</span>\n", styles: [":host([hidden]){display:none!important}:host{display:inline-flex;gap:var(--st-espacement-1);align-items:center}code{padding-block:var(--st-espacement-1);padding-inline:var(--st-espacement-2);font-family:var(--st-police-mono);font-size:var(--st-taille-sm);color:var(--st-couleur-texte);background:var(--st-couleur-surface-enfoncee);border:1px solid var(--st-couleur-bordure);border-radius:var(--st-rayon-sm);overflow-wrap:anywhere;-webkit-user-select:all;user-select:all}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "component", type: StIconButton, selector: "button[stIconButton]", inputs: ["icone", "etiquette", "variante", "taille", "enfonce"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
719
971
  }
720
972
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StCode, decorators: [{
721
973
  type: Component,
722
- args: [{ selector: 'st-code', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StIconButton], host: { class: 'st-code' }, template: "<code aria-hidden=\"true\">{{ valeur() }}</code>\n<span class=\"st-vh\">{{ etiquetteLue() + ' ' + valeur() }}</span>\n\n@if (copiePossible()) {\n <!-- eslint-disable-next-line @angular-eslint/template/elements-content --\n Le contenu vient du gabarit de stIconButton. Le nom accessible est\n impose par le type (`etiquette` est requis) et verifie par axe. -->\n <button\n stIconButton\n type=\"button\"\n icone=\"copie\"\n taille=\"sm\"\n [etiquette]=\"libelleCopierLu()\"\n (click)=\"auClicDeCopie()\"\n ></button>\n}\n\n<span class=\"st-vh\" aria-live=\"polite\">{{ texteDeConfirmation() }}</span>\n", styles: [":host{display:inline-flex;gap:var(--st-espacement-1);align-items:center}code{padding-block:var(--st-espacement-1);padding-inline:var(--st-espacement-2);font-family:var(--st-police-mono);font-size:var(--st-taille-sm);color:var(--st-couleur-texte);background:var(--st-couleur-surface-enfoncee);border:1px solid var(--st-couleur-bordure);border-radius:var(--st-rayon-sm);overflow-wrap:anywhere;-webkit-user-select:all;user-select:all}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"] }]
974
+ args: [{ selector: 'st-code', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StIconButton], host: { class: 'st-code' }, template: "<code aria-hidden=\"true\">{{ valeur() }}</code>\n<span class=\"st-vh\">{{ etiquetteLue() + ' ' + valeur() }}</span>\n\n@if (copiePossible()) {\n <!-- eslint-disable-next-line @angular-eslint/template/elements-content --\n Le contenu vient du gabarit de stIconButton. Le nom accessible est\n impose par le type (`etiquette` est requis) et verifie par axe. -->\n <button\n stIconButton\n type=\"button\"\n icone=\"copie\"\n taille=\"sm\"\n [etiquette]=\"libelleCopierLu()\"\n (click)=\"auClicDeCopie()\"\n ></button>\n}\n\n<span class=\"st-vh\" aria-live=\"polite\">{{ annonce.texte() }}</span>\n", styles: [":host([hidden]){display:none!important}:host{display:inline-flex;gap:var(--st-espacement-1);align-items:center}code{padding-block:var(--st-espacement-1);padding-inline:var(--st-espacement-2);font-family:var(--st-police-mono);font-size:var(--st-taille-sm);color:var(--st-couleur-texte);background:var(--st-couleur-surface-enfoncee);border:1px solid var(--st-couleur-bordure);border-radius:var(--st-rayon-sm);overflow-wrap:anywhere;-webkit-user-select:all;user-select:all}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"] }]
723
975
  }], propDecorators: { valeur: [{ type: i0.Input, args: [{ isSignal: true, alias: "valeur", required: true }] }], copiable: [{ type: i0.Input, args: [{ isSignal: true, alias: "copiable", required: false }] }], etiquette: [{ type: i0.Input, args: [{ isSignal: true, alias: "etiquette", required: false }] }], libelleCopier: [{ type: i0.Input, args: [{ isSignal: true, alias: "libelleCopier", required: false }] }], messageDeConfirmation: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageDeConfirmation", required: false }] }], copie: [{ type: i0.Output, args: ["copie"] }] } });
724
976
 
725
977
  /**
@@ -735,7 +987,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
735
987
  */
736
988
  class StMasked {
737
989
  libelles = inject(ST_LIBELLES);
738
- destruction = inject(DestroyRef);
739
990
  valeur = input.required(/* @ts-ignore */
740
991
  ...(ngDevMode ? [{ debugName: "valeur" }] : /* istanbul ignore next */ []));
741
992
  type = input('iban', /* @ts-ignore */
@@ -751,10 +1002,21 @@ class StMasked {
751
1002
  libelleMasquer = input(null, /* @ts-ignore */
752
1003
  ...(ngDevMode ? [{ debugName: "libelleMasquer" }] : /* istanbul ignore next */ []));
753
1004
  revelation = output();
754
- annonce = signal('', /* @ts-ignore */
755
- ...(ngDevMode ? [{ debugName: "annonce" }] : /* istanbul ignore next */ []));
756
- texteDAnnonce = this.annonce.asReadonly();
1005
+ /**
1006
+ * ⚠️ Par `AnnonceLocale`, et non par un signal pose directement. La 0.2.0
1007
+ * reposait « Valeur masquee a nouveau » a l'identique : aucune mutation, donc
1008
+ * une seconde remise en masque jamais annoncee.
1009
+ */
1010
+ annonce = new AnnonceLocale(inject(DestroyRef));
757
1011
  minuterie = null;
1012
+ constructor() {
1013
+ // Enregistre UNE fois. La 0.2.0 l'enregistrait a chaque revelation, et
1014
+ // chaque clic empilait un rappel de plus.
1015
+ inject(DestroyRef).onDestroy(() => {
1016
+ if (this.minuterie !== null)
1017
+ clearTimeout(this.minuterie);
1018
+ });
1019
+ }
758
1020
  valeurMasquee = computed(() => {
759
1021
  const valeur = this.valeur();
760
1022
  switch (this.type()) {
@@ -800,7 +1062,6 @@ class StMasked {
800
1062
  }
801
1063
  this.revele.set(true);
802
1064
  this.revelation.emit({ type: this.type() });
803
- this.annonce.set('');
804
1065
  // Re-masquage automatique : une valeur revelee puis oubliee a l'ecran est
805
1066
  // lisible par quiconque passe derriere.
806
1067
  if (this.minuterie !== null)
@@ -808,10 +1069,6 @@ class StMasked {
808
1069
  this.minuterie = setTimeout(() => {
809
1070
  this.masquer();
810
1071
  }, this.dureeDeRevelationEnSecondes() * 1000);
811
- this.destruction.onDestroy(() => {
812
- if (this.minuterie !== null)
813
- clearTimeout(this.minuterie);
814
- });
815
1072
  }
816
1073
  masquer() {
817
1074
  if (this.minuterie !== null) {
@@ -821,15 +1078,15 @@ class StMasked {
821
1078
  if (!this.revele())
822
1079
  return;
823
1080
  this.revele.set(false);
824
- this.annonce.set(this.libelles().valeurMasqueeANouveau);
1081
+ this.annonce.annoncer(this.libelles().valeurMasqueeANouveau);
825
1082
  }
826
1083
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StMasked, deps: [], target: i0.ɵɵFactoryTarget.Component });
827
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StMasked, isStandalone: true, selector: "st-masked", inputs: { valeur: { classPropertyName: "valeur", publicName: "valeur", isSignal: true, isRequired: true, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, revele: { classPropertyName: "revele", publicName: "revele", isSignal: true, isRequired: false, transformFunction: null }, revelationAutorisee: { classPropertyName: "revelationAutorisee", publicName: "revelationAutorisee", isSignal: true, isRequired: false, transformFunction: null }, dureeDeRevelationEnSecondes: { classPropertyName: "dureeDeRevelationEnSecondes", publicName: "dureeDeRevelationEnSecondes", isSignal: true, isRequired: false, transformFunction: null }, libelleAfficher: { classPropertyName: "libelleAfficher", publicName: "libelleAfficher", isSignal: true, isRequired: false, transformFunction: null }, libelleMasquer: { classPropertyName: "libelleMasquer", publicName: "libelleMasquer", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { revele: "reveleChange", revelation: "revelation" }, host: { properties: { "attr.data-type": "type()" }, classAttribute: "st-masked" }, ngImport: i0, template: "<span class=\"st-masked__valeur\" aria-hidden=\"true\">{{ valeurAffichee() }}</span>\n<span class=\"st-vh\">{{ nomAccessible() }}</span>\n\n@if (revelationAutorisee()) {\n <!-- eslint-disable-next-line @angular-eslint/template/elements-content --\n Le contenu vient du gabarit de stIconButton. Le nom accessible est\n impose par le type (`etiquette` est requis) et verifie par axe. -->\n <button\n stIconButton\n type=\"button\"\n taille=\"sm\"\n [icone]=\"revele() ? 'oeil-barre' : 'oeil'\"\n [etiquette]=\"libelleDuBouton()\"\n [enfonce]=\"revele()\"\n (click)=\"basculer()\"\n ></button>\n}\n\n<span class=\"st-vh\" aria-live=\"polite\">{{ texteDAnnonce() }}</span>\n", styles: [":host{display:inline-flex;gap:var(--st-espacement-2);align-items:center}.st-masked__valeur{font-family:var(--st-police-mono);color:var(--st-couleur-texte);letter-spacing:.02em}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "component", type: StIconButton, selector: "button[stIconButton]", inputs: ["icone", "etiquette", "variante", "taille", "enfonce"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1084
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StMasked, isStandalone: true, selector: "st-masked", inputs: { valeur: { classPropertyName: "valeur", publicName: "valeur", isSignal: true, isRequired: true, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, revele: { classPropertyName: "revele", publicName: "revele", isSignal: true, isRequired: false, transformFunction: null }, revelationAutorisee: { classPropertyName: "revelationAutorisee", publicName: "revelationAutorisee", isSignal: true, isRequired: false, transformFunction: null }, dureeDeRevelationEnSecondes: { classPropertyName: "dureeDeRevelationEnSecondes", publicName: "dureeDeRevelationEnSecondes", isSignal: true, isRequired: false, transformFunction: null }, libelleAfficher: { classPropertyName: "libelleAfficher", publicName: "libelleAfficher", isSignal: true, isRequired: false, transformFunction: null }, libelleMasquer: { classPropertyName: "libelleMasquer", publicName: "libelleMasquer", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { revele: "reveleChange", revelation: "revelation" }, host: { properties: { "attr.data-type": "type()" }, classAttribute: "st-masked" }, ngImport: i0, template: "<span class=\"st-masked__valeur\" aria-hidden=\"true\">{{ valeurAffichee() }}</span>\n<span class=\"st-vh\">{{ nomAccessible() }}</span>\n\n@if (revelationAutorisee()) {\n <!-- eslint-disable-next-line @angular-eslint/template/elements-content --\n Le contenu vient du gabarit de stIconButton. Le nom accessible est\n impose par le type (`etiquette` est requis) et verifie par axe. -->\n <button\n stIconButton\n type=\"button\"\n taille=\"sm\"\n [icone]=\"revele() ? 'oeil-barre' : 'oeil'\"\n [etiquette]=\"libelleDuBouton()\"\n [enfonce]=\"revele()\"\n (click)=\"basculer()\"\n ></button>\n}\n\n<span class=\"st-vh\" aria-live=\"polite\">{{ annonce.texte() }}</span>\n", styles: [":host([hidden]){display:none!important}:host{display:inline-flex;gap:var(--st-espacement-2);align-items:center}.st-masked__valeur{font-family:var(--st-police-mono);color:var(--st-couleur-texte);letter-spacing:.02em}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "component", type: StIconButton, selector: "button[stIconButton]", inputs: ["icone", "etiquette", "variante", "taille", "enfonce"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
828
1085
  }
829
1086
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StMasked, decorators: [{
830
1087
  type: Component,
831
- args: [{ selector: 'st-masked', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StIconButton], host: { class: 'st-masked', '[attr.data-type]': 'type()' }, template: "<span class=\"st-masked__valeur\" aria-hidden=\"true\">{{ valeurAffichee() }}</span>\n<span class=\"st-vh\">{{ nomAccessible() }}</span>\n\n@if (revelationAutorisee()) {\n <!-- eslint-disable-next-line @angular-eslint/template/elements-content --\n Le contenu vient du gabarit de stIconButton. Le nom accessible est\n impose par le type (`etiquette` est requis) et verifie par axe. -->\n <button\n stIconButton\n type=\"button\"\n taille=\"sm\"\n [icone]=\"revele() ? 'oeil-barre' : 'oeil'\"\n [etiquette]=\"libelleDuBouton()\"\n [enfonce]=\"revele()\"\n (click)=\"basculer()\"\n ></button>\n}\n\n<span class=\"st-vh\" aria-live=\"polite\">{{ texteDAnnonce() }}</span>\n", styles: [":host{display:inline-flex;gap:var(--st-espacement-2);align-items:center}.st-masked__valeur{font-family:var(--st-police-mono);color:var(--st-couleur-texte);letter-spacing:.02em}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"] }]
832
- }], propDecorators: { valeur: [{ type: i0.Input, args: [{ isSignal: true, alias: "valeur", required: true }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], revele: [{ type: i0.Input, args: [{ isSignal: true, alias: "revele", required: false }] }, { type: i0.Output, args: ["reveleChange"] }], revelationAutorisee: [{ type: i0.Input, args: [{ isSignal: true, alias: "revelationAutorisee", required: false }] }], dureeDeRevelationEnSecondes: [{ type: i0.Input, args: [{ isSignal: true, alias: "dureeDeRevelationEnSecondes", required: false }] }], libelleAfficher: [{ type: i0.Input, args: [{ isSignal: true, alias: "libelleAfficher", required: false }] }], libelleMasquer: [{ type: i0.Input, args: [{ isSignal: true, alias: "libelleMasquer", required: false }] }], revelation: [{ type: i0.Output, args: ["revelation"] }] } });
1088
+ args: [{ selector: 'st-masked', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StIconButton], host: { class: 'st-masked', '[attr.data-type]': 'type()' }, template: "<span class=\"st-masked__valeur\" aria-hidden=\"true\">{{ valeurAffichee() }}</span>\n<span class=\"st-vh\">{{ nomAccessible() }}</span>\n\n@if (revelationAutorisee()) {\n <!-- eslint-disable-next-line @angular-eslint/template/elements-content --\n Le contenu vient du gabarit de stIconButton. Le nom accessible est\n impose par le type (`etiquette` est requis) et verifie par axe. -->\n <button\n stIconButton\n type=\"button\"\n taille=\"sm\"\n [icone]=\"revele() ? 'oeil-barre' : 'oeil'\"\n [etiquette]=\"libelleDuBouton()\"\n [enfonce]=\"revele()\"\n (click)=\"basculer()\"\n ></button>\n}\n\n<span class=\"st-vh\" aria-live=\"polite\">{{ annonce.texte() }}</span>\n", styles: [":host([hidden]){display:none!important}:host{display:inline-flex;gap:var(--st-espacement-2);align-items:center}.st-masked__valeur{font-family:var(--st-police-mono);color:var(--st-couleur-texte);letter-spacing:.02em}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"] }]
1089
+ }], ctorParameters: () => [], propDecorators: { valeur: [{ type: i0.Input, args: [{ isSignal: true, alias: "valeur", required: true }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], revele: [{ type: i0.Input, args: [{ isSignal: true, alias: "revele", required: false }] }, { type: i0.Output, args: ["reveleChange"] }], revelationAutorisee: [{ type: i0.Input, args: [{ isSignal: true, alias: "revelationAutorisee", required: false }] }], dureeDeRevelationEnSecondes: [{ type: i0.Input, args: [{ isSignal: true, alias: "dureeDeRevelationEnSecondes", required: false }] }], libelleAfficher: [{ type: i0.Input, args: [{ isSignal: true, alias: "libelleAfficher", required: false }] }], libelleMasquer: [{ type: i0.Input, args: [{ isSignal: true, alias: "libelleMasquer", required: false }] }], revelation: [{ type: i0.Output, args: ["revelation"] }] } });
833
1090
 
834
1091
  /**
835
1092
  * Somme d'argent.
@@ -866,7 +1123,7 @@ class StMoney {
866
1123
  }), /* @ts-ignore */
867
1124
  ...(ngDevMode ? [{ debugName: "texte" }] : /* istanbul ignore next */ []));
868
1125
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StMoney, deps: [], target: i0.ɵɵFactoryTarget.Component });
869
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StMoney, isStandalone: true, selector: "st-money", inputs: { valeur: { classPropertyName: "valeur", publicName: "valeur", isSignal: true, isRequired: true, transformFunction: null }, signeExplicite: { classPropertyName: "signeExplicite", publicName: "signeExplicite", isSignal: true, isRequired: false, transformFunction: null }, sansDevise: { classPropertyName: "sansDevise", publicName: "sansDevise", isSignal: true, isRequired: false, transformFunction: null }, taille: { classPropertyName: "taille", publicName: "taille", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-taille": "taille()", "attr.data-signe": "signe()" }, classAttribute: "st-money" }, ngImport: i0, template: "{{ texte() }}\n", styles: [":host{font-variant-numeric:tabular-nums;font-weight:var(--st-graisse-moyenne);color:var(--st-couleur-texte);white-space:nowrap}:host([data-signe=negatif]){color:var(--st-couleur-danger)}:host([data-taille=sm]){font-size:var(--st-taille-sm)}:host([data-taille=lg]){font-size:var(--st-taille-lg)}:host([data-taille=xl]){font-size:var(--st-taille-xl)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1126
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StMoney, isStandalone: true, selector: "st-money", inputs: { valeur: { classPropertyName: "valeur", publicName: "valeur", isSignal: true, isRequired: true, transformFunction: null }, signeExplicite: { classPropertyName: "signeExplicite", publicName: "signeExplicite", isSignal: true, isRequired: false, transformFunction: null }, sansDevise: { classPropertyName: "sansDevise", publicName: "sansDevise", isSignal: true, isRequired: false, transformFunction: null }, taille: { classPropertyName: "taille", publicName: "taille", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-taille": "taille()", "attr.data-signe": "signe()" }, classAttribute: "st-money" }, ngImport: i0, template: "{{ texte() }}\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{font-variant-numeric:tabular-nums;font-weight:var(--st-graisse-moyenne);color:var(--st-couleur-texte);white-space:nowrap}:host([data-signe=negatif]){color:var(--st-couleur-danger)}:host([data-taille=sm]){font-size:var(--st-taille-sm)}:host([data-taille=lg]){font-size:var(--st-taille-lg)}:host([data-taille=xl]){font-size:var(--st-taille-xl)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
870
1127
  }
871
1128
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StMoney, decorators: [{
872
1129
  type: Component,
@@ -874,7 +1131,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
874
1131
  class: 'st-money',
875
1132
  '[attr.data-taille]': 'taille()',
876
1133
  '[attr.data-signe]': 'signe()',
877
- }, template: "{{ texte() }}\n", styles: [":host{font-variant-numeric:tabular-nums;font-weight:var(--st-graisse-moyenne);color:var(--st-couleur-texte);white-space:nowrap}:host([data-signe=negatif]){color:var(--st-couleur-danger)}:host([data-taille=sm]){font-size:var(--st-taille-sm)}:host([data-taille=lg]){font-size:var(--st-taille-lg)}:host([data-taille=xl]){font-size:var(--st-taille-xl)}\n"] }]
1134
+ }, template: "{{ texte() }}\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{font-variant-numeric:tabular-nums;font-weight:var(--st-graisse-moyenne);color:var(--st-couleur-texte);white-space:nowrap}:host([data-signe=negatif]){color:var(--st-couleur-danger)}:host([data-taille=sm]){font-size:var(--st-taille-sm)}:host([data-taille=lg]){font-size:var(--st-taille-lg)}:host([data-taille=xl]){font-size:var(--st-taille-xl)}\n"] }]
878
1135
  }], propDecorators: { valeur: [{ type: i0.Input, args: [{ isSignal: true, alias: "valeur", required: true }] }], signeExplicite: [{ type: i0.Input, args: [{ isSignal: true, alias: "signeExplicite", required: false }] }], sansDevise: [{ type: i0.Input, args: [{ isSignal: true, alias: "sansDevise", required: false }] }], taille: [{ type: i0.Input, args: [{ isSignal: true, alias: "taille", required: false }] }] } });
879
1136
 
880
1137
  const OPTIONS = {
@@ -985,11 +1242,11 @@ class StDate {
985
1242
  }, /* @ts-ignore */
986
1243
  ...(ngDevMode ? [{ debugName: "texteAccessible" }] : /* istanbul ignore next */ []));
987
1244
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StDate, deps: [], target: i0.ɵɵFactoryTarget.Component });
988
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StDate, isStandalone: true, selector: "st-date", inputs: { valeur: { classPropertyName: "valeur", publicName: "valeur", isSignal: true, isRequired: true, transformFunction: null }, format: { classPropertyName: "format", publicName: "format", isSignal: true, isRequired: false, transformFunction: null }, fuseau: { classPropertyName: "fuseau", publicName: "fuseau", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "st-date" }, ngImport: i0, template: "@if (estValide()) {\n <time [attr.datetime]=\"iso()\" aria-hidden=\"true\">{{ texte() }}</time>\n @if (texteAccessible(); as lu) {\n <!-- Rien quand le format affiche se lit deja : un noeud vide ferait\n croire a un texte de remplacement absent. -->\n <span class=\"st-vh\">{{ lu }}</span>\n }\n}\n", styles: [":host{font-variant-numeric:tabular-nums;color:var(--st-couleur-texte);white-space:nowrap}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1245
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StDate, isStandalone: true, selector: "st-date", inputs: { valeur: { classPropertyName: "valeur", publicName: "valeur", isSignal: true, isRequired: true, transformFunction: null }, format: { classPropertyName: "format", publicName: "format", isSignal: true, isRequired: false, transformFunction: null }, fuseau: { classPropertyName: "fuseau", publicName: "fuseau", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "st-date" }, ngImport: i0, template: "@if (estValide()) {\n <time [attr.datetime]=\"iso()\" aria-hidden=\"true\">{{ texte() }}</time>\n @if (texteAccessible(); as lu) {\n <!-- Rien quand le format affiche se lit deja : un noeud vide ferait\n croire a un texte de remplacement absent. -->\n <span class=\"st-vh\">{{ lu }}</span>\n }\n}\n", styles: [":host([hidden]){display:none!important}:host{font-variant-numeric:tabular-nums;color:var(--st-couleur-texte);white-space:nowrap}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
989
1246
  }
990
1247
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StDate, decorators: [{
991
1248
  type: Component,
992
- args: [{ selector: 'st-date', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'st-date' }, template: "@if (estValide()) {\n <time [attr.datetime]=\"iso()\" aria-hidden=\"true\">{{ texte() }}</time>\n @if (texteAccessible(); as lu) {\n <!-- Rien quand le format affiche se lit deja : un noeud vide ferait\n croire a un texte de remplacement absent. -->\n <span class=\"st-vh\">{{ lu }}</span>\n }\n}\n", styles: [":host{font-variant-numeric:tabular-nums;color:var(--st-couleur-texte);white-space:nowrap}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"] }]
1249
+ args: [{ selector: 'st-date', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'st-date' }, template: "@if (estValide()) {\n <time [attr.datetime]=\"iso()\" aria-hidden=\"true\">{{ texte() }}</time>\n @if (texteAccessible(); as lu) {\n <!-- Rien quand le format affiche se lit deja : un noeud vide ferait\n croire a un texte de remplacement absent. -->\n <span class=\"st-vh\">{{ lu }}</span>\n }\n}\n", styles: [":host([hidden]){display:none!important}:host{font-variant-numeric:tabular-nums;color:var(--st-couleur-texte);white-space:nowrap}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"] }]
993
1250
  }], propDecorators: { valeur: [{ type: i0.Input, args: [{ isSignal: true, alias: "valeur", required: true }] }], format: [{ type: i0.Input, args: [{ isSignal: true, alias: "format", required: false }] }], fuseau: [{ type: i0.Input, args: [{ isSignal: true, alias: "fuseau", required: false }] }] } });
994
1251
 
995
1252
  const MINUTE = 60_000;
@@ -1095,11 +1352,11 @@ class StRelativeTime {
1095
1352
  }, /* @ts-ignore */
1096
1353
  ...(ngDevMode ? [{ debugName: "texteAccessible" }] : /* istanbul ignore next */ []));
1097
1354
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StRelativeTime, deps: [], target: i0.ɵɵFactoryTarget.Component });
1098
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StRelativeTime, isStandalone: true, selector: "st-relative-time", inputs: { valeur: { classPropertyName: "valeur", publicName: "valeur", isSignal: true, isRequired: true, transformFunction: null }, rafraichir: { classPropertyName: "rafraichir", publicName: "rafraichir", isSignal: true, isRequired: false, transformFunction: null }, seuilAbsoluEnJours: { classPropertyName: "seuilAbsoluEnJours", publicName: "seuilAbsoluEnJours", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "st-relative-time" }, ngImport: i0, template: "@if (estValide()) {\n <time [attr.datetime]=\"iso()\" aria-hidden=\"true\">{{ texte() }}</time>\n @if (texteAccessible(); as lu) {\n <!-- Rien quand le format affiche se lit deja : un noeud vide ferait\n croire a un texte de remplacement absent. -->\n <span class=\"st-vh\">{{ lu }}</span>\n }\n}\n", styles: [":host{font-size:var(--st-taille-sm);color:var(--st-couleur-texte-discret)}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1355
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StRelativeTime, isStandalone: true, selector: "st-relative-time", inputs: { valeur: { classPropertyName: "valeur", publicName: "valeur", isSignal: true, isRequired: true, transformFunction: null }, rafraichir: { classPropertyName: "rafraichir", publicName: "rafraichir", isSignal: true, isRequired: false, transformFunction: null }, seuilAbsoluEnJours: { classPropertyName: "seuilAbsoluEnJours", publicName: "seuilAbsoluEnJours", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "st-relative-time" }, ngImport: i0, template: "@if (estValide()) {\n <time [attr.datetime]=\"iso()\" aria-hidden=\"true\">{{ texte() }}</time>\n @if (texteAccessible(); as lu) {\n <!-- Rien quand le format affiche se lit deja : un noeud vide ferait\n croire a un texte de remplacement absent. -->\n <span class=\"st-vh\">{{ lu }}</span>\n }\n}\n", styles: [":host([hidden]){display:none!important}:host{font-size:var(--st-taille-sm);color:var(--st-couleur-texte-discret)}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1099
1356
  }
1100
1357
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StRelativeTime, decorators: [{
1101
1358
  type: Component,
1102
- args: [{ selector: 'st-relative-time', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'st-relative-time' }, template: "@if (estValide()) {\n <time [attr.datetime]=\"iso()\" aria-hidden=\"true\">{{ texte() }}</time>\n @if (texteAccessible(); as lu) {\n <!-- Rien quand le format affiche se lit deja : un noeud vide ferait\n croire a un texte de remplacement absent. -->\n <span class=\"st-vh\">{{ lu }}</span>\n }\n}\n", styles: [":host{font-size:var(--st-taille-sm);color:var(--st-couleur-texte-discret)}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"] }]
1359
+ args: [{ selector: 'st-relative-time', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'st-relative-time' }, template: "@if (estValide()) {\n <time [attr.datetime]=\"iso()\" aria-hidden=\"true\">{{ texte() }}</time>\n @if (texteAccessible(); as lu) {\n <!-- Rien quand le format affiche se lit deja : un noeud vide ferait\n croire a un texte de remplacement absent. -->\n <span class=\"st-vh\">{{ lu }}</span>\n }\n}\n", styles: [":host([hidden]){display:none!important}:host{font-size:var(--st-taille-sm);color:var(--st-couleur-texte-discret)}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"] }]
1103
1360
  }], ctorParameters: () => [], propDecorators: { valeur: [{ type: i0.Input, args: [{ isSignal: true, alias: "valeur", required: true }] }], rafraichir: [{ type: i0.Input, args: [{ isSignal: true, alias: "rafraichir", required: false }] }], seuilAbsoluEnJours: [{ type: i0.Input, args: [{ isSignal: true, alias: "seuilAbsoluEnJours", required: false }] }] } });
1104
1361
 
1105
1362
  /**
@@ -1137,14 +1394,14 @@ class StCount {
1137
1394
  }, /* @ts-ignore */
1138
1395
  ...(ngDevMode ? [{ debugName: "texte" }] : /* istanbul ignore next */ []));
1139
1396
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StCount, deps: [], target: i0.ɵɵFactoryTarget.Component });
1140
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StCount, isStandalone: true, selector: "st-count", inputs: { valeur: { classPropertyName: "valeur", publicName: "valeur", isSignal: true, isRequired: true, transformFunction: null }, ton: { classPropertyName: "ton", publicName: "ton", isSignal: true, isRequired: false, transformFunction: null }, abregerAuDela: { classPropertyName: "abregerAuDela", publicName: "abregerAuDela", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-ton": "ton()" }, classAttribute: "st-count" }, ngImport: i0, template: "<span aria-hidden=\"true\">{{ texte() }}</span>\n\n@if (estAbrege()) {\n <!-- Abrege a l'ecran, entier a l'oral : \u00AB 1,2 k \u00BB ne se lit pas. -->\n <span class=\"st-vh\">{{ texteComplet() }}</span>\n}\n", styles: [":host{font-variant-numeric:tabular-nums;font-weight:var(--st-graisse-moyenne);color:var(--st-couleur-texte);white-space:nowrap}:host([data-ton=discret]){color:var(--st-couleur-texte-discret)}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1397
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StCount, isStandalone: true, selector: "st-count", inputs: { valeur: { classPropertyName: "valeur", publicName: "valeur", isSignal: true, isRequired: true, transformFunction: null }, ton: { classPropertyName: "ton", publicName: "ton", isSignal: true, isRequired: false, transformFunction: null }, abregerAuDela: { classPropertyName: "abregerAuDela", publicName: "abregerAuDela", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-ton": "ton()" }, classAttribute: "st-count" }, ngImport: i0, template: "<span aria-hidden=\"true\">{{ texte() }}</span>\n\n@if (estAbrege()) {\n <!-- Abrege a l'ecran, entier a l'oral : \u00AB 1,2 k \u00BB ne se lit pas. -->\n <span class=\"st-vh\">{{ texteComplet() }}</span>\n}\n", styles: [":host([hidden]){display:none!important}:host{font-variant-numeric:tabular-nums;font-weight:var(--st-graisse-moyenne);color:var(--st-couleur-texte);white-space:nowrap}:host([data-ton=discret]){color:var(--st-couleur-texte-discret)}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1141
1398
  }
1142
1399
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StCount, decorators: [{
1143
1400
  type: Component,
1144
1401
  args: [{ selector: 'st-count', changeDetection: ChangeDetectionStrategy.OnPush, host: {
1145
1402
  class: 'st-count',
1146
1403
  '[attr.data-ton]': 'ton()',
1147
- }, template: "<span aria-hidden=\"true\">{{ texte() }}</span>\n\n@if (estAbrege()) {\n <!-- Abrege a l'ecran, entier a l'oral : \u00AB 1,2 k \u00BB ne se lit pas. -->\n <span class=\"st-vh\">{{ texteComplet() }}</span>\n}\n", styles: [":host{font-variant-numeric:tabular-nums;font-weight:var(--st-graisse-moyenne);color:var(--st-couleur-texte);white-space:nowrap}:host([data-ton=discret]){color:var(--st-couleur-texte-discret)}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"] }]
1404
+ }, template: "<span aria-hidden=\"true\">{{ texte() }}</span>\n\n@if (estAbrege()) {\n <!-- Abrege a l'ecran, entier a l'oral : \u00AB 1,2 k \u00BB ne se lit pas. -->\n <span class=\"st-vh\">{{ texteComplet() }}</span>\n}\n", styles: [":host([hidden]){display:none!important}:host{font-variant-numeric:tabular-nums;font-weight:var(--st-graisse-moyenne);color:var(--st-couleur-texte);white-space:nowrap}:host([data-ton=discret]){color:var(--st-couleur-texte-discret)}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"] }]
1148
1405
  }], propDecorators: { valeur: [{ type: i0.Input, args: [{ isSignal: true, alias: "valeur", required: true }] }], ton: [{ type: i0.Input, args: [{ isSignal: true, alias: "ton", required: false }] }], abregerAuDela: [{ type: i0.Input, args: [{ isSignal: true, alias: "abregerAuDela", required: false }] }] } });
1149
1406
 
1150
1407
  /**
@@ -1171,7 +1428,7 @@ class StStatusPill {
1171
1428
  ton = input('neutre', /* @ts-ignore */
1172
1429
  ...(ngDevMode ? [{ debugName: "ton" }] : /* istanbul ignore next */ []));
1173
1430
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StStatusPill, deps: [], target: i0.ɵɵFactoryTarget.Component });
1174
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StStatusPill, isStandalone: true, selector: "st-status-pill", inputs: { statut: { classPropertyName: "statut", publicName: "statut", isSignal: true, isRequired: true, transformFunction: null }, libelle: { classPropertyName: "libelle", publicName: "libelle", isSignal: true, isRequired: true, transformFunction: null }, icone: { classPropertyName: "icone", publicName: "icone", isSignal: true, isRequired: true, transformFunction: null }, ton: { classPropertyName: "ton", publicName: "ton", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-ton": "ton()", "attr.data-statut": "statut()" }, classAttribute: "st-status-pill" }, ngImport: i0, template: "<st-icon [nom]=\"icone()\" taille=\"sm\" />\n<span class=\"st-status-pill__libelle\">{{ libelle() }}</span>\n", styles: [":host{display:inline-flex;gap:var(--st-espacement-2);align-items:center;min-block-size:1.5rem;padding-block:var(--st-espacement-1);padding-inline:var(--st-espacement-3);font-size:var(--st-taille-sm);font-weight:var(--st-graisse-moyenne);line-height:var(--st-interligne-serre);color:var(--st-couleur-texte);background:var(--st-couleur-surface-enfoncee);border-radius:var(--st-rayon-pleine)}:host([data-ton=primaire]){color:var(--st-couleur-sur-primaire-discret);background:var(--st-couleur-primaire-discret)}:host([data-ton=succes]){color:var(--st-couleur-sur-succes-discret);background:var(--st-couleur-succes-discret)}:host([data-ton=avertissement]){color:var(--st-couleur-sur-avertissement-discret);background:var(--st-couleur-avertissement-discret)}:host([data-ton=danger]){color:var(--st-couleur-sur-danger-discret);background:var(--st-couleur-danger-discret)}.st-status-pill__libelle{white-space:normal}\n"], dependencies: [{ kind: "component", type: StIcon, selector: "st-icon", inputs: ["nom", "taille", "ton", "etiquette"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1431
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StStatusPill, isStandalone: true, selector: "st-status-pill", inputs: { statut: { classPropertyName: "statut", publicName: "statut", isSignal: true, isRequired: true, transformFunction: null }, libelle: { classPropertyName: "libelle", publicName: "libelle", isSignal: true, isRequired: true, transformFunction: null }, icone: { classPropertyName: "icone", publicName: "icone", isSignal: true, isRequired: true, transformFunction: null }, ton: { classPropertyName: "ton", publicName: "ton", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-ton": "ton()", "attr.data-statut": "statut()" }, classAttribute: "st-status-pill" }, ngImport: i0, template: "<st-icon [nom]=\"icone()\" taille=\"sm\" />\n<span class=\"st-status-pill__libelle\">{{ libelle() }}</span>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:inline-flex;gap:var(--st-espacement-2);align-items:center;min-block-size:1.5rem;padding-block:var(--st-espacement-1);padding-inline:var(--st-espacement-3);font-size:var(--st-taille-sm);font-weight:var(--st-graisse-moyenne);line-height:var(--st-interligne-serre);color:var(--st-couleur-texte);background:var(--st-couleur-surface-enfoncee);border-radius:var(--st-rayon-pleine)}:host([data-ton=primaire]){color:var(--st-couleur-sur-primaire-discret);background:var(--st-couleur-primaire-discret)}:host([data-ton=succes]){color:var(--st-couleur-sur-succes-discret);background:var(--st-couleur-succes-discret)}:host([data-ton=avertissement]){color:var(--st-couleur-sur-avertissement-discret);background:var(--st-couleur-avertissement-discret)}:host([data-ton=danger]){color:var(--st-couleur-sur-danger-discret);background:var(--st-couleur-danger-discret)}.st-status-pill__libelle{white-space:normal}\n"], dependencies: [{ kind: "component", type: StIcon, selector: "st-icon", inputs: ["nom", "taille", "ton", "etiquette"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1175
1432
  }
1176
1433
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StStatusPill, decorators: [{
1177
1434
  type: Component,
@@ -1179,7 +1436,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
1179
1436
  class: 'st-status-pill',
1180
1437
  '[attr.data-ton]': 'ton()',
1181
1438
  '[attr.data-statut]': 'statut()',
1182
- }, template: "<st-icon [nom]=\"icone()\" taille=\"sm\" />\n<span class=\"st-status-pill__libelle\">{{ libelle() }}</span>\n", styles: [":host{display:inline-flex;gap:var(--st-espacement-2);align-items:center;min-block-size:1.5rem;padding-block:var(--st-espacement-1);padding-inline:var(--st-espacement-3);font-size:var(--st-taille-sm);font-weight:var(--st-graisse-moyenne);line-height:var(--st-interligne-serre);color:var(--st-couleur-texte);background:var(--st-couleur-surface-enfoncee);border-radius:var(--st-rayon-pleine)}:host([data-ton=primaire]){color:var(--st-couleur-sur-primaire-discret);background:var(--st-couleur-primaire-discret)}:host([data-ton=succes]){color:var(--st-couleur-sur-succes-discret);background:var(--st-couleur-succes-discret)}:host([data-ton=avertissement]){color:var(--st-couleur-sur-avertissement-discret);background:var(--st-couleur-avertissement-discret)}:host([data-ton=danger]){color:var(--st-couleur-sur-danger-discret);background:var(--st-couleur-danger-discret)}.st-status-pill__libelle{white-space:normal}\n"] }]
1439
+ }, template: "<st-icon [nom]=\"icone()\" taille=\"sm\" />\n<span class=\"st-status-pill__libelle\">{{ libelle() }}</span>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:inline-flex;gap:var(--st-espacement-2);align-items:center;min-block-size:1.5rem;padding-block:var(--st-espacement-1);padding-inline:var(--st-espacement-3);font-size:var(--st-taille-sm);font-weight:var(--st-graisse-moyenne);line-height:var(--st-interligne-serre);color:var(--st-couleur-texte);background:var(--st-couleur-surface-enfoncee);border-radius:var(--st-rayon-pleine)}:host([data-ton=primaire]){color:var(--st-couleur-sur-primaire-discret);background:var(--st-couleur-primaire-discret)}:host([data-ton=succes]){color:var(--st-couleur-sur-succes-discret);background:var(--st-couleur-succes-discret)}:host([data-ton=avertissement]){color:var(--st-couleur-sur-avertissement-discret);background:var(--st-couleur-avertissement-discret)}:host([data-ton=danger]){color:var(--st-couleur-sur-danger-discret);background:var(--st-couleur-danger-discret)}.st-status-pill__libelle{white-space:normal}\n"] }]
1183
1440
  }], propDecorators: { statut: [{ type: i0.Input, args: [{ isSignal: true, alias: "statut", required: true }] }], libelle: [{ type: i0.Input, args: [{ isSignal: true, alias: "libelle", required: true }] }], icone: [{ type: i0.Input, args: [{ isSignal: true, alias: "icone", required: true }] }], ton: [{ type: i0.Input, args: [{ isSignal: true, alias: "ton", required: false }] }] } });
1184
1441
 
1185
1442
  /**
@@ -1212,7 +1469,7 @@ class StBadge {
1212
1469
  }, /* @ts-ignore */
1213
1470
  ...(ngDevMode ? [{ debugName: "texte" }] : /* istanbul ignore next */ []));
1214
1471
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StBadge, deps: [], target: i0.ɵɵFactoryTarget.Component });
1215
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StBadge, isStandalone: true, selector: "st-badge", inputs: { valeur: { classPropertyName: "valeur", publicName: "valeur", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, ton: { classPropertyName: "ton", publicName: "ton", isSignal: true, isRequired: false, transformFunction: null }, point: { classPropertyName: "point", publicName: "point", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "aria-hidden": "true" }, properties: { "attr.data-ton": "ton()", "attr.data-point": "point() ? \"\" : null" }, classAttribute: "st-badge" }, ngImport: i0, template: "{{ texte() }}\n", styles: [":host{display:inline-flex;align-items:center;justify-content:center;min-inline-size:1.25rem;block-size:1.25rem;padding-inline:var(--st-espacement-1);font-size:var(--st-taille-xs);font-weight:var(--st-graisse-semi);line-height:1;color:var(--st-couleur-sur-danger);background:var(--st-couleur-danger);border:2px solid var(--st-couleur-surface);border-radius:var(--st-rayon-pleine)}:host([data-point]){inline-size:.5rem;min-inline-size:0;block-size:.5rem;padding:0}:host([data-ton=neutre]){color:var(--st-couleur-texte);background:var(--st-couleur-surface-enfoncee)}:host([data-ton=primaire]){color:var(--st-couleur-sur-primaire);background:var(--st-couleur-primaire)}:host([data-ton=succes]){color:var(--st-couleur-sur-succes);background:var(--st-couleur-succes)}:host([data-ton=avertissement]){color:var(--st-couleur-sur-avertissement);background:var(--st-couleur-avertissement)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1472
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StBadge, isStandalone: true, selector: "st-badge", inputs: { valeur: { classPropertyName: "valeur", publicName: "valeur", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, ton: { classPropertyName: "ton", publicName: "ton", isSignal: true, isRequired: false, transformFunction: null }, point: { classPropertyName: "point", publicName: "point", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "aria-hidden": "true" }, properties: { "attr.data-ton": "ton()", "attr.data-point": "point() ? \"\" : null" }, classAttribute: "st-badge" }, ngImport: i0, template: "{{ texte() }}\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:inline-flex;align-items:center;justify-content:center;min-inline-size:1.25rem;block-size:1.25rem;padding-inline:var(--st-espacement-1);font-size:var(--st-taille-xs);font-weight:var(--st-graisse-semi);line-height:1;color:var(--st-couleur-sur-danger);background:var(--st-couleur-danger);border:2px solid var(--st-couleur-surface);border-radius:var(--st-rayon-pleine)}:host([data-point]){inline-size:.5rem;min-inline-size:0;block-size:.5rem;padding:0}:host([data-ton=neutre]){color:var(--st-couleur-texte);background:var(--st-couleur-surface-enfoncee)}:host([data-ton=primaire]){color:var(--st-couleur-sur-primaire);background:var(--st-couleur-primaire)}:host([data-ton=succes]){color:var(--st-couleur-sur-succes);background:var(--st-couleur-succes)}:host([data-ton=avertissement]){color:var(--st-couleur-sur-avertissement);background:var(--st-couleur-avertissement)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1216
1473
  }
1217
1474
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StBadge, decorators: [{
1218
1475
  type: Component,
@@ -1221,7 +1478,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
1221
1478
  'aria-hidden': 'true',
1222
1479
  '[attr.data-ton]': 'ton()',
1223
1480
  '[attr.data-point]': 'point() ? "" : null',
1224
- }, template: "{{ texte() }}\n", styles: [":host{display:inline-flex;align-items:center;justify-content:center;min-inline-size:1.25rem;block-size:1.25rem;padding-inline:var(--st-espacement-1);font-size:var(--st-taille-xs);font-weight:var(--st-graisse-semi);line-height:1;color:var(--st-couleur-sur-danger);background:var(--st-couleur-danger);border:2px solid var(--st-couleur-surface);border-radius:var(--st-rayon-pleine)}:host([data-point]){inline-size:.5rem;min-inline-size:0;block-size:.5rem;padding:0}:host([data-ton=neutre]){color:var(--st-couleur-texte);background:var(--st-couleur-surface-enfoncee)}:host([data-ton=primaire]){color:var(--st-couleur-sur-primaire);background:var(--st-couleur-primaire)}:host([data-ton=succes]){color:var(--st-couleur-sur-succes);background:var(--st-couleur-succes)}:host([data-ton=avertissement]){color:var(--st-couleur-sur-avertissement);background:var(--st-couleur-avertissement)}\n"] }]
1481
+ }, template: "{{ texte() }}\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:inline-flex;align-items:center;justify-content:center;min-inline-size:1.25rem;block-size:1.25rem;padding-inline:var(--st-espacement-1);font-size:var(--st-taille-xs);font-weight:var(--st-graisse-semi);line-height:1;color:var(--st-couleur-sur-danger);background:var(--st-couleur-danger);border:2px solid var(--st-couleur-surface);border-radius:var(--st-rayon-pleine)}:host([data-point]){inline-size:.5rem;min-inline-size:0;block-size:.5rem;padding:0}:host([data-ton=neutre]){color:var(--st-couleur-texte);background:var(--st-couleur-surface-enfoncee)}:host([data-ton=primaire]){color:var(--st-couleur-sur-primaire);background:var(--st-couleur-primaire)}:host([data-ton=succes]){color:var(--st-couleur-sur-succes);background:var(--st-couleur-succes)}:host([data-ton=avertissement]){color:var(--st-couleur-sur-avertissement);background:var(--st-couleur-avertissement)}\n"] }]
1225
1482
  }], propDecorators: { valeur: [{ type: i0.Input, args: [{ isSignal: true, alias: "valeur", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], ton: [{ type: i0.Input, args: [{ isSignal: true, alias: "ton", required: false }] }], point: [{ type: i0.Input, args: [{ isSignal: true, alias: "point", required: false }] }] } });
1226
1483
 
1227
1484
  /**
@@ -1271,14 +1528,14 @@ class StTag {
1271
1528
  parent.focus();
1272
1529
  }
1273
1530
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StTag, deps: [], target: i0.ɵɵFactoryTarget.Component });
1274
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StTag, isStandalone: true, selector: "st-tag", inputs: { libelle: { classPropertyName: "libelle", publicName: "libelle", isSignal: true, isRequired: true, transformFunction: null }, supprimable: { classPropertyName: "supprimable", publicName: "supprimable", isSignal: true, isRequired: false, transformFunction: null }, ton: { classPropertyName: "ton", publicName: "ton", isSignal: true, isRequired: false, transformFunction: null }, prefixeDeSuppression: { classPropertyName: "prefixeDeSuppression", publicName: "prefixeDeSuppression", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { supprime: "supprime" }, host: { properties: { "attr.data-ton": "ton()" }, classAttribute: "st-tag" }, ngImport: i0, template: "<span class=\"st-tag__libelle\">{{ libelle() }}</span>\n\n@if (supprimable()) {\n <!-- eslint-disable-next-line @angular-eslint/template/elements-content --\n Le contenu vient du gabarit de stIconButton. Le nom accessible est\n impose par le type (`etiquette` est requis) et verifie par axe. -->\n <button\n stIconButton\n type=\"button\"\n icone=\"croix\"\n taille=\"sm\"\n [etiquette]=\"libelleDeSuppression()\"\n (click)=\"auRetrait()\"\n ></button>\n}\n", styles: [":host{display:inline-flex;gap:var(--st-espacement-1);align-items:center;min-block-size:2rem;padding-block:var(--st-espacement-1);padding-inline:var(--st-espacement-3);font-size:var(--st-taille-sm);color:var(--st-couleur-texte);background:var(--st-couleur-surface-enfoncee);border:1px solid var(--st-couleur-bordure);border-radius:var(--st-rayon-sm)}:host([data-ton=primaire]){color:var(--st-couleur-sur-primaire-discret);background:var(--st-couleur-primaire-discret);border-color:transparent}:host ::ng-deep .st-icon-button{min-inline-size:1.5rem;min-block-size:1.5rem}@media(pointer:coarse){:host ::ng-deep .st-icon-button{min-inline-size:var(--st-cible-tactile-min);min-block-size:var(--st-cible-tactile-min)}}\n"], dependencies: [{ kind: "component", type: StIconButton, selector: "button[stIconButton]", inputs: ["icone", "etiquette", "variante", "taille", "enfonce"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1531
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StTag, isStandalone: true, selector: "st-tag", inputs: { libelle: { classPropertyName: "libelle", publicName: "libelle", isSignal: true, isRequired: true, transformFunction: null }, supprimable: { classPropertyName: "supprimable", publicName: "supprimable", isSignal: true, isRequired: false, transformFunction: null }, ton: { classPropertyName: "ton", publicName: "ton", isSignal: true, isRequired: false, transformFunction: null }, prefixeDeSuppression: { classPropertyName: "prefixeDeSuppression", publicName: "prefixeDeSuppression", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { supprime: "supprime" }, host: { properties: { "attr.data-ton": "ton()" }, classAttribute: "st-tag" }, ngImport: i0, template: "<span class=\"st-tag__libelle\">{{ libelle() }}</span>\n\n@if (supprimable()) {\n <!-- eslint-disable-next-line @angular-eslint/template/elements-content --\n Le contenu vient du gabarit de stIconButton. Le nom accessible est\n impose par le type (`etiquette` est requis) et verifie par axe. -->\n <button\n stIconButton\n type=\"button\"\n icone=\"croix\"\n taille=\"sm\"\n [etiquette]=\"libelleDeSuppression()\"\n (click)=\"auRetrait()\"\n ></button>\n}\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:inline-flex;gap:var(--st-espacement-1);align-items:center;min-block-size:2rem;padding-block:var(--st-espacement-1);padding-inline:var(--st-espacement-3);font-size:var(--st-taille-sm);color:var(--st-couleur-texte);background:var(--st-couleur-surface-enfoncee);border:1px solid var(--st-couleur-bordure);border-radius:var(--st-rayon-sm)}:host([data-ton=primaire]){color:var(--st-couleur-sur-primaire-discret);background:var(--st-couleur-primaire-discret);border-color:transparent}:host ::ng-deep .st-icon-button{min-inline-size:1.5rem;min-block-size:1.5rem}@media(pointer:coarse){:host ::ng-deep .st-icon-button{min-inline-size:var(--st-cible-tactile-min);min-block-size:var(--st-cible-tactile-min)}}\n"], dependencies: [{ kind: "component", type: StIconButton, selector: "button[stIconButton]", inputs: ["icone", "etiquette", "variante", "taille", "enfonce"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1275
1532
  }
1276
1533
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StTag, decorators: [{
1277
1534
  type: Component,
1278
1535
  args: [{ selector: 'st-tag', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StIconButton], host: {
1279
1536
  class: 'st-tag',
1280
1537
  '[attr.data-ton]': 'ton()',
1281
- }, template: "<span class=\"st-tag__libelle\">{{ libelle() }}</span>\n\n@if (supprimable()) {\n <!-- eslint-disable-next-line @angular-eslint/template/elements-content --\n Le contenu vient du gabarit de stIconButton. Le nom accessible est\n impose par le type (`etiquette` est requis) et verifie par axe. -->\n <button\n stIconButton\n type=\"button\"\n icone=\"croix\"\n taille=\"sm\"\n [etiquette]=\"libelleDeSuppression()\"\n (click)=\"auRetrait()\"\n ></button>\n}\n", styles: [":host{display:inline-flex;gap:var(--st-espacement-1);align-items:center;min-block-size:2rem;padding-block:var(--st-espacement-1);padding-inline:var(--st-espacement-3);font-size:var(--st-taille-sm);color:var(--st-couleur-texte);background:var(--st-couleur-surface-enfoncee);border:1px solid var(--st-couleur-bordure);border-radius:var(--st-rayon-sm)}:host([data-ton=primaire]){color:var(--st-couleur-sur-primaire-discret);background:var(--st-couleur-primaire-discret);border-color:transparent}:host ::ng-deep .st-icon-button{min-inline-size:1.5rem;min-block-size:1.5rem}@media(pointer:coarse){:host ::ng-deep .st-icon-button{min-inline-size:var(--st-cible-tactile-min);min-block-size:var(--st-cible-tactile-min)}}\n"] }]
1538
+ }, template: "<span class=\"st-tag__libelle\">{{ libelle() }}</span>\n\n@if (supprimable()) {\n <!-- eslint-disable-next-line @angular-eslint/template/elements-content --\n Le contenu vient du gabarit de stIconButton. Le nom accessible est\n impose par le type (`etiquette` est requis) et verifie par axe. -->\n <button\n stIconButton\n type=\"button\"\n icone=\"croix\"\n taille=\"sm\"\n [etiquette]=\"libelleDeSuppression()\"\n (click)=\"auRetrait()\"\n ></button>\n}\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:inline-flex;gap:var(--st-espacement-1);align-items:center;min-block-size:2rem;padding-block:var(--st-espacement-1);padding-inline:var(--st-espacement-3);font-size:var(--st-taille-sm);color:var(--st-couleur-texte);background:var(--st-couleur-surface-enfoncee);border:1px solid var(--st-couleur-bordure);border-radius:var(--st-rayon-sm)}:host([data-ton=primaire]){color:var(--st-couleur-sur-primaire-discret);background:var(--st-couleur-primaire-discret);border-color:transparent}:host ::ng-deep .st-icon-button{min-inline-size:1.5rem;min-block-size:1.5rem}@media(pointer:coarse){:host ::ng-deep .st-icon-button{min-inline-size:var(--st-cible-tactile-min);min-block-size:var(--st-cible-tactile-min)}}\n"] }]
1282
1539
  }], propDecorators: { libelle: [{ type: i0.Input, args: [{ isSignal: true, alias: "libelle", required: true }] }], supprimable: [{ type: i0.Input, args: [{ isSignal: true, alias: "supprimable", required: false }] }], ton: [{ type: i0.Input, args: [{ isSignal: true, alias: "ton", required: false }] }], prefixeDeSuppression: [{ type: i0.Input, args: [{ isSignal: true, alias: "prefixeDeSuppression", required: false }] }], supprime: [{ type: i0.Output, args: ["supprime"] }] } });
1283
1540
 
1284
1541
  /**
@@ -1333,7 +1590,7 @@ class StAvatar {
1333
1590
  this.imageEchouee.set(true);
1334
1591
  }
1335
1592
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StAvatar, deps: [], target: i0.ɵɵFactoryTarget.Component });
1336
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StAvatar, isStandalone: true, selector: "st-avatar", inputs: { nom: { classPropertyName: "nom", publicName: "nom", isSignal: true, isRequired: true, transformFunction: null }, sourceImage: { classPropertyName: "sourceImage", publicName: "sourceImage", isSignal: true, isRequired: false, transformFunction: null }, taille: { classPropertyName: "taille", publicName: "taille", isSignal: true, isRequired: false, transformFunction: null }, forme: { classPropertyName: "forme", publicName: "forme", isSignal: true, isRequired: false, transformFunction: null }, nomAdjacent: { classPropertyName: "nomAdjacent", publicName: "nomAdjacent", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-taille": "taille()", "attr.data-forme": "forme()" }, classAttribute: "st-avatar" }, ngImport: i0, template: "@if (afficheLImage()) {\n <!-- eslint-disable-next-line @angular-eslint/template/prefer-ngsrc --\n NgOptimizedImage exige des dimensions statiques ou un chargeur configure.\n Une photo de profil vient d'une URL tierce de dimensions inconnues, et\n optimiser une image de 40 px ne rapporte rien. -->\n <img [src]=\"sourceImage()\" [alt]=\"texteAlternatif()\" (error)=\"auxEchecsDImage()\" />\n} @else {\n <span class=\"st-avatar__initiales\" [attr.aria-hidden]=\"nomAdjacent() ? 'true' : null\">{{\n initiales()\n }}</span>\n @if (!nomAdjacent()) {\n <span class=\"st-vh\">{{ nom() }}</span>\n }\n}\n", styles: [":host{display:inline-flex;flex:none;align-items:center;justify-content:center;inline-size:var(--st-avatar-taille, 2.5rem);block-size:var(--st-avatar-taille, 2.5rem);overflow:hidden;color:var(--st-couleur-sur-primaire-discret);background:var(--st-couleur-primaire-discret);border-radius:var(--st-rayon-pleine)}img{inline-size:100%;block-size:100%;object-fit:cover}.st-avatar__initiales{font-size:.4em;font-weight:var(--st-graisse-semi);line-height:1;letter-spacing:.02em}:host([data-forme=carre]){border-radius:var(--st-rayon-md)}:host([data-taille=xs]){--st-avatar-taille: 1.5rem}:host([data-taille=sm]){--st-avatar-taille: 2rem}:host([data-taille=lg]){--st-avatar-taille: 4rem}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1593
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StAvatar, isStandalone: true, selector: "st-avatar", inputs: { nom: { classPropertyName: "nom", publicName: "nom", isSignal: true, isRequired: true, transformFunction: null }, sourceImage: { classPropertyName: "sourceImage", publicName: "sourceImage", isSignal: true, isRequired: false, transformFunction: null }, taille: { classPropertyName: "taille", publicName: "taille", isSignal: true, isRequired: false, transformFunction: null }, forme: { classPropertyName: "forme", publicName: "forme", isSignal: true, isRequired: false, transformFunction: null }, nomAdjacent: { classPropertyName: "nomAdjacent", publicName: "nomAdjacent", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-taille": "taille()", "attr.data-forme": "forme()" }, classAttribute: "st-avatar" }, ngImport: i0, template: "@if (afficheLImage()) {\n <!-- eslint-disable-next-line @angular-eslint/template/prefer-ngsrc --\n NgOptimizedImage exige des dimensions statiques ou un chargeur configure.\n Une photo de profil vient d'une URL tierce de dimensions inconnues, et\n optimiser une image de 40 px ne rapporte rien. -->\n <img [src]=\"sourceImage()\" [alt]=\"texteAlternatif()\" (error)=\"auxEchecsDImage()\" />\n} @else {\n <span class=\"st-avatar__initiales\" [attr.aria-hidden]=\"nomAdjacent() ? 'true' : null\">{{\n initiales()\n }}</span>\n @if (!nomAdjacent()) {\n <span class=\"st-vh\">{{ nom() }}</span>\n }\n}\n", styles: [":host([hidden]){display:none!important}:host{display:inline-flex;flex:none;align-items:center;justify-content:center;inline-size:var(--st-avatar-taille, 2.5rem);block-size:var(--st-avatar-taille, 2.5rem);overflow:hidden;color:var(--st-couleur-sur-primaire-discret);background:var(--st-couleur-primaire-discret);border-radius:var(--st-rayon-pleine)}img{inline-size:100%;block-size:100%;object-fit:cover}.st-avatar__initiales{font-size:.4em;font-weight:var(--st-graisse-semi);line-height:1;letter-spacing:.02em}:host([data-forme=carre]){border-radius:var(--st-rayon-md)}:host([data-taille=xs]){--st-avatar-taille: 1.5rem}:host([data-taille=sm]){--st-avatar-taille: 2rem}:host([data-taille=lg]){--st-avatar-taille: 4rem}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1337
1594
  }
1338
1595
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StAvatar, decorators: [{
1339
1596
  type: Component,
@@ -1341,7 +1598,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
1341
1598
  class: 'st-avatar',
1342
1599
  '[attr.data-taille]': 'taille()',
1343
1600
  '[attr.data-forme]': 'forme()',
1344
- }, template: "@if (afficheLImage()) {\n <!-- eslint-disable-next-line @angular-eslint/template/prefer-ngsrc --\n NgOptimizedImage exige des dimensions statiques ou un chargeur configure.\n Une photo de profil vient d'une URL tierce de dimensions inconnues, et\n optimiser une image de 40 px ne rapporte rien. -->\n <img [src]=\"sourceImage()\" [alt]=\"texteAlternatif()\" (error)=\"auxEchecsDImage()\" />\n} @else {\n <span class=\"st-avatar__initiales\" [attr.aria-hidden]=\"nomAdjacent() ? 'true' : null\">{{\n initiales()\n }}</span>\n @if (!nomAdjacent()) {\n <span class=\"st-vh\">{{ nom() }}</span>\n }\n}\n", styles: [":host{display:inline-flex;flex:none;align-items:center;justify-content:center;inline-size:var(--st-avatar-taille, 2.5rem);block-size:var(--st-avatar-taille, 2.5rem);overflow:hidden;color:var(--st-couleur-sur-primaire-discret);background:var(--st-couleur-primaire-discret);border-radius:var(--st-rayon-pleine)}img{inline-size:100%;block-size:100%;object-fit:cover}.st-avatar__initiales{font-size:.4em;font-weight:var(--st-graisse-semi);line-height:1;letter-spacing:.02em}:host([data-forme=carre]){border-radius:var(--st-rayon-md)}:host([data-taille=xs]){--st-avatar-taille: 1.5rem}:host([data-taille=sm]){--st-avatar-taille: 2rem}:host([data-taille=lg]){--st-avatar-taille: 4rem}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"] }]
1601
+ }, template: "@if (afficheLImage()) {\n <!-- eslint-disable-next-line @angular-eslint/template/prefer-ngsrc --\n NgOptimizedImage exige des dimensions statiques ou un chargeur configure.\n Une photo de profil vient d'une URL tierce de dimensions inconnues, et\n optimiser une image de 40 px ne rapporte rien. -->\n <img [src]=\"sourceImage()\" [alt]=\"texteAlternatif()\" (error)=\"auxEchecsDImage()\" />\n} @else {\n <span class=\"st-avatar__initiales\" [attr.aria-hidden]=\"nomAdjacent() ? 'true' : null\">{{\n initiales()\n }}</span>\n @if (!nomAdjacent()) {\n <span class=\"st-vh\">{{ nom() }}</span>\n }\n}\n", styles: [":host([hidden]){display:none!important}:host{display:inline-flex;flex:none;align-items:center;justify-content:center;inline-size:var(--st-avatar-taille, 2.5rem);block-size:var(--st-avatar-taille, 2.5rem);overflow:hidden;color:var(--st-couleur-sur-primaire-discret);background:var(--st-couleur-primaire-discret);border-radius:var(--st-rayon-pleine)}img{inline-size:100%;block-size:100%;object-fit:cover}.st-avatar__initiales{font-size:.4em;font-weight:var(--st-graisse-semi);line-height:1;letter-spacing:.02em}:host([data-forme=carre]){border-radius:var(--st-rayon-md)}:host([data-taille=xs]){--st-avatar-taille: 1.5rem}:host([data-taille=sm]){--st-avatar-taille: 2rem}:host([data-taille=lg]){--st-avatar-taille: 4rem}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"] }]
1345
1602
  }], propDecorators: { nom: [{ type: i0.Input, args: [{ isSignal: true, alias: "nom", required: true }] }], sourceImage: [{ type: i0.Input, args: [{ isSignal: true, alias: "sourceImage", required: false }] }], taille: [{ type: i0.Input, args: [{ isSignal: true, alias: "taille", required: false }] }], forme: [{ type: i0.Input, args: [{ isSignal: true, alias: "forme", required: false }] }], nomAdjacent: [{ type: i0.Input, args: [{ isSignal: true, alias: "nomAdjacent", required: false }] }] } });
1346
1603
 
1347
1604
  /**
@@ -1361,14 +1618,14 @@ class StEmpty {
1361
1618
  niveauDuTitre = input(3, /* @ts-ignore */
1362
1619
  ...(ngDevMode ? [{ debugName: "niveauDuTitre" }] : /* istanbul ignore next */ []));
1363
1620
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StEmpty, deps: [], target: i0.ɵɵFactoryTarget.Component });
1364
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StEmpty, isStandalone: true, selector: "st-empty", inputs: { titre: { classPropertyName: "titre", publicName: "titre", isSignal: true, isRequired: true, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, icone: { classPropertyName: "icone", publicName: "icone", isSignal: true, isRequired: false, transformFunction: null }, niveauDuTitre: { classPropertyName: "niveauDuTitre", publicName: "niveauDuTitre", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "st-empty" }, ngImport: i0, template: "<st-icon [nom]=\"icone()\" taille=\"xl\" ton=\"discret\" />\n<st-heading [niveau]=\"niveauDuTitre()\" taille=\"lg\">{{ titre() }}</st-heading>\n@if (description(); as texte) {\n <st-text variante=\"discret\">{{ texte }}</st-text>\n}\n<div class=\"st-empty__action\"><ng-content /></div>\n", styles: [":host{display:flex;flex-direction:column;gap:var(--st-espacement-3);align-items:center;justify-content:center;min-block-size:12rem;padding:var(--st-espacement-8);text-align:center}.st-empty__action:empty{display:none}\n"], dependencies: [{ kind: "component", type: StIcon, selector: "st-icon", inputs: ["nom", "taille", "ton", "etiquette"] }, { kind: "component", type: StHeading, selector: "st-heading", inputs: ["niveau", "taille", "identifiant"] }, { kind: "component", type: StText, selector: "st-text", inputs: ["variante", "graisse", "enLigne", "tronquerA"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1621
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StEmpty, isStandalone: true, selector: "st-empty", inputs: { titre: { classPropertyName: "titre", publicName: "titre", isSignal: true, isRequired: true, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, icone: { classPropertyName: "icone", publicName: "icone", isSignal: true, isRequired: false, transformFunction: null }, niveauDuTitre: { classPropertyName: "niveauDuTitre", publicName: "niveauDuTitre", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "st-empty" }, ngImport: i0, template: "<st-icon [nom]=\"icone()\" taille=\"xl\" ton=\"discret\" />\n<st-heading [niveau]=\"niveauDuTitre()\" taille=\"lg\">{{ titre() }}</st-heading>\n@if (description(); as texte) {\n <st-text variante=\"discret\">{{ texte }}</st-text>\n}\n<div class=\"st-empty__action\"><ng-content /></div>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:flex;flex-direction:column;gap:var(--st-espacement-3);align-items:center;justify-content:center;min-block-size:12rem;padding:var(--st-espacement-8);text-align:center}.st-empty__action:empty{display:none}\n"], dependencies: [{ kind: "component", type: StIcon, selector: "st-icon", inputs: ["nom", "taille", "ton", "etiquette"] }, { kind: "component", type: StHeading, selector: "st-heading", inputs: ["niveau", "taille", "identifiant"] }, { kind: "component", type: StText, selector: "st-text", inputs: ["variante", "graisse", "enLigne", "tronquerA"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1365
1622
  }
1366
1623
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StEmpty, decorators: [{
1367
1624
  type: Component,
1368
- args: [{ selector: 'st-empty', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StIcon, StHeading, StText], host: { class: 'st-empty' }, template: "<st-icon [nom]=\"icone()\" taille=\"xl\" ton=\"discret\" />\n<st-heading [niveau]=\"niveauDuTitre()\" taille=\"lg\">{{ titre() }}</st-heading>\n@if (description(); as texte) {\n <st-text variante=\"discret\">{{ texte }}</st-text>\n}\n<div class=\"st-empty__action\"><ng-content /></div>\n", styles: [":host{display:flex;flex-direction:column;gap:var(--st-espacement-3);align-items:center;justify-content:center;min-block-size:12rem;padding:var(--st-espacement-8);text-align:center}.st-empty__action:empty{display:none}\n"] }]
1625
+ args: [{ selector: 'st-empty', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StIcon, StHeading, StText], host: { class: 'st-empty' }, template: "<st-icon [nom]=\"icone()\" taille=\"xl\" ton=\"discret\" />\n<st-heading [niveau]=\"niveauDuTitre()\" taille=\"lg\">{{ titre() }}</st-heading>\n@if (description(); as texte) {\n <st-text variante=\"discret\">{{ texte }}</st-text>\n}\n<div class=\"st-empty__action\"><ng-content /></div>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:flex;flex-direction:column;gap:var(--st-espacement-3);align-items:center;justify-content:center;min-block-size:12rem;padding:var(--st-espacement-8);text-align:center}.st-empty__action:empty{display:none}\n"] }]
1369
1626
  }], propDecorators: { titre: [{ type: i0.Input, args: [{ isSignal: true, alias: "titre", required: true }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], icone: [{ type: i0.Input, args: [{ isSignal: true, alias: "icone", required: false }] }], niveauDuTitre: [{ type: i0.Input, args: [{ isSignal: true, alias: "niveauDuTitre", required: false }] }] } });
1370
1627
 
1371
- const ICONE = {
1628
+ const ICONE$2 = {
1372
1629
  'hors-ligne': 'hors-ligne',
1373
1630
  serveur: 'serveur',
1374
1631
  client: 'triangle-alerte',
@@ -1415,12 +1672,12 @@ class StError {
1415
1672
  ...(ngDevMode ? [{ debugName: "etiquetteDeTraceLue" }] : /* istanbul ignore next */ []));
1416
1673
  etiquetteDuCode = computed(() => this.libelles().codeTechnique, /* @ts-ignore */
1417
1674
  ...(ngDevMode ? [{ debugName: "etiquetteDuCode" }] : /* istanbul ignore next */ []));
1418
- icone = computed(() => ICONE[this.variante()], /* @ts-ignore */
1675
+ icone = computed(() => ICONE$2[this.variante()], /* @ts-ignore */
1419
1676
  ...(ngDevMode ? [{ debugName: "icone" }] : /* istanbul ignore next */ []));
1420
1677
  sAnnonce = computed(() => this.regionParente === null, /* @ts-ignore */
1421
1678
  ...(ngDevMode ? [{ debugName: "sAnnonce" }] : /* istanbul ignore next */ []));
1422
1679
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StError, deps: [], target: i0.ɵɵFactoryTarget.Component });
1423
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StError, isStandalone: true, selector: "st-error", inputs: { variante: { classPropertyName: "variante", publicName: "variante", isSignal: true, isRequired: false, transformFunction: null }, code: { classPropertyName: "code", publicName: "code", isSignal: true, isRequired: true, transformFunction: null }, titre: { classPropertyName: "titre", publicName: "titre", isSignal: true, isRequired: true, transformFunction: null }, message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null }, traceId: { classPropertyName: "traceId", publicName: "traceId", isSignal: true, isRequired: false, transformFunction: null }, niveauDuTitre: { classPropertyName: "niveauDuTitre", publicName: "niveauDuTitre", isSignal: true, isRequired: false, transformFunction: null }, rejouable: { classPropertyName: "rejouable", publicName: "rejouable", isSignal: true, isRequired: false, transformFunction: null }, rejeuEnCours: { classPropertyName: "rejeuEnCours", publicName: "rejeuEnCours", isSignal: true, isRequired: false, transformFunction: null }, libelleRejeu: { classPropertyName: "libelleRejeu", publicName: "libelleRejeu", isSignal: true, isRequired: false, transformFunction: null }, etiquetteDeTrace: { classPropertyName: "etiquetteDeTrace", publicName: "etiquetteDeTrace", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { rejeu: "rejeu" }, host: { properties: { "attr.data-variante": "variante()", "attr.role": "sAnnonce() ? \"alert\" : null" }, classAttribute: "st-error" }, ngImport: i0, template: "<st-icon [nom]=\"icone()\" taille=\"lg\" />\n\n<div class=\"st-error__corps\">\n <st-heading [niveau]=\"niveauDuTitre()\" taille=\"lg\">{{ titre() }}</st-heading>\n <st-text variante=\"corps-sm\">{{ message() }}</st-text>\n\n <p class=\"st-error__technique\">\n <st-code [valeur]=\"code()\" [etiquette]=\"etiquetteDuCode()\" [copiable]=\"false\" />\n @if (traceId(); as trace) {\n <st-code [valeur]=\"trace\" [etiquette]=\"etiquetteDeTraceLue()\" />\n }\n </p>\n\n @if (rejouable()) {\n <button\n stButton\n type=\"button\"\n variante=\"secondaire\"\n [chargement]=\"rejeuEnCours()\"\n (click)=\"rejeu.emit()\"\n >\n {{ libelleRejeuLu() }}\n </button>\n }\n</div>\n", styles: [":host{display:flex;gap:var(--st-espacement-3);align-items:flex-start;padding:var(--st-espacement-4);color:var(--st-couleur-sur-danger-discret);background:var(--st-couleur-danger-discret);border-inline-start:3px solid var(--st-couleur-danger);border-radius:var(--st-rayon-md)}:host([data-variante=hors-ligne]){color:var(--st-couleur-sur-avertissement-discret);background:var(--st-couleur-avertissement-discret);border-inline-start-color:var(--st-couleur-avertissement)}.st-error__corps{display:flex;flex:1;flex-direction:column;gap:var(--st-espacement-2);align-items:flex-start}.st-error__technique{display:flex;flex-wrap:wrap;gap:var(--st-espacement-2);margin:0}\n"], dependencies: [{ kind: "component", type: StIcon, selector: "st-icon", inputs: ["nom", "taille", "ton", "etiquette"] }, { kind: "component", type: StHeading, selector: "st-heading", inputs: ["niveau", "taille", "identifiant"] }, { kind: "component", type: StText, selector: "st-text", inputs: ["variante", "graisse", "enLigne", "tronquerA"] }, { kind: "component", type: StButton, selector: "button[stButton]", inputs: ["variante", "taille", "pleineLargeur", "iconeAvant", "iconeApres", "chargement"] }, { kind: "component", type: StCode, selector: "st-code", inputs: ["valeur", "copiable", "etiquette", "libelleCopier", "messageDeConfirmation"], outputs: ["copie"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1680
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StError, isStandalone: true, selector: "st-error", inputs: { variante: { classPropertyName: "variante", publicName: "variante", isSignal: true, isRequired: false, transformFunction: null }, code: { classPropertyName: "code", publicName: "code", isSignal: true, isRequired: true, transformFunction: null }, titre: { classPropertyName: "titre", publicName: "titre", isSignal: true, isRequired: true, transformFunction: null }, message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null }, traceId: { classPropertyName: "traceId", publicName: "traceId", isSignal: true, isRequired: false, transformFunction: null }, niveauDuTitre: { classPropertyName: "niveauDuTitre", publicName: "niveauDuTitre", isSignal: true, isRequired: false, transformFunction: null }, rejouable: { classPropertyName: "rejouable", publicName: "rejouable", isSignal: true, isRequired: false, transformFunction: null }, rejeuEnCours: { classPropertyName: "rejeuEnCours", publicName: "rejeuEnCours", isSignal: true, isRequired: false, transformFunction: null }, libelleRejeu: { classPropertyName: "libelleRejeu", publicName: "libelleRejeu", isSignal: true, isRequired: false, transformFunction: null }, etiquetteDeTrace: { classPropertyName: "etiquetteDeTrace", publicName: "etiquetteDeTrace", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { rejeu: "rejeu" }, host: { properties: { "attr.data-variante": "variante()", "attr.role": "sAnnonce() ? \"alert\" : null" }, classAttribute: "st-error" }, ngImport: i0, template: "<st-icon [nom]=\"icone()\" taille=\"lg\" />\n\n<div class=\"st-error__corps\">\n <st-heading [niveau]=\"niveauDuTitre()\" taille=\"lg\">{{ titre() }}</st-heading>\n <st-text variante=\"corps-sm\">{{ message() }}</st-text>\n\n <p class=\"st-error__technique\">\n <st-code [valeur]=\"code()\" [etiquette]=\"etiquetteDuCode()\" [copiable]=\"false\" />\n @if (traceId(); as trace) {\n <st-code [valeur]=\"trace\" [etiquette]=\"etiquetteDeTraceLue()\" />\n }\n </p>\n\n @if (rejouable()) {\n <button\n stButton\n type=\"button\"\n variante=\"secondaire\"\n [chargement]=\"rejeuEnCours()\"\n (click)=\"rejeu.emit()\"\n >\n {{ libelleRejeuLu() }}\n </button>\n }\n</div>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:flex;gap:var(--st-espacement-3);align-items:flex-start;padding:var(--st-espacement-4);color:var(--st-couleur-sur-danger-discret);background:var(--st-couleur-danger-discret);border-inline-start:3px solid var(--st-couleur-danger);border-radius:var(--st-rayon-md)}:host([data-variante=hors-ligne]){color:var(--st-couleur-sur-avertissement-discret);background:var(--st-couleur-avertissement-discret);border-inline-start-color:var(--st-couleur-avertissement)}.st-error__corps{display:flex;flex:1;flex-direction:column;gap:var(--st-espacement-2);align-items:flex-start}.st-error__technique{display:flex;flex-wrap:wrap;gap:var(--st-espacement-2);margin:0}\n"], dependencies: [{ kind: "component", type: StIcon, selector: "st-icon", inputs: ["nom", "taille", "ton", "etiquette"] }, { kind: "component", type: StHeading, selector: "st-heading", inputs: ["niveau", "taille", "identifiant"] }, { kind: "component", type: StText, selector: "st-text", inputs: ["variante", "graisse", "enLigne", "tronquerA"] }, { kind: "component", type: StButton, selector: "button[stButton]", inputs: ["variante", "taille", "pleineLargeur", "iconeAvant", "iconeApres", "chargement", "indisponible"] }, { kind: "component", type: StCode, selector: "st-code", inputs: ["valeur", "copiable", "etiquette", "libelleCopier", "messageDeConfirmation"], outputs: ["copie"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1424
1681
  }
1425
1682
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StError, decorators: [{
1426
1683
  type: Component,
@@ -1428,7 +1685,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
1428
1685
  class: 'st-error',
1429
1686
  '[attr.data-variante]': 'variante()',
1430
1687
  '[attr.role]': 'sAnnonce() ? "alert" : null',
1431
- }, template: "<st-icon [nom]=\"icone()\" taille=\"lg\" />\n\n<div class=\"st-error__corps\">\n <st-heading [niveau]=\"niveauDuTitre()\" taille=\"lg\">{{ titre() }}</st-heading>\n <st-text variante=\"corps-sm\">{{ message() }}</st-text>\n\n <p class=\"st-error__technique\">\n <st-code [valeur]=\"code()\" [etiquette]=\"etiquetteDuCode()\" [copiable]=\"false\" />\n @if (traceId(); as trace) {\n <st-code [valeur]=\"trace\" [etiquette]=\"etiquetteDeTraceLue()\" />\n }\n </p>\n\n @if (rejouable()) {\n <button\n stButton\n type=\"button\"\n variante=\"secondaire\"\n [chargement]=\"rejeuEnCours()\"\n (click)=\"rejeu.emit()\"\n >\n {{ libelleRejeuLu() }}\n </button>\n }\n</div>\n", styles: [":host{display:flex;gap:var(--st-espacement-3);align-items:flex-start;padding:var(--st-espacement-4);color:var(--st-couleur-sur-danger-discret);background:var(--st-couleur-danger-discret);border-inline-start:3px solid var(--st-couleur-danger);border-radius:var(--st-rayon-md)}:host([data-variante=hors-ligne]){color:var(--st-couleur-sur-avertissement-discret);background:var(--st-couleur-avertissement-discret);border-inline-start-color:var(--st-couleur-avertissement)}.st-error__corps{display:flex;flex:1;flex-direction:column;gap:var(--st-espacement-2);align-items:flex-start}.st-error__technique{display:flex;flex-wrap:wrap;gap:var(--st-espacement-2);margin:0}\n"] }]
1688
+ }, template: "<st-icon [nom]=\"icone()\" taille=\"lg\" />\n\n<div class=\"st-error__corps\">\n <st-heading [niveau]=\"niveauDuTitre()\" taille=\"lg\">{{ titre() }}</st-heading>\n <st-text variante=\"corps-sm\">{{ message() }}</st-text>\n\n <p class=\"st-error__technique\">\n <st-code [valeur]=\"code()\" [etiquette]=\"etiquetteDuCode()\" [copiable]=\"false\" />\n @if (traceId(); as trace) {\n <st-code [valeur]=\"trace\" [etiquette]=\"etiquetteDeTraceLue()\" />\n }\n </p>\n\n @if (rejouable()) {\n <button\n stButton\n type=\"button\"\n variante=\"secondaire\"\n [chargement]=\"rejeuEnCours()\"\n (click)=\"rejeu.emit()\"\n >\n {{ libelleRejeuLu() }}\n </button>\n }\n</div>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:flex;gap:var(--st-espacement-3);align-items:flex-start;padding:var(--st-espacement-4);color:var(--st-couleur-sur-danger-discret);background:var(--st-couleur-danger-discret);border-inline-start:3px solid var(--st-couleur-danger);border-radius:var(--st-rayon-md)}:host([data-variante=hors-ligne]){color:var(--st-couleur-sur-avertissement-discret);background:var(--st-couleur-avertissement-discret);border-inline-start-color:var(--st-couleur-avertissement)}.st-error__corps{display:flex;flex:1;flex-direction:column;gap:var(--st-espacement-2);align-items:flex-start}.st-error__technique{display:flex;flex-wrap:wrap;gap:var(--st-espacement-2);margin:0}\n"] }]
1432
1689
  }], propDecorators: { variante: [{ type: i0.Input, args: [{ isSignal: true, alias: "variante", required: false }] }], code: [{ type: i0.Input, args: [{ isSignal: true, alias: "code", required: true }] }], titre: [{ type: i0.Input, args: [{ isSignal: true, alias: "titre", required: true }] }], message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: true }] }], traceId: [{ type: i0.Input, args: [{ isSignal: true, alias: "traceId", required: false }] }], niveauDuTitre: [{ type: i0.Input, args: [{ isSignal: true, alias: "niveauDuTitre", required: false }] }], rejouable: [{ type: i0.Input, args: [{ isSignal: true, alias: "rejouable", required: false }] }], rejeuEnCours: [{ type: i0.Input, args: [{ isSignal: true, alias: "rejeuEnCours", required: false }] }], libelleRejeu: [{ type: i0.Input, args: [{ isSignal: true, alias: "libelleRejeu", required: false }] }], etiquetteDeTrace: [{ type: i0.Input, args: [{ isSignal: true, alias: "etiquetteDeTrace", required: false }] }], rejeu: [{ type: i0.Output, args: ["rejeu"] }] } });
1433
1690
 
1434
1691
  /**
@@ -1451,16 +1708,2373 @@ class StOfflineBanner {
1451
1708
  rejeuEnCours = input(false, { ...(ngDevMode ? { debugName: "rejeuEnCours" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1452
1709
  rejeu = output();
1453
1710
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StOfflineBanner, deps: [], target: i0.ɵɵFactoryTarget.Component });
1454
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StOfflineBanner, isStandalone: true, selector: "st-offline-banner", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null }, libelleRejeu: { classPropertyName: "libelleRejeu", publicName: "libelleRejeu", isSignal: true, isRequired: false, transformFunction: null }, rejeuEnCours: { classPropertyName: "rejeuEnCours", publicName: "rejeuEnCours", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { rejeu: "rejeu" }, host: { attributes: { "role": "status" }, classAttribute: "st-offline-banner" }, ngImport: i0, template: "<st-icon nom=\"hors-ligne\" taille=\"sm\" />\n<span class=\"st-offline-banner__message\">{{ message() }}</span>\n\n@if (libelleRejeu(); as libelle) {\n <button\n stButton\n type=\"button\"\n variante=\"discret\"\n taille=\"sm\"\n [chargement]=\"rejeuEnCours()\"\n (click)=\"rejeu.emit()\"\n >\n {{ libelle }}\n </button>\n}\n", styles: [":host{position:sticky;inset-block-start:0;z-index:var(--st-plan-entete);display:flex;flex-wrap:wrap;gap:var(--st-espacement-2);align-items:center;min-block-size:2.5rem;padding-block:var(--st-espacement-2);padding-inline:var(--st-espacement-4);color:var(--st-couleur-sur-avertissement-discret);background:var(--st-couleur-avertissement-discret);border-block-end:1px solid var(--st-couleur-avertissement)}.st-offline-banner__message{flex:1;font-size:var(--st-taille-sm)}\n"], dependencies: [{ kind: "component", type: StIcon, selector: "st-icon", inputs: ["nom", "taille", "ton", "etiquette"] }, { kind: "component", type: StButton, selector: "button[stButton]", inputs: ["variante", "taille", "pleineLargeur", "iconeAvant", "iconeApres", "chargement"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1711
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StOfflineBanner, isStandalone: true, selector: "st-offline-banner", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null }, libelleRejeu: { classPropertyName: "libelleRejeu", publicName: "libelleRejeu", isSignal: true, isRequired: false, transformFunction: null }, rejeuEnCours: { classPropertyName: "rejeuEnCours", publicName: "rejeuEnCours", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { rejeu: "rejeu" }, host: { attributes: { "role": "status" }, classAttribute: "st-offline-banner" }, ngImport: i0, template: "<st-icon nom=\"hors-ligne\" taille=\"sm\" />\n<span class=\"st-offline-banner__message\">{{ message() }}</span>\n\n@if (libelleRejeu(); as libelle) {\n <button\n stButton\n type=\"button\"\n variante=\"discret\"\n taille=\"sm\"\n [chargement]=\"rejeuEnCours()\"\n (click)=\"rejeu.emit()\"\n >\n {{ libelle }}\n </button>\n}\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{position:sticky;inset-block-start:0;z-index:var(--st-plan-entete);display:flex;flex-wrap:wrap;gap:var(--st-espacement-2);align-items:center;min-block-size:2.5rem;padding-block:var(--st-espacement-2);padding-inline:var(--st-espacement-4);color:var(--st-couleur-sur-avertissement-discret);background:var(--st-couleur-avertissement-discret);border-block-end:1px solid var(--st-couleur-avertissement)}.st-offline-banner__message{flex:1;font-size:var(--st-taille-sm)}\n"], dependencies: [{ kind: "component", type: StIcon, selector: "st-icon", inputs: ["nom", "taille", "ton", "etiquette"] }, { kind: "component", type: StButton, selector: "button[stButton]", inputs: ["variante", "taille", "pleineLargeur", "iconeAvant", "iconeApres", "chargement", "indisponible"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1455
1712
  }
1456
1713
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StOfflineBanner, decorators: [{
1457
1714
  type: Component,
1458
1715
  args: [{ selector: 'st-offline-banner', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StIcon, StButton], host: {
1459
1716
  class: 'st-offline-banner',
1460
1717
  role: 'status',
1461
- }, template: "<st-icon nom=\"hors-ligne\" taille=\"sm\" />\n<span class=\"st-offline-banner__message\">{{ message() }}</span>\n\n@if (libelleRejeu(); as libelle) {\n <button\n stButton\n type=\"button\"\n variante=\"discret\"\n taille=\"sm\"\n [chargement]=\"rejeuEnCours()\"\n (click)=\"rejeu.emit()\"\n >\n {{ libelle }}\n </button>\n}\n", styles: [":host{position:sticky;inset-block-start:0;z-index:var(--st-plan-entete);display:flex;flex-wrap:wrap;gap:var(--st-espacement-2);align-items:center;min-block-size:2.5rem;padding-block:var(--st-espacement-2);padding-inline:var(--st-espacement-4);color:var(--st-couleur-sur-avertissement-discret);background:var(--st-couleur-avertissement-discret);border-block-end:1px solid var(--st-couleur-avertissement)}.st-offline-banner__message{flex:1;font-size:var(--st-taille-sm)}\n"] }]
1718
+ }, template: "<st-icon nom=\"hors-ligne\" taille=\"sm\" />\n<span class=\"st-offline-banner__message\">{{ message() }}</span>\n\n@if (libelleRejeu(); as libelle) {\n <button\n stButton\n type=\"button\"\n variante=\"discret\"\n taille=\"sm\"\n [chargement]=\"rejeuEnCours()\"\n (click)=\"rejeu.emit()\"\n >\n {{ libelle }}\n </button>\n}\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{position:sticky;inset-block-start:0;z-index:var(--st-plan-entete);display:flex;flex-wrap:wrap;gap:var(--st-espacement-2);align-items:center;min-block-size:2.5rem;padding-block:var(--st-espacement-2);padding-inline:var(--st-espacement-4);color:var(--st-couleur-sur-avertissement-discret);background:var(--st-couleur-avertissement-discret);border-block-end:1px solid var(--st-couleur-avertissement)}.st-offline-banner__message{flex:1;font-size:var(--st-taille-sm)}\n"] }]
1462
1719
  }], propDecorators: { message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: true }] }], libelleRejeu: [{ type: i0.Input, args: [{ isSignal: true, alias: "libelleRejeu", required: false }] }], rejeuEnCours: [{ type: i0.Input, args: [{ isSignal: true, alias: "rejeuEnCours", required: false }] }], rejeu: [{ type: i0.Output, args: ["rejeu"] }] } });
1463
1720
 
1721
+ /**
1722
+ * Surface qui regroupe un contenu.
1723
+ *
1724
+ * ⚠️ **Elle n'est jamais cliquable en entier**, et c'est un refus delibere. Une
1725
+ * carte munie d'un `(click)` produit, pour qui ecoute la page, UN seul controle
1726
+ * dont le nom accessible est tout le texte de la carte — titre, montant, date,
1727
+ * mention legale d'un trait. Elle est aussi injoignable au clavier sans
1728
+ * `tabindex`, qui la ferait alors annoncer deux fois.
1729
+ *
1730
+ * Le motif correct : un lien ou un bouton unique DANS la carte, etendu
1731
+ * visuellement a toute sa surface par la classe `st-carte__lien-etendu`. Le
1732
+ * nom accessible reste celui du lien, le clavier fonctionne sans rien ajouter,
1733
+ * et la zone cliquable est la meme.
1734
+ *
1735
+ * ```html
1736
+ * <st-card>
1737
+ * <st-heading [niveau]="3">
1738
+ * <a class="st-carte__lien-etendu" routerLink="/comptes/12">Compte courant</a>
1739
+ * </st-heading>
1740
+ * <st-money [montant]="solde" />
1741
+ * </st-card>
1742
+ * ```
1743
+ */
1744
+ class StCard {
1745
+ relief = input('pose', /* @ts-ignore */
1746
+ ...(ngDevMode ? [{ debugName: "relief" }] : /* istanbul ignore next */ []));
1747
+ rembourrage = input('md', /* @ts-ignore */
1748
+ ...(ngDevMode ? [{ debugName: "rembourrage" }] : /* istanbul ignore next */ []));
1749
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StCard, deps: [], target: i0.ɵɵFactoryTarget.Component });
1750
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StCard, isStandalone: true, selector: "st-card", inputs: { relief: { classPropertyName: "relief", publicName: "relief", isSignal: true, isRequired: false, transformFunction: null }, rembourrage: { classPropertyName: "rembourrage", publicName: "rembourrage", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-relief": "relief()", "attr.data-rembourrage": "rembourrage()" }, classAttribute: "st-card" }, ngImport: i0, template: "<ng-content />\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{position:relative;display:block;color:var(--st-couleur-texte);background:var(--st-carte-fond, var(--st-couleur-surface));border-radius:var(--st-carte-rayon, var(--st-rayon-lg))}:host([data-relief=plat]){box-shadow:var(--st-ombre-none)}:host([data-relief=pose]){border:1px solid var(--st-couleur-bordure);box-shadow:var(--st-ombre-sm)}:host([data-relief=flottant]){box-shadow:var(--st-ombre-md)}:host([data-rembourrage=aucun]){padding:0}:host([data-rembourrage=sm]){padding:var(--st-espacement-3)}:host([data-rembourrage=md]){padding:var(--st-espacement-4)}:host([data-rembourrage=lg]){padding:var(--st-espacement-6)}@media(forced-colors:active){:host{border:1px solid CanvasText}}:host ::ng-deep .st-carte__lien-etendu:after{position:absolute;inset:0;content:\"\"}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1751
+ }
1752
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StCard, decorators: [{
1753
+ type: Component,
1754
+ args: [{ selector: 'st-card', changeDetection: ChangeDetectionStrategy.OnPush, host: {
1755
+ class: 'st-card',
1756
+ '[attr.data-relief]': 'relief()',
1757
+ '[attr.data-rembourrage]': 'rembourrage()',
1758
+ }, template: "<ng-content />\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{position:relative;display:block;color:var(--st-couleur-texte);background:var(--st-carte-fond, var(--st-couleur-surface));border-radius:var(--st-carte-rayon, var(--st-rayon-lg))}:host([data-relief=plat]){box-shadow:var(--st-ombre-none)}:host([data-relief=pose]){border:1px solid var(--st-couleur-bordure);box-shadow:var(--st-ombre-sm)}:host([data-relief=flottant]){box-shadow:var(--st-ombre-md)}:host([data-rembourrage=aucun]){padding:0}:host([data-rembourrage=sm]){padding:var(--st-espacement-3)}:host([data-rembourrage=md]){padding:var(--st-espacement-4)}:host([data-rembourrage=lg]){padding:var(--st-espacement-6)}@media(forced-colors:active){:host{border:1px solid CanvasText}}:host ::ng-deep .st-carte__lien-etendu:after{position:absolute;inset:0;content:\"\"}\n"] }]
1759
+ }], propDecorators: { relief: [{ type: i0.Input, args: [{ isSignal: true, alias: "relief", required: false }] }], rembourrage: [{ type: i0.Input, args: [{ isSignal: true, alias: "rembourrage", required: false }] }] } });
1760
+
1761
+ /**
1762
+ * Regroupement de contenu, expose comme REPERE de navigation quand il porte un
1763
+ * nom.
1764
+ *
1765
+ * ⚠️ Le point qui decide de tout : `role="region"` n'est expose comme repere
1766
+ * que s'il a un NOM ACCESSIBLE. Sans nom, la plupart des lecteurs d'ecran
1767
+ * l'ignorent purement et simplement — la balise est la, le repere n'existe pas,
1768
+ * et rien ne le signale. Le composant refuse donc de poser le role quand il ne
1769
+ * peut pas le nommer : une section anonyme reste un simple bloc, ce qu'elle est
1770
+ * reellement.
1771
+ *
1772
+ * Deux facons de la nommer, et la seconde vaut mieux : `titreDe` pointe le
1773
+ * titre deja affiche, ce qui garde un seul texte a traduire et a maintenir.
1774
+ *
1775
+ * ```html
1776
+ * <st-heading [niveau]="2" identifiant="titre-operations">Operations</st-heading>
1777
+ * <st-section titreDe="titre-operations">…</st-section>
1778
+ * ```
1779
+ */
1780
+ class StSection {
1781
+ /** Nom accessible ecrit a la main. A preferer `titreDe` quand un titre existe. */
1782
+ etiquette = input(null, /* @ts-ignore */
1783
+ ...(ngDevMode ? [{ debugName: "etiquette" }] : /* istanbul ignore next */ []));
1784
+ /** Identifiant du titre qui nomme la section. Prime sur `etiquette`. */
1785
+ titreDe = input(null, /* @ts-ignore */
1786
+ ...(ngDevMode ? [{ debugName: "titreDe" }] : /* istanbul ignore next */ []));
1787
+ espacement = input('md', /* @ts-ignore */
1788
+ ...(ngDevMode ? [{ debugName: "espacement" }] : /* istanbul ignore next */ []));
1789
+ estUnRepere = computed(() => this.titreDe() !== null || this.etiquette() !== null, /* @ts-ignore */
1790
+ ...(ngDevMode ? [{ debugName: "estUnRepere" }] : /* istanbul ignore next */ []));
1791
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StSection, deps: [], target: i0.ɵɵFactoryTarget.Component });
1792
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StSection, isStandalone: true, selector: "st-section", inputs: { etiquette: { classPropertyName: "etiquette", publicName: "etiquette", isSignal: true, isRequired: false, transformFunction: null }, titreDe: { classPropertyName: "titreDe", publicName: "titreDe", isSignal: true, isRequired: false, transformFunction: null }, espacement: { classPropertyName: "espacement", publicName: "espacement", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.role": "estUnRepere() ? \"region\" : null", "attr.aria-label": "titreDe() === null ? etiquette() : null", "attr.aria-labelledby": "titreDe()", "attr.data-espacement": "espacement()" }, classAttribute: "st-section" }, ngImport: i0, template: "<ng-content />\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block}:host([data-espacement=aucun]){margin-block-end:0}:host([data-espacement=sm]){margin-block-end:var(--st-espacement-4)}:host([data-espacement=md]){margin-block-end:var(--st-espacement-6)}:host([data-espacement=lg]){margin-block-end:var(--st-espacement-8)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1793
+ }
1794
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StSection, decorators: [{
1795
+ type: Component,
1796
+ args: [{ selector: 'st-section', changeDetection: ChangeDetectionStrategy.OnPush, host: {
1797
+ class: 'st-section',
1798
+ '[attr.role]': 'estUnRepere() ? "region" : null',
1799
+ '[attr.aria-label]': 'titreDe() === null ? etiquette() : null',
1800
+ '[attr.aria-labelledby]': 'titreDe()',
1801
+ '[attr.data-espacement]': 'espacement()',
1802
+ }, template: "<ng-content />\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block}:host([data-espacement=aucun]){margin-block-end:0}:host([data-espacement=sm]){margin-block-end:var(--st-espacement-4)}:host([data-espacement=md]){margin-block-end:var(--st-espacement-6)}:host([data-espacement=lg]){margin-block-end:var(--st-espacement-8)}\n"] }]
1803
+ }], propDecorators: { etiquette: [{ type: i0.Input, args: [{ isSignal: true, alias: "etiquette", required: false }] }], titreDe: [{ type: i0.Input, args: [{ isSignal: true, alias: "titreDe", required: false }] }], espacement: [{ type: i0.Input, args: [{ isSignal: true, alias: "espacement", required: false }] }] } });
1804
+
1805
+ /**
1806
+ * Trait de separation.
1807
+ *
1808
+ * ⚠️ **Decoratif par defaut, et c'est le bon defaut.** Un `<hr>` porte le role
1809
+ * `separator` de facon implicite, que les lecteurs d'ecran annoncent. Sur une
1810
+ * page qui en compte huit — ce qui est courant dans une liste de reglages — la
1811
+ * lecture est ponctuee de huit « separateur » qui n'apprennent rien.
1812
+ *
1813
+ * Le role ne se pose que lorsque le trait porte vraiment du sens : il separe
1814
+ * alors deux GROUPES que rien d'autre ne distingue, comme les sections d'un
1815
+ * menu. Regle de tri : si le retirer ne retire aucune information, il est
1816
+ * decoratif.
1817
+ */
1818
+ class StDivider {
1819
+ orientation = input('horizontale', /* @ts-ignore */
1820
+ ...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
1821
+ /** Le trait separe deux groupes distincts, et doit donc etre annonce. */
1822
+ porteurDeSens = input(false, { ...(ngDevMode ? { debugName: "porteurDeSens" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1823
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StDivider, deps: [], target: i0.ɵɵFactoryTarget.Component });
1824
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StDivider, isStandalone: true, selector: "st-divider", inputs: { orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, porteurDeSens: { classPropertyName: "porteurDeSens", publicName: "porteurDeSens", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.role": "porteurDeSens() ? \"separator\" : \"none\"", "attr.aria-hidden": "porteurDeSens() ? null : \"true\"", "attr.aria-orientation": "porteurDeSens() && orientation() === \"verticale\" ? \"vertical\" : null", "attr.data-orientation": "orientation()" }, classAttribute: "st-divider" }, ngImport: i0, template: "", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block;flex:none;background:var(--st-couleur-bordure);border:0}:host([data-orientation=horizontale]){inline-size:100%;block-size:var(--st-separateur-epaisseur, 1px);margin-block:var(--st-separateur-marge, var(--st-espacement-4))}:host([data-orientation=verticale]){inline-size:var(--st-separateur-epaisseur, 1px);align-self:stretch;margin-inline:var(--st-separateur-marge, var(--st-espacement-4))}@media(forced-colors:active){:host{background:CanvasText}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1825
+ }
1826
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StDivider, decorators: [{
1827
+ type: Component,
1828
+ args: [{ selector: 'st-divider', changeDetection: ChangeDetectionStrategy.OnPush, host: {
1829
+ class: 'st-divider',
1830
+ '[attr.role]': 'porteurDeSens() ? "separator" : "none"',
1831
+ '[attr.aria-hidden]': 'porteurDeSens() ? null : "true"',
1832
+ // ⚠️ Annonce seulement quand elle differe du defaut d'ARIA, qui est
1833
+ // horizontal : un `aria-orientation="horizontal"` partout est du bruit.
1834
+ '[attr.aria-orientation]': 'porteurDeSens() && orientation() === "verticale" ? "vertical" : null',
1835
+ '[attr.data-orientation]': 'orientation()',
1836
+ }, template: "", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block;flex:none;background:var(--st-couleur-bordure);border:0}:host([data-orientation=horizontale]){inline-size:100%;block-size:var(--st-separateur-epaisseur, 1px);margin-block:var(--st-separateur-marge, var(--st-espacement-4))}:host([data-orientation=verticale]){inline-size:var(--st-separateur-epaisseur, 1px);align-self:stretch;margin-inline:var(--st-separateur-marge, var(--st-espacement-4))}@media(forced-colors:active){:host{background:CanvasText}}\n"] }]
1837
+ }], propDecorators: { orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], porteurDeSens: [{ type: i0.Input, args: [{ isSignal: true, alias: "porteurDeSens", required: false }] }] } });
1838
+
1839
+ /**
1840
+ * Titre de page : le `h1`, et les actions qui lui sont attachees.
1841
+ *
1842
+ * ⚠️ Il rend une **vraie balise `h1`**, la ou `st-heading` porte
1843
+ * `role="heading"` sur son hote. La raison est precise : `StNavigation` de
1844
+ * `@starterlib/core` vise le titre de niveau 1 pour y poser le focus apres une
1845
+ * navigation, et une vraie balise est ce que trouvent aussi les extensions, le
1846
+ * mode lecture et les outils d'audit. Un `h1` par page, jamais deux.
1847
+ *
1848
+ * ⚠️ **Il ne gere PAS le focus**, et ce n'est pas un oubli. Le noyau le fait
1849
+ * deja a chaque changement de route. Deux mecanismes qui deplacent le focus a
1850
+ * la meme milliseconde ne se completent pas : ils se battent, et le gagnant
1851
+ * depend de l'ordre de rendu — donc du hasard.
1852
+ *
1853
+ * ```html
1854
+ * <st-page-title>
1855
+ * Mes operations
1856
+ * <button stButton variante="primaire" actions>Exporter</button>
1857
+ * </st-page-title>
1858
+ * ```
1859
+ */
1860
+ class StPageTitle {
1861
+ /** Texte secondaire sous le titre. Jamais porteur d'information critique. */
1862
+ precision = input(null, /* @ts-ignore */
1863
+ ...(ngDevMode ? [{ debugName: "precision" }] : /* istanbul ignore next */ []));
1864
+ /** Cible d'un `aria-labelledby` : une region se nomme par son titre. */
1865
+ identifiant = input(null, /* @ts-ignore */
1866
+ ...(ngDevMode ? [{ debugName: "identifiant" }] : /* istanbul ignore next */ []));
1867
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StPageTitle, deps: [], target: i0.ɵɵFactoryTarget.Component });
1868
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StPageTitle, isStandalone: true, selector: "st-page-title", inputs: { precision: { classPropertyName: "precision", publicName: "precision", isSignal: true, isRequired: false, transformFunction: null }, identifiant: { classPropertyName: "identifiant", publicName: "identifiant", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "st-page-title" }, ngImport: i0, template: "<div class=\"st-page-title__ligne\">\n <h1 class=\"st-page-title__titre\" [attr.id]=\"identifiant()\"><ng-content /></h1>\n <div class=\"st-page-title__actions\"><ng-content select=\"[actions]\" /></div>\n</div>\n@if (precision() !== null) {\n <p class=\"st-page-title__precision\">{{ precision() }}</p>\n}\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block;margin-block-end:var(--st-espacement-6)}.st-page-title__ligne{display:flex;flex-wrap:wrap;gap:var(--st-espacement-3);align-items:flex-start;justify-content:space-between}.st-page-title__titre:focus{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-page-title__titre{margin:0;font-family:var(--st-police-base);font-size:var(--st-taille-3xl);font-weight:var(--st-graisse-semi);line-height:var(--st-interligne-serre);color:var(--st-couleur-texte);text-wrap:balance}.st-page-title__actions:empty{display:none}.st-page-title__actions{display:flex;flex-wrap:wrap;gap:var(--st-espacement-2);align-items:center}.st-page-title__precision{margin:var(--st-espacement-2) 0 0;font-size:var(--st-taille-sm);color:var(--st-couleur-texte-discret)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1869
+ }
1870
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StPageTitle, decorators: [{
1871
+ type: Component,
1872
+ args: [{ selector: 'st-page-title', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'st-page-title' }, template: "<div class=\"st-page-title__ligne\">\n <h1 class=\"st-page-title__titre\" [attr.id]=\"identifiant()\"><ng-content /></h1>\n <div class=\"st-page-title__actions\"><ng-content select=\"[actions]\" /></div>\n</div>\n@if (precision() !== null) {\n <p class=\"st-page-title__precision\">{{ precision() }}</p>\n}\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block;margin-block-end:var(--st-espacement-6)}.st-page-title__ligne{display:flex;flex-wrap:wrap;gap:var(--st-espacement-3);align-items:flex-start;justify-content:space-between}.st-page-title__titre:focus{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-page-title__titre{margin:0;font-family:var(--st-police-base);font-size:var(--st-taille-3xl);font-weight:var(--st-graisse-semi);line-height:var(--st-interligne-serre);color:var(--st-couleur-texte);text-wrap:balance}.st-page-title__actions:empty{display:none}.st-page-title__actions{display:flex;flex-wrap:wrap;gap:var(--st-espacement-2);align-items:center}.st-page-title__precision{margin:var(--st-espacement-2) 0 0;font-size:var(--st-taille-sm);color:var(--st-couleur-texte-discret)}\n"] }]
1873
+ }], propDecorators: { precision: [{ type: i0.Input, args: [{ isSignal: true, alias: "precision", required: false }] }], identifiant: [{ type: i0.Input, args: [{ isSignal: true, alias: "identifiant", required: false }] }] } });
1874
+
1875
+ /**
1876
+ * Fil d'Ariane.
1877
+ *
1878
+ * ⚠️ **Le dernier maillon n'est pas un lien.** C'est la page courante : un lien
1879
+ * vers l'endroit ou l'on se trouve deja n'apporte rien, et il ajoute un arret
1880
+ * de tabulation sur chaque page du site. Il porte `aria-current="page"`, qui
1881
+ * est ce que le lecteur d'ecran annonce a sa place.
1882
+ *
1883
+ * ⚠️ **Les separateurs sont poses en `aria-hidden`.** Un chevron ou une barre
1884
+ * oblique laisses dans l'arbre d'accessibilite se lit « barre oblique » entre
1885
+ * chaque maillon : « Accueil barre oblique Comptes barre oblique Operations ».
1886
+ * Les poser en contenu engendre par CSS ne suffit pas — Chrome et Firefox
1887
+ * exposent `content` a l'arbre d'accessibilite.
1888
+ *
1889
+ * ⚠️ La liste est ORDONNEE (`ol`) : l'ordre des maillons est l'information.
1890
+ *
1891
+ * ⚠️ **Les liens passent par le routeur.** La premiere version posait des
1892
+ * `href` bruts : dans une SPA, un clic quittait l'application, repassait par la
1893
+ * coquille du BFF et perdait tout l'etat en memoire — sur le composant de
1894
+ * navigation le plus clique apres le menu.
1895
+ */
1896
+ class StBreadcrumb {
1897
+ libelles = inject(ST_LIBELLES);
1898
+ maillons = input.required(/* @ts-ignore */
1899
+ ...(ngDevMode ? [{ debugName: "maillons" }] : /* istanbul ignore next */ []));
1900
+ /** `null` : le texte vient du dictionnaire de l'application. */
1901
+ etiquette = input(null, /* @ts-ignore */
1902
+ ...(ngDevMode ? [{ debugName: "etiquette" }] : /* istanbul ignore next */ []));
1903
+ /** Caractere de separation. Muet pour les technologies d'assistance. */
1904
+ separateur = input('/', /* @ts-ignore */
1905
+ ...(ngDevMode ? [{ debugName: "separateur" }] : /* istanbul ignore next */ []));
1906
+ etiquetteLue = computed(() => this.etiquette() ?? this.libelles().filDAriane, /* @ts-ignore */
1907
+ ...(ngDevMode ? [{ debugName: "etiquetteLue" }] : /* istanbul ignore next */ []));
1908
+ /** Le dernier maillon est la page courante, jamais un lien. */
1909
+ derniereIndice = computed(() => this.maillons().length - 1, /* @ts-ignore */
1910
+ ...(ngDevMode ? [{ debugName: "derniereIndice" }] : /* istanbul ignore next */ []));
1911
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StBreadcrumb, deps: [], target: i0.ɵɵFactoryTarget.Component });
1912
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StBreadcrumb, isStandalone: true, selector: "st-breadcrumb", inputs: { maillons: { classPropertyName: "maillons", publicName: "maillons", isSignal: true, isRequired: true, transformFunction: null }, etiquette: { classPropertyName: "etiquette", publicName: "etiquette", isSignal: true, isRequired: false, transformFunction: null }, separateur: { classPropertyName: "separateur", publicName: "separateur", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "st-breadcrumb" }, ngImport: i0, template: "<nav [attr.aria-label]=\"etiquetteLue()\">\n <ol class=\"st-breadcrumb__liste\">\n @for (maillon of maillons(); track $index; let indice = $index, premier = $first) {\n <li class=\"st-breadcrumb__maillon\">\n @if (!premier) {\n <span class=\"st-breadcrumb__separateur\" aria-hidden=\"true\">{{ separateur() }}</span>\n }\n @if (indice === derniereIndice() || maillon.lien === undefined) {\n <span aria-current=\"page\">{{ maillon.libelle }}</span>\n } @else {\n <a [routerLink]=\"maillon.lien\">{{ maillon.libelle }}</a>\n }\n </li>\n }\n </ol>\n</nav>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block;margin-block-end:var(--st-espacement-4);font-size:var(--st-taille-sm)}.st-breadcrumb__liste{display:flex;flex-wrap:wrap;gap:var(--st-espacement-2);align-items:center;padding:0;margin:0;list-style:none}.st-breadcrumb__maillon{display:flex;gap:var(--st-espacement-2);align-items:center;color:var(--st-couleur-texte-discret)}.st-breadcrumb__separateur{color:var(--st-couleur-texte-discret)}a:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}a{color:var(--st-couleur-texte-discret);text-decoration:underline;border-radius:var(--st-rayon-xs)}a:hover{color:var(--st-couleur-texte)}[aria-current=page]{font-weight:var(--st-graisse-semi);color:var(--st-couleur-texte)}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1913
+ }
1914
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StBreadcrumb, decorators: [{
1915
+ type: Component,
1916
+ args: [{ selector: 'st-breadcrumb', changeDetection: ChangeDetectionStrategy.OnPush, imports: [RouterLink], host: { class: 'st-breadcrumb' }, template: "<nav [attr.aria-label]=\"etiquetteLue()\">\n <ol class=\"st-breadcrumb__liste\">\n @for (maillon of maillons(); track $index; let indice = $index, premier = $first) {\n <li class=\"st-breadcrumb__maillon\">\n @if (!premier) {\n <span class=\"st-breadcrumb__separateur\" aria-hidden=\"true\">{{ separateur() }}</span>\n }\n @if (indice === derniereIndice() || maillon.lien === undefined) {\n <span aria-current=\"page\">{{ maillon.libelle }}</span>\n } @else {\n <a [routerLink]=\"maillon.lien\">{{ maillon.libelle }}</a>\n }\n </li>\n }\n </ol>\n</nav>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block;margin-block-end:var(--st-espacement-4);font-size:var(--st-taille-sm)}.st-breadcrumb__liste{display:flex;flex-wrap:wrap;gap:var(--st-espacement-2);align-items:center;padding:0;margin:0;list-style:none}.st-breadcrumb__maillon{display:flex;gap:var(--st-espacement-2);align-items:center;color:var(--st-couleur-texte-discret)}.st-breadcrumb__separateur{color:var(--st-couleur-texte-discret)}a:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}a{color:var(--st-couleur-texte-discret);text-decoration:underline;border-radius:var(--st-rayon-xs)}a:hover{color:var(--st-couleur-texte)}[aria-current=page]{font-weight:var(--st-graisse-semi);color:var(--st-couleur-texte)}\n"] }]
1917
+ }], propDecorators: { maillons: [{ type: i0.Input, args: [{ isSignal: true, alias: "maillons", required: true }] }], etiquette: [{ type: i0.Input, args: [{ isSignal: true, alias: "etiquette", required: false }] }], separateur: [{ type: i0.Input, args: [{ isSignal: true, alias: "separateur", required: false }] }] } });
1918
+
1919
+ /** Identifiant par defaut du contenu principal, pose par `st-app-shell`. */
1920
+ const IDENTIFIANT_DU_CONTENU_PRINCIPAL = 'contenu-principal';
1921
+ /**
1922
+ * Lien d'evitement : aller au contenu sans traverser la navigation.
1923
+ *
1924
+ * WCAG 2.4.1. Sans lui, chaque page impose a qui navigue au clavier de
1925
+ * traverser l'en-tete et tout le menu avant d'atteindre ce qu'il est venu lire —
1926
+ * trente arrets de tabulation, a chaque changement de page.
1927
+ *
1928
+ * ⚠️ **Le focus est pose par script, et la navigation par ancre est annulee.**
1929
+ * Deux raisons, et chacune suffit :
1930
+ *
1931
+ * 1. Un `href="#contenu"` se resout contre `<base href>`. Sous
1932
+ * `/ui/<interface>/`, il vise `/ui/<interface>/#contenu` : un rechargement
1933
+ * complet de la coquille, au lieu d'un saut dans la page.
1934
+ * 2. Suivre une ancre deplace la vue sans toujours deplacer le FOCUS. La
1935
+ * tabulation suivante repart alors du lien d'evitement, et le saut n'a servi
1936
+ * a rien.
1937
+ *
1938
+ * Le `href` reste pose : c'est lui qui fait du lien un lien, pour le lecteur
1939
+ * d'ecran comme pour le clic du milieu.
1940
+ *
1941
+ * ⚠️ Il doit etre le PREMIER element focalisable du document. Le composant ne
1942
+ * peut pas l'imposer ; `st-app-shell` le fait.
1943
+ */
1944
+ class StSkipLink {
1945
+ document = inject(DOCUMENT);
1946
+ libelles = inject(ST_LIBELLES);
1947
+ /** Identifiant de l'element a atteindre. */
1948
+ cible = input(IDENTIFIANT_DU_CONTENU_PRINCIPAL, /* @ts-ignore */
1949
+ ...(ngDevMode ? [{ debugName: "cible" }] : /* istanbul ignore next */ []));
1950
+ /** `null` : le texte vient du dictionnaire de l'application. */
1951
+ libelle = input(null, /* @ts-ignore */
1952
+ ...(ngDevMode ? [{ debugName: "libelle" }] : /* istanbul ignore next */ []));
1953
+ libelleLu = computed(() => this.libelle() ?? this.libelles().allerAuContenu, /* @ts-ignore */
1954
+ ...(ngDevMode ? [{ debugName: "libelleLu" }] : /* istanbul ignore next */ []));
1955
+ ancre = computed(() => `#${this.cible()}`, /* @ts-ignore */
1956
+ ...(ngDevMode ? [{ debugName: "ancre" }] : /* istanbul ignore next */ []));
1957
+ aller(evenement) {
1958
+ const cible = this.document.getElementById(this.cible());
1959
+ if (cible === null)
1960
+ return;
1961
+ evenement.preventDefault();
1962
+ // `tabindex="-1"` : un `main` n'est pas focalisable, et `focus()` sur un
1963
+ // element qui ne l'est pas ne fait rien — en silence.
1964
+ if (!cible.hasAttribute('tabindex'))
1965
+ cible.setAttribute('tabindex', '-1');
1966
+ cible.focus();
1967
+ }
1968
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StSkipLink, deps: [], target: i0.ɵɵFactoryTarget.Component });
1969
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StSkipLink, isStandalone: true, selector: "st-skip-link", inputs: { cible: { classPropertyName: "cible", publicName: "cible", isSignal: true, isRequired: false, transformFunction: null }, libelle: { classPropertyName: "libelle", publicName: "libelle", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "st-skip-link" }, ngImport: i0, template: "<a class=\"st-skip-link__lien\" [attr.href]=\"ancre()\" (click)=\"aller($event)\">{{ libelleLu() }}</a>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}.st-skip-link__lien{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}.st-skip-link__lien:focus{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-skip-link__lien:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip-path:none;white-space:normal;position:fixed;inset-block-start:var(--st-espacement-2);inset-inline-start:var(--st-espacement-2);z-index:var(--st-plan-notification);padding:var(--st-espacement-2) var(--st-espacement-4);font-weight:var(--st-graisse-semi);color:var(--st-couleur-sur-primaire);background:var(--st-couleur-primaire);border-radius:var(--st-rayon-md)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1970
+ }
1971
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StSkipLink, decorators: [{
1972
+ type: Component,
1973
+ args: [{ selector: 'st-skip-link', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'st-skip-link' }, template: "<a class=\"st-skip-link__lien\" [attr.href]=\"ancre()\" (click)=\"aller($event)\">{{ libelleLu() }}</a>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}.st-skip-link__lien{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}.st-skip-link__lien:focus{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-skip-link__lien:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip-path:none;white-space:normal;position:fixed;inset-block-start:var(--st-espacement-2);inset-inline-start:var(--st-espacement-2);z-index:var(--st-plan-notification);padding:var(--st-espacement-2) var(--st-espacement-4);font-weight:var(--st-graisse-semi);color:var(--st-couleur-sur-primaire);background:var(--st-couleur-primaire);border-radius:var(--st-rayon-md)}\n"] }]
1974
+ }], propDecorators: { cible: [{ type: i0.Input, args: [{ isSignal: true, alias: "cible", required: false }] }], libelle: [{ type: i0.Input, args: [{ isSignal: true, alias: "libelle", required: false }] }] } });
1975
+
1976
+ /**
1977
+ * Coquille d'une application : lien d'evitement, en-tete, navigation, contenu
1978
+ * principal, pied de page.
1979
+ *
1980
+ * ```html
1981
+ * <st-app-shell>
1982
+ * <ng-container entete>…</ng-container>
1983
+ * <ng-container navigation>…</ng-container>
1984
+ * <router-outlet />
1985
+ * <ng-container pied>…</ng-container>
1986
+ * </st-app-shell>
1987
+ * ```
1988
+ *
1989
+ * ⚠️ Son role est de garantir les REPERES, et un seul de chaque. Une page qui
1990
+ * compte deux `main` — frequent quand une micro-SPA pose le sien dans celui de
1991
+ * la coquille — prive le lecteur d'ecran du raccourci « aller au contenu
1992
+ * principal » : il ne sait plus lequel viser. Les remotes ne posent donc
1993
+ * jamais de `main`, `header` ni `footer` de premier niveau.
1994
+ *
1995
+ * ⚠️ Le lien d'evitement est rendu EN PREMIER, avant l'en-tete : c'est la seule
1996
+ * place ou il sert. Place apres, il faut deja avoir traverse ce qu'il permet
1997
+ * d'eviter.
1998
+ *
1999
+ * Le contenu principal porte l'identifiant vise par le lien d'evitement.
2000
+ * Le focus de navigation, lui, vise le titre de niveau 1 : voir `StNavigation`
2001
+ * de `@starterlib/core`. Les deux se completent — l'un au chargement d'une
2002
+ * page, l'autre a chaque changement de route.
2003
+ *
2004
+ * ⚠️ La coquille ne pose PAS de `<nav>` autour de la navigation : c'est
2005
+ * `st-sidenav` qui porte ce repere. Pose ici aussi, il s'imbriquerait — le
2006
+ * lecteur d'ecran annoncerait « navigation, navigation » — et resterait vide
2007
+ * sur petit ecran, quand le contenu part dans le tiroir.
2008
+ */
2009
+ class StAppShell {
2010
+ identifiantDuContenu = IDENTIFIANT_DU_CONTENU_PRINCIPAL;
2011
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StAppShell, deps: [], target: i0.ɵɵFactoryTarget.Component });
2012
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.6", type: StAppShell, isStandalone: true, selector: "st-app-shell", host: { classAttribute: "st-app-shell" }, ngImport: i0, template: "<st-skip-link [cible]=\"identifiantDuContenu\" />\n\n<header class=\"st-app-shell__entete\">\n <ng-content select=\"[entete]\" />\n</header>\n\n<div class=\"st-app-shell__corps\">\n <div class=\"st-app-shell__navigation\">\n <ng-content select=\"[navigation]\" />\n </div>\n\n <main class=\"st-app-shell__contenu\" [id]=\"identifiantDuContenu\">\n <ng-content />\n </main>\n</div>\n\n<footer class=\"st-app-shell__pied\">\n <ng-content select=\"[pied]\" />\n</footer>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:flex;flex-direction:column;min-block-size:100dvh;color:var(--st-couleur-texte);background:var(--st-couleur-fond)}.st-app-shell__entete{position:sticky;inset-block-start:0;z-index:var(--st-plan-entete);background:var(--st-couleur-surface);border-block-end:1px solid var(--st-couleur-bordure)}.st-app-shell__corps{display:flex;flex:1 1 auto;flex-direction:column}.st-app-shell__navigation:empty,.st-app-shell__entete:empty,.st-app-shell__pied:empty{display:none}.st-app-shell__contenu{flex:1 1 auto;min-inline-size:0;padding:var(--st-espacement-6) var(--st-espacement-4)}.st-app-shell__contenu:focus{outline:none}.st-app-shell__pied{padding:var(--st-espacement-4);color:var(--st-couleur-texte-discret);border-block-start:1px solid var(--st-couleur-bordure)}@media(min-width:64rem){.st-app-shell__corps{flex-direction:row}.st-app-shell__navigation{flex:none;inline-size:var(--st-coquille-largeur-navigation, 16rem);border-inline-end:1px solid var(--st-couleur-bordure)}.st-app-shell__contenu{padding:var(--st-espacement-8)}}\n"], dependencies: [{ kind: "component", type: StSkipLink, selector: "st-skip-link", inputs: ["cible", "libelle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2013
+ }
2014
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StAppShell, decorators: [{
2015
+ type: Component,
2016
+ args: [{ selector: 'st-app-shell', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StSkipLink], host: { class: 'st-app-shell' }, template: "<st-skip-link [cible]=\"identifiantDuContenu\" />\n\n<header class=\"st-app-shell__entete\">\n <ng-content select=\"[entete]\" />\n</header>\n\n<div class=\"st-app-shell__corps\">\n <div class=\"st-app-shell__navigation\">\n <ng-content select=\"[navigation]\" />\n </div>\n\n <main class=\"st-app-shell__contenu\" [id]=\"identifiantDuContenu\">\n <ng-content />\n </main>\n</div>\n\n<footer class=\"st-app-shell__pied\">\n <ng-content select=\"[pied]\" />\n</footer>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:flex;flex-direction:column;min-block-size:100dvh;color:var(--st-couleur-texte);background:var(--st-couleur-fond)}.st-app-shell__entete{position:sticky;inset-block-start:0;z-index:var(--st-plan-entete);background:var(--st-couleur-surface);border-block-end:1px solid var(--st-couleur-bordure)}.st-app-shell__corps{display:flex;flex:1 1 auto;flex-direction:column}.st-app-shell__navigation:empty,.st-app-shell__entete:empty,.st-app-shell__pied:empty{display:none}.st-app-shell__contenu{flex:1 1 auto;min-inline-size:0;padding:var(--st-espacement-6) var(--st-espacement-4)}.st-app-shell__contenu:focus{outline:none}.st-app-shell__pied{padding:var(--st-espacement-4);color:var(--st-couleur-texte-discret);border-block-start:1px solid var(--st-couleur-bordure)}@media(min-width:64rem){.st-app-shell__corps{flex-direction:row}.st-app-shell__navigation{flex:none;inline-size:var(--st-coquille-largeur-navigation, 16rem);border-inline-end:1px solid var(--st-couleur-bordure)}.st-app-shell__contenu{padding:var(--st-espacement-8)}}\n"] }]
2017
+ }] });
2018
+
2019
+ /**
2020
+ * Contenu de l'en-tete : bouton de navigation, marque, puis actions.
2021
+ *
2022
+ * ```html
2023
+ * <st-app-shell>
2024
+ * <st-header entete>
2025
+ * <button bascule stButton [stSidenavToggle]="navigation">Menu</button>
2026
+ * <a marque routerLink="/"><st-logo nom="Banque Exemple" clair="/logo.svg" /></a>
2027
+ * <st-lang-switch [courante]="langue.courante()" (choisie)="langue.changer($event)" />
2028
+ * <button stButton [stMenuTrigger]="compte">Mon compte</button>
2029
+ * </st-header>
2030
+ * </st-app-shell>
2031
+ * ```
2032
+ *
2033
+ * ⚠️ **Aucun repere pose ici.** Le `header` de `st-app-shell` est deja le
2034
+ * repere « banniere » ; en ajouter un second dans le premier ferait annoncer
2035
+ * deux bannieres.
2036
+ *
2037
+ * ⚠️ **Composition, pas assemblage.** Il ne cree ni menu, ni bascule, ni logo :
2038
+ * il les place. C'est ce qui le garde dans le tronc — importer `st-menu` l'aurait
2039
+ * fait sortir vers un point d'entree secondaire — et qui laisse chaque SPA
2040
+ * choisir ses actions.
2041
+ *
2042
+ * L'ordre du DOM est l'ordre de lecture et de tabulation : bouton de
2043
+ * navigation, marque, actions. Il n'est jamais inverse par le style.
2044
+ */
2045
+ // eslint-disable-next-line @typescript-eslint/no-extraneous-class -- composant de mise en page pur : tout est dans son gabarit et sa feuille.
2046
+ class StHeader {
2047
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StHeader, deps: [], target: i0.ɵɵFactoryTarget.Component });
2048
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.6", type: StHeader, isStandalone: true, selector: "st-header", host: { classAttribute: "st-header" }, ngImport: i0, template: "<div class=\"st-header__debut\">\n <ng-content select=\"[bascule]\" />\n <ng-content select=\"[marque]\" />\n</div>\n<div class=\"st-header__actions\">\n <ng-content />\n</div>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:flex;flex-wrap:wrap;gap:var(--st-espacement-3);align-items:center;justify-content:space-between;min-block-size:3.5rem;padding:var(--st-espacement-2) var(--st-espacement-4)}.st-header__debut,.st-header__actions{display:flex;flex-wrap:wrap;gap:var(--st-espacement-2);align-items:center}.st-header__actions:empty{display:none}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2049
+ }
2050
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StHeader, decorators: [{
2051
+ type: Component,
2052
+ args: [{ selector: 'st-header', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'st-header' }, template: "<div class=\"st-header__debut\">\n <ng-content select=\"[bascule]\" />\n <ng-content select=\"[marque]\" />\n</div>\n<div class=\"st-header__actions\">\n <ng-content />\n</div>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:flex;flex-wrap:wrap;gap:var(--st-espacement-3);align-items:center;justify-content:space-between;min-block-size:3.5rem;padding:var(--st-espacement-2) var(--st-espacement-4)}.st-header__debut,.st-header__actions{display:flex;flex-wrap:wrap;gap:var(--st-espacement-2);align-items:center}.st-header__actions:empty{display:none}\n"] }]
2053
+ }] });
2054
+
2055
+ const FOCALISABLES = 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), ' +
2056
+ 'textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
2057
+ // Valeurs de `Node.DOCUMENT_POSITION_*`, ecrites en clair : `Node` n'existe pas
2058
+ // au rendu serveur, et la comparaison ne doit pas en dependre au chargement.
2059
+ const PRECEDE = 2;
2060
+ const SUIT = 4;
2061
+ /**
2062
+ * ⚠️ L'icone doit differer par sa FORME d'un ton a l'autre, et non seulement
2063
+ * par sa couleur : un message porte par la seule couleur est illisible pour une
2064
+ * personne daltonienne, a l'impression, et sous un theme a fort contraste.
2065
+ */
2066
+ const ICONE$1 = {
2067
+ neutre: 'cercle-info',
2068
+ primaire: 'cercle-info',
2069
+ succes: 'cercle-coche',
2070
+ avertissement: 'triangle-alerte',
2071
+ danger: 'cercle-croix',
2072
+ };
2073
+ /**
2074
+ * Message de page, persistant jusqu'a ce qu'on le ferme.
2075
+ *
2076
+ * Distinct de `st-offline-banner`, qui dit un fait qu'on ne peut pas fermer, et
2077
+ * de `st-error`, qui remplace un contenu au lieu de l'accompagner.
2078
+ *
2079
+ * ⚠️ **Elle est une region vivante, et ce n'est pas redondant au chargement.**
2080
+ * Un lecteur d'ecran annonce les MUTATIONS d'une region qu'il observe deja :
2081
+ * une banniere presente des l'affichage est lue avec la page, une fois, puis
2082
+ * son apparition ulterieure est annoncee. Le meme mecanisme sert les deux cas.
2083
+ *
2084
+ * ⚠️ Le ton `danger` passe en `alert` (assertif) : une operation qui vient
2085
+ * d'echouer doit interrompre. Les autres restent en `status`, sinon une
2086
+ * confirmation couperait la lecture en cours et ferait perdre sa place.
2087
+ *
2088
+ * ⚠️ Comme `st-spinner` et `st-error`, elle se tait dans une region vivante
2089
+ * existante : sans cela, le lecteur annonce deux fois le meme message.
2090
+ */
2091
+ class StBanner {
2092
+ element = inject(ElementRef);
2093
+ regionParente = inject(REGION_VIVANTE_PARENTE, { optional: true });
2094
+ libelles = inject(ST_LIBELLES);
2095
+ ton = input('neutre', /* @ts-ignore */
2096
+ ...(ngDevMode ? [{ debugName: "ton" }] : /* istanbul ignore next */ []));
2097
+ message = input.required(/* @ts-ignore */
2098
+ ...(ngDevMode ? [{ debugName: "message" }] : /* istanbul ignore next */ []));
2099
+ /** Titre court au-dessus du message. Le message seul suffit le plus souvent. */
2100
+ titre = input(null, /* @ts-ignore */
2101
+ ...(ngDevMode ? [{ debugName: "titre" }] : /* istanbul ignore next */ []));
2102
+ fermable = input(false, { ...(ngDevMode ? { debugName: "fermable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2103
+ /** `null` : le texte vient du dictionnaire de l'application. */
2104
+ libelleFermeture = input(null, /* @ts-ignore */
2105
+ ...(ngDevMode ? [{ debugName: "libelleFermeture" }] : /* istanbul ignore next */ []));
2106
+ ferme = output();
2107
+ icone = computed(() => ICONE$1[this.ton()], /* @ts-ignore */
2108
+ ...(ngDevMode ? [{ debugName: "icone" }] : /* istanbul ignore next */ []));
2109
+ libelleFermetureLu = computed(() => this.libelleFermeture() ?? this.libelles().fermerLeMessage, /* @ts-ignore */
2110
+ ...(ngDevMode ? [{ debugName: "libelleFermetureLu" }] : /* istanbul ignore next */ []));
2111
+ roleLu = computed(() => {
2112
+ if (this.regionParente !== null)
2113
+ return null;
2114
+ return this.ton() === 'danger' ? 'alert' : 'status';
2115
+ }, /* @ts-ignore */
2116
+ ...(ngDevMode ? [{ debugName: "roleLu" }] : /* istanbul ignore next */ []));
2117
+ /**
2118
+ * ⚠️ Le focus est DEPLACE avant l'emission. Sans cela, le bouton disparait
2119
+ * sous le doigt de l'utilisateur clavier, le focus retombe sur le corps du
2120
+ * document, et la navigation repart du haut de la page — le meme defaut que
2121
+ * sur une liste d'etiquettes, et l'un des plus frequents.
2122
+ */
2123
+ fermer() {
2124
+ this.deplacerLeFocus();
2125
+ this.ferme.emit();
2126
+ }
2127
+ /**
2128
+ * Cible, dans l'ordre : le premier element focalisable qui SUIT la banniere
2129
+ * dans le document, sinon le dernier qui la precede, sinon le conteneur s'il
2130
+ * est focalisable par script.
2131
+ *
2132
+ * ⚠️ L'ordre du DOCUMENT, et non les descendants du voisin. La premiere
2133
+ * version cherchait dans `nextElementSibling` : un bouton pose directement
2134
+ * apres la banniere n'etait pas trouve, puisqu'il n'est pas son propre
2135
+ * descendant, et le focus retombait sur le corps du document.
2136
+ */
2137
+ deplacerLeFocus() {
2138
+ const hote = this.element.nativeElement;
2139
+ const candidats = [...hote.ownerDocument.querySelectorAll(FOCALISABLES)].filter((candidat) => !hote.contains(candidat));
2140
+ const suivant = candidats.find((candidat) => (hote.compareDocumentPosition(candidat) & SUIT) !== 0);
2141
+ if (suivant !== undefined) {
2142
+ suivant.focus();
2143
+ return;
2144
+ }
2145
+ const precedent = candidats
2146
+ .reverse()
2147
+ .find((candidat) => (hote.compareDocumentPosition(candidat) & PRECEDE) !== 0);
2148
+ if (precedent !== undefined) {
2149
+ precedent.focus();
2150
+ return;
2151
+ }
2152
+ const parent = hote.parentElement;
2153
+ if (parent?.hasAttribute('tabindex') === true)
2154
+ parent.focus();
2155
+ }
2156
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StBanner, deps: [], target: i0.ɵɵFactoryTarget.Component });
2157
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StBanner, isStandalone: true, selector: "st-banner", inputs: { ton: { classPropertyName: "ton", publicName: "ton", isSignal: true, isRequired: false, transformFunction: null }, message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null }, titre: { classPropertyName: "titre", publicName: "titre", isSignal: true, isRequired: false, transformFunction: null }, fermable: { classPropertyName: "fermable", publicName: "fermable", isSignal: true, isRequired: false, transformFunction: null }, libelleFermeture: { classPropertyName: "libelleFermeture", publicName: "libelleFermeture", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { ferme: "ferme" }, host: { properties: { "attr.data-ton": "ton()", "attr.role": "roleLu()" }, classAttribute: "st-banner" }, ngImport: i0, template: "<st-icon [nom]=\"icone()\" taille=\"sm\" />\n<div class=\"st-banner__corps\">\n @if (titre() !== null) {\n <p class=\"st-banner__titre\">{{ titre() }}</p>\n }\n <p class=\"st-banner__message\">{{ message() }}</p>\n <ng-content />\n</div>\n@if (fermable()) {\n <!-- eslint-disable-next-line @angular-eslint/template/elements-content --\n Le contenu vient du gabarit de stIconButton. Le nom accessible est\n impose par le type (`etiquette` est requis) et verifie par axe. -->\n <button\n stIconButton\n type=\"button\"\n icone=\"croix\"\n taille=\"sm\"\n [etiquette]=\"libelleFermetureLu()\"\n (click)=\"fermer()\"\n ></button>\n}\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:flex;gap:var(--st-espacement-3);align-items:flex-start;padding:var(--st-espacement-3) var(--st-espacement-4);margin-block-end:var(--st-espacement-4);border:1px solid transparent;border-radius:var(--st-rayon-md)}.st-banner__corps{flex:1 1 auto;min-inline-size:0}.st-banner__titre{margin:0 0 var(--st-espacement-1);font-weight:var(--st-graisse-semi)}.st-banner__message{margin:0}:host([data-ton=neutre]){color:var(--st-couleur-texte);background:var(--st-couleur-surface-enfoncee);border-color:var(--st-couleur-bordure)}:host([data-ton=primaire]){color:var(--st-couleur-sur-primaire-discret);background:var(--st-couleur-primaire-discret)}:host([data-ton=succes]){color:var(--st-couleur-sur-succes-discret);background:var(--st-couleur-succes-discret)}:host([data-ton=avertissement]){color:var(--st-couleur-sur-avertissement-discret);background:var(--st-couleur-avertissement-discret)}:host([data-ton=danger]){color:var(--st-couleur-sur-danger-discret);background:var(--st-couleur-danger-discret)}@media(forced-colors:active){:host{border-color:CanvasText}}\n"], dependencies: [{ kind: "component", type: StIcon, selector: "st-icon", inputs: ["nom", "taille", "ton", "etiquette"] }, { kind: "component", type: StIconButton, selector: "button[stIconButton]", inputs: ["icone", "etiquette", "variante", "taille", "enfonce"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2158
+ }
2159
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StBanner, decorators: [{
2160
+ type: Component,
2161
+ args: [{ selector: 'st-banner', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StIcon, StIconButton], host: {
2162
+ class: 'st-banner',
2163
+ '[attr.data-ton]': 'ton()',
2164
+ '[attr.role]': 'roleLu()',
2165
+ }, template: "<st-icon [nom]=\"icone()\" taille=\"sm\" />\n<div class=\"st-banner__corps\">\n @if (titre() !== null) {\n <p class=\"st-banner__titre\">{{ titre() }}</p>\n }\n <p class=\"st-banner__message\">{{ message() }}</p>\n <ng-content />\n</div>\n@if (fermable()) {\n <!-- eslint-disable-next-line @angular-eslint/template/elements-content --\n Le contenu vient du gabarit de stIconButton. Le nom accessible est\n impose par le type (`etiquette` est requis) et verifie par axe. -->\n <button\n stIconButton\n type=\"button\"\n icone=\"croix\"\n taille=\"sm\"\n [etiquette]=\"libelleFermetureLu()\"\n (click)=\"fermer()\"\n ></button>\n}\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:flex;gap:var(--st-espacement-3);align-items:flex-start;padding:var(--st-espacement-3) var(--st-espacement-4);margin-block-end:var(--st-espacement-4);border:1px solid transparent;border-radius:var(--st-rayon-md)}.st-banner__corps{flex:1 1 auto;min-inline-size:0}.st-banner__titre{margin:0 0 var(--st-espacement-1);font-weight:var(--st-graisse-semi)}.st-banner__message{margin:0}:host([data-ton=neutre]){color:var(--st-couleur-texte);background:var(--st-couleur-surface-enfoncee);border-color:var(--st-couleur-bordure)}:host([data-ton=primaire]){color:var(--st-couleur-sur-primaire-discret);background:var(--st-couleur-primaire-discret)}:host([data-ton=succes]){color:var(--st-couleur-sur-succes-discret);background:var(--st-couleur-succes-discret)}:host([data-ton=avertissement]){color:var(--st-couleur-sur-avertissement-discret);background:var(--st-couleur-avertissement-discret)}:host([data-ton=danger]){color:var(--st-couleur-sur-danger-discret);background:var(--st-couleur-danger-discret)}@media(forced-colors:active){:host{border-color:CanvasText}}\n"] }]
2166
+ }], propDecorators: { ton: [{ type: i0.Input, args: [{ isSignal: true, alias: "ton", required: false }] }], message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: true }] }], titre: [{ type: i0.Input, args: [{ isSignal: true, alias: "titre", required: false }] }], fermable: [{ type: i0.Input, args: [{ isSignal: true, alias: "fermable", required: false }] }], libelleFermeture: [{ type: i0.Input, args: [{ isSignal: true, alias: "libelleFermeture", required: false }] }], ferme: [{ type: i0.Output, args: ["ferme"] }] } });
2167
+
2168
+ /** Une FORME par ton, jamais la couleur seule. */
2169
+ const ICONE = {
2170
+ neutre: 'cercle-info',
2171
+ primaire: 'cercle-info',
2172
+ succes: 'cercle-coche',
2173
+ avertissement: 'triangle-alerte',
2174
+ danger: 'cercle-croix',
2175
+ };
2176
+ /**
2177
+ * Message court attache a une zone precise : une aide sous un champ, une
2178
+ * consequence sous un choix, une contrainte au-dessus d'un bouton.
2179
+ *
2180
+ * Distinct de `st-banner`, qui parle de la PAGE et se ferme.
2181
+ *
2182
+ * ⚠️ **Aucun role, aucune region vivante**, et c'est la difference qui compte.
2183
+ * Un message en ligne est lu quand on atteint l'endroit auquel il se rattache ;
2184
+ * en faire une region vivante le ferait annoncer hors contexte, et une
2185
+ * vingtaine de champs produiraient vingt annonces a l'ouverture de l'ecran.
2186
+ *
2187
+ * ⚠️ Pour une erreur de SAISIE, ce composant ne suffit pas : le champ doit
2188
+ * porter `aria-describedby` vers l'identifiant du message, sans quoi le lien
2189
+ * entre les deux n'existe que visuellement. C'est `st-form-field` de la
2190
+ * vague 3 qui posera ce lien.
2191
+ */
2192
+ class StInlineMessage {
2193
+ ton = input('neutre', /* @ts-ignore */
2194
+ ...(ngDevMode ? [{ debugName: "ton" }] : /* istanbul ignore next */ []));
2195
+ /** Cible d'un `aria-describedby` pose par le champ decrit. */
2196
+ identifiant = input(null, /* @ts-ignore */
2197
+ ...(ngDevMode ? [{ debugName: "identifiant" }] : /* istanbul ignore next */ []));
2198
+ icone = computed(() => ICONE[this.ton()], /* @ts-ignore */
2199
+ ...(ngDevMode ? [{ debugName: "icone" }] : /* istanbul ignore next */ []));
2200
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StInlineMessage, deps: [], target: i0.ɵɵFactoryTarget.Component });
2201
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StInlineMessage, isStandalone: true, selector: "st-inline-message", inputs: { ton: { classPropertyName: "ton", publicName: "ton", isSignal: true, isRequired: false, transformFunction: null }, identifiant: { classPropertyName: "identifiant", publicName: "identifiant", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-ton": "ton()", "attr.id": "identifiant()" }, classAttribute: "st-inline-message" }, ngImport: i0, template: "<st-icon [nom]=\"icone()\" taille=\"xs\" />\n<span class=\"st-inline-message__texte\"><ng-content /></span>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:flex;gap:var(--st-espacement-2);align-items:flex-start;font-size:var(--st-taille-sm);line-height:var(--st-interligne-normal)}:host([data-ton=neutre]){color:var(--st-couleur-texte-discret)}:host([data-ton=primaire]){color:var(--st-couleur-primaire)}:host([data-ton=succes]){color:var(--st-couleur-succes)}:host([data-ton=avertissement]){color:var(--st-couleur-avertissement)}:host([data-ton=danger]){color:var(--st-couleur-danger)}\n"], dependencies: [{ kind: "component", type: StIcon, selector: "st-icon", inputs: ["nom", "taille", "ton", "etiquette"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2202
+ }
2203
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StInlineMessage, decorators: [{
2204
+ type: Component,
2205
+ args: [{ selector: 'st-inline-message', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StIcon], host: {
2206
+ class: 'st-inline-message',
2207
+ '[attr.data-ton]': 'ton()',
2208
+ '[attr.id]': 'identifiant()',
2209
+ }, template: "<st-icon [nom]=\"icone()\" taille=\"xs\" />\n<span class=\"st-inline-message__texte\"><ng-content /></span>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:flex;gap:var(--st-espacement-2);align-items:flex-start;font-size:var(--st-taille-sm);line-height:var(--st-interligne-normal)}:host([data-ton=neutre]){color:var(--st-couleur-texte-discret)}:host([data-ton=primaire]){color:var(--st-couleur-primaire)}:host([data-ton=succes]){color:var(--st-couleur-succes)}:host([data-ton=avertissement]){color:var(--st-couleur-avertissement)}:host([data-ton=danger]){color:var(--st-couleur-danger)}\n"] }]
2210
+ }], propDecorators: { ton: [{ type: i0.Input, args: [{ isSignal: true, alias: "ton", required: false }] }], identifiant: [{ type: i0.Input, args: [{ isSignal: true, alias: "identifiant", required: false }] }] } });
2211
+
2212
+ /**
2213
+ * Le texte d'une erreur, dans la langue courante.
2214
+ *
2215
+ * ⚠️ **Un `message` fourni l'emporte toujours.** Un validateur metier, ou une
2216
+ * erreur du serveur deja traduite, en sait plus que le genre : « IBAN d'un pays
2217
+ * non pris en charge » vaut mieux que « Le format n'est pas valide ».
2218
+ *
2219
+ * ⚠️ **Un genre inconnu rend un message generique, jamais le genre brut.**
2220
+ * Afficher `ibanChecksum` a une personne qui saisit un IBAN, c'est lui montrer le
2221
+ * code source.
2222
+ *
2223
+ * La locale sert aux messages qui citent un format, une date ou une taille : « au
2224
+ * format jj/mm/aaaa » n'est pas « mm/dd/yyyy ».
2225
+ */
2226
+ function messageDErreur(erreur, libelles, locale = 'fr-FR') {
2227
+ const fourni = erreur.message?.trim();
2228
+ if (fourni !== undefined && fourni !== '')
2229
+ return fourni;
2230
+ const propriete = (nom) => erreur[nom];
2231
+ const nombre = (nom) => {
2232
+ const valeur = propriete(nom);
2233
+ return typeof valeur === 'number' ? valeur : undefined;
2234
+ };
2235
+ const texte = (nom) => {
2236
+ const valeur = propriete(nom);
2237
+ return typeof valeur === 'string' ? valeur : undefined;
2238
+ };
2239
+ switch (erreur.kind) {
2240
+ case 'required':
2241
+ return libelles.champObligatoire;
2242
+ case 'email':
2243
+ return libelles.adresseInvalide;
2244
+ case 'pattern':
2245
+ return libelles.formatInvalide;
2246
+ case 'iban':
2247
+ return libelles.ibanInvalide;
2248
+ case 'telephone':
2249
+ return libelles.telephoneInvalide;
2250
+ case 'minLength': {
2251
+ const minimum = nombre('minLength');
2252
+ return minimum === undefined ? libelles.valeurInvalide : libelles.longueurMinimale(minimum);
2253
+ }
2254
+ case 'maxLength': {
2255
+ const maximum = nombre('maxLength');
2256
+ return maximum === undefined ? libelles.valeurInvalide : libelles.longueurMaximale(maximum);
2257
+ }
2258
+ case 'min': {
2259
+ const minimum = nombre('min');
2260
+ return minimum === undefined
2261
+ ? libelles.valeurInvalide
2262
+ : libelles.valeurMinimale(String(minimum));
2263
+ }
2264
+ case 'max': {
2265
+ const maximum = nombre('max');
2266
+ return maximum === undefined
2267
+ ? libelles.valeurInvalide
2268
+ : libelles.valeurMaximale(String(maximum));
2269
+ }
2270
+ case 'montant': {
2271
+ const devise = texte('devise') ?? 'EUR';
2272
+ const exemple = formaterMontant(montant((123456n * 10n ** BigInt(decimalesDe(devise))) / 100n, devise), {
2273
+ locale,
2274
+ sansDevise: true,
2275
+ });
2276
+ return libelles.montantIllisible(exemple);
2277
+ }
2278
+ case 'decimales': {
2279
+ const decimales = nombre('decimales');
2280
+ return decimales === undefined
2281
+ ? libelles.valeurInvalide
2282
+ : libelles.tropDeDecimales(decimales);
2283
+ }
2284
+ case 'date':
2285
+ return libelles.dateIllisible(motifLocal(libelles, locale), exempleDeDate(locale));
2286
+ case 'dateMin': {
2287
+ const minimum = texte('min');
2288
+ return minimum === undefined
2289
+ ? libelles.valeurInvalide
2290
+ : libelles.dateTropTot(formaterDateLongue(minimum, locale));
2291
+ }
2292
+ case 'dateMax': {
2293
+ const maximum = texte('max');
2294
+ return maximum === undefined
2295
+ ? libelles.valeurInvalide
2296
+ : libelles.dateTropTard(formaterDateLongue(maximum, locale));
2297
+ }
2298
+ case 'plageDeDates':
2299
+ return libelles.finAvantDebut;
2300
+ case 'fichierTaille': {
2301
+ const fichier = texte('fichier');
2302
+ const maximum = nombre('max');
2303
+ return fichier === undefined || maximum === undefined
2304
+ ? libelles.valeurInvalide
2305
+ : libelles.fichierTropVolumineux(fichier, formaterTaille(maximum, locale));
2306
+ }
2307
+ case 'fichierType': {
2308
+ const fichier = texte('fichier');
2309
+ return fichier === undefined
2310
+ ? libelles.valeurInvalide
2311
+ : libelles.typeDeFichierRefuse(fichier);
2312
+ }
2313
+ case 'fichiersNombre': {
2314
+ const maximum = nombre('max');
2315
+ return maximum === undefined ? libelles.valeurInvalide : libelles.tropDeFichiers(maximum);
2316
+ }
2317
+ default:
2318
+ return libelles.valeurInvalide;
2319
+ }
2320
+ }
2321
+ /** Le motif a taper dans la langue courante : `jj/mm/aaaa`. */
2322
+ function motifLocal(libelles, locale) {
2323
+ return motifDeDate(locale, {
2324
+ jour: libelles.lettreDuJour,
2325
+ mois: libelles.lettreDuMois,
2326
+ annee: libelles.lettreDeLAnnee,
2327
+ });
2328
+ }
2329
+ /**
2330
+ * Un jour superieur a 12 : « 31/03/2026 » montre sans ambiguite ou va le jour,
2331
+ * ce que « 01/02/2026 » ne dit pas.
2332
+ */
2333
+ function exempleDeDate(locale) {
2334
+ return formaterDateSaisie('2026-03-31', locale);
2335
+ }
2336
+ /**
2337
+ * Erreur d'IBAN, a brancher sur un schema :
2338
+ *
2339
+ * ```ts
2340
+ * validate(chemin.iban, ({ value }) => erreurIban(value()));
2341
+ * ```
2342
+ *
2343
+ * Une fonction pure plutot qu'une regle toute faite : fournir la regle
2344
+ * importerait `validate` d'`@angular/forms` A L'EXECUTION, et le socle ne
2345
+ * l'importe que pour ses types (audit de la vague 3, V3-1).
2346
+ *
2347
+ * ⚠️ Confort de saisie, jamais controle (SEC-5) : le serveur revalide. Un champ
2348
+ * vide n'est pas « invalide » ici — c'est `required` qui le dit, avec le bon
2349
+ * message.
2350
+ */
2351
+ function erreurIban(valeur) {
2352
+ if (valeur.trim() === '')
2353
+ return null;
2354
+ return ibanEstValide(valeur) ? null : { kind: 'iban' };
2355
+ }
2356
+ /**
2357
+ * Erreur de FORME d'un numero de telephone : chiffres, `+` de tete facultatif,
2358
+ * de 4 a 15 chiffres — la longueur maximale d'un numero international (E.164).
2359
+ *
2360
+ * ```ts
2361
+ * validate(chemin.telephone, ({ value }) => erreurTelephone(value()));
2362
+ * ```
2363
+ *
2364
+ * ⚠️ Une forme valide ne dit pas que le numero existe : seul le serveur le sait.
2365
+ * Un champ vide n'est pas une erreur de forme : l'obligation est une autre regle.
2366
+ */
2367
+ function erreurTelephone(valeur) {
2368
+ const numero = normaliserTelephone(valeur);
2369
+ if (numero === '')
2370
+ return null;
2371
+ return /^\+?[0-9]{4,15}$/.test(numero) ? null : { kind: 'telephone' };
2372
+ }
2373
+ /**
2374
+ * Erreur de bornes d'une date, a brancher sur un schema :
2375
+ *
2376
+ * ```ts
2377
+ * validate(chemin.naissance, ({ value }) => erreurDate(value(), { max: aujourdHui }));
2378
+ * ```
2379
+ *
2380
+ * Les bornes du schema et celles passees au calendrier doivent etre les memes :
2381
+ * le calendrier grise, le schema refuse une date tapee a la main.
2382
+ */
2383
+ function erreurDate(valeur, bornes) {
2384
+ if (valeur === null || valeur === '')
2385
+ return null;
2386
+ const { min, max } = bornes;
2387
+ if (min !== undefined && min !== null && valeur < min) {
2388
+ return { kind: 'dateMin', min };
2389
+ }
2390
+ if (max !== undefined && max !== null && valeur > max) {
2391
+ return { kind: 'dateMax', max };
2392
+ }
2393
+ return null;
2394
+ }
2395
+ /** Une fin anterieure au debut. Une borne manquante n'est pas une erreur de plage. */
2396
+ function erreurPlageDeDates(plage) {
2397
+ const { debut, fin } = plage;
2398
+ if (debut === null || fin === null)
2399
+ return null;
2400
+ return fin < debut ? { kind: 'plageDeDates' } : null;
2401
+ }
2402
+ /**
2403
+ * Erreurs d'une liste de fichiers, une par fichier refuse, pour dire LEQUEL :
2404
+ *
2405
+ * ```ts
2406
+ * validate(chemin.pieces, ({ value }) => erreursDeFichiers(value(), regles));
2407
+ * ```
2408
+ *
2409
+ * ⚠️ Confort, jamais securite (SEC-5) : le type se deduit de l'extension, et le
2410
+ * serveur relit le contenu.
2411
+ */
2412
+ function erreursDeFichiers(fichiers, regles) {
2413
+ const erreurs = [];
2414
+ const { accept = '', tailleMax, nombreMax } = regles;
2415
+ if (nombreMax !== undefined && fichiers.length > nombreMax) {
2416
+ erreurs.push({ kind: 'fichiersNombre', max: nombreMax });
2417
+ }
2418
+ for (const fichier of fichiers) {
2419
+ if (!typeDeFichierAccepte(fichier, accept)) {
2420
+ erreurs.push({ kind: 'fichierType', fichier: fichier.name });
2421
+ }
2422
+ else if (tailleMax !== undefined && fichier.size > tailleMax) {
2423
+ erreurs.push({
2424
+ kind: 'fichierTaille',
2425
+ fichier: fichier.name,
2426
+ max: tailleMax,
2427
+ });
2428
+ }
2429
+ }
2430
+ return erreurs;
2431
+ }
2432
+ /**
2433
+ * Erreurs a afficher par un champ qui LIT sa saisie (`transformedValue`) : celles
2434
+ * du formulaire, plus les erreurs de lecture qu'il ne connait pas encore.
2435
+ *
2436
+ * ⚠️ Relie a un formulaire, un champ recoit ses erreurs de lecture DANS `errors`,
2437
+ * par Signal Forms. Employe seul, par `[(value)]`, il ne les recoit nulle part :
2438
+ * sans cette fusion, « 12,5,3 » s'afficherait sans le moindre message. Une erreur
2439
+ * deja presente — meme genre, meme partie — n'est pas repetee.
2440
+ */
2441
+ function fusionnerErreurs(formulaire, lecture) {
2442
+ const cle = (erreur) => `${erreur.kind}|${erreur.partie ?? ''}`;
2443
+ const connues = new Set(formulaire.map(cle));
2444
+ return [...formulaire, ...lecture.filter((erreur) => !connues.has(cle(erreur)))];
2445
+ }
2446
+
2447
+ /**
2448
+ * Base des champs du socle : le contrat Signal Forms, ecrit une fois — tout sauf
2449
+ * `value`, dont le type depend du champ (texte, montant, date).
2450
+ *
2451
+ * ⚠️ **Une base, et non une copie par champ.** Neuf membres de contrat recopies
2452
+ * dans six composants, c'est six occasions d'en oublier un — et l'oubli ne se
2453
+ * voit pas : un champ sans `touched` n'affiche jamais ses erreurs, un champ sans
2454
+ * reflet de `hidden` ne se masque pas, et rien n'echoue.
2455
+ *
2456
+ * Les noms restent anglais : voir le glossaire, § 8.
2457
+ *
2458
+ * Le gabarit du champ doit nommer son element natif `#champ`, et le brancher sur
2459
+ * `touch` a la perte du focus.
2460
+ */
2461
+ class ContratDeChamp {
2462
+ libelle = input.required(/* @ts-ignore */
2463
+ ...(ngDevMode ? [{ debugName: "libelle" }] : /* istanbul ignore next */ []));
2464
+ aide = input(null, /* @ts-ignore */
2465
+ ...(ngDevMode ? [{ debugName: "aide" }] : /* istanbul ignore next */ []));
2466
+ errors = input([], /* @ts-ignore */
2467
+ ...(ngDevMode ? [{ debugName: "errors" }] : /* istanbul ignore next */ []));
2468
+ touched = input(false, { ...(ngDevMode ? { debugName: "touched" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2469
+ disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2470
+ readonly = input(false, { ...(ngDevMode ? { debugName: "readonly" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2471
+ required = input(false, { ...(ngDevMode ? { debugName: "required" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2472
+ hidden = input(false, { ...(ngDevMode ? { debugName: "hidden" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2473
+ name = input('', /* @ts-ignore */
2474
+ ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
2475
+ touch = output();
2476
+ champ = viewChild('champ', /* @ts-ignore */
2477
+ ...(ngDevMode ? [{ debugName: "champ" }] : /* istanbul ignore next */ []));
2478
+ /** Appele par Signal Forms pour amener le focus sur un champ en erreur. */
2479
+ focus(options) {
2480
+ this.champ()?.nativeElement.focus(options);
2481
+ }
2482
+ texteSaisi(evenement) {
2483
+ return evenement.target.value;
2484
+ }
2485
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ContratDeChamp, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2486
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "22.1.6", type: ContratDeChamp, isStandalone: true, inputs: { libelle: { classPropertyName: "libelle", publicName: "libelle", isSignal: true, isRequired: true, transformFunction: null }, aide: { classPropertyName: "aide", publicName: "aide", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, hidden: { classPropertyName: "hidden", publicName: "hidden", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { touch: "touch" }, host: { properties: { "attr.hidden": "hidden() ? \"\" : null" } }, viewQueries: [{ propertyName: "champ", first: true, predicate: ["champ"], descendants: true, isSignal: true }], ngImport: i0 });
2487
+ }
2488
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ContratDeChamp, decorators: [{
2489
+ type: Directive,
2490
+ args: [{
2491
+ host: {
2492
+ // L'entree `hidden` du contrat n'ecrit pas l'attribut : on le reflete, sans
2493
+ // quoi la regle `:host([hidden])` du socle ne s'applique pas.
2494
+ '[attr.hidden]': 'hidden() ? "" : null',
2495
+ },
2496
+ }]
2497
+ }], propDecorators: { libelle: [{ type: i0.Input, args: [{ isSignal: true, alias: "libelle", required: true }] }], aide: [{ type: i0.Input, args: [{ isSignal: true, alias: "aide", required: false }] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], hidden: [{ type: i0.Input, args: [{ isSignal: true, alias: "hidden", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], touch: [{ type: i0.Output, args: ["touch"] }], champ: [{ type: i0.ViewChild, args: ['champ', { isSignal: true }] }] } });
2498
+ /** Base des champs dont la valeur est le texte saisi. */
2499
+ class ControleDeSaisie extends ContratDeChamp {
2500
+ value = model('', /* @ts-ignore */
2501
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
2502
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ControleDeSaisie, deps: null, target: i0.ɵɵFactoryTarget.Directive });
2503
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.6", type: ControleDeSaisie, isStandalone: true, inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, usesInheritance: true, ngImport: i0 });
2504
+ }
2505
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ControleDeSaisie, decorators: [{
2506
+ type: Directive
2507
+ }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }] } });
2508
+
2509
+ let compteur$6 = 0;
2510
+ /** Elements qu'un `label for` etiquette. */
2511
+ const ELEMENTS_ETIQUETABLES = new Set([
2512
+ 'INPUT',
2513
+ 'SELECT',
2514
+ 'TEXTAREA',
2515
+ 'BUTTON',
2516
+ 'METER',
2517
+ 'OUTPUT',
2518
+ 'PROGRESS',
2519
+ ]);
2520
+ /**
2521
+ * Etiquette, aide, erreur et controle d'un champ de saisie — et le cablage qui
2522
+ * les relie.
2523
+ *
2524
+ * ⚠️ **Le SEUL endroit ou ce cablage existe** (audit de la vague 3, V3-2). Chaque
2525
+ * champ du socle l'emploie au lieu de refaire identifiants, `aria-describedby` et
2526
+ * `aria-invalid` : c'est precisement le code que l'on croit fini et qui se perd,
2527
+ * un champ specialise a la fois.
2528
+ *
2529
+ * L'ordre visuel suit celui de la lecture : etiquette, aide, erreur, controle.
2530
+ * L'erreur est AU-DESSUS du controle, pour etre vue avant de retaper.
2531
+ *
2532
+ * ⚠️ **L'erreur n'est pas une region vivante.** Annoncee a la perte du focus, elle
2533
+ * couperait la lecture du champ suivant, ou la personne est deja passee. Elle est
2534
+ * reliee au controle, donc lue quand on y revient ; a l'envoi, c'est le
2535
+ * recapitulatif d'erreurs qui prend le focus et les enumere.
2536
+ */
2537
+ class StFormField {
2538
+ libelles = inject(ST_LIBELLES);
2539
+ locale = inject(ST_LOCALE);
2540
+ element = inject(ElementRef);
2541
+ /**
2542
+ * ⚠️ OBLIGATOIRE et toujours visible (UX-1). Un texte indicatif ne le remplace
2543
+ * jamais : il disparait a la premiere frappe.
2544
+ */
2545
+ libelle = input.required(/* @ts-ignore */
2546
+ ...(ngDevMode ? [{ debugName: "libelle" }] : /* istanbul ignore next */ []));
2547
+ /** Aide permanente : format attendu, exemple. Lue apres l'etiquette. */
2548
+ aide = input(null, /* @ts-ignore */
2549
+ ...(ngDevMode ? [{ debugName: "aide" }] : /* istanbul ignore next */ []));
2550
+ /** Texte complementaire tenu a jour par le controle, comme un compteur. */
2551
+ complement = input(null, /* @ts-ignore */
2552
+ ...(ngDevMode ? [{ debugName: "complement" }] : /* istanbul ignore next */ []));
2553
+ erreurs = input([], /* @ts-ignore */
2554
+ ...(ngDevMode ? [{ debugName: "erreurs" }] : /* istanbul ignore next */ []));
2555
+ /**
2556
+ * ⚠️ Faux tant que la personne n'a pas quitte le champ ou tente l'envoi (UX-3) :
2557
+ * un formulaire vierge couvert d'erreurs accuse avant qu'on ait rien fait.
2558
+ */
2559
+ afficherErreurs = input(false, { ...(ngDevMode ? { debugName: "afficherErreurs" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2560
+ obligatoire = input(false, { ...(ngDevMode ? { debugName: "obligatoire" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2561
+ /**
2562
+ * ⚠️ Change l'ordre VISUEL, jamais celui du document : l'etiquette reste
2563
+ * reliee par `for`, et l'ordre de tabulation ne passe que par le controle.
2564
+ */
2565
+ disposition = input('empilee', /* @ts-ignore */
2566
+ ...(ngDevMode ? [{ debugName: "disposition" }] : /* istanbul ignore next */ []));
2567
+ /**
2568
+ * Etiquette lue mais non affichee.
2569
+ *
2570
+ * ⚠️ Reservee a la RECHERCHE, ou l'icone, le bouton et la position en tete de
2571
+ * page disent deja le but du champ. Partout ailleurs, une etiquette masquee est
2572
+ * l'etiquette qui manque au moment ou l'on tape (UX-1).
2573
+ */
2574
+ libelleMasque = input(false, { ...(ngDevMode ? { debugName: "libelleMasque" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2575
+ /** Identifiants du champ, lus par `stControleDeChamp` et par le gabarit. */
2576
+ identifiants = (() => {
2577
+ const base = `st-champ-${(compteur$6 += 1).toString()}`;
2578
+ return {
2579
+ controle: base,
2580
+ libelle: `${base}-libelle`,
2581
+ aide: `${base}-aide`,
2582
+ complement: `${base}-complement`,
2583
+ erreur: `${base}-erreur`,
2584
+ };
2585
+ })();
2586
+ libelleObligatoire = computed(() => this.libelles().obligatoire, /* @ts-ignore */
2587
+ ...(ngDevMode ? [{ debugName: "libelleObligatoire" }] : /* istanbul ignore next */ []));
2588
+ /** Messages a afficher, dans la langue courante. Vide tant qu'ils ne doivent pas l'etre. */
2589
+ messages = computed(() => {
2590
+ if (!this.afficherErreurs())
2591
+ return [];
2592
+ const libelles = this.libelles();
2593
+ const locale = this.locale();
2594
+ return this.erreurs().map((erreur) => messageDErreur(erreur, libelles, locale));
2595
+ }, /* @ts-ignore */
2596
+ ...(ngDevMode ? [{ debugName: "messages" }] : /* istanbul ignore next */ []));
2597
+ /**
2598
+ * Un clic sur l'etiquette d'un controle non natif n'y mene pas de lui-meme :
2599
+ * on y amene le focus, comme le navigateur le fait pour un champ natif.
2600
+ */
2601
+ focaliserLeControle() {
2602
+ const controle = this.element.nativeElement.querySelector(`#${this.identifiants.controle}`);
2603
+ if (controle !== null && !ELEMENTS_ETIQUETABLES.has(controle.tagName))
2604
+ controle.focus();
2605
+ }
2606
+ /** Lu par le controle pour `aria-invalid`. */
2607
+ enErreur = computed(() => this.messages().length > 0, /* @ts-ignore */
2608
+ ...(ngDevMode ? [{ debugName: "enErreur" }] : /* istanbul ignore next */ []));
2609
+ /**
2610
+ * ⚠️ Seuls les elements PRESENTS sont references : un `aria-describedby` qui
2611
+ * vise un identifiant absent est ignore par certains lecteurs d'ecran — tout
2612
+ * entier, y compris les references valides qui l'accompagnent.
2613
+ */
2614
+ descriptions = computed(() => {
2615
+ const ids = [];
2616
+ if (this.aide() !== null)
2617
+ ids.push(this.identifiants.aide);
2618
+ if (this.complement() !== null)
2619
+ ids.push(this.identifiants.complement);
2620
+ if (this.enErreur())
2621
+ ids.push(this.identifiants.erreur);
2622
+ return ids.length === 0 ? null : ids.join(' ');
2623
+ }, /* @ts-ignore */
2624
+ ...(ngDevMode ? [{ debugName: "descriptions" }] : /* istanbul ignore next */ []));
2625
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StFormField, deps: [], target: i0.ɵɵFactoryTarget.Component });
2626
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StFormField, isStandalone: true, selector: "st-form-field", inputs: { libelle: { classPropertyName: "libelle", publicName: "libelle", isSignal: true, isRequired: true, transformFunction: null }, aide: { classPropertyName: "aide", publicName: "aide", isSignal: true, isRequired: false, transformFunction: null }, complement: { classPropertyName: "complement", publicName: "complement", isSignal: true, isRequired: false, transformFunction: null }, erreurs: { classPropertyName: "erreurs", publicName: "erreurs", isSignal: true, isRequired: false, transformFunction: null }, afficherErreurs: { classPropertyName: "afficherErreurs", publicName: "afficherErreurs", isSignal: true, isRequired: false, transformFunction: null }, obligatoire: { classPropertyName: "obligatoire", publicName: "obligatoire", isSignal: true, isRequired: false, transformFunction: null }, disposition: { classPropertyName: "disposition", publicName: "disposition", isSignal: true, isRequired: false, transformFunction: null }, libelleMasque: { classPropertyName: "libelleMasque", publicName: "libelleMasque", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-en-erreur": "enErreur() ? \"\" : null", "attr.data-disposition": "disposition()" }, classAttribute: "st-form-field" }, ngImport: i0, template: "<!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus --\n Le clic sur une etiquette est une commodite de souris, comme pour tout\n champ natif : au clavier, le controle se rejoint par tabulation, et\n l'etiquette n'a pas a recevoir le focus. -->\n<label\n class=\"st-form-field__libelle\"\n [class.st-vh]=\"libelleMasque()\"\n [id]=\"identifiants.libelle\"\n [for]=\"identifiants.controle\"\n [attr.data-libelle]=\"libelle()\"\n (click)=\"focaliserLeControle()\"\n>\n {{ libelle() }}\n @if (obligatoire()) {\n <span class=\"st-form-field__obligatoire\">{{ libelleObligatoire() }}</span>\n }\n</label>\n\n@if (aide(); as texte) {\n <p class=\"st-form-field__aide\" [id]=\"identifiants.aide\">{{ texte }}</p>\n}\n\n@if (enErreur()) {\n <div class=\"st-form-field__erreurs\" [id]=\"identifiants.erreur\">\n @for (message of messages(); track $index) {\n <st-inline-message ton=\"danger\">{{ message }}</st-inline-message>\n }\n </div>\n}\n\n<div class=\"st-form-field__controle\">\n <ng-content />\n</div>\n\n@if (complement(); as texte) {\n <p class=\"st-form-field__complement\" [id]=\"identifiants.complement\">{{ texte }}</p>\n}\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:grid;grid-template-areas:\"libelle\" \"aide\" \"erreur\" \"controle\" \"complement\";grid-template-columns:minmax(0,1fr);gap:var(--st-espacement-1);margin-block-end:var(--st-espacement-5)}:host([data-disposition=case]){grid-template-areas:\"erreur erreur\" \"controle libelle\" \". aide\" \". complement\";grid-template-columns:auto minmax(0,1fr);column-gap:var(--st-espacement-2);align-items:center}.st-form-field__libelle{grid-area:libelle}.st-form-field__aide{grid-area:aide}.st-form-field__erreurs{grid-area:erreur}.st-form-field__controle{grid-area:controle}.st-form-field__complement{grid-area:complement}:host([data-disposition=case]) .st-form-field__libelle{font-weight:var(--st-graisse-normale)}.st-form-field__libelle{font-weight:var(--st-graisse-semi);color:var(--st-couleur-texte)}.st-form-field__obligatoire{margin-inline-start:var(--st-espacement-1);font-weight:var(--st-graisse-normale);color:var(--st-couleur-texte-discret)}.st-form-field__aide,.st-form-field__complement{margin:0;font-size:var(--st-taille-sm);color:var(--st-couleur-texte-discret)}:host([data-en-erreur]){padding-inline-start:var(--st-espacement-3);border-inline-start:3px solid var(--st-couleur-danger)}\n"], dependencies: [{ kind: "component", type: StInlineMessage, selector: "st-inline-message", inputs: ["ton", "identifiant"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2627
+ }
2628
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StFormField, decorators: [{
2629
+ type: Component,
2630
+ args: [{ selector: 'st-form-field', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StInlineMessage], host: {
2631
+ class: 'st-form-field',
2632
+ '[attr.data-en-erreur]': 'enErreur() ? "" : null',
2633
+ '[attr.data-disposition]': 'disposition()',
2634
+ }, template: "<!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus --\n Le clic sur une etiquette est une commodite de souris, comme pour tout\n champ natif : au clavier, le controle se rejoint par tabulation, et\n l'etiquette n'a pas a recevoir le focus. -->\n<label\n class=\"st-form-field__libelle\"\n [class.st-vh]=\"libelleMasque()\"\n [id]=\"identifiants.libelle\"\n [for]=\"identifiants.controle\"\n [attr.data-libelle]=\"libelle()\"\n (click)=\"focaliserLeControle()\"\n>\n {{ libelle() }}\n @if (obligatoire()) {\n <span class=\"st-form-field__obligatoire\">{{ libelleObligatoire() }}</span>\n }\n</label>\n\n@if (aide(); as texte) {\n <p class=\"st-form-field__aide\" [id]=\"identifiants.aide\">{{ texte }}</p>\n}\n\n@if (enErreur()) {\n <div class=\"st-form-field__erreurs\" [id]=\"identifiants.erreur\">\n @for (message of messages(); track $index) {\n <st-inline-message ton=\"danger\">{{ message }}</st-inline-message>\n }\n </div>\n}\n\n<div class=\"st-form-field__controle\">\n <ng-content />\n</div>\n\n@if (complement(); as texte) {\n <p class=\"st-form-field__complement\" [id]=\"identifiants.complement\">{{ texte }}</p>\n}\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:grid;grid-template-areas:\"libelle\" \"aide\" \"erreur\" \"controle\" \"complement\";grid-template-columns:minmax(0,1fr);gap:var(--st-espacement-1);margin-block-end:var(--st-espacement-5)}:host([data-disposition=case]){grid-template-areas:\"erreur erreur\" \"controle libelle\" \". aide\" \". complement\";grid-template-columns:auto minmax(0,1fr);column-gap:var(--st-espacement-2);align-items:center}.st-form-field__libelle{grid-area:libelle}.st-form-field__aide{grid-area:aide}.st-form-field__erreurs{grid-area:erreur}.st-form-field__controle{grid-area:controle}.st-form-field__complement{grid-area:complement}:host([data-disposition=case]) .st-form-field__libelle{font-weight:var(--st-graisse-normale)}.st-form-field__libelle{font-weight:var(--st-graisse-semi);color:var(--st-couleur-texte)}.st-form-field__obligatoire{margin-inline-start:var(--st-espacement-1);font-weight:var(--st-graisse-normale);color:var(--st-couleur-texte-discret)}.st-form-field__aide,.st-form-field__complement{margin:0;font-size:var(--st-taille-sm);color:var(--st-couleur-texte-discret)}:host([data-en-erreur]){padding-inline-start:var(--st-espacement-3);border-inline-start:3px solid var(--st-couleur-danger)}\n"] }]
2635
+ }], propDecorators: { libelle: [{ type: i0.Input, args: [{ isSignal: true, alias: "libelle", required: true }] }], aide: [{ type: i0.Input, args: [{ isSignal: true, alias: "aide", required: false }] }], complement: [{ type: i0.Input, args: [{ isSignal: true, alias: "complement", required: false }] }], erreurs: [{ type: i0.Input, args: [{ isSignal: true, alias: "erreurs", required: false }] }], afficherErreurs: [{ type: i0.Input, args: [{ isSignal: true, alias: "afficherErreurs", required: false }] }], obligatoire: [{ type: i0.Input, args: [{ isSignal: true, alias: "obligatoire", required: false }] }], disposition: [{ type: i0.Input, args: [{ isSignal: true, alias: "disposition", required: false }] }], libelleMasque: [{ type: i0.Input, args: [{ isSignal: true, alias: "libelleMasque", required: false }] }] } });
2636
+ /**
2637
+ * Pose sur l'element natif d'un champ le cablage de son `st-form-field` :
2638
+ * identifiant, description, invalidite, obligation.
2639
+ *
2640
+ * ⚠️ `aria-required` et NON l'attribut `required` natif. Le natif declenche la
2641
+ * validation du navigateur a l'envoi : une bulle « Veuillez renseigner ce champ »
2642
+ * dans la langue du NAVIGATEUR, pas dans celle de l'application, et qui double
2643
+ * le message du socle.
2644
+ */
2645
+ class StControleDeChamp {
2646
+ champ = inject(StFormField);
2647
+ /**
2648
+ * ⚠️ `label for` n'etiquette que les elements natifs de formulaire. Le
2649
+ * declencheur d'une selection multiple est un `div` de role `combobox` : sans
2650
+ * `aria-labelledby`, il n'aurait aucun nom, et l'etiquette visible ne dirait
2651
+ * rien au lecteur d'ecran.
2652
+ */
2653
+ etiquetable = ELEMENTS_ETIQUETABLES.has(inject(ElementRef).nativeElement.tagName);
2654
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StControleDeChamp, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2655
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.6", type: StControleDeChamp, isStandalone: true, selector: "[stControleDeChamp]", host: { properties: { "id": "champ.identifiants.controle", "attr.aria-labelledby": "etiquetable ? null : champ.identifiants.libelle", "attr.aria-describedby": "champ.descriptions()", "attr.aria-invalid": "champ.enErreur() ? \"true\" : null", "attr.aria-required": "champ.obligatoire() ? \"true\" : null" } }, ngImport: i0 });
2656
+ }
2657
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StControleDeChamp, decorators: [{
2658
+ type: Directive,
2659
+ args: [{
2660
+ selector: '[stControleDeChamp]',
2661
+ host: {
2662
+ '[id]': 'champ.identifiants.controle',
2663
+ '[attr.aria-labelledby]': 'etiquetable ? null : champ.identifiants.libelle',
2664
+ '[attr.aria-describedby]': 'champ.descriptions()',
2665
+ '[attr.aria-invalid]': 'champ.enErreur() ? "true" : null',
2666
+ '[attr.aria-required]': 'champ.obligatoire() ? "true" : null',
2667
+ },
2668
+ }]
2669
+ }] });
2670
+
2671
+ /**
2672
+ * Champ de saisie d'une ligne, integre a Signal Forms.
2673
+ *
2674
+ * ```html
2675
+ * <st-input libelle="Nom du beneficiaire" autocomplete="name" [formField]="virement.beneficiaire" />
2676
+ * <!-- ou, sans formulaire : -->
2677
+ * <st-input libelle="Reference" [(value)]="reference" />
2678
+ * ```
2679
+ *
2680
+ * ⚠️ **Contrat Signal Forms, noms anglais.** `value`, `errors`, `touched`,
2681
+ * `disabled`… sont cherches PAR LEUR NOM par la directive `[formField]` : les
2682
+ * traduire romprait l'integration sans la moindre erreur (audit de la vague 3,
2683
+ * V3-1). L'import d'`@angular/forms` est un import de TYPE : aucun code n'entre
2684
+ * dans le paquet.
2685
+ *
2686
+ * ⚠️ **Pas d'attribut `maxlength` natif.** Il TRONQUE en silence un texte colle
2687
+ * trop long : la personne croit avoir saisi sa reference entiere, et n'en envoie
2688
+ * que le debut. La limite passe par la validation, qui DIT le depassement.
2689
+ */
2690
+ class StInput extends ControleDeSaisie {
2691
+ type = input('text', /* @ts-ignore */
2692
+ ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
2693
+ /**
2694
+ * WCAG 1.3.5 : identifie le but du champ, pour le remplissage automatique et les
2695
+ * aides techniques. `null` : laisse le navigateur decider.
2696
+ */
2697
+ autocomplete = input(null, /* @ts-ignore */
2698
+ ...(ngDevMode ? [{ debugName: "autocomplete" }] : /* istanbul ignore next */ []));
2699
+ /** Clavier virtuel adapte : `numeric`, `decimal`, `email`… */
2700
+ inputmode = input(null, /* @ts-ignore */
2701
+ ...(ngDevMode ? [{ debugName: "inputmode" }] : /* istanbul ignore next */ []));
2702
+ surSaisie(evenement) {
2703
+ this.value.set(this.texteSaisi(evenement));
2704
+ }
2705
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StInput, deps: null, target: i0.ɵɵFactoryTarget.Component });
2706
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StInput, isStandalone: true, selector: "st-input", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, autocomplete: { classPropertyName: "autocomplete", publicName: "autocomplete", isSignal: true, isRequired: false, transformFunction: null }, inputmode: { classPropertyName: "inputmode", publicName: "inputmode", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "st-input" }, usesInheritance: true, ngImport: i0, template: "<st-form-field\n [libelle]=\"libelle()\"\n [aide]=\"aide()\"\n [erreurs]=\"errors()\"\n [afficherErreurs]=\"touched()\"\n [obligatoire]=\"required()\"\n>\n <input\n #champ\n class=\"st-input__champ\"\n stControleDeChamp\n [type]=\"type()\"\n [value]=\"value()\"\n [attr.name]=\"name() || null\"\n [attr.autocomplete]=\"autocomplete()\"\n [attr.inputmode]=\"inputmode()\"\n [disabled]=\"disabled()\"\n [readOnly]=\"readonly()\"\n (input)=\"surSaisie($event)\"\n (blur)=\"touch.emit()\"\n />\n</st-form-field>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block}.st-input__champ:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-input__champ{box-sizing:border-box;inline-size:100%;min-block-size:var(--st-cible-tactile-min);padding:var(--st-espacement-2) var(--st-espacement-3);font:inherit;color:var(--st-couleur-texte);background:var(--st-couleur-surface);border:1px solid var(--st-couleur-bordure-forte);border-radius:var(--st-rayon-sm)}.st-input__champ[aria-invalid=true]{border-color:var(--st-couleur-danger);box-shadow:inset 0 0 0 1px var(--st-couleur-danger)}.st-input__champ:disabled{color:var(--st-couleur-texte-desactive);cursor:not-allowed;background:var(--st-couleur-surface-enfoncee)}.st-input__champ:read-only:not(:disabled){background:var(--st-couleur-surface-enfoncee)}\n"], dependencies: [{ kind: "component", type: StFormField, selector: "st-form-field", inputs: ["libelle", "aide", "complement", "erreurs", "afficherErreurs", "obligatoire", "disposition", "libelleMasque"] }, { kind: "directive", type: StControleDeChamp, selector: "[stControleDeChamp]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2707
+ }
2708
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StInput, decorators: [{
2709
+ type: Component,
2710
+ args: [{ selector: 'st-input', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StFormField, StControleDeChamp], host: { class: 'st-input' }, template: "<st-form-field\n [libelle]=\"libelle()\"\n [aide]=\"aide()\"\n [erreurs]=\"errors()\"\n [afficherErreurs]=\"touched()\"\n [obligatoire]=\"required()\"\n>\n <input\n #champ\n class=\"st-input__champ\"\n stControleDeChamp\n [type]=\"type()\"\n [value]=\"value()\"\n [attr.name]=\"name() || null\"\n [attr.autocomplete]=\"autocomplete()\"\n [attr.inputmode]=\"inputmode()\"\n [disabled]=\"disabled()\"\n [readOnly]=\"readonly()\"\n (input)=\"surSaisie($event)\"\n (blur)=\"touch.emit()\"\n />\n</st-form-field>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block}.st-input__champ:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-input__champ{box-sizing:border-box;inline-size:100%;min-block-size:var(--st-cible-tactile-min);padding:var(--st-espacement-2) var(--st-espacement-3);font:inherit;color:var(--st-couleur-texte);background:var(--st-couleur-surface);border:1px solid var(--st-couleur-bordure-forte);border-radius:var(--st-rayon-sm)}.st-input__champ[aria-invalid=true]{border-color:var(--st-couleur-danger);box-shadow:inset 0 0 0 1px var(--st-couleur-danger)}.st-input__champ:disabled{color:var(--st-couleur-texte-desactive);cursor:not-allowed;background:var(--st-couleur-surface-enfoncee)}.st-input__champ:read-only:not(:disabled){background:var(--st-couleur-surface-enfoncee)}\n"] }]
2711
+ }], propDecorators: { type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], autocomplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocomplete", required: false }] }], inputmode: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputmode", required: false }] }] } });
2712
+
2713
+ /** Restant a partir duquel le compteur se signale. */
2714
+ const SEUILS_D_ANNONCE = [20, 10, 0];
2715
+ /**
2716
+ * Zone de texte, integree a Signal Forms, avec compteur quand une longueur
2717
+ * maximale est fixee.
2718
+ *
2719
+ * ⚠️ **Le compteur n'est pas annonce a chaque frappe** : une region vivante qui
2720
+ * change a chaque caractere recouvre ce que la personne tape. Il est RELIE a la
2721
+ * zone — donc lu quand on y revient — et seuls les seuils (20, 10, 0 restants)
2722
+ * et le depassement s'annoncent (UX-11).
2723
+ *
2724
+ * ⚠️ **Pas de `maxlength` natif**, meme raison que `st-input` : un texte colle
2725
+ * serait tronque en silence. Le compteur affiche le depassement, la validation
2726
+ * le refuse.
2727
+ */
2728
+ class StTextarea extends ControleDeSaisie {
2729
+ libelles = inject(ST_LIBELLES);
2730
+ lignes = input(4, /* @ts-ignore */
2731
+ ...(ngDevMode ? [{ debugName: "lignes" }] : /* istanbul ignore next */ []));
2732
+ /** Contrat Signal Forms : la longueur maximale fixee par le schema. */
2733
+ maxLength = input(undefined, /* @ts-ignore */
2734
+ ...(ngDevMode ? [{ debugName: "maxLength" }] : /* istanbul ignore next */ []));
2735
+ annonce = new AnnonceLocale(inject(DestroyRef));
2736
+ restants = computed(() => {
2737
+ const maximum = this.maxLength();
2738
+ return maximum === undefined ? null : maximum - this.value().length;
2739
+ }, /* @ts-ignore */
2740
+ ...(ngDevMode ? [{ debugName: "restants" }] : /* istanbul ignore next */ []));
2741
+ compteur = computed(() => {
2742
+ const restants = this.restants();
2743
+ if (restants === null)
2744
+ return null;
2745
+ const libelles = this.libelles();
2746
+ return restants >= 0
2747
+ ? libelles.caracteresRestants(restants)
2748
+ : libelles.caracteresEnTrop(-restants);
2749
+ }, /* @ts-ignore */
2750
+ ...(ngDevMode ? [{ debugName: "compteur" }] : /* istanbul ignore next */ []));
2751
+ constructor() {
2752
+ super();
2753
+ let precedent = null;
2754
+ effect(() => {
2755
+ const restants = this.restants();
2756
+ if (restants === null)
2757
+ return;
2758
+ const avant = precedent;
2759
+ precedent = restants;
2760
+ if (avant === null)
2761
+ return;
2762
+ const franchi = SEUILS_D_ANNONCE.some((seuil) => avant > seuil && restants <= seuil) ||
2763
+ (avant >= 0 && restants < 0);
2764
+ const texte = this.compteur();
2765
+ if (franchi && texte !== null)
2766
+ this.annonce.annoncer(texte);
2767
+ });
2768
+ }
2769
+ surSaisie(evenement) {
2770
+ this.value.set(this.texteSaisi(evenement));
2771
+ }
2772
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StTextarea, deps: [], target: i0.ɵɵFactoryTarget.Component });
2773
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StTextarea, isStandalone: true, selector: "st-textarea", inputs: { lignes: { classPropertyName: "lignes", publicName: "lignes", isSignal: true, isRequired: false, transformFunction: null }, maxLength: { classPropertyName: "maxLength", publicName: "maxLength", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "st-textarea" }, usesInheritance: true, ngImport: i0, template: "<st-form-field\n [libelle]=\"libelle()\"\n [aide]=\"aide()\"\n [complement]=\"compteur()\"\n [erreurs]=\"errors()\"\n [afficherErreurs]=\"touched()\"\n [obligatoire]=\"required()\"\n>\n <textarea\n #champ\n class=\"st-textarea__champ\"\n stControleDeChamp\n [rows]=\"lignes()\"\n [value]=\"value()\"\n [attr.name]=\"name() || null\"\n [disabled]=\"disabled()\"\n [readOnly]=\"readonly()\"\n (input)=\"surSaisie($event)\"\n (blur)=\"touch.emit()\"\n ></textarea>\n</st-form-field>\n<span class=\"st-vh\" aria-live=\"polite\">{{ annonce.texte() }}</span>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block}.st-textarea__champ:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-textarea__champ{box-sizing:border-box;inline-size:100%;min-block-size:var(--st-cible-tactile-min);padding:var(--st-espacement-2) var(--st-espacement-3);font:inherit;color:var(--st-couleur-texte);background:var(--st-couleur-surface);border:1px solid var(--st-couleur-bordure-forte);border-radius:var(--st-rayon-sm)}.st-textarea__champ[aria-invalid=true]{border-color:var(--st-couleur-danger);box-shadow:inset 0 0 0 1px var(--st-couleur-danger)}.st-textarea__champ:disabled{color:var(--st-couleur-texte-desactive);cursor:not-allowed;background:var(--st-couleur-surface-enfoncee)}.st-textarea__champ:read-only:not(:disabled){background:var(--st-couleur-surface-enfoncee)}.st-textarea__champ{resize:vertical}\n"], dependencies: [{ kind: "component", type: StFormField, selector: "st-form-field", inputs: ["libelle", "aide", "complement", "erreurs", "afficherErreurs", "obligatoire", "disposition", "libelleMasque"] }, { kind: "directive", type: StControleDeChamp, selector: "[stControleDeChamp]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2774
+ }
2775
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StTextarea, decorators: [{
2776
+ type: Component,
2777
+ args: [{ selector: 'st-textarea', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StFormField, StControleDeChamp], host: { class: 'st-textarea' }, template: "<st-form-field\n [libelle]=\"libelle()\"\n [aide]=\"aide()\"\n [complement]=\"compteur()\"\n [erreurs]=\"errors()\"\n [afficherErreurs]=\"touched()\"\n [obligatoire]=\"required()\"\n>\n <textarea\n #champ\n class=\"st-textarea__champ\"\n stControleDeChamp\n [rows]=\"lignes()\"\n [value]=\"value()\"\n [attr.name]=\"name() || null\"\n [disabled]=\"disabled()\"\n [readOnly]=\"readonly()\"\n (input)=\"surSaisie($event)\"\n (blur)=\"touch.emit()\"\n ></textarea>\n</st-form-field>\n<span class=\"st-vh\" aria-live=\"polite\">{{ annonce.texte() }}</span>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block}.st-textarea__champ:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-textarea__champ{box-sizing:border-box;inline-size:100%;min-block-size:var(--st-cible-tactile-min);padding:var(--st-espacement-2) var(--st-espacement-3);font:inherit;color:var(--st-couleur-texte);background:var(--st-couleur-surface);border:1px solid var(--st-couleur-bordure-forte);border-radius:var(--st-rayon-sm)}.st-textarea__champ[aria-invalid=true]{border-color:var(--st-couleur-danger);box-shadow:inset 0 0 0 1px var(--st-couleur-danger)}.st-textarea__champ:disabled{color:var(--st-couleur-texte-desactive);cursor:not-allowed;background:var(--st-couleur-surface-enfoncee)}.st-textarea__champ:read-only:not(:disabled){background:var(--st-couleur-surface-enfoncee)}.st-textarea__champ{resize:vertical}\n"] }]
2778
+ }], ctorParameters: () => [], propDecorators: { lignes: [{ type: i0.Input, args: [{ isSignal: true, alias: "lignes", required: false }] }], maxLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLength", required: false }] }] } });
2779
+
2780
+ let compteur$5 = 0;
2781
+ /**
2782
+ * Groupe de controles, nomme par sa QUESTION.
2783
+ *
2784
+ * ⚠️ `fieldset` et `legend` natifs (UX-7). Sans legende, un lecteur d'ecran
2785
+ * annonce « Oui, bouton radio » et « Non, bouton radio » : la reponse, jamais la
2786
+ * question. La legende est lue a l'entree dans le groupe.
2787
+ *
2788
+ * C'est le pendant de `st-form-field` pour un GROUPE : l'aide et l'erreur sont
2789
+ * reliees au `fieldset` par `aria-describedby`, et l'erreur porte sur le groupe
2790
+ * entier — « Choisissez un mode de reglement » — et non sur chaque option.
2791
+ *
2792
+ * ⚠️ L'obligation se dit dans la legende, en texte : `aria-required` n'est pas
2793
+ * valide sur un groupe, et `required` natif ferait parler le navigateur dans sa
2794
+ * propre langue.
2795
+ */
2796
+ class StFieldset {
2797
+ libelles = inject(ST_LIBELLES);
2798
+ locale = inject(ST_LOCALE);
2799
+ /** La question posee par le groupe. Obligatoire. */
2800
+ legende = input.required(/* @ts-ignore */
2801
+ ...(ngDevMode ? [{ debugName: "legende" }] : /* istanbul ignore next */ []));
2802
+ aide = input(null, /* @ts-ignore */
2803
+ ...(ngDevMode ? [{ debugName: "aide" }] : /* istanbul ignore next */ []));
2804
+ erreurs = input([], /* @ts-ignore */
2805
+ ...(ngDevMode ? [{ debugName: "erreurs" }] : /* istanbul ignore next */ []));
2806
+ afficherErreurs = input(false, { ...(ngDevMode ? { debugName: "afficherErreurs" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2807
+ obligatoire = input(false, { ...(ngDevMode ? { debugName: "obligatoire" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2808
+ base = `st-groupe-${(compteur$5 += 1).toString()}`;
2809
+ identifiantAide = `${this.base}-aide`;
2810
+ identifiantErreur = `${this.base}-erreur`;
2811
+ libelleObligatoire = computed(() => this.libelles().obligatoire, /* @ts-ignore */
2812
+ ...(ngDevMode ? [{ debugName: "libelleObligatoire" }] : /* istanbul ignore next */ []));
2813
+ messages = computed(() => {
2814
+ if (!this.afficherErreurs())
2815
+ return [];
2816
+ const libelles = this.libelles();
2817
+ const locale = this.locale();
2818
+ return this.erreurs().map((erreur) => messageDErreur(erreur, libelles, locale));
2819
+ }, /* @ts-ignore */
2820
+ ...(ngDevMode ? [{ debugName: "messages" }] : /* istanbul ignore next */ []));
2821
+ enErreur = computed(() => this.messages().length > 0, /* @ts-ignore */
2822
+ ...(ngDevMode ? [{ debugName: "enErreur" }] : /* istanbul ignore next */ []));
2823
+ descriptions = computed(() => {
2824
+ const ids = [];
2825
+ if (this.aide() !== null)
2826
+ ids.push(this.identifiantAide);
2827
+ if (this.enErreur())
2828
+ ids.push(this.identifiantErreur);
2829
+ return ids.length === 0 ? null : ids.join(' ');
2830
+ }, /* @ts-ignore */
2831
+ ...(ngDevMode ? [{ debugName: "descriptions" }] : /* istanbul ignore next */ []));
2832
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StFieldset, deps: [], target: i0.ɵɵFactoryTarget.Component });
2833
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StFieldset, isStandalone: true, selector: "st-fieldset", inputs: { legende: { classPropertyName: "legende", publicName: "legende", isSignal: true, isRequired: true, transformFunction: null }, aide: { classPropertyName: "aide", publicName: "aide", isSignal: true, isRequired: false, transformFunction: null }, erreurs: { classPropertyName: "erreurs", publicName: "erreurs", isSignal: true, isRequired: false, transformFunction: null }, afficherErreurs: { classPropertyName: "afficherErreurs", publicName: "afficherErreurs", isSignal: true, isRequired: false, transformFunction: null }, obligatoire: { classPropertyName: "obligatoire", publicName: "obligatoire", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-en-erreur": "enErreur() ? \"\" : null" }, classAttribute: "st-fieldset" }, ngImport: i0, template: "<fieldset class=\"st-fieldset__groupe\" [attr.aria-describedby]=\"descriptions()\">\n <legend class=\"st-fieldset__legende\" [attr.data-libelle]=\"legende()\">\n {{ legende() }}\n @if (obligatoire()) {\n <span class=\"st-fieldset__obligatoire\">{{ libelleObligatoire() }}</span>\n }\n </legend>\n\n @if (aide(); as texte) {\n <p class=\"st-fieldset__aide\" [id]=\"identifiantAide\">{{ texte }}</p>\n }\n\n @if (enErreur()) {\n <div class=\"st-fieldset__erreurs\" [id]=\"identifiantErreur\">\n @for (message of messages(); track $index) {\n <st-inline-message ton=\"danger\">{{ message }}</st-inline-message>\n }\n </div>\n }\n\n <div class=\"st-fieldset__controles\">\n <ng-content />\n </div>\n</fieldset>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block;margin-block-end:var(--st-espacement-5)}.st-fieldset__groupe{min-inline-size:0;padding:0;margin:0;border:0}.st-fieldset__legende{padding:0;margin-block-end:var(--st-espacement-2);font-weight:var(--st-graisse-semi);color:var(--st-couleur-texte)}.st-fieldset__obligatoire{margin-inline-start:var(--st-espacement-1);font-weight:var(--st-graisse-normale);color:var(--st-couleur-texte-discret)}.st-fieldset__aide{margin:0 0 var(--st-espacement-2);font-size:var(--st-taille-sm);color:var(--st-couleur-texte-discret)}.st-fieldset__erreurs{margin-block-end:var(--st-espacement-2)}.st-fieldset__controles{display:flex;flex-direction:column;gap:var(--st-espacement-2)}:host([data-en-erreur]) .st-fieldset__groupe{padding-inline-start:var(--st-espacement-3);border-inline-start:3px solid var(--st-couleur-danger)}\n"], dependencies: [{ kind: "component", type: StInlineMessage, selector: "st-inline-message", inputs: ["ton", "identifiant"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2834
+ }
2835
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StFieldset, decorators: [{
2836
+ type: Component,
2837
+ args: [{ selector: 'st-fieldset', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StInlineMessage], host: {
2838
+ class: 'st-fieldset',
2839
+ '[attr.data-en-erreur]': 'enErreur() ? "" : null',
2840
+ }, template: "<fieldset class=\"st-fieldset__groupe\" [attr.aria-describedby]=\"descriptions()\">\n <legend class=\"st-fieldset__legende\" [attr.data-libelle]=\"legende()\">\n {{ legende() }}\n @if (obligatoire()) {\n <span class=\"st-fieldset__obligatoire\">{{ libelleObligatoire() }}</span>\n }\n </legend>\n\n @if (aide(); as texte) {\n <p class=\"st-fieldset__aide\" [id]=\"identifiantAide\">{{ texte }}</p>\n }\n\n @if (enErreur()) {\n <div class=\"st-fieldset__erreurs\" [id]=\"identifiantErreur\">\n @for (message of messages(); track $index) {\n <st-inline-message ton=\"danger\">{{ message }}</st-inline-message>\n }\n </div>\n }\n\n <div class=\"st-fieldset__controles\">\n <ng-content />\n </div>\n</fieldset>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block;margin-block-end:var(--st-espacement-5)}.st-fieldset__groupe{min-inline-size:0;padding:0;margin:0;border:0}.st-fieldset__legende{padding:0;margin-block-end:var(--st-espacement-2);font-weight:var(--st-graisse-semi);color:var(--st-couleur-texte)}.st-fieldset__obligatoire{margin-inline-start:var(--st-espacement-1);font-weight:var(--st-graisse-normale);color:var(--st-couleur-texte-discret)}.st-fieldset__aide{margin:0 0 var(--st-espacement-2);font-size:var(--st-taille-sm);color:var(--st-couleur-texte-discret)}.st-fieldset__erreurs{margin-block-end:var(--st-espacement-2)}.st-fieldset__controles{display:flex;flex-direction:column;gap:var(--st-espacement-2)}:host([data-en-erreur]) .st-fieldset__groupe{padding-inline-start:var(--st-espacement-3);border-inline-start:3px solid var(--st-couleur-danger)}\n"] }]
2841
+ }], propDecorators: { legende: [{ type: i0.Input, args: [{ isSignal: true, alias: "legende", required: true }] }], aide: [{ type: i0.Input, args: [{ isSignal: true, alias: "aide", required: false }] }], erreurs: [{ type: i0.Input, args: [{ isSignal: true, alias: "erreurs", required: false }] }], afficherErreurs: [{ type: i0.Input, args: [{ isSignal: true, alias: "afficherErreurs", required: false }] }], obligatoire: [{ type: i0.Input, args: [{ isSignal: true, alias: "obligatoire", required: false }] }] } });
2842
+
2843
+ /**
2844
+ * Case a cocher, integree a Signal Forms.
2845
+ *
2846
+ * ```html
2847
+ * <st-checkbox libelle="J'accepte les conditions generales" [formField]="inscription.conditions" />
2848
+ * ```
2849
+ *
2850
+ * Un element `input type="checkbox"` natif : Espace coche, l'etat est annonce,
2851
+ * et la case suit le reglage de contraste du systeme sans rien ecrire.
2852
+ *
2853
+ * ⚠️ **Pour un choix a envoyer avec un formulaire.** Un reglage qui s'applique
2854
+ * IMMEDIATEMENT est un `st-switch` : la case promet un effet a l'envoi, et
2855
+ * l'interrupteur un effet tout de suite (UX-8).
2856
+ */
2857
+ class StCheckbox {
2858
+ libelle = input.required(/* @ts-ignore */
2859
+ ...(ngDevMode ? [{ debugName: "libelle" }] : /* istanbul ignore next */ []));
2860
+ aide = input(null, /* @ts-ignore */
2861
+ ...(ngDevMode ? [{ debugName: "aide" }] : /* istanbul ignore next */ []));
2862
+ /** Contrat Signal Forms. */
2863
+ checked = model(false, /* @ts-ignore */
2864
+ ...(ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []));
2865
+ errors = input([], /* @ts-ignore */
2866
+ ...(ngDevMode ? [{ debugName: "errors" }] : /* istanbul ignore next */ []));
2867
+ touched = input(false, { ...(ngDevMode ? { debugName: "touched" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2868
+ disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2869
+ required = input(false, { ...(ngDevMode ? { debugName: "required" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2870
+ hidden = input(false, { ...(ngDevMode ? { debugName: "hidden" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2871
+ name = input('', /* @ts-ignore */
2872
+ ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
2873
+ touch = output();
2874
+ champ = viewChild.required('champ', /* @ts-ignore */
2875
+ ...(ngDevMode ? [{ debugName: "champ" }] : /* istanbul ignore next */ []));
2876
+ focus(options) {
2877
+ this.champ().nativeElement.focus(options);
2878
+ }
2879
+ surChangement(evenement) {
2880
+ this.checked.set(evenement.target.checked);
2881
+ }
2882
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StCheckbox, deps: [], target: i0.ɵɵFactoryTarget.Component });
2883
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.6", type: StCheckbox, isStandalone: true, selector: "st-checkbox", inputs: { libelle: { classPropertyName: "libelle", publicName: "libelle", isSignal: true, isRequired: true, transformFunction: null }, aide: { classPropertyName: "aide", publicName: "aide", isSignal: true, isRequired: false, transformFunction: null }, checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, hidden: { classPropertyName: "hidden", publicName: "hidden", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange", touch: "touch" }, host: { properties: { "attr.hidden": "hidden() ? \"\" : null" }, classAttribute: "st-checkbox" }, viewQueries: [{ propertyName: "champ", first: true, predicate: ["champ"], descendants: true, isSignal: true }], ngImport: i0, template: "<st-form-field\n disposition=\"case\"\n [libelle]=\"libelle()\"\n [aide]=\"aide()\"\n [erreurs]=\"errors()\"\n [afficherErreurs]=\"touched()\"\n [obligatoire]=\"required()\"\n>\n <input\n #champ\n class=\"st-checkbox__case\"\n type=\"checkbox\"\n stControleDeChamp\n [checked]=\"checked()\"\n [attr.name]=\"name() || null\"\n [disabled]=\"disabled()\"\n (change)=\"surChangement($event)\"\n (blur)=\"touch.emit()\"\n />\n</st-form-field>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block}.st-checkbox__case:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-checkbox__case{inline-size:1.5rem;block-size:1.5rem;margin:0;cursor:pointer;accent-color:var(--st-couleur-primaire)}.st-checkbox__case:disabled{cursor:not-allowed}\n"], dependencies: [{ kind: "component", type: StFormField, selector: "st-form-field", inputs: ["libelle", "aide", "complement", "erreurs", "afficherErreurs", "obligatoire", "disposition", "libelleMasque"] }, { kind: "directive", type: StControleDeChamp, selector: "[stControleDeChamp]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2884
+ }
2885
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StCheckbox, decorators: [{
2886
+ type: Component,
2887
+ args: [{ selector: 'st-checkbox', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StFormField, StControleDeChamp], host: {
2888
+ class: 'st-checkbox',
2889
+ '[attr.hidden]': 'hidden() ? "" : null',
2890
+ }, template: "<st-form-field\n disposition=\"case\"\n [libelle]=\"libelle()\"\n [aide]=\"aide()\"\n [erreurs]=\"errors()\"\n [afficherErreurs]=\"touched()\"\n [obligatoire]=\"required()\"\n>\n <input\n #champ\n class=\"st-checkbox__case\"\n type=\"checkbox\"\n stControleDeChamp\n [checked]=\"checked()\"\n [attr.name]=\"name() || null\"\n [disabled]=\"disabled()\"\n (change)=\"surChangement($event)\"\n (blur)=\"touch.emit()\"\n />\n</st-form-field>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block}.st-checkbox__case:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-checkbox__case{inline-size:1.5rem;block-size:1.5rem;margin:0;cursor:pointer;accent-color:var(--st-couleur-primaire)}.st-checkbox__case:disabled{cursor:not-allowed}\n"] }]
2891
+ }], propDecorators: { libelle: [{ type: i0.Input, args: [{ isSignal: true, alias: "libelle", required: true }] }], aide: [{ type: i0.Input, args: [{ isSignal: true, alias: "aide", required: false }] }], checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }, { type: i0.Output, args: ["checkedChange"] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], hidden: [{ type: i0.Input, args: [{ isSignal: true, alias: "hidden", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], touch: [{ type: i0.Output, args: ["touch"] }], champ: [{ type: i0.ViewChild, args: ['champ', { isSignal: true }] }] } });
2892
+
2893
+ let compteur$4 = 0;
2894
+ /**
2895
+ * Groupe de boutons radio, integre a Signal Forms.
2896
+ *
2897
+ * ```html
2898
+ * <st-radio-group legende="Mode de reglement" [options]="modes" [formField]="commande.mode" />
2899
+ * ```
2900
+ *
2901
+ * ⚠️ **De vrais boutons radio natifs** : un seul arret de tabulation pour le
2902
+ * groupe, deplacement aux fleches, « 2 sur 3 » annonce. Les recrire en ARIA,
2903
+ * c'est cent lignes pour obtenir moins bien — meme raison que `st-theme-toggle`.
2904
+ *
2905
+ * ⚠️ **L'erreur porte sur le groupe**, par `st-fieldset`, et non sur chaque option :
2906
+ * « Choisissez un mode de reglement », une fois.
2907
+ *
2908
+ * `touch` n'est emis que lorsque le focus QUITTE le groupe : passer d'une option a
2909
+ * l'autre aux fleches n'est pas une fin de saisie, et l'erreur n'a pas a surgir
2910
+ * pendant qu'on choisit.
2911
+ */
2912
+ class StRadioGroup {
2913
+ element = inject(ElementRef);
2914
+ legende = input.required(/* @ts-ignore */
2915
+ ...(ngDevMode ? [{ debugName: "legende" }] : /* istanbul ignore next */ []));
2916
+ aide = input(null, /* @ts-ignore */
2917
+ ...(ngDevMode ? [{ debugName: "aide" }] : /* istanbul ignore next */ []));
2918
+ options = input.required(/* @ts-ignore */
2919
+ ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
2920
+ /** Contrat Signal Forms. */
2921
+ value = model('', /* @ts-ignore */
2922
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
2923
+ errors = input([], /* @ts-ignore */
2924
+ ...(ngDevMode ? [{ debugName: "errors" }] : /* istanbul ignore next */ []));
2925
+ touched = input(false, { ...(ngDevMode ? { debugName: "touched" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2926
+ disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2927
+ required = input(false, { ...(ngDevMode ? { debugName: "required" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2928
+ hidden = input(false, { ...(ngDevMode ? { debugName: "hidden" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2929
+ name = input('', /* @ts-ignore */
2930
+ ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
2931
+ touch = output();
2932
+ /** Nom partage par les options : sans lui, chaque radio forme son propre groupe. */
2933
+ nomParDefaut = `st-radio-${(compteur$4 += 1).toString()}`;
2934
+ nomDuGroupe() {
2935
+ return this.name() === '' ? this.nomParDefaut : this.name();
2936
+ }
2937
+ identifiantAide(indice) {
2938
+ return `${this.nomParDefaut}-aide-${indice.toString()}`;
2939
+ }
2940
+ /** Focus sur l'option cochee, sinon la premiere disponible : c'est l'arret du groupe. */
2941
+ focus(options) {
2942
+ const hote = this.element.nativeElement;
2943
+ const cible = hote.querySelector('input:checked') ??
2944
+ hote.querySelector('input:not(:disabled)');
2945
+ cible?.focus(options);
2946
+ }
2947
+ choisir(valeur) {
2948
+ this.value.set(valeur);
2949
+ }
2950
+ aLaSortie(evenement) {
2951
+ const suivant = evenement.relatedTarget;
2952
+ if (suivant !== null && this.element.nativeElement.contains(suivant))
2953
+ return;
2954
+ this.touch.emit();
2955
+ }
2956
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StRadioGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
2957
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StRadioGroup, isStandalone: true, selector: "st-radio-group", inputs: { legende: { classPropertyName: "legende", publicName: "legende", isSignal: true, isRequired: true, transformFunction: null }, aide: { classPropertyName: "aide", publicName: "aide", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, hidden: { classPropertyName: "hidden", publicName: "hidden", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touch: "touch" }, host: { listeners: { "focusout": "aLaSortie($event)" }, properties: { "attr.hidden": "hidden() ? \"\" : null" }, classAttribute: "st-radio-group" }, ngImport: i0, template: "<st-fieldset\n [legende]=\"legende()\"\n [aide]=\"aide()\"\n [erreurs]=\"errors()\"\n [afficherErreurs]=\"touched()\"\n [obligatoire]=\"required()\"\n>\n @for (option of options(); track option.valeur; let indice = $index) {\n <div class=\"st-radio-group__option\">\n <input\n class=\"st-radio-group__radio\"\n type=\"radio\"\n [id]=\"nomDuGroupe() + '-' + indice\"\n [name]=\"nomDuGroupe()\"\n [value]=\"option.valeur\"\n [checked]=\"option.valeur === value()\"\n [disabled]=\"disabled() || option.desactivee === true\"\n [attr.aria-describedby]=\"option.aide ? identifiantAide(indice) : null\"\n (change)=\"choisir(option.valeur)\"\n />\n <label class=\"st-radio-group__libelle\" [for]=\"nomDuGroupe() + '-' + indice\">\n {{ option.libelle }}\n </label>\n @if (option.aide; as aide) {\n <p class=\"st-radio-group__aide\" [id]=\"identifiantAide(indice)\">{{ aide }}</p>\n }\n </div>\n }\n</st-fieldset>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block}.st-radio-group__option{display:grid;grid-template-columns:auto minmax(0,1fr);column-gap:var(--st-espacement-2);align-items:center}.st-radio-group__radio:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-radio-group__radio{inline-size:1.5rem;block-size:1.5rem;margin:0;cursor:pointer;accent-color:var(--st-couleur-primaire)}.st-radio-group__radio:disabled{cursor:not-allowed}.st-radio-group__libelle{cursor:pointer}.st-radio-group__aide{grid-column:2;margin:0;font-size:var(--st-taille-sm);color:var(--st-couleur-texte-discret)}\n"], dependencies: [{ kind: "component", type: StFieldset, selector: "st-fieldset", inputs: ["legende", "aide", "erreurs", "afficherErreurs", "obligatoire"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2958
+ }
2959
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StRadioGroup, decorators: [{
2960
+ type: Component,
2961
+ args: [{ selector: 'st-radio-group', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StFieldset], host: {
2962
+ class: 'st-radio-group',
2963
+ '[attr.hidden]': 'hidden() ? "" : null',
2964
+ '(focusout)': 'aLaSortie($event)',
2965
+ }, template: "<st-fieldset\n [legende]=\"legende()\"\n [aide]=\"aide()\"\n [erreurs]=\"errors()\"\n [afficherErreurs]=\"touched()\"\n [obligatoire]=\"required()\"\n>\n @for (option of options(); track option.valeur; let indice = $index) {\n <div class=\"st-radio-group__option\">\n <input\n class=\"st-radio-group__radio\"\n type=\"radio\"\n [id]=\"nomDuGroupe() + '-' + indice\"\n [name]=\"nomDuGroupe()\"\n [value]=\"option.valeur\"\n [checked]=\"option.valeur === value()\"\n [disabled]=\"disabled() || option.desactivee === true\"\n [attr.aria-describedby]=\"option.aide ? identifiantAide(indice) : null\"\n (change)=\"choisir(option.valeur)\"\n />\n <label class=\"st-radio-group__libelle\" [for]=\"nomDuGroupe() + '-' + indice\">\n {{ option.libelle }}\n </label>\n @if (option.aide; as aide) {\n <p class=\"st-radio-group__aide\" [id]=\"identifiantAide(indice)\">{{ aide }}</p>\n }\n </div>\n }\n</st-fieldset>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block}.st-radio-group__option{display:grid;grid-template-columns:auto minmax(0,1fr);column-gap:var(--st-espacement-2);align-items:center}.st-radio-group__radio:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-radio-group__radio{inline-size:1.5rem;block-size:1.5rem;margin:0;cursor:pointer;accent-color:var(--st-couleur-primaire)}.st-radio-group__radio:disabled{cursor:not-allowed}.st-radio-group__libelle{cursor:pointer}.st-radio-group__aide{grid-column:2;margin:0;font-size:var(--st-taille-sm);color:var(--st-couleur-texte-discret)}\n"] }]
2966
+ }], propDecorators: { legende: [{ type: i0.Input, args: [{ isSignal: true, alias: "legende", required: true }] }], aide: [{ type: i0.Input, args: [{ isSignal: true, alias: "aide", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], hidden: [{ type: i0.Input, args: [{ isSignal: true, alias: "hidden", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], touch: [{ type: i0.Output, args: ["touch"] }] } });
2967
+
2968
+ /**
2969
+ * Interrupteur : un reglage qui s'applique IMMEDIATEMENT.
2970
+ *
2971
+ * ```html
2972
+ * <st-switch libelle="Notifications par SMS" [(checked)]="sms" (checkedChange)="enregistrer($event)" />
2973
+ * ```
2974
+ *
2975
+ * ⚠️ **Jamais dans un formulaire a envoyer** (UX-8). Un interrupteur promet que
2976
+ * l'effet a lieu au basculement ; pose au-dessus d'un bouton « Enregistrer », il
2977
+ * ment — la personne croit le reglage applique, quitte la page, et le perd. Pour
2978
+ * un choix envoye plus tard, c'est `st-checkbox`.
2979
+ *
2980
+ * C'est pourquoi il n'affiche aucune erreur de validation : un reglage immediat
2981
+ * ne se valide pas a l'envoi. Un refus du serveur se dit par un message, et
2982
+ * l'interrupteur revient a son etat precedent.
2983
+ *
2984
+ * ⚠️ Une case a cocher native avec `role="switch"` : Espace bascule, l'etiquette
2985
+ * est reliee par `for`, et le lecteur d'ecran annonce « active » ou
2986
+ * « desactive » — mieux qu'un `div` qui imiterait tout cela.
2987
+ */
2988
+ class StSwitch {
2989
+ libelle = input.required(/* @ts-ignore */
2990
+ ...(ngDevMode ? [{ debugName: "libelle" }] : /* istanbul ignore next */ []));
2991
+ aide = input(null, /* @ts-ignore */
2992
+ ...(ngDevMode ? [{ debugName: "aide" }] : /* istanbul ignore next */ []));
2993
+ /** Contrat Signal Forms. */
2994
+ checked = model(false, /* @ts-ignore */
2995
+ ...(ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []));
2996
+ disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2997
+ hidden = input(false, { ...(ngDevMode ? { debugName: "hidden" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
2998
+ name = input('', /* @ts-ignore */
2999
+ ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
3000
+ touch = output();
3001
+ champ = viewChild.required('champ', /* @ts-ignore */
3002
+ ...(ngDevMode ? [{ debugName: "champ" }] : /* istanbul ignore next */ []));
3003
+ focus(options) {
3004
+ this.champ().nativeElement.focus(options);
3005
+ }
3006
+ surChangement(evenement) {
3007
+ this.checked.set(evenement.target.checked);
3008
+ }
3009
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StSwitch, deps: [], target: i0.ɵɵFactoryTarget.Component });
3010
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.6", type: StSwitch, isStandalone: true, selector: "st-switch", inputs: { libelle: { classPropertyName: "libelle", publicName: "libelle", isSignal: true, isRequired: true, transformFunction: null }, aide: { classPropertyName: "aide", publicName: "aide", isSignal: true, isRequired: false, transformFunction: null }, checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, hidden: { classPropertyName: "hidden", publicName: "hidden", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange", touch: "touch" }, host: { properties: { "attr.hidden": "hidden() ? \"\" : null" }, classAttribute: "st-switch" }, viewQueries: [{ propertyName: "champ", first: true, predicate: ["champ"], descendants: true, isSignal: true }], ngImport: i0, template: "<st-form-field disposition=\"case\" [libelle]=\"libelle()\" [aide]=\"aide()\">\n <input\n #champ\n class=\"st-switch__interrupteur\"\n type=\"checkbox\"\n role=\"switch\"\n stControleDeChamp\n [checked]=\"checked()\"\n [attr.aria-checked]=\"checked()\"\n [attr.name]=\"name() || null\"\n [disabled]=\"disabled()\"\n (change)=\"surChangement($event)\"\n (blur)=\"touch.emit()\"\n />\n</st-form-field>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block}.st-switch__interrupteur:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-switch__interrupteur{position:relative;inline-size:2.75rem;block-size:1.5rem;margin:0;cursor:pointer;background:var(--st-couleur-surface-enfoncee);border:1px solid var(--st-couleur-bordure-forte);border-radius:var(--st-rayon-pleine);appearance:none}.st-switch__interrupteur:after{position:absolute;inset-block-start:50%;inset-inline-start:.125rem;inline-size:1.125rem;block-size:1.125rem;content:\"\";background:var(--st-couleur-texte-discret);border-radius:var(--st-rayon-pleine);transition:inset-inline-start var(--st-duree-rapide) ease;transform:translateY(-50%)}.st-switch__interrupteur:checked{background:var(--st-couleur-primaire);border-color:var(--st-couleur-primaire)}.st-switch__interrupteur:checked:after{inset-inline-start:calc(100% - 1.25rem);background:var(--st-couleur-sur-primaire)}.st-switch__interrupteur:disabled{cursor:not-allowed;opacity:.6}@media(forced-colors:active){.st-switch__interrupteur{border-color:CanvasText}.st-switch__interrupteur:after{background:CanvasText}.st-switch__interrupteur:checked:after{background:Highlight}}\n"], dependencies: [{ kind: "component", type: StFormField, selector: "st-form-field", inputs: ["libelle", "aide", "complement", "erreurs", "afficherErreurs", "obligatoire", "disposition", "libelleMasque"] }, { kind: "directive", type: StControleDeChamp, selector: "[stControleDeChamp]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3011
+ }
3012
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StSwitch, decorators: [{
3013
+ type: Component,
3014
+ args: [{ selector: 'st-switch', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StFormField, StControleDeChamp], host: {
3015
+ class: 'st-switch',
3016
+ '[attr.hidden]': 'hidden() ? "" : null',
3017
+ }, template: "<st-form-field disposition=\"case\" [libelle]=\"libelle()\" [aide]=\"aide()\">\n <input\n #champ\n class=\"st-switch__interrupteur\"\n type=\"checkbox\"\n role=\"switch\"\n stControleDeChamp\n [checked]=\"checked()\"\n [attr.aria-checked]=\"checked()\"\n [attr.name]=\"name() || null\"\n [disabled]=\"disabled()\"\n (change)=\"surChangement($event)\"\n (blur)=\"touch.emit()\"\n />\n</st-form-field>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block}.st-switch__interrupteur:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-switch__interrupteur{position:relative;inline-size:2.75rem;block-size:1.5rem;margin:0;cursor:pointer;background:var(--st-couleur-surface-enfoncee);border:1px solid var(--st-couleur-bordure-forte);border-radius:var(--st-rayon-pleine);appearance:none}.st-switch__interrupteur:after{position:absolute;inset-block-start:50%;inset-inline-start:.125rem;inline-size:1.125rem;block-size:1.125rem;content:\"\";background:var(--st-couleur-texte-discret);border-radius:var(--st-rayon-pleine);transition:inset-inline-start var(--st-duree-rapide) ease;transform:translateY(-50%)}.st-switch__interrupteur:checked{background:var(--st-couleur-primaire);border-color:var(--st-couleur-primaire)}.st-switch__interrupteur:checked:after{inset-inline-start:calc(100% - 1.25rem);background:var(--st-couleur-sur-primaire)}.st-switch__interrupteur:disabled{cursor:not-allowed;opacity:.6}@media(forced-colors:active){.st-switch__interrupteur{border-color:CanvasText}.st-switch__interrupteur:after{background:CanvasText}.st-switch__interrupteur:checked:after{background:Highlight}}\n"] }]
3018
+ }], propDecorators: { libelle: [{ type: i0.Input, args: [{ isSignal: true, alias: "libelle", required: true }] }], aide: [{ type: i0.Input, args: [{ isSignal: true, alias: "aide", required: false }] }], checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }, { type: i0.Output, args: ["checkedChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], hidden: [{ type: i0.Input, args: [{ isSignal: true, alias: "hidden", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], touch: [{ type: i0.Output, args: ["touch"] }], champ: [{ type: i0.ViewChild, args: ['champ', { isSignal: true }] }] } });
3019
+
3020
+ let compteur$3 = 0;
3021
+ /**
3022
+ * Recapitulatif des erreurs d'un formulaire, a l'envoi.
3023
+ *
3024
+ * ```html
3025
+ * <st-error-summary [erreurs]="tentative() ? virement().errorSummary() : []" />
3026
+ * ```
3027
+ *
3028
+ * ⚠️ **Il prend le focus en apparaissant** (UX-5). Sans lui, une personne au
3029
+ * clavier ou au lecteur d'ecran appuie sur « Envoyer », et rien ne se passe : le
3030
+ * champ refuse est en haut de la page, hors de sa vue, et personne ne le lui dit.
3031
+ *
3032
+ * ⚠️ **Chaque ligne nomme son champ.** « Ce champ est obligatoire. » repete cinq
3033
+ * fois n'apprend rien ; « Nom du beneficiaire : ce champ est obligatoire. », si.
3034
+ * Le libelle est lu sur l'element lie au champ, par Signal Forms — sans registre,
3035
+ * et quel que soit le composant.
3036
+ *
3037
+ * ⚠️ **Une ligne par champ**, la premiere erreur seulement : trois erreurs sur le
3038
+ * meme IBAN font trois lignes pour une seule correction.
3039
+ *
3040
+ * ⚠️ **Une region nommee par son titre.** Un `div` sans role ne PEUT pas porter
3041
+ * `aria-labelledby` : le nom serait ignore, et le focus n'annoncerait rien. En
3042
+ * region, il annonce « 2 erreurs a corriger » a l'arrivee du focus, et se
3043
+ * retrouve dans la liste des reperes.
3044
+ *
3045
+ * Chaque ligne amene le focus sur son champ : c'est le champ, et non la ligne,
3046
+ * qu'il faut corriger. Une erreur rattachee au formulaire entier — un refus du
3047
+ * serveur sur un champ inconnu — s'affiche sans lien.
3048
+ */
3049
+ class StErrorSummary {
3050
+ libelles = inject(ST_LIBELLES);
3051
+ locale = inject(ST_LOCALE);
3052
+ element = inject(ElementRef);
3053
+ injecteur = inject(Injector);
3054
+ erreurs = input.required(/* @ts-ignore */
3055
+ ...(ngDevMode ? [{ debugName: "erreurs" }] : /* istanbul ignore next */ []));
3056
+ /** `null` : « N erreurs a corriger », du dictionnaire. */
3057
+ titre = input(null, /* @ts-ignore */
3058
+ ...(ngDevMode ? [{ debugName: "titre" }] : /* istanbul ignore next */ []));
3059
+ /** Unique par instance : deux recapitulatifs sur une page partageraient leur titre. */
3060
+ identifiantDuTitre = `st-recapitulatif-${(compteur$3 += 1).toString()}`;
3061
+ lignes = computed(() => {
3062
+ const libelles = this.libelles();
3063
+ const locale = this.locale();
3064
+ const vus = new Set();
3065
+ const lignes = [];
3066
+ for (const erreur of this.erreurs()) {
3067
+ const champ = erreur.fieldTree;
3068
+ if (champ !== undefined) {
3069
+ if (vus.has(champ))
3070
+ continue;
3071
+ vus.add(champ);
3072
+ }
3073
+ const etat = champ?.();
3074
+ const liaison = etat?.formFieldBindings()[0];
3075
+ lignes.push({
3076
+ libelle: liaison === undefined ? null : libelleDe(liaison.element),
3077
+ message: messageDErreur(erreur, libelles, locale),
3078
+ aller: () => {
3079
+ etat?.focusBoundControl();
3080
+ },
3081
+ });
3082
+ }
3083
+ return lignes;
3084
+ }, /* @ts-ignore */
3085
+ ...(ngDevMode ? [{ debugName: "lignes" }] : /* istanbul ignore next */ []));
3086
+ titreLu = computed(() => this.titre() ?? this.libelles().erreursACorriger(this.lignes().length), /* @ts-ignore */
3087
+ ...(ngDevMode ? [{ debugName: "titreLu" }] : /* istanbul ignore next */ []));
3088
+ constructor() {
3089
+ // Le focus a l'APPARITION seulement : le reprendre a chaque correction
3090
+ // arracherait la personne au champ qu'elle est en train de corriger.
3091
+ let visible = false;
3092
+ effect(() => {
3093
+ const maintenant = this.lignes().length > 0;
3094
+ if (maintenant && !visible) {
3095
+ afterNextRender(() => {
3096
+ this.focus();
3097
+ }, { injector: this.injecteur });
3098
+ }
3099
+ visible = maintenant;
3100
+ });
3101
+ }
3102
+ /** A appeler apres un envoi refuse, quand le recapitulatif etait deja visible. */
3103
+ focus() {
3104
+ this.element.nativeElement.querySelector('.st-error-summary__cadre')?.focus();
3105
+ }
3106
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StErrorSummary, deps: [], target: i0.ɵɵFactoryTarget.Component });
3107
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StErrorSummary, isStandalone: true, selector: "st-error-summary", inputs: { erreurs: { classPropertyName: "erreurs", publicName: "erreurs", isSignal: true, isRequired: true, transformFunction: null }, titre: { classPropertyName: "titre", publicName: "titre", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.hidden": "lignes().length === 0 ? \"\" : null" }, classAttribute: "st-error-summary" }, ngImport: i0, template: "@if (lignes().length > 0) {\n <div\n class=\"st-error-summary__cadre\"\n role=\"region\"\n tabindex=\"-1\"\n [attr.aria-labelledby]=\"identifiantDuTitre\"\n >\n <h2 class=\"st-error-summary__titre\" [id]=\"identifiantDuTitre\">\n <st-icon nom=\"cercle-croix\" taille=\"sm\" />\n {{ titreLu() }}\n </h2>\n <ul class=\"st-error-summary__liste\">\n @for (ligne of lignes(); track $index) {\n <li>\n @if (ligne.libelle !== null) {\n <button type=\"button\" class=\"st-error-summary__lien\" (click)=\"ligne.aller()\">\n {{ ligne.libelle }} : {{ ligne.message }}\n </button>\n } @else {\n {{ ligne.message }}\n }\n </li>\n }\n </ul>\n </div>\n}\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block;margin-block-end:var(--st-espacement-5)}.st-error-summary__cadre:focus{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-error-summary__cadre{padding:var(--st-espacement-4);color:var(--st-couleur-sur-danger-discret);background:var(--st-couleur-danger-discret);border:2px solid var(--st-couleur-danger);border-radius:var(--st-rayon-md)}.st-error-summary__titre{display:flex;gap:var(--st-espacement-2);align-items:center;margin:0 0 var(--st-espacement-2);font-size:var(--st-taille-lg)}.st-error-summary__liste{padding-inline-start:var(--st-espacement-5);margin:0}.st-error-summary__lien:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-error-summary__lien{padding:0;font:inherit;color:inherit;text-align:start;text-decoration:underline;cursor:pointer;background:none;border:0}@media(forced-colors:active){.st-error-summary__cadre{border-color:CanvasText}}\n"], dependencies: [{ kind: "component", type: StIcon, selector: "st-icon", inputs: ["nom", "taille", "ton", "etiquette"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3108
+ }
3109
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StErrorSummary, decorators: [{
3110
+ type: Component,
3111
+ args: [{ selector: 'st-error-summary', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StIcon], host: {
3112
+ class: 'st-error-summary',
3113
+ '[attr.hidden]': 'lignes().length === 0 ? "" : null',
3114
+ }, template: "@if (lignes().length > 0) {\n <div\n class=\"st-error-summary__cadre\"\n role=\"region\"\n tabindex=\"-1\"\n [attr.aria-labelledby]=\"identifiantDuTitre\"\n >\n <h2 class=\"st-error-summary__titre\" [id]=\"identifiantDuTitre\">\n <st-icon nom=\"cercle-croix\" taille=\"sm\" />\n {{ titreLu() }}\n </h2>\n <ul class=\"st-error-summary__liste\">\n @for (ligne of lignes(); track $index) {\n <li>\n @if (ligne.libelle !== null) {\n <button type=\"button\" class=\"st-error-summary__lien\" (click)=\"ligne.aller()\">\n {{ ligne.libelle }} : {{ ligne.message }}\n </button>\n } @else {\n {{ ligne.message }}\n }\n </li>\n }\n </ul>\n </div>\n}\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block;margin-block-end:var(--st-espacement-5)}.st-error-summary__cadre:focus{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-error-summary__cadre{padding:var(--st-espacement-4);color:var(--st-couleur-sur-danger-discret);background:var(--st-couleur-danger-discret);border:2px solid var(--st-couleur-danger);border-radius:var(--st-rayon-md)}.st-error-summary__titre{display:flex;gap:var(--st-espacement-2);align-items:center;margin:0 0 var(--st-espacement-2);font-size:var(--st-taille-lg)}.st-error-summary__liste{padding-inline-start:var(--st-espacement-5);margin:0}.st-error-summary__lien:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-error-summary__lien{padding:0;font:inherit;color:inherit;text-align:start;text-decoration:underline;cursor:pointer;background:none;border:0}@media(forced-colors:active){.st-error-summary__cadre{border-color:CanvasText}}\n"] }]
3115
+ }], ctorParameters: () => [], propDecorators: { erreurs: [{ type: i0.Input, args: [{ isSignal: true, alias: "erreurs", required: true }] }], titre: [{ type: i0.Input, args: [{ isSignal: true, alias: "titre", required: false }] }] } });
3116
+ /**
3117
+ * Libelle d'un champ, lu sur l'element lie : l'attribut pose par le socle, sinon
3118
+ * l'etiquette native, sinon `aria-label`.
3119
+ */
3120
+ function libelleDe(element) {
3121
+ const socle = element.querySelector('[data-libelle]')?.getAttribute('data-libelle');
3122
+ if (socle !== null && socle !== undefined)
3123
+ return socle;
3124
+ const etiquette = element.labels?.[0]?.textContent.trim();
3125
+ if (etiquette !== undefined && etiquette !== '')
3126
+ return etiquette;
3127
+ return element.getAttribute('aria-label');
3128
+ }
3129
+
3130
+ /**
3131
+ * Mot de passe, avec revelation.
3132
+ *
3133
+ * ```html
3134
+ * <st-password-field libelle="Mot de passe" usage="creation" [regles]="regles" [formField]="compte.motDePasse" />
3135
+ * ```
3136
+ *
3137
+ * ⚠️ **`autocomplete` selon l'usage** (SEC-2) : `current-password` a la connexion,
3138
+ * `new-password` a la creation — c'est ce qui fait proposer par le gestionnaire
3139
+ * un mot de passe FORT au bon endroit, et non l'ancien.
3140
+ *
3141
+ * ⚠️ **Le collage n'est jamais bloque** (SEC-1, NIST SP 800-63B) : l'interdire
3142
+ * pousse vers des mots de passe courts, retenus de tete, et casse les
3143
+ * gestionnaires de mots de passe.
3144
+ *
3145
+ * ⚠️ **Revele, il se remasque des que le focus quitte le champ, et a l'envoi du
3146
+ * formulaire** (SEC-4) : un mot de passe laisse en clair reste lisible par-dessus
3147
+ * l'epaule, sur l'ecran suivant comme sur celui-ci. L'envoi par Entree ne fait
3148
+ * pas quitter le champ : d'ou l'ecoute de `submit`, qui remonte jusqu'au document.
3149
+ *
3150
+ * Le bouton de revelation est un bouton bascule : `aria-pressed` porte l'etat, et
3151
+ * l'etiquette ne change PAS — « Masquer le mot de passe, enfonce » se lirait
3152
+ * comme une double negation.
3153
+ *
3154
+ * ⚠️ **Aucun indicateur de « force »**, et c'est un refus. Une estimation faite
3155
+ * dans le navigateur donne « fort » a `Motdepasse1!` : elle rassure a tort. Les
3156
+ * regles sont affichees AVANT la saisie (UX-10), et c'est le serveur qui verifie —
3157
+ * y compris contre les mots de passe deja divulgues, qu'aucune regle locale ne
3158
+ * voit.
3159
+ */
3160
+ class StPasswordField extends ControleDeSaisie {
3161
+ libelles = inject(ST_LIBELLES);
3162
+ element = inject(ElementRef);
3163
+ usage = input('connexion', /* @ts-ignore */
3164
+ ...(ngDevMode ? [{ debugName: "usage" }] : /* istanbul ignore next */ []));
3165
+ /** Regles affichees avant la saisie, comme aide du champ. */
3166
+ regles = input([], /* @ts-ignore */
3167
+ ...(ngDevMode ? [{ debugName: "regles" }] : /* istanbul ignore next */ []));
3168
+ revele = signal(false, /* @ts-ignore */
3169
+ ...(ngDevMode ? [{ debugName: "revele" }] : /* istanbul ignore next */ []));
3170
+ autocomplete = computed(() => this.usage() === 'creation' ? 'new-password' : 'current-password', /* @ts-ignore */
3171
+ ...(ngDevMode ? [{ debugName: "autocomplete" }] : /* istanbul ignore next */ []));
3172
+ aideLue = computed(() => {
3173
+ const regles = this.regles();
3174
+ const aide = this.aide();
3175
+ if (regles.length === 0)
3176
+ return aide;
3177
+ return [aide, ...regles].filter((texte) => texte !== null).join(' ');
3178
+ }, /* @ts-ignore */
3179
+ ...(ngDevMode ? [{ debugName: "aideLue" }] : /* istanbul ignore next */ []));
3180
+ basculer() {
3181
+ this.revele.update((revele) => !revele);
3182
+ // Revele alors que le focus est ailleurs — clic direct sur le bouton, champ
3183
+ // rempli par le gestionnaire —, il ne pourrait plus quitter le champ : rien ne
3184
+ // le remasquerait. Au clavier, le focus est deja sur le bouton, et y reste.
3185
+ const hote = this.element.nativeElement;
3186
+ if (this.revele() && !hote.contains(hote.ownerDocument.activeElement))
3187
+ this.focus();
3188
+ }
3189
+ surSaisie(evenement) {
3190
+ this.value.set(this.texteSaisi(evenement));
3191
+ }
3192
+ aLEnvoi(evenement) {
3193
+ const formulaire = evenement.target;
3194
+ if (formulaire?.contains(this.element.nativeElement) === true)
3195
+ this.revele.set(false);
3196
+ }
3197
+ aLaSortie(evenement) {
3198
+ const suivant = evenement.relatedTarget;
3199
+ if (suivant !== null && this.element.nativeElement.contains(suivant))
3200
+ return;
3201
+ this.revele.set(false);
3202
+ }
3203
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StPasswordField, deps: null, target: i0.ɵɵFactoryTarget.Component });
3204
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StPasswordField, isStandalone: true, selector: "st-password-field", inputs: { usage: { classPropertyName: "usage", publicName: "usage", isSignal: true, isRequired: false, transformFunction: null }, regles: { classPropertyName: "regles", publicName: "regles", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "focusout": "aLaSortie($event)", "document:submit": "aLEnvoi($event)" }, classAttribute: "st-password-field" }, usesInheritance: true, ngImport: i0, template: "<st-form-field\n [libelle]=\"libelle()\"\n [aide]=\"aideLue()\"\n [erreurs]=\"errors()\"\n [afficherErreurs]=\"touched()\"\n [obligatoire]=\"required()\"\n>\n <div class=\"st-password-field__ligne\">\n <input\n #champ\n class=\"st-password-field__champ\"\n stControleDeChamp\n spellcheck=\"false\"\n autocapitalize=\"none\"\n autocorrect=\"off\"\n [type]=\"revele() ? 'text' : 'password'\"\n [value]=\"value()\"\n [attr.autocomplete]=\"autocomplete()\"\n [attr.name]=\"name() || null\"\n [disabled]=\"disabled()\"\n [readOnly]=\"readonly()\"\n (input)=\"surSaisie($event)\"\n (blur)=\"touch.emit()\"\n />\n <!-- eslint-disable-next-line @angular-eslint/template/elements-content --\n Le contenu vient du gabarit de stIconButton. Le nom accessible est\n impose par le type (`etiquette` est requis) et verifie par axe.\n `mousedown` sans effet par defaut : le focus reste dans le champ. Safari\n ne donne pas le focus a un bouton clique, et la sortie du champ\n remasquerait juste avant que le clic ne revele a nouveau. -->\n <button\n stIconButton\n type=\"button\"\n [icone]=\"revele() ? 'oeil-barre' : 'oeil'\"\n [etiquette]=\"libelles().afficherLeMotDePasse\"\n [enfonce]=\"revele()\"\n [disabled]=\"disabled()\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"basculer()\"\n ></button>\n </div>\n</st-form-field>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block}.st-password-field__ligne{display:flex;gap:var(--st-espacement-1);align-items:center}.st-password-field__champ:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-password-field__champ{box-sizing:border-box;inline-size:100%;min-block-size:var(--st-cible-tactile-min);padding:var(--st-espacement-2) var(--st-espacement-3);font:inherit;color:var(--st-couleur-texte);background:var(--st-couleur-surface);border:1px solid var(--st-couleur-bordure-forte);border-radius:var(--st-rayon-sm)}.st-password-field__champ[aria-invalid=true]{border-color:var(--st-couleur-danger);box-shadow:inset 0 0 0 1px var(--st-couleur-danger)}.st-password-field__champ:disabled{color:var(--st-couleur-texte-desactive);cursor:not-allowed;background:var(--st-couleur-surface-enfoncee)}.st-password-field__champ:read-only:not(:disabled){background:var(--st-couleur-surface-enfoncee)}.st-password-field__champ{flex:1 1 auto}\n"], dependencies: [{ kind: "component", type: StFormField, selector: "st-form-field", inputs: ["libelle", "aide", "complement", "erreurs", "afficherErreurs", "obligatoire", "disposition", "libelleMasque"] }, { kind: "directive", type: StControleDeChamp, selector: "[stControleDeChamp]" }, { kind: "component", type: StIconButton, selector: "button[stIconButton]", inputs: ["icone", "etiquette", "variante", "taille", "enfonce"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3205
+ }
3206
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StPasswordField, decorators: [{
3207
+ type: Component,
3208
+ args: [{ selector: 'st-password-field', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StFormField, StControleDeChamp, StIconButton], host: {
3209
+ class: 'st-password-field',
3210
+ '(focusout)': 'aLaSortie($event)',
3211
+ '(document:submit)': 'aLEnvoi($event)',
3212
+ }, template: "<st-form-field\n [libelle]=\"libelle()\"\n [aide]=\"aideLue()\"\n [erreurs]=\"errors()\"\n [afficherErreurs]=\"touched()\"\n [obligatoire]=\"required()\"\n>\n <div class=\"st-password-field__ligne\">\n <input\n #champ\n class=\"st-password-field__champ\"\n stControleDeChamp\n spellcheck=\"false\"\n autocapitalize=\"none\"\n autocorrect=\"off\"\n [type]=\"revele() ? 'text' : 'password'\"\n [value]=\"value()\"\n [attr.autocomplete]=\"autocomplete()\"\n [attr.name]=\"name() || null\"\n [disabled]=\"disabled()\"\n [readOnly]=\"readonly()\"\n (input)=\"surSaisie($event)\"\n (blur)=\"touch.emit()\"\n />\n <!-- eslint-disable-next-line @angular-eslint/template/elements-content --\n Le contenu vient du gabarit de stIconButton. Le nom accessible est\n impose par le type (`etiquette` est requis) et verifie par axe.\n `mousedown` sans effet par defaut : le focus reste dans le champ. Safari\n ne donne pas le focus a un bouton clique, et la sortie du champ\n remasquerait juste avant que le clic ne revele a nouveau. -->\n <button\n stIconButton\n type=\"button\"\n [icone]=\"revele() ? 'oeil-barre' : 'oeil'\"\n [etiquette]=\"libelles().afficherLeMotDePasse\"\n [enfonce]=\"revele()\"\n [disabled]=\"disabled()\"\n (mousedown)=\"$event.preventDefault()\"\n (click)=\"basculer()\"\n ></button>\n </div>\n</st-form-field>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block}.st-password-field__ligne{display:flex;gap:var(--st-espacement-1);align-items:center}.st-password-field__champ:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-password-field__champ{box-sizing:border-box;inline-size:100%;min-block-size:var(--st-cible-tactile-min);padding:var(--st-espacement-2) var(--st-espacement-3);font:inherit;color:var(--st-couleur-texte);background:var(--st-couleur-surface);border:1px solid var(--st-couleur-bordure-forte);border-radius:var(--st-rayon-sm)}.st-password-field__champ[aria-invalid=true]{border-color:var(--st-couleur-danger);box-shadow:inset 0 0 0 1px var(--st-couleur-danger)}.st-password-field__champ:disabled{color:var(--st-couleur-texte-desactive);cursor:not-allowed;background:var(--st-couleur-surface-enfoncee)}.st-password-field__champ:read-only:not(:disabled){background:var(--st-couleur-surface-enfoncee)}.st-password-field__champ{flex:1 1 auto}\n"] }]
3213
+ }], propDecorators: { usage: [{ type: i0.Input, args: [{ isSignal: true, alias: "usage", required: false }] }], regles: [{ type: i0.Input, args: [{ isSignal: true, alias: "regles", required: false }] }] } });
3214
+
3215
+ /**
3216
+ * Code a usage unique : second facteur, code recu par SMS ou par courriel.
3217
+ *
3218
+ * ⚠️ **UN seul champ, pas six cases** (UX-9). Six champs cassent le collage, le
3219
+ * remplissage automatique du code recu par SMS, et la lecture au lecteur d'ecran,
3220
+ * qui annonce six champs sans nom au lieu d'un seul.
3221
+ *
3222
+ * ⚠️ `autocomplete="one-time-code"` : iOS et Android proposent alors le code recu,
3223
+ * d'un toucher. Clavier numerique par `inputmode`, et NON par `type="number"`,
3224
+ * qui retire les zeros de tete et accepte « 1e5 ».
3225
+ *
3226
+ * ⚠️ **Aucun envoi automatique** a la sixieme saisie : un formulaire qui part de
3227
+ * lui-meme surprend (WCAG 3.2.2), et part aussi avec un code mal colle. Le code
3228
+ * colle est nettoye de ses espaces et tirets — « 123 456 » —, jamais tronque.
3229
+ */
3230
+ class StOtpField extends ControleDeSaisie {
3231
+ libelles = inject(ST_LIBELLES);
3232
+ longueur = input(6, /* @ts-ignore */
3233
+ ...(ngDevMode ? [{ debugName: "longueur" }] : /* istanbul ignore next */ []));
3234
+ aideLue = computed(() => this.aide() ?? this.libelles().codeAChiffres(this.longueur()), /* @ts-ignore */
3235
+ ...(ngDevMode ? [{ debugName: "aideLue" }] : /* istanbul ignore next */ []));
3236
+ surSaisie(evenement) {
3237
+ this.value.set(this.texteSaisi(evenement).replace(/[\s-]/g, ''));
3238
+ }
3239
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StOtpField, deps: null, target: i0.ɵɵFactoryTarget.Component });
3240
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StOtpField, isStandalone: true, selector: "st-otp-field", inputs: { longueur: { classPropertyName: "longueur", publicName: "longueur", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "st-otp-field" }, usesInheritance: true, ngImport: i0, template: "<st-form-field\n [libelle]=\"libelle()\"\n [aide]=\"aideLue()\"\n [erreurs]=\"errors()\"\n [afficherErreurs]=\"touched()\"\n [obligatoire]=\"required()\"\n>\n <input\n #champ\n class=\"st-otp-field__champ\"\n stControleDeChamp\n type=\"text\"\n inputmode=\"numeric\"\n autocomplete=\"one-time-code\"\n spellcheck=\"false\"\n autocapitalize=\"none\"\n [value]=\"value()\"\n [attr.name]=\"name() || null\"\n [disabled]=\"disabled()\"\n [readOnly]=\"readonly()\"\n (input)=\"surSaisie($event)\"\n (blur)=\"touch.emit()\"\n />\n</st-form-field>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block}.st-otp-field__champ:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-otp-field__champ{box-sizing:border-box;inline-size:100%;min-block-size:var(--st-cible-tactile-min);padding:var(--st-espacement-2) var(--st-espacement-3);font:inherit;color:var(--st-couleur-texte);background:var(--st-couleur-surface);border:1px solid var(--st-couleur-bordure-forte);border-radius:var(--st-rayon-sm)}.st-otp-field__champ[aria-invalid=true]{border-color:var(--st-couleur-danger);box-shadow:inset 0 0 0 1px var(--st-couleur-danger)}.st-otp-field__champ:disabled{color:var(--st-couleur-texte-desactive);cursor:not-allowed;background:var(--st-couleur-surface-enfoncee)}.st-otp-field__champ:read-only:not(:disabled){background:var(--st-couleur-surface-enfoncee)}.st-otp-field__champ{max-inline-size:12rem;font-family:var(--st-police-mono);font-variant-numeric:tabular-nums;letter-spacing:.3em}\n"], dependencies: [{ kind: "component", type: StFormField, selector: "st-form-field", inputs: ["libelle", "aide", "complement", "erreurs", "afficherErreurs", "obligatoire", "disposition", "libelleMasque"] }, { kind: "directive", type: StControleDeChamp, selector: "[stControleDeChamp]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3241
+ }
3242
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StOtpField, decorators: [{
3243
+ type: Component,
3244
+ args: [{ selector: 'st-otp-field', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StFormField, StControleDeChamp], host: { class: 'st-otp-field' }, template: "<st-form-field\n [libelle]=\"libelle()\"\n [aide]=\"aideLue()\"\n [erreurs]=\"errors()\"\n [afficherErreurs]=\"touched()\"\n [obligatoire]=\"required()\"\n>\n <input\n #champ\n class=\"st-otp-field__champ\"\n stControleDeChamp\n type=\"text\"\n inputmode=\"numeric\"\n autocomplete=\"one-time-code\"\n spellcheck=\"false\"\n autocapitalize=\"none\"\n [value]=\"value()\"\n [attr.name]=\"name() || null\"\n [disabled]=\"disabled()\"\n [readOnly]=\"readonly()\"\n (input)=\"surSaisie($event)\"\n (blur)=\"touch.emit()\"\n />\n</st-form-field>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block}.st-otp-field__champ:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-otp-field__champ{box-sizing:border-box;inline-size:100%;min-block-size:var(--st-cible-tactile-min);padding:var(--st-espacement-2) var(--st-espacement-3);font:inherit;color:var(--st-couleur-texte);background:var(--st-couleur-surface);border:1px solid var(--st-couleur-bordure-forte);border-radius:var(--st-rayon-sm)}.st-otp-field__champ[aria-invalid=true]{border-color:var(--st-couleur-danger);box-shadow:inset 0 0 0 1px var(--st-couleur-danger)}.st-otp-field__champ:disabled{color:var(--st-couleur-texte-desactive);cursor:not-allowed;background:var(--st-couleur-surface-enfoncee)}.st-otp-field__champ:read-only:not(:disabled){background:var(--st-couleur-surface-enfoncee)}.st-otp-field__champ{max-inline-size:12rem;font-family:var(--st-police-mono);font-variant-numeric:tabular-nums;letter-spacing:.3em}\n"] }]
3245
+ }], propDecorators: { longueur: [{ type: i0.Input, args: [{ isSignal: true, alias: "longueur", required: false }] }] } });
3246
+
3247
+ /**
3248
+ * Champ de recherche : un repere, un champ, un bouton.
3249
+ *
3250
+ * ```html
3251
+ * <st-search-field libelle="Rechercher un beneficiaire" (recherche)="filtrer($event)" />
3252
+ * ```
3253
+ *
3254
+ * ⚠️ **Un repere `search`** : la recherche se retrouve dans la liste des reperes du
3255
+ * lecteur d'ecran, a cote de la navigation et du contenu.
3256
+ *
3257
+ * L'etiquette est lue sans etre affichee — seule exception au socle (UX-1) : la
3258
+ * loupe, le bouton et la position disent deja le but du champ.
3259
+ *
3260
+ * ⚠️ **Jamais dans l'adresse quand le terme est personnel** (SEC-6). Chercher un
3261
+ * nom, un IBAN ou un numero en `?q=` inscrit la donnee dans l'historique, dans les
3262
+ * journaux des intermediaires, et dans l'en-tete `Referer` des pages suivantes.
3263
+ * `recherche` emet le terme : c'est a l'appelant de ne pas le mettre dans l'URL.
3264
+ */
3265
+ class StSearchField extends ControleDeSaisie {
3266
+ libelles = inject(ST_LIBELLES);
3267
+ /** Emis a la validation — Entree ou bouton —, et non a chaque frappe. */
3268
+ recherche = output();
3269
+ surSaisie(evenement) {
3270
+ this.value.set(this.texteSaisi(evenement));
3271
+ }
3272
+ lancer(evenement) {
3273
+ evenement?.preventDefault();
3274
+ this.recherche.emit(this.value().trim());
3275
+ }
3276
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StSearchField, deps: null, target: i0.ɵɵFactoryTarget.Component });
3277
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.6", type: StSearchField, isStandalone: true, selector: "st-search-field", outputs: { recherche: "recherche" }, host: { attributes: { "role": "search" }, classAttribute: "st-search-field" }, usesInheritance: true, ngImport: i0, template: "<st-form-field\n libelleMasque\n [libelle]=\"libelle()\"\n [aide]=\"aide()\"\n [erreurs]=\"errors()\"\n [afficherErreurs]=\"touched()\"\n>\n <div class=\"st-search-field__ligne\">\n <st-icon class=\"st-search-field__loupe\" nom=\"recherche\" taille=\"sm\" />\n <input\n #champ\n class=\"st-search-field__champ\"\n stControleDeChamp\n type=\"search\"\n enterkeyhint=\"search\"\n [value]=\"value()\"\n [attr.name]=\"name() || null\"\n [disabled]=\"disabled()\"\n (input)=\"surSaisie($event)\"\n (keydown.enter)=\"lancer($event)\"\n (blur)=\"touch.emit()\"\n />\n <button stButton type=\"button\" [disabled]=\"disabled()\" (click)=\"lancer()\">\n {{ libelles().rechercher }}\n </button>\n </div>\n</st-form-field>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block}.st-search-field__ligne{position:relative;display:flex;gap:var(--st-espacement-2);align-items:center}.st-search-field__loupe{position:absolute;inset-inline-start:var(--st-espacement-3);color:var(--st-couleur-texte-discret);pointer-events:none}.st-search-field__champ:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-search-field__champ{box-sizing:border-box;inline-size:100%;min-block-size:var(--st-cible-tactile-min);padding:var(--st-espacement-2) var(--st-espacement-3);font:inherit;color:var(--st-couleur-texte);background:var(--st-couleur-surface);border:1px solid var(--st-couleur-bordure-forte);border-radius:var(--st-rayon-sm)}.st-search-field__champ[aria-invalid=true]{border-color:var(--st-couleur-danger);box-shadow:inset 0 0 0 1px var(--st-couleur-danger)}.st-search-field__champ:disabled{color:var(--st-couleur-texte-desactive);cursor:not-allowed;background:var(--st-couleur-surface-enfoncee)}.st-search-field__champ:read-only:not(:disabled){background:var(--st-couleur-surface-enfoncee)}.st-search-field__champ{flex:1 1 auto;padding-inline-start:calc(var(--st-espacement-3) * 2 + 1rem)}\n"], dependencies: [{ kind: "component", type: StFormField, selector: "st-form-field", inputs: ["libelle", "aide", "complement", "erreurs", "afficherErreurs", "obligatoire", "disposition", "libelleMasque"] }, { kind: "directive", type: StControleDeChamp, selector: "[stControleDeChamp]" }, { kind: "component", type: StIcon, selector: "st-icon", inputs: ["nom", "taille", "ton", "etiquette"] }, { kind: "component", type: StButton, selector: "button[stButton]", inputs: ["variante", "taille", "pleineLargeur", "iconeAvant", "iconeApres", "chargement", "indisponible"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3278
+ }
3279
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StSearchField, decorators: [{
3280
+ type: Component,
3281
+ args: [{ selector: 'st-search-field', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StFormField, StControleDeChamp, StIcon, StButton], host: { class: 'st-search-field', role: 'search' }, template: "<st-form-field\n libelleMasque\n [libelle]=\"libelle()\"\n [aide]=\"aide()\"\n [erreurs]=\"errors()\"\n [afficherErreurs]=\"touched()\"\n>\n <div class=\"st-search-field__ligne\">\n <st-icon class=\"st-search-field__loupe\" nom=\"recherche\" taille=\"sm\" />\n <input\n #champ\n class=\"st-search-field__champ\"\n stControleDeChamp\n type=\"search\"\n enterkeyhint=\"search\"\n [value]=\"value()\"\n [attr.name]=\"name() || null\"\n [disabled]=\"disabled()\"\n (input)=\"surSaisie($event)\"\n (keydown.enter)=\"lancer($event)\"\n (blur)=\"touch.emit()\"\n />\n <button stButton type=\"button\" [disabled]=\"disabled()\" (click)=\"lancer()\">\n {{ libelles().rechercher }}\n </button>\n </div>\n</st-form-field>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block}.st-search-field__ligne{position:relative;display:flex;gap:var(--st-espacement-2);align-items:center}.st-search-field__loupe{position:absolute;inset-inline-start:var(--st-espacement-3);color:var(--st-couleur-texte-discret);pointer-events:none}.st-search-field__champ:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-search-field__champ{box-sizing:border-box;inline-size:100%;min-block-size:var(--st-cible-tactile-min);padding:var(--st-espacement-2) var(--st-espacement-3);font:inherit;color:var(--st-couleur-texte);background:var(--st-couleur-surface);border:1px solid var(--st-couleur-bordure-forte);border-radius:var(--st-rayon-sm)}.st-search-field__champ[aria-invalid=true]{border-color:var(--st-couleur-danger);box-shadow:inset 0 0 0 1px var(--st-couleur-danger)}.st-search-field__champ:disabled{color:var(--st-couleur-texte-desactive);cursor:not-allowed;background:var(--st-couleur-surface-enfoncee)}.st-search-field__champ:read-only:not(:disabled){background:var(--st-couleur-surface-enfoncee)}.st-search-field__champ{flex:1 1 auto;padding-inline-start:calc(var(--st-espacement-3) * 2 + 1rem)}\n"] }]
3282
+ }], propDecorators: { recherche: [{ type: i0.Output, args: ["recherche"] }] } });
3283
+
3284
+ /**
3285
+ * IBAN. La valeur du modele est NORMALISEE — sans espaces, en majuscules —, et
3286
+ * l'affichage groupe par quatre.
3287
+ *
3288
+ * ```html
3289
+ * <st-iban-field libelle="IBAN du beneficiaire" [formField]="virement.iban" />
3290
+ * <!-- schema : validate(chemin.iban, ({ value }) => erreurIban(value())) -->
3291
+ * ```
3292
+ *
3293
+ * ⚠️ **Le groupement se fait a la sortie du champ, jamais pendant la frappe.**
3294
+ * Reformater a chaque caractere deplace le curseur a la fin : corriger une
3295
+ * erreur au milieu de 27 caracteres devient impossible, chaque frappe renvoyant a
3296
+ * la fin de la ligne.
3297
+ *
3298
+ * ⚠️ **Aucune verification de validite ici** : elle appartient au schema, par
3299
+ * `erreurIban`, pour s'afficher au bon moment et par le bon canal. Et elle reste un
3300
+ * confort (SEC-5) : le serveur revalide.
3301
+ *
3302
+ * `autocapitalize="characters"` et correction orthographique coupee : un IBAN
3303
+ * n'est pas un mot, et une correction automatique le fausserait.
3304
+ */
3305
+ class StIbanField extends ControleDeSaisie {
3306
+ libelles = inject(ST_LIBELLES);
3307
+ enSaisie = signal(false, /* @ts-ignore */
3308
+ ...(ngDevMode ? [{ debugName: "enSaisie" }] : /* istanbul ignore next */ []));
3309
+ brut = signal('', /* @ts-ignore */
3310
+ ...(ngDevMode ? [{ debugName: "brut" }] : /* istanbul ignore next */ []));
3311
+ aideLue = computed(() => this.aide() ?? this.libelles().exempleDIban, /* @ts-ignore */
3312
+ ...(ngDevMode ? [{ debugName: "aideLue" }] : /* istanbul ignore next */ []));
3313
+ /**
3314
+ * Brut pendant la saisie ; groupe par quatre au repos. Une valeur changee de
3315
+ * l'exterieur pendant la saisie — remise a zero du formulaire — l'emporte sur
3316
+ * le brut, qui ne la represente plus.
3317
+ */
3318
+ affichage = computed(() => {
3319
+ const valeur = this.value();
3320
+ const brut = this.brut();
3321
+ return this.enSaisie() && normaliserIban(brut) === valeur ? brut : formaterIban(valeur);
3322
+ }, /* @ts-ignore */
3323
+ ...(ngDevMode ? [{ debugName: "affichage" }] : /* istanbul ignore next */ []));
3324
+ auFocus() {
3325
+ this.brut.set(formaterIban(this.value()));
3326
+ this.enSaisie.set(true);
3327
+ }
3328
+ surSaisie(evenement) {
3329
+ const saisie = this.texteSaisi(evenement);
3330
+ this.brut.set(saisie);
3331
+ this.value.set(normaliserIban(saisie));
3332
+ }
3333
+ aLaSortie() {
3334
+ this.enSaisie.set(false);
3335
+ this.touch.emit();
3336
+ }
3337
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StIbanField, deps: null, target: i0.ɵɵFactoryTarget.Component });
3338
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.6", type: StIbanField, isStandalone: true, selector: "st-iban-field", host: { classAttribute: "st-iban-field" }, usesInheritance: true, ngImport: i0, template: "<st-form-field\n [libelle]=\"libelle()\"\n [aide]=\"aideLue()\"\n [erreurs]=\"errors()\"\n [afficherErreurs]=\"touched()\"\n [obligatoire]=\"required()\"\n>\n <input\n #champ\n class=\"st-iban-field__champ\"\n stControleDeChamp\n type=\"text\"\n autocomplete=\"off\"\n autocapitalize=\"characters\"\n autocorrect=\"off\"\n spellcheck=\"false\"\n [value]=\"affichage()\"\n [attr.name]=\"name() || null\"\n [disabled]=\"disabled()\"\n [readOnly]=\"readonly()\"\n (focus)=\"auFocus()\"\n (input)=\"surSaisie($event)\"\n (blur)=\"aLaSortie()\"\n />\n</st-form-field>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block}.st-iban-field__champ:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-iban-field__champ{box-sizing:border-box;inline-size:100%;min-block-size:var(--st-cible-tactile-min);padding:var(--st-espacement-2) var(--st-espacement-3);font:inherit;color:var(--st-couleur-texte);background:var(--st-couleur-surface);border:1px solid var(--st-couleur-bordure-forte);border-radius:var(--st-rayon-sm)}.st-iban-field__champ[aria-invalid=true]{border-color:var(--st-couleur-danger);box-shadow:inset 0 0 0 1px var(--st-couleur-danger)}.st-iban-field__champ:disabled{color:var(--st-couleur-texte-desactive);cursor:not-allowed;background:var(--st-couleur-surface-enfoncee)}.st-iban-field__champ:read-only:not(:disabled){background:var(--st-couleur-surface-enfoncee)}.st-iban-field__champ{font-family:var(--st-police-mono);font-variant-numeric:tabular-nums}\n"], dependencies: [{ kind: "component", type: StFormField, selector: "st-form-field", inputs: ["libelle", "aide", "complement", "erreurs", "afficherErreurs", "obligatoire", "disposition", "libelleMasque"] }, { kind: "directive", type: StControleDeChamp, selector: "[stControleDeChamp]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3339
+ }
3340
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StIbanField, decorators: [{
3341
+ type: Component,
3342
+ args: [{ selector: 'st-iban-field', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StFormField, StControleDeChamp], host: { class: 'st-iban-field' }, template: "<st-form-field\n [libelle]=\"libelle()\"\n [aide]=\"aideLue()\"\n [erreurs]=\"errors()\"\n [afficherErreurs]=\"touched()\"\n [obligatoire]=\"required()\"\n>\n <input\n #champ\n class=\"st-iban-field__champ\"\n stControleDeChamp\n type=\"text\"\n autocomplete=\"off\"\n autocapitalize=\"characters\"\n autocorrect=\"off\"\n spellcheck=\"false\"\n [value]=\"affichage()\"\n [attr.name]=\"name() || null\"\n [disabled]=\"disabled()\"\n [readOnly]=\"readonly()\"\n (focus)=\"auFocus()\"\n (input)=\"surSaisie($event)\"\n (blur)=\"aLaSortie()\"\n />\n</st-form-field>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block}.st-iban-field__champ:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-iban-field__champ{box-sizing:border-box;inline-size:100%;min-block-size:var(--st-cible-tactile-min);padding:var(--st-espacement-2) var(--st-espacement-3);font:inherit;color:var(--st-couleur-texte);background:var(--st-couleur-surface);border:1px solid var(--st-couleur-bordure-forte);border-radius:var(--st-rayon-sm)}.st-iban-field__champ[aria-invalid=true]{border-color:var(--st-couleur-danger);box-shadow:inset 0 0 0 1px var(--st-couleur-danger)}.st-iban-field__champ:disabled{color:var(--st-couleur-texte-desactive);cursor:not-allowed;background:var(--st-couleur-surface-enfoncee)}.st-iban-field__champ:read-only:not(:disabled){background:var(--st-couleur-surface-enfoncee)}.st-iban-field__champ{font-family:var(--st-police-mono);font-variant-numeric:tabular-nums}\n"] }]
3343
+ }] });
3344
+
3345
+ /**
3346
+ * Numero de telephone. La valeur du modele ne garde que les chiffres et le `+` de
3347
+ * tete ; la saisie s'affiche telle qu'elle a ete tapee.
3348
+ *
3349
+ * ```html
3350
+ * <st-phone-field libelle="Telephone portable" [formField]="contact.telephone" />
3351
+ * <!-- schema : validate(chemin.telephone, ({ value }) => erreurTelephone(value())) -->
3352
+ * ```
3353
+ *
3354
+ * ⚠️ **Aucun formatage automatique.** Le groupement des chiffres depend du pays,
3355
+ * et reformater pendant la frappe renvoie le curseur en fin de ligne. La saisie
3356
+ * reste celle de la personne, espaces et points compris.
3357
+ *
3358
+ * ⚠️ **Pas de selecteur de pays, pas de verification par pays.** Il faudrait une
3359
+ * table des plans de numerotation, lourde et souvent perimee : c'est au serveur
3360
+ * de dire si le numero existe (SEC-5). `erreurTelephone` ne verifie que la forme.
3361
+ *
3362
+ * `type="tel"`, et jamais `type="number"` : un numero n'est pas une quantite, et le
3363
+ * champ numerique retire le zero de tete et le `+`.
3364
+ */
3365
+ class StPhoneField extends ControleDeSaisie {
3366
+ autocomplete = input('tel', /* @ts-ignore */
3367
+ ...(ngDevMode ? [{ debugName: "autocomplete" }] : /* istanbul ignore next */ []));
3368
+ brut = signal(null, /* @ts-ignore */
3369
+ ...(ngDevMode ? [{ debugName: "brut" }] : /* istanbul ignore next */ []));
3370
+ /**
3371
+ * La saisie telle que tapee, tant qu'elle represente encore la valeur ; une
3372
+ * valeur changee de l'exterieur — remise a zero, pre-remplissage — l'emporte.
3373
+ */
3374
+ affichage = computed(() => {
3375
+ const valeur = this.value();
3376
+ const brut = this.brut();
3377
+ return brut !== null && normaliserTelephone(brut) === valeur ? brut : valeur;
3378
+ }, /* @ts-ignore */
3379
+ ...(ngDevMode ? [{ debugName: "affichage" }] : /* istanbul ignore next */ []));
3380
+ surSaisie(evenement) {
3381
+ const saisie = this.texteSaisi(evenement);
3382
+ this.brut.set(saisie);
3383
+ this.value.set(normaliserTelephone(saisie));
3384
+ }
3385
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StPhoneField, deps: null, target: i0.ɵɵFactoryTarget.Component });
3386
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StPhoneField, isStandalone: true, selector: "st-phone-field", inputs: { autocomplete: { classPropertyName: "autocomplete", publicName: "autocomplete", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "st-phone-field" }, usesInheritance: true, ngImport: i0, template: "<st-form-field\n [libelle]=\"libelle()\"\n [aide]=\"aide()\"\n [erreurs]=\"errors()\"\n [afficherErreurs]=\"touched()\"\n [obligatoire]=\"required()\"\n>\n <input\n #champ\n class=\"st-phone-field__champ\"\n stControleDeChamp\n type=\"tel\"\n [attr.autocomplete]=\"autocomplete()\"\n [value]=\"affichage()\"\n [attr.name]=\"name() || null\"\n [disabled]=\"disabled()\"\n [readOnly]=\"readonly()\"\n (input)=\"surSaisie($event)\"\n (blur)=\"touch.emit()\"\n />\n</st-form-field>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block}.st-phone-field__champ:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-phone-field__champ{box-sizing:border-box;inline-size:100%;min-block-size:var(--st-cible-tactile-min);padding:var(--st-espacement-2) var(--st-espacement-3);font:inherit;color:var(--st-couleur-texte);background:var(--st-couleur-surface);border:1px solid var(--st-couleur-bordure-forte);border-radius:var(--st-rayon-sm)}.st-phone-field__champ[aria-invalid=true]{border-color:var(--st-couleur-danger);box-shadow:inset 0 0 0 1px var(--st-couleur-danger)}.st-phone-field__champ:disabled{color:var(--st-couleur-texte-desactive);cursor:not-allowed;background:var(--st-couleur-surface-enfoncee)}.st-phone-field__champ:read-only:not(:disabled){background:var(--st-couleur-surface-enfoncee)}.st-phone-field__champ{font-variant-numeric:tabular-nums}\n"], dependencies: [{ kind: "component", type: StFormField, selector: "st-form-field", inputs: ["libelle", "aide", "complement", "erreurs", "afficherErreurs", "obligatoire", "disposition", "libelleMasque"] }, { kind: "directive", type: StControleDeChamp, selector: "[stControleDeChamp]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3387
+ }
3388
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StPhoneField, decorators: [{
3389
+ type: Component,
3390
+ args: [{ selector: 'st-phone-field', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StFormField, StControleDeChamp], host: { class: 'st-phone-field' }, template: "<st-form-field\n [libelle]=\"libelle()\"\n [aide]=\"aide()\"\n [erreurs]=\"errors()\"\n [afficherErreurs]=\"touched()\"\n [obligatoire]=\"required()\"\n>\n <input\n #champ\n class=\"st-phone-field__champ\"\n stControleDeChamp\n type=\"tel\"\n [attr.autocomplete]=\"autocomplete()\"\n [value]=\"affichage()\"\n [attr.name]=\"name() || null\"\n [disabled]=\"disabled()\"\n [readOnly]=\"readonly()\"\n (input)=\"surSaisie($event)\"\n (blur)=\"touch.emit()\"\n />\n</st-form-field>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block}.st-phone-field__champ:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-phone-field__champ{box-sizing:border-box;inline-size:100%;min-block-size:var(--st-cible-tactile-min);padding:var(--st-espacement-2) var(--st-espacement-3);font:inherit;color:var(--st-couleur-texte);background:var(--st-couleur-surface);border:1px solid var(--st-couleur-bordure-forte);border-radius:var(--st-rayon-sm)}.st-phone-field__champ[aria-invalid=true]{border-color:var(--st-couleur-danger);box-shadow:inset 0 0 0 1px var(--st-couleur-danger)}.st-phone-field__champ:disabled{color:var(--st-couleur-texte-desactive);cursor:not-allowed;background:var(--st-couleur-surface-enfoncee)}.st-phone-field__champ:read-only:not(:disabled){background:var(--st-couleur-surface-enfoncee)}.st-phone-field__champ{font-variant-numeric:tabular-nums}\n"] }]
3391
+ }], propDecorators: { autocomplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocomplete", required: false }] }] } });
3392
+
3393
+ /** Sans accents ni casse : « eleve » trouve « Élève ». */
3394
+ function normaliserPourRecherche(texte) {
3395
+ return texte
3396
+ .normalize('NFD')
3397
+ .replace(/[\u0300-\u036f]/g, '')
3398
+ .toLocaleLowerCase()
3399
+ .trim();
3400
+ }
3401
+ /** Options dont le libelle CONTIENT le texte cherche, sans accents ni casse. */
3402
+ function filtrerOptions(options, recherche) {
3403
+ const cherche = normaliserPourRecherche(recherche);
3404
+ if (cherche === '')
3405
+ return options;
3406
+ return options.filter((option) => normaliserPourRecherche(option.libelle).includes(cherche));
3407
+ }
3408
+
3409
+ /**
3410
+ * Liste deroulante, sur un `select` NATIF.
3411
+ *
3412
+ * ```html
3413
+ * <st-select libelle="Pays" [options]="pays" autocomplete="country" [formField]="adresse.pays" />
3414
+ * ```
3415
+ *
3416
+ * ⚠️ **Natif, et non une liste ARIA** (FE-4). Le `select` natif ouvre le selecteur
3417
+ * du systeme sur mobile, se remplit automatiquement, se parcourt a la lettre, et
3418
+ * se lit partout. Une liste recomposee en ARIA ne fait jamais mieux sur ces
3419
+ * points ; elle ne se justifie que pour filtrer une longue liste — c'est
3420
+ * `st-combobox` — ou choisir plusieurs valeurs — `st-multiselect`.
3421
+ *
3422
+ * La premiere option, vide, dit « Choisir… » : sans elle, la premiere vraie
3423
+ * option paraitrait choisie alors que personne ne l'a fait. Le modele vaut
3424
+ * alors `''`, que `required` refuse.
3425
+ *
3426
+ * `readonly` n'existe pas sur un `select` : le champ annonce `aria-readonly` et
3427
+ * ignore le changement, plutot que d'etre desactive — un champ desactive sort de
3428
+ * l'ordre de tabulation, et sa valeur ne se lit plus.
3429
+ */
3430
+ class StSelect extends ControleDeSaisie {
3431
+ libelles = inject(ST_LIBELLES);
3432
+ options = input.required(/* @ts-ignore */
3433
+ ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
3434
+ /** Texte de l'option vide. Par defaut : « Choisir… ». */
3435
+ texteVide = input(null, /* @ts-ignore */
3436
+ ...(ngDevMode ? [{ debugName: "texteVide" }] : /* istanbul ignore next */ []));
3437
+ /** WCAG 1.3.5 : `country`, `sex`, `honorific-prefix`… */
3438
+ autocomplete = input(null, /* @ts-ignore */
3439
+ ...(ngDevMode ? [{ debugName: "autocomplete" }] : /* istanbul ignore next */ []));
3440
+ /** Options consecutives d'un meme groupe, dans l'ordre fourni. */
3441
+ blocs = computed(() => {
3442
+ const blocs = [];
3443
+ for (const option of this.options()) {
3444
+ const groupe = option.groupe ?? null;
3445
+ const dernier = blocs.at(-1);
3446
+ if (dernier?.groupe === groupe)
3447
+ dernier.options.push(option);
3448
+ else
3449
+ blocs.push({ groupe, options: [option] });
3450
+ }
3451
+ return blocs;
3452
+ }, /* @ts-ignore */
3453
+ ...(ngDevMode ? [{ debugName: "blocs" }] : /* istanbul ignore next */ []));
3454
+ surChoix(evenement) {
3455
+ const element = evenement.target;
3456
+ if (this.readonly()) {
3457
+ element.value = this.value();
3458
+ return;
3459
+ }
3460
+ this.value.set(element.value);
3461
+ }
3462
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StSelect, deps: null, target: i0.ɵɵFactoryTarget.Component });
3463
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StSelect, isStandalone: true, selector: "st-select", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, texteVide: { classPropertyName: "texteVide", publicName: "texteVide", isSignal: true, isRequired: false, transformFunction: null }, autocomplete: { classPropertyName: "autocomplete", publicName: "autocomplete", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "st-select" }, usesInheritance: true, ngImport: i0, template: "<st-form-field\n [libelle]=\"libelle()\"\n [aide]=\"aide()\"\n [erreurs]=\"errors()\"\n [afficherErreurs]=\"touched()\"\n [obligatoire]=\"required()\"\n>\n <div class=\"st-select__cadre\">\n <select\n #champ\n class=\"st-select__champ\"\n stControleDeChamp\n [attr.name]=\"name() || null\"\n [attr.autocomplete]=\"autocomplete()\"\n [attr.aria-readonly]=\"readonly() ? 'true' : null\"\n [disabled]=\"disabled()\"\n (change)=\"surChoix($event)\"\n (blur)=\"touch.emit()\"\n >\n <option value=\"\" [selected]=\"value() === ''\">{{ texteVide() ?? libelles().choisir }}</option>\n @for (bloc of blocs(); track $index) {\n @if (bloc.groupe === null) {\n @for (option of bloc.options; track option.valeur) {\n <option\n [value]=\"option.valeur\"\n [selected]=\"option.valeur === value()\"\n [disabled]=\"option.desactivee === true\"\n >\n {{ option.libelle }}\n </option>\n }\n } @else {\n <optgroup [label]=\"bloc.groupe\">\n @for (option of bloc.options; track option.valeur) {\n <option\n [value]=\"option.valeur\"\n [selected]=\"option.valeur === value()\"\n [disabled]=\"option.desactivee === true\"\n >\n {{ option.libelle }}\n </option>\n }\n </optgroup>\n }\n }\n </select>\n <st-icon class=\"st-select__chevron\" nom=\"chevron-bas\" taille=\"sm\" />\n </div>\n</st-form-field>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block}.st-select__cadre{position:relative}.st-select__champ:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-select__champ{box-sizing:border-box;inline-size:100%;min-block-size:var(--st-cible-tactile-min);padding:var(--st-espacement-2) var(--st-espacement-3);font:inherit;color:var(--st-couleur-texte);background:var(--st-couleur-surface);border:1px solid var(--st-couleur-bordure-forte);border-radius:var(--st-rayon-sm)}.st-select__champ[aria-invalid=true]{border-color:var(--st-couleur-danger);box-shadow:inset 0 0 0 1px var(--st-couleur-danger)}.st-select__champ:disabled{color:var(--st-couleur-texte-desactive);cursor:not-allowed;background:var(--st-couleur-surface-enfoncee)}.st-select__champ:read-only:not(:disabled){background:var(--st-couleur-surface-enfoncee)}.st-select__champ{padding-inline-end:calc(var(--st-espacement-3) * 2 + 1rem);cursor:pointer;appearance:none}.st-select__chevron{position:absolute;inset-block-start:50%;inset-inline-end:var(--st-espacement-3);color:var(--st-couleur-texte-discret);pointer-events:none;transform:translateY(-50%)}@media(forced-colors:active){.st-select__chevron{color:CanvasText}}\n"], dependencies: [{ kind: "component", type: StFormField, selector: "st-form-field", inputs: ["libelle", "aide", "complement", "erreurs", "afficherErreurs", "obligatoire", "disposition", "libelleMasque"] }, { kind: "directive", type: StControleDeChamp, selector: "[stControleDeChamp]" }, { kind: "component", type: StIcon, selector: "st-icon", inputs: ["nom", "taille", "ton", "etiquette"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3464
+ }
3465
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StSelect, decorators: [{
3466
+ type: Component,
3467
+ args: [{ selector: 'st-select', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StFormField, StControleDeChamp, StIcon], host: { class: 'st-select' }, template: "<st-form-field\n [libelle]=\"libelle()\"\n [aide]=\"aide()\"\n [erreurs]=\"errors()\"\n [afficherErreurs]=\"touched()\"\n [obligatoire]=\"required()\"\n>\n <div class=\"st-select__cadre\">\n <select\n #champ\n class=\"st-select__champ\"\n stControleDeChamp\n [attr.name]=\"name() || null\"\n [attr.autocomplete]=\"autocomplete()\"\n [attr.aria-readonly]=\"readonly() ? 'true' : null\"\n [disabled]=\"disabled()\"\n (change)=\"surChoix($event)\"\n (blur)=\"touch.emit()\"\n >\n <option value=\"\" [selected]=\"value() === ''\">{{ texteVide() ?? libelles().choisir }}</option>\n @for (bloc of blocs(); track $index) {\n @if (bloc.groupe === null) {\n @for (option of bloc.options; track option.valeur) {\n <option\n [value]=\"option.valeur\"\n [selected]=\"option.valeur === value()\"\n [disabled]=\"option.desactivee === true\"\n >\n {{ option.libelle }}\n </option>\n }\n } @else {\n <optgroup [label]=\"bloc.groupe\">\n @for (option of bloc.options; track option.valeur) {\n <option\n [value]=\"option.valeur\"\n [selected]=\"option.valeur === value()\"\n [disabled]=\"option.desactivee === true\"\n >\n {{ option.libelle }}\n </option>\n }\n </optgroup>\n }\n }\n </select>\n <st-icon class=\"st-select__chevron\" nom=\"chevron-bas\" taille=\"sm\" />\n </div>\n</st-form-field>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block}.st-select__cadre{position:relative}.st-select__champ:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-select__champ{box-sizing:border-box;inline-size:100%;min-block-size:var(--st-cible-tactile-min);padding:var(--st-espacement-2) var(--st-espacement-3);font:inherit;color:var(--st-couleur-texte);background:var(--st-couleur-surface);border:1px solid var(--st-couleur-bordure-forte);border-radius:var(--st-rayon-sm)}.st-select__champ[aria-invalid=true]{border-color:var(--st-couleur-danger);box-shadow:inset 0 0 0 1px var(--st-couleur-danger)}.st-select__champ:disabled{color:var(--st-couleur-texte-desactive);cursor:not-allowed;background:var(--st-couleur-surface-enfoncee)}.st-select__champ:read-only:not(:disabled){background:var(--st-couleur-surface-enfoncee)}.st-select__champ{padding-inline-end:calc(var(--st-espacement-3) * 2 + 1rem);cursor:pointer;appearance:none}.st-select__chevron{position:absolute;inset-block-start:50%;inset-inline-end:var(--st-espacement-3);color:var(--st-couleur-texte-discret);pointer-events:none;transform:translateY(-50%)}@media(forced-colors:active){.st-select__chevron{color:CanvasText}}\n"] }]
3468
+ }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], texteVide: [{ type: i0.Input, args: [{ isSignal: true, alias: "texteVide", required: false }] }], autocomplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocomplete", required: false }] }] } });
3469
+
3470
+ let compteur$2 = 0;
3471
+ /** Un lundi connu, pour nommer les jours de la semaine sans horloge. */
3472
+ const LUNDI_DE_REFERENCE = '2006-01-02';
3473
+ /** « Aujourd'hui » dans un fuseau : la date du poste n'est pas celle de la personne. */
3474
+ function dateDuJour(fuseau) {
3475
+ const parties = new Intl.DateTimeFormat('en-CA', {
3476
+ timeZone: fuseau,
3477
+ year: 'numeric',
3478
+ month: '2-digit',
3479
+ day: '2-digit',
3480
+ }).formatToParts(new Date());
3481
+ const partie = (type) => parties.find((p) => p.type === type)?.value ?? '';
3482
+ return `${partie('year')}-${partie('month')}-${partie('day')}`;
3483
+ }
3484
+ /**
3485
+ * Calendrier d'un mois, pour choisir une date.
3486
+ *
3487
+ * ```html
3488
+ * <st-calendar [selection]="depart()" dateMin="2026-09-17" (choix)="depart.set($event)" />
3489
+ * ```
3490
+ *
3491
+ * ⚠️ **Une aide, jamais la seule voie.** Dans `st-date-field`, le calendrier
3492
+ * complete un champ texte : une date de naissance se tape plus vite qu'elle ne se
3493
+ * cherche mois par mois, et un calendrier reste penible au lecteur d'ecran.
3494
+ *
3495
+ * ⚠️ **Le clavier navigue de DATE en date, pas de cellule en cellule** (decision
3496
+ * D7 de l'audit de la vague 3). Fleche droite le 30 septembre mene au 1er
3497
+ * octobre ; Page suivante change de mois, Maj + Page d'annee ; Debut et Fin vont
3498
+ * aux bords de la semaine de la LOCALE. La grille d'Angular Aria deplace un focus
3499
+ * entre cellules affichees : il aurait fallu la contourner sur chaque touche qui
3500
+ * compte, et elle aurait fait entrer le CDK dans les formulaires.
3501
+ *
3502
+ * Semaine commencant au jour de la locale, noms de jours et de mois dans la
3503
+ * langue courante, « aujourd'hui » dans le fuseau de la personne
3504
+ * (`FUSEAU_PAR_DEFAUT`) et non celui du poste.
3505
+ */
3506
+ class StCalendar {
3507
+ libelles = inject(ST_LIBELLES);
3508
+ locale = inject(ST_LOCALE);
3509
+ element = inject(ElementRef);
3510
+ injecteur = inject(Injector);
3511
+ aujourdHui = dateDuJour(inject(FUSEAU_PAR_DEFAUT));
3512
+ selection = input(null, /* @ts-ignore */
3513
+ ...(ngDevMode ? [{ debugName: "selection" }] : /* istanbul ignore next */ []));
3514
+ dateMin = input(null, /* @ts-ignore */
3515
+ ...(ngDevMode ? [{ debugName: "dateMin" }] : /* istanbul ignore next */ []));
3516
+ dateMax = input(null, /* @ts-ignore */
3517
+ ...(ngDevMode ? [{ debugName: "dateMax" }] : /* istanbul ignore next */ []));
3518
+ /** Periode a faire ressortir, pour un choix de plage. */
3519
+ plage = input(null, /* @ts-ignore */
3520
+ ...(ngDevMode ? [{ debugName: "plage" }] : /* istanbul ignore next */ []));
3521
+ choix = output();
3522
+ /** Echap : le conteneur decide de fermer, et ou rendre le focus. */
3523
+ fermeture = output();
3524
+ identifiants = (() => {
3525
+ const base = `st-calendrier-${(compteur$2 += 1).toString()}`;
3526
+ return { titre: `${base}-titre`, aide: `${base}-aide` };
3527
+ })();
3528
+ /** La date qui porte le focus. Suit la selection, bornee. */
3529
+ active = linkedSignal(() => bornerDate(this.selection() ?? this.aujourdHui, this.dateMin(), this.dateMax()), /* @ts-ignore */
3530
+ ...(ngDevMode ? [{ debugName: "active" }] : /* istanbul ignore next */ []));
3531
+ premierJour = computed(() => premierJourDeLaSemaine(this.locale()), /* @ts-ignore */
3532
+ ...(ngDevMode ? [{ debugName: "premierJour" }] : /* istanbul ignore next */ []));
3533
+ titre = computed(() => {
3534
+ const [annee, mois] = this.active().split('-').map(Number);
3535
+ return new Intl.DateTimeFormat(this.locale(), {
3536
+ month: 'long',
3537
+ year: 'numeric',
3538
+ timeZone: 'UTC',
3539
+ }).format(Date.UTC(annee ?? 2000, (mois ?? 1) - 1, 1));
3540
+ }, /* @ts-ignore */
3541
+ ...(ngDevMode ? [{ debugName: "titre" }] : /* istanbul ignore next */ []));
3542
+ joursDeLaSemaine = computed(() => {
3543
+ const locale = this.locale();
3544
+ const court = new Intl.DateTimeFormat(locale, { weekday: 'short', timeZone: 'UTC' });
3545
+ const long = new Intl.DateTimeFormat(locale, { weekday: 'long', timeZone: 'UTC' });
3546
+ return Array.from({ length: 7 }, (_, index) => {
3547
+ const date = ajouterJours(LUNDI_DE_REFERENCE, (this.premierJour() - 1 + index) % 7);
3548
+ const instant = Date.parse(`${date}T00:00:00Z`);
3549
+ return { court: court.format(instant), long: long.format(instant) };
3550
+ });
3551
+ }, /* @ts-ignore */
3552
+ ...(ngDevMode ? [{ debugName: "joursDeLaSemaine" }] : /* istanbul ignore next */ []));
3553
+ semaines = computed(() => {
3554
+ const active = this.active();
3555
+ const [annee, mois] = active.split('-').map(Number);
3556
+ const locale = this.locale();
3557
+ const lecture = new Intl.DateTimeFormat(locale, { dateStyle: 'full', timeZone: 'UTC' });
3558
+ const numero = new Intl.NumberFormat(locale);
3559
+ const selection = this.selection();
3560
+ const debut = this.plage()?.debut ?? null;
3561
+ const fin = this.plage()?.fin ?? null;
3562
+ const min = this.dateMin();
3563
+ const max = this.dateMax();
3564
+ const prefixe = active.slice(0, 7);
3565
+ return semainesDuMois(annee ?? 2000, mois ?? 1, this.premierJour()).map((semaine) => semaine.map((date) => ({
3566
+ date,
3567
+ horsDuMois: !date.startsWith(prefixe),
3568
+ numero: numero.format(Number(date.slice(8))),
3569
+ nom: lecture.format(Date.parse(`${date}T00:00:00Z`)),
3570
+ horsBornes: (min !== null && date < min) || (max !== null && date > max),
3571
+ choisi: date === selection || date === debut || date === fin,
3572
+ dansLaPlage: debut !== null && fin !== null && date > debut && date < fin,
3573
+ aujourdHui: date === this.aujourdHui,
3574
+ })));
3575
+ }, /* @ts-ignore */
3576
+ ...(ngDevMode ? [{ debugName: "semaines" }] : /* istanbul ignore next */ []));
3577
+ moisPrecedentPossible = computed(() => {
3578
+ const min = this.dateMin();
3579
+ return min === null || this.active().slice(0, 7) > min.slice(0, 7);
3580
+ }, /* @ts-ignore */
3581
+ ...(ngDevMode ? [{ debugName: "moisPrecedentPossible" }] : /* istanbul ignore next */ []));
3582
+ moisSuivantPossible = computed(() => {
3583
+ const max = this.dateMax();
3584
+ return max === null || this.active().slice(0, 7) < max.slice(0, 7);
3585
+ }, /* @ts-ignore */
3586
+ ...(ngDevMode ? [{ debugName: "moisSuivantPossible" }] : /* istanbul ignore next */ []));
3587
+ estActive(date) {
3588
+ return date === this.active();
3589
+ }
3590
+ /** Amene le focus sur la date active. */
3591
+ focus() {
3592
+ this.element.nativeElement
3593
+ .querySelector('button[data-date][tabindex="0"]')
3594
+ ?.focus();
3595
+ }
3596
+ changerDeMois(ecart) {
3597
+ this.active.set(bornerDate(ajouterMois(this.active(), ecart), this.dateMin(), this.dateMax()));
3598
+ }
3599
+ choisir(jour) {
3600
+ if (jour.horsBornes)
3601
+ return;
3602
+ this.active.set(jour.date);
3603
+ this.choix.emit(jour.date);
3604
+ }
3605
+ surTouche(evenement) {
3606
+ const active = this.active();
3607
+ const droiteAGauche = getComputedStyle(this.element.nativeElement).direction === 'rtl';
3608
+ const recul = (jourDeLaSemaine(active) - this.premierJour() + 7) % 7;
3609
+ const mois = evenement.shiftKey ? 12 : 1;
3610
+ const cibles = {
3611
+ ArrowRight: () => ajouterJours(active, droiteAGauche ? -1 : 1),
3612
+ ArrowLeft: () => ajouterJours(active, droiteAGauche ? 1 : -1),
3613
+ ArrowDown: () => ajouterJours(active, 7),
3614
+ ArrowUp: () => ajouterJours(active, -7),
3615
+ Home: () => ajouterJours(active, -recul),
3616
+ End: () => ajouterJours(active, 6 - recul),
3617
+ PageDown: () => ajouterMois(active, mois),
3618
+ PageUp: () => ajouterMois(active, -mois),
3619
+ };
3620
+ if (evenement.key === 'Escape') {
3621
+ evenement.preventDefault();
3622
+ this.fermeture.emit();
3623
+ return;
3624
+ }
3625
+ // Les fleches ne deplacent la date que depuis la grille : sur les boutons de
3626
+ // mois, elles gardent leur sens pour le navigateur et le lecteur d'ecran.
3627
+ const depuisLaGrille = evenement.target.hasAttribute('data-date');
3628
+ const cible = cibles[evenement.key];
3629
+ if (cible === undefined || !depuisLaGrille)
3630
+ return;
3631
+ evenement.preventDefault();
3632
+ this.active.set(bornerDate(cible(), this.dateMin(), this.dateMax()));
3633
+ afterNextRender(() => {
3634
+ this.focus();
3635
+ }, { injector: this.injecteur });
3636
+ }
3637
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StCalendar, deps: [], target: i0.ɵɵFactoryTarget.Component });
3638
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StCalendar, isStandalone: true, selector: "st-calendar", inputs: { selection: { classPropertyName: "selection", publicName: "selection", isSignal: true, isRequired: false, transformFunction: null }, dateMin: { classPropertyName: "dateMin", publicName: "dateMin", isSignal: true, isRequired: false, transformFunction: null }, dateMax: { classPropertyName: "dateMax", publicName: "dateMax", isSignal: true, isRequired: false, transformFunction: null }, plage: { classPropertyName: "plage", publicName: "plage", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { choix: "choix", fermeture: "fermeture" }, host: { listeners: { "keydown": "surTouche($event)" }, classAttribute: "st-calendar" }, ngImport: i0, template: "<div class=\"st-calendar__entete\">\n <!-- eslint-disable-next-line @angular-eslint/template/elements-content --\n Le contenu vient du gabarit de stIconButton, et l'etiquette est requise. -->\n <button\n stIconButton\n type=\"button\"\n icone=\"chevron-gauche\"\n [etiquette]=\"libelles().moisPrecedent\"\n [disabled]=\"!moisPrecedentPossible()\"\n (click)=\"changerDeMois(-1)\"\n ></button>\n <!-- Region vivante : changer de mois a la souris ne deplace pas le focus, et le\n nouveau mois doit se dire. -->\n <p class=\"st-calendar__titre\" aria-live=\"polite\" [id]=\"identifiants.titre\">{{ titre() }}</p>\n <!-- eslint-disable-next-line @angular-eslint/template/elements-content --\n Le contenu vient du gabarit de stIconButton, et l'etiquette est requise. -->\n <button\n stIconButton\n type=\"button\"\n icone=\"chevron-droite\"\n [etiquette]=\"libelles().moisSuivant\"\n [disabled]=\"!moisSuivantPossible()\"\n (click)=\"changerDeMois(1)\"\n ></button>\n</div>\n\n<table\n class=\"st-calendar__grille\"\n role=\"grid\"\n [attr.aria-labelledby]=\"identifiants.titre\"\n [attr.aria-describedby]=\"identifiants.aide\"\n>\n <thead>\n <tr>\n @for (jour of joursDeLaSemaine(); track $index) {\n <th class=\"st-calendar__jour-de-semaine\" scope=\"col\" [attr.abbr]=\"jour.long\">\n {{ jour.court }}\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (semaine of semaines(); track semaine[0]?.date) {\n <tr>\n @for (jour of semaine; track jour.date) {\n @if (jour.horsDuMois) {\n <td class=\"st-calendar__vide\"></td>\n } @else {\n <td [attr.aria-selected]=\"jour.choisi ? 'true' : null\">\n <button\n class=\"st-calendar__jour\"\n type=\"button\"\n [attr.data-date]=\"jour.date\"\n [attr.data-plage]=\"jour.dansLaPlage ? '' : null\"\n [attr.tabindex]=\"estActive(jour.date) ? 0 : -1\"\n [attr.aria-label]=\"jour.nom\"\n [attr.aria-current]=\"jour.aujourdHui ? 'date' : null\"\n [attr.aria-disabled]=\"jour.horsBornes ? 'true' : null\"\n (click)=\"choisir(jour)\"\n >\n {{ jour.numero }}\n </button>\n </td>\n }\n }\n </tr>\n }\n </tbody>\n</table>\n\n<p class=\"st-calendar__aide\" [id]=\"identifiants.aide\">{{ libelles().aideDuCalendrier }}</p>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:inline-block;padding:var(--st-espacement-3);color:var(--st-couleur-texte);background:var(--st-couleur-surface);border:1px solid var(--st-couleur-bordure-forte);border-radius:var(--st-rayon-md)}.st-calendar__entete{display:flex;gap:var(--st-espacement-2);align-items:center;justify-content:space-between;margin-block-end:var(--st-espacement-2)}.st-calendar__titre{margin:0;font-weight:var(--st-graisse-semi);text-transform:capitalize}.st-calendar__grille{border-collapse:collapse}.st-calendar__jour-de-semaine{padding-block-end:var(--st-espacement-1);font-size:var(--st-taille-sm);font-weight:var(--st-graisse-semi);color:var(--st-couleur-texte-discret);text-align:center}.st-calendar__jour:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-calendar__jour{inline-size:var(--st-cible-tactile-min);block-size:var(--st-cible-tactile-min);font:inherit;font-variant-numeric:tabular-nums;color:inherit;cursor:pointer;background:transparent;border:1px solid transparent;border-radius:var(--st-rayon-sm)}.st-calendar__jour:hover:not([aria-disabled=true]){background:var(--st-couleur-surface-enfoncee)}.st-calendar__jour[aria-current=date]{font-weight:var(--st-graisse-semi);border-color:var(--st-couleur-bordure-forte)}.st-calendar__jour[data-plage]{background:var(--st-couleur-surface-enfoncee)}.st-calendar__jour[aria-disabled=true]{color:var(--st-couleur-texte-desactive);text-decoration:line-through;cursor:not-allowed}[aria-selected=true]>.st-calendar__jour{font-weight:var(--st-graisse-semi);color:var(--st-couleur-sur-primaire);background:var(--st-couleur-primaire)}.st-calendar__aide{max-inline-size:20rem;margin:var(--st-espacement-2) 0 0;font-size:var(--st-taille-sm);color:var(--st-couleur-texte-discret)}@media(forced-colors:active){[aria-selected=true]>.st-calendar__jour{forced-color-adjust:none;color:HighlightText;background:Highlight}}\n"], dependencies: [{ kind: "component", type: StIconButton, selector: "button[stIconButton]", inputs: ["icone", "etiquette", "variante", "taille", "enfonce"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3639
+ }
3640
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StCalendar, decorators: [{
3641
+ type: Component,
3642
+ args: [{ selector: 'st-calendar', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StIconButton], host: {
3643
+ class: 'st-calendar',
3644
+ '(keydown)': 'surTouche($event)',
3645
+ }, template: "<div class=\"st-calendar__entete\">\n <!-- eslint-disable-next-line @angular-eslint/template/elements-content --\n Le contenu vient du gabarit de stIconButton, et l'etiquette est requise. -->\n <button\n stIconButton\n type=\"button\"\n icone=\"chevron-gauche\"\n [etiquette]=\"libelles().moisPrecedent\"\n [disabled]=\"!moisPrecedentPossible()\"\n (click)=\"changerDeMois(-1)\"\n ></button>\n <!-- Region vivante : changer de mois a la souris ne deplace pas le focus, et le\n nouveau mois doit se dire. -->\n <p class=\"st-calendar__titre\" aria-live=\"polite\" [id]=\"identifiants.titre\">{{ titre() }}</p>\n <!-- eslint-disable-next-line @angular-eslint/template/elements-content --\n Le contenu vient du gabarit de stIconButton, et l'etiquette est requise. -->\n <button\n stIconButton\n type=\"button\"\n icone=\"chevron-droite\"\n [etiquette]=\"libelles().moisSuivant\"\n [disabled]=\"!moisSuivantPossible()\"\n (click)=\"changerDeMois(1)\"\n ></button>\n</div>\n\n<table\n class=\"st-calendar__grille\"\n role=\"grid\"\n [attr.aria-labelledby]=\"identifiants.titre\"\n [attr.aria-describedby]=\"identifiants.aide\"\n>\n <thead>\n <tr>\n @for (jour of joursDeLaSemaine(); track $index) {\n <th class=\"st-calendar__jour-de-semaine\" scope=\"col\" [attr.abbr]=\"jour.long\">\n {{ jour.court }}\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (semaine of semaines(); track semaine[0]?.date) {\n <tr>\n @for (jour of semaine; track jour.date) {\n @if (jour.horsDuMois) {\n <td class=\"st-calendar__vide\"></td>\n } @else {\n <td [attr.aria-selected]=\"jour.choisi ? 'true' : null\">\n <button\n class=\"st-calendar__jour\"\n type=\"button\"\n [attr.data-date]=\"jour.date\"\n [attr.data-plage]=\"jour.dansLaPlage ? '' : null\"\n [attr.tabindex]=\"estActive(jour.date) ? 0 : -1\"\n [attr.aria-label]=\"jour.nom\"\n [attr.aria-current]=\"jour.aujourdHui ? 'date' : null\"\n [attr.aria-disabled]=\"jour.horsBornes ? 'true' : null\"\n (click)=\"choisir(jour)\"\n >\n {{ jour.numero }}\n </button>\n </td>\n }\n }\n </tr>\n }\n </tbody>\n</table>\n\n<p class=\"st-calendar__aide\" [id]=\"identifiants.aide\">{{ libelles().aideDuCalendrier }}</p>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:inline-block;padding:var(--st-espacement-3);color:var(--st-couleur-texte);background:var(--st-couleur-surface);border:1px solid var(--st-couleur-bordure-forte);border-radius:var(--st-rayon-md)}.st-calendar__entete{display:flex;gap:var(--st-espacement-2);align-items:center;justify-content:space-between;margin-block-end:var(--st-espacement-2)}.st-calendar__titre{margin:0;font-weight:var(--st-graisse-semi);text-transform:capitalize}.st-calendar__grille{border-collapse:collapse}.st-calendar__jour-de-semaine{padding-block-end:var(--st-espacement-1);font-size:var(--st-taille-sm);font-weight:var(--st-graisse-semi);color:var(--st-couleur-texte-discret);text-align:center}.st-calendar__jour:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-calendar__jour{inline-size:var(--st-cible-tactile-min);block-size:var(--st-cible-tactile-min);font:inherit;font-variant-numeric:tabular-nums;color:inherit;cursor:pointer;background:transparent;border:1px solid transparent;border-radius:var(--st-rayon-sm)}.st-calendar__jour:hover:not([aria-disabled=true]){background:var(--st-couleur-surface-enfoncee)}.st-calendar__jour[aria-current=date]{font-weight:var(--st-graisse-semi);border-color:var(--st-couleur-bordure-forte)}.st-calendar__jour[data-plage]{background:var(--st-couleur-surface-enfoncee)}.st-calendar__jour[aria-disabled=true]{color:var(--st-couleur-texte-desactive);text-decoration:line-through;cursor:not-allowed}[aria-selected=true]>.st-calendar__jour{font-weight:var(--st-graisse-semi);color:var(--st-couleur-sur-primaire);background:var(--st-couleur-primaire)}.st-calendar__aide{max-inline-size:20rem;margin:var(--st-espacement-2) 0 0;font-size:var(--st-taille-sm);color:var(--st-couleur-texte-discret)}@media(forced-colors:active){[aria-selected=true]>.st-calendar__jour{forced-color-adjust:none;color:HighlightText;background:Highlight}}\n"] }]
3646
+ }], propDecorators: { selection: [{ type: i0.Input, args: [{ isSignal: true, alias: "selection", required: false }] }], dateMin: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateMin", required: false }] }], dateMax: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateMax", required: false }] }], plage: [{ type: i0.Input, args: [{ isSignal: true, alias: "plage", required: false }] }], choix: [{ type: i0.Output, args: ["choix"] }], fermeture: [{ type: i0.Output, args: ["fermeture"] }] } });
3647
+
3648
+ /** Deux choix du meme fichier ne l'ajoutent pas deux fois. */
3649
+ function empreinte(fichier) {
3650
+ return `${fichier.name}|${fichier.size.toString()}|${fichier.lastModified.toString()}`;
3651
+ }
3652
+ /**
3653
+ * Choix de fichiers, sur un `input type="file"` natif.
3654
+ *
3655
+ * ```html
3656
+ * <st-file-upload libelle="Justificatifs" accept=".pdf, image/*" [tailleMax]="5_000_000" multiple
3657
+ * [formField]="dossier.pieces" />
3658
+ * <!-- schema : validate(chemin.pieces, ({ value }) => erreursDeFichiers(value(), regles)) -->
3659
+ * ```
3660
+ *
3661
+ * Le modele est la liste des `File` choisis. L'envoi appartient a l'application,
3662
+ * par `@starterlib/core` : le composant choisit, il ne televerse pas.
3663
+ *
3664
+ * ⚠️ **L'element natif reste la voie principale** (FE-4) : il ouvre le selecteur
3665
+ * du systeme, l'appareil photo sur mobile, et se commande au clavier. Il est
3666
+ * masque visuellement, pas retire : le bouton affiche est son etiquette. Le
3667
+ * depot par glisser est un complement a la souris, jamais la seule voie.
3668
+ *
3669
+ * ⚠️ **Aucun apercu d'image** (SEC-7). Un apercu passe par une adresse `blob:`
3670
+ * que la politique de securite du contenu doit autoriser, et un SVG affiche peut
3671
+ * porter du script. Le nom et la taille suffisent a reconnaitre un fichier.
3672
+ *
3673
+ * ⚠️ **`accept`, `tailleMax` et `nombreMax` sont un confort** (SEC-5) : ils
3674
+ * s'affichent en aide et filtrent le selecteur du systeme, mais la verification
3675
+ * est dans le schema — `erreursDeFichiers` —, et le serveur relit le contenu.
3676
+ *
3677
+ * Chaque changement de la liste s'annonce : « 2 fichiers choisis ». Un fichier
3678
+ * retire rend le focus au bouton de retrait suivant, ou au choix de fichiers : le
3679
+ * focus ne tombe jamais sur le document.
3680
+ */
3681
+ class StFileUpload extends ContratDeChamp {
3682
+ libelles = inject(ST_LIBELLES);
3683
+ locale = inject(ST_LOCALE);
3684
+ element = inject(ElementRef);
3685
+ injecteur = inject(Injector);
3686
+ value = model([], /* @ts-ignore */
3687
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
3688
+ /** Attribut `accept` natif : `.pdf, image/*`. */
3689
+ accept = input('', /* @ts-ignore */
3690
+ ...(ngDevMode ? [{ debugName: "accept" }] : /* istanbul ignore next */ []));
3691
+ multiple = input(false, { ...(ngDevMode ? { debugName: "multiple" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3692
+ /** En octets. Affiche en aide ; la verification est dans le schema. */
3693
+ tailleMax = input(null, /* @ts-ignore */
3694
+ ...(ngDevMode ? [{ debugName: "tailleMax" }] : /* istanbul ignore next */ []));
3695
+ annonce = new AnnonceLocale(inject(DestroyRef));
3696
+ survol = signal(false, /* @ts-ignore */
3697
+ ...(ngDevMode ? [{ debugName: "survol" }] : /* istanbul ignore next */ []));
3698
+ aideLue = computed(() => {
3699
+ const libelles = this.libelles();
3700
+ const textes = [this.aide()];
3701
+ if (this.accept().trim() !== '')
3702
+ textes.push(libelles.typesAcceptes(this.accept()));
3703
+ const taille = this.tailleMax();
3704
+ if (taille !== null)
3705
+ textes.push(libelles.tailleMaximale(formaterTaille(taille, this.locale())));
3706
+ const aide = textes.filter((texte) => texte !== null).join(' ');
3707
+ return aide === '' ? null : aide;
3708
+ }, /* @ts-ignore */
3709
+ ...(ngDevMode ? [{ debugName: "aideLue" }] : /* istanbul ignore next */ []));
3710
+ lignes = computed(() => {
3711
+ const locale = this.locale();
3712
+ return this.value().map((fichier) => ({
3713
+ fichier,
3714
+ cle: empreinte(fichier),
3715
+ taille: formaterTaille(fichier.size, locale),
3716
+ }));
3717
+ }, /* @ts-ignore */
3718
+ ...(ngDevMode ? [{ debugName: "lignes" }] : /* istanbul ignore next */ []));
3719
+ surChoix(evenement) {
3720
+ const element = evenement.target;
3721
+ this.ajouter(Array.from(element.files ?? []));
3722
+ // Vide, pour qu'un second choix du meme fichier declenche encore `change`.
3723
+ element.value = '';
3724
+ }
3725
+ surSurvol(evenement) {
3726
+ if (this.disabled() || this.readonly())
3727
+ return;
3728
+ evenement.preventDefault();
3729
+ this.survol.set(true);
3730
+ }
3731
+ surDepot(evenement) {
3732
+ evenement.preventDefault();
3733
+ this.survol.set(false);
3734
+ if (this.disabled() || this.readonly())
3735
+ return;
3736
+ this.ajouter(Array.from(evenement.dataTransfer?.files ?? []));
3737
+ }
3738
+ retirer(indice) {
3739
+ const restants = this.value().filter((_, position) => position !== indice);
3740
+ this.value.set(restants);
3741
+ this.annonce.annoncer(this.libelles().nombreDeFichiers(restants.length));
3742
+ afterNextRender(() => {
3743
+ const boutons = this.element.nativeElement.querySelectorAll('.st-file-upload__retrait');
3744
+ const suivant = boutons[Math.min(indice, boutons.length - 1)];
3745
+ if (suivant !== undefined)
3746
+ suivant.focus();
3747
+ else
3748
+ this.focus();
3749
+ }, { injector: this.injecteur });
3750
+ }
3751
+ aLaSortie(evenement) {
3752
+ const suivant = evenement.relatedTarget;
3753
+ if (suivant !== null && this.element.nativeElement.contains(suivant))
3754
+ return;
3755
+ this.touch.emit();
3756
+ }
3757
+ ajouter(fichiers) {
3758
+ if (fichiers.length === 0 || this.disabled() || this.readonly())
3759
+ return;
3760
+ let liste;
3761
+ if (this.multiple()) {
3762
+ const connus = new Set(this.value().map(empreinte));
3763
+ liste = [...this.value(), ...fichiers.filter((fichier) => !connus.has(empreinte(fichier)))];
3764
+ }
3765
+ else {
3766
+ liste = fichiers.slice(0, 1);
3767
+ }
3768
+ this.value.set(liste);
3769
+ // Le choix est complet : ses erreurs — taille, type — se montrent tout de suite.
3770
+ this.touch.emit();
3771
+ this.annonce.annoncer(this.libelles().nombreDeFichiers(liste.length));
3772
+ }
3773
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StFileUpload, deps: null, target: i0.ɵɵFactoryTarget.Component });
3774
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StFileUpload, isStandalone: true, selector: "st-file-upload", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, tailleMax: { classPropertyName: "tailleMax", publicName: "tailleMax", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { listeners: { "focusout": "aLaSortie($event)" }, classAttribute: "st-file-upload" }, usesInheritance: true, ngImport: i0, template: "<st-form-field\n [libelle]=\"libelle()\"\n [aide]=\"aideLue()\"\n [erreurs]=\"errors()\"\n [afficherErreurs]=\"touched()\"\n [obligatoire]=\"required()\"\n>\n <div\n class=\"st-file-upload__zone\"\n [attr.data-survol]=\"survol() ? '' : null\"\n [attr.data-desactive]=\"disabled() ? '' : null\"\n (dragover)=\"surSurvol($event)\"\n (dragleave)=\"survol.set(false)\"\n (drop)=\"surDepot($event)\"\n >\n <input\n #champ\n class=\"st-file-upload__natif\"\n stControleDeChamp\n type=\"file\"\n [accept]=\"accept()\"\n [multiple]=\"multiple()\"\n [attr.name]=\"name() || null\"\n [disabled]=\"disabled() || readonly()\"\n (change)=\"surChoix($event)\"\n />\n <!-- Voie de la souris vers le champ natif. Masque au lecteur d'ecran et hors\n tabulation : le clavier et le lecteur d'ecran passent par le champ natif,\n deja nomme par l'etiquette du champ. -->\n <span class=\"st-file-upload__bouton\" aria-hidden=\"true\" (click)=\"champ.click()\">\n <st-icon nom=\"televerser\" taille=\"sm\" />\n {{ multiple() ? libelles().choisirDesFichiers : libelles().choisirUnFichier }}\n </span>\n @if (multiple()) {\n <span class=\"st-file-upload__depot\" aria-hidden=\"true\">{{ libelles().ouDeposerIci }}</span>\n }\n </div>\n\n @if (lignes().length > 0) {\n <ul class=\"st-file-upload__liste\">\n @for (ligne of lignes(); track ligne.cle; let indice = $index) {\n <li class=\"st-file-upload__fichier\">\n <st-icon nom=\"fichier\" taille=\"sm\" />\n <span class=\"st-file-upload__nom\">{{ ligne.fichier.name }}</span>\n <span class=\"st-file-upload__taille\">{{ ligne.taille }}</span>\n <!-- eslint-disable-next-line @angular-eslint/template/elements-content --\n Le contenu vient du gabarit de stIconButton, et l'etiquette est requise. -->\n <button\n class=\"st-file-upload__retrait\"\n stIconButton\n type=\"button\"\n icone=\"corbeille\"\n taille=\"sm\"\n [etiquette]=\"libelles().retirerLeFichier(ligne.fichier.name)\"\n [disabled]=\"disabled() || readonly()\"\n (click)=\"retirer(indice)\"\n ></button>\n </li>\n }\n </ul>\n }\n</st-form-field>\n<span class=\"st-vh\" aria-live=\"polite\">{{ annonce.texte() }}</span>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block}.st-file-upload__zone{position:relative;display:flex;flex-wrap:wrap;gap:var(--st-espacement-2) var(--st-espacement-3);align-items:center;padding:var(--st-espacement-3);border:1px dashed var(--st-couleur-bordure-forte);border-radius:var(--st-rayon-md)}.st-file-upload__zone[data-survol]{background:var(--st-couleur-surface-enfoncee);border-style:solid}.st-file-upload__natif{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}.st-file-upload__bouton{display:inline-flex;gap:var(--st-espacement-2);align-items:center;min-block-size:var(--st-cible-tactile-min);padding:var(--st-espacement-2) var(--st-espacement-4);font-weight:var(--st-graisse-semi);color:var(--st-couleur-texte);cursor:pointer;background:var(--st-couleur-surface);border:1px solid var(--st-couleur-bordure-forte);border-radius:var(--st-rayon-sm)}.st-file-upload__natif:focus-visible+.st-file-upload__bouton{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}[aria-invalid=true]+.st-file-upload__bouton{border-color:var(--st-couleur-danger);box-shadow:inset 0 0 0 1px var(--st-couleur-danger)}.st-file-upload__natif:disabled+.st-file-upload__bouton{color:var(--st-couleur-texte-desactive);cursor:not-allowed;background:var(--st-couleur-surface-enfoncee)}.st-file-upload__depot{color:var(--st-couleur-texte-discret)}.st-file-upload__liste{display:grid;gap:var(--st-espacement-1);padding:0;margin:var(--st-espacement-2) 0 0;list-style:none}.st-file-upload__fichier{display:flex;gap:var(--st-espacement-2);align-items:center}.st-file-upload__nom{min-inline-size:0;overflow-wrap:anywhere}.st-file-upload__taille{flex:none;color:var(--st-couleur-texte-discret);font-variant-numeric:tabular-nums}\n"], dependencies: [{ kind: "component", type: StFormField, selector: "st-form-field", inputs: ["libelle", "aide", "complement", "erreurs", "afficherErreurs", "obligatoire", "disposition", "libelleMasque"] }, { kind: "directive", type: StControleDeChamp, selector: "[stControleDeChamp]" }, { kind: "component", type: StIcon, selector: "st-icon", inputs: ["nom", "taille", "ton", "etiquette"] }, { kind: "component", type: StIconButton, selector: "button[stIconButton]", inputs: ["icone", "etiquette", "variante", "taille", "enfonce"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3775
+ }
3776
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StFileUpload, decorators: [{
3777
+ type: Component,
3778
+ args: [{ selector: 'st-file-upload', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StFormField, StControleDeChamp, StIcon, StIconButton], host: {
3779
+ class: 'st-file-upload',
3780
+ '(focusout)': 'aLaSortie($event)',
3781
+ }, template: "<st-form-field\n [libelle]=\"libelle()\"\n [aide]=\"aideLue()\"\n [erreurs]=\"errors()\"\n [afficherErreurs]=\"touched()\"\n [obligatoire]=\"required()\"\n>\n <div\n class=\"st-file-upload__zone\"\n [attr.data-survol]=\"survol() ? '' : null\"\n [attr.data-desactive]=\"disabled() ? '' : null\"\n (dragover)=\"surSurvol($event)\"\n (dragleave)=\"survol.set(false)\"\n (drop)=\"surDepot($event)\"\n >\n <input\n #champ\n class=\"st-file-upload__natif\"\n stControleDeChamp\n type=\"file\"\n [accept]=\"accept()\"\n [multiple]=\"multiple()\"\n [attr.name]=\"name() || null\"\n [disabled]=\"disabled() || readonly()\"\n (change)=\"surChoix($event)\"\n />\n <!-- Voie de la souris vers le champ natif. Masque au lecteur d'ecran et hors\n tabulation : le clavier et le lecteur d'ecran passent par le champ natif,\n deja nomme par l'etiquette du champ. -->\n <span class=\"st-file-upload__bouton\" aria-hidden=\"true\" (click)=\"champ.click()\">\n <st-icon nom=\"televerser\" taille=\"sm\" />\n {{ multiple() ? libelles().choisirDesFichiers : libelles().choisirUnFichier }}\n </span>\n @if (multiple()) {\n <span class=\"st-file-upload__depot\" aria-hidden=\"true\">{{ libelles().ouDeposerIci }}</span>\n }\n </div>\n\n @if (lignes().length > 0) {\n <ul class=\"st-file-upload__liste\">\n @for (ligne of lignes(); track ligne.cle; let indice = $index) {\n <li class=\"st-file-upload__fichier\">\n <st-icon nom=\"fichier\" taille=\"sm\" />\n <span class=\"st-file-upload__nom\">{{ ligne.fichier.name }}</span>\n <span class=\"st-file-upload__taille\">{{ ligne.taille }}</span>\n <!-- eslint-disable-next-line @angular-eslint/template/elements-content --\n Le contenu vient du gabarit de stIconButton, et l'etiquette est requise. -->\n <button\n class=\"st-file-upload__retrait\"\n stIconButton\n type=\"button\"\n icone=\"corbeille\"\n taille=\"sm\"\n [etiquette]=\"libelles().retirerLeFichier(ligne.fichier.name)\"\n [disabled]=\"disabled() || readonly()\"\n (click)=\"retirer(indice)\"\n ></button>\n </li>\n }\n </ul>\n }\n</st-form-field>\n<span class=\"st-vh\" aria-live=\"polite\">{{ annonce.texte() }}</span>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block}.st-file-upload__zone{position:relative;display:flex;flex-wrap:wrap;gap:var(--st-espacement-2) var(--st-espacement-3);align-items:center;padding:var(--st-espacement-3);border:1px dashed var(--st-couleur-bordure-forte);border-radius:var(--st-rayon-md)}.st-file-upload__zone[data-survol]{background:var(--st-couleur-surface-enfoncee);border-style:solid}.st-file-upload__natif{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}.st-file-upload__bouton{display:inline-flex;gap:var(--st-espacement-2);align-items:center;min-block-size:var(--st-cible-tactile-min);padding:var(--st-espacement-2) var(--st-espacement-4);font-weight:var(--st-graisse-semi);color:var(--st-couleur-texte);cursor:pointer;background:var(--st-couleur-surface);border:1px solid var(--st-couleur-bordure-forte);border-radius:var(--st-rayon-sm)}.st-file-upload__natif:focus-visible+.st-file-upload__bouton{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}[aria-invalid=true]+.st-file-upload__bouton{border-color:var(--st-couleur-danger);box-shadow:inset 0 0 0 1px var(--st-couleur-danger)}.st-file-upload__natif:disabled+.st-file-upload__bouton{color:var(--st-couleur-texte-desactive);cursor:not-allowed;background:var(--st-couleur-surface-enfoncee)}.st-file-upload__depot{color:var(--st-couleur-texte-discret)}.st-file-upload__liste{display:grid;gap:var(--st-espacement-1);padding:0;margin:var(--st-espacement-2) 0 0;list-style:none}.st-file-upload__fichier{display:flex;gap:var(--st-espacement-2);align-items:center}.st-file-upload__nom{min-inline-size:0;overflow-wrap:anywhere}.st-file-upload__taille{flex:none;color:var(--st-couleur-texte-discret);font-variant-numeric:tabular-nums}\n"] }]
3782
+ }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], tailleMax: [{ type: i0.Input, args: [{ isSignal: true, alias: "tailleMax", required: false }] }] } });
3783
+
3784
+ let compteur$1 = 0;
3785
+ /**
3786
+ * Choix du theme : systeme, clair, sombre.
3787
+ *
3788
+ * ⚠️ **Trois etats, donc PAS un interrupteur.** `role="switch"` et
3789
+ * `aria-pressed` sont binaires : poses sur un choix a trois valeurs, ils
3790
+ * annoncent « active » ou « desactive » sans jamais dire lequel des trois est
3791
+ * retenu. Un groupe de boutons radio dit exactement « Sombre, bouton radio,
3792
+ * coche, 3 sur 3 ».
3793
+ *
3794
+ * ⚠️ **Composant de PRESENTATION.** Il n'injecte pas `StTheme` : `ui` ne depend
3795
+ * pas de `@starterlib/core` (ADR 0003). La coquille le relie au noyau :
3796
+ *
3797
+ * ```html
3798
+ * <st-theme-toggle [choix]="theme.choix()" (choisi)="theme.choisir($event)" />
3799
+ * ```
3800
+ */
3801
+ class StThemeToggle {
3802
+ libelles = inject(ST_LIBELLES);
3803
+ choix = input.required(/* @ts-ignore */
3804
+ ...(ngDevMode ? [{ debugName: "choix" }] : /* istanbul ignore next */ []));
3805
+ /** Legende visible. Masquee par defaut, mais toujours lue : elle nomme le groupe. */
3806
+ legendeVisible = input(false, { ...(ngDevMode ? { debugName: "legendeVisible" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3807
+ choisi = output();
3808
+ /** Unique par instance : deux bascules sur la meme page partageraient leur groupe radio. */
3809
+ nom = `st-theme-${(compteur$1 += 1).toString()}`;
3810
+ legende = computed(() => this.libelles().theme, /* @ts-ignore */
3811
+ ...(ngDevMode ? [{ debugName: "legende" }] : /* istanbul ignore next */ []));
3812
+ options = computed(() => {
3813
+ const libelles = this.libelles();
3814
+ const texte = {
3815
+ systeme: libelles.themeSysteme,
3816
+ clair: libelles.themeClair,
3817
+ sombre: libelles.themeSombre,
3818
+ };
3819
+ return CHOIX_DE_THEME.map((valeur) => ({ valeur, libelle: texte[valeur] }));
3820
+ }, /* @ts-ignore */
3821
+ ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
3822
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StThemeToggle, deps: [], target: i0.ɵɵFactoryTarget.Component });
3823
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StThemeToggle, isStandalone: true, selector: "st-theme-toggle", inputs: { choix: { classPropertyName: "choix", publicName: "choix", isSignal: true, isRequired: true, transformFunction: null }, legendeVisible: { classPropertyName: "legendeVisible", publicName: "legendeVisible", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { choisi: "choisi" }, host: { classAttribute: "st-theme-toggle" }, ngImport: i0, template: "<fieldset class=\"st-theme-toggle__groupe\">\n <legend [class.st-vh]=\"!legendeVisible()\">{{ legende() }}</legend>\n @for (option of options(); track option.valeur) {\n <label>\n <input\n type=\"radio\"\n [name]=\"nom\"\n [value]=\"option.valeur\"\n [checked]=\"option.valeur === choix()\"\n (change)=\"choisi.emit(option.valeur)\"\n />\n <span>{{ option.libelle }}</span>\n </label>\n }\n</fieldset>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:inline-block}.st-theme-toggle__groupe{display:inline-flex;flex-wrap:wrap;gap:0;padding:0;margin:0;border:0}.st-theme-toggle__groupe legend{padding:0;margin-block-end:var(--st-espacement-2);font-size:var(--st-taille-sm);font-weight:var(--st-graisse-semi)}.st-theme-toggle__groupe input{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}.st-theme-toggle__groupe label{display:inline-flex;align-items:center;min-block-size:var(--st-cible-tactile-min);padding:var(--st-espacement-1) var(--st-espacement-3);color:var(--st-couleur-texte);cursor:pointer;background:var(--st-couleur-surface);border:1px solid var(--st-couleur-bordure-forte)}.st-theme-toggle__groupe label+label{margin-inline-start:-1px}.st-theme-toggle__groupe label:first-of-type{border-start-start-radius:var(--st-rayon-md);border-end-start-radius:var(--st-rayon-md)}.st-theme-toggle__groupe label:last-of-type{border-start-end-radius:var(--st-rayon-md);border-end-end-radius:var(--st-rayon-md)}.st-theme-toggle__groupe label:has(input:checked){position:relative;font-weight:var(--st-graisse-semi);color:var(--st-couleur-sur-primaire);background:var(--st-couleur-primaire);border-color:var(--st-couleur-primaire)}.st-theme-toggle__groupe label:has(input:focus-visible){position:relative;z-index:1;outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}@media(forced-colors:active){.st-theme-toggle__groupe label:has(input:checked){forced-color-adjust:none;color:HighlightText;background:Highlight}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3824
+ }
3825
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StThemeToggle, decorators: [{
3826
+ type: Component,
3827
+ args: [{ selector: 'st-theme-toggle', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'st-theme-toggle' }, template: "<fieldset class=\"st-theme-toggle__groupe\">\n <legend [class.st-vh]=\"!legendeVisible()\">{{ legende() }}</legend>\n @for (option of options(); track option.valeur) {\n <label>\n <input\n type=\"radio\"\n [name]=\"nom\"\n [value]=\"option.valeur\"\n [checked]=\"option.valeur === choix()\"\n (change)=\"choisi.emit(option.valeur)\"\n />\n <span>{{ option.libelle }}</span>\n </label>\n }\n</fieldset>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:inline-block}.st-theme-toggle__groupe{display:inline-flex;flex-wrap:wrap;gap:0;padding:0;margin:0;border:0}.st-theme-toggle__groupe legend{padding:0;margin-block-end:var(--st-espacement-2);font-size:var(--st-taille-sm);font-weight:var(--st-graisse-semi)}.st-theme-toggle__groupe input{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}.st-theme-toggle__groupe label{display:inline-flex;align-items:center;min-block-size:var(--st-cible-tactile-min);padding:var(--st-espacement-1) var(--st-espacement-3);color:var(--st-couleur-texte);cursor:pointer;background:var(--st-couleur-surface);border:1px solid var(--st-couleur-bordure-forte)}.st-theme-toggle__groupe label+label{margin-inline-start:-1px}.st-theme-toggle__groupe label:first-of-type{border-start-start-radius:var(--st-rayon-md);border-end-start-radius:var(--st-rayon-md)}.st-theme-toggle__groupe label:last-of-type{border-start-end-radius:var(--st-rayon-md);border-end-end-radius:var(--st-rayon-md)}.st-theme-toggle__groupe label:has(input:checked){position:relative;font-weight:var(--st-graisse-semi);color:var(--st-couleur-sur-primaire);background:var(--st-couleur-primaire);border-color:var(--st-couleur-primaire)}.st-theme-toggle__groupe label:has(input:focus-visible){position:relative;z-index:1;outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}@media(forced-colors:active){.st-theme-toggle__groupe label:has(input:checked){forced-color-adjust:none;color:HighlightText;background:Highlight}}\n"] }]
3828
+ }], propDecorators: { choix: [{ type: i0.Input, args: [{ isSignal: true, alias: "choix", required: true }] }], legendeVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "legendeVisible", required: false }] }], choisi: [{ type: i0.Output, args: ["choisi"] }] } });
3829
+
3830
+ /**
3831
+ * Nom de chaque langue ECRIT DANS CETTE LANGUE, et jamais traduit.
3832
+ *
3833
+ * ⚠️ Une personne qui ne lit pas le francais ne cherche pas « Anglais » : elle
3834
+ * cherche « English ». Traduire le nom des langues dans la langue courante rend
3835
+ * le selecteur illisible precisement pour qui en a besoin.
3836
+ */
3837
+ const ENDONYMES = {
3838
+ fr: 'Français',
3839
+ en: 'English',
3840
+ };
3841
+ let compteur = 0;
3842
+ /**
3843
+ * Choix de la langue de l'interface.
3844
+ *
3845
+ * ⚠️ **Chaque option porte son propre `lang`.** Sans lui, un lecteur d'ecran
3846
+ * regle en francais lit « English » avec une voix francaise, et le mot devient
3847
+ * incomprehensible pour la personne anglophone qui cherchait justement a
3848
+ * l'entendre.
3849
+ *
3850
+ * ⚠️ **Composant de PRESENTATION.** Il n'injecte pas `StLangue` : `ui` ne depend
3851
+ * pas de `@starterlib/core` (ADR 0003). La coquille le relie au noyau :
3852
+ *
3853
+ * ```html
3854
+ * <st-lang-switch [courante]="langue.courante()" (choisie)="langue.changer($event)" />
3855
+ * ```
3856
+ */
3857
+ class StLangSwitch {
3858
+ libelles = inject(ST_LIBELLES);
3859
+ courante = input.required(/* @ts-ignore */
3860
+ ...(ngDevMode ? [{ debugName: "courante" }] : /* istanbul ignore next */ []));
3861
+ langues = input(LANGUES, /* @ts-ignore */
3862
+ ...(ngDevMode ? [{ debugName: "langues" }] : /* istanbul ignore next */ []));
3863
+ legendeVisible = input(false, { ...(ngDevMode ? { debugName: "legendeVisible" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3864
+ choisie = output();
3865
+ nom = `st-langue-${(compteur += 1).toString()}`;
3866
+ legende = computed(() => this.libelles().langue, /* @ts-ignore */
3867
+ ...(ngDevMode ? [{ debugName: "legende" }] : /* istanbul ignore next */ []));
3868
+ options = computed(() => this.langues().map((code) => ({ code, endonyme: ENDONYMES[code] })), /* @ts-ignore */
3869
+ ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
3870
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StLangSwitch, deps: [], target: i0.ɵɵFactoryTarget.Component });
3871
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StLangSwitch, isStandalone: true, selector: "st-lang-switch", inputs: { courante: { classPropertyName: "courante", publicName: "courante", isSignal: true, isRequired: true, transformFunction: null }, langues: { classPropertyName: "langues", publicName: "langues", isSignal: true, isRequired: false, transformFunction: null }, legendeVisible: { classPropertyName: "legendeVisible", publicName: "legendeVisible", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { choisie: "choisie" }, host: { classAttribute: "st-lang-switch" }, ngImport: i0, template: "<fieldset class=\"st-lang-switch__groupe\">\n <legend [class.st-vh]=\"!legendeVisible()\">{{ legende() }}</legend>\n @for (option of options(); track option.code) {\n <label>\n <input\n type=\"radio\"\n [name]=\"nom\"\n [value]=\"option.code\"\n [checked]=\"option.code === courante()\"\n (change)=\"choisie.emit(option.code)\"\n />\n <span [attr.lang]=\"option.code\">{{ option.endonyme }}</span>\n </label>\n }\n</fieldset>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:inline-block}.st-lang-switch__groupe{display:inline-flex;flex-wrap:wrap;gap:0;padding:0;margin:0;border:0}.st-lang-switch__groupe legend{padding:0;margin-block-end:var(--st-espacement-2);font-size:var(--st-taille-sm);font-weight:var(--st-graisse-semi)}.st-lang-switch__groupe input{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}.st-lang-switch__groupe label{display:inline-flex;align-items:center;min-block-size:var(--st-cible-tactile-min);padding:var(--st-espacement-1) var(--st-espacement-3);color:var(--st-couleur-texte);cursor:pointer;background:var(--st-couleur-surface);border:1px solid var(--st-couleur-bordure-forte)}.st-lang-switch__groupe label+label{margin-inline-start:-1px}.st-lang-switch__groupe label:first-of-type{border-start-start-radius:var(--st-rayon-md);border-end-start-radius:var(--st-rayon-md)}.st-lang-switch__groupe label:last-of-type{border-start-end-radius:var(--st-rayon-md);border-end-end-radius:var(--st-rayon-md)}.st-lang-switch__groupe label:has(input:checked){position:relative;font-weight:var(--st-graisse-semi);color:var(--st-couleur-sur-primaire);background:var(--st-couleur-primaire);border-color:var(--st-couleur-primaire)}.st-lang-switch__groupe label:has(input:focus-visible){position:relative;z-index:1;outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}@media(forced-colors:active){.st-lang-switch__groupe label:has(input:checked){forced-color-adjust:none;color:HighlightText;background:Highlight}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3872
+ }
3873
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StLangSwitch, decorators: [{
3874
+ type: Component,
3875
+ args: [{ selector: 'st-lang-switch', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'st-lang-switch' }, template: "<fieldset class=\"st-lang-switch__groupe\">\n <legend [class.st-vh]=\"!legendeVisible()\">{{ legende() }}</legend>\n @for (option of options(); track option.code) {\n <label>\n <input\n type=\"radio\"\n [name]=\"nom\"\n [value]=\"option.code\"\n [checked]=\"option.code === courante()\"\n (change)=\"choisie.emit(option.code)\"\n />\n <span [attr.lang]=\"option.code\">{{ option.endonyme }}</span>\n </label>\n }\n</fieldset>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:inline-block}.st-lang-switch__groupe{display:inline-flex;flex-wrap:wrap;gap:0;padding:0;margin:0;border:0}.st-lang-switch__groupe legend{padding:0;margin-block-end:var(--st-espacement-2);font-size:var(--st-taille-sm);font-weight:var(--st-graisse-semi)}.st-lang-switch__groupe input{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}.st-lang-switch__groupe label{display:inline-flex;align-items:center;min-block-size:var(--st-cible-tactile-min);padding:var(--st-espacement-1) var(--st-espacement-3);color:var(--st-couleur-texte);cursor:pointer;background:var(--st-couleur-surface);border:1px solid var(--st-couleur-bordure-forte)}.st-lang-switch__groupe label+label{margin-inline-start:-1px}.st-lang-switch__groupe label:first-of-type{border-start-start-radius:var(--st-rayon-md);border-end-start-radius:var(--st-rayon-md)}.st-lang-switch__groupe label:last-of-type{border-start-end-radius:var(--st-rayon-md);border-end-end-radius:var(--st-rayon-md)}.st-lang-switch__groupe label:has(input:checked){position:relative;font-weight:var(--st-graisse-semi);color:var(--st-couleur-sur-primaire);background:var(--st-couleur-primaire);border-color:var(--st-couleur-primaire)}.st-lang-switch__groupe label:has(input:focus-visible){position:relative;z-index:1;outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}@media(forced-colors:active){.st-lang-switch__groupe label:has(input:checked){forced-color-adjust:none;color:HighlightText;background:Highlight}}\n"] }]
3876
+ }], propDecorators: { courante: [{ type: i0.Input, args: [{ isSignal: true, alias: "courante", required: true }] }], langues: [{ type: i0.Input, args: [{ isSignal: true, alias: "langues", required: false }] }], legendeVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "legendeVisible", required: false }] }], choisie: [{ type: i0.Output, args: ["choisie"] }] } });
3877
+
3878
+ /**
3879
+ * Bouton qui copie une valeur : reference de virement, adresse de depot, lien
3880
+ * de partage.
3881
+ *
3882
+ * ⚠️ **Un element, et non un attribut pose sur un `<button>`.** La confirmation
3883
+ * passe par une region vivante voisine du bouton ; posee DANS le bouton, elle
3884
+ * entrerait dans son nom accessible, qui deviendrait « Copier Copie ».
3885
+ *
3886
+ * ⚠️ **Le libelle du bouton ne change pas** apres la copie, pour la raison que
3887
+ * donne `st-code` : le lecteur d'ecran annoncerait un autre controle que celui
3888
+ * qu'il a sous le doigt.
3889
+ *
3890
+ * ⚠️ **Jamais de secret.** Ce qui entre dans le presse-papiers est conserve par
3891
+ * les gestionnaires d'historique et synchronise entre appareils : ni mot de
3892
+ * passe, ni jeton, ni code a usage unique.
3893
+ *
3894
+ * Sans presse-papiers — hors contexte securise — le bouton n'est pas rendu : un
3895
+ * controle qui ne peut rien faire ne doit pas s'offrir.
3896
+ */
3897
+ class StCopyButton {
3898
+ document = inject(DOCUMENT);
3899
+ libelles = inject(ST_LIBELLES);
3900
+ valeur = input.required(/* @ts-ignore */
3901
+ ...(ngDevMode ? [{ debugName: "valeur" }] : /* istanbul ignore next */ []));
3902
+ /**
3903
+ * `null` : le texte vient du dictionnaire de l'application.
3904
+ *
3905
+ * ⚠️ En icone seule, c'est le nom accessible du bouton : il doit dire CE qui
3906
+ * est copie quand la page en offre plusieurs — « Copier l'IBAN » et non
3907
+ * « Copier » repete cinq fois.
3908
+ */
3909
+ libelle = input(null, /* @ts-ignore */
3910
+ ...(ngDevMode ? [{ debugName: "libelle" }] : /* istanbul ignore next */ []));
3911
+ iconeSeule = input(false, { ...(ngDevMode ? { debugName: "iconeSeule" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3912
+ messageDeConfirmation = input(null, /* @ts-ignore */
3913
+ ...(ngDevMode ? [{ debugName: "messageDeConfirmation" }] : /* istanbul ignore next */ []));
3914
+ copie = output();
3915
+ annonce = new AnnonceLocale(inject(DestroyRef));
3916
+ disponible = pressePapiersDisponible(this.document);
3917
+ libelleLu = computed(() => this.libelle() ?? this.libelles().copier, /* @ts-ignore */
3918
+ ...(ngDevMode ? [{ debugName: "libelleLu" }] : /* istanbul ignore next */ []));
3919
+ async copier() {
3920
+ const issue = await copierDansLePressePapiers(this.document, this.valeur());
3921
+ if (issue === 'copie') {
3922
+ this.copie.emit(this.valeur());
3923
+ this.annonce.annoncer(this.messageDeConfirmation() ?? this.libelles().copieEffectuee);
3924
+ }
3925
+ else if (issue === 'refusee') {
3926
+ this.annonce.annoncer(this.libelles().copieImpossible);
3927
+ }
3928
+ }
3929
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StCopyButton, deps: [], target: i0.ɵɵFactoryTarget.Component });
3930
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StCopyButton, isStandalone: true, selector: "st-copy-button", inputs: { valeur: { classPropertyName: "valeur", publicName: "valeur", isSignal: true, isRequired: true, transformFunction: null }, libelle: { classPropertyName: "libelle", publicName: "libelle", isSignal: true, isRequired: false, transformFunction: null }, iconeSeule: { classPropertyName: "iconeSeule", publicName: "iconeSeule", isSignal: true, isRequired: false, transformFunction: null }, messageDeConfirmation: { classPropertyName: "messageDeConfirmation", publicName: "messageDeConfirmation", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { copie: "copie" }, host: { classAttribute: "st-copy-button" }, ngImport: i0, template: "@if (disponible) {\n @if (iconeSeule()) {\n <!-- eslint-disable-next-line @angular-eslint/template/elements-content --\n Le contenu vient du gabarit de stIconButton. Le nom accessible est\n impose par le type (`etiquette` est requis) et verifie par axe. -->\n <button\n stIconButton\n type=\"button\"\n icone=\"copie\"\n taille=\"sm\"\n [etiquette]=\"libelleLu()\"\n (click)=\"copier()\"\n ></button>\n } @else {\n <button\n stButton\n type=\"button\"\n variante=\"secondaire\"\n taille=\"sm\"\n iconeAvant=\"copie\"\n (click)=\"copier()\"\n >\n {{ libelleLu() }}\n </button>\n }\n}\n<span class=\"st-vh\" aria-live=\"polite\">{{ annonce.texte() }}</span>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:inline-flex;align-items:center}\n"], dependencies: [{ kind: "component", type: StButton, selector: "button[stButton]", inputs: ["variante", "taille", "pleineLargeur", "iconeAvant", "iconeApres", "chargement", "indisponible"] }, { kind: "component", type: StIconButton, selector: "button[stIconButton]", inputs: ["icone", "etiquette", "variante", "taille", "enfonce"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3931
+ }
3932
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StCopyButton, decorators: [{
3933
+ type: Component,
3934
+ args: [{ selector: 'st-copy-button', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StButton, StIconButton], host: { class: 'st-copy-button' }, template: "@if (disponible) {\n @if (iconeSeule()) {\n <!-- eslint-disable-next-line @angular-eslint/template/elements-content --\n Le contenu vient du gabarit de stIconButton. Le nom accessible est\n impose par le type (`etiquette` est requis) et verifie par axe. -->\n <button\n stIconButton\n type=\"button\"\n icone=\"copie\"\n taille=\"sm\"\n [etiquette]=\"libelleLu()\"\n (click)=\"copier()\"\n ></button>\n } @else {\n <button\n stButton\n type=\"button\"\n variante=\"secondaire\"\n taille=\"sm\"\n iconeAvant=\"copie\"\n (click)=\"copier()\"\n >\n {{ libelleLu() }}\n </button>\n }\n}\n<span class=\"st-vh\" aria-live=\"polite\">{{ annonce.texte() }}</span>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:inline-flex;align-items:center}\n"] }]
3935
+ }], propDecorators: { valeur: [{ type: i0.Input, args: [{ isSignal: true, alias: "valeur", required: true }] }], libelle: [{ type: i0.Input, args: [{ isSignal: true, alias: "libelle", required: false }] }], iconeSeule: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconeSeule", required: false }] }], messageDeConfirmation: [{ type: i0.Input, args: [{ isSignal: true, alias: "messageDeConfirmation", required: false }] }], copie: [{ type: i0.Output, args: ["copie"] }] } });
3936
+
3937
+ /**
3938
+ * Compte a rebours avant un nouvel essai, pour une reponse `429` et son en-tete
3939
+ * `Retry-After`.
3940
+ *
3941
+ * ```html
3942
+ * @if (erreur.reessayerDans !== null) {
3943
+ * <st-timer [secondes]="erreur.reessayerDans" (termine)="reessayable.set(true)" />
3944
+ * }
3945
+ * ```
3946
+ *
3947
+ * ⚠️ **Il n'annonce PAS chaque seconde.** Une region vivante qui change toutes les
3948
+ * secondes recouvre tout ce que le lecteur d'ecran essaie de dire, et empeche de
3949
+ * lire le formulaire que la personne est justement en train de garder pret. Le
3950
+ * decompte porte `role="timer"`, dont la valeur implicite est
3951
+ * `aria-live="off"` : il se LIT quand on l'atteint. Seule la fin s'annonce.
3952
+ *
3953
+ * ⚠️ **Le temps restant se calcule contre l'horloge, pas en comptant les
3954
+ * battements.** Un onglet en arriere-plan voit ses minuteries ralenties a une par
3955
+ * minute : un compteur decremente a chaque battement afficherait encore
3956
+ * « 45 s » a son retour, bien apres que le serveur a leve la limite.
3957
+ */
3958
+ class StTimer {
3959
+ libelles = inject(ST_LIBELLES);
3960
+ locale = inject(ST_LOCALE);
3961
+ /** Duree d'attente en secondes, telle que `Retry-After` la donne. */
3962
+ secondes = input.required(/* @ts-ignore */
3963
+ ...(ngDevMode ? [{ debugName: "secondes" }] : /* istanbul ignore next */ []));
3964
+ termine = output();
3965
+ annonce = new AnnonceLocale(inject(DestroyRef));
3966
+ restant = signal(0, /* @ts-ignore */
3967
+ ...(ngDevMode ? [{ debugName: "restant" }] : /* istanbul ignore next */ []));
3968
+ echeance = 0;
3969
+ minuterie = null;
3970
+ texte = computed(() => {
3971
+ const restant = this.restant();
3972
+ const libelles = this.libelles();
3973
+ return restant > 0
3974
+ ? libelles.reessayerDans(formaterDuree(restant, this.locale()))
3975
+ : libelles.reessayerMaintenant;
3976
+ }, /* @ts-ignore */
3977
+ ...(ngDevMode ? [{ debugName: "texte" }] : /* istanbul ignore next */ []));
3978
+ constructor() {
3979
+ const destruction = inject(DestroyRef);
3980
+ destruction.onDestroy(() => {
3981
+ this.arreter();
3982
+ });
3983
+ // Une nouvelle duree relance le decompte : un second 429 repousse l'echeance.
3984
+ // Demarre apres le rendu, jamais au rendu serveur, ou une minuterie
3985
+ // empecherait la page de se stabiliser.
3986
+ let pret = false;
3987
+ afterNextRender(() => {
3988
+ pret = true;
3989
+ this.demarrer(this.secondes());
3990
+ });
3991
+ effect(() => {
3992
+ const secondes = this.secondes();
3993
+ if (pret)
3994
+ this.demarrer(secondes);
3995
+ });
3996
+ }
3997
+ demarrer(secondes) {
3998
+ this.arreter();
3999
+ this.echeance = Date.now() + Math.max(0, secondes) * 1000;
4000
+ this.battre();
4001
+ this.minuterie = setInterval(() => {
4002
+ this.battre();
4003
+ }, 1000);
4004
+ }
4005
+ battre() {
4006
+ const restant = Math.max(0, Math.ceil((this.echeance - Date.now()) / 1000));
4007
+ this.restant.set(restant);
4008
+ if (restant > 0)
4009
+ return;
4010
+ this.arreter();
4011
+ this.annonce.annoncer(this.libelles().reessayerMaintenant);
4012
+ this.termine.emit();
4013
+ }
4014
+ arreter() {
4015
+ if (this.minuterie !== null)
4016
+ clearInterval(this.minuterie);
4017
+ this.minuterie = null;
4018
+ }
4019
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StTimer, deps: [], target: i0.ɵɵFactoryTarget.Component });
4020
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.6", type: StTimer, isStandalone: true, selector: "st-timer", inputs: { secondes: { classPropertyName: "secondes", publicName: "secondes", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { termine: "termine" }, host: { classAttribute: "st-timer" }, ngImport: i0, template: "<span class=\"st-timer__decompte\" role=\"timer\">{{ texte() }}</span>\n<span class=\"st-vh\" aria-live=\"polite\">{{ annonce.texte() }}</span>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:inline-block;color:var(--st-couleur-texte-discret);font-variant-numeric:tabular-nums}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4021
+ }
4022
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StTimer, decorators: [{
4023
+ type: Component,
4024
+ args: [{ selector: 'st-timer', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'st-timer' }, template: "<span class=\"st-timer__decompte\" role=\"timer\">{{ texte() }}</span>\n<span class=\"st-vh\" aria-live=\"polite\">{{ annonce.texte() }}</span>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:inline-block;color:var(--st-couleur-texte-discret);font-variant-numeric:tabular-nums}\n"] }]
4025
+ }], ctorParameters: () => [], propDecorators: { secondes: [{ type: i0.Input, args: [{ isSignal: true, alias: "secondes", required: true }] }], termine: [{ type: i0.Output, args: ["termine"] }] } });
4026
+
4027
+ /**
4028
+ * Logo de l'organisation, en variante claire, sombre et monochrome.
4029
+ *
4030
+ * ⚠️ **Le texte alternatif est le NOM de l'organisation, jamais « logo ».** Un
4031
+ * lecteur d'ecran annonce deja « image » : « Logo Banque Exemple » se lit
4032
+ * « image, logo Banque Exemple ». Pose dans un lien vers l'accueil, ce nom
4033
+ * devient celui du lien — il doit donc dire ou il mene.
4034
+ *
4035
+ * ⚠️ **Decoratif quand le nom est ecrit a cote.** Le repeter ferait lire
4036
+ * « Banque Exemple Banque Exemple ».
4037
+ *
4038
+ * La variante suit le theme EFFECTIF pose par `StTheme` sur `<html data-theme>`,
4039
+ * et non `prefers-color-scheme` : une personne qui a choisi le clair sur un
4040
+ * systeme sombre doit voir le logo clair. Sous contraste force, la variante
4041
+ * monochrome prend le relais — un logo en couleurs peut y disparaitre sur le
4042
+ * fond impose.
4043
+ *
4044
+ * Les images viennent de la meme origine : la politique de securite du contenu
4045
+ * n'autorise pas d'autre source d'image sans extension explicite cote BFF.
4046
+ */
4047
+ class StLogo {
4048
+ /** Nom de l'organisation : c'est le texte alternatif. */
4049
+ nom = input.required(/* @ts-ignore */
4050
+ ...(ngDevMode ? [{ debugName: "nom" }] : /* istanbul ignore next */ []));
4051
+ clair = input.required(/* @ts-ignore */
4052
+ ...(ngDevMode ? [{ debugName: "clair" }] : /* istanbul ignore next */ []));
4053
+ /** `null` : la variante claire sert aussi sur fond sombre. */
4054
+ sombre = input(null, /* @ts-ignore */
4055
+ ...(ngDevMode ? [{ debugName: "sombre" }] : /* istanbul ignore next */ []));
4056
+ /** `null` : aucune variante dediee au contraste force. */
4057
+ monochrome = input(null, /* @ts-ignore */
4058
+ ...(ngDevMode ? [{ debugName: "monochrome" }] : /* istanbul ignore next */ []));
4059
+ decoratif = input(false, { ...(ngDevMode ? { debugName: "decoratif" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
4060
+ hauteur = input('2rem', /* @ts-ignore */
4061
+ ...(ngDevMode ? [{ debugName: "hauteur" }] : /* istanbul ignore next */ []));
4062
+ texteAlternatif = computed(() => (this.decoratif() ? '' : this.nom()), /* @ts-ignore */
4063
+ ...(ngDevMode ? [{ debugName: "texteAlternatif" }] : /* istanbul ignore next */ []));
4064
+ sourceSombre = computed(() => this.sombre() ?? this.clair(), /* @ts-ignore */
4065
+ ...(ngDevMode ? [{ debugName: "sourceSombre" }] : /* istanbul ignore next */ []));
4066
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StLogo, deps: [], target: i0.ɵɵFactoryTarget.Component });
4067
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StLogo, isStandalone: true, selector: "st-logo", inputs: { nom: { classPropertyName: "nom", publicName: "nom", isSignal: true, isRequired: true, transformFunction: null }, clair: { classPropertyName: "clair", publicName: "clair", isSignal: true, isRequired: true, transformFunction: null }, sombre: { classPropertyName: "sombre", publicName: "sombre", isSignal: true, isRequired: false, transformFunction: null }, monochrome: { classPropertyName: "monochrome", publicName: "monochrome", isSignal: true, isRequired: false, transformFunction: null }, decoratif: { classPropertyName: "decoratif", publicName: "decoratif", isSignal: true, isRequired: false, transformFunction: null }, hauteur: { classPropertyName: "hauteur", publicName: "hauteur", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-monochrome": "monochrome() === null ? null : \"\"", "style.--st-logo-hauteur": "hauteur()" }, classAttribute: "st-logo" }, ngImport: i0, template: "<!-- `loading=\"lazy\"` : la variante masquee n'est pas telechargee, la visible\n l'est aussitot puisqu'elle est a l'ecran.\n\n `prefer-ngsrc` ecarte pour les trois images : NgOptimizedImage exige une\n largeur et une hauteur fixes, or un logo n'a qu'une hauteur \u2014 sa largeur\n suit ses proportions, propres a chaque organisation. Et un logo est presque\n toujours un SVG, pour lequel un jeu de resolutions ne rapporte rien. -->\n<!-- eslint-disable-next-line @angular-eslint/template/prefer-ngsrc -- voir ci-dessus -->\n<img class=\"st-logo__clair\" loading=\"lazy\" [src]=\"clair()\" [alt]=\"texteAlternatif()\" />\n<!-- eslint-disable-next-line @angular-eslint/template/prefer-ngsrc -- voir ci-dessus -->\n<img class=\"st-logo__sombre\" loading=\"lazy\" [src]=\"sourceSombre()\" [alt]=\"texteAlternatif()\" />\n@if (monochrome(); as source) {\n <!-- eslint-disable-next-line @angular-eslint/template/prefer-ngsrc -- voir ci-dessus -->\n <img class=\"st-logo__monochrome\" loading=\"lazy\" [src]=\"source\" [alt]=\"texteAlternatif()\" />\n}\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:inline-flex;align-items:center}img{inline-size:auto;block-size:var(--st-logo-hauteur, 2rem);max-inline-size:100%}.st-logo__sombre,.st-logo__monochrome{display:none}:host-context([data-theme=sombre]) .st-logo__clair{display:none}:host-context([data-theme=sombre]) .st-logo__sombre{display:inline}@media(forced-colors:active){:host([data-monochrome]) .st-logo__clair,:host([data-monochrome]) .st-logo__sombre{display:none}:host([data-monochrome]) .st-logo__monochrome{display:inline}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4068
+ }
4069
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StLogo, decorators: [{
4070
+ type: Component,
4071
+ args: [{ selector: 'st-logo', changeDetection: ChangeDetectionStrategy.OnPush, host: {
4072
+ class: 'st-logo',
4073
+ '[attr.data-monochrome]': 'monochrome() === null ? null : ""',
4074
+ '[style.--st-logo-hauteur]': 'hauteur()',
4075
+ }, template: "<!-- `loading=\"lazy\"` : la variante masquee n'est pas telechargee, la visible\n l'est aussitot puisqu'elle est a l'ecran.\n\n `prefer-ngsrc` ecarte pour les trois images : NgOptimizedImage exige une\n largeur et une hauteur fixes, or un logo n'a qu'une hauteur \u2014 sa largeur\n suit ses proportions, propres a chaque organisation. Et un logo est presque\n toujours un SVG, pour lequel un jeu de resolutions ne rapporte rien. -->\n<!-- eslint-disable-next-line @angular-eslint/template/prefer-ngsrc -- voir ci-dessus -->\n<img class=\"st-logo__clair\" loading=\"lazy\" [src]=\"clair()\" [alt]=\"texteAlternatif()\" />\n<!-- eslint-disable-next-line @angular-eslint/template/prefer-ngsrc -- voir ci-dessus -->\n<img class=\"st-logo__sombre\" loading=\"lazy\" [src]=\"sourceSombre()\" [alt]=\"texteAlternatif()\" />\n@if (monochrome(); as source) {\n <!-- eslint-disable-next-line @angular-eslint/template/prefer-ngsrc -- voir ci-dessus -->\n <img class=\"st-logo__monochrome\" loading=\"lazy\" [src]=\"source\" [alt]=\"texteAlternatif()\" />\n}\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:inline-flex;align-items:center}img{inline-size:auto;block-size:var(--st-logo-hauteur, 2rem);max-inline-size:100%}.st-logo__sombre,.st-logo__monochrome{display:none}:host-context([data-theme=sombre]) .st-logo__clair{display:none}:host-context([data-theme=sombre]) .st-logo__sombre{display:inline}@media(forced-colors:active){:host([data-monochrome]) .st-logo__clair,:host([data-monochrome]) .st-logo__sombre{display:none}:host([data-monochrome]) .st-logo__monochrome{display:inline}}\n"] }]
4076
+ }], propDecorators: { nom: [{ type: i0.Input, args: [{ isSignal: true, alias: "nom", required: true }] }], clair: [{ type: i0.Input, args: [{ isSignal: true, alias: "clair", required: true }] }], sombre: [{ type: i0.Input, args: [{ isSignal: true, alias: "sombre", required: false }] }], monochrome: [{ type: i0.Input, args: [{ isSignal: true, alias: "monochrome", required: false }] }], decoratif: [{ type: i0.Input, args: [{ isSignal: true, alias: "decoratif", required: false }] }], hauteur: [{ type: i0.Input, args: [{ isSignal: true, alias: "hauteur", required: false }] }] } });
4077
+
1464
4078
  /**
1465
4079
  * Les gabarits des cinq etats, declares DANS `<st-state>`.
1466
4080
  *
@@ -1780,7 +4394,7 @@ class StState {
1780
4394
  return gabarit ?? null;
1781
4395
  }
1782
4396
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StState, deps: [], target: i0.ɵɵFactoryTarget.Component });
1783
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StState, isStandalone: true, selector: "st-state", inputs: { ressource: { classPropertyName: "ressource", publicName: "ressource", isSignal: true, isRequired: false, transformFunction: null }, etat: { classPropertyName: "etat", publicName: "etat", isSignal: true, isRequired: false, transformFunction: null }, estVide: { classPropertyName: "estVide", publicName: "estVide", isSignal: true, isRequired: false, transformFunction: null }, squelette: { classPropertyName: "squelette", publicName: "squelette", isSignal: true, isRequired: false, transformFunction: null }, lignesDeSquelette: { classPropertyName: "lignesDeSquelette", publicName: "lignesDeSquelette", isSignal: true, isRequired: false, transformFunction: null }, annonces: { classPropertyName: "annonces", publicName: "annonces", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-etat": "etatEffectif()", "attr.data-rechargement": "enRechargement() ? \"\" : null", "attr.aria-busy": "enAttente() ? \"true\" : null" }, classAttribute: "st-state" }, providers: [{ provide: REGION_VIVANTE_PARENTE, useValue: true }], queries: [{ propertyName: "gabaritSucces", first: true, predicate: StSucces, descendants: true, isSignal: true }, { propertyName: "gabaritErreur", first: true, predicate: StErreur, descendants: true, isSignal: true }, { propertyName: "gabaritVide", first: true, predicate: StVide, descendants: true, isSignal: true }, { propertyName: "gabaritHorsLigne", first: true, predicate: StHorsLigne, descendants: true, isSignal: true }, { propertyName: "gabaritChargement", first: true, predicate: StChargement, descendants: true, isSignal: true }], ngImport: i0, template: "@if (montreLaSilhouetteParDefaut()) {\n @if (squelette(); as variante) {\n <st-skeleton [variante]=\"variante\" [lignes]=\"lignesDeSquelette()\" />\n } @else {\n <st-spinner />\n }\n} @else if (gabaritDeLEtat(); as gabarit) {\n <ng-container [ngTemplateOutlet]=\"gabarit\" [ngTemplateOutletContext]=\"contexte()\" />\n}\n\n<span class=\"st-vh\" aria-live=\"polite\">{{ annonce() }}</span>\n", styles: [":host{display:block}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: StSkeleton, selector: "st-skeleton", inputs: ["variante", "lignes", "colonnes", "anime"] }, { kind: "component", type: StSpinner, selector: "st-spinner", inputs: ["taille", "ton", "etiquette"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4397
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StState, isStandalone: true, selector: "st-state", inputs: { ressource: { classPropertyName: "ressource", publicName: "ressource", isSignal: true, isRequired: false, transformFunction: null }, etat: { classPropertyName: "etat", publicName: "etat", isSignal: true, isRequired: false, transformFunction: null }, estVide: { classPropertyName: "estVide", publicName: "estVide", isSignal: true, isRequired: false, transformFunction: null }, squelette: { classPropertyName: "squelette", publicName: "squelette", isSignal: true, isRequired: false, transformFunction: null }, lignesDeSquelette: { classPropertyName: "lignesDeSquelette", publicName: "lignesDeSquelette", isSignal: true, isRequired: false, transformFunction: null }, annonces: { classPropertyName: "annonces", publicName: "annonces", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-etat": "etatEffectif()", "attr.data-rechargement": "enRechargement() ? \"\" : null", "attr.aria-busy": "enAttente() ? \"true\" : null" }, classAttribute: "st-state" }, providers: [{ provide: REGION_VIVANTE_PARENTE, useValue: true }], queries: [{ propertyName: "gabaritSucces", first: true, predicate: StSucces, descendants: true, isSignal: true }, { propertyName: "gabaritErreur", first: true, predicate: StErreur, descendants: true, isSignal: true }, { propertyName: "gabaritVide", first: true, predicate: StVide, descendants: true, isSignal: true }, { propertyName: "gabaritHorsLigne", first: true, predicate: StHorsLigne, descendants: true, isSignal: true }, { propertyName: "gabaritChargement", first: true, predicate: StChargement, descendants: true, isSignal: true }], ngImport: i0, template: "@if (montreLaSilhouetteParDefaut()) {\n @if (squelette(); as variante) {\n <st-skeleton [variante]=\"variante\" [lignes]=\"lignesDeSquelette()\" />\n } @else {\n <st-spinner />\n }\n} @else if (gabaritDeLEtat(); as gabarit) {\n <ng-container [ngTemplateOutlet]=\"gabarit\" [ngTemplateOutletContext]=\"contexte()\" />\n}\n\n<span class=\"st-vh\" aria-live=\"polite\">{{ annonce() }}</span>\n", styles: [":host([hidden]){display:none!important}:host{display:block}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: StSkeleton, selector: "st-skeleton", inputs: ["variante", "lignes", "colonnes", "anime"] }, { kind: "component", type: StSpinner, selector: "st-spinner", inputs: ["taille", "ton", "etiquette"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1784
4398
  }
1785
4399
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StState, decorators: [{
1786
4400
  type: Component,
@@ -1789,7 +4403,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
1789
4403
  '[attr.data-etat]': 'etatEffectif()',
1790
4404
  '[attr.data-rechargement]': 'enRechargement() ? "" : null',
1791
4405
  '[attr.aria-busy]': 'enAttente() ? "true" : null',
1792
- }, template: "@if (montreLaSilhouetteParDefaut()) {\n @if (squelette(); as variante) {\n <st-skeleton [variante]=\"variante\" [lignes]=\"lignesDeSquelette()\" />\n } @else {\n <st-spinner />\n }\n} @else if (gabaritDeLEtat(); as gabarit) {\n <ng-container [ngTemplateOutlet]=\"gabarit\" [ngTemplateOutletContext]=\"contexte()\" />\n}\n\n<span class=\"st-vh\" aria-live=\"polite\">{{ annonce() }}</span>\n", styles: [":host{display:block}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"] }]
4406
+ }, template: "@if (montreLaSilhouetteParDefaut()) {\n @if (squelette(); as variante) {\n <st-skeleton [variante]=\"variante\" [lignes]=\"lignesDeSquelette()\" />\n } @else {\n <st-spinner />\n }\n} @else if (gabaritDeLEtat(); as gabarit) {\n <ng-container [ngTemplateOutlet]=\"gabarit\" [ngTemplateOutletContext]=\"contexte()\" />\n}\n\n<span class=\"st-vh\" aria-live=\"polite\">{{ annonce() }}</span>\n", styles: [":host([hidden]){display:none!important}:host{display:block}.st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"] }]
1793
4407
  }], ctorParameters: () => [], propDecorators: { ressource: [{ type: i0.Input, args: [{ isSignal: true, alias: "ressource", required: false }] }], etat: [{ type: i0.Input, args: [{ isSignal: true, alias: "etat", required: false }] }], estVide: [{ type: i0.Input, args: [{ isSignal: true, alias: "estVide", required: false }] }], squelette: [{ type: i0.Input, args: [{ isSignal: true, alias: "squelette", required: false }] }], lignesDeSquelette: [{ type: i0.Input, args: [{ isSignal: true, alias: "lignesDeSquelette", required: false }] }], annonces: [{ type: i0.Input, args: [{ isSignal: true, alias: "annonces", required: false }] }], gabaritSucces: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StSucces), { isSignal: true }] }], gabaritErreur: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StErreur), { isSignal: true }] }], gabaritVide: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StVide), { isSignal: true }] }], gabaritHorsLigne: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StHorsLigne), { isSignal: true }] }], gabaritChargement: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StChargement), { isSignal: true }] }] } });
1794
4408
 
1795
4409
  /**
@@ -1804,5 +4418,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
1804
4418
  * Generated bundle index. Do not edit.
1805
4419
  */
1806
4420
 
1807
- export { CHEMIN_DU_SPRITE, FUSEAU_PAR_DEFAUT, GABARITS_D_ETAT, LIBELLES_EN, LIBELLES_FR, NOMS_DICONE, REGION_VIVANTE_PARENTE, ST_LIBELLES, ST_LOCALE, StAvatar, StBadge, StButton, StButtonGroup, StChargement, StCode, StCount, StDate, StEmpty, StErreur, StError, StHeading, StHorsLigne, StIcon, StIconButton, StLink, StMasked, StMoney, StOfflineBanner, StProgress, StRelativeTime, StSkeleton, StSpinner, StState, StStatusPill, StSucces, StTag, StText, StVide, fournirCheminDuSprite, provideStarterUi };
4421
+ export { AnnonceLocale, CHEMIN_DU_SPRITE, ContratDeChamp, ControleDeSaisie, FUSEAU_PAR_DEFAUT, GABARITS_D_ETAT, IDENTIFIANT_DU_CONTENU_PRINCIPAL, LIBELLES_EN, LIBELLES_FR, NOMS_DICONE, REGION_VIVANTE_PARENTE, ST_LIBELLES, ST_LOCALE, StAppShell, StAvatar, StBadge, StBanner, StBreadcrumb, StButton, StButtonGroup, StCalendar, StCard, StChargement, StCheckbox, StCode, StControleDeChamp, StCopyButton, StCount, StDate, StDivider, StEmpty, StErreur, StError, StErrorSummary, StFieldset, StFileUpload, StFormField, StHeader, StHeading, StHorsLigne, StIbanField, StIcon, StIconButton, StInlineMessage, StInput, StLangSwitch, StLink, StLogo, StMasked, StMoney, StOfflineBanner, StOtpField, StPageTitle, StPasswordField, StPhoneField, StProgress, StRadioGroup, StRelativeTime, StSearchField, StSection, StSelect, StSkeleton, StSkipLink, StSpinner, StState, StStatusPill, StSucces, StSwitch, StTag, StText, StTextarea, StThemeToggle, StTimer, StVide, copierDansLePressePapiers, erreurDate, erreurIban, erreurPlageDeDates, erreurTelephone, erreursDeFichiers, exempleDeDate, filtrerOptions, formaterDuree, fournirCheminDuSprite, fusionnerErreurs, messageDErreur, motifLocal, normaliserPourRecherche, pressePapiersDisponible, provideStarterUi };
1808
4422
  //# sourceMappingURL=starterlib-ui.mjs.map