@ktortu/aaa 0.1.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +151 -0
  3. package/button/button-tokens.css +152 -0
  4. package/button/button.css +319 -0
  5. package/card/card-tokens.css +49 -0
  6. package/card/card.css +200 -0
  7. package/cdk/styles/foundation.css +83 -0
  8. package/cdk/styles/tabs.css +276 -0
  9. package/dialog/dialog.css +350 -0
  10. package/fesm2022/ktortu-aaa-button.mjs +128 -0
  11. package/fesm2022/ktortu-aaa-button.mjs.map +1 -0
  12. package/fesm2022/ktortu-aaa-card.mjs +209 -0
  13. package/fesm2022/ktortu-aaa-card.mjs.map +1 -0
  14. package/fesm2022/ktortu-aaa-cdk.mjs +183 -0
  15. package/fesm2022/ktortu-aaa-cdk.mjs.map +1 -0
  16. package/fesm2022/ktortu-aaa-dialog.mjs +512 -0
  17. package/fesm2022/ktortu-aaa-dialog.mjs.map +1 -0
  18. package/fesm2022/ktortu-aaa-forms.mjs +3215 -0
  19. package/fesm2022/ktortu-aaa-forms.mjs.map +1 -0
  20. package/fesm2022/ktortu-aaa-menu.mjs +315 -0
  21. package/fesm2022/ktortu-aaa-menu.mjs.map +1 -0
  22. package/fesm2022/ktortu-aaa-tabs.mjs +79 -0
  23. package/fesm2022/ktortu-aaa-tabs.mjs.map +1 -0
  24. package/fesm2022/ktortu-aaa-tooltip.mjs +356 -0
  25. package/fesm2022/ktortu-aaa-tooltip.mjs.map +1 -0
  26. package/fesm2022/ktortu-aaa.mjs +17 -0
  27. package/fesm2022/ktortu-aaa.mjs.map +1 -0
  28. package/forms/checkbox/checkbox-group.css +55 -0
  29. package/forms/checkbox/checkbox.css +216 -0
  30. package/forms/chips/chip-list.css +70 -0
  31. package/forms/chips/chip.css +92 -0
  32. package/forms/chips/tokens.css +102 -0
  33. package/forms/field/field.css +87 -0
  34. package/forms/multi-select/multi-select.css +136 -0
  35. package/forms/radio/radio-group.css +55 -0
  36. package/forms/radio/radio.css +165 -0
  37. package/forms/styles/field-box.css +171 -0
  38. package/forms/styles/select-panel.css +464 -0
  39. package/forms/styles/tokens.css +67 -0
  40. package/forms/switch/switch.css +188 -0
  41. package/menu/menu-tokens.css +58 -0
  42. package/menu/menu.css +224 -0
  43. package/package.json +96 -0
  44. package/styles/button.css +6 -0
  45. package/styles/card.css +6 -0
  46. package/styles/dialog.css +6 -0
  47. package/styles/forms.css +13 -0
  48. package/styles/foundation.css +7 -0
  49. package/styles/menu.css +6 -0
  50. package/styles/styles.css +24 -0
  51. package/styles/tabs.css +5 -0
  52. package/styles/tooltip.css +5 -0
  53. package/themes/theme-ant.css +44 -0
  54. package/themes/theme-architecte.css +83 -0
  55. package/themes/theme-aurora.css +97 -0
  56. package/themes/theme-bootstrap.css +46 -0
  57. package/themes/theme-carbon.css +49 -0
  58. package/themes/theme-catppuccin.css +66 -0
  59. package/themes/theme-cyberpunk.css +211 -0
  60. package/themes/theme-fluent.css +45 -0
  61. package/themes/theme-material-you.css +74 -0
  62. package/themes/theme-material.css +48 -0
  63. package/themes/theme-primer.css +46 -0
  64. package/themes/theme-vegetal.css +78 -0
  65. package/tooltip/tooltip.css +129 -0
  66. package/types/ktortu-aaa-button.d.ts +70 -0
  67. package/types/ktortu-aaa-card.d.ts +143 -0
  68. package/types/ktortu-aaa-cdk.d.ts +110 -0
  69. package/types/ktortu-aaa-dialog.d.ts +286 -0
  70. package/types/ktortu-aaa-forms.d.ts +1574 -0
  71. package/types/ktortu-aaa-menu.d.ts +171 -0
  72. package/types/ktortu-aaa-tabs.d.ts +27 -0
  73. package/types/ktortu-aaa-tooltip.d.ts +90 -0
  74. package/types/ktortu-aaa.d.ts +8 -0
@@ -0,0 +1,1574 @@
1
+ import * as _angular_core from '@angular/core';
2
+ import { InjectionToken, Signal, TemplateRef, ModelSignal, ElementRef, PipeTransform } from '@angular/core';
3
+ import * as _angular_forms_signals from '@angular/forms/signals';
4
+ import { WithOptionalFieldTree, ValidationError, FormValueControl } from '@angular/forms/signals';
5
+ import * as _ktortu_aaa_forms from '@ktortu/aaa/forms';
6
+ import { Listbox } from '@angular/aria/listbox';
7
+ import { Combobox } from '@angular/aria/combobox';
8
+ import { KtViewport } from '@ktortu/aaa/cdk';
9
+ import { Temporal } from 'temporal-polyfill';
10
+ export { Temporal as TemporalNamespace } from 'temporal-polyfill';
11
+
12
+ /** État d'un champ pertinent pour décider de l'affichage des erreurs. */
13
+ interface KtFieldErrorState {
14
+ invalid: boolean;
15
+ touched: boolean;
16
+ dirty: boolean;
17
+ }
18
+ /** Décide QUAND afficher les erreurs d'un champ (équivalent signal de l'ErrorStateMatcher Material). */
19
+ type KtFieldErrorMatcher = (state: KtFieldErrorState) => boolean;
20
+ /** Défaut : afficher l'erreur une fois le champ quitté (blur). */
21
+ declare const defaultKtFieldErrorMatcher: KtFieldErrorMatcher;
22
+ /** Défauts applicables à tous les champs (surchargeables par champ via les inputs).
23
+ Lib neutre i18n : les textes sont fournis par le consommateur, ici en une fois.
24
+ Fourni en `Partial` : un consommateur n'override que ce qu'il veut. */
25
+ interface KtFieldConfig {
26
+ /** Libellé accessible du bouton d'effacement. */
27
+ clearLabel: string;
28
+ /** Libellé accessible du bouton d'aide (i18n). */
29
+ helpLabel: string;
30
+ /** Quand afficher les erreurs. Défaut : `invalid && touched`. */
31
+ errorMatcher: KtFieldErrorMatcher;
32
+ /** Masquer le hint quand l'erreur s'affiche (façon Material). Défaut : `false`. */
33
+ hideHintWhenInvalid: boolean;
34
+ /** Afficher toutes les erreurs au lieu de la première seule. Défaut : `false`. */
35
+ showAllErrors: boolean;
36
+ }
37
+ declare const KT_FIELD_CONFIG: InjectionToken<Partial<KtFieldConfig>>;
38
+ /** Parent field interface representing shared states for its controls. */
39
+ interface KtFieldParent {
40
+ readonly baseId: Signal<string>;
41
+ readonly describedBy: Signal<string | null>;
42
+ readonly invalid: Signal<boolean>;
43
+ readonly required: Signal<boolean>;
44
+ }
45
+ declare const KT_FIELD: InjectionToken<KtFieldParent>;
46
+
47
+ /** Forme minimale d'une erreur affichable — découple `Field` de Signal Forms. */
48
+ interface KtFieldError {
49
+ kind: string;
50
+ message?: string;
51
+ }
52
+ /** Chrome de champ agnostique du système de forms : label + contrôle projeté + hint + erreur,
53
+ et centralisation du câblage a11y. Nourri par des inputs simples.
54
+
55
+ @example
56
+ ```html
57
+ <kt-field label="E-mail" hint="Nous ne partagerons jamais votre adresse." [invalid]="emailInvalid()" [errors]="emailErrors()" required>
58
+ <input ktFieldControl type="email" [(ngModel)]="email" />
59
+ </kt-field>
60
+ ``` */
61
+ declare class KtField implements KtFieldParent {
62
+ private readonly config;
63
+ /** Libellé du champ. @default undefined */
64
+ readonly label: _angular_core.InputSignal<string | undefined>;
65
+ /** Texte d'aide affiché sous le contrôle. @default undefined */
66
+ readonly hint: _angular_core.InputSignal<string | undefined>;
67
+ /** Contenu de l'aide contextuelle (texte ou `TemplateRef`) rendu dans le tooltip d'aide. @default undefined */
68
+ readonly helpText: _angular_core.InputSignal<string | TemplateRef<unknown> | undefined>;
69
+ /** Libellé accessible du déclencheur d'aide. @default KT_FIELD_CONFIG.helpLabel ?? 'Help' */
70
+ readonly helpLabel: _angular_core.InputSignal<string>;
71
+ /** id(s) externe(s) à ajouter à l'`aria-describedby` du contrôle (découplage). @default undefined */
72
+ readonly customDescribedBy: _angular_core.InputSignal<string | undefined>;
73
+ /** Émis au clic sur le déclencheur d'aide (le `preventDefault`/`stopPropagation` est déjà appliqué). */
74
+ readonly helpClick: _angular_core.OutputEmitterRef<MouseEvent>;
75
+ /** Erreurs de validation à afficher sous le contrôle. @default [] */
76
+ readonly errors: _angular_core.InputSignal<readonly KtFieldError[]>;
77
+ /** Marque le champ comme invalide (pose `aria-invalid` et conditionne l'affichage des erreurs). @default false */
78
+ readonly invalid: _angular_core.InputSignal<boolean>;
79
+ /** Affiche l'astérisque requis et pose `aria-required` sur le contrôle. @default false */
80
+ readonly required: _angular_core.InputSignal<boolean>;
81
+ /** id imposé (sélecteurs de test stables) ; sinon auto-généré, anti-collision. */
82
+ readonly fieldId: _angular_core.InputSignal<string | undefined>;
83
+ /** Masquer le hint quand l'erreur s'affiche (façon Material). */
84
+ readonly hideHintWhenInvalid: _angular_core.InputSignal<boolean>;
85
+ /** Afficher toutes les erreurs au lieu de la première seule. */
86
+ readonly showAllErrors: _angular_core.InputSignal<boolean>;
87
+ private readonly control;
88
+ private readonly templateTooltip;
89
+ private readonly projectedTooltip;
90
+ private readonly activeTooltip;
91
+ private readonly idGen;
92
+ private readonly uid;
93
+ readonly baseId: _angular_core.Signal<string>;
94
+ protected readonly labelId: _angular_core.Signal<string>;
95
+ protected readonly hintId: _angular_core.Signal<string>;
96
+ protected readonly errorId: _angular_core.Signal<string>;
97
+ protected readonly hasError: _angular_core.Signal<boolean>;
98
+ protected readonly showHint: _angular_core.Signal<boolean>;
99
+ protected readonly displayedErrors: _angular_core.Signal<readonly KtFieldError[]>;
100
+ readonly describedBy: _angular_core.Signal<string | null>;
101
+ protected onHelpClick(event: MouseEvent): void;
102
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtField, never>;
103
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<KtField, "kt-field", never, { "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; }; "errors": { "alias": "errors"; "required": false; "isSignal": true; }; "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "fieldId": { "alias": "fieldId"; "required": false; "isSignal": true; }; "hideHintWhenInvalid": { "alias": "hideHintWhenInvalid"; "required": false; "isSignal": true; }; "showAllErrors": { "alias": "showAllErrors"; "required": false; "isSignal": true; }; }, { "helpClick": "helpClick"; }, ["control", "projectedTooltip"], ["[ktFieldHelp]", "*"], true, never>;
104
+ }
105
+
106
+ /** Marque le contrôle (natif ou custom) d'un champ pour que `Field` y câble l'a11y
107
+ (id, aria-describedby, aria-invalid, aria-required). */
108
+ declare class KtFieldControl {
109
+ private readonly parent;
110
+ protected readonly id: _angular_core.Signal<string | null>;
111
+ protected readonly describedBy: _angular_core.Signal<string | null>;
112
+ protected readonly invalid: _angular_core.Signal<boolean>;
113
+ protected readonly required: _angular_core.Signal<boolean>;
114
+ readonly element: HTMLElement;
115
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtFieldControl, never>;
116
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<KtFieldControl, "[ktFieldControl]", never, {}, {}, never, never, true, never>;
117
+ }
118
+
119
+ /** Suggestion d'un champ de saisie (rendu `<datalist>`) : soit la valeur seule, soit un couple
120
+ `{ value, label }` où `label` est le texte affiché et `value` ce qui est inséré dans le champ.
121
+ @template V Type de la valeur du champ (string, number, ou type Temporal selon le champ). */
122
+ type KtSuggestion<V> = V | {
123
+ value: V;
124
+ label?: string;
125
+ };
126
+ /** Option `<datalist>` normalisée : `value` est la chaîne posée sur l'attribut DOM, `label` le
127
+ libellé affiché (ou `null`). */
128
+ interface KtDatalistOption {
129
+ value: string;
130
+ label: string | null;
131
+ }
132
+
133
+ /** Base partagée des champs simples (TextField, NumberField) : état FormValueControl,
134
+ présentation (label/hint/prefix/suffix/clear) et politique d'affichage des erreurs.
135
+ La valeur, son parsing et la notion de « vide » sont fournis par la sous-classe. */
136
+ declare abstract class KtBaseInputField<T> {
137
+ protected readonly config: Partial<_ktortu_aaa_forms.KtFieldConfig> | null;
138
+ /** Valeur du contrôle — déclarée concrètement par la sous-classe. */
139
+ abstract value: ModelSignal<T>;
140
+ /** Marque le champ comme « visité » (déclenche l'affichage des erreurs). Deux-way. @default false */
141
+ readonly touched: ModelSignal<boolean>;
142
+ /** Désactive la saisie et le focus. @default false */
143
+ readonly disabled: _angular_core.InputSignal<boolean>;
144
+ /** Rend le champ en lecture seule (valeur visible, non modifiable). @default false */
145
+ readonly readonly: _angular_core.InputSignal<boolean>;
146
+ /** Le champ est-il en erreur (état fourni par la validation). @default false */
147
+ readonly invalid: _angular_core.InputSignal<boolean>;
148
+ /** Marque le champ comme requis (ajoute `aria-required`). @default false */
149
+ readonly required: _angular_core.InputSignal<boolean>;
150
+ /** Le champ a-t-il été modifié depuis sa valeur initiale. @default false */
151
+ readonly dirty: _angular_core.InputSignal<boolean>;
152
+ /** Liste des erreurs de validation à afficher. @default [] */
153
+ readonly errors: _angular_core.InputSignal<readonly WithOptionalFieldTree<ValidationError>[]>;
154
+ /** Attribut `name` natif du contrôle. @default '' */
155
+ readonly name: _angular_core.InputSignal<string>;
156
+ /** id imposé pour des sélecteurs de test stables ; sinon auto-généré par Field. */
157
+ readonly id: _angular_core.InputSignal<string | undefined>;
158
+ /** Libellé du champ (associé via `<label for>`). */
159
+ readonly label: _angular_core.InputSignal<string | undefined>;
160
+ /** Texte d'aide affiché sous le champ quand il est valide. */
161
+ readonly hint: _angular_core.InputSignal<string | undefined>;
162
+ /** Aide contextuelle riche : texte ou `TemplateRef` projeté dans une infobulle d'aide. */
163
+ readonly helpText: _angular_core.InputSignal<string | TemplateRef<unknown> | undefined>;
164
+ /** Libellé accessible du bouton d'aide. @default 'Help' (ou KT_FIELD_CONFIG.helpLabel) */
165
+ readonly helpLabel: _angular_core.InputSignal<string>;
166
+ /** Force la valeur de `aria-describedby` (sinon dérivée de hint/erreur). */
167
+ readonly customDescribedBy: _angular_core.InputSignal<string | undefined>;
168
+ /** Émis au clic sur le bouton d'aide contextuelle. */
169
+ readonly helpClick: _angular_core.OutputEmitterRef<MouseEvent>;
170
+ /** Texte indicatif affiché dans le champ vide. */
171
+ readonly placeholder: _angular_core.InputSignal<string | undefined>;
172
+ /** Indice d'autoremplissage du navigateur (attribut `autocomplete` natif) ; ex. `'current-password'`,
173
+ `'new-password'`, `'email'`, `'username'`, `'off'`.
174
+ @default undefined */
175
+ readonly autocomplete: _angular_core.InputSignal<AutoFill | undefined>;
176
+ /** Nom d'icône Material Symbols affichée en tête de champ. */
177
+ readonly icon: _angular_core.InputSignal<string | undefined>;
178
+ /** Affiche un bouton « effacer » quand le champ contient une valeur. @default false */
179
+ readonly clearable: _angular_core.InputSignalWithTransform<boolean, unknown>;
180
+ /** Contenu décoratif en tête de champ : texte ou `TemplateRef`. */
181
+ readonly prefix: _angular_core.InputSignal<string | TemplateRef<unknown> | undefined>;
182
+ /** Contenu décoratif en fin de champ : texte ou `TemplateRef`. */
183
+ readonly suffix: _angular_core.InputSignal<string | TemplateRef<unknown> | undefined>;
184
+ /** Libellé i18n du bouton « effacer ». @default 'Clear' (ou KT_FIELD_CONFIG.clearLabel) */
185
+ readonly clearLabel: _angular_core.InputSignal<string>;
186
+ /** Quand afficher l'erreur ; surcharge KT_FIELD_CONFIG et le défaut (`invalid && touched`). */
187
+ readonly errorMatcher: _angular_core.InputSignal<KtFieldErrorMatcher | undefined>;
188
+ protected readonly inputRef: _angular_core.Signal<ElementRef<HTMLInputElement | HTMLTextAreaElement> | undefined>;
189
+ private readonly matcher;
190
+ protected readonly showInvalid: _angular_core.Signal<boolean>;
191
+ protected readonly showClear: _angular_core.Signal<boolean>;
192
+ protected asTemplate(value: string | TemplateRef<unknown> | undefined): TemplateRef<unknown> | null;
193
+ protected asText(value: string | TemplateRef<unknown> | undefined): string | null;
194
+ protected onInput(event: Event): void;
195
+ protected onKeyDown(event: KeyboardEvent): void;
196
+ protected clear(): void;
197
+ /** Parse la saisie brute en valeur typée. */
198
+ protected abstract parse(raw: string): T;
199
+ /** Représentation « vide » de la valeur. */
200
+ protected abstract emptyValue(): T;
201
+ /** La valeur est-elle vide (affichage du bouton d'effacement) ? */
202
+ protected abstract isEmpty(value: T): boolean;
203
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtBaseInputField<any>, never>;
204
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<KtBaseInputField<any>, never, never, { "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; }; "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; }; "autocomplete": { "alias": "autocomplete"; "required": false; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "clearable": { "alias": "clearable"; "required": false; "isSignal": true; }; "prefix": { "alias": "prefix"; "required": false; "isSignal": true; }; "suffix": { "alias": "suffix"; "required": false; "isSignal": true; }; "clearLabel": { "alias": "clearLabel"; "required": false; "isSignal": true; }; "errorMatcher": { "alias": "errorMatcher"; "required": false; "isSignal": true; }; }, { "touched": "touchedChange"; "helpClick": "helpClick"; }, never, never, true, never>;
205
+ }
206
+
207
+ /**
208
+ * Champ numérique : valeur `number | null` (champ vide ⇒ `null`, jamais `NaN`), intégré aux
209
+ * Signal Forms via `FormValueControl`. Hérite de la présentation commune (label/hint/clear/
210
+ * préfixe/suffixe/erreurs) de `KtBaseInputField`.
211
+ *
212
+ * @example
213
+ * ```html
214
+ * <kt-number-field label="Quantité" [(value)]="qty" [min]="0" [step]="1" />
215
+ * ```
216
+ */
217
+ declare class KtNumberField extends KtBaseInputField<number | null> implements FormValueControl<number | null> {
218
+ /** Valeur saisie (two-way). `null` = champ vide. @default null */
219
+ readonly value: _angular_core.ModelSignal<number | null>;
220
+ /** Borne minimale (attribut `min` natif). @default undefined */
221
+ readonly min: _angular_core.InputSignal<number | undefined>;
222
+ /** Borne maximale (attribut `max` natif). @default undefined */
223
+ readonly max: _angular_core.InputSignal<number | undefined>;
224
+ /** Pas d'incrément (attribut `step` natif). @default undefined */
225
+ readonly step: _angular_core.InputSignal<number | undefined>;
226
+ /** Suggestions d'autocomplétion proposées via un `<datalist>` natif (la saisie reste libre).
227
+ Valeurs simples (`number[]`) ou couples `{ value, label }` pour distinguer libellé affiché et
228
+ valeur insérée. @default undefined */
229
+ readonly suggestions: _angular_core.InputSignal<readonly KtSuggestion<number>[] | undefined>;
230
+ private readonly idGen;
231
+ private readonly uid;
232
+ protected readonly datalistId: string;
233
+ protected readonly hasSuggestions: _angular_core.Signal<boolean>;
234
+ protected readonly datalistOptions: _angular_core.Signal<readonly KtDatalistOption[]>;
235
+ protected readonly rawValue: _angular_forms_signals.TransformedValueSignal<string>;
236
+ protected parse(raw: string): number | null;
237
+ protected onKeyDown(event: KeyboardEvent): void;
238
+ private adjustValue;
239
+ protected emptyValue(): number | null;
240
+ protected isEmpty(value: number | null): boolean;
241
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtNumberField, never>;
242
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<KtNumberField, "kt-number-field", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "min": { "alias": "min"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "step": { "alias": "step"; "required": false; "isSignal": true; }; "suggestions": { "alias": "suggestions"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, ["[ktFieldHelp]"], true, never>;
243
+ }
244
+
245
+ /**
246
+ * Zone de texte multi-ligne (valeur `string`) intégrée aux Signal Forms via `FormValueControl`.
247
+ * Autosize en CSS (`field-sizing: content`) ; hérite de la présentation commune de `KtBaseInputField`.
248
+ *
249
+ * @example
250
+ * ```html
251
+ * <kt-text-area label="Commentaire" [(value)]="comment" [rows]="4" />
252
+ * ```
253
+ */
254
+ declare class KtTextArea extends KtBaseInputField<string> implements FormValueControl<string> {
255
+ /** Valeur saisie (two-way). @default '' */
256
+ readonly value: _angular_core.ModelSignal<string>;
257
+ /** Hauteur initiale (lignes). L'autosize est géré en CSS via `field-sizing: content`. @default 3 */
258
+ readonly rows: _angular_core.InputSignal<number>;
259
+ /** Plafond de caractères ; poussé par le form (validateur maxLength) ou par le consommateur. @default undefined */
260
+ readonly maxLength: _angular_core.InputSignal<number | undefined>;
261
+ protected parse(raw: string): string;
262
+ protected emptyValue(): string;
263
+ protected isEmpty(value: string): boolean;
264
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtTextArea, never>;
265
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<KtTextArea, "kt-text-area", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "rows": { "alias": "rows"; "required": false; "isSignal": true; }; "maxLength": { "alias": "maxLength"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, ["[ktFieldHelp]"], true, never>;
266
+ }
267
+
268
+ /** Types texte dont la valeur reste une string (number/date = composants séparés). */
269
+ type KtTextFieldType = 'text' | 'email' | 'password' | 'search' | 'tel' | 'url';
270
+ /**
271
+ * Champ texte (valeur `string`) intégré aux Signal Forms via `FormValueControl`. Hérite de la
272
+ * présentation commune (label/hint/clear/préfixe/suffixe/erreurs) de `KtBaseInputField`.
273
+ *
274
+ * @example
275
+ * ```html
276
+ * <kt-text-field label="E-mail" type="email" [(value)]="email" required />
277
+ * ```
278
+ */
279
+ declare class KtTextField extends KtBaseInputField<string> implements FormValueControl<string> {
280
+ /** Valeur saisie (two-way). @default '' */
281
+ readonly value: _angular_core.ModelSignal<string>;
282
+ /** Variante HTML du champ (pilote `type` natif et le clavier mobile). @default 'text' */
283
+ readonly type: _angular_core.InputSignal<KtTextFieldType>;
284
+ /** Suggestions d'autocomplétion proposées via un `<datalist>` natif (la saisie reste libre).
285
+ Valeurs simples (`string[]`) ou couples `{ value, label }` pour distinguer libellé affiché et
286
+ valeur insérée. @default undefined */
287
+ readonly suggestions: _angular_core.InputSignal<readonly KtSuggestion<string>[] | undefined>;
288
+ private readonly idGen;
289
+ private readonly uid;
290
+ protected readonly datalistId: string;
291
+ protected readonly hasSuggestions: _angular_core.Signal<boolean>;
292
+ protected readonly datalistOptions: _angular_core.Signal<readonly KtDatalistOption[]>;
293
+ protected parse(raw: string): string;
294
+ protected emptyValue(): string;
295
+ protected isEmpty(value: string): boolean;
296
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtTextField, never>;
297
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<KtTextField, "kt-text-field", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "type": { "alias": "type"; "required": false; "isSignal": true; }; "suggestions": { "alias": "suggestions"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, ["[ktFieldHelp]"], true, never>;
298
+ }
299
+
300
+ /**
301
+ * Bouton bascule (Switch / Slide-Toggle) accessible conforme aux normes WAI-ARIA.
302
+ * Permet d'activer ou désactiver une option avec effet immédiat.
303
+ * Intégré aux Signal Forms de l'application via FormValueControl.
304
+ *
305
+ * @example
306
+ * ```html
307
+ * <kt-switch label="Notifications par e-mail" [(value)]="emailNotif" />
308
+ * ```
309
+ */
310
+ declare class KtSwitch implements FormValueControl<boolean> {
311
+ private readonly config;
312
+ /** État de la bascule (two-way) : `true` = activé, `false` = désactivé. @default false */
313
+ readonly value: _angular_core.ModelSignal<boolean>;
314
+ /** État « touché » (two-way), généralement piloté par `[formField]`. @default false */
315
+ readonly touched: _angular_core.ModelSignal<boolean>;
316
+ /** Désactive la bascule (non actionnable). @default false */
317
+ readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
318
+ /** Marque la bascule comme invalide (combiné à `touched`/`dirty` via l'`errorMatcher`). @default false */
319
+ readonly invalid: _angular_core.InputSignal<boolean>;
320
+ /** Affiche l'astérisque requis sur le libellé. @default false */
321
+ readonly required: _angular_core.InputSignalWithTransform<boolean, unknown>;
322
+ /** État « modifié » (entre dans la logique d'affichage des erreurs). @default false */
323
+ readonly dirty: _angular_core.InputSignal<boolean>;
324
+ /** Erreurs de validation à afficher sous la bascule. @default [] */
325
+ readonly errors: _angular_core.InputSignal<readonly WithOptionalFieldTree<ValidationError>[]>;
326
+ /** Identifiant logique du contrôle (à titre indicatif). @default '' */
327
+ readonly name: _angular_core.InputSignal<string>;
328
+ /** id imposé (sélecteurs de test stables) ; sinon auto-généré, anti-collision. @default undefined */
329
+ readonly id: _angular_core.InputSignal<string | undefined>;
330
+ /** Texte du libellé associé à la bascule. @default undefined */
331
+ readonly label: _angular_core.InputSignal<string | undefined>;
332
+ /** Texte d'aide affiché sous la bascule (masqué quand une erreur s'affiche). @default undefined */
333
+ readonly hint: _angular_core.InputSignal<string | undefined>;
334
+ /** Nom accessible (`aria-label`) quand `label` est absent. @default undefined */
335
+ readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
336
+ /** Stratégie décidant quand afficher les erreurs (sinon celle du `KT_FIELD_CONFIG`). @default undefined */
337
+ readonly errorMatcher: _angular_core.InputSignal<KtFieldErrorMatcher | undefined>;
338
+ /** Afficher toutes les erreurs au lieu de la première seule. @default KT_FIELD_CONFIG.showAllErrors ?? false */
339
+ readonly showAllErrors: _angular_core.InputSignal<boolean>;
340
+ private readonly idGen;
341
+ private readonly uid;
342
+ protected readonly baseId: _angular_core.Signal<string>;
343
+ protected readonly labelId: _angular_core.Signal<string>;
344
+ protected readonly hintId: _angular_core.Signal<string>;
345
+ protected readonly errorId: _angular_core.Signal<string>;
346
+ private readonly matcher;
347
+ protected readonly showInvalid: _angular_core.Signal<boolean>;
348
+ protected readonly displayedErrors: _angular_core.Signal<readonly WithOptionalFieldTree<ValidationError>[]>;
349
+ protected readonly resolvedAriaLabel: _angular_core.Signal<string | null>;
350
+ protected readonly describedBy: _angular_core.Signal<string | null>;
351
+ protected toggle(): void;
352
+ protected onSpacebar(event: Event): void;
353
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtSwitch, never>;
354
+ 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; }; "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>;
355
+ }
356
+
357
+ /**
358
+ * Groupe de cases à cocher (Checkbox Group) conforme à l'ARIA APG / RGAA.
359
+ * Orchestrateur : porte une valeur TABLEAU (`FormValueControl<V[]>`) et la sémantique de groupe
360
+ * (`role="group"`, légende, `aria-required`/`aria-invalid`, erreurs).
361
+ *
362
+ * Différence APG avec le radio-group : PAS de roving tabindex — chaque `kt-checkbox` reste
363
+ * tabbable et coche/décoche indépendamment. Les options sont fournies par le dev (boucle `@for`
364
+ * ou en dur) ; `compareWith` gère l'égalité quand les valeurs d'option sont des objets.
365
+ *
366
+ * @example
367
+ * ```html
368
+ * <kt-checkbox-group label="Centres d'intérêt" [(value)]="interests" required>
369
+ * <kt-checkbox [value]="'sport'" label="Sport" />
370
+ * <kt-checkbox [value]="'musique'" label="Musique" />
371
+ * <kt-checkbox [value]="'cinema'" label="Cinéma" />
372
+ * </kt-checkbox-group>
373
+ * ```
374
+ */
375
+ declare class KtCheckboxGroup<V> implements FormValueControl<V[]> {
376
+ private readonly config;
377
+ /** Sélection courante : tableau des valeurs d'options cochées (two-way). @default [] */
378
+ readonly value: _angular_core.ModelSignal<V[]>;
379
+ /** État « touché » (two-way), généralement piloté par `[formField]`. @default false */
380
+ readonly touched: _angular_core.ModelSignal<boolean>;
381
+ /** Désactive le groupe entier (hérité par chaque case enfant). @default false */
382
+ readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
383
+ /** Marque le groupe comme invalide (combiné à `touched`/`dirty` via l'`errorMatcher`). @default false */
384
+ readonly invalid: _angular_core.InputSignal<boolean>;
385
+ /** Affiche l'astérisque requis et `aria-required` sur le groupe. @default false */
386
+ readonly required: _angular_core.InputSignalWithTransform<boolean, unknown>;
387
+ /** État « modifié » (entre dans la logique d'affichage des erreurs). @default false */
388
+ readonly dirty: _angular_core.InputSignal<boolean>;
389
+ /** Erreurs de validation à afficher sous le groupe. @default [] */
390
+ readonly errors: _angular_core.InputSignal<readonly WithOptionalFieldTree<ValidationError>[]>;
391
+ /** Attribut `name` partagé (à titre indicatif). @default '' */
392
+ readonly name: _angular_core.InputSignal<string>;
393
+ /** id imposé (sélecteurs de test stables) ; sinon auto-généré, anti-collision. @default undefined */
394
+ readonly id: _angular_core.InputSignal<string | undefined>;
395
+ /** Légende du groupe (`aria-labelledby`). @default undefined */
396
+ readonly label: _angular_core.InputSignal<string | undefined>;
397
+ /** Texte d'aide affiché sous le groupe (masqué quand une erreur s'affiche). @default undefined */
398
+ readonly hint: _angular_core.InputSignal<string | undefined>;
399
+ /** Nom accessible (`aria-label`) du groupe quand `label` est absent. @default undefined */
400
+ readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
401
+ /** Stratégie décidant quand afficher les erreurs (sinon celle du `KT_FIELD_CONFIG`). @default undefined */
402
+ readonly errorMatcher: _angular_core.InputSignal<KtFieldErrorMatcher | undefined>;
403
+ /** Afficher toutes les erreurs au lieu de la première seule. @default KT_FIELD_CONFIG.showAllErrors ?? false */
404
+ readonly showAllErrors: _angular_core.InputSignal<boolean>;
405
+ /** Égalité des valeurs en mode objet (défaut : identité `===`). */
406
+ readonly compareWith: _angular_core.InputSignal<((a: V, b: V) => boolean) | undefined>;
407
+ private readonly idGen;
408
+ private readonly uid;
409
+ protected readonly baseId: _angular_core.Signal<string>;
410
+ protected readonly labelId: _angular_core.Signal<string>;
411
+ protected readonly hintId: _angular_core.Signal<string>;
412
+ protected readonly errorId: _angular_core.Signal<string>;
413
+ private readonly matcher;
414
+ protected readonly showInvalid: _angular_core.Signal<boolean>;
415
+ protected readonly displayedErrors: _angular_core.Signal<readonly WithOptionalFieldTree<ValidationError>[]>;
416
+ protected readonly resolvedAriaLabel: _angular_core.Signal<string | null>;
417
+ protected readonly describedBy: _angular_core.Signal<string | null>;
418
+ private readonly comparator;
419
+ /** La valeur d'option d'un enfant est-elle dans la sélection ? (lu dans le `computed` enfant) */
420
+ isSelected(optionValue: V): boolean;
421
+ /** Ajoute/retire une valeur d'option de la sélection (émis par un enfant au `change` natif). */
422
+ toggle(optionValue: V, checked: boolean): void;
423
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtCheckboxGroup<any>, never>;
424
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<KtCheckboxGroup<any>, "kt-checkbox-group", 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; }; "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; }; "compareWith": { "alias": "compareWith"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "touched": "touchedChange"; }, never, ["*"], true, never>;
425
+ }
426
+
427
+ /**
428
+ * Case à cocher (Checkbox) accessible conforme aux normes WAI-ARIA / RGAA.
429
+ * Bâtie sur un `<input type="checkbox">` NATIF (clavier, clic-label, état `indeterminate`,
430
+ * mode contraste élevé gratuits), redessinée via `appearance: none` + pseudo-éléments thémés.
431
+ *
432
+ * DEUX MODES, selon la présence d'un `kt-checkbox-group` parent :
433
+ * - Autonome : `value` est l'état coché (`boolean`, two-way), intégré aux Signal Forms via
434
+ * `FormValueControl<boolean>` (même contrat que `kt-switch`).
435
+ * - Dans un groupe : `value` est la VALEUR d'option représentée ; l'état coché dérive de
436
+ * l'appartenance au tableau du groupe, et le (dé)cochage met à jour ce tableau.
437
+ *
438
+ * Libellé : `label` (texte) par défaut ; un contenu projeté le remplace visuellement pour les
439
+ * rendus riches (carte/option), `ariaLabel` portant alors le nom accessible si besoin.
440
+ *
441
+ * @example
442
+ * ```html
443
+ * <!-- Autonome -->
444
+ * <kt-checkbox label="Accepter les conditions" [(value)]="accepted" required />
445
+ *
446
+ * <!-- Dans un groupe -->
447
+ * <kt-checkbox-group label="Centres d'intérêt" [(value)]="interests">
448
+ * <kt-checkbox [value]="'sport'" label="Sport" />
449
+ * <kt-checkbox [value]="'musique'" label="Musique" />
450
+ * </kt-checkbox-group>
451
+ * ```
452
+ */
453
+ declare class KtCheckbox<V = boolean> implements FormValueControl<V> {
454
+ private readonly config;
455
+ /** Groupe parent optionnel : présent ⇒ la case appartient à un `kt-checkbox-group`. */
456
+ protected readonly group: KtCheckboxGroup<V> | null;
457
+ /** Autonome : état coché (`boolean`, two-way). En groupe : la valeur d'option représentée. */
458
+ readonly value: _angular_core.ModelSignal<V>;
459
+ /** Tri-état visuel (parent d'une arborescence) : propriété DOM `indeterminate`, pas un attribut. */
460
+ readonly indeterminate: _angular_core.InputSignalWithTransform<boolean, unknown>;
461
+ /** État « touché » (two-way), généralement piloté par `[formField]`. @default false */
462
+ readonly touched: _angular_core.ModelSignal<boolean>;
463
+ /** Désactive la case (héritable du groupe parent). @default false */
464
+ readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
465
+ /** Marque la case comme invalide (combiné à `touched`/`dirty` via l'`errorMatcher`). @default false */
466
+ readonly invalid: _angular_core.InputSignal<boolean>;
467
+ /** Affiche l'astérisque requis et `aria-required`. @default false */
468
+ readonly required: _angular_core.InputSignalWithTransform<boolean, unknown>;
469
+ /** État « modifié » (entre dans la logique d'affichage des erreurs). @default false */
470
+ readonly dirty: _angular_core.InputSignal<boolean>;
471
+ /** Erreurs de validation à afficher sous la case. @default [] */
472
+ readonly errors: _angular_core.InputSignal<readonly WithOptionalFieldTree<ValidationError>[]>;
473
+ /** Attribut `name` du `<input>` natif. @default '' */
474
+ readonly name: _angular_core.InputSignal<string>;
475
+ /** id imposé (sélecteurs de test stables) ; sinon auto-généré, anti-collision. @default undefined */
476
+ readonly id: _angular_core.InputSignal<string | undefined>;
477
+ /** Texte du libellé (remplacé visuellement par un contenu projeté). @default undefined */
478
+ readonly label: _angular_core.InputSignal<string | undefined>;
479
+ /** Texte d'aide affiché sous la case (masqué quand une erreur s'affiche). @default undefined */
480
+ readonly hint: _angular_core.InputSignal<string | undefined>;
481
+ /** Nom accessible (`aria-label`) pour une case sans libellé textuel. @default undefined */
482
+ readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
483
+ /** Stratégie décidant quand afficher les erreurs (sinon celle du `KT_FIELD_CONFIG`). @default undefined */
484
+ readonly errorMatcher: _angular_core.InputSignal<KtFieldErrorMatcher | undefined>;
485
+ /** Afficher toutes les erreurs au lieu de la première seule. @default KT_FIELD_CONFIG.showAllErrors ?? false */
486
+ readonly showAllErrors: _angular_core.InputSignal<boolean>;
487
+ private readonly inputEl;
488
+ private readonly idGen;
489
+ private readonly uid;
490
+ protected readonly baseId: _angular_core.Signal<string>;
491
+ protected readonly hintId: _angular_core.Signal<string>;
492
+ protected readonly errorId: _angular_core.Signal<string>;
493
+ /** Coché : appartenance au groupe le cas échéant, sinon l'état booléen propre.
494
+ (Nommé `isChecked` car `FormValueControl` réserve la propriété `checked`.) */
495
+ protected readonly isChecked: _angular_core.Signal<boolean>;
496
+ /** Désactivé : hérité du groupe le cas échéant. */
497
+ protected readonly isDisabled: _angular_core.Signal<boolean>;
498
+ private readonly matcher;
499
+ protected readonly showInvalid: _angular_core.Signal<boolean>;
500
+ protected readonly displayedErrors: _angular_core.Signal<readonly WithOptionalFieldTree<ValidationError>[]>;
501
+ protected readonly resolvedAriaLabel: _angular_core.Signal<string | null>;
502
+ protected readonly describedBy: _angular_core.Signal<string | null>;
503
+ constructor();
504
+ protected onChange(event: Event): void;
505
+ protected onBlur(): void;
506
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtCheckbox<any>, never>;
507
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<KtCheckbox<any>, "kt-checkbox", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "indeterminate": { "alias": "indeterminate"; "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; }; "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>;
508
+ }
509
+
510
+ /**
511
+ * Groupe de boutons radio (Radio Group) conforme à l'ARIA APG / RGAA.
512
+ * Orchestrateur : porte la valeur (`FormValueControl<V | null>`), génère le `name` partagé et la
513
+ * sémantique de groupe (`role="radiogroup"`, légende, `aria-required`/`aria-invalid`, erreurs).
514
+ *
515
+ * Le clavier (roving tabindex + flèches qui déplacent ET cochent) est laissé au NATIF : les
516
+ * `<input type="radio">` des `kt-radio` enfants partagent le `name` du groupe — rien à réimplémenter.
517
+ * Les options sont fournies par le dev (boucle `@for` ou déclaration en dur) ; `compareWith` gère
518
+ * l'égalité quand `value` est un objet.
519
+ *
520
+ * @example
521
+ * ```html
522
+ * <kt-radio-group label="Civilité" [(value)]="civility" required>
523
+ * <kt-radio [value]="'mme'" label="Madame" />
524
+ * <kt-radio [value]="'m'" label="Monsieur" />
525
+ * <kt-radio [value]="'autre'" label="Autre" />
526
+ * </kt-radio-group>
527
+ * ```
528
+ */
529
+ declare class KtRadioGroup<V> implements FormValueControl<V | null> {
530
+ private readonly config;
531
+ /** Valeur sélectionnée (two-way), ou `null` si aucune option n'est cochée. @default null */
532
+ readonly value: _angular_core.ModelSignal<V | null>;
533
+ /** État « touché » (two-way), généralement piloté par `[formField]`. @default false */
534
+ readonly touched: _angular_core.ModelSignal<boolean>;
535
+ /** Désactive le groupe entier (hérité par chaque radio enfant). @default false */
536
+ readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
537
+ /** Marque le groupe comme invalide (combiné à `touched`/`dirty` via l'`errorMatcher`). @default false */
538
+ readonly invalid: _angular_core.InputSignal<boolean>;
539
+ /** Affiche l'astérisque requis et `aria-required` sur le groupe. @default false */
540
+ readonly required: _angular_core.InputSignalWithTransform<boolean, unknown>;
541
+ /** État « modifié » (entre dans la logique d'affichage des erreurs). @default false */
542
+ readonly dirty: _angular_core.InputSignal<boolean>;
543
+ /** Erreurs de validation à afficher sous le groupe. @default [] */
544
+ readonly errors: _angular_core.InputSignal<readonly WithOptionalFieldTree<ValidationError>[]>;
545
+ /** Base du `name` partagé par les radios enfants (sinon auto-généré). @default '' */
546
+ readonly name: _angular_core.InputSignal<string>;
547
+ /** id imposé (sélecteurs de test stables) ; sinon auto-généré, anti-collision. @default undefined */
548
+ readonly id: _angular_core.InputSignal<string | undefined>;
549
+ /** Légende du groupe (`aria-labelledby`). @default undefined */
550
+ readonly label: _angular_core.InputSignal<string | undefined>;
551
+ /** Texte d'aide affiché sous le groupe (masqué quand une erreur s'affiche). @default undefined */
552
+ readonly hint: _angular_core.InputSignal<string | undefined>;
553
+ /** Nom accessible (`aria-label`) du groupe quand `label` est absent. @default undefined */
554
+ readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
555
+ /** Stratégie décidant quand afficher les erreurs (sinon celle du `KT_FIELD_CONFIG`). @default undefined */
556
+ readonly errorMatcher: _angular_core.InputSignal<KtFieldErrorMatcher | undefined>;
557
+ /** Afficher toutes les erreurs au lieu de la première seule. @default KT_FIELD_CONFIG.showAllErrors ?? false */
558
+ readonly showAllErrors: _angular_core.InputSignal<boolean>;
559
+ /** Égalité des valeurs en mode objet (défaut : identité `===`). Seul rescapé du contrat select. */
560
+ readonly compareWith: _angular_core.InputSignal<((a: V, b: V) => boolean) | undefined>;
561
+ private readonly idGen;
562
+ private readonly uid;
563
+ protected readonly baseId: _angular_core.Signal<string>;
564
+ /** `name` partagé par les radios enfants → regroupement clavier NATIF (roving + flèches). */
565
+ readonly groupName: _angular_core.Signal<string>;
566
+ protected readonly labelId: _angular_core.Signal<string>;
567
+ protected readonly hintId: _angular_core.Signal<string>;
568
+ protected readonly errorId: _angular_core.Signal<string>;
569
+ private readonly matcher;
570
+ protected readonly showInvalid: _angular_core.Signal<boolean>;
571
+ protected readonly displayedErrors: _angular_core.Signal<readonly WithOptionalFieldTree<ValidationError>[]>;
572
+ protected readonly resolvedAriaLabel: _angular_core.Signal<string | null>;
573
+ protected readonly describedBy: _angular_core.Signal<string | null>;
574
+ private readonly comparator;
575
+ /** Le `value` d'un enfant correspond-il à la sélection courante ? (lu dans le `computed` enfant) */
576
+ isSelected(radioValue: V): boolean;
577
+ /** Commit d'une sélection émis par un enfant au `change` natif. */
578
+ select(radioValue: V): void;
579
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtRadioGroup<any>, never>;
580
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<KtRadioGroup<any>, "kt-radio-group", 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; }; "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; }; "compareWith": { "alias": "compareWith"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "touched": "touchedChange"; }, never, ["*"], true, never>;
581
+ }
582
+
583
+ /**
584
+ * Bouton radio individuel (enfant déclaratif de `kt-radio-group`).
585
+ * `<input type="radio">` NATIF partageant le `name` du groupe : clavier (roving + flèches) gratuit.
586
+ * Le libellé suit la même règle que la checkbox : `label` texte par défaut, contenu projeté en
587
+ * override visuel (carte sélectionnable), `ariaLabel` pour le nom accessible d'une option non-textuelle.
588
+ *
589
+ * @example
590
+ * ```html
591
+ * <kt-radio-group label="Civilité" [(value)]="civility">
592
+ * <kt-radio [value]="'mme'" label="Madame" />
593
+ * <kt-radio [value]="'m'" label="Monsieur" />
594
+ * </kt-radio-group>
595
+ * ```
596
+ */
597
+ declare class KtRadio<V> {
598
+ protected readonly group: KtRadioGroup<V>;
599
+ /** Valeur d'option représentée par ce radio (sélectionnée ⇒ devient la valeur du groupe). @default (requis) */
600
+ readonly value: _angular_core.InputSignal<V>;
601
+ /** Texte du libellé (remplacé visuellement par un contenu projeté). @default undefined */
602
+ readonly label: _angular_core.InputSignal<string | undefined>;
603
+ /** Texte d'aide affiché sous le radio. @default undefined */
604
+ readonly hint: _angular_core.InputSignal<string | undefined>;
605
+ /** Nom accessible (`aria-label`) pour une option sans libellé textuel. @default undefined */
606
+ readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
607
+ /** Désactive ce radio (combiné à l'état désactivé du groupe). @default false */
608
+ readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
609
+ /** id imposé (sélecteurs de test stables) ; sinon auto-généré, anti-collision. @default undefined */
610
+ readonly id: _angular_core.InputSignal<string | undefined>;
611
+ private readonly idGen;
612
+ private readonly uid;
613
+ protected readonly baseId: _angular_core.Signal<string>;
614
+ protected readonly hintId: _angular_core.Signal<string>;
615
+ protected readonly checked: _angular_core.Signal<boolean>;
616
+ protected readonly isDisabled: _angular_core.Signal<boolean>;
617
+ protected onChange(): void;
618
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtRadio<any>, never>;
619
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<KtRadio<any>, "kt-radio", never, { "value": { "alias": "value"; "required": true; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
620
+ }
621
+
622
+ /** Clé (propriété) OU fonction d'accès, pour dériver une valeur d'un item.
623
+ Partagé par les sélecteurs (BaseSelect) et les chips (ChipList). */
624
+ type KtKeyish<T, R> = keyof T | ((item: T) => R);
625
+
626
+ /** Base partagée des sélecteurs à liste fermée (Select single et MultiSelect), bâtis sur
627
+ `@angular/aria` (Combobox + Listbox) : options et dérivation (clé/fonction), état poussé
628
+ par `[formField]`, popup Popover responsive (dropdown ancré desktop ↔ bottom-sheet
629
+ téléphone, drag-to-dismiss), filtrage opt-in avec live region, clavier commun (Échap
630
+ global, Tab APG depuis le filtre). La VALEUR (`V | null` vs `V[]`) et `selectionChange`
631
+ restent dans les sous-classes : leurs types divergent, chacune implémente seule
632
+ `FormValueControl<…>`. Même pattern d'héritage que `BaseInputField`.
633
+
634
+ @template T Type d'une option (élément du tableau `options`).
635
+ @template V Type de la valeur émise par le contrôle (défaut `T` : l'objet entier ;
636
+ ou la clé extraite quand `optionValue` est fourni). */
637
+ declare abstract class KtBaseSelect<T, V = T> {
638
+ protected readonly fieldConfig: Partial<_ktortu_aaa_forms.KtFieldConfig> | null;
639
+ protected readonly config: Partial<_ktortu_aaa_forms.KtSelectConfigOptions> | null;
640
+ protected readonly host: ElementRef<HTMLElement>;
641
+ private readonly ngZone;
642
+ protected readonly doc: Document;
643
+ private readonly platformId;
644
+ private readonly destroyRef;
645
+ private wasExpanded;
646
+ /** Liste des options affichées (source de vérité du contrôle). */
647
+ readonly options: _angular_core.InputSignal<readonly T[]>;
648
+ /** Libellé affiché d'une option : clé OU fonction. Défaut : `label`/`name`, sinon `String(option)`. */
649
+ readonly optionLabel: _angular_core.InputSignal<KtKeyish<T, string> | undefined>;
650
+ /** Dérive la valeur de sortie ET l'identité d'une option.
651
+ - Fourni (clé/fonction) ⇒ `value` = la/les clé(s) extraite(s).
652
+ - Omis ⇒ `value` = l'objet entier ; l'identité interne dérive de `id`/`value`. */
653
+ readonly optionValue: _angular_core.InputSignal<KtKeyish<T, V> | undefined>;
654
+ /** Désactivation d'une option : clé OU fonction renvoyant un booléen. Défaut : aucune option désactivée. */
655
+ readonly optionDisabled: _angular_core.InputSignal<KtKeyish<T, boolean> | undefined>;
656
+ /** Égalité des options en mode objet (présélection). Défaut : comparaison par identité (`id`/`value`). */
657
+ readonly compareWith: _angular_core.InputSignal<((a: T, b: T) => boolean) | undefined>;
658
+ /** Émis au clic sur le bouton d'aide contextuelle. */
659
+ readonly helpClick: _angular_core.OutputEmitterRef<MouseEvent>;
660
+ /** Le champ a-t-il été visité ? Poussé par `[formField]` ; passe à `true` à la première sélection. @default false */
661
+ readonly touched: _angular_core.ModelSignal<boolean>;
662
+ /** Champ désactivé (trigger inerte). Poussé par `[formField]`. @default false */
663
+ readonly disabled: _angular_core.InputSignal<boolean>;
664
+ /** Champ en lecture seule (sélection figée, valeur affichée). Poussé par `[formField]`. @default false */
665
+ readonly readonly: _angular_core.InputSignal<boolean>;
666
+ /** Le champ est-il invalide ? Pilote l'affichage des erreurs. Poussé par `[formField]`. @default false */
667
+ readonly invalid: _angular_core.InputSignal<boolean>;
668
+ /** Champ obligatoire (marqueur visuel/ARIA). Poussé par `[formField]`. @default false */
669
+ readonly required: _angular_core.InputSignal<boolean>;
670
+ /** Le champ a-t-il été modifié depuis sa valeur initiale ? Poussé par `[formField]`. @default false */
671
+ readonly dirty: _angular_core.InputSignal<boolean>;
672
+ /** Erreurs de validation à afficher. Poussé par `[formField]`. @default [] */
673
+ readonly errors: _angular_core.InputSignal<readonly WithOptionalFieldTree<ValidationError>[]>;
674
+ /** Attribut `name` logique du contrôle (à titre indicatif). @default '' */
675
+ readonly name: _angular_core.InputSignal<string>;
676
+ /** id imposé (sélecteurs de test stables) ; sinon auto-généré par Field. @default undefined */
677
+ readonly id: _angular_core.InputSignal<string | undefined>;
678
+ /** Libellé du champ (rendu par Field). @default undefined */
679
+ readonly label: _angular_core.InputSignal<string | undefined>;
680
+ /** Texte d'aide affiché sous le champ quand il est valide. @default undefined */
681
+ readonly hint: _angular_core.InputSignal<string | undefined>;
682
+ /** Aide contextuelle riche : texte ou `TemplateRef` rendu dans une infobulle d'aide. @default undefined */
683
+ readonly helpText: _angular_core.InputSignal<string | TemplateRef<unknown> | undefined>;
684
+ /** Libellé accessible du bouton d'aide. @default 'Help' (ou KT_FIELD_CONFIG.helpLabel) */
685
+ readonly helpLabel: _angular_core.InputSignal<string>;
686
+ /** Force la valeur de `aria-describedby` (sinon dérivée de hint/erreur). @default undefined */
687
+ readonly customDescribedBy: _angular_core.InputSignal<string | undefined>;
688
+ /** Texte indicatif affiché quand aucune option n'est sélectionnée. @default undefined */
689
+ readonly placeholder: _angular_core.InputSignal<string | undefined>;
690
+ /** Quand afficher l'erreur ; surcharge KT_FIELD_CONFIG et le défaut (`invalid && touched`). @default undefined */
691
+ readonly errorMatcher: _angular_core.InputSignal<KtFieldErrorMatcher | undefined>;
692
+ /** Affiche un champ de recherche en tête du popup (desktop) / de la sheet (téléphone).
693
+ Pour les listes longues ; le texte tapé ne sert qu'à filtrer (réinitialisé à la fermeture). */
694
+ readonly filterable: _angular_core.InputSignal<boolean>;
695
+ /** Placeholder du champ de recherche du popup. Défaut : `KT_SELECT_CONFIG.filterPlaceholder` ou vide. */
696
+ readonly filterPlaceholder: _angular_core.InputSignal<string | undefined>;
697
+ /** Libellé accessible du champ de recherche. Défaut : `KT_SELECT_CONFIG.filterLabel` ou « Filter options ». */
698
+ readonly filterLabel: _angular_core.InputSignal<string | undefined>;
699
+ /** Prédicat de filtre custom `(option, texte tapé brut)`.
700
+ Défaut : libellé de l'option, insensible à la casse et aux accents. */
701
+ readonly filterFn: _angular_core.InputSignal<((option: T, query: string) => boolean) | undefined>;
702
+ /** Nombre maximal d'options affichées dans le DOM en mode filtrable pour optimiser les performances. @default 100 */
703
+ readonly maxVisibleOptions: _angular_core.InputSignal<number>;
704
+ /** Texte informatif de troncature des résultats (visuel). */
705
+ readonly truncatedResultsText: _angular_core.InputSignal<((max: number, total: number) => string) | undefined>;
706
+ /** Annonce de la troncature des résultats (live region). */
707
+ readonly truncatedResultsAnnouncement: _angular_core.InputSignal<((max: number, total: number) => string) | undefined>;
708
+ protected readonly expanded: _angular_core.WritableSignal<boolean>;
709
+ protected readonly viewport: KtViewport;
710
+ /** Écran compact (téléphone / fenêtre étroite) : bascule le popup en bottom-sheet modale.
711
+ Source unique configurable par appli (`KtViewport` / `provideKtBreakpoints`) ; pilote aussi
712
+ la classe CSS `kt-select__popup--sheet` du template. */
713
+ protected readonly compact: Signal<boolean>;
714
+ protected readonly triggerEl: Signal<ElementRef<HTMLElement> | undefined>;
715
+ protected readonly popupEl: Signal<ElementRef<HTMLElement> | undefined>;
716
+ private readonly idGen;
717
+ private readonly uid;
718
+ private readonly anchorName;
719
+ /** id du panneau (élément widget) en mode filtrable — cible de l'aria-controls du trigger. */
720
+ protected readonly panelId: string;
721
+ protected readonly filterInputEl: Signal<ElementRef<HTMLInputElement> | undefined>;
722
+ protected readonly listboxEl: Signal<ElementRef<HTMLElement> | undefined>;
723
+ protected readonly listboxDir: Signal<Listbox<any> | undefined>;
724
+ protected readonly comboboxDir: Signal<Combobox | undefined>;
725
+ /** Suit l'état réel du Popover : la fermeture peut être synchrone (Tab) ET pilotée par
726
+ l'effect — sans ce flag, le second `hidePopover()` jetterait une InvalidStateError. */
727
+ private popoverShown;
728
+ private readonly matcher;
729
+ protected readonly showInvalid: Signal<boolean>;
730
+ protected readonly resolvedPlaceholder: Signal<string>;
731
+ protected readonly resolvedEmptyText: Signal<string>;
732
+ protected readonly resolvedCloseLabel: Signal<string>;
733
+ protected readonly resolvedFilterPlaceholder: Signal<string>;
734
+ protected readonly resolvedFilterLabel: Signal<string>;
735
+ protected readonly resolvedFilterResultsText: Signal<(count: number) => string>;
736
+ protected readonly resolvedTruncatedResultsText: Signal<(max: number, total: number) => string>;
737
+ protected readonly resolvedTruncatedResultsAnnouncement: Signal<(max: number, total: number) => string>;
738
+ protected readonly fieldErrors: Signal<{
739
+ kind: string;
740
+ message: string | undefined;
741
+ }[]>;
742
+ private readonly labelAccessor;
743
+ private readonly valueAccessor;
744
+ private readonly disabledAccessor;
745
+ /** Comparateur effectif en mode objet : `compareWith`, sinon égalité par identité. */
746
+ protected readonly comparator: Signal<(a: T, b: T) => boolean>;
747
+ protected labelOf(item: T): string;
748
+ protected keyOf(item: T): unknown;
749
+ protected disabledOf(item: T): boolean;
750
+ protected readonly filterText: _angular_core.WritableSignal<string>;
751
+ /** Annonce différée du nombre de résultats (live region `role="status"`). */
752
+ protected readonly announcedCount: _angular_core.WritableSignal<string>;
753
+ private announceTimer;
754
+ /** Options visibles : les options, restreintes par le filtre quand il est actif. */
755
+ protected readonly filteredOptions: Signal<readonly T[]>;
756
+ /** Les options affichées dans le DOM. La limitation (maxVisibleOptions) n'est appliquée qu'en mode filtrable. */
757
+ protected readonly displayedOptions: Signal<readonly T[]>;
758
+ /** Valeur poussée au ngListbox sous-jacent : tableau de clés (0/1 en single, N en multi). */
759
+ protected abstract readonly listboxValue: Signal<unknown[]>;
760
+ /** Réception des (dé)sélections du listbox — la sémantique de commit diverge (single/multi). */
761
+ protected abstract onListboxValueChange(keys: readonly unknown[]): void;
762
+ /** Texte de la live region du filtre. Virtuel : le multi y ajoute « , M selected ». */
763
+ protected composeFilterAnnouncement(): string;
764
+ constructor();
765
+ protected onFilterInput(event: Event): void;
766
+ /** Relaye la navigation vers le listbox : le focus DOM est dans le champ de filtre et les
767
+ keydown du popup ne remontent pas au combobox (le popup est un sibling DOM du trigger).
768
+ Shift+flèches : extension de plage (multi ; sans effet en single). Home/End/Espace/
769
+ caractères restent dans le champ (convention APG des combobox éditables). */
770
+ protected onFilterKeydown(event: KeyboardEvent): void;
771
+ /** Échap depuis n'importe où dans le composant popup ouvert : après un clic souris sur une
772
+ option, le focus DOM est sur le listbox (pas le trigger) — ni le listbox ni le combobox ne
773
+ gèrent Échap là. Le popup est rendu dans le sous-arbre DOM de l'hôte : l'événement y bulle.
774
+ (Trigger et champ de filtre gèrent leur Échap en amont avec stopPropagation : pas de doublon.) */
775
+ protected onHostKeydown(event: KeyboardEvent): void;
776
+ /** Annonce le contenu du filtre ~500 ms après la dernière frappe (évite le spam SR). */
777
+ protected scheduleResultsAnnouncement(): void;
778
+ /** Annonce immédiate dans la live region du panneau (annule une annonce différée en attente). */
779
+ protected announceNow(text: string): void;
780
+ /** Séquelle de la purge interne du Listbox (il vide sa valeur dès qu'un item n'est plus
781
+ rendu) : quand le filtre redécouvre des options sélectionnées, le binding `[value]` ne
782
+ re-pousse rien (`listboxValue` n'a pas changé) — on resynchronise le modèle du Listbox
783
+ avec les clés sélectionnées actuellement visibles. */
784
+ protected resyncListboxSelection(): void;
785
+ /** Desktop filtrable : le focus DOM vit dans le popup (champ/options) — on le rend au trigger
786
+ à la fermeture, sinon il tombe sur `<body>`. (Écran compact : déjà géré par l'effect `compact`.) */
787
+ protected refocusTriggerAfterFilterClose(): void;
788
+ /** Fermeture synchrone du Popover (l'effect, différé, ne re-cachera pas : flag popoverShown). */
789
+ protected closePopupNow(): void;
790
+ private readonly sheetDrag;
791
+ protected onDragStart(event: PointerEvent): void;
792
+ private animateAndCloseSelect;
793
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtBaseSelect<any, any>, never>;
794
+ 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; }; "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; }; "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>;
795
+ }
796
+
797
+ /** Contexte typé reçu par le template d'une option (`ktSelectOption`). */
798
+ interface KtSelectOptionContext<T> {
799
+ /** L'option en cours de rendu → `let-option`. */
800
+ $implicit: T;
801
+ /** L'option est-elle sélectionnée ? → `let-selected="selected"`. */
802
+ selected: boolean;
803
+ /** L'option est-elle active (survol/clavier) ? → `let-active="active"`. */
804
+ active: boolean;
805
+ }
806
+ /** Contexte typé reçu par le template du trigger (`ktSelectTrigger`). */
807
+ interface KtSelectTriggerContext<T> {
808
+ /** L'option sélectionnée (ou `null`) → `let-option`. */
809
+ $implicit: T | null;
810
+ }
811
+ /** Template de rendu d'une option, posé sur un `<ng-template>` projeté dans `kt-select`.
812
+ L'input sert UNIQUEMENT à inférer `T` (re-bind de la liste d'options) ; `ngTemplateContextGuard`
813
+ type alors les variables `let-` (`option: T`, `selected`/`active: boolean`). Requiert `strictTemplates`.
814
+
815
+ ```html
816
+ <kt-select [options]="users" optionLabel="name">
817
+ <ng-template [ktSelectOption]="users" let-user let-selected="selected">
818
+ <user-badge [user]="user" /> @if (selected) { ✓ }
819
+ </ng-template>
820
+ </kt-select>
821
+ ``` */
822
+ declare class KtSelectOptionDef<T> {
823
+ readonly ktSelectOption: _angular_core.InputSignal<readonly T[]>;
824
+ readonly template: TemplateRef<KtSelectOptionContext<T>>;
825
+ static ngTemplateContextGuard<T>(_dir: KtSelectOptionDef<T>, ctx: unknown): ctx is KtSelectOptionContext<T>;
826
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtSelectOptionDef<any>, never>;
827
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<KtSelectOptionDef<any>, "ng-template[ktSelectOption]", never, { "ktSelectOption": { "alias": "ktSelectOption"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
828
+ }
829
+ /** Template de rendu du trigger (libellé de la valeur courante). Même mécanisme typé que `ktSelectOption`.
830
+ Contexte : `let-option` = l'option sélectionnée (`T | null`).
831
+
832
+ ```html
833
+ <kt-select [options]="users" [(value)]="selected">
834
+ <ng-template [ktSelectTrigger]="users" let-user>
835
+ @if (user) { <user-badge [user]="user" /> } @else { Choisir… }
836
+ </ng-template>
837
+ </kt-select>
838
+ ``` */
839
+ declare class KtSelectTriggerDef<T> {
840
+ readonly ktSelectTrigger: _angular_core.InputSignal<readonly T[]>;
841
+ readonly template: TemplateRef<KtSelectTriggerContext<T>>;
842
+ static ngTemplateContextGuard<T>(_dir: KtSelectTriggerDef<T>, ctx: unknown): ctx is KtSelectTriggerContext<T>;
843
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtSelectTriggerDef<any>, never>;
844
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<KtSelectTriggerDef<any>, "ng-template[ktSelectTrigger]", never, { "ktSelectTrigger": { "alias": "ktSelectTrigger"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
845
+ }
846
+
847
+ /** Payload de l'évènement `selectionChange` d'un `kt-select`. */
848
+ interface KtSelectSelectionChange<T, V = T> {
849
+ /** Valeur émise : clé extraite ou objet entier (`null` si la sélection est effacée). */
850
+ value: V | null;
851
+ /** Option correspondante (`null` si la sélection est effacée). */
852
+ option: T | null;
853
+ }
854
+ /** Select single (« select-only combobox » WAI-ARIA) bâti sur `@angular/aria`.
855
+ Choix dans une liste fermée, sans saisie. Présentation responsive (un seul Popover, CSS @media) :
856
+ desktop = dropdown ancré (focus sur le trigger / activedescendant) ; téléphone tactile = bottom-sheet
857
+ en bas d'écran (focusMode 'roving', options réellement focusables, scrim ::backdrop, cibles ≥44px).
858
+ Composé avec `Field` ; s'intègre aux Signal Forms via `[formField]`.
859
+ Tout le commun (popup, filtre, clavier, drag-to-dismiss) vit dans `BaseSelect`.
860
+
861
+ @template T Type d'une option (élément du tableau `options`).
862
+ @template V Type de la valeur émise (défaut `T` ; clé extraite si `optionValue` est fourni).
863
+
864
+ @example
865
+ ```html
866
+ <kt-select [options]="users" optionLabel="name" optionValue="id" [(value)]="selectedId" />
867
+ ``` */
868
+ declare class KtSelect<T, V = T> extends KtBaseSelect<T, V> implements FormValueControl<V | null> {
869
+ /** Valeur sélectionnée (clé extraite, ou objet entier si `optionValue` est omis ; `null` si rien). @default null */
870
+ readonly value: _angular_core.ModelSignal<V | null>;
871
+ /** Émis à chaque sélection. Payload : `{ value, option }` — `value` est la valeur émise (clé ou objet),
872
+ `option` l'objet option correspondant (`null` si la sélection est effacée). */
873
+ readonly selectionChange: _angular_core.OutputEmitterRef<KtSelectSelectionChange<T, V>>;
874
+ protected readonly optionDef: _angular_core.Signal<KtSelectOptionDef<any> | undefined>;
875
+ protected readonly triggerDef: _angular_core.Signal<KtSelectTriggerDef<any> | undefined>;
876
+ /** Fermer le popup après une sélection (sémantique single ; le multi reste ouvert). */
877
+ private readonly closeOnSelect;
878
+ /** Option correspondant à la valeur courante (clé extraite, ou objet si `optionValue` est omis). */
879
+ protected readonly selectedOption: _angular_core.Signal<T | null>;
880
+ /** Valeur du listbox : tableau de clés (0 ou 1 élément en single). */
881
+ protected readonly listboxValue: _angular_core.Signal<unknown[]>;
882
+ protected onListboxValueChange(keys: readonly unknown[]): void;
883
+ /** La sélection courante est-elle masquée par le filtre ou la troncation ? (≠ retirée des données). */
884
+ private isSelectionFilteredOut;
885
+ private commitSelection;
886
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtSelect<any, any>, never>;
887
+ 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>;
888
+ }
889
+
890
+ /** Défauts applicables à tous les `kt-select` (surchargeables par champ via les inputs).
891
+ Lib neutre i18n : les textes sont fournis par le consommateur (ici en une fois).
892
+ Fourni en `Partial` : un consommateur n'override que ce qu'il veut.
893
+ Calqué sur `KT_FIELD_CONFIG`. */
894
+ interface KtSelectConfigOptions {
895
+ /** Texte affiché quand aucune option n'est sélectionnée. */
896
+ placeholder: string;
897
+ /** Texte affiché quand la liste filtrée/d'options est vide. */
898
+ emptyText: string;
899
+ /** Libellé accessible du bouton de fermeture de la bottom-sheet mobile. */
900
+ closeLabel: string;
901
+ /** Fermer le popup après une sélection. Défaut (single) : `true`. */
902
+ closeOnSelect: boolean;
903
+ /** Placeholder du champ de filtre des select filtrables (`[filterable]`). */
904
+ filterPlaceholder: string;
905
+ /** Libellé accessible (aria-label) du champ de filtre. */
906
+ filterLabel: string;
907
+ /** Annonce du nombre de résultats du filtre (live region). Fonction : laisse le
908
+ consommateur gérer les pluriels i18n. Défaut : `'1 result'` / `'N results'`. */
909
+ filterResultsText: (count: number) => string;
910
+ /** Libellé accessible du bouton de retrait d'un chip. Défaut : `'Remove X'`. */
911
+ removeItemLabel: (itemLabel: string) => string;
912
+ /** Libellé accessible du conteneur de chips (reçoit le label du champ, pour
913
+ distinguer plusieurs multi-selects d'une page). Défaut : `'Selected items for X'`. */
914
+ selectedItemsLabel: (fieldLabel: string | undefined) => string;
915
+ /** Résumé affiché sur le trigger au-delà du seuil d'énumération. Défaut : `'N items selected'`. */
916
+ selectionSummaryText: (count: number) => string;
917
+ /** Annonce live après le retrait d'un élément (chip ou tout effacer). Défaut : `'X removed'`. */
918
+ itemRemovedText: (itemLabel: string) => string;
919
+ /** Compteur de sélection (live region du filtre, actions de masse). Défaut : `'N selected'`. */
920
+ selectionCountText: (count: number) => string;
921
+ /** Libellé du bouton « tout sélectionner » du popup (`[selectionActions]`). Défaut : `'Select all'`. */
922
+ selectAllLabel: string;
923
+ /** Libellé du bouton « tout effacer » du popup (`[selectionActions]`). Défaut : `'Clear all'`. */
924
+ clearAllLabel: string;
925
+ /** Libellé du bouton dépliant les chips repliés (`[maxVisibleChips]`). Défaut : `'+N more'`. */
926
+ moreChipsLabel: (hiddenCount: number) => string;
927
+ /** Libellé du même bouton une fois déplié. Défaut : `'Show less'`. */
928
+ lessChipsLabel: string;
929
+ /** Texte informatif de troncature des résultats (visuel). Défaut : `'Showing first X results of Y...'`. */
930
+ truncatedResultsText: (max: number, total: number) => string;
931
+ /** Annonce de la troncature des résultats (live region). Défaut : `'X results displayed out of Y...'`. */
932
+ truncatedResultsAnnouncement: (max: number, total: number) => string;
933
+ }
934
+ declare const KT_SELECT_CONFIG: InjectionToken<Partial<KtSelectConfigOptions>>;
935
+
936
+ /** Configure les `kt-select` d'un sous-arbre via DI (équivalent du Context provider de react-select).
937
+ Alternative à un provider global de `KT_SELECT_CONFIG` : on pose la directive sur un conteneur et
938
+ tous les `kt-select` descendants en héritent.
939
+
940
+ ```html
941
+ <div [ktSelectConfig]="{ placeholder: 'Choisir…', emptyText: 'Aucun résultat' }">
942
+ <kt-select … />
943
+ </div>
944
+ ```
945
+
946
+ La directive EST fournie comme `KT_SELECT_CONFIG` (`useExisting`) : les getters exposent l'objet
947
+ bindé sous la forme `Partial<KtSelectConfigOptions>` attendue par le composant. */
948
+ declare class KtSelectConfig implements Partial<KtSelectConfigOptions> {
949
+ readonly ktSelectConfig: _angular_core.InputSignal<Partial<KtSelectConfigOptions>>;
950
+ /** Config héritée du contexte parent (provider global ou directive englobante) : la
951
+ directive ne masque que les clés qu'elle définit, le reste continue d'en hériter. */
952
+ private readonly parent;
953
+ private resolve;
954
+ get placeholder(): string | undefined;
955
+ get emptyText(): string | undefined;
956
+ get closeLabel(): string | undefined;
957
+ get closeOnSelect(): boolean | undefined;
958
+ get filterPlaceholder(): string | undefined;
959
+ get filterLabel(): string | undefined;
960
+ get filterResultsText(): ((count: number) => string) | undefined;
961
+ get removeItemLabel(): ((itemLabel: string) => string) | undefined;
962
+ get selectedItemsLabel(): ((fieldLabel: string | undefined) => string) | undefined;
963
+ get selectionSummaryText(): ((count: number) => string) | undefined;
964
+ get itemRemovedText(): ((itemLabel: string) => string) | undefined;
965
+ get selectionCountText(): ((count: number) => string) | undefined;
966
+ get selectAllLabel(): string | undefined;
967
+ get clearAllLabel(): string | undefined;
968
+ get moreChipsLabel(): ((hiddenCount: number) => string) | undefined;
969
+ get lessChipsLabel(): string | undefined;
970
+ get truncatedResultsText(): ((max: number, total: number) => string) | undefined;
971
+ get truncatedResultsAnnouncement(): ((max: number, total: number) => string) | undefined;
972
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtSelectConfig, never>;
973
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<KtSelectConfig, "[ktSelectConfig]", never, { "ktSelectConfig": { "alias": "ktSelectConfig"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
974
+ }
975
+
976
+ /** Contexte typé reçu par le template d'une option (`ktMultiSelectOption`). */
977
+ interface KtMultiSelectOptionContext<T> {
978
+ /** L'option en cours de rendu → `let-option`. */
979
+ $implicit: T;
980
+ /** L'option est-elle sélectionnée ? → `let-selected="selected"`. */
981
+ selected: boolean;
982
+ /** L'option est-elle active (survol/clavier) ? → `let-active="active"`. */
983
+ active: boolean;
984
+ }
985
+ /** Contexte typé reçu par le template du trigger (`ktMultiSelectTrigger`). */
986
+ interface KtMultiSelectTriggerContext<T> {
987
+ /** Les options sélectionnées (tableau d'objets) → `let-options`. */
988
+ $implicit: readonly T[];
989
+ }
990
+ /** Contexte typé reçu par le template de chip (`ktMultiSelectChip`). */
991
+ interface KtMultiSelectChipContext<T> {
992
+ /** L'option sélectionnée correspondante → `let-option`. */
993
+ $implicit: T;
994
+ /** Fonction pour retirer cet élément de la sélection → `let-remove="remove"`. */
995
+ remove: () => void;
996
+ }
997
+ /** Template de rendu d'une option dans la liste du multi-select. L'input sert à inférer `T` ;
998
+ `ngTemplateContextGuard` type les variables `let-`.
999
+ Contexte : `let-option` = l'option (`T`), `let-selected` / `let-active` = booléens.
1000
+
1001
+ ```html
1002
+ <kt-multi-select [options]="tags">
1003
+ <ng-template [ktMultiSelectOption]="tags" let-tag let-selected="selected">
1004
+ <tag-badge [tag]="tag" /> @if (selected) { ✓ }
1005
+ </ng-template>
1006
+ </kt-multi-select>
1007
+ ``` */
1008
+ declare class KtMultiSelectOptionDef<T> {
1009
+ readonly ktMultiSelectOption: _angular_core.InputSignal<readonly T[]>;
1010
+ readonly template: TemplateRef<KtMultiSelectOptionContext<T>>;
1011
+ static ngTemplateContextGuard<T>(_dir: KtMultiSelectOptionDef<T>, ctx: unknown): ctx is KtMultiSelectOptionContext<T>;
1012
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtMultiSelectOptionDef<any>, never>;
1013
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<KtMultiSelectOptionDef<any>, "ng-template[ktMultiSelectOption]", never, { "ktMultiSelectOption": { "alias": "ktMultiSelectOption"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
1014
+ }
1015
+ /** Template de rendu du trigger (contenu du bouton déclencheur) pour le multi-select.
1016
+ Contexte : `let-options` = le tableau des options sélectionnées (`readonly T[]`).
1017
+
1018
+ ```html
1019
+ <kt-multi-select [options]="tags">
1020
+ <ng-template [ktMultiSelectTrigger]="tags" let-options>
1021
+ @if (options.length) { {{ options.length }} sélectionné(s) } @else { Choisir… }
1022
+ </ng-template>
1023
+ </kt-multi-select>
1024
+ ``` */
1025
+ declare class KtMultiSelectTriggerDef<T> {
1026
+ readonly ktMultiSelectTrigger: _angular_core.InputSignal<readonly T[]>;
1027
+ readonly template: TemplateRef<KtMultiSelectTriggerContext<T>>;
1028
+ static ngTemplateContextGuard<T>(_dir: KtMultiSelectTriggerDef<T>, ctx: unknown): ctx is KtMultiSelectTriggerContext<T>;
1029
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtMultiSelectTriggerDef<any>, never>;
1030
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<KtMultiSelectTriggerDef<any>, "ng-template[ktMultiSelectTrigger]", never, { "ktMultiSelectTrigger": { "alias": "ktMultiSelectTrigger"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
1031
+ }
1032
+ /** Template de rendu d'un jeton (chip) affiché sous le multi-select.
1033
+ Contexte : `let-option` = l'option sélectionnée (`T`), `let-remove` = fonction qui la retire.
1034
+
1035
+ ```html
1036
+ <kt-multi-select [options]="tags">
1037
+ <ng-template [ktMultiSelectChip]="tags" let-tag let-remove="remove">
1038
+ <kt-chip [removable]="true" (remove)="remove()">{{ tag.name }}</kt-chip>
1039
+ </ng-template>
1040
+ </kt-multi-select>
1041
+ ``` */
1042
+ declare class KtMultiSelectChipDef<T> {
1043
+ readonly ktMultiSelectChip: _angular_core.InputSignal<readonly T[]>;
1044
+ readonly template: TemplateRef<KtMultiSelectChipContext<T>>;
1045
+ static ngTemplateContextGuard<T>(_dir: KtMultiSelectChipDef<T>, ctx: unknown): ctx is KtMultiSelectChipContext<T>;
1046
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtMultiSelectChipDef<any>, never>;
1047
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<KtMultiSelectChipDef<any>, "ng-template[ktMultiSelectChip]", never, { "ktMultiSelectChip": { "alias": "ktMultiSelectChip"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
1048
+ }
1049
+
1050
+ /** Payload de l'évènement `selectionChange` d'un `kt-multi-select`. */
1051
+ interface KtMultiSelectSelectionChange<T, V = T> {
1052
+ /** Valeurs émises : clés extraites ou objets entiers, dans l'ordre de sélection. */
1053
+ value: V[];
1054
+ /** Options correspondantes, dans l'ordre de sélection. */
1055
+ options: T[];
1056
+ }
1057
+ /**
1058
+ * Composant de sélection multiple (Multi-Select) conforme aux exigences d'accessibilité (WCAG 2.2 AAA / RGAA).
1059
+ * Repose sur `@angular/aria/combobox` et `@angular/aria/listbox` avec [multi]="true".
1060
+ * Présentation adaptative : dropdown (desktop) ou bottom-sheet modale (téléphone tactile).
1061
+ * Option 1 : Résumé textuel sur le trigger et chips révocables affichés en dessous.
1062
+ *
1063
+ * Clavier multi-sélection (APG) : Espace/Entrée toggle, Shift+flèches étend la sélection,
1064
+ * Ctrl+A tout (dé)sélectionne, Shift+Espace sélectionne la plage, typeahead — majoritairement
1065
+ * natifs via `@angular/aria` ; les combos non relayés par la lib le sont via `onTriggerKeydown`.
1066
+ * Tout le commun (popup, filtre, clavier, drag-to-dismiss) vit dans `BaseSelect`.
1067
+ *
1068
+ * @template T Type d'une option (élément du tableau `options`).
1069
+ * @template V Type des valeurs émises (défaut `T` ; clés extraites si `optionValue` est fourni).
1070
+ *
1071
+ * @example
1072
+ * ```html
1073
+ * <kt-multi-select [options]="tags" optionLabel="name" optionValue="id" [(value)]="selectedIds" />
1074
+ * ```
1075
+ */
1076
+ declare class KtMultiSelect<T, V = T> extends KtBaseSelect<T, V> implements FormValueControl<V[]> {
1077
+ /** Valeurs sélectionnées (clés extraites, ou objets entiers si `optionValue` est omis). @default [] */
1078
+ readonly value: _angular_core.ModelSignal<V[]>;
1079
+ /** Émis à chaque (dé)sélection. Payload : `{ value, options }` — `value` le tableau des valeurs émises
1080
+ (clés ou objets), `options` les objets options correspondants, dans l'ordre de sélection. */
1081
+ readonly selectionChange: _angular_core.OutputEmitterRef<KtMultiSelectSelectionChange<T, V>>;
1082
+ /** Bouton « tout effacer » sur le champ (même contrat que `clearable` de BaseInputField). @default false */
1083
+ readonly clearable: _angular_core.InputSignalWithTransform<boolean, unknown>;
1084
+ /** Libellé i18n du bouton « tout effacer ». @default 'Clear' (ou KT_FIELD_CONFIG.clearLabel) */
1085
+ readonly clearLabel: _angular_core.InputSignal<string>;
1086
+ /** Barre « Tout sélectionner / Tout effacer » en tête du popup (bascule le popup en panneau dialog). */
1087
+ readonly selectionActions: _angular_core.InputSignalWithTransform<boolean, unknown>;
1088
+ /** Nombre maximal de chips affichés avant repli derrière un bouton « +N more ». Défaut : illimité. */
1089
+ readonly maxVisibleChips: _angular_core.InputSignal<number | undefined>;
1090
+ protected readonly optionDef: _angular_core.Signal<KtMultiSelectOptionDef<any> | undefined>;
1091
+ protected readonly triggerDef: _angular_core.Signal<KtMultiSelectTriggerDef<any> | undefined>;
1092
+ protected readonly chipDef: _angular_core.Signal<KtMultiSelectChipDef<any> | undefined>;
1093
+ private readonly chipList;
1094
+ protected readonly resolvedRemoveItemLabel: _angular_core.Signal<(itemLabel: string) => string>;
1095
+ protected readonly resolvedSelectedItemsLabel: _angular_core.Signal<string>;
1096
+ private readonly resolvedSelectionSummaryText;
1097
+ protected readonly resolvedItemRemovedText: _angular_core.Signal<(itemLabel: string) => string>;
1098
+ private readonly resolvedSelectionCountText;
1099
+ protected readonly resolvedSelectAllLabel: _angular_core.Signal<string>;
1100
+ protected readonly resolvedClearAllLabel: _angular_core.Signal<string>;
1101
+ protected readonly resolvedMoreChipsLabel: _angular_core.Signal<(hiddenCount: number) => string>;
1102
+ protected readonly resolvedLessChipsLabel: _angular_core.Signal<string>;
1103
+ /** Accesseurs bridgés vers le ChipList (fonctions fléchées : une référence de méthode
1104
+ non liée perdrait `this`). */
1105
+ protected readonly chipLabelOf: (item: T) => string;
1106
+ protected readonly chipKeyOf: (item: T) => unknown;
1107
+ /** Options correspondant aux entrées de `value`, dans l'ordre de sélection.
1108
+ Mode objet : chaque entrée est ramenée à l'option canonique équivalente (compareWith). */
1109
+ protected readonly selectedOptions: _angular_core.Signal<T[]>;
1110
+ protected readonly triggerText: _angular_core.Signal<string>;
1111
+ /** Valeur brute transmise au ngListbox sous-jacent (tableau de clés). */
1112
+ protected readonly listboxValue: _angular_core.Signal<unknown[]>;
1113
+ protected readonly showClear: _angular_core.Signal<boolean>;
1114
+ /** Le popup utilise la structure « panneau dialog » (champ de filtre et/ou barre d'actions). */
1115
+ protected readonly dialogMode: _angular_core.Signal<boolean>;
1116
+ /** Compteur de sélection affiché dans le panneau (info déjà portée par la live region → aria-hidden). */
1117
+ protected readonly selectionCountLabel: _angular_core.Signal<string>;
1118
+ /** Clé listbox d'une entrée de `value` (mode objet : clé de l'option canonique équivalente). */
1119
+ private entryKey;
1120
+ /** Entrée de `value` à committer pour une clé listbox (mode objet : l'option entière). */
1121
+ private entryForKey;
1122
+ protected onListboxValueChange(keys: readonly unknown[]): void;
1123
+ private commitValue;
1124
+ /** Comble les combos que le relay du combobox ne transmet pas en activedescendant :
1125
+ Shift+Espace (sélection de plage) et Ctrl/Cmd+Shift+Home/End (plage jusqu'aux bornes). */
1126
+ protected onTriggerKeydown(event: KeyboardEvent): void;
1127
+ /** En panneau dialog, le relay du combobox vise le widget (la div), pas le listbox descendant :
1128
+ on fait suivre au listbox les événements relayés (target = la div elle-même uniquement —
1129
+ les keydown des éléments internes, qui bubblent, ne sont pas re-forwardés). */
1130
+ protected onPanelKeydown(event: KeyboardEvent): void;
1131
+ /** « N results » + « , M selected » quand des sélections existent (dont celles hors filtre). */
1132
+ protected composeFilterAnnouncement(): string;
1133
+ /** Retire une option de la valeur (annonce et focus : délégués au ChipList). */
1134
+ protected removeOption(option: T): void;
1135
+ private removeFromValue;
1136
+ /** Vide toute la sélection depuis le champ (bouton `clearable`). */
1137
+ protected clearSelection(): void;
1138
+ /** Sélectionne toutes les options visibles non désactivées (sémantique du Ctrl+A natif :
1139
+ avec un filtre actif, seules les options filtrées sont concernées). */
1140
+ protected selectAllFiltered(): void;
1141
+ /** Désélectionne toutes les options visibles (les sélections masquées par le filtre restent). */
1142
+ protected clearAllFiltered(): void;
1143
+ /** Annonce immédiate (action ponctuelle, pas de débounce) du total sélectionné. */
1144
+ private announceSelectionCount;
1145
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtMultiSelect<any, any>, never>;
1146
+ 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>;
1147
+ }
1148
+
1149
+ /** Portée de transition des chips. Fourni par `ChipList` (via `useExisting`) ; injecté en
1150
+ optionnel par `Chip` pour ne porter un `view-transition-name` QUE pendant la transition
1151
+ de SA liste — sinon tous les chips de la page deviendraient des groupes indépendants et
1152
+ « glisseraient » individuellement à chaque reflow déclenché par une autre liste.
1153
+ Fichier séparé : évite l'import circulaire Chip ↔ ChipList. */
1154
+ declare abstract class ChipTransitionScope {
1155
+ abstract readonly transitioning: Signal<boolean>;
1156
+ }
1157
+
1158
+ /**
1159
+ * Pilule individuelle (tag). Utilisable seule (tag statique) ou dans `kt-chip-list`.
1160
+ * Le label vient de la projection de contenu ; `removable` ajoute un bouton « retirer »
1161
+ * (24px visibles, cible 44px via ::after — technique des boutons icon-only).
1162
+ *
1163
+ * @example
1164
+ * ```html
1165
+ * <kt-chip>Angular</kt-chip>
1166
+ * <kt-chip removable removeLabel="Retirer Angular" (remove)="onRemove()">Angular</kt-chip>
1167
+ * ```
1168
+ */
1169
+ declare class KtChip {
1170
+ protected readonly scope: ChipTransitionScope | null;
1171
+ private readonly idGen;
1172
+ /** Nom de View Transition propre au chip (détail interne, posé en host binding). */
1173
+ protected readonly viewTransitionName: string;
1174
+ /** Affiche le bouton « retirer » (sinon tag statique sans bouton). @default false */
1175
+ readonly removable: _angular_core.InputSignalWithTransform<boolean, unknown>;
1176
+ /** Chip désactivé (bouton « retirer » inactif). @default false */
1177
+ readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
1178
+ /** Libellé accessible du bouton « retirer » (inclure le nom de l'item : « Remove X »). @default 'Remove' */
1179
+ readonly removeLabel: _angular_core.InputSignal<string>;
1180
+ /** Émis au clic sur le bouton « retirer » (le parent décide de retirer le chip). */
1181
+ readonly remove: _angular_core.OutputEmitterRef<void>;
1182
+ private readonly removeBtn;
1183
+ /** Focus programmatique du bouton « retirer » (focus management d'`kt-chip-list`). */
1184
+ focusRemove(): void;
1185
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtChip, never>;
1186
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<KtChip, "kt-chip", never, { "removable": { "alias": "removable"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "removeLabel": { "alias": "removeLabel"; "required": false; "isSignal": true; }; }, { "remove": "remove"; }, never, ["*"], true, never>;
1187
+ }
1188
+
1189
+ /** Contexte typé reçu par le template d'un chip custom (`ktChipItem`). */
1190
+ interface KtChipItemContext<T> {
1191
+ /** L'item en cours de rendu → `let-item`. */
1192
+ $implicit: T;
1193
+ /** Fonction pour retirer cet item de la liste → `let-remove="remove"`. */
1194
+ remove: () => void;
1195
+ }
1196
+ /** Template de rendu custom d'un chip dans `kt-chip-list`.
1197
+ Structurellement compatible avec `MultiSelectChipContext` (forwardable).
1198
+ Contexte : `let-item` = l'item rendu (`T`), `let-remove` = fonction qui le retire.
1199
+
1200
+ ```html
1201
+ <kt-chip-list [items]="tags">
1202
+ <ng-template [ktChipItem]="tags" let-tag let-remove="remove">
1203
+ <kt-chip [removable]="true" (remove)="remove()">{{ tag.name }}</kt-chip>
1204
+ </ng-template>
1205
+ </kt-chip-list>
1206
+ ``` */
1207
+ declare class KtChipItemDef<T> {
1208
+ readonly ktChipItem: _angular_core.InputSignal<readonly T[]>;
1209
+ readonly template: TemplateRef<KtChipItemContext<T>>;
1210
+ static ngTemplateContextGuard<T>(_dir: KtChipItemDef<T>, ctx: unknown): ctx is KtChipItemContext<T>;
1211
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtChipItemDef<any>, never>;
1212
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<KtChipItemDef<any>, "ng-template[ktChipItem]", never, { "ktChipItem": { "alias": "ktChipItem"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
1213
+ }
1214
+
1215
+ /**
1216
+ * Liste de chips révocables (`role="list"`) : repli au-delà de `maxVisible` (« +N more »),
1217
+ * annonces lecteur d'écran (live region TOUJOURS rendue, y compris liste vide) et gestion
1218
+ * du focus au retrait (chip suivant, sinon `emptyFocusTarget`).
1219
+ * La liste ne possède PAS la donnée : le retrait émet `removed` et le parent met à jour
1220
+ * `items` (pattern contrôlé). Rendu custom par chip via `ng-template[ktChipItem]` (projeté)
1221
+ * ou `[chipTemplate]` (TemplateRef forwardé, ex. depuis MultiSelect) — le focus management
1222
+ * ne voit pas les boutons des templates custom (view queries non traversantes) : le repli
1223
+ * `emptyFocusTarget` couvre ce cas.
1224
+ *
1225
+ * @example
1226
+ * ```html
1227
+ * <kt-chip-list [items]="tags()" [maxVisible]="3" (removed)="onRemoved($event)" />
1228
+ * ```
1229
+ */
1230
+ declare class KtChipList<T> implements ChipTransitionScope {
1231
+ private readonly config;
1232
+ private readonly injector;
1233
+ private readonly host;
1234
+ private readonly doc;
1235
+ private readonly platformId;
1236
+ private readonly cdr;
1237
+ /** Vrai pendant la View Transition de CETTE liste : les chips (standards via Chip,
1238
+ custom via tokens.css) ne portent leur `view-transition-name` que dans cette fenêtre. */
1239
+ readonly transitioning: _angular_core.WritableSignal<boolean>;
1240
+ /** Items affichés sous forme de chips (la liste ne possède pas la donnée : pattern contrôlé). */
1241
+ readonly items: _angular_core.InputSignal<readonly T[]>;
1242
+ /** Libellé d'un item : clé OU fonction. @default `label`/`name`, sinon `String(item)` */
1243
+ readonly itemLabel: _angular_core.InputSignal<KtKeyish<T, string> | undefined>;
1244
+ /** Identité d'un item (track du @for) : clé OU fonction. @default `id`/`value`, sinon l'item */
1245
+ readonly itemKey: _angular_core.InputSignal<KtKeyish<T, unknown> | undefined>;
1246
+ /** Chips révocables (bouton « retirer » par chip). @default true */
1247
+ readonly removable: _angular_core.InputSignalWithTransform<boolean, unknown>;
1248
+ /** Liste désactivée (boutons « retirer » présents mais inactifs). @default false */
1249
+ readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
1250
+ /** Lecture seule : les boutons « retirer » sont absents (≠ disabled : présents mais inactifs). @default false */
1251
+ readonly readonly: _angular_core.InputSignalWithTransform<boolean, unknown>;
1252
+ /** Nombre maximal de chips affichés avant repli derrière « +N more ». @default undefined (illimité) */
1253
+ readonly maxVisible: _angular_core.InputSignal<number | undefined>;
1254
+ /** Libellé accessible de la liste (`aria-label`). Défaut : `KT_CHIPS_CONFIG.listLabel` ou « Selected items ». */
1255
+ readonly listLabel: _angular_core.InputSignal<string | undefined>;
1256
+ /** Construit le libellé du bouton « retirer » à partir du libellé de l'item. @default `« Remove {label} »` */
1257
+ readonly removeItemLabel: _angular_core.InputSignal<((itemLabel: string) => string) | undefined>;
1258
+ /** Construit le message d'annonce après retrait (live region). @default `« {label} removed »` */
1259
+ readonly itemRemovedText: _angular_core.InputSignal<((itemLabel: string) => string) | undefined>;
1260
+ /** Construit le libellé du bouton de repli à partir du nombre masqué. @default `« +{n} more »` */
1261
+ readonly moreLabel: _angular_core.InputSignal<((hiddenCount: number) => string) | undefined>;
1262
+ /** Libellé du bouton qui replie la liste dépliée. Défaut : `KT_CHIPS_CONFIG.lessLabel` ou « Show less ». */
1263
+ readonly lessLabel: _angular_core.InputSignal<string | undefined>;
1264
+ /** Template custom forwardé (alternative au `ng-template[ktChipItem]` projeté). @default null */
1265
+ readonly chipTemplate: _angular_core.InputSignal<TemplateRef<KtChipItemContext<T>> | null>;
1266
+ /** Élément à focuser quand le dernier chip est retiré (ex. le trigger du champ parent). @default undefined */
1267
+ readonly emptyFocusTarget: _angular_core.InputSignal<HTMLElement | undefined>;
1268
+ /** Émis quand un chip est retiré (le parent doit retirer l'item de `items`).
1269
+ Payload : `{ item, index }` — l'item retiré et son index dans `items` au moment du retrait. */
1270
+ readonly removed: _angular_core.OutputEmitterRef<{
1271
+ item: T;
1272
+ index: number;
1273
+ }>;
1274
+ protected readonly itemDef: _angular_core.Signal<KtChipItemDef<any> | undefined>;
1275
+ private readonly chips;
1276
+ protected readonly resolvedListLabel: _angular_core.Signal<string>;
1277
+ private readonly resolvedRemoveItemLabel;
1278
+ private readonly resolvedItemRemovedText;
1279
+ protected readonly resolvedMoreLabel: _angular_core.Signal<(hiddenCount: number) => string>;
1280
+ protected readonly resolvedLessLabel: _angular_core.Signal<string>;
1281
+ private readonly labelAccessor;
1282
+ private readonly keyAccessor;
1283
+ protected labelOf(item: T): string;
1284
+ protected keyOf(item: T): unknown;
1285
+ protected removeLabelFor(item: T): string;
1286
+ /** Template effectif : contenu projeté (ktChipItem) prioritaire sur l'input forwardé. */
1287
+ protected readonly effectiveTemplate: _angular_core.Signal<TemplateRef<KtChipItemContext<any>> | null>;
1288
+ protected readonly showRemove: _angular_core.Signal<boolean>;
1289
+ protected readonly expanded: _angular_core.WritableSignal<boolean>;
1290
+ protected readonly overflow: _angular_core.Signal<boolean>;
1291
+ protected readonly hiddenCount: _angular_core.Signal<number>;
1292
+ protected readonly visibleItems: _angular_core.Signal<readonly T[]>;
1293
+ protected readonly status: _angular_core.WritableSignal<string>;
1294
+ private statusTimer;
1295
+ constructor();
1296
+ private readonly idGen;
1297
+ protected readonly moreBtnTransitionName: string;
1298
+ /** Annonce un message dans la live region de la liste (effacé après ~2 s).
1299
+ Public : permet au parent d'annoncer des actions liées (ex. « tout effacer »). */
1300
+ announce(text: string): void;
1301
+ private activeTransition;
1302
+ /** Exécute `action` dans une View Transition (morph des chips qui se déplacent, entrée/sortie
1303
+ stylées via `::view-transition-*(.chip-transition)` — cf. tokens.css). Transition SCOPÉE à
1304
+ l'élément quand le navigateur le permet (`element.startViewTransition`, Chrome 147+) ; sinon
1305
+ transition document — dans les deux cas, seuls les chips de CETTE liste sont nommés (cf.
1306
+ `transitioning`). Fallback : action directe si l'API est absente ou si l'utilisateur
1307
+ préfère moins de mouvement. */
1308
+ private withViewTransition;
1309
+ /** Retrait demandé : annonce, émet vers le parent (qui met à jour `items`), puis focus
1310
+ le chip suivant — sinon `emptyFocusTarget` (le bouton focusé disparaît du DOM). */
1311
+ protected removeAt(item: T, index: number): void;
1312
+ protected removeCallback(item: T, index: number): () => void;
1313
+ /** Déplie/replie ; au dépliage, focus sur le premier chip nouvellement révélé. */
1314
+ protected toggleExpanded(): void;
1315
+ protected onKeydown(event: KeyboardEvent): void;
1316
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtChipList<any>, never>;
1317
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<KtChipList<any>, "kt-chip-list", never, { "items": { "alias": "items"; "required": true; "isSignal": true; }; "itemLabel": { "alias": "itemLabel"; "required": false; "isSignal": true; }; "itemKey": { "alias": "itemKey"; "required": false; "isSignal": true; }; "removable": { "alias": "removable"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "maxVisible": { "alias": "maxVisible"; "required": false; "isSignal": true; }; "listLabel": { "alias": "listLabel"; "required": false; "isSignal": true; }; "removeItemLabel": { "alias": "removeItemLabel"; "required": false; "isSignal": true; }; "itemRemovedText": { "alias": "itemRemovedText"; "required": false; "isSignal": true; }; "moreLabel": { "alias": "moreLabel"; "required": false; "isSignal": true; }; "lessLabel": { "alias": "lessLabel"; "required": false; "isSignal": true; }; "chipTemplate": { "alias": "chipTemplate"; "required": false; "isSignal": true; }; "emptyFocusTarget": { "alias": "emptyFocusTarget"; "required": false; "isSignal": true; }; }, { "removed": "removed"; }, ["itemDef"], never, true, never>;
1318
+ }
1319
+
1320
+ /** Défauts applicables à tous les `kt-chip-list` (surchargeables par liste via les inputs).
1321
+ Lib neutre i18n : les textes sont fournis par le consommateur (ici en une fois).
1322
+ Fourni en `Partial` : un consommateur n'override que ce qu'il veut.
1323
+ Calqué sur `KT_FIELD_CONFIG`/`KT_SELECT_CONFIG`.
1324
+ NB : le MultiSelect passe ses propres textes (résolus depuis KT_SELECT_CONFIG) en inputs —
1325
+ ils priment donc sur ce token pour les chips rendus sous un multi-select. */
1326
+ interface KtChipsConfig {
1327
+ /** Libellé accessible du bouton de retrait d'un chip. Défaut : `'Remove X'`. */
1328
+ removeItemLabel: (itemLabel: string) => string;
1329
+ /** Annonce live après le retrait d'un chip. Défaut : `'X removed'`. */
1330
+ itemRemovedText: (itemLabel: string) => string;
1331
+ /** Libellé du bouton dépliant les chips repliés (`[maxVisible]`). Défaut : `'+N more'`. */
1332
+ moreLabel: (hiddenCount: number) => string;
1333
+ /** Libellé du même bouton une fois déplié. Défaut : `'Show less'`. */
1334
+ lessLabel: string;
1335
+ /** Libellé accessible du conteneur (`role="list"`). Défaut : `'Selected items'`. */
1336
+ listLabel: string;
1337
+ }
1338
+ declare const KT_CHIPS_CONFIG: InjectionToken<Partial<KtChipsConfig>>;
1339
+
1340
+ /** Base partagée des champs Temporal (Date/Time/DateTime/YearMonth).
1341
+ Toute la logique commune (parsing tolérant, valeur vide `null`, `displayValue` pour l'input
1342
+ natif) vit ici ; chaque sous-classe ne fournit que la construction et la sérialisation propres
1343
+ à son type Temporal (`fromString` / `serialize`).
1344
+
1345
+ Contrat abstrait : une sous-classe implémente uniquement le couple
1346
+ `fromString` (chaîne ISO de l'input natif → valeur typée `T`) et `serialize`
1347
+ (valeur `T` → chaîne ISO pour l'attribut `[value]` de l'input). La valeur exposée
1348
+ reste toujours `T | null`, où `null` représente le champ vide ; le parsing est
1349
+ tolérant (saisie partielle/invalide → `null`, jamais d'exception ni de valeur fausse).
1350
+
1351
+ @template T Type Temporal porté par le champ (ex. `Temporal.PlainDate`,
1352
+ `Temporal.PlainTime`, …). Doit exposer `toString()`. La valeur du champ est `T | null`. */
1353
+ declare abstract class KtBaseTemporalField<T extends {
1354
+ toString(): string;
1355
+ }> extends KtBaseInputField<T | null> {
1356
+ private readonly doc;
1357
+ constructor();
1358
+ /** Construit la valeur typée depuis la chaîne ISO de l'input natif (ex. `Temporal.PlainDate.from`). */
1359
+ protected abstract fromString(raw: string): T;
1360
+ /** Sérialise la valeur au format attendu par l'input natif (précision adaptée au type). */
1361
+ protected abstract serialize(value: T): string;
1362
+ protected parse(raw: string): T | null;
1363
+ protected emptyValue(): T | null;
1364
+ protected isEmpty(value: T | null): boolean;
1365
+ /** Représentation ISO pour l'attribut `[value]` de l'input natif (null → champ vide). */
1366
+ protected readonly displayValue: _angular_core.Signal<string>;
1367
+ /** Suggestions proposées via un `<datalist>` natif (le picker date/heure reste disponible).
1368
+ Valeurs Temporal simples ou couples `{ value, label }` ; chaque valeur est sérialisée au
1369
+ format de l'input via `serialize`. @default undefined */
1370
+ readonly suggestions: _angular_core.InputSignal<readonly KtSuggestion<T>[] | undefined>;
1371
+ private readonly idGen;
1372
+ private readonly uid;
1373
+ protected readonly datalistId: string;
1374
+ protected readonly hasSuggestions: _angular_core.Signal<boolean>;
1375
+ protected readonly datalistOptions: _angular_core.Signal<readonly KtDatalistOption[]>;
1376
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtBaseTemporalField<any>, never>;
1377
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<KtBaseTemporalField<any>, never, never, { "suggestions": { "alias": "suggestions"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1378
+ }
1379
+
1380
+ /** Date civile (jour/mois/année), sans heure ni fuseau — alias de `Temporal.PlainDate`.
1381
+ À utiliser pour une date « pure » : naissance, échéance, jour d'un événement.
1382
+ *
1383
+ * @example
1384
+ * ```ts
1385
+ * import { type CalendarDate } from '@ktortu/aaa';
1386
+ * ```
1387
+ */
1388
+ type CalendarDate = Temporal.PlainDate;
1389
+ /** Heure « au mur » (heure/minute/seconde), sans date ni fuseau — alias de `Temporal.PlainTime`.
1390
+ À utiliser pour une heure isolée : heure d'ouverture, créneau de rendez-vous récurrent. */
1391
+ type WallTime = Temporal.PlainTime;
1392
+ /** Date + heure locale, sans fuseau — alias de `Temporal.PlainDateTime`.
1393
+ À utiliser quand date et heure comptent mais que le fuseau est implicite/non pertinent
1394
+ (heure « au mur » : ne représente pas un instant absolu). */
1395
+ type LocalDateTime = Temporal.PlainDateTime;
1396
+ /** Instant absolu sur la ligne du temps, en UTC — alias de `Temporal.Instant`.
1397
+ À utiliser pour horodater un événement réel (création, mesure) indépendamment du fuseau
1398
+ d'affichage ; la conversion en heure locale se fait à la présentation (via `KtClock`). */
1399
+ type Timestamp = Temporal.Instant;
1400
+ /** Instant + fuseau nommé (IANA) — alias de `Temporal.ZonedDateTime`.
1401
+ À utiliser quand le fuseau fait partie de la donnée (ex. « 14h00 à Paris ») et doit être
1402
+ conservé, contrairement à `Timestamp` qui ne porte pas de fuseau. */
1403
+ type ZonedTimestamp = Temporal.ZonedDateTime;
1404
+
1405
+ /** Champ « date sans heure » : valeur = `Temporal.PlainDate`, input natif `type="date"`.
1406
+ *
1407
+ * @example
1408
+ * ```html
1409
+ * <kt-date-field label="Date de naissance" [(value)]="birthDate" />
1410
+ * ```
1411
+ */
1412
+ declare class KtDateField extends KtBaseTemporalField<Temporal.PlainDate> implements FormValueControl<Temporal.PlainDate | null> {
1413
+ /** Valeur du champ : un `Temporal.PlainDate` (date civile sans heure ni fuseau).
1414
+ `null` = champ vide.
1415
+ @default null */
1416
+ value: _angular_core.ModelSignal<Temporal.PlainDate | null>;
1417
+ protected fromString(raw: string): Temporal.PlainDate;
1418
+ protected serialize(value: Temporal.PlainDate): string;
1419
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtDateField, never>;
1420
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<KtDateField, "kt-date-field", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, ["[ktFieldHelp]"], true, never>;
1421
+ }
1422
+
1423
+ /** Champ « heure sans date » : valeur = `Temporal.PlainTime`, input natif `type="time"`.
1424
+ *
1425
+ * @example
1426
+ * ```html
1427
+ * <kt-time-field label="Heure de rendez-vous" [(value)]="appointmentTime" />
1428
+ * ```
1429
+ */
1430
+ declare class KtTimeField extends KtBaseTemporalField<Temporal.PlainTime> implements FormValueControl<Temporal.PlainTime | null> {
1431
+ /** Valeur du champ : un `Temporal.PlainTime` (heure « au mur », sans date ni fuseau).
1432
+ `null` = champ vide.
1433
+ @default null */
1434
+ value: _angular_core.ModelSignal<Temporal.PlainTime | null>;
1435
+ protected fromString(raw: string): Temporal.PlainTime;
1436
+ protected serialize(value: Temporal.PlainTime): string;
1437
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtTimeField, never>;
1438
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<KtTimeField, "kt-time-field", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, ["[ktFieldHelp]"], true, never>;
1439
+ }
1440
+
1441
+ /** Champ « date-heure sans fuseau » : valeur = `Temporal.PlainDateTime`, input
1442
+ natif `type="datetime-local"`. Volontairement SANS timezone (heure « au mur »).
1443
+ *
1444
+ * @example
1445
+ * ```html
1446
+ * <kt-date-time-field label="Début de l'événement" [(value)]="startsAt" />
1447
+ * ```
1448
+ */
1449
+ declare class KtDateTimeField extends KtBaseTemporalField<Temporal.PlainDateTime> implements FormValueControl<Temporal.PlainDateTime | null> {
1450
+ /** Valeur du champ : un `Temporal.PlainDateTime` (date + heure « au mur », sans fuseau).
1451
+ `null` = champ vide.
1452
+ @default null */
1453
+ value: _angular_core.ModelSignal<Temporal.PlainDateTime | null>;
1454
+ protected fromString(raw: string): Temporal.PlainDateTime;
1455
+ protected serialize(value: Temporal.PlainDateTime): string;
1456
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtDateTimeField, never>;
1457
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<KtDateTimeField, "kt-date-time-field", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, ["[ktFieldHelp]"], true, never>;
1458
+ }
1459
+
1460
+ /** Champ « mois/année » (ex. expiration de carte) : valeur = `Temporal.PlainYearMonth`,
1461
+ input natif `type="month"`.
1462
+ *
1463
+ * @example
1464
+ * ```html
1465
+ * <kt-year-month-field label="Expiration" [(value)]="cardExpiry" />
1466
+ * ```
1467
+ */
1468
+ declare class KtYearMonthField extends KtBaseTemporalField<Temporal.PlainYearMonth> implements FormValueControl<Temporal.PlainYearMonth | null> {
1469
+ /** Valeur du champ : un `Temporal.PlainYearMonth` (mois + année, sans jour ni fuseau).
1470
+ `null` = champ vide.
1471
+ @default null */
1472
+ value: _angular_core.ModelSignal<Temporal.PlainYearMonth | null>;
1473
+ protected fromString(raw: string): Temporal.PlainYearMonth;
1474
+ protected serialize(value: Temporal.PlainYearMonth): string;
1475
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtYearMonthField, never>;
1476
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<KtYearMonthField, "kt-year-month-field", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, ["[ktFieldHelp]"], true, never>;
1477
+ }
1478
+
1479
+ /** Champ « instant absolu » : valeur = `Temporal.Instant` (UTC), saisi et affiché en **heure
1480
+ locale** via un input `type="datetime-local"`. Conçu pour le flux serveur-UTC → affichage/édition
1481
+ locale → renvoi UTC. Le fuseau local vient du service `KtClock` (injecté → testable).
1482
+
1483
+ Conversion UTC↔heure locale : à l'affichage, l'`Instant` UTC est projeté dans le fuseau
1484
+ local (`KtClock.timeZoneId()`) pour produire l'heure « au mur » montrée à l'utilisateur ; à la
1485
+ saisie, cette heure locale est réinterprétée dans le même fuseau puis reconvertie en `Instant`
1486
+ UTC. Fournir un `KtClock` figé en test garantit une conversion déterministe.
1487
+ *
1488
+ * @example
1489
+ * ```html
1490
+ * <kt-instant-field label="Horodatage" [(value)]="recordedAt" />
1491
+ * ```
1492
+ */
1493
+ declare class KtInstantField extends KtBaseTemporalField<Temporal.Instant> implements FormValueControl<Temporal.Instant | null> {
1494
+ private readonly clock;
1495
+ /** Valeur du champ : un `Temporal.Instant` (instant absolu en UTC), saisi/affiché en heure
1496
+ locale via `KtClock`. `null` = champ vide.
1497
+ @default null */
1498
+ value: _angular_core.ModelSignal<Temporal.Instant | null>;
1499
+ protected fromString(raw: string): Temporal.Instant;
1500
+ protected serialize(value: Temporal.Instant): string;
1501
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtInstantField, never>;
1502
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<KtInstantField, "kt-instant-field", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, ["[ktFieldHelp]"], true, never>;
1503
+ }
1504
+
1505
+ /** Valeurs Temporal formatables pour l'affichage (toutes exposent `toLocaleString`). */
1506
+ type FormattableTemporal = Temporal.PlainDate | Temporal.PlainTime | Temporal.PlainDateTime | Temporal.PlainYearMonth | Temporal.Instant | Temporal.ZonedDateTime;
1507
+ /** Formate une valeur Temporal pour l'affichage selon la locale active.
1508
+ `DatePipe` n'accepte pas Temporal (seulement `Date|string|number`) → pipe dédié, basé sur
1509
+ `toLocaleString` (interface `Intl.DateTimeFormat`). Cohérent avec la neutralité i18n de la lib
1510
+ (format au runtime via `LOCALE_ID`, pas `$localize`).
1511
+
1512
+ Un `Instant` n'a pas de fuseau propre → il est affiché dans la **zone locale** (via `KtClock`).
1513
+ Un `ZonedDateTime` est affiché dans **sa propre** zone. Les `Plain*` n'ont pas de fuseau.
1514
+ *
1515
+ * @example
1516
+ * ```html
1517
+ * <!-- format par défaut de la locale active -->
1518
+ * {{ d | temporalDate }}
1519
+ * <!-- options Intl.DateTimeFormat -->
1520
+ * {{ d | temporalDate:{ month: 'long' } }}
1521
+ * {{ d | temporalDate:{ dateStyle: 'full' } }}
1522
+ * ```
1523
+ */
1524
+ declare class KtTemporalDatePipe implements PipeTransform {
1525
+ private readonly locale;
1526
+ private readonly clock;
1527
+ transform(value: FormattableTemporal | null | undefined, options?: Intl.DateTimeFormatOptions): string;
1528
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtTemporalDatePipe, never>;
1529
+ static ɵpipe: _angular_core.ɵɵPipeDeclaration<KtTemporalDatePipe, "temporalDate", true>;
1530
+ }
1531
+
1532
+ /** Source unique de l'heure courante et du **fuseau local** de l'utilisateur.
1533
+ Injectable (et donc figeable en test) : `vi.useFakeTimers()` ne fige PAS `Temporal.Now`.
1534
+ Règle d'équipe : ne jamais appeler `Temporal.Now.*` en direct ailleurs — passer par `KtClock`. */
1535
+ declare class KtClock {
1536
+ /** Fuseau IANA local de l'utilisateur (auto-détecté), ex. `"Europe/Paris"`.
1537
+ Sert de zone de référence pour `today()` et pour les conversions UTC↔local.
1538
+ @returns L'identifiant de fuseau IANA. */
1539
+ timeZoneId(): string;
1540
+ /** Instant absolu courant, sur la ligne du temps (UTC), indépendant du fuseau.
1541
+ @returns L'instant présent en `Temporal.Instant`. */
1542
+ now(): Temporal.Instant;
1543
+ /** Date civile du jour telle qu'observée dans le fuseau local (`timeZoneId()`).
1544
+ @returns Le jour courant en `Temporal.PlainDate`. */
1545
+ today(): Temporal.PlainDate;
1546
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtClock, never>;
1547
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<KtClock>;
1548
+ }
1549
+ /** Horloge figée pour les tests : fige l'instant ET le fuseau (sinon un test passe en France mais
1550
+ échoue sur un runner CI en UTC). À fournir via `{ provide: KtClock, useValue: new KtFixedClock(...) }`. */
1551
+ declare class KtFixedClock extends KtClock {
1552
+ private readonly fixedInstant;
1553
+ private readonly zone;
1554
+ /** Construit une horloge figée déterministe pour les tests.
1555
+ @param fixedInstant Instant absolu (UTC) renvoyé tel quel par `now()` et utilisé comme base de `today()`.
1556
+ @param zone Fuseau IANA fixe (ex. `"Europe/Paris"`) renvoyé par `timeZoneId()`.
1557
+ *
1558
+ * @example
1559
+ * ```ts
1560
+ * TestBed.configureTestingModule({
1561
+ * providers: [
1562
+ * { provide: KtClock, useValue: new KtFixedClock(Temporal.Instant.from('2026-06-18T10:00:00Z'), 'Europe/Paris') },
1563
+ * ],
1564
+ * });
1565
+ * ```
1566
+ */
1567
+ constructor(fixedInstant: Temporal.Instant, zone: string);
1568
+ timeZoneId(): string;
1569
+ now(): Temporal.Instant;
1570
+ today(): Temporal.PlainDate;
1571
+ }
1572
+
1573
+ export { KT_CHIPS_CONFIG, KT_FIELD, KT_FIELD_CONFIG, KT_SELECT_CONFIG, KtBaseTemporalField, KtCheckbox, KtCheckboxGroup, KtChip, KtChipItemDef, KtChipList, KtClock, KtDateField, KtDateTimeField, KtField, KtFieldControl, KtFixedClock, KtInstantField, KtMultiSelect, KtMultiSelectChipDef, KtMultiSelectOptionDef, KtMultiSelectTriggerDef, KtNumberField, KtRadio, KtRadioGroup, KtSelect, KtSelectConfig, KtSelectOptionDef, KtSelectTriggerDef, KtSwitch, KtTemporalDatePipe, KtTextArea, KtTextField, KtTimeField, KtYearMonthField, defaultKtFieldErrorMatcher };
1574
+ export type { CalendarDate, KtChipItemContext, KtChipsConfig, KtFieldConfig, KtFieldError, KtFieldErrorMatcher, KtFieldErrorState, KtFieldParent, KtKeyish, KtMultiSelectChipContext, KtMultiSelectOptionContext, KtMultiSelectSelectionChange, KtMultiSelectTriggerContext, KtSelectConfigOptions, KtSelectOptionContext, KtSelectSelectionChange, KtSelectTriggerContext, KtSuggestion, KtTextFieldType, LocalDateTime, Timestamp, WallTime, ZonedTimestamp };