@starterlib/ui 0.7.2 → 0.9.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.
Files changed (55) hide show
  1. package/LICENCES-TIERCES.md +236 -0
  2. package/README.md +163 -56
  3. package/assets/icones/catalogue.json +3296 -0
  4. package/assets/icones/sprite.svg +235 -35
  5. package/fesm2022/starterlib-ui-arbre.mjs +475 -0
  6. package/fesm2022/starterlib-ui-arbre.mjs.map +1 -0
  7. package/fesm2022/starterlib-ui-donnees.mjs +3561 -0
  8. package/fesm2022/starterlib-ui-donnees.mjs.map +1 -0
  9. package/fesm2022/starterlib-ui-formulaires.mjs +3186 -442
  10. package/fesm2022/starterlib-ui-formulaires.mjs.map +1 -1
  11. package/fesm2022/starterlib-ui-libelles-en.mjs +383 -0
  12. package/fesm2022/starterlib-ui-libelles-en.mjs.map +1 -0
  13. package/fesm2022/starterlib-ui-listes.mjs +5367 -0
  14. package/fesm2022/starterlib-ui-listes.mjs.map +1 -0
  15. package/fesm2022/starterlib-ui-messagerie.mjs +737 -0
  16. package/fesm2022/starterlib-ui-messagerie.mjs.map +1 -0
  17. package/fesm2022/starterlib-ui-navigation.mjs +509 -0
  18. package/fesm2022/starterlib-ui-navigation.mjs.map +1 -0
  19. package/fesm2022/starterlib-ui-onglets.mjs +371 -0
  20. package/fesm2022/starterlib-ui-onglets.mjs.map +1 -0
  21. package/fesm2022/starterlib-ui-parcours.mjs +2449 -0
  22. package/fesm2022/starterlib-ui-parcours.mjs.map +1 -0
  23. package/fesm2022/starterlib-ui-qr.mjs +907 -0
  24. package/fesm2022/starterlib-ui-qr.mjs.map +1 -0
  25. package/fesm2022/starterlib-ui-saisie.mjs +8609 -0
  26. package/fesm2022/starterlib-ui-saisie.mjs.map +1 -0
  27. package/fesm2022/starterlib-ui-selection.mjs +1341 -0
  28. package/fesm2022/starterlib-ui-selection.mjs.map +1 -0
  29. package/fesm2022/starterlib-ui-sens.mjs +59 -0
  30. package/fesm2022/starterlib-ui-sens.mjs.map +1 -0
  31. package/fesm2022/starterlib-ui-surfaces.mjs +5140 -1387
  32. package/fesm2022/starterlib-ui-surfaces.mjs.map +1 -1
  33. package/fesm2022/starterlib-ui.mjs +10729 -5689
  34. package/fesm2022/starterlib-ui.mjs.map +1 -1
  35. package/package.json +58 -17
  36. package/styles/amorce.css +69 -0
  37. package/styles/couches.css +178 -0
  38. package/types/starterlib-ui-arbre.d.ts +225 -0
  39. package/types/starterlib-ui-donnees.d.ts +1489 -0
  40. package/types/starterlib-ui-formulaires.d.ts +1174 -138
  41. package/types/starterlib-ui-libelles-en.d.ts +5 -0
  42. package/types/starterlib-ui-listes.d.ts +2487 -0
  43. package/types/starterlib-ui-messagerie.d.ts +317 -0
  44. package/types/starterlib-ui-navigation.d.ts +242 -0
  45. package/types/starterlib-ui-onglets.d.ts +212 -0
  46. package/types/starterlib-ui-parcours.d.ts +916 -0
  47. package/types/starterlib-ui-qr.d.ts +105 -0
  48. package/types/starterlib-ui-saisie.d.ts +3806 -0
  49. package/types/starterlib-ui-selection.d.ts +488 -0
  50. package/types/starterlib-ui-sens.d.ts +44 -0
  51. package/types/starterlib-ui-surfaces.d.ts +1899 -510
  52. package/types/starterlib-ui.d.ts +4731 -2678
  53. package/fesm2022/starterlib-ui-interactions.mjs +0 -598
  54. package/fesm2022/starterlib-ui-interactions.mjs.map +0 -1
  55. package/types/starterlib-ui-interactions.d.ts +0 -316
@@ -1,15 +1,110 @@
1
- import * as _starterlib_ui from '@starterlib/ui';
2
- import { ContratDeChamp, ErreurAffichable } from '@starterlib/ui';
3
- import * as _angular_forms_signals from '@angular/forms/signals';
4
- import { FormValueControl } from '@angular/forms/signals';
5
- import * as _angular_core from '@angular/core';
6
- import { DateIso, PlageDeDates } from '@starterlib/util';
7
-
1
+ import { FieldTree, FormValueControl, TreeValidationResult } from "@angular/forms/signals";
2
+ import { AnneesDuCalendrier, ContratDeChamp, ContratDeChampABornes, ControleDeSaisie, ErreurAffichable, EtatDEnvoi, OptionDeListe, OptionRadio } from "@starterlib/ui/saisie";
3
+ import * as i0 from "@angular/core";
4
+ import { InjectionToken, Provider, Signal } from "@angular/core";
5
+ import { AnnonceLocale, CatalogueDuPointDEntree, LibellesUi } from "@starterlib/ui";
6
+ import { DateIso, FrequenceDeRecurrence, HeureIso, PlageDeDates, Recurrence } from "@starterlib/util";
7
+ /**
8
+ * L'envoi d'un formulaire valide. Il rend les refus du serveur, que Signal Forms place sous leur
9
+ * champ (`fieldTree`) et au recapitulatif, puis efface des que la valeur du champ change ; rien
10
+ * (`undefined`) pour un envoi reussi.
11
+ */
12
+ export type EnvoiDeFormulaire<TModele> = (formulaire: FieldTree<TModele>) => Promise<TreeValidationResult>;
13
+ /**
14
+ * Un formulaire du socle : la plomberie de l'envoi, ecrite une fois (lot 247).
15
+ *
16
+ * ```html
17
+ * <form [stForm]="virement" [envoyerAvec]="envoyer" (envoi)="confirmer($event)" #formulaire="stForm">
18
+ * <st-error-summary />
19
+ * <st-input libelle="Beneficiaire" [formField]="virement.beneficiaire" />
20
+ * <st-button type="submit" [chargement]="formulaire.enCours()">Envoyer</st-button>
21
+ * </form>
22
+ * ```
23
+ *
24
+ * ```ts
25
+ * readonly envoyer: EnvoiDeFormulaire<Virement> = async (formulaire) => {
26
+ * try {
27
+ * await this.api.virer(formulaire().value());
28
+ * return undefined;
29
+ * } catch (erreur) {
30
+ * return versErreursDeFormulaire(versApiError(erreur), formulaire);
31
+ * }
32
+ * };
33
+ * ```
34
+ *
35
+ * - `novalidate` : les bulles natives du navigateur, dans sa langue, ne doublent pas les messages
36
+ * du socle.
37
+ * - L'envoi (`submit()` de Signal Forms) marque chaque champ touche ; valide, il appelle
38
+ * `envoyerAvec`. Les refus du serveur s'affichent sous leur champ et au recapitulatif.
39
+ * - Pendant l'envoi, le formulaire est `aria-busy` et un second envoi est IGNORE (double clic,
40
+ * Entree repetee) : une seule operation part.
41
+ * - Le `st-error-summary` qu'il contient le lit sans rien lier : il apparait a la premiere
42
+ * tentative refusee et reprend le focus a CHAQUE nouvelle tentative (UX-5), jamais a une simple
43
+ * correction.
44
+ * - ⚠️ Un envoi reussi remet le formulaire au propre (`reset()` : ni touche, ni modifie, valeurs
45
+ * gardees) et `tentative` a zero, PUIS emet `(envoi)` avec la valeur envoyee. Le formulaire vide
46
+ * ensuite ne montre ni recapitulatif focalise ni erreur sous ses champs (constat A0922), meme
47
+ * quand l'application vide son modele dans `envoyerAvec`.
48
+ * - L'option `submission` de `form()` n'est pas lue : l'envoi passe par `envoyerAvec`. Ne pas
49
+ * poser `[formRoot]` sur le meme formulaire, il enverrait une seconde fois.
50
+ *
51
+ * Dans `@starterlib/ui/formulaires` : l'envoi est du CODE d'`@angular/forms`, que
52
+ * `@starterlib/ui/saisie` n'importe pas (ADR 0003, ADR web 0005 D135).
53
+ */
54
+ export declare class StForm<TModele> implements EtatDEnvoi {
55
+ private readonly destruction;
56
+ /** Le formulaire de Signal Forms. */
57
+ readonly stForm: import("@angular/core").InputSignal<FieldTree<TModele>>;
58
+ /** L'envoi, appele seulement quand le formulaire est valide ; `null` : `(envoi)` suffit. */
59
+ readonly envoyerAvec: import("@angular/core").InputSignal<EnvoiDeFormulaire<TModele> | null>;
60
+ /** Emis apres un envoi reussi, avec la valeur envoyee. */
61
+ readonly envoi: import("@angular/core").OutputEmitterRef<TModele>;
62
+ private readonly tentatives;
63
+ /**
64
+ * L'envoi de la directive, de la tentative a son issue. ⚠️ Plus long que `submitting()` de Signal
65
+ * Forms, qui retombe AVANT que la directive remette le formulaire au propre : une detection de
66
+ * changements tombee entre les deux voyait un formulaire vide, une tentative comptee, et le
67
+ * recapitulatif surgissait, focalise, apres un succes.
68
+ */
69
+ private readonly envoiEnCours;
70
+ /** Les tentatives d'envoi depuis le dernier envoi reussi. */
71
+ readonly tentative: import("@angular/core").Signal<number>;
72
+ /**
73
+ * Un envoi court, le sien ou un `submit()` lance ailleurs : le formulaire est `aria-busy`, un
74
+ * second envoi est ignore.
75
+ */
76
+ readonly enCours: import("@angular/core").Signal<boolean>;
77
+ /**
78
+ * Les erreurs a recapituler : aucune avant la premiere tentative, ni pendant l'envoi (un modele
79
+ * vide par `envoyerAvec` ne fait pas surgir le recapitulatif), ni apres un envoi reussi.
80
+ */
81
+ readonly recapitulatif: import("@angular/core").Signal<import("@angular/forms/signals").ValidationError.WithFieldTree[]>;
82
+ protected surEnvoi(evenement: Event): Promise<void>;
83
+ static ɵfac: i0.ɵɵFactoryDeclaration<StForm<any>, never>;
84
+ static ɵdir: i0.ɵɵDirectiveDeclaration<StForm<any>, "form[stForm]", ["stForm"], {
85
+ "stForm": {
86
+ "alias": "stForm";
87
+ "required": true;
88
+ "isSignal": true;
89
+ };
90
+ "envoyerAvec": {
91
+ "alias": "envoyerAvec";
92
+ "required": false;
93
+ "isSignal": true;
94
+ };
95
+ }, {
96
+ "envoi": "envoi";
97
+ }, never, never, true, never>;
98
+ }
99
+ /** Remplissage automatique d'un montant : `transaction-amount` pour un paiement, rien sinon. */
100
+ export type RemplissageDeMontant = 'transaction-amount';
8
101
  /**
9
102
  * Montant, en UNITES MINEURES : `123456n` pour 1 234,56 EUR.
10
103
  *
11
104
  * ```html
12
105
  * <st-amount-field libelle="Montant du virement" devise="EUR" [formField]="virement.montant" />
106
+ * <!-- ou, sans formulaire : -->
107
+ * <st-amount-field #plafond libelle="Plafond" devise="EUR" [(value)]="plafond" />
13
108
  * ```
14
109
  *
15
110
  * ⚠️ **Jamais un nombre a virgule flottante** (SEC-8) : le modele est un `bigint`,
@@ -19,41 +114,339 @@ import { DateIso, PlageDeDates } from '@starterlib/util';
19
114
  * ⚠️ **Un texte ambigu est refuse, jamais devine.** « 1.250 » en francais serait
20
115
  * mille deux cent cinquante ou un virgule vingt-cinq : le champ dit l'erreur et
21
116
  * garde le texte, plutot que d'envoyer un montant mille fois trop grand. Une
22
- * saisie illisible laisse le MODELE inchange et rend le formulaire invalide, par
23
- * `transformedValue` : il ne part pas avec l'ancien montant.
117
+ * saisie illisible remet le MODELE a `null` — en formulaire comme seul (constats A1123,
118
+ * A1169) : aucun montant perime (« 12,34 » d'une frappe « 12,345 ») ne subsiste chez
119
+ * l'appelant. Le formulaire est invalide par `transformedValue` ; employe seul, `lectureInvalide`
120
+ * distingue un champ vide d'un champ illisible.
121
+ *
122
+ * ⚠️ **Une devise mal formee ne casse pas le rendu, et ne jette aucune frappe** : `devise` liee a
123
+ * une donnee en cours de chargement (`compte()?.devise ?? ''`) laisse le champ sans symbole, en
124
+ * lecture seule et `aria-busy`, jusqu'a ce qu'un code de trois lettres arrive (avertissement en
125
+ * developpement), au lieu de lever `RangeError` dans un calcul du gabarit (constats A1177, A1193)
126
+ * — ou d'accepter une frappe qu'il ne saurait pas lire.
127
+ *
128
+ * ⚠️ **Une devise qui change garde le montant qu'on voit.** Le modele est en unites mineures de
129
+ * la devise : reformate dans une autre, « 1 234,50 € » tape devenait « 123 450 ¥ », un montant cent
130
+ * fois plus grand, sans rien dire. Le texte affiche est RELU dans la nouvelle devise (« 1 234,50 »
131
+ * refuse en yens : au plus 0 decimale) ; un montant du modele que la devise attendait (devise en
132
+ * cours de chargement) s'affiche des qu'elle arrive.
133
+ *
134
+ * Le code de la devise est un bloc DANS le cadre (planche 3b), place avant ou apres la valeur
135
+ * selon la locale (`Intl`, « 1 234,56 CHF » en fr-CH, « £1,234.56 » en en-GB) ; il est
136
+ * masque au lecteur d'ecran, qui lit le NOM de la devise en description. Valeur alignee a la
137
+ * fin, chiffres tabulaires a zero barre : plusieurs montants s'alignent en colonne.
24
138
  *
25
139
  * Le groupement « 1 234,56 » s'applique a la sortie du champ, jamais pendant la
26
- * frappe. `type="text"` et `inputmode="decimal"` : `type="number"` accepte
140
+ * frappe, et s'annonce. `type="text"` et `inputmode="decimal"` : `type="number"` accepte
27
141
  * « 1e5 », change la valeur a la molette, et ignore la virgule selon le navigateur.
28
142
  *
29
- * Les bornes — montant minimal, plafond — sont des regles du schema, en unites
30
- * mineures ; le serveur les revalide (SEC-5).
31
- */
32
- declare class StAmountField extends ContratDeChamp implements FormValueControl<bigint | null> {
33
- private readonly libelles;
34
- private readonly locale;
35
- readonly value: _angular_core.ModelSignal<bigint | null>;
36
- /** Code ISO 4217. Fixe l'echelle : 2 decimales en euros, 0 en yens. */
37
- readonly devise: _angular_core.InputSignal<string>;
38
- /** `transaction-amount` pour un paiement. */
39
- readonly autocomplete: _angular_core.InputSignal<string | null>;
40
- /**
41
- * Quitte au moins une fois. Relie a un formulaire, `touched` le dit ; employe
42
- * seul, rien ne le dirait, et une saisie illisible ne s'afficherait jamais.
43
- */
44
- protected readonly quitte: _angular_core.WritableSignal<boolean>;
45
- protected readonly saisie: _angular_forms_signals.TransformedValueSignal<string>;
46
- protected readonly erreursAffichees: _angular_core.Signal<readonly _starterlib_ui.ErreurAffichable[]>;
47
- /** Symbole affiche a cote du champ ; le nom de la devise, lui, est lu. */
48
- protected readonly symbole: _angular_core.Signal<string>;
49
- protected readonly deviseLue: _angular_core.Signal<string>;
50
- protected surSaisie(evenement: Event): void;
51
- protected aLaSortie(): void;
52
- private formater;
53
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<StAmountField, never>;
54
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<StAmountField, "st-amount-field", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "devise": { "alias": "devise"; "required": true; "isSignal": true; }; "autocomplete": { "alias": "autocomplete"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, never>;
55
- }
56
-
143
+ * Les bornes — montant minimal, plafond — sont des regles du schema, en unites mineures
144
+ * (`{ kind: 'min', min: 1000n }`) ; le message les dit en devise (« 10,00 € »), et le serveur
145
+ * les revalide (SEC-5).
146
+ */
147
+ export declare class StAmountField extends ContratDeChamp implements FormValueControl<bigint | null> {
148
+ private readonly libelles;
149
+ private readonly locale;
150
+ protected readonly annonce: AnnonceLocale;
151
+ protected readonly idDevise: string;
152
+ readonly value: import("@angular/core").ModelSignal<bigint | null>;
153
+ /** Code ISO 4217. Fixe l'echelle : 2 decimales en euros, 0 en yens. */
154
+ readonly devise: import("@angular/core").InputSignal<string>;
155
+ /** `transaction-amount` pour un paiement ; rien sinon (WCAG 1.3.5). */
156
+ readonly autocomplete: import("@angular/core").InputSignal<"transaction-amount" | null>;
157
+ /** Texte lu apres l'aide et tenu a jour par l'application (« Solde disponible : … »). */
158
+ readonly complement: import("@angular/core").InputSignal<string | null>;
159
+ /** Toute la largeur de sa colonne, au lieu des 16rem d'un montant de formulaire. */
160
+ readonly pleineLargeur: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
161
+ /**
162
+ * Identifiants d'autres textes qui decrivent le champ (`aria-describedby`) : l'aide du groupe
163
+ * d'une plage (`st-amount-range`, lot 255), lue depuis chaque champ et non du seul groupe.
164
+ */
165
+ readonly decritPar: import("@angular/core").InputSignal<readonly string[]>;
166
+ /**
167
+ * Quitte au moins une fois. Relie a un formulaire, `touched` le dit ; employe
168
+ * seul, rien ne le dirait, et une saisie illisible ne s'afficherait jamais.
169
+ */
170
+ protected readonly quitte: import("@angular/core").WritableSignal<boolean>;
171
+ private avertie;
172
+ /** Le code en majuscules s'il est bien forme, sinon `null` (chargement, faute de frappe). */
173
+ protected readonly deviseSure: import("@angular/core").Signal<string | null>;
174
+ protected readonly saisie: import("@angular/forms/signals").TransformedValueSignal<string>;
175
+ /**
176
+ * Vrai quand le texte saisi n'est pas un montant : le modele vaut alors `null`, comme un champ
177
+ * vide. Pour l'appelant sans formulaire, qui doit distinguer les deux.
178
+ */
179
+ readonly lectureInvalide: import("@angular/core").Signal<boolean>;
180
+ /** Erreurs du schema (bornes dites en devise), puis celles de la lecture. */
181
+ protected readonly erreursAffichees: import("@angular/core").Signal<readonly ErreurAffichable[]>;
182
+ /** Parties de la devise pour la locale : son symbole (« CHF », « € », « £ ») et sa place. */
183
+ private readonly parties;
184
+ /** Symbole affiche dans le cadre ; le nom de la devise, lui, est lu. */
185
+ protected readonly symbole: import("@angular/core").Signal<string>;
186
+ protected readonly symboleAvant: import("@angular/core").Signal<boolean>;
187
+ protected readonly deviseLue: import("@angular/core").Signal<string | null>;
188
+ protected readonly descriptionsDuControle: import("@angular/core").Signal<string[]>;
189
+ constructor();
190
+ /** Un clic sur le bloc de devise ou la marge du cadre donne le focus a la zone de frappe. */
191
+ protected surPressionDuCadre(evenement: MouseEvent): void;
192
+ protected surSaisie(evenement: Event): void;
193
+ protected aLaSortie(): void;
194
+ /** Une borne en unites mineures (`bigint`) se dit en devise : « au moins 10,00 € ». */
195
+ private borneEnDevise;
196
+ private formater;
197
+ static ɵfac: i0.ɵɵFactoryDeclaration<StAmountField, never>;
198
+ static ɵcmp: i0.ɵɵComponentDeclaration<StAmountField, "st-amount-field", never, {
199
+ "value": {
200
+ "alias": "value";
201
+ "required": false;
202
+ "isSignal": true;
203
+ };
204
+ "devise": {
205
+ "alias": "devise";
206
+ "required": true;
207
+ "isSignal": true;
208
+ };
209
+ "autocomplete": {
210
+ "alias": "autocomplete";
211
+ "required": false;
212
+ "isSignal": true;
213
+ };
214
+ "complement": {
215
+ "alias": "complement";
216
+ "required": false;
217
+ "isSignal": true;
218
+ };
219
+ "pleineLargeur": {
220
+ "alias": "pleineLargeur";
221
+ "required": false;
222
+ "isSignal": true;
223
+ };
224
+ "decritPar": {
225
+ "alias": "decritPar";
226
+ "required": false;
227
+ "isSignal": true;
228
+ };
229
+ }, {
230
+ "value": "valueChange";
231
+ }, never, ["[stMeta]", "[stAide]", "[stIndication]"], true, never>;
232
+ }
233
+ /**
234
+ * Les libelles propres a `@starterlib/ui/formulaires` (lot 255) : le catalogue par point d'entree
235
+ * (AD-10, D147), apres celui de la messagerie. Seuls les NOUVEAUX libelles des champs composes y
236
+ * vivent ; ceux d'avant restent au dictionnaire du tronc jusqu'a la cloture du train (lot 268). La
237
+ * langue suit celle du dictionnaire du tronc.
238
+ */
239
+ export interface LibellesFormulaires {
240
+ readonly montantMinimal: string;
241
+ readonly montantMaximal: string;
242
+ readonly frequence: string;
243
+ readonly frequences: Readonly<Record<FrequenceDeRecurrence, string>>;
244
+ readonly intervalle: string;
245
+ /** L'unite de l'intervalle, apres le nombre (« 2 mois »). */
246
+ readonly unitesDIntervalle: Readonly<Record<FrequenceDeRecurrence, string>>;
247
+ readonly jourDuMois: string;
248
+ /** L'option vide du jour du mois : le jour de la premiere echeance, a defaut. */
249
+ readonly jourDeLaPremiereEcheance: string;
250
+ /** L'aide du jour du mois, dite AVANT la saisie : la regle des 29, 30 et 31. */
251
+ readonly regleDeFinDeMois: string;
252
+ readonly premiereEcheance: string;
253
+ readonly fin: string;
254
+ readonly finJamais: string;
255
+ readonly finALaDate: string;
256
+ readonly finApresNombre: string;
257
+ readonly derniereEcheance: string;
258
+ readonly nombreDEcheances: string;
259
+ readonly recapitulatif: string;
260
+ }
261
+ export declare const LIBELLES_FORMULAIRES_FR: LibellesFormulaires;
262
+ export declare const LIBELLES_FORMULAIRES_EN: LibellesFormulaires;
263
+ /** Les catalogues de `formulaires` par langue ; une application en ajoute par la fonction ci-dessous. */
264
+ export declare const ST_LIBELLES_FORMULAIRES: InjectionToken<Readonly<Record<string, LibellesFormulaires>>>;
265
+ export declare function fournirLibellesFormulaires(catalogues: Readonly<Record<string, LibellesFormulaires>>): Provider;
266
+ /**
267
+ * Le catalogue de la langue du dictionnaire du tronc ; le francais a defaut, un repli signale en
268
+ * developpement (audit du 2026-09-27, D-29). A appeler dans un contexte d'injection.
269
+ */
270
+ export declare function libellesDesFormulaires(): Signal<LibellesFormulaires>;
271
+ /**
272
+ * Le catalogue de `formulaires` ET la langue de son repli (`catalogueDuPointDEntree`) : `lang` de
273
+ * ce qu'il ecrit seul (audit du 2026-09-27, D-29). A appeler dans un contexte d'injection.
274
+ */
275
+ export declare function catalogueDesFormulaires(): Signal<CatalogueDuPointDEntree<LibellesFormulaires>>;
276
+ /** Une plage de montants, en unites mineures de la devise (`bigint`), bornes facultatives. */
277
+ export interface PlageDeMontants {
278
+ readonly min: bigint | null;
279
+ readonly max: bigint | null;
280
+ }
281
+ /** Les libelles des deux parties, quand « Montant minimal » ne dit pas la chose. */
282
+ export interface EtiquettesDePlage {
283
+ readonly min: string;
284
+ readonly max: string;
285
+ }
286
+ /**
287
+ * L'erreur de plage, a poser dans le schema :
288
+ * `validate(chemin.plafond, ({ value }) => erreurPlageDeMontants(value()))`. Elle s'affiche sous
289
+ * le MAXIMUM, la partie a corriger.
290
+ */
291
+ export declare function erreurPlageDeMontants(plage: PlageDeMontants): ErreurAffichable | null;
292
+ /**
293
+ * Une plage de montants (lot 255) : un minimum et un maximum dans une meme devise, pour filtrer
294
+ * des operations ou borner un plafond.
295
+ *
296
+ * ```html
297
+ * <st-amount-range libelle="Montant de l'operation" devise="EUR" [formField]="filtres.montant" />
298
+ * ```
299
+ *
300
+ * - Un `st-fieldset` nomme par sa question, deux `st-amount-field` (« Montant minimal »,
301
+ * « Montant maximal ») dans la devise commune.
302
+ * - L'aide du groupe DECRIT les deux champs (`aria-describedby` de chacun), et non le seul
303
+ * `fieldset` : le defaut releve sur `st-date-range` ne se recopie pas.
304
+ * - L'erreur de plage (`erreurPlageDeMontants`) s'affiche sous le maximum, qui passe
305
+ * `aria-invalid` ; `focus()` y va. Une lecture illisible reste sous son champ, et `focus()` va
306
+ * au premier champ en erreur, sinon au minimum.
307
+ * - Catalogue retombe sur le francais (audit du 2026-09-27, D-29) : signale en developpement, sans
308
+ * `lang`. Ses deux libelles nomment des champs de saisie, que partagent le nom de la devise et
309
+ * les erreurs, dans la langue de la page.
310
+ */
311
+ export declare class StAmountRange extends ContratDeChamp implements FormValueControl<PlageDeMontants> {
312
+ protected readonly libellesDesChamps: Signal<LibellesFormulaires>;
313
+ readonly value: import("@angular/core").ModelSignal<PlageDeMontants>;
314
+ /** Code ISO 4217 de la devise commune (« EUR »). */
315
+ readonly devise: import("@angular/core").InputSignal<string>;
316
+ readonly etiquettes: import("@angular/core").InputSignal<EtiquettesDePlage | null>;
317
+ private readonly fieldset;
318
+ private readonly champs;
319
+ /** Quitte au moins une fois : sans formulaire, rien d'autre ne dirait d'afficher les erreurs. */
320
+ protected readonly quitte: import("@angular/core").WritableSignal<boolean>;
321
+ protected readonly etiquettesLues: Signal<EtiquettesDePlage>;
322
+ /** La plage fautive se dit sous le maximum ; les autres erreurs du schema, au groupe. */
323
+ protected readonly erreursDuMaximum: Signal<import("@angular/forms/signals").ValidationError.WithOptionalFieldTree[]>;
324
+ protected readonly erreursDuGroupe: Signal<import("@angular/forms/signals").ValidationError.WithOptionalFieldTree[]>;
325
+ /** L'aide du groupe, quand il en a une : elle decrit chacun des deux champs. */
326
+ protected readonly decritPar: Signal<readonly string[]>;
327
+ protected changer(partie: keyof PlageDeMontants, montant: bigint | null): void;
328
+ protected quitter(): void;
329
+ /** Au maximum quand la plage est fautive, au premier champ illisible, sinon au minimum. */
330
+ focus(options?: FocusOptions): void;
331
+ static ɵfac: i0.ɵɵFactoryDeclaration<StAmountRange, never>;
332
+ static ɵcmp: i0.ɵɵComponentDeclaration<StAmountRange, "st-amount-range", never, {
333
+ "value": {
334
+ "alias": "value";
335
+ "required": false;
336
+ "isSignal": true;
337
+ };
338
+ "devise": {
339
+ "alias": "devise";
340
+ "required": true;
341
+ "isSignal": true;
342
+ };
343
+ "etiquettes": {
344
+ "alias": "etiquettes";
345
+ "required": false;
346
+ "isSignal": true;
347
+ };
348
+ }, {
349
+ "value": "valueChange";
350
+ }, never, never, true, never>;
351
+ }
352
+ /**
353
+ * Sortie du focus HORS d'un composant a calendrier : ferme le calendrier, marque le champ quitte.
354
+ *
355
+ * Un focus parti vers un element du composant n'est pas une sortie ; un focus parti vers un
356
+ * element exterieur (Tab) en est une, tranchee sur-le-champ. Les autres cas se tranchent APRES,
357
+ * sur l'element actif :
358
+ *
359
+ * - ⚠️ **Retrait du DOM** : changer de mois detruit le bouton du jour qui porte le focus, et
360
+ * Chromium emet un `focusout` sans cible. Le calendrier rend le focus au nouveau jour dans le
361
+ * meme rendu : la decision, prise en microtache, trouve le focus revenu, ou une cible retiree.
362
+ * - ⚠️ **Appui dans le composant** (WebKit, constat A1153 ; clic dans le blanc d'un calendrier
363
+ * place dans un `st-dialog`) : le focus part sans cible, ou vers un ancetre focalisable
364
+ * (`cdk-dialog-container`, `main[tabindex=-1]`), AVANT le clic, qui vient au relachement. La
365
+ * decision attend le relachement ; le calendrier annule en plus `mousedown` hors de sa liste
366
+ * d'annees, pour que le focus reste ou il est.
367
+ */
368
+ declare class SortieDuComposant {
369
+ private readonly hote;
370
+ private readonly sortir;
371
+ private appui;
372
+ private enAttente;
373
+ /** Retire les ecouteurs d'un appui en cours ; `null` hors appui. */
374
+ private retirerLesEcouteurs;
375
+ private minuterie;
376
+ /**
377
+ * A construire dans un contexte d'injection (initialiseur de champ du composant) : un composant
378
+ * detruit en plein appui (une route quittee au relachement) ne laisse ni ecouteur sur le document
379
+ * ni minuterie (audit du 2026-09-27, Q-19).
380
+ */
381
+ constructor(hote: HTMLElement, sortir: () => void);
382
+ /** A brancher sur `(pointerdown)` de l'hote. */
383
+ surPointeur(): void;
384
+ /** A brancher sur `(focusout)` de l'hote. */
385
+ surFocusout(evenement: FocusEvent): void;
386
+ private trancher;
387
+ }
388
+ /** Les bornes d'une date, dites dans l'aide AVANT la saisie ; `null` sans borne. */
389
+ declare function texteDesBornes(libelles: LibellesUi, locale: string, min: DateIso | null, max: DateIso | null): string | null;
390
+ /** Les raccourcis en liste pleine largeur (planche 3a) ou en grille de deux colonnes (planche 3b). */
391
+ type DispositionDesRaccourcis = 'liste' | 'grille';
392
+ /** Un raccourci tel que le groupe l'affiche. */
393
+ interface RaccourciAffiche {
394
+ readonly cle: string;
395
+ readonly libelle: string;
396
+ readonly precision: string | null;
397
+ readonly choisi: boolean;
398
+ }
399
+ /**
400
+ * Raccourcis d'une date ou d'une periode (interne a `ui/formulaires`) : des BOUTONS A BASCULE
401
+ * (`aria-pressed`, ADR 0005, D66), pas des puces de filtre, dans un groupe nomme par son titre.
402
+ * Le raccourci choisi est celui dont la valeur est dans le modele : filet primaire double (rien ne
403
+ * bouge), texte primaire, coche ; la precision (« J-30 ») est un repere visuel, le nom est le
404
+ * libelle seul, stable quel que soit l'etat.
405
+ */
406
+ declare class StRaccourcisDeDates {
407
+ readonly titre: import("@angular/core").InputSignal<string>;
408
+ readonly disposition: import("@angular/core").InputSignal<DispositionDesRaccourcis>;
409
+ readonly raccourcis: import("@angular/core").InputSignal<readonly RaccourciAffiche[]>;
410
+ readonly desactive: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
411
+ /** La cle du raccourci active. */
412
+ readonly choix: import("@angular/core").OutputEmitterRef<string>;
413
+ protected readonly idDuTitre: string;
414
+ static ɵfac: i0.ɵɵFactoryDeclaration<StRaccourcisDeDates, never>;
415
+ static ɵcmp: i0.ɵɵComponentDeclaration<StRaccourcisDeDates, "st-raccourcis-de-dates", never, {
416
+ "titre": {
417
+ "alias": "titre";
418
+ "required": true;
419
+ "isSignal": true;
420
+ };
421
+ "disposition": {
422
+ "alias": "disposition";
423
+ "required": false;
424
+ "isSignal": true;
425
+ };
426
+ "raccourcis": {
427
+ "alias": "raccourcis";
428
+ "required": true;
429
+ "isSignal": true;
430
+ };
431
+ "desactive": {
432
+ "alias": "desactive";
433
+ "required": false;
434
+ "isSignal": true;
435
+ };
436
+ }, {
437
+ "choix": "choix";
438
+ }, never, never, true, never>;
439
+ }
440
+ /**
441
+ * Une date predefinie (« Fin de mois ») : l'application la calcule, le composant n'a pas
442
+ * d'horloge. `precision` est un repere visuel court, non lu.
443
+ */
444
+ export interface RaccourciDeDate {
445
+ readonly cle: string;
446
+ readonly libelle: string;
447
+ readonly precision?: string;
448
+ readonly date: DateIso;
449
+ }
57
450
  /**
58
451
  * Date calendaire : un champ texte, et un calendrier pour qui prefere choisir.
59
452
  *
@@ -72,52 +465,141 @@ declare class StAmountField extends ContratDeChamp implements FormValueControl<b
72
465
  * `jj/mm/aaaa` ou `mm/dd/yyyy` — suit la langue courante, et il est dit en aide.
73
466
  *
74
467
  * ⚠️ **Le calendrier est une aide, pas la seule voie** : une date de naissance
75
- * se tape plus vite qu'elle ne se cherche mois par mois. Il s'ouvre sous le champ,
76
- * dans le flux de la page : pas de surcouche a positionner, rien de rogne dans
77
- * un dialogue, et le CDK n'entre pas dans les formulaires.
78
- *
79
- * Une date illisible ou inexistante — « 31/02/2026 » — garde le texte, laisse le
80
- * modele inchange et rend le formulaire invalide.
81
- */
82
- declare class StDateField extends ContratDeChamp implements FormValueControl<DateIso | null> {
83
- protected readonly libelles: _angular_core.Signal<_starterlib_ui.LibellesUi>;
84
- private readonly locale;
85
- private readonly element;
86
- private readonly injecteur;
87
- readonly value: _angular_core.ModelSignal<string | null>;
88
- /** Bornes du calendrier. Les memes que celles du schema : voir `erreurDate`. */
89
- readonly dateMin: _angular_core.InputSignal<string | null>;
90
- readonly dateMax: _angular_core.InputSignal<string | null>;
91
- /** `bday` pour une date de naissance. */
92
- readonly autocomplete: _angular_core.InputSignal<string | null>;
93
- protected readonly ouvert: _angular_core.WritableSignal<boolean>;
94
- protected readonly identifiantCalendrier: string;
95
- private readonly calendrier;
96
- private readonly bouton;
97
- /**
98
- * Quitte au moins une fois. Relie a un formulaire, `touched` le dit ; employe
99
- * seul, rien ne le dirait, et une saisie illisible ne s'afficherait jamais.
100
- */
101
- protected readonly quitte: _angular_core.WritableSignal<boolean>;
102
- protected readonly saisie: _angular_forms_signals.TransformedValueSignal<string>;
103
- protected readonly aideLue: _angular_core.Signal<string>;
104
- protected readonly erreursAffichees: _angular_core.Signal<readonly _starterlib_ui.ErreurAffichable[]>;
105
- protected surSaisie(evenement: Event): void;
106
- protected aLaSortieDuChamp(): void;
107
- protected basculer(): void;
108
- protected choisir(date: DateIso): void;
109
- /** Echap rend le focus au bouton qui a ouvert le calendrier. */
110
- protected fermer(rendreLeFocus: boolean): void;
111
- protected aLaSortieDuComposant(evenement: FocusEvent): void;
112
- private formater;
113
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<StDateField, never>;
114
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<StDateField, "st-date-field", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "dateMin": { "alias": "dateMin"; "required": false; "isSignal": true; }; "dateMax": { "alias": "dateMax"; "required": false; "isSignal": true; }; "autocomplete": { "alias": "autocomplete"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, never>;
115
- }
116
-
468
+ * se tape plus vite qu'elle ne se cherche mois par mois. Il flotte sous le champ, dans la couche
469
+ * superieure du navigateur, comme la liste d'un `select` (ADR 0005, D132 : popover natif) : rien
470
+ * ne descend ni ne bouge autour, rien n'est rogne dans un dialogue, et le CDK n'entre toujours
471
+ * pas dans les formulaires.
472
+ *
473
+ * Une date illisible ou inexistante — « 31/02/2026 » — garde le texte, VIDE le modele
474
+ * (`null`, jamais la derniere date lisible : un appelant en `[(value)]` ne part pas avec une
475
+ * date perimee) et rend le formulaire invalide. Les bornes `dateMin` / `dateMax` se disent dans
476
+ * l'aide, avant la saisie ; Alt + Fleche bas ouvre le calendrier depuis le champ.
477
+ */
478
+ export declare class StDateField extends ContratDeChamp implements FormValueControl<DateIso | null> {
479
+ protected readonly libelles: import("@angular/core").Signal<import("@starterlib/ui").LibellesUi>;
480
+ private readonly locale;
481
+ private readonly element;
482
+ private readonly injecteur;
483
+ readonly value: import("@angular/core").ModelSignal<string | null>;
484
+ /** Bornes du calendrier. Les memes que celles du schema : voir `erreurDate`. */
485
+ readonly dateMin: import("@angular/core").InputSignal<string | null>;
486
+ readonly dateMax: import("@angular/core").InputSignal<string | null>;
487
+ /** `bday` pour une date de naissance. */
488
+ readonly autocomplete: import("@angular/core").InputSignal<string | null>;
489
+ /** Annees du saut d'annee du calendrier (`{ min: 1900, max: 2026 }` pour une naissance). */
490
+ readonly annees: import("@angular/core").InputSignal<AnneesDuCalendrier | null>;
491
+ /** Dates predefinies, en boutons a bascule sous le champ (planche 3b, D66). */
492
+ readonly raccourcis: import("@angular/core").InputSignal<readonly RaccourciDeDate[]>;
493
+ /** `liste` (defaut) ou `grille` de deux colonnes (planche 3b). */
494
+ readonly dispositionDesRaccourcis: import("@angular/core").InputSignal<DispositionDesRaccourcis>;
495
+ /** Titre des raccourcis. Par defaut : « Dates predefinies ». */
496
+ readonly titreDesRaccourcis: import("@angular/core").InputSignal<string | null>;
497
+ /** Les raccourcis, dont celui qui est dans le modele (le choisi). */
498
+ protected readonly raccourcisAffiches: import("@angular/core").Signal<readonly RaccourciAffiche[]>;
499
+ protected readonly titreDesRaccourcisLu: import("@angular/core").Signal<string>;
500
+ /** Un raccourci pose sa date dans le modele ; le focus reste sur lui (`aria-pressed`). */
501
+ protected choisirUnRaccourci(cle: string): void;
502
+ protected readonly ouvert: import("@angular/core").WritableSignal<boolean>;
503
+ protected readonly identifiantCalendrier: string;
504
+ private readonly calendrier;
505
+ private readonly bouton;
506
+ /**
507
+ * Quitte au moins une fois. Relie a un formulaire, `touched` le dit ; employe
508
+ * seul, rien ne le dirait, et une saisie illisible ne s'afficherait jamais.
509
+ */
510
+ protected readonly quitte: import("@angular/core").WritableSignal<boolean>;
511
+ protected readonly saisie: import("@angular/forms/signals").TransformedValueSignal<string>;
512
+ /**
513
+ * La saisie est-elle illisible ? Le modele vaut alors `null` (la partie fautive, pour une
514
+ * plage), comme un champ vide : l'appelant sans formulaire distingue les deux par lui.
515
+ */
516
+ readonly lectureInvalide: import("@angular/core").Signal<boolean>;
517
+ protected readonly aideLue: import("@angular/core").Signal<string>;
518
+ /** Sortie du focus hors du composant : ferme le calendrier et marque le champ quitte. */
519
+ protected readonly sortie: SortieDuComposant;
520
+ protected readonly erreursAffichees: import("@angular/core").Signal<readonly import("@starterlib/ui/saisie").ErreurAffichable[]>;
521
+ protected surSaisie(evenement: Event): void;
522
+ /** Alt + Fleche bas ouvre le calendrier depuis le champ (motif APG d'une liste deroulante). */
523
+ protected surToucheDuChamp(evenement: KeyboardEvent): void;
524
+ /**
525
+ * Echap, calendrier ouvert, focus sur le champ ou le bouton : ferme et s'arrete ici (un
526
+ * `st-dialog` hote ne se ferme pas avec le calendrier). Depuis la grille, le calendrier l'a deja
527
+ * consommee.
528
+ */
529
+ protected surEchap(evenement: Event): void;
530
+ protected aLaSortieDuChamp(): void;
531
+ protected basculer(): void;
532
+ protected choisir(date: DateIso): void;
533
+ /** Echap (et le bouton qui referme) rend le focus au bouton qui a ouvert le calendrier. */
534
+ protected fermer(rendreLeFocus: boolean): void;
535
+ private formater;
536
+ static ɵfac: i0.ɵɵFactoryDeclaration<StDateField, never>;
537
+ static ɵcmp: i0.ɵɵComponentDeclaration<StDateField, "st-date-field", never, {
538
+ "value": {
539
+ "alias": "value";
540
+ "required": false;
541
+ "isSignal": true;
542
+ };
543
+ "dateMin": {
544
+ "alias": "dateMin";
545
+ "required": false;
546
+ "isSignal": true;
547
+ };
548
+ "dateMax": {
549
+ "alias": "dateMax";
550
+ "required": false;
551
+ "isSignal": true;
552
+ };
553
+ "autocomplete": {
554
+ "alias": "autocomplete";
555
+ "required": false;
556
+ "isSignal": true;
557
+ };
558
+ "annees": {
559
+ "alias": "annees";
560
+ "required": false;
561
+ "isSignal": true;
562
+ };
563
+ "raccourcis": {
564
+ "alias": "raccourcis";
565
+ "required": false;
566
+ "isSignal": true;
567
+ };
568
+ "dispositionDesRaccourcis": {
569
+ "alias": "dispositionDesRaccourcis";
570
+ "required": false;
571
+ "isSignal": true;
572
+ };
573
+ "titreDesRaccourcis": {
574
+ "alias": "titreDesRaccourcis";
575
+ "required": false;
576
+ "isSignal": true;
577
+ };
578
+ }, {
579
+ "value": "valueChange";
580
+ }, never, never, true, never>;
581
+ }
117
582
  type Partie = 'debut' | 'fin';
583
+ /**
584
+ * Une periode predefinie (« 30 derniers jours ») : l'application en calcule les dates, le composant
585
+ * n'a pas d'horloge. `precision` est un repere visuel court (« J-30 »), non lu.
586
+ */
587
+ export interface RaccourciDePeriode {
588
+ readonly cle: string;
589
+ readonly libelle: string;
590
+ readonly precision?: string;
591
+ readonly plage: PlageDeDates;
592
+ }
593
+ /**
594
+ * `complete` : les deux champs et leurs calendriers. `resume` (planche 4, barre de filtres) : un
595
+ * bouton-champ qui dit la periode (« 1–30 sept. 2026 ») et deploie les champs dessous.
596
+ */
597
+ export type VarianteDePlage = 'complete' | 'resume';
598
+ /** Le style de l'etiquette de la variante `resume` (`micro-capitales` dans une barre de filtres). */
599
+ export type PresentationDePlage = 'libelle' | 'micro-capitales';
118
600
  interface SaisieDePlage {
119
- readonly debut: string;
120
- readonly fin: string;
601
+ readonly debut: string;
602
+ readonly fin: string;
121
603
  }
122
604
  /**
123
605
  * Plage de dates : un debut, une fin, dans un groupe nomme par sa question.
@@ -137,62 +619,616 @@ interface SaisieDePlage {
137
619
  * lequel des champs est faux. L'erreur de lecture marque aussi son champ
138
620
  * `aria-invalid`, et lui seul.
139
621
  *
622
+ * ⚠️ **Chaque partie se lit seule** : une partie illisible passe a `null` dans le modele, l'autre
623
+ * y entre telle quelle (plus de « tout ou rien » : un debut efface ne reste pas dans le modele
624
+ * parce que la fin est illisible). Le formulaire reste invalide tant qu'une partie l'est.
625
+ *
626
+ * Chaque champ est decrit par l'aide du groupe et, en erreur, par ses messages (`aria-describedby`,
627
+ * `aria-errormessage`) ; une erreur du GROUPE (`required`) marque les deux champs. `focus()` va a
628
+ * la premiere partie en erreur, sinon au debut ; Echap rend le focus au bouton qui a ouvert.
629
+ *
140
630
  * L'obligation d'une borne est une regle du schema : `required` ne sait pas ce
141
631
  * qu'est une plage « vide ».
142
632
  */
143
- declare class StDateRange extends ContratDeChamp implements FormValueControl<PlageDeDates> {
144
- protected readonly libelles: _angular_core.Signal<_starterlib_ui.LibellesUi>;
145
- private readonly locale;
146
- private readonly element;
147
- private readonly injecteur;
148
- readonly value: _angular_core.ModelSignal<PlageDeDates>;
149
- readonly dateMin: _angular_core.InputSignal<string | null>;
150
- readonly dateMax: _angular_core.InputSignal<string | null>;
151
- /** Etiquettes des deux champs. Par defaut : « Date de debut », « Date de fin ». */
152
- readonly libelleDebut: _angular_core.InputSignal<string | null>;
153
- readonly libelleFin: _angular_core.InputSignal<string | null>;
154
- protected readonly parties: readonly Partie[];
155
- protected readonly ouvert: _angular_core.WritableSignal<Partie | null>;
156
- protected readonly identifiants: {
157
- readonly debut: `${string}-debut`;
158
- readonly fin: `${string}-fin`;
159
- readonly calendrier: `${string}-calendrier`;
160
- };
161
- private readonly calendrier;
162
- /**
163
- * Quitte au moins une fois. Relie a un formulaire, `touched` le dit ; employe
164
- * seul, rien ne le dirait, et une saisie illisible ne s'afficherait jamais.
165
- */
166
- protected readonly quitte: _angular_core.WritableSignal<boolean>;
167
- protected readonly saisie: _angular_forms_signals.TransformedValueSignal<SaisieDePlage>;
168
- protected readonly etiquettes: _angular_core.Signal<{
169
- debut: string;
170
- fin: string;
171
- }>;
172
- protected readonly aideLue: _angular_core.Signal<string>;
173
- /** Chaque erreur prefixee de sa partie, dans la langue courante. */
174
- protected readonly erreursAffichees: _angular_core.Signal<readonly ErreurAffichable[]>;
175
- protected readonly invalide: _angular_core.Signal<{
176
- debut: boolean;
177
- fin: boolean;
178
- }>;
179
- protected surSaisie(partie: Partie, evenement: Event): void;
180
- protected aLaSortieDuChamp(): void;
181
- protected basculer(partie: Partie): void;
182
- protected bornes(partie: Partie): {
183
- min: DateIso | null;
184
- max: DateIso | null;
185
- };
186
- protected choisir(partie: Partie, date: DateIso): void;
187
- protected fermer(partie: Partie): void;
188
- protected aLaSortieDuComposant(evenement: FocusEvent): void;
189
- /** `null` : vide. `undefined` : illisible. */
190
- private lirePartie;
191
- private formater;
192
- /** La partie visee : celle d'une erreur de lecture, la fin pour une plage inversee. */
193
- private partieDe;
194
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<StDateRange, never>;
195
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<StDateRange, "st-date-range", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "dateMin": { "alias": "dateMin"; "required": false; "isSignal": true; }; "dateMax": { "alias": "dateMax"; "required": false; "isSignal": true; }; "libelleDebut": { "alias": "libelleDebut"; "required": false; "isSignal": true; }; "libelleFin": { "alias": "libelleFin"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, never>;
196
- }
197
-
198
- export { StAmountField, StDateField, StDateRange };
633
+ export declare class StDateRange extends ContratDeChamp implements FormValueControl<PlageDeDates> {
634
+ protected readonly libelles: import("@angular/core").Signal<import("@starterlib/ui").LibellesUi>;
635
+ private readonly locale;
636
+ private readonly element;
637
+ private readonly injecteur;
638
+ readonly value: import("@angular/core").ModelSignal<PlageDeDates>;
639
+ readonly dateMin: import("@angular/core").InputSignal<string | null>;
640
+ readonly dateMax: import("@angular/core").InputSignal<string | null>;
641
+ /** Etiquettes des deux champs. Par defaut : « Date de debut », « Date de fin ». */
642
+ readonly libelleDebut: import("@angular/core").InputSignal<string | null>;
643
+ readonly libelleFin: import("@angular/core").InputSignal<string | null>;
644
+ /** Annees du saut d'annee du calendrier. */
645
+ readonly annees: import("@angular/core").InputSignal<AnneesDuCalendrier | null>;
646
+ /** Periodes predefinies, en boutons a bascule au-dessus des champs (planche 3a, D66). */
647
+ readonly raccourcis: import("@angular/core").InputSignal<readonly RaccourciDePeriode[]>;
648
+ /** `liste` (defaut, planche 3a) ou `grille` de deux colonnes (planche 3b). */
649
+ readonly dispositionDesRaccourcis: import("@angular/core").InputSignal<DispositionDesRaccourcis>;
650
+ /** Titre des raccourcis. Par defaut : « Periodes predefinies ». */
651
+ readonly titreDesRaccourcis: import("@angular/core").InputSignal<string | null>;
652
+ /** `complete` (defaut) ou `resume` : un bouton-champ qui deploie les champs (planche 4). */
653
+ readonly variante: import("@angular/core").InputSignal<VarianteDePlage>;
654
+ /** L'etiquette de la variante `resume`. */
655
+ readonly presentation: import("@angular/core").InputSignal<PresentationDePlage>;
656
+ protected readonly parties: readonly Partie[];
657
+ protected readonly ouvert: import("@angular/core").WritableSignal<Partie | null>;
658
+ /** Variante `resume` : les champs deployes sous le bouton-champ. */
659
+ protected readonly deploye: import("@angular/core").WritableSignal<boolean>;
660
+ protected readonly identifiants: {
661
+ readonly debut: `${string}-debut`;
662
+ readonly fin: `${string}-fin`;
663
+ readonly boutons: {
664
+ readonly debut: `${string}-bouton-debut`;
665
+ readonly fin: `${string}-bouton-fin`;
666
+ };
667
+ readonly calendrier: `${string}-calendrier`;
668
+ readonly resume: `${string}-resume`;
669
+ readonly libelleDuResume: `${string}-resume-libelle`;
670
+ readonly valeurDuResume: `${string}-resume-valeur`;
671
+ readonly detail: `${string}-detail`;
672
+ };
673
+ private readonly calendrier;
674
+ private readonly fieldset;
675
+ /** Les lignes des deux parties, ancres de leur calendrier flottant. */
676
+ private readonly lignes;
677
+ /**
678
+ * Quitte au moins une fois. Relie a un formulaire, `touched` le dit ; employe
679
+ * seul, rien ne le dirait, et une saisie illisible ne s'afficherait jamais.
680
+ */
681
+ protected readonly quitte: import("@angular/core").WritableSignal<boolean>;
682
+ protected readonly saisie: import("@angular/forms/signals").TransformedValueSignal<SaisieDePlage>;
683
+ /**
684
+ * La saisie est-elle illisible ? Le modele vaut alors `null` (la partie fautive, pour une
685
+ * plage), comme un champ vide : l'appelant sans formulaire distingue les deux par lui.
686
+ */
687
+ readonly lectureInvalide: import("@angular/core").Signal<boolean>;
688
+ protected readonly etiquettes: import("@angular/core").Signal<{
689
+ debut: string;
690
+ fin: string;
691
+ }>;
692
+ protected readonly aideLue: import("@angular/core").Signal<string>;
693
+ /** Les raccourcis, dont celui qui est dans le modele (le choisi). */
694
+ protected readonly raccourcisAffiches: import("@angular/core").Signal<readonly RaccourciAffiche[]>;
695
+ protected readonly titreDesRaccourcisLu: import("@angular/core").Signal<string>;
696
+ /**
697
+ * La periode dite par le bouton-champ de la variante `resume` : « 1–30 sept. 2026 » par `Intl`
698
+ * (formatRange, dans la langue de la page), une borne seule par « A partir du » ou « Jusqu’au »,
699
+ * rien choisi par « Choisir une periode ».
700
+ */
701
+ protected readonly periodeLue: import("@angular/core").Signal<string>;
702
+ protected readonly periodeChoisie: import("@angular/core").Signal<boolean>;
703
+ /**
704
+ * Sortie du focus hors du composant : ferme le calendrier (et le panneau de la variante resume)
705
+ * et marque le champ quitte.
706
+ */
707
+ protected readonly sortie: SortieDuComposant;
708
+ /**
709
+ * Chaque erreur prefixee de sa partie, dans la langue courante et avec SA ponctuation
710
+ * (`libelleEtMessage` : « Date de fin : ... », « End date: ... ») ; le separateur ecrit en dur
711
+ * mettait une espace insecable avant les deux-points jusqu'en anglais (audit UI du 2026-09-27,
712
+ * D-26).
713
+ */
714
+ protected readonly erreursAffichees: import("@angular/core").Signal<readonly ErreurAffichable[]>;
715
+ /** Parties en erreur. Une erreur du GROUPE (`required`, regle du schema) les vise toutes deux. */
716
+ private readonly enErreur;
717
+ protected readonly invalide: import("@angular/core").Signal<{
718
+ debut: boolean;
719
+ fin: boolean;
720
+ }>;
721
+ /**
722
+ * Description de chaque champ : l'aide du groupe, puis ses erreurs quand il est invalide (WCAG
723
+ * 3.3.1 et 3.3.3 au niveau du CHAMP, et non du seul `fieldset`). Les messages sont prefixes de
724
+ * leur partie : lus depuis un champ, ils disent lequel corriger.
725
+ */
726
+ protected readonly descriptions: import("@angular/core").Signal<{
727
+ debut: string | null;
728
+ fin: string | null;
729
+ erreur: `${string}-erreur` | null;
730
+ }>;
731
+ /** Un raccourci pose sa periode dans le modele ; le focus reste sur lui (`aria-pressed`). */
732
+ protected choisirUnRaccourci(cle: string): void;
733
+ /**
734
+ * Variante `resume` : le bouton-champ ouvre le panneau des champs, en couche flottante sous lui,
735
+ * et y porte le focus (le premier raccourci, sinon la date de debut) ; il le referme.
736
+ */
737
+ protected basculerLeResume(): void;
738
+ /** L'ancre du calendrier d'une partie : sa ligne (champ et bouton). */
739
+ protected ancreDe(partie: Partie): HTMLElement | null;
740
+ protected surSaisie(partie: Partie, evenement: Event): void;
741
+ /** Alt + Fleche bas ouvre le calendrier de la partie depuis son champ. */
742
+ protected surToucheDuChamp(partie: Partie, evenement: KeyboardEvent): void;
743
+ /**
744
+ * Echap, calendrier ouvert, focus sur un champ ou un bouton : ferme et s'arrete ici (un
745
+ * `st-dialog` hote ne se ferme pas avec le calendrier).
746
+ */
747
+ protected surEchap(evenement: Event): void;
748
+ protected aLaSortieDuChamp(): void;
749
+ protected basculer(partie: Partie): void;
750
+ protected bornes(partie: Partie): {
751
+ min: DateIso | null;
752
+ max: DateIso | null;
753
+ };
754
+ protected choisir(partie: Partie, date: DateIso): void;
755
+ /**
756
+ * Ferme le calendrier. Apres un choix, le focus revient au CHAMP (la date s'y relit et se
757
+ * corrige au clavier) ; apres Echap, au BOUTON qui a ouvert, comme `st-date-field`.
758
+ */
759
+ protected fermer(partie: Partie, versLeBouton?: boolean): void;
760
+ /**
761
+ * Appele par Signal Forms pour amener le focus sur un champ en erreur : la PREMIERE partie en
762
+ * erreur (la fin, si seule la fin l'est), sinon le debut.
763
+ */
764
+ focus(options?: FocusOptions): void;
765
+ /** `null` : vide. `undefined` : illisible. */
766
+ private lirePartie;
767
+ private formater;
768
+ /** La partie visee : celle d'une erreur de lecture, la fin pour une plage inversee. */
769
+ private partieDe;
770
+ static ɵfac: i0.ɵɵFactoryDeclaration<StDateRange, never>;
771
+ static ɵcmp: i0.ɵɵComponentDeclaration<StDateRange, "st-date-range", never, {
772
+ "value": {
773
+ "alias": "value";
774
+ "required": false;
775
+ "isSignal": true;
776
+ };
777
+ "dateMin": {
778
+ "alias": "dateMin";
779
+ "required": false;
780
+ "isSignal": true;
781
+ };
782
+ "dateMax": {
783
+ "alias": "dateMax";
784
+ "required": false;
785
+ "isSignal": true;
786
+ };
787
+ "libelleDebut": {
788
+ "alias": "libelleDebut";
789
+ "required": false;
790
+ "isSignal": true;
791
+ };
792
+ "libelleFin": {
793
+ "alias": "libelleFin";
794
+ "required": false;
795
+ "isSignal": true;
796
+ };
797
+ "annees": {
798
+ "alias": "annees";
799
+ "required": false;
800
+ "isSignal": true;
801
+ };
802
+ "raccourcis": {
803
+ "alias": "raccourcis";
804
+ "required": false;
805
+ "isSignal": true;
806
+ };
807
+ "dispositionDesRaccourcis": {
808
+ "alias": "dispositionDesRaccourcis";
809
+ "required": false;
810
+ "isSignal": true;
811
+ };
812
+ "titreDesRaccourcis": {
813
+ "alias": "titreDesRaccourcis";
814
+ "required": false;
815
+ "isSignal": true;
816
+ };
817
+ "variante": {
818
+ "alias": "variante";
819
+ "required": false;
820
+ "isSignal": true;
821
+ };
822
+ "presentation": {
823
+ "alias": "presentation";
824
+ "required": false;
825
+ "isSignal": true;
826
+ };
827
+ }, {
828
+ "value": "valueChange";
829
+ }, never, never, true, never>;
830
+ }
831
+ /**
832
+ * Heure d'horloge : un champ texte, au format de la langue courante.
833
+ *
834
+ * ```html
835
+ * <st-time-field libelle="Heure d'execution" heureMin="08:00" heureMax="18:00"
836
+ * fuseau="Europe/Paris" [formField]="virement.heure" />
837
+ * <!-- schema : validate(chemin.heure, ({ value }) => erreurHeure(value(), { min: '08:00', max: '18:00' })) -->
838
+ * ```
839
+ *
840
+ * Le modele est une heure `HH:MM` (`HH:MM:SS` avec `secondes`) ou `null`, jamais un objet
841
+ * `Date` : une heure de rendez-vous n'a ni date ni fuseau. Le fuseau, s'il compte, se dit en aide
842
+ * (`fuseau`, un nom IANA) : il ne change pas la valeur.
843
+ *
844
+ * ⚠️ **Un champ texte, jamais `type="time"`** (D7 de l'audit de la vague 3, comme les dates ;
845
+ * ADR 0005, D110) : le champ natif suit la langue du NAVIGATEUR, pas celle de l'application, et son
846
+ * rendu varie d'un moteur a l'autre. Le format attendu — `hh:mm`, ou `hh:mm AM/PM` — et un exemple
847
+ * sont dits en aide.
848
+ *
849
+ * ⚠️ **Rien n'est devine** (`lireHeure`) : « 2:30 » sans marque, dans une locale a douze heures,
850
+ * est refuse ; « 2:30 pm » dans une locale a vingt-quatre heures aussi. « 1430 » se lit 14:30 :
851
+ * le pave numerique d'un telephone n'a pas de deux-points. Une saisie illisible garde le texte,
852
+ * vide le modele et rend le formulaire invalide, comme `st-date-field`.
853
+ */
854
+ export declare class StTimeField extends ContratDeChamp implements FormValueControl<HeureIso | null> {
855
+ protected readonly libelles: import("@angular/core").Signal<LibellesUi>;
856
+ private readonly locale;
857
+ readonly value: import("@angular/core").ModelSignal<string | null>;
858
+ /** Bornes dites dans l'aide ; les memes que celles du schema (`erreurHeure`). */
859
+ readonly heureMin: import("@angular/core").InputSignal<string | null>;
860
+ readonly heureMax: import("@angular/core").InputSignal<string | null>;
861
+ /** Lire et rendre les secondes (`HH:MM:SS`). */
862
+ readonly secondes: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
863
+ /** Le fuseau de l'heure (IANA, `Europe/Paris`), nomme dans l'aide. */
864
+ readonly fuseau: import("@angular/core").InputSignal<string | null>;
865
+ readonly autocomplete: import("@angular/core").InputSignal<string | null>;
866
+ /**
867
+ * Quitte au moins une fois. Relie a un formulaire, `touched` le dit ; employe seul, rien ne le
868
+ * dirait, et une saisie illisible ne s'afficherait jamais.
869
+ */
870
+ protected readonly quitte: import("@angular/core").WritableSignal<boolean>;
871
+ protected readonly saisie: import("@angular/forms/signals").TransformedValueSignal<string>;
872
+ /** La saisie est-elle illisible ? Le modele vaut alors `null`, comme un champ vide. */
873
+ readonly lectureInvalide: import("@angular/core").Signal<boolean>;
874
+ /** Le pave numerique la ou l'heure s'ecrit en chiffres ; le clavier complet pour « PM ». */
875
+ protected readonly clavier: import("@angular/core").Signal<"numeric" | "text">;
876
+ /** Le nom generique d'un fuseau se lit a une date d'aujourd'hui (util ne lit pas l'horloge). */
877
+ private readonly instantDuNomDeFuseau;
878
+ protected readonly aideLue: import("@angular/core").Signal<string>;
879
+ constructor();
880
+ protected readonly erreursAffichees: import("@angular/core").Signal<readonly import("@starterlib/ui/saisie").ErreurAffichable[]>;
881
+ protected surSaisie(evenement: Event): void;
882
+ protected aLaSortieDuChamp(): void;
883
+ private formater;
884
+ static ɵfac: i0.ɵɵFactoryDeclaration<StTimeField, never>;
885
+ static ɵcmp: i0.ɵɵComponentDeclaration<StTimeField, "st-time-field", never, {
886
+ "value": {
887
+ "alias": "value";
888
+ "required": false;
889
+ "isSignal": true;
890
+ };
891
+ "heureMin": {
892
+ "alias": "heureMin";
893
+ "required": false;
894
+ "isSignal": true;
895
+ };
896
+ "heureMax": {
897
+ "alias": "heureMax";
898
+ "required": false;
899
+ "isSignal": true;
900
+ };
901
+ "secondes": {
902
+ "alias": "secondes";
903
+ "required": false;
904
+ "isSignal": true;
905
+ };
906
+ "fuseau": {
907
+ "alias": "fuseau";
908
+ "required": false;
909
+ "isSignal": true;
910
+ };
911
+ "autocomplete": {
912
+ "alias": "autocomplete";
913
+ "required": false;
914
+ "isSignal": true;
915
+ };
916
+ }, {
917
+ "value": "valueChange";
918
+ }, never, never, true, never>;
919
+ }
920
+ /**
921
+ * Nombre tape en chiffres : une quantite, une duree, un taux. Pas pour l'argent (`st-amount-field`,
922
+ * unites mineures).
923
+ *
924
+ * ```html
925
+ * <st-number-field libelle="Duree du pret" unite="mois" pas="12" [formField]="pret.duree" />
926
+ * <!-- schema : min(chemin.duree, 12) ; max(chemin.duree, 360) -->
927
+ * ```
928
+ *
929
+ * ⚠️ **Un champ texte, jamais `type="number"`** (GOV.UK) : le champ natif change la valeur a la
930
+ * molette, accepte « 1e5 », et lit la virgule ou non selon le navigateur. `inputmode` ouvre le
931
+ * pave numerique (`decimal` quand le champ admet des decimales).
932
+ *
933
+ * ⚠️ **Rien n'est devine** (`lireNombre`, les regles de `lireMontant`) : « 1.250 » en francais est
934
+ * refuse. Une saisie illisible garde le texte, vide le modele (aucun nombre perime, constat A1123)
935
+ * et rend le formulaire invalide ; `lectureInvalide` le dit a l'appelant sans formulaire. Des
936
+ * decimales dans un entier (`decimales` 0, par defaut) : « Saisissez un nombre entier. »
937
+ *
938
+ * - `pas` : les boutons - et + DANS le cadre, et le motif « spinbutton » de l'APG (fleches haut et
939
+ * bas, Page haut et bas de dix pas, Debut et Fin aux bornes) ; sans `pas`, un champ texte
940
+ * ordinaire. Les boutons, nommes « Diminuer <libelle> » et « Augmenter <libelle> » (D127), ne
941
+ * prennent pas le focus : le clavier passe par les fleches. Un modele vide commence a la borne
942
+ * basse (ou a 0).
943
+ * - Bornes : `min` et `max` du schema (Signal Forms les pose) ; le pas s'y arrete, et les messages
944
+ * les disent. Le serveur les revalide (SEC-5).
945
+ * - `unite` : dans le cadre, apres la valeur (« mois », « % »), masquee au lecteur d'ecran qui la
946
+ * lit en description.
947
+ *
948
+ * Le groupement « 1 234 » s'applique a la sortie du champ, jamais pendant la frappe.
949
+ */
950
+ export declare class StNumberField extends ContratDeChampABornes<number | null> implements FormValueControl<number | null> {
951
+ protected readonly libelles: import("@angular/core").Signal<import("@starterlib/ui").LibellesUi>;
952
+ private readonly locale;
953
+ protected readonly idUnite: string;
954
+ readonly value: import("@angular/core").ModelSignal<number | null>;
955
+ /** Decimales admises : 0, un entier, par defaut. */
956
+ readonly decimales: import("@angular/core").InputSignalWithTransform<number, unknown>;
957
+ /** Pas des boutons et des fleches ; `null` (defaut) : ni boutons, ni motif « spinbutton ». */
958
+ readonly pas: import("@angular/core").InputSignalWithTransform<number | null, unknown>;
959
+ /** L'unite, dans le cadre apres la valeur (« mois », « % ») et lue en description. */
960
+ readonly unite: import("@angular/core").InputSignal<string | null>;
961
+ /** Quitte au moins une fois : sans formulaire, rien d'autre ne montrerait l'erreur de lecture. */
962
+ protected readonly quitte: import("@angular/core").WritableSignal<boolean>;
963
+ private averti;
964
+ /** Les decimales admises, en entier positif ; celles d'un pas plus fin sont signalees. */
965
+ protected readonly decimalesAdmises: import("@angular/core").Signal<number>;
966
+ protected readonly saisie: import("@angular/forms/signals").TransformedValueSignal<string>;
967
+ /** Vrai quand le texte saisi n'est pas un nombre (le modele vaut alors `null`). */
968
+ readonly lectureInvalide: import("@angular/core").Signal<boolean>;
969
+ protected readonly erreursAffichees: import("@angular/core").Signal<readonly import("@starterlib/ui/saisie").ErreurAffichable[]>;
970
+ protected readonly modifiable: import("@angular/core").Signal<boolean>;
971
+ protected readonly peutDiminuer: import("@angular/core").Signal<boolean>;
972
+ protected readonly peutAugmenter: import("@angular/core").Signal<boolean>;
973
+ /** La valeur et son unite, telles qu'un lecteur d'ecran les dit (« 24 mois »). */
974
+ protected readonly valeurLue: import("@angular/core").Signal<string | null>;
975
+ protected readonly uniteLue: import("@angular/core").Signal<string | null>;
976
+ protected readonly descriptionsDuControle: import("@angular/core").Signal<string[]>;
977
+ /** Un clic sur l'unite ou la marge du cadre donne le focus a la zone de frappe. */
978
+ protected surPressionDuCadre(evenement: MouseEvent): void;
979
+ protected surSaisie(evenement: Event): void;
980
+ /** Fleches, pages, Debut et Fin : seulement avec un pas, et sur un champ modifiable. */
981
+ protected surTouche(evenement: KeyboardEvent): void;
982
+ /** Avance de `nombreDePas` pas (negatif : recule) ; un modele vide part de la borne basse. */
983
+ protected avancer(nombreDePas: number): void;
984
+ protected aLaSortie(): void;
985
+ private poser;
986
+ private formater;
987
+ static ɵfac: i0.ɵɵFactoryDeclaration<StNumberField, never>;
988
+ static ɵcmp: i0.ɵɵComponentDeclaration<StNumberField, "st-number-field", never, {
989
+ "value": {
990
+ "alias": "value";
991
+ "required": false;
992
+ "isSignal": true;
993
+ };
994
+ "decimales": {
995
+ "alias": "decimales";
996
+ "required": false;
997
+ "isSignal": true;
998
+ };
999
+ "pas": {
1000
+ "alias": "pas";
1001
+ "required": false;
1002
+ "isSignal": true;
1003
+ };
1004
+ "unite": {
1005
+ "alias": "unite";
1006
+ "required": false;
1007
+ "isSignal": true;
1008
+ };
1009
+ }, {
1010
+ "value": "valueChange";
1011
+ }, never, ["[stMeta]", "[stAide]", "[stIndication]"], true, never>;
1012
+ }
1013
+ /**
1014
+ * Curseur d'une valeur bornee : le montant ou la duree d'un simulateur, un plafond.
1015
+ *
1016
+ * ```html
1017
+ * <st-range-slider libelle="Duree" unite="mois" pas="6" avecChamp [formField]="simulation.duree" />
1018
+ * <!-- schema : min(chemin.duree, 6) ; max(chemin.duree, 84) -->
1019
+ * ```
1020
+ *
1021
+ * ⚠️ **Le curseur natif d'abord** (`input type="range"`, FE-4) : clavier (fleches, Page haut et
1022
+ * bas, Debut, Fin), toucher et lecteurs d'ecran le connaissent. La feuille ne change que sa peau :
1023
+ * piste de 4 px, part remplie a l'encre primaire, pastille de 20 px dans une cible de 44 px.
1024
+ *
1025
+ * - Bornes : `min` et `max` du schema (Signal Forms les pose) ; 0 et 100 sans elles.
1026
+ * - La valeur se lit en permanence, a cote du curseur (`output` relie au curseur, sans region
1027
+ * vivante : le curseur l'annonce deja par `aria-valuetext`, « 24 mois ») ; les bornes, dessous.
1028
+ * - `avecChamp` : un `st-number-field` jumeau, pour une valeur precise (GOV.UK deconseille le
1029
+ * curseur seul), nomme « <libelle>, en chiffres » ; les deux restent synchronises.
1030
+ * - `formaterValeur` : ce que la valeur affiche et fait lire (« 12 000 € ») ; par defaut le nombre
1031
+ * et son unite.
1032
+ */
1033
+ export declare class StRangeSlider extends ContratDeChampABornes<number | null> implements FormValueControl<number | null> {
1034
+ protected readonly libelles: import("@angular/core").Signal<import("@starterlib/ui").LibellesUi>;
1035
+ private readonly locale;
1036
+ readonly value: import("@angular/core").ModelSignal<number | null>;
1037
+ /** Le pas du curseur, 1 par defaut ; ses decimales sont celles de la valeur. */
1038
+ readonly pas: import("@angular/core").InputSignalWithTransform<number, unknown>;
1039
+ /** L'unite, dite apres la valeur (« mois »). */
1040
+ readonly unite: import("@angular/core").InputSignal<string | null>;
1041
+ /** Un champ numerique jumeau, pour saisir une valeur precise. */
1042
+ readonly avecChamp: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
1043
+ /** Le texte de la valeur (« 12 000 € ») ; par defaut le nombre de la locale et l'unite. */
1044
+ readonly formaterValeur: import("@angular/core").InputSignal<((valeur: number) => string) | null>;
1045
+ protected readonly quitte: import("@angular/core").WritableSignal<boolean>;
1046
+ private readonly enveloppe;
1047
+ /** L'identifiant du curseur, que l'`output` cite dans son `for`. */
1048
+ protected readonly idDuCurseur: import("@angular/core").Signal<string>;
1049
+ protected readonly bas: import("@angular/core").Signal<number>;
1050
+ protected readonly haut: import("@angular/core").Signal<number>;
1051
+ protected readonly pasSur: import("@angular/core").Signal<number>;
1052
+ protected readonly decimales: import("@angular/core").Signal<number>;
1053
+ /** La part remplie de la piste, de 0 a 100 %. */
1054
+ protected readonly partRemplie: import("@angular/core").Signal<string>;
1055
+ protected readonly valeurLue: import("@angular/core").Signal<string>;
1056
+ protected readonly erreursAffichees: import("@angular/core").Signal<readonly import("@starterlib/ui/saisie").ErreurAffichable[]>;
1057
+ protected ecrire(valeur: number): string;
1058
+ protected surCurseur(evenement: Event): void;
1059
+ protected depuisLeChamp(valeur: number | null): void;
1060
+ protected aLaSortie(): void;
1061
+ static ɵfac: i0.ɵɵFactoryDeclaration<StRangeSlider, never>;
1062
+ static ɵcmp: i0.ɵɵComponentDeclaration<StRangeSlider, "st-range-slider", never, {
1063
+ "value": {
1064
+ "alias": "value";
1065
+ "required": false;
1066
+ "isSignal": true;
1067
+ };
1068
+ "pas": {
1069
+ "alias": "pas";
1070
+ "required": false;
1071
+ "isSignal": true;
1072
+ };
1073
+ "unite": {
1074
+ "alias": "unite";
1075
+ "required": false;
1076
+ "isSignal": true;
1077
+ };
1078
+ "avecChamp": {
1079
+ "alias": "avecChamp";
1080
+ "required": false;
1081
+ "isSignal": true;
1082
+ };
1083
+ "formaterValeur": {
1084
+ "alias": "formaterValeur";
1085
+ "required": false;
1086
+ "isSignal": true;
1087
+ };
1088
+ }, {
1089
+ "value": "valueChange";
1090
+ }, never, ["[stMeta]", "[stAide]", "[stIndication]"], true, never>;
1091
+ }
1092
+ /** `tel` : numero complet, indicatif compris. `tel-national` : sans indicatif. */
1093
+ export type RemplissageDeTelephone = 'tel' | 'tel-national';
1094
+ /**
1095
+ * Numero de telephone. La valeur du modele ne garde que les chiffres et le `+` de
1096
+ * tete ; la saisie s'affiche telle qu'elle a ete tapee.
1097
+ *
1098
+ * ```html
1099
+ * <st-phone-field libelle="Telephone portable" [formField]="contact.telephone" />
1100
+ * <!-- schema : validate(chemin.telephone, ({ value }) => erreurTelephone(value())) -->
1101
+ * ```
1102
+ *
1103
+ * ⚠️ **Le format est dit AVANT la saisie** : l'aide par defaut donne un exemple avec
1104
+ * l'indicatif (« … par exemple +33 6 12 34 56 78. »), au lieu de n'expliquer le format
1105
+ * qu'apres coup, par l'erreur.
1106
+ *
1107
+ * ⚠️ **Aucun formatage automatique.** Le groupement des chiffres depend du pays,
1108
+ * et reformater pendant la frappe renvoie le curseur en fin de ligne. La saisie
1109
+ * reste celle de la personne, espaces et points compris.
1110
+ *
1111
+ * ⚠️ **Une lettre tapee est dite, pas avalee en silence** : le modele n'en garde rien
1112
+ * (`normaliserTelephone`), mais la FORME de la saisie (« 06 12 AB ») est une erreur de lecture,
1113
+ * portee par `transformedValue` : relie a un formulaire, elle le rend invalide — le schema, qui ne
1114
+ * voit que le modele normalise, ne pourrait pas la voir — et le numero ampute ne part pas ;
1115
+ * employe seul, le champ la montre apres sa sortie.
1116
+ *
1117
+ * ⚠️ **Pas de selecteur de pays, pas de verification par pays.** Il faudrait une
1118
+ * table des plans de numerotation, lourde et souvent perimee : c'est au serveur
1119
+ * de dire si le numero existe (SEC-5). `erreurTelephone` ne verifie que la forme.
1120
+ *
1121
+ * `type="tel"`, et jamais `type="number"` : un numero n'est pas une quantite, et le
1122
+ * champ numerique retire le zero de tete et le `+`. Chiffres tabulaires a zero barre (un numero
1123
+ * se dicte), en ilot de gauche a droite.
1124
+ */
1125
+ export declare class StPhoneField extends ControleDeSaisie {
1126
+ private readonly libelles;
1127
+ readonly autocomplete: import("@angular/core").InputSignal<RemplissageDeTelephone>;
1128
+ /** Quitte au moins une fois : employe seul, rien d'autre ne dirait quand montrer la forme. */
1129
+ private readonly quitte;
1130
+ protected readonly aideLue: import("@angular/core").Signal<string>;
1131
+ /**
1132
+ * La saisie telle que tapee ; le modele n'en garde que les chiffres et le `+` de tete. Une forme
1133
+ * qui n'est pas celle d'un numero est une erreur de LECTURE : elle entre dans la validite du
1134
+ * formulaire. Une valeur changee de l'exterieur — remise a zero, pre-remplissage — l'emporte.
1135
+ */
1136
+ protected readonly saisie: import("@angular/forms/signals").TransformedValueSignal<string>;
1137
+ /** Les erreurs du schema, puis celle de la forme de la saisie (une seule fois par genre). */
1138
+ protected readonly erreursAffichees: import("@angular/core").Signal<readonly import("@starterlib/ui/saisie").ErreurAffichable[]>;
1139
+ protected readonly afficherErreurs: import("@angular/core").Signal<boolean>;
1140
+ protected surSaisie(evenement: Event): void;
1141
+ protected aLaSortie(): void;
1142
+ static ɵfac: i0.ɵɵFactoryDeclaration<StPhoneField, never>;
1143
+ static ɵcmp: i0.ɵɵComponentDeclaration<StPhoneField, "st-phone-field", never, {
1144
+ "autocomplete": {
1145
+ "alias": "autocomplete";
1146
+ "required": false;
1147
+ "isSignal": true;
1148
+ };
1149
+ }, {}, never, ["[stMeta]", "[stAide]", "[stIndication]"], true, never>;
1150
+ }
1151
+ type Fin = 'jamais' | 'date' | 'nombre';
1152
+ /** Ce que la personne a choisi, meme incomplet : le modele n'en recoit qu'une recurrence entiere. */
1153
+ interface Brouillon {
1154
+ readonly frequence: FrequenceDeRecurrence;
1155
+ readonly intervalle: number | null;
1156
+ readonly jourDuMois: number | null;
1157
+ readonly debut: DateIso | null;
1158
+ readonly fin: Fin;
1159
+ readonly jusquau: DateIso | null;
1160
+ readonly nombre: number | null;
1161
+ }
1162
+ /**
1163
+ * La recurrence d'un ordre permanent (lot 255) : frequence, intervalle, jour du mois, premiere
1164
+ * echeance, fin ; et son recapitulatif en toutes lettres. Les libelles par defaut disent
1165
+ * « echeance », jamais « virement » : un prelevement ou un rendez-vous se repetent aussi (audit du
1166
+ * 2026-09-27, Q-26) ; une application les precise par `fournirLibellesFormulaires`.
1167
+ *
1168
+ * ```html
1169
+ * <st-recurrence-field libelle="Periodicite du virement" [dateMin]="aujourdhui"
1170
+ * [formField]="ordre.recurrence" />
1171
+ * ```
1172
+ *
1173
+ * - Un `st-fieldset` nomme par sa question : la frequence (`st-select`), l'intervalle
1174
+ * (`st-number-field`, son unite), le jour du mois (mensuel et annuel), la premiere echeance
1175
+ * (`st-date-field`), la fin (`st-radio-group` : jusqu'a nouvel ordre, a une date, apres un
1176
+ * nombre).
1177
+ * - La regle des 29, 30 et 31 est l'AIDE du jour du mois, dite avant toute saisie.
1178
+ * - Le recapitulatif (`decrireRecurrence`, `st-text`) DECRIT le groupe (`aria-describedby`) sans
1179
+ * region vivante : il ne s'annonce pas a chaque choix.
1180
+ * - Le modele est une `Recurrence` (RFC 5545 : FREQ, INTERVAL, BYMONTHDAY, UNTIL, COUNT) des que le
1181
+ * premiere echeance est connue, `null` avant ; les choix incomplets sont gardes.
1182
+ * - Catalogue retombe sur le francais (audit du 2026-09-27, D-29) : `lang="fr"` sur ce qu'il ecrit
1183
+ * seul, le jour du mois, la fin et le titre du recapitulatif. Le reste garde la langue de la
1184
+ * page : la question et l'aide de l'application, les champs de saisie (leurs erreurs et le
1185
+ * bouton du calendrier viennent du tronc), la frequence (son option vide aussi) et le
1186
+ * recapitulatif, ecrit dans la locale.
1187
+ */
1188
+ export declare class StRecurrenceField extends ContratDeChamp implements FormValueControl<Recurrence | null> {
1189
+ private readonly locale;
1190
+ private readonly catalogue;
1191
+ protected readonly libellesDesChamps: Signal<LibellesFormulaires>;
1192
+ /** `fr` quand le catalogue retombe sur le francais, `null` sinon (D-29). */
1193
+ protected readonly langueDeRepli: Signal<string | null>;
1194
+ readonly value: import("@angular/core").ModelSignal<Recurrence | null>;
1195
+ /** La premiere echeance possible (aujourd'hui, pour un ordre a venir) : l'application la sait. */
1196
+ readonly dateMin: import("@angular/core").InputSignal<string | null>;
1197
+ private readonly frequenceChamp;
1198
+ private readonly debutChamp;
1199
+ protected readonly idDuRecapitulatif: string;
1200
+ protected readonly quitte: import("@angular/core").WritableSignal<boolean>;
1201
+ /** Le brouillon suit le modele quand il change d'ailleurs, et garde ses choix quand il est vide. */
1202
+ protected readonly brouillon: import("@angular/core").WritableSignal<Brouillon>;
1203
+ protected readonly optionsDeFrequence: Signal<readonly OptionDeListe[]>;
1204
+ protected readonly optionsDeJour: Signal<readonly OptionDeListe[]>;
1205
+ protected readonly optionsDeFin: Signal<readonly OptionRadio[]>;
1206
+ protected readonly avecJourDuMois: Signal<boolean>;
1207
+ protected readonly jourChoisi: Signal<string>;
1208
+ protected readonly unite: Signal<string>;
1209
+ protected readonly recapitulatif: Signal<string | null>;
1210
+ protected readonly decritPar: Signal<readonly string[]>;
1211
+ protected modifier(partie: Partial<Brouillon>): void;
1212
+ protected choisirLaFrequence(valeur: string): void;
1213
+ protected choisirLeJour(valeur: string): void;
1214
+ protected choisirLaFin(valeur: string): void;
1215
+ protected quitter(): void;
1216
+ /** A la premiere echeance quand elle manque, sinon a la frequence. */
1217
+ focus(options?: FocusOptions): void;
1218
+ static ɵfac: i0.ɵɵFactoryDeclaration<StRecurrenceField, never>;
1219
+ static ɵcmp: i0.ɵɵComponentDeclaration<StRecurrenceField, "st-recurrence-field", never, {
1220
+ "value": {
1221
+ "alias": "value";
1222
+ "required": false;
1223
+ "isSignal": true;
1224
+ };
1225
+ "dateMin": {
1226
+ "alias": "dateMin";
1227
+ "required": false;
1228
+ "isSignal": true;
1229
+ };
1230
+ }, {
1231
+ "value": "valueChange";
1232
+ }, never, never, true, never>;
1233
+ }
1234
+ export type { DispositionDesRaccourcis };