@starterlib/ui 0.12.0 → 0.13.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.
@@ -1861,6 +1861,123 @@ export declare class StFreshness {
1861
1861
  "perimee": "perimee";
1862
1862
  }, never, never, true, never>;
1863
1863
  }
1864
+ /** Une image a inspecter : son contenu, charge par l'application, et ce qu'elle montre, deja traduit. */
1865
+ export interface ImageAInspecter {
1866
+ /** Le contenu (`Blob`), charge par l'application par `@starterlib/core`, sans cache. */
1867
+ readonly contenu: Blob;
1868
+ /** Ce que montre l'image (« Recto de la piece »), son nom au lecteur d'ecran et sa legende. */
1869
+ readonly libelle: string;
1870
+ }
1871
+ /** Les bornes et les pas du zoom (1 : l'image ajustee a la largeur du panneau) et du contraste. */
1872
+ export declare const BORNES_DE_LA_VISIONNEUSE: {
1873
+ readonly zoom: {
1874
+ readonly min: 0.5;
1875
+ readonly max: 4;
1876
+ readonly pas: 0.25;
1877
+ };
1878
+ readonly contraste: {
1879
+ readonly min: 0.5;
1880
+ readonly max: 2;
1881
+ readonly pas: 0.25;
1882
+ };
1883
+ };
1884
+ type EtatDuPanneau = 'chargement' | 'prete' | 'illisible';
1885
+ /**
1886
+ * Visionneuse de pieces (P08-17 d'Aplomb, DEC-090) : une image, ou deux cote a cote (recto et verso,
1887
+ * piece et selfie), a inspecter a l'ecran SANS la telecharger.
1888
+ *
1889
+ * ```html
1890
+ * <st-image-viewer libelle="Piece d'identite" [images]="pieces()" filigrane="M. Operateur, 14/10/2026" />
1891
+ * ```
1892
+ *
1893
+ * - **Aucune adresse vers l'image** : le contenu (`Blob`, charge par l'application par
1894
+ * `@starterlib/core`, la piece etant servie sans cache par le serveur) est decode une fois en
1895
+ * `ImageBitmap`, dessine dans un canevas, puis le bitmap est ferme : une seule image decodee par
1896
+ * panneau, aucune `ObjectURL` (ni lien, ni `blob:` a autoriser dans la politique de securite du
1897
+ * contenu), aucun bouton de telechargement, aucun menu contextuel « Enregistrer l'image ». Les
1898
+ * canevas sont vides a la destruction, et a chaque changement d'images.
1899
+ * - **Zoom, rotation, contraste** a la barre d'outils et au clavier, communs aux deux panneaux ; le
1900
+ * defilement de l'un suit celui de l'autre. Raccourcis : `+` et `-` (zoom), `r` et `Maj+r`
1901
+ * (rotation a droite et a gauche), `c` et `Maj+c` (contraste), `0` (vue d'origine) ; les fleches
1902
+ * font defiler le panneau qui a le focus. Chaque changement s'annonce poliment.
1903
+ * - **Filigrane** (`filigrane` : identite de l'operateur et date, texte fourni) par-dessus chaque
1904
+ * panneau, a l'ecran comme a l'impression ; les images, elles, ne s'impriment pas.
1905
+ * - Rien n'est stocke dans le navigateur.
1906
+ */
1907
+ export declare class StImageViewer {
1908
+ /** Une ou deux images ; au-dela de deux, les suivantes sont ignorees. */
1909
+ readonly images: import("@angular/core").InputSignal<readonly ImageAInspecter[]>;
1910
+ /** Le nom du groupe (« Piece d'identite de la demande 42 »). */
1911
+ readonly libelle: import("@angular/core").InputSignal<string>;
1912
+ /** Le texte du filigrane (identite de l'operateur, date), deja traduit ; `null` : aucun. */
1913
+ readonly filigrane: import("@angular/core").InputSignal<string | null>;
1914
+ protected readonly libelles: import("@angular/core").Signal<import("@starterlib/ui/donnees").LibellesDonnees>;
1915
+ protected readonly bornes: {
1916
+ readonly zoom: {
1917
+ readonly min: 0.5;
1918
+ readonly max: 4;
1919
+ readonly pas: 0.25;
1920
+ };
1921
+ readonly contraste: {
1922
+ readonly min: 0.5;
1923
+ readonly max: 2;
1924
+ readonly pas: 0.25;
1925
+ };
1926
+ };
1927
+ protected readonly zoom: import("@angular/core").WritableSignal<number>;
1928
+ protected readonly rotation: import("@angular/core").WritableSignal<number>;
1929
+ protected readonly contraste: import("@angular/core").WritableSignal<number>;
1930
+ protected readonly etats: import("@angular/core").WritableSignal<readonly EtatDuPanneau[]>;
1931
+ private readonly dimensions;
1932
+ private readonly ajustements;
1933
+ private readonly toiles;
1934
+ private readonly defilements;
1935
+ protected readonly annonce: AnnonceLocale;
1936
+ protected readonly identifiantDeLAide: string;
1937
+ /** Une generation par jeu d'images : un decodage en retard ne dessine jamais dans un canevas reutilise. */
1938
+ private generation;
1939
+ private synchronisationEnCours;
1940
+ protected readonly affichees: import("@angular/core").Signal<ImageAInspecter[]>;
1941
+ protected readonly transformation: import("@angular/core").Signal<string>;
1942
+ protected readonly filtre: import("@angular/core").Signal<string>;
1943
+ /** Taille affichee du canevas et de sa boite (la boite echange ses cotes a 90 et 270 degres). */
1944
+ protected readonly mesures: import("@angular/core").Signal<({
1945
+ largeur: number;
1946
+ hauteur: number;
1947
+ boiteLargeur: number;
1948
+ boiteHauteur: number;
1949
+ } | null)[]>;
1950
+ constructor();
1951
+ private dessiner;
1952
+ protected zoomer(sens: 1 | -1): void;
1953
+ protected tourner(degres: 90 | -90): void;
1954
+ protected contraster(sens: 1 | -1): void;
1955
+ protected reinitialiser(): void;
1956
+ protected pourcentage(valeur: number): number;
1957
+ private annoncerLaVue;
1958
+ protected auClavier(evenement: KeyboardEvent): void;
1959
+ /** Le defilement d'un panneau, reporte en proportion sur l'autre (une seule fois, sans rebond). */
1960
+ protected synchroniser(indice: number): void;
1961
+ protected interdireLeMenu(evenement: Event): void;
1962
+ static ɵfac: i0.ɵɵFactoryDeclaration<StImageViewer, never>;
1963
+ static ɵcmp: i0.ɵɵComponentDeclaration<StImageViewer, "st-image-viewer", never, {
1964
+ "images": {
1965
+ "alias": "images";
1966
+ "required": true;
1967
+ "isSignal": true;
1968
+ };
1969
+ "libelle": {
1970
+ "alias": "libelle";
1971
+ "required": true;
1972
+ "isSignal": true;
1973
+ };
1974
+ "filigrane": {
1975
+ "alias": "filigrane";
1976
+ "required": false;
1977
+ "isSignal": true;
1978
+ };
1979
+ }, {}, never, never, true, never>;
1980
+ }
1864
1981
  /**
1865
1982
  * Les libelles de `@starterlib/ui/donnees` (P08-08) : le catalogue par point d'entree (AD-10, D154),
1866
1983
  * comme ceux de la navigation et des formulaires. La langue suit celle du dictionnaire du tronc.
@@ -1874,6 +1991,20 @@ export interface LibellesDonnees {
1874
1991
  readonly perimeeDepuis: (duree: string) => string;
1875
1992
  /** Le nom de la donnee devant son etat, espace finale comprise (« Positions : »). */
1876
1993
  readonly libelleDeLaDonnee: (libelle: string) => string;
1994
+ /** `st-image-viewer` (P08-17) : le nom de sa barre d'outils. */
1995
+ readonly outilsDeLaVisionneuse: string;
1996
+ readonly reduire: string;
1997
+ readonly agrandir: string;
1998
+ readonly tournerAGauche: string;
1999
+ readonly tournerADroite: string;
2000
+ readonly moinsDeContraste: string;
2001
+ readonly plusDeContraste: string;
2002
+ readonly vueDOrigine: string;
2003
+ /** Les raccourcis de la visionneuse, en aide visible sous la barre. */
2004
+ readonly raccourcisDeLaVisionneuse: string;
2005
+ /** L'annonce de la vue : zoom et contraste en pour cent, rotation en degres. */
2006
+ readonly etatDeLaVue: (zoom: number, rotation: number, contraste: number) => string;
2007
+ readonly imageIllisible: string;
1877
2008
  }
1878
2009
  export declare const LIBELLES_DONNEES_FR: LibellesDonnees;
1879
2010
  export declare const LIBELLES_DONNEES_EN: LibellesDonnees;
@@ -3470,6 +3470,19 @@ export declare class StFileUpload extends ContratDeChamp implements FormValueCon
3470
3470
  readonly nombreMax: import("@angular/core").InputSignal<number | null>;
3471
3471
  /** Texte du bouton de choix. `null` : « Choisir un fichier » ou « Choisir des fichiers ». */
3472
3472
  readonly libelleDuChoix: import("@angular/core").InputSignal<string | null>;
3473
+ /**
3474
+ * Appareil photo natif (P08-17 d'Aplomb) : l'attribut `capture` du champ natif, `environment`
3475
+ * (camera arriere : une piece, un document) ou `user` (camera avant). `null` (defaut) : aucun
3476
+ * attribut, et le selecteur du systeme d'un telephone propose deja l'appareil photo des que
3477
+ * `accept` admet des images.
3478
+ *
3479
+ * ⚠️ Le televersement reste toujours possible (SPEC-ONBOARDING 28) : les navigateurs de bureau
3480
+ * ignorent l'attribut et ouvrent le selecteur de fichiers ; Safari sur iOS propose la photo, la
3481
+ * phototheque et les fichiers ; Chrome sur Android ouvre directement l'appareil photo. Une page
3482
+ * qui veut garder les fichiers sur Android offre un second champ sans `capture`. Aucune capture
3483
+ * en direct ni detection de presence : la photo prise est un fichier comme un autre.
3484
+ */
3485
+ readonly capture: import("@angular/core").InputSignal<"environment" | "user" | null>;
3473
3486
  /**
3474
3487
  * Ou en est chaque fichier, par `cleDeFichier`. Le composant AFFICHE ce trajet,
3475
3488
  * il ne le fait pas : `StTeleversement` de `@starterlib/core` s'en charge.
@@ -3580,6 +3593,11 @@ export declare class StFileUpload extends ContratDeChamp implements FormValueCon
3580
3593
  "required": false;
3581
3594
  "isSignal": true;
3582
3595
  };
3596
+ "capture": {
3597
+ "alias": "capture";
3598
+ "required": false;
3599
+ "isSignal": true;
3600
+ };
3583
3601
  "etats": {
3584
3602
  "alias": "etats";
3585
3603
  "required": false;
@@ -99,5 +99,216 @@ export declare class StVirtualList<T = unknown> {
99
99
  };
100
100
  }, {}, ["ligne"], never, true, never>;
101
101
  }
102
+ /**
103
+ * Une colonne de `st-virtual-table`, decrite en donnees : la forme de `ColonneDeTableau` de
104
+ * `st-data-table` (`@starterlib/ui/listes`), qu'une application passe telle quelle. Ce point
105
+ * d'entree n'importe aucun autre point d'entree du socle : la forme est redite, pas importee.
106
+ */
107
+ export interface ColonneVirtuelle {
108
+ readonly cle: string;
109
+ readonly libelle: string;
110
+ /** `fin` pour les nombres et les montants. */
111
+ readonly alignement?: 'debut' | 'fin';
112
+ /** Seulement si le SERVEUR trie sur cette colonne : le tableau emet `tri`, il ne reordonne rien. */
113
+ readonly triable?: boolean;
114
+ /** Libelle lu mais non affiche : colonne d'actions. Jamais vide. */
115
+ readonly libelleMasque?: boolean;
116
+ }
117
+ export type SensDeTriVirtuel = 'croissant' | 'decroissant';
118
+ export interface TriVirtuel {
119
+ readonly cle: string;
120
+ readonly sens: SensDeTriVirtuel;
121
+ }
122
+ /** Contexte d'un gabarit de cellule : la ligne, sa colonne et son rang dans le tableau ENTIER. */
123
+ export interface ContexteDeCelluleVirtuelle<T> {
124
+ readonly $implicit: T;
125
+ readonly colonne: ColonneVirtuelle;
126
+ readonly index: number;
127
+ }
128
+ /**
129
+ * Rendu d'une cellule de `st-virtual-table` : la meme ecriture que pour `st-data-table`, type par
130
+ * `[stCelluleDe]` :
131
+ *
132
+ * ```html
133
+ * <ng-template stCellule="montant" [stCelluleDe]="lignes()" let-ligne>
134
+ * {{ ligne.montant }}
135
+ * </ng-template>
136
+ * ```
137
+ */
138
+ export declare class StCelluleVirtuelle<T> {
139
+ readonly cle: import("@angular/core").InputSignal<string>;
140
+ /** Sert seulement au typage du contexte ; nom de l'attribut, d'ou l'absence d'alias. */
141
+ readonly stCelluleDe: import("@angular/core").InputSignal<readonly T[] | null | undefined>;
142
+ readonly gabarit: TemplateRef<ContexteDeCelluleVirtuelle<T>>;
143
+ static ngTemplateContextGuard<T>(_directive: StCelluleVirtuelle<T>, _contexte: unknown): _contexte is ContexteDeCelluleVirtuelle<T>;
144
+ static ɵfac: i0.ɵɵFactoryDeclaration<StCelluleVirtuelle<any>, never>;
145
+ static ɵdir: i0.ɵɵDirectiveDeclaration<StCelluleVirtuelle<any>, "ng-template[stCellule]", never, {
146
+ "cle": {
147
+ "alias": "stCellule";
148
+ "required": true;
149
+ "isSignal": true;
150
+ };
151
+ "stCelluleDe": {
152
+ "alias": "stCelluleDe";
153
+ "required": false;
154
+ "isSignal": true;
155
+ };
156
+ }, {}, never, never, true, never>;
157
+ }
158
+ /** Le prochain sens d'un tri : non trie, croissant, decroissant, puis non trie (ou croissant). */
159
+ export declare function prochainSensVirtuel(actuel: SensDeTriVirtuel | null, ternaire?: boolean): SensDeTriVirtuel | null;
160
+ /**
161
+ * Tableau virtualise (P08-19 d'Aplomb ; lot 267, sous la condition ecrite de `README.md`) : des
162
+ * centaines de milliers de lignes AFFICHEES ensemble, dont seules celles de la fenetre (et une
163
+ * marge) existent dans le document, sur un `<table>` NATIF. A l'echelle seulement : au MVP,
164
+ * `st-data-table` et la pagination par curseur suffisent.
165
+ *
166
+ * ```html
167
+ * <st-virtual-table legende="Journal technique" [colonnes]="colonnes" [lignes]="lignes()" cle="id"
168
+ * [(tri)]="tri">
169
+ * <ng-template stCellule="niveau" [stCelluleDe]="lignes()" let-ligne>{{ ligne.niveau }}</ng-template>
170
+ * </st-virtual-table>
171
+ * ```
172
+ *
173
+ * - **Un tableau, pas une grille** : le lecteur d'ecran le parcourt de cellule en cellule. La
174
+ * table porte `aria-rowcount` (lignes de donnees et ligne d'en-tete), chaque ligne rendue son
175
+ * `aria-rowindex` dans le tableau ENTIER : « ligne 4 201 sur 100 001 » alors que trente lignes
176
+ * seulement existent. Legende obligatoire (`caption`), colonne d'en-tete de ligne (la premiere
177
+ * par defaut, `enTeteDeLigne`), en-tete fige en haut de la fenetre.
178
+ * - **Tri PILOTE** : un clic sur une colonne `triable` emet `tri` (croissant, decroissant, puis non
179
+ * trie ; `triTernaire` a faux revient a croissant), porte par `aria-sort` ; le tableau ne
180
+ * reordonne JAMAIS les lignes, le serveur le fait.
181
+ * - **Selection par cle** (`selectionnable`, `[(selection)]`, `cle`) : une case par ligne, nommee
182
+ * par l'en-tete de sa ligne ; la colonne porte `libelleDeSelection`. Aucune selection globale :
183
+ * sur cent mille lignes, elle appartient au serveur. Une SEULE case dans l'ordre de tabulation
184
+ * (tabindex itinerant) : fleches haut et bas, Debut et Fin passent de case en case et amenent la
185
+ * ligne dans la fenetre ; sans cela, Tab parcourait cent mille cases et ne sortait jamais du
186
+ * tableau.
187
+ * - **Hauteur de ligne FIXE** (`hauteurDeLigne`, pixels CSS) : le calcul de la fenetre en depend ;
188
+ * le texte qui deborde se tronque dans sa cellule. Fenetre focalisable et nommee par la legende,
189
+ * qui defile aux fleches et a Page suivante ; hauteur `hauteurDeFenetre` (`24rem` par defaut).
190
+ */
191
+ export declare class StVirtualTable<T = unknown> {
192
+ readonly legende: import("@angular/core").InputSignal<string>;
193
+ readonly colonnes: import("@angular/core").InputSignal<readonly ColonneVirtuelle[]>;
194
+ readonly lignes: import("@angular/core").InputSignal<readonly T[]>;
195
+ /** La propriete qui identifie une ligne : suivi du rendu et selection. */
196
+ readonly cle: import("@angular/core").InputSignal<keyof T & string>;
197
+ /** La colonne d'en-tete de ligne (`th scope="row"`) ; la premiere par defaut. */
198
+ readonly enTeteDeLigne: import("@angular/core").InputSignal<string | null>;
199
+ readonly hauteurDeLigne: import("@angular/core").InputSignalWithTransform<number, unknown>;
200
+ /** Hauteur de la fenetre, longueur CSS : `24rem` par defaut. */
201
+ readonly hauteurDeFenetre: import("@angular/core").InputSignal<string>;
202
+ readonly tri: import("@angular/core").ModelSignal<TriVirtuel | null>;
203
+ readonly triTernaire: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
204
+ readonly selectionnable: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
205
+ readonly selection: import("@angular/core").ModelSignal<readonly string[]>;
206
+ /** Le nom, lu, de la colonne des cases (« Selection »), deja traduit. */
207
+ readonly libelleDeSelection: import("@angular/core").InputSignal<string>;
208
+ private readonly cellules;
209
+ private readonly fenetre;
210
+ protected readonly identifiant: string;
211
+ /** Decalage de l'en-tete fige : la fenetre deplace son contenu, l'en-tete revient en haut. */
212
+ protected readonly decalageDeLEnTete: import("@angular/core").WritableSignal<number>;
213
+ protected readonly hauteur: import("@angular/core").Signal<number>;
214
+ /** Marges de rendu : cinq lignes au moins de part et d'autre, dix au plus (60 lignes au plus). */
215
+ protected readonly margeMin: import("@angular/core").Signal<number>;
216
+ protected readonly margeMax: import("@angular/core").Signal<number>;
217
+ protected readonly colonneEnTete: import("@angular/core").Signal<string | null>;
218
+ protected readonly gabarits: import("@angular/core").Signal<Map<string, TemplateRef<ContexteDeCelluleVirtuelle<T>>>>;
219
+ private readonly choisies;
220
+ private readonly hote;
221
+ private readonly document;
222
+ /** La case active (tabindex itinerant) et la plage des lignes rendues. */
223
+ private readonly rangActif;
224
+ private readonly plageRendue;
225
+ /** La case dans l'ordre de tabulation : l'active si elle est rendue, sinon la premiere rendue. */
226
+ protected readonly rangTabulable: import("@angular/core").Signal<number>;
227
+ protected readonly suivi: (_rang: number, ligne: T) => unknown;
228
+ constructor();
229
+ protected cleDe(ligne: T): string;
230
+ /** La valeur brute d'une cellule sans gabarit : un texte, un nombre ou un booleen ; rien d'autre. */
231
+ protected valeur(ligne: T, colonne: ColonneVirtuelle): string;
232
+ protected identifiantDeLigne(rang: number): string;
233
+ protected triDe(colonne: ColonneVirtuelle): 'ascending' | 'descending' | 'none' | null;
234
+ protected trier(colonne: ColonneVirtuelle): void;
235
+ protected estChoisie(ligne: T): boolean;
236
+ protected basculer(ligne: T): void;
237
+ /** La case devient l'active quand elle recoit le focus (clic, Tab). */
238
+ protected activer(rang: number): void;
239
+ /** Fleches haut et bas, Debut et Fin : la case voisine, ou la premiere et la derniere. */
240
+ protected naviguer(evenement: KeyboardEvent, rang: number): void;
241
+ private caseDu;
242
+ /** Focalise la case d'un rang des qu'elle est rendue (quelques images apres un defilement). */
243
+ private focaliser;
244
+ /** Amene une ligne dans la fenetre (« aller a la ligne 42 000 »). */
245
+ allerA(rang: number, comportement?: ScrollBehavior): void;
246
+ static ɵfac: i0.ɵɵFactoryDeclaration<StVirtualTable<any>, never>;
247
+ static ɵcmp: i0.ɵɵComponentDeclaration<StVirtualTable<any>, "st-virtual-table", never, {
248
+ "legende": {
249
+ "alias": "legende";
250
+ "required": true;
251
+ "isSignal": true;
252
+ };
253
+ "colonnes": {
254
+ "alias": "colonnes";
255
+ "required": true;
256
+ "isSignal": true;
257
+ };
258
+ "lignes": {
259
+ "alias": "lignes";
260
+ "required": true;
261
+ "isSignal": true;
262
+ };
263
+ "cle": {
264
+ "alias": "cle";
265
+ "required": true;
266
+ "isSignal": true;
267
+ };
268
+ "enTeteDeLigne": {
269
+ "alias": "enTeteDeLigne";
270
+ "required": false;
271
+ "isSignal": true;
272
+ };
273
+ "hauteurDeLigne": {
274
+ "alias": "hauteurDeLigne";
275
+ "required": false;
276
+ "isSignal": true;
277
+ };
278
+ "hauteurDeFenetre": {
279
+ "alias": "hauteurDeFenetre";
280
+ "required": false;
281
+ "isSignal": true;
282
+ };
283
+ "tri": {
284
+ "alias": "tri";
285
+ "required": false;
286
+ "isSignal": true;
287
+ };
288
+ "triTernaire": {
289
+ "alias": "triTernaire";
290
+ "required": false;
291
+ "isSignal": true;
292
+ };
293
+ "selectionnable": {
294
+ "alias": "selectionnable";
295
+ "required": false;
296
+ "isSignal": true;
297
+ };
298
+ "selection": {
299
+ "alias": "selection";
300
+ "required": false;
301
+ "isSignal": true;
302
+ };
303
+ "libelleDeSelection": {
304
+ "alias": "libelleDeSelection";
305
+ "required": false;
306
+ "isSignal": true;
307
+ };
308
+ }, {
309
+ "tri": "triChange";
310
+ "selection": "selectionChange";
311
+ }, ["cellules"], never, true, never>;
312
+ }
102
313
 
103
314
  export {};
package/virtuel/README.md CHANGED
@@ -33,6 +33,45 @@ Ce qu'elle n'est pas : une grille editable (`st-data-grid`) ni une liste de tran
33
33
  - `allerA(rang)` : amene une ligne dans la fenetre.
34
34
  - Hauteur de la fenetre : l'entree `hauteurDeFenetre`, une longueur CSS (`24rem` par defaut).
35
35
 
36
+ ## `st-virtual-table` (P08-19 d'Aplomb)
37
+
38
+ Meme condition d'entree, aux volumes de l'echelle : des centaines de milliers de lignes d'un
39
+ journal technique ou d'un audit, affichees ensemble (au MVP, `st-data-table` et la pagination par
40
+ curseur suffisent ; ecran nomme : P13-11).
41
+
42
+ ```html
43
+ <st-virtual-table
44
+ legende="Journal technique"
45
+ [colonnes]="colonnes"
46
+ [lignes]="lignes()"
47
+ cle="id"
48
+ [(tri)]="tri"
49
+ selectionnable
50
+ libelleDeSelection="Selection"
51
+ [(selection)]="choisies"
52
+ >
53
+ <ng-template stCellule="niveau" [stCelluleDe]="lignes()" let-ligne
54
+ >{{ ligne.niveau }}</ng-template
55
+ >
56
+ </st-virtual-table>
57
+ ```
58
+
59
+ - Un `<table>` NATIF, pas une grille : `caption` (la `legende`, qui nomme aussi la fenetre),
60
+ `aria-rowcount` sur la table (lignes et ligne d'en-tete), `aria-rowindex` sur chaque ligne rendue
61
+ (rang dans le tableau ENTIER), en-tete de ligne `th scope="row"` (la premiere colonne par defaut,
62
+ `enTeteDeLigne`), en-tete fige en haut de la fenetre.
63
+ - Colonnes : la forme de `ColonneDeTableau` de `st-data-table` (`ColonneVirtuelle` : `cle`,
64
+ `libelle`, `alignement`, `triable`, `libelleMasque`), redite et non importee : ce point d'entree
65
+ n'en importe aucun autre. Cellules : `ng-template [stCellule]`, la meme ecriture.
66
+ - Tri PILOTE (`[(tri)]`, `triTernaire`) : un clic emet la demande, `aria-sort` la porte ; les lignes
67
+ ne sont jamais reordonnees, le serveur le fait.
68
+ - Selection par cle (`selectionnable`, `[(selection)]`, `cle`, `libelleDeSelection`) : une case par
69
+ ligne, nommee par l'en-tete de sa ligne ; aucune selection globale (elle appartient au serveur).
70
+ - `hauteurDeLigne` FIXE (44 par defaut ; nulle ou negative refusee), `hauteurDeFenetre` (`24rem`),
71
+ `allerA(rang)`. Au plus soixante lignes dans le document (marges de cinq a dix lignes).
72
+ - Essais : `st-virtual-table.spec.ts` (cent mille lignes, au plus soixante rendues, rang et total,
73
+ tri pilote, selection par cle, accessibilite) ; banc : cent mille lignes fictives.
74
+
36
75
  ## Gardes et poids
37
76
 
38
77
  - Point d'entree a lui : il traine `@angular/cdk/scrolling` et RIEN d'autre (`pnpm paquets:check`,