@ktortu/aaa 0.1.0-beta.0 → 0.9.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 (37) hide show
  1. package/README.md +23 -7
  2. package/cdk/styles/tabs.css +100 -21
  3. package/fesm2022/ktortu-aaa-button.mjs +18 -11
  4. package/fesm2022/ktortu-aaa-button.mjs.map +1 -1
  5. package/fesm2022/ktortu-aaa-card.mjs +29 -4
  6. package/fesm2022/ktortu-aaa-card.mjs.map +1 -1
  7. package/fesm2022/ktortu-aaa-cdk.mjs +58 -15
  8. package/fesm2022/ktortu-aaa-cdk.mjs.map +1 -1
  9. package/fesm2022/ktortu-aaa-dialog.mjs +69 -12
  10. package/fesm2022/ktortu-aaa-dialog.mjs.map +1 -1
  11. package/fesm2022/ktortu-aaa-forms.mjs +455 -260
  12. package/fesm2022/ktortu-aaa-forms.mjs.map +1 -1
  13. package/fesm2022/ktortu-aaa-i18n.mjs +114 -0
  14. package/fesm2022/ktortu-aaa-i18n.mjs.map +1 -0
  15. package/fesm2022/ktortu-aaa-menu.mjs +38 -13
  16. package/fesm2022/ktortu-aaa-menu.mjs.map +1 -1
  17. package/fesm2022/ktortu-aaa-tabs.mjs +319 -42
  18. package/fesm2022/ktortu-aaa-tabs.mjs.map +1 -1
  19. package/fesm2022/ktortu-aaa-tooltip.mjs +3 -2
  20. package/fesm2022/ktortu-aaa-tooltip.mjs.map +1 -1
  21. package/fesm2022/ktortu-aaa.mjs +1 -0
  22. package/fesm2022/ktortu-aaa.mjs.map +1 -1
  23. package/forms/radio/radio-group.css +3 -3
  24. package/forms/styles/field-box.css +150 -2
  25. package/forms/styles/tokens.css +3 -0
  26. package/menu/menu.css +8 -4
  27. package/package.json +5 -1
  28. package/types/ktortu-aaa-button.d.ts +22 -8
  29. package/types/ktortu-aaa-card.d.ts +24 -4
  30. package/types/ktortu-aaa-cdk.d.ts +38 -0
  31. package/types/ktortu-aaa-dialog.d.ts +45 -9
  32. package/types/ktortu-aaa-forms.d.ts +336 -149
  33. package/types/ktortu-aaa-i18n.d.ts +74 -0
  34. package/types/ktortu-aaa-menu.d.ts +15 -8
  35. package/types/ktortu-aaa-tabs.d.ts +130 -13
  36. package/types/ktortu-aaa-tooltip.d.ts +5 -0
  37. package/types/ktortu-aaa.d.ts +1 -0
@@ -1,22 +1,33 @@
1
1
  import * as _angular_core from '@angular/core';
2
- import { InjectionToken, Signal, TemplateRef, ModelSignal, ElementRef, PipeTransform } from '@angular/core';
2
+ import { InjectionToken, Signal, Provider, TemplateRef, ModelSignal, ElementRef, PipeTransform } from '@angular/core';
3
+ import * as _ktortu_aaa_forms from '@ktortu/aaa/forms';
3
4
  import * as _angular_forms_signals from '@angular/forms/signals';
4
5
  import { WithOptionalFieldTree, ValidationError, FormValueControl } from '@angular/forms/signals';
5
- import * as _ktortu_aaa_forms from '@ktortu/aaa/forms';
6
6
  import { Listbox } from '@angular/aria/listbox';
7
7
  import { Combobox } from '@angular/aria/combobox';
8
8
  import { KtViewport } from '@ktortu/aaa/cdk';
9
- import { Temporal } from 'temporal-polyfill';
9
+ import * as temporal_polyfill from 'temporal-polyfill';
10
+ import { Temporal as Temporal$1 } from 'temporal-polyfill';
10
11
  export { Temporal as TemporalNamespace } from 'temporal-polyfill';
11
12
 
12
13
  /** État d'un champ pertinent pour décider de l'affichage des erreurs. */
13
14
  interface KtFieldErrorState {
15
+ /** Le champ est-il en erreur de validation. */
14
16
  invalid: boolean;
17
+ /** Le champ a-t-il été visité (blur). */
15
18
  touched: boolean;
19
+ /** Le champ a-t-il été modifié depuis sa valeur initiale. */
16
20
  dirty: boolean;
17
21
  }
18
22
  /** Décide QUAND afficher les erreurs d'un champ (équivalent signal de l'ErrorStateMatcher Material). */
19
23
  type KtFieldErrorMatcher = (state: KtFieldErrorState) => boolean;
24
+ /** Apparence du chrome de champ. `fill` = label au-dessus (défaut historique) ; `outline` = bordure
25
+ + label flottant qui se loge dans la bordure (transition douce depuis Angular Material « outline »). */
26
+ type KtFieldAppearance = 'fill' | 'outline';
27
+ /** Politique du label flottant (apparence `outline` uniquement). `auto` = flotte au focus / quand le
28
+ champ est rempli ; `always` = toujours flotté, même vide (le placeholder s'affiche alors). Équivaut
29
+ au `floatLabel` d'Angular Material. */
30
+ type KtFloatLabel = 'auto' | 'always';
20
31
  /** Défaut : afficher l'erreur une fois le champ quitté (blur). */
21
32
  declare const defaultKtFieldErrorMatcher: KtFieldErrorMatcher;
22
33
  /** Défauts applicables à tous les champs (surchargeables par champ via les inputs).
@@ -33,20 +44,45 @@ interface KtFieldConfig {
33
44
  hideHintWhenInvalid: boolean;
34
45
  /** Afficher toutes les erreurs au lieu de la première seule. Défaut : `false`. */
35
46
  showAllErrors: boolean;
47
+ /** Message d'erreur d'un `kt-number-field` quand la saisie n'est pas un nombre valide.
48
+ Défaut (anglais neutre) : `'Please enter a valid number.'`. */
49
+ numberParseError: string;
50
+ /** Apparence par défaut de tous les champs (`fill` | `outline`). Défaut : `'fill'`. */
51
+ appearance: KtFieldAppearance;
52
+ /** Politique du label flottant en `outline` (`auto` | `always`). Défaut : `'auto'`. */
53
+ floatLabel: KtFloatLabel;
36
54
  }
37
55
  declare const KT_FIELD_CONFIG: InjectionToken<Partial<KtFieldConfig>>;
56
+ /**
57
+ * Fournit des défauts de champ (apparence, libellés, matcher d'erreurs…) pour un sous-arbre ou
58
+ * l'application entière. Idéal pour une transition globale — ex. tout passer en `outline` façon
59
+ * Material en un seul provider.
60
+ *
61
+ * @example
62
+ * ```ts
63
+ * // app.config.ts
64
+ * providers: [provideKtField({ appearance: 'outline' })]
65
+ * ```
66
+ */
67
+ declare function provideKtField(config: Partial<KtFieldConfig>): Provider;
38
68
  /** Parent field interface representing shared states for its controls. */
39
69
  interface KtFieldParent {
70
+ /** id de base du champ, posé sur le contrôle (`[id]`). */
40
71
  readonly baseId: Signal<string>;
72
+ /** Valeur de `aria-describedby` à câbler sur le contrôle (ou `null`). */
41
73
  readonly describedBy: Signal<string | null>;
74
+ /** Le champ est-il en erreur (pose `aria-invalid`). */
42
75
  readonly invalid: Signal<boolean>;
76
+ /** Le champ est-il requis (pose `aria-required`). */
43
77
  readonly required: Signal<boolean>;
44
78
  }
45
79
  declare const KT_FIELD: InjectionToken<KtFieldParent>;
46
80
 
47
81
  /** Forme minimale d'une erreur affichable — découple `Field` de Signal Forms. */
48
82
  interface KtFieldError {
83
+ /** Identifiant du type d'erreur (ex. `'required'`, `'email'`). */
49
84
  kind: string;
85
+ /** Message lisible affiché à l'utilisateur (optionnel). */
50
86
  message?: string;
51
87
  }
52
88
  /** Chrome de champ agnostique du système de forms : label + contrôle projeté + hint + erreur,
@@ -75,15 +111,25 @@ declare class KtField implements KtFieldParent {
75
111
  /** Erreurs de validation à afficher sous le contrôle. @default [] */
76
112
  readonly errors: _angular_core.InputSignal<readonly KtFieldError[]>;
77
113
  /** Marque le champ comme invalide (pose `aria-invalid` et conditionne l'affichage des erreurs). @default false */
78
- readonly invalid: _angular_core.InputSignal<boolean>;
114
+ readonly invalid: _angular_core.InputSignalWithTransform<boolean, unknown>;
79
115
  /** 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. */
116
+ readonly required: _angular_core.InputSignalWithTransform<boolean, unknown>;
117
+ /** id imposé (sélecteurs de test stables) ; sinon auto-généré, anti-collision. @default undefined */
82
118
  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>;
119
+ /** Masquer le hint quand l'erreur s'affiche (façon Material). @default KT_FIELD_CONFIG.hideHintWhenInvalid ?? false */
120
+ readonly hideHintWhenInvalid: _angular_core.InputSignalWithTransform<boolean, unknown>;
121
+ /** Afficher toutes les erreurs au lieu de la première seule. @default KT_FIELD_CONFIG.showAllErrors ?? false */
122
+ readonly showAllErrors: _angular_core.InputSignalWithTransform<boolean, unknown>;
123
+ /** Apparence du chrome : `fill` (label au-dessus) ou `outline` (bordure + label flottant, façon
124
+ Material). Non fournie ⇒ valeur du `KT_FIELD_CONFIG`, sinon `'fill'`. @default undefined */
125
+ readonly appearance: _angular_core.InputSignal<KtFieldAppearance | undefined>;
126
+ /** Apparence effective : input ?? KT_FIELD_CONFIG.appearance ?? 'fill'. */
127
+ protected readonly resolvedAppearance: _angular_core.Signal<KtFieldAppearance>;
128
+ /** Politique du label flottant (outline) : `auto` (flotte au focus/rempli) ou `always` (toujours
129
+ flotté, même vide). Non fournie ⇒ valeur du `KT_FIELD_CONFIG`, sinon `'auto'`. @default undefined */
130
+ readonly floatLabel: _angular_core.InputSignal<KtFloatLabel | undefined>;
131
+ /** Politique effective : input ?? KT_FIELD_CONFIG.floatLabel ?? 'auto'. */
132
+ protected readonly resolvedFloatLabel: _angular_core.Signal<KtFloatLabel>;
87
133
  private readonly control;
88
134
  private readonly templateTooltip;
89
135
  private readonly projectedTooltip;
@@ -100,39 +146,45 @@ declare class KtField implements KtFieldParent {
100
146
  readonly describedBy: _angular_core.Signal<string | null>;
101
147
  protected onHelpClick(event: MouseEvent): void;
102
148
  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>;
149
+ 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; }; "appearance": { "alias": "appearance"; "required": false; "isSignal": true; }; "floatLabel": { "alias": "floatLabel"; "required": false; "isSignal": true; }; }, { "helpClick": "helpClick"; }, ["control", "projectedTooltip"], ["[ktFieldHelp]", "*"], true, never>;
104
150
  }
105
151
 
106
152
  /** 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). */
153
+ (id, aria-describedby, aria-invalid, aria-required).
154
+
155
+ @example
156
+ ```html
157
+ <kt-field label="E-mail" [invalid]="invalid()" [errors]="errors()">
158
+ <input ktFieldControl type="email" [(ngModel)]="email" />
159
+ </kt-field>
160
+ ``` */
108
161
  declare class KtFieldControl {
109
162
  private readonly parent;
110
163
  protected readonly id: _angular_core.Signal<string | null>;
111
164
  protected readonly describedBy: _angular_core.Signal<string | null>;
112
165
  protected readonly invalid: _angular_core.Signal<boolean>;
113
166
  protected readonly required: _angular_core.Signal<boolean>;
167
+ /** Élément DOM hôte du contrôle (exposé pour le focus / la mesure par le parent). */
114
168
  readonly element: HTMLElement;
115
169
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtFieldControl, never>;
116
170
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<KtFieldControl, "[ktFieldControl]", never, {}, {}, never, never, true, never>;
117
171
  }
118
172
 
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
173
  /** Base partagée des champs simples (TextField, NumberField) : état FormValueControl,
134
174
  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. */
175
+ La valeur, son parsing et la notion de « vide » sont fournis par la sous-classe.
176
+
177
+ @example
178
+ ```ts
179
+ // Sous-classement : on fournit value (model concret) + parse/emptyValue/isEmpty.
180
+ @Component({ selector: 'kt-text-field', templateUrl: './text-field.html' })
181
+ export class KtTextField extends KtBaseInputField<string> implements FormValueControl<string> {
182
+ readonly value = model<string>('');
183
+ protected parse(raw: string): string { return raw; }
184
+ protected emptyValue(): string { return ''; }
185
+ protected isEmpty(value: string): boolean { return value.length === 0; }
186
+ }
187
+ ``` */
136
188
  declare abstract class KtBaseInputField<T> {
137
189
  protected readonly config: Partial<_ktortu_aaa_forms.KtFieldConfig> | null;
138
190
  /** Valeur du contrôle — déclarée concrètement par la sous-classe. */
@@ -140,55 +192,71 @@ declare abstract class KtBaseInputField<T> {
140
192
  /** Marque le champ comme « visité » (déclenche l'affichage des erreurs). Deux-way. @default false */
141
193
  readonly touched: ModelSignal<boolean>;
142
194
  /** Désactive la saisie et le focus. @default false */
143
- readonly disabled: _angular_core.InputSignal<boolean>;
195
+ readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
144
196
  /** Rend le champ en lecture seule (valeur visible, non modifiable). @default false */
145
- readonly readonly: _angular_core.InputSignal<boolean>;
197
+ readonly readonly: _angular_core.InputSignalWithTransform<boolean, unknown>;
146
198
  /** Le champ est-il en erreur (état fourni par la validation). @default false */
147
- readonly invalid: _angular_core.InputSignal<boolean>;
199
+ readonly invalid: _angular_core.InputSignalWithTransform<boolean, unknown>;
148
200
  /** Marque le champ comme requis (ajoute `aria-required`). @default false */
149
- readonly required: _angular_core.InputSignal<boolean>;
201
+ readonly required: _angular_core.InputSignalWithTransform<boolean, unknown>;
150
202
  /** Le champ a-t-il été modifié depuis sa valeur initiale. @default false */
151
- readonly dirty: _angular_core.InputSignal<boolean>;
203
+ readonly dirty: _angular_core.InputSignalWithTransform<boolean, unknown>;
152
204
  /** Liste des erreurs de validation à afficher. @default [] */
153
205
  readonly errors: _angular_core.InputSignal<readonly WithOptionalFieldTree<ValidationError>[]>;
154
206
  /** Attribut `name` natif du contrôle. @default '' */
155
207
  readonly name: _angular_core.InputSignal<string>;
156
- /** id imposé pour des sélecteurs de test stables ; sinon auto-généré par Field. */
208
+ /** id imposé pour des sélecteurs de test stables ; sinon auto-généré par Field. @default undefined */
157
209
  readonly id: _angular_core.InputSignal<string | undefined>;
158
- /** Libellé du champ (associé via `<label for>`). */
210
+ /** Libellé du champ (associé via `<label for>`). @default undefined */
159
211
  readonly label: _angular_core.InputSignal<string | undefined>;
160
- /** Texte d'aide affiché sous le champ quand il est valide. */
212
+ /** Texte d'aide affiché sous le champ quand il est valide. @default undefined */
161
213
  readonly hint: _angular_core.InputSignal<string | undefined>;
162
- /** Aide contextuelle riche : texte ou `TemplateRef` projeté dans une infobulle d'aide. */
214
+ /** Aide contextuelle riche : texte ou `TemplateRef` projeté dans une infobulle d'aide. @default undefined */
163
215
  readonly helpText: _angular_core.InputSignal<string | TemplateRef<unknown> | undefined>;
164
216
  /** Libellé accessible du bouton d'aide. @default 'Help' (ou KT_FIELD_CONFIG.helpLabel) */
165
217
  readonly helpLabel: _angular_core.InputSignal<string>;
166
- /** Force la valeur de `aria-describedby` (sinon dérivée de hint/erreur). */
218
+ /** Force la valeur de `aria-describedby` (sinon dérivée de hint/erreur). @default undefined */
167
219
  readonly customDescribedBy: _angular_core.InputSignal<string | undefined>;
168
220
  /** Émis au clic sur le bouton d'aide contextuelle. */
169
221
  readonly helpClick: _angular_core.OutputEmitterRef<MouseEvent>;
170
- /** Texte indicatif affiché dans le champ vide. */
222
+ /** Texte indicatif affiché dans le champ vide. @default undefined */
171
223
  readonly placeholder: _angular_core.InputSignal<string | undefined>;
172
224
  /** Indice d'autoremplissage du navigateur (attribut `autocomplete` natif) ; ex. `'current-password'`,
173
225
  `'new-password'`, `'email'`, `'username'`, `'off'`.
174
226
  @default undefined */
175
227
  readonly autocomplete: _angular_core.InputSignal<AutoFill | undefined>;
176
- /** Nom d'icône Material Symbols affichée en tête de champ. */
228
+ /** Nom d'icône Material Symbols affichée en tête de champ. @default undefined */
177
229
  readonly icon: _angular_core.InputSignal<string | undefined>;
178
230
  /** Affiche un bouton « effacer » quand le champ contient une valeur. @default false */
179
231
  readonly clearable: _angular_core.InputSignalWithTransform<boolean, unknown>;
180
- /** Contenu décoratif en tête de champ : texte ou `TemplateRef`. */
232
+ /** Contenu décoratif en tête de champ : texte ou `TemplateRef`. @default undefined */
181
233
  readonly prefix: _angular_core.InputSignal<string | TemplateRef<unknown> | undefined>;
182
- /** Contenu décoratif en fin de champ : texte ou `TemplateRef`. */
234
+ /** Contenu décoratif en fin de champ : texte ou `TemplateRef`. @default undefined */
183
235
  readonly suffix: _angular_core.InputSignal<string | TemplateRef<unknown> | undefined>;
184
236
  /** Libellé i18n du bouton « effacer ». @default 'Clear' (ou KT_FIELD_CONFIG.clearLabel) */
185
237
  readonly clearLabel: _angular_core.InputSignal<string>;
186
- /** Quand afficher l'erreur ; surcharge KT_FIELD_CONFIG et le défaut (`invalid && touched`). */
238
+ /** Quand afficher l'erreur ; surcharge KT_FIELD_CONFIG et le défaut (`invalid && touched`). @default undefined */
187
239
  readonly errorMatcher: _angular_core.InputSignal<KtFieldErrorMatcher | undefined>;
240
+ /** Apparence du chrome (`fill` | `outline`) ; non fournie ⇒ `KT_FIELD_CONFIG.appearance` ?? `'fill'`.
241
+ @default undefined */
242
+ readonly appearance: _angular_core.InputSignal<KtFieldAppearance | undefined>;
243
+ /** Politique du label flottant en outline (`auto` | `always`) ; non fournie ⇒ `KT_FIELD_CONFIG.floatLabel`
244
+ ?? `'auto'`. En `always`, le label reste en haut même vide et le placeholder s'affiche. @default undefined */
245
+ readonly floatLabel: _angular_core.InputSignal<KtFloatLabel | undefined>;
188
246
  protected readonly inputRef: _angular_core.Signal<ElementRef<HTMLInputElement | HTMLTextAreaElement> | undefined>;
189
247
  private readonly matcher;
190
248
  protected readonly showInvalid: _angular_core.Signal<boolean>;
191
249
  protected readonly showClear: _angular_core.Signal<boolean>;
250
+ /** Apparence effective (input ?? config ?? 'fill'). Sert aux templates : forward à `kt-field` et,
251
+ en outline, pose une sentinelle de placeholder pour la détection « rempli » du label flottant. */
252
+ protected readonly outline: _angular_core.Signal<boolean>;
253
+ /** Label toujours flotté en outline (input ?? config ?? 'auto'). */
254
+ protected readonly alwaysFloat: _angular_core.Signal<boolean>;
255
+ /** Valeur de l'attribut `placeholder` natif selon l'apparence :
256
+ - fill : le placeholder tel quel ;
257
+ - outline + always : le vrai placeholder (le label est en haut, pas de chevauchement) ;
258
+ - outline + auto : sentinelle `' '` (le label tient lieu de placeholder ; active `:placeholder-shown`). */
259
+ protected readonly placeholderAttr: _angular_core.Signal<string | null>;
192
260
  protected asTemplate(value: string | TemplateRef<unknown> | undefined): TemplateRef<unknown> | null;
193
261
  protected asText(value: string | TemplateRef<unknown> | undefined): string | null;
194
262
  protected onInput(event: Event): void;
@@ -201,8 +269,26 @@ declare abstract class KtBaseInputField<T> {
201
269
  /** La valeur est-elle vide (affichage du bouton d'effacement) ? */
202
270
  protected abstract isEmpty(value: T): boolean;
203
271
  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>;
272
+ 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; }; "appearance": { "alias": "appearance"; "required": false; "isSignal": true; }; "floatLabel": { "alias": "floatLabel"; "required": false; "isSignal": true; }; }, { "touched": "touchedChange"; "helpClick": "helpClick"; }, never, never, true, never>;
273
+ }
274
+
275
+ /** Suggestion d'un champ de saisie (rendu `<datalist>`) : soit la valeur seule, soit un couple
276
+ `{ value, label }` où `label` est le texte affiché et `value` ce qui est inséré dans le champ.
277
+ @template V Type de la valeur du champ (string, number, ou type Temporal selon le champ). */
278
+ type KtSuggestion<V> = V | {
279
+ value: V;
280
+ label?: string;
281
+ };
282
+ /** Option `<datalist>` normalisée : `value` est la chaîne posée sur l'attribut DOM, `label` le
283
+ libellé affiché (ou `null`). */
284
+ interface KtDatalistOption {
285
+ value: string;
286
+ label: string | null;
205
287
  }
288
+ /** Normalise une liste de suggestions en options `<datalist>`. `toValue` sérialise la valeur en
289
+ chaîne attendue par l'input natif (identité pour le texte, `String()` pour les nombres,
290
+ `serialize()` pour les champs Temporal). */
291
+ declare function normalizeKtSuggestions<V>(suggestions: readonly KtSuggestion<V>[] | undefined, toValue: (value: V) => string): readonly KtDatalistOption[];
206
292
 
207
293
  /**
208
294
  * Champ numérique : valeur `number | null` (champ vide ⇒ `null`, jamais `NaN`), intégré aux
@@ -231,7 +317,7 @@ declare class KtNumberField extends KtBaseInputField<number | null> implements F
231
317
  private readonly uid;
232
318
  protected readonly datalistId: string;
233
319
  protected readonly hasSuggestions: _angular_core.Signal<boolean>;
234
- protected readonly datalistOptions: _angular_core.Signal<readonly KtDatalistOption[]>;
320
+ protected readonly datalistOptions: _angular_core.Signal<readonly _ktortu_aaa_forms.KtDatalistOption[]>;
235
321
  protected readonly rawValue: _angular_forms_signals.TransformedValueSignal<string>;
236
322
  protected parse(raw: string): number | null;
237
323
  protected onKeyDown(event: KeyboardEvent): void;
@@ -289,7 +375,7 @@ declare class KtTextField extends KtBaseInputField<string> implements FormValueC
289
375
  private readonly uid;
290
376
  protected readonly datalistId: string;
291
377
  protected readonly hasSuggestions: _angular_core.Signal<boolean>;
292
- protected readonly datalistOptions: _angular_core.Signal<readonly KtDatalistOption[]>;
378
+ protected readonly datalistOptions: _angular_core.Signal<readonly _ktortu_aaa_forms.KtDatalistOption[]>;
293
379
  protected parse(raw: string): string;
294
380
  protected emptyValue(): string;
295
381
  protected isEmpty(value: string): boolean;
@@ -316,11 +402,11 @@ declare class KtSwitch implements FormValueControl<boolean> {
316
402
  /** Désactive la bascule (non actionnable). @default false */
317
403
  readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
318
404
  /** Marque la bascule comme invalide (combiné à `touched`/`dirty` via l'`errorMatcher`). @default false */
319
- readonly invalid: _angular_core.InputSignal<boolean>;
405
+ readonly invalid: _angular_core.InputSignalWithTransform<boolean, unknown>;
320
406
  /** Affiche l'astérisque requis sur le libellé. @default false */
321
407
  readonly required: _angular_core.InputSignalWithTransform<boolean, unknown>;
322
408
  /** État « modifié » (entre dans la logique d'affichage des erreurs). @default false */
323
- readonly dirty: _angular_core.InputSignal<boolean>;
409
+ readonly dirty: _angular_core.InputSignalWithTransform<boolean, unknown>;
324
410
  /** Erreurs de validation à afficher sous la bascule. @default [] */
325
411
  readonly errors: _angular_core.InputSignal<readonly WithOptionalFieldTree<ValidationError>[]>;
326
412
  /** Identifiant logique du contrôle (à titre indicatif). @default '' */
@@ -336,7 +422,7 @@ declare class KtSwitch implements FormValueControl<boolean> {
336
422
  /** Stratégie décidant quand afficher les erreurs (sinon celle du `KT_FIELD_CONFIG`). @default undefined */
337
423
  readonly errorMatcher: _angular_core.InputSignal<KtFieldErrorMatcher | undefined>;
338
424
  /** Afficher toutes les erreurs au lieu de la première seule. @default KT_FIELD_CONFIG.showAllErrors ?? false */
339
- readonly showAllErrors: _angular_core.InputSignal<boolean>;
425
+ readonly showAllErrors: _angular_core.InputSignalWithTransform<boolean, unknown>;
340
426
  private readonly idGen;
341
427
  private readonly uid;
342
428
  protected readonly baseId: _angular_core.Signal<string>;
@@ -348,6 +434,7 @@ declare class KtSwitch implements FormValueControl<boolean> {
348
434
  protected readonly displayedErrors: _angular_core.Signal<readonly WithOptionalFieldTree<ValidationError>[]>;
349
435
  protected readonly resolvedAriaLabel: _angular_core.Signal<string | null>;
350
436
  protected readonly describedBy: _angular_core.Signal<string | null>;
437
+ constructor();
351
438
  protected toggle(): void;
352
439
  protected onSpacebar(event: Event): void;
353
440
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtSwitch, never>;
@@ -366,9 +453,9 @@ declare class KtSwitch implements FormValueControl<boolean> {
366
453
  * @example
367
454
  * ```html
368
455
  * <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" />
456
+ * <kt-checkbox [optionValue]="'sport'" label="Sport" />
457
+ * <kt-checkbox [optionValue]="'musique'" label="Musique" />
458
+ * <kt-checkbox [optionValue]="'cinema'" label="Cinéma" />
372
459
  * </kt-checkbox-group>
373
460
  * ```
374
461
  */
@@ -381,14 +468,16 @@ declare class KtCheckboxGroup<V> implements FormValueControl<V[]> {
381
468
  /** Désactive le groupe entier (hérité par chaque case enfant). @default false */
382
469
  readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
383
470
  /** Marque le groupe comme invalide (combiné à `touched`/`dirty` via l'`errorMatcher`). @default false */
384
- readonly invalid: _angular_core.InputSignal<boolean>;
471
+ readonly invalid: _angular_core.InputSignalWithTransform<boolean, unknown>;
385
472
  /** Affiche l'astérisque requis et `aria-required` sur le groupe. @default false */
386
473
  readonly required: _angular_core.InputSignalWithTransform<boolean, unknown>;
387
474
  /** État « modifié » (entre dans la logique d'affichage des erreurs). @default false */
388
- readonly dirty: _angular_core.InputSignal<boolean>;
475
+ readonly dirty: _angular_core.InputSignalWithTransform<boolean, unknown>;
389
476
  /** Erreurs de validation à afficher sous le groupe. @default [] */
390
477
  readonly errors: _angular_core.InputSignal<readonly WithOptionalFieldTree<ValidationError>[]>;
391
- /** Attribut `name` partagé (à titre indicatif). @default '' */
478
+ /** Nom logique du groupe, à titre INDICATIF : contrairement à `kt-radio-group` (où `name` est
479
+ propagé aux `<input>` natifs pour le regroupement radio), il n'est PAS répercuté sur les cases
480
+ enfants (les checkboxes n'ont pas besoin d'un `name` partagé). @default '' */
392
481
  readonly name: _angular_core.InputSignal<string>;
393
482
  /** id imposé (sélecteurs de test stables) ; sinon auto-généré, anti-collision. @default undefined */
394
483
  readonly id: _angular_core.InputSignal<string | undefined>;
@@ -401,7 +490,7 @@ declare class KtCheckboxGroup<V> implements FormValueControl<V[]> {
401
490
  /** Stratégie décidant quand afficher les erreurs (sinon celle du `KT_FIELD_CONFIG`). @default undefined */
402
491
  readonly errorMatcher: _angular_core.InputSignal<KtFieldErrorMatcher | undefined>;
403
492
  /** Afficher toutes les erreurs au lieu de la première seule. @default KT_FIELD_CONFIG.showAllErrors ?? false */
404
- readonly showAllErrors: _angular_core.InputSignal<boolean>;
493
+ readonly showAllErrors: _angular_core.InputSignalWithTransform<boolean, unknown>;
405
494
  /** Égalité des valeurs en mode objet (défaut : identité `===`). */
406
495
  readonly compareWith: _angular_core.InputSignal<((a: V, b: V) => boolean) | undefined>;
407
496
  private readonly idGen;
@@ -432,8 +521,9 @@ declare class KtCheckboxGroup<V> implements FormValueControl<V[]> {
432
521
  * DEUX MODES, selon la présence d'un `kt-checkbox-group` parent :
433
522
  * - Autonome : `value` est l'état coché (`boolean`, two-way), intégré aux Signal Forms via
434
523
  * `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.
524
+ * - Dans un groupe : `optionValue` porte la VALEUR d'option représentée ; l'état coché dérive de
525
+ * l'appartenance au tableau du groupe, et le (dé)cochage met à jour ce tableau. `value` est
526
+ * alors ignoré (c'est le groupe qui détient la sélection).
437
527
  *
438
528
  * Libellé : `label` (texte) par défaut ; un contenu projeté le remplace visuellement pour les
439
529
  * rendus riches (carte/option), `ariaLabel` portant alors le nom accessible si besoin.
@@ -445,17 +535,21 @@ declare class KtCheckboxGroup<V> implements FormValueControl<V[]> {
445
535
  *
446
536
  * <!-- Dans un groupe -->
447
537
  * <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" />
538
+ * <kt-checkbox [optionValue]="'sport'" label="Sport" />
539
+ * <kt-checkbox [optionValue]="'musique'" label="Musique" />
450
540
  * </kt-checkbox-group>
451
541
  * ```
452
542
  */
453
- declare class KtCheckbox<V = boolean> implements FormValueControl<V> {
543
+ declare class KtCheckbox<V = unknown> implements FormValueControl<boolean> {
454
544
  private readonly config;
455
545
  /** Groupe parent optionnel : présent ⇒ la case appartient à un `kt-checkbox-group`. */
456
546
  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>;
547
+ /** État coché (`boolean`, two-way) en mode autonome. Ignoré en mode groupe : c'est alors
548
+ `optionValue` + le tableau du groupe qui font foi. @default false */
549
+ readonly value: _angular_core.ModelSignal<boolean>;
550
+ /** Mode groupe uniquement : valeur d'option contribuée au tableau du `kt-checkbox-group` parent
551
+ quand la case est cochée. Sans effet en mode autonome. @default undefined */
552
+ readonly optionValue: _angular_core.InputSignal<V | undefined>;
459
553
  /** Tri-état visuel (parent d'une arborescence) : propriété DOM `indeterminate`, pas un attribut. */
460
554
  readonly indeterminate: _angular_core.InputSignalWithTransform<boolean, unknown>;
461
555
  /** État « touché » (two-way), généralement piloté par `[formField]`. @default false */
@@ -463,11 +557,11 @@ declare class KtCheckbox<V = boolean> implements FormValueControl<V> {
463
557
  /** Désactive la case (héritable du groupe parent). @default false */
464
558
  readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
465
559
  /** Marque la case comme invalide (combiné à `touched`/`dirty` via l'`errorMatcher`). @default false */
466
- readonly invalid: _angular_core.InputSignal<boolean>;
560
+ readonly invalid: _angular_core.InputSignalWithTransform<boolean, unknown>;
467
561
  /** Affiche l'astérisque requis et `aria-required`. @default false */
468
562
  readonly required: _angular_core.InputSignalWithTransform<boolean, unknown>;
469
563
  /** État « modifié » (entre dans la logique d'affichage des erreurs). @default false */
470
- readonly dirty: _angular_core.InputSignal<boolean>;
564
+ readonly dirty: _angular_core.InputSignalWithTransform<boolean, unknown>;
471
565
  /** Erreurs de validation à afficher sous la case. @default [] */
472
566
  readonly errors: _angular_core.InputSignal<readonly WithOptionalFieldTree<ValidationError>[]>;
473
567
  /** Attribut `name` du `<input>` natif. @default '' */
@@ -483,8 +577,9 @@ declare class KtCheckbox<V = boolean> implements FormValueControl<V> {
483
577
  /** Stratégie décidant quand afficher les erreurs (sinon celle du `KT_FIELD_CONFIG`). @default undefined */
484
578
  readonly errorMatcher: _angular_core.InputSignal<KtFieldErrorMatcher | undefined>;
485
579
  /** Afficher toutes les erreurs au lieu de la première seule. @default KT_FIELD_CONFIG.showAllErrors ?? false */
486
- readonly showAllErrors: _angular_core.InputSignal<boolean>;
580
+ readonly showAllErrors: _angular_core.InputSignalWithTransform<boolean, unknown>;
487
581
  private readonly inputEl;
582
+ private readonly el;
488
583
  private readonly idGen;
489
584
  private readonly uid;
490
585
  protected readonly baseId: _angular_core.Signal<string>;
@@ -504,7 +599,7 @@ declare class KtCheckbox<V = boolean> implements FormValueControl<V> {
504
599
  protected onChange(event: Event): void;
505
600
  protected onBlur(): void;
506
601
  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>;
602
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<KtCheckbox<any>, "kt-checkbox", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "optionValue": { "alias": "optionValue"; "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
603
  }
509
604
 
510
605
  /**
@@ -520,9 +615,9 @@ declare class KtCheckbox<V = boolean> implements FormValueControl<V> {
520
615
  * @example
521
616
  * ```html
522
617
  * <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" />
618
+ * <kt-radio [optionValue]="'mme'" label="Madame" />
619
+ * <kt-radio [optionValue]="'m'" label="Monsieur" />
620
+ * <kt-radio [optionValue]="'autre'" label="Autre" />
526
621
  * </kt-radio-group>
527
622
  * ```
528
623
  */
@@ -535,11 +630,11 @@ declare class KtRadioGroup<V> implements FormValueControl<V | null> {
535
630
  /** Désactive le groupe entier (hérité par chaque radio enfant). @default false */
536
631
  readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
537
632
  /** Marque le groupe comme invalide (combiné à `touched`/`dirty` via l'`errorMatcher`). @default false */
538
- readonly invalid: _angular_core.InputSignal<boolean>;
633
+ readonly invalid: _angular_core.InputSignalWithTransform<boolean, unknown>;
539
634
  /** Affiche l'astérisque requis et `aria-required` sur le groupe. @default false */
540
635
  readonly required: _angular_core.InputSignalWithTransform<boolean, unknown>;
541
636
  /** État « modifié » (entre dans la logique d'affichage des erreurs). @default false */
542
- readonly dirty: _angular_core.InputSignal<boolean>;
637
+ readonly dirty: _angular_core.InputSignalWithTransform<boolean, unknown>;
543
638
  /** Erreurs de validation à afficher sous le groupe. @default [] */
544
639
  readonly errors: _angular_core.InputSignal<readonly WithOptionalFieldTree<ValidationError>[]>;
545
640
  /** Base du `name` partagé par les radios enfants (sinon auto-généré). @default '' */
@@ -555,7 +650,7 @@ declare class KtRadioGroup<V> implements FormValueControl<V | null> {
555
650
  /** Stratégie décidant quand afficher les erreurs (sinon celle du `KT_FIELD_CONFIG`). @default undefined */
556
651
  readonly errorMatcher: _angular_core.InputSignal<KtFieldErrorMatcher | undefined>;
557
652
  /** Afficher toutes les erreurs au lieu de la première seule. @default KT_FIELD_CONFIG.showAllErrors ?? false */
558
- readonly showAllErrors: _angular_core.InputSignal<boolean>;
653
+ readonly showAllErrors: _angular_core.InputSignalWithTransform<boolean, unknown>;
559
654
  /** Égalité des valeurs en mode objet (défaut : identité `===`). Seul rescapé du contrat select. */
560
655
  readonly compareWith: _angular_core.InputSignal<((a: V, b: V) => boolean) | undefined>;
561
656
  private readonly idGen;
@@ -572,7 +667,7 @@ declare class KtRadioGroup<V> implements FormValueControl<V | null> {
572
667
  protected readonly resolvedAriaLabel: _angular_core.Signal<string | null>;
573
668
  protected readonly describedBy: _angular_core.Signal<string | null>;
574
669
  private readonly comparator;
575
- /** Le `value` d'un enfant correspond-il à la sélection courante ? (lu dans le `computed` enfant) */
670
+ /** L'`optionValue` d'un enfant correspond-il à la sélection courante ? (lu dans le `computed` enfant) */
576
671
  isSelected(radioValue: V): boolean;
577
672
  /** Commit d'une sélection émis par un enfant au `change` natif. */
578
673
  select(radioValue: V): void;
@@ -589,15 +684,16 @@ declare class KtRadioGroup<V> implements FormValueControl<V | null> {
589
684
  * @example
590
685
  * ```html
591
686
  * <kt-radio-group label="Civilité" [(value)]="civility">
592
- * <kt-radio [value]="'mme'" label="Madame" />
593
- * <kt-radio [value]="'m'" label="Monsieur" />
687
+ * <kt-radio [optionValue]="'mme'" label="Madame" />
688
+ * <kt-radio [optionValue]="'m'" label="Monsieur" />
594
689
  * </kt-radio-group>
595
690
  * ```
596
691
  */
597
692
  declare class KtRadio<V> {
598
693
  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>;
694
+ /** Valeur d'option représentée par ce radio (sélectionnée ⇒ devient la valeur du groupe). Nommée
695
+ `optionValue` pour s'aligner sur `kt-checkbox` (où `value` = état coché). @default (requis) */
696
+ readonly optionValue: _angular_core.InputSignal<V>;
601
697
  /** Texte du libellé (remplacé visuellement par un contenu projeté). @default undefined */
602
698
  readonly label: _angular_core.InputSignal<string | undefined>;
603
699
  /** Texte d'aide affiché sous le radio. @default undefined */
@@ -614,9 +710,11 @@ declare class KtRadio<V> {
614
710
  protected readonly hintId: _angular_core.Signal<string>;
615
711
  protected readonly checked: _angular_core.Signal<boolean>;
616
712
  protected readonly isDisabled: _angular_core.Signal<boolean>;
713
+ private readonly el;
714
+ constructor();
617
715
  protected onChange(): void;
618
716
  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>;
717
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<KtRadio<any>, "kt-radio", never, { "optionValue": { "alias": "optionValue"; "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
718
  }
621
719
 
622
720
  /** Clé (propriété) OU fonction d'accès, pour dériver une valeur d'un item.
@@ -660,15 +758,15 @@ declare abstract class KtBaseSelect<T, V = T> {
660
758
  /** Le champ a-t-il été visité ? Poussé par `[formField]` ; passe à `true` à la première sélection. @default false */
661
759
  readonly touched: _angular_core.ModelSignal<boolean>;
662
760
  /** Champ désactivé (trigger inerte). Poussé par `[formField]`. @default false */
663
- readonly disabled: _angular_core.InputSignal<boolean>;
761
+ readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
664
762
  /** Champ en lecture seule (sélection figée, valeur affichée). Poussé par `[formField]`. @default false */
665
- readonly readonly: _angular_core.InputSignal<boolean>;
763
+ readonly readonly: _angular_core.InputSignalWithTransform<boolean, unknown>;
666
764
  /** Le champ est-il invalide ? Pilote l'affichage des erreurs. Poussé par `[formField]`. @default false */
667
- readonly invalid: _angular_core.InputSignal<boolean>;
765
+ readonly invalid: _angular_core.InputSignalWithTransform<boolean, unknown>;
668
766
  /** Champ obligatoire (marqueur visuel/ARIA). Poussé par `[formField]`. @default false */
669
- readonly required: _angular_core.InputSignal<boolean>;
767
+ readonly required: _angular_core.InputSignalWithTransform<boolean, unknown>;
670
768
  /** Le champ a-t-il été modifié depuis sa valeur initiale ? Poussé par `[formField]`. @default false */
671
- readonly dirty: _angular_core.InputSignal<boolean>;
769
+ readonly dirty: _angular_core.InputSignalWithTransform<boolean, unknown>;
672
770
  /** Erreurs de validation à afficher. Poussé par `[formField]`. @default [] */
673
771
  readonly errors: _angular_core.InputSignal<readonly WithOptionalFieldTree<ValidationError>[]>;
674
772
  /** Attribut `name` logique du contrôle (à titre indicatif). @default '' */
@@ -689,9 +787,15 @@ declare abstract class KtBaseSelect<T, V = T> {
689
787
  readonly placeholder: _angular_core.InputSignal<string | undefined>;
690
788
  /** Quand afficher l'erreur ; surcharge KT_FIELD_CONFIG et le défaut (`invalid && touched`). @default undefined */
691
789
  readonly errorMatcher: _angular_core.InputSignal<KtFieldErrorMatcher | undefined>;
790
+ /** Apparence du chrome (`fill` | `outline`) ; non fournie ⇒ `KT_FIELD_CONFIG.appearance` ?? `'fill'`.
791
+ @default undefined */
792
+ readonly appearance: _angular_core.InputSignal<KtFieldAppearance | undefined>;
793
+ /** Politique du label flottant en outline (`auto` | `always`) ; non fournie ⇒ `KT_FIELD_CONFIG.floatLabel`
794
+ ?? `'auto'`. @default undefined */
795
+ readonly floatLabel: _angular_core.InputSignal<KtFloatLabel | undefined>;
692
796
  /** 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>;
797
+ Pour les listes longues ; le texte tapé ne sert qu'à filtrer (réinitialisé à la fermeture). @default false */
798
+ readonly filterable: _angular_core.InputSignalWithTransform<boolean, unknown>;
695
799
  /** Placeholder du champ de recherche du popup. Défaut : `KT_SELECT_CONFIG.filterPlaceholder` ou vide. */
696
800
  readonly filterPlaceholder: _angular_core.InputSignal<string | undefined>;
697
801
  /** Libellé accessible du champ de recherche. Défaut : `KT_SELECT_CONFIG.filterLabel` ou « Filter options ». */
@@ -791,7 +895,7 @@ declare abstract class KtBaseSelect<T, V = T> {
791
895
  protected onDragStart(event: PointerEvent): void;
792
896
  private animateAndCloseSelect;
793
897
  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>;
898
+ 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; }; "appearance": { "alias": "appearance"; "required": false; "isSignal": true; }; "floatLabel": { "alias": "floatLabel"; "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
899
  }
796
900
 
797
901
  /** Contexte typé reçu par le template d'une option (`ktSelectOption`). */
@@ -863,7 +967,12 @@ interface KtSelectSelectionChange<T, V = T> {
863
967
 
864
968
  @example
865
969
  ```html
866
- <kt-select [options]="users" optionLabel="name" optionValue="id" [(value)]="selectedId" />
970
+ <kt-select
971
+ [options]="users"
972
+ optionLabel="name"
973
+ optionValue="id"
974
+ [(value)]="selectedId"
975
+ (selectionChange)="onSelectionChange($event)" />
867
976
  ``` */
868
977
  declare class KtSelect<T, V = T> extends KtBaseSelect<T, V> implements FormValueControl<V | null> {
869
978
  /** Valeur sélectionnée (clé extraite, ou objet entier si `optionValue` est omis ; `null` si rien). @default null */
@@ -932,6 +1041,13 @@ interface KtSelectConfigOptions {
932
1041
  truncatedResultsAnnouncement: (max: number, total: number) => string;
933
1042
  }
934
1043
  declare const KT_SELECT_CONFIG: InjectionToken<Partial<KtSelectConfigOptions>>;
1044
+ /**
1045
+ * Source UNIQUE des défauts (anglais neutre) de la config select / multi-select. Constitue le 3e
1046
+ * maillon de la résolution `input() ?? KT_SELECT_CONFIG ?? DEFAULT_KT_SELECT_CONFIG`, jusqu'ici
1047
+ * éparpillé entre `base-select.ts`, `multi-select.ts` et des fonctions locales. Centralisé ici pour
1048
+ * éviter toute dérive et garantir la complétude des traductions (cf. test de complétude i18n).
1049
+ */
1050
+ declare const DEFAULT_KT_SELECT_CONFIG: Required<KtSelectConfigOptions>;
935
1051
 
936
1052
  /** Configure les `kt-select` d'un sous-arbre via DI (équivalent du Context provider de react-select).
937
1053
  Alternative à un provider global de `KT_SELECT_CONFIG` : on pose la directive sur un conteneur et
@@ -945,30 +1061,13 @@ declare const KT_SELECT_CONFIG: InjectionToken<Partial<KtSelectConfigOptions>>;
945
1061
 
946
1062
  La directive EST fournie comme `KT_SELECT_CONFIG` (`useExisting`) : les getters exposent l'objet
947
1063
  bindé sous la forme `Partial<KtSelectConfigOptions>` attendue par le composant. */
948
- declare class KtSelectConfig implements Partial<KtSelectConfigOptions> {
1064
+ declare class KtSelectConfig {
949
1065
  readonly ktSelectConfig: _angular_core.InputSignal<Partial<KtSelectConfigOptions>>;
950
1066
  /** Config héritée du contexte parent (provider global ou directive englobante) : la
951
1067
  directive ne masque que les clés qu'elle définit, le reste continue d'en hériter. */
952
1068
  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;
1069
+ /** Résout une clé : valeur bindée sur la directive, sinon valeur héritée du contexte parent. */
1070
+ resolve<K extends keyof KtSelectConfigOptions>(key: K): Partial<KtSelectConfigOptions>[K];
972
1071
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtSelectConfig, never>;
973
1072
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<KtSelectConfig, "[ktSelectConfig]", never, { "ktSelectConfig": { "alias": "ktSelectConfig"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
974
1073
  }
@@ -1070,7 +1169,12 @@ interface KtMultiSelectSelectionChange<T, V = T> {
1070
1169
  *
1071
1170
  * @example
1072
1171
  * ```html
1073
- * <kt-multi-select [options]="tags" optionLabel="name" optionValue="id" [(value)]="selectedIds" />
1172
+ * <kt-multi-select
1173
+ * [options]="tags"
1174
+ * optionLabel="name"
1175
+ * optionValue="id"
1176
+ * [(value)]="selectedIds"
1177
+ * (selectionChange)="onSelectionChange($event)" />
1074
1178
  * ```
1075
1179
  */
1076
1180
  declare class KtMultiSelect<T, V = T> extends KtBaseSelect<T, V> implements FormValueControl<V[]> {
@@ -1180,7 +1284,11 @@ declare class KtChip {
1180
1284
  /** Émis au clic sur le bouton « retirer » (le parent décide de retirer le chip). */
1181
1285
  readonly remove: _angular_core.OutputEmitterRef<void>;
1182
1286
  private readonly removeBtn;
1183
- /** Focus programmatique du bouton « retirer » (focus management d'`kt-chip-list`). */
1287
+ /**
1288
+ * Focus programmatique du bouton « retirer ». Helper de coordination interne (focus management
1289
+ * d'`kt-chip-list`), non destiné aux consommateurs.
1290
+ * @internal
1291
+ */
1184
1292
  focusRemove(): void;
1185
1293
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtChip, never>;
1186
1294
  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>;
@@ -1205,6 +1313,7 @@ interface KtChipItemContext<T> {
1205
1313
  </kt-chip-list>
1206
1314
  ``` */
1207
1315
  declare class KtChipItemDef<T> {
1316
+ /** Liste des items rendus par ce template (sert aussi à inférer le type `T` du contexte). */
1208
1317
  readonly ktChipItem: _angular_core.InputSignal<readonly T[]>;
1209
1318
  readonly template: TemplateRef<KtChipItemContext<T>>;
1210
1319
  static ngTemplateContextGuard<T>(_dir: KtChipItemDef<T>, ctx: unknown): ctx is KtChipItemContext<T>;
@@ -1234,6 +1343,7 @@ declare class KtChipList<T> implements ChipTransitionScope {
1234
1343
  private readonly doc;
1235
1344
  private readonly platformId;
1236
1345
  private readonly cdr;
1346
+ private readonly ngZone;
1237
1347
  /** Vrai pendant la View Transition de CETTE liste : les chips (standards via Chip,
1238
1348
  custom via tokens.css) ne portent leur `view-transition-name` que dans cette fenêtre. */
1239
1349
  readonly transitioning: _angular_core.WritableSignal<boolean>;
@@ -1338,8 +1448,8 @@ interface KtChipsConfig {
1338
1448
  declare const KT_CHIPS_CONFIG: InjectionToken<Partial<KtChipsConfig>>;
1339
1449
 
1340
1450
  /** 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
1451
+ Toute la logique commune (parsing tolérant, valeur vide `null`, synchronisation de l'input natif)
1452
+ vit ici ; chaque sous-classe ne fournit que la construction et la sérialisation propres
1343
1453
  à son type Temporal (`fromString` / `serialize`).
1344
1454
 
1345
1455
  Contrat abstrait : une sous-classe implémente uniquement le couple
@@ -1349,7 +1459,20 @@ declare const KT_CHIPS_CONFIG: InjectionToken<Partial<KtChipsConfig>>;
1349
1459
  tolérant (saisie partielle/invalide → `null`, jamais d'exception ni de valeur fausse).
1350
1460
 
1351
1461
  @template T Type Temporal porté par le champ (ex. `Temporal.PlainDate`,
1352
- `Temporal.PlainTime`, …). Doit exposer `toString()`. La valeur du champ est `T | null`. */
1462
+ `Temporal.PlainTime`, …). Doit exposer `toString()`. La valeur du champ est `T | null`.
1463
+
1464
+ @example
1465
+ ```ts
1466
+ // Sous-classer : ne fournir que fromString (input natif → T) et serialize (T → input natif).
1467
+ export class KtDateField extends KtBaseTemporalField<Temporal.PlainDate> {
1468
+ protected override fromString(raw: string): Temporal.PlainDate {
1469
+ return Temporal.PlainDate.from(raw);
1470
+ }
1471
+ protected override serialize(value: Temporal.PlainDate): string {
1472
+ return value.toString();
1473
+ }
1474
+ }
1475
+ ``` */
1353
1476
  declare abstract class KtBaseTemporalField<T extends {
1354
1477
  toString(): string;
1355
1478
  }> extends KtBaseInputField<T | null> {
@@ -1362,8 +1485,16 @@ declare abstract class KtBaseTemporalField<T extends {
1362
1485
  protected parse(raw: string): T | null;
1363
1486
  protected emptyValue(): T | null;
1364
1487
  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>;
1488
+ /** Borne minimale autorisée (membre `min` du contrat `FormValueControl`, aussi posé en attribut
1489
+ `min` natif via `serialize`). Non bornée par défaut. @default undefined */
1490
+ readonly min: _angular_core.InputSignal<T | undefined>;
1491
+ /** Borne maximale autorisée (membre `max` du contrat `FormValueControl`, aussi posé en attribut
1492
+ `max` natif via `serialize`). Non bornée par défaut. @default undefined */
1493
+ readonly max: _angular_core.InputSignal<T | undefined>;
1494
+ /** Représentation ISO de `min` pour l'attribut natif (`null` quand non borné). */
1495
+ protected readonly serializedMin: _angular_core.Signal<string | null>;
1496
+ /** Représentation ISO de `max` pour l'attribut natif (`null` quand non borné). */
1497
+ protected readonly serializedMax: _angular_core.Signal<string | null>;
1367
1498
  /** Suggestions proposées via un `<datalist>` natif (le picker date/heure reste disponible).
1368
1499
  Valeurs Temporal simples ou couples `{ value, label }` ; chaque valeur est sérialisée au
1369
1500
  format de l'input via `serialize`. @default undefined */
@@ -1372,11 +1503,60 @@ declare abstract class KtBaseTemporalField<T extends {
1372
1503
  private readonly uid;
1373
1504
  protected readonly datalistId: string;
1374
1505
  protected readonly hasSuggestions: _angular_core.Signal<boolean>;
1375
- protected readonly datalistOptions: _angular_core.Signal<readonly KtDatalistOption[]>;
1506
+ protected readonly datalistOptions: _angular_core.Signal<readonly _ktortu_aaa_forms.KtDatalistOption[]>;
1376
1507
  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>;
1508
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<KtBaseTemporalField<any>, never, never, { "min": { "alias": "min"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "suggestions": { "alias": "suggestions"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1509
+ }
1510
+
1511
+ /** Précision de saisie/sérialisation des champs Temporal porteurs d'une heure. */
1512
+ type KtTimePrecision = 'minute' | 'second';
1513
+ /** Base des champs Temporal porteurs d'une heure (`Time`, `DateTime`, `Instant`). Ajoute le réglage
1514
+ `precision` qui pilote, d'un seul point, la sérialisation (`smallestUnit` du `toString`) et
1515
+ l'attribut `step` natif de l'input — un input `time`/`datetime-local` n'affiche le sélecteur de
1516
+ secondes que si `step` < 60. Les champs sans heure (`Date`, `YearMonth`) n'héritent pas de cette
1517
+ base. Chaque sous-classe lit `precision()` dans son `serialize`.
1518
+
1519
+ @example
1520
+ ```ts
1521
+ // Sous-classer : lire precision() dans serialize pour piloter smallestUnit.
1522
+ export class KtTimeField extends KtBaseTimeTemporalField<Temporal.PlainTime> {
1523
+ protected override fromString(raw: string): Temporal.PlainTime {
1524
+ return Temporal.PlainTime.from(raw);
1525
+ }
1526
+ protected override serialize(value: Temporal.PlainTime): string {
1527
+ return value.toString({ smallestUnit: this.precision() });
1528
+ }
1529
+ }
1530
+ ``` */
1531
+ declare abstract class KtBaseTimeTemporalField<T extends {
1532
+ toString(): string;
1533
+ }> extends KtBaseTemporalField<T> {
1534
+ /** Précision de l'heure : `'minute'` (secondes masquées) ou `'second'`.
1535
+ @default 'minute' */
1536
+ readonly precision: _angular_core.InputSignal<KtTimePrecision>;
1537
+ /** Attribut `step` natif : `'1'` (seconde) en précision seconde, sinon `null` (pas natif = minute). */
1538
+ protected readonly step: _angular_core.Signal<string | null>;
1539
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtBaseTimeTemporalField<any>, never>;
1540
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<KtBaseTimeTemporalField<any>, never, never, { "precision": { "alias": "precision"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1378
1541
  }
1379
1542
 
1543
+ /**
1544
+ * Point d'import unique de Temporal pour toute la lib.
1545
+ *
1546
+ * - La **valeur** runtime `Temporal` vient de `globalThis.Temporal` : native sur Chrome/Edge 144+,
1547
+ * Firefox 139+, Node 26+ ; sinon posée par le polyfill chargé dans `main.ts`
1548
+ * (`temporal-polyfill/global`) ou `test-setup.ts`.
1549
+ * - Les **types** (`TemporalNamespace.PlainDate`, …) viennent d'un `import type` (effacé au build
1550
+ * → 0 KB, le polyfill n'est jamais bundlé dans la lib).
1551
+ *
1552
+ * Convention : importer `{ Temporal, type TemporalNamespace }` — `Temporal` pour les appels
1553
+ * (`Temporal.PlainDate.from(...)`), `TemporalNamespace` pour les annotations
1554
+ * (`TemporalNamespace.PlainDate`). Le jour où le natif est garanti partout (Safari inclus), il
1555
+ * suffira de retirer le polyfill de `main.ts` : ce fichier ne change pas.
1556
+ */
1557
+ type TemporalImpl = (typeof temporal_polyfill)['Temporal'];
1558
+ declare const Temporal: TemporalImpl;
1559
+
1380
1560
  /** Date civile (jour/mois/année), sans heure ni fuseau — alias de `Temporal.PlainDate`.
1381
1561
  À utiliser pour une date « pure » : naissance, échéance, jour d'un événement.
1382
1562
  *
@@ -1385,22 +1565,22 @@ declare abstract class KtBaseTemporalField<T extends {
1385
1565
  * import { type CalendarDate } from '@ktortu/aaa';
1386
1566
  * ```
1387
1567
  */
1388
- type CalendarDate = Temporal.PlainDate;
1568
+ type CalendarDate = Temporal$1.PlainDate;
1389
1569
  /** Heure « au mur » (heure/minute/seconde), sans date ni fuseau — alias de `Temporal.PlainTime`.
1390
1570
  À utiliser pour une heure isolée : heure d'ouverture, créneau de rendez-vous récurrent. */
1391
- type WallTime = Temporal.PlainTime;
1571
+ type WallTime = Temporal$1.PlainTime;
1392
1572
  /** Date + heure locale, sans fuseau — alias de `Temporal.PlainDateTime`.
1393
1573
  À utiliser quand date et heure comptent mais que le fuseau est implicite/non pertinent
1394
1574
  (heure « au mur » : ne représente pas un instant absolu). */
1395
- type LocalDateTime = Temporal.PlainDateTime;
1575
+ type LocalDateTime = Temporal$1.PlainDateTime;
1396
1576
  /** Instant absolu sur la ligne du temps, en UTC — alias de `Temporal.Instant`.
1397
1577
  À utiliser pour horodater un événement réel (création, mesure) indépendamment du fuseau
1398
1578
  d'affichage ; la conversion en heure locale se fait à la présentation (via `KtClock`). */
1399
- type Timestamp = Temporal.Instant;
1579
+ type Timestamp = Temporal$1.Instant;
1400
1580
  /** Instant + fuseau nommé (IANA) — alias de `Temporal.ZonedDateTime`.
1401
1581
  À utiliser quand le fuseau fait partie de la donnée (ex. « 14h00 à Paris ») et doit être
1402
1582
  conservé, contrairement à `Timestamp` qui ne porte pas de fuseau. */
1403
- type ZonedTimestamp = Temporal.ZonedDateTime;
1583
+ type ZonedTimestamp = Temporal$1.ZonedDateTime;
1404
1584
 
1405
1585
  /** Champ « date sans heure » : valeur = `Temporal.PlainDate`, input natif `type="date"`.
1406
1586
  *
@@ -1409,13 +1589,13 @@ type ZonedTimestamp = Temporal.ZonedDateTime;
1409
1589
  * <kt-date-field label="Date de naissance" [(value)]="birthDate" />
1410
1590
  * ```
1411
1591
  */
1412
- declare class KtDateField extends KtBaseTemporalField<Temporal.PlainDate> implements FormValueControl<Temporal.PlainDate | null> {
1592
+ declare class KtDateField extends KtBaseTemporalField<Temporal$1.PlainDate> implements FormValueControl<Temporal$1.PlainDate | null> {
1413
1593
  /** Valeur du champ : un `Temporal.PlainDate` (date civile sans heure ni fuseau).
1414
1594
  `null` = champ vide.
1415
1595
  @default null */
1416
- value: _angular_core.ModelSignal<Temporal.PlainDate | null>;
1417
- protected fromString(raw: string): Temporal.PlainDate;
1418
- protected serialize(value: Temporal.PlainDate): string;
1596
+ value: _angular_core.ModelSignal<Temporal$1.PlainDate | null>;
1597
+ protected fromString(raw: string): Temporal$1.PlainDate;
1598
+ protected serialize(value: Temporal$1.PlainDate): string;
1419
1599
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtDateField, never>;
1420
1600
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<KtDateField, "kt-date-field", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, ["[ktFieldHelp]"], true, never>;
1421
1601
  }
@@ -1427,13 +1607,13 @@ declare class KtDateField extends KtBaseTemporalField<Temporal.PlainDate> implem
1427
1607
  * <kt-time-field label="Heure de rendez-vous" [(value)]="appointmentTime" />
1428
1608
  * ```
1429
1609
  */
1430
- declare class KtTimeField extends KtBaseTemporalField<Temporal.PlainTime> implements FormValueControl<Temporal.PlainTime | null> {
1610
+ declare class KtTimeField extends KtBaseTimeTemporalField<Temporal$1.PlainTime> implements FormValueControl<Temporal$1.PlainTime | null> {
1431
1611
  /** Valeur du champ : un `Temporal.PlainTime` (heure « au mur », sans date ni fuseau).
1432
1612
  `null` = champ vide.
1433
1613
  @default null */
1434
- value: _angular_core.ModelSignal<Temporal.PlainTime | null>;
1435
- protected fromString(raw: string): Temporal.PlainTime;
1436
- protected serialize(value: Temporal.PlainTime): string;
1614
+ value: _angular_core.ModelSignal<Temporal$1.PlainTime | null>;
1615
+ protected fromString(raw: string): Temporal$1.PlainTime;
1616
+ protected serialize(value: Temporal$1.PlainTime): string;
1437
1617
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtTimeField, never>;
1438
1618
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<KtTimeField, "kt-time-field", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, ["[ktFieldHelp]"], true, never>;
1439
1619
  }
@@ -1446,13 +1626,13 @@ declare class KtTimeField extends KtBaseTemporalField<Temporal.PlainTime> implem
1446
1626
  * <kt-date-time-field label="Début de l'événement" [(value)]="startsAt" />
1447
1627
  * ```
1448
1628
  */
1449
- declare class KtDateTimeField extends KtBaseTemporalField<Temporal.PlainDateTime> implements FormValueControl<Temporal.PlainDateTime | null> {
1629
+ declare class KtDateTimeField extends KtBaseTimeTemporalField<Temporal$1.PlainDateTime> implements FormValueControl<Temporal$1.PlainDateTime | null> {
1450
1630
  /** Valeur du champ : un `Temporal.PlainDateTime` (date + heure « au mur », sans fuseau).
1451
1631
  `null` = champ vide.
1452
1632
  @default null */
1453
- value: _angular_core.ModelSignal<Temporal.PlainDateTime | null>;
1454
- protected fromString(raw: string): Temporal.PlainDateTime;
1455
- protected serialize(value: Temporal.PlainDateTime): string;
1633
+ value: _angular_core.ModelSignal<Temporal$1.PlainDateTime | null>;
1634
+ protected fromString(raw: string): Temporal$1.PlainDateTime;
1635
+ protected serialize(value: Temporal$1.PlainDateTime): string;
1456
1636
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtDateTimeField, never>;
1457
1637
  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
1638
  }
@@ -1465,13 +1645,13 @@ declare class KtDateTimeField extends KtBaseTemporalField<Temporal.PlainDateTime
1465
1645
  * <kt-year-month-field label="Expiration" [(value)]="cardExpiry" />
1466
1646
  * ```
1467
1647
  */
1468
- declare class KtYearMonthField extends KtBaseTemporalField<Temporal.PlainYearMonth> implements FormValueControl<Temporal.PlainYearMonth | null> {
1648
+ declare class KtYearMonthField extends KtBaseTemporalField<Temporal$1.PlainYearMonth> implements FormValueControl<Temporal$1.PlainYearMonth | null> {
1469
1649
  /** Valeur du champ : un `Temporal.PlainYearMonth` (mois + année, sans jour ni fuseau).
1470
1650
  `null` = champ vide.
1471
1651
  @default null */
1472
- value: _angular_core.ModelSignal<Temporal.PlainYearMonth | null>;
1473
- protected fromString(raw: string): Temporal.PlainYearMonth;
1474
- protected serialize(value: Temporal.PlainYearMonth): string;
1652
+ value: _angular_core.ModelSignal<Temporal$1.PlainYearMonth | null>;
1653
+ protected fromString(raw: string): Temporal$1.PlainYearMonth;
1654
+ protected serialize(value: Temporal$1.PlainYearMonth): string;
1475
1655
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtYearMonthField, never>;
1476
1656
  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
1657
  }
@@ -1490,20 +1670,20 @@ declare class KtYearMonthField extends KtBaseTemporalField<Temporal.PlainYearMon
1490
1670
  * <kt-instant-field label="Horodatage" [(value)]="recordedAt" />
1491
1671
  * ```
1492
1672
  */
1493
- declare class KtInstantField extends KtBaseTemporalField<Temporal.Instant> implements FormValueControl<Temporal.Instant | null> {
1673
+ declare class KtInstantField extends KtBaseTimeTemporalField<Temporal$1.Instant> implements FormValueControl<Temporal$1.Instant | null> {
1494
1674
  private readonly clock;
1495
1675
  /** Valeur du champ : un `Temporal.Instant` (instant absolu en UTC), saisi/affiché en heure
1496
1676
  locale via `KtClock`. `null` = champ vide.
1497
1677
  @default null */
1498
- value: _angular_core.ModelSignal<Temporal.Instant | null>;
1499
- protected fromString(raw: string): Temporal.Instant;
1500
- protected serialize(value: Temporal.Instant): string;
1678
+ value: _angular_core.ModelSignal<Temporal$1.Instant | null>;
1679
+ protected fromString(raw: string): Temporal$1.Instant;
1680
+ protected serialize(value: Temporal$1.Instant): string;
1501
1681
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtInstantField, never>;
1502
1682
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<KtInstantField, "kt-instant-field", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, ["[ktFieldHelp]"], true, never>;
1503
1683
  }
1504
1684
 
1505
1685
  /** Valeurs Temporal formatables pour l'affichage (toutes exposent `toLocaleString`). */
1506
- type FormattableTemporal = Temporal.PlainDate | Temporal.PlainTime | Temporal.PlainDateTime | Temporal.PlainYearMonth | Temporal.Instant | Temporal.ZonedDateTime;
1686
+ type FormattableTemporal = Temporal$1.PlainDate | Temporal$1.PlainTime | Temporal$1.PlainDateTime | Temporal$1.PlainYearMonth | Temporal$1.Instant | Temporal$1.ZonedDateTime;
1507
1687
  /** Formate une valeur Temporal pour l'affichage selon la locale active.
1508
1688
  `DatePipe` n'accepte pas Temporal (seulement `Date|string|number`) → pipe dédié, basé sur
1509
1689
  `toLocaleString` (interface `Intl.DateTimeFormat`). Cohérent avec la neutralité i18n de la lib
@@ -1524,6 +1704,13 @@ type FormattableTemporal = Temporal.PlainDate | Temporal.PlainTime | Temporal.Pl
1524
1704
  declare class KtTemporalDatePipe implements PipeTransform {
1525
1705
  private readonly locale;
1526
1706
  private readonly clock;
1707
+ /** Formate la valeur Temporal en chaîne localisée via `toLocaleString`.
1708
+ * @param value Valeur Temporal à formater (`Plain*`, `Instant` ou `ZonedDateTime`) ; `null`/`undefined` → chaîne vide.
1709
+ * @param options Options `Intl.DateTimeFormatOptions` transmises telles quelles. Styles globaux :
1710
+ * `dateStyle`/`timeStyle` (`'full' | 'long' | 'medium' | 'short'`). Champs fins :
1711
+ * `weekday`/`era`/`month` (`'long' | 'short' | 'narrow'`), `year`/`day`/`hour`/`minute`/`second`
1712
+ * (`'numeric' | '2-digit'`), `hour12`, `timeZoneName`, `timeZone`, etc. Omis → format par défaut de la locale.
1713
+ * @returns La chaîne formatée selon la locale active (`LOCALE_ID`), ou `''` si la valeur est absente. */
1527
1714
  transform(value: FormattableTemporal | null | undefined, options?: Intl.DateTimeFormatOptions): string;
1528
1715
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtTemporalDatePipe, never>;
1529
1716
  static ɵpipe: _angular_core.ɵɵPipeDeclaration<KtTemporalDatePipe, "temporalDate", true>;
@@ -1539,10 +1726,10 @@ declare class KtClock {
1539
1726
  timeZoneId(): string;
1540
1727
  /** Instant absolu courant, sur la ligne du temps (UTC), indépendant du fuseau.
1541
1728
  @returns L'instant présent en `Temporal.Instant`. */
1542
- now(): Temporal.Instant;
1729
+ now(): Temporal$1.Instant;
1543
1730
  /** Date civile du jour telle qu'observée dans le fuseau local (`timeZoneId()`).
1544
1731
  @returns Le jour courant en `Temporal.PlainDate`. */
1545
- today(): Temporal.PlainDate;
1732
+ today(): Temporal$1.PlainDate;
1546
1733
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtClock, never>;
1547
1734
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<KtClock>;
1548
1735
  }
@@ -1564,11 +1751,11 @@ declare class KtFixedClock extends KtClock {
1564
1751
  * });
1565
1752
  * ```
1566
1753
  */
1567
- constructor(fixedInstant: Temporal.Instant, zone: string);
1754
+ constructor(fixedInstant: Temporal$1.Instant, zone: string);
1568
1755
  timeZoneId(): string;
1569
- now(): Temporal.Instant;
1570
- today(): Temporal.PlainDate;
1756
+ now(): Temporal$1.Instant;
1757
+ today(): Temporal$1.PlainDate;
1571
1758
  }
1572
1759
 
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 };
1760
+ export { DEFAULT_KT_SELECT_CONFIG, KT_CHIPS_CONFIG, KT_FIELD, KT_FIELD_CONFIG, KT_SELECT_CONFIG, KtBaseInputField, KtBaseSelect, KtBaseTemporalField, KtBaseTimeTemporalField, 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, Temporal, defaultKtFieldErrorMatcher, normalizeKtSuggestions, provideKtField };
1761
+ export type { CalendarDate, KtChipItemContext, KtChipsConfig, KtDatalistOption, KtFieldAppearance, KtFieldConfig, KtFieldError, KtFieldErrorMatcher, KtFieldErrorState, KtFieldParent, KtFloatLabel, KtKeyish, KtMultiSelectChipContext, KtMultiSelectOptionContext, KtMultiSelectSelectionChange, KtMultiSelectTriggerContext, KtSelectConfigOptions, KtSelectOptionContext, KtSelectSelectionChange, KtSelectTriggerContext, KtSuggestion, KtTextFieldType, KtTimePrecision, LocalDateTime, Timestamp, WallTime, ZonedTimestamp };