@ktortu/aaa 0.1.0-beta.0 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +27 -9
  2. package/cdk/styles/tabs.css +100 -21
  3. package/fesm2022/ktortu-aaa-button.mjs +18 -11
  4. package/fesm2022/ktortu-aaa-button.mjs.map +1 -1
  5. package/fesm2022/ktortu-aaa-card.mjs +29 -4
  6. package/fesm2022/ktortu-aaa-card.mjs.map +1 -1
  7. package/fesm2022/ktortu-aaa-cdk.mjs +59 -15
  8. package/fesm2022/ktortu-aaa-cdk.mjs.map +1 -1
  9. package/fesm2022/ktortu-aaa-dialog.mjs +134 -24
  10. package/fesm2022/ktortu-aaa-dialog.mjs.map +1 -1
  11. package/fesm2022/ktortu-aaa-forms.mjs +748 -294
  12. package/fesm2022/ktortu-aaa-forms.mjs.map +1 -1
  13. package/fesm2022/ktortu-aaa-i18n.mjs +139 -0
  14. package/fesm2022/ktortu-aaa-i18n.mjs.map +1 -0
  15. package/fesm2022/ktortu-aaa-menu.mjs +38 -13
  16. package/fesm2022/ktortu-aaa-menu.mjs.map +1 -1
  17. package/fesm2022/ktortu-aaa-snackbar.mjs +465 -0
  18. package/fesm2022/ktortu-aaa-snackbar.mjs.map +1 -0
  19. package/fesm2022/ktortu-aaa-tabs.mjs +319 -42
  20. package/fesm2022/ktortu-aaa-tabs.mjs.map +1 -1
  21. package/fesm2022/ktortu-aaa-tooltip.mjs +3 -2
  22. package/fesm2022/ktortu-aaa-tooltip.mjs.map +1 -1
  23. package/fesm2022/ktortu-aaa.mjs +2 -0
  24. package/fesm2022/ktortu-aaa.mjs.map +1 -1
  25. package/forms/checkbox/checkbox-group.css +0 -8
  26. package/forms/chips/chip-list.css +5 -0
  27. package/forms/radio/radio-group.css +0 -8
  28. package/forms/styles/field-box.css +152 -2
  29. package/forms/styles/field-pending.css +46 -0
  30. package/forms/styles/select-panel.css +4 -0
  31. package/forms/styles/tokens.css +3 -0
  32. package/menu/menu.css +8 -4
  33. package/package.json +9 -1
  34. package/snackbar/snackbar-tokens.css +53 -0
  35. package/snackbar/snackbar.css +175 -0
  36. package/styles/forms.css +1 -0
  37. package/styles/snackbar.css +9 -0
  38. package/styles/styles.css +1 -0
  39. package/types/ktortu-aaa-button.d.ts +22 -8
  40. package/types/ktortu-aaa-card.d.ts +24 -4
  41. package/types/ktortu-aaa-cdk.d.ts +38 -0
  42. package/types/ktortu-aaa-dialog.d.ts +129 -31
  43. package/types/ktortu-aaa-forms.d.ts +503 -160
  44. package/types/ktortu-aaa-i18n.d.ts +77 -0
  45. package/types/ktortu-aaa-menu.d.ts +15 -8
  46. package/types/ktortu-aaa-snackbar.d.ts +275 -0
  47. package/types/ktortu-aaa-tabs.d.ts +130 -13
  48. package/types/ktortu-aaa-tooltip.d.ts +5 -0
  49. package/types/ktortu-aaa.d.ts +2 -0
@@ -0,0 +1,77 @@
1
+ import { EnvironmentProviders } from '@angular/core';
2
+ import { KtFieldConfig, KtSelectConfigOptions, KtChipsConfig } from '@ktortu/aaa/forms';
3
+ import { KtSnackbarConfig } from '@ktortu/aaa/snackbar';
4
+ import { KtTabsConfig } from '@ktortu/aaa/tabs';
5
+
6
+ /**
7
+ * Agrégat de TOUS les libellés traduisibles de la lib, groupés par famille de composants.
8
+ * Chaque clé reprend la config du token correspondant (`Partial` : tout est optionnel — on ne
9
+ * fournit que ce qu'on veut traduire). C'est l'« interface de traduction » unique de la lib :
10
+ * un point d'entrée pour brancher une langue d'un coup.
11
+ *
12
+ * @see provideKtTranslations pour enregistrer un jeu de libellés.
13
+ * @see provideKtDefaultFR pour partir des libellés français.
14
+ */
15
+ interface KtTranslations {
16
+ /** Libellés des champs (`clearLabel`, `helpLabel`) → {@link KT_FIELD_CONFIG}. */
17
+ field?: Partial<KtFieldConfig>;
18
+ /** Libellés des selects / multi-selects → {@link KT_SELECT_CONFIG}. */
19
+ select?: Partial<KtSelectConfigOptions>;
20
+ /** Libellés des listes de chips → {@link KT_CHIPS_CONFIG}. */
21
+ chips?: Partial<KtChipsConfig>;
22
+ /** Libellés de la snackbar (`closeLabel`) → {@link KT_SNACKBAR_CONFIG}. */
23
+ snackbar?: Partial<KtSnackbarConfig>;
24
+ /** Libellés de la pagination des onglets → {@link KT_TABS_CONFIG}. */
25
+ tabs?: Partial<KtTabsConfig>;
26
+ }
27
+ /**
28
+ * Enregistre, en un seul appel, les libellés fournis sur les tokens de config de la lib.
29
+ * Base = défauts anglais de chaque composant ; seules les familles **présentes** dans `t` sont
30
+ * fournies (les autres gardent leur défaut anglais et restent surchargeables ailleurs).
31
+ *
32
+ * À placer dans les `providers` de `app.config.ts` (ou de tout injecteur).
33
+ *
34
+ * @param t Libellés à fournir, groupés par famille ; seules les familles présentes sont enregistrées.
35
+ * @returns Les `EnvironmentProviders` liant chaque famille présente à son token de config.
36
+ * @example
37
+ * ```ts
38
+ * provideKtTranslations({ tabs: { nextLabel: 'Suivant', previousLabel: 'Précédent' } })
39
+ * ```
40
+ */
41
+ declare function provideKtTranslations(t: KtTranslations): EnvironmentProviders;
42
+ /**
43
+ * Fusion par famille de deux {@link KtTranslations} : `over` écrase `base`, clé par clé.
44
+ * @param base Libellés de référence (ex. un dictionnaire de langue complet).
45
+ * @param over Libellés prioritaires venant écraser `base`.
46
+ * @returns Un nouveau {@link KtTranslations} fusionné, famille par famille.
47
+ * @example mergeKtTranslations(KT_FR_TRANSLATIONS, { tabs: { nextLabel: 'Suivant' } })
48
+ */
49
+ declare function mergeKtTranslations(base: KtTranslations, over: KtTranslations): KtTranslations;
50
+
51
+ /**
52
+ * Dictionnaire **français** complet de tous les libellés de la lib. Figé et réutilisable :
53
+ * importable tel quel (ex. pour le composer avec d'autres réglages) ou via {@link provideKtDefaultFR}.
54
+ * Les libellés à pluriels sont des fonctions, pour laisser la grammaire au consommateur.
55
+ */
56
+ declare const KT_FR_TRANSLATIONS: KtTranslations;
57
+ /**
58
+ * Enregistre les libellés **français** par défaut sur toute la lib, en un seul appel.
59
+ * `overrides` permet d'ajuster ponctuellement sans tout réécrire (fusion par famille,
60
+ * cf. {@link mergeKtTranslations}). À placer dans les `providers` de `app.config.ts`.
61
+ *
62
+ * @param overrides Libellés à ajuster par-dessus le français (fusion par famille). Défaut : `{}`.
63
+ * @returns Les `EnvironmentProviders` enregistrant le français (fusionné aux `overrides`).
64
+ * @example
65
+ * ```ts
66
+ * // app.config.ts
67
+ * providers: [
68
+ * provideKtDefaultFR(), // tout en français
69
+ * // ou en ajustant un libellé précis :
70
+ * provideKtDefaultFR({ tabs: { nextLabel: 'Suivant' } }),
71
+ * ]
72
+ * ```
73
+ */
74
+ declare function provideKtDefaultFR(overrides?: KtTranslations): EnvironmentProviders;
75
+
76
+ export { KT_FR_TRANSLATIONS, mergeKtTranslations, provideKtDefaultFR, provideKtTranslations };
77
+ export type { KtTranslations };
@@ -48,7 +48,6 @@ declare class KtMenu {
48
48
  * ```
49
49
  */
50
50
  declare class KtMenuItem {
51
- private readonly host;
52
51
  private readonly ariaItem;
53
52
  private readonly platformId;
54
53
  protected anchorName: string | undefined;
@@ -88,7 +87,6 @@ declare class KtMenuSeparator {
88
87
  * ```
89
88
  */
90
89
  declare class KtMenuTrigger {
91
- private readonly host;
92
90
  private readonly ariaTrigger;
93
91
  private readonly platformId;
94
92
  private readonly idGen;
@@ -111,8 +109,13 @@ declare class KtMenuTrigger {
111
109
  */
112
110
  declare class KtMenuItemCheckbox {
113
111
  private readonly ariaItem;
114
- /** État coché, bidirectionnel : `[(checked)]`. */
112
+ private readonly host;
113
+ /**
114
+ * État coché, bidirectionnel : `[(checked)]`.
115
+ * @default false
116
+ */
115
117
  readonly checked: i0.ModelSignal<boolean>;
118
+ constructor();
116
119
  protected activate(event: Event): void;
117
120
  static ɵfac: i0.ɵɵFactoryDeclaration<KtMenuItemCheckbox, never>;
118
121
  static ɵdir: i0.ɵɵDirectiveDeclaration<KtMenuItemCheckbox, "[ktMenuItemCheckbox]", never, { "checked": { "alias": "checked"; "required": false; "isSignal": true; }; }, { "checked": "checkedChange"; }, never, never, true, never>;
@@ -133,7 +136,10 @@ declare const KT_MENU_RADIO_GROUP: InjectionToken<KtMenuRadioGroup<unknown>>;
133
136
  * ```
134
137
  */
135
138
  declare class KtMenuRadioGroup<V> {
136
- /** Valeur sélectionnée du groupe, bidirectionnelle : `[(value)]`. */
139
+ /**
140
+ * Valeur sélectionnée du groupe, bidirectionnelle : `[(value)]`.
141
+ * @default null
142
+ */
137
143
  readonly value: i0.ModelSignal<V | null>;
138
144
  static ɵfac: i0.ɵɵFactoryDeclaration<KtMenuRadioGroup<any>, never>;
139
145
  static ɵdir: i0.ɵɵDirectiveDeclaration<KtMenuRadioGroup<any>, "[ktMenuRadioGroup]", ["ktMenuRadioGroup"], { "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, never>;
@@ -151,7 +157,8 @@ declare class KtMenuRadioGroup<V> {
151
157
  declare class KtMenuItemRadio<V> {
152
158
  private readonly ariaItem;
153
159
  private readonly group;
154
- /** Valeur portée par ce radio (comparée à celle du groupe). */
160
+ private readonly host;
161
+ /** Valeur portée par ce radio (comparée à celle du groupe). @default (requis) */
155
162
  readonly value: i0.InputSignal<V>;
156
163
  protected readonly checked: i0.Signal<boolean>;
157
164
  constructor();
@@ -162,10 +169,10 @@ declare class KtMenuItemRadio<V> {
162
169
 
163
170
  /**
164
171
  * Import ergonomique de toute la famille menu (couche de THÈME ktortu) en une fois :
165
- * `imports: [KT_MENU]` au lieu d'énumérer chaque directive. À composer avec les directives
172
+ * `imports: [KtMenuImports]` au lieu d'énumérer chaque directive. À composer avec les directives
166
173
  * d'`@angular/aria/menu` (`Menu`, `MenuItem`, `MenuTrigger`, `MenuContent`), qui apportent le
167
174
  * comportement accessible.
168
175
  */
169
- declare const KT_MENU: readonly [typeof KtMenu, typeof KtMenuItem, typeof KtMenuSeparator, typeof KtMenuTrigger, typeof KtMenuItemCheckbox, typeof KtMenuItemRadio, typeof KtMenuRadioGroup];
176
+ declare const KtMenuImports: readonly [typeof KtMenu, typeof KtMenuItem, typeof KtMenuSeparator, typeof KtMenuTrigger, typeof KtMenuItemCheckbox, typeof KtMenuItemRadio, typeof KtMenuRadioGroup];
170
177
 
171
- export { KT_MENU, KT_MENU_RADIO_GROUP, KtMenu, KtMenuItem, KtMenuItemCheckbox, KtMenuItemRadio, KtMenuRadioGroup, KtMenuSeparator, KtMenuTrigger };
178
+ export { KT_MENU_RADIO_GROUP, KtMenu, KtMenuImports, KtMenuItem, KtMenuItemCheckbox, KtMenuItemRadio, KtMenuRadioGroup, KtMenuSeparator, KtMenuTrigger };
@@ -0,0 +1,275 @@
1
+ import * as i0 from '@angular/core';
2
+ import { InjectionToken, Provider, OnDestroy } from '@angular/core';
3
+ import { Observable } from 'rxjs';
4
+
5
+ /** Politesse de l'annonce au lecteur d'écran (relayée à `LiveAnnouncer`). */
6
+ type KtSnackbarPoliteness = 'polite' | 'assertive';
7
+ /** Bord d'ancrage de la snackbar dans le viewport. */
8
+ type KtSnackbarPosition = 'top' | 'bottom';
9
+ /**
10
+ * Régime temporel de la snackbar :
11
+ * - `'auto'` : disparition automatique après `duration`, **mise en pause au survol et au focus**
12
+ * clavier (WCAG 1.4.13 / 2.2.1). Conforme **AA**. C'est le défaut.
13
+ * - `'manual'` : **aucune** minuterie, la snackbar reste jusqu'à fermeture explicite
14
+ * (bouton de fermeture ou `ref.dismiss()`). Conforme **2.2.3 (AAA)** au sens strict.
15
+ *
16
+ * Conformément aux recommandations d'accessibilité (Roselli/Soueidan), la snackbar ne porte **pas
17
+ * d'action interactive** (ex. « Annuler ») : une action auto-disparaissante n'est pas atteignable et
18
+ * une live region n'expose pas ses boutons. Pour un undo, préférez un mécanisme atteignable côté app
19
+ * (Ctrl+Z, bannière persistante).
20
+ */
21
+ type KtSnackbarTiming = 'auto' | 'manual';
22
+ /**
23
+ * Variante sémantique de la snackbar. Pilote uniquement l'**apparence** (couleur d'accent + icône),
24
+ * via l'attribut `data-variant` et les tokens CSS `--snackbar-*` — donc entièrement gérée par le
25
+ * thème, sans logique TypeScript. Découplée de la `politeness` (une « erreur » n'est pas forcément
26
+ * une urgence assertive). La couleur n'est jamais le seul indice : chaque variante porte une **icône**
27
+ * de forme distincte (WCAG 1.4.1).
28
+ * - `'neutral'` : pastille neutre, sans icône (défaut) ;
29
+ * - `'info' | 'success' | 'warning' | 'error'` : accent + icône dédiés.
30
+ */
31
+ type KtSnackbarVariant = 'neutral' | 'info' | 'success' | 'warning' | 'error';
32
+ /**
33
+ * Défauts de la snackbar, injectables via `provideKtSnackbar` / `KT_SNACKBAR_CONFIG`.
34
+ * Tous les champs sont surchargeables **par appel** via les options de `KtSnackbar.open()`.
35
+ *
36
+ * Résolution en cascade (convention de la lib) : `option d'open ?? KT_SNACKBAR_CONFIG ?? défaut`.
37
+ */
38
+ interface KtSnackbarConfig {
39
+ /**
40
+ * Durée d'affichage en régime `'auto'`. Soit un **nombre fixe** (ms), soit le sentinel
41
+ * **`'reading-time'`** (DÉFAUT) qui **calcule** la durée d'après la longueur du message :
42
+ * `clamp(longueur × readingTimePerChar, readingTimeMin, readingTimeMax)`. Passer un nombre à
43
+ * `open()` force donc une durée fixe pour cet appel.
44
+ *
45
+ * ⚠️ Gardez le message **court** : une snackbar est un message transitoire (pas un paragraphe).
46
+ * Un message long fait grimper la durée jusqu'au plafond `readingTimeMax`.
47
+ * @default 'reading-time'
48
+ */
49
+ duration: number | 'reading-time';
50
+ /** Plancher (ms) de la durée calculée (`'reading-time'`) — laisse le temps de lire un message court. @default 4000 */
51
+ readingTimeMin: number;
52
+ /** Plafond (ms) de la durée calculée (`'reading-time'`) — borne un message long. @default 10000 */
53
+ readingTimeMax: number;
54
+ /** Coefficient de lecture : millisecondes ajoutées par caractère du message. @default 60 (~200 mots/min) */
55
+ readingTimePerChar: number;
56
+ /** Régime temporel (cf. {@link KtSnackbarTiming}). @default 'auto' (AA + pause) */
57
+ timing: KtSnackbarTiming;
58
+ /** Bord d'ancrage dans le viewport. @default 'bottom' */
59
+ position: KtSnackbarPosition;
60
+ /** Politesse de l'annonce lecteur d'écran. @default 'polite' */
61
+ politeness: KtSnackbarPoliteness;
62
+ /** Variante sémantique (apparence seule, cf. {@link KtSnackbarVariant}). @default 'neutral' */
63
+ variant: KtSnackbarVariant;
64
+ /** Affiche un bouton de fermeture (cible 44px, AAA). @default true */
65
+ closable: boolean;
66
+ /** Nom accessible du bouton de fermeture. @default 'Close' (FR fourni en lot L3) */
67
+ closeLabel: string;
68
+ /**
69
+ * Taille maximale de la file FIFO (snackbar affichée + en attente). Au-delà, les **plus anciennes
70
+ * en attente** sont retirées silencieusement. Une seule snackbar est visible à la fois. @default 3
71
+ */
72
+ max: number;
73
+ }
74
+ /** Défauts AAA-orientés de la snackbar (anglais neutre). */
75
+ declare const KT_SNACKBAR_DEFAULTS: KtSnackbarConfig;
76
+ declare const KT_SNACKBAR_CONFIG: InjectionToken<Partial<KtSnackbarConfig>>;
77
+ /**
78
+ * Options ponctuelles d'ouverture d'une snackbar : un sous-ensemble (toutes facultatives) de la
79
+ * config, prioritaire sur `KT_SNACKBAR_CONFIG` et sur les défauts.
80
+ */
81
+ type KtSnackbarOptions = Partial<KtSnackbarConfig>;
82
+ /**
83
+ * Fournit des défauts de snackbar pour un sous-arbre ou l'application entière.
84
+ *
85
+ * @example
86
+ * ```ts
87
+ * // app.config.ts — bascule TOUTE l'app en AAA strict (aucune disparition automatique)
88
+ * providers: [provideKtSnackbar({ timing: 'manual' })]
89
+ * ```
90
+ * @example
91
+ * ```ts
92
+ * providers: [provideKtSnackbar({ duration: 8000, position: 'top' })]
93
+ * ```
94
+ */
95
+ declare function provideKtSnackbar(config: Partial<KtSnackbarConfig>): Provider;
96
+
97
+ /**
98
+ * Raison de fermeture d'une snackbar, transmise par {@link KtSnackbarRef.afterDismissed}.
99
+ * - `'timeout'` : la minuterie (régime `'auto'`) est arrivée à échéance ;
100
+ * - `'dismiss'` : fermeture explicite (bouton de fermeture, `Échap`, ou `ref.dismiss()`) ;
101
+ * - `'replaced'` : la snackbar a été retirée de la file sans être affichée (file pleine — cf. `max`).
102
+ */
103
+ type KtSnackbarDismissReason = 'timeout' | 'dismiss' | 'replaced';
104
+ /**
105
+ * Référence d'une snackbar ouverte, renvoyée par `KtSnackbar.open()`. Permet de fermer la
106
+ * snackbar par programmation et d'observer sa fermeture.
107
+ *
108
+ * Le débutant peut l'ignorer (`snackbar.open('…')`) ; le code avancé s'en sert pour piloter la
109
+ * fermeture et réagir à la raison de fin.
110
+ *
111
+ * @example
112
+ * ```ts
113
+ * const ref = snackbar.open('Brouillon enregistré');
114
+ * ref.afterDismissed().subscribe((reason) => console.log(reason)); // 'timeout' | 'dismiss' | 'replaced'
115
+ * // plus tard : ref.dismiss();
116
+ * ```
117
+ */
118
+ declare class KtSnackbarRef {
119
+ private readonly onDismiss;
120
+ private readonly _afterDismissed;
121
+ private settled;
122
+ /**
123
+ * @param onDismiss Rappel exécuté une fois à la fermeture (animation de sortie + démontage de
124
+ * l'overlay + avance de la file), fourni par le service.
125
+ * @internal Construit par `KtSnackbar` — n'instanciez pas `KtSnackbarRef` directement.
126
+ */
127
+ constructor(onDismiss: (reason: KtSnackbarDismissReason) => void);
128
+ /**
129
+ * Ferme la snackbar (idempotent). Déclenche la sortie/démontage puis émet la raison sur
130
+ * `afterDismissed()`.
131
+ * @param reason Raison de fermeture. @default 'dismiss'
132
+ */
133
+ dismiss(reason?: KtSnackbarDismissReason): void;
134
+ /** Émet une fois (puis complète) à la fermeture, avec la {@link KtSnackbarDismissReason}. */
135
+ afterDismissed(): Observable<KtSnackbarDismissReason>;
136
+ }
137
+
138
+ /**
139
+ * Service d'ouverture des snackbars `@ktortu/aaa` — feedback **non bloquant** qui confirme une
140
+ * action ou signale un événement transitoire sans interrompre la tâche (n'utilisez PAS de snackbar
141
+ * pour une information critique à acquitter : préférez le dialog).
142
+ *
143
+ * Architecture a11y :
144
+ * - **CDK Overlay** pour le panneau visuel, **CDK LiveAnnouncer** pour l'annonce — **un seul canal**
145
+ * d'annonce (le panneau n'est pas une live region) ;
146
+ * - **le focus n'est jamais déplacé** vers la snackbar (RGAA « message de statut » / WCAG 4.1.3) ;
147
+ * - disparition automatique **en pause au survol et au focus** (régime `'auto'`, défaut AA), ou
148
+ * persistante (`timing: 'manual'`, AAA) ;
149
+ * - **file FIFO** : une seule snackbar visible, les suivantes patientent (live region non saturée).
150
+ * La file est bornée par `max` (défaut 3) ; les messages **identiques** sont fusionnés (coalescing) ;
151
+ * - **Échap** ferme la snackbar affichée (la plus récente).
152
+ *
153
+ * Requiert côté hôte les styles `@angular/cdk/overlay-prebuilt.css` **et**
154
+ * `@angular/cdk/a11y-prebuilt.css` (ce dernier masque l'élément du LiveAnnouncer).
155
+ *
156
+ * @example
157
+ * ```ts
158
+ * private readonly snackbar = inject(KtSnackbar);
159
+ * this.snackbar.open('Brouillon enregistré'); // disparaît, annonce polie
160
+ * this.snackbar.open('Fichier supprimé', { variant: 'success' }); // variante (couleur + icône)
161
+ * this.snackbar.open('Hors ligne', { timing: 'manual' }); // reste jusqu'à fermeture (AAA)
162
+ * ```
163
+ */
164
+ declare class KtSnackbar implements OnDestroy {
165
+ private readonly overlay;
166
+ private readonly injector;
167
+ private readonly liveAnnouncer;
168
+ private readonly config;
169
+ private readonly platformId;
170
+ private readonly doc;
171
+ /** File FIFO : `queue[0]` est la snackbar affichée dès qu'elle est attachée. */
172
+ private readonly queue;
173
+ private active;
174
+ private escapeRegistered;
175
+ /**
176
+ * Ouvre une snackbar affichant `message`. Les `options` priment sur `KT_SNACKBAR_CONFIG`, qui
177
+ * prime sur les défauts. Renvoie une {@link KtSnackbarRef} (ignorable dans le cas simple).
178
+ *
179
+ * Une seule snackbar est visible : si une autre est affichée, celle-ci patiente en file (FIFO).
180
+ * Un `message` identique à une snackbar déjà affichée ou en attente est **fusionné** : on renvoie
181
+ * alors la référence existante sans rien ré-empiler.
182
+ *
183
+ * @param message Texte affiché et annoncé au lecteur d'écran.
184
+ * @param options Surcharges ponctuelles (durée, régime, position, politesse, variante, fermeture).
185
+ * @returns La référence de la snackbar (existante en cas de fusion).
186
+ */
187
+ open(message: string, options?: KtSnackbarOptions): KtSnackbarRef;
188
+ ngOnDestroy(): void;
189
+ /** Borne la file (affichée + en attente) : retire les plus ANCIENNES en attente au-delà de `max`. */
190
+ private enforceMax;
191
+ /** Affiche la tête de file si rien n'est actuellement visible. */
192
+ private showHead;
193
+ /** Retire l'élément de la file ; s'il est affiché, joue la sortie puis démonte et avance la file. */
194
+ private handleDismiss;
195
+ private readonly onDocumentKeydown;
196
+ private registerEscape;
197
+ private unregisterEscape;
198
+ /**
199
+ * Durée effective (ms) en régime `'auto'`. Un nombre est pris tel quel (durée fixe) ; le sentinel
200
+ * `'reading-time'` calcule `clamp(longueur × perChar, min, max)`.
201
+ */
202
+ private computeDuration;
203
+ /** Résolution en cascade `option ?? KT_SNACKBAR_CONFIG ?? défaut`, champ par champ. */
204
+ private resolve;
205
+ static ɵfac: i0.ɵɵFactoryDeclaration<KtSnackbar, never>;
206
+ static ɵprov: i0.ɵɵInjectableDeclaration<KtSnackbar>;
207
+ }
208
+
209
+ /**
210
+ * Données résolues passées au conteneur visuel à l'ouverture (injectées via {@link KT_SNACKBAR_CONTEXT}).
211
+ * Produites par `KtSnackbar` après résolution `option ?? config ?? défaut`.
212
+ */
213
+ interface KtSnackbarContext {
214
+ /** Message affiché et annoncé. */
215
+ readonly message: string;
216
+ /** Variante sémantique (apparence : accent + icône). */
217
+ readonly variant: KtSnackbarVariant;
218
+ /** Affiche le bouton de fermeture. */
219
+ readonly closable: boolean;
220
+ /** Nom accessible du bouton de fermeture. */
221
+ readonly closeLabel: string;
222
+ /** Régime temporel (la minuterie n'existe qu'en `'auto'`). */
223
+ readonly timing: KtSnackbarTiming;
224
+ /** Durée (ms) avant disparition automatique en régime `'auto'`. */
225
+ readonly duration: number;
226
+ }
227
+ declare const KT_SNACKBAR_CONTEXT: InjectionToken<KtSnackbarContext>;
228
+ /**
229
+ * Conteneur visuel d'une snackbar. **Volontairement pas une live region** (aucun `role`/`aria-live`
230
+ * sur l'hôte) : l'annonce passe par un canal UNIQUE, le `LiveAnnouncer` du service. On évite ainsi
231
+ * la double-annonce et l'écrasement de politesse observés sur d'autres libs.
232
+ *
233
+ * En régime `'auto'`, la minuterie de disparition se met **en pause au survol et au focus** clavier
234
+ * (WCAG 1.4.13 / 2.2.1) et reprend quand ni le pointeur ni le focus ne sont sur la snackbar.
235
+ * L'icône de variante est **décorative** (`aria-hidden`) : la forme distincte sert d'indice non
236
+ * coloré (WCAG 1.4.1), le sens reste porté par le texte.
237
+ *
238
+ * @internal Monté par `KtSnackbar` via un `ComponentPortal`.
239
+ */
240
+ declare class KtSnackbarContainer {
241
+ protected readonly context: KtSnackbarContext;
242
+ private readonly ref;
243
+ private readonly platformId;
244
+ private readonly host;
245
+ /** Vrai pendant l'animation de sortie (déclenche la classe `kt-snackbar--leaving`). */
246
+ protected readonly leaving: i0.WritableSignal<boolean>;
247
+ private timer;
248
+ private remaining;
249
+ private deadline;
250
+ private hovered;
251
+ private focused;
252
+ constructor();
253
+ protected close(): void;
254
+ /**
255
+ * Joue l'animation de sortie puis invoque `done` (démontage de l'overlay côté service). Appelé par
256
+ * le service à la fermeture. Sans animation (durée nulle, `prefers-reduced-motion`, ou SSR), `done`
257
+ * est invoqué immédiatement. Filet de sécurité par `setTimeout` si `transitionend` ne se déclenche pas.
258
+ */
259
+ playExit(done: () => void): void;
260
+ protected onPointerEnter(): void;
261
+ protected onPointerLeave(): void;
262
+ protected onFocusEnter(): void;
263
+ protected onFocusLeave(): void;
264
+ private maybeResume;
265
+ private startTimer;
266
+ private pauseTimer;
267
+ private clearTimer;
268
+ /** Durée (ms) de la transition de sortie, lue sur l'hôte (0 si aucune — ex. reduced-motion). */
269
+ private exitDurationMs;
270
+ static ɵfac: i0.ɵɵFactoryDeclaration<KtSnackbarContainer, never>;
271
+ static ɵcmp: i0.ɵɵComponentDeclaration<KtSnackbarContainer, "kt-snackbar-container", never, {}, {}, never, never, true, never>;
272
+ }
273
+
274
+ export { KT_SNACKBAR_CONFIG, KT_SNACKBAR_CONTEXT, KT_SNACKBAR_DEFAULTS, KtSnackbar, KtSnackbarContainer, KtSnackbarRef, provideKtSnackbar };
275
+ export type { KtSnackbarConfig, KtSnackbarContext, KtSnackbarDismissReason, KtSnackbarOptions, KtSnackbarPoliteness, KtSnackbarPosition, KtSnackbarTiming, KtSnackbarVariant };
@@ -1,27 +1,144 @@
1
- import * as i0 from '@angular/core';
1
+ import * as _angular_core from '@angular/core';
2
+ import { InjectionToken } from '@angular/core';
2
3
 
3
4
  /**
4
- * Amène l'onglet sélectionné dans la zone visible quand la liste d'onglets déborde et défile
5
- * (cf. tabs.css). Le focus clavier d'`@angular/aria` scrolle déjà l'onglet focalisé ; cette
6
- * directive couvre ce que le CSS seul ne peut pas faire de façon fiable : l'onglet actif
7
- * **hors-champ au montage** et lors d'un **changement de sélection programmatique**.
5
+ * Pilote le **débordement** d'une liste d'onglets `@angular/aria/tabs` (cf. tabs.css). Deux rôles :
6
+ *
7
+ * 1. **Scroll-into-view** : amène l'onglet sélectionné dans la vue au montage et lors d'un changement
8
+ * de sélection programmatique (ce que le CSS seul ne fait pas), en respectant `prefers-reduced-motion`.
9
+ * 2. **Pagination** : expose un état réactif (`canScrollStart()`, `canScrollEnd()`, `overflowing()`,
10
+ * `orientation()`) et une méthode `scrollByPage()`, pour brancher des boutons chevrons (cf. le
11
+ * composant clé-en-main `KtTabScrollerPager`, ou des boutons custom via `exportAs: 'ktTabScroller'`).
8
12
  *
9
13
  * Opt-in, à poser sur `[ngTabList]` :
10
14
  *
11
15
  * @example
12
16
  * ```html
13
- * <ul ngTabList ktTabScroll [(selectedTab)]="tab"> … </ul>
17
+ * <ul ngTabList ktTabScroller #s="ktTabScroller" [(selectedTab)]="tab"> … </ul>
18
+ * <button (click)="s.scrollByPage('start')" [disabled]="!s.canScrollStart()">‹</button>
14
19
  * ```
15
- *
16
- * Intégrée réactivement avec `@angular/aria/tabs` via son `ModelSignal` `selectedTab`.
17
20
  */
18
- declare class KtTabScroll {
21
+ declare class KtTabScroller {
19
22
  private readonly list;
20
23
  private readonly tabList;
24
+ private readonly doc;
25
+ private readonly destroyRef;
26
+ /** Préférence « réduire les animations », lue à chaud (absente possible en SSR/jsdom). */
27
+ private readonly reducedMotion;
28
+ /**
29
+ * Métriques de débordement. Mises à jour UNIQUEMENT depuis des callbacks navigateur
30
+ * (`afterNextRender`, `scroll`, `ResizeObserver`, `MutationObserver`) — jamais depuis le corps
31
+ * d'un effet réactif, pour rester conforme (pas d'écriture de signal dans un effet).
32
+ */
33
+ private readonly metrics;
34
+ /** Reste-t-il du contenu hors-champ côté début (à brancher sur le bouton « précédent ») ? */
35
+ readonly canScrollStart: _angular_core.Signal<boolean>;
36
+ /** Reste-t-il du contenu hors-champ côté fin (à brancher sur le bouton « suivant ») ? */
37
+ readonly canScrollEnd: _angular_core.Signal<boolean>;
38
+ /** La liste déborde-t-elle ? (utile pour masquer toute la barre de pagination). */
39
+ readonly overflowing: _angular_core.Signal<boolean>;
40
+ /** Axe courant, dérivé de l'orientation `@angular/aria`. */
41
+ readonly orientation: _angular_core.Signal<"horizontal" | "vertical">;
42
+ constructor();
43
+ /**
44
+ * Fait défiler d'environ une « page » (≈ {@link PAGE_RATIO} de la zone visible) vers le début ou la
45
+ * fin. `behavior` respecte `prefers-reduced-motion`. Le navigateur sature au min/max ; les boutons
46
+ * câblés sont `disabled` aux extrémités, donc l'appel n'a pas lieu à vide.
47
+ */
48
+ scrollByPage(dir: 'start' | 'end'): void;
49
+ /** Met à jour le signal de métriques. Appelé depuis des callbacks navigateur (jamais un effet). */
50
+ private remeasure;
51
+ /** Mesure le débordement (lecture pure de géométrie, n'écrit rien). */
52
+ private measure;
53
+ private isVertical;
54
+ private isRtl;
55
+ /**
56
+ * `auto` si l'utilisateur a demandé à réduire les animations (WCAG 2.3.3 AAA), `smooth` sinon.
57
+ * Passer un `behavior` explicite à `scrollTo`/`scrollBy` écrase la propriété CSS `scroll-behavior`,
58
+ * d'où la nécessité de répliquer ici la décision que le CSS prend via `prefers-reduced-motion`.
59
+ */
60
+ private scrollBehavior;
61
+ /**
62
+ * Calcule l'offset à atteindre pour amener l'onglet actif dans la vue, ou `null` s'il est déjà
63
+ * visible (ou s'il n'y a aucun onglet sélectionné). Lit `selectedTab()` → dépendance réactive.
64
+ */
65
+ private computeScrollTarget;
66
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtTabScroller, never>;
67
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<KtTabScroller, "[ngTabList][ktTabScroller]", ["ktTabScroller"], {}, {}, never, never, true, never>;
68
+ }
69
+
70
+ /**
71
+ * Composant clé-en-main : enveloppe une liste d'onglets `@angular/aria/tabs` débordante de deux
72
+ * **chevrons de pagination** accessibles (style Material). Il ne contient aucune logique propre :
73
+ * il lit l'état réactif de la directive headless {@link KtTabScroller} (à poser sur le `ngTabList`
74
+ * projeté) et câble deux boutons {@link KtButton}.
75
+ *
76
+ * @example
77
+ * ```html
78
+ * <kt-tab-scroller>
79
+ * <ul ngTabList ktTabScroller [(selectedTab)]="tab">
80
+ * @for (t of tabs; track t) { <li ngTab [value]="t">…</li> }
81
+ * </ul>
82
+ * </kt-tab-scroller>
83
+ * ```
84
+ */
85
+ declare class KtTabScrollerPager {
86
+ private readonly host;
87
+ private readonly doc;
88
+ /** Défauts d'app (provider global `KT_TABS_CONFIG`) ; les inputs ci-dessous priment dessus. */
89
+ private readonly config;
90
+ /** La directive headless posée sur le `ngTabList` projeté (`descendants` car dans le viewport). */
91
+ protected readonly scroller: _angular_core.Signal<KtTabScroller>;
92
+ /** Sens de lecture (figé au montage : le RTL inverse les chevrons gauche/droite). */
93
+ private readonly dir;
94
+ protected readonly startIcon: _angular_core.Signal<"expand_less" | "chevron_right" | "chevron_left">;
95
+ protected readonly endIcon: _angular_core.Signal<"chevron_right" | "chevron_left" | "expand_more">;
96
+ /**
97
+ * Noms accessibles des chevrons (`aria-label`). Résolution `input ?? KT_TABS_CONFIG ?? défaut`,
98
+ * comme partout dans la lib (cf. `KT_FIELD_CONFIG`/`KT_CHIPS_CONFIG`). Défauts en anglais : lib
99
+ * neutre i18n, les textes sont fournis par le consommateur (provider global ou binding).
100
+ */
101
+ /**
102
+ * `aria-label` du chevron « onglets précédents ».
103
+ * @default config.previousLabel ?? 'Previous tabs'
104
+ */
105
+ readonly previousLabel: _angular_core.InputSignal<string>;
106
+ /**
107
+ * `aria-label` du chevron « onglets suivants ».
108
+ * @default config.nextLabel ?? 'Next tabs'
109
+ */
110
+ readonly nextLabel: _angular_core.InputSignal<string>;
21
111
  constructor();
22
- private scrollSelectedIntoView;
23
- static ɵfac: i0.ɵɵFactoryDeclaration<KtTabScroll, never>;
24
- static ɵdir: i0.ɵɵDirectiveDeclaration<KtTabScroll, "[ngTabList][ktTabScroll]", never, {}, {}, never, never, true, never>;
112
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtTabScrollerPager, never>;
113
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<KtTabScrollerPager, "kt-tab-scroller", never, { "previousLabel": { "alias": "previousLabel"; "required": false; "isSignal": true; }; "nextLabel": { "alias": "nextLabel"; "required": false; "isSignal": true; }; }, {}, ["scroller"], ["[ngTabList]"], true, never>;
114
+ }
115
+
116
+ /**
117
+ * @deprecated Utilisez {@link KtTabScroller} (sélecteur `[ktTabScroller]`) : même défilement de
118
+ * l'onglet sélectionné dans la vue, plus la pagination par chevrons. `ktTabScroll` reste un **alias
119
+ * fonctionnel** (il applique `KtTabScroller` comme directive hôte) et sera retiré dans une version
120
+ * majeure ultérieure.
121
+ *
122
+ * Note : depuis cette version, une liste pilotée par `ktTabScroll`/`ktTabScroller` masque sa
123
+ * scrollbar native par défaut (les chevrons / ombres prennent le relais). Réafficher la barre via
124
+ * `--tab-scroller-scrollbar: thin`.
125
+ */
126
+ declare class KtTabScroll {
127
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtTabScroll, never>;
128
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<KtTabScroll, "[ngTabList][ktTabScroll]", ["ktTabScroll"], {}, {}, never, never, true, [{ directive: typeof KtTabScroller; inputs: {}; outputs: {}; }]>;
129
+ }
130
+
131
+ /** Défauts applicables à tous les `kt-tab-scroller` (surchargeables par instance via les inputs).
132
+ Lib neutre i18n : les textes sont fournis par le consommateur (ici en une fois).
133
+ Fourni en `Partial` : un consommateur n'override que ce qu'il veut.
134
+ Calqué sur `KT_FIELD_CONFIG`/`KT_CHIPS_CONFIG`. */
135
+ interface KtTabsConfig {
136
+ /** `aria-label` du chevron de pagination « onglets précédents ». Défaut : `'Previous tabs'`. */
137
+ previousLabel: string;
138
+ /** `aria-label` du chevron de pagination « onglets suivants ». Défaut : `'Next tabs'`. */
139
+ nextLabel: string;
25
140
  }
141
+ declare const KT_TABS_CONFIG: InjectionToken<Partial<KtTabsConfig>>;
26
142
 
27
- export { KtTabScroll };
143
+ export { KT_TABS_CONFIG, KtTabScroll, KtTabScroller, KtTabScrollerPager };
144
+ export type { KtTabsConfig };
@@ -2,9 +2,13 @@ import * as _angular_core from '@angular/core';
2
2
  import { InjectionToken, OnDestroy, TemplateRef, Provider } from '@angular/core';
3
3
 
4
4
  type KtTooltipPosition = 'top' | 'bottom' | 'left' | 'right';
5
+ /** Défauts d'infobulle (délais, position) injectables via `provideKtTooltip` / `KT_TOOLTIP_CONFIG`. */
5
6
  interface KtTooltipConfig {
7
+ /** Délai (ms) avant apparition au survol/focus. */
6
8
  showDelay: number;
9
+ /** Délai (ms) avant masquage (laisse le temps d'atteindre l'infobulle, WCAG « hoverable »). */
7
10
  hideDelay: number;
11
+ /** Position de l'infobulle autour de la cible. */
8
12
  position: KtTooltipPosition;
9
13
  }
10
14
  declare const KT_TOOLTIP_CONFIG: InjectionToken<Partial<KtTooltipConfig>>;
@@ -50,6 +54,7 @@ declare class KtTooltip implements OnDestroy {
50
54
  private readonly idGen;
51
55
  private readonly uid;
52
56
  private readonly tooltipId;
57
+ /** Id du noeud `role="tooltip"`. Public : sert aux liaisons d'accessibilité (`aria-describedby`) du déclencheur. */
53
58
  readonly idForA11y: string;
54
59
  private readonly anchorName;
55
60
  /** Vrai quand l'infobulle est susceptible de s'afficher (contenu non vide et non désactivée).
@@ -3,6 +3,8 @@ export * from '@ktortu/aaa/card';
3
3
  export * from '@ktortu/aaa/cdk';
4
4
  export * from '@ktortu/aaa/dialog';
5
5
  export * from '@ktortu/aaa/forms';
6
+ export * from '@ktortu/aaa/i18n';
6
7
  export * from '@ktortu/aaa/menu';
8
+ export * from '@ktortu/aaa/snackbar';
7
9
  export * from '@ktortu/aaa/tabs';
8
10
  export * from '@ktortu/aaa/tooltip';