@ktortu/aaa 0.9.0 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,8 @@
1
1
  import * as _angular_core from '@angular/core';
2
2
  import { InjectionToken, Signal, Provider, TemplateRef, ModelSignal, ElementRef, PipeTransform } from '@angular/core';
3
- import * as _ktortu_aaa_forms from '@ktortu/aaa/forms';
4
3
  import * as _angular_forms_signals from '@angular/forms/signals';
5
- import { WithOptionalFieldTree, ValidationError, FormValueControl } from '@angular/forms/signals';
4
+ import { ValidationError, WithOptionalFieldTree, 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';
@@ -21,6 +21,16 @@ interface KtFieldErrorState {
21
21
  }
22
22
  /** Décide QUAND afficher les erreurs d'un champ (équivalent signal de l'ErrorStateMatcher Material). */
23
23
  type KtFieldErrorMatcher = (state: KtFieldErrorState) => boolean;
24
+ /** Erreur à résoudre en message : la `ValidationError` de Signal Forms. Selon le `kind`, ses
25
+ sous-types portent des params typés (`min`, `max`, `minLength`, `maxLength`, `minDate`,
26
+ `maxDate`, `pattern`…) lisibles via {@link ktErrorParam}. */
27
+ type KtResolvableError = ValidationError;
28
+ /** Fabrique de message par défaut pour un `kind` : reçoit l'erreur complète (params accessibles). */
29
+ type KtErrorMessageFactory = (error: KtResolvableError) => string;
30
+ /** Messages d'erreur par défaut indexés par `kind`. Valeur statique (kinds sans param : `required`,
31
+ `email`) ou fabrique (kinds paramétrés : `min`, `minLength`…). Une chaîne vide (`''`) supprime
32
+ l'affichage du message — le champ reste invalide, mais sans texte (cf. récap d'erreurs externe). */
33
+ type KtFieldErrorMessages = Record<string, string | KtErrorMessageFactory>;
24
34
  /** Apparence du chrome de champ. `fill` = label au-dessus (défaut historique) ; `outline` = bordure
25
35
  + label flottant qui se loge dans la bordure (transition douce depuis Angular Material « outline »). */
26
36
  type KtFieldAppearance = 'fill' | 'outline';
@@ -47,6 +57,11 @@ interface KtFieldConfig {
47
57
  /** Message d'erreur d'un `kt-number-field` quand la saisie n'est pas un nombre valide.
48
58
  Défaut (anglais neutre) : `'Please enter a valid number.'`. */
49
59
  numberParseError: string;
60
+ /** Messages d'erreur par défaut indexés par `kind` (`required`, `email`, `min`, `minLength`…),
61
+ fusionnés par-dessus les défauts anglais embarqués (cf. `KT_DEFAULT_FIELD_ERROR_MESSAGES`).
62
+ Un message explicite passé au validateur Signal Forms (`{ message }`) reste prioritaire ; une
63
+ valeur `''` supprime le texte d'un `kind`. Défaut : `{}` (on garde les défauts anglais). */
64
+ errorMessages: Partial<KtFieldErrorMessages>;
50
65
  /** Apparence par défaut de tous les champs (`fill` | `outline`). Défaut : `'fill'`. */
51
66
  appearance: KtFieldAppearance;
52
67
  /** Politique du label flottant en `outline` (`auto` | `always`). Défaut : `'auto'`. */
@@ -54,15 +69,33 @@ interface KtFieldConfig {
54
69
  }
55
70
  declare const KT_FIELD_CONFIG: InjectionToken<Partial<KtFieldConfig>>;
56
71
  /**
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.
72
+ * Fournit des défauts de champ (apparence, libellés, matcher d'erreurs, messages d'erreur par
73
+ * défaut…) pour un sous-arbre ou l'application entière. Idéal pour une transition globale — ex. tout
74
+ * passer en `outline` façon Material en un seul provider.
60
75
  *
61
76
  * @example
62
77
  * ```ts
63
- * // app.config.ts
78
+ * // app.config.ts — apparence globale
64
79
  * providers: [provideKtField({ appearance: 'outline' })]
65
80
  * ```
81
+ *
82
+ * @example
83
+ * ```ts
84
+ * // Surcharger des messages d'erreur par défaut (fusionnés par-dessus les défauts anglais).
85
+ * // Une fabrique reçoit l'erreur complète : ses params typés sont lisibles via `ktErrorParam`.
86
+ * providers: [
87
+ * provideKtField({
88
+ * errorMessages: {
89
+ * required: 'Champ obligatoire.',
90
+ * minLength: (e) => `Au moins ${ktErrorParam<number>(e, 'minLength')} caractères.`,
91
+ * pattern: '', // '' supprime le texte de ce kind : champ rouge, sans message
92
+ * },
93
+ * }),
94
+ * ]
95
+ * ```
96
+ *
97
+ * @remarks Pour passer toute la lib en français d'un coup (libellés + messages d'erreur), préférez
98
+ * `provideKtDefaultFR()` (paquet `@ktortu/aaa/i18n`), qui fournit déjà un dictionnaire complet.
66
99
  */
67
100
  declare function provideKtField(config: Partial<KtFieldConfig>): Provider;
68
101
  /** Parent field interface representing shared states for its controls. */
@@ -170,6 +203,54 @@ declare class KtFieldControl {
170
203
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<KtFieldControl, "[ktFieldControl]", never, {}, {}, never, never, true, never>;
171
204
  }
172
205
 
206
+ /**
207
+ * Lit un param typé d'une `ValidationError` (ex. `min`, `minLength`, `maxLength`, `minDate`…).
208
+ * Les sous-types d'erreur de Signal Forms exposent ces params, mais le type de base `ValidationError`
209
+ * ne les déclare pas : ce helper centralise l'accès pour les fabriques de message, sans `any`.
210
+ *
211
+ * @example
212
+ * ```ts
213
+ * minLength: (e) => `Au moins ${ktErrorParam<number>(e, 'minLength')} caractères.`
214
+ * ```
215
+ */
216
+ declare function ktErrorParam<T>(error: KtResolvableError, key: string): T;
217
+ /**
218
+ * Messages d'erreur **anglais** par défaut de la lib, indexés par `kind`. Couvrent tous les
219
+ * validateurs natifs de Signal Forms (`required`, `email`, `min`, `max`, `minLength`, `maxLength`,
220
+ * `minDate`, `maxDate`, `pattern`). Surchargeables famille par famille via `KT_FIELD_CONFIG.errorMessages`
221
+ * (ou globalement par langue, cf. `provideKtDefaultFR`). Le `numberParseError` reste géré à la source
222
+ * par `kt-number-field` (kind `parse`).
223
+ */
224
+ declare const KT_DEFAULT_FIELD_ERROR_MESSAGES: KtFieldErrorMessages;
225
+ /**
226
+ * Résout le **message par défaut** d'une erreur de validation à partir de son `kind` (et de ses
227
+ * params typés), en fusionnant les défauts anglais embarqués avec les surcharges du `KT_FIELD_CONFIG`.
228
+ *
229
+ * Utilisé par chaque contrôle `kt-*` au moment du rendu, là où la `ValidationError` complète (params)
230
+ * est encore disponible — `kt-field` reste agnostique de Signal Forms. Précédence du texte affiché :
231
+ * `message` du validateur > `KT_FIELD_CONFIG.errorMessages[kind]` > défaut anglais > rien.
232
+ *
233
+ * Injectable racine : un seul résolveur partagé par tous les champs.
234
+ */
235
+ declare class KtFieldErrorResolver {
236
+ private readonly config;
237
+ /** Map effective : défauts anglais + surcharges du `KT_FIELD_CONFIG`, par `kind`. */
238
+ private readonly messages;
239
+ /**
240
+ * Message par défaut d'une erreur (selon son `kind` + params), ou `undefined` si aucun défaut
241
+ * n'est connu pour ce `kind` (l'UI n'affiche alors rien).
242
+ */
243
+ resolve(error: KtResolvableError): string | undefined;
244
+ /**
245
+ * Prépare une liste d'erreurs pour l'affichage : applique la précédence (message du validateur
246
+ * sinon défaut résolu) et **écarte les erreurs au message vide** — suppression explicite via
247
+ * `{ message: '' }`. Le champ reste invalide (rouge / `aria-invalid`), simplement sans texte.
248
+ */
249
+ resolveAll(errors: readonly KtResolvableError[]): KtFieldError[];
250
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtFieldErrorResolver, never>;
251
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<KtFieldErrorResolver>;
252
+ }
253
+
173
254
  /** Base partagée des champs simples (TextField, NumberField) : état FormValueControl,
174
255
  présentation (label/hint/prefix/suffix/clear) et politique d'affichage des erreurs.
175
256
  La valeur, son parsing et la notion de « vide » sont fournis par la sous-classe.
@@ -187,6 +268,7 @@ declare class KtFieldControl {
187
268
  ``` */
188
269
  declare abstract class KtBaseInputField<T> {
189
270
  protected readonly config: Partial<_ktortu_aaa_forms.KtFieldConfig> | null;
271
+ private readonly errorResolver;
190
272
  /** Valeur du contrôle — déclarée concrètement par la sous-classe. */
191
273
  abstract value: ModelSignal<T>;
192
274
  /** Marque le champ comme « visité » (déclenche l'affichage des erreurs). Deux-way. @default false */
@@ -201,6 +283,8 @@ declare abstract class KtBaseInputField<T> {
201
283
  readonly required: _angular_core.InputSignalWithTransform<boolean, unknown>;
202
284
  /** Le champ a-t-il été modifié depuis sa valeur initiale. @default false */
203
285
  readonly dirty: _angular_core.InputSignalWithTransform<boolean, unknown>;
286
+ /** Validation asynchrone en cours (poussé par `[field]`) : pose `aria-busy` + `data-pending`. @default false */
287
+ readonly pending: _angular_core.InputSignalWithTransform<boolean, unknown>;
204
288
  /** Liste des erreurs de validation à afficher. @default [] */
205
289
  readonly errors: _angular_core.InputSignal<readonly WithOptionalFieldTree<ValidationError>[]>;
206
290
  /** Attribut `name` natif du contrôle. @default '' */
@@ -246,6 +330,8 @@ declare abstract class KtBaseInputField<T> {
246
330
  protected readonly inputRef: _angular_core.Signal<ElementRef<HTMLInputElement | HTMLTextAreaElement> | undefined>;
247
331
  private readonly matcher;
248
332
  protected readonly showInvalid: _angular_core.Signal<boolean>;
333
+ /** Erreurs prêtes pour `kt-field` : messages par défaut résolus, suppressions (`message: ''`) écartées. */
334
+ protected readonly displayErrors: _angular_core.Signal<_ktortu_aaa_forms.KtFieldError[]>;
249
335
  protected readonly showClear: _angular_core.Signal<boolean>;
250
336
  /** Apparence effective (input ?? config ?? 'fill'). Sert aux templates : forward à `kt-field` et,
251
337
  en outline, pose une sentinelle de placeholder pour la détection « rempli » du label flottant. */
@@ -261,6 +347,12 @@ declare abstract class KtBaseInputField<T> {
261
347
  protected asText(value: string | TemplateRef<unknown> | undefined): string | null;
262
348
  protected onInput(event: Event): void;
263
349
  protected onKeyDown(event: KeyboardEvent): void;
350
+ /** Focus le contrôle natif (utilisé par Signal Forms `focusBoundControl`). */
351
+ focus(options?: FocusOptions): void;
352
+ /** Ré-aligne le texte affiché sur la valeur courante (utilisé par Signal Forms `reset`). */
353
+ reset(): void;
354
+ /** Représentation texte de la valeur pour l'input natif. Surchargeable par sous-classe. */
355
+ protected displayValue(): string;
264
356
  protected clear(): void;
265
357
  /** Parse la saisie brute en valeur typée. */
266
358
  protected abstract parse(raw: string): T;
@@ -269,7 +361,7 @@ declare abstract class KtBaseInputField<T> {
269
361
  /** La valeur est-elle vide (affichage du bouton d'effacement) ? */
270
362
  protected abstract isEmpty(value: T): boolean;
271
363
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtBaseInputField<any>, 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>;
364
+ 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; }; "pending": { "alias": "pending"; "required": false; "isSignal": true; }; "errors": { "alias": "errors"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "helpText": { "alias": "helpText"; "required": false; "isSignal": true; }; "helpLabel": { "alias": "helpLabel"; "required": false; "isSignal": true; }; "customDescribedBy": { "alias": "customDescribedBy"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "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
365
  }
274
366
 
275
367
  /** Suggestion d'un champ de saisie (rendu `<datalist>`) : soit la valeur seule, soit un couple
@@ -322,6 +414,7 @@ declare class KtNumberField extends KtBaseInputField<number | null> implements F
322
414
  protected parse(raw: string): number | null;
323
415
  protected onKeyDown(event: KeyboardEvent): void;
324
416
  private adjustValue;
417
+ reset(): void;
325
418
  protected emptyValue(): number | null;
326
419
  protected isEmpty(value: number | null): boolean;
327
420
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtNumberField, never>;
@@ -342,13 +435,20 @@ declare class KtTextArea extends KtBaseInputField<string> implements FormValueCo
342
435
  readonly value: _angular_core.ModelSignal<string>;
343
436
  /** Hauteur initiale (lignes). L'autosize est géré en CSS via `field-sizing: content`. @default 3 */
344
437
  readonly rows: _angular_core.InputSignal<number>;
438
+ /** Plancher de caractères (attribut `minlength` natif ; poussé par le validateur minLength). @default undefined */
439
+ readonly minLength: _angular_core.InputSignal<number | undefined>;
345
440
  /** Plafond de caractères ; poussé par le form (validateur maxLength) ou par le consommateur. @default undefined */
346
441
  readonly maxLength: _angular_core.InputSignal<number | undefined>;
442
+ /** Motifs de validation (contrat Signal Forms). L'attribut natif `pattern` ne prend qu'une regex →
443
+ seule la première est posée. @default [] */
444
+ readonly pattern: _angular_core.InputSignal<readonly RegExp[]>;
445
+ /** Source de la première regex pour l'attribut `pattern` natif (`null` si aucune). */
446
+ protected readonly patternAttr: _angular_core.Signal<string>;
347
447
  protected parse(raw: string): string;
348
448
  protected emptyValue(): string;
349
449
  protected isEmpty(value: string): boolean;
350
450
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtTextArea, never>;
351
- 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>;
451
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<KtTextArea, "kt-text-area", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "rows": { "alias": "rows"; "required": false; "isSignal": true; }; "minLength": { "alias": "minLength"; "required": false; "isSignal": true; }; "maxLength": { "alias": "maxLength"; "required": false; "isSignal": true; }; "pattern": { "alias": "pattern"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, ["[ktFieldHelp]"], true, never>;
352
452
  }
353
453
 
354
454
  /** Types texte dont la valeur reste une string (number/date = composants séparés). */
@@ -367,6 +467,15 @@ declare class KtTextField extends KtBaseInputField<string> implements FormValueC
367
467
  readonly value: _angular_core.ModelSignal<string>;
368
468
  /** Variante HTML du champ (pilote `type` natif et le clavier mobile). @default 'text' */
369
469
  readonly type: _angular_core.InputSignal<KtTextFieldType>;
470
+ /** Plancher de caractères (attribut `minlength` natif ; poussé par le validateur minLength). @default undefined */
471
+ readonly minLength: _angular_core.InputSignal<number | undefined>;
472
+ /** Plafond de caractères (attribut `maxlength` natif ; poussé par le validateur maxLength). @default undefined */
473
+ readonly maxLength: _angular_core.InputSignal<number | undefined>;
474
+ /** Motifs de validation (contrat Signal Forms). L'attribut natif `pattern` ne prend qu'une regex →
475
+ seule la première est posée. @default [] */
476
+ readonly pattern: _angular_core.InputSignal<readonly RegExp[]>;
477
+ /** Source de la première regex pour l'attribut `pattern` natif (`null` si aucune). */
478
+ protected readonly patternAttr: _angular_core.Signal<string>;
370
479
  /** Suggestions d'autocomplétion proposées via un `<datalist>` natif (la saisie reste libre).
371
480
  Valeurs simples (`string[]`) ou couples `{ value, label }` pour distinguer libellé affiché et
372
481
  valeur insérée. @default undefined */
@@ -380,7 +489,7 @@ declare class KtTextField extends KtBaseInputField<string> implements FormValueC
380
489
  protected emptyValue(): string;
381
490
  protected isEmpty(value: string): boolean;
382
491
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtTextField, never>;
383
- 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>;
492
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<KtTextField, "kt-text-field", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "type": { "alias": "type"; "required": false; "isSignal": true; }; "minLength": { "alias": "minLength"; "required": false; "isSignal": true; }; "maxLength": { "alias": "maxLength"; "required": false; "isSignal": true; }; "pattern": { "alias": "pattern"; "required": false; "isSignal": true; }; "suggestions": { "alias": "suggestions"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, ["[ktFieldHelp]"], true, never>;
384
493
  }
385
494
 
386
495
  /**
@@ -407,6 +516,8 @@ declare class KtSwitch implements FormValueControl<boolean> {
407
516
  readonly required: _angular_core.InputSignalWithTransform<boolean, unknown>;
408
517
  /** État « modifié » (entre dans la logique d'affichage des erreurs). @default false */
409
518
  readonly dirty: _angular_core.InputSignalWithTransform<boolean, unknown>;
519
+ /** Validation asynchrone en cours (poussé par `[field]`) : pose `aria-busy` + `data-pending`. @default false */
520
+ readonly pending: _angular_core.InputSignalWithTransform<boolean, unknown>;
410
521
  /** Erreurs de validation à afficher sous la bascule. @default [] */
411
522
  readonly errors: _angular_core.InputSignal<readonly WithOptionalFieldTree<ValidationError>[]>;
412
523
  /** Identifiant logique du contrôle (à titre indicatif). @default '' */
@@ -423,6 +534,8 @@ declare class KtSwitch implements FormValueControl<boolean> {
423
534
  readonly errorMatcher: _angular_core.InputSignal<KtFieldErrorMatcher | undefined>;
424
535
  /** Afficher toutes les erreurs au lieu de la première seule. @default KT_FIELD_CONFIG.showAllErrors ?? false */
425
536
  readonly showAllErrors: _angular_core.InputSignalWithTransform<boolean, unknown>;
537
+ private readonly switchBtn;
538
+ private readonly errorResolver;
426
539
  private readonly idGen;
427
540
  private readonly uid;
428
541
  protected readonly baseId: _angular_core.Signal<string>;
@@ -431,14 +544,18 @@ declare class KtSwitch implements FormValueControl<boolean> {
431
544
  protected readonly errorId: _angular_core.Signal<string>;
432
545
  private readonly matcher;
433
546
  protected readonly showInvalid: _angular_core.Signal<boolean>;
434
- protected readonly displayedErrors: _angular_core.Signal<readonly WithOptionalFieldTree<ValidationError>[]>;
547
+ /** Erreurs résolues (messages par défaut appliqués, suppressions `message: ''` écartées). */
548
+ protected readonly resolvedErrors: _angular_core.Signal<_ktortu_aaa_forms.KtFieldError[]>;
549
+ protected readonly displayedErrors: _angular_core.Signal<_ktortu_aaa_forms.KtFieldError[]>;
435
550
  protected readonly resolvedAriaLabel: _angular_core.Signal<string | null>;
436
551
  protected readonly describedBy: _angular_core.Signal<string | null>;
437
552
  constructor();
553
+ /** Focus le bouton bascule natif (utilisé par Signal Forms `focusBoundControl`). */
554
+ focus(options?: FocusOptions): void;
438
555
  protected toggle(): void;
439
556
  protected onSpacebar(event: Event): void;
440
557
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtSwitch, never>;
441
- 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>;
558
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<KtSwitch, "kt-switch", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "touched": { "alias": "touched"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "dirty": { "alias": "dirty"; "required": false; "isSignal": true; }; "pending": { "alias": "pending"; "required": false; "isSignal": true; }; "errors": { "alias": "errors"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "errorMatcher": { "alias": "errorMatcher"; "required": false; "isSignal": true; }; "showAllErrors": { "alias": "showAllErrors"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "touched": "touchedChange"; }, never, never, true, never>;
442
559
  }
443
560
 
444
561
  /**
@@ -473,6 +590,8 @@ declare class KtCheckboxGroup<V> implements FormValueControl<V[]> {
473
590
  readonly required: _angular_core.InputSignalWithTransform<boolean, unknown>;
474
591
  /** État « modifié » (entre dans la logique d'affichage des erreurs). @default false */
475
592
  readonly dirty: _angular_core.InputSignalWithTransform<boolean, unknown>;
593
+ /** Validation asynchrone en cours (poussé par `[field]`) : pose `aria-busy` + `data-pending`. @default false */
594
+ readonly pending: _angular_core.InputSignalWithTransform<boolean, unknown>;
476
595
  /** Erreurs de validation à afficher sous le groupe. @default [] */
477
596
  readonly errors: _angular_core.InputSignal<readonly WithOptionalFieldTree<ValidationError>[]>;
478
597
  /** Nom logique du groupe, à titre INDICATIF : contrairement à `kt-radio-group` (où `name` est
@@ -493,6 +612,8 @@ declare class KtCheckboxGroup<V> implements FormValueControl<V[]> {
493
612
  readonly showAllErrors: _angular_core.InputSignalWithTransform<boolean, unknown>;
494
613
  /** Égalité des valeurs en mode objet (défaut : identité `===`). */
495
614
  readonly compareWith: _angular_core.InputSignal<((a: V, b: V) => boolean) | undefined>;
615
+ private readonly el;
616
+ private readonly errorResolver;
496
617
  private readonly idGen;
497
618
  private readonly uid;
498
619
  protected readonly baseId: _angular_core.Signal<string>;
@@ -501,16 +622,20 @@ declare class KtCheckboxGroup<V> implements FormValueControl<V[]> {
501
622
  protected readonly errorId: _angular_core.Signal<string>;
502
623
  private readonly matcher;
503
624
  protected readonly showInvalid: _angular_core.Signal<boolean>;
504
- protected readonly displayedErrors: _angular_core.Signal<readonly WithOptionalFieldTree<ValidationError>[]>;
625
+ /** Erreurs résolues (messages par défaut appliqués, suppressions `message: ''` écartées). */
626
+ protected readonly resolvedErrors: _angular_core.Signal<_ktortu_aaa_forms.KtFieldError[]>;
627
+ protected readonly displayedErrors: _angular_core.Signal<_ktortu_aaa_forms.KtFieldError[]>;
505
628
  protected readonly resolvedAriaLabel: _angular_core.Signal<string | null>;
506
629
  protected readonly describedBy: _angular_core.Signal<string | null>;
507
630
  private readonly comparator;
508
631
  /** La valeur d'option d'un enfant est-elle dans la sélection ? (lu dans le `computed` enfant) */
509
632
  isSelected(optionValue: V): boolean;
633
+ /** Focus la première case activable (utilisé par Signal Forms `focusBoundControl`). */
634
+ focus(options?: FocusOptions): void;
510
635
  /** Ajoute/retire une valeur d'option de la sélection (émis par un enfant au `change` natif). */
511
636
  toggle(optionValue: V, checked: boolean): void;
512
637
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtCheckboxGroup<any>, never>;
513
- 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>;
638
+ 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; }; "pending": { "alias": "pending"; "required": false; "isSignal": true; }; "errors": { "alias": "errors"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "errorMatcher": { "alias": "errorMatcher"; "required": false; "isSignal": true; }; "showAllErrors": { "alias": "showAllErrors"; "required": false; "isSignal": true; }; "compareWith": { "alias": "compareWith"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "touched": "touchedChange"; }, never, ["*"], true, never>;
514
639
  }
515
640
 
516
641
  /**
@@ -562,6 +687,8 @@ declare class KtCheckbox<V = unknown> implements FormValueControl<boolean> {
562
687
  readonly required: _angular_core.InputSignalWithTransform<boolean, unknown>;
563
688
  /** État « modifié » (entre dans la logique d'affichage des erreurs). @default false */
564
689
  readonly dirty: _angular_core.InputSignalWithTransform<boolean, unknown>;
690
+ /** Validation asynchrone en cours (poussé par `[field]`) : pose `aria-busy` + `data-pending`. @default false */
691
+ readonly pending: _angular_core.InputSignalWithTransform<boolean, unknown>;
565
692
  /** Erreurs de validation à afficher sous la case. @default [] */
566
693
  readonly errors: _angular_core.InputSignal<readonly WithOptionalFieldTree<ValidationError>[]>;
567
694
  /** Attribut `name` du `<input>` natif. @default '' */
@@ -580,6 +707,7 @@ declare class KtCheckbox<V = unknown> implements FormValueControl<boolean> {
580
707
  readonly showAllErrors: _angular_core.InputSignalWithTransform<boolean, unknown>;
581
708
  private readonly inputEl;
582
709
  private readonly el;
710
+ private readonly errorResolver;
583
711
  private readonly idGen;
584
712
  private readonly uid;
585
713
  protected readonly baseId: _angular_core.Signal<string>;
@@ -592,14 +720,18 @@ declare class KtCheckbox<V = unknown> implements FormValueControl<boolean> {
592
720
  protected readonly isDisabled: _angular_core.Signal<boolean>;
593
721
  private readonly matcher;
594
722
  protected readonly showInvalid: _angular_core.Signal<boolean>;
595
- protected readonly displayedErrors: _angular_core.Signal<readonly WithOptionalFieldTree<ValidationError>[]>;
723
+ /** Erreurs résolues (messages par défaut appliqués, suppressions `message: ''` écartées). */
724
+ protected readonly resolvedErrors: _angular_core.Signal<_ktortu_aaa_forms.KtFieldError[]>;
725
+ protected readonly displayedErrors: _angular_core.Signal<_ktortu_aaa_forms.KtFieldError[]>;
596
726
  protected readonly resolvedAriaLabel: _angular_core.Signal<string | null>;
597
727
  protected readonly describedBy: _angular_core.Signal<string | null>;
598
728
  constructor();
729
+ /** Focus la case native (utilisé par Signal Forms `focusBoundControl`). */
730
+ focus(options?: FocusOptions): void;
599
731
  protected onChange(event: Event): void;
600
732
  protected onBlur(): void;
601
733
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtCheckbox<any>, 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>;
734
+ 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; }; "pending": { "alias": "pending"; "required": false; "isSignal": true; }; "errors": { "alias": "errors"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "errorMatcher": { "alias": "errorMatcher"; "required": false; "isSignal": true; }; "showAllErrors": { "alias": "showAllErrors"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "touched": "touchedChange"; }, never, ["*"], true, never>;
603
735
  }
604
736
 
605
737
  /**
@@ -635,6 +767,8 @@ declare class KtRadioGroup<V> implements FormValueControl<V | null> {
635
767
  readonly required: _angular_core.InputSignalWithTransform<boolean, unknown>;
636
768
  /** État « modifié » (entre dans la logique d'affichage des erreurs). @default false */
637
769
  readonly dirty: _angular_core.InputSignalWithTransform<boolean, unknown>;
770
+ /** Validation asynchrone en cours (poussé par `[field]`) : pose `aria-busy` + `data-pending`. @default false */
771
+ readonly pending: _angular_core.InputSignalWithTransform<boolean, unknown>;
638
772
  /** Erreurs de validation à afficher sous le groupe. @default [] */
639
773
  readonly errors: _angular_core.InputSignal<readonly WithOptionalFieldTree<ValidationError>[]>;
640
774
  /** Base du `name` partagé par les radios enfants (sinon auto-généré). @default '' */
@@ -653,6 +787,8 @@ declare class KtRadioGroup<V> implements FormValueControl<V | null> {
653
787
  readonly showAllErrors: _angular_core.InputSignalWithTransform<boolean, unknown>;
654
788
  /** Égalité des valeurs en mode objet (défaut : identité `===`). Seul rescapé du contrat select. */
655
789
  readonly compareWith: _angular_core.InputSignal<((a: V, b: V) => boolean) | undefined>;
790
+ private readonly el;
791
+ private readonly errorResolver;
656
792
  private readonly idGen;
657
793
  private readonly uid;
658
794
  protected readonly baseId: _angular_core.Signal<string>;
@@ -663,16 +799,21 @@ declare class KtRadioGroup<V> implements FormValueControl<V | null> {
663
799
  protected readonly errorId: _angular_core.Signal<string>;
664
800
  private readonly matcher;
665
801
  protected readonly showInvalid: _angular_core.Signal<boolean>;
666
- protected readonly displayedErrors: _angular_core.Signal<readonly WithOptionalFieldTree<ValidationError>[]>;
802
+ /** Erreurs résolues (messages par défaut appliqués, suppressions `message: ''` écartées). */
803
+ protected readonly resolvedErrors: _angular_core.Signal<_ktortu_aaa_forms.KtFieldError[]>;
804
+ protected readonly displayedErrors: _angular_core.Signal<_ktortu_aaa_forms.KtFieldError[]>;
667
805
  protected readonly resolvedAriaLabel: _angular_core.Signal<string | null>;
668
806
  protected readonly describedBy: _angular_core.Signal<string | null>;
669
807
  private readonly comparator;
670
808
  /** L'`optionValue` d'un enfant correspond-il à la sélection courante ? (lu dans le `computed` enfant) */
671
809
  isSelected(radioValue: V): boolean;
810
+ /** Focus l'option pertinente (utilisé par Signal Forms `focusBoundControl`) : le radio coché
811
+ s'il existe, sinon le premier radio activable — conforme au roving tabindex natif. */
812
+ focus(options?: FocusOptions): void;
672
813
  /** Commit d'une sélection émis par un enfant au `change` natif. */
673
814
  select(radioValue: V): void;
674
815
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtRadioGroup<any>, never>;
675
- 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>;
816
+ 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; }; "pending": { "alias": "pending"; "required": false; "isSignal": true; }; "errors": { "alias": "errors"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "errorMatcher": { "alias": "errorMatcher"; "required": false; "isSignal": true; }; "showAllErrors": { "alias": "showAllErrors"; "required": false; "isSignal": true; }; "compareWith": { "alias": "compareWith"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "touched": "touchedChange"; }, never, ["*"], true, never>;
676
817
  }
677
818
 
678
819
  /**
@@ -734,6 +875,7 @@ type KtKeyish<T, R> = keyof T | ((item: T) => R);
734
875
  ou la clé extraite quand `optionValue` est fourni). */
735
876
  declare abstract class KtBaseSelect<T, V = T> {
736
877
  protected readonly fieldConfig: Partial<_ktortu_aaa_forms.KtFieldConfig> | null;
878
+ private readonly errorResolver;
737
879
  protected readonly config: Partial<_ktortu_aaa_forms.KtSelectConfigOptions> | null;
738
880
  protected readonly host: ElementRef<HTMLElement>;
739
881
  private readonly ngZone;
@@ -767,6 +909,8 @@ declare abstract class KtBaseSelect<T, V = T> {
767
909
  readonly required: _angular_core.InputSignalWithTransform<boolean, unknown>;
768
910
  /** Le champ a-t-il été modifié depuis sa valeur initiale ? Poussé par `[formField]`. @default false */
769
911
  readonly dirty: _angular_core.InputSignalWithTransform<boolean, unknown>;
912
+ /** Validation asynchrone en cours (poussé par `[field]`) : pose `aria-busy` + `data-pending`. @default false */
913
+ readonly pending: _angular_core.InputSignalWithTransform<boolean, unknown>;
770
914
  /** Erreurs de validation à afficher. Poussé par `[formField]`. @default [] */
771
915
  readonly errors: _angular_core.InputSignal<readonly WithOptionalFieldTree<ValidationError>[]>;
772
916
  /** Attribut `name` logique du contrôle (à titre indicatif). @default '' */
@@ -839,10 +983,7 @@ declare abstract class KtBaseSelect<T, V = T> {
839
983
  protected readonly resolvedFilterResultsText: Signal<(count: number) => string>;
840
984
  protected readonly resolvedTruncatedResultsText: Signal<(max: number, total: number) => string>;
841
985
  protected readonly resolvedTruncatedResultsAnnouncement: Signal<(max: number, total: number) => string>;
842
- protected readonly fieldErrors: Signal<{
843
- kind: string;
844
- message: string | undefined;
845
- }[]>;
986
+ protected readonly fieldErrors: Signal<_ktortu_aaa_forms.KtFieldError[]>;
846
987
  private readonly labelAccessor;
847
988
  private readonly valueAccessor;
848
989
  private readonly disabledAccessor;
@@ -886,6 +1027,11 @@ declare abstract class KtBaseSelect<T, V = T> {
886
1027
  re-pousse rien (`listboxValue` n'a pas changé) — on resynchronise le modèle du Listbox
887
1028
  avec les clés sélectionnées actuellement visibles. */
888
1029
  protected resyncListboxSelection(): void;
1030
+ /** Focus le trigger natif (utilisé par Signal Forms `focusBoundControl`). */
1031
+ focus(options?: FocusOptions): void;
1032
+ /** Referme le panneau et vide le filtre (utilisé par Signal Forms `reset`). La sélection du
1033
+ listbox dérive de `value()` (computed) et se resynchronise seule. */
1034
+ reset(): void;
889
1035
  /** Desktop filtrable : le focus DOM vit dans le popup (champ/options) — on le rend au trigger
890
1036
  à la fermeture, sinon il tombe sur `<body>`. (Écran compact : déjà géré par l'effect `compact`.) */
891
1037
  protected refocusTriggerAfterFilterClose(): void;
@@ -895,7 +1041,7 @@ declare abstract class KtBaseSelect<T, V = T> {
895
1041
  protected onDragStart(event: PointerEvent): void;
896
1042
  private animateAndCloseSelect;
897
1043
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtBaseSelect<any, any>, 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>;
1044
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<KtBaseSelect<any, any>, never, never, { "options": { "alias": "options"; "required": true; "isSignal": true; }; "optionLabel": { "alias": "optionLabel"; "required": false; "isSignal": true; }; "optionValue": { "alias": "optionValue"; "required": false; "isSignal": true; }; "optionDisabled": { "alias": "optionDisabled"; "required": false; "isSignal": true; }; "compareWith": { "alias": "compareWith"; "required": false; "isSignal": true; }; "touched": { "alias": "touched"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "dirty": { "alias": "dirty"; "required": false; "isSignal": true; }; "pending": { "alias": "pending"; "required": false; "isSignal": true; }; "errors": { "alias": "errors"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "helpText": { "alias": "helpText"; "required": false; "isSignal": true; }; "helpLabel": { "alias": "helpLabel"; "required": false; "isSignal": true; }; "customDescribedBy": { "alias": "customDescribedBy"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "errorMatcher": { "alias": "errorMatcher"; "required": false; "isSignal": true; }; "appearance": { "alias": "appearance"; "required": false; "isSignal": true; }; "floatLabel": { "alias": "floatLabel"; "required": false; "isSignal": true; }; "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>;
899
1045
  }
900
1046
 
901
1047
  /** Contexte typé reçu par le template d'une option (`ktSelectOption`). */
@@ -1483,6 +1629,12 @@ declare abstract class KtBaseTemporalField<T extends {
1483
1629
  /** Sérialise la valeur au format attendu par l'input natif (précision adaptée au type). */
1484
1630
  protected abstract serialize(value: T): string;
1485
1631
  protected parse(raw: string): T | null;
1632
+ protected displayValue(): string;
1633
+ /** Efface AUSSI l'input natif. L'effet de synchro ignore une mise à `null` quand l'input est
1634
+ focalisé (pour ne pas écraser une saisie partielle en cours), or `clear()` focalise justement
1635
+ le champ — sans ce forçage, le bouton « effacer » (et Échap) resterait sans effet sur les
1636
+ champs temporels. */
1637
+ protected clear(): void;
1486
1638
  protected emptyValue(): T | null;
1487
1639
  protected isEmpty(value: T | null): boolean;
1488
1640
  /** Borne minimale autorisée (membre `min` du contrat `FormValueControl`, aussi posé en attribut
@@ -1555,6 +1707,10 @@ declare abstract class KtBaseTimeTemporalField<T extends {
1555
1707
  * suffira de retirer le polyfill de `main.ts` : ce fichier ne change pas.
1556
1708
  */
1557
1709
  type TemporalImpl = (typeof temporal_polyfill)['Temporal'];
1710
+ /** Point d'accès `Temporal` de la lib. Proxy à résolution paresseuse : le namespace réel n'est lu
1711
+ qu'au premier accès de propriété (`Temporal.PlainDate`…), jamais à l'import — ce qui supprime la
1712
+ dépendance à l'ordre d'init des modules et fait booter Safari/WebKit tant que le polyfill est
1713
+ importé dans `main.ts`. */
1558
1714
  declare const Temporal: TemporalImpl;
1559
1715
 
1560
1716
  /** Date civile (jour/mois/année), sans heure ni fuseau — alias de `Temporal.PlainDate`.
@@ -1757,5 +1913,5 @@ declare class KtFixedClock extends KtClock {
1757
1913
  today(): Temporal$1.PlainDate;
1758
1914
  }
1759
1915
 
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 };
1916
+ export { DEFAULT_KT_SELECT_CONFIG, KT_CHIPS_CONFIG, KT_DEFAULT_FIELD_ERROR_MESSAGES, KT_FIELD, KT_FIELD_CONFIG, KT_SELECT_CONFIG, KtBaseInputField, KtBaseSelect, KtBaseTemporalField, KtBaseTimeTemporalField, KtCheckbox, KtCheckboxGroup, KtChip, KtChipItemDef, KtChipList, KtClock, KtDateField, KtDateTimeField, KtField, KtFieldControl, KtFieldErrorResolver, KtFixedClock, KtInstantField, KtMultiSelect, KtMultiSelectChipDef, KtMultiSelectOptionDef, KtMultiSelectTriggerDef, KtNumberField, KtRadio, KtRadioGroup, KtSelect, KtSelectConfig, KtSelectOptionDef, KtSelectTriggerDef, KtSwitch, KtTemporalDatePipe, KtTextArea, KtTextField, KtTimeField, KtYearMonthField, Temporal, defaultKtFieldErrorMatcher, ktErrorParam, normalizeKtSuggestions, provideKtField };
1917
+ export type { CalendarDate, KtChipItemContext, KtChipsConfig, KtDatalistOption, KtErrorMessageFactory, KtFieldAppearance, KtFieldConfig, KtFieldError, KtFieldErrorMatcher, KtFieldErrorMessages, KtFieldErrorState, KtFieldParent, KtFloatLabel, KtKeyish, KtMultiSelectChipContext, KtMultiSelectOptionContext, KtMultiSelectSelectionChange, KtMultiSelectTriggerContext, KtResolvableError, KtSelectConfigOptions, KtSelectOptionContext, KtSelectSelectionChange, KtSelectTriggerContext, KtSuggestion, KtTextFieldType, KtTimePrecision, LocalDateTime, Timestamp, WallTime, ZonedTimestamp };
@@ -1,5 +1,6 @@
1
1
  import { EnvironmentProviders } from '@angular/core';
2
2
  import { KtFieldConfig, KtSelectConfigOptions, KtChipsConfig } from '@ktortu/aaa/forms';
3
+ import { KtSnackbarConfig } from '@ktortu/aaa/snackbar';
3
4
  import { KtTabsConfig } from '@ktortu/aaa/tabs';
4
5
 
5
6
  /**
@@ -18,6 +19,8 @@ interface KtTranslations {
18
19
  select?: Partial<KtSelectConfigOptions>;
19
20
  /** Libellés des listes de chips → {@link KT_CHIPS_CONFIG}. */
20
21
  chips?: Partial<KtChipsConfig>;
22
+ /** Libellés de la snackbar (`closeLabel`) → {@link KT_SNACKBAR_CONFIG}. */
23
+ snackbar?: Partial<KtSnackbarConfig>;
21
24
  /** Libellés de la pagination des onglets → {@link KT_TABS_CONFIG}. */
22
25
  tabs?: Partial<KtTabsConfig>;
23
26
  }