@ktortu/aaa 0.9.1 → 0.9.2

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 (39) hide show
  1. package/fesm2022/ktortu-aaa-button.mjs +10 -2
  2. package/fesm2022/ktortu-aaa-button.mjs.map +1 -1
  3. package/fesm2022/ktortu-aaa-card.mjs +14 -5
  4. package/fesm2022/ktortu-aaa-card.mjs.map +1 -1
  5. package/fesm2022/ktortu-aaa-cdk.mjs +49 -2
  6. package/fesm2022/ktortu-aaa-cdk.mjs.map +1 -1
  7. package/fesm2022/ktortu-aaa-dialog.mjs +19 -31
  8. package/fesm2022/ktortu-aaa-dialog.mjs.map +1 -1
  9. package/fesm2022/ktortu-aaa-disclosure.mjs +201 -0
  10. package/fesm2022/ktortu-aaa-disclosure.mjs.map +1 -0
  11. package/fesm2022/ktortu-aaa-forms.mjs +210 -93
  12. package/fesm2022/ktortu-aaa-forms.mjs.map +1 -1
  13. package/fesm2022/ktortu-aaa-progress-bar.mjs +91 -0
  14. package/fesm2022/ktortu-aaa-progress-bar.mjs.map +1 -0
  15. package/fesm2022/ktortu-aaa-snackbar.mjs +16 -3
  16. package/fesm2022/ktortu-aaa-snackbar.mjs.map +1 -1
  17. package/fesm2022/ktortu-aaa-tooltip.mjs +20 -30
  18. package/fesm2022/ktortu-aaa-tooltip.mjs.map +1 -1
  19. package/fesm2022/ktortu-aaa.mjs +1 -0
  20. package/fesm2022/ktortu-aaa.mjs.map +1 -1
  21. package/forms/field/field.css +16 -0
  22. package/forms/styles/field-box.css +11 -5
  23. package/package.json +9 -1
  24. package/progress-bar/progress-bar.css +127 -0
  25. package/styles/disclosure.css +6 -0
  26. package/styles/progress-bar.css +5 -0
  27. package/styles/styles.css +2 -0
  28. package/themes/theme-cyberpunk.css +11 -0
  29. package/tooltip/tooltip.css +1 -1
  30. package/types/ktortu-aaa-button.d.ts +2 -0
  31. package/types/ktortu-aaa-card.d.ts +3 -0
  32. package/types/ktortu-aaa-cdk.d.ts +27 -1
  33. package/types/ktortu-aaa-dialog.d.ts +7 -14
  34. package/types/ktortu-aaa-disclosure.d.ts +112 -0
  35. package/types/ktortu-aaa-forms.d.ts +66 -14
  36. package/types/ktortu-aaa-progress-bar.d.ts +27 -0
  37. package/types/ktortu-aaa-snackbar.d.ts +11 -68
  38. package/types/ktortu-aaa-tooltip.d.ts +0 -1
  39. package/types/ktortu-aaa.d.ts +1 -0
@@ -0,0 +1,91 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, ElementRef, signal, input, booleanAttribute, computed, Component } from '@angular/core';
3
+ import { KtIdGenerator } from '@ktortu/aaa/cdk';
4
+
5
+ class KtProgressBar {
6
+ idGen = inject(KtIdGenerator);
7
+ elementRef = inject(ElementRef);
8
+ labelId = `kt-progress-bar-label-${this.idGen.generateId('progress-bar')}`;
9
+ hasProjectedContent = signal(false, /* @ts-ignore */
10
+ ...(ngDevMode ? [{ debugName: "hasProjectedContent" }] : /* istanbul ignore next */ []));
11
+ /** Mode de fonctionnement de la barre de progression. @default 'indeterminate' */
12
+ mode = input('indeterminate', /* @ts-ignore */
13
+ ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
14
+ /** Valeur de la progression (entre 0 et 100). Ignorée en mode 'indeterminate'. @default 0 */
15
+ value = input(0, { ...(ngDevMode ? { debugName: "value" } : /* istanbul ignore next */ {}), transform: (v) => Math.max(0, Math.min(100, Number(v) || 0)) });
16
+ /** Label textuel optionnel passé par attribut. */
17
+ label = input(/* @ts-ignore */
18
+ ...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
19
+ /** Détermine si le label textuel doit être visible à l'écran. @default true */
20
+ labelVisible = input(true, { ...(ngDevMode ? { debugName: "labelVisible" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
21
+ /** Permet de figer l'animation indéterminée (utile pour les tests). @default false */
22
+ reducedMotion = input(false, { ...(ngDevMode ? { debugName: "reducedMotion" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
23
+ /** Indique si le composant dispose d'un label défini (soit via input, soit par projection). */
24
+ hasLabel = computed(() => !!this.label() || this.hasProjectedContent(), /* @ts-ignore */
25
+ ...(ngDevMode ? [{ debugName: "hasLabel" }] : /* istanbul ignore next */ []));
26
+ transformStyle = computed(() => {
27
+ if (this.mode() === 'indeterminate')
28
+ return null;
29
+ return `scaleX(${this.value() / 100})`;
30
+ }, /* @ts-ignore */
31
+ ...(ngDevMode ? [{ debugName: "transformStyle" }] : /* istanbul ignore next */ []));
32
+ ngAfterViewInit() {
33
+ // Vérification asynchrone pour voir s'il y a du contenu projeté dans l'élément hôte
34
+ const hostText = this.elementRef.nativeElement.textContent?.trim() || '';
35
+ if (hostText.length > 0) {
36
+ this.hasProjectedContent.set(true);
37
+ }
38
+ }
39
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: KtProgressBar, deps: [], target: i0.ɵɵFactoryTarget.Component });
40
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.1", type: KtProgressBar, isStandalone: true, selector: "kt-progress-bar", inputs: { mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, labelVisible: { classPropertyName: "labelVisible", publicName: "labelVisible", isSignal: true, isRequired: false, transformFunction: null }, reducedMotion: { classPropertyName: "reducedMotion", publicName: "reducedMotion", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "progressbar", "data-testid": "kt-progress-bar" }, properties: { "attr.aria-valuemin": "0", "attr.aria-valuemax": "100", "attr.aria-valuenow": "mode() === \"determinate\" ? value() : null", "attr.aria-labelledby": "hasLabel() ? labelId : null", "attr.aria-label": "!hasLabel() ? \"Chargement\" : null", "attr.data-mode": "mode()" } }, ngImport: i0, template: `
41
+ <div [id]="labelId" class="kt-progress-bar-label" [class.kt-sr-only]="!labelVisible()">
42
+ @if (label()) {
43
+ {{ label() }}
44
+ } @else {
45
+ <ng-content />
46
+ }
47
+ </div>
48
+ <div class="kt-progress-bar-track">
49
+ <div
50
+ class="kt-progress-bar-indicator"
51
+ [style.transform]="transformStyle()"
52
+ [class.kt-reduced-motion]="reducedMotion()"
53
+ ></div>
54
+ </div>
55
+ `, isInline: true, styles: [":host{display:flex;flex-direction:column;width:100%;gap:var(--kt-progress-bar-gap, 8px)}.kt-progress-bar-label{font-family:var(--kt-font-family, sans-serif);font-size:var(--kt-font-size-sm, .875rem);color:var(--kt-text-color-secondary, var(--kt-neutral-dark, #555));text-align:var(--kt-progress-bar-label-align, start)}.kt-progress-bar-label:empty{display:none}.kt-progress-bar-track{width:100%;height:var(--kt-progress-bar-height, 4px);overflow:hidden;background-color:var(--kt-progress-bar-track-color, var(--kt-neutral-light, #e0e0e0));border-radius:var(--kt-progress-bar-border-radius, 2px);position:relative}.kt-progress-bar-indicator{position:absolute;inset:0;background-color:var(--kt-progress-bar-indicator-color, var(--kt-primary, #0056b3));transform-origin:top left;transition:transform .25s ease;will-change:transform}:host([data-mode=\"indeterminate\"]) .kt-progress-bar-indicator{animation:kt-progress-bar-indeterminate-translate 2.2s infinite cubic-bezier(.4,0,.2,1),kt-progress-bar-indeterminate-scale 2.2s infinite ease-in-out,kt-progress-bar-indeterminate-fade 2.2s infinite linear;transform-origin:left}.kt-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}@keyframes kt-progress-bar-indeterminate-translate{0%{translate:-100% 0}to{translate:100% 0}}@keyframes kt-progress-bar-indeterminate-scale{0%{scale:.15 1}35%{scale:.7 1}70%{scale:.4 1}to{scale:.15 1}}@keyframes kt-progress-bar-indeterminate-fade{0%{opacity:0}15%{opacity:1}85%{opacity:1}to{opacity:0}}@media(prefers-reduced-motion:reduce){:host([data-mode=\"indeterminate\"]) .kt-progress-bar-indicator{animation:kt-progress-bar-pulsate 2s infinite ease-in-out;transform:none;transform-origin:center}}.kt-progress-bar-indicator.kt-reduced-motion{animation:kt-progress-bar-pulsate 2s infinite ease-in-out!important;transform:none!important;transform-origin:center!important}@keyframes kt-progress-bar-pulsate{0%{opacity:.3}50%{opacity:.8}to{opacity:.3}}\n"] });
56
+ }
57
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: KtProgressBar, decorators: [{
58
+ type: Component,
59
+ args: [{ selector: 'kt-progress-bar', standalone: true, template: `
60
+ <div [id]="labelId" class="kt-progress-bar-label" [class.kt-sr-only]="!labelVisible()">
61
+ @if (label()) {
62
+ {{ label() }}
63
+ } @else {
64
+ <ng-content />
65
+ }
66
+ </div>
67
+ <div class="kt-progress-bar-track">
68
+ <div
69
+ class="kt-progress-bar-indicator"
70
+ [style.transform]="transformStyle()"
71
+ [class.kt-reduced-motion]="reducedMotion()"
72
+ ></div>
73
+ </div>
74
+ `, host: {
75
+ role: 'progressbar',
76
+ 'data-testid': 'kt-progress-bar',
77
+ '[attr.aria-valuemin]': '0',
78
+ '[attr.aria-valuemax]': '100',
79
+ '[attr.aria-valuenow]': 'mode() === "determinate" ? value() : null',
80
+ '[attr.aria-labelledby]': 'hasLabel() ? labelId : null',
81
+ '[attr.aria-label]': '!hasLabel() ? "Chargement" : null',
82
+ '[attr.data-mode]': 'mode()',
83
+ }, styles: [":host{display:flex;flex-direction:column;width:100%;gap:var(--kt-progress-bar-gap, 8px)}.kt-progress-bar-label{font-family:var(--kt-font-family, sans-serif);font-size:var(--kt-font-size-sm, .875rem);color:var(--kt-text-color-secondary, var(--kt-neutral-dark, #555));text-align:var(--kt-progress-bar-label-align, start)}.kt-progress-bar-label:empty{display:none}.kt-progress-bar-track{width:100%;height:var(--kt-progress-bar-height, 4px);overflow:hidden;background-color:var(--kt-progress-bar-track-color, var(--kt-neutral-light, #e0e0e0));border-radius:var(--kt-progress-bar-border-radius, 2px);position:relative}.kt-progress-bar-indicator{position:absolute;inset:0;background-color:var(--kt-progress-bar-indicator-color, var(--kt-primary, #0056b3));transform-origin:top left;transition:transform .25s ease;will-change:transform}:host([data-mode=\"indeterminate\"]) .kt-progress-bar-indicator{animation:kt-progress-bar-indeterminate-translate 2.2s infinite cubic-bezier(.4,0,.2,1),kt-progress-bar-indeterminate-scale 2.2s infinite ease-in-out,kt-progress-bar-indeterminate-fade 2.2s infinite linear;transform-origin:left}.kt-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}@keyframes kt-progress-bar-indeterminate-translate{0%{translate:-100% 0}to{translate:100% 0}}@keyframes kt-progress-bar-indeterminate-scale{0%{scale:.15 1}35%{scale:.7 1}70%{scale:.4 1}to{scale:.15 1}}@keyframes kt-progress-bar-indeterminate-fade{0%{opacity:0}15%{opacity:1}85%{opacity:1}to{opacity:0}}@media(prefers-reduced-motion:reduce){:host([data-mode=\"indeterminate\"]) .kt-progress-bar-indicator{animation:kt-progress-bar-pulsate 2s infinite ease-in-out;transform:none;transform-origin:center}}.kt-progress-bar-indicator.kt-reduced-motion{animation:kt-progress-bar-pulsate 2s infinite ease-in-out!important;transform:none!important;transform-origin:center!important}@keyframes kt-progress-bar-pulsate{0%{opacity:.3}50%{opacity:.8}to{opacity:.3}}\n"] }]
84
+ }], propDecorators: { mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], labelVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelVisible", required: false }] }], reducedMotion: [{ type: i0.Input, args: [{ isSignal: true, alias: "reducedMotion", required: false }] }] } });
85
+
86
+ /**
87
+ * Generated bundle index. Do not edit.
88
+ */
89
+
90
+ export { KtProgressBar };
91
+ //# sourceMappingURL=ktortu-aaa-progress-bar.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ktortu-aaa-progress-bar.mjs","sources":["../../../../projects/ktortu/aaa/progress-bar/progress-bar.ts","../../../../projects/ktortu/aaa/progress-bar/ktortu-aaa-progress-bar.ts"],"sourcesContent":["import { Component, input, computed, booleanAttribute, inject, ElementRef, signal, AfterViewInit } from '@angular/core';\nimport { KtIdGenerator } from '@ktortu/aaa/cdk';\n\n@Component({\n selector: 'kt-progress-bar',\n standalone: true,\n template: `\n <div [id]=\"labelId\" class=\"kt-progress-bar-label\" [class.kt-sr-only]=\"!labelVisible()\">\n @if (label()) {\n {{ label() }}\n } @else {\n <ng-content />\n }\n </div>\n <div class=\"kt-progress-bar-track\">\n <div\n class=\"kt-progress-bar-indicator\"\n [style.transform]=\"transformStyle()\"\n [class.kt-reduced-motion]=\"reducedMotion()\"\n ></div>\n </div>\n `,\n styleUrl: './progress-bar.css',\n host: {\n role: 'progressbar',\n 'data-testid': 'kt-progress-bar',\n '[attr.aria-valuemin]': '0',\n '[attr.aria-valuemax]': '100',\n '[attr.aria-valuenow]': 'mode() === \"determinate\" ? value() : null',\n '[attr.aria-labelledby]': 'hasLabel() ? labelId : null',\n '[attr.aria-label]': '!hasLabel() ? \"Chargement\" : null',\n '[attr.data-mode]': 'mode()',\n },\n})\nexport class KtProgressBar implements AfterViewInit {\n private readonly idGen = inject(KtIdGenerator);\n private readonly elementRef = inject(ElementRef);\n\n protected readonly labelId = `kt-progress-bar-label-${this.idGen.generateId('progress-bar')}`;\n private readonly hasProjectedContent = signal(false);\n\n /** Mode de fonctionnement de la barre de progression. @default 'indeterminate' */\n readonly mode = input<'determinate' | 'indeterminate'>('indeterminate');\n\n /** Valeur de la progression (entre 0 et 100). Ignorée en mode 'indeterminate'. @default 0 */\n readonly value = input<number, unknown>(0, {\n transform: (v: unknown) => Math.max(0, Math.min(100, Number(v) || 0)),\n });\n\n /** Label textuel optionnel passé par attribut. */\n readonly label = input<string>();\n\n /** Détermine si le label textuel doit être visible à l'écran. @default true */\n readonly labelVisible = input<boolean, unknown>(true, { transform: booleanAttribute });\n\n /** Permet de figer l'animation indéterminée (utile pour les tests). @default false */\n readonly reducedMotion = input<boolean, unknown>(false, { transform: booleanAttribute });\n\n /** Indique si le composant dispose d'un label défini (soit via input, soit par projection). */\n protected readonly hasLabel = computed(() => !!this.label() || this.hasProjectedContent());\n\n protected readonly transformStyle = computed(() => {\n if (this.mode() === 'indeterminate') return null;\n return `scaleX(${this.value() / 100})`;\n });\n\n ngAfterViewInit(): void {\n // Vérification asynchrone pour voir s'il y a du contenu projeté dans l'élément hôte\n const hostText = this.elementRef.nativeElement.textContent?.trim() || '';\n if (hostText.length > 0) {\n this.hasProjectedContent.set(true);\n }\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -278,7 +278,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImpor
278
278
  * - **Échap** ferme la snackbar affichée (la plus récente).
279
279
  *
280
280
  * Requiert côté hôte les styles `@angular/cdk/overlay-prebuilt.css` **et**
281
- * `@angular/cdk/a11y-prebuilt.css` (ce dernier masque l'élément du LiveAnnouncer).
281
+ * `@angular/cdk/a11y-prebuilt.css` (ce dernier masque l'élément du LiveAnnouncer), en plus de
282
+ * `@ktortu/aaa/snackbar.css`.
283
+ *
284
+ * > [!IMPORTANT]
285
+ * > **Prérequis d'intégration obligatoire :**
286
+ * > Ce service ne fonctionnera pas correctement sans l'importation de ces deux fichiers CSS de l'overlay CDK et d'accessibilité dans votre feuille de styles globale ou votre build.
282
287
  *
283
288
  * @example
284
289
  * ```ts
@@ -307,6 +312,9 @@ class KtSnackbar {
307
312
  * Un `message` identique à une snackbar déjà affichée ou en attente est **fusionné** : on renvoie
308
313
  * alors la référence existante sans rien ré-empiler.
309
314
  *
315
+ * > [!IMPORTANT]
316
+ * > Assurez-vous d'avoir importé `@angular/cdk/overlay-prebuilt.css` et `@angular/cdk/a11y-prebuilt.css` dans votre application hôte.
317
+ *
310
318
  * @param message Texte affiché et annoncé au lecteur d'écran.
311
319
  * @param options Surcharges ponctuelles (durée, régime, position, politesse, variante, fermeture).
312
320
  * @returns La référence de la snackbar (existante en cas de fusion).
@@ -445,7 +453,9 @@ class KtSnackbar {
445
453
  politeness: options?.politeness ?? config?.politeness ?? KT_SNACKBAR_DEFAULTS.politeness,
446
454
  variant: options?.variant ?? config?.variant ?? KT_SNACKBAR_DEFAULTS.variant,
447
455
  closable: options?.closable ?? config?.closable ?? KT_SNACKBAR_DEFAULTS.closable,
448
- closeLabel: options?.closeLabel ?? config?.closeLabel ?? KT_SNACKBAR_DEFAULTS.closeLabel,
456
+ // `|| ...` (et non seulement `??`) : un closeLabel vide/blanc produirait un bouton de fermeture
457
+ // SANS nom accessible (WCAG 4.1.2) ; on cascade vers le niveau suivant, défaut neutre en dernier.
458
+ closeLabel: options?.closeLabel?.trim() || config?.closeLabel?.trim() || KT_SNACKBAR_DEFAULTS.closeLabel,
449
459
  max: options?.max ?? config?.max ?? KT_SNACKBAR_DEFAULTS.max,
450
460
  };
451
461
  }
@@ -457,9 +467,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImpor
457
467
  args: [{ providedIn: 'root' }]
458
468
  }] });
459
469
 
470
+ // `KtSnackbarContainer` / `KT_SNACKBAR_CONTEXT` / `KtSnackbarContext` sont des artefacts internes
471
+ // (montés/fournis par `KtSnackbar` via `ComponentPortal`) : ils ne sont volontairement PAS exposés.
472
+
460
473
  /**
461
474
  * Generated bundle index. Do not edit.
462
475
  */
463
476
 
464
- export { KT_SNACKBAR_CONFIG, KT_SNACKBAR_CONTEXT, KT_SNACKBAR_DEFAULTS, KtSnackbar, KtSnackbarContainer, KtSnackbarRef, provideKtSnackbar };
477
+ export { KT_SNACKBAR_CONFIG, KT_SNACKBAR_DEFAULTS, KtSnackbar, KtSnackbarRef, provideKtSnackbar };
465
478
  //# sourceMappingURL=ktortu-aaa-snackbar.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ktortu-aaa-snackbar.mjs","sources":["../../../../projects/ktortu/aaa/snackbar/snackbar-config.ts","../../../../projects/ktortu/aaa/snackbar/snackbar-ref.ts","../../../../projects/ktortu/aaa/snackbar/snackbar-container.ts","../../../../projects/ktortu/aaa/snackbar/snackbar.service.ts","../../../../projects/ktortu/aaa/snackbar/ktortu-aaa-snackbar.ts"],"sourcesContent":["import { InjectionToken, Provider } from '@angular/core';\n\n/** Politesse de l'annonce au lecteur d'écran (relayée à `LiveAnnouncer`). */\nexport type KtSnackbarPoliteness = 'polite' | 'assertive';\n\n/** Bord d'ancrage de la snackbar dans le viewport. */\nexport type KtSnackbarPosition = 'top' | 'bottom';\n\n/**\n * Régime temporel de la snackbar :\n * - `'auto'` : disparition automatique après `duration`, **mise en pause au survol et au focus**\n * clavier (WCAG 1.4.13 / 2.2.1). Conforme **AA**. C'est le défaut.\n * - `'manual'` : **aucune** minuterie, la snackbar reste jusqu'à fermeture explicite\n * (bouton de fermeture ou `ref.dismiss()`). Conforme **2.2.3 (AAA)** au sens strict.\n *\n * Conformément aux recommandations d'accessibilité (Roselli/Soueidan), la snackbar ne porte **pas\n * d'action interactive** (ex. « Annuler ») : une action auto-disparaissante n'est pas atteignable et\n * une live region n'expose pas ses boutons. Pour un undo, préférez un mécanisme atteignable côté app\n * (Ctrl+Z, bannière persistante).\n */\nexport type KtSnackbarTiming = 'auto' | 'manual';\n\n/**\n * Variante sémantique de la snackbar. Pilote uniquement l'**apparence** (couleur d'accent + icône),\n * via l'attribut `data-variant` et les tokens CSS `--snackbar-*` — donc entièrement gérée par le\n * thème, sans logique TypeScript. Découplée de la `politeness` (une « erreur » n'est pas forcément\n * une urgence assertive). La couleur n'est jamais le seul indice : chaque variante porte une **icône**\n * de forme distincte (WCAG 1.4.1).\n * - `'neutral'` : pastille neutre, sans icône (défaut) ;\n * - `'info' | 'success' | 'warning' | 'error'` : accent + icône dédiés.\n */\nexport type KtSnackbarVariant = 'neutral' | 'info' | 'success' | 'warning' | 'error';\n\n/**\n * Défauts de la snackbar, injectables via `provideKtSnackbar` / `KT_SNACKBAR_CONFIG`.\n * Tous les champs sont surchargeables **par appel** via les options de `KtSnackbar.open()`.\n *\n * Résolution en cascade (convention de la lib) : `option d'open ?? KT_SNACKBAR_CONFIG ?? défaut`.\n */\nexport interface KtSnackbarConfig {\n /**\n * Durée d'affichage en régime `'auto'`. Soit un **nombre fixe** (ms), soit le sentinel\n * **`'reading-time'`** (DÉFAUT) qui **calcule** la durée d'après la longueur du message :\n * `clamp(longueur × readingTimePerChar, readingTimeMin, readingTimeMax)`. Passer un nombre à\n * `open()` force donc une durée fixe pour cet appel.\n *\n * ⚠️ Gardez le message **court** : une snackbar est un message transitoire (pas un paragraphe).\n * Un message long fait grimper la durée jusqu'au plafond `readingTimeMax`.\n * @default 'reading-time'\n */\n duration: number | 'reading-time';\n /** Plancher (ms) de la durée calculée (`'reading-time'`) — laisse le temps de lire un message court. @default 4000 */\n readingTimeMin: number;\n /** Plafond (ms) de la durée calculée (`'reading-time'`) — borne un message long. @default 10000 */\n readingTimeMax: number;\n /** Coefficient de lecture : millisecondes ajoutées par caractère du message. @default 60 (~200 mots/min) */\n readingTimePerChar: number;\n /** Régime temporel (cf. {@link KtSnackbarTiming}). @default 'auto' (AA + pause) */\n timing: KtSnackbarTiming;\n /** Bord d'ancrage dans le viewport. @default 'bottom' */\n position: KtSnackbarPosition;\n /** Politesse de l'annonce lecteur d'écran. @default 'polite' */\n politeness: KtSnackbarPoliteness;\n /** Variante sémantique (apparence seule, cf. {@link KtSnackbarVariant}). @default 'neutral' */\n variant: KtSnackbarVariant;\n /** Affiche un bouton de fermeture (cible 44px, AAA). @default true */\n closable: boolean;\n /** Nom accessible du bouton de fermeture. @default 'Close' (FR fourni en lot L3) */\n closeLabel: string;\n /**\n * Taille maximale de la file FIFO (snackbar affichée + en attente). Au-delà, les **plus anciennes\n * en attente** sont retirées silencieusement. Une seule snackbar est visible à la fois. @default 3\n */\n max: number;\n}\n\n/** Défauts AAA-orientés de la snackbar (anglais neutre). */\nexport const KT_SNACKBAR_DEFAULTS: KtSnackbarConfig = {\n // Stryker disable next-line StringLiteral: équivalent — computeDuration() traite toute valeur non numérique comme reading-time\n duration: 'reading-time',\n readingTimeMin: 4000,\n readingTimeMax: 10000,\n readingTimePerChar: 60,\n timing: 'auto',\n position: 'bottom',\n politeness: 'polite',\n variant: 'neutral',\n closable: true,\n closeLabel: 'Close',\n max: 3,\n};\n\n// Stryker disable next-line StringLiteral: libellé de debug du token d'injection (sans effet runtime)\nexport const KT_SNACKBAR_CONFIG = new InjectionToken<Partial<KtSnackbarConfig>>('KT_SNACKBAR_CONFIG');\n\n/**\n * Options ponctuelles d'ouverture d'une snackbar : un sous-ensemble (toutes facultatives) de la\n * config, prioritaire sur `KT_SNACKBAR_CONFIG` et sur les défauts.\n */\nexport type KtSnackbarOptions = Partial<KtSnackbarConfig>;\n\n/**\n * Fournit des défauts de snackbar pour un sous-arbre ou l'application entière.\n *\n * @example\n * ```ts\n * // app.config.ts — bascule TOUTE l'app en AAA strict (aucune disparition automatique)\n * providers: [provideKtSnackbar({ timing: 'manual' })]\n * ```\n * @example\n * ```ts\n * providers: [provideKtSnackbar({ duration: 8000, position: 'top' })]\n * ```\n */\nexport function provideKtSnackbar(config: Partial<KtSnackbarConfig>): Provider {\n return { provide: KT_SNACKBAR_CONFIG, useValue: config };\n}\n","import { Observable, Subject } from 'rxjs';\n\n/**\n * Raison de fermeture d'une snackbar, transmise par {@link KtSnackbarRef.afterDismissed}.\n * - `'timeout'` : la minuterie (régime `'auto'`) est arrivée à échéance ;\n * - `'dismiss'` : fermeture explicite (bouton de fermeture, `Échap`, ou `ref.dismiss()`) ;\n * - `'replaced'` : la snackbar a été retirée de la file sans être affichée (file pleine — cf. `max`).\n */\nexport type KtSnackbarDismissReason = 'timeout' | 'dismiss' | 'replaced';\n\n/**\n * Référence d'une snackbar ouverte, renvoyée par `KtSnackbar.open()`. Permet de fermer la\n * snackbar par programmation et d'observer sa fermeture.\n *\n * Le débutant peut l'ignorer (`snackbar.open('…')`) ; le code avancé s'en sert pour piloter la\n * fermeture et réagir à la raison de fin.\n *\n * @example\n * ```ts\n * const ref = snackbar.open('Brouillon enregistré');\n * ref.afterDismissed().subscribe((reason) => console.log(reason)); // 'timeout' | 'dismiss' | 'replaced'\n * // plus tard : ref.dismiss();\n * ```\n */\nexport class KtSnackbarRef {\n private readonly _afterDismissed = new Subject<KtSnackbarDismissReason>();\n private settled = false;\n\n /**\n * @param onDismiss Rappel exécuté une fois à la fermeture (animation de sortie + démontage de\n * l'overlay + avance de la file), fourni par le service.\n * @internal Construit par `KtSnackbar` — n'instanciez pas `KtSnackbarRef` directement.\n */\n constructor(private readonly onDismiss: (reason: KtSnackbarDismissReason) => void) {}\n\n /**\n * Ferme la snackbar (idempotent). Déclenche la sortie/démontage puis émet la raison sur\n * `afterDismissed()`.\n * @param reason Raison de fermeture. @default 'dismiss'\n */\n dismiss(reason: KtSnackbarDismissReason = 'dismiss'): void {\n if (this.settled) return;\n this.settled = true;\n this.onDismiss(reason);\n this._afterDismissed.next(reason);\n this._afterDismissed.complete();\n }\n\n /** Émet une fois (puis complète) à la fermeture, avec la {@link KtSnackbarDismissReason}. */\n afterDismissed(): Observable<KtSnackbarDismissReason> {\n return this._afterDismissed.asObservable();\n }\n}\n","import { isPlatformBrowser } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n ElementRef,\n InjectionToken,\n PLATFORM_ID,\n afterNextRender,\n inject,\n signal,\n} from '@angular/core';\n\nimport { KtSnackbarTiming, KtSnackbarVariant } from './snackbar-config';\nimport { KtSnackbarRef } from './snackbar-ref';\n\n/**\n * Données résolues passées au conteneur visuel à l'ouverture (injectées via {@link KT_SNACKBAR_CONTEXT}).\n * Produites par `KtSnackbar` après résolution `option ?? config ?? défaut`.\n */\nexport interface KtSnackbarContext {\n /** Message affiché et annoncé. */\n readonly message: string;\n /** Variante sémantique (apparence : accent + icône). */\n readonly variant: KtSnackbarVariant;\n /** Affiche le bouton de fermeture. */\n readonly closable: boolean;\n /** Nom accessible du bouton de fermeture. */\n readonly closeLabel: string;\n /** Régime temporel (la minuterie n'existe qu'en `'auto'`). */\n readonly timing: KtSnackbarTiming;\n /** Durée (ms) avant disparition automatique en régime `'auto'`. */\n readonly duration: number;\n}\n\n// Stryker disable next-line StringLiteral: libellé de debug du token d'injection (sans effet runtime)\nexport const KT_SNACKBAR_CONTEXT = new InjectionToken<KtSnackbarContext>('KT_SNACKBAR_CONTEXT');\n\n/**\n * Conteneur visuel d'une snackbar. **Volontairement pas une live region** (aucun `role`/`aria-live`\n * sur l'hôte) : l'annonce passe par un canal UNIQUE, le `LiveAnnouncer` du service. On évite ainsi\n * la double-annonce et l'écrasement de politesse observés sur d'autres libs.\n *\n * En régime `'auto'`, la minuterie de disparition se met **en pause au survol et au focus** clavier\n * (WCAG 1.4.13 / 2.2.1) et reprend quand ni le pointeur ni le focus ne sont sur la snackbar.\n * L'icône de variante est **décorative** (`aria-hidden`) : la forme distincte sert d'indice non\n * coloré (WCAG 1.4.1), le sens reste porté par le texte.\n *\n * @internal Monté par `KtSnackbar` via un `ComponentPortal`.\n */\n@Component({\n selector: 'kt-snackbar-container',\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n class: 'kt-snackbar',\n '[attr.data-variant]': 'context.variant',\n '[class.kt-snackbar--leaving]': 'leaving()',\n '(mouseenter)': 'onPointerEnter()',\n '(mouseleave)': 'onPointerLeave()',\n '(focusin)': 'onFocusEnter()',\n '(focusout)': 'onFocusLeave()',\n },\n template: `\n @if (context.variant !== 'neutral') {\n <span class=\"kt-snackbar__icon\" aria-hidden=\"true\"></span>\n }\n <span class=\"kt-snackbar__message\">{{ context.message }}</span>\n @if (context.closable) {\n <button\n type=\"button\"\n class=\"kt-snackbar__close\"\n [attr.aria-label]=\"context.closeLabel\"\n (click)=\"close()\"\n ></button>\n }\n `,\n})\nexport class KtSnackbarContainer {\n protected readonly context = inject(KT_SNACKBAR_CONTEXT);\n private readonly ref = inject(KtSnackbarRef);\n private readonly platformId = inject(PLATFORM_ID);\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n\n /** Vrai pendant l'animation de sortie (déclenche la classe `kt-snackbar--leaving`). */\n protected readonly leaving = signal(false);\n\n private timer: ReturnType<typeof setTimeout> | undefined;\n private remaining = this.context.duration;\n private deadline = 0;\n private hovered = false;\n private focused = false;\n\n constructor() {\n if (this.context.timing === 'auto' && isPlatformBrowser(this.platformId)) {\n afterNextRender(() => this.startTimer(this.context.duration));\n }\n inject(DestroyRef).onDestroy(() => this.clearTimer());\n }\n\n protected close(): void {\n this.ref.dismiss('dismiss');\n }\n\n /**\n * Joue l'animation de sortie puis invoque `done` (démontage de l'overlay côté service). Appelé par\n * le service à la fermeture. Sans animation (durée nulle, `prefers-reduced-motion`, ou SSR), `done`\n * est invoqué immédiatement. Filet de sécurité par `setTimeout` si `transitionend` ne se déclenche pas.\n */\n playExit(done: () => void): void {\n this.clearTimer();\n if (!isPlatformBrowser(this.platformId)) {\n done();\n return;\n }\n const durationMs = this.exitDurationMs();\n // Stryker disable all: animation de sortie pilotée par une transition CSS réelle. En jsdom\n // `transitionDuration` est vide → `exitDurationMs()` vaut 0 → ce code n'est jamais atteint.\n // Comportement (jeu de l'animation puis démontage) vérifié en e2e (sortie + reduced-motion).\n if (durationMs <= 0) {\n done();\n return;\n }\n\n this.leaving.set(true);\n let finished = false;\n const finish = (): void => {\n if (finished) return;\n finished = true;\n this.host.removeEventListener('transitionend', onTransitionEnd);\n done();\n };\n const onTransitionEnd = (event: TransitionEvent): void => {\n if (event.target === this.host) finish();\n };\n this.host.addEventListener('transitionend', onTransitionEnd);\n setTimeout(finish, durationMs + 50);\n // Stryker restore all\n }\n\n protected onPointerEnter(): void {\n this.hovered = true;\n this.pauseTimer();\n }\n\n protected onPointerLeave(): void {\n this.hovered = false;\n this.maybeResume();\n }\n\n protected onFocusEnter(): void {\n this.focused = true;\n this.pauseTimer();\n }\n\n protected onFocusLeave(): void {\n this.focused = false;\n this.maybeResume();\n }\n\n private maybeResume(): void {\n if (this.hovered || this.focused) return;\n if (this.context.timing !== 'auto' || this.timer !== undefined || this.leaving()) return;\n if (this.remaining <= 0) {\n this.ref.dismiss('timeout');\n return;\n }\n this.startTimer(this.remaining);\n }\n\n private startTimer(ms: number): void {\n this.deadline = Date.now() + ms;\n this.timer = setTimeout(() => this.ref.dismiss('timeout'), ms);\n }\n\n private pauseTimer(): void {\n if (this.timer === undefined) return;\n this.remaining = Math.max(0, this.deadline - Date.now());\n this.clearTimer();\n }\n\n private clearTimer(): void {\n if (this.timer === undefined) return;\n clearTimeout(this.timer);\n this.timer = undefined;\n }\n\n /** Durée (ms) de la transition de sortie, lue sur l'hôte (0 si aucune — ex. reduced-motion). */\n private exitDurationMs(): number {\n // Stryker disable all: lecture/parsing de `transition-duration` CSS — en jsdom\n // `getComputedStyle().transitionDuration` est toujours vide (renvoie 0). Le parsing réel\n // (ms vs s, valeurs multiples, NaN) est exercé en e2e ; intestable en environnement jsdom.\n const raw = getComputedStyle(this.host).transitionDuration || '';\n const first = raw.split(',')[0].trim();\n if (!first) return 0;\n const value = parseFloat(first);\n if (Number.isNaN(value)) return 0;\n return first.endsWith('ms') ? value : value * 1000;\n // Stryker restore all\n }\n}\n","import { LiveAnnouncer } from '@angular/cdk/a11y';\nimport { Overlay, OverlayRef } from '@angular/cdk/overlay';\nimport { ComponentPortal } from '@angular/cdk/portal';\nimport { DOCUMENT, isPlatformBrowser } from '@angular/common';\nimport { ComponentRef, Injectable, Injector, OnDestroy, PLATFORM_ID, inject } from '@angular/core';\n\nimport {\n KT_SNACKBAR_CONFIG,\n KT_SNACKBAR_DEFAULTS,\n KtSnackbarConfig,\n KtSnackbarOptions,\n KtSnackbarPoliteness,\n KtSnackbarPosition,\n} from './snackbar-config';\nimport { KT_SNACKBAR_CONTEXT, KtSnackbarContainer, KtSnackbarContext } from './snackbar-container';\nimport { KtSnackbarRef } from './snackbar-ref';\n\n/** Élément de la file FIFO interne (une seule snackbar visible à la fois). */\ninterface KtSnackbarQueueItem {\n ref: KtSnackbarRef;\n readonly context: KtSnackbarContext;\n readonly position: KtSnackbarPosition;\n readonly politeness: KtSnackbarPoliteness;\n}\n\n/**\n * Service d'ouverture des snackbars `@ktortu/aaa` — feedback **non bloquant** qui confirme une\n * action ou signale un événement transitoire sans interrompre la tâche (n'utilisez PAS de snackbar\n * pour une information critique à acquitter : préférez le dialog).\n *\n * Architecture a11y :\n * - **CDK Overlay** pour le panneau visuel, **CDK LiveAnnouncer** pour l'annonce — **un seul canal**\n * d'annonce (le panneau n'est pas une live region) ;\n * - **le focus n'est jamais déplacé** vers la snackbar (RGAA « message de statut » / WCAG 4.1.3) ;\n * - disparition automatique **en pause au survol et au focus** (régime `'auto'`, défaut AA), ou\n * persistante (`timing: 'manual'`, AAA) ;\n * - **file FIFO** : une seule snackbar visible, les suivantes patientent (live region non saturée).\n * La file est bornée par `max` (défaut 3) ; les messages **identiques** sont fusionnés (coalescing) ;\n * - **Échap** ferme la snackbar affichée (la plus récente).\n *\n * Requiert côté hôte les styles `@angular/cdk/overlay-prebuilt.css` **et**\n * `@angular/cdk/a11y-prebuilt.css` (ce dernier masque l'élément du LiveAnnouncer).\n *\n * @example\n * ```ts\n * private readonly snackbar = inject(KtSnackbar);\n * this.snackbar.open('Brouillon enregistré'); // disparaît, annonce polie\n * this.snackbar.open('Fichier supprimé', { variant: 'success' }); // variante (couleur + icône)\n * this.snackbar.open('Hors ligne', { timing: 'manual' }); // reste jusqu'à fermeture (AAA)\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class KtSnackbar implements OnDestroy {\n private readonly overlay = inject(Overlay);\n private readonly injector = inject(Injector);\n private readonly liveAnnouncer = inject(LiveAnnouncer);\n private readonly config = inject(KT_SNACKBAR_CONFIG, { optional: true });\n private readonly platformId = inject(PLATFORM_ID);\n private readonly doc = inject(DOCUMENT);\n\n /** File FIFO : `queue[0]` est la snackbar affichée dès qu'elle est attachée. */\n private readonly queue: KtSnackbarQueueItem[] = [];\n private active: { item: KtSnackbarQueueItem; overlayRef: OverlayRef; cmp: ComponentRef<KtSnackbarContainer> } | null =\n null;\n private escapeRegistered = false;\n\n /**\n * Ouvre une snackbar affichant `message`. Les `options` priment sur `KT_SNACKBAR_CONFIG`, qui\n * prime sur les défauts. Renvoie une {@link KtSnackbarRef} (ignorable dans le cas simple).\n *\n * Une seule snackbar est visible : si une autre est affichée, celle-ci patiente en file (FIFO).\n * Un `message` identique à une snackbar déjà affichée ou en attente est **fusionné** : on renvoie\n * alors la référence existante sans rien ré-empiler.\n *\n * @param message Texte affiché et annoncé au lecteur d'écran.\n * @param options Surcharges ponctuelles (durée, régime, position, politesse, variante, fermeture).\n * @returns La référence de la snackbar (existante en cas de fusion).\n */\n open(message: string, options?: KtSnackbarOptions): KtSnackbarRef {\n const resolved = this.resolve(options);\n\n // SSR : aucun overlay côté serveur — on renvoie une référence inerte déjà fermée.\n if (!isPlatformBrowser(this.platformId)) {\n const inert = new KtSnackbarRef(() => {\n /* SSR : aucun overlay à fermer. */\n });\n inert.dismiss('dismiss');\n return inert;\n }\n\n // Coalescing : message identique déjà affiché ou en file → on réutilise la référence existante.\n const existing = this.queue.find((entry) => entry.context.message === message);\n if (existing) return existing.ref;\n\n const context: KtSnackbarContext = {\n message,\n variant: resolved.variant,\n closable: resolved.closable,\n closeLabel: resolved.closeLabel,\n timing: resolved.timing,\n duration: this.computeDuration(message, resolved),\n };\n const item = { context, position: resolved.position, politeness: resolved.politeness } as KtSnackbarQueueItem;\n item.ref = new KtSnackbarRef(() => this.handleDismiss(item));\n\n this.queue.push(item);\n this.enforceMax(resolved.max);\n this.showHead();\n return item.ref;\n }\n\n ngOnDestroy(): void {\n this.unregisterEscape();\n this.active?.overlayRef.dispose();\n this.active = null;\n this.queue.length = 0;\n }\n\n /** Borne la file (affichée + en attente) : retire les plus ANCIENNES en attente au-delà de `max`. */\n private enforceMax(max: number): void {\n const limit = Math.max(1, max);\n while (this.queue.length > limit) {\n const oldestWaiting = this.queue.find((entry) => entry !== this.active?.item);\n if (!oldestWaiting) break;\n // Jamais affichée : la fermeture est routée via handleDismiss (qui la retire de la file).\n oldestWaiting.ref.dismiss('replaced');\n }\n }\n\n /** Affiche la tête de file si rien n'est actuellement visible. */\n private showHead(): void {\n if (this.active || this.queue.length === 0) return;\n const item = this.queue[0];\n\n const positionStrategy = this.overlay.position().global().centerHorizontally();\n if (item.position === 'top') positionStrategy.top('0');\n else positionStrategy.bottom('0');\n\n const overlayRef = this.overlay.create({\n positionStrategy,\n panelClass: ['kt-snackbar-pane', `kt-snackbar-pane--${item.position}`],\n });\n\n const injector = Injector.create({\n parent: this.injector,\n providers: [\n { provide: KtSnackbarRef, useValue: item.ref },\n { provide: KT_SNACKBAR_CONTEXT, useValue: item.context },\n ],\n });\n\n const cmp = overlayRef.attach(new ComponentPortal(KtSnackbarContainer, null, injector));\n\n // Canal d'annonce UNIQUE : le panneau visuel n'est pas une live region.\n void this.liveAnnouncer.announce(item.context.message, item.politeness);\n\n this.active = { item, overlayRef, cmp };\n this.registerEscape();\n }\n\n /** Retire l'élément de la file ; s'il est affiché, joue la sortie puis démonte et avance la file. */\n private handleDismiss(item: KtSnackbarQueueItem): void {\n const index = this.queue.indexOf(item);\n if (index === -1) return;\n\n if (this.active && this.active.item === item) {\n const { overlayRef, cmp } = this.active;\n this.active = null;\n this.queue.splice(index, 1);\n cmp.instance.playExit(() => {\n overlayRef.dispose();\n this.showHead();\n if (this.queue.length === 0) this.unregisterEscape();\n });\n return;\n }\n\n // En attente : aucun visuel à démonter.\n this.queue.splice(index, 1);\n }\n\n private readonly onDocumentKeydown = (event: KeyboardEvent): void => {\n // Échap ferme la plus récente (= la snackbar affichée).\n if (event.key === 'Escape') this.active?.item.ref.dismiss('dismiss');\n };\n\n private registerEscape(): void {\n if (this.escapeRegistered) return;\n this.doc.addEventListener('keydown', this.onDocumentKeydown);\n this.escapeRegistered = true;\n }\n\n private unregisterEscape(): void {\n if (!this.escapeRegistered) return;\n this.doc.removeEventListener('keydown', this.onDocumentKeydown);\n this.escapeRegistered = false;\n }\n\n /**\n * Durée effective (ms) en régime `'auto'`. Un nombre est pris tel quel (durée fixe) ; le sentinel\n * `'reading-time'` calcule `clamp(longueur × perChar, min, max)`.\n */\n private computeDuration(message: string, resolved: KtSnackbarConfig): number {\n const setting = resolved.duration;\n if (typeof setting === 'number') return setting;\n const computed = message.length * resolved.readingTimePerChar;\n return Math.min(resolved.readingTimeMax, Math.max(resolved.readingTimeMin, computed));\n }\n\n /** Résolution en cascade `option ?? KT_SNACKBAR_CONFIG ?? défaut`, champ par champ. */\n private resolve(options?: KtSnackbarOptions): KtSnackbarConfig {\n const config = this.config;\n return {\n duration: options?.duration ?? config?.duration ?? KT_SNACKBAR_DEFAULTS.duration,\n readingTimeMin: options?.readingTimeMin ?? config?.readingTimeMin ?? KT_SNACKBAR_DEFAULTS.readingTimeMin,\n readingTimeMax: options?.readingTimeMax ?? config?.readingTimeMax ?? KT_SNACKBAR_DEFAULTS.readingTimeMax,\n readingTimePerChar:\n options?.readingTimePerChar ?? config?.readingTimePerChar ?? KT_SNACKBAR_DEFAULTS.readingTimePerChar,\n timing: options?.timing ?? config?.timing ?? KT_SNACKBAR_DEFAULTS.timing,\n position: options?.position ?? config?.position ?? KT_SNACKBAR_DEFAULTS.position,\n politeness: options?.politeness ?? config?.politeness ?? KT_SNACKBAR_DEFAULTS.politeness,\n variant: options?.variant ?? config?.variant ?? KT_SNACKBAR_DEFAULTS.variant,\n closable: options?.closable ?? config?.closable ?? KT_SNACKBAR_DEFAULTS.closable,\n closeLabel: options?.closeLabel ?? config?.closeLabel ?? KT_SNACKBAR_DEFAULTS.closeLabel,\n max: options?.max ?? config?.max ?? KT_SNACKBAR_DEFAULTS.max,\n };\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;;;;;AA4EA;AACO,MAAM,oBAAoB,GAAqB;;AAEpD,IAAA,QAAQ,EAAE,cAAc;AACxB,IAAA,cAAc,EAAE,IAAI;AACpB,IAAA,cAAc,EAAE,KAAK;AACrB,IAAA,kBAAkB,EAAE,EAAE;AACtB,IAAA,MAAM,EAAE,MAAM;AACd,IAAA,QAAQ,EAAE,QAAQ;AAClB,IAAA,UAAU,EAAE,QAAQ;AACpB,IAAA,OAAO,EAAE,SAAS;AAClB,IAAA,QAAQ,EAAE,IAAI;AACd,IAAA,UAAU,EAAE,OAAO;AACnB,IAAA,GAAG,EAAE,CAAC;;AAGR;MACa,kBAAkB,GAAG,IAAI,cAAc,CAA4B,oBAAoB;AAQpG;;;;;;;;;;;;AAYG;AACG,SAAU,iBAAiB,CAAC,MAAiC,EAAA;IACjE,OAAO,EAAE,OAAO,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,EAAE;AAC1D;;AC1GA;;;;;;;;;;;;;AAaG;MACU,aAAa,CAAA;AASK,IAAA,SAAA;AARZ,IAAA,eAAe,GAAG,IAAI,OAAO,EAA2B;IACjE,OAAO,GAAG,KAAK;AAEvB;;;;AAIG;AACH,IAAA,WAAA,CAA6B,SAAoD,EAAA;QAApD,IAAA,CAAA,SAAS,GAAT,SAAS;IAA8C;AAEpF;;;;AAIG;IACH,OAAO,CAAC,SAAkC,SAAS,EAAA;QACjD,IAAI,IAAI,CAAC,OAAO;YAAE;AAClB,QAAA,IAAI,CAAC,OAAO,GAAG,IAAI;AACnB,QAAA,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;AACtB,QAAA,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC;AACjC,QAAA,IAAI,CAAC,eAAe,CAAC,QAAQ,EAAE;IACjC;;IAGA,cAAc,GAAA;AACZ,QAAA,OAAO,IAAI,CAAC,eAAe,CAAC,YAAY,EAAE;IAC5C;AACD;;ACjBD;MACa,mBAAmB,GAAG,IAAI,cAAc,CAAoB,qBAAqB;AAE9F;;;;;;;;;;;AAWG;MA4BU,mBAAmB,CAAA;AACX,IAAA,OAAO,GAAG,MAAM,CAAC,mBAAmB,CAAC;AACvC,IAAA,GAAG,GAAG,MAAM,CAAC,aAAa,CAAC;AAC3B,IAAA,UAAU,GAAG,MAAM,CAAC,WAAW,CAAC;AAChC,IAAA,IAAI,GAAG,MAAM,CAA0B,UAAU,CAAC,CAAC,aAAa;;IAG9D,OAAO,GAAG,MAAM,CAAC,KAAK;gFAAC;AAElC,IAAA,KAAK;AACL,IAAA,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ;IACjC,QAAQ,GAAG,CAAC;IACZ,OAAO,GAAG,KAAK;IACf,OAAO,GAAG,KAAK;AAEvB,IAAA,WAAA,GAAA;AACE,QAAA,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,MAAM,IAAI,iBAAiB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE;AACxE,YAAA,eAAe,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC/D;AACA,QAAA,MAAM,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;IACvD;IAEU,KAAK,GAAA;AACb,QAAA,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC;IAC7B;AAEA;;;;AAIG;AACH,IAAA,QAAQ,CAAC,IAAgB,EAAA;QACvB,IAAI,CAAC,UAAU,EAAE;QACjB,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE;AACvC,YAAA,IAAI,EAAE;YACN;QACF;AACA,QAAA,MAAM,UAAU,GAAG,IAAI,CAAC,cAAc,EAAE;;;;AAIxC,QAAA,IAAI,UAAU,IAAI,CAAC,EAAE;AACnB,YAAA,IAAI,EAAE;YACN;QACF;AAEA,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;QACtB,IAAI,QAAQ,GAAG,KAAK;QACpB,MAAM,MAAM,GAAG,MAAW;AACxB,YAAA,IAAI,QAAQ;gBAAE;YACd,QAAQ,GAAG,IAAI;YACf,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,eAAe,EAAE,eAAe,CAAC;AAC/D,YAAA,IAAI,EAAE;AACR,QAAA,CAAC;AACD,QAAA,MAAM,eAAe,GAAG,CAAC,KAAsB,KAAU;AACvD,YAAA,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,CAAC,IAAI;AAAE,gBAAA,MAAM,EAAE;AAC1C,QAAA,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,eAAe,EAAE,eAAe,CAAC;AAC5D,QAAA,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,EAAE,CAAC;;IAErC;IAEU,cAAc,GAAA;AACtB,QAAA,IAAI,CAAC,OAAO,GAAG,IAAI;QACnB,IAAI,CAAC,UAAU,EAAE;IACnB;IAEU,cAAc,GAAA;AACtB,QAAA,IAAI,CAAC,OAAO,GAAG,KAAK;QACpB,IAAI,CAAC,WAAW,EAAE;IACpB;IAEU,YAAY,GAAA;AACpB,QAAA,IAAI,CAAC,OAAO,GAAG,IAAI;QACnB,IAAI,CAAC,UAAU,EAAE;IACnB;IAEU,YAAY,GAAA;AACpB,QAAA,IAAI,CAAC,OAAO,GAAG,KAAK;QACpB,IAAI,CAAC,WAAW,EAAE;IACpB;IAEQ,WAAW,GAAA;AACjB,QAAA,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO;YAAE;AAClC,QAAA,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,MAAM,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,EAAE;YAAE;AAClF,QAAA,IAAI,IAAI,CAAC,SAAS,IAAI,CAAC,EAAE;AACvB,YAAA,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC;YAC3B;QACF;AACA,QAAA,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC;IACjC;AAEQ,IAAA,UAAU,CAAC,EAAU,EAAA;QAC3B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE;AAC/B,QAAA,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC;IAChE;IAEQ,UAAU,GAAA;AAChB,QAAA,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;YAAE;AAC9B,QAAA,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACxD,IAAI,CAAC,UAAU,EAAE;IACnB;IAEQ,UAAU,GAAA;AAChB,QAAA,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;YAAE;AAC9B,QAAA,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC;AACxB,QAAA,IAAI,CAAC,KAAK,GAAG,SAAS;IACxB;;IAGQ,cAAc,GAAA;;;;AAIpB,QAAA,MAAM,GAAG,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,kBAAkB,IAAI,EAAE;AAChE,QAAA,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;AACtC,QAAA,IAAI,CAAC,KAAK;AAAE,YAAA,OAAO,CAAC;AACpB,QAAA,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC;AAC/B,QAAA,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC;AAAE,YAAA,OAAO,CAAC;AACjC,QAAA,OAAO,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI;;IAEpD;uGAzHW,mBAAmB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAnB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,mBAAmB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,uBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,YAAA,EAAA,kBAAA,EAAA,YAAA,EAAA,kBAAA,EAAA,SAAA,EAAA,gBAAA,EAAA,UAAA,EAAA,gBAAA,EAAA,EAAA,UAAA,EAAA,EAAA,mBAAA,EAAA,iBAAA,EAAA,4BAAA,EAAA,WAAA,EAAA,EAAA,cAAA,EAAA,aAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAfpB;;;;;;;;;;;;;AAaT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAEU,mBAAmB,EAAA,UAAA,EAAA,CAAA;kBA3B/B,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,uBAAuB;oBACjC,eAAe,EAAE,uBAAuB,CAAC,MAAM;AAC/C,oBAAA,IAAI,EAAE;AACJ,wBAAA,KAAK,EAAE,aAAa;AACpB,wBAAA,qBAAqB,EAAE,iBAAiB;AACxC,wBAAA,8BAA8B,EAAE,WAAW;AAC3C,wBAAA,cAAc,EAAE,kBAAkB;AAClC,wBAAA,cAAc,EAAE,kBAAkB;AAClC,wBAAA,WAAW,EAAE,gBAAgB;AAC7B,wBAAA,YAAY,EAAE,gBAAgB;AAC/B,qBAAA;AACD,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;AAaT,EAAA,CAAA;AACF,iBAAA;;;ACnDD;;;;;;;;;;;;;;;;;;;;;;;;;AAyBG;MAEU,UAAU,CAAA;AACJ,IAAA,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;AACzB,IAAA,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;AAC3B,IAAA,aAAa,GAAG,MAAM,CAAC,aAAa,CAAC;IACrC,MAAM,GAAG,MAAM,CAAC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AACvD,IAAA,UAAU,GAAG,MAAM,CAAC,WAAW,CAAC;AAChC,IAAA,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC;;IAGtB,KAAK,GAA0B,EAAE;IAC1C,MAAM,GACZ,IAAI;IACE,gBAAgB,GAAG,KAAK;AAEhC;;;;;;;;;;;AAWG;IACH,IAAI,CAAC,OAAe,EAAE,OAA2B,EAAA;QAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC;;QAGtC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE;AACvC,YAAA,MAAM,KAAK,GAAG,IAAI,aAAa,CAAC,MAAK;;AAErC,YAAA,CAAC,CAAC;AACF,YAAA,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;AACxB,YAAA,OAAO,KAAK;QACd;;QAGA,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,OAAO,CAAC,OAAO,KAAK,OAAO,CAAC;AAC9E,QAAA,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAC,GAAG;AAEjC,QAAA,MAAM,OAAO,GAAsB;YACjC,OAAO;YACP,OAAO,EAAE,QAAQ,CAAC,OAAO;YACzB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,UAAU,EAAE,QAAQ,CAAC,UAAU;YAC/B,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,QAAQ,EAAE,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,QAAQ,CAAC;SAClD;AACD,QAAA,MAAM,IAAI,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,UAAU,EAAE,QAAQ,CAAC,UAAU,EAAyB;AAC7G,QAAA,IAAI,CAAC,GAAG,GAAG,IAAI,aAAa,CAAC,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;AAE5D,QAAA,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;AACrB,QAAA,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC;QAC7B,IAAI,CAAC,QAAQ,EAAE;QACf,OAAO,IAAI,CAAC,GAAG;IACjB;IAEA,WAAW,GAAA;QACT,IAAI,CAAC,gBAAgB,EAAE;AACvB,QAAA,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,EAAE;AACjC,QAAA,IAAI,CAAC,MAAM,GAAG,IAAI;AAClB,QAAA,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;IACvB;;AAGQ,IAAA,UAAU,CAAC,GAAW,EAAA;QAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC;QAC9B,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,KAAK,EAAE;YAChC,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,KAAK,KAAK,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAC7E,YAAA,IAAI,CAAC,aAAa;gBAAE;;AAEpB,YAAA,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC;QACvC;IACF;;IAGQ,QAAQ,GAAA;QACd,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE;QAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;AAE1B,QAAA,MAAM,gBAAgB,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,CAAC,kBAAkB,EAAE;AAC9E,QAAA,IAAI,IAAI,CAAC,QAAQ,KAAK,KAAK;AAAE,YAAA,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC;;AACjD,YAAA,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC;AAEjC,QAAA,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;YACrC,gBAAgB;YAChB,UAAU,EAAE,CAAC,kBAAkB,EAAE,qBAAqB,IAAI,CAAC,QAAQ,CAAA,CAAE,CAAC;AACvE,SAAA,CAAC;AAEF,QAAA,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC;YAC/B,MAAM,EAAE,IAAI,CAAC,QAAQ;AACrB,YAAA,SAAS,EAAE;gBACT,EAAE,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE;gBAC9C,EAAE,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE;AACzD,aAAA;AACF,SAAA,CAAC;AAEF,QAAA,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,eAAe,CAAC,mBAAmB,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;;AAGvF,QAAA,KAAK,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC;QAEvE,IAAI,CAAC,MAAM,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE;QACvC,IAAI,CAAC,cAAc,EAAE;IACvB;;AAGQ,IAAA,aAAa,CAAC,IAAyB,EAAA;QAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;QACtC,IAAI,KAAK,KAAK,CAAC,CAAC;YAAE;AAElB,QAAA,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,IAAI,EAAE;YAC5C,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM;AACvC,YAAA,IAAI,CAAC,MAAM,GAAG,IAAI;YAClB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;AAC3B,YAAA,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAK;gBACzB,UAAU,CAAC,OAAO,EAAE;gBACpB,IAAI,CAAC,QAAQ,EAAE;AACf,gBAAA,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;oBAAE,IAAI,CAAC,gBAAgB,EAAE;AACtD,YAAA,CAAC,CAAC;YACF;QACF;;QAGA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;IAC7B;AAEiB,IAAA,iBAAiB,GAAG,CAAC,KAAoB,KAAU;;AAElE,QAAA,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ;YAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC;AACtE,IAAA,CAAC;IAEO,cAAc,GAAA;QACpB,IAAI,IAAI,CAAC,gBAAgB;YAAE;QAC3B,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,iBAAiB,CAAC;AAC5D,QAAA,IAAI,CAAC,gBAAgB,GAAG,IAAI;IAC9B;IAEQ,gBAAgB,GAAA;QACtB,IAAI,CAAC,IAAI,CAAC,gBAAgB;YAAE;QAC5B,IAAI,CAAC,GAAG,CAAC,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,iBAAiB,CAAC;AAC/D,QAAA,IAAI,CAAC,gBAAgB,GAAG,KAAK;IAC/B;AAEA;;;AAGG;IACK,eAAe,CAAC,OAAe,EAAE,QAA0B,EAAA;AACjE,QAAA,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ;QACjC,IAAI,OAAO,OAAO,KAAK,QAAQ;AAAE,YAAA,OAAO,OAAO;QAC/C,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,GAAG,QAAQ,CAAC,kBAAkB;AAC7D,QAAA,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,cAAc,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;IACvF;;AAGQ,IAAA,OAAO,CAAC,OAA2B,EAAA;AACzC,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM;QAC1B,OAAO;YACL,QAAQ,EAAE,OAAO,EAAE,QAAQ,IAAI,MAAM,EAAE,QAAQ,IAAI,oBAAoB,CAAC,QAAQ;YAChF,cAAc,EAAE,OAAO,EAAE,cAAc,IAAI,MAAM,EAAE,cAAc,IAAI,oBAAoB,CAAC,cAAc;YACxG,cAAc,EAAE,OAAO,EAAE,cAAc,IAAI,MAAM,EAAE,cAAc,IAAI,oBAAoB,CAAC,cAAc;YACxG,kBAAkB,EAChB,OAAO,EAAE,kBAAkB,IAAI,MAAM,EAAE,kBAAkB,IAAI,oBAAoB,CAAC,kBAAkB;YACtG,MAAM,EAAE,OAAO,EAAE,MAAM,IAAI,MAAM,EAAE,MAAM,IAAI,oBAAoB,CAAC,MAAM;YACxE,QAAQ,EAAE,OAAO,EAAE,QAAQ,IAAI,MAAM,EAAE,QAAQ,IAAI,oBAAoB,CAAC,QAAQ;YAChF,UAAU,EAAE,OAAO,EAAE,UAAU,IAAI,MAAM,EAAE,UAAU,IAAI,oBAAoB,CAAC,UAAU;YACxF,OAAO,EAAE,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,OAAO,IAAI,oBAAoB,CAAC,OAAO;YAC5E,QAAQ,EAAE,OAAO,EAAE,QAAQ,IAAI,MAAM,EAAE,QAAQ,IAAI,oBAAoB,CAAC,QAAQ;YAChF,UAAU,EAAE,OAAO,EAAE,UAAU,IAAI,MAAM,EAAE,UAAU,IAAI,oBAAoB,CAAC,UAAU;YACxF,GAAG,EAAE,OAAO,EAAE,GAAG,IAAI,MAAM,EAAE,GAAG,IAAI,oBAAoB,CAAC,GAAG;SAC7D;IACH;uGA9KW,UAAU,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAV,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,UAAU,cADG,MAAM,EAAA,CAAA;;2FACnB,UAAU,EAAA,UAAA,EAAA,CAAA;kBADtB,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;ACnDlC;;AAEG;;;;"}
1
+ {"version":3,"file":"ktortu-aaa-snackbar.mjs","sources":["../../../../projects/ktortu/aaa/snackbar/snackbar-config.ts","../../../../projects/ktortu/aaa/snackbar/snackbar-ref.ts","../../../../projects/ktortu/aaa/snackbar/snackbar-container.ts","../../../../projects/ktortu/aaa/snackbar/snackbar.service.ts","../../../../projects/ktortu/aaa/snackbar/public-api.ts","../../../../projects/ktortu/aaa/snackbar/ktortu-aaa-snackbar.ts"],"sourcesContent":["import { InjectionToken, Provider } from '@angular/core';\n\n/** Politesse de l'annonce au lecteur d'écran (relayée à `LiveAnnouncer`). */\nexport type KtSnackbarPoliteness = 'polite' | 'assertive';\n\n/** Bord d'ancrage de la snackbar dans le viewport. */\nexport type KtSnackbarPosition = 'top' | 'bottom';\n\n/**\n * Régime temporel de la snackbar :\n * - `'auto'` : disparition automatique après `duration`, **mise en pause au survol et au focus**\n * clavier (WCAG 1.4.13 / 2.2.1). Conforme **AA**. C'est le défaut.\n * - `'manual'` : **aucune** minuterie, la snackbar reste jusqu'à fermeture explicite\n * (bouton de fermeture ou `ref.dismiss()`). Conforme **2.2.3 (AAA)** au sens strict.\n *\n * Conformément aux recommandations d'accessibilité (Roselli/Soueidan), la snackbar ne porte **pas\n * d'action interactive** (ex. « Annuler ») : une action auto-disparaissante n'est pas atteignable et\n * une live region n'expose pas ses boutons. Pour un undo, préférez un mécanisme atteignable côté app\n * (Ctrl+Z, bannière persistante).\n */\nexport type KtSnackbarTiming = 'auto' | 'manual';\n\n/**\n * Variante sémantique de la snackbar. Pilote uniquement l'**apparence** (couleur d'accent + icône),\n * via l'attribut `data-variant` et les tokens CSS `--snackbar-*` — donc entièrement gérée par le\n * thème, sans logique TypeScript. Découplée de la `politeness` (une « erreur » n'est pas forcément\n * une urgence assertive). La couleur n'est jamais le seul indice : chaque variante porte une **icône**\n * de forme distincte (WCAG 1.4.1).\n * - `'neutral'` : pastille neutre, sans icône (défaut) ;\n * - `'info' | 'success' | 'warning' | 'error'` : accent + icône dédiés.\n */\nexport type KtSnackbarVariant = 'neutral' | 'info' | 'success' | 'warning' | 'error';\n\n/**\n * Défauts de la snackbar, injectables via `provideKtSnackbar` / `KT_SNACKBAR_CONFIG`.\n * Tous les champs sont surchargeables **par appel** via les options de `KtSnackbar.open()`.\n *\n * Résolution en cascade (convention de la lib) : `option d'open ?? KT_SNACKBAR_CONFIG ?? défaut`.\n */\nexport interface KtSnackbarConfig {\n /**\n * Durée d'affichage en régime `'auto'`. Soit un **nombre fixe** (ms), soit le sentinel\n * **`'reading-time'`** (DÉFAUT) qui **calcule** la durée d'après la longueur du message :\n * `clamp(longueur × readingTimePerChar, readingTimeMin, readingTimeMax)`. Passer un nombre à\n * `open()` force donc une durée fixe pour cet appel.\n *\n * ⚠️ Gardez le message **court** : une snackbar est un message transitoire (pas un paragraphe).\n * Un message long fait grimper la durée jusqu'au plafond `readingTimeMax`.\n * @default 'reading-time'\n */\n duration: number | 'reading-time';\n /** Plancher (ms) de la durée calculée (`'reading-time'`) — laisse le temps de lire un message court. @default 4000 */\n readingTimeMin: number;\n /** Plafond (ms) de la durée calculée (`'reading-time'`) — borne un message long. @default 10000 */\n readingTimeMax: number;\n /** Coefficient de lecture : millisecondes ajoutées par caractère du message. @default 60 (~200 mots/min) */\n readingTimePerChar: number;\n /** Régime temporel (cf. {@link KtSnackbarTiming}). @default 'auto' (AA + pause) */\n timing: KtSnackbarTiming;\n /** Bord d'ancrage dans le viewport. @default 'bottom' */\n position: KtSnackbarPosition;\n /** Politesse de l'annonce lecteur d'écran. @default 'polite' */\n politeness: KtSnackbarPoliteness;\n /** Variante sémantique (apparence seule, cf. {@link KtSnackbarVariant}). @default 'neutral' */\n variant: KtSnackbarVariant;\n /** Affiche un bouton de fermeture (cible 44px, AAA). @default true */\n closable: boolean;\n /** Nom accessible du bouton de fermeture. @default 'Close' (FR fourni en lot L3) */\n closeLabel: string;\n /**\n * Taille maximale de la file FIFO (snackbar affichée + en attente). Au-delà, les **plus anciennes\n * en attente** sont retirées silencieusement. Une seule snackbar est visible à la fois. @default 3\n */\n max: number;\n}\n\n/** Défauts AAA-orientés de la snackbar (anglais neutre). */\nexport const KT_SNACKBAR_DEFAULTS: KtSnackbarConfig = {\n // Stryker disable next-line StringLiteral: équivalent — computeDuration() traite toute valeur non numérique comme reading-time\n duration: 'reading-time',\n readingTimeMin: 4000,\n readingTimeMax: 10000,\n readingTimePerChar: 60,\n timing: 'auto',\n position: 'bottom',\n politeness: 'polite',\n variant: 'neutral',\n closable: true,\n closeLabel: 'Close',\n max: 3,\n};\n\n// Stryker disable next-line StringLiteral: libellé de debug du token d'injection (sans effet runtime)\nexport const KT_SNACKBAR_CONFIG = new InjectionToken<Partial<KtSnackbarConfig>>('KT_SNACKBAR_CONFIG');\n\n/**\n * Options ponctuelles d'ouverture d'une snackbar : un sous-ensemble (toutes facultatives) de la\n * config, prioritaire sur `KT_SNACKBAR_CONFIG` et sur les défauts.\n */\nexport type KtSnackbarOptions = Partial<KtSnackbarConfig>;\n\n/**\n * Fournit des défauts de snackbar pour un sous-arbre ou l'application entière.\n *\n * @example\n * ```ts\n * // app.config.ts — bascule TOUTE l'app en AAA strict (aucune disparition automatique)\n * providers: [provideKtSnackbar({ timing: 'manual' })]\n * ```\n * @example\n * ```ts\n * providers: [provideKtSnackbar({ duration: 8000, position: 'top' })]\n * ```\n */\nexport function provideKtSnackbar(config: Partial<KtSnackbarConfig>): Provider {\n return { provide: KT_SNACKBAR_CONFIG, useValue: config };\n}\n","import { Observable, Subject } from 'rxjs';\n\n/**\n * Raison de fermeture d'une snackbar, transmise par {@link KtSnackbarRef.afterDismissed}.\n * - `'timeout'` : la minuterie (régime `'auto'`) est arrivée à échéance ;\n * - `'dismiss'` : fermeture explicite (bouton de fermeture, `Échap`, ou `ref.dismiss()`) ;\n * - `'replaced'` : la snackbar a été retirée de la file sans être affichée (file pleine — cf. `max`).\n */\nexport type KtSnackbarDismissReason = 'timeout' | 'dismiss' | 'replaced';\n\n/**\n * Référence d'une snackbar ouverte, renvoyée par `KtSnackbar.open()`. Permet de fermer la\n * snackbar par programmation et d'observer sa fermeture.\n *\n * Le débutant peut l'ignorer (`snackbar.open('…')`) ; le code avancé s'en sert pour piloter la\n * fermeture et réagir à la raison de fin.\n *\n * @example\n * ```ts\n * const ref = snackbar.open('Brouillon enregistré');\n * ref.afterDismissed().subscribe((reason) => console.log(reason)); // 'timeout' | 'dismiss' | 'replaced'\n * // plus tard : ref.dismiss();\n * ```\n */\nexport class KtSnackbarRef {\n private readonly _afterDismissed = new Subject<KtSnackbarDismissReason>();\n private settled = false;\n\n /**\n * @param onDismiss Rappel exécuté une fois à la fermeture (animation de sortie + démontage de\n * l'overlay + avance de la file), fourni par le service.\n * @internal Construit par `KtSnackbar` — n'instanciez pas `KtSnackbarRef` directement.\n */\n constructor(private readonly onDismiss: (reason: KtSnackbarDismissReason) => void) {}\n\n /**\n * Ferme la snackbar (idempotent). Déclenche la sortie/démontage puis émet la raison sur\n * `afterDismissed()`.\n * @param reason Raison de fermeture. @default 'dismiss'\n */\n dismiss(reason: KtSnackbarDismissReason = 'dismiss'): void {\n if (this.settled) return;\n this.settled = true;\n this.onDismiss(reason);\n this._afterDismissed.next(reason);\n this._afterDismissed.complete();\n }\n\n /** Émet une fois (puis complète) à la fermeture, avec la {@link KtSnackbarDismissReason}. */\n afterDismissed(): Observable<KtSnackbarDismissReason> {\n return this._afterDismissed.asObservable();\n }\n}\n","import { isPlatformBrowser } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n ElementRef,\n InjectionToken,\n PLATFORM_ID,\n afterNextRender,\n inject,\n signal,\n} from '@angular/core';\n\nimport { KtSnackbarTiming, KtSnackbarVariant } from './snackbar-config';\nimport { KtSnackbarRef } from './snackbar-ref';\n\n/**\n * Données résolues passées au conteneur visuel à l'ouverture (injectées via {@link KT_SNACKBAR_CONTEXT}).\n * Produites par `KtSnackbar` après résolution `option ?? config ?? défaut`.\n */\nexport interface KtSnackbarContext {\n /** Message affiché et annoncé. */\n readonly message: string;\n /** Variante sémantique (apparence : accent + icône). */\n readonly variant: KtSnackbarVariant;\n /** Affiche le bouton de fermeture. */\n readonly closable: boolean;\n /** Nom accessible du bouton de fermeture. */\n readonly closeLabel: string;\n /** Régime temporel (la minuterie n'existe qu'en `'auto'`). */\n readonly timing: KtSnackbarTiming;\n /** Durée (ms) avant disparition automatique en régime `'auto'`. */\n readonly duration: number;\n}\n\n// Stryker disable next-line StringLiteral: libellé de debug du token d'injection (sans effet runtime)\nexport const KT_SNACKBAR_CONTEXT = new InjectionToken<KtSnackbarContext>('KT_SNACKBAR_CONTEXT');\n\n/**\n * Conteneur visuel d'une snackbar. **Volontairement pas une live region** (aucun `role`/`aria-live`\n * sur l'hôte) : l'annonce passe par un canal UNIQUE, le `LiveAnnouncer` du service. On évite ainsi\n * la double-annonce et l'écrasement de politesse observés sur d'autres libs.\n *\n * En régime `'auto'`, la minuterie de disparition se met **en pause au survol et au focus** clavier\n * (WCAG 1.4.13 / 2.2.1) et reprend quand ni le pointeur ni le focus ne sont sur la snackbar.\n * L'icône de variante est **décorative** (`aria-hidden`) : la forme distincte sert d'indice non\n * coloré (WCAG 1.4.1), le sens reste porté par le texte.\n *\n * @internal Monté par `KtSnackbar` via un `ComponentPortal`.\n */\n@Component({\n selector: 'kt-snackbar-container',\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n class: 'kt-snackbar',\n '[attr.data-variant]': 'context.variant',\n '[class.kt-snackbar--leaving]': 'leaving()',\n '(mouseenter)': 'onPointerEnter()',\n '(mouseleave)': 'onPointerLeave()',\n '(focusin)': 'onFocusEnter()',\n '(focusout)': 'onFocusLeave()',\n },\n template: `\n @if (context.variant !== 'neutral') {\n <span class=\"kt-snackbar__icon\" aria-hidden=\"true\"></span>\n }\n <span class=\"kt-snackbar__message\">{{ context.message }}</span>\n @if (context.closable) {\n <button\n type=\"button\"\n class=\"kt-snackbar__close\"\n [attr.aria-label]=\"context.closeLabel\"\n (click)=\"close()\"\n ></button>\n }\n `,\n})\nexport class KtSnackbarContainer {\n protected readonly context = inject(KT_SNACKBAR_CONTEXT);\n private readonly ref = inject(KtSnackbarRef);\n private readonly platformId = inject(PLATFORM_ID);\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n\n /** Vrai pendant l'animation de sortie (déclenche la classe `kt-snackbar--leaving`). */\n protected readonly leaving = signal(false);\n\n private timer: ReturnType<typeof setTimeout> | undefined;\n private remaining = this.context.duration;\n private deadline = 0;\n private hovered = false;\n private focused = false;\n\n constructor() {\n if (this.context.timing === 'auto' && isPlatformBrowser(this.platformId)) {\n afterNextRender(() => this.startTimer(this.context.duration));\n }\n inject(DestroyRef).onDestroy(() => this.clearTimer());\n }\n\n protected close(): void {\n this.ref.dismiss('dismiss');\n }\n\n /**\n * Joue l'animation de sortie puis invoque `done` (démontage de l'overlay côté service). Appelé par\n * le service à la fermeture. Sans animation (durée nulle, `prefers-reduced-motion`, ou SSR), `done`\n * est invoqué immédiatement. Filet de sécurité par `setTimeout` si `transitionend` ne se déclenche pas.\n */\n playExit(done: () => void): void {\n this.clearTimer();\n if (!isPlatformBrowser(this.platformId)) {\n done();\n return;\n }\n const durationMs = this.exitDurationMs();\n // Stryker disable all: animation de sortie pilotée par une transition CSS réelle. En jsdom\n // `transitionDuration` est vide → `exitDurationMs()` vaut 0 → ce code n'est jamais atteint.\n // Comportement (jeu de l'animation puis démontage) vérifié en e2e (sortie + reduced-motion).\n if (durationMs <= 0) {\n done();\n return;\n }\n\n this.leaving.set(true);\n let finished = false;\n const finish = (): void => {\n if (finished) return;\n finished = true;\n this.host.removeEventListener('transitionend', onTransitionEnd);\n done();\n };\n const onTransitionEnd = (event: TransitionEvent): void => {\n if (event.target === this.host) finish();\n };\n this.host.addEventListener('transitionend', onTransitionEnd);\n setTimeout(finish, durationMs + 50);\n // Stryker restore all\n }\n\n protected onPointerEnter(): void {\n this.hovered = true;\n this.pauseTimer();\n }\n\n protected onPointerLeave(): void {\n this.hovered = false;\n this.maybeResume();\n }\n\n protected onFocusEnter(): void {\n this.focused = true;\n this.pauseTimer();\n }\n\n protected onFocusLeave(): void {\n this.focused = false;\n this.maybeResume();\n }\n\n private maybeResume(): void {\n if (this.hovered || this.focused) return;\n if (this.context.timing !== 'auto' || this.timer !== undefined || this.leaving()) return;\n if (this.remaining <= 0) {\n this.ref.dismiss('timeout');\n return;\n }\n this.startTimer(this.remaining);\n }\n\n private startTimer(ms: number): void {\n this.deadline = Date.now() + ms;\n this.timer = setTimeout(() => this.ref.dismiss('timeout'), ms);\n }\n\n private pauseTimer(): void {\n if (this.timer === undefined) return;\n this.remaining = Math.max(0, this.deadline - Date.now());\n this.clearTimer();\n }\n\n private clearTimer(): void {\n if (this.timer === undefined) return;\n clearTimeout(this.timer);\n this.timer = undefined;\n }\n\n /** Durée (ms) de la transition de sortie, lue sur l'hôte (0 si aucune — ex. reduced-motion). */\n private exitDurationMs(): number {\n // Stryker disable all: lecture/parsing de `transition-duration` CSS — en jsdom\n // `getComputedStyle().transitionDuration` est toujours vide (renvoie 0). Le parsing réel\n // (ms vs s, valeurs multiples, NaN) est exercé en e2e ; intestable en environnement jsdom.\n const raw = getComputedStyle(this.host).transitionDuration || '';\n const first = raw.split(',')[0].trim();\n if (!first) return 0;\n const value = parseFloat(first);\n if (Number.isNaN(value)) return 0;\n return first.endsWith('ms') ? value : value * 1000;\n // Stryker restore all\n }\n}\n","import { LiveAnnouncer } from '@angular/cdk/a11y';\nimport { Overlay, OverlayRef } from '@angular/cdk/overlay';\nimport { ComponentPortal } from '@angular/cdk/portal';\nimport { DOCUMENT, isPlatformBrowser } from '@angular/common';\nimport { ComponentRef, Injectable, Injector, OnDestroy, PLATFORM_ID, inject } from '@angular/core';\n\nimport {\n KT_SNACKBAR_CONFIG,\n KT_SNACKBAR_DEFAULTS,\n KtSnackbarConfig,\n KtSnackbarOptions,\n KtSnackbarPoliteness,\n KtSnackbarPosition,\n} from './snackbar-config';\nimport { KT_SNACKBAR_CONTEXT, KtSnackbarContainer, KtSnackbarContext } from './snackbar-container';\nimport { KtSnackbarRef } from './snackbar-ref';\n\n/** Élément de la file FIFO interne (une seule snackbar visible à la fois). */\ninterface KtSnackbarQueueItem {\n ref: KtSnackbarRef;\n readonly context: KtSnackbarContext;\n readonly position: KtSnackbarPosition;\n readonly politeness: KtSnackbarPoliteness;\n}\n\n/**\n * Service d'ouverture des snackbars `@ktortu/aaa` — feedback **non bloquant** qui confirme une\n * action ou signale un événement transitoire sans interrompre la tâche (n'utilisez PAS de snackbar\n * pour une information critique à acquitter : préférez le dialog).\n *\n * Architecture a11y :\n * - **CDK Overlay** pour le panneau visuel, **CDK LiveAnnouncer** pour l'annonce — **un seul canal**\n * d'annonce (le panneau n'est pas une live region) ;\n * - **le focus n'est jamais déplacé** vers la snackbar (RGAA « message de statut » / WCAG 4.1.3) ;\n * - disparition automatique **en pause au survol et au focus** (régime `'auto'`, défaut AA), ou\n * persistante (`timing: 'manual'`, AAA) ;\n * - **file FIFO** : une seule snackbar visible, les suivantes patientent (live region non saturée).\n * La file est bornée par `max` (défaut 3) ; les messages **identiques** sont fusionnés (coalescing) ;\n * - **Échap** ferme la snackbar affichée (la plus récente).\n *\n * Requiert côté hôte les styles `@angular/cdk/overlay-prebuilt.css` **et**\n * `@angular/cdk/a11y-prebuilt.css` (ce dernier masque l'élément du LiveAnnouncer), en plus de\n * `@ktortu/aaa/snackbar.css`.\n *\n * > [!IMPORTANT]\n * > **Prérequis d'intégration obligatoire :**\n * > Ce service ne fonctionnera pas correctement sans l'importation de ces deux fichiers CSS de l'overlay CDK et d'accessibilité dans votre feuille de styles globale ou votre build.\n *\n * @example\n * ```ts\n * private readonly snackbar = inject(KtSnackbar);\n * this.snackbar.open('Brouillon enregistré'); // disparaît, annonce polie\n * this.snackbar.open('Fichier supprimé', { variant: 'success' }); // variante (couleur + icône)\n * this.snackbar.open('Hors ligne', { timing: 'manual' }); // reste jusqu'à fermeture (AAA)\n * ```\n */\n@Injectable({ providedIn: 'root' })\nexport class KtSnackbar implements OnDestroy {\n private readonly overlay = inject(Overlay);\n private readonly injector = inject(Injector);\n private readonly liveAnnouncer = inject(LiveAnnouncer);\n private readonly config = inject(KT_SNACKBAR_CONFIG, { optional: true });\n private readonly platformId = inject(PLATFORM_ID);\n private readonly doc = inject(DOCUMENT);\n\n /** File FIFO : `queue[0]` est la snackbar affichée dès qu'elle est attachée. */\n private readonly queue: KtSnackbarQueueItem[] = [];\n private active: { item: KtSnackbarQueueItem; overlayRef: OverlayRef; cmp: ComponentRef<KtSnackbarContainer> } | null =\n null;\n private escapeRegistered = false;\n\n /**\n * Ouvre une snackbar affichant `message`. Les `options` priment sur `KT_SNACKBAR_CONFIG`, qui\n * prime sur les défauts. Renvoie une {@link KtSnackbarRef} (ignorable dans le cas simple).\n *\n * Une seule snackbar est visible : si une autre est affichée, celle-ci patiente en file (FIFO).\n * Un `message` identique à une snackbar déjà affichée ou en attente est **fusionné** : on renvoie\n * alors la référence existante sans rien ré-empiler.\n *\n * > [!IMPORTANT]\n * > Assurez-vous d'avoir importé `@angular/cdk/overlay-prebuilt.css` et `@angular/cdk/a11y-prebuilt.css` dans votre application hôte.\n *\n * @param message Texte affiché et annoncé au lecteur d'écran.\n * @param options Surcharges ponctuelles (durée, régime, position, politesse, variante, fermeture).\n * @returns La référence de la snackbar (existante en cas de fusion).\n */\n open(message: string, options?: KtSnackbarOptions): KtSnackbarRef {\n const resolved = this.resolve(options);\n\n // SSR : aucun overlay côté serveur — on renvoie une référence inerte déjà fermée.\n if (!isPlatformBrowser(this.platformId)) {\n const inert = new KtSnackbarRef(() => {\n /* SSR : aucun overlay à fermer. */\n });\n inert.dismiss('dismiss');\n return inert;\n }\n\n // Coalescing : message identique déjà affiché ou en file → on réutilise la référence existante.\n const existing = this.queue.find((entry) => entry.context.message === message);\n if (existing) return existing.ref;\n\n const context: KtSnackbarContext = {\n message,\n variant: resolved.variant,\n closable: resolved.closable,\n closeLabel: resolved.closeLabel,\n timing: resolved.timing,\n duration: this.computeDuration(message, resolved),\n };\n const item = { context, position: resolved.position, politeness: resolved.politeness } as KtSnackbarQueueItem;\n item.ref = new KtSnackbarRef(() => this.handleDismiss(item));\n\n this.queue.push(item);\n this.enforceMax(resolved.max);\n this.showHead();\n return item.ref;\n }\n\n ngOnDestroy(): void {\n this.unregisterEscape();\n this.active?.overlayRef.dispose();\n this.active = null;\n this.queue.length = 0;\n }\n\n /** Borne la file (affichée + en attente) : retire les plus ANCIENNES en attente au-delà de `max`. */\n private enforceMax(max: number): void {\n const limit = Math.max(1, max);\n while (this.queue.length > limit) {\n const oldestWaiting = this.queue.find((entry) => entry !== this.active?.item);\n if (!oldestWaiting) break;\n // Jamais affichée : la fermeture est routée via handleDismiss (qui la retire de la file).\n oldestWaiting.ref.dismiss('replaced');\n }\n }\n\n /** Affiche la tête de file si rien n'est actuellement visible. */\n private showHead(): void {\n if (this.active || this.queue.length === 0) return;\n const item = this.queue[0];\n\n const positionStrategy = this.overlay.position().global().centerHorizontally();\n if (item.position === 'top') positionStrategy.top('0');\n else positionStrategy.bottom('0');\n\n const overlayRef = this.overlay.create({\n positionStrategy,\n panelClass: ['kt-snackbar-pane', `kt-snackbar-pane--${item.position}`],\n });\n\n const injector = Injector.create({\n parent: this.injector,\n providers: [\n { provide: KtSnackbarRef, useValue: item.ref },\n { provide: KT_SNACKBAR_CONTEXT, useValue: item.context },\n ],\n });\n\n const cmp = overlayRef.attach(new ComponentPortal(KtSnackbarContainer, null, injector));\n\n // Canal d'annonce UNIQUE : le panneau visuel n'est pas une live region.\n void this.liveAnnouncer.announce(item.context.message, item.politeness);\n\n this.active = { item, overlayRef, cmp };\n this.registerEscape();\n }\n\n /** Retire l'élément de la file ; s'il est affiché, joue la sortie puis démonte et avance la file. */\n private handleDismiss(item: KtSnackbarQueueItem): void {\n const index = this.queue.indexOf(item);\n if (index === -1) return;\n\n if (this.active && this.active.item === item) {\n const { overlayRef, cmp } = this.active;\n this.active = null;\n this.queue.splice(index, 1);\n cmp.instance.playExit(() => {\n overlayRef.dispose();\n this.showHead();\n if (this.queue.length === 0) this.unregisterEscape();\n });\n return;\n }\n\n // En attente : aucun visuel à démonter.\n this.queue.splice(index, 1);\n }\n\n private readonly onDocumentKeydown = (event: KeyboardEvent): void => {\n // Échap ferme la plus récente (= la snackbar affichée).\n if (event.key === 'Escape') this.active?.item.ref.dismiss('dismiss');\n };\n\n private registerEscape(): void {\n if (this.escapeRegistered) return;\n this.doc.addEventListener('keydown', this.onDocumentKeydown);\n this.escapeRegistered = true;\n }\n\n private unregisterEscape(): void {\n if (!this.escapeRegistered) return;\n this.doc.removeEventListener('keydown', this.onDocumentKeydown);\n this.escapeRegistered = false;\n }\n\n /**\n * Durée effective (ms) en régime `'auto'`. Un nombre est pris tel quel (durée fixe) ; le sentinel\n * `'reading-time'` calcule `clamp(longueur × perChar, min, max)`.\n */\n private computeDuration(message: string, resolved: KtSnackbarConfig): number {\n const setting = resolved.duration;\n if (typeof setting === 'number') return setting;\n const computed = message.length * resolved.readingTimePerChar;\n return Math.min(resolved.readingTimeMax, Math.max(resolved.readingTimeMin, computed));\n }\n\n /** Résolution en cascade `option ?? KT_SNACKBAR_CONFIG ?? défaut`, champ par champ. */\n private resolve(options?: KtSnackbarOptions): KtSnackbarConfig {\n const config = this.config;\n return {\n duration: options?.duration ?? config?.duration ?? KT_SNACKBAR_DEFAULTS.duration,\n readingTimeMin: options?.readingTimeMin ?? config?.readingTimeMin ?? KT_SNACKBAR_DEFAULTS.readingTimeMin,\n readingTimeMax: options?.readingTimeMax ?? config?.readingTimeMax ?? KT_SNACKBAR_DEFAULTS.readingTimeMax,\n readingTimePerChar:\n options?.readingTimePerChar ?? config?.readingTimePerChar ?? KT_SNACKBAR_DEFAULTS.readingTimePerChar,\n timing: options?.timing ?? config?.timing ?? KT_SNACKBAR_DEFAULTS.timing,\n position: options?.position ?? config?.position ?? KT_SNACKBAR_DEFAULTS.position,\n politeness: options?.politeness ?? config?.politeness ?? KT_SNACKBAR_DEFAULTS.politeness,\n variant: options?.variant ?? config?.variant ?? KT_SNACKBAR_DEFAULTS.variant,\n closable: options?.closable ?? config?.closable ?? KT_SNACKBAR_DEFAULTS.closable,\n // `|| ...` (et non seulement `??`) : un closeLabel vide/blanc produirait un bouton de fermeture\n // SANS nom accessible (WCAG 4.1.2) ; on cascade vers le niveau suivant, défaut neutre en dernier.\n closeLabel: options?.closeLabel?.trim() || config?.closeLabel?.trim() || KT_SNACKBAR_DEFAULTS.closeLabel,\n max: options?.max ?? config?.max ?? KT_SNACKBAR_DEFAULTS.max,\n };\n }\n}\n","export * from './snackbar.service';\nexport * from './snackbar-ref';\nexport * from './snackbar-config';\n// `KtSnackbarContainer` / `KT_SNACKBAR_CONTEXT` / `KtSnackbarContext` sont des artefacts internes\n// (montés/fournis par `KtSnackbar` via `ComponentPortal`) : ils ne sont volontairement PAS exposés.\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { DOCUMENT, isPlatformBrowser } from '@angular/common';
2
2
  import * as i0 from '@angular/core';
3
- import { InjectionToken, inject, ElementRef, Renderer2, ViewContainerRef, NgZone, PLATFORM_ID, input, booleanAttribute, computed, signal, effect, TemplateRef, isDevMode, Directive } from '@angular/core';
3
+ import { InjectionToken, inject, ElementRef, Renderer2, ViewContainerRef, PLATFORM_ID, input, booleanAttribute, computed, signal, effect, TemplateRef, isDevMode, Directive } from '@angular/core';
4
4
  import { KtIdGenerator } from '@ktortu/aaa/cdk';
5
5
 
6
6
  const KT_TOOLTIP_CONFIG = new InjectionToken('KT_TOOLTIP_CONFIG');
@@ -33,7 +33,6 @@ class KtTooltip {
33
33
  host = inject(ElementRef);
34
34
  renderer = inject(Renderer2);
35
35
  vcr = inject(ViewContainerRef);
36
- ngZone = inject(NgZone);
37
36
  platformId = inject(PLATFORM_ID);
38
37
  /** Contenu de l'infobulle : texte simple (injecté en `textContent`) ou `TemplateRef` non interactif. */
39
38
  ktTooltip = input.required(/* @ts-ignore */
@@ -67,7 +66,8 @@ class KtTooltip {
67
66
  }, /* @ts-ignore */
68
67
  ...(ngDevMode ? [{ debugName: "isActive" }] : /* istanbul ignore next */ []));
69
68
  // Retourner null retire l'attribut (même astuce que aria-disabled dans button).
70
- // Corrigé : aria-describedby n'est présent sur le déclencheur que si le tooltip est affiché.
69
+ // aria-describedby n'est posé sur le déclencheur que lorsque le tooltip est affiché : sinon il
70
+ // référencerait un nœud absent du DOM (création lazy), donnant une référence pendante aux AT.
71
71
  describedById = computed(() => (this.isActive() && this.isShown() ? this.tooltipId : null), /* @ts-ignore */
72
72
  ...(ngDevMode ? [{ debugName: "describedById" }] : /* istanbul ignore next */ []));
73
73
  tip = null;
@@ -126,27 +126,19 @@ class KtTooltip {
126
126
  show() {
127
127
  if (!this.isActive())
128
128
  return;
129
- this.ngZone.runOutsideAngular(() => {
130
- clearTimeout(this.hideTimer);
131
- this.showTimer = setTimeout(() => {
132
- this.ngZone.run(() => {
133
- if (this.isShown())
134
- return;
135
- this.isShown.set(true);
136
- if (!this.supportsAnchor) {
137
- this.registerFallbackListeners();
138
- }
139
- });
140
- }, this.showDelay());
141
- });
129
+ clearTimeout(this.hideTimer);
130
+ this.showTimer = setTimeout(() => {
131
+ if (this.isShown())
132
+ return;
133
+ this.isShown.set(true);
134
+ if (!this.supportsAnchor) {
135
+ this.registerFallbackListeners();
136
+ }
137
+ }, this.showDelay());
142
138
  }
143
139
  hide() {
144
- this.ngZone.runOutsideAngular(() => {
145
- clearTimeout(this.showTimer);
146
- this.hideTimer = setTimeout(() => {
147
- this.ngZone.run(() => this.dismiss());
148
- }, this.hideDelay());
149
- });
140
+ clearTimeout(this.showTimer);
141
+ this.hideTimer = setTimeout(() => this.dismiss(), this.hideDelay());
150
142
  }
151
143
  onEscape(event) {
152
144
  if (!this.isShown())
@@ -317,14 +309,12 @@ class KtTooltip {
317
309
  this.clearFallbackListeners();
318
310
  if (this.supportsAnchor || !isPlatformBrowser(this.platformId))
319
311
  return;
320
- this.ngZone.runOutsideAngular(() => {
321
- const onScrollOrResize = () => {
322
- this.positionFallback();
323
- };
324
- window.addEventListener('scroll', onScrollOrResize, { passive: true, capture: true });
325
- window.addEventListener('resize', onScrollOrResize);
326
- this.fallbackListeners.push(() => window.removeEventListener('scroll', onScrollOrResize, { capture: true }), () => window.removeEventListener('resize', onScrollOrResize));
327
- });
312
+ const onScrollOrResize = () => {
313
+ this.positionFallback();
314
+ };
315
+ window.addEventListener('scroll', onScrollOrResize, { passive: true, capture: true });
316
+ window.addEventListener('resize', onScrollOrResize);
317
+ this.fallbackListeners.push(() => window.removeEventListener('scroll', onScrollOrResize, { capture: true }), () => window.removeEventListener('resize', onScrollOrResize));
328
318
  }
329
319
  clearFallbackListeners() {
330
320
  for (const remove of this.fallbackListeners)
@@ -1 +1 @@
1
- {"version":3,"file":"ktortu-aaa-tooltip.mjs","sources":["../../../../projects/ktortu/aaa/tooltip/tooltip.ts","../../../../projects/ktortu/aaa/tooltip/ktortu-aaa-tooltip.ts"],"sourcesContent":["import { DOCUMENT, isPlatformBrowser } from '@angular/common';\nimport {\n Directive,\n ElementRef,\n EmbeddedViewRef,\n InjectionToken,\n NgZone,\n OnDestroy,\n Provider,\n Renderer2,\n TemplateRef,\n ViewContainerRef,\n booleanAttribute,\n computed,\n effect,\n inject,\n input,\n isDevMode,\n signal,\n PLATFORM_ID,\n} from '@angular/core';\nimport { KtIdGenerator } from '@ktortu/aaa/cdk';\n\nexport type KtTooltipPosition = 'top' | 'bottom' | 'left' | 'right';\n\n/** Défauts d'infobulle (délais, position) injectables via `provideKtTooltip` / `KT_TOOLTIP_CONFIG`. */\nexport interface KtTooltipConfig {\n /** Délai (ms) avant apparition au survol/focus. */\n showDelay: number;\n /** Délai (ms) avant masquage (laisse le temps d'atteindre l'infobulle, WCAG « hoverable »). */\n hideDelay: number;\n /** Position de l'infobulle autour de la cible. */\n position: KtTooltipPosition;\n}\n\nexport const KT_TOOLTIP_CONFIG = new InjectionToken<Partial<KtTooltipConfig>>('KT_TOOLTIP_CONFIG');\n\n/**\n * Fournit des défauts d'infobulle (délais, position) pour un sous-arbre ou l'application entière.\n *\n * @example\n * ```ts\n * providers: [provideKtTooltip({ showDelay: 300, position: 'bottom' })]\n * ```\n */\nexport function provideKtTooltip(config: Partial<KtTooltipConfig>): Provider {\n return { provide: KT_TOOLTIP_CONFIG, useValue: config };\n}\n\n/**\n * Infobulle accessible posée sur n'importe quel élément focusable/survolable.\n * Apparaît au survol et au focus, reste « hoverable » (WCAG 1.4.13) et se ferme\n * par Échap. Le contenu peut être un texte simple ou un `TemplateRef` **non interactif**\n * (un `role=\"tooltip\"` ne doit pas contenir de lien/bouton/champ).\n *\n * @example\n * ```html\n * <button ktTooltip=\"Enregistrer le brouillon\">Enregistrer</button>\n * <span ktTooltip=\"Aide\" tooltipPosition=\"right\" [showDelay]=\"300\">?</span>\n * ```\n */\n@Directive({\n selector: '[ktTooltip]',\n host: {\n '[attr.aria-describedby]': 'describedById()',\n '(mouseenter)': 'show()',\n '(mouseleave)': 'hide()',\n '(focusin)': 'show()',\n '(focusout)': 'hide()',\n '(keydown.escape)': 'onEscape($event)',\n },\n})\nexport class KtTooltip implements OnDestroy {\n private readonly config = inject(KT_TOOLTIP_CONFIG, { optional: true });\n private readonly doc = inject(DOCUMENT);\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly renderer = inject(Renderer2);\n private readonly vcr = inject(ViewContainerRef);\n private readonly ngZone = inject(NgZone);\n private readonly platformId = inject(PLATFORM_ID);\n\n /** Contenu de l'infobulle : texte simple (injecté en `textContent`) ou `TemplateRef` non interactif. */\n readonly ktTooltip = input.required<string | TemplateRef<unknown>>();\n /** Position de l'infobulle autour de la cible. @default 'top' (ou KT_TOOLTIP_CONFIG.position) */\n readonly tooltipPosition = input<KtTooltipPosition>(this.config?.position ?? 'top');\n /** Désactive l'affichage de l'infobulle. @default false */\n readonly tooltipDisabled = input<boolean, unknown>(false, { transform: booleanAttribute });\n /** Délai (ms) avant apparition au survol/focus. @default 150 (ou KT_TOOLTIP_CONFIG.showDelay) */\n readonly showDelay = input<number>(this.config?.showDelay ?? 150);\n /** Délai (ms) avant masquage ; laisse le temps d'amener le pointeur sur l'infobulle (WCAG « hoverable »). @default 100 (ou KT_TOOLTIP_CONFIG.hideDelay) */\n readonly hideDelay = input<number>(this.config?.hideDelay ?? 100);\n\n private readonly idGen = inject(KtIdGenerator);\n private readonly uid = this.idGen.generateId('tooltip');\n private readonly tooltipId = `kt-tooltip-${this.uid}`;\n /** Id du noeud `role=\"tooltip\"`. Public : sert aux liaisons d'accessibilité (`aria-describedby`) du déclencheur. */\n readonly idForA11y = this.tooltipId;\n private readonly anchorName = `--kt-tooltip-anchor-${this.uid}`;\n\n /** Vrai quand l'infobulle est susceptible de s'afficher (contenu non vide et non désactivée).\n Public : lu par `KtField` pour câbler `aria-describedby` du contrôle sur l'infobulle d'aide. */\n readonly isActive = computed(() => {\n if (this.tooltipDisabled()) return false;\n\n const content = this.ktTooltip();\n if (typeof content === 'string') return content.trim().length > 0;\n return true;\n });\n\n // Retourner null retire l'attribut (même astuce que aria-disabled dans button).\n // Corrigé : aria-describedby n'est présent sur le déclencheur que si le tooltip est affiché.\n protected describedById = computed(() => (this.isActive() && this.isShown() ? this.tooltipId : null));\n\n private tip: HTMLElement | null = null;\n private view: EmbeddedViewRef<unknown> | null = null;\n private listeners: (() => void)[] = [];\n private showTimer: ReturnType<typeof setTimeout> | undefined;\n private hideTimer: ReturnType<typeof setTimeout> | undefined;\n private readonly isShown = signal(false);\n private _supportsAnchor: boolean | null = null;\n private get supportsAnchor(): boolean {\n if (this._supportsAnchor === null) {\n this._supportsAnchor =\n isPlatformBrowser(this.platformId) &&\n typeof CSS !== 'undefined' &&\n typeof CSS.supports === 'function' &&\n CSS.supports('anchor-name: --x');\n }\n return this._supportsAnchor;\n }\n private fallbackListeners: (() => void)[] = [];\n private activeTemplate: TemplateRef<unknown> | null = null;\n private escListener: (() => void) | null = null;\n\n constructor() {\n // Ancre le déclencheur. setProperty (et non Renderer2.setStyle) car les propriétés\n // CSS à tiret ne sont appliquées qu'ainsi de façon fiable.\n if (isPlatformBrowser(this.platformId)) {\n this.host.nativeElement.style.setProperty('anchor-name', this.anchorName);\n }\n\n // Gestion réactive du cycle de vie du DOM du Tooltip\n effect(() => {\n if (!isPlatformBrowser(this.platformId)) return;\n\n // Création lazy : uniquement si actif ET affiché\n if (!this.isActive() || !this.isShown()) {\n this.destroyTip();\n return;\n }\n\n const tip = this.ensureTip();\n this.registerEscapeListener();\n this.syncContent();\n\n try {\n tip.showPopover?.();\n } catch {\n // Ignorer si déjà ouvert ou non supporté\n }\n\n if (!this.supportsAnchor) {\n this.positionFallback();\n }\n });\n }\n\n ngOnDestroy(): void {\n this.destroyTip();\n }\n\n protected show(): void {\n if (!this.isActive()) return;\n\n this.ngZone.runOutsideAngular(() => {\n clearTimeout(this.hideTimer);\n this.showTimer = setTimeout(() => {\n this.ngZone.run(() => {\n if (this.isShown()) return;\n\n this.isShown.set(true);\n\n if (!this.supportsAnchor) {\n this.registerFallbackListeners();\n }\n });\n }, this.showDelay());\n });\n }\n\n protected hide(): void {\n this.ngZone.runOutsideAngular(() => {\n clearTimeout(this.showTimer);\n this.hideTimer = setTimeout(() => {\n this.ngZone.run(() => this.dismiss());\n }, this.hideDelay());\n });\n }\n\n protected onEscape(event: Event): void {\n if (!this.isShown()) return;\n\n // Dismiss sans déplacer le pointeur (WCAG 1.4.13) ; on n'annule pas l'action native.\n this.dismiss();\n event.stopPropagation();\n }\n\n private dismiss(): void {\n if (!this.isShown()) return;\n\n this.isShown.set(false);\n }\n\n private ensureTip(): HTMLElement {\n if (this.tip) return this.tip;\n\n const tip = this.renderer.createElement('div') as HTMLElement;\n this.renderer.setAttribute(tip, 'role', 'tooltip');\n this.renderer.setAttribute(tip, 'id', this.tooltipId);\n // manual : on gère nous-mêmes Échap et la fermeture au survol/blur.\n this.renderer.setAttribute(tip, 'popover', 'manual');\n this.renderer.addClass(tip, 'kt-tooltip');\n // setProperty natif : indispensable pour une propriété CSS à tiret.\n tip.style.setProperty('position-anchor', this.anchorName);\n // Top-layer : ajouté au body, immunisé contre overflow/z-index.\n this.renderer.appendChild(this.doc.body, tip);\n\n // Hoverable : passer le pointeur du trigger au tooltip ne le ferme pas.\n this.listeners.push(\n this.renderer.listen(tip, 'mouseenter', () => clearTimeout(this.hideTimer)),\n this.renderer.listen(tip, 'mouseleave', () => this.hide()),\n );\n\n this.tip = tip;\n return tip;\n }\n\n private registerEscapeListener(): void {\n if (this.escListener) return;\n this.escListener = this.renderer.listen('document', 'keydown.escape', (event: KeyboardEvent) => {\n if (this.isShown()) {\n this.dismiss();\n event.stopPropagation();\n }\n });\n }\n\n private syncContent(): void {\n if (!this.tip) return;\n\n this.renderer.setAttribute(this.tip, 'data-position', this.tooltipPosition());\n\n const content = this.ktTooltip();\n\n if (content instanceof TemplateRef) {\n if (this.activeTemplate === content) return;\n this.clearContent();\n this.activeTemplate = content;\n\n this.view = this.vcr.createEmbeddedView(content);\n this.view.detectChanges();\n for (const node of this.view.rootNodes) {\n this.renderer.appendChild(this.tip, node);\n }\n if (isDevMode()) {\n this.warnIfInteractive();\n }\n return;\n }\n\n this.clearContent();\n this.renderer.setProperty(this.tip, 'textContent', content);\n }\n\n private clearContent(): void {\n if (this.view) {\n this.view.destroy();\n this.view = null;\n }\n this.activeTemplate = null;\n if (this.tip) {\n this.renderer.setProperty(this.tip, 'textContent', '');\n }\n }\n\n // Garde-fou a11y : un role=\"tooltip\" ne doit pas contenir d'éléments focusables.\n private warnIfInteractive(): void {\n if (!this.tip) return;\n\n const interactive = this.tip.querySelector('a[href], button, input, select, textarea, [tabindex]');\n if (!interactive) return;\n\n console.warn(\n `[ktTooltip] Un role=\"tooltip\" ne doit pas contenir d'éléments interactifs ` +\n `(<${interactive.nodeName.toLowerCase()}>). Utilisez plutôt un toggletip ou un <dialog>.`,\n );\n }\n\n private destroyTip(): void {\n clearTimeout(this.showTimer);\n clearTimeout(this.hideTimer);\n\n for (const unlisten of this.listeners) unlisten();\n this.listeners = [];\n this.clearFallbackListeners();\n\n if (this.escListener) {\n this.escListener();\n this.escListener = null;\n }\n\n this.view?.destroy();\n this.view = null;\n this.activeTemplate = null;\n\n if (this.tip) {\n try {\n this.tip.hidePopover?.();\n } catch {\n // Ignorer si déjà fermé ou non supporté\n }\n this.tip.remove();\n this.tip = null;\n }\n\n if (this.isShown()) {\n this.isShown.set(false);\n }\n }\n\n private positionFallback(): void {\n if (!this.tip) return;\n const triggerEl = this.host.nativeElement;\n const triggerRect = triggerEl.getBoundingClientRect();\n const tooltipRect = this.tip.getBoundingClientRect();\n const position = this.tooltipPosition();\n const gap = 8;\n\n let top = 0;\n let left = 0;\n\n if (position === 'top') {\n top = triggerRect.top - tooltipRect.height - gap;\n left = triggerRect.left + (triggerRect.width - tooltipRect.width) / 2;\n } else if (position === 'bottom') {\n top = triggerRect.bottom + gap;\n left = triggerRect.left + (triggerRect.width - tooltipRect.width) / 2;\n } else if (position === 'left') {\n top = triggerRect.top + (triggerRect.height - tooltipRect.height) / 2;\n left = triggerRect.left - tooltipRect.width - gap;\n } else if (position === 'right') {\n top = triggerRect.top + (triggerRect.height - tooltipRect.height) / 2;\n left = triggerRect.right + gap;\n }\n\n const viewWidth = window.innerWidth;\n const viewHeight = window.innerHeight;\n\n if (left < 4) left = 4;\n if (left + tooltipRect.width > viewWidth - 4) {\n left = viewWidth - tooltipRect.width - 4;\n }\n if (top < 4) {\n if (position === 'top') {\n top = triggerRect.bottom + gap;\n } else {\n top = 4;\n }\n }\n if (top + tooltipRect.height > viewHeight - 4) {\n if (position === 'bottom') {\n top = triggerRect.top - tooltipRect.height - gap;\n } else {\n top = viewHeight - tooltipRect.height - 4;\n }\n }\n\n this.tip.style.position = 'fixed';\n this.tip.style.top = `${top}px`;\n this.tip.style.left = `${left}px`;\n this.tip.style.margin = '0';\n }\n\n private registerFallbackListeners(): void {\n this.clearFallbackListeners();\n if (this.supportsAnchor || !isPlatformBrowser(this.platformId)) return;\n\n this.ngZone.runOutsideAngular(() => {\n const onScrollOrResize = () => {\n this.positionFallback();\n };\n window.addEventListener('scroll', onScrollOrResize, { passive: true, capture: true });\n window.addEventListener('resize', onScrollOrResize);\n\n this.fallbackListeners.push(\n () => window.removeEventListener('scroll', onScrollOrResize, { capture: true }),\n () => window.removeEventListener('resize', onScrollOrResize),\n );\n });\n }\n\n private clearFallbackListeners(): void {\n for (const remove of this.fallbackListeners) remove();\n this.fallbackListeners = [];\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ktortu-aaa-tooltip.mjs","sources":["../../../../projects/ktortu/aaa/tooltip/tooltip.ts","../../../../projects/ktortu/aaa/tooltip/ktortu-aaa-tooltip.ts"],"sourcesContent":["import { DOCUMENT, isPlatformBrowser } from '@angular/common';\nimport {\n Directive,\n ElementRef,\n EmbeddedViewRef,\n InjectionToken,\n OnDestroy,\n Provider,\n Renderer2,\n TemplateRef,\n ViewContainerRef,\n booleanAttribute,\n computed,\n effect,\n inject,\n input,\n isDevMode,\n signal,\n PLATFORM_ID,\n} from '@angular/core';\nimport { KtIdGenerator } from '@ktortu/aaa/cdk';\n\nexport type KtTooltipPosition = 'top' | 'bottom' | 'left' | 'right';\n\n/** Défauts d'infobulle (délais, position) injectables via `provideKtTooltip` / `KT_TOOLTIP_CONFIG`. */\nexport interface KtTooltipConfig {\n /** Délai (ms) avant apparition au survol/focus. */\n showDelay: number;\n /** Délai (ms) avant masquage (laisse le temps d'atteindre l'infobulle, WCAG « hoverable »). */\n hideDelay: number;\n /** Position de l'infobulle autour de la cible. */\n position: KtTooltipPosition;\n}\n\nexport const KT_TOOLTIP_CONFIG = new InjectionToken<Partial<KtTooltipConfig>>('KT_TOOLTIP_CONFIG');\n\n/**\n * Fournit des défauts d'infobulle (délais, position) pour un sous-arbre ou l'application entière.\n *\n * @example\n * ```ts\n * providers: [provideKtTooltip({ showDelay: 300, position: 'bottom' })]\n * ```\n */\nexport function provideKtTooltip(config: Partial<KtTooltipConfig>): Provider {\n return { provide: KT_TOOLTIP_CONFIG, useValue: config };\n}\n\n/**\n * Infobulle accessible posée sur n'importe quel élément focusable/survolable.\n * Apparaît au survol et au focus, reste « hoverable » (WCAG 1.4.13) et se ferme\n * par Échap. Le contenu peut être un texte simple ou un `TemplateRef` **non interactif**\n * (un `role=\"tooltip\"` ne doit pas contenir de lien/bouton/champ).\n *\n * @example\n * ```html\n * <button ktTooltip=\"Enregistrer le brouillon\">Enregistrer</button>\n * <span ktTooltip=\"Aide\" tooltipPosition=\"right\" [showDelay]=\"300\">?</span>\n * ```\n */\n@Directive({\n selector: '[ktTooltip]',\n host: {\n '[attr.aria-describedby]': 'describedById()',\n '(mouseenter)': 'show()',\n '(mouseleave)': 'hide()',\n '(focusin)': 'show()',\n '(focusout)': 'hide()',\n '(keydown.escape)': 'onEscape($event)',\n },\n})\nexport class KtTooltip implements OnDestroy {\n private readonly config = inject(KT_TOOLTIP_CONFIG, { optional: true });\n private readonly doc = inject(DOCUMENT);\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly renderer = inject(Renderer2);\n private readonly vcr = inject(ViewContainerRef);\n private readonly platformId = inject(PLATFORM_ID);\n\n /** Contenu de l'infobulle : texte simple (injecté en `textContent`) ou `TemplateRef` non interactif. */\n readonly ktTooltip = input.required<string | TemplateRef<unknown>>();\n /** Position de l'infobulle autour de la cible. @default 'top' (ou KT_TOOLTIP_CONFIG.position) */\n readonly tooltipPosition = input<KtTooltipPosition>(this.config?.position ?? 'top');\n /** Désactive l'affichage de l'infobulle. @default false */\n readonly tooltipDisabled = input<boolean, unknown>(false, { transform: booleanAttribute });\n /** Délai (ms) avant apparition au survol/focus. @default 150 (ou KT_TOOLTIP_CONFIG.showDelay) */\n readonly showDelay = input<number>(this.config?.showDelay ?? 150);\n /** Délai (ms) avant masquage ; laisse le temps d'amener le pointeur sur l'infobulle (WCAG « hoverable »). @default 100 (ou KT_TOOLTIP_CONFIG.hideDelay) */\n readonly hideDelay = input<number>(this.config?.hideDelay ?? 100);\n\n private readonly idGen = inject(KtIdGenerator);\n private readonly uid = this.idGen.generateId('tooltip');\n private readonly tooltipId = `kt-tooltip-${this.uid}`;\n /** Id du noeud `role=\"tooltip\"`. Public : sert aux liaisons d'accessibilité (`aria-describedby`) du déclencheur. */\n readonly idForA11y = this.tooltipId;\n private readonly anchorName = `--kt-tooltip-anchor-${this.uid}`;\n\n /** Vrai quand l'infobulle est susceptible de s'afficher (contenu non vide et non désactivée).\n Public : lu par `KtField` pour câbler `aria-describedby` du contrôle sur l'infobulle d'aide. */\n readonly isActive = computed(() => {\n if (this.tooltipDisabled()) return false;\n\n const content = this.ktTooltip();\n if (typeof content === 'string') return content.trim().length > 0;\n return true;\n });\n\n // Retourner null retire l'attribut (même astuce que aria-disabled dans button).\n // aria-describedby n'est posé sur le déclencheur que lorsque le tooltip est affiché : sinon il\n // référencerait un nœud absent du DOM (création lazy), donnant une référence pendante aux AT.\n protected describedById = computed(() => (this.isActive() && this.isShown() ? this.tooltipId : null));\n\n private tip: HTMLElement | null = null;\n private view: EmbeddedViewRef<unknown> | null = null;\n private listeners: (() => void)[] = [];\n private showTimer: ReturnType<typeof setTimeout> | undefined;\n private hideTimer: ReturnType<typeof setTimeout> | undefined;\n private readonly isShown = signal(false);\n private _supportsAnchor: boolean | null = null;\n private get supportsAnchor(): boolean {\n if (this._supportsAnchor === null) {\n this._supportsAnchor =\n isPlatformBrowser(this.platformId) &&\n typeof CSS !== 'undefined' &&\n typeof CSS.supports === 'function' &&\n CSS.supports('anchor-name: --x');\n }\n return this._supportsAnchor;\n }\n private fallbackListeners: (() => void)[] = [];\n private activeTemplate: TemplateRef<unknown> | null = null;\n private escListener: (() => void) | null = null;\n\n constructor() {\n // Ancre le déclencheur. setProperty (et non Renderer2.setStyle) car les propriétés\n // CSS à tiret ne sont appliquées qu'ainsi de façon fiable.\n if (isPlatformBrowser(this.platformId)) {\n this.host.nativeElement.style.setProperty('anchor-name', this.anchorName);\n }\n\n // Gestion réactive du cycle de vie du DOM du Tooltip\n effect(() => {\n if (!isPlatformBrowser(this.platformId)) return;\n\n // Création lazy : uniquement si actif ET affiché\n if (!this.isActive() || !this.isShown()) {\n this.destroyTip();\n return;\n }\n\n const tip = this.ensureTip();\n this.registerEscapeListener();\n this.syncContent();\n\n try {\n tip.showPopover?.();\n } catch {\n // Ignorer si déjà ouvert ou non supporté\n }\n\n if (!this.supportsAnchor) {\n this.positionFallback();\n }\n });\n }\n\n ngOnDestroy(): void {\n this.destroyTip();\n }\n\n protected show(): void {\n if (!this.isActive()) return;\n\n clearTimeout(this.hideTimer);\n this.showTimer = setTimeout(() => {\n if (this.isShown()) return;\n\n this.isShown.set(true);\n\n if (!this.supportsAnchor) {\n this.registerFallbackListeners();\n }\n }, this.showDelay());\n }\n\n protected hide(): void {\n clearTimeout(this.showTimer);\n this.hideTimer = setTimeout(() => this.dismiss(), this.hideDelay());\n }\n\n protected onEscape(event: Event): void {\n if (!this.isShown()) return;\n\n // Dismiss sans déplacer le pointeur (WCAG 1.4.13) ; on n'annule pas l'action native.\n this.dismiss();\n event.stopPropagation();\n }\n\n private dismiss(): void {\n if (!this.isShown()) return;\n\n this.isShown.set(false);\n }\n\n private ensureTip(): HTMLElement {\n if (this.tip) return this.tip;\n\n const tip = this.renderer.createElement('div') as HTMLElement;\n this.renderer.setAttribute(tip, 'role', 'tooltip');\n this.renderer.setAttribute(tip, 'id', this.tooltipId);\n // manual : on gère nous-mêmes Échap et la fermeture au survol/blur.\n this.renderer.setAttribute(tip, 'popover', 'manual');\n this.renderer.addClass(tip, 'kt-tooltip');\n // setProperty natif : indispensable pour une propriété CSS à tiret.\n tip.style.setProperty('position-anchor', this.anchorName);\n // Top-layer : ajouté au body, immunisé contre overflow/z-index.\n this.renderer.appendChild(this.doc.body, tip);\n\n // Hoverable : passer le pointeur du trigger au tooltip ne le ferme pas.\n this.listeners.push(\n this.renderer.listen(tip, 'mouseenter', () => clearTimeout(this.hideTimer)),\n this.renderer.listen(tip, 'mouseleave', () => this.hide()),\n );\n\n this.tip = tip;\n return tip;\n }\n\n private registerEscapeListener(): void {\n if (this.escListener) return;\n this.escListener = this.renderer.listen('document', 'keydown.escape', (event: KeyboardEvent) => {\n if (this.isShown()) {\n this.dismiss();\n event.stopPropagation();\n }\n });\n }\n\n private syncContent(): void {\n if (!this.tip) return;\n\n this.renderer.setAttribute(this.tip, 'data-position', this.tooltipPosition());\n\n const content = this.ktTooltip();\n\n if (content instanceof TemplateRef) {\n if (this.activeTemplate === content) return;\n this.clearContent();\n this.activeTemplate = content;\n\n this.view = this.vcr.createEmbeddedView(content);\n this.view.detectChanges();\n for (const node of this.view.rootNodes) {\n this.renderer.appendChild(this.tip, node);\n }\n if (isDevMode()) {\n this.warnIfInteractive();\n }\n return;\n }\n\n this.clearContent();\n this.renderer.setProperty(this.tip, 'textContent', content);\n }\n\n private clearContent(): void {\n if (this.view) {\n this.view.destroy();\n this.view = null;\n }\n this.activeTemplate = null;\n if (this.tip) {\n this.renderer.setProperty(this.tip, 'textContent', '');\n }\n }\n\n // Garde-fou a11y : un role=\"tooltip\" ne doit pas contenir d'éléments focusables.\n private warnIfInteractive(): void {\n if (!this.tip) return;\n\n const interactive = this.tip.querySelector('a[href], button, input, select, textarea, [tabindex]');\n if (!interactive) return;\n\n console.warn(\n `[ktTooltip] Un role=\"tooltip\" ne doit pas contenir d'éléments interactifs ` +\n `(<${interactive.nodeName.toLowerCase()}>). Utilisez plutôt un toggletip ou un <dialog>.`,\n );\n }\n\n private destroyTip(): void {\n clearTimeout(this.showTimer);\n clearTimeout(this.hideTimer);\n\n for (const unlisten of this.listeners) unlisten();\n this.listeners = [];\n this.clearFallbackListeners();\n\n if (this.escListener) {\n this.escListener();\n this.escListener = null;\n }\n\n this.view?.destroy();\n this.view = null;\n this.activeTemplate = null;\n\n if (this.tip) {\n try {\n this.tip.hidePopover?.();\n } catch {\n // Ignorer si déjà fermé ou non supporté\n }\n this.tip.remove();\n this.tip = null;\n }\n\n if (this.isShown()) {\n this.isShown.set(false);\n }\n }\n\n private positionFallback(): void {\n if (!this.tip) return;\n const triggerEl = this.host.nativeElement;\n const triggerRect = triggerEl.getBoundingClientRect();\n const tooltipRect = this.tip.getBoundingClientRect();\n const position = this.tooltipPosition();\n const gap = 8;\n\n let top = 0;\n let left = 0;\n\n if (position === 'top') {\n top = triggerRect.top - tooltipRect.height - gap;\n left = triggerRect.left + (triggerRect.width - tooltipRect.width) / 2;\n } else if (position === 'bottom') {\n top = triggerRect.bottom + gap;\n left = triggerRect.left + (triggerRect.width - tooltipRect.width) / 2;\n } else if (position === 'left') {\n top = triggerRect.top + (triggerRect.height - tooltipRect.height) / 2;\n left = triggerRect.left - tooltipRect.width - gap;\n } else if (position === 'right') {\n top = triggerRect.top + (triggerRect.height - tooltipRect.height) / 2;\n left = triggerRect.right + gap;\n }\n\n const viewWidth = window.innerWidth;\n const viewHeight = window.innerHeight;\n\n if (left < 4) left = 4;\n if (left + tooltipRect.width > viewWidth - 4) {\n left = viewWidth - tooltipRect.width - 4;\n }\n if (top < 4) {\n if (position === 'top') {\n top = triggerRect.bottom + gap;\n } else {\n top = 4;\n }\n }\n if (top + tooltipRect.height > viewHeight - 4) {\n if (position === 'bottom') {\n top = triggerRect.top - tooltipRect.height - gap;\n } else {\n top = viewHeight - tooltipRect.height - 4;\n }\n }\n\n this.tip.style.position = 'fixed';\n this.tip.style.top = `${top}px`;\n this.tip.style.left = `${left}px`;\n this.tip.style.margin = '0';\n }\n\n private registerFallbackListeners(): void {\n this.clearFallbackListeners();\n if (this.supportsAnchor || !isPlatformBrowser(this.platformId)) return;\n\n const onScrollOrResize = () => {\n this.positionFallback();\n };\n window.addEventListener('scroll', onScrollOrResize, { passive: true, capture: true });\n window.addEventListener('resize', onScrollOrResize);\n\n this.fallbackListeners.push(\n () => window.removeEventListener('scroll', onScrollOrResize, { capture: true }),\n () => window.removeEventListener('resize', onScrollOrResize),\n );\n }\n\n private clearFallbackListeners(): void {\n for (const remove of this.fallbackListeners) remove();\n this.fallbackListeners = [];\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -8,6 +8,7 @@ export * from '@ktortu/aaa/menu';
8
8
  export * from '@ktortu/aaa/snackbar';
9
9
  export * from '@ktortu/aaa/tabs';
10
10
  export * from '@ktortu/aaa/tooltip';
11
+ export * from '@ktortu/aaa/progress-bar';
11
12
 
12
13
  /*
13
14
  * Public API Surface of @ktortu/aaa
@@ -1 +1 @@
1
- {"version":3,"file":"ktortu-aaa.mjs","sources":["../../../../projects/ktortu/aaa/src/public-api.ts","../../../../projects/ktortu/aaa/src/ktortu-aaa.ts"],"sourcesContent":["/*\n * Public API Surface of @ktortu/aaa\n */\nexport * from '@ktortu/aaa/button';\nexport * from '@ktortu/aaa/card';\nexport * from '@ktortu/aaa/cdk';\nexport * from '@ktortu/aaa/dialog';\nexport * from '@ktortu/aaa/forms';\nexport * from '@ktortu/aaa/i18n';\nexport * from '@ktortu/aaa/menu';\nexport * from '@ktortu/aaa/snackbar';\nexport * from '@ktortu/aaa/tabs';\nexport * from '@ktortu/aaa/tooltip';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;;;;;;;;AAAA;;AAEG;;ACFH;;AAEG"}
1
+ {"version":3,"file":"ktortu-aaa.mjs","sources":["../../../../projects/ktortu/aaa/src/public-api.ts","../../../../projects/ktortu/aaa/src/ktortu-aaa.ts"],"sourcesContent":["/*\n * Public API Surface of @ktortu/aaa\n */\nexport * from '@ktortu/aaa/button';\nexport * from '@ktortu/aaa/card';\nexport * from '@ktortu/aaa/cdk';\nexport * from '@ktortu/aaa/dialog';\nexport * from '@ktortu/aaa/forms';\nexport * from '@ktortu/aaa/i18n';\nexport * from '@ktortu/aaa/menu';\nexport * from '@ktortu/aaa/snackbar';\nexport * from '@ktortu/aaa/tabs';\nexport * from '@ktortu/aaa/tooltip';\nexport * from '@ktortu/aaa/progress-bar';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;;;;;;;;;AAAA;;AAEG;;ACFH;;AAEG"}
@@ -71,6 +71,22 @@
71
71
  color: var(--field-error-color, #8c1d18);
72
72
  }
73
73
 
74
+ /* Copie visually-hidden du texte d'aide : présente en permanence dans l'arbre d'accessibilité
75
+ (technique clip), contrairement à la bulle du tooltip créée à la volée → aria-describedby du
76
+ contrôle résout toujours sa cible (pas de référence pendante pour les lecteurs d'écran). */
77
+ .kt-field__help-description {
78
+ position: absolute;
79
+ inset-block-start: 0;
80
+ inset-inline-start: 0;
81
+ inline-size: 1px;
82
+ block-size: 1px;
83
+ padding: 0;
84
+ margin: -1px;
85
+ overflow: hidden;
86
+ clip-path: inset(50%);
87
+ white-space: nowrap;
88
+ }
89
+
74
90
  /* Apparition d'un message d'erreur : token de BASCULE (non déclaré => aucune animation).
75
91
  Sur le MESSAGE (inséré à l'invalidation) — PAS sur le conteneur, qui vit en permanence
76
92
  (région live). Keyframes de thème : transform/opacity/filter seulement (les spans sont