@starterlib/ui 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,9 @@
1
1
  import * as _angular_core from '@angular/core';
2
2
  import { InjectionToken, Signal, Provider, DestroyRef, Resource, TemplateRef } from '@angular/core';
3
- import { Ton, Montant, TonSemantique, ChoixDeTheme, Langue, EtatDeBloc } from '@starterlib/util';
3
+ import { Ton, Montant, TonSemantique, DateIso, PlageDeDates, DescriptionDeFichier, ChoixDeTheme, Langue, EtatDeBloc } from '@starterlib/util';
4
4
  export { ETATS_DE_BLOC, EtatDeBloc } from '@starterlib/util';
5
+ import { ValidationError, FormValueControl, FormCheckboxControl } from '@angular/forms/signals';
6
+ import * as _starterlib_ui from '@starterlib/ui';
5
7
 
6
8
  /**
7
9
  * Les textes que les composants portent eux-memes.
@@ -59,7 +61,63 @@ interface LibellesUi {
59
61
  readonly sessionExpireDans: (duree: string) => string;
60
62
  readonly resterConnecte: string;
61
63
  readonly seDeconnecter: string;
64
+ /** Saisie */
65
+ readonly obligatoire: string;
66
+ readonly champObligatoire: string;
67
+ readonly valeurInvalide: string;
68
+ readonly adresseInvalide: string;
69
+ readonly formatInvalide: string;
70
+ readonly longueurMinimale: (minimum: number) => string;
71
+ readonly longueurMaximale: (maximum: number) => string;
72
+ readonly valeurMinimale: (minimum: string) => string;
73
+ readonly valeurMaximale: (maximum: string) => string;
74
+ readonly caracteresRestants: (restants: number) => string;
75
+ readonly caracteresEnTrop: (enTrop: number) => string;
76
+ readonly erreursACorriger: (nombre: number) => string;
77
+ readonly afficherLeMotDePasse: string;
78
+ readonly codeAChiffres: (longueur: number) => string;
79
+ readonly ibanInvalide: string;
80
+ readonly telephoneInvalide: string;
81
+ readonly exempleDIban: string;
82
+ readonly rechercher: string;
62
83
  readonly fermerLeMessage: string;
84
+ /** Montants */
85
+ readonly montantIllisible: (exemple: string) => string;
86
+ readonly tropDeDecimales: (decimales: number) => string;
87
+ readonly deviseDuMontant: (devise: string) => string;
88
+ /** Dates */
89
+ readonly lettreDuJour: string;
90
+ readonly lettreDuMois: string;
91
+ readonly lettreDeLAnnee: string;
92
+ readonly formatDeDate: (motif: string, exemple: string) => string;
93
+ readonly dateIllisible: (motif: string, exemple: string) => string;
94
+ readonly dateTropTot: (date: string) => string;
95
+ readonly dateTropTard: (date: string) => string;
96
+ readonly finAvantDebut: string;
97
+ readonly dateDeDebut: string;
98
+ readonly dateDeFin: string;
99
+ readonly choisirDansLeCalendrier: (champ: string) => string;
100
+ readonly moisPrecedent: string;
101
+ readonly moisSuivant: string;
102
+ readonly aideDuCalendrier: string;
103
+ /** Listes de choix */
104
+ readonly choisir: string;
105
+ readonly nombreDeResultats: (nombre: number) => string;
106
+ readonly nombreDeSelections: (nombre: number) => string;
107
+ readonly retirerLeChoix: (choix: string) => string;
108
+ readonly afficherLesChoix: (champ: string) => string;
109
+ /** Fichiers */
110
+ readonly choisirDesFichiers: string;
111
+ readonly choisirUnFichier: string;
112
+ readonly ouDeposerIci: string;
113
+ readonly aucunFichier: string;
114
+ readonly nombreDeFichiers: (nombre: number) => string;
115
+ readonly retirerLeFichier: (fichier: string) => string;
116
+ readonly fichierTropVolumineux: (fichier: string, taille: string) => string;
117
+ readonly typeDeFichierRefuse: (fichier: string) => string;
118
+ readonly tropDeFichiers: (nombre: number) => string;
119
+ readonly typesAcceptes: (types: string) => string;
120
+ readonly tailleMaximale: (taille: string) => string;
63
121
  /** Dialogues */
64
122
  readonly confirmer: string;
65
123
  readonly annuler: string;
@@ -243,7 +301,7 @@ type TonDIcone = Exclude<Ton, 'inverse'>;
243
301
  */
244
302
  declare class StIcon {
245
303
  private readonly cheminDuSprite;
246
- readonly nom: _angular_core.InputSignal<"copie" | "boite-vide" | "cercle" | "cercle-coche" | "cercle-croix" | "cercle-info" | "chevron-bas" | "chevron-droite" | "chevron-gauche" | "chevron-haut" | "coche" | "corbeille" | "croix" | "hors-ligne" | "lien-externe" | "menu" | "oeil" | "oeil-barre" | "plus" | "rafraichir" | "recherche" | "serveur" | "triangle-alerte" | "utilisateur">;
304
+ readonly nom: _angular_core.InputSignal<"copie" | "boite-vide" | "calendrier" | "cercle" | "cercle-coche" | "cercle-croix" | "cercle-info" | "chevron-bas" | "chevron-droite" | "chevron-gauche" | "chevron-haut" | "coche" | "corbeille" | "croix" | "fichier" | "hors-ligne" | "lien-externe" | "menu" | "oeil" | "oeil-barre" | "plus" | "rafraichir" | "recherche" | "serveur" | "televerser" | "triangle-alerte" | "utilisateur">;
247
305
  readonly taille: _angular_core.InputSignal<TailleDIcone>;
248
306
  readonly ton: _angular_core.InputSignal<TonDIcone>;
249
307
  /** `null` : l'icone est decorative et reste muette pour les lecteurs. */
@@ -262,7 +320,7 @@ declare class StIcon {
262
320
  * reference `use` vers un identifiant absent ne rend RIEN, sans erreur, et le
263
321
  * defaut passe la revue.
264
322
  */
265
- declare const NOMS_DICONE: readonly ["boite-vide", "cercle", "cercle-coche", "cercle-croix", "cercle-info", "chevron-bas", "chevron-droite", "chevron-gauche", "chevron-haut", "coche", "copie", "corbeille", "croix", "hors-ligne", "lien-externe", "menu", "oeil", "oeil-barre", "plus", "rafraichir", "recherche", "serveur", "triangle-alerte", "utilisateur"];
323
+ declare const NOMS_DICONE: readonly ["boite-vide", "calendrier", "cercle", "cercle-coche", "cercle-croix", "cercle-info", "chevron-bas", "chevron-droite", "chevron-gauche", "chevron-haut", "coche", "copie", "corbeille", "croix", "fichier", "hors-ligne", "lien-externe", "menu", "oeil", "oeil-barre", "plus", "rafraichir", "recherche", "serveur", "televerser", "triangle-alerte", "utilisateur"];
266
324
  type NomDIcone = (typeof NOMS_DICONE)[number];
267
325
 
268
326
  type VarianteDeTexte = 'corps' | 'corps-sm' | 'discret' | 'legende' | 'mono';
@@ -419,8 +477,8 @@ declare class StButton {
419
477
  readonly variante: _angular_core.InputSignal<VarianteDeBouton>;
420
478
  readonly taille: _angular_core.InputSignal<TailleDeBouton>;
421
479
  readonly pleineLargeur: _angular_core.InputSignalWithTransform<boolean, unknown>;
422
- readonly iconeAvant: _angular_core.InputSignal<"copie" | "boite-vide" | "cercle" | "cercle-coche" | "cercle-croix" | "cercle-info" | "chevron-bas" | "chevron-droite" | "chevron-gauche" | "chevron-haut" | "coche" | "corbeille" | "croix" | "hors-ligne" | "lien-externe" | "menu" | "oeil" | "oeil-barre" | "plus" | "rafraichir" | "recherche" | "serveur" | "triangle-alerte" | "utilisateur" | null>;
423
- readonly iconeApres: _angular_core.InputSignal<"copie" | "boite-vide" | "cercle" | "cercle-coche" | "cercle-croix" | "cercle-info" | "chevron-bas" | "chevron-droite" | "chevron-gauche" | "chevron-haut" | "coche" | "corbeille" | "croix" | "hors-ligne" | "lien-externe" | "menu" | "oeil" | "oeil-barre" | "plus" | "rafraichir" | "recherche" | "serveur" | "triangle-alerte" | "utilisateur" | null>;
480
+ readonly iconeAvant: _angular_core.InputSignal<"copie" | "boite-vide" | "calendrier" | "cercle" | "cercle-coche" | "cercle-croix" | "cercle-info" | "chevron-bas" | "chevron-droite" | "chevron-gauche" | "chevron-haut" | "coche" | "corbeille" | "croix" | "fichier" | "hors-ligne" | "lien-externe" | "menu" | "oeil" | "oeil-barre" | "plus" | "rafraichir" | "recherche" | "serveur" | "televerser" | "triangle-alerte" | "utilisateur" | null>;
481
+ readonly iconeApres: _angular_core.InputSignal<"copie" | "boite-vide" | "calendrier" | "cercle" | "cercle-coche" | "cercle-croix" | "cercle-info" | "chevron-bas" | "chevron-droite" | "chevron-gauche" | "chevron-haut" | "coche" | "corbeille" | "croix" | "fichier" | "hors-ligne" | "lien-externe" | "menu" | "oeil" | "oeil-barre" | "plus" | "rafraichir" | "recherche" | "serveur" | "televerser" | "triangle-alerte" | "utilisateur" | null>;
424
482
  /**
425
483
  * Action en cours. Tant qu'il vaut vrai, les clics sont avales : c'est le
426
484
  * mecanisme d'anti double soumission. L'appelant doit le lever DES la
@@ -458,7 +516,7 @@ type VarianteDeBoutonIcone = Extract<VarianteDeBouton, 'discret' | 'secondaire'
458
516
  * de facon fiable.
459
517
  */
460
518
  declare class StIconButton {
461
- readonly icone: _angular_core.InputSignal<"copie" | "boite-vide" | "cercle" | "cercle-coche" | "cercle-croix" | "cercle-info" | "chevron-bas" | "chevron-droite" | "chevron-gauche" | "chevron-haut" | "coche" | "corbeille" | "croix" | "hors-ligne" | "lien-externe" | "menu" | "oeil" | "oeil-barre" | "plus" | "rafraichir" | "recherche" | "serveur" | "triangle-alerte" | "utilisateur">;
519
+ readonly icone: _angular_core.InputSignal<"copie" | "boite-vide" | "calendrier" | "cercle" | "cercle-coche" | "cercle-croix" | "cercle-info" | "chevron-bas" | "chevron-droite" | "chevron-gauche" | "chevron-haut" | "coche" | "corbeille" | "croix" | "fichier" | "hors-ligne" | "lien-externe" | "menu" | "oeil" | "oeil-barre" | "plus" | "rafraichir" | "recherche" | "serveur" | "televerser" | "triangle-alerte" | "utilisateur">;
462
520
  /** Nom accessible du controle. Sans lui, l'icone ne dit rien. */
463
521
  readonly etiquette: _angular_core.InputSignal<string>;
464
522
  readonly variante: _angular_core.InputSignal<VarianteDeBoutonIcone>;
@@ -750,7 +808,7 @@ declare class StStatusPill {
750
808
  readonly statut: _angular_core.InputSignal<string>;
751
809
  /** Texte deja traduit par l'appelant : le socle ne traduit rien. */
752
810
  readonly libelle: _angular_core.InputSignal<string>;
753
- readonly icone: _angular_core.InputSignal<"copie" | "boite-vide" | "cercle" | "cercle-coche" | "cercle-croix" | "cercle-info" | "chevron-bas" | "chevron-droite" | "chevron-gauche" | "chevron-haut" | "coche" | "corbeille" | "croix" | "hors-ligne" | "lien-externe" | "menu" | "oeil" | "oeil-barre" | "plus" | "rafraichir" | "recherche" | "serveur" | "triangle-alerte" | "utilisateur">;
811
+ readonly icone: _angular_core.InputSignal<"copie" | "boite-vide" | "calendrier" | "cercle" | "cercle-coche" | "cercle-croix" | "cercle-info" | "chevron-bas" | "chevron-droite" | "chevron-gauche" | "chevron-haut" | "coche" | "corbeille" | "croix" | "fichier" | "hors-ligne" | "lien-externe" | "menu" | "oeil" | "oeil-barre" | "plus" | "rafraichir" | "recherche" | "serveur" | "televerser" | "triangle-alerte" | "utilisateur">;
754
812
  readonly ton: _angular_core.InputSignal<TonSemantique>;
755
813
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<StStatusPill, never>;
756
814
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<StStatusPill, "st-status-pill", never, { "statut": { "alias": "statut"; "required": true; "isSignal": true; }; "libelle": { "alias": "libelle"; "required": true; "isSignal": true; }; "icone": { "alias": "icone"; "required": true; "isSignal": true; }; "ton": { "alias": "ton"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
@@ -843,7 +901,7 @@ declare class StAvatar {
843
901
  declare class StEmpty {
844
902
  readonly titre: _angular_core.InputSignal<string>;
845
903
  readonly description: _angular_core.InputSignal<string | null>;
846
- readonly icone: _angular_core.InputSignal<"copie" | "boite-vide" | "cercle" | "cercle-coche" | "cercle-croix" | "cercle-info" | "chevron-bas" | "chevron-droite" | "chevron-gauche" | "chevron-haut" | "coche" | "corbeille" | "croix" | "hors-ligne" | "lien-externe" | "menu" | "oeil" | "oeil-barre" | "plus" | "rafraichir" | "recherche" | "serveur" | "triangle-alerte" | "utilisateur">;
904
+ readonly icone: _angular_core.InputSignal<"copie" | "boite-vide" | "calendrier" | "cercle" | "cercle-coche" | "cercle-croix" | "cercle-info" | "chevron-bas" | "chevron-droite" | "chevron-gauche" | "chevron-haut" | "coche" | "corbeille" | "croix" | "fichier" | "hors-ligne" | "lien-externe" | "menu" | "oeil" | "oeil-barre" | "plus" | "rafraichir" | "recherche" | "serveur" | "televerser" | "triangle-alerte" | "utilisateur">;
847
905
  readonly niveauDuTitre: _angular_core.InputSignal<NiveauDeTitre>;
848
906
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<StEmpty, never>;
849
907
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<StEmpty, "st-empty", never, { "titre": { "alias": "titre"; "required": true; "isSignal": true; }; "description": { "alias": "description"; "required": false; "isSignal": true; }; "icone": { "alias": "icone"; "required": false; "isSignal": true; }; "niveauDuTitre": { "alias": "niveauDuTitre"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
@@ -881,7 +939,7 @@ declare class StError {
881
939
  protected readonly libelleRejeuLu: _angular_core.Signal<string>;
882
940
  protected readonly etiquetteDeTraceLue: _angular_core.Signal<string>;
883
941
  protected readonly etiquetteDuCode: _angular_core.Signal<string>;
884
- protected readonly icone: _angular_core.Signal<"copie" | "boite-vide" | "cercle" | "cercle-coche" | "cercle-croix" | "cercle-info" | "chevron-bas" | "chevron-droite" | "chevron-gauche" | "chevron-haut" | "coche" | "corbeille" | "croix" | "hors-ligne" | "lien-externe" | "menu" | "oeil" | "oeil-barre" | "plus" | "rafraichir" | "recherche" | "serveur" | "triangle-alerte" | "utilisateur">;
942
+ protected readonly icone: _angular_core.Signal<"copie" | "boite-vide" | "calendrier" | "cercle" | "cercle-coche" | "cercle-croix" | "cercle-info" | "chevron-bas" | "chevron-droite" | "chevron-gauche" | "chevron-haut" | "coche" | "corbeille" | "croix" | "fichier" | "hors-ligne" | "lien-externe" | "menu" | "oeil" | "oeil-barre" | "plus" | "rafraichir" | "recherche" | "serveur" | "televerser" | "triangle-alerte" | "utilisateur">;
885
943
  protected readonly sAnnonce: _angular_core.Signal<boolean>;
886
944
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<StError, never>;
887
945
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<StError, "st-error", never, { "variante": { "alias": "variante"; "required": false; "isSignal": true; }; "code": { "alias": "code"; "required": true; "isSignal": true; }; "titre": { "alias": "titre"; "required": true; "isSignal": true; }; "message": { "alias": "message"; "required": true; "isSignal": true; }; "traceId": { "alias": "traceId"; "required": false; "isSignal": true; }; "niveauDuTitre": { "alias": "niveauDuTitre"; "required": false; "isSignal": true; }; "rejouable": { "alias": "rejouable"; "required": false; "isSignal": true; }; "rejeuEnCours": { "alias": "rejeuEnCours"; "required": false; "isSignal": true; }; "libelleRejeu": { "alias": "libelleRejeu"; "required": false; "isSignal": true; }; "etiquetteDeTrace": { "alias": "etiquetteDeTrace"; "required": false; "isSignal": true; }; }, { "rejeu": "rejeu"; }, never, never, true, never>;
@@ -1209,7 +1267,7 @@ declare class StBanner {
1209
1267
  /** `null` : le texte vient du dictionnaire de l'application. */
1210
1268
  readonly libelleFermeture: _angular_core.InputSignal<string | null>;
1211
1269
  readonly ferme: _angular_core.OutputEmitterRef<void>;
1212
- protected readonly icone: _angular_core.Signal<"copie" | "boite-vide" | "cercle" | "cercle-coche" | "cercle-croix" | "cercle-info" | "chevron-bas" | "chevron-droite" | "chevron-gauche" | "chevron-haut" | "coche" | "corbeille" | "croix" | "hors-ligne" | "lien-externe" | "menu" | "oeil" | "oeil-barre" | "plus" | "rafraichir" | "recherche" | "serveur" | "triangle-alerte" | "utilisateur">;
1270
+ protected readonly icone: _angular_core.Signal<"copie" | "boite-vide" | "calendrier" | "cercle" | "cercle-coche" | "cercle-croix" | "cercle-info" | "chevron-bas" | "chevron-droite" | "chevron-gauche" | "chevron-haut" | "coche" | "corbeille" | "croix" | "fichier" | "hors-ligne" | "lien-externe" | "menu" | "oeil" | "oeil-barre" | "plus" | "rafraichir" | "recherche" | "serveur" | "televerser" | "triangle-alerte" | "utilisateur">;
1213
1271
  protected readonly libelleFermetureLu: _angular_core.Signal<string>;
1214
1272
  protected readonly roleLu: _angular_core.Signal<"status" | "alert" | null>;
1215
1273
  /**
@@ -1255,11 +1313,898 @@ declare class StInlineMessage {
1255
1313
  readonly ton: _angular_core.InputSignal<TonSemantique>;
1256
1314
  /** Cible d'un `aria-describedby` pose par le champ decrit. */
1257
1315
  readonly identifiant: _angular_core.InputSignal<string | null>;
1258
- protected readonly icone: _angular_core.Signal<"copie" | "boite-vide" | "cercle" | "cercle-coche" | "cercle-croix" | "cercle-info" | "chevron-bas" | "chevron-droite" | "chevron-gauche" | "chevron-haut" | "coche" | "corbeille" | "croix" | "hors-ligne" | "lien-externe" | "menu" | "oeil" | "oeil-barre" | "plus" | "rafraichir" | "recherche" | "serveur" | "triangle-alerte" | "utilisateur">;
1316
+ protected readonly icone: _angular_core.Signal<"copie" | "boite-vide" | "calendrier" | "cercle" | "cercle-coche" | "cercle-croix" | "cercle-info" | "chevron-bas" | "chevron-droite" | "chevron-gauche" | "chevron-haut" | "coche" | "corbeille" | "croix" | "fichier" | "hors-ligne" | "lien-externe" | "menu" | "oeil" | "oeil-barre" | "plus" | "rafraichir" | "recherche" | "serveur" | "televerser" | "triangle-alerte" | "utilisateur">;
1259
1317
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<StInlineMessage, never>;
1260
1318
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<StInlineMessage, "st-inline-message", never, { "ton": { "alias": "ton"; "required": false; "isSignal": true; }; "identifiant": { "alias": "identifiant"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
1261
1319
  }
1262
1320
 
1321
+ /**
1322
+ * Forme minimale d'une erreur de validation, telle que Signal Forms la rend :
1323
+ * un genre, et parfois un message.
1324
+ *
1325
+ * Structurelle, pour ne pas importer `@angular/forms` a l'execution (audit de la
1326
+ * vague 3, V3-1). Les proprietes propres a chaque genre — `minLength`, `max`… —
1327
+ * se lisent par leur nom.
1328
+ */
1329
+ interface ErreurAffichable {
1330
+ readonly kind: string;
1331
+ readonly message?: string;
1332
+ }
1333
+ /**
1334
+ * Le texte d'une erreur, dans la langue courante.
1335
+ *
1336
+ * ⚠️ **Un `message` fourni l'emporte toujours.** Un validateur metier, ou une
1337
+ * erreur du serveur deja traduite, en sait plus que le genre : « IBAN d'un pays
1338
+ * non pris en charge » vaut mieux que « Le format n'est pas valide ».
1339
+ *
1340
+ * ⚠️ **Un genre inconnu rend un message generique, jamais le genre brut.**
1341
+ * Afficher `ibanChecksum` a une personne qui saisit un IBAN, c'est lui montrer le
1342
+ * code source.
1343
+ *
1344
+ * La locale sert aux messages qui citent un format, une date ou une taille : « au
1345
+ * format jj/mm/aaaa » n'est pas « mm/dd/yyyy ».
1346
+ */
1347
+ declare function messageDErreur(erreur: ErreurAffichable, libelles: LibellesUi, locale?: string): string;
1348
+ /** Le motif a taper dans la langue courante : `jj/mm/aaaa`. */
1349
+ declare function motifLocal(libelles: LibellesUi, locale: string): string;
1350
+ /**
1351
+ * Un jour superieur a 12 : « 31/03/2026 » montre sans ambiguite ou va le jour,
1352
+ * ce que « 01/02/2026 » ne dit pas.
1353
+ */
1354
+ declare function exempleDeDate(locale: string): string;
1355
+ /**
1356
+ * Erreur d'IBAN, a brancher sur un schema :
1357
+ *
1358
+ * ```ts
1359
+ * validate(chemin.iban, ({ value }) => erreurIban(value()));
1360
+ * ```
1361
+ *
1362
+ * Une fonction pure plutot qu'une regle toute faite : fournir la regle
1363
+ * importerait `validate` d'`@angular/forms` A L'EXECUTION, et le socle ne
1364
+ * l'importe que pour ses types (audit de la vague 3, V3-1).
1365
+ *
1366
+ * ⚠️ Confort de saisie, jamais controle (SEC-5) : le serveur revalide. Un champ
1367
+ * vide n'est pas « invalide » ici — c'est `required` qui le dit, avec le bon
1368
+ * message.
1369
+ */
1370
+ declare function erreurIban(valeur: string): ErreurAffichable | null;
1371
+ /**
1372
+ * Erreur de FORME d'un numero de telephone : chiffres, `+` de tete facultatif,
1373
+ * de 4 a 15 chiffres — la longueur maximale d'un numero international (E.164).
1374
+ *
1375
+ * ```ts
1376
+ * validate(chemin.telephone, ({ value }) => erreurTelephone(value()));
1377
+ * ```
1378
+ *
1379
+ * ⚠️ Une forme valide ne dit pas que le numero existe : seul le serveur le sait.
1380
+ * Un champ vide n'est pas une erreur de forme : l'obligation est une autre regle.
1381
+ */
1382
+ declare function erreurTelephone(valeur: string): ErreurAffichable | null;
1383
+ /** Bornes d'une date, en ISO. Absente : pas de borne. */
1384
+ interface BornesDeDate {
1385
+ readonly min?: DateIso | null;
1386
+ readonly max?: DateIso | null;
1387
+ }
1388
+ /**
1389
+ * Erreur de bornes d'une date, a brancher sur un schema :
1390
+ *
1391
+ * ```ts
1392
+ * validate(chemin.naissance, ({ value }) => erreurDate(value(), { max: aujourdHui }));
1393
+ * ```
1394
+ *
1395
+ * Les bornes du schema et celles passees au calendrier doivent etre les memes :
1396
+ * le calendrier grise, le schema refuse une date tapee a la main.
1397
+ */
1398
+ declare function erreurDate(valeur: DateIso | null, bornes: BornesDeDate): ErreurAffichable | null;
1399
+ /** Une fin anterieure au debut. Une borne manquante n'est pas une erreur de plage. */
1400
+ declare function erreurPlageDeDates(plage: PlageDeDates): ErreurAffichable | null;
1401
+ /** Regles de `st-file-upload`, les memes que ses entrees. */
1402
+ interface ReglesDeFichiers {
1403
+ /** Attribut `accept` : `.pdf, image/*`. */
1404
+ readonly accept?: string;
1405
+ /** En octets. */
1406
+ readonly tailleMax?: number;
1407
+ readonly nombreMax?: number;
1408
+ }
1409
+ /**
1410
+ * Erreurs d'une liste de fichiers, une par fichier refuse, pour dire LEQUEL :
1411
+ *
1412
+ * ```ts
1413
+ * validate(chemin.pieces, ({ value }) => erreursDeFichiers(value(), regles));
1414
+ * ```
1415
+ *
1416
+ * ⚠️ Confort, jamais securite (SEC-5) : le type se deduit de l'extension, et le
1417
+ * serveur relit le contenu.
1418
+ */
1419
+ declare function erreursDeFichiers(fichiers: readonly DescriptionDeFichier[], regles: ReglesDeFichiers): ErreurAffichable[];
1420
+ /**
1421
+ * Erreurs a afficher par un champ qui LIT sa saisie (`transformedValue`) : celles
1422
+ * du formulaire, plus les erreurs de lecture qu'il ne connait pas encore.
1423
+ *
1424
+ * ⚠️ Relie a un formulaire, un champ recoit ses erreurs de lecture DANS `errors`,
1425
+ * par Signal Forms. Employe seul, par `[(value)]`, il ne les recoit nulle part :
1426
+ * sans cette fusion, « 12,5,3 » s'afficherait sans le moindre message. Une erreur
1427
+ * deja presente — meme genre, meme partie — n'est pas repetee.
1428
+ */
1429
+ declare function fusionnerErreurs(formulaire: readonly ValidationError.WithOptionalFieldTree[], lecture: readonly ValidationError.WithoutFieldTree[]): readonly ErreurAffichable[];
1430
+
1431
+ /** Elements natifs qui portent la saisie d'un champ du socle. */
1432
+ type ElementDeSaisie = HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement;
1433
+ /**
1434
+ * Base des champs du socle : le contrat Signal Forms, ecrit une fois — tout sauf
1435
+ * `value`, dont le type depend du champ (texte, montant, date).
1436
+ *
1437
+ * ⚠️ **Une base, et non une copie par champ.** Neuf membres de contrat recopies
1438
+ * dans six composants, c'est six occasions d'en oublier un — et l'oubli ne se
1439
+ * voit pas : un champ sans `touched` n'affiche jamais ses erreurs, un champ sans
1440
+ * reflet de `hidden` ne se masque pas, et rien n'echoue.
1441
+ *
1442
+ * Les noms restent anglais : voir le glossaire, § 8.
1443
+ *
1444
+ * Le gabarit du champ doit nommer son element natif `#champ`, et le brancher sur
1445
+ * `touch` a la perte du focus.
1446
+ */
1447
+ declare abstract class ContratDeChamp {
1448
+ readonly libelle: _angular_core.InputSignal<string>;
1449
+ readonly aide: _angular_core.InputSignal<string | null>;
1450
+ readonly errors: _angular_core.InputSignal<readonly ValidationError.WithOptionalFieldTree[]>;
1451
+ readonly touched: _angular_core.InputSignalWithTransform<boolean, unknown>;
1452
+ readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
1453
+ readonly readonly: _angular_core.InputSignalWithTransform<boolean, unknown>;
1454
+ readonly required: _angular_core.InputSignalWithTransform<boolean, unknown>;
1455
+ readonly hidden: _angular_core.InputSignalWithTransform<boolean, unknown>;
1456
+ readonly name: _angular_core.InputSignal<string>;
1457
+ readonly touch: _angular_core.OutputEmitterRef<void>;
1458
+ private readonly champ;
1459
+ /** Appele par Signal Forms pour amener le focus sur un champ en erreur. */
1460
+ focus(options?: FocusOptions): void;
1461
+ protected texteSaisi(evenement: Event): string;
1462
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ContratDeChamp, never>;
1463
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<ContratDeChamp, never, never, { "libelle": { "alias": "libelle"; "required": true; "isSignal": true; }; "aide": { "alias": "aide"; "required": false; "isSignal": true; }; "errors": { "alias": "errors"; "required": false; "isSignal": true; }; "touched": { "alias": "touched"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "hidden": { "alias": "hidden"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; }, { "touch": "touch"; }, never, never, true, never>;
1464
+ }
1465
+ /** Base des champs dont la valeur est le texte saisi. */
1466
+ declare abstract class ControleDeSaisie extends ContratDeChamp implements FormValueControl<string> {
1467
+ readonly value: _angular_core.ModelSignal<string>;
1468
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ControleDeSaisie, never>;
1469
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<ControleDeSaisie, never, never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, never>;
1470
+ }
1471
+
1472
+ /**
1473
+ * `empilee` : etiquette au-dessus du controle, pour un champ texte.
1474
+ * `case` : controle AVANT son etiquette, pour une case a cocher ou un interrupteur.
1475
+ */
1476
+ type DispositionDeChamp = 'empilee' | 'case';
1477
+ /**
1478
+ * Etiquette, aide, erreur et controle d'un champ de saisie — et le cablage qui
1479
+ * les relie.
1480
+ *
1481
+ * ⚠️ **Le SEUL endroit ou ce cablage existe** (audit de la vague 3, V3-2). Chaque
1482
+ * champ du socle l'emploie au lieu de refaire identifiants, `aria-describedby` et
1483
+ * `aria-invalid` : c'est precisement le code que l'on croit fini et qui se perd,
1484
+ * un champ specialise a la fois.
1485
+ *
1486
+ * L'ordre visuel suit celui de la lecture : etiquette, aide, erreur, controle.
1487
+ * L'erreur est AU-DESSUS du controle, pour etre vue avant de retaper.
1488
+ *
1489
+ * ⚠️ **L'erreur n'est pas une region vivante.** Annoncee a la perte du focus, elle
1490
+ * couperait la lecture du champ suivant, ou la personne est deja passee. Elle est
1491
+ * reliee au controle, donc lue quand on y revient ; a l'envoi, c'est le
1492
+ * recapitulatif d'erreurs qui prend le focus et les enumere.
1493
+ */
1494
+ declare class StFormField {
1495
+ private readonly libelles;
1496
+ private readonly locale;
1497
+ private readonly element;
1498
+ /**
1499
+ * ⚠️ OBLIGATOIRE et toujours visible (UX-1). Un texte indicatif ne le remplace
1500
+ * jamais : il disparait a la premiere frappe.
1501
+ */
1502
+ readonly libelle: _angular_core.InputSignal<string>;
1503
+ /** Aide permanente : format attendu, exemple. Lue apres l'etiquette. */
1504
+ readonly aide: _angular_core.InputSignal<string | null>;
1505
+ /** Texte complementaire tenu a jour par le controle, comme un compteur. */
1506
+ readonly complement: _angular_core.InputSignal<string | null>;
1507
+ readonly erreurs: _angular_core.InputSignal<readonly ErreurAffichable[]>;
1508
+ /**
1509
+ * ⚠️ Faux tant que la personne n'a pas quitte le champ ou tente l'envoi (UX-3) :
1510
+ * un formulaire vierge couvert d'erreurs accuse avant qu'on ait rien fait.
1511
+ */
1512
+ readonly afficherErreurs: _angular_core.InputSignalWithTransform<boolean, unknown>;
1513
+ readonly obligatoire: _angular_core.InputSignalWithTransform<boolean, unknown>;
1514
+ /**
1515
+ * ⚠️ Change l'ordre VISUEL, jamais celui du document : l'etiquette reste
1516
+ * reliee par `for`, et l'ordre de tabulation ne passe que par le controle.
1517
+ */
1518
+ readonly disposition: _angular_core.InputSignal<DispositionDeChamp>;
1519
+ /**
1520
+ * Etiquette lue mais non affichee.
1521
+ *
1522
+ * ⚠️ Reservee a la RECHERCHE, ou l'icone, le bouton et la position en tete de
1523
+ * page disent deja le but du champ. Partout ailleurs, une etiquette masquee est
1524
+ * l'etiquette qui manque au moment ou l'on tape (UX-1).
1525
+ */
1526
+ readonly libelleMasque: _angular_core.InputSignalWithTransform<boolean, unknown>;
1527
+ /** Identifiants du champ, lus par `stControleDeChamp` et par le gabarit. */
1528
+ readonly identifiants: {
1529
+ readonly controle: string;
1530
+ readonly libelle: `${string}-libelle`;
1531
+ readonly aide: `${string}-aide`;
1532
+ readonly complement: `${string}-complement`;
1533
+ readonly erreur: `${string}-erreur`;
1534
+ };
1535
+ protected readonly libelleObligatoire: _angular_core.Signal<string>;
1536
+ /** Messages a afficher, dans la langue courante. Vide tant qu'ils ne doivent pas l'etre. */
1537
+ protected readonly messages: _angular_core.Signal<string[]>;
1538
+ /**
1539
+ * Un clic sur l'etiquette d'un controle non natif n'y mene pas de lui-meme :
1540
+ * on y amene le focus, comme le navigateur le fait pour un champ natif.
1541
+ */
1542
+ protected focaliserLeControle(): void;
1543
+ /** Lu par le controle pour `aria-invalid`. */
1544
+ readonly enErreur: _angular_core.Signal<boolean>;
1545
+ /**
1546
+ * ⚠️ Seuls les elements PRESENTS sont references : un `aria-describedby` qui
1547
+ * vise un identifiant absent est ignore par certains lecteurs d'ecran — tout
1548
+ * entier, y compris les references valides qui l'accompagnent.
1549
+ */
1550
+ readonly descriptions: _angular_core.Signal<string | null>;
1551
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<StFormField, never>;
1552
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<StFormField, "st-form-field", never, { "libelle": { "alias": "libelle"; "required": true; "isSignal": true; }; "aide": { "alias": "aide"; "required": false; "isSignal": true; }; "complement": { "alias": "complement"; "required": false; "isSignal": true; }; "erreurs": { "alias": "erreurs"; "required": false; "isSignal": true; }; "afficherErreurs": { "alias": "afficherErreurs"; "required": false; "isSignal": true; }; "obligatoire": { "alias": "obligatoire"; "required": false; "isSignal": true; }; "disposition": { "alias": "disposition"; "required": false; "isSignal": true; }; "libelleMasque": { "alias": "libelleMasque"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
1553
+ }
1554
+ /**
1555
+ * Pose sur l'element natif d'un champ le cablage de son `st-form-field` :
1556
+ * identifiant, description, invalidite, obligation.
1557
+ *
1558
+ * ⚠️ `aria-required` et NON l'attribut `required` natif. Le natif declenche la
1559
+ * validation du navigateur a l'envoi : une bulle « Veuillez renseigner ce champ »
1560
+ * dans la langue du NAVIGATEUR, pas dans celle de l'application, et qui double
1561
+ * le message du socle.
1562
+ */
1563
+ declare class StControleDeChamp {
1564
+ protected readonly champ: StFormField;
1565
+ /**
1566
+ * ⚠️ `label for` n'etiquette que les elements natifs de formulaire. Le
1567
+ * declencheur d'une selection multiple est un `div` de role `combobox` : sans
1568
+ * `aria-labelledby`, il n'aurait aucun nom, et l'etiquette visible ne dirait
1569
+ * rien au lecteur d'ecran.
1570
+ */
1571
+ protected readonly etiquetable: boolean;
1572
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<StControleDeChamp, never>;
1573
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<StControleDeChamp, "[stControleDeChamp]", never, {}, {}, never, never, true, never>;
1574
+ }
1575
+
1576
+ type TypeDeSaisie = 'text' | 'email' | 'tel' | 'url' | 'search';
1577
+ /**
1578
+ * Champ de saisie d'une ligne, integre a Signal Forms.
1579
+ *
1580
+ * ```html
1581
+ * <st-input libelle="Nom du beneficiaire" autocomplete="name" [formField]="virement.beneficiaire" />
1582
+ * <!-- ou, sans formulaire : -->
1583
+ * <st-input libelle="Reference" [(value)]="reference" />
1584
+ * ```
1585
+ *
1586
+ * ⚠️ **Contrat Signal Forms, noms anglais.** `value`, `errors`, `touched`,
1587
+ * `disabled`… sont cherches PAR LEUR NOM par la directive `[formField]` : les
1588
+ * traduire romprait l'integration sans la moindre erreur (audit de la vague 3,
1589
+ * V3-1). L'import d'`@angular/forms` est un import de TYPE : aucun code n'entre
1590
+ * dans le paquet.
1591
+ *
1592
+ * ⚠️ **Pas d'attribut `maxlength` natif.** Il TRONQUE en silence un texte colle
1593
+ * trop long : la personne croit avoir saisi sa reference entiere, et n'en envoie
1594
+ * que le debut. La limite passe par la validation, qui DIT le depassement.
1595
+ */
1596
+ declare class StInput extends ControleDeSaisie {
1597
+ readonly type: _angular_core.InputSignal<TypeDeSaisie>;
1598
+ /**
1599
+ * WCAG 1.3.5 : identifie le but du champ, pour le remplissage automatique et les
1600
+ * aides techniques. `null` : laisse le navigateur decider.
1601
+ */
1602
+ readonly autocomplete: _angular_core.InputSignal<string | null>;
1603
+ /** Clavier virtuel adapte : `numeric`, `decimal`, `email`… */
1604
+ readonly inputmode: _angular_core.InputSignal<string | null>;
1605
+ protected surSaisie(evenement: Event): void;
1606
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<StInput, never>;
1607
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<StInput, "st-input", never, { "type": { "alias": "type"; "required": false; "isSignal": true; }; "autocomplete": { "alias": "autocomplete"; "required": false; "isSignal": true; }; "inputmode": { "alias": "inputmode"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1608
+ }
1609
+
1610
+ /**
1611
+ * Zone de texte, integree a Signal Forms, avec compteur quand une longueur
1612
+ * maximale est fixee.
1613
+ *
1614
+ * ⚠️ **Le compteur n'est pas annonce a chaque frappe** : une region vivante qui
1615
+ * change a chaque caractere recouvre ce que la personne tape. Il est RELIE a la
1616
+ * zone — donc lu quand on y revient — et seuls les seuils (20, 10, 0 restants)
1617
+ * et le depassement s'annoncent (UX-11).
1618
+ *
1619
+ * ⚠️ **Pas de `maxlength` natif**, meme raison que `st-input` : un texte colle
1620
+ * serait tronque en silence. Le compteur affiche le depassement, la validation
1621
+ * le refuse.
1622
+ */
1623
+ declare class StTextarea extends ControleDeSaisie {
1624
+ private readonly libelles;
1625
+ readonly lignes: _angular_core.InputSignal<number>;
1626
+ /** Contrat Signal Forms : la longueur maximale fixee par le schema. */
1627
+ readonly maxLength: _angular_core.InputSignal<number | undefined>;
1628
+ protected readonly annonce: AnnonceLocale;
1629
+ private readonly restants;
1630
+ protected readonly compteur: _angular_core.Signal<string | null>;
1631
+ constructor();
1632
+ protected surSaisie(evenement: Event): void;
1633
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<StTextarea, never>;
1634
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<StTextarea, "st-textarea", never, { "lignes": { "alias": "lignes"; "required": false; "isSignal": true; }; "maxLength": { "alias": "maxLength"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1635
+ }
1636
+
1637
+ /**
1638
+ * Groupe de controles, nomme par sa QUESTION.
1639
+ *
1640
+ * ⚠️ `fieldset` et `legend` natifs (UX-7). Sans legende, un lecteur d'ecran
1641
+ * annonce « Oui, bouton radio » et « Non, bouton radio » : la reponse, jamais la
1642
+ * question. La legende est lue a l'entree dans le groupe.
1643
+ *
1644
+ * C'est le pendant de `st-form-field` pour un GROUPE : l'aide et l'erreur sont
1645
+ * reliees au `fieldset` par `aria-describedby`, et l'erreur porte sur le groupe
1646
+ * entier — « Choisissez un mode de reglement » — et non sur chaque option.
1647
+ *
1648
+ * ⚠️ L'obligation se dit dans la legende, en texte : `aria-required` n'est pas
1649
+ * valide sur un groupe, et `required` natif ferait parler le navigateur dans sa
1650
+ * propre langue.
1651
+ */
1652
+ declare class StFieldset {
1653
+ private readonly libelles;
1654
+ private readonly locale;
1655
+ /** La question posee par le groupe. Obligatoire. */
1656
+ readonly legende: _angular_core.InputSignal<string>;
1657
+ readonly aide: _angular_core.InputSignal<string | null>;
1658
+ readonly erreurs: _angular_core.InputSignal<readonly ErreurAffichable[]>;
1659
+ readonly afficherErreurs: _angular_core.InputSignalWithTransform<boolean, unknown>;
1660
+ readonly obligatoire: _angular_core.InputSignalWithTransform<boolean, unknown>;
1661
+ private readonly base;
1662
+ protected readonly identifiantAide: string;
1663
+ protected readonly identifiantErreur: string;
1664
+ protected readonly libelleObligatoire: _angular_core.Signal<string>;
1665
+ protected readonly messages: _angular_core.Signal<string[]>;
1666
+ protected readonly enErreur: _angular_core.Signal<boolean>;
1667
+ protected readonly descriptions: _angular_core.Signal<string | null>;
1668
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<StFieldset, never>;
1669
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<StFieldset, "st-fieldset", never, { "legende": { "alias": "legende"; "required": true; "isSignal": true; }; "aide": { "alias": "aide"; "required": false; "isSignal": true; }; "erreurs": { "alias": "erreurs"; "required": false; "isSignal": true; }; "afficherErreurs": { "alias": "afficherErreurs"; "required": false; "isSignal": true; }; "obligatoire": { "alias": "obligatoire"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
1670
+ }
1671
+
1672
+ /**
1673
+ * Case a cocher, integree a Signal Forms.
1674
+ *
1675
+ * ```html
1676
+ * <st-checkbox libelle="J'accepte les conditions generales" [formField]="inscription.conditions" />
1677
+ * ```
1678
+ *
1679
+ * Un element `input type="checkbox"` natif : Espace coche, l'etat est annonce,
1680
+ * et la case suit le reglage de contraste du systeme sans rien ecrire.
1681
+ *
1682
+ * ⚠️ **Pour un choix a envoyer avec un formulaire.** Un reglage qui s'applique
1683
+ * IMMEDIATEMENT est un `st-switch` : la case promet un effet a l'envoi, et
1684
+ * l'interrupteur un effet tout de suite (UX-8).
1685
+ */
1686
+ declare class StCheckbox implements FormCheckboxControl {
1687
+ readonly libelle: _angular_core.InputSignal<string>;
1688
+ readonly aide: _angular_core.InputSignal<string | null>;
1689
+ /** Contrat Signal Forms. */
1690
+ readonly checked: _angular_core.ModelSignal<boolean>;
1691
+ readonly errors: _angular_core.InputSignal<readonly ValidationError.WithOptionalFieldTree[]>;
1692
+ readonly touched: _angular_core.InputSignalWithTransform<boolean, unknown>;
1693
+ readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
1694
+ readonly required: _angular_core.InputSignalWithTransform<boolean, unknown>;
1695
+ readonly hidden: _angular_core.InputSignalWithTransform<boolean, unknown>;
1696
+ readonly name: _angular_core.InputSignal<string>;
1697
+ readonly touch: _angular_core.OutputEmitterRef<void>;
1698
+ private readonly champ;
1699
+ focus(options?: FocusOptions): void;
1700
+ protected surChangement(evenement: Event): void;
1701
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<StCheckbox, never>;
1702
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<StCheckbox, "st-checkbox", never, { "libelle": { "alias": "libelle"; "required": true; "isSignal": true; }; "aide": { "alias": "aide"; "required": false; "isSignal": true; }; "checked": { "alias": "checked"; "required": false; "isSignal": true; }; "errors": { "alias": "errors"; "required": false; "isSignal": true; }; "touched": { "alias": "touched"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "hidden": { "alias": "hidden"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; }, { "checked": "checkedChange"; "touch": "touch"; }, never, never, true, never>;
1703
+ }
1704
+
1705
+ /** Une option du groupe. */
1706
+ interface OptionRadio {
1707
+ readonly valeur: string;
1708
+ readonly libelle: string;
1709
+ /** Precision sous le libelle, reliee a l'option. */
1710
+ readonly aide?: string;
1711
+ readonly desactivee?: boolean;
1712
+ }
1713
+ /**
1714
+ * Groupe de boutons radio, integre a Signal Forms.
1715
+ *
1716
+ * ```html
1717
+ * <st-radio-group legende="Mode de reglement" [options]="modes" [formField]="commande.mode" />
1718
+ * ```
1719
+ *
1720
+ * ⚠️ **De vrais boutons radio natifs** : un seul arret de tabulation pour le
1721
+ * groupe, deplacement aux fleches, « 2 sur 3 » annonce. Les recrire en ARIA,
1722
+ * c'est cent lignes pour obtenir moins bien — meme raison que `st-theme-toggle`.
1723
+ *
1724
+ * ⚠️ **L'erreur porte sur le groupe**, par `st-fieldset`, et non sur chaque option :
1725
+ * « Choisissez un mode de reglement », une fois.
1726
+ *
1727
+ * `touch` n'est emis que lorsque le focus QUITTE le groupe : passer d'une option a
1728
+ * l'autre aux fleches n'est pas une fin de saisie, et l'erreur n'a pas a surgir
1729
+ * pendant qu'on choisit.
1730
+ */
1731
+ declare class StRadioGroup implements FormValueControl<string> {
1732
+ private readonly element;
1733
+ readonly legende: _angular_core.InputSignal<string>;
1734
+ readonly aide: _angular_core.InputSignal<string | null>;
1735
+ readonly options: _angular_core.InputSignal<readonly OptionRadio[]>;
1736
+ /** Contrat Signal Forms. */
1737
+ readonly value: _angular_core.ModelSignal<string>;
1738
+ readonly errors: _angular_core.InputSignal<readonly ValidationError.WithOptionalFieldTree[]>;
1739
+ readonly touched: _angular_core.InputSignalWithTransform<boolean, unknown>;
1740
+ readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
1741
+ readonly required: _angular_core.InputSignalWithTransform<boolean, unknown>;
1742
+ readonly hidden: _angular_core.InputSignalWithTransform<boolean, unknown>;
1743
+ readonly name: _angular_core.InputSignal<string>;
1744
+ readonly touch: _angular_core.OutputEmitterRef<void>;
1745
+ /** Nom partage par les options : sans lui, chaque radio forme son propre groupe. */
1746
+ private readonly nomParDefaut;
1747
+ protected nomDuGroupe(): string;
1748
+ protected identifiantAide(indice: number): string;
1749
+ /** Focus sur l'option cochee, sinon la premiere disponible : c'est l'arret du groupe. */
1750
+ focus(options?: FocusOptions): void;
1751
+ protected choisir(valeur: string): void;
1752
+ protected aLaSortie(evenement: FocusEvent): void;
1753
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<StRadioGroup, never>;
1754
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<StRadioGroup, "st-radio-group", never, { "legende": { "alias": "legende"; "required": true; "isSignal": true; }; "aide": { "alias": "aide"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": true; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "errors": { "alias": "errors"; "required": false; "isSignal": true; }; "touched": { "alias": "touched"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "hidden": { "alias": "hidden"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "touch": "touch"; }, never, never, true, never>;
1755
+ }
1756
+
1757
+ /**
1758
+ * Interrupteur : un reglage qui s'applique IMMEDIATEMENT.
1759
+ *
1760
+ * ```html
1761
+ * <st-switch libelle="Notifications par SMS" [(checked)]="sms" (checkedChange)="enregistrer($event)" />
1762
+ * ```
1763
+ *
1764
+ * ⚠️ **Jamais dans un formulaire a envoyer** (UX-8). Un interrupteur promet que
1765
+ * l'effet a lieu au basculement ; pose au-dessus d'un bouton « Enregistrer », il
1766
+ * ment — la personne croit le reglage applique, quitte la page, et le perd. Pour
1767
+ * un choix envoye plus tard, c'est `st-checkbox`.
1768
+ *
1769
+ * C'est pourquoi il n'affiche aucune erreur de validation : un reglage immediat
1770
+ * ne se valide pas a l'envoi. Un refus du serveur se dit par un message, et
1771
+ * l'interrupteur revient a son etat precedent.
1772
+ *
1773
+ * ⚠️ Une case a cocher native avec `role="switch"` : Espace bascule, l'etiquette
1774
+ * est reliee par `for`, et le lecteur d'ecran annonce « active » ou
1775
+ * « desactive » — mieux qu'un `div` qui imiterait tout cela.
1776
+ */
1777
+ declare class StSwitch implements FormCheckboxControl {
1778
+ readonly libelle: _angular_core.InputSignal<string>;
1779
+ readonly aide: _angular_core.InputSignal<string | null>;
1780
+ /** Contrat Signal Forms. */
1781
+ readonly checked: _angular_core.ModelSignal<boolean>;
1782
+ readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
1783
+ readonly hidden: _angular_core.InputSignalWithTransform<boolean, unknown>;
1784
+ readonly name: _angular_core.InputSignal<string>;
1785
+ readonly touch: _angular_core.OutputEmitterRef<void>;
1786
+ private readonly champ;
1787
+ focus(options?: FocusOptions): void;
1788
+ protected surChangement(evenement: Event): void;
1789
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<StSwitch, never>;
1790
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<StSwitch, "st-switch", never, { "libelle": { "alias": "libelle"; "required": true; "isSignal": true; }; "aide": { "alias": "aide"; "required": false; "isSignal": true; }; "checked": { "alias": "checked"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "hidden": { "alias": "hidden"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; }, { "checked": "checkedChange"; "touch": "touch"; }, never, never, true, never>;
1791
+ }
1792
+
1793
+ /** Une ligne du recapitulatif. */
1794
+ interface LigneDErreur {
1795
+ readonly libelle: string | null;
1796
+ readonly message: string;
1797
+ readonly aller: () => void;
1798
+ }
1799
+ /**
1800
+ * Recapitulatif des erreurs d'un formulaire, a l'envoi.
1801
+ *
1802
+ * ```html
1803
+ * <st-error-summary [erreurs]="tentative() ? virement().errorSummary() : []" />
1804
+ * ```
1805
+ *
1806
+ * ⚠️ **Il prend le focus en apparaissant** (UX-5). Sans lui, une personne au
1807
+ * clavier ou au lecteur d'ecran appuie sur « Envoyer », et rien ne se passe : le
1808
+ * champ refuse est en haut de la page, hors de sa vue, et personne ne le lui dit.
1809
+ *
1810
+ * ⚠️ **Chaque ligne nomme son champ.** « Ce champ est obligatoire. » repete cinq
1811
+ * fois n'apprend rien ; « Nom du beneficiaire : ce champ est obligatoire. », si.
1812
+ * Le libelle est lu sur l'element lie au champ, par Signal Forms — sans registre,
1813
+ * et quel que soit le composant.
1814
+ *
1815
+ * ⚠️ **Une ligne par champ**, la premiere erreur seulement : trois erreurs sur le
1816
+ * meme IBAN font trois lignes pour une seule correction.
1817
+ *
1818
+ * ⚠️ **Une region nommee par son titre.** Un `div` sans role ne PEUT pas porter
1819
+ * `aria-labelledby` : le nom serait ignore, et le focus n'annoncerait rien. En
1820
+ * region, il annonce « 2 erreurs a corriger » a l'arrivee du focus, et se
1821
+ * retrouve dans la liste des reperes.
1822
+ *
1823
+ * Chaque ligne amene le focus sur son champ : c'est le champ, et non la ligne,
1824
+ * qu'il faut corriger. Une erreur rattachee au formulaire entier — un refus du
1825
+ * serveur sur un champ inconnu — s'affiche sans lien.
1826
+ */
1827
+ declare class StErrorSummary {
1828
+ private readonly libelles;
1829
+ private readonly locale;
1830
+ private readonly element;
1831
+ private readonly injecteur;
1832
+ readonly erreurs: _angular_core.InputSignal<readonly ValidationError.WithOptionalFieldTree[]>;
1833
+ /** `null` : « N erreurs a corriger », du dictionnaire. */
1834
+ readonly titre: _angular_core.InputSignal<string | null>;
1835
+ /** Unique par instance : deux recapitulatifs sur une page partageraient leur titre. */
1836
+ protected readonly identifiantDuTitre: string;
1837
+ protected readonly lignes: _angular_core.Signal<readonly LigneDErreur[]>;
1838
+ protected readonly titreLu: _angular_core.Signal<string>;
1839
+ constructor();
1840
+ /** A appeler apres un envoi refuse, quand le recapitulatif etait deja visible. */
1841
+ focus(): void;
1842
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<StErrorSummary, never>;
1843
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<StErrorSummary, "st-error-summary", never, { "erreurs": { "alias": "erreurs"; "required": true; "isSignal": true; }; "titre": { "alias": "titre"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1844
+ }
1845
+
1846
+ /** `connexion` : un mot de passe existant. `creation` : un nouveau. */
1847
+ type UsageDuMotDePasse = 'connexion' | 'creation';
1848
+ /**
1849
+ * Mot de passe, avec revelation.
1850
+ *
1851
+ * ```html
1852
+ * <st-password-field libelle="Mot de passe" usage="creation" [regles]="regles" [formField]="compte.motDePasse" />
1853
+ * ```
1854
+ *
1855
+ * ⚠️ **`autocomplete` selon l'usage** (SEC-2) : `current-password` a la connexion,
1856
+ * `new-password` a la creation — c'est ce qui fait proposer par le gestionnaire
1857
+ * un mot de passe FORT au bon endroit, et non l'ancien.
1858
+ *
1859
+ * ⚠️ **Le collage n'est jamais bloque** (SEC-1, NIST SP 800-63B) : l'interdire
1860
+ * pousse vers des mots de passe courts, retenus de tete, et casse les
1861
+ * gestionnaires de mots de passe.
1862
+ *
1863
+ * ⚠️ **Revele, il se remasque des que le focus quitte le champ, et a l'envoi du
1864
+ * formulaire** (SEC-4) : un mot de passe laisse en clair reste lisible par-dessus
1865
+ * l'epaule, sur l'ecran suivant comme sur celui-ci. L'envoi par Entree ne fait
1866
+ * pas quitter le champ : d'ou l'ecoute de `submit`, qui remonte jusqu'au document.
1867
+ *
1868
+ * Le bouton de revelation est un bouton bascule : `aria-pressed` porte l'etat, et
1869
+ * l'etiquette ne change PAS — « Masquer le mot de passe, enfonce » se lirait
1870
+ * comme une double negation.
1871
+ *
1872
+ * ⚠️ **Aucun indicateur de « force »**, et c'est un refus. Une estimation faite
1873
+ * dans le navigateur donne « fort » a `Motdepasse1!` : elle rassure a tort. Les
1874
+ * regles sont affichees AVANT la saisie (UX-10), et c'est le serveur qui verifie —
1875
+ * y compris contre les mots de passe deja divulgues, qu'aucune regle locale ne
1876
+ * voit.
1877
+ */
1878
+ declare class StPasswordField extends ControleDeSaisie {
1879
+ protected readonly libelles: _angular_core.Signal<_starterlib_ui.LibellesUi>;
1880
+ private readonly element;
1881
+ readonly usage: _angular_core.InputSignal<UsageDuMotDePasse>;
1882
+ /** Regles affichees avant la saisie, comme aide du champ. */
1883
+ readonly regles: _angular_core.InputSignal<readonly string[]>;
1884
+ protected readonly revele: _angular_core.WritableSignal<boolean>;
1885
+ protected readonly autocomplete: _angular_core.Signal<"current-password" | "new-password">;
1886
+ protected readonly aideLue: _angular_core.Signal<string | null>;
1887
+ protected basculer(): void;
1888
+ protected surSaisie(evenement: Event): void;
1889
+ protected aLEnvoi(evenement: Event): void;
1890
+ protected aLaSortie(evenement: FocusEvent): void;
1891
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<StPasswordField, never>;
1892
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<StPasswordField, "st-password-field", never, { "usage": { "alias": "usage"; "required": false; "isSignal": true; }; "regles": { "alias": "regles"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1893
+ }
1894
+
1895
+ /**
1896
+ * Code a usage unique : second facteur, code recu par SMS ou par courriel.
1897
+ *
1898
+ * ⚠️ **UN seul champ, pas six cases** (UX-9). Six champs cassent le collage, le
1899
+ * remplissage automatique du code recu par SMS, et la lecture au lecteur d'ecran,
1900
+ * qui annonce six champs sans nom au lieu d'un seul.
1901
+ *
1902
+ * ⚠️ `autocomplete="one-time-code"` : iOS et Android proposent alors le code recu,
1903
+ * d'un toucher. Clavier numerique par `inputmode`, et NON par `type="number"`,
1904
+ * qui retire les zeros de tete et accepte « 1e5 ».
1905
+ *
1906
+ * ⚠️ **Aucun envoi automatique** a la sixieme saisie : un formulaire qui part de
1907
+ * lui-meme surprend (WCAG 3.2.2), et part aussi avec un code mal colle. Le code
1908
+ * colle est nettoye de ses espaces et tirets — « 123 456 » —, jamais tronque.
1909
+ */
1910
+ declare class StOtpField extends ControleDeSaisie {
1911
+ private readonly libelles;
1912
+ readonly longueur: _angular_core.InputSignal<number>;
1913
+ protected readonly aideLue: _angular_core.Signal<string>;
1914
+ protected surSaisie(evenement: Event): void;
1915
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<StOtpField, never>;
1916
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<StOtpField, "st-otp-field", never, { "longueur": { "alias": "longueur"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1917
+ }
1918
+
1919
+ /**
1920
+ * Champ de recherche : un repere, un champ, un bouton.
1921
+ *
1922
+ * ```html
1923
+ * <st-search-field libelle="Rechercher un beneficiaire" (recherche)="filtrer($event)" />
1924
+ * ```
1925
+ *
1926
+ * ⚠️ **Un repere `search`** : la recherche se retrouve dans la liste des reperes du
1927
+ * lecteur d'ecran, a cote de la navigation et du contenu.
1928
+ *
1929
+ * L'etiquette est lue sans etre affichee — seule exception au socle (UX-1) : la
1930
+ * loupe, le bouton et la position disent deja le but du champ.
1931
+ *
1932
+ * ⚠️ **Jamais dans l'adresse quand le terme est personnel** (SEC-6). Chercher un
1933
+ * nom, un IBAN ou un numero en `?q=` inscrit la donnee dans l'historique, dans les
1934
+ * journaux des intermediaires, et dans l'en-tete `Referer` des pages suivantes.
1935
+ * `recherche` emet le terme : c'est a l'appelant de ne pas le mettre dans l'URL.
1936
+ */
1937
+ declare class StSearchField extends ControleDeSaisie {
1938
+ protected readonly libelles: _angular_core.Signal<_starterlib_ui.LibellesUi>;
1939
+ /** Emis a la validation — Entree ou bouton —, et non a chaque frappe. */
1940
+ readonly recherche: _angular_core.OutputEmitterRef<string>;
1941
+ protected surSaisie(evenement: Event): void;
1942
+ protected lancer(evenement?: Event): void;
1943
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<StSearchField, never>;
1944
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<StSearchField, "st-search-field", never, {}, { "recherche": "recherche"; }, never, never, true, never>;
1945
+ }
1946
+
1947
+ /**
1948
+ * IBAN. La valeur du modele est NORMALISEE — sans espaces, en majuscules —, et
1949
+ * l'affichage groupe par quatre.
1950
+ *
1951
+ * ```html
1952
+ * <st-iban-field libelle="IBAN du beneficiaire" [formField]="virement.iban" />
1953
+ * <!-- schema : validate(chemin.iban, ({ value }) => erreurIban(value())) -->
1954
+ * ```
1955
+ *
1956
+ * ⚠️ **Le groupement se fait a la sortie du champ, jamais pendant la frappe.**
1957
+ * Reformater a chaque caractere deplace le curseur a la fin : corriger une
1958
+ * erreur au milieu de 27 caracteres devient impossible, chaque frappe renvoyant a
1959
+ * la fin de la ligne.
1960
+ *
1961
+ * ⚠️ **Aucune verification de validite ici** : elle appartient au schema, par
1962
+ * `erreurIban`, pour s'afficher au bon moment et par le bon canal. Et elle reste un
1963
+ * confort (SEC-5) : le serveur revalide.
1964
+ *
1965
+ * `autocapitalize="characters"` et correction orthographique coupee : un IBAN
1966
+ * n'est pas un mot, et une correction automatique le fausserait.
1967
+ */
1968
+ declare class StIbanField extends ControleDeSaisie {
1969
+ private readonly libelles;
1970
+ private readonly enSaisie;
1971
+ private readonly brut;
1972
+ protected readonly aideLue: _angular_core.Signal<string>;
1973
+ /**
1974
+ * Brut pendant la saisie ; groupe par quatre au repos. Une valeur changee de
1975
+ * l'exterieur pendant la saisie — remise a zero du formulaire — l'emporte sur
1976
+ * le brut, qui ne la represente plus.
1977
+ */
1978
+ protected readonly affichage: _angular_core.Signal<string>;
1979
+ protected auFocus(): void;
1980
+ protected surSaisie(evenement: Event): void;
1981
+ protected aLaSortie(): void;
1982
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<StIbanField, never>;
1983
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<StIbanField, "st-iban-field", never, {}, {}, never, never, true, never>;
1984
+ }
1985
+
1986
+ /** `tel` : numero complet, indicatif compris. `tel-national` : sans indicatif. */
1987
+ type RemplissageDeTelephone = 'tel' | 'tel-national';
1988
+ /**
1989
+ * Numero de telephone. La valeur du modele ne garde que les chiffres et le `+` de
1990
+ * tete ; la saisie s'affiche telle qu'elle a ete tapee.
1991
+ *
1992
+ * ```html
1993
+ * <st-phone-field libelle="Telephone portable" [formField]="contact.telephone" />
1994
+ * <!-- schema : validate(chemin.telephone, ({ value }) => erreurTelephone(value())) -->
1995
+ * ```
1996
+ *
1997
+ * ⚠️ **Aucun formatage automatique.** Le groupement des chiffres depend du pays,
1998
+ * et reformater pendant la frappe renvoie le curseur en fin de ligne. La saisie
1999
+ * reste celle de la personne, espaces et points compris.
2000
+ *
2001
+ * ⚠️ **Pas de selecteur de pays, pas de verification par pays.** Il faudrait une
2002
+ * table des plans de numerotation, lourde et souvent perimee : c'est au serveur
2003
+ * de dire si le numero existe (SEC-5). `erreurTelephone` ne verifie que la forme.
2004
+ *
2005
+ * `type="tel"`, et jamais `type="number"` : un numero n'est pas une quantite, et le
2006
+ * champ numerique retire le zero de tete et le `+`.
2007
+ */
2008
+ declare class StPhoneField extends ControleDeSaisie {
2009
+ readonly autocomplete: _angular_core.InputSignal<RemplissageDeTelephone>;
2010
+ private readonly brut;
2011
+ /**
2012
+ * La saisie telle que tapee, tant qu'elle represente encore la valeur ; une
2013
+ * valeur changee de l'exterieur — remise a zero, pre-remplissage — l'emporte.
2014
+ */
2015
+ protected readonly affichage: _angular_core.Signal<string>;
2016
+ protected surSaisie(evenement: Event): void;
2017
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<StPhoneField, never>;
2018
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<StPhoneField, "st-phone-field", never, { "autocomplete": { "alias": "autocomplete"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
2019
+ }
2020
+
2021
+ /**
2022
+ * Un choix d'une liste : `st-select`, `st-combobox`, `st-multiselect`.
2023
+ *
2024
+ * La `valeur` part dans le modele, le `libelle` s'affiche : un identifiant
2025
+ * technique ne s'affiche jamais, et un libelle traduit ne s'envoie jamais.
2026
+ */
2027
+ interface OptionDeListe {
2028
+ readonly valeur: string;
2029
+ readonly libelle: string;
2030
+ readonly desactivee?: boolean;
2031
+ /** Regroupe les options consecutives sous un intitule (`optgroup`). */
2032
+ readonly groupe?: string;
2033
+ }
2034
+ /** Sans accents ni casse : « eleve » trouve « Élève ». */
2035
+ declare function normaliserPourRecherche(texte: string): string;
2036
+ /** Options dont le libelle CONTIENT le texte cherche, sans accents ni casse. */
2037
+ declare function filtrerOptions(options: readonly OptionDeListe[], recherche: string): readonly OptionDeListe[];
2038
+
2039
+ interface BlocDOptions {
2040
+ readonly groupe: string | null;
2041
+ readonly options: readonly OptionDeListe[];
2042
+ }
2043
+ /**
2044
+ * Liste deroulante, sur un `select` NATIF.
2045
+ *
2046
+ * ```html
2047
+ * <st-select libelle="Pays" [options]="pays" autocomplete="country" [formField]="adresse.pays" />
2048
+ * ```
2049
+ *
2050
+ * ⚠️ **Natif, et non une liste ARIA** (FE-4). Le `select` natif ouvre le selecteur
2051
+ * du systeme sur mobile, se remplit automatiquement, se parcourt a la lettre, et
2052
+ * se lit partout. Une liste recomposee en ARIA ne fait jamais mieux sur ces
2053
+ * points ; elle ne se justifie que pour filtrer une longue liste — c'est
2054
+ * `st-combobox` — ou choisir plusieurs valeurs — `st-multiselect`.
2055
+ *
2056
+ * La premiere option, vide, dit « Choisir… » : sans elle, la premiere vraie
2057
+ * option paraitrait choisie alors que personne ne l'a fait. Le modele vaut
2058
+ * alors `''`, que `required` refuse.
2059
+ *
2060
+ * `readonly` n'existe pas sur un `select` : le champ annonce `aria-readonly` et
2061
+ * ignore le changement, plutot que d'etre desactive — un champ desactive sort de
2062
+ * l'ordre de tabulation, et sa valeur ne se lit plus.
2063
+ */
2064
+ declare class StSelect extends ControleDeSaisie {
2065
+ protected readonly libelles: _angular_core.Signal<_starterlib_ui.LibellesUi>;
2066
+ readonly options: _angular_core.InputSignal<readonly OptionDeListe[]>;
2067
+ /** Texte de l'option vide. Par defaut : « Choisir… ». */
2068
+ readonly texteVide: _angular_core.InputSignal<string | null>;
2069
+ /** WCAG 1.3.5 : `country`, `sex`, `honorific-prefix`… */
2070
+ readonly autocomplete: _angular_core.InputSignal<string | null>;
2071
+ /** Options consecutives d'un meme groupe, dans l'ordre fourni. */
2072
+ protected readonly blocs: _angular_core.Signal<readonly BlocDOptions[]>;
2073
+ protected surChoix(evenement: Event): void;
2074
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<StSelect, never>;
2075
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<StSelect, "st-select", never, { "options": { "alias": "options"; "required": true; "isSignal": true; }; "texteVide": { "alias": "texteVide"; "required": false; "isSignal": true; }; "autocomplete": { "alias": "autocomplete"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
2076
+ }
2077
+
2078
+ interface Jour {
2079
+ readonly date: DateIso;
2080
+ /** Jour d'un mois voisin : cellule vide, la date vit dans son propre mois. */
2081
+ readonly horsDuMois: boolean;
2082
+ readonly numero: string;
2083
+ readonly nom: string;
2084
+ readonly horsBornes: boolean;
2085
+ readonly choisi: boolean;
2086
+ readonly dansLaPlage: boolean;
2087
+ readonly aujourdHui: boolean;
2088
+ }
2089
+ /**
2090
+ * Calendrier d'un mois, pour choisir une date.
2091
+ *
2092
+ * ```html
2093
+ * <st-calendar [selection]="depart()" dateMin="2026-09-17" (choix)="depart.set($event)" />
2094
+ * ```
2095
+ *
2096
+ * ⚠️ **Une aide, jamais la seule voie.** Dans `st-date-field`, le calendrier
2097
+ * complete un champ texte : une date de naissance se tape plus vite qu'elle ne se
2098
+ * cherche mois par mois, et un calendrier reste penible au lecteur d'ecran.
2099
+ *
2100
+ * ⚠️ **Le clavier navigue de DATE en date, pas de cellule en cellule** (decision
2101
+ * D7 de l'audit de la vague 3). Fleche droite le 30 septembre mene au 1er
2102
+ * octobre ; Page suivante change de mois, Maj + Page d'annee ; Debut et Fin vont
2103
+ * aux bords de la semaine de la LOCALE. La grille d'Angular Aria deplace un focus
2104
+ * entre cellules affichees : il aurait fallu la contourner sur chaque touche qui
2105
+ * compte, et elle aurait fait entrer le CDK dans les formulaires.
2106
+ *
2107
+ * Semaine commencant au jour de la locale, noms de jours et de mois dans la
2108
+ * langue courante, « aujourd'hui » dans le fuseau de la personne
2109
+ * (`FUSEAU_PAR_DEFAUT`) et non celui du poste.
2110
+ */
2111
+ declare class StCalendar {
2112
+ protected readonly libelles: _angular_core.Signal<_starterlib_ui.LibellesUi>;
2113
+ private readonly locale;
2114
+ private readonly element;
2115
+ private readonly injecteur;
2116
+ private readonly aujourdHui;
2117
+ readonly selection: _angular_core.InputSignal<string | null>;
2118
+ readonly dateMin: _angular_core.InputSignal<string | null>;
2119
+ readonly dateMax: _angular_core.InputSignal<string | null>;
2120
+ /** Periode a faire ressortir, pour un choix de plage. */
2121
+ readonly plage: _angular_core.InputSignal<PlageDeDates | null>;
2122
+ readonly choix: _angular_core.OutputEmitterRef<string>;
2123
+ /** Echap : le conteneur decide de fermer, et ou rendre le focus. */
2124
+ readonly fermeture: _angular_core.OutputEmitterRef<void>;
2125
+ protected readonly identifiants: {
2126
+ readonly titre: `${string}-titre`;
2127
+ readonly aide: `${string}-aide`;
2128
+ };
2129
+ /** La date qui porte le focus. Suit la selection, bornee. */
2130
+ private readonly active;
2131
+ private readonly premierJour;
2132
+ protected readonly titre: _angular_core.Signal<string>;
2133
+ protected readonly joursDeLaSemaine: _angular_core.Signal<{
2134
+ court: string;
2135
+ long: string;
2136
+ }[]>;
2137
+ protected readonly semaines: _angular_core.Signal<readonly (readonly Jour[])[]>;
2138
+ protected readonly moisPrecedentPossible: _angular_core.Signal<boolean>;
2139
+ protected readonly moisSuivantPossible: _angular_core.Signal<boolean>;
2140
+ protected estActive(date: DateIso): boolean;
2141
+ /** Amene le focus sur la date active. */
2142
+ focus(): void;
2143
+ protected changerDeMois(ecart: number): void;
2144
+ protected choisir(jour: Jour): void;
2145
+ protected surTouche(evenement: KeyboardEvent): void;
2146
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<StCalendar, never>;
2147
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<StCalendar, "st-calendar", never, { "selection": { "alias": "selection"; "required": false; "isSignal": true; }; "dateMin": { "alias": "dateMin"; "required": false; "isSignal": true; }; "dateMax": { "alias": "dateMax"; "required": false; "isSignal": true; }; "plage": { "alias": "plage"; "required": false; "isSignal": true; }; }, { "choix": "choix"; "fermeture": "fermeture"; }, never, never, true, never>;
2148
+ }
2149
+
2150
+ /**
2151
+ * Choix de fichiers, sur un `input type="file"` natif.
2152
+ *
2153
+ * ```html
2154
+ * <st-file-upload libelle="Justificatifs" accept=".pdf, image/*" [tailleMax]="5_000_000" multiple
2155
+ * [formField]="dossier.pieces" />
2156
+ * <!-- schema : validate(chemin.pieces, ({ value }) => erreursDeFichiers(value(), regles)) -->
2157
+ * ```
2158
+ *
2159
+ * Le modele est la liste des `File` choisis. L'envoi appartient a l'application,
2160
+ * par `@starterlib/core` : le composant choisit, il ne televerse pas.
2161
+ *
2162
+ * ⚠️ **L'element natif reste la voie principale** (FE-4) : il ouvre le selecteur
2163
+ * du systeme, l'appareil photo sur mobile, et se commande au clavier. Il est
2164
+ * masque visuellement, pas retire : le bouton affiche est son etiquette. Le
2165
+ * depot par glisser est un complement a la souris, jamais la seule voie.
2166
+ *
2167
+ * ⚠️ **Aucun apercu d'image** (SEC-7). Un apercu passe par une adresse `blob:`
2168
+ * que la politique de securite du contenu doit autoriser, et un SVG affiche peut
2169
+ * porter du script. Le nom et la taille suffisent a reconnaitre un fichier.
2170
+ *
2171
+ * ⚠️ **`accept`, `tailleMax` et `nombreMax` sont un confort** (SEC-5) : ils
2172
+ * s'affichent en aide et filtrent le selecteur du systeme, mais la verification
2173
+ * est dans le schema — `erreursDeFichiers` —, et le serveur relit le contenu.
2174
+ *
2175
+ * Chaque changement de la liste s'annonce : « 2 fichiers choisis ». Un fichier
2176
+ * retire rend le focus au bouton de retrait suivant, ou au choix de fichiers : le
2177
+ * focus ne tombe jamais sur le document.
2178
+ */
2179
+ declare class StFileUpload extends ContratDeChamp implements FormValueControl<readonly File[]> {
2180
+ protected readonly libelles: _angular_core.Signal<_starterlib_ui.LibellesUi>;
2181
+ private readonly locale;
2182
+ private readonly element;
2183
+ private readonly injecteur;
2184
+ readonly value: _angular_core.ModelSignal<readonly File[]>;
2185
+ /** Attribut `accept` natif : `.pdf, image/*`. */
2186
+ readonly accept: _angular_core.InputSignal<string>;
2187
+ readonly multiple: _angular_core.InputSignalWithTransform<boolean, unknown>;
2188
+ /** En octets. Affiche en aide ; la verification est dans le schema. */
2189
+ readonly tailleMax: _angular_core.InputSignal<number | null>;
2190
+ protected readonly annonce: AnnonceLocale;
2191
+ protected readonly survol: _angular_core.WritableSignal<boolean>;
2192
+ protected readonly aideLue: _angular_core.Signal<string | null>;
2193
+ protected readonly lignes: _angular_core.Signal<{
2194
+ fichier: File;
2195
+ cle: string;
2196
+ taille: string;
2197
+ }[]>;
2198
+ protected surChoix(evenement: Event): void;
2199
+ protected surSurvol(evenement: DragEvent): void;
2200
+ protected surDepot(evenement: DragEvent): void;
2201
+ protected retirer(indice: number): void;
2202
+ protected aLaSortie(evenement: FocusEvent): void;
2203
+ private ajouter;
2204
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<StFileUpload, never>;
2205
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<StFileUpload, "st-file-upload", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "accept": { "alias": "accept"; "required": false; "isSignal": true; }; "multiple": { "alias": "multiple"; "required": false; "isSignal": true; }; "tailleMax": { "alias": "tailleMax"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, never>;
2206
+ }
2207
+
1263
2208
  /**
1264
2209
  * Choix du theme : systeme, clair, sombre.
1265
2210
  *
@@ -1591,5 +2536,5 @@ declare class StChargement {
1591
2536
  /** Toutes les directives de gabarit, a importer d'un coup. */
1592
2537
  declare const GABARITS_D_ETAT: readonly [typeof StSucces, typeof StErreur, typeof StVide, typeof StHorsLigne, typeof StChargement];
1593
2538
 
1594
- export { AnnonceLocale, CHEMIN_DU_SPRITE, FUSEAU_PAR_DEFAUT, GABARITS_D_ETAT, IDENTIFIANT_DU_CONTENU_PRINCIPAL, LIBELLES_EN, LIBELLES_FR, NOMS_DICONE, REGION_VIVANTE_PARENTE, ST_LIBELLES, ST_LOCALE, StAppShell, StAvatar, StBadge, StBanner, StBreadcrumb, StButton, StButtonGroup, StCard, StChargement, StCode, StCopyButton, StCount, StDate, StDivider, StEmpty, StErreur, StError, StHeader, StHeading, StHorsLigne, StIcon, StIconButton, StInlineMessage, StLangSwitch, StLink, StLogo, StMasked, StMoney, StOfflineBanner, StPageTitle, StProgress, StRelativeTime, StSection, StSkeleton, StSkipLink, StSpinner, StState, StStatusPill, StSucces, StTag, StText, StThemeToggle, StTimer, StVide, copierDansLePressePapiers, formaterDuree, fournirCheminDuSprite, pressePapiersDisponible, provideStarterUi };
1595
- export type { ConfigurationUi, FormatDeDate, GraisseDeTexte, IssueDeCopie, LibellesUi, MaillonDeFil, NiveauDeTitre, NomDIcone, OrientationDeSeparateur, ReliefDeCarte, RembourrageDeCarte, TailleDIcone, TailleDeBouton, TailleDeSpinner, TailleDeTitre, TonDIcone, TonDeBadge, TonDeBanniere, TonDeMessage, TonDeProgression, TonDeSpinner, TonDeStatut, TypeMasque, VarianteDErreur, VarianteDeBouton, VarianteDeBoutonIcone, VarianteDeLien, VarianteDeSquelette, VarianteDeTexte };
2539
+ export { AnnonceLocale, CHEMIN_DU_SPRITE, ContratDeChamp, ControleDeSaisie, FUSEAU_PAR_DEFAUT, GABARITS_D_ETAT, IDENTIFIANT_DU_CONTENU_PRINCIPAL, LIBELLES_EN, LIBELLES_FR, NOMS_DICONE, REGION_VIVANTE_PARENTE, ST_LIBELLES, ST_LOCALE, StAppShell, StAvatar, StBadge, StBanner, StBreadcrumb, StButton, StButtonGroup, StCalendar, StCard, StChargement, StCheckbox, StCode, StControleDeChamp, StCopyButton, StCount, StDate, StDivider, StEmpty, StErreur, StError, StErrorSummary, StFieldset, StFileUpload, StFormField, StHeader, StHeading, StHorsLigne, StIbanField, StIcon, StIconButton, StInlineMessage, StInput, StLangSwitch, StLink, StLogo, StMasked, StMoney, StOfflineBanner, StOtpField, StPageTitle, StPasswordField, StPhoneField, StProgress, StRadioGroup, StRelativeTime, StSearchField, StSection, StSelect, StSkeleton, StSkipLink, StSpinner, StState, StStatusPill, StSucces, StSwitch, StTag, StText, StTextarea, StThemeToggle, StTimer, StVide, copierDansLePressePapiers, erreurDate, erreurIban, erreurPlageDeDates, erreurTelephone, erreursDeFichiers, exempleDeDate, filtrerOptions, formaterDuree, fournirCheminDuSprite, fusionnerErreurs, messageDErreur, motifLocal, normaliserPourRecherche, pressePapiersDisponible, provideStarterUi };
2540
+ export type { BornesDeDate, ConfigurationUi, DispositionDeChamp, ElementDeSaisie, ErreurAffichable, FormatDeDate, GraisseDeTexte, IssueDeCopie, LibellesUi, MaillonDeFil, NiveauDeTitre, NomDIcone, OptionDeListe, OptionRadio, OrientationDeSeparateur, ReglesDeFichiers, ReliefDeCarte, RembourrageDeCarte, RemplissageDeTelephone, TailleDIcone, TailleDeBouton, TailleDeSpinner, TailleDeTitre, TonDIcone, TonDeBadge, TonDeBanniere, TonDeMessage, TonDeProgression, TonDeSpinner, TonDeStatut, TypeDeSaisie, TypeMasque, UsageDuMotDePasse, VarianteDErreur, VarianteDeBouton, VarianteDeBoutonIcone, VarianteDeLien, VarianteDeSquelette, VarianteDeTexte };