@starterlib/ui 0.1.0 → 0.2.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,21 +1,153 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, input, computed, ChangeDetectionStrategy, Component, ElementRef, DestroyRef, model, output, signal, LOCALE_ID, afterNextRender, isDevMode } from '@angular/core';
3
- import { DOCUMENT, NgTemplateOutlet } from '@angular/common';
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';
4
3
  import { masquerIban, masquerTelephone, masquerCarte, quatreDerniers, formaterIban, formaterMontant } from '@starterlib/util';
4
+ export { ETATS_DE_BLOC } from '@starterlib/util';
5
+ import { DOCUMENT, NgTemplateOutlet } from '@angular/common';
6
+
7
+ /**
8
+ * Defaut francais, identique mot pour mot aux textes ecrits en dur jusqu'a la
9
+ * 0.1.1 : une application qui ne fournit rien ne change pas de comportement.
10
+ *
11
+ * Il existe pour que le socle reste utilisable sans i18n, pas pour dispenser
12
+ * d'en avoir une. Une application bilingue DOIT fournir son propre dictionnaire
13
+ * sous forme de signal — sinon la moitie de l'interface reste en francais quand
14
+ * l'utilisateur passe a l'anglais, et rien ne le signale.
15
+ */
16
+ const LIBELLES_FR = {
17
+ chargementEnCours: 'Chargement en cours',
18
+ erreurSurvenue: 'Une erreur est survenue',
19
+ aucunResultat: 'Aucun resultat',
20
+ horsConnexion: 'Hors connexion',
21
+ reessayer: 'Reessayer',
22
+ identifiantDeTrace: 'Identifiant de trace',
23
+ codeTechnique: 'Code',
24
+ copier: 'Copier',
25
+ copieEffectuee: 'Copie',
26
+ afficher: 'Afficher',
27
+ masquer: 'Masquer',
28
+ valeurMasqueeANouveau: 'Valeur masquee a nouveau',
29
+ natureIban: 'IBAN',
30
+ natureCarte: 'carte',
31
+ natureTelephone: 'numero',
32
+ seTerminantPar: (nature, quatreDerniers) => `${nature} se terminant par ${quatreDerniers}`,
33
+ nouvelleFenetre: '(nouvelle fenetre)',
34
+ retirer: 'Retirer',
35
+ aLInstant: "a l'instant",
36
+ };
37
+ /** Traduction anglaise du meme dictionnaire. La paire est obligatoire. */
38
+ const LIBELLES_EN = {
39
+ chargementEnCours: 'Loading',
40
+ erreurSurvenue: 'Something went wrong',
41
+ aucunResultat: 'No results',
42
+ horsConnexion: 'Offline',
43
+ reessayer: 'Try again',
44
+ identifiantDeTrace: 'Trace identifier',
45
+ codeTechnique: 'Code',
46
+ copier: 'Copy',
47
+ copieEffectuee: 'Copied',
48
+ afficher: 'Show',
49
+ masquer: 'Hide',
50
+ valeurMasqueeANouveau: 'Value hidden again',
51
+ natureIban: 'IBAN',
52
+ natureCarte: 'card',
53
+ natureTelephone: 'number',
54
+ seTerminantPar: (nature, quatreDerniers) => `${nature} ending in ${quatreDerniers}`,
55
+ nouvelleFenetre: '(opens in a new window)',
56
+ retirer: 'Remove',
57
+ aLInstant: 'just now',
58
+ };
5
59
 
6
60
  /**
7
- * Chemin du sprite SVG des icones. Chaque SPA le remplace par son actif
8
- * empreinte (`/assets/icones/sprite.<hash>.svg`) pour beneficier d'un cache
9
- * immuable. Le defaut vise le chemin non empreinte, utilisable en
10
- * developpement.
61
+ * Locale de formatage des montants, des dates et des nombres, **sous forme de
62
+ * signal**.
63
+ *
64
+ * ⚠️ Pourquoi pas `LOCALE_ID` : il est fige au demarrage de l'application. Or
65
+ * l'ADR 0014 du backend exige de changer de langue SANS recharger — la coquille
66
+ * detient la langue, et tout doit basculer d'un coup. Un composant qui lit
67
+ * `LOCALE_ID` continuerait d'afficher « 1 234,50 € » dans une interface passee
68
+ * a l'anglais.
69
+ *
70
+ * Le defaut lit `LOCALE_ID` : une application qui ne fournit rien garde le
71
+ * comportement d'avant, simplement sans pouvoir changer de langue a chaud.
72
+ */
73
+ const ST_LOCALE = new InjectionToken('st.locale', {
74
+ providedIn: 'root',
75
+ factory: () => {
76
+ const locale = inject(LOCALE_ID);
77
+ return signal(locale).asReadonly();
78
+ },
79
+ });
80
+ /**
81
+ * Textes portes par les composants eux-memes, sous forme de signal pour la
82
+ * meme raison que la locale.
83
+ */
84
+ const ST_LIBELLES = new InjectionToken('st.libelles', {
85
+ providedIn: 'root',
86
+ factory: () => signal(LIBELLES_FR).asReadonly(),
87
+ });
88
+ /**
89
+ * Chemin du sprite SVG des icones, **fourni par l'application**.
90
+ *
91
+ * ⚠️ Aucun defaut, et c'est voulu. Un defaut absolu (`/assets/icones/...`) est
92
+ * faux des que l'interface est servie sous un prefixe (`/ui/<interface>/`), et
93
+ * l'echec est MUET : la reference externe d'un `<use>` qui ne resout pas ne
94
+ * leve rien, toutes les icones restent vides, et la regle « un statut se lit
95
+ * par une icone ET un texte » tombe sans que rien ne le signale. Mieux vaut
96
+ * echouer au demarrage, une fois, avec la marche a suivre.
97
+ *
98
+ * L'actif est publie avec le paquet :
99
+ * `node_modules/@starterlib/ui/assets/icones/sprite.svg`. Chaque SPA le copie
100
+ * dans ses actifs (bloc `assets` de `angular.json`), puis fournit son chemin —
101
+ * de preference empreinte, pour un cache immuable :
102
+ *
103
+ * ```ts
104
+ * { provide: CHEMIN_DU_SPRITE, useValue: '/ui/socle/assets/icones/sprite.svg' }
105
+ * ```
11
106
  */
12
107
  const CHEMIN_DU_SPRITE = new InjectionToken('st.chemin-du-sprite', {
13
108
  providedIn: 'root',
14
- factory: () => '/assets/icones/sprite.svg',
109
+ factory: () => {
110
+ throw new Error('CHEMIN_DU_SPRITE n\'est pas fourni. Copiez "@starterlib/ui/assets/icones/sprite.svg"' +
111
+ " dans les actifs de l'application, puis fournissez son chemin :" +
112
+ " { provide: CHEMIN_DU_SPRITE, useValue: '/ui/<interface>/assets/icones/sprite.svg' }.");
113
+ },
15
114
  });
115
+ /**
116
+ * Fournit le chemin du sprite. A poser une fois, dans la configuration de
117
+ * l'application — jamais dans un composant, ou deux branches de l'arbre
118
+ * pourraient viser deux sprites differents.
119
+ */
120
+ function fournirCheminDuSprite(chemin) {
121
+ return { provide: CHEMIN_DU_SPRITE, useValue: chemin };
122
+ }
123
+ /**
124
+ * Configure `@starterlib/ui` pour toute l'application.
125
+ *
126
+ * ⚠️ A appeler dans l'HOTE uniquement. Dans un assemblage federe, un remote qui
127
+ * la rappellerait poserait un second jeu de valeurs dans son injecteur de
128
+ * route : deux locales, deux dictionnaires, et la moitie de l'ecran resterait
129
+ * dans l'ancienne langue apres une bascule.
130
+ */
131
+ function provideStarterUi(configuration) {
132
+ const fournisseurs = [fournirCheminDuSprite(configuration.cheminDuSprite)];
133
+ if (configuration.locale !== undefined) {
134
+ fournisseurs.push({ provide: ST_LOCALE, useValue: enSignal(configuration.locale) });
135
+ }
136
+ if (configuration.libelles !== undefined) {
137
+ fournisseurs.push({ provide: ST_LIBELLES, useValue: enSignal(configuration.libelles) });
138
+ }
139
+ if (configuration.fuseau !== undefined) {
140
+ fournisseurs.push({ provide: FUSEAU_PAR_DEFAUT, useValue: configuration.fuseau });
141
+ }
142
+ return fournisseurs;
143
+ }
144
+ /** Une valeur figee reste acceptee : toute application ne change pas de langue. */
145
+ function enSignal(valeur) {
146
+ return typeof valeur === 'function' ? valeur : signal(valeur).asReadonly();
147
+ }
16
148
  /**
17
149
  * Marque la presence d'une region vivante possedee par un ancetre, en pratique
18
- * la directive `stState`.
150
+ * le composant `st-state`.
19
151
  *
20
152
  * Tout composant susceptible de porter un `role="status"` l'injecte en
21
153
  * optionnel et **se tait** s'il en trouve un. Sans cela, un indicateur de
@@ -34,13 +166,12 @@ const FUSEAU_PAR_DEFAUT = new InjectionToken('st.fuseau-par-defaut', {
34
166
  factory: () => 'Europe/Paris',
35
167
  });
36
168
 
37
- const ETATS_DE_BLOC = [
38
- 'chargement',
39
- 'erreur',
40
- 'vide',
41
- 'hors-ligne',
42
- 'succes',
43
- ];
169
+ /**
170
+ * Les cinq etats de bloc vivent dans `@starterlib/util` depuis la 0.2.0 : le
171
+ * noyau en a besoin pour deriver l'etat d'une ressource, et il ne doit pas
172
+ * dependre des composants. Reexportes ici pour que `@starterlib/ui` reste le
173
+ * seul import necessaire a qui n'ecrit que de l'interface.
174
+ */
44
175
 
45
176
  /**
46
177
  * Icone tiree d'un sprite SVG servi en meme origine.
@@ -60,7 +191,7 @@ class StIcon {
60
191
  ...(ngDevMode ? [{ debugName: "nom" }] : /* istanbul ignore next */ []));
61
192
  taille = input('md', /* @ts-ignore */
62
193
  ...(ngDevMode ? [{ debugName: "taille" }] : /* istanbul ignore next */ []));
63
- ton = input('courant', /* @ts-ignore */
194
+ ton = input('neutre', /* @ts-ignore */
64
195
  ...(ngDevMode ? [{ debugName: "ton" }] : /* istanbul ignore next */ []));
65
196
  /** `null` : l'icone est decorative et reste muette pour les lecteurs. */
66
197
  etiquette = input(null, /* @ts-ignore */
@@ -70,7 +201,7 @@ class StIcon {
70
201
  reference = computed(() => `${this.cheminDuSprite}#${this.nom()}`, /* @ts-ignore */
71
202
  ...(ngDevMode ? [{ debugName: "reference" }] : /* istanbul ignore next */ []));
72
203
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StIcon, deps: [], target: i0.ɵɵFactoryTarget.Component });
73
- 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:var(--st-couleur-texte)}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 });
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 });
74
205
  }
75
206
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StIcon, decorators: [{
76
207
  type: Component,
@@ -78,11 +209,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
78
209
  class: 'st-icon',
79
210
  '[attr.data-taille]': 'taille()',
80
211
  '[attr.data-ton]': 'ton()',
81
- }, 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:var(--st-couleur-texte)}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"] }]
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"] }]
82
213
  }], 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 }] }] } });
83
214
 
84
215
  /**
85
- * Noms du sprite, engendres depuis `assets/icones/sprite.svg`.
216
+ * Noms du sprite, tenus a l'identique de `assets/icones/sprite.svg` par les
217
+ * tests de `st-icon.spec.ts` (dans les deux sens).
86
218
  *
87
219
  * Le type existe pour qu'une faute de frappe echoue a la compilation : une
88
220
  * reference `use` vers un identifiant absent ne rend RIEN, sans erreur, et le
@@ -127,8 +259,7 @@ class StText {
127
259
  ...(ngDevMode ? [{ debugName: "variante" }] : /* istanbul ignore next */ []));
128
260
  graisse = input('normale', /* @ts-ignore */
129
261
  ...(ngDevMode ? [{ debugName: "graisse" }] : /* istanbul ignore next */ []));
130
- enLigne = input(false, /* @ts-ignore */
131
- ...(ngDevMode ? [{ debugName: "enLigne" }] : /* istanbul ignore next */ []));
262
+ enLigne = input(false, { ...(ngDevMode ? { debugName: "enLigne" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
132
263
  /**
133
264
  * Nombre de lignes au-dela duquel le texte est coupe.
134
265
  *
@@ -211,16 +342,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
211
342
  */
212
343
  class StSpinner {
213
344
  regionParente = inject(REGION_VIVANTE_PARENTE, { optional: true });
345
+ libelles = inject(ST_LIBELLES);
214
346
  taille = input('md', /* @ts-ignore */
215
347
  ...(ngDevMode ? [{ debugName: "taille" }] : /* istanbul ignore next */ []));
216
348
  ton = input('primaire', /* @ts-ignore */
217
349
  ...(ngDevMode ? [{ debugName: "ton" }] : /* istanbul ignore next */ []));
218
- etiquette = input('Chargement en cours', /* @ts-ignore */
350
+ /** `null` : le texte vient du dictionnaire de l'application. */
351
+ etiquette = input(null, /* @ts-ignore */
219
352
  ...(ngDevMode ? [{ debugName: "etiquette" }] : /* istanbul ignore next */ []));
353
+ etiquetteLue = computed(() => this.etiquette() ?? this.libelles().chargementEnCours, /* @ts-ignore */
354
+ ...(ngDevMode ? [{ debugName: "etiquetteLue" }] : /* istanbul ignore next */ []));
220
355
  sAnnonce = computed(() => this.regionParente === null, /* @ts-ignore */
221
356
  ...(ngDevMode ? [{ debugName: "sAnnonce" }] : /* istanbul ignore next */ []));
222
357
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StSpinner, deps: [], target: i0.ɵɵFactoryTarget.Component });
223
- 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() ? etiquette() : 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=courant]){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 });
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 });
224
359
  }
225
360
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StSpinner, decorators: [{
226
361
  type: Component,
@@ -229,8 +364,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
229
364
  '[attr.data-taille]': 'taille()',
230
365
  '[attr.data-ton]': 'ton()',
231
366
  '[attr.role]': 'sAnnonce() ? "status" : null',
232
- '[attr.aria-label]': 'sAnnonce() ? etiquette() : null',
233
- }, 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=courant]){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"] }]
367
+ '[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"] }]
234
369
  }], 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 }] }] } });
235
370
 
236
371
  /**
@@ -271,7 +406,7 @@ class StProgress {
271
406
  }, /* @ts-ignore */
272
407
  ...(ngDevMode ? [{ debugName: "pourcentage" }] : /* istanbul ignore next */ []));
273
408
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StProgress, deps: [], target: i0.ɵɵFactoryTarget.Component });
274
- 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:calc(var(--st-progress-part, 0) * 1%);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 });
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 });
275
410
  }
276
411
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StProgress, decorators: [{
277
412
  type: Component,
@@ -286,7 +421,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
286
421
  '[attr.aria-valuenow]': 'valeurAnnoncee()',
287
422
  '[attr.aria-valuetext]': 'texteDeValeur()',
288
423
  '[style.--st-progress-part.%]': 'pourcentage()',
289
- }, 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:calc(var(--st-progress-part, 0) * 1%);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"] }]
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"] }]
290
425
  }], 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 }] }] } });
291
426
 
292
427
  /**
@@ -306,8 +441,7 @@ class StSkeleton {
306
441
  ...(ngDevMode ? [{ debugName: "lignes" }] : /* istanbul ignore next */ []));
307
442
  colonnes = input(4, /* @ts-ignore */
308
443
  ...(ngDevMode ? [{ debugName: "colonnes" }] : /* istanbul ignore next */ []));
309
- anime = input(true, /* @ts-ignore */
310
- ...(ngDevMode ? [{ debugName: "anime" }] : /* istanbul ignore next */ []));
444
+ anime = input(true, { ...(ngDevMode ? { debugName: "anime" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
311
445
  indicesDeLigne = computed(() => Array.from({ length: Math.max(1, this.lignes()) }, (_, index) => index), /* @ts-ignore */
312
446
  ...(ngDevMode ? [{ debugName: "indicesDeLigne" }] : /* istanbul ignore next */ []));
313
447
  indicesDeColonne = computed(() => Array.from({ length: Math.max(1, this.colonnes()) }, (_, index) => index), /* @ts-ignore */
@@ -334,6 +468,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
334
468
  * tabulation si quelqu'un lui pose un `tabindex`. Tout fonctionne en
335
469
  * demonstration et casse au premier formulaire reel.
336
470
  *
471
+ * ⚠️ L'indicateur de chargement est MUET (`aria-hidden`) : pose dans le bouton,
472
+ * son `role="status"` entrait dans le nom accessible, qui devenait « Chargement
473
+ * en cours Valider ». L'annonce de l'action en cours revient a l'annonceur
474
+ * global du noyau, pas au bouton.
475
+ *
337
476
  * ⚠️ Pendant le chargement, le bouton porte `aria-disabled` et NON `disabled` :
338
477
  * l'attribut natif lui retire le focus, le lecteur d'ecran perd le controle
339
478
  * qu'il avait sous le doigt et retombe sur le corps du document. Les clics
@@ -344,8 +483,7 @@ class StButton {
344
483
  ...(ngDevMode ? [{ debugName: "variante" }] : /* istanbul ignore next */ []));
345
484
  taille = input('md', /* @ts-ignore */
346
485
  ...(ngDevMode ? [{ debugName: "taille" }] : /* istanbul ignore next */ []));
347
- pleineLargeur = input(false, /* @ts-ignore */
348
- ...(ngDevMode ? [{ debugName: "pleineLargeur" }] : /* istanbul ignore next */ []));
486
+ pleineLargeur = input(false, { ...(ngDevMode ? { debugName: "pleineLargeur" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
349
487
  iconeAvant = input(null, /* @ts-ignore */
350
488
  ...(ngDevMode ? [{ debugName: "iconeAvant" }] : /* istanbul ignore next */ []));
351
489
  iconeApres = input(null, /* @ts-ignore */
@@ -355,8 +493,14 @@ class StButton {
355
493
  * mecanisme d'anti double soumission. L'appelant doit le lever DES la
356
494
  * soumission, pas a l'arrivee de la reponse.
357
495
  */
358
- chargement = input(false, /* @ts-ignore */
359
- ...(ngDevMode ? [{ debugName: "chargement" }] : /* istanbul ignore next */ []));
496
+ chargement = input(false, { ...(ngDevMode ? { debugName: "chargement" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
497
+ /**
498
+ * Le ton suit le FOND du bouton, et non le bouton en general : sur une
499
+ * variante posee sur la surface (`secondaire`, qui est le defaut, et
500
+ * `discret`), un indicateur en ton inverse tombait a 1,00:1 — invisible.
501
+ */
502
+ tonDuChargement = computed(() => this.variante() === 'primaire' || this.variante() === 'danger' ? 'inverse' : 'neutre', /* @ts-ignore */
503
+ ...(ngDevMode ? [{ debugName: "tonDuChargement" }] : /* istanbul ignore next */ []));
360
504
  constructor() {
361
505
  const element = inject(ElementRef).nativeElement;
362
506
  const garde = (evenement) => {
@@ -379,7 +523,7 @@ class StButton {
379
523
  });
380
524
  }
381
525
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StButton, deps: [], target: i0.ɵɵFactoryTarget.Component });
382
- 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 (chargement()) {\n <st-spinner taille=\"sm\" ton=\"inverse\" />\n} @else 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 (!chargement() && iconeApres()) {\n <st-icon [nom]=\"iconeApres()!\" taille=\"sm\" />\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{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;border-radius:inherit}: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([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;border-radius:inherit;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=destructeur]){color:var(--st-couleur-sur-danger);background:var(--st-couleur-danger);border-color:transparent}:host([data-variante=destructeur]):focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px;border-radius:inherit;box-shadow:0 0 0 2px var(--st-couleur-surface)}:host([data-variante=destructeur]):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 });
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 });
383
527
  }
384
528
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StButton, decorators: [{
385
529
  type: Component,
@@ -390,7 +534,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
390
534
  '[attr.data-pleine-largeur]': 'pleineLargeur() ? "" : null',
391
535
  '[attr.aria-disabled]': 'chargement() ? "true" : null',
392
536
  '[attr.aria-busy]': 'chargement() ? "true" : null',
393
- }, template: "@if (chargement()) {\n <st-spinner taille=\"sm\" ton=\"inverse\" />\n} @else 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 (!chargement() && iconeApres()) {\n <st-icon [nom]=\"iconeApres()!\" taille=\"sm\" />\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{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;border-radius:inherit}: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([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;border-radius:inherit;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=destructeur]){color:var(--st-couleur-sur-danger);background:var(--st-couleur-danger);border-color:transparent}:host([data-variante=destructeur]):focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px;border-radius:inherit;box-shadow:0 0 0 2px var(--st-couleur-surface)}:host([data-variante=destructeur]):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"] }]
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"] }]
394
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 }] }] } });
395
539
 
396
540
  /**
@@ -410,11 +554,18 @@ class StIconButton {
410
554
  ...(ngDevMode ? [{ debugName: "variante" }] : /* istanbul ignore next */ []));
411
555
  taille = input('md', /* @ts-ignore */
412
556
  ...(ngDevMode ? [{ debugName: "taille" }] : /* istanbul ignore next */ []));
413
- /** `null` : le bouton n'est pas a deux etats et n'annonce aucune pression. */
414
- enfonce = model(null, /* @ts-ignore */
557
+ /**
558
+ * `null` : le bouton n'est pas a deux etats et n'annonce aucune pression.
559
+ *
560
+ * ⚠️ Une ENTREE, et non un `model`. Le composant ne bascule rien de lui-meme :
561
+ * l'etat enfonce reflete une donnee que l'appelant detient. En `model`,
562
+ * `[(enfonce)]` compilait et ne remontait jamais — une liaison bidirectionnelle
563
+ * muette est pire qu'absente, puisqu'elle se relit comme fonctionnelle.
564
+ */
565
+ enfonce = input(null, /* @ts-ignore */
415
566
  ...(ngDevMode ? [{ debugName: "enfonce" }] : /* istanbul ignore next */ []));
416
567
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StIconButton, deps: [], target: i0.ɵɵFactoryTarget.Component });
417
- 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 } }, outputs: { enfonce: "enfonceChange" }, 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;border-radius:inherit}: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=destructeur]){color:var(--st-couleur-danger)}:host([data-variante=destructeur]):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 });
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 });
418
569
  }
419
570
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StIconButton, decorators: [{
420
571
  type: Component,
@@ -424,8 +575,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
424
575
  '[attr.data-taille]': 'taille()',
425
576
  '[attr.aria-label]': 'etiquette()',
426
577
  '[attr.aria-pressed]': 'enfonce() === null ? null : enfonce()',
427
- }, 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;border-radius:inherit}: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=destructeur]){color:var(--st-couleur-danger)}:host([data-variante=destructeur]):hover:not(:disabled){background:var(--st-couleur-danger-discret)}\n"] }]
428
- }], 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 }] }, { type: i0.Output, args: ["enfonceChange"] }] } });
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"] }]
579
+ }], 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 }] }] } });
429
580
 
430
581
  /**
431
582
  * Lien, pose en attribut sur un `<a>` natif.
@@ -438,16 +589,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
438
589
  * quiconque regarde l'ecran.
439
590
  */
440
591
  class StLink {
592
+ libelles = inject(ST_LIBELLES);
441
593
  variante = input('texte', /* @ts-ignore */
442
594
  ...(ngDevMode ? [{ debugName: "variante" }] : /* istanbul ignore next */ []));
443
595
  /** Ouvre dans un nouvel onglet, et l'annonce dans le nom accessible. */
444
- externe = input(false, /* @ts-ignore */
445
- ...(ngDevMode ? [{ debugName: "externe" }] : /* istanbul ignore next */ []));
446
- /** Mention lue par les lecteurs d'ecran quand le lien sort du site. */
447
- mentionExterne = input('(nouvelle fenetre)', /* @ts-ignore */
596
+ externe = input(false, { ...(ngDevMode ? { debugName: "externe" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
597
+ /**
598
+ * Mention lue par les lecteurs d'ecran quand le lien sort du site.
599
+ * `null` : le texte vient du dictionnaire de l'application.
600
+ */
601
+ mentionExterne = input(null, /* @ts-ignore */
448
602
  ...(ngDevMode ? [{ debugName: "mentionExterne" }] : /* istanbul ignore next */ []));
603
+ mentionExterneLue = computed(() => this.mentionExterne() ?? this.libelles().nouvelleFenetre, /* @ts-ignore */
604
+ ...(ngDevMode ? [{ debugName: "mentionExterneLue" }] : /* istanbul ignore next */ []));
449
605
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StLink, deps: [], target: i0.ɵɵFactoryTarget.Component });
450
- 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\">{{ mentionExterne() }}</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;border-radius:inherit}: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 });
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 });
451
607
  }
452
608
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StLink, decorators: [{
453
609
  type: Component,
@@ -456,7 +612,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
456
612
  '[attr.data-variante]': 'variante()',
457
613
  '[attr.target]': 'externe() ? "_blank" : null',
458
614
  '[attr.rel]': 'externe() ? "noopener noreferrer" : null',
459
- }, template: "<ng-content />\n@if (externe()) {\n <st-icon nom=\"lien-externe\" taille=\"xs\" />\n <span class=\"st-vh\">{{ mentionExterne() }}</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;border-radius:inherit}: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"] }]
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"] }]
460
616
  }], 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 }] }] } });
461
617
 
462
618
  /**
@@ -474,8 +630,7 @@ class StButtonGroup {
474
630
  orientation = input('horizontale', /* @ts-ignore */
475
631
  ...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
476
632
  /** Boutons jointifs, rayons fusionnes. */
477
- attache = input(false, /* @ts-ignore */
478
- ...(ngDevMode ? [{ debugName: "attache" }] : /* istanbul ignore next */ []));
633
+ attache = input(false, { ...(ngDevMode ? { debugName: "attache" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
479
634
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StButtonGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
480
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 });
481
636
  }
@@ -502,16 +657,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
502
657
  class StCode {
503
658
  document = inject(DOCUMENT);
504
659
  destruction = inject(DestroyRef);
660
+ libelles = inject(ST_LIBELLES);
505
661
  valeur = input.required(/* @ts-ignore */
506
662
  ...(ngDevMode ? [{ debugName: "valeur" }] : /* istanbul ignore next */ []));
507
- etiquette = input('Identifiant de trace', /* @ts-ignore */
663
+ copiable = input(true, { ...(ngDevMode ? { debugName: "copiable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
664
+ /** `null` : les textes viennent du dictionnaire de l'application. */
665
+ etiquette = input(null, /* @ts-ignore */
508
666
  ...(ngDevMode ? [{ debugName: "etiquette" }] : /* istanbul ignore next */ []));
509
- copiable = input(true, /* @ts-ignore */
510
- ...(ngDevMode ? [{ debugName: "copiable" }] : /* istanbul ignore next */ []));
511
- libelleCopier = input('Copier', /* @ts-ignore */
667
+ libelleCopier = input(null, /* @ts-ignore */
512
668
  ...(ngDevMode ? [{ debugName: "libelleCopier" }] : /* istanbul ignore next */ []));
513
- messageDeConfirmation = input('Copie', /* @ts-ignore */
669
+ messageDeConfirmation = input(null, /* @ts-ignore */
514
670
  ...(ngDevMode ? [{ debugName: "messageDeConfirmation" }] : /* istanbul ignore next */ []));
671
+ etiquetteLue = computed(() => this.etiquette() ?? this.libelles().identifiantDeTrace, /* @ts-ignore */
672
+ ...(ngDevMode ? [{ debugName: "etiquetteLue" }] : /* istanbul ignore next */ []));
673
+ libelleCopierLu = computed(() => this.libelleCopier() ?? this.libelles().copier, /* @ts-ignore */
674
+ ...(ngDevMode ? [{ debugName: "libelleCopierLu" }] : /* istanbul ignore next */ []));
515
675
  copie = output();
516
676
  confirmation = signal('', /* @ts-ignore */
517
677
  ...(ngDevMode ? [{ debugName: "confirmation" }] : /* istanbul ignore next */ []));
@@ -542,7 +702,7 @@ class StCode {
542
702
  return;
543
703
  }
544
704
  this.copie.emit(this.valeur());
545
- this.confirmation.set(this.messageDeConfirmation());
705
+ this.confirmation.set(this.messageDeConfirmation() ?? this.libelles().copieEffectuee);
546
706
  if (this.minuterie !== null)
547
707
  clearTimeout(this.minuterie);
548
708
  this.minuterie = setTimeout(() => {
@@ -555,18 +715,13 @@ class StCode {
555
715
  });
556
716
  }
557
717
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StCode, deps: [], target: i0.ɵɵFactoryTarget.Component });
558
- 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 }, etiquette: { classPropertyName: "etiquette", publicName: "etiquette", isSignal: true, isRequired: false, transformFunction: null }, copiable: { classPropertyName: "copiable", publicName: "copiable", 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 [attr.aria-label]=\"etiquette() + ' ' + valeur()\">{{ valeur() }}</code>\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]=\"libelleCopier()\"\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"], outputs: ["enfonceChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
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 });
559
719
  }
560
720
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StCode, decorators: [{
561
721
  type: Component,
562
- args: [{ selector: 'st-code', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StIconButton], host: { class: 'st-code' }, template: "<code [attr.aria-label]=\"etiquette() + ' ' + valeur()\">{{ valeur() }}</code>\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]=\"libelleCopier()\"\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"] }]
563
- }], propDecorators: { valeur: [{ type: i0.Input, args: [{ isSignal: true, alias: "valeur", required: true }] }], etiquette: [{ type: i0.Input, args: [{ isSignal: true, alias: "etiquette", required: false }] }], copiable: [{ type: i0.Input, args: [{ isSignal: true, alias: "copiable", 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"] }] } });
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"] }]
723
+ }], 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"] }] } });
564
724
 
565
- const LIBELLE_DU_TYPE = {
566
- iban: 'IBAN',
567
- carte: 'carte',
568
- telephone: 'numero',
569
- };
570
725
  /**
571
726
  * Identifiant sensible, masque par defaut.
572
727
  *
@@ -579,6 +734,7 @@ const LIBELLE_DU_TYPE = {
579
734
  * journal.
580
735
  */
581
736
  class StMasked {
737
+ libelles = inject(ST_LIBELLES);
582
738
  destruction = inject(DestroyRef);
583
739
  valeur = input.required(/* @ts-ignore */
584
740
  ...(ngDevMode ? [{ debugName: "valeur" }] : /* istanbul ignore next */ []));
@@ -586,13 +742,13 @@ class StMasked {
586
742
  ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
587
743
  revele = model(false, /* @ts-ignore */
588
744
  ...(ngDevMode ? [{ debugName: "revele" }] : /* istanbul ignore next */ []));
589
- revelationAutorisee = input(false, /* @ts-ignore */
590
- ...(ngDevMode ? [{ debugName: "revelationAutorisee" }] : /* istanbul ignore next */ []));
745
+ revelationAutorisee = input(false, { ...(ngDevMode ? { debugName: "revelationAutorisee" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
591
746
  dureeDeRevelationEnSecondes = input(30, /* @ts-ignore */
592
747
  ...(ngDevMode ? [{ debugName: "dureeDeRevelationEnSecondes" }] : /* istanbul ignore next */ []));
593
- libelleAfficher = input('Afficher', /* @ts-ignore */
748
+ /** `null` : les textes viennent du dictionnaire de l'application. */
749
+ libelleAfficher = input(null, /* @ts-ignore */
594
750
  ...(ngDevMode ? [{ debugName: "libelleAfficher" }] : /* istanbul ignore next */ []));
595
- libelleMasquer = input('Masquer', /* @ts-ignore */
751
+ libelleMasquer = input(null, /* @ts-ignore */
596
752
  ...(ngDevMode ? [{ debugName: "libelleMasquer" }] : /* istanbul ignore next */ []));
597
753
  revelation = output();
598
754
  annonce = signal('', /* @ts-ignore */
@@ -613,14 +769,26 @@ class StMasked {
613
769
  ...(ngDevMode ? [{ debugName: "valeurMasquee" }] : /* istanbul ignore next */ []));
614
770
  valeurAffichee = computed(() => this.revele() ? this.valeurLisible() : this.valeurMasquee(), /* @ts-ignore */
615
771
  ...(ngDevMode ? [{ debugName: "valeurAffichee" }] : /* istanbul ignore next */ []));
772
+ /**
773
+ * La nature et la tournure viennent du dictionnaire : l'ordre des mots change
774
+ * d'une langue a l'autre, « IBAN se terminant par 2606 » contre « IBAN ending
775
+ * in 2606 ». Une chaine a trous ne suffirait pas.
776
+ */
616
777
  nomAccessible = computed(() => {
617
- const nature = LIBELLE_DU_TYPE[this.type()];
778
+ const libelles = this.libelles();
779
+ const nature = {
780
+ iban: libelles.natureIban,
781
+ carte: libelles.natureCarte,
782
+ telephone: libelles.natureTelephone,
783
+ }[this.type()];
618
784
  if (this.revele())
619
785
  return `${nature} ${this.valeurLisible()}`;
620
- return `${nature} se terminant par ${quatreDerniers(this.valeur())}`;
786
+ return libelles.seTerminantPar(nature, quatreDerniers(this.valeur()));
621
787
  }, /* @ts-ignore */
622
788
  ...(ngDevMode ? [{ debugName: "nomAccessible" }] : /* istanbul ignore next */ []));
623
- libelleDuBouton = computed(() => this.revele() ? this.libelleMasquer() : this.libelleAfficher(), /* @ts-ignore */
789
+ libelleDuBouton = computed(() => this.revele()
790
+ ? (this.libelleMasquer() ?? this.libelles().masquer)
791
+ : (this.libelleAfficher() ?? this.libelles().afficher), /* @ts-ignore */
624
792
  ...(ngDevMode ? [{ debugName: "libelleDuBouton" }] : /* istanbul ignore next */ []));
625
793
  valeurLisible() {
626
794
  return this.type() === 'iban' ? formaterIban(this.valeur()) : this.valeur();
@@ -653,14 +821,14 @@ class StMasked {
653
821
  if (!this.revele())
654
822
  return;
655
823
  this.revele.set(false);
656
- this.annonce.set('Valeur masquee a nouveau');
824
+ this.annonce.set(this.libelles().valeurMasqueeANouveau);
657
825
  }
658
826
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StMasked, deps: [], target: i0.ɵɵFactoryTarget.Component });
659
- 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\" [attr.aria-label]=\"nomAccessible()\">{{ valeurAffichee() }}</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"], outputs: ["enfonceChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
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 });
660
828
  }
661
829
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StMasked, decorators: [{
662
830
  type: Component,
663
- args: [{ selector: 'st-masked', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StIconButton], host: { class: 'st-masked', '[attr.data-type]': 'type()' }, template: "<span class=\"st-masked__valeur\" [attr.aria-label]=\"nomAccessible()\">{{ valeurAffichee() }}</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"] }]
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"] }]
664
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"] }] } });
665
833
 
666
834
  /**
@@ -675,13 +843,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
675
843
  * contraste ne doivent jamais transformer un debit en credit.
676
844
  */
677
845
  class StMoney {
678
- locale = inject(LOCALE_ID);
846
+ locale = inject(ST_LOCALE);
679
847
  valeur = input.required(/* @ts-ignore */
680
848
  ...(ngDevMode ? [{ debugName: "valeur" }] : /* istanbul ignore next */ []));
681
- signeExplicite = input(false, /* @ts-ignore */
682
- ...(ngDevMode ? [{ debugName: "signeExplicite" }] : /* istanbul ignore next */ []));
683
- sansDevise = input(false, /* @ts-ignore */
684
- ...(ngDevMode ? [{ debugName: "sansDevise" }] : /* istanbul ignore next */ []));
849
+ signeExplicite = input(false, { ...(ngDevMode ? { debugName: "signeExplicite" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
850
+ sansDevise = input(false, { ...(ngDevMode ? { debugName: "sansDevise" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
685
851
  taille = input('md', /* @ts-ignore */
686
852
  ...(ngDevMode ? [{ debugName: "taille" }] : /* istanbul ignore next */ []));
687
853
  signe = computed(() => {
@@ -694,7 +860,7 @@ class StMoney {
694
860
  }, /* @ts-ignore */
695
861
  ...(ngDevMode ? [{ debugName: "signe" }] : /* istanbul ignore next */ []));
696
862
  texte = computed(() => formaterMontant(this.valeur(), {
697
- locale: this.locale,
863
+ locale: this.locale(),
698
864
  signeExplicite: this.signeExplicite(),
699
865
  sansDevise: this.sansDevise(),
700
866
  }), /* @ts-ignore */
@@ -735,7 +901,7 @@ const OPTIONS = {
735
901
  * ambigu a l'oral, et l'ordre jour-mois n'est pas universel.
736
902
  */
737
903
  class StDate {
738
- locale = inject(LOCALE_ID);
904
+ locale = inject(ST_LOCALE);
739
905
  fuseauParDefaut = inject(FUSEAU_PAR_DEFAUT);
740
906
  valeur = input.required(/* @ts-ignore */
741
907
  ...(ngDevMode ? [{ debugName: "valeur" }] : /* istanbul ignore next */ []));
@@ -743,6 +909,20 @@ class StDate {
743
909
  ...(ngDevMode ? [{ debugName: "format" }] : /* istanbul ignore next */ []));
744
910
  fuseau = input(null, /* @ts-ignore */
745
911
  ...(ngDevMode ? [{ debugName: "fuseau" }] : /* istanbul ignore next */ []));
912
+ /**
913
+ * Une DATE DE CALENDRIER (`2026-09-12`) n'est pas un instant : une date de
914
+ * naissance, une echeance ou un jour de valeur n'ont pas d'heure, et ne
915
+ * doivent pas changer de jour selon le fuseau de qui les regarde.
916
+ *
917
+ * ⚠️ Le piege est dans la norme : `new Date('2026-09-12')` vaut minuit UTC,
918
+ * donc le 11 septembre partout a l'ouest de Greenwich. Une echeance affichee
919
+ * la veille est un defaut que personne ne voit depuis l'Europe.
920
+ */
921
+ estDateDeCalendrier = computed(() => {
922
+ const valeur = this.valeur();
923
+ return typeof valeur === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(valeur);
924
+ }, /* @ts-ignore */
925
+ ...(ngDevMode ? [{ debugName: "estDateDeCalendrier" }] : /* istanbul ignore next */ []));
746
926
  date = computed(() => {
747
927
  const valeur = this.valeur();
748
928
  return valeur instanceof Date ? valeur : new Date(valeur);
@@ -750,14 +930,44 @@ class StDate {
750
930
  ...(ngDevMode ? [{ debugName: "date" }] : /* istanbul ignore next */ []));
751
931
  estValide = computed(() => !Number.isNaN(this.date().getTime()), /* @ts-ignore */
752
932
  ...(ngDevMode ? [{ debugName: "estValide" }] : /* istanbul ignore next */ []));
753
- iso = computed(() => (this.estValide() ? this.date().toISOString() : null), /* @ts-ignore */
933
+ /**
934
+ * Le fuseau de rendu. Pour une date de calendrier, c'est UTC : la valeur a
935
+ * ete construite a minuit UTC, la relire en UTC rend donc le jour ecrit.
936
+ */
937
+ fuseauDeRendu = computed(() => this.estDateDeCalendrier() ? 'UTC' : (this.fuseau() ?? this.fuseauParDefaut), /* @ts-ignore */
938
+ ...(ngDevMode ? [{ debugName: "fuseauDeRendu" }] : /* istanbul ignore next */ []));
939
+ /**
940
+ * Une date de calendrier porte `2026-09-12`, sans heure ni decalage : c'est
941
+ * la forme que la norme HTML attend, et la seule qui ne mente pas.
942
+ */
943
+ iso = computed(() => {
944
+ if (!this.estValide())
945
+ return null;
946
+ if (this.estDateDeCalendrier())
947
+ return this.date().toISOString().slice(0, 10);
948
+ return this.date().toISOString();
949
+ }, /* @ts-ignore */
754
950
  ...(ngDevMode ? [{ debugName: "iso" }] : /* istanbul ignore next */ []));
951
+ /** Une date sans heure ne peut pas en afficher une. */
952
+ optionsDeFormat = computed(() => {
953
+ const options = OPTIONS[this.format()];
954
+ if (!this.estDateDeCalendrier())
955
+ return options;
956
+ // Le format « heure » n'a aucun sens ici : il ne resterait rien a afficher.
957
+ if (this.format() === 'heure')
958
+ return OPTIONS.court;
959
+ const sansHeure = { ...options };
960
+ delete sansHeure.hour;
961
+ delete sansHeure.minute;
962
+ return sansHeure;
963
+ }, /* @ts-ignore */
964
+ ...(ngDevMode ? [{ debugName: "optionsDeFormat" }] : /* istanbul ignore next */ []));
755
965
  texte = computed(() => {
756
966
  if (!this.estValide())
757
967
  return '';
758
- return new Intl.DateTimeFormat(this.locale, {
759
- ...OPTIONS[this.format()],
760
- timeZone: this.fuseau() ?? this.fuseauParDefaut,
968
+ return new Intl.DateTimeFormat(this.locale(), {
969
+ ...this.optionsDeFormat(),
970
+ timeZone: this.fuseauDeRendu(),
761
971
  }).format(this.date());
762
972
  }, /* @ts-ignore */
763
973
  ...(ngDevMode ? [{ debugName: "texte" }] : /* istanbul ignore next */ []));
@@ -766,20 +976,20 @@ class StDate {
766
976
  if (!this.estValide())
767
977
  return '';
768
978
  if (this.format() === 'court') {
769
- return new Intl.DateTimeFormat(this.locale, {
979
+ return new Intl.DateTimeFormat(this.locale(), {
770
980
  ...OPTIONS.long,
771
- timeZone: this.fuseau() ?? this.fuseauParDefaut,
981
+ timeZone: this.fuseauDeRendu(),
772
982
  }).format(this.date());
773
983
  }
774
984
  return null;
775
985
  }, /* @ts-ignore */
776
986
  ...(ngDevMode ? [{ debugName: "texteAccessible" }] : /* istanbul ignore next */ []));
777
987
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StDate, deps: [], target: i0.ɵɵFactoryTarget.Component });
778
- 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()\" [attr.aria-label]=\"texteAccessible()\">{{ texte() }}</time>\n}\n", styles: [":host{font-variant-numeric:tabular-nums;color:var(--st-couleur-texte);white-space:nowrap}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
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 });
779
989
  }
780
990
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StDate, decorators: [{
781
991
  type: Component,
782
- args: [{ selector: 'st-date', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'st-date' }, template: "@if (estValide()) {\n <time [attr.datetime]=\"iso()\" [attr.aria-label]=\"texteAccessible()\">{{ texte() }}</time>\n}\n", styles: [":host{font-variant-numeric:tabular-nums;color:var(--st-couleur-texte);white-space:nowrap}\n"] }]
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"] }]
783
993
  }], 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 }] }] } });
784
994
 
785
995
  const MINUTE = 60_000;
@@ -796,12 +1006,12 @@ const JOUR = 24 * HEURE;
796
1006
  * vieille de trois jours reveille l'onglet pour rien.
797
1007
  */
798
1008
  class StRelativeTime {
799
- locale = inject(LOCALE_ID);
1009
+ locale = inject(ST_LOCALE);
1010
+ libelles = inject(ST_LIBELLES);
800
1011
  fuseau = inject(FUSEAU_PAR_DEFAUT);
801
1012
  valeur = input.required(/* @ts-ignore */
802
1013
  ...(ngDevMode ? [{ debugName: "valeur" }] : /* istanbul ignore next */ []));
803
- rafraichir = input(true, /* @ts-ignore */
804
- ...(ngDevMode ? [{ debugName: "rafraichir" }] : /* istanbul ignore next */ []));
1014
+ rafraichir = input(true, { ...(ngDevMode ? { debugName: "rafraichir" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
805
1015
  /** Au-dela de ce nombre de jours, la date absolue est plus parlante. */
806
1016
  seuilAbsoluEnJours = input(7, /* @ts-ignore */
807
1017
  ...(ngDevMode ? [{ debugName: "seuilAbsoluEnJours" }] : /* istanbul ignore next */ []));
@@ -849,7 +1059,7 @@ class StRelativeTime {
849
1059
  return '';
850
1060
  const cible = this.dateEnMillisecondes();
851
1061
  if (this.depasseLeSeuil()) {
852
- return new Intl.DateTimeFormat(this.locale, {
1062
+ return new Intl.DateTimeFormat(this.locale(), {
853
1063
  day: 'numeric',
854
1064
  month: 'long',
855
1065
  year: 'numeric',
@@ -860,8 +1070,8 @@ class StRelativeTime {
860
1070
  const absolu = Math.abs(ecart);
861
1071
  // Sous dix secondes, « il y a 0 seconde » est plus deroutant qu'utile.
862
1072
  if (absolu < 10_000)
863
- return "a l'instant";
864
- const format = new Intl.RelativeTimeFormat(this.locale, { numeric: 'auto' });
1073
+ return this.libelles().aLInstant;
1074
+ const format = new Intl.RelativeTimeFormat(this.locale(), { numeric: 'auto' });
865
1075
  if (absolu < MINUTE)
866
1076
  return format.format(Math.round(ecart / 1000), 'second');
867
1077
  if (absolu < HEURE)
@@ -874,7 +1084,7 @@ class StRelativeTime {
874
1084
  texteAccessible = computed(() => {
875
1085
  if (!this.estValide())
876
1086
  return '';
877
- return new Intl.DateTimeFormat(this.locale, {
1087
+ return new Intl.DateTimeFormat(this.locale(), {
878
1088
  day: 'numeric',
879
1089
  month: 'long',
880
1090
  year: 'numeric',
@@ -885,11 +1095,11 @@ class StRelativeTime {
885
1095
  }, /* @ts-ignore */
886
1096
  ...(ngDevMode ? [{ debugName: "texteAccessible" }] : /* istanbul ignore next */ []));
887
1097
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StRelativeTime, deps: [], target: i0.ɵɵFactoryTarget.Component });
888
- 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()\" [attr.aria-label]=\"texteAccessible()\">{{ texte() }}</time>\n}\n", styles: [":host{font-size:var(--st-taille-sm);color:var(--st-couleur-texte-discret)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
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 });
889
1099
  }
890
1100
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StRelativeTime, decorators: [{
891
1101
  type: Component,
892
- args: [{ selector: 'st-relative-time', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'st-relative-time' }, template: "@if (estValide()) {\n <time [attr.datetime]=\"iso()\" [attr.aria-label]=\"texteAccessible()\">{{ texte() }}</time>\n}\n", styles: [":host{font-size:var(--st-taille-sm);color:var(--st-couleur-texte-discret)}\n"] }]
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"] }]
893
1103
  }], 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 }] }] } });
894
1104
 
895
1105
  /**
@@ -902,10 +1112,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
902
1112
  * d'information pour qui ecoute la page.
903
1113
  */
904
1114
  class StCount {
905
- locale = inject(LOCALE_ID);
1115
+ locale = inject(ST_LOCALE);
906
1116
  valeur = input.required(/* @ts-ignore */
907
1117
  ...(ngDevMode ? [{ debugName: "valeur" }] : /* istanbul ignore next */ []));
908
- ton = input('courant', /* @ts-ignore */
1118
+ ton = input('neutre', /* @ts-ignore */
909
1119
  ...(ngDevMode ? [{ debugName: "ton" }] : /* istanbul ignore next */ []));
910
1120
  /** `null` : jamais d'abreviation. */
911
1121
  abregerAuDela = input(1000, /* @ts-ignore */
@@ -915,27 +1125,26 @@ class StCount {
915
1125
  return seuil !== null && Math.abs(this.valeur()) >= seuil;
916
1126
  }, /* @ts-ignore */
917
1127
  ...(ngDevMode ? [{ debugName: "estAbrege" }] : /* istanbul ignore next */ []));
918
- texteComplet = computed(() => new Intl.NumberFormat(this.locale).format(this.valeur()), /* @ts-ignore */
1128
+ texteComplet = computed(() => new Intl.NumberFormat(this.locale()).format(this.valeur()), /* @ts-ignore */
919
1129
  ...(ngDevMode ? [{ debugName: "texteComplet" }] : /* istanbul ignore next */ []));
920
1130
  texte = computed(() => {
921
1131
  if (!this.estAbrege())
922
1132
  return this.texteComplet();
923
- return new Intl.NumberFormat(this.locale, {
1133
+ return new Intl.NumberFormat(this.locale(), {
924
1134
  notation: 'compact',
925
1135
  maximumFractionDigits: 1,
926
1136
  }).format(this.valeur());
927
1137
  }, /* @ts-ignore */
928
1138
  ...(ngDevMode ? [{ debugName: "texte" }] : /* istanbul ignore next */ []));
929
1139
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StCount, deps: [], target: i0.ɵɵFactoryTarget.Component });
930
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.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()", "attr.aria-label": "estAbrege() ? texteComplet() : null" }, classAttribute: "st-count" }, 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-ton=discret]){color:var(--st-couleur-texte-discret)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
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 });
931
1141
  }
932
1142
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StCount, decorators: [{
933
1143
  type: Component,
934
1144
  args: [{ selector: 'st-count', changeDetection: ChangeDetectionStrategy.OnPush, host: {
935
1145
  class: 'st-count',
936
1146
  '[attr.data-ton]': 'ton()',
937
- '[attr.aria-label]': 'estAbrege() ? texteComplet() : null',
938
- }, 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-ton=discret]){color:var(--st-couleur-texte-discret)}\n"] }]
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"] }]
939
1148
  }], 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 }] }] } });
940
1149
 
941
1150
  /**
@@ -962,7 +1171,7 @@ class StStatusPill {
962
1171
  ton = input('neutre', /* @ts-ignore */
963
1172
  ...(ngDevMode ? [{ debugName: "ton" }] : /* istanbul ignore next */ []));
964
1173
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StStatusPill, deps: [], target: i0.ɵɵFactoryTarget.Component });
965
- 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=info]){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 });
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 });
966
1175
  }
967
1176
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StStatusPill, decorators: [{
968
1177
  type: Component,
@@ -970,7 +1179,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
970
1179
  class: 'st-status-pill',
971
1180
  '[attr.data-ton]': 'ton()',
972
1181
  '[attr.data-statut]': 'statut()',
973
- }, 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=info]){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"] }]
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"] }]
974
1183
  }], 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 }] }] } });
975
1184
 
976
1185
  /**
@@ -990,8 +1199,7 @@ class StBadge {
990
1199
  ton = input('danger', /* @ts-ignore */
991
1200
  ...(ngDevMode ? [{ debugName: "ton" }] : /* istanbul ignore next */ []));
992
1201
  /** Point seul, sans chiffre : signale une nouveaute sans la quantifier. */
993
- point = input(false, /* @ts-ignore */
994
- ...(ngDevMode ? [{ debugName: "point" }] : /* istanbul ignore next */ []));
1202
+ point = input(false, { ...(ngDevMode ? { debugName: "point" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
995
1203
  texte = computed(() => {
996
1204
  if (this.point())
997
1205
  return '';
@@ -1026,16 +1234,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
1026
1234
  */
1027
1235
  class StTag {
1028
1236
  element = inject(ElementRef);
1237
+ libelles = inject(ST_LIBELLES);
1029
1238
  libelle = input.required(/* @ts-ignore */
1030
1239
  ...(ngDevMode ? [{ debugName: "libelle" }] : /* istanbul ignore next */ []));
1031
- supprimable = input(false, /* @ts-ignore */
1032
- ...(ngDevMode ? [{ debugName: "supprimable" }] : /* istanbul ignore next */ []));
1240
+ supprimable = input(false, { ...(ngDevMode ? { debugName: "supprimable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1033
1241
  ton = input('neutre', /* @ts-ignore */
1034
1242
  ...(ngDevMode ? [{ debugName: "ton" }] : /* istanbul ignore next */ []));
1035
- prefixeDeSuppression = input('Retirer', /* @ts-ignore */
1243
+ /** `null` : le texte vient du dictionnaire de l'application. */
1244
+ prefixeDeSuppression = input(null, /* @ts-ignore */
1036
1245
  ...(ngDevMode ? [{ debugName: "prefixeDeSuppression" }] : /* istanbul ignore next */ []));
1037
1246
  supprime = output();
1038
- libelleDeSuppression = computed(() => `${this.prefixeDeSuppression()} ${this.libelle()}`, /* @ts-ignore */
1247
+ libelleDeSuppression = computed(() => `${this.prefixeDeSuppression() ?? this.libelles().retirer} ${this.libelle()}`, /* @ts-ignore */
1039
1248
  ...(ngDevMode ? [{ debugName: "libelleDeSuppression" }] : /* istanbul ignore next */ []));
1040
1249
  auRetrait() {
1041
1250
  this.deplacerLeFocus();
@@ -1062,7 +1271,7 @@ class StTag {
1062
1271
  parent.focus();
1063
1272
  }
1064
1273
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StTag, deps: [], target: i0.ɵɵFactoryTarget.Component });
1065
- 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"], outputs: ["enfonceChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
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 });
1066
1275
  }
1067
1276
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StTag, decorators: [{
1068
1277
  type: Component,
@@ -1104,8 +1313,7 @@ class StAvatar {
1104
1313
  * `true` quand le nom figure deja a cote de l'avatar, ce qui est le cas
1105
1314
  * courant : l'avatar devient alors decoratif et se tait.
1106
1315
  */
1107
- nomAdjacent = input(true, /* @ts-ignore */
1108
- ...(ngDevMode ? [{ debugName: "nomAdjacent" }] : /* istanbul ignore next */ []));
1316
+ nomAdjacent = input(true, { ...(ngDevMode ? { debugName: "nomAdjacent" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1109
1317
  imageEchouee = signal(false, /* @ts-ignore */
1110
1318
  ...(ngDevMode ? [{ debugName: "imageEchouee" }] : /* istanbul ignore next */ []));
1111
1319
  afficheLImage = computed(() => this.sourceImage() !== null && !this.imageEchouee(), /* @ts-ignore */
@@ -1179,6 +1387,7 @@ const ICONE = {
1179
1387
  */
1180
1388
  class StError {
1181
1389
  regionParente = inject(REGION_VIVANTE_PARENTE, { optional: true });
1390
+ libelles = inject(ST_LIBELLES);
1182
1391
  variante = input('serveur', /* @ts-ignore */
1183
1392
  ...(ngDevMode ? [{ debugName: "variante" }] : /* istanbul ignore next */ []));
1184
1393
  /** Code machine stable, tel que rendu par le backend. */
@@ -1192,21 +1401,26 @@ class StError {
1192
1401
  ...(ngDevMode ? [{ debugName: "traceId" }] : /* istanbul ignore next */ []));
1193
1402
  niveauDuTitre = input(3, /* @ts-ignore */
1194
1403
  ...(ngDevMode ? [{ debugName: "niveauDuTitre" }] : /* istanbul ignore next */ []));
1195
- rejouable = input(true, /* @ts-ignore */
1196
- ...(ngDevMode ? [{ debugName: "rejouable" }] : /* istanbul ignore next */ []));
1197
- libelleRejeu = input('Reessayer', /* @ts-ignore */
1404
+ rejouable = input(true, { ...(ngDevMode ? { debugName: "rejouable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1405
+ rejeuEnCours = input(false, { ...(ngDevMode ? { debugName: "rejeuEnCours" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1406
+ /** `null` : les textes viennent du dictionnaire de l'application. */
1407
+ libelleRejeu = input(null, /* @ts-ignore */
1198
1408
  ...(ngDevMode ? [{ debugName: "libelleRejeu" }] : /* istanbul ignore next */ []));
1199
- rejeuEnCours = input(false, /* @ts-ignore */
1200
- ...(ngDevMode ? [{ debugName: "rejeuEnCours" }] : /* istanbul ignore next */ []));
1201
- etiquetteDeTrace = input('Identifiant de trace', /* @ts-ignore */
1409
+ etiquetteDeTrace = input(null, /* @ts-ignore */
1202
1410
  ...(ngDevMode ? [{ debugName: "etiquetteDeTrace" }] : /* istanbul ignore next */ []));
1203
1411
  rejeu = output();
1412
+ libelleRejeuLu = computed(() => this.libelleRejeu() ?? this.libelles().reessayer, /* @ts-ignore */
1413
+ ...(ngDevMode ? [{ debugName: "libelleRejeuLu" }] : /* istanbul ignore next */ []));
1414
+ etiquetteDeTraceLue = computed(() => this.etiquetteDeTrace() ?? this.libelles().identifiantDeTrace, /* @ts-ignore */
1415
+ ...(ngDevMode ? [{ debugName: "etiquetteDeTraceLue" }] : /* istanbul ignore next */ []));
1416
+ etiquetteDuCode = computed(() => this.libelles().codeTechnique, /* @ts-ignore */
1417
+ ...(ngDevMode ? [{ debugName: "etiquetteDuCode" }] : /* istanbul ignore next */ []));
1204
1418
  icone = computed(() => ICONE[this.variante()], /* @ts-ignore */
1205
1419
  ...(ngDevMode ? [{ debugName: "icone" }] : /* istanbul ignore next */ []));
1206
1420
  sAnnonce = computed(() => this.regionParente === null, /* @ts-ignore */
1207
1421
  ...(ngDevMode ? [{ debugName: "sAnnonce" }] : /* istanbul ignore next */ []));
1208
1422
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StError, deps: [], target: i0.ɵɵFactoryTarget.Component });
1209
- 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 }, libelleRejeu: { classPropertyName: "libelleRejeu", publicName: "libelleRejeu", isSignal: true, isRequired: false, transformFunction: null }, rejeuEnCours: { classPropertyName: "rejeuEnCours", publicName: "rejeuEnCours", 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=\"Code\" [copiable]=\"false\" />\n @if (traceId(); as trace) {\n <st-code [valeur]=\"trace\" [etiquette]=\"etiquetteDeTrace()\" />\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 {{ libelleRejeu() }}\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", "etiquette", "copiable", "libelleCopier", "messageDeConfirmation"], outputs: ["copie"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
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 });
1210
1424
  }
1211
1425
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StError, decorators: [{
1212
1426
  type: Component,
@@ -1214,8 +1428,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
1214
1428
  class: 'st-error',
1215
1429
  '[attr.data-variante]': 'variante()',
1216
1430
  '[attr.role]': 'sAnnonce() ? "alert" : null',
1217
- }, 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=\"Code\" [copiable]=\"false\" />\n @if (traceId(); as trace) {\n <st-code [valeur]=\"trace\" [etiquette]=\"etiquetteDeTrace()\" />\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 {{ libelleRejeu() }}\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"] }]
1218
- }], 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 }] }], libelleRejeu: [{ type: i0.Input, args: [{ isSignal: true, alias: "libelleRejeu", required: false }] }], rejeuEnCours: [{ type: i0.Input, args: [{ isSignal: true, alias: "rejeuEnCours", required: false }] }], etiquetteDeTrace: [{ type: i0.Input, args: [{ isSignal: true, alias: "etiquetteDeTrace", required: false }] }], rejeu: [{ type: i0.Output, args: ["rejeu"] }] } });
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"] }]
1432
+ }], 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"] }] } });
1219
1433
 
1220
1434
  /**
1221
1435
  * Banniere de perte de connexion.
@@ -1234,8 +1448,7 @@ class StOfflineBanner {
1234
1448
  ...(ngDevMode ? [{ debugName: "message" }] : /* istanbul ignore next */ []));
1235
1449
  libelleRejeu = input(null, /* @ts-ignore */
1236
1450
  ...(ngDevMode ? [{ debugName: "libelleRejeu" }] : /* istanbul ignore next */ []));
1237
- rejeuEnCours = input(false, /* @ts-ignore */
1238
- ...(ngDevMode ? [{ debugName: "rejeuEnCours" }] : /* istanbul ignore next */ []));
1451
+ rejeuEnCours = input(false, { ...(ngDevMode ? { debugName: "rejeuEnCours" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1239
1452
  rejeu = output();
1240
1453
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StOfflineBanner, deps: [], target: i0.ɵɵFactoryTarget.Component });
1241
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 });
@@ -1248,50 +1461,252 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
1248
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"] }]
1249
1462
  }], 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"] }] } });
1250
1463
 
1251
- const ANNONCES_PAR_DEFAUT = {
1252
- chargement: 'Chargement en cours',
1253
- erreur: 'Une erreur est survenue',
1254
- vide: 'Aucun resultat',
1255
- 'hors-ligne': 'Hors connexion',
1256
- succes: '',
1257
- };
1464
+ /**
1465
+ * Les gabarits des cinq etats, declares DANS `<st-state>`.
1466
+ *
1467
+ * ⚠️ Pourquoi des directives de contenu plutot que des entrees `TemplateRef` :
1468
+ * un `<ng-template>` declare a l'exterieur du composant appartient a
1469
+ * l'injecteur de l'endroit ou il est ECRIT, pas de celui qui le rend. Les
1470
+ * fournisseurs de `st-state` — dont `REGION_VIVANTE_PARENTE`, qui fait taire
1471
+ * les annonces en double — ne l'atteignaient donc pas, et l'erreur etait
1472
+ * annoncee deux fois. Passer par le contenu rend la declaration a l'exterieur
1473
+ * impossible : le defaut ne peut plus revenir.
1474
+ */
1475
+ class StSucces {
1476
+ gabarit = inject(TemplateRef);
1477
+ /**
1478
+ * La ressource n'est lue nulle part : elle porte le TYPE de la valeur, pour
1479
+ * que `let-valeur` soit type dans le gabarit au lieu d'etre `unknown`.
1480
+ */
1481
+ stSucces = input(undefined, /* @ts-ignore */
1482
+ ...(ngDevMode ? [{ debugName: "stSucces" }] : /* istanbul ignore next */ []));
1483
+ /**
1484
+ * `Exclude<T, undefined>` : une ressource sans valeur initiale se type
1485
+ * `T | undefined`, mais st-state ne rend ce gabarit QUE lorsqu'une valeur
1486
+ * existe. Sans cela, chaque gabarit de succes devrait ecrire `page?.length`
1487
+ * pour un cas qui ne se produit pas.
1488
+ */
1489
+ static ngTemplateContextGuard(_directive, _contexte) {
1490
+ return true;
1491
+ }
1492
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StSucces, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1493
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.6", type: StSucces, isStandalone: true, selector: "ng-template[stSucces]", inputs: { stSucces: { classPropertyName: "stSucces", publicName: "stSucces", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
1494
+ }
1495
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StSucces, decorators: [{
1496
+ type: Directive,
1497
+ args: [{ selector: 'ng-template[stSucces]' }]
1498
+ }], propDecorators: { stSucces: [{ type: i0.Input, args: [{ isSignal: true, alias: "stSucces", required: false }] }] } });
1499
+ /** Erreur. Le contexte porte l'erreur elle-meme, pour l'afficher ou la traduire. */
1500
+ class StErreur {
1501
+ gabarit = inject(TemplateRef);
1502
+ static ngTemplateContextGuard(_directive, _contexte) {
1503
+ return true;
1504
+ }
1505
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StErreur, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1506
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.6", type: StErreur, isStandalone: true, selector: "ng-template[stErreur]", ngImport: i0 });
1507
+ }
1508
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StErreur, decorators: [{
1509
+ type: Directive,
1510
+ args: [{ selector: 'ng-template[stErreur]' }]
1511
+ }] });
1512
+ class StVide {
1513
+ gabarit = inject(TemplateRef);
1514
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StVide, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1515
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.6", type: StVide, isStandalone: true, selector: "ng-template[stVide]", ngImport: i0 });
1516
+ }
1517
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StVide, decorators: [{
1518
+ type: Directive,
1519
+ args: [{ selector: 'ng-template[stVide]' }]
1520
+ }] });
1521
+ class StHorsLigne {
1522
+ gabarit = inject(TemplateRef);
1523
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StHorsLigne, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1524
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.6", type: StHorsLigne, isStandalone: true, selector: "ng-template[stHorsLigne]", ngImport: i0 });
1525
+ }
1526
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StHorsLigne, decorators: [{
1527
+ type: Directive,
1528
+ args: [{ selector: 'ng-template[stHorsLigne]' }]
1529
+ }] });
1530
+ /** Chargement sur mesure. Sans lui, `st-state` rend sa silhouette par defaut. */
1531
+ class StChargement {
1532
+ gabarit = inject(TemplateRef);
1533
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StChargement, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1534
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.6", type: StChargement, isStandalone: true, selector: "ng-template[stChargement]", ngImport: i0 });
1535
+ }
1536
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StChargement, decorators: [{
1537
+ type: Directive,
1538
+ args: [{ selector: 'ng-template[stChargement]' }]
1539
+ }] });
1540
+ /** Toutes les directives de gabarit, a importer d'un coup. */
1541
+ const GABARITS_D_ETAT = [StSucces, StErreur, StVide, StHorsLigne, StChargement];
1542
+
1543
+ /**
1544
+ * Delai avant d'afficher un chargement. En dessous, l'attente ne se voit pas,
1545
+ * et faire clignoter une silhouette coute plus en confort qu'elle ne rapporte
1546
+ * en information.
1547
+ */
1548
+ const DELAI_AVANT_AFFICHAGE_MS = 200;
1549
+ /**
1550
+ * Duree minimale d'affichage une fois la silhouette montree. Sans elle, une
1551
+ * reponse arrivant a 210 ms produit un eclair : apparition, disparition.
1552
+ */
1553
+ const DUREE_MINIMALE_MS = 400;
1554
+ /** Vrai pour une collection vide, une valeur absente, ou une page sans element. */
1555
+ function estVideParDefaut(valeur) {
1556
+ if (valeur === null || valeur === undefined)
1557
+ return true;
1558
+ if (Array.isArray(valeur))
1559
+ return valeur.length === 0;
1560
+ // Les pages du socle backend portent leurs elements dans `content`.
1561
+ if (typeof valeur === 'object' && 'content' in valeur) {
1562
+ const { content: contenu } = valeur;
1563
+ return Array.isArray(contenu) && contenu.length === 0;
1564
+ }
1565
+ return false;
1566
+ }
1258
1567
  /**
1259
1568
  * Impose les cinq etats a un bloc qui consomme l'API, et centralise leur
1260
1569
  * annonce.
1261
1570
  *
1571
+ * Deux usages. Le plus courant passe la ressource, et l'etat s'en deduit :
1572
+ *
1573
+ * ```html
1574
+ * <st-state [ressource]="operations">
1575
+ * <ng-template [stSucces]="operations" let-page>…</ng-template>
1576
+ * <ng-template stErreur let-erreur><st-error … /></ng-template>
1577
+ * <ng-template stVide><st-empty … /></ng-template>
1578
+ * </st-state>
1579
+ * ```
1580
+ *
1581
+ * L'autre pose `[etat]` a la main, pour un bloc qui ne vient pas d'une
1582
+ * ressource — une soumission de formulaire, par exemple.
1583
+ *
1584
+ * ⚠️ Un RECHARGEMENT garde le contenu affiche. Revenir a la silhouette a chaque
1585
+ * changement de filtre fait clignoter la page entiere et perd la position de
1586
+ * lecture ; seul le premier chargement n'a rien a montrer.
1587
+ *
1262
1588
  * ⚠️ L'hote ne porte PAS `role="status"`, contrairement a ce qu'on attendrait :
1263
1589
  * un remplacement de contenu A L'INTERIEUR d'une region vivante fait relire
1264
1590
  * tout le sous-arbre par le lecteur d'ecran a chaque bascule d'etat. Seule une
1265
- * petite zone masquee porte l'annonce, qui tient en quelques mots. L'hote se
1266
- * contente d'`aria-busy`.
1267
- *
1268
- * Il fournit `REGION_VIVANTE_PARENTE` : les composants qu'il rend (indicateur
1269
- * de chargement, erreur) detectent sa presence et se taisent, au lieu
1270
- * d'annoncer une deuxieme fois le meme fait.
1591
+ * petite zone masquee porte l'annonce, qui tient en quelques mots.
1271
1592
  */
1272
1593
  class StState {
1273
- etat = input.required(/* @ts-ignore */
1594
+ libelles = inject(ST_LIBELLES);
1595
+ /** La ressource dont l'etat se deduit. */
1596
+ ressource = input(null, /* @ts-ignore */
1597
+ ...(ngDevMode ? [{ debugName: "ressource" }] : /* istanbul ignore next */ []));
1598
+ /** Etat pose a la main. Il prime sur la ressource quand les deux existent. */
1599
+ etat = input(null, /* @ts-ignore */
1274
1600
  ...(ngDevMode ? [{ debugName: "etat" }] : /* istanbul ignore next */ []));
1275
- /** Le chemin nominal. Obligatoire : un bloc sans succes n'a pas de raison d'etre. */
1276
- succes = input.required(/* @ts-ignore */
1277
- ...(ngDevMode ? [{ debugName: "succes" }] : /* istanbul ignore next */ []));
1278
- chargement = input(null, /* @ts-ignore */
1279
- ...(ngDevMode ? [{ debugName: "chargement" }] : /* istanbul ignore next */ []));
1280
- erreur = input(null, /* @ts-ignore */
1281
- ...(ngDevMode ? [{ debugName: "erreur" }] : /* istanbul ignore next */ []));
1282
- vide = input(null, /* @ts-ignore */
1283
- ...(ngDevMode ? [{ debugName: "vide" }] : /* istanbul ignore next */ []));
1284
- horsLigne = input(null, /* @ts-ignore */
1285
- ...(ngDevMode ? [{ debugName: "horsLigne" }] : /* istanbul ignore next */ []));
1601
+ /** Ce qui compte comme « vide » : par defaut, une collection sans element. */
1602
+ estVide = input(estVideParDefaut, /* @ts-ignore */
1603
+ ...(ngDevMode ? [{ debugName: "estVide" }] : /* istanbul ignore next */ []));
1286
1604
  /** Silhouette par defaut du chargement. `null` : un indicateur tournant. */
1287
1605
  squelette = input('texte', /* @ts-ignore */
1288
1606
  ...(ngDevMode ? [{ debugName: "squelette" }] : /* istanbul ignore next */ []));
1289
1607
  lignesDeSquelette = input(3, /* @ts-ignore */
1290
1608
  ...(ngDevMode ? [{ debugName: "lignesDeSquelette" }] : /* istanbul ignore next */ []));
1291
- annonces = input(ANNONCES_PAR_DEFAUT, /* @ts-ignore */
1609
+ /** `null` : les annonces viennent du dictionnaire de l'application. */
1610
+ annonces = input(null, /* @ts-ignore */
1292
1611
  ...(ngDevMode ? [{ debugName: "annonces" }] : /* istanbul ignore next */ []));
1293
- annonce = computed(() => this.annonces()[this.etat()], /* @ts-ignore */
1612
+ gabaritSucces = contentChild(StSucces, /* @ts-ignore */
1613
+ ...(ngDevMode ? [{ debugName: "gabaritSucces" }] : /* istanbul ignore next */ []));
1614
+ gabaritErreur = contentChild(StErreur, /* @ts-ignore */
1615
+ ...(ngDevMode ? [{ debugName: "gabaritErreur" }] : /* istanbul ignore next */ []));
1616
+ gabaritVide = contentChild(StVide, /* @ts-ignore */
1617
+ ...(ngDevMode ? [{ debugName: "gabaritVide" }] : /* istanbul ignore next */ []));
1618
+ gabaritHorsLigne = contentChild(StHorsLigne, /* @ts-ignore */
1619
+ ...(ngDevMode ? [{ debugName: "gabaritHorsLigne" }] : /* istanbul ignore next */ []));
1620
+ gabaritChargement = contentChild(StChargement, /* @ts-ignore */
1621
+ ...(ngDevMode ? [{ debugName: "gabaritChargement" }] : /* istanbul ignore next */ []));
1622
+ instantane = computed(() => {
1623
+ const ressource = this.ressource();
1624
+ if (ressource === null)
1625
+ return { statut: 'idle', valeur: undefined };
1626
+ return {
1627
+ statut: ressource.status(),
1628
+ valeur: ressource.hasValue() ? ressource.value() : undefined,
1629
+ };
1630
+ }, /* @ts-ignore */
1631
+ ...(ngDevMode ? [{ debugName: "instantane" }] : /* istanbul ignore next */ []));
1632
+ /**
1633
+ * La derniere valeur connue, gardee pendant qu'une autre se charge.
1634
+ *
1635
+ * ⚠️ Necessaire, et pas seulement confortable : un changement de PARAMETRE
1636
+ * n'est pas un `reload`. Angular traite le premier comme une nouvelle
1637
+ * requete — statut « loading », valeur videe. Sans cette memoire, changer un
1638
+ * filtre ou tourner une page ferait donc disparaitre le tableau, clignoter la
1639
+ * page, et perdre la position de lecture. Une erreur, elle, ne garde rien :
1640
+ * afficher des donnees perimees sous un message d'erreur serait mentir.
1641
+ */
1642
+ valeurRetenue = linkedSignal({ ...(ngDevMode ? { debugName: "valeurRetenue" } : /* istanbul ignore next */ {}), source: () => this.instantane(),
1643
+ computation: (source, precedent) => {
1644
+ if (source.valeur !== undefined)
1645
+ return source.valeur;
1646
+ const enCoursDeChargement = source.statut === 'loading' || source.statut === 'reloading';
1647
+ return enCoursDeChargement ? precedent?.value : undefined;
1648
+ } });
1649
+ /** Etat deduit de la ressource, valeur retenue comprise. */
1650
+ etatDeLaRessource = computed(() => {
1651
+ if (this.ressource() === null)
1652
+ return null;
1653
+ const { statut } = this.instantane();
1654
+ if (statut === 'error') {
1655
+ // Une requete qui n'a jamais atteint le serveur rend le statut 0 : c'est
1656
+ // une perte de reseau, pas une panne serveur. Lu par forme plutot que par
1657
+ // type, pour ne pas lier les composants au client HTTP.
1658
+ const erreur = this.ressource()?.error();
1659
+ return erreur?.status === 0 ? 'hors-ligne' : 'erreur';
1660
+ }
1661
+ const valeur = this.valeurRetenue();
1662
+ if (valeur === undefined)
1663
+ return statut === 'idle' || statut === 'loading' ? 'chargement' : 'vide';
1664
+ return this.estVide()(valeur) ? 'vide' : 'succes';
1665
+ }, /* @ts-ignore */
1666
+ ...(ngDevMode ? [{ debugName: "etatDeLaRessource" }] : /* istanbul ignore next */ []));
1667
+ etatEffectif = computed(() => this.etat() ?? this.etatDeLaRessource() ?? 'chargement', /* @ts-ignore */
1668
+ ...(ngDevMode ? [{ debugName: "etatEffectif" }] : /* istanbul ignore next */ []));
1669
+ /**
1670
+ * Une valeur est affichee, et une autre arrive — par rappel explicite ou par
1671
+ * changement de parametre.
1672
+ */
1673
+ enRechargement = computed(() => {
1674
+ const { statut } = this.instantane();
1675
+ if (statut !== 'loading' && statut !== 'reloading')
1676
+ return false;
1677
+ return this.valeurRetenue() !== undefined;
1678
+ }, /* @ts-ignore */
1679
+ ...(ngDevMode ? [{ debugName: "enRechargement" }] : /* istanbul ignore next */ []));
1680
+ enAttente = computed(() => this.etatEffectif() === 'chargement' || this.enRechargement(), /* @ts-ignore */
1681
+ ...(ngDevMode ? [{ debugName: "enAttente" }] : /* istanbul ignore next */ []));
1682
+ annoncesLues = computed(() => {
1683
+ const fournies = this.annonces();
1684
+ if (fournies !== null)
1685
+ return fournies;
1686
+ const libelles = this.libelles();
1687
+ return {
1688
+ chargement: libelles.chargementEnCours,
1689
+ erreur: libelles.erreurSurvenue,
1690
+ vide: libelles.aucunResultat,
1691
+ 'hors-ligne': libelles.horsConnexion,
1692
+ // Le succes ne s'annonce pas : c'est le contenu lui-meme qui parle.
1693
+ succes: '',
1694
+ };
1695
+ }, /* @ts-ignore */
1696
+ ...(ngDevMode ? [{ debugName: "annoncesLues" }] : /* istanbul ignore next */ []));
1697
+ annonce = computed(() => this.annoncesLues()[this.etatEffectif()], /* @ts-ignore */
1294
1698
  ...(ngDevMode ? [{ debugName: "annonce" }] : /* istanbul ignore next */ []));
1699
+ /** Contexte passe au gabarit : la valeur en succes, l'erreur en erreur. */
1700
+ contexte = computed(() => {
1701
+ const ressource = this.ressource();
1702
+ if (ressource === null)
1703
+ return { $implicit: undefined };
1704
+ if (this.etatEffectif() === 'erreur' || this.etatEffectif() === 'hors-ligne') {
1705
+ return { $implicit: ressource.error() };
1706
+ }
1707
+ return { $implicit: this.valeurRetenue() };
1708
+ }, /* @ts-ignore */
1709
+ ...(ngDevMode ? [{ debugName: "contexte" }] : /* istanbul ignore next */ []));
1295
1710
  /**
1296
1711
  * Les etats degrades n'ont pas de rendu par defaut : afficher un texte
1297
1712
  * generique a la place d'un vrai ecran vide ou d'une vraie erreur donnerait
@@ -1299,43 +1714,83 @@ class StState {
1299
1714
  * voie, en developpement.
1300
1715
  */
1301
1716
  gabaritDeLEtat = computed(() => {
1302
- switch (this.etat()) {
1717
+ switch (this.etatEffectif()) {
1303
1718
  case 'erreur':
1304
- return this.signalerSiAbsent(this.erreur(), 'erreur');
1719
+ return this.signalerSiAbsent(this.gabaritErreur()?.gabarit, 'erreur');
1305
1720
  case 'vide':
1306
- return this.signalerSiAbsent(this.vide(), 'vide');
1721
+ return this.signalerSiAbsent(this.gabaritVide()?.gabarit, 'vide');
1307
1722
  case 'hors-ligne':
1308
- return this.signalerSiAbsent(this.horsLigne() ?? this.erreur(), 'hors-ligne');
1723
+ return this.signalerSiAbsent(this.gabaritHorsLigne()?.gabarit ?? this.gabaritErreur()?.gabarit, 'hors-ligne');
1309
1724
  case 'chargement':
1310
- return this.chargement();
1725
+ return this.gabaritChargement()?.gabarit ?? null;
1311
1726
  default:
1312
- return this.succes();
1727
+ return this.signalerSiAbsent(this.gabaritSucces()?.gabarit, 'succes');
1313
1728
  }
1314
1729
  }, /* @ts-ignore */
1315
1730
  ...(ngDevMode ? [{ debugName: "gabaritDeLEtat" }] : /* istanbul ignore next */ []));
1316
- montreLaSilhouetteParDefaut = computed(() => this.etat() === 'chargement' && this.chargement() === null, /* @ts-ignore */
1731
+ chargementVisible = signal(false, /* @ts-ignore */
1732
+ ...(ngDevMode ? [{ debugName: "chargementVisible" }] : /* istanbul ignore next */ []));
1733
+ /** La silhouette par defaut, une fois le delai anti-clignotement passe. */
1734
+ montreLaSilhouetteParDefaut = computed(() => this.etatEffectif() === 'chargement' &&
1735
+ this.gabaritChargement() === undefined &&
1736
+ this.chargementVisible(), /* @ts-ignore */
1317
1737
  ...(ngDevMode ? [{ debugName: "montreLaSilhouetteParDefaut" }] : /* istanbul ignore next */ []));
1738
+ constructor() {
1739
+ let minuterie = null;
1740
+ let afficheDepuis = 0;
1741
+ const arreter = () => {
1742
+ if (minuterie !== null)
1743
+ clearTimeout(minuterie);
1744
+ minuterie = null;
1745
+ };
1746
+ effect(() => {
1747
+ const charge = this.etatEffectif() === 'chargement';
1748
+ arreter();
1749
+ if (charge) {
1750
+ if (this.chargementVisible())
1751
+ return;
1752
+ minuterie = setTimeout(() => {
1753
+ afficheDepuis = Date.now();
1754
+ this.chargementVisible.set(true);
1755
+ }, DELAI_AVANT_AFFICHAGE_MS);
1756
+ return;
1757
+ }
1758
+ if (!this.chargementVisible())
1759
+ return;
1760
+ // Deja affichee : elle reste le temps minimal, sinon elle clignote.
1761
+ const reste = DUREE_MINIMALE_MS - (Date.now() - afficheDepuis);
1762
+ if (reste <= 0) {
1763
+ this.chargementVisible.set(false);
1764
+ return;
1765
+ }
1766
+ minuterie = setTimeout(() => {
1767
+ this.chargementVisible.set(false);
1768
+ }, reste);
1769
+ });
1770
+ inject(DestroyRef).onDestroy(arreter);
1771
+ }
1318
1772
  signalerSiAbsent(gabarit, nom) {
1319
- if (gabarit === null && isDevMode()) {
1773
+ if (gabarit === undefined && isDevMode()) {
1320
1774
  // Volontairement un avertissement et non une exception : casser l'ecran
1321
1775
  // entier pour un etat degrade non traite aggraverait la panne en
1322
1776
  // production. En developpement, le message est impossible a manquer.
1323
1777
  console.warn(`[st-state] Etat « ${nom} » atteint sans gabarit. Les cinq etats doivent etre traites : ` +
1324
- 'fournir [erreur], [vide] et [horsLigne].');
1778
+ 'declarer <ng-template stErreur>, <ng-template stVide> et <ng-template stHorsLigne>.');
1325
1779
  }
1326
- return gabarit;
1780
+ return gabarit ?? null;
1327
1781
  }
1328
1782
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StState, deps: [], target: i0.ɵɵFactoryTarget.Component });
1329
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StState, isStandalone: true, selector: "st-state", inputs: { etat: { classPropertyName: "etat", publicName: "etat", isSignal: true, isRequired: true, transformFunction: null }, succes: { classPropertyName: "succes", publicName: "succes", isSignal: true, isRequired: true, transformFunction: null }, chargement: { classPropertyName: "chargement", publicName: "chargement", isSignal: true, isRequired: false, transformFunction: null }, erreur: { classPropertyName: "erreur", publicName: "erreur", isSignal: true, isRequired: false, transformFunction: null }, vide: { classPropertyName: "vide", publicName: "vide", isSignal: true, isRequired: false, transformFunction: null }, horsLigne: { classPropertyName: "horsLigne", publicName: "horsLigne", 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": "etat()", "attr.aria-busy": "etat() === \"chargement\" ? \"true\" : null" }, classAttribute: "st-state" }, providers: [{ provide: REGION_VIVANTE_PARENTE, useValue: 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\" />\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 });
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 });
1330
1784
  }
1331
1785
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StState, decorators: [{
1332
1786
  type: Component,
1333
1787
  args: [{ selector: 'st-state', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgTemplateOutlet, StSkeleton, StSpinner], providers: [{ provide: REGION_VIVANTE_PARENTE, useValue: true }], host: {
1334
1788
  class: 'st-state',
1335
- '[attr.data-etat]': 'etat()',
1336
- '[attr.aria-busy]': 'etat() === "chargement" ? "true" : null',
1337
- }, 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\" />\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"] }]
1338
- }], propDecorators: { etat: [{ type: i0.Input, args: [{ isSignal: true, alias: "etat", required: true }] }], succes: [{ type: i0.Input, args: [{ isSignal: true, alias: "succes", required: true }] }], chargement: [{ type: i0.Input, args: [{ isSignal: true, alias: "chargement", required: false }] }], erreur: [{ type: i0.Input, args: [{ isSignal: true, alias: "erreur", required: false }] }], vide: [{ type: i0.Input, args: [{ isSignal: true, alias: "vide", required: false }] }], horsLigne: [{ type: i0.Input, args: [{ isSignal: true, alias: "horsLigne", 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 }] }] } });
1789
+ '[attr.data-etat]': 'etatEffectif()',
1790
+ '[attr.data-rechargement]': 'enRechargement() ? "" : null',
1791
+ '[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"] }]
1793
+ }], 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 }] }] } });
1339
1794
 
1340
1795
  /**
1341
1796
  * @starterlib/ui — bibliotheque de composants du socle frontal.
@@ -1349,5 +1804,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
1349
1804
  * Generated bundle index. Do not edit.
1350
1805
  */
1351
1806
 
1352
- export { CHEMIN_DU_SPRITE, ETATS_DE_BLOC, FUSEAU_PAR_DEFAUT, NOMS_DICONE, REGION_VIVANTE_PARENTE, StAvatar, StBadge, StButton, StButtonGroup, StCode, StCount, StDate, StEmpty, StError, StHeading, StIcon, StIconButton, StLink, StMasked, StMoney, StOfflineBanner, StProgress, StRelativeTime, StSkeleton, StSpinner, StState, StStatusPill, StTag, StText };
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 };
1353
1808
  //# sourceMappingURL=starterlib-ui.mjs.map