@ktortu/aaa 0.9.7 → 0.9.9

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.
@@ -547,9 +547,19 @@ declare class KtPasswordField extends KtBaseInputField<string> implements FormVa
547
547
  * Permet d'activer ou désactiver une option avec effet immédiat.
548
548
  * Intégré aux Signal Forms de l'application via FormValueControl.
549
549
  *
550
+ * Libellé : `label` (texte) par défaut ; un contenu projeté le remplace pour les rendus riches
551
+ * (image + texte, spans empilés…). `ariaLabel` porte alors le nom accessible si le contenu projeté
552
+ * n'a pas de texte (WCAG 4.1.2). Même règle que `kt-checkbox` / `kt-radio`.
553
+ *
550
554
  * @example
551
555
  * ```html
556
+ * <!-- Simple -->
552
557
  * <kt-switch label="Notifications par e-mail" [(value)]="emailNotif" />
558
+ *
559
+ * <!-- Contenu projeté (image + texte) -->
560
+ * <kt-switch [(value)]="emailNotif">
561
+ * <img ngSrc="/assets/mail.png" width="20" height="20" alt="" /> Notifications par e-mail
562
+ * </kt-switch>
553
563
  * ```
554
564
  */
555
565
  declare class KtSwitch implements FormValueControl<boolean> {
@@ -574,7 +584,7 @@ declare class KtSwitch implements FormValueControl<boolean> {
574
584
  readonly name: _angular_core.InputSignal<string>;
575
585
  /** id imposé (sélecteurs de test stables) ; sinon auto-généré, anti-collision. @default undefined */
576
586
  readonly id: _angular_core.InputSignal<string | undefined>;
577
- /** Texte du libellé associé à la bascule. @default undefined */
587
+ /** Texte du libellé (remplacé visuellement par un contenu projeté). @default undefined */
578
588
  readonly label: _angular_core.InputSignal<string | undefined>;
579
589
  /** Texte d'aide affiché sous la bascule (masqué quand une erreur s'affiche). @default undefined */
580
590
  readonly hint: _angular_core.InputSignal<string | undefined>;
@@ -585,6 +595,7 @@ declare class KtSwitch implements FormValueControl<boolean> {
585
595
  /** Afficher toutes les erreurs au lieu de la première seule. @default KT_FIELD_CONFIG.showAllErrors ?? false */
586
596
  readonly showAllErrors: _angular_core.InputSignalWithTransform<boolean, unknown>;
587
597
  private readonly switchBtn;
598
+ private readonly el;
588
599
  private readonly errorResolver;
589
600
  private readonly idGen;
590
601
  private readonly uid;
@@ -605,7 +616,7 @@ declare class KtSwitch implements FormValueControl<boolean> {
605
616
  protected toggle(): void;
606
617
  protected onSpacebar(event: Event): void;
607
618
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtSwitch, never>;
608
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<KtSwitch, "kt-switch", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "touched": { "alias": "touched"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "dirty": { "alias": "dirty"; "required": false; "isSignal": true; }; "pending": { "alias": "pending"; "required": false; "isSignal": true; }; "errors": { "alias": "errors"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "errorMatcher": { "alias": "errorMatcher"; "required": false; "isSignal": true; }; "showAllErrors": { "alias": "showAllErrors"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "touched": "touchedChange"; }, never, never, true, never>;
619
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<KtSwitch, "kt-switch", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "touched": { "alias": "touched"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "dirty": { "alias": "dirty"; "required": false; "isSignal": true; }; "pending": { "alias": "pending"; "required": false; "isSignal": true; }; "errors": { "alias": "errors"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "errorMatcher": { "alias": "errorMatcher"; "required": false; "isSignal": true; }; "showAllErrors": { "alias": "showAllErrors"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "touched": "touchedChange"; }, never, ["*"], true, never>;
609
620
  }
610
621
 
611
622
  /**
@@ -998,6 +1009,11 @@ declare abstract class KtBaseSelect<T, V = T> {
998
1009
  readonly hideLabel: _angular_core.InputSignalWithTransform<boolean, unknown>;
999
1010
  /** Masquer visuellement le bloc d'erreur. @default KT_FIELD_CONFIG.hideErrors ?? false */
1000
1011
  readonly hideErrors: _angular_core.InputSignalWithTransform<boolean, unknown>;
1012
+ /** Bouton « effacer » (×) sur le champ quand une valeur est sélectionnée (même contrat que
1013
+ `clearable` de BaseInputField ; single vide la sélection, multi vide toute la sélection). @default false */
1014
+ readonly clearable: _angular_core.InputSignalWithTransform<boolean, unknown>;
1015
+ /** Libellé i18n du bouton « effacer ». @default 'Clear' (ou KT_FIELD_CONFIG.clearLabel) */
1016
+ readonly clearLabel: _angular_core.InputSignal<string>;
1001
1017
  /** Affiche un champ de recherche en tête du popup (desktop) / de la sheet (téléphone).
1002
1018
  Pour les listes longues ; le texte tapé ne sert qu'à filtrer (réinitialisé à la fermeture). @default false */
1003
1019
  readonly filterable: _angular_core.InputSignalWithTransform<boolean, unknown>;
@@ -1098,11 +1114,27 @@ declare abstract class KtBaseSelect<T, V = T> {
1098
1114
  protected refocusTriggerAfterFilterClose(): void;
1099
1115
  /** Fermeture synchrone du Popover (l'effect, différé, ne re-cachera pas : flag popoverShown). */
1100
1116
  protected closePopupNow(): void;
1101
- private readonly sheetDrag;
1102
- protected onDragStart(event: PointerEvent): void;
1117
+ private sheetEl;
1118
+ private sheetState;
1119
+ /** Armé quand l'ouverture a dépassé 50px : un repos à ~0 est alors forcément le snap « fermé »
1120
+ (et non la position initiale) — même logique que le prototype du spike. */
1121
+ private sheetArmed;
1122
+ private sheetCloseTimer;
1123
+ private resetSheetState;
1124
+ private prefersReducedMotion;
1125
+ /** Entrée de la sheet : position « fermée » puis scroll animé vers le snap « ouvert ». */
1126
+ private openSheetByScroll;
1127
+ /** Détection du snap « fermé » par position de scroll (ni scrollsnapchange ni scrollend :
1128
+ non interopérables — cf. ADR-0005). Un geste de l'utilisateur qui amène la sheet au repos
1129
+ à 0 EST la fermeture ; les fermetures programmatiques y convergent aussi. */
1130
+ private readonly onSheetScroll;
1131
+ /** La molette ne ferme JAMAIS la sheet (pas de geste souris — ADR-0005) : seule la listbox
1132
+ peut consommer, dans les limites de son propre défilement. */
1133
+ private readonly onSheetWheel;
1134
+ private finalizeSheetClose;
1103
1135
  private animateAndCloseSelect;
1104
1136
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtBaseSelect<any, any>, never>;
1105
- static ɵdir: _angular_core.ɵɵDirectiveDeclaration<KtBaseSelect<any, any>, never, never, { "options": { "alias": "options"; "required": true; "isSignal": true; }; "optionLabel": { "alias": "optionLabel"; "required": false; "isSignal": true; }; "optionValue": { "alias": "optionValue"; "required": false; "isSignal": true; }; "optionDisabled": { "alias": "optionDisabled"; "required": false; "isSignal": true; }; "compareWith": { "alias": "compareWith"; "required": false; "isSignal": true; }; "touched": { "alias": "touched"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "dirty": { "alias": "dirty"; "required": false; "isSignal": true; }; "pending": { "alias": "pending"; "required": false; "isSignal": true; }; "errors": { "alias": "errors"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "helpText": { "alias": "helpText"; "required": false; "isSignal": true; }; "helpLabel": { "alias": "helpLabel"; "required": false; "isSignal": true; }; "customDescribedBy": { "alias": "customDescribedBy"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "errorMatcher": { "alias": "errorMatcher"; "required": false; "isSignal": true; }; "appearance": { "alias": "appearance"; "required": false; "isSignal": true; }; "floatLabel": { "alias": "floatLabel"; "required": false; "isSignal": true; }; "hideLabel": { "alias": "hideLabel"; "required": false; "isSignal": true; }; "hideErrors": { "alias": "hideErrors"; "required": false; "isSignal": true; }; "filterable": { "alias": "filterable"; "required": false; "isSignal": true; }; "filterPlaceholder": { "alias": "filterPlaceholder"; "required": false; "isSignal": true; }; "filterLabel": { "alias": "filterLabel"; "required": false; "isSignal": true; }; "filterFn": { "alias": "filterFn"; "required": false; "isSignal": true; }; "maxVisibleOptions": { "alias": "maxVisibleOptions"; "required": false; "isSignal": true; }; "truncatedResultsText": { "alias": "truncatedResultsText"; "required": false; "isSignal": true; }; "truncatedResultsAnnouncement": { "alias": "truncatedResultsAnnouncement"; "required": false; "isSignal": true; }; }, { "helpClick": "helpClick"; "touched": "touchedChange"; }, never, never, true, never>;
1137
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<KtBaseSelect<any, any>, never, never, { "options": { "alias": "options"; "required": true; "isSignal": true; }; "optionLabel": { "alias": "optionLabel"; "required": false; "isSignal": true; }; "optionValue": { "alias": "optionValue"; "required": false; "isSignal": true; }; "optionDisabled": { "alias": "optionDisabled"; "required": false; "isSignal": true; }; "compareWith": { "alias": "compareWith"; "required": false; "isSignal": true; }; "touched": { "alias": "touched"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "dirty": { "alias": "dirty"; "required": false; "isSignal": true; }; "pending": { "alias": "pending"; "required": false; "isSignal": true; }; "errors": { "alias": "errors"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "helpText": { "alias": "helpText"; "required": false; "isSignal": true; }; "helpLabel": { "alias": "helpLabel"; "required": false; "isSignal": true; }; "customDescribedBy": { "alias": "customDescribedBy"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "errorMatcher": { "alias": "errorMatcher"; "required": false; "isSignal": true; }; "appearance": { "alias": "appearance"; "required": false; "isSignal": true; }; "floatLabel": { "alias": "floatLabel"; "required": false; "isSignal": true; }; "hideLabel": { "alias": "hideLabel"; "required": false; "isSignal": true; }; "hideErrors": { "alias": "hideErrors"; "required": false; "isSignal": true; }; "clearable": { "alias": "clearable"; "required": false; "isSignal": true; }; "clearLabel": { "alias": "clearLabel"; "required": false; "isSignal": true; }; "filterable": { "alias": "filterable"; "required": false; "isSignal": true; }; "filterPlaceholder": { "alias": "filterPlaceholder"; "required": false; "isSignal": true; }; "filterLabel": { "alias": "filterLabel"; "required": false; "isSignal": true; }; "filterFn": { "alias": "filterFn"; "required": false; "isSignal": true; }; "maxVisibleOptions": { "alias": "maxVisibleOptions"; "required": false; "isSignal": true; }; "truncatedResultsText": { "alias": "truncatedResultsText"; "required": false; "isSignal": true; }; "truncatedResultsAnnouncement": { "alias": "truncatedResultsAnnouncement"; "required": false; "isSignal": true; }; }, { "helpClick": "helpClick"; "touched": "touchedChange"; }, never, never, true, never>;
1106
1138
  }
1107
1139
 
1108
1140
  /** Contexte typé reçu par le template d'une option (`ktSelectOption`). */
@@ -1191,6 +1223,10 @@ declare class KtSelect<T, V = T> extends KtBaseSelect<T, V> implements FormValue
1191
1223
  protected readonly triggerDef: _angular_core.Signal<KtSelectTriggerDef<any> | undefined>;
1192
1224
  /** Fermer le popup après une sélection (sémantique single ; le multi reste ouvert). */
1193
1225
  private readonly closeOnSelect;
1226
+ /** Affiche le bouton « effacer » (×) sur le champ dès qu'une valeur est présente (`clearable`).
1227
+ Basé sur `value()` et non `selectedOption()` : une clé orpheline (option retirée des données)
1228
+ reste effaçable. */
1229
+ protected readonly showClear: _angular_core.Signal<boolean>;
1194
1230
  /** Option correspondant à la valeur courante (clé extraite, ou objet si `optionValue` est omis). */
1195
1231
  protected readonly selectedOption: _angular_core.Signal<T | null>;
1196
1232
  /** Valeur du listbox : tableau de clés (0 ou 1 élément en single). */
@@ -1199,6 +1235,8 @@ declare class KtSelect<T, V = T> extends KtBaseSelect<T, V> implements FormValue
1199
1235
  /** La sélection courante est-elle masquée par le filtre ou la troncation ? (≠ retirée des données). */
1200
1236
  private isSelectionFilteredOut;
1201
1237
  private commitSelection;
1238
+ /** Efface la sélection depuis le champ (bouton `clearable`) et rend le focus au trigger. */
1239
+ protected clearSelection(): void;
1202
1240
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtSelect<any, any>, never>;
1203
1241
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<KtSelect<any, any>, "kt-select", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "selectionChange": "selectionChange"; }, ["optionDef", "triggerDef"], ["[ktFieldHelp]"], true, never>;
1204
1242
  }
@@ -1390,10 +1428,6 @@ declare class KtMultiSelect<T, V = T> extends KtBaseSelect<T, V> implements Form
1390
1428
  /** Émis à chaque (dé)sélection. Payload : `{ value, options }` — `value` le tableau des valeurs émises
1391
1429
  (clés ou objets), `options` les objets options correspondants, dans l'ordre de sélection. */
1392
1430
  readonly selectionChange: _angular_core.OutputEmitterRef<KtMultiSelectSelectionChange<T, V>>;
1393
- /** Bouton « tout effacer » sur le champ (même contrat que `clearable` de BaseInputField). @default false */
1394
- readonly clearable: _angular_core.InputSignalWithTransform<boolean, unknown>;
1395
- /** Libellé i18n du bouton « tout effacer ». @default 'Clear' (ou KT_FIELD_CONFIG.clearLabel) */
1396
- readonly clearLabel: _angular_core.InputSignal<string>;
1397
1431
  /** Barre « Tout sélectionner / Tout effacer » en tête du popup (bascule le popup en panneau dialog). */
1398
1432
  readonly selectionActions: _angular_core.InputSignalWithTransform<boolean, unknown>;
1399
1433
  /** Nombre maximal de chips affichés avant repli derrière un bouton « +N more ». Défaut : illimité. */
@@ -1454,7 +1488,7 @@ declare class KtMultiSelect<T, V = T> extends KtBaseSelect<T, V> implements Form
1454
1488
  /** Annonce immédiate (action ponctuelle, pas de débounce) du total sélectionné. */
1455
1489
  private announceSelectionCount;
1456
1490
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtMultiSelect<any, any>, never>;
1457
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<KtMultiSelect<any, any>, "kt-multi-select", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "clearable": { "alias": "clearable"; "required": false; "isSignal": true; }; "clearLabel": { "alias": "clearLabel"; "required": false; "isSignal": true; }; "selectionActions": { "alias": "selectionActions"; "required": false; "isSignal": true; }; "maxVisibleChips": { "alias": "maxVisibleChips"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "selectionChange": "selectionChange"; }, ["optionDef", "triggerDef", "chipDef"], ["[ktFieldHelp]"], true, never>;
1491
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<KtMultiSelect<any, any>, "kt-multi-select", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "selectionActions": { "alias": "selectionActions"; "required": false; "isSignal": true; }; "maxVisibleChips": { "alias": "maxVisibleChips"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "selectionChange": "selectionChange"; }, ["optionDef", "triggerDef", "chipDef"], ["[ktFieldHelp]"], true, never>;
1458
1492
  }
1459
1493
 
1460
1494
  /** Portée de transition des chips. Fourni par `ChipList` (via `useExisting`) ; injecté en
@@ -1718,12 +1752,30 @@ declare class KtChipList<T> implements ChipTransitionScope {
1718
1752
  Public : permet au parent d'annoncer des actions liées (ex. « tout effacer »). */
1719
1753
  announce(text: string): void;
1720
1754
  private activeTransition;
1755
+ /**
1756
+ * Vrai sur le moteur WebKit (Safari desktop + TOUS les navigateurs iOS, qui embarquent WebKit).
1757
+ *
1758
+ * Contournement DOCUMENTÉ et RÉVERSIBLE d'un bug de compositing des View Transitions au niveau
1759
+ * document sur WebKit : après la transition, les chips (hôtes d'éléments custom dont le
1760
+ * `view-transition-name` est posé puis retiré dynamiquement) ne se repeignent pas — seules les
1761
+ * croix « retirer » (boutons natifs, compositées sur une couche distincte) subsistent à l'écran.
1762
+ * Touche aussi bien le retrait que le déplier/replier : les deux passent par ce wrapper.
1763
+ *
1764
+ * Le défaut n'est PAS feature-detectable : `startViewTransition` répond présente puis rate le
1765
+ * rendu final, d'où la détection de MOTEUR. `navigator.vendor` est gelé pour compat — vaut
1766
+ * « Apple Computer, Inc. » sur WebKit UNIQUEMENT (Blink = « Google Inc. », Gecko = « »). On NE
1767
+ * gate PAS sur l'absence de la variante scopée `element.startViewTransition` : cela exclurait
1768
+ * Firefox à tort (transition document parfaitement rendue chez lui). À RETIRER quand Safari
1769
+ * corrigera le compositing.
1770
+ */
1771
+ private isWebKitEngine;
1721
1772
  /** Exécute `action` dans une View Transition (morph des chips qui se déplacent, entrée/sortie
1722
1773
  stylées via `::view-transition-*(.chip-transition)` — cf. tokens.css). Transition SCOPÉE à
1723
1774
  l'élément quand le navigateur le permet (`element.startViewTransition`, Chrome 147+) ; sinon
1724
1775
  transition document — dans les deux cas, seuls les chips de CETTE liste sont nommés (cf.
1725
- `transitioning`). Fallback : action directe si l'API est absente ou si l'utilisateur
1726
- préfère moins de mouvement. */
1776
+ `transitioning`). Fallback : action directe (retrait/dépli instantané, état final garanti
1777
+ correct) si l'API est absente, si l'utilisateur préfère moins de mouvement, ou sur WebKit
1778
+ (bug de compositing, cf. `isWebKitEngine`). */
1727
1779
  private withViewTransition;
1728
1780
  /** Retrait demandé : annonce, émet vers le parent (qui met à jour `items`), puis focus
1729
1781
  le chip suivant — sinon `emptyFocusTarget` (le bouton focusé disparaît du DOM). */
@@ -75,6 +75,22 @@ declare class KtTooltip implements OnDestroy {
75
75
  ngOnDestroy(): void;
76
76
  protected show(): void;
77
77
  protected hide(): void;
78
+ /**
79
+ * Fermeture immédiate à l'activation de la cible (clic souris, tap tactile, stylet).
80
+ * Dès que l'utilisateur AGIT sur l'élément (typiquement un bouton qui ouvre une bottom sheet ou un
81
+ * dialog), l'infobulle a fini son rôle : on la ferme sans attendre le hideDelay, et on purge un
82
+ * affichage en attente pour qu'il ne surgisse pas après coup.
83
+ *
84
+ * Sans ce déclencheur, une infobulle affichée au survol SURVIVAIT à l'ouverture d'un overlay : le
85
+ * pointeur reste sur la cible (aucun `mouseleave`) et un clic ne défocalise pas toujours (aucun
86
+ * `focusout` fiable, ex. Safari/Firefox macOS). Comme l'infobulle est un popover en top layer, elle
87
+ * flottait alors AU-DESSUS de l'overlay (lui empilé au z-index) — impossible à masquer autrement.
88
+ *
89
+ * `pointerdown` (et non `click`) car il précède l'ouverture de l'overlay et le déplacement de focus
90
+ * → zéro flash. On ne fait ni preventDefault ni stopPropagation : l'action native (clic) doit suivre
91
+ * son cours. Le cas clavier (Entrée/Espace) reste couvert par `focusout` quand l'overlay prend le focus.
92
+ */
93
+ protected onActivate(): void;
78
94
  protected onEscape(event: Event): void;
79
95
  private dismiss;
80
96
  private ensureTip;