@ktortu/aaa 0.9.3 → 0.9.5
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 +50 -0
- package/disclosure/disclosure-tokens.css +18 -0
- package/disclosure/disclosure.css +84 -0
- package/fesm2022/ktortu-aaa-dialog.mjs +27 -13
- package/fesm2022/ktortu-aaa-dialog.mjs.map +1 -1
- package/fesm2022/ktortu-aaa-forms.mjs +339 -7
- package/fesm2022/ktortu-aaa-forms.mjs.map +1 -1
- package/fesm2022/ktortu-aaa.mjs +1 -0
- package/fesm2022/ktortu-aaa.mjs.map +1 -1
- package/forms/chips/chip-listbox.css +41 -0
- package/forms/chips/chip.css +47 -0
- package/forms/chips/tokens.css +5 -0
- package/package.json +1 -1
- package/types/ktortu-aaa-dialog.d.ts +23 -1
- package/types/ktortu-aaa-forms.d.ts +95 -3
- package/types/ktortu-aaa.d.ts +1 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NgTemplateOutlet, DOCUMENT, isPlatformBrowser } from '@angular/common';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
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,
|
|
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, afterRenderEffect, Injector, ChangeDetectorRef, viewChildren, LOCALE_ID, Pipe } from '@angular/core';
|
|
4
4
|
import { KtTooltip } from '@ktortu/aaa/tooltip';
|
|
5
5
|
import { KtIdGenerator, KT_AUDIT_ENABLED, KtBodyScrollLock, KtViewport, createKtSheetDrag } from '@ktortu/aaa/cdk';
|
|
6
6
|
import { transformedValue } from '@angular/forms/signals';
|
|
@@ -2570,7 +2570,297 @@ class ChipTransitionScope {
|
|
|
2570
2570
|
}
|
|
2571
2571
|
|
|
2572
2572
|
/**
|
|
2573
|
-
*
|
|
2573
|
+
* Groupe de puces sélectionnables (Chip Listbox) conforme à l'ARIA Listbox / WCAG AAA.
|
|
2574
|
+
* Orchestrateur : s'intègre aux formulaires réactifs ou de modèle via `FormValueControl`.
|
|
2575
|
+
* Permet la sélection simple ou multiple, avec gestion du roving tabindex et des touches fléchées
|
|
2576
|
+
* de façon autonome et robuste.
|
|
2577
|
+
*
|
|
2578
|
+
* @example
|
|
2579
|
+
* ```html
|
|
2580
|
+
* <kt-chip-listbox label="Filtres" [(value)]="selectedTags" multiple>
|
|
2581
|
+
* <kt-chip [value]="'angular'">Angular</kt-chip>
|
|
2582
|
+
* <kt-chip [value]="'react'">React</kt-chip>
|
|
2583
|
+
* </kt-chip-listbox>
|
|
2584
|
+
* ```
|
|
2585
|
+
*/
|
|
2586
|
+
class KtChipListbox {
|
|
2587
|
+
config = inject(KT_FIELD_CONFIG, { optional: true });
|
|
2588
|
+
doc = inject(DOCUMENT);
|
|
2589
|
+
/** Valeur sélectionnée (two-way) : tableau de valeurs (si multiple) ou valeur unique (si simple). */
|
|
2590
|
+
value = model(null, /* @ts-ignore */
|
|
2591
|
+
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
2592
|
+
// --- État poussé par [formField] ---
|
|
2593
|
+
/** État « touché » (two-way), piloté par `[formField]`. @default false */
|
|
2594
|
+
touched = model(false, /* @ts-ignore */
|
|
2595
|
+
...(ngDevMode ? [{ debugName: "touched" }] : /* istanbul ignore next */ []));
|
|
2596
|
+
/** Désactive le groupe de puces. @default false */
|
|
2597
|
+
disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
2598
|
+
/** Mode lecture seule (bloque la sélection). @default false */
|
|
2599
|
+
readonly = input(false, { ...(ngDevMode ? { debugName: "readonly" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
2600
|
+
/** Marque le groupe comme invalide. @default false */
|
|
2601
|
+
invalid = input(false, { ...(ngDevMode ? { debugName: "invalid" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
2602
|
+
/** Affiche l'astérisque requis et aria-required sur le groupe. @default false */
|
|
2603
|
+
required = input(false, { ...(ngDevMode ? { debugName: "required" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
2604
|
+
/** État « modifié » (dirty). @default false */
|
|
2605
|
+
dirty = input(false, { ...(ngDevMode ? { debugName: "dirty" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
2606
|
+
/** Validation asynchrone en cours. @default false */
|
|
2607
|
+
pending = input(false, { ...(ngDevMode ? { debugName: "pending" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
2608
|
+
/** Erreurs de validation à afficher. @default [] */
|
|
2609
|
+
errors = input([], /* @ts-ignore */
|
|
2610
|
+
...(ngDevMode ? [{ debugName: "errors" }] : /* istanbul ignore next */ []));
|
|
2611
|
+
// --- Configuration ---
|
|
2612
|
+
/** Autorise la sélection de plusieurs puces. @default false */
|
|
2613
|
+
multiple = input(false, { ...(ngDevMode ? { debugName: "multiple" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
2614
|
+
/** Identifiant du composant (sélecteurs de test stables). @default auto-généré */
|
|
2615
|
+
id = input(/* @ts-ignore */
|
|
2616
|
+
...(ngDevMode ? [undefined, { debugName: "id" }] : /* istanbul ignore next */ []));
|
|
2617
|
+
/** Libellé (légende) du groupe de puces. @default undefined */
|
|
2618
|
+
label = input(/* @ts-ignore */
|
|
2619
|
+
...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
|
|
2620
|
+
/** Texte d'aide affiché sous le groupe. @default undefined */
|
|
2621
|
+
hint = input(/* @ts-ignore */
|
|
2622
|
+
...(ngDevMode ? [undefined, { debugName: "hint" }] : /* istanbul ignore next */ []));
|
|
2623
|
+
/** Nom accessible (aria-label) quand label est absent. @default undefined */
|
|
2624
|
+
ariaLabel = input(/* @ts-ignore */
|
|
2625
|
+
...(ngDevMode ? [undefined, { debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
2626
|
+
/** Stratégie d'affichage des erreurs. @default undefined */
|
|
2627
|
+
errorMatcher = input(/* @ts-ignore */
|
|
2628
|
+
...(ngDevMode ? [undefined, { debugName: "errorMatcher" }] : /* istanbul ignore next */ []));
|
|
2629
|
+
/** Afficher toutes les erreurs. @default false */
|
|
2630
|
+
showAllErrors = input(this.config?.showAllErrors ?? false, { ...(ngDevMode ? { debugName: "showAllErrors" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
2631
|
+
/** Fonction de comparaison de valeurs pour déterminer la sélection. */
|
|
2632
|
+
compareWith = input(/* @ts-ignore */
|
|
2633
|
+
...(ngDevMode ? [undefined, { debugName: "compareWith" }] : /* istanbul ignore next */ []));
|
|
2634
|
+
el = inject(ElementRef);
|
|
2635
|
+
errorResolver = inject(KtFieldErrorResolver);
|
|
2636
|
+
idGen = inject(KtIdGenerator);
|
|
2637
|
+
uid = this.idGen.generateId('chip-listbox');
|
|
2638
|
+
baseId = computed(() => this.id() ?? `kt-chip-listbox-${this.uid}`, /* @ts-ignore */
|
|
2639
|
+
...(ngDevMode ? [{ debugName: "baseId" }] : /* istanbul ignore next */ []));
|
|
2640
|
+
labelId = computed(() => `${this.baseId()}-label`, /* @ts-ignore */
|
|
2641
|
+
...(ngDevMode ? [{ debugName: "labelId" }] : /* istanbul ignore next */ []));
|
|
2642
|
+
hintId = computed(() => `${this.baseId()}-hint`, /* @ts-ignore */
|
|
2643
|
+
...(ngDevMode ? [{ debugName: "hintId" }] : /* istanbul ignore next */ []));
|
|
2644
|
+
errorId = computed(() => `${this.baseId()}-error`, /* @ts-ignore */
|
|
2645
|
+
...(ngDevMode ? [{ debugName: "errorId" }] : /* istanbul ignore next */ []));
|
|
2646
|
+
activeIndex = signal(0, /* @ts-ignore */
|
|
2647
|
+
...(ngDevMode ? [{ debugName: "activeIndex" }] : /* istanbul ignore next */ []));
|
|
2648
|
+
matcher = computed(() => this.errorMatcher() ?? this.config?.errorMatcher ?? defaultKtFieldErrorMatcher, /* @ts-ignore */
|
|
2649
|
+
...(ngDevMode ? [{ debugName: "matcher" }] : /* istanbul ignore next */ []));
|
|
2650
|
+
showInvalid = computed(() => this.matcher()({ invalid: this.invalid(), touched: this.touched(), dirty: this.dirty() }), /* @ts-ignore */
|
|
2651
|
+
...(ngDevMode ? [{ debugName: "showInvalid" }] : /* istanbul ignore next */ []));
|
|
2652
|
+
resolvedErrors = computed(() => this.errorResolver.resolveAll(this.errors()), /* @ts-ignore */
|
|
2653
|
+
...(ngDevMode ? [{ debugName: "resolvedErrors" }] : /* istanbul ignore next */ []));
|
|
2654
|
+
displayedErrors = computed(() => this.showAllErrors() ? this.resolvedErrors() : this.resolvedErrors().slice(0, 1), /* @ts-ignore */
|
|
2655
|
+
...(ngDevMode ? [{ debugName: "displayedErrors" }] : /* istanbul ignore next */ []));
|
|
2656
|
+
resolvedAriaLabel = computed(() => this.ariaLabel() ?? null, /* @ts-ignore */
|
|
2657
|
+
...(ngDevMode ? [{ debugName: "resolvedAriaLabel" }] : /* istanbul ignore next */ []));
|
|
2658
|
+
describedBy = computed(() => {
|
|
2659
|
+
const ids = [];
|
|
2660
|
+
if (this.hint() && !this.showInvalid())
|
|
2661
|
+
ids.push(this.hintId());
|
|
2662
|
+
if (this.showInvalid() && this.resolvedErrors().length > 0)
|
|
2663
|
+
ids.push(this.errorId());
|
|
2664
|
+
return ids.length ? ids.join(' ') : null;
|
|
2665
|
+
}, /* @ts-ignore */
|
|
2666
|
+
...(ngDevMode ? [{ debugName: "describedBy" }] : /* istanbul ignore next */ []));
|
|
2667
|
+
comparator = computed(() => this.compareWith() ?? ((a, b) => a === b), /* @ts-ignore */
|
|
2668
|
+
...(ngDevMode ? [{ debugName: "comparator" }] : /* istanbul ignore next */ []));
|
|
2669
|
+
constructor() {
|
|
2670
|
+
// Roving tabindex : un seul chip porte tabindex=0 (les autres -1) dans la liste
|
|
2671
|
+
afterRenderEffect(() => {
|
|
2672
|
+
this.value();
|
|
2673
|
+
const active = this.activeIndex();
|
|
2674
|
+
const focusables = this.query('.kt-chip');
|
|
2675
|
+
if (focusables.length === 0)
|
|
2676
|
+
return;
|
|
2677
|
+
const clamped = Math.min(Math.max(active, 0), focusables.length - 1);
|
|
2678
|
+
for (let i = 0; i < focusables.length; i++) {
|
|
2679
|
+
focusables[i].tabIndex = i === clamped ? 0 : -1;
|
|
2680
|
+
}
|
|
2681
|
+
});
|
|
2682
|
+
}
|
|
2683
|
+
query(selector) {
|
|
2684
|
+
return Array.from(this.el.nativeElement.querySelectorAll(selector));
|
|
2685
|
+
}
|
|
2686
|
+
/** Détermine si une valeur d'option est sélectionnée. */
|
|
2687
|
+
isSelected(optionValue) {
|
|
2688
|
+
const val = this.value();
|
|
2689
|
+
if (val === null || val === undefined)
|
|
2690
|
+
return false;
|
|
2691
|
+
const cmp = this.comparator();
|
|
2692
|
+
if (this.multiple()) {
|
|
2693
|
+
return Array.isArray(val) && val.some((v) => cmp(v, optionValue));
|
|
2694
|
+
}
|
|
2695
|
+
return cmp(val, optionValue);
|
|
2696
|
+
}
|
|
2697
|
+
/** Bascule la sélection d'une valeur d'option. */
|
|
2698
|
+
toggle(optionValue) {
|
|
2699
|
+
if (this.disabled() || this.readonly())
|
|
2700
|
+
return;
|
|
2701
|
+
const cmp = this.comparator();
|
|
2702
|
+
if (this.multiple()) {
|
|
2703
|
+
const arr = this.value() ?? [];
|
|
2704
|
+
const exists = arr.some((v) => cmp(v, optionValue));
|
|
2705
|
+
if (exists) {
|
|
2706
|
+
this.value.set(arr.filter((v) => !cmp(v, optionValue)));
|
|
2707
|
+
}
|
|
2708
|
+
else {
|
|
2709
|
+
this.value.set([...arr, optionValue]);
|
|
2710
|
+
}
|
|
2711
|
+
}
|
|
2712
|
+
else {
|
|
2713
|
+
const current = this.value();
|
|
2714
|
+
if (current !== null && cmp(current, optionValue)) {
|
|
2715
|
+
this.value.set(null);
|
|
2716
|
+
}
|
|
2717
|
+
else {
|
|
2718
|
+
this.value.set(optionValue);
|
|
2719
|
+
}
|
|
2720
|
+
}
|
|
2721
|
+
this.touched.set(true);
|
|
2722
|
+
}
|
|
2723
|
+
onKeydown(event) {
|
|
2724
|
+
const key = event.key;
|
|
2725
|
+
if (!['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Home', 'End', ' ', 'Enter'].includes(key)) {
|
|
2726
|
+
return;
|
|
2727
|
+
}
|
|
2728
|
+
const focusables = this.query('.kt-chip');
|
|
2729
|
+
if (focusables.length === 0)
|
|
2730
|
+
return;
|
|
2731
|
+
const currentIndex = focusables.indexOf(this.doc.activeElement);
|
|
2732
|
+
if (key === ' ' || key === 'Enter') {
|
|
2733
|
+
event.preventDefault();
|
|
2734
|
+
if (currentIndex >= 0) {
|
|
2735
|
+
// Déclenche l'événement click natif du chip, qui est intercepté par le listener du chip
|
|
2736
|
+
focusables[currentIndex].click();
|
|
2737
|
+
}
|
|
2738
|
+
return;
|
|
2739
|
+
}
|
|
2740
|
+
let nextIndex = currentIndex;
|
|
2741
|
+
if (key === 'ArrowRight' || key === 'ArrowDown') {
|
|
2742
|
+
nextIndex = (currentIndex + 1) % focusables.length;
|
|
2743
|
+
}
|
|
2744
|
+
else if (key === 'ArrowLeft' || key === 'ArrowUp') {
|
|
2745
|
+
nextIndex = (currentIndex - 1 + focusables.length) % focusables.length;
|
|
2746
|
+
}
|
|
2747
|
+
else if (key === 'Home') {
|
|
2748
|
+
nextIndex = 0;
|
|
2749
|
+
}
|
|
2750
|
+
else if (key === 'End') {
|
|
2751
|
+
nextIndex = focusables.length - 1;
|
|
2752
|
+
}
|
|
2753
|
+
if (nextIndex >= 0 && nextIndex < focusables.length) {
|
|
2754
|
+
event.preventDefault();
|
|
2755
|
+
this.activeIndex.set(nextIndex);
|
|
2756
|
+
focusables[nextIndex].focus();
|
|
2757
|
+
}
|
|
2758
|
+
}
|
|
2759
|
+
onFocusin(event) {
|
|
2760
|
+
const index = this.query('.kt-chip').indexOf(event.target);
|
|
2761
|
+
if (index >= 0)
|
|
2762
|
+
this.activeIndex.set(index);
|
|
2763
|
+
}
|
|
2764
|
+
/** Focus la première option active. */
|
|
2765
|
+
focus(options) {
|
|
2766
|
+
this.el.nativeElement.querySelector('.kt-chip:not([disabled])')?.focus(options);
|
|
2767
|
+
}
|
|
2768
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: KtChipListbox, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2769
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.1", type: KtChipListbox, isStandalone: true, selector: "kt-chip-listbox", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", 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 }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, dirty: { classPropertyName: "dirty", publicName: "dirty", isSignal: true, isRequired: false, transformFunction: null }, pending: { classPropertyName: "pending", publicName: "pending", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, errorMatcher: { classPropertyName: "errorMatcher", publicName: "errorMatcher", isSignal: true, isRequired: false, transformFunction: null }, showAllErrors: { classPropertyName: "showAllErrors", publicName: "showAllErrors", isSignal: true, isRequired: false, transformFunction: null }, compareWith: { classPropertyName: "compareWith", publicName: "compareWith", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange" }, host: { listeners: { "keydown": "onKeydown($event)", "focusin": "onFocusin($event)" }, classAttribute: "kt-chip-listbox-container" }, ngImport: i0, template: `
|
|
2770
|
+
<div
|
|
2771
|
+
class="kt-chip-listbox-field"
|
|
2772
|
+
[class.kt-chip-listbox-field--invalid]="showInvalid()"
|
|
2773
|
+
[class.kt-chip-listbox-field--disabled]="disabled()"
|
|
2774
|
+
>
|
|
2775
|
+
@if (label(); as labelText) {
|
|
2776
|
+
<span [id]="labelId()" class="kt-chip-listbox__legend">
|
|
2777
|
+
{{ labelText }}
|
|
2778
|
+
@if (required()) {
|
|
2779
|
+
<span class="kt-chip-listbox__required" aria-hidden="true">*</span>
|
|
2780
|
+
}
|
|
2781
|
+
</span>
|
|
2782
|
+
}
|
|
2783
|
+
|
|
2784
|
+
<div
|
|
2785
|
+
class="kt-chip-listbox__options"
|
|
2786
|
+
role="listbox"
|
|
2787
|
+
[id]="baseId()"
|
|
2788
|
+
[attr.aria-multiselectable]="multiple() ? 'true' : null"
|
|
2789
|
+
[attr.aria-labelledby]="label() ? labelId() : null"
|
|
2790
|
+
[attr.aria-label]="!label() ? resolvedAriaLabel() : null"
|
|
2791
|
+
[attr.aria-describedby]="describedBy()"
|
|
2792
|
+
[attr.aria-required]="required() ? 'true' : null"
|
|
2793
|
+
[attr.aria-invalid]="showInvalid() ? 'true' : null"
|
|
2794
|
+
[attr.aria-disabled]="disabled() ? 'true' : null"
|
|
2795
|
+
>
|
|
2796
|
+
<ng-content />
|
|
2797
|
+
</div>
|
|
2798
|
+
|
|
2799
|
+
@if (hint() && !showInvalid()) {
|
|
2800
|
+
<p [id]="hintId()" class="kt-chip-listbox__hint">{{ hint() }}</p>
|
|
2801
|
+
}
|
|
2802
|
+
<div [id]="errorId()" class="kt-chip-listbox__error" aria-live="polite">
|
|
2803
|
+
@if (showInvalid()) {
|
|
2804
|
+
@for (error of displayedErrors(); track $index) {
|
|
2805
|
+
<span class="kt-chip-listbox__error-message">{{ error.message }}</span>
|
|
2806
|
+
}
|
|
2807
|
+
}
|
|
2808
|
+
</div>
|
|
2809
|
+
</div>
|
|
2810
|
+
`, isInline: true, styles: ["@layer kt-aaa.components{.kt-chip-listbox-field{display:flex;flex-direction:column;gap:.5rem}.kt-chip-listbox__legend{font-size:.875rem;font-weight:500;color:var(--field-label-color, currentColor)}.kt-chip-listbox__required{color:var(--kt-danger);margin-inline-start:.125rem}.kt-chip-listbox__options{display:flex;flex-wrap:wrap;gap:.5rem;outline:none}.kt-chip-listbox__hint{font-size:.75rem;color:var(--field-hint-color);margin:0}.kt-chip-listbox__error{font-size:.75rem;color:var(--field-error-color);min-block-size:1.25rem}.kt-chip-listbox__error-message{display:block}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2811
|
+
}
|
|
2812
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: KtChipListbox, decorators: [{
|
|
2813
|
+
type: Component,
|
|
2814
|
+
args: [{ selector: 'kt-chip-listbox', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
2815
|
+
class: 'kt-chip-listbox-container',
|
|
2816
|
+
'(keydown)': 'onKeydown($event)',
|
|
2817
|
+
'(focusin)': 'onFocusin($event)',
|
|
2818
|
+
}, template: `
|
|
2819
|
+
<div
|
|
2820
|
+
class="kt-chip-listbox-field"
|
|
2821
|
+
[class.kt-chip-listbox-field--invalid]="showInvalid()"
|
|
2822
|
+
[class.kt-chip-listbox-field--disabled]="disabled()"
|
|
2823
|
+
>
|
|
2824
|
+
@if (label(); as labelText) {
|
|
2825
|
+
<span [id]="labelId()" class="kt-chip-listbox__legend">
|
|
2826
|
+
{{ labelText }}
|
|
2827
|
+
@if (required()) {
|
|
2828
|
+
<span class="kt-chip-listbox__required" aria-hidden="true">*</span>
|
|
2829
|
+
}
|
|
2830
|
+
</span>
|
|
2831
|
+
}
|
|
2832
|
+
|
|
2833
|
+
<div
|
|
2834
|
+
class="kt-chip-listbox__options"
|
|
2835
|
+
role="listbox"
|
|
2836
|
+
[id]="baseId()"
|
|
2837
|
+
[attr.aria-multiselectable]="multiple() ? 'true' : null"
|
|
2838
|
+
[attr.aria-labelledby]="label() ? labelId() : null"
|
|
2839
|
+
[attr.aria-label]="!label() ? resolvedAriaLabel() : null"
|
|
2840
|
+
[attr.aria-describedby]="describedBy()"
|
|
2841
|
+
[attr.aria-required]="required() ? 'true' : null"
|
|
2842
|
+
[attr.aria-invalid]="showInvalid() ? 'true' : null"
|
|
2843
|
+
[attr.aria-disabled]="disabled() ? 'true' : null"
|
|
2844
|
+
>
|
|
2845
|
+
<ng-content />
|
|
2846
|
+
</div>
|
|
2847
|
+
|
|
2848
|
+
@if (hint() && !showInvalid()) {
|
|
2849
|
+
<p [id]="hintId()" class="kt-chip-listbox__hint">{{ hint() }}</p>
|
|
2850
|
+
}
|
|
2851
|
+
<div [id]="errorId()" class="kt-chip-listbox__error" aria-live="polite">
|
|
2852
|
+
@if (showInvalid()) {
|
|
2853
|
+
@for (error of displayedErrors(); track $index) {
|
|
2854
|
+
<span class="kt-chip-listbox__error-message">{{ error.message }}</span>
|
|
2855
|
+
}
|
|
2856
|
+
}
|
|
2857
|
+
</div>
|
|
2858
|
+
</div>
|
|
2859
|
+
`, styles: ["@layer kt-aaa.components{.kt-chip-listbox-field{display:flex;flex-direction:column;gap:.5rem}.kt-chip-listbox__legend{font-size:.875rem;font-weight:500;color:var(--field-label-color, currentColor)}.kt-chip-listbox__required{color:var(--kt-danger);margin-inline-start:.125rem}.kt-chip-listbox__options{display:flex;flex-wrap:wrap;gap:.5rem;outline:none}.kt-chip-listbox__hint{font-size:.75rem;color:var(--field-hint-color);margin:0}.kt-chip-listbox__error{font-size:.75rem;color:var(--field-error-color);min-block-size:1.25rem}.kt-chip-listbox__error-message{display:block}}\n"] }]
|
|
2860
|
+
}], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], dirty: [{ type: i0.Input, args: [{ isSignal: true, alias: "dirty", required: false }] }], pending: [{ type: i0.Input, args: [{ isSignal: true, alias: "pending", required: false }] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], errorMatcher: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMatcher", required: false }] }], showAllErrors: [{ type: i0.Input, args: [{ isSignal: true, alias: "showAllErrors", required: false }] }], compareWith: [{ type: i0.Input, args: [{ isSignal: true, alias: "compareWith", required: false }] }] } });
|
|
2861
|
+
|
|
2862
|
+
/**
|
|
2863
|
+
* Pilule individuelle (tag). Utilisable seule (tag statique), dans `kt-chip-list` ou dans `kt-chip-listbox`.
|
|
2574
2864
|
* Le label vient de la projection de contenu ; `removable` ajoute un bouton « retirer »
|
|
2575
2865
|
* (24px visibles, cible 44px via ::after — technique des boutons icon-only).
|
|
2576
2866
|
*
|
|
@@ -2582,6 +2872,7 @@ class ChipTransitionScope {
|
|
|
2582
2872
|
*/
|
|
2583
2873
|
class KtChip {
|
|
2584
2874
|
scope = inject(ChipTransitionScope, { optional: true });
|
|
2875
|
+
listbox = inject(forwardRef(() => KtChipListbox), { optional: true });
|
|
2585
2876
|
idGen = inject(KtIdGenerator);
|
|
2586
2877
|
/** Nom de View Transition propre au chip (détail interne, posé en host binding). */
|
|
2587
2878
|
viewTransitionName = `chip-${this.idGen.generateId('chip')}`;
|
|
@@ -2592,10 +2883,47 @@ class KtChip {
|
|
|
2592
2883
|
/** Libellé accessible du bouton « retirer » (inclure le nom de l'item : « Remove X »). @default 'Remove' */
|
|
2593
2884
|
removeLabel = input('Remove', /* @ts-ignore */
|
|
2594
2885
|
...(ngDevMode ? [{ debugName: "removeLabel" }] : /* istanbul ignore next */ []));
|
|
2886
|
+
/** État sélectionné unitaire (quand utilisé hors boîte de liste). @default false */
|
|
2887
|
+
checked = input(false, { ...(ngDevMode ? { debugName: "checked" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
2888
|
+
/** Valeur portée par la puce (utilisée au sein d'un groupe de sélection). */
|
|
2889
|
+
value = input(/* @ts-ignore */
|
|
2890
|
+
...(ngDevMode ? [undefined, { debugName: "value" }] : /* istanbul ignore next */ []));
|
|
2595
2891
|
/** Émis au clic sur le bouton « retirer » (le parent décide de retirer le chip). */
|
|
2596
2892
|
remove = output();
|
|
2893
|
+
initialRole;
|
|
2894
|
+
/** Rôle d'accessibilité calculé (préserve les rôles statiques comme listitem). */
|
|
2895
|
+
role = computed(() => {
|
|
2896
|
+
if (this.listbox) {
|
|
2897
|
+
return 'option';
|
|
2898
|
+
}
|
|
2899
|
+
return this.initialRole;
|
|
2900
|
+
}, /* @ts-ignore */
|
|
2901
|
+
...(ngDevMode ? [{ debugName: "role" }] : /* istanbul ignore next */ []));
|
|
2902
|
+
/** Signal consolidé de l'état de sélection (dérivé du parent listbox ou de l'input checked). */
|
|
2903
|
+
selected = computed(() => {
|
|
2904
|
+
if (this.listbox) {
|
|
2905
|
+
return this.listbox.isSelected(this.value());
|
|
2906
|
+
}
|
|
2907
|
+
return this.checked();
|
|
2908
|
+
}, /* @ts-ignore */
|
|
2909
|
+
...(ngDevMode ? [{ debugName: "selected" }] : /* istanbul ignore next */ []));
|
|
2597
2910
|
removeBtn = viewChild('removeBtn', /* @ts-ignore */
|
|
2598
2911
|
...(ngDevMode ? [{ debugName: "removeBtn" }] : /* istanbul ignore next */ []));
|
|
2912
|
+
constructor() {
|
|
2913
|
+
const el = inject(ElementRef);
|
|
2914
|
+
// Lit le rôle défini statiquement sur l'élément avant que les host bindings ne s'évaluent
|
|
2915
|
+
this.initialRole = el.nativeElement.getAttribute('role');
|
|
2916
|
+
el.nativeElement.addEventListener('click', (event) => {
|
|
2917
|
+
// Empêche le clic de basculer la sélection si on clique sur le bouton de retrait
|
|
2918
|
+
const target = event.target;
|
|
2919
|
+
if (target.closest('.kt-chip__remove')) {
|
|
2920
|
+
return;
|
|
2921
|
+
}
|
|
2922
|
+
if (this.listbox && !this.disabled() && !this.listbox.disabled() && !this.listbox.readonly()) {
|
|
2923
|
+
this.listbox.toggle(this.value());
|
|
2924
|
+
}
|
|
2925
|
+
});
|
|
2926
|
+
}
|
|
2599
2927
|
/**
|
|
2600
2928
|
* Focus programmatique du bouton « retirer ». Helper de coordination interne (focus management
|
|
2601
2929
|
* d'`kt-chip-list`), non destiné aux consommateurs.
|
|
@@ -2605,19 +2933,23 @@ class KtChip {
|
|
|
2605
2933
|
this.removeBtn()?.nativeElement.focus();
|
|
2606
2934
|
}
|
|
2607
2935
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: KtChip, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2608
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.1", type: KtChip, isStandalone: true, selector: "kt-chip", inputs: { removable: { classPropertyName: "removable", publicName: "removable", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, removeLabel: { classPropertyName: "removeLabel", publicName: "removeLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { remove: "remove" }, host: { properties: { "style.view-transition-name": "scope?.transitioning() ? viewTransitionName : null", "style.view-transition-class": "\"chip-transition\"" }, classAttribute: "kt-chip" }, viewQueries: [{ propertyName: "removeBtn", first: true, predicate: ["removeBtn"], descendants: true, isSignal: true }], ngImport: i0, template: "<span class=\"kt-chip__label\"><ng-content /></span>\n@if (removable()) {\n <button\n #removeBtn\n type=\"button\"\n class=\"kt-chip__remove\"\n [disabled]=\"disabled()\"\n [attr.aria-label]=\"removeLabel()\"\n (click)=\"remove.emit()\"\n >\n <span class=\"kt-chip__close-icon\" aria-hidden=\"true\">close</span>\n </button>\n}\n", styles: ["@layer kt-aaa.components{:host{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-size:var(--chip-font-size);color:var(--chip-color)}.kt-chip__label{max-inline-size:12rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kt-chip__remove{position:relative;display:inline-flex;align-items:center;justify-content:center;inline-size:24px;block-size:24px;padding:0;border:0;border-radius:50%;background:transparent;color:var(--chip-remove-color);cursor:pointer;font-size:.75rem;transition:var(--chip-remove-transition, background-color .15s ease)}.kt-chip__remove:after{content:\"\";position:absolute;inset:-10px}.kt-chip__remove:hover{background-color:var(--chip-remove-bg-hover);color:var(--chip-remove-color-hover)}:host(:hover){box-shadow:var(--chip-shadow-hover, var(--chip-shadow, none))}.kt-chip__remove:focus-visible{outline:2px solid var(--chip-focus-ring);outline-offset:1px}.kt-chip__remove:disabled{cursor:not-allowed;opacity:.5}.kt-chip__close-icon{font-family:Material Symbols Outlined;font-feature-settings:\"liga\";font-size:1rem;line-height:1;-webkit-font-smoothing:antialiased}@media(pointer:coarse){:host{min-block-size:32px}.kt-chip__remove{inline-size:28px;block-size:28px;font-size:.875rem}.kt-chip__remove:after{inset:-8px}}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2936
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.1", type: KtChip, isStandalone: true, selector: "kt-chip", inputs: { removable: { classPropertyName: "removable", publicName: "removable", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, removeLabel: { classPropertyName: "removeLabel", publicName: "removeLabel", isSignal: true, isRequired: false, transformFunction: null }, checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { remove: "remove" }, host: { properties: { "class.kt-chip--selected": "selected()", "attr.role": "role()", "attr.aria-selected": "listbox ? (selected() ? \"true\" : \"false\") : null", "attr.aria-disabled": "disabled() ? \"true\" : null", "style.view-transition-name": "scope?.transitioning() ? viewTransitionName : null", "style.view-transition-class": "\"chip-transition\"" }, classAttribute: "kt-chip" }, viewQueries: [{ propertyName: "removeBtn", first: true, predicate: ["removeBtn"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (selected()) {\n <span class=\"kt-chip__selected-icon\" aria-hidden=\"true\">check</span>\n}\n<span class=\"kt-chip__label\"><ng-content /></span>\n@if (removable()) {\n <button\n #removeBtn\n type=\"button\"\n class=\"kt-chip__remove\"\n [disabled]=\"disabled()\"\n [attr.aria-label]=\"removeLabel()\"\n (click)=\"remove.emit()\"\n >\n <span class=\"kt-chip__close-icon\" aria-hidden=\"true\">close</span>\n </button>\n}\n", styles: ["@layer kt-aaa.components{:host{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-size:var(--chip-font-size);color:var(--chip-color)}.kt-chip__label{max-inline-size:12rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kt-chip__remove{position:relative;display:inline-flex;align-items:center;justify-content:center;inline-size:24px;block-size:24px;padding:0;border:0;border-radius:50%;background:transparent;color:var(--chip-remove-color);cursor:pointer;font-size:.75rem;transition:var(--chip-remove-transition, background-color .15s ease)}.kt-chip__remove:after{content:\"\";position:absolute;inset:-10px}.kt-chip__remove:hover{background-color:var(--chip-remove-bg-hover);color:var(--chip-remove-color-hover)}:host(:hover){box-shadow:var(--chip-shadow-hover, var(--chip-shadow, none))}.kt-chip__remove:focus-visible{outline:2px solid var(--chip-focus-ring);outline-offset:1px}.kt-chip__remove:disabled{cursor:not-allowed;opacity:.5}.kt-chip__close-icon{font-family:Material Symbols Outlined;font-feature-settings:\"liga\";font-size:1rem;line-height:1;-webkit-font-smoothing:antialiased}@media(pointer:coarse){:host{min-block-size:32px}.kt-chip__remove{inline-size:28px;block-size:28px;font-size:.875rem}.kt-chip__remove:after{inset:-8px}}:host(.kt-chip--selected){background:var(--chip-selected-bg, var(--chip-bg-hover));border-color:var(--chip-selected-border, var(--chip-focus-ring));color:var(--chip-selected-color, var(--chip-color))}.kt-chip__selected-icon{font-family:Material Symbols Outlined;font-feature-settings:\"liga\";font-size:1rem;line-height:1;-webkit-font-smoothing:antialiased;margin-inline-end:.125rem}:host([role=\"option\"]){transition:background-color .15s ease,border-color .15s ease,color .15s ease,box-shadow .15s ease}:host([role=\"option\"]:not([aria-disabled=\"true\"])){cursor:pointer}:host([role=\"option\"]:not([aria-disabled=\"true\"]):hover){background-color:var(--chip-bg-hover);box-shadow:var(--chip-shadow-hover, var(--chip-shadow, none))}:host([role=\"option\"].kt-chip--selected:not([aria-disabled=\"true\"]):hover){background-color:color-mix(in srgb,var(--chip-selected-bg) 85%,var(--kt-primary))}:host([role=\"option\"]:focus-visible){outline:2px solid var(--chip-focus-ring);outline-offset:2px}:host([role=\"option\"][aria-disabled=\"true\"]){cursor:not-allowed;opacity:.5}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2609
2937
|
}
|
|
2610
2938
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: KtChip, decorators: [{
|
|
2611
2939
|
type: Component,
|
|
2612
2940
|
args: [{ selector: 'kt-chip', changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
2613
2941
|
class: 'kt-chip',
|
|
2942
|
+
'[class.kt-chip--selected]': 'selected()',
|
|
2943
|
+
'[attr.role]': 'role()',
|
|
2944
|
+
'[attr.aria-selected]': 'listbox ? (selected() ? "true" : "false") : null',
|
|
2945
|
+
'[attr.aria-disabled]': 'disabled() ? "true" : null',
|
|
2614
2946
|
// Nommé UNIQUEMENT pendant la transition de SA liste (cf. ChipTransitionScope) : un nom
|
|
2615
2947
|
// permanent ferait participer tous les chips de la page à chaque View Transition (glissement
|
|
2616
2948
|
// individuel au moindre reflow). Chip seul (hors liste) : jamais nommé.
|
|
2617
2949
|
'[style.view-transition-name]': 'scope?.transitioning() ? viewTransitionName : null',
|
|
2618
2950
|
'[style.view-transition-class]': '"chip-transition"',
|
|
2619
|
-
}, template: "<span class=\"kt-chip__label\"><ng-content /></span>\n@if (removable()) {\n <button\n #removeBtn\n type=\"button\"\n class=\"kt-chip__remove\"\n [disabled]=\"disabled()\"\n [attr.aria-label]=\"removeLabel()\"\n (click)=\"remove.emit()\"\n >\n <span class=\"kt-chip__close-icon\" aria-hidden=\"true\">close</span>\n </button>\n}\n", styles: ["@layer kt-aaa.components{:host{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-size:var(--chip-font-size);color:var(--chip-color)}.kt-chip__label{max-inline-size:12rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kt-chip__remove{position:relative;display:inline-flex;align-items:center;justify-content:center;inline-size:24px;block-size:24px;padding:0;border:0;border-radius:50%;background:transparent;color:var(--chip-remove-color);cursor:pointer;font-size:.75rem;transition:var(--chip-remove-transition, background-color .15s ease)}.kt-chip__remove:after{content:\"\";position:absolute;inset:-10px}.kt-chip__remove:hover{background-color:var(--chip-remove-bg-hover);color:var(--chip-remove-color-hover)}:host(:hover){box-shadow:var(--chip-shadow-hover, var(--chip-shadow, none))}.kt-chip__remove:focus-visible{outline:2px solid var(--chip-focus-ring);outline-offset:1px}.kt-chip__remove:disabled{cursor:not-allowed;opacity:.5}.kt-chip__close-icon{font-family:Material Symbols Outlined;font-feature-settings:\"liga\";font-size:1rem;line-height:1;-webkit-font-smoothing:antialiased}@media(pointer:coarse){:host{min-block-size:32px}.kt-chip__remove{inline-size:28px;block-size:28px;font-size:.875rem}.kt-chip__remove:after{inset:-8px}}}\n"] }]
|
|
2620
|
-
}], propDecorators: { removable: [{ type: i0.Input, args: [{ isSignal: true, alias: "removable", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], removeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "removeLabel", required: false }] }], remove: [{ type: i0.Output, args: ["remove"] }], removeBtn: [{ type: i0.ViewChild, args: ['removeBtn', { isSignal: true }] }] } });
|
|
2951
|
+
}, template: "@if (selected()) {\n <span class=\"kt-chip__selected-icon\" aria-hidden=\"true\">check</span>\n}\n<span class=\"kt-chip__label\"><ng-content /></span>\n@if (removable()) {\n <button\n #removeBtn\n type=\"button\"\n class=\"kt-chip__remove\"\n [disabled]=\"disabled()\"\n [attr.aria-label]=\"removeLabel()\"\n (click)=\"remove.emit()\"\n >\n <span class=\"kt-chip__close-icon\" aria-hidden=\"true\">close</span>\n </button>\n}\n", styles: ["@layer kt-aaa.components{:host{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-size:var(--chip-font-size);color:var(--chip-color)}.kt-chip__label{max-inline-size:12rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kt-chip__remove{position:relative;display:inline-flex;align-items:center;justify-content:center;inline-size:24px;block-size:24px;padding:0;border:0;border-radius:50%;background:transparent;color:var(--chip-remove-color);cursor:pointer;font-size:.75rem;transition:var(--chip-remove-transition, background-color .15s ease)}.kt-chip__remove:after{content:\"\";position:absolute;inset:-10px}.kt-chip__remove:hover{background-color:var(--chip-remove-bg-hover);color:var(--chip-remove-color-hover)}:host(:hover){box-shadow:var(--chip-shadow-hover, var(--chip-shadow, none))}.kt-chip__remove:focus-visible{outline:2px solid var(--chip-focus-ring);outline-offset:1px}.kt-chip__remove:disabled{cursor:not-allowed;opacity:.5}.kt-chip__close-icon{font-family:Material Symbols Outlined;font-feature-settings:\"liga\";font-size:1rem;line-height:1;-webkit-font-smoothing:antialiased}@media(pointer:coarse){:host{min-block-size:32px}.kt-chip__remove{inline-size:28px;block-size:28px;font-size:.875rem}.kt-chip__remove:after{inset:-8px}}:host(.kt-chip--selected){background:var(--chip-selected-bg, var(--chip-bg-hover));border-color:var(--chip-selected-border, var(--chip-focus-ring));color:var(--chip-selected-color, var(--chip-color))}.kt-chip__selected-icon{font-family:Material Symbols Outlined;font-feature-settings:\"liga\";font-size:1rem;line-height:1;-webkit-font-smoothing:antialiased;margin-inline-end:.125rem}:host([role=\"option\"]){transition:background-color .15s ease,border-color .15s ease,color .15s ease,box-shadow .15s ease}:host([role=\"option\"]:not([aria-disabled=\"true\"])){cursor:pointer}:host([role=\"option\"]:not([aria-disabled=\"true\"]):hover){background-color:var(--chip-bg-hover);box-shadow:var(--chip-shadow-hover, var(--chip-shadow, none))}:host([role=\"option\"].kt-chip--selected:not([aria-disabled=\"true\"]):hover){background-color:color-mix(in srgb,var(--chip-selected-bg) 85%,var(--kt-primary))}:host([role=\"option\"]:focus-visible){outline:2px solid var(--chip-focus-ring);outline-offset:2px}:host([role=\"option\"][aria-disabled=\"true\"]){cursor:not-allowed;opacity:.5}}\n"] }]
|
|
2952
|
+
}], ctorParameters: () => [], propDecorators: { removable: [{ type: i0.Input, args: [{ isSignal: true, alias: "removable", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], removeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "removeLabel", required: false }] }], checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], remove: [{ type: i0.Output, args: ["remove"] }], removeBtn: [{ type: i0.ViewChild, args: ['removeBtn', { isSignal: true }] }] } });
|
|
2621
2953
|
|
|
2622
2954
|
/** Template de rendu custom d'un chip dans `kt-chip-list`.
|
|
2623
2955
|
Structurellement compatible avec `MultiSelectChipContext` (forwardable).
|
|
@@ -2980,7 +3312,7 @@ class KtChipList {
|
|
|
2980
3312
|
this.activeIndex.set(index);
|
|
2981
3313
|
}
|
|
2982
3314
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: KtChipList, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
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 });
|
|
3315
|
+
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", "checked", "value"], outputs: ["remove"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2984
3316
|
}
|
|
2985
3317
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: KtChipList, decorators: [{
|
|
2986
3318
|
type: Component,
|
|
@@ -3779,5 +4111,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImpor
|
|
|
3779
4111
|
* Generated bundle index. Do not edit.
|
|
3780
4112
|
*/
|
|
3781
4113
|
|
|
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 };
|
|
4114
|
+
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, KtChipListbox, 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 };
|
|
3783
4115
|
//# sourceMappingURL=ktortu-aaa-forms.mjs.map
|