@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.
- package/LICENCES-TIERCES.md +236 -0
- package/README.md +163 -56
- package/assets/icones/catalogue.json +3296 -0
- package/assets/icones/sprite.svg +235 -35
- package/fesm2022/starterlib-ui-arbre.mjs +475 -0
- package/fesm2022/starterlib-ui-arbre.mjs.map +1 -0
- package/fesm2022/starterlib-ui-donnees.mjs +3561 -0
- package/fesm2022/starterlib-ui-donnees.mjs.map +1 -0
- package/fesm2022/starterlib-ui-formulaires.mjs +3186 -442
- package/fesm2022/starterlib-ui-formulaires.mjs.map +1 -1
- package/fesm2022/starterlib-ui-libelles-en.mjs +383 -0
- package/fesm2022/starterlib-ui-libelles-en.mjs.map +1 -0
- package/fesm2022/starterlib-ui-listes.mjs +5367 -0
- package/fesm2022/starterlib-ui-listes.mjs.map +1 -0
- package/fesm2022/starterlib-ui-messagerie.mjs +737 -0
- package/fesm2022/starterlib-ui-messagerie.mjs.map +1 -0
- package/fesm2022/starterlib-ui-navigation.mjs +509 -0
- package/fesm2022/starterlib-ui-navigation.mjs.map +1 -0
- package/fesm2022/starterlib-ui-onglets.mjs +371 -0
- package/fesm2022/starterlib-ui-onglets.mjs.map +1 -0
- package/fesm2022/starterlib-ui-parcours.mjs +2449 -0
- package/fesm2022/starterlib-ui-parcours.mjs.map +1 -0
- package/fesm2022/starterlib-ui-qr.mjs +907 -0
- package/fesm2022/starterlib-ui-qr.mjs.map +1 -0
- package/fesm2022/starterlib-ui-saisie.mjs +8609 -0
- package/fesm2022/starterlib-ui-saisie.mjs.map +1 -0
- package/fesm2022/starterlib-ui-selection.mjs +1341 -0
- package/fesm2022/starterlib-ui-selection.mjs.map +1 -0
- package/fesm2022/starterlib-ui-sens.mjs +59 -0
- package/fesm2022/starterlib-ui-sens.mjs.map +1 -0
- package/fesm2022/starterlib-ui-surfaces.mjs +5140 -1387
- package/fesm2022/starterlib-ui-surfaces.mjs.map +1 -1
- package/fesm2022/starterlib-ui.mjs +10729 -5689
- package/fesm2022/starterlib-ui.mjs.map +1 -1
- package/package.json +58 -17
- package/styles/amorce.css +69 -0
- package/styles/couches.css +178 -0
- package/types/starterlib-ui-arbre.d.ts +225 -0
- package/types/starterlib-ui-donnees.d.ts +1489 -0
- package/types/starterlib-ui-formulaires.d.ts +1174 -138
- package/types/starterlib-ui-libelles-en.d.ts +5 -0
- package/types/starterlib-ui-listes.d.ts +2487 -0
- package/types/starterlib-ui-messagerie.d.ts +317 -0
- package/types/starterlib-ui-navigation.d.ts +242 -0
- package/types/starterlib-ui-onglets.d.ts +212 -0
- package/types/starterlib-ui-parcours.d.ts +916 -0
- package/types/starterlib-ui-qr.d.ts +105 -0
- package/types/starterlib-ui-saisie.d.ts +3806 -0
- package/types/starterlib-ui-selection.d.ts +488 -0
- package/types/starterlib-ui-sens.d.ts +44 -0
- package/types/starterlib-ui-surfaces.d.ts +1899 -510
- package/types/starterlib-ui.d.ts +4731 -2678
- package/fesm2022/starterlib-ui-interactions.mjs +0 -598
- package/fesm2022/starterlib-ui-interactions.mjs.map +0 -1
- package/types/starterlib-ui-interactions.d.ts +0 -316
|
@@ -1,15 +1,110 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { ContratDeChamp, ErreurAffichable } from
|
|
3
|
-
import * as
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import { DateIso, PlageDeDates } from
|
|
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
|
|
23
|
-
*
|
|
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
|
-
*
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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
|
|
76
|
-
*
|
|
77
|
-
* un dialogue, et le CDK n'entre
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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
|
-
|
|
120
|
-
|
|
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
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
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 };
|