@starterlib/ui 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +83 -16
- package/assets/icones/sprite.svg +3 -0
- package/fesm2022/starterlib-ui-formulaires.mjs +446 -0
- package/fesm2022/starterlib-ui-formulaires.mjs.map +1 -0
- package/fesm2022/starterlib-ui-interactions.mjs +536 -0
- package/fesm2022/starterlib-ui-interactions.mjs.map +1 -0
- package/fesm2022/starterlib-ui-surfaces.mjs +1106 -11
- package/fesm2022/starterlib-ui-surfaces.mjs.map +1 -1
- package/fesm2022/starterlib-ui.mjs +2719 -105
- package/fesm2022/starterlib-ui.mjs.map +1 -1
- package/package.json +24 -3
- package/types/starterlib-ui-formulaires.d.ts +198 -0
- package/types/starterlib-ui-interactions.d.ts +269 -0
- package/types/starterlib-ui-surfaces.d.ts +607 -16
- package/types/starterlib-ui.d.ts +1598 -24
|
@@ -0,0 +1,198 @@
|
|
|
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
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Montant, en UNITES MINEURES : `123456n` pour 1 234,56 EUR.
|
|
10
|
+
*
|
|
11
|
+
* ```html
|
|
12
|
+
* <st-amount-field libelle="Montant du virement" devise="EUR" [formField]="virement.montant" />
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* ⚠️ **Jamais un nombre a virgule flottante** (SEC-8) : le modele est un `bigint`,
|
|
16
|
+
* lu chiffre par chiffre par `lireMontant`. `0,1 + 0,2` ne fait pas `0,3`, et
|
|
17
|
+
* 1 234,56 EUR ne doit pas devenir 1 234,5599999.
|
|
18
|
+
*
|
|
19
|
+
* ⚠️ **Un texte ambigu est refuse, jamais devine.** « 1.250 » en francais serait
|
|
20
|
+
* mille deux cent cinquante ou un virgule vingt-cinq : le champ dit l'erreur et
|
|
21
|
+
* 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.
|
|
24
|
+
*
|
|
25
|
+
* 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
|
|
27
|
+
* « 1e5 », change la valeur a la molette, et ignore la virgule selon le navigateur.
|
|
28
|
+
*
|
|
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
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Date calendaire : un champ texte, et un calendrier pour qui prefere choisir.
|
|
59
|
+
*
|
|
60
|
+
* ```html
|
|
61
|
+
* <st-date-field libelle="Date de naissance" autocomplete="bday" [dateMax]="aujourdHui"
|
|
62
|
+
* [formField]="profil.naissance" />
|
|
63
|
+
* <!-- schema : validate(chemin.naissance, ({ value }) => erreurDate(value(), { max: aujourdHui })) -->
|
|
64
|
+
* ```
|
|
65
|
+
*
|
|
66
|
+
* Le modele est une date ISO — `2026-09-17` — ou `null`, jamais un objet `Date` :
|
|
67
|
+
* une date calendaire n'a ni heure ni fuseau.
|
|
68
|
+
*
|
|
69
|
+
* ⚠️ **Un champ texte d'abord** (decision D7 de l'audit de la vague 3). Le champ
|
|
70
|
+
* natif `type="date"` affiche son format dans la langue du NAVIGATEUR : il ne
|
|
71
|
+
* bascule pas quand l'application change de langue. Ici, le format attendu —
|
|
72
|
+
* `jj/mm/aaaa` ou `mm/dd/yyyy` — suit la langue courante, et il est dit en aide.
|
|
73
|
+
*
|
|
74
|
+
* ⚠️ **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
|
+
|
|
117
|
+
type Partie = 'debut' | 'fin';
|
|
118
|
+
interface SaisieDePlage {
|
|
119
|
+
readonly debut: string;
|
|
120
|
+
readonly fin: string;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Plage de dates : un debut, une fin, dans un groupe nomme par sa question.
|
|
124
|
+
*
|
|
125
|
+
* ```html
|
|
126
|
+
* <st-date-range libelle="Periode du sejour" [formField]="reservation.sejour" />
|
|
127
|
+
* <!-- schema : validate(chemin.sejour, ({ value }) => erreurPlageDeDates(value())) -->
|
|
128
|
+
* ```
|
|
129
|
+
*
|
|
130
|
+
* Deux champs texte etiquetes — « Date de debut », « Date de fin » — dans un
|
|
131
|
+
* `fieldset` dont la legende est le `libelle` : chacun se lit avec la question.
|
|
132
|
+
* Chaque champ a son calendrier ; celui de la fin s'ouvre au mois du debut et
|
|
133
|
+
* refuse les jours qui le precedent.
|
|
134
|
+
*
|
|
135
|
+
* ⚠️ **Une erreur dit QUELLE date corriger** : « Date de fin : saisissez une date
|
|
136
|
+
* qui existe… ». Sans le nom de la partie, deux messages identiques ne disent pas
|
|
137
|
+
* lequel des champs est faux. L'erreur de lecture marque aussi son champ
|
|
138
|
+
* `aria-invalid`, et lui seul.
|
|
139
|
+
*
|
|
140
|
+
* L'obligation d'une borne est une regle du schema : `required` ne sait pas ce
|
|
141
|
+
* qu'est une plage « vide ».
|
|
142
|
+
*/
|
|
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 };
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import * as _angular_core from '@angular/core';
|
|
2
|
+
import * as i1 from '@angular/aria/tabs';
|
|
3
|
+
import * as _starterlib_ui from '@starterlib/ui';
|
|
4
|
+
import { ControleDeSaisie, OptionDeListe, AnnonceLocale, ContratDeChamp } from '@starterlib/ui';
|
|
5
|
+
import { FormValueControl } from '@angular/forms/signals';
|
|
6
|
+
|
|
7
|
+
/** Un onglet, decrit par l'appelant. */
|
|
8
|
+
interface Onglet {
|
|
9
|
+
/** Identifiant stable, qui relie l'onglet a son `st-tab-panel`. */
|
|
10
|
+
readonly valeur: string;
|
|
11
|
+
readonly libelle: string;
|
|
12
|
+
readonly desactive?: boolean;
|
|
13
|
+
}
|
|
14
|
+
type ActivationDOnglet = 'manuelle' | 'automatique';
|
|
15
|
+
type OrientationDOnglets = 'horizontale' | 'verticale';
|
|
16
|
+
/**
|
|
17
|
+
* Onglets, sur les primitives `@angular/aria/tabs`.
|
|
18
|
+
*
|
|
19
|
+
* ```html
|
|
20
|
+
* <st-tabs etiquette="Compte" [onglets]="onglets" [(selection)]="onglet">
|
|
21
|
+
* <st-tab-panel valeur="operations">
|
|
22
|
+
* <ng-template stTabContent><app-operations /></ng-template>
|
|
23
|
+
* </st-tab-panel>
|
|
24
|
+
* <st-tab-panel valeur="virements">
|
|
25
|
+
* <ng-template stTabContent><app-virements /></ng-template>
|
|
26
|
+
* </st-tab-panel>
|
|
27
|
+
* </st-tabs>
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* ⚠️ **La liste d'onglets est rendue par le composant, a partir de donnees**, et
|
|
31
|
+
* non projetee. Les primitives d'Aria relient un onglet a sa liste par
|
|
32
|
+
* INJECTION, et un contenu projete garde l'injecteur de l'endroit ou il est
|
|
33
|
+
* ecrit : c'est la lecon de `st-menu`, ou des elements projetes ne
|
|
34
|
+
* s'enregistraient jamais. Rendue ici, la liste est a coup sur sous la bonne
|
|
35
|
+
* primitive — et ses valeurs peuvent etre dites en francais.
|
|
36
|
+
*
|
|
37
|
+
* Les PANNEAUX, eux, sont projetes : ecrits directement sous `st-tabs`, leur
|
|
38
|
+
* injecteur parent est celui de l'hote, qui porte la primitive `Tabs`.
|
|
39
|
+
*
|
|
40
|
+
* ⚠️ **Activation manuelle par defaut.** En activation automatique, chaque
|
|
41
|
+
* fleche SELECTIONNE l'onglet atteint ; son contenu differe se rend, et charge
|
|
42
|
+
* ses donnees. Parcourir cinq onglets au clavier lancerait cinq requetes pour en
|
|
43
|
+
* lire un. En manuelle, les fleches deplacent le focus et Entree ou Espace
|
|
44
|
+
* selectionne. `automatique` reste le bon choix quand les panneaux sont deja la
|
|
45
|
+
* et s'affichent sans delai.
|
|
46
|
+
*/
|
|
47
|
+
declare class StTabs {
|
|
48
|
+
readonly onglets: _angular_core.InputSignal<readonly Onglet[]>;
|
|
49
|
+
/** Nom accessible de la liste : sans lui, plusieurs listes d'onglets se confondent. */
|
|
50
|
+
readonly etiquette: _angular_core.InputSignal<string>;
|
|
51
|
+
readonly activation: _angular_core.InputSignal<ActivationDOnglet>;
|
|
52
|
+
readonly orientation: _angular_core.InputSignal<OrientationDOnglets>;
|
|
53
|
+
/** Valeur de l'onglet selectionne. `undefined` : le premier onglet disponible. */
|
|
54
|
+
readonly selection: _angular_core.ModelSignal<string | undefined>;
|
|
55
|
+
/**
|
|
56
|
+
* ⚠️ Toujours un onglet selectionne. Le motif ARIA l'exige : une liste sans
|
|
57
|
+
* selection n'affiche aucun panneau, et la page parait vide sans raison.
|
|
58
|
+
*/
|
|
59
|
+
protected readonly selectionEffective: _angular_core.Signal<string | undefined>;
|
|
60
|
+
protected readonly modeAria: _angular_core.Signal<"follow" | "explicit">;
|
|
61
|
+
protected readonly orientationAria: _angular_core.Signal<"vertical" | "horizontal">;
|
|
62
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<StTabs, never>;
|
|
63
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<StTabs, "st-tabs", never, { "onglets": { "alias": "onglets"; "required": true; "isSignal": true; }; "etiquette": { "alias": "etiquette"; "required": true; "isSignal": true; }; "activation": { "alias": "activation"; "required": false; "isSignal": true; }; "orientation": { "alias": "orientation"; "required": false; "isSignal": true; }; "selection": { "alias": "selection"; "required": false; "isSignal": true; }; }, { "selection": "selectionChange"; }, never, ["*"], true, [{ directive: typeof i1.Tabs; inputs: {}; outputs: {}; }]>;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Panneau d'un onglet, relie par sa `valeur`.
|
|
68
|
+
*
|
|
69
|
+
* ⚠️ La primitive d'Aria ne masque RIEN : elle pose `inert` sur le panneau
|
|
70
|
+
* inactif, ce qui le retire de l'arbre d'accessibilite et du clavier, mais le
|
|
71
|
+
* laisse a l'ecran. Sa documentation le dit en une ligne. Sans le style de ce
|
|
72
|
+
* composant, tous les panneaux s'affichaient empiles, muets et intouchables.
|
|
73
|
+
*/
|
|
74
|
+
declare class StTabPanel {
|
|
75
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<StTabPanel, never>;
|
|
76
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<StTabPanel, "st-tab-panel", never, {}, {}, never, ["*"], true, [{ directive: typeof i1.TabPanel; inputs: { "value": "valeur"; }; outputs: {}; }]>;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Contenu differe d'un panneau : rendu a la premiere selection de son onglet.
|
|
81
|
+
*
|
|
82
|
+
* Un ecran a cinq onglets ne charge ainsi que celui qu'on regarde. Voir
|
|
83
|
+
* l'activation manuelle de `st-tabs` : c'est ce qui empeche qu'un simple
|
|
84
|
+
* parcours au clavier les rende tous.
|
|
85
|
+
*/
|
|
86
|
+
declare class StTabContent {
|
|
87
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<StTabContent, never>;
|
|
88
|
+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<StTabContent, "ng-template[stTabContent]", never, {}, {}, never, never, true, [{ directive: typeof i1.TabContent; inputs: {}; outputs: {}; }]>;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
type ModeDeNavigation = 'auto' | 'persistant' | 'modal';
|
|
92
|
+
/**
|
|
93
|
+
* Navigation laterale : une region a cote du contenu sur grand ecran, un tiroir
|
|
94
|
+
* sur petit ecran.
|
|
95
|
+
*
|
|
96
|
+
* ```html
|
|
97
|
+
* <st-app-shell>
|
|
98
|
+
* <button entete stButton [stSidenavToggle]="navigation">Menu</button>
|
|
99
|
+
* <st-sidenav navigation #navigation etiquette="Navigation principale">
|
|
100
|
+
* <a routerLink="/comptes">Comptes</a>
|
|
101
|
+
* </st-sidenav>
|
|
102
|
+
* …
|
|
103
|
+
* </st-app-shell>
|
|
104
|
+
* ```
|
|
105
|
+
*
|
|
106
|
+
* ⚠️ **Deux modes, jamais confondus.** Persistante, c'est une REGION de la page :
|
|
107
|
+
* aucun piege, rien a ouvrir. Modale, c'est un TIROIR, donc un `StDialog` — role,
|
|
108
|
+
* piegeage du focus, Echap, retour du focus au bouton — et non une region
|
|
109
|
+
* glissee par-dessus la page avec un peu de CSS, qui laisserait le clavier
|
|
110
|
+
* parcourir la page cachee dessous.
|
|
111
|
+
*
|
|
112
|
+
* ⚠️ **Elle porte son propre `<nav>`, et un seul a la fois.** Sur petit ecran,
|
|
113
|
+
* la region en ligne DISPARAIT quand le tiroir prend le relais : laissee en
|
|
114
|
+
* place, elle resterait un repere de navigation vide, que le lecteur d'ecran
|
|
115
|
+
* proposerait sans rien y trouver.
|
|
116
|
+
*
|
|
117
|
+
* Un lien suivi dans le tiroir le ferme : `StDialog` se ferme a toute navigation
|
|
118
|
+
* du routeur.
|
|
119
|
+
*/
|
|
120
|
+
declare class StSidenav {
|
|
121
|
+
private readonly dialogues;
|
|
122
|
+
private readonly libelles;
|
|
123
|
+
/**
|
|
124
|
+
* Nom du repere. `null` : « Navigation principale », du dictionnaire. A
|
|
125
|
+
* renseigner des qu'une page compte deux navigations, qui doivent se
|
|
126
|
+
* distinguer.
|
|
127
|
+
*/
|
|
128
|
+
readonly etiquette: _angular_core.InputSignal<string | null>;
|
|
129
|
+
protected readonly etiquetteLue: _angular_core.Signal<string>;
|
|
130
|
+
/** `auto` : persistante sur grand ecran, tiroir en dessous. */
|
|
131
|
+
readonly mode: _angular_core.InputSignal<ModeDeNavigation>;
|
|
132
|
+
readonly identifiant: string;
|
|
133
|
+
private readonly ecranLarge;
|
|
134
|
+
/** Mode reellement applique. Lu par le bouton, qui ne s'affiche qu'en tiroir. */
|
|
135
|
+
readonly modeEffectif: _angular_core.Signal<"persistant" | "modal">;
|
|
136
|
+
private readonly ouvertInterne;
|
|
137
|
+
readonly ouvert: _angular_core.Signal<boolean>;
|
|
138
|
+
private readonly gabarit;
|
|
139
|
+
private reference;
|
|
140
|
+
constructor();
|
|
141
|
+
ouvrir(): void;
|
|
142
|
+
fermer(): void;
|
|
143
|
+
basculer(): void;
|
|
144
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<StSidenav, never>;
|
|
145
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<StSidenav, "st-sidenav", never, { "etiquette": { "alias": "etiquette"; "required": false; "isSignal": true; }; "mode": { "alias": "mode"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Bouton qui ouvre la navigation en tiroir.
|
|
150
|
+
*
|
|
151
|
+
* ⚠️ **Masque quand la navigation est persistante.** Un bouton « Menu » qui ne
|
|
152
|
+
* fait rien, parce que la navigation est deja affichee a cote, est un arret de
|
|
153
|
+
* tabulation inutile et une promesse non tenue.
|
|
154
|
+
*
|
|
155
|
+
* ⚠️ `aria-expanded` suit l'ouverture du tiroir : sans lui, rien ne dit a qui
|
|
156
|
+
* n'en voit pas l'effet que le bouton a agi.
|
|
157
|
+
*/
|
|
158
|
+
declare class StSidenavToggle {
|
|
159
|
+
readonly stSidenavToggle: _angular_core.InputSignal<StSidenav>;
|
|
160
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<StSidenavToggle, never>;
|
|
161
|
+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<StSidenavToggle, "[stSidenavToggle]", never, { "stSidenavToggle": { "alias": "stSidenavToggle"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** `local` : le composant filtre `options`. `distant` : l'application filtre, sur `recherche`. */
|
|
165
|
+
type FiltrageDeListe = 'local' | 'distant';
|
|
166
|
+
/**
|
|
167
|
+
* Liste de choix a filtrer en tapant, sur `@angular/aria/combobox` et
|
|
168
|
+
* `@angular/aria/listbox`.
|
|
169
|
+
*
|
|
170
|
+
* ```html
|
|
171
|
+
* <st-combobox libelle="Beneficiaire" [options]="beneficiaires" [formField]="virement.beneficiaire" />
|
|
172
|
+
* <!-- liste servie par le serveur : -->
|
|
173
|
+
* <st-combobox libelle="Commune" filtrage="distant" [options]="communes()"
|
|
174
|
+
* (recherche)="terme.set($event)" [formField]="adresse.commune" />
|
|
175
|
+
* ```
|
|
176
|
+
*
|
|
177
|
+
* Le modele est la VALEUR de l'option choisie, `''` sans choix. Le texte tape ne
|
|
178
|
+
* part jamais dans le modele : « Pari » n'est pas une commune.
|
|
179
|
+
*
|
|
180
|
+
* ⚠️ **Pour une longue liste seulement.** Sous une vingtaine d'options,
|
|
181
|
+
* `st-select` — natif — est plus sur, et plus rapide sur mobile.
|
|
182
|
+
*
|
|
183
|
+
* - La liste s'ouvre a la frappe et a la fleche bas ; Entree choisit, Echap
|
|
184
|
+
* ferme. Le focus reste dans le champ (`aria-activedescendant`).
|
|
185
|
+
* - Le nombre de resultats s'annonce apres la frappe, une fois : le lecteur
|
|
186
|
+
* d'ecran ne voit pas la liste se reduire.
|
|
187
|
+
* - ⚠️ **Quitter le champ sans choisir rend le texte du choix precedent.** Un
|
|
188
|
+
* texte qui ne correspond a aucune option ne reste pas affiche comme s'il etait
|
|
189
|
+
* retenu ; un champ vide, lui, retire le choix.
|
|
190
|
+
* - La liste est posee dans la couche superieure du navigateur (`popover`) par le
|
|
191
|
+
* CDK : un dialogue ou un tableau defilant ne la rogne pas.
|
|
192
|
+
*
|
|
193
|
+
* ⚠️ En `distant`, `recherche` est emis a chaque frappe : a l'application de
|
|
194
|
+
* temporiser, et de ne pas mettre le terme dans l'adresse (SEC-6).
|
|
195
|
+
*/
|
|
196
|
+
declare class StCombobox extends ControleDeSaisie {
|
|
197
|
+
protected readonly libelles: _angular_core.Signal<_starterlib_ui.LibellesUi>;
|
|
198
|
+
private readonly element;
|
|
199
|
+
private readonly injecteur;
|
|
200
|
+
readonly options: _angular_core.InputSignal<readonly OptionDeListe[]>;
|
|
201
|
+
readonly filtrage: _angular_core.InputSignal<FiltrageDeListe>;
|
|
202
|
+
/** Texte tape, a chaque frappe. Sert au filtrage `distant`. */
|
|
203
|
+
readonly recherche: _angular_core.OutputEmitterRef<string>;
|
|
204
|
+
protected readonly annonce: AnnonceLocale;
|
|
205
|
+
protected readonly ouvert: _angular_core.WritableSignal<boolean>;
|
|
206
|
+
/** Texte du champ : le libelle du choix, tant que la personne ne tape pas. */
|
|
207
|
+
protected readonly texte: _angular_core.WritableSignal<string>;
|
|
208
|
+
/** Ce qui filtre : vide a l'ouverture par la fleche, pour montrer toute la liste. */
|
|
209
|
+
private readonly filtre;
|
|
210
|
+
/** Option active dans la liste ; le choix n'est retenu qu'a la validation. */
|
|
211
|
+
protected readonly surlignee: _angular_core.WritableSignal<string[]>;
|
|
212
|
+
protected readonly visibles: _angular_core.Signal<readonly OptionDeListe[]>;
|
|
213
|
+
private readonly liste;
|
|
214
|
+
constructor();
|
|
215
|
+
protected surSaisie(evenement: Event): void;
|
|
216
|
+
protected basculer(): void;
|
|
217
|
+
protected valider(): void;
|
|
218
|
+
protected aLaSortie(evenement: FocusEvent): void;
|
|
219
|
+
private libelleDe;
|
|
220
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<StCombobox, never>;
|
|
221
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<StCombobox, "st-combobox", never, { "options": { "alias": "options"; "required": true; "isSignal": true; }; "filtrage": { "alias": "filtrage"; "required": false; "isSignal": true; }; }, { "recherche": "recherche"; }, never, never, true, never>;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Choix de plusieurs valeurs dans une liste, sur `@angular/aria/combobox` et
|
|
226
|
+
* `@angular/aria/listbox`.
|
|
227
|
+
*
|
|
228
|
+
* ```html
|
|
229
|
+
* <st-multiselect libelle="Comptes a inclure" [options]="comptes" [formField]="releve.comptes" />
|
|
230
|
+
* ```
|
|
231
|
+
*
|
|
232
|
+
* Le modele est la liste des VALEURS choisies, dans l'ordre des options.
|
|
233
|
+
*
|
|
234
|
+
* - Fleche bas, Entree ou Espace ouvrent la liste ; Espace coche ou decoche
|
|
235
|
+
* l'option active sans fermer ; Echap ferme.
|
|
236
|
+
* - ⚠️ **Chaque choix reste visible et retirable** sous le champ, par un bouton
|
|
237
|
+
* « Retirer … ». Un resume « 3 choix » dans le declencheur ne dit pas lesquels,
|
|
238
|
+
* et obligerait a rouvrir la liste pour en retirer un.
|
|
239
|
+
* - Un choix retire rend le focus au retrait suivant, ou au champ : le focus ne
|
|
240
|
+
* tombe jamais sur le document.
|
|
241
|
+
*
|
|
242
|
+
* ⚠️ Sous une dizaine d'options, un groupe de cases a cocher (`st-fieldset` et
|
|
243
|
+
* `st-checkbox`) est plus simple : tout est visible, rien a ouvrir.
|
|
244
|
+
*/
|
|
245
|
+
declare class StMultiselect extends ContratDeChamp implements FormValueControl<readonly string[]> {
|
|
246
|
+
protected readonly libelles: _angular_core.Signal<_starterlib_ui.LibellesUi>;
|
|
247
|
+
private readonly element;
|
|
248
|
+
private readonly injecteur;
|
|
249
|
+
readonly value: _angular_core.ModelSignal<readonly string[]>;
|
|
250
|
+
readonly options: _angular_core.InputSignal<readonly OptionDeListe[]>;
|
|
251
|
+
protected readonly annonce: AnnonceLocale;
|
|
252
|
+
protected readonly ouvert: _angular_core.WritableSignal<boolean>;
|
|
253
|
+
private readonly liste;
|
|
254
|
+
/** La liste d'Aria attend un tableau modifiable ; le modele, lui, est en lecture seule. */
|
|
255
|
+
protected readonly valeursDeListe: _angular_core.Signal<string[]>;
|
|
256
|
+
protected readonly choisies: _angular_core.Signal<OptionDeListe[]>;
|
|
257
|
+
protected readonly resume: _angular_core.Signal<string>;
|
|
258
|
+
constructor();
|
|
259
|
+
/** Le declencheur n'est pas un champ natif : la base ne le trouve pas par `#champ`. */
|
|
260
|
+
focus(options?: FocusOptions): void;
|
|
261
|
+
protected surChoix(valeurs: readonly string[]): void;
|
|
262
|
+
protected retirer(valeur: string, indice: number): void;
|
|
263
|
+
protected aLaSortie(evenement: FocusEvent): void;
|
|
264
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<StMultiselect, never>;
|
|
265
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<StMultiselect, "st-multiselect", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": true; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, never>;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export { StCombobox, StMultiselect, StSidenav, StSidenavToggle, StTabContent, StTabPanel, StTabs };
|
|
269
|
+
export type { ActivationDOnglet, FiltrageDeListe, ModeDeNavigation, Onglet, OrientationDOnglets };
|