@ktortu/aaa 0.9.1 → 0.9.3
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.
- package/dialog/dialog.css +6 -0
- package/fesm2022/ktortu-aaa-button.mjs +10 -2
- package/fesm2022/ktortu-aaa-button.mjs.map +1 -1
- package/fesm2022/ktortu-aaa-card.mjs +112 -99
- package/fesm2022/ktortu-aaa-card.mjs.map +1 -1
- package/fesm2022/ktortu-aaa-cdk.mjs +49 -2
- package/fesm2022/ktortu-aaa-cdk.mjs.map +1 -1
- package/fesm2022/ktortu-aaa-dialog.mjs +240 -32
- package/fesm2022/ktortu-aaa-dialog.mjs.map +1 -1
- package/fesm2022/ktortu-aaa-disclosure.mjs +203 -0
- package/fesm2022/ktortu-aaa-disclosure.mjs.map +1 -0
- package/fesm2022/ktortu-aaa-forms.mjs +217 -103
- package/fesm2022/ktortu-aaa-forms.mjs.map +1 -1
- package/fesm2022/ktortu-aaa-progress-bar.mjs +91 -0
- package/fesm2022/ktortu-aaa-progress-bar.mjs.map +1 -0
- package/fesm2022/ktortu-aaa-snackbar.mjs +16 -3
- package/fesm2022/ktortu-aaa-snackbar.mjs.map +1 -1
- package/fesm2022/ktortu-aaa-tooltip.mjs +20 -30
- package/fesm2022/ktortu-aaa-tooltip.mjs.map +1 -1
- package/fesm2022/ktortu-aaa.mjs +1 -0
- package/fesm2022/ktortu-aaa.mjs.map +1 -1
- package/forms/field/field.css +16 -0
- package/forms/styles/field-box.css +11 -5
- package/package.json +9 -1
- package/progress-bar/progress-bar.css +127 -0
- package/styles/disclosure.css +6 -0
- package/styles/progress-bar.css +5 -0
- package/styles/styles.css +2 -0
- package/themes/theme-cyberpunk.css +11 -0
- package/tooltip/tooltip.css +1 -1
- package/types/ktortu-aaa-button.d.ts +2 -0
- package/types/ktortu-aaa-card.d.ts +69 -65
- package/types/ktortu-aaa-cdk.d.ts +27 -1
- package/types/ktortu-aaa-dialog.d.ts +134 -15
- package/types/ktortu-aaa-disclosure.d.ts +121 -0
- package/types/ktortu-aaa-forms.d.ts +69 -16
- package/types/ktortu-aaa-progress-bar.d.ts +27 -0
- package/types/ktortu-aaa-snackbar.d.ts +11 -68
- package/types/ktortu-aaa-tooltip.d.ts +0 -1
- package/types/ktortu-aaa.d.ts +1 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { NgTemplateOutlet, DOCUMENT, isPlatformBrowser } from '@angular/common';
|
|
1
2
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, inject, computed, ElementRef, Directive, input, output, booleanAttribute, contentChild,
|
|
3
|
+
import { InjectionToken, inject, computed, ElementRef, Directive, input, output, booleanAttribute, contentChild, TemplateRef, forwardRef, ChangeDetectionStrategy, Component, Injectable, model, viewChild, signal, afterNextRender, isDevMode, DestroyRef, effect, PLATFORM_ID, untracked, Injector, ChangeDetectorRef, viewChildren, afterRenderEffect, LOCALE_ID, Pipe } from '@angular/core';
|
|
3
4
|
import { KtTooltip } from '@ktortu/aaa/tooltip';
|
|
4
|
-
import { KtIdGenerator, KtViewport, createKtSheetDrag } from '@ktortu/aaa/cdk';
|
|
5
|
-
import { NgTemplateOutlet, DOCUMENT, isPlatformBrowser } from '@angular/common';
|
|
5
|
+
import { KtIdGenerator, KT_AUDIT_ENABLED, KtBodyScrollLock, KtViewport, createKtSheetDrag } from '@ktortu/aaa/cdk';
|
|
6
6
|
import { transformedValue } from '@angular/forms/signals';
|
|
7
7
|
import { Listbox, Option } from '@angular/aria/listbox';
|
|
8
8
|
import { Combobox, ComboboxPopup, ComboboxWidget } from '@angular/aria/combobox';
|
|
@@ -142,14 +142,6 @@ class KtField {
|
|
|
142
142
|
// Le contrôle est projeté : l'injection DI ne le traverse pas, on le cible via contentChild.
|
|
143
143
|
control = contentChild(KtFieldControl, /* @ts-ignore */
|
|
144
144
|
...(ngDevMode ? [{ debugName: "control" }] : /* istanbul ignore next */ []));
|
|
145
|
-
// Détecte le tooltip d'aide standard défini dans field.html (input DX)
|
|
146
|
-
templateTooltip = viewChild(KtTooltip, /* @ts-ignore */
|
|
147
|
-
...(ngDevMode ? [{ debugName: "templateTooltip" }] : /* istanbul ignore next */ []));
|
|
148
|
-
// Détecte un tooltip d'aide custom projeté dans le slot ktFieldHelp
|
|
149
|
-
projectedTooltip = contentChild(KtTooltip, { ...(ngDevMode ? { debugName: "projectedTooltip" } : /* istanbul ignore next */ {}), descendants: true });
|
|
150
|
-
// Résout le tooltip actif
|
|
151
|
-
activeTooltip = computed(() => this.projectedTooltip() ?? this.templateTooltip(), /* @ts-ignore */
|
|
152
|
-
...(ngDevMode ? [{ debugName: "activeTooltip" }] : /* istanbul ignore next */ []));
|
|
153
145
|
idGen = inject(KtIdGenerator);
|
|
154
146
|
uid = this.idGen.generateId('field');
|
|
155
147
|
baseId = computed(() => this.fieldId() ?? `kt-field-${this.uid}`, /* @ts-ignore */
|
|
@@ -160,6 +152,28 @@ class KtField {
|
|
|
160
152
|
...(ngDevMode ? [{ debugName: "hintId" }] : /* istanbul ignore next */ []));
|
|
161
153
|
errorId = computed(() => `${this.baseId()}-error`, /* @ts-ignore */
|
|
162
154
|
...(ngDevMode ? [{ debugName: "errorId" }] : /* istanbul ignore next */ []));
|
|
155
|
+
helpId = computed(() => `${this.baseId()}-help`, /* @ts-ignore */
|
|
156
|
+
...(ngDevMode ? [{ debugName: "helpId" }] : /* istanbul ignore next */ []));
|
|
157
|
+
// `helpText` accepte texte simple OU TemplateRef : on sépare les deux pour la copie cachée (a11y).
|
|
158
|
+
helpTemplate = computed(() => {
|
|
159
|
+
const help = this.helpText();
|
|
160
|
+
return help instanceof TemplateRef ? help : null;
|
|
161
|
+
}, /* @ts-ignore */
|
|
162
|
+
...(ngDevMode ? [{ debugName: "helpTemplate" }] : /* istanbul ignore next */ []));
|
|
163
|
+
helpString = computed(() => {
|
|
164
|
+
const help = this.helpText();
|
|
165
|
+
return typeof help === 'string' ? help : null;
|
|
166
|
+
}, /* @ts-ignore */
|
|
167
|
+
...(ngDevMode ? [{ debugName: "helpString" }] : /* istanbul ignore next */ []));
|
|
168
|
+
// Aide réellement signifiante : texte non blanc, ou TemplateRef. Un texte vide/blanc rend le
|
|
169
|
+
// bouton d'aide (DX) mais ne doit PAS être référencé par aria-describedby (rien à annoncer).
|
|
170
|
+
hasHelp = computed(() => {
|
|
171
|
+
const help = this.helpText();
|
|
172
|
+
if (help == null)
|
|
173
|
+
return false;
|
|
174
|
+
return typeof help === 'string' ? help.trim().length > 0 : true;
|
|
175
|
+
}, /* @ts-ignore */
|
|
176
|
+
...(ngDevMode ? [{ debugName: "hasHelp" }] : /* istanbul ignore next */ []));
|
|
163
177
|
hasError = computed(() => this.invalid() && this.errors().length > 0, /* @ts-ignore */
|
|
164
178
|
...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
|
|
165
179
|
// Hint visible sauf s'il est masqué en erreur (option façon Material).
|
|
@@ -174,11 +188,11 @@ class KtField {
|
|
|
174
188
|
ids.push(this.hintId());
|
|
175
189
|
if (this.hasError())
|
|
176
190
|
ids.push(this.errorId());
|
|
177
|
-
//
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
191
|
+
// Aide contextuelle : référence une copie TOUJOURS présente (visually-hidden) du texte d'aide.
|
|
192
|
+
// Le tooltip visuel n'est créé dans le DOM qu'à l'affichage ; cette copie garantit que les
|
|
193
|
+
// technologies d'assistance trouvent toujours la description, sans référence pendante.
|
|
194
|
+
if (this.hasHelp())
|
|
195
|
+
ids.push(this.helpId());
|
|
182
196
|
// Ajout de l'ID personnalisé externe (decouplage complet)
|
|
183
197
|
const custom = this.customDescribedBy();
|
|
184
198
|
if (custom)
|
|
@@ -192,15 +206,15 @@ class KtField {
|
|
|
192
206
|
this.helpClick.emit(event);
|
|
193
207
|
}
|
|
194
208
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: KtField, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
195
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.1", type: KtField, isStandalone: true, selector: "kt-field", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, helpText: { classPropertyName: "helpText", publicName: "helpText", isSignal: true, isRequired: false, transformFunction: null }, helpLabel: { classPropertyName: "helpLabel", publicName: "helpLabel", isSignal: true, isRequired: false, transformFunction: null }, customDescribedBy: { classPropertyName: "customDescribedBy", publicName: "customDescribedBy", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, fieldId: { classPropertyName: "fieldId", publicName: "fieldId", isSignal: true, isRequired: false, transformFunction: null }, hideHintWhenInvalid: { classPropertyName: "hideHintWhenInvalid", publicName: "hideHintWhenInvalid", isSignal: true, isRequired: false, transformFunction: null }, showAllErrors: { classPropertyName: "showAllErrors", publicName: "showAllErrors", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, floatLabel: { classPropertyName: "floatLabel", publicName: "floatLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { helpClick: "helpClick" }, host: { properties: { "attr.data-appearance": "resolvedAppearance()", "attr.data-float-label": "resolvedFloatLabel()" } }, providers: [{ provide: KT_FIELD, useExisting: forwardRef(() => KtField) }], queries: [{ propertyName: "control", first: true, predicate: KtFieldControl, descendants: true, isSignal: true }
|
|
209
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.1", type: KtField, isStandalone: true, selector: "kt-field", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, helpText: { classPropertyName: "helpText", publicName: "helpText", isSignal: true, isRequired: false, transformFunction: null }, helpLabel: { classPropertyName: "helpLabel", publicName: "helpLabel", isSignal: true, isRequired: false, transformFunction: null }, customDescribedBy: { classPropertyName: "customDescribedBy", publicName: "customDescribedBy", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, fieldId: { classPropertyName: "fieldId", publicName: "fieldId", isSignal: true, isRequired: false, transformFunction: null }, hideHintWhenInvalid: { classPropertyName: "hideHintWhenInvalid", publicName: "hideHintWhenInvalid", isSignal: true, isRequired: false, transformFunction: null }, showAllErrors: { classPropertyName: "showAllErrors", publicName: "showAllErrors", isSignal: true, isRequired: false, transformFunction: null }, appearance: { classPropertyName: "appearance", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, floatLabel: { classPropertyName: "floatLabel", publicName: "floatLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { helpClick: "helpClick" }, host: { properties: { "attr.data-appearance": "resolvedAppearance()", "attr.data-float-label": "resolvedFloatLabel()" } }, providers: [{ provide: KT_FIELD, useExisting: forwardRef(() => KtField) }], queries: [{ propertyName: "control", first: true, predicate: KtFieldControl, descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"kt-field__header\">\n @if (label(); as labelText) {\n <label class=\"kt-field__label\" [id]=\"labelId()\" [for]=\"baseId()\">\n {{ labelText }}\n @if (required()) {\n <span class=\"kt-field__required\" aria-hidden=\"true\">*</span>\n }\n </label>\n }\n\n @if (helpText(); as help) {\n <button\n type=\"button\"\n class=\"kt-field__help\"\n [ktTooltip]=\"help\"\n [attr.aria-label]=\"helpLabel()\"\n [attr.aria-describedby]=\"null\"\n (click)=\"onHelpClick($event)\"\n >\n <span class=\"kt-field__help-icon\" aria-hidden=\"true\">help</span>\n </button>\n }\n\n <ng-content select=\"[ktFieldHelp]\" />\n</div>\n\n<div class=\"kt-field__control\">\n <ng-content />\n</div>\n\n@if (hasHelp()) {\n <!-- Copie de l'aide TOUJOURS pr\u00E9sente (visually-hidden) : cible stable d'aria-describedby du\n contr\u00F4le, alors que la bulle visuelle du tooltip n'existe dans le DOM qu'\u00E0 l'affichage. -->\n <span [id]=\"helpId()\" class=\"kt-field__help-description\">\n @if (helpTemplate(); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n } @else {\n {{ helpString() }}\n }\n </span>\n}\n\n@if (showHint()) {\n <p class=\"kt-field__hint\" [id]=\"hintId()\">{{ hint() }}</p>\n}\n\n<!-- R\u00E9gion live toujours pr\u00E9sente : les AT annoncent l'erreur d\u00E8s son apparition. -->\n<p class=\"kt-field__error\" [id]=\"errorId()\" aria-live=\"polite\">\n @if (hasError()) {\n @for (error of displayedErrors(); track $index) {\n <span class=\"kt-field__error-message\">{{ error.message }}</span>\n }\n }\n</p>\n", styles: ["@layer kt-aaa.components{:host{display:flex;flex-direction:column;gap:var(--field-gap, .375rem);font-size:var(--field-font-size, 1rem);color:var(--field-color, inherit)}.kt-field__header{display:flex;align-items:center;gap:.375rem}.kt-field__label{font-size:var(--field-label-font-size, .875rem);font-weight:var(--field-label-weight, 500);text-transform:var(--field-label-transform, none);letter-spacing:var(--field-label-letter-spacing, normal);color:var(--field-label-color, inherit)}.kt-field__help{display:inline-flex;align-items:center;justify-content:center;padding:0;border:0;background:transparent;color:var(--field-icon-color, #474747);cursor:pointer;position:relative}.kt-field__help:after{content:\"\";position:absolute;inset:-12px}.kt-field__help-icon{font-family:Material Symbols Outlined;font-size:1.25rem;line-height:1;font-feature-settings:\"liga\";-webkit-font-smoothing:antialiased}.kt-field__required{margin-inline-start:.125rem;color:var(--field-required-color, #8c1d18)}.kt-field__hint{margin:0;font-size:var(--field-hint-font-size, .8125rem);color:var(--field-hint-color, #474747)}.kt-field__error{margin:0;display:flex;flex-direction:column;font-size:var(--field-hint-font-size, .8125rem);color:var(--field-error-color, #8c1d18)}.kt-field__help-description{position:absolute;inset-block-start:0;inset-inline-start:0;inline-size:1px;block-size:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.kt-field__error-message{animation:var(--field-error-animation, none)}@media(prefers-reduced-motion:reduce){.kt-field__error-message{animation:none}}}\n"], dependencies: [{ kind: "directive", type: KtTooltip, selector: "[ktTooltip]", inputs: ["ktTooltip", "tooltipPosition", "tooltipDisabled", "showDelay", "hideDelay"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
196
210
|
}
|
|
197
211
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: KtField, decorators: [{
|
|
198
212
|
type: Component,
|
|
199
|
-
args: [{ selector: 'kt-field', imports: [KtTooltip], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
213
|
+
args: [{ selector: 'kt-field', imports: [KtTooltip, NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
200
214
|
'[attr.data-appearance]': 'resolvedAppearance()',
|
|
201
215
|
'[attr.data-float-label]': 'resolvedFloatLabel()',
|
|
202
|
-
}, providers: [{ provide: KT_FIELD, useExisting: forwardRef(() => KtField) }], template: "<div class=\"kt-field__header\">\n @if (label(); as labelText) {\n <label class=\"kt-field__label\" [id]=\"labelId()\" [for]=\"baseId()\">\n {{ labelText }}\n @if (required()) {\n <span class=\"kt-field__required\" aria-hidden=\"true\">*</span>\n }\n </label>\n }\n\n @if (helpText(); as help) {\n <button\n type=\"button\"\n class=\"kt-field__help\"\n [ktTooltip]=\"help\"\n [attr.aria-label]=\"helpLabel()\"\n [attr.aria-describedby]=\"null\"\n (click)=\"onHelpClick($event)\"\n >\n <span class=\"kt-field__help-icon\" aria-hidden=\"true\">help</span>\n </button>\n }\n\n <ng-content select=\"[ktFieldHelp]\" />\n</div>\n\n<div class=\"kt-field__control\">\n <ng-content />\n</div>\n\n@if (showHint()) {\n <p class=\"kt-field__hint\" [id]=\"hintId()\">{{ hint() }}</p>\n}\n\n<!-- R\u00E9gion live toujours pr\u00E9sente : les AT annoncent l'erreur d\u00E8s son apparition. -->\n<p class=\"kt-field__error\" [id]=\"errorId()\" aria-live=\"polite\">\n @if (hasError()) {\n @for (error of displayedErrors(); track $index) {\n <span class=\"kt-field__error-message\">{{ error.message }}</span>\n }\n }\n</p>\n", styles: ["@layer kt-aaa.components{:host{display:flex;flex-direction:column;gap:var(--field-gap, .375rem);font-size:var(--field-font-size, 1rem);color:var(--field-color, inherit)}.kt-field__header{display:flex;align-items:center;gap:.375rem}.kt-field__label{font-size:var(--field-label-font-size, .875rem);font-weight:var(--field-label-weight, 500);text-transform:var(--field-label-transform, none);letter-spacing:var(--field-label-letter-spacing, normal);color:var(--field-label-color, inherit)}.kt-field__help{display:inline-flex;align-items:center;justify-content:center;padding:0;border:0;background:transparent;color:var(--field-icon-color, #474747);cursor:pointer;position:relative}.kt-field__help:after{content:\"\";position:absolute;inset:-12px}.kt-field__help-icon{font-family:Material Symbols Outlined;font-size:1.25rem;line-height:1;font-feature-settings:\"liga\";-webkit-font-smoothing:antialiased}.kt-field__required{margin-inline-start:.125rem;color:var(--field-required-color, #8c1d18)}.kt-field__hint{margin:0;font-size:var(--field-hint-font-size, .8125rem);color:var(--field-hint-color, #474747)}.kt-field__error{margin:0;display:flex;flex-direction:column;font-size:var(--field-hint-font-size, .8125rem);color:var(--field-error-color, #8c1d18)}.kt-field__error-message{animation:var(--field-error-animation, none)}@media(prefers-reduced-motion:reduce){.kt-field__error-message{animation:none}}}\n"] }]
|
|
203
|
-
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], helpText: [{ type: i0.Input, args: [{ isSignal: true, alias: "helpText", required: false }] }], helpLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "helpLabel", required: false }] }], customDescribedBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "customDescribedBy", required: false }] }], helpClick: [{ type: i0.Output, args: ["helpClick"] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], fieldId: [{ type: i0.Input, args: [{ isSignal: true, alias: "fieldId", required: false }] }], hideHintWhenInvalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideHintWhenInvalid", required: false }] }], showAllErrors: [{ type: i0.Input, args: [{ isSignal: true, alias: "showAllErrors", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], floatLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "floatLabel", required: false }] }], control: [{ type: i0.ContentChild, args: [i0.forwardRef(() => KtFieldControl), { isSignal: true }] }]
|
|
216
|
+
}, providers: [{ provide: KT_FIELD, useExisting: forwardRef(() => KtField) }], template: "<div class=\"kt-field__header\">\n @if (label(); as labelText) {\n <label class=\"kt-field__label\" [id]=\"labelId()\" [for]=\"baseId()\">\n {{ labelText }}\n @if (required()) {\n <span class=\"kt-field__required\" aria-hidden=\"true\">*</span>\n }\n </label>\n }\n\n @if (helpText(); as help) {\n <button\n type=\"button\"\n class=\"kt-field__help\"\n [ktTooltip]=\"help\"\n [attr.aria-label]=\"helpLabel()\"\n [attr.aria-describedby]=\"null\"\n (click)=\"onHelpClick($event)\"\n >\n <span class=\"kt-field__help-icon\" aria-hidden=\"true\">help</span>\n </button>\n }\n\n <ng-content select=\"[ktFieldHelp]\" />\n</div>\n\n<div class=\"kt-field__control\">\n <ng-content />\n</div>\n\n@if (hasHelp()) {\n <!-- Copie de l'aide TOUJOURS pr\u00E9sente (visually-hidden) : cible stable d'aria-describedby du\n contr\u00F4le, alors que la bulle visuelle du tooltip n'existe dans le DOM qu'\u00E0 l'affichage. -->\n <span [id]=\"helpId()\" class=\"kt-field__help-description\">\n @if (helpTemplate(); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n } @else {\n {{ helpString() }}\n }\n </span>\n}\n\n@if (showHint()) {\n <p class=\"kt-field__hint\" [id]=\"hintId()\">{{ hint() }}</p>\n}\n\n<!-- R\u00E9gion live toujours pr\u00E9sente : les AT annoncent l'erreur d\u00E8s son apparition. -->\n<p class=\"kt-field__error\" [id]=\"errorId()\" aria-live=\"polite\">\n @if (hasError()) {\n @for (error of displayedErrors(); track $index) {\n <span class=\"kt-field__error-message\">{{ error.message }}</span>\n }\n }\n</p>\n", styles: ["@layer kt-aaa.components{:host{display:flex;flex-direction:column;gap:var(--field-gap, .375rem);font-size:var(--field-font-size, 1rem);color:var(--field-color, inherit)}.kt-field__header{display:flex;align-items:center;gap:.375rem}.kt-field__label{font-size:var(--field-label-font-size, .875rem);font-weight:var(--field-label-weight, 500);text-transform:var(--field-label-transform, none);letter-spacing:var(--field-label-letter-spacing, normal);color:var(--field-label-color, inherit)}.kt-field__help{display:inline-flex;align-items:center;justify-content:center;padding:0;border:0;background:transparent;color:var(--field-icon-color, #474747);cursor:pointer;position:relative}.kt-field__help:after{content:\"\";position:absolute;inset:-12px}.kt-field__help-icon{font-family:Material Symbols Outlined;font-size:1.25rem;line-height:1;font-feature-settings:\"liga\";-webkit-font-smoothing:antialiased}.kt-field__required{margin-inline-start:.125rem;color:var(--field-required-color, #8c1d18)}.kt-field__hint{margin:0;font-size:var(--field-hint-font-size, .8125rem);color:var(--field-hint-color, #474747)}.kt-field__error{margin:0;display:flex;flex-direction:column;font-size:var(--field-hint-font-size, .8125rem);color:var(--field-error-color, #8c1d18)}.kt-field__help-description{position:absolute;inset-block-start:0;inset-inline-start:0;inline-size:1px;block-size:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.kt-field__error-message{animation:var(--field-error-animation, none)}@media(prefers-reduced-motion:reduce){.kt-field__error-message{animation:none}}}\n"] }]
|
|
217
|
+
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], helpText: [{ type: i0.Input, args: [{ isSignal: true, alias: "helpText", required: false }] }], helpLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "helpLabel", required: false }] }], customDescribedBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "customDescribedBy", required: false }] }], helpClick: [{ type: i0.Output, args: ["helpClick"] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], fieldId: [{ type: i0.Input, args: [{ isSignal: true, alias: "fieldId", required: false }] }], hideHintWhenInvalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideHintWhenInvalid", required: false }] }], showAllErrors: [{ type: i0.Input, args: [{ isSignal: true, alias: "showAllErrors", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], floatLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "floatLabel", required: false }] }], control: [{ type: i0.ContentChild, args: [i0.forwardRef(() => KtFieldControl), { isSignal: true }] }] } });
|
|
204
218
|
|
|
205
219
|
/**
|
|
206
220
|
* Lit un param typé d'une `ValidationError` (ex. `min`, `minLength`, `maxLength`, `minDate`…).
|
|
@@ -614,13 +628,6 @@ class KtTextArea extends KtBaseInputField {
|
|
|
614
628
|
/** Plafond de caractères ; poussé par le form (validateur maxLength) ou par le consommateur. @default undefined */
|
|
615
629
|
maxLength = input(/* @ts-ignore */
|
|
616
630
|
...(ngDevMode ? [undefined, { debugName: "maxLength" }] : /* istanbul ignore next */ []));
|
|
617
|
-
/** Motifs de validation (contrat Signal Forms). L'attribut natif `pattern` ne prend qu'une regex →
|
|
618
|
-
seule la première est posée. @default [] */
|
|
619
|
-
pattern = input([], /* @ts-ignore */
|
|
620
|
-
...(ngDevMode ? [{ debugName: "pattern" }] : /* istanbul ignore next */ []));
|
|
621
|
-
/** Source de la première regex pour l'attribut `pattern` natif (`null` si aucune). */
|
|
622
|
-
patternAttr = computed(() => this.pattern()[0]?.source ?? null, /* @ts-ignore */
|
|
623
|
-
...(ngDevMode ? [{ debugName: "patternAttr" }] : /* istanbul ignore next */ []));
|
|
624
631
|
parse(raw) {
|
|
625
632
|
return raw;
|
|
626
633
|
}
|
|
@@ -631,12 +638,12 @@ class KtTextArea extends KtBaseInputField {
|
|
|
631
638
|
return value.length === 0;
|
|
632
639
|
}
|
|
633
640
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: KtTextArea, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
634
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.1", type: KtTextArea, isStandalone: true, selector: "kt-text-area", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, minLength: { classPropertyName: "minLength", publicName: "minLength", isSignal: true, isRequired: false, transformFunction: null }, maxLength: { classPropertyName: "maxLength", publicName: "maxLength", isSignal: true, isRequired: false, transformFunction: null }
|
|
641
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.1", type: KtTextArea, isStandalone: true, selector: "kt-text-area", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, minLength: { classPropertyName: "minLength", publicName: "minLength", isSignal: true, isRequired: false, transformFunction: null }, maxLength: { classPropertyName: "maxLength", publicName: "maxLength", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, usesInheritance: true, ngImport: i0, template: "<kt-field\n [label]=\"label()\"\n [hint]=\"hint()\"\n [helpText]=\"helpText()\"\n [helpLabel]=\"helpLabel()\"\n [customDescribedBy]=\"customDescribedBy()\"\n [errors]=\"displayErrors()\"\n [invalid]=\"showInvalid()\"\n [required]=\"required()\"\n [fieldId]=\"id()\"\n [appearance]=\"appearance()\"\n [floatLabel]=\"floatLabel()\"\n (helpClick)=\"helpClick.emit($event)\"\n>\n <ng-content select=\"[ktFieldHelp]\" />\n <div\n class=\"kt-field-box\"\n data-multiline\n [attr.data-invalid]=\"showInvalid() ? '' : null\"\n [attr.data-disabled]=\"disabled() ? '' : null\"\n [attr.data-pending]=\"pending() ? '' : null\"\n >\n @if (icon(); as icon) {\n <span class=\"kt-field-box__icon\" aria-hidden=\"true\">{{ icon }}</span>\n }\n\n @if (prefix(); as prefix) {\n <span class=\"kt-field-box__affix\">\n @if (asTemplate(prefix); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n } @else {\n {{ asText(prefix) }}\n }\n </span>\n }\n\n <textarea\n #input\n ktFieldControl\n class=\"kt-field-box__input\"\n [value]=\"value()\"\n [rows]=\"rows()\"\n [style.min-height.lh]=\"rows()\"\n [disabled]=\"disabled()\"\n [readOnly]=\"readonly()\"\n [attr.aria-busy]=\"pending() ? 'true' : null\"\n [attr.name]=\"name() || null\"\n [attr.placeholder]=\"placeholderAttr()\"\n [attr.autocomplete]=\"autocomplete() || null\"\n [attr.minlength]=\"minLength() ?? null\"\n [attr.maxlength]=\"maxLength() ?? null\"\n (keydown)=\"onKeyDown($event)\"\n (input)=\"onInput($event)\"\n (blur)=\"touched.set(true)\"\n ></textarea>\n\n @if (showClear()) {\n <button type=\"button\" class=\"kt-field-box__clear\" [attr.aria-label]=\"clearLabel()\" (click)=\"clear()\">\n <span class=\"kt-field-box__icon\" aria-hidden=\"true\">close</span>\n </button>\n }\n\n @if (suffix(); as suffix) {\n <span class=\"kt-field-box__affix\">\n @if (asTemplate(suffix); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n } @else {\n {{ asText(suffix) }}\n }\n </span>\n }\n </div>\n</kt-field>\n", dependencies: [{ kind: "component", type: KtField, selector: "kt-field", inputs: ["label", "hint", "helpText", "helpLabel", "customDescribedBy", "errors", "invalid", "required", "fieldId", "hideHintWhenInvalid", "showAllErrors", "appearance", "floatLabel"], outputs: ["helpClick"] }, { kind: "directive", type: KtFieldControl, selector: "[ktFieldControl]" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
635
642
|
}
|
|
636
643
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: KtTextArea, decorators: [{
|
|
637
644
|
type: Component,
|
|
638
|
-
args: [{ selector: 'kt-text-area', imports: [KtField, KtFieldControl, NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, template: "<kt-field\n [label]=\"label()\"\n [hint]=\"hint()\"\n [helpText]=\"helpText()\"\n [helpLabel]=\"helpLabel()\"\n [customDescribedBy]=\"customDescribedBy()\"\n [errors]=\"displayErrors()\"\n [invalid]=\"showInvalid()\"\n [required]=\"required()\"\n [fieldId]=\"id()\"\n [appearance]=\"appearance()\"\n [floatLabel]=\"floatLabel()\"\n (helpClick)=\"helpClick.emit($event)\"\n>\n <ng-content select=\"[ktFieldHelp]\" />\n <div\n class=\"kt-field-box\"\n data-multiline\n [attr.data-invalid]=\"showInvalid() ? '' : null\"\n [attr.data-disabled]=\"disabled() ? '' : null\"\n [attr.data-pending]=\"pending() ? '' : null\"\n >\n @if (icon(); as icon) {\n <span class=\"kt-field-box__icon\" aria-hidden=\"true\">{{ icon }}</span>\n }\n\n @if (prefix(); as prefix) {\n <span class=\"kt-field-box__affix\">\n @if (asTemplate(prefix); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n } @else {\n {{ asText(prefix) }}\n }\n </span>\n }\n\n <textarea\n #input\n ktFieldControl\n class=\"kt-field-box__input\"\n [value]=\"value()\"\n [rows]=\"rows()\"\n [style.min-height.lh]=\"rows()\"\n [disabled]=\"disabled()\"\n [readOnly]=\"readonly()\"\n [attr.aria-busy]=\"pending() ? 'true' : null\"\n [attr.name]=\"name() || null\"\n [attr.placeholder]=\"placeholderAttr()\"\n [attr.autocomplete]=\"autocomplete() || null\"\n [attr.minlength]=\"minLength() ?? null\"\n [attr.maxlength]=\"maxLength() ?? null\"\n
|
|
639
|
-
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], minLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minLength", required: false }] }], maxLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLength", required: false }] }]
|
|
645
|
+
args: [{ selector: 'kt-text-area', imports: [KtField, KtFieldControl, NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, template: "<kt-field\n [label]=\"label()\"\n [hint]=\"hint()\"\n [helpText]=\"helpText()\"\n [helpLabel]=\"helpLabel()\"\n [customDescribedBy]=\"customDescribedBy()\"\n [errors]=\"displayErrors()\"\n [invalid]=\"showInvalid()\"\n [required]=\"required()\"\n [fieldId]=\"id()\"\n [appearance]=\"appearance()\"\n [floatLabel]=\"floatLabel()\"\n (helpClick)=\"helpClick.emit($event)\"\n>\n <ng-content select=\"[ktFieldHelp]\" />\n <div\n class=\"kt-field-box\"\n data-multiline\n [attr.data-invalid]=\"showInvalid() ? '' : null\"\n [attr.data-disabled]=\"disabled() ? '' : null\"\n [attr.data-pending]=\"pending() ? '' : null\"\n >\n @if (icon(); as icon) {\n <span class=\"kt-field-box__icon\" aria-hidden=\"true\">{{ icon }}</span>\n }\n\n @if (prefix(); as prefix) {\n <span class=\"kt-field-box__affix\">\n @if (asTemplate(prefix); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n } @else {\n {{ asText(prefix) }}\n }\n </span>\n }\n\n <textarea\n #input\n ktFieldControl\n class=\"kt-field-box__input\"\n [value]=\"value()\"\n [rows]=\"rows()\"\n [style.min-height.lh]=\"rows()\"\n [disabled]=\"disabled()\"\n [readOnly]=\"readonly()\"\n [attr.aria-busy]=\"pending() ? 'true' : null\"\n [attr.name]=\"name() || null\"\n [attr.placeholder]=\"placeholderAttr()\"\n [attr.autocomplete]=\"autocomplete() || null\"\n [attr.minlength]=\"minLength() ?? null\"\n [attr.maxlength]=\"maxLength() ?? null\"\n (keydown)=\"onKeyDown($event)\"\n (input)=\"onInput($event)\"\n (blur)=\"touched.set(true)\"\n ></textarea>\n\n @if (showClear()) {\n <button type=\"button\" class=\"kt-field-box__clear\" [attr.aria-label]=\"clearLabel()\" (click)=\"clear()\">\n <span class=\"kt-field-box__icon\" aria-hidden=\"true\">close</span>\n </button>\n }\n\n @if (suffix(); as suffix) {\n <span class=\"kt-field-box__affix\">\n @if (asTemplate(suffix); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n } @else {\n {{ asText(suffix) }}\n }\n </span>\n }\n </div>\n</kt-field>\n" }]
|
|
646
|
+
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], minLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minLength", required: false }] }], maxLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLength", required: false }] }] } });
|
|
640
647
|
|
|
641
648
|
/**
|
|
642
649
|
* Champ texte (valeur `string`) intégré aux Signal Forms via `FormValueControl`. Hérite de la
|
|
@@ -696,6 +703,72 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImpor
|
|
|
696
703
|
args: [{ selector: 'kt-text-field', imports: [KtField, KtFieldControl, NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, template: "<kt-field\n [label]=\"label()\"\n [hint]=\"hint()\"\n [helpText]=\"helpText()\"\n [helpLabel]=\"helpLabel()\"\n [customDescribedBy]=\"customDescribedBy()\"\n [errors]=\"displayErrors()\"\n [invalid]=\"showInvalid()\"\n [required]=\"required()\"\n [fieldId]=\"id()\"\n [appearance]=\"appearance()\"\n [floatLabel]=\"floatLabel()\"\n (helpClick)=\"helpClick.emit($event)\"\n>\n <ng-content select=\"[ktFieldHelp]\" />\n <div\n class=\"kt-field-box\"\n [attr.data-invalid]=\"showInvalid() ? '' : null\"\n [attr.data-disabled]=\"disabled() ? '' : null\"\n [attr.data-pending]=\"pending() ? '' : null\"\n >\n @if (icon(); as icon) {\n <span class=\"kt-field-box__icon\" aria-hidden=\"true\">{{ icon }}</span>\n }\n\n @if (prefix(); as prefix) {\n <span class=\"kt-field-box__affix\">\n @if (asTemplate(prefix); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n } @else {\n {{ asText(prefix) }}\n }\n </span>\n }\n\n <input\n #input\n ktFieldControl\n class=\"kt-field-box__input\"\n [type]=\"type()\"\n [value]=\"value()\"\n [disabled]=\"disabled()\"\n [readOnly]=\"readonly()\"\n [attr.aria-busy]=\"pending() ? 'true' : null\"\n [attr.name]=\"name() || null\"\n [attr.placeholder]=\"placeholderAttr()\"\n [attr.autocomplete]=\"autocomplete() || null\"\n [attr.minlength]=\"minLength() ?? null\"\n [attr.maxlength]=\"maxLength() ?? null\"\n [attr.pattern]=\"patternAttr()\"\n [attr.list]=\"hasSuggestions() ? datalistId : null\"\n (keydown)=\"onKeyDown($event)\"\n (input)=\"onInput($event)\"\n (blur)=\"touched.set(true)\"\n />\n\n @if (hasSuggestions()) {\n <datalist [id]=\"datalistId\">\n @for (option of datalistOptions(); track $index) {\n <option [value]=\"option.value\" [attr.label]=\"option.label\"></option>\n }\n </datalist>\n }\n\n @if (showClear()) {\n <button type=\"button\" class=\"kt-field-box__clear\" [attr.aria-label]=\"clearLabel()\" (click)=\"clear()\">\n <span class=\"kt-field-box__icon\" aria-hidden=\"true\">close</span>\n </button>\n }\n\n @if (suffix(); as suffix) {\n <span class=\"kt-field-box__affix\">\n @if (asTemplate(suffix); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n } @else {\n {{ asText(suffix) }}\n }\n </span>\n }\n </div>\n</kt-field>\n" }]
|
|
697
704
|
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], minLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minLength", required: false }] }], maxLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLength", required: false }] }], pattern: [{ type: i0.Input, args: [{ isSignal: true, alias: "pattern", required: false }] }], suggestions: [{ type: i0.Input, args: [{ isSignal: true, alias: "suggestions", required: false }] }] } });
|
|
698
705
|
|
|
706
|
+
/**
|
|
707
|
+
* Champ mot de passe (valeur `string`) intégré aux Signal Forms via `FormValueControl`.
|
|
708
|
+
* Inclut un bouton pour masquer/afficher la saisie en clair de manière accessible.
|
|
709
|
+
*
|
|
710
|
+
* @example
|
|
711
|
+
* ```html
|
|
712
|
+
* <kt-password-field label="Mot de passe" [(value)]="password" required />
|
|
713
|
+
* ```
|
|
714
|
+
*/
|
|
715
|
+
class KtPasswordField extends KtBaseInputField {
|
|
716
|
+
/** Valeur saisie (two-way). @default '' */
|
|
717
|
+
value = model('', /* @ts-ignore */
|
|
718
|
+
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
719
|
+
/** Plancher de caractères (attribut `minlength` natif ; poussé par le validateur minLength). @default undefined */
|
|
720
|
+
minLength = input(/* @ts-ignore */
|
|
721
|
+
...(ngDevMode ? [undefined, { debugName: "minLength" }] : /* istanbul ignore next */ []));
|
|
722
|
+
/** Plafond de caractères (attribut `maxlength` natif ; poussé par le validateur maxLength). @default undefined */
|
|
723
|
+
maxLength = input(/* @ts-ignore */
|
|
724
|
+
...(ngDevMode ? [undefined, { debugName: "maxLength" }] : /* istanbul ignore next */ []));
|
|
725
|
+
/** Motifs de validation. @default [] */
|
|
726
|
+
pattern = input([], /* @ts-ignore */
|
|
727
|
+
...(ngDevMode ? [{ debugName: "pattern" }] : /* istanbul ignore next */ []));
|
|
728
|
+
/** Source de la première regex pour l'attribut `pattern` natif (`null` si aucune). */
|
|
729
|
+
patternAttr = computed(() => this.pattern()[0]?.source ?? null, /* @ts-ignore */
|
|
730
|
+
...(ngDevMode ? [{ debugName: "patternAttr" }] : /* istanbul ignore next */ []));
|
|
731
|
+
/** Indice d'autoremplissage effectif (par défaut 'current-password'). */
|
|
732
|
+
resolvedAutocomplete = computed(() => this.autocomplete() ?? 'current-password', /* @ts-ignore */
|
|
733
|
+
...(ngDevMode ? [{ debugName: "resolvedAutocomplete" }] : /* istanbul ignore next */ []));
|
|
734
|
+
/** État de visibilité du mot de passe en clair. @default false */
|
|
735
|
+
isPasswordVisible = signal(false, /* @ts-ignore */
|
|
736
|
+
...(ngDevMode ? [{ debugName: "isPasswordVisible" }] : /* istanbul ignore next */ []));
|
|
737
|
+
/** Type natif de l'input selon l'état de visibilité. */
|
|
738
|
+
inputType = computed(() => (this.isPasswordVisible() ? 'text' : 'password'), /* @ts-ignore */
|
|
739
|
+
...(ngDevMode ? [{ debugName: "inputType" }] : /* istanbul ignore next */ []));
|
|
740
|
+
idGen = inject(KtIdGenerator);
|
|
741
|
+
uid = this.idGen.generateId('password-field');
|
|
742
|
+
inputId = computed(() => this.id() ?? `kt-password-field-${this.uid}`, /* @ts-ignore */
|
|
743
|
+
...(ngDevMode ? [{ debugName: "inputId" }] : /* istanbul ignore next */ []));
|
|
744
|
+
parse(raw) {
|
|
745
|
+
return raw;
|
|
746
|
+
}
|
|
747
|
+
emptyValue() {
|
|
748
|
+
return '';
|
|
749
|
+
}
|
|
750
|
+
isEmpty(value) {
|
|
751
|
+
return value.length === 0;
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Bascule l'état de visibilité du mot de passe.
|
|
755
|
+
* Utilise preventDefault() pour empêcher l'input de perdre le focus.
|
|
756
|
+
*/
|
|
757
|
+
toggleVisibility(event) {
|
|
758
|
+
event.preventDefault();
|
|
759
|
+
if (this.disabled() || this.readonly()) {
|
|
760
|
+
return;
|
|
761
|
+
}
|
|
762
|
+
this.isPasswordVisible.update((visible) => !visible);
|
|
763
|
+
}
|
|
764
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: KtPasswordField, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
765
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.1", type: KtPasswordField, isStandalone: true, selector: "kt-password-field", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, minLength: { classPropertyName: "minLength", publicName: "minLength", isSignal: true, isRequired: false, transformFunction: null }, maxLength: { classPropertyName: "maxLength", publicName: "maxLength", isSignal: true, isRequired: false, transformFunction: null }, pattern: { classPropertyName: "pattern", publicName: "pattern", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, usesInheritance: true, ngImport: i0, template: "<kt-field\n [label]=\"label()\"\n [hint]=\"hint()\"\n [helpText]=\"helpText()\"\n [helpLabel]=\"helpLabel()\"\n [customDescribedBy]=\"customDescribedBy()\"\n [errors]=\"displayErrors()\"\n [invalid]=\"showInvalid()\"\n [required]=\"required()\"\n [fieldId]=\"inputId()\"\n [appearance]=\"appearance()\"\n [floatLabel]=\"floatLabel()\"\n (helpClick)=\"helpClick.emit($event)\"\n>\n <ng-content select=\"[ktFieldHelp]\" />\n <div\n class=\"kt-field-box\"\n [attr.data-invalid]=\"showInvalid() ? '' : null\"\n [attr.data-disabled]=\"disabled() ? '' : null\"\n [attr.data-pending]=\"pending() ? '' : null\"\n >\n @if (icon(); as icon) {\n <span class=\"kt-field-box__icon\" aria-hidden=\"true\">{{ icon }}</span>\n }\n\n @if (prefix(); as prefix) {\n <span class=\"kt-field-box__affix\">\n @if (asTemplate(prefix); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n } @else {\n {{ asText(prefix) }}\n }\n </span>\n }\n\n <input\n #input\n ktFieldControl\n class=\"kt-field-box__input\"\n [type]=\"inputType()\"\n [value]=\"value()\"\n [disabled]=\"disabled()\"\n [readOnly]=\"readonly()\"\n [attr.aria-busy]=\"pending() ? 'true' : null\"\n [attr.name]=\"name() || null\"\n [attr.placeholder]=\"placeholderAttr()\"\n [attr.autocomplete]=\"resolvedAutocomplete()\"\n [attr.minlength]=\"minLength() ?? null\"\n [attr.maxlength]=\"maxLength() ?? null\"\n [attr.pattern]=\"patternAttr()\"\n (keydown)=\"onKeyDown($event)\"\n (input)=\"onInput($event)\"\n (blur)=\"touched.set(true)\"\n />\n\n @if (showClear()) {\n <button type=\"button\" class=\"kt-field-box__clear\" [attr.aria-label]=\"clearLabel()\" (click)=\"clear()\">\n <span class=\"kt-field-box__icon\" aria-hidden=\"true\">close</span>\n </button>\n }\n\n <button\n type=\"button\"\n class=\"kt-field-box__toggle\"\n [disabled]=\"disabled() || readonly()\"\n [attr.aria-label]=\"isPasswordVisible() ? 'Masquer le mot de passe' : 'Afficher le mot de passe'\"\n [attr.aria-controls]=\"inputId()\"\n (mousedown)=\"toggleVisibility($event)\"\n >\n <span class=\"kt-field-box__icon\" aria-hidden=\"true\">\n {{ isPasswordVisible() ? 'visibility_off' : 'visibility' }}\n </span>\n </button>\n\n @if (suffix(); as suffix) {\n <span class=\"kt-field-box__affix\">\n @if (asTemplate(suffix); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n } @else {\n {{ asText(suffix) }}\n }\n </span>\n }\n </div>\n</kt-field>\n", dependencies: [{ kind: "component", type: KtField, selector: "kt-field", inputs: ["label", "hint", "helpText", "helpLabel", "customDescribedBy", "errors", "invalid", "required", "fieldId", "hideHintWhenInvalid", "showAllErrors", "appearance", "floatLabel"], outputs: ["helpClick"] }, { kind: "directive", type: KtFieldControl, selector: "[ktFieldControl]" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
766
|
+
}
|
|
767
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: KtPasswordField, decorators: [{
|
|
768
|
+
type: Component,
|
|
769
|
+
args: [{ selector: 'kt-password-field', imports: [KtField, KtFieldControl, NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, template: "<kt-field\n [label]=\"label()\"\n [hint]=\"hint()\"\n [helpText]=\"helpText()\"\n [helpLabel]=\"helpLabel()\"\n [customDescribedBy]=\"customDescribedBy()\"\n [errors]=\"displayErrors()\"\n [invalid]=\"showInvalid()\"\n [required]=\"required()\"\n [fieldId]=\"inputId()\"\n [appearance]=\"appearance()\"\n [floatLabel]=\"floatLabel()\"\n (helpClick)=\"helpClick.emit($event)\"\n>\n <ng-content select=\"[ktFieldHelp]\" />\n <div\n class=\"kt-field-box\"\n [attr.data-invalid]=\"showInvalid() ? '' : null\"\n [attr.data-disabled]=\"disabled() ? '' : null\"\n [attr.data-pending]=\"pending() ? '' : null\"\n >\n @if (icon(); as icon) {\n <span class=\"kt-field-box__icon\" aria-hidden=\"true\">{{ icon }}</span>\n }\n\n @if (prefix(); as prefix) {\n <span class=\"kt-field-box__affix\">\n @if (asTemplate(prefix); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n } @else {\n {{ asText(prefix) }}\n }\n </span>\n }\n\n <input\n #input\n ktFieldControl\n class=\"kt-field-box__input\"\n [type]=\"inputType()\"\n [value]=\"value()\"\n [disabled]=\"disabled()\"\n [readOnly]=\"readonly()\"\n [attr.aria-busy]=\"pending() ? 'true' : null\"\n [attr.name]=\"name() || null\"\n [attr.placeholder]=\"placeholderAttr()\"\n [attr.autocomplete]=\"resolvedAutocomplete()\"\n [attr.minlength]=\"minLength() ?? null\"\n [attr.maxlength]=\"maxLength() ?? null\"\n [attr.pattern]=\"patternAttr()\"\n (keydown)=\"onKeyDown($event)\"\n (input)=\"onInput($event)\"\n (blur)=\"touched.set(true)\"\n />\n\n @if (showClear()) {\n <button type=\"button\" class=\"kt-field-box__clear\" [attr.aria-label]=\"clearLabel()\" (click)=\"clear()\">\n <span class=\"kt-field-box__icon\" aria-hidden=\"true\">close</span>\n </button>\n }\n\n <button\n type=\"button\"\n class=\"kt-field-box__toggle\"\n [disabled]=\"disabled() || readonly()\"\n [attr.aria-label]=\"isPasswordVisible() ? 'Masquer le mot de passe' : 'Afficher le mot de passe'\"\n [attr.aria-controls]=\"inputId()\"\n (mousedown)=\"toggleVisibility($event)\"\n >\n <span class=\"kt-field-box__icon\" aria-hidden=\"true\">\n {{ isPasswordVisible() ? 'visibility_off' : 'visibility' }}\n </span>\n </button>\n\n @if (suffix(); as suffix) {\n <span class=\"kt-field-box__affix\">\n @if (asTemplate(suffix); as tpl) {\n <ng-container [ngTemplateOutlet]=\"tpl\" />\n } @else {\n {{ asText(suffix) }}\n }\n </span>\n }\n </div>\n</kt-field>\n" }]
|
|
770
|
+
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], minLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minLength", required: false }] }], maxLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLength", required: false }] }], pattern: [{ type: i0.Input, args: [{ isSignal: true, alias: "pattern", required: false }] }] } });
|
|
771
|
+
|
|
699
772
|
/**
|
|
700
773
|
* Bouton bascule (Switch / Slide-Toggle) accessible conforme aux normes WAI-ARIA.
|
|
701
774
|
* Permet d'activer ou désactiver une option avec effet immédiat.
|
|
@@ -1203,6 +1276,8 @@ class KtCheckbox {
|
|
|
1203
1276
|
inputEl = viewChild.required('input');
|
|
1204
1277
|
el = inject(ElementRef);
|
|
1205
1278
|
errorResolver = inject(KtFieldErrorResolver);
|
|
1279
|
+
auditEnabled = inject(KT_AUDIT_ENABLED);
|
|
1280
|
+
isDestroyed = false;
|
|
1206
1281
|
idGen = inject(KtIdGenerator);
|
|
1207
1282
|
uid = this.idGen.generateId('checkbox');
|
|
1208
1283
|
baseId = computed(() => this.id() ?? `kt-checkbox-${this.uid}`, /* @ts-ignore */
|
|
@@ -1239,23 +1314,25 @@ class KtCheckbox {
|
|
|
1239
1314
|
}, /* @ts-ignore */
|
|
1240
1315
|
...(ngDevMode ? [{ debugName: "describedBy" }] : /* istanbul ignore next */ []));
|
|
1241
1316
|
constructor() {
|
|
1317
|
+
inject(DestroyRef).onDestroy(() => {
|
|
1318
|
+
this.isDestroyed = true;
|
|
1319
|
+
});
|
|
1242
1320
|
// `indeterminate` est une PROPRIÉTÉ (non un attribut) : poussée impérativement sur l'input natif.
|
|
1243
1321
|
effect(() => {
|
|
1244
1322
|
this.inputEl().nativeElement.indeterminate = this.indeterminate();
|
|
1245
1323
|
});
|
|
1246
|
-
|
|
1324
|
+
}
|
|
1325
|
+
ngAfterViewInit() {
|
|
1326
|
+
// Garde-fou a11y (navigateur uniquement) : nom accessible = `label`, `ariaLabel` OU contenu
|
|
1247
1327
|
// projeté. Sans aucun des trois, la case est annoncée vide (WCAG 4.1.2).
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
console.warn('[ktCheckbox] sans `label`, `ariaLabel` ni contenu projeté : annoncée sans nom accessible (WCAG 4.1.2).');
|
|
1257
|
-
}
|
|
1258
|
-
});
|
|
1328
|
+
if (this.isDestroyed)
|
|
1329
|
+
return;
|
|
1330
|
+
if (!this.auditEnabled || this.label() || this.ariaLabel())
|
|
1331
|
+
return;
|
|
1332
|
+
const labelText = this.el.nativeElement.querySelector('.kt-checkbox__label')?.textContent?.replace('*', '').trim();
|
|
1333
|
+
if (!labelText) {
|
|
1334
|
+
console.warn('[ktCheckbox] sans `label`, `ariaLabel` ni contenu projeté : annoncée sans nom accessible (WCAG 4.1.2).');
|
|
1335
|
+
}
|
|
1259
1336
|
}
|
|
1260
1337
|
/** Focus la case native (utilisé par Signal Forms `focusBoundControl`). */
|
|
1261
1338
|
focus(options) {
|
|
@@ -1775,11 +1852,23 @@ class KtBaseSelect {
|
|
|
1775
1852
|
errorResolver = inject(KtFieldErrorResolver);
|
|
1776
1853
|
config = inject(KT_SELECT_CONFIG, { optional: true });
|
|
1777
1854
|
host = inject(ElementRef);
|
|
1778
|
-
ngZone = inject(NgZone);
|
|
1779
1855
|
doc = inject(DOCUMENT);
|
|
1780
1856
|
platformId = inject(PLATFORM_ID);
|
|
1781
1857
|
destroyRef = inject(DestroyRef);
|
|
1858
|
+
bodyScrollLock = inject(KtBodyScrollLock);
|
|
1782
1859
|
wasExpanded = false;
|
|
1860
|
+
scrollLocked = false;
|
|
1861
|
+
/** Pose/relâche le verrou de scroll du fond de façon idempotente (n'agit qu'à la transition),
|
|
1862
|
+
via le compteur partagé `KtBodyScrollLock` — deux sheets ouvertes ne se désynchronisent pas. */
|
|
1863
|
+
setBodyScrollLock(lock) {
|
|
1864
|
+
if (lock === this.scrollLocked)
|
|
1865
|
+
return;
|
|
1866
|
+
this.scrollLocked = lock;
|
|
1867
|
+
if (lock)
|
|
1868
|
+
this.bodyScrollLock.lock();
|
|
1869
|
+
else
|
|
1870
|
+
this.bodyScrollLock.unlock();
|
|
1871
|
+
}
|
|
1783
1872
|
// --- Données / dérivation (clé OU fonction, défauts intelligents) ---
|
|
1784
1873
|
/** Liste des options affichées (source de vérité du contrôle). */
|
|
1785
1874
|
options = input.required(/* @ts-ignore */
|
|
@@ -2033,9 +2122,7 @@ class KtBaseSelect {
|
|
|
2033
2122
|
this.destroyRef.onDestroy(() => {
|
|
2034
2123
|
clearTimeout(this.announceTimer);
|
|
2035
2124
|
this.sheetDrag.destroy();
|
|
2036
|
-
|
|
2037
|
-
this.doc.body.style.overflow = '';
|
|
2038
|
-
}
|
|
2125
|
+
this.setBodyScrollLock(false);
|
|
2039
2126
|
});
|
|
2040
2127
|
// Préserve le contenu du template sur mobile pour permettre l'animation de sortie
|
|
2041
2128
|
effect(() => {
|
|
@@ -2044,42 +2131,36 @@ class KtBaseSelect {
|
|
|
2044
2131
|
cb.preserveContent.set(this.compact());
|
|
2045
2132
|
}
|
|
2046
2133
|
});
|
|
2047
|
-
// Sheet mobile : verrouille le scroll du fond et restitue le focus au
|
|
2134
|
+
// Sheet mobile : verrouille le scroll du fond (compteur partagé) et restitue le focus au
|
|
2135
|
+
// trigger à la fermeture.
|
|
2048
2136
|
effect(() => {
|
|
2049
|
-
if (!this.compact())
|
|
2050
|
-
return;
|
|
2051
2137
|
if (!isPlatformBrowser(this.platformId))
|
|
2052
2138
|
return;
|
|
2053
|
-
|
|
2054
|
-
|
|
2139
|
+
const compact = this.compact();
|
|
2140
|
+
const expanded = this.expanded();
|
|
2141
|
+
this.setBodyScrollLock(compact && expanded);
|
|
2142
|
+
if (compact && expanded) {
|
|
2055
2143
|
this.wasExpanded = true;
|
|
2056
2144
|
}
|
|
2057
|
-
else {
|
|
2058
|
-
this.
|
|
2059
|
-
if (this.wasExpanded) {
|
|
2060
|
-
this.triggerEl()?.nativeElement.focus();
|
|
2061
|
-
}
|
|
2145
|
+
else if (compact && this.wasExpanded) {
|
|
2146
|
+
this.triggerEl()?.nativeElement.focus();
|
|
2062
2147
|
}
|
|
2063
2148
|
});
|
|
2064
|
-
// Ferme au clic/tap en dehors du composant (remplace le binding d'hôte statique document:pointerdown
|
|
2065
|
-
//
|
|
2149
|
+
// Ferme au clic/tap en dehors du composant (remplace le binding d'hôte statique document:pointerdown,
|
|
2150
|
+
// enregistré dynamiquement pour pouvoir comparer la cible au popup monté dans un overlay).
|
|
2066
2151
|
if (isPlatformBrowser(this.platformId)) {
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
this.doc.addEventListener('pointerdown', onPointerDown);
|
|
2080
|
-
this.destroyRef.onDestroy(() => {
|
|
2081
|
-
this.doc.removeEventListener('pointerdown', onPointerDown);
|
|
2082
|
-
});
|
|
2152
|
+
const onPointerDown = (event) => {
|
|
2153
|
+
if (!this.expanded())
|
|
2154
|
+
return;
|
|
2155
|
+
const target = event.target;
|
|
2156
|
+
const popup = this.popupEl()?.nativeElement;
|
|
2157
|
+
if (target && (!this.host.nativeElement.contains(target) || target === popup)) {
|
|
2158
|
+
this.expanded.set(false);
|
|
2159
|
+
}
|
|
2160
|
+
};
|
|
2161
|
+
this.doc.addEventListener('pointerdown', onPointerDown);
|
|
2162
|
+
this.destroyRef.onDestroy(() => {
|
|
2163
|
+
this.doc.removeEventListener('pointerdown', onPointerDown);
|
|
2083
2164
|
});
|
|
2084
2165
|
}
|
|
2085
2166
|
// Fait défiler la liste pour afficher l'option active lors de la navigation au clavier (mode activedescendant).
|
|
@@ -2092,9 +2173,9 @@ class KtBaseSelect {
|
|
|
2092
2173
|
if (!listbox)
|
|
2093
2174
|
return;
|
|
2094
2175
|
const activeEl = listbox.querySelector('.kt-select__option--active');
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
}
|
|
2176
|
+
// `?.` : scrollIntoView n'est pas implémenté par tous les environnements de test (jsdom) ;
|
|
2177
|
+
// sans ce garde, un consommateur testant le Select en jsdom subit un crash en rAF.
|
|
2178
|
+
activeEl?.scrollIntoView?.({ block: 'nearest' });
|
|
2098
2179
|
});
|
|
2099
2180
|
});
|
|
2100
2181
|
if (isDevMode()) {
|
|
@@ -2159,14 +2240,10 @@ class KtBaseSelect {
|
|
|
2159
2240
|
}
|
|
2160
2241
|
/** Annonce le contenu du filtre ~500 ms après la dernière frappe (évite le spam SR). */
|
|
2161
2242
|
scheduleResultsAnnouncement() {
|
|
2162
|
-
this.
|
|
2163
|
-
|
|
2164
|
-
this.
|
|
2165
|
-
|
|
2166
|
-
this.announcedCount.set(this.composeFilterAnnouncement());
|
|
2167
|
-
});
|
|
2168
|
-
}, ANNOUNCE_DELAY_MS);
|
|
2169
|
-
});
|
|
2243
|
+
clearTimeout(this.announceTimer);
|
|
2244
|
+
this.announceTimer = setTimeout(() => {
|
|
2245
|
+
this.announcedCount.set(this.composeFilterAnnouncement());
|
|
2246
|
+
}, ANNOUNCE_DELAY_MS);
|
|
2170
2247
|
}
|
|
2171
2248
|
/** Annonce immédiate dans la live region du panneau (annule une annonce différée en attente). */
|
|
2172
2249
|
announceNow(text) {
|
|
@@ -2595,7 +2672,6 @@ class KtChipList {
|
|
|
2595
2672
|
doc = inject(DOCUMENT);
|
|
2596
2673
|
platformId = inject(PLATFORM_ID);
|
|
2597
2674
|
cdr = inject(ChangeDetectorRef);
|
|
2598
|
-
ngZone = inject(NgZone);
|
|
2599
2675
|
/** Vrai pendant la View Transition de CETTE liste : les chips (standards via Chip,
|
|
2600
2676
|
custom via tokens.css) ne portent leur `view-transition-name` que dans cette fenêtre. */
|
|
2601
2677
|
transitioning = signal(false, /* @ts-ignore */
|
|
@@ -2646,6 +2722,19 @@ class KtChipList {
|
|
|
2646
2722
|
...(ngDevMode ? [{ debugName: "itemDef" }] : /* istanbul ignore next */ []));
|
|
2647
2723
|
chips = viewChildren(KtChip, /* @ts-ignore */
|
|
2648
2724
|
...(ngDevMode ? [{ debugName: "chips" }] : /* istanbul ignore next */ []));
|
|
2725
|
+
// Sélecteurs des focusables (source unique, dédupliquée) : boutons « retirer » + focusables de
|
|
2726
|
+
// templates custom, avec (séquence clavier complète / roving) ou sans (cible de focus au retrait)
|
|
2727
|
+
// le bouton de repli « +N more ».
|
|
2728
|
+
static CHIP_FOCUSABLES = '.kt-chip__remove, .kt-chip-list__item button, .kt-chip-list__item [tabindex]';
|
|
2729
|
+
static ROVING_FOCUSABLES = `${KtChipList.CHIP_FOCUSABLES}, .kt-chip-list__more`;
|
|
2730
|
+
query(selector) {
|
|
2731
|
+
return Array.from(this.host.nativeElement.querySelectorAll(selector));
|
|
2732
|
+
}
|
|
2733
|
+
/** Index de l'unique focusable portant `tabindex="0"` : point d'entrée clavier UNIQUE dans la
|
|
2734
|
+
liste (pattern composite WAI-ARIA). Les flèches/Home/End le déplacent ; un focus direct
|
|
2735
|
+
(souris) le resynchronise via `onFocusin`. */
|
|
2736
|
+
activeIndex = signal(0, /* @ts-ignore */
|
|
2737
|
+
...(ngDevMode ? [{ debugName: "activeIndex" }] : /* istanbul ignore next */ []));
|
|
2649
2738
|
// --- Textes résolus (input > KT_CHIPS_CONFIG > défaut lib neutre EN) ---
|
|
2650
2739
|
resolvedListLabel = computed(() => this.listLabel() ?? this.config?.listLabel ?? 'Selected items', /* @ts-ignore */
|
|
2651
2740
|
...(ngDevMode ? [{ debugName: "resolvedListLabel" }] : /* istanbul ignore next */ []));
|
|
@@ -2711,7 +2800,22 @@ class KtChipList {
|
|
|
2711
2800
|
untracked(() => {
|
|
2712
2801
|
this.expanded.set(false);
|
|
2713
2802
|
});
|
|
2714
|
-
}
|
|
2803
|
+
});
|
|
2804
|
+
// Roving tabindex : un seul focusable porte tabindex=0 (les autres -1), recalculé après chaque
|
|
2805
|
+
// rendu (items/repli/index actif). Garantit un point d'entrée clavier UNIQUE (Tab) ; la
|
|
2806
|
+
// navigation interne reste aux flèches/Home/End.
|
|
2807
|
+
afterRenderEffect(() => {
|
|
2808
|
+
this.visibleItems();
|
|
2809
|
+
this.expanded();
|
|
2810
|
+
const active = this.activeIndex();
|
|
2811
|
+
const focusables = this.query(KtChipList.ROVING_FOCUSABLES);
|
|
2812
|
+
if (focusables.length === 0)
|
|
2813
|
+
return;
|
|
2814
|
+
const clamped = Math.min(Math.max(active, 0), focusables.length - 1);
|
|
2815
|
+
for (let i = 0; i < focusables.length; i++) {
|
|
2816
|
+
focusables[i].tabIndex = i === clamped ? 0 : -1;
|
|
2817
|
+
}
|
|
2818
|
+
});
|
|
2715
2819
|
inject(DestroyRef).onDestroy(() => clearTimeout(this.statusTimer));
|
|
2716
2820
|
}
|
|
2717
2821
|
idGen = inject(KtIdGenerator);
|
|
@@ -2769,9 +2873,9 @@ class KtChipList {
|
|
|
2769
2873
|
// (`appRef.tick()`) corrigerait le rendu mais ajouterait une passe synchrone sur toute l'appli à
|
|
2770
2874
|
// chaque retrait. On préfère DIFFÉRER la capture de l'état « après » : le callback d'une View
|
|
2771
2875
|
// Transition peut renvoyer une Promise, le navigateur attend sa résolution avant le snapshot.
|
|
2772
|
-
//
|
|
2773
|
-
//
|
|
2774
|
-
|
|
2876
|
+
// La mutation passe par un signal (le parent met à jour `items`) : en zoneless, c'est ce signal
|
|
2877
|
+
// qui planifie la CD (OnPush, seules les vues « dirty » sont vérifiées) ; on résout au prochain rendu.
|
|
2878
|
+
action();
|
|
2775
2879
|
return new Promise((resolve) => {
|
|
2776
2880
|
let settled = false;
|
|
2777
2881
|
const done = () => {
|
|
@@ -2782,7 +2886,7 @@ class KtChipList {
|
|
|
2782
2886
|
};
|
|
2783
2887
|
afterNextRender({ read: done }, { injector: this.injector });
|
|
2784
2888
|
// Garde-fou : si aucun rendu n'est planifié (retrait ignoré par le parent), ne pas figer la page.
|
|
2785
|
-
|
|
2889
|
+
setTimeout(done, 100);
|
|
2786
2890
|
});
|
|
2787
2891
|
});
|
|
2788
2892
|
this.activeTransition = vt;
|
|
@@ -2805,10 +2909,11 @@ class KtChipList {
|
|
|
2805
2909
|
this.removed.emit({ item, index });
|
|
2806
2910
|
afterNextRender({
|
|
2807
2911
|
read: () => {
|
|
2808
|
-
const
|
|
2809
|
-
const
|
|
2810
|
-
const target = focusables[
|
|
2912
|
+
const focusables = this.query(KtChipList.CHIP_FOCUSABLES);
|
|
2913
|
+
const targetIndex = Math.min(index, focusables.length - 1);
|
|
2914
|
+
const target = focusables[targetIndex];
|
|
2811
2915
|
if (target) {
|
|
2916
|
+
this.activeIndex.set(targetIndex);
|
|
2812
2917
|
target.focus();
|
|
2813
2918
|
return;
|
|
2814
2919
|
}
|
|
@@ -2830,9 +2935,12 @@ class KtChipList {
|
|
|
2830
2935
|
const firstRevealed = this.maxVisible() ?? 0;
|
|
2831
2936
|
afterNextRender({
|
|
2832
2937
|
read: () => {
|
|
2833
|
-
const
|
|
2834
|
-
const
|
|
2835
|
-
|
|
2938
|
+
const focusables = this.query(KtChipList.CHIP_FOCUSABLES);
|
|
2939
|
+
const target = focusables[firstRevealed];
|
|
2940
|
+
if (target) {
|
|
2941
|
+
this.activeIndex.set(firstRevealed);
|
|
2942
|
+
target.focus();
|
|
2943
|
+
}
|
|
2836
2944
|
},
|
|
2837
2945
|
}, { injector: this.injector });
|
|
2838
2946
|
});
|
|
@@ -2842,12 +2950,10 @@ class KtChipList {
|
|
|
2842
2950
|
if (!['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Home', 'End'].includes(key)) {
|
|
2843
2951
|
return;
|
|
2844
2952
|
}
|
|
2845
|
-
const
|
|
2846
|
-
const focusables = Array.from(hostEl.querySelectorAll('.kt-chip__remove, .kt-chip-list__item button, .kt-chip-list__item [tabindex="0"], .kt-chip-list__more'));
|
|
2953
|
+
const focusables = this.query(KtChipList.ROVING_FOCUSABLES);
|
|
2847
2954
|
if (focusables.length === 0)
|
|
2848
2955
|
return;
|
|
2849
|
-
const
|
|
2850
|
-
const currentIndex = focusables.indexOf(active);
|
|
2956
|
+
const currentIndex = focusables.indexOf(this.doc.activeElement);
|
|
2851
2957
|
let nextIndex = -1;
|
|
2852
2958
|
if (key === 'ArrowRight' || key === 'ArrowDown') {
|
|
2853
2959
|
nextIndex = currentIndex + 1;
|
|
@@ -2863,11 +2969,18 @@ class KtChipList {
|
|
|
2863
2969
|
}
|
|
2864
2970
|
if (nextIndex >= 0 && nextIndex < focusables.length) {
|
|
2865
2971
|
event.preventDefault();
|
|
2972
|
+
this.activeIndex.set(nextIndex);
|
|
2866
2973
|
focusables[nextIndex].focus();
|
|
2867
2974
|
}
|
|
2868
2975
|
}
|
|
2976
|
+
/** Resynchronise le point de tabulation unique sur l'élément réellement focusé (souris/voix). */
|
|
2977
|
+
onFocusin(event) {
|
|
2978
|
+
const index = this.query(KtChipList.ROVING_FOCUSABLES).indexOf(event.target);
|
|
2979
|
+
if (index >= 0)
|
|
2980
|
+
this.activeIndex.set(index);
|
|
2981
|
+
}
|
|
2869
2982
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: KtChipList, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2870
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.1", type: KtChipList, isStandalone: true, selector: "kt-chip-list", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, itemLabel: { classPropertyName: "itemLabel", publicName: "itemLabel", isSignal: true, isRequired: false, transformFunction: null }, itemKey: { classPropertyName: "itemKey", publicName: "itemKey", isSignal: true, isRequired: false, transformFunction: null }, removable: { classPropertyName: "removable", publicName: "removable", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, maxVisible: { classPropertyName: "maxVisible", publicName: "maxVisible", isSignal: true, isRequired: false, transformFunction: null }, listLabel: { classPropertyName: "listLabel", publicName: "listLabel", isSignal: true, isRequired: false, transformFunction: null }, removeItemLabel: { classPropertyName: "removeItemLabel", publicName: "removeItemLabel", isSignal: true, isRequired: false, transformFunction: null }, itemRemovedText: { classPropertyName: "itemRemovedText", publicName: "itemRemovedText", isSignal: true, isRequired: false, transformFunction: null }, moreLabel: { classPropertyName: "moreLabel", publicName: "moreLabel", isSignal: true, isRequired: false, transformFunction: null }, lessLabel: { classPropertyName: "lessLabel", publicName: "lessLabel", isSignal: true, isRequired: false, transformFunction: null }, chipTemplate: { classPropertyName: "chipTemplate", publicName: "chipTemplate", isSignal: true, isRequired: false, transformFunction: null }, emptyFocusTarget: { classPropertyName: "emptyFocusTarget", publicName: "emptyFocusTarget", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { removed: "removed" }, host: { listeners: { "keydown": "onKeydown($event)" }, properties: { "attr.data-empty": "items().length === 0 ? '' : null", "attr.data-vt-active": "transitioning() ? '' : null" } }, providers: [{ provide: ChipTransitionScope, useExisting: KtChipList }], queries: [{ propertyName: "itemDef", first: true, predicate: KtChipItemDef, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "chips", predicate: KtChip, descendants: true, isSignal: true }], ngImport: i0, template: "@if (items().length > 0) {\n <div class=\"kt-chip-list\">\n <div class=\"kt-chip-list__items\" role=\"list\" [attr.aria-label]=\"resolvedListLabel()\">\n @for (item of visibleItems(); track keyOf(item); let i = $index) {\n @if (effectiveTemplate(); as tpl) {\n <div role=\"listitem\" class=\"kt-chip-list__item\">\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: item, remove: removeCallback(item, i) }\"\n />\n </div>\n } @else {\n <kt-chip\n role=\"listitem\"\n [removable]=\"showRemove()\"\n [disabled]=\"disabled()\"\n [removeLabel]=\"removeLabelFor(item)\"\n (remove)=\"removeAt(item, i)\"\n >{{ labelOf(item) }}</kt-chip\n >\n }\n }\n </div>\n <!-- Le bouton de repli/d\u00E9pli n'est PAS un chip : hors du role=\"list\" pour ne pas \u00EAtre\n annonc\u00E9 comme un item de la liste (reste dans la m\u00EAme rang\u00E9e flex). -->\n @if (overflow()) {\n <button\n type=\"button\"\n class=\"kt-chip-list__more\"\n [attr.aria-expanded]=\"expanded()\"\n [style.view-transition-name]=\"transitioning() ? moreBtnTransitionName : null\"\n [style.view-transition-class]=\"'chip-transition'\"\n (click)=\"toggleExpanded()\"\n >\n {{ expanded() ? resolvedLessLabel() : resolvedMoreLabel()(hiddenCount()) }}\n </button>\n }\n </div>\n}\n<!-- Annonce des retraits : TOUJOURS rendue (hors du @if, sinon elle dispara\u00EEt avec le dernier chip). -->\n<div class=\"kt-chip-list__status\" role=\"status\" aria-live=\"polite\">{{ status() }}</div>\n", styles: ["@layer kt-aaa.components{:host{display:block}.kt-chip-list{display:flex;flex-wrap:wrap;gap:.5rem}.kt-chip-list__items,.kt-chip-list__item{display:contents}.kt-chip-list__more{display:inline-flex;align-items:center;gap:var(--chip-gap);padding:var(--chip-padding-y) var(--chip-padding-x);border-radius:var(--chip-radius);background:var(--chip-bg);border:1px solid var(--chip-border);box-shadow:var(--chip-shadow, none);font:inherit;font-size:var(--chip-font-size);color:var(--chip-color);cursor:pointer;min-block-size:24px}.kt-chip-list__more:hover{background:var(--chip-bg-hover);box-shadow:var(--chip-shadow-hover, var(--chip-shadow, none))}.kt-chip-list__more:focus-visible{outline:2px solid var(--chip-focus-ring);outline-offset:1px}.kt-chip-list__status{position:absolute;inset-block-start:0;inset-inline-start:0;inline-size:1px;block-size:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}@media(pointer:coarse){.kt-chip-list__more{min-block-size:32px}}}\n"], dependencies: [{ kind: "component", type: KtChip, selector: "kt-chip", inputs: ["removable", "disabled", "removeLabel"], outputs: ["remove"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2983
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.1", type: KtChipList, isStandalone: true, selector: "kt-chip-list", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, itemLabel: { classPropertyName: "itemLabel", publicName: "itemLabel", isSignal: true, isRequired: false, transformFunction: null }, itemKey: { classPropertyName: "itemKey", publicName: "itemKey", isSignal: true, isRequired: false, transformFunction: null }, removable: { classPropertyName: "removable", publicName: "removable", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, maxVisible: { classPropertyName: "maxVisible", publicName: "maxVisible", isSignal: true, isRequired: false, transformFunction: null }, listLabel: { classPropertyName: "listLabel", publicName: "listLabel", isSignal: true, isRequired: false, transformFunction: null }, removeItemLabel: { classPropertyName: "removeItemLabel", publicName: "removeItemLabel", isSignal: true, isRequired: false, transformFunction: null }, itemRemovedText: { classPropertyName: "itemRemovedText", publicName: "itemRemovedText", isSignal: true, isRequired: false, transformFunction: null }, moreLabel: { classPropertyName: "moreLabel", publicName: "moreLabel", isSignal: true, isRequired: false, transformFunction: null }, lessLabel: { classPropertyName: "lessLabel", publicName: "lessLabel", isSignal: true, isRequired: false, transformFunction: null }, chipTemplate: { classPropertyName: "chipTemplate", publicName: "chipTemplate", isSignal: true, isRequired: false, transformFunction: null }, emptyFocusTarget: { classPropertyName: "emptyFocusTarget", publicName: "emptyFocusTarget", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { removed: "removed" }, host: { listeners: { "keydown": "onKeydown($event)", "focusin": "onFocusin($event)" }, properties: { "attr.data-empty": "items().length === 0 ? '' : null", "attr.data-vt-active": "transitioning() ? '' : null" } }, providers: [{ provide: ChipTransitionScope, useExisting: KtChipList }], queries: [{ propertyName: "itemDef", first: true, predicate: KtChipItemDef, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "chips", predicate: KtChip, descendants: true, isSignal: true }], ngImport: i0, template: "@if (items().length > 0) {\n <div class=\"kt-chip-list\">\n <div class=\"kt-chip-list__items\" role=\"list\" [attr.aria-label]=\"resolvedListLabel()\">\n @for (item of visibleItems(); track keyOf(item); let i = $index) {\n @if (effectiveTemplate(); as tpl) {\n <div role=\"listitem\" class=\"kt-chip-list__item\">\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: item, remove: removeCallback(item, i) }\"\n />\n </div>\n } @else {\n <kt-chip\n role=\"listitem\"\n [removable]=\"showRemove()\"\n [disabled]=\"disabled()\"\n [removeLabel]=\"removeLabelFor(item)\"\n (remove)=\"removeAt(item, i)\"\n >{{ labelOf(item) }}</kt-chip\n >\n }\n }\n </div>\n <!-- Le bouton de repli/d\u00E9pli n'est PAS un chip : hors du role=\"list\" pour ne pas \u00EAtre\n annonc\u00E9 comme un item de la liste (reste dans la m\u00EAme rang\u00E9e flex). -->\n @if (overflow()) {\n <button\n type=\"button\"\n class=\"kt-chip-list__more\"\n [attr.aria-expanded]=\"expanded()\"\n [style.view-transition-name]=\"transitioning() ? moreBtnTransitionName : null\"\n [style.view-transition-class]=\"'chip-transition'\"\n (click)=\"toggleExpanded()\"\n >\n {{ expanded() ? resolvedLessLabel() : resolvedMoreLabel()(hiddenCount()) }}\n </button>\n }\n </div>\n}\n<!-- Annonce des retraits : TOUJOURS rendue (hors du @if, sinon elle dispara\u00EEt avec le dernier chip). -->\n<div class=\"kt-chip-list__status\" role=\"status\" aria-live=\"polite\">{{ status() }}</div>\n", styles: ["@layer kt-aaa.components{:host{display:block}.kt-chip-list{display:flex;flex-wrap:wrap;gap:.5rem}.kt-chip-list__items,.kt-chip-list__item{display:contents}.kt-chip-list__more{display:inline-flex;align-items:center;gap:var(--chip-gap);padding:var(--chip-padding-y) var(--chip-padding-x);border-radius:var(--chip-radius);background:var(--chip-bg);border:1px solid var(--chip-border);box-shadow:var(--chip-shadow, none);font:inherit;font-size:var(--chip-font-size);color:var(--chip-color);cursor:pointer;min-block-size:24px}.kt-chip-list__more:hover{background:var(--chip-bg-hover);box-shadow:var(--chip-shadow-hover, var(--chip-shadow, none))}.kt-chip-list__more:focus-visible{outline:2px solid var(--chip-focus-ring);outline-offset:1px}.kt-chip-list__status{position:absolute;inset-block-start:0;inset-inline-start:0;inline-size:1px;block-size:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}@media(pointer:coarse){.kt-chip-list__more{min-block-size:32px}}}\n"], dependencies: [{ kind: "component", type: KtChip, selector: "kt-chip", inputs: ["removable", "disabled", "removeLabel"], outputs: ["remove"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2871
2984
|
}
|
|
2872
2985
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: KtChipList, decorators: [{
|
|
2873
2986
|
type: Component,
|
|
@@ -2877,6 +2990,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImpor
|
|
|
2877
2990
|
// nomment les chips à template custom QUE sous ce marqueur (cf. ChipTransitionScope).
|
|
2878
2991
|
'[attr.data-vt-active]': "transitioning() ? '' : null",
|
|
2879
2992
|
'(keydown)': 'onKeydown($event)',
|
|
2993
|
+
'(focusin)': 'onFocusin($event)',
|
|
2880
2994
|
}, template: "@if (items().length > 0) {\n <div class=\"kt-chip-list\">\n <div class=\"kt-chip-list__items\" role=\"list\" [attr.aria-label]=\"resolvedListLabel()\">\n @for (item of visibleItems(); track keyOf(item); let i = $index) {\n @if (effectiveTemplate(); as tpl) {\n <div role=\"listitem\" class=\"kt-chip-list__item\">\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: item, remove: removeCallback(item, i) }\"\n />\n </div>\n } @else {\n <kt-chip\n role=\"listitem\"\n [removable]=\"showRemove()\"\n [disabled]=\"disabled()\"\n [removeLabel]=\"removeLabelFor(item)\"\n (remove)=\"removeAt(item, i)\"\n >{{ labelOf(item) }}</kt-chip\n >\n }\n }\n </div>\n <!-- Le bouton de repli/d\u00E9pli n'est PAS un chip : hors du role=\"list\" pour ne pas \u00EAtre\n annonc\u00E9 comme un item de la liste (reste dans la m\u00EAme rang\u00E9e flex). -->\n @if (overflow()) {\n <button\n type=\"button\"\n class=\"kt-chip-list__more\"\n [attr.aria-expanded]=\"expanded()\"\n [style.view-transition-name]=\"transitioning() ? moreBtnTransitionName : null\"\n [style.view-transition-class]=\"'chip-transition'\"\n (click)=\"toggleExpanded()\"\n >\n {{ expanded() ? resolvedLessLabel() : resolvedMoreLabel()(hiddenCount()) }}\n </button>\n }\n </div>\n}\n<!-- Annonce des retraits : TOUJOURS rendue (hors du @if, sinon elle dispara\u00EEt avec le dernier chip). -->\n<div class=\"kt-chip-list__status\" role=\"status\" aria-live=\"polite\">{{ status() }}</div>\n", styles: ["@layer kt-aaa.components{:host{display:block}.kt-chip-list{display:flex;flex-wrap:wrap;gap:.5rem}.kt-chip-list__items,.kt-chip-list__item{display:contents}.kt-chip-list__more{display:inline-flex;align-items:center;gap:var(--chip-gap);padding:var(--chip-padding-y) var(--chip-padding-x);border-radius:var(--chip-radius);background:var(--chip-bg);border:1px solid var(--chip-border);box-shadow:var(--chip-shadow, none);font:inherit;font-size:var(--chip-font-size);color:var(--chip-color);cursor:pointer;min-block-size:24px}.kt-chip-list__more:hover{background:var(--chip-bg-hover);box-shadow:var(--chip-shadow-hover, var(--chip-shadow, none))}.kt-chip-list__more:focus-visible{outline:2px solid var(--chip-focus-ring);outline-offset:1px}.kt-chip-list__status{position:absolute;inset-block-start:0;inset-inline-start:0;inline-size:1px;block-size:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}@media(pointer:coarse){.kt-chip-list__more{min-block-size:32px}}}\n"] }]
|
|
2881
2995
|
}], ctorParameters: () => [], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], itemLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemLabel", required: false }] }], itemKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemKey", required: false }] }], removable: [{ type: i0.Input, args: [{ isSignal: true, alias: "removable", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], maxVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxVisible", required: false }] }], listLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "listLabel", required: false }] }], removeItemLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "removeItemLabel", required: false }] }], itemRemovedText: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemRemovedText", required: false }] }], moreLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "moreLabel", required: false }] }], lessLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "lessLabel", required: false }] }], chipTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "chipTemplate", required: false }] }], emptyFocusTarget: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyFocusTarget", required: false }] }], removed: [{ type: i0.Output, args: ["removed"] }], itemDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => KtChipItemDef), { isSignal: true }] }], chips: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => KtChip), { isSignal: true }] }] } });
|
|
2882
2996
|
|
|
@@ -3665,5 +3779,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImpor
|
|
|
3665
3779
|
* Generated bundle index. Do not edit.
|
|
3666
3780
|
*/
|
|
3667
3781
|
|
|
3668
|
-
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 };
|
|
3782
|
+
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, KtPasswordField, KtRadio, KtRadioGroup, KtSelect, KtSelectConfig, KtSelectOptionDef, KtSelectTriggerDef, KtSwitch, KtTemporalDatePipe, KtTextArea, KtTextField, KtTimeField, KtYearMonthField, Temporal, defaultKtFieldErrorMatcher, ktErrorParam, normalizeKtSuggestions, provideKtField };
|
|
3669
3783
|
//# sourceMappingURL=ktortu-aaa-forms.mjs.map
|