fold-ng 0.24.0 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3070,6 +3070,31 @@ class FoldInputComponent {
3070
3070
  /** Placeholder text. */
3071
3071
  placeholder = input("", /* @ts-ignore */
3072
3072
  ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
3073
+ /**
3074
+ * An icon drawn **inside the box, before the text** — a magnifier on a search
3075
+ * field, a currency mark on an amount.
3076
+ *
3077
+ * The input reserves the room itself, so the glyph never sits on the text.
3078
+ * Purely decorative: it is `aria-hidden`, and it never replaces a `label` or
3079
+ * an `ariaLabel` — an icon is not an accessible name.
3080
+ */
3081
+ leadingIcon = input(undefined, /* @ts-ignore */
3082
+ ...(ngDevMode ? [{ debugName: "leadingIcon" }] : /* istanbul ignore next */ []));
3083
+ /**
3084
+ * Show a trailing **clear** button while the field holds text.
3085
+ *
3086
+ * The affordance every search box grows by hand: a conditional `×` that empties
3087
+ * the value and gives the focus back, so typing can resume without a second
3088
+ * click. Off by default — a form field that clears itself invites the accident
3089
+ * it cannot undo.
3090
+ *
3091
+ * A `revealable` password wins the trailing slot: the two never make sense
3092
+ * together, and hiding the reveal would be the worse of the two losses.
3093
+ */
3094
+ clearable = input(false, { ...(ngDevMode ? { debugName: "clearable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
3095
+ /** Accessible name of the clear button. Override it to translate. */
3096
+ clearLabel = input("Clear", /* @ts-ignore */
3097
+ ...(ngDevMode ? [{ debugName: "clearLabel" }] : /* istanbul ignore next */ []));
3073
3098
  /** Render as read-only. Named `readOnly` (not `readonly`) to avoid the
3074
3099
  * signal-forms `FormField` reserved `readonly` field-state binding. */
3075
3100
  readOnly = input(false, /* @ts-ignore */
@@ -3094,6 +3119,9 @@ class FoldInputComponent {
3094
3119
  ...(ngDevMode ? [{ debugName: "autocomplete" }] : /* istanbul ignore next */ []));
3095
3120
  /** Unique, SSR-safe id for label association (see {@link FoldIdService}). */
3096
3121
  inputId = inject(FoldIdService).next("fold-input");
3122
+ /** The native control — the clear button hands the focus back to it. */
3123
+ field = viewChild("field", /* @ts-ignore */
3124
+ ...(ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []));
3097
3125
  /** The message to show under the field: the first error, once touched. */
3098
3126
  errorMessage = computed(() => {
3099
3127
  if (!this.touched()) {
@@ -3123,9 +3151,25 @@ class FoldInputComponent {
3123
3151
  /** The reveal control's accessible name, tracking its state. */
3124
3152
  revealAria = computed(() => this.revealed() ? this.hideLabel() : this.revealLabel(), /* @ts-ignore */
3125
3153
  ...(ngDevMode ? [{ debugName: "revealAria" }] : /* istanbul ignore next */ []));
3154
+ /**
3155
+ * Whether to render the clear button: asked for, something to clear, and a
3156
+ * field that can still be edited. A `×` over a read-only value would promise
3157
+ * a gesture the control refuses.
3158
+ */
3159
+ showClear = computed(() => this.clearable() &&
3160
+ this.value() !== "" &&
3161
+ !this.disabled() &&
3162
+ !this.readOnly() &&
3163
+ !this.showReveal(), /* @ts-ignore */
3164
+ ...(ngDevMode ? [{ debugName: "showClear" }] : /* istanbul ignore next */ []));
3126
3165
  toggleReveal() {
3127
3166
  this.revealed.update((shown) => !shown);
3128
3167
  }
3168
+ /** Empties the field and returns the focus, so typing resumes in place. */
3169
+ clear() {
3170
+ this.value.set("");
3171
+ this.field()?.nativeElement.focus();
3172
+ }
3129
3173
  /** Handles native input event. `value.set()` also fires the model's
3130
3174
  * auto `valueChange` output for standalone `(valueChange)` consumers. */
3131
3175
  onInputChange(event) {
@@ -3136,14 +3180,14 @@ class FoldInputComponent {
3136
3180
  this.touched.set(true);
3137
3181
  }
3138
3182
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FoldInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3139
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: FoldInputComponent, isStandalone: true, selector: "fold-input", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, revealable: { classPropertyName: "revealable", publicName: "revealable", isSignal: true, isRequired: false, transformFunction: null }, revealLabel: { classPropertyName: "revealLabel", publicName: "revealLabel", isSignal: true, isRequired: false, transformFunction: null }, hideLabel: { classPropertyName: "hideLabel", publicName: "hideLabel", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, optional: { classPropertyName: "optional", publicName: "optional", isSignal: true, isRequired: false, transformFunction: null }, optionalLabel: { classPropertyName: "optionalLabel", publicName: "optionalLabel", isSignal: true, isRequired: false, transformFunction: null }, info: { classPropertyName: "info", publicName: "info", isSignal: true, isRequired: false, transformFunction: null }, infoLabel: { classPropertyName: "infoLabel", publicName: "infoLabel", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, readOnly: { classPropertyName: "readOnly", publicName: "readOnly", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null }, autocomplete: { classPropertyName: "autocomplete", publicName: "autocomplete", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange" }, host: { properties: { "class": "size() + \" \" + align() + \" \" + variant()" } }, ngImport: i0, template: "<fold-input-base\n [label]=\"label()\"\n [for]=\"inputId\"\n [required]=\"required()\"\n [optional]=\"optional()\"\n [optionalLabel]=\"optionalLabel()\"\n [info]=\"info()\"\n [infoLabel]=\"infoLabel()\"\n [hint]=\"hint()\"\n [error]=\"errorMessage()\"\n>\n <div class=\"in-field\">\n <input\n [id]=\"inputId\"\n [class.has-reveal]=\"showReveal()\"\n [attr.type]=\"effectiveType()\"\n [attr.placeholder]=\"placeholder()\"\n [attr.readonly]=\"readOnly() || null\"\n [attr.disabled]=\"disabled() || null\"\n [attr.required]=\"required() || null\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.autocomplete]=\"autocomplete()\"\n [value]=\"value()\"\n (input)=\"onInputChange($event)\"\n (blur)=\"onBlur()\"\n />\n @if (showReveal()) {\n <button\n type=\"button\"\n class=\"in-reveal\"\n [attr.aria-label]=\"revealAria()\"\n [attr.aria-pressed]=\"revealed()\"\n [disabled]=\"disabled() || readOnly()\"\n (click)=\"toggleReveal()\"\n >\n <fold-icon\n [name]=\"revealed() ? 'eye-off' : 'eye'\"\n size=\"sm\"\n aria-hidden=\"true\"\n />\n </button>\n }\n </div>\n</fold-input-base>\n", styles: ["@charset \"UTF-8\";:host{display:block}input,select,textarea{all:unset;box-sizing:border-box;width:100%;font-family:inherit;color:var(--fold-color-text);background:var(--fold-color-surface-card);border:1px solid var(--fold-color-border-subtle);transition:border-color var(--fold-motion-fast),box-shadow var(--fold-motion-fast)}input::placeholder,select::placeholder,textarea::placeholder{color:var(--fold-color-text-faded)}input:hover:not(:disabled):not(:read-only):not(:focus),select:hover:not(:disabled):not(:read-only):not(:focus),textarea:hover:not(:disabled):not(:read-only):not(:focus){border-color:var(--fold-color-border)}input:focus,select:focus,textarea:focus{border-color:var(--fold-color-primary);box-shadow:0 0 0 2px var(--fold-color-primary-border)}input:disabled,select:disabled,textarea:disabled{opacity:.4;cursor:not-allowed}input:read-only,select:read-only,textarea:read-only{opacity:.6;cursor:default}input[type=number],select[type=number],textarea[type=number]{appearance:textfield;-moz-appearance:textfield}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button,select[type=number]::-webkit-inner-spin-button,select[type=number]::-webkit-outer-spin-button,textarea[type=number]::-webkit-inner-spin-button,textarea[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}:host(.sm) input,:host(.sm) select{height:1.75rem;font-size:var(--fold-text-sm);padding:.25rem .5rem;border-radius:var(--fold-radius-xs)}:host(.sm) textarea{font-size:var(--fold-text-sm);padding:.25rem .5rem;border-radius:var(--fold-radius-xs)}:host(.md) input,:host(.md) select{height:2.25rem;font-size:var(--fold-text-base);padding:.4rem .65rem;border-radius:var(--fold-radius-sm)}:host(.md) textarea{font-size:var(--fold-text-base);padding:.4rem .65rem;border-radius:var(--fold-radius-sm)}:host(.lg) input,:host(.lg) select{height:2.75rem;font-size:var(--fold-text-lg);padding:.5rem .75rem;border-radius:var(--fold-radius-sm)}:host(.lg) textarea{font-size:var(--fold-text-lg);padding:.5rem .75rem;border-radius:var(--fold-radius-sm)}:host(.center) input{text-align:center}:host(.panel) input,:host(.panel) select,:host(.panel) textarea{height:auto;padding:var(--fold-space-sm) var(--fold-space-sm);border-radius:var(--fold-radius-sm);background:var(--fold-color-surface-raised)}:host(.panel) input:focus,:host(.panel) select:focus,:host(.panel) textarea:focus{box-shadow:none}.in-field{position:relative}:host input.has-reveal{padding-inline-end:2.1rem}.in-reveal{all:unset;position:absolute;inset-inline-end:.4rem;top:50%;transform:translateY(-50%);display:grid;place-items:center;padding:.2rem;border-radius:var(--fold-radius-xs);color:var(--fold-color-text-muted);cursor:pointer}.in-reveal:hover:not(:disabled),.in-reveal:focus-visible{color:var(--fold-color-text);background:var(--fold-color-surface-hover)}.in-reveal:focus-visible{outline:2px solid var(--fold-color-primary-border);outline-offset:1px}.in-reveal:disabled{cursor:not-allowed;opacity:.4}@media(forced-colors:active){.in-reveal:focus-visible{outline-color:Highlight}}\n"], dependencies: [{ kind: "component", type: FoldInputBaseComponent, selector: "fold-input-base", inputs: ["label", "for", "required", "optional", "optionalLabel", "hint", "error", "info", "infoLabel"] }, { kind: "component", type: FoldIconComponent, selector: "fold-icon", inputs: ["name", "size", "tone", "title"] }] });
3183
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: FoldInputComponent, isStandalone: true, selector: "fold-input", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, revealable: { classPropertyName: "revealable", publicName: "revealable", isSignal: true, isRequired: false, transformFunction: null }, revealLabel: { classPropertyName: "revealLabel", publicName: "revealLabel", isSignal: true, isRequired: false, transformFunction: null }, hideLabel: { classPropertyName: "hideLabel", publicName: "hideLabel", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, optional: { classPropertyName: "optional", publicName: "optional", isSignal: true, isRequired: false, transformFunction: null }, optionalLabel: { classPropertyName: "optionalLabel", publicName: "optionalLabel", isSignal: true, isRequired: false, transformFunction: null }, info: { classPropertyName: "info", publicName: "info", isSignal: true, isRequired: false, transformFunction: null }, infoLabel: { classPropertyName: "infoLabel", publicName: "infoLabel", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, leadingIcon: { classPropertyName: "leadingIcon", publicName: "leadingIcon", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, clearLabel: { classPropertyName: "clearLabel", publicName: "clearLabel", isSignal: true, isRequired: false, transformFunction: null }, readOnly: { classPropertyName: "readOnly", publicName: "readOnly", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null }, autocomplete: { classPropertyName: "autocomplete", publicName: "autocomplete", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange" }, host: { properties: { "class": "size() + \" \" + align() + \" \" + variant()" } }, viewQueries: [{ propertyName: "field", first: true, predicate: ["field"], descendants: true, isSignal: true }], ngImport: i0, template: "<fold-input-base\n [label]=\"label()\"\n [for]=\"inputId\"\n [required]=\"required()\"\n [optional]=\"optional()\"\n [optionalLabel]=\"optionalLabel()\"\n [info]=\"info()\"\n [infoLabel]=\"infoLabel()\"\n [hint]=\"hint()\"\n [error]=\"errorMessage()\"\n>\n <div class=\"in-field\">\n @if (leadingIcon(); as glyph) {\n <fold-icon class=\"in-lead\" [name]=\"glyph\" size=\"sm\" aria-hidden=\"true\" />\n }\n <input\n #field\n [id]=\"inputId\"\n [class.has-lead]=\"leadingIcon() !== undefined\"\n [class.has-reveal]=\"showReveal() || showClear()\"\n [attr.type]=\"effectiveType()\"\n [attr.placeholder]=\"placeholder()\"\n [attr.readonly]=\"readOnly() || null\"\n [attr.disabled]=\"disabled() || null\"\n [attr.required]=\"required() || null\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.autocomplete]=\"autocomplete()\"\n [value]=\"value()\"\n (input)=\"onInputChange($event)\"\n (blur)=\"onBlur()\"\n />\n @if (showReveal()) {\n <button\n type=\"button\"\n class=\"in-reveal\"\n [attr.aria-label]=\"revealAria()\"\n [attr.aria-pressed]=\"revealed()\"\n [disabled]=\"disabled() || readOnly()\"\n (click)=\"toggleReveal()\"\n >\n <fold-icon\n [name]=\"revealed() ? 'eye-off' : 'eye'\"\n size=\"sm\"\n aria-hidden=\"true\"\n />\n </button>\n } @else if (showClear()) {\n <button\n type=\"button\"\n class=\"in-reveal\"\n [attr.aria-label]=\"clearLabel()\"\n (click)=\"clear()\"\n >\n <fold-icon name=\"close\" size=\"sm\" aria-hidden=\"true\" />\n </button>\n }\n </div>\n</fold-input-base>\n", styles: ["@charset \"UTF-8\";:host{display:block}input,select,textarea{all:unset;box-sizing:border-box;width:100%;font-family:inherit;color:var(--fold-color-text);background:var(--fold-color-surface-card);border:1px solid var(--fold-color-border-subtle);transition:border-color var(--fold-motion-fast),box-shadow var(--fold-motion-fast)}input::placeholder,select::placeholder,textarea::placeholder{color:var(--fold-color-text-faded)}input:hover:not(:disabled):not(:read-only):not(:focus),select:hover:not(:disabled):not(:read-only):not(:focus),textarea:hover:not(:disabled):not(:read-only):not(:focus){border-color:var(--fold-color-border)}input:focus,select:focus,textarea:focus{border-color:var(--fold-color-primary);box-shadow:0 0 0 2px var(--fold-color-primary-border)}input:disabled,select:disabled,textarea:disabled{opacity:.4;cursor:not-allowed}input:read-only,select:read-only,textarea:read-only{opacity:.6;cursor:default}input[type=number],select[type=number],textarea[type=number]{appearance:textfield;-moz-appearance:textfield}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button,select[type=number]::-webkit-inner-spin-button,select[type=number]::-webkit-outer-spin-button,textarea[type=number]::-webkit-inner-spin-button,textarea[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}:host(.sm) input,:host(.sm) select{height:1.75rem;font-size:var(--fold-text-sm);padding:.25rem .5rem;border-radius:var(--fold-radius-xs)}:host(.sm) textarea{font-size:var(--fold-text-sm);padding:.25rem .5rem;border-radius:var(--fold-radius-xs)}:host(.md) input,:host(.md) select{height:2.25rem;font-size:var(--fold-text-base);padding:.4rem .65rem;border-radius:var(--fold-radius-sm)}:host(.md) textarea{font-size:var(--fold-text-base);padding:.4rem .65rem;border-radius:var(--fold-radius-sm)}:host(.lg) input,:host(.lg) select{height:2.75rem;font-size:var(--fold-text-lg);padding:.5rem .75rem;border-radius:var(--fold-radius-sm)}:host(.lg) textarea{font-size:var(--fold-text-lg);padding:.5rem .75rem;border-radius:var(--fold-radius-sm)}:host(.center) input{text-align:center}:host(.panel) input,:host(.panel) select,:host(.panel) textarea{height:auto;padding:var(--fold-space-sm) var(--fold-space-sm);border-radius:var(--fold-radius-sm);background:var(--fold-color-surface-raised)}:host(.panel) input:focus,:host(.panel) select:focus,:host(.panel) textarea:focus{box-shadow:none}.in-field{position:relative}:host input.has-reveal{padding-inline-end:2.1rem}:host input.has-lead{padding-inline-start:2.1rem}.in-lead{position:absolute;inset-inline-start:.6rem;top:50%;transform:translateY(-50%);display:grid;place-items:center;color:var(--fold-color-text-muted);pointer-events:none}.in-reveal{all:unset;position:absolute;inset-inline-end:.4rem;top:50%;transform:translateY(-50%);display:grid;place-items:center;padding:.2rem;border-radius:var(--fold-radius-xs);color:var(--fold-color-text-muted);cursor:pointer}.in-reveal:hover:not(:disabled),.in-reveal:focus-visible{color:var(--fold-color-text);background:var(--fold-color-surface-hover)}.in-reveal:focus-visible{outline:2px solid var(--fold-color-primary-border);outline-offset:1px}.in-reveal:disabled{cursor:not-allowed;opacity:.4}@media(forced-colors:active){.in-reveal:focus-visible{outline-color:Highlight}}\n"], dependencies: [{ kind: "component", type: FoldInputBaseComponent, selector: "fold-input-base", inputs: ["label", "for", "required", "optional", "optionalLabel", "hint", "error", "info", "infoLabel"] }, { kind: "component", type: FoldIconComponent, selector: "fold-icon", inputs: ["name", "size", "tone", "title"] }] });
3140
3184
  }
3141
3185
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FoldInputComponent, decorators: [{
3142
3186
  type: Component,
3143
3187
  args: [{ selector: "fold-input", standalone: true, imports: [FoldInputBaseComponent, FoldIconComponent], host: {
3144
3188
  "[class]": 'size() + " " + align() + " " + variant()',
3145
- }, template: "<fold-input-base\n [label]=\"label()\"\n [for]=\"inputId\"\n [required]=\"required()\"\n [optional]=\"optional()\"\n [optionalLabel]=\"optionalLabel()\"\n [info]=\"info()\"\n [infoLabel]=\"infoLabel()\"\n [hint]=\"hint()\"\n [error]=\"errorMessage()\"\n>\n <div class=\"in-field\">\n <input\n [id]=\"inputId\"\n [class.has-reveal]=\"showReveal()\"\n [attr.type]=\"effectiveType()\"\n [attr.placeholder]=\"placeholder()\"\n [attr.readonly]=\"readOnly() || null\"\n [attr.disabled]=\"disabled() || null\"\n [attr.required]=\"required() || null\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.autocomplete]=\"autocomplete()\"\n [value]=\"value()\"\n (input)=\"onInputChange($event)\"\n (blur)=\"onBlur()\"\n />\n @if (showReveal()) {\n <button\n type=\"button\"\n class=\"in-reveal\"\n [attr.aria-label]=\"revealAria()\"\n [attr.aria-pressed]=\"revealed()\"\n [disabled]=\"disabled() || readOnly()\"\n (click)=\"toggleReveal()\"\n >\n <fold-icon\n [name]=\"revealed() ? 'eye-off' : 'eye'\"\n size=\"sm\"\n aria-hidden=\"true\"\n />\n </button>\n }\n </div>\n</fold-input-base>\n", styles: ["@charset \"UTF-8\";:host{display:block}input,select,textarea{all:unset;box-sizing:border-box;width:100%;font-family:inherit;color:var(--fold-color-text);background:var(--fold-color-surface-card);border:1px solid var(--fold-color-border-subtle);transition:border-color var(--fold-motion-fast),box-shadow var(--fold-motion-fast)}input::placeholder,select::placeholder,textarea::placeholder{color:var(--fold-color-text-faded)}input:hover:not(:disabled):not(:read-only):not(:focus),select:hover:not(:disabled):not(:read-only):not(:focus),textarea:hover:not(:disabled):not(:read-only):not(:focus){border-color:var(--fold-color-border)}input:focus,select:focus,textarea:focus{border-color:var(--fold-color-primary);box-shadow:0 0 0 2px var(--fold-color-primary-border)}input:disabled,select:disabled,textarea:disabled{opacity:.4;cursor:not-allowed}input:read-only,select:read-only,textarea:read-only{opacity:.6;cursor:default}input[type=number],select[type=number],textarea[type=number]{appearance:textfield;-moz-appearance:textfield}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button,select[type=number]::-webkit-inner-spin-button,select[type=number]::-webkit-outer-spin-button,textarea[type=number]::-webkit-inner-spin-button,textarea[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}:host(.sm) input,:host(.sm) select{height:1.75rem;font-size:var(--fold-text-sm);padding:.25rem .5rem;border-radius:var(--fold-radius-xs)}:host(.sm) textarea{font-size:var(--fold-text-sm);padding:.25rem .5rem;border-radius:var(--fold-radius-xs)}:host(.md) input,:host(.md) select{height:2.25rem;font-size:var(--fold-text-base);padding:.4rem .65rem;border-radius:var(--fold-radius-sm)}:host(.md) textarea{font-size:var(--fold-text-base);padding:.4rem .65rem;border-radius:var(--fold-radius-sm)}:host(.lg) input,:host(.lg) select{height:2.75rem;font-size:var(--fold-text-lg);padding:.5rem .75rem;border-radius:var(--fold-radius-sm)}:host(.lg) textarea{font-size:var(--fold-text-lg);padding:.5rem .75rem;border-radius:var(--fold-radius-sm)}:host(.center) input{text-align:center}:host(.panel) input,:host(.panel) select,:host(.panel) textarea{height:auto;padding:var(--fold-space-sm) var(--fold-space-sm);border-radius:var(--fold-radius-sm);background:var(--fold-color-surface-raised)}:host(.panel) input:focus,:host(.panel) select:focus,:host(.panel) textarea:focus{box-shadow:none}.in-field{position:relative}:host input.has-reveal{padding-inline-end:2.1rem}.in-reveal{all:unset;position:absolute;inset-inline-end:.4rem;top:50%;transform:translateY(-50%);display:grid;place-items:center;padding:.2rem;border-radius:var(--fold-radius-xs);color:var(--fold-color-text-muted);cursor:pointer}.in-reveal:hover:not(:disabled),.in-reveal:focus-visible{color:var(--fold-color-text);background:var(--fold-color-surface-hover)}.in-reveal:focus-visible{outline:2px solid var(--fold-color-primary-border);outline-offset:1px}.in-reveal:disabled{cursor:not-allowed;opacity:.4}@media(forced-colors:active){.in-reveal:focus-visible{outline-color:Highlight}}\n"] }]
3146
- }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], revealable: [{ type: i0.Input, args: [{ isSignal: true, alias: "revealable", required: false }] }], revealLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "revealLabel", required: false }] }], hideLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideLabel", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], optional: [{ type: i0.Input, args: [{ isSignal: true, alias: "optional", required: false }] }], optionalLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionalLabel", required: false }] }], info: [{ type: i0.Input, args: [{ isSignal: true, alias: "info", required: false }] }], infoLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "infoLabel", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], readOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readOnly", required: false }] }], autofocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "autofocus", required: false }] }], autocomplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocomplete", required: false }] }] } });
3189
+ }, template: "<fold-input-base\n [label]=\"label()\"\n [for]=\"inputId\"\n [required]=\"required()\"\n [optional]=\"optional()\"\n [optionalLabel]=\"optionalLabel()\"\n [info]=\"info()\"\n [infoLabel]=\"infoLabel()\"\n [hint]=\"hint()\"\n [error]=\"errorMessage()\"\n>\n <div class=\"in-field\">\n @if (leadingIcon(); as glyph) {\n <fold-icon class=\"in-lead\" [name]=\"glyph\" size=\"sm\" aria-hidden=\"true\" />\n }\n <input\n #field\n [id]=\"inputId\"\n [class.has-lead]=\"leadingIcon() !== undefined\"\n [class.has-reveal]=\"showReveal() || showClear()\"\n [attr.type]=\"effectiveType()\"\n [attr.placeholder]=\"placeholder()\"\n [attr.readonly]=\"readOnly() || null\"\n [attr.disabled]=\"disabled() || null\"\n [attr.required]=\"required() || null\"\n [attr.aria-invalid]=\"errorMessage() ? true : null\"\n [attr.aria-describedby]=\"describedBy()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.autocomplete]=\"autocomplete()\"\n [value]=\"value()\"\n (input)=\"onInputChange($event)\"\n (blur)=\"onBlur()\"\n />\n @if (showReveal()) {\n <button\n type=\"button\"\n class=\"in-reveal\"\n [attr.aria-label]=\"revealAria()\"\n [attr.aria-pressed]=\"revealed()\"\n [disabled]=\"disabled() || readOnly()\"\n (click)=\"toggleReveal()\"\n >\n <fold-icon\n [name]=\"revealed() ? 'eye-off' : 'eye'\"\n size=\"sm\"\n aria-hidden=\"true\"\n />\n </button>\n } @else if (showClear()) {\n <button\n type=\"button\"\n class=\"in-reveal\"\n [attr.aria-label]=\"clearLabel()\"\n (click)=\"clear()\"\n >\n <fold-icon name=\"close\" size=\"sm\" aria-hidden=\"true\" />\n </button>\n }\n </div>\n</fold-input-base>\n", styles: ["@charset \"UTF-8\";:host{display:block}input,select,textarea{all:unset;box-sizing:border-box;width:100%;font-family:inherit;color:var(--fold-color-text);background:var(--fold-color-surface-card);border:1px solid var(--fold-color-border-subtle);transition:border-color var(--fold-motion-fast),box-shadow var(--fold-motion-fast)}input::placeholder,select::placeholder,textarea::placeholder{color:var(--fold-color-text-faded)}input:hover:not(:disabled):not(:read-only):not(:focus),select:hover:not(:disabled):not(:read-only):not(:focus),textarea:hover:not(:disabled):not(:read-only):not(:focus){border-color:var(--fold-color-border)}input:focus,select:focus,textarea:focus{border-color:var(--fold-color-primary);box-shadow:0 0 0 2px var(--fold-color-primary-border)}input:disabled,select:disabled,textarea:disabled{opacity:.4;cursor:not-allowed}input:read-only,select:read-only,textarea:read-only{opacity:.6;cursor:default}input[type=number],select[type=number],textarea[type=number]{appearance:textfield;-moz-appearance:textfield}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button,select[type=number]::-webkit-inner-spin-button,select[type=number]::-webkit-outer-spin-button,textarea[type=number]::-webkit-inner-spin-button,textarea[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}:host(.sm) input,:host(.sm) select{height:1.75rem;font-size:var(--fold-text-sm);padding:.25rem .5rem;border-radius:var(--fold-radius-xs)}:host(.sm) textarea{font-size:var(--fold-text-sm);padding:.25rem .5rem;border-radius:var(--fold-radius-xs)}:host(.md) input,:host(.md) select{height:2.25rem;font-size:var(--fold-text-base);padding:.4rem .65rem;border-radius:var(--fold-radius-sm)}:host(.md) textarea{font-size:var(--fold-text-base);padding:.4rem .65rem;border-radius:var(--fold-radius-sm)}:host(.lg) input,:host(.lg) select{height:2.75rem;font-size:var(--fold-text-lg);padding:.5rem .75rem;border-radius:var(--fold-radius-sm)}:host(.lg) textarea{font-size:var(--fold-text-lg);padding:.5rem .75rem;border-radius:var(--fold-radius-sm)}:host(.center) input{text-align:center}:host(.panel) input,:host(.panel) select,:host(.panel) textarea{height:auto;padding:var(--fold-space-sm) var(--fold-space-sm);border-radius:var(--fold-radius-sm);background:var(--fold-color-surface-raised)}:host(.panel) input:focus,:host(.panel) select:focus,:host(.panel) textarea:focus{box-shadow:none}.in-field{position:relative}:host input.has-reveal{padding-inline-end:2.1rem}:host input.has-lead{padding-inline-start:2.1rem}.in-lead{position:absolute;inset-inline-start:.6rem;top:50%;transform:translateY(-50%);display:grid;place-items:center;color:var(--fold-color-text-muted);pointer-events:none}.in-reveal{all:unset;position:absolute;inset-inline-end:.4rem;top:50%;transform:translateY(-50%);display:grid;place-items:center;padding:.2rem;border-radius:var(--fold-radius-xs);color:var(--fold-color-text-muted);cursor:pointer}.in-reveal:hover:not(:disabled),.in-reveal:focus-visible{color:var(--fold-color-text);background:var(--fold-color-surface-hover)}.in-reveal:focus-visible{outline:2px solid var(--fold-color-primary-border);outline-offset:1px}.in-reveal:disabled{cursor:not-allowed;opacity:.4}@media(forced-colors:active){.in-reveal:focus-visible{outline-color:Highlight}}\n"] }]
3190
+ }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], revealable: [{ type: i0.Input, args: [{ isSignal: true, alias: "revealable", required: false }] }], revealLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "revealLabel", required: false }] }], hideLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideLabel", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], optional: [{ type: i0.Input, args: [{ isSignal: true, alias: "optional", required: false }] }], optionalLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionalLabel", required: false }] }], info: [{ type: i0.Input, args: [{ isSignal: true, alias: "info", required: false }] }], infoLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "infoLabel", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], leadingIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "leadingIcon", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], clearLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearLabel", required: false }] }], readOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readOnly", required: false }] }], autofocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "autofocus", required: false }] }], autocomplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocomplete", required: false }] }], field: [{ type: i0.ViewChild, args: ["field", { isSignal: true }] }] } });
3147
3191
 
3148
3192
  /** The English defaults — the base every override merges onto. */
3149
3193
  const FOLD_INLINE_CONFIRM_DEFAULT_LABELS = {
@@ -3386,7 +3430,7 @@ class FoldInlineConfirmComponent {
3386
3430
  this.cancelled.emit();
3387
3431
  }
3388
3432
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FoldInlineConfirmComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3389
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: FoldInlineConfirmComponent, isStandalone: true, selector: "fold-inline-confirm", inputs: { intent: { classPropertyName: "intent", publicName: "intent", isSignal: true, isRequired: false, transformFunction: null }, message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: false, transformFunction: null }, match: { classPropertyName: "match", publicName: "match", isSignal: true, isRequired: false, transformFunction: null }, password: { classPropertyName: "password", publicName: "password", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, confirmIcon: { classPropertyName: "confirmIcon", publicName: "confirmIcon", isSignal: true, isRequired: false, transformFunction: null }, cancelIcon: { classPropertyName: "cancelIcon", publicName: "cancelIcon", isSignal: true, isRequired: false, transformFunction: null }, keepOpenOnConfirm: { classPropertyName: "keepOpenOnConfirm", publicName: "keepOpenOnConfirm", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { confirmed: "confirmed", cancelled: "cancelled", open: "openChange" }, host: { properties: { "class.is-open": "open()" } }, viewQueries: [{ propertyName: "triggerEl", first: true, predicate: ["triggerWrap"], descendants: true, isSignal: true }, { propertyName: "groupEl", first: true, predicate: ["groupEl"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (!open()) {\n <!-- Idle: the host's projected trigger. A click anywhere in it starts the\n flow; the trigger itself stays a real focusable control (button / anchor),\n so keyboard activation is native (Enter/Space \u2192 click) \u2014 no extra\n role/tabindex, and no keydown handler that would double-fire. -->\n <span #triggerWrap class=\"fic-trigger\" (click)=\"activate()\">\n <ng-content />\n </span>\n} @else {\n <div\n #groupEl\n class=\"fic-confirm\"\n role=\"group\"\n [attr.aria-label]=\"l().group\"\n (keydown.escape)=\"cancel(); $event.stopPropagation()\"\n >\n @if (message(); as text) {\n <p class=\"fic-message\" [id]=\"msgId\">{{ text }}</p>\n }\n\n @if (needsInput()) {\n <fold-input\n class=\"fic-field\"\n [label]=\"prompt()\"\n [type]=\"fieldType()\"\n [size]=\"size() === 'lg' ? 'lg' : 'sm'\"\n [placeholder]=\"placeholder() ?? ''\"\n [autocomplete]=\"password() ? 'current-password' : 'off'\"\n [(value)]=\"typed\"\n (keydown.enter)=\"confirm()\"\n />\n }\n\n <div class=\"fic-actions\">\n <button\n foldButton\n emphasis=\"solid\"\n [intent]=\"intent()\"\n [size]=\"size()\"\n [icon]=\"confirmIcon()\"\n [disabled]=\"!canConfirm()\"\n [attr.aria-describedby]=\"message() ? msgId : null\"\n (click)=\"confirm()\"\n >\n {{ loading() ? l().busy : l().confirm }}\n </button>\n\n @if (cancelIcon(); as icon) {\n <fold-button-icon\n [icon]=\"icon\"\n tone=\"ghost\"\n [size]=\"size()\"\n [disabled]=\"loading()\"\n [tooltip]=\"l().cancelAria\"\n (clicked)=\"cancel()\"\n />\n } @else {\n <button\n foldButton\n emphasis=\"soft\"\n intent=\"neutral\"\n [size]=\"size()\"\n [disabled]=\"loading()\"\n (click)=\"cancel()\"\n >\n {{ l().cancel }}\n </button>\n }\n </div>\n </div>\n}\n", styles: [":host{display:inline-flex;align-items:center;min-width:0}.fic-trigger{display:contents}.fic-confirm{display:inline-flex;flex-direction:column;gap:var(--fold-space-sm);min-width:0;animation:fic-in var(--fold-motion-fast)}.fic-message{margin:0;font-size:var(--fold-text-xs);line-height:var(--fold-leading-normal);color:var(--fold-color-text-secondary)}.fic-field{display:block;width:15rem;max-width:100%}.fic-actions{display:inline-flex;align-items:center;gap:var(--fold-space-xs)}@keyframes fic-in{0%{opacity:0;transform:translateY(-2px)}to{opacity:1;transform:none}}@media(prefers-reduced-motion:reduce){.fic-confirm{animation:none}}\n"], dependencies: [{ kind: "component", type: FoldButtonComponent, selector: "button[foldButton], a[foldButton]", inputs: ["emphasis", "intent", "size", "shape", "block", "icon", "iconTrailing", "type", "disabled", "loading"] }, { kind: "component", type: FoldButtonIconComponent, selector: "fold-button-icon", inputs: ["icon", "shape", "size", "tone", "disabled", "loading", "tooltip", "type"], outputs: ["clicked"] }, { kind: "component", type: FoldInputComponent, selector: "fold-input", inputs: ["value", "disabled", "touched", "errors", "type", "revealable", "revealLabel", "hideLabel", "size", "align", "variant", "label", "required", "optional", "optionalLabel", "info", "infoLabel", "ariaLabel", "hint", "placeholder", "readOnly", "autofocus", "autocomplete"], outputs: ["valueChange", "touchedChange"] }] });
3433
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: FoldInlineConfirmComponent, isStandalone: true, selector: "fold-inline-confirm", inputs: { intent: { classPropertyName: "intent", publicName: "intent", isSignal: true, isRequired: false, transformFunction: null }, message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: false, transformFunction: null }, match: { classPropertyName: "match", publicName: "match", isSignal: true, isRequired: false, transformFunction: null }, password: { classPropertyName: "password", publicName: "password", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, confirmIcon: { classPropertyName: "confirmIcon", publicName: "confirmIcon", isSignal: true, isRequired: false, transformFunction: null }, cancelIcon: { classPropertyName: "cancelIcon", publicName: "cancelIcon", isSignal: true, isRequired: false, transformFunction: null }, keepOpenOnConfirm: { classPropertyName: "keepOpenOnConfirm", publicName: "keepOpenOnConfirm", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { confirmed: "confirmed", cancelled: "cancelled", open: "openChange" }, host: { properties: { "class.is-open": "open()" } }, viewQueries: [{ propertyName: "triggerEl", first: true, predicate: ["triggerWrap"], descendants: true, isSignal: true }, { propertyName: "groupEl", first: true, predicate: ["groupEl"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (!open()) {\n <!-- Idle: the host's projected trigger. A click anywhere in it starts the\n flow; the trigger itself stays a real focusable control (button / anchor),\n so keyboard activation is native (Enter/Space \u2192 click) \u2014 no extra\n role/tabindex, and no keydown handler that would double-fire. -->\n <span #triggerWrap class=\"fic-trigger\" (click)=\"activate()\">\n <ng-content />\n </span>\n} @else {\n <div\n #groupEl\n class=\"fic-confirm\"\n role=\"group\"\n [attr.aria-label]=\"l().group\"\n (keydown.escape)=\"cancel(); $event.stopPropagation()\"\n >\n @if (message(); as text) {\n <p class=\"fic-message\" [id]=\"msgId\">{{ text }}</p>\n }\n\n @if (needsInput()) {\n <fold-input\n class=\"fic-field\"\n [label]=\"prompt()\"\n [type]=\"fieldType()\"\n [size]=\"size() === 'lg' ? 'lg' : 'sm'\"\n [placeholder]=\"placeholder() ?? ''\"\n [autocomplete]=\"password() ? 'current-password' : 'off'\"\n [(value)]=\"typed\"\n (keydown.enter)=\"confirm()\"\n />\n }\n\n <div class=\"fic-actions\">\n <button\n foldButton\n emphasis=\"solid\"\n [intent]=\"intent()\"\n [size]=\"size()\"\n [icon]=\"confirmIcon()\"\n [disabled]=\"!canConfirm()\"\n [attr.aria-describedby]=\"message() ? msgId : null\"\n (click)=\"confirm()\"\n >\n {{ loading() ? l().busy : l().confirm }}\n </button>\n\n @if (cancelIcon(); as icon) {\n <fold-button-icon\n [icon]=\"icon\"\n tone=\"ghost\"\n [size]=\"size()\"\n [disabled]=\"loading()\"\n [tooltip]=\"l().cancelAria\"\n (clicked)=\"cancel()\"\n />\n } @else {\n <button\n foldButton\n emphasis=\"soft\"\n intent=\"neutral\"\n [size]=\"size()\"\n [disabled]=\"loading()\"\n (click)=\"cancel()\"\n >\n {{ l().cancel }}\n </button>\n }\n </div>\n </div>\n}\n", styles: [":host{display:inline-flex;align-items:center;min-width:0}.fic-trigger{display:contents}.fic-confirm{display:inline-flex;flex-direction:column;gap:var(--fold-space-sm);min-width:0;animation:fic-in var(--fold-motion-fast)}.fic-message{margin:0;font-size:var(--fold-text-xs);line-height:var(--fold-leading-normal);color:var(--fold-color-text-secondary)}.fic-field{display:block;width:15rem;max-width:100%}.fic-actions{display:inline-flex;align-items:center;gap:var(--fold-space-xs)}@keyframes fic-in{0%{opacity:0;transform:translateY(-2px)}to{opacity:1;transform:none}}@media(prefers-reduced-motion:reduce){.fic-confirm{animation:none}}\n"], dependencies: [{ kind: "component", type: FoldButtonComponent, selector: "button[foldButton], a[foldButton]", inputs: ["emphasis", "intent", "size", "shape", "block", "icon", "iconTrailing", "type", "disabled", "loading"] }, { kind: "component", type: FoldButtonIconComponent, selector: "fold-button-icon", inputs: ["icon", "shape", "size", "tone", "disabled", "loading", "tooltip", "type"], outputs: ["clicked"] }, { kind: "component", type: FoldInputComponent, selector: "fold-input", inputs: ["value", "disabled", "touched", "errors", "type", "revealable", "revealLabel", "hideLabel", "size", "align", "variant", "label", "required", "optional", "optionalLabel", "info", "infoLabel", "ariaLabel", "hint", "placeholder", "leadingIcon", "clearable", "clearLabel", "readOnly", "autofocus", "autocomplete"], outputs: ["valueChange", "touchedChange"] }] });
3390
3434
  }
3391
3435
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FoldInlineConfirmComponent, decorators: [{
3392
3436
  type: Component,
@@ -5258,6 +5302,47 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
5258
5302
  args: [{ selector: "ng-template[foldRowDetail]", standalone: true }]
5259
5303
  }] });
5260
5304
 
5305
+ /**
5306
+ * Marks the `<ng-template>` that renders a row's **note** — a full-width line
5307
+ * that sits under its row and is **always visible**:
5308
+ *
5309
+ * ```html
5310
+ * <fold-data-table [rowNote]="isLate" …>
5311
+ * <ng-template foldRowNote let-row let-i="index">
5312
+ * <fold-callout variant="warning">…</fold-callout>
5313
+ * </ng-template>
5314
+ * </fold-data-table>
5315
+ * ```
5316
+ *
5317
+ * The template context is `{ $implicit: row, index }`.
5318
+ *
5319
+ * **A note is not a drawer.** {@link FoldDataTableRowDetailDirective} hides
5320
+ * something until asked and grows a toggle column to ask with; a note hides
5321
+ * nothing, so there is nothing to reveal, no chevron, and no `aria-expanded`.
5322
+ * Reach for a note when the row's own cells cannot hold what must be read at
5323
+ * the same moment as the row — a warning that comes with the action answering
5324
+ * it, a refusal and its reason.
5325
+ *
5326
+ * 🔴 **It takes TWO halves, and the second is not ceremony.** The template says
5327
+ * *what* a note looks like; the `rowNote` predicate says *which* rows have one.
5328
+ * Without the predicate every row would emit a `<tr>` — empty for most of them,
5329
+ * and an empty row is not invisible: a screen reader walks into it and
5330
+ * announces a blank line per record. The predicate is what keeps the table
5331
+ * honest about how many rows it has.
5332
+ *
5333
+ * As with cell templates, `let-row` is untyped by design — annotate through the
5334
+ * parent component's typed helpers.
5335
+ */
5336
+ class FoldDataTableRowNoteDirective {
5337
+ template = inject(TemplateRef);
5338
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FoldDataTableRowNoteDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
5339
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.8", type: FoldDataTableRowNoteDirective, isStandalone: true, selector: "ng-template[foldRowNote]", ngImport: i0 });
5340
+ }
5341
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FoldDataTableRowNoteDirective, decorators: [{
5342
+ type: Directive,
5343
+ args: [{ selector: "ng-template[foldRowNote]", standalone: true }]
5344
+ }] });
5345
+
5261
5346
  /**
5262
5347
  * Roving-tabindex DOM helpers for `fold-data-table` body rows — pure functions
5263
5348
  * that move focus between `<tr>` siblings, so the component's keydown handler
@@ -5537,6 +5622,16 @@ class FoldDataTableComponent {
5537
5622
  /** Optional per-row semantic tone (left accent + tint). */
5538
5623
  rowTone = input(/* @ts-ignore */
5539
5624
  ...(ngDevMode ? [undefined, { debugName: "rowTone" }] : /* istanbul ignore next */ []));
5625
+ /**
5626
+ * Which rows carry a **note** — the always-visible line a `foldRowNote`
5627
+ * template draws beneath its row.
5628
+ *
5629
+ * Both halves are required for anything to render: this says *which* rows,
5630
+ * the template says *what*. See {@link FoldDataTableRowNoteDirective} for why
5631
+ * a row without a note must emit no `<tr>` at all.
5632
+ */
5633
+ rowNote = input(/* @ts-ignore */
5634
+ ...(ngDevMode ? [undefined, { debugName: "rowNote" }] : /* istanbul ignore next */ []));
5540
5635
  sort = input(null, /* @ts-ignore */
5541
5636
  ...(ngDevMode ? [{ debugName: "sort" }] : /* istanbul ignore next */ []));
5542
5637
  empty = input(/* @ts-ignore */
@@ -5705,6 +5800,11 @@ class FoldDataTableComponent {
5705
5800
  return map;
5706
5801
  }, /* @ts-ignore */
5707
5802
  ...(ngDevMode ? [{ debugName: "cellMap" }] : /* istanbul ignore next */ []));
5803
+ rowNoteTpl = contentChild(FoldDataTableRowNoteDirective, /* @ts-ignore */
5804
+ ...(ngDevMode ? [{ debugName: "rowNoteTpl" }] : /* istanbul ignore next */ []));
5805
+ /** The note template, or `null`. Paired with `rowNote` to decide each row. */
5806
+ rowNoteTemplate = computed(() => this.rowNoteTpl()?.template ?? null, /* @ts-ignore */
5807
+ ...(ngDevMode ? [{ debugName: "rowNoteTemplate" }] : /* istanbul ignore next */ []));
5708
5808
  rowDetail = contentChild(FoldDataTableRowDetailDirective, /* @ts-ignore */
5709
5809
  ...(ngDevMode ? [{ debugName: "rowDetail" }] : /* istanbul ignore next */ []));
5710
5810
  /** The drawer template, or `null`. Its PRESENCE is the feature switch. */
@@ -5830,6 +5930,14 @@ class FoldDataTableComponent {
5830
5930
  toneOf(row) {
5831
5931
  return this.rowTone()?.(row) ?? null;
5832
5932
  }
5933
+ /**
5934
+ * Does this row draw a note? Both halves must be there — the template and the
5935
+ * predicate. Either alone renders nothing, which is the quiet behaviour a
5936
+ * half-wired table should have.
5937
+ */
5938
+ hasNote(row, index) {
5939
+ return (this.rowNoteTemplate() !== null && (this.rowNote()?.(row, index) ?? false));
5940
+ }
5833
5941
  isSorted(key) {
5834
5942
  return this.sort()?.key === key;
5835
5943
  }
@@ -5943,7 +6051,7 @@ class FoldDataTableComponent {
5943
6051
  }
5944
6052
  }
5945
6053
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FoldDataTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5946
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: FoldDataTableComponent, isStandalone: true, selector: "fold-data-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: true, transformFunction: null }, rowKey: { classPropertyName: "rowKey", publicName: "rowKey", isSignal: true, isRequired: false, transformFunction: null }, rowTone: { classPropertyName: "rowTone", publicName: "rowTone", isSignal: true, isRequired: false, transformFunction: null }, sort: { classPropertyName: "sort", publicName: "sort", isSignal: true, isRequired: false, transformFunction: null }, empty: { classPropertyName: "empty", publicName: "empty", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, caption: { classPropertyName: "caption", publicName: "caption", isSignal: true, isRequired: false, transformFunction: null }, clickable: { classPropertyName: "clickable", publicName: "clickable", isSignal: true, isRequired: false, transformFunction: null }, zebra: { classPropertyName: "zebra", publicName: "zebra", isSignal: true, isRequired: false, transformFunction: null }, hover: { classPropertyName: "hover", publicName: "hover", isSignal: true, isRequired: false, transformFunction: null }, narrowLayout: { classPropertyName: "narrowLayout", publicName: "narrowLayout", isSignal: true, isRequired: false, transformFunction: null }, cardsAt: { classPropertyName: "cardsAt", publicName: "cardsAt", isSignal: true, isRequired: false, transformFunction: null }, rowCardChrome: { classPropertyName: "rowCardChrome", publicName: "rowCardChrome", isSignal: true, isRequired: false, transformFunction: null }, mobileLayout: { classPropertyName: "mobileLayout", publicName: "mobileLayout", isSignal: true, isRequired: false, transformFunction: null }, density: { classPropertyName: "density", publicName: "density", isSignal: true, isRequired: false, transformFunction: null }, stickyFirst: { classPropertyName: "stickyFirst", publicName: "stickyFirst", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, selectionLabel: { classPropertyName: "selectionLabel", publicName: "selectionLabel", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: false, transformFunction: null }, expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null }, expandMode: { classPropertyName: "expandMode", publicName: "expandMode", isSignal: true, isRequired: false, transformFunction: null }, toolbarSurface: { classPropertyName: "toolbarSurface", publicName: "toolbarSurface", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selected: "selectedChange", expanded: "expandedChange", sortChange: "sortChange", rowClick: "rowClick" }, queries: [{ propertyName: "cells", predicate: FoldDataTableCellDirective, isSignal: true }, { propertyName: "rowDetail", first: true, predicate: FoldDataTableRowDetailDirective, descendants: true, isSignal: true }, { propertyName: "rowCard", first: true, predicate: FoldDataTableRowCardDirective, descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"folddt-wrap\"\n [class.folddt--zebra]=\"zebra()\"\n [class.folddt--hover]=\"hover()\"\n [class.folddt--narrow]=\"isNarrow()\"\n [class.folddt--compact]=\"density() === 'compact'\"\n [class.folddt--sticky-first]=\"stickyFirst()\"\n [class.folddt--select]=\"selectable()\"\n>\n <div\n class=\"folddt-toolbar\"\n [class.folddt-toolbar--sunken]=\"toolbarSurface() === 'sunken'\"\n [class.folddt-toolbar--raised]=\"toolbarSurface() === 'raised'\"\n [class.folddt-toolbar--accent]=\"toolbarSurface() === 'accent'\"\n [attr.data-surface]=\"toolbarSurface() === 'accent' ? 'accent' : null\"\n >\n <ng-content select=\"[foldToolbar]\" />\n </div>\n @if (!cardMode()) {\n <div class=\"folddt-scroll\">\n <table class=\"folddt\" [attr.aria-colcount]=\"colCount()\">\n @if (caption(); as cap) {\n <caption class=\"folddt-caption\">\n {{\n cap\n }}\n </caption>\n }\n <thead>\n <tr>\n @if (selectable()) {\n <th scope=\"col\" class=\"folddt-select-h\">\n <fold-checkbox\n size=\"sm\"\n [ariaLabel]=\"l().selectAll\"\n [checked]=\"allSelected()\"\n [indeterminate]=\"someSelected()\"\n (checkedChange)=\"toggleAll()\"\n />\n </th>\n }\n @for (col of columns(); track col.key) {\n <th\n scope=\"col\"\n [class.is-primary-h]=\"col.key === primaryKey()\"\n [style.width]=\"col.width || null\"\n [attr.aria-sort]=\"col.sortable ? ariaSort(col.key) : null\"\n >\n @if (col.sortable) {\n <button\n type=\"button\"\n class=\"folddt-th-sort\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n [attr.aria-label]=\"l().sortBy(col.label)\"\n (click)=\"sortChange.emit(col.key)\"\n >\n <span>{{ col.label }}</span>\n <fold-icon\n class=\"folddt-arrow\"\n [class.on]=\"isSorted(col.key)\"\n [name]=\"sortIcon(col.key)\"\n [size]=\"14\"\n />\n </button>\n } @else {\n <span\n class=\"folddt-th-plain\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n >{{ col.label }}</span\n >\n }\n </th>\n }\n @if (expandable()) {\n <!-- Une colonne sans nom : son en-t\u00EAte est vide \u00C0 DESSEIN, mais\n pas muette \u2014 le libell\u00E9 part en texte masqu\u00E9, sinon la\n derni\u00E8re colonne est annonc\u00E9e \u00AB colonne 8 \u00BB. -->\n <th scope=\"col\" class=\"folddt-expand-h\">\n <span class=\"folddt-sr\">{{ l().expandRow }}</span>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of rows(); track keyOf(row, $index); let i = $index) {\n @let tone = toneOf(row);\n <tr\n class=\"folddt-row\"\n [class.tone-warning]=\"tone === 'warning'\"\n [class.tone-alert]=\"tone === 'alert'\"\n [class.tone-success]=\"tone === 'success'\"\n [class.clickable]=\"clickable()\"\n [class.is-selected]=\"selectable() && isRowSelected(row, i)\"\n [attr.tabindex]=\"rowTabIndex(row, i)\"\n [attr.aria-selected]=\"selectable() ? isRowSelected(row, i) : null\"\n (click)=\"onRowActivate(row)\"\n (focus)=\"onRowFocus(row, i)\"\n (keydown)=\"onRowKeydown($event, row)\"\n >\n @if (selectable()) {\n <td class=\"folddt-cell folddt-cell--select\">\n <fold-checkbox\n size=\"sm\"\n [ariaLabel]=\"labelFor(row)\"\n [checked]=\"isRowSelected(row, i)\"\n (click)=\"$event.stopPropagation()\"\n (checkedChange)=\"toggleRow(row, i)\"\n />\n </td>\n }\n @for (col of columns(); track col.key) {\n @if (col.key === primaryKey()) {\n <th\n scope=\"row\"\n class=\"folddt-cell is-primary\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n [class.truncate]=\"col.truncate\"\n [ngClass]=\"col.cellClass || ''\"\n [attr.data-label]=\"col.label\"\n >\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </th>\n } @else {\n <td\n class=\"folddt-cell\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n [class.truncate]=\"col.truncate\"\n [ngClass]=\"col.cellClass || ''\"\n [attr.data-label]=\"col.label\"\n >\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </td>\n }\n }\n @if (expandable()) {\n <td class=\"folddt-cell folddt-cell--expand\">\n <button\n type=\"button\"\n class=\"folddt-expand\"\n [attr.aria-expanded]=\"isRowExpanded(row, i)\"\n [attr.aria-controls]=\"detailId(row, i)\"\n [attr.aria-label]=\"\n isRowExpanded(row, i) ? l().collapseRow : l().expandRow\n \"\n (click)=\"$event.stopPropagation(); toggleExpand(row, i)\"\n >\n <fold-icon\n [name]=\"\n isRowExpanded(row, i) ? 'chevron-up' : 'chevron-down'\n \"\n [size]=\"16\"\n />\n </button>\n </td>\n }\n </tr>\n @if (expandable() && isRowExpanded(row, i)) {\n <!-- La rang\u00E9e du tiroir ne porte PAS de `tabindex` : elle reste\n hors du groupe \u00E0 navigation par fl\u00E8ches, que les helpers\n savent enjamber. Une rang\u00E9e focusable de plus ferait deux\n arr\u00EAts pour une seule ligne de tableau. -->\n <tr class=\"folddt-detail-row\">\n <td\n class=\"folddt-detail\"\n [id]=\"detailId(row, i)\"\n [attr.colspan]=\"colCount()\"\n >\n <ng-container\n [ngTemplateOutlet]=\"rowDetailTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </td>\n </tr>\n }\n }\n </tbody>\n </table>\n </div>\n } @else {\n <!-- `role=\"list\"` on a <ul> looks redundant and is not: `list-style: none`\n strips list semantics in Safari, which is exactly what the styling\n does. One list, one shell \u2014 the projected template supplies the\n CONTENT, the shell supplies the chrome (outline, tone, selection), so a\n consumer never reinvents them. -->\n <ul class=\"folddt-cardlist\" role=\"list\">\n @for (row of rows(); track keyOf(row, $index); let i = $index) {\n @let tone = toneOf(row);\n <li\n class=\"folddt-card\"\n [class.is-bare]=\"rowCardChrome() === 'none' && rowCardTemplate()\"\n [class.tone-warning]=\"tone === 'warning'\"\n [class.tone-alert]=\"tone === 'alert'\"\n [class.tone-success]=\"tone === 'success'\"\n [class.is-selected]=\"selectable() && isRowSelected(row, i)\"\n [attr.aria-selected]=\"selectable() ? isRowSelected(row, i) : null\"\n >\n @if (\n selectable() && !(rowCardChrome() === \"none\" && rowCardTemplate())\n ) {\n <fold-checkbox\n class=\"folddt-card-select\"\n size=\"sm\"\n [ariaLabel]=\"labelFor(row)\"\n [checked]=\"isRowSelected(row, i)\"\n (click)=\"$event.stopPropagation()\"\n (checkedChange)=\"toggleRow(row, i)\"\n />\n }\n <div class=\"folddt-card-body\">\n @if (rowCardTemplate(); as card) {\n <ng-container\n [ngTemplateOutlet]=\"card\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n @if (overlineColumn(); as col) {\n <p class=\"folddt-card-overline\">\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </p>\n }\n @if (identityColumn(); as col) {\n <p class=\"folddt-card-identity\">\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </p>\n }\n <!-- A <dl> and not a `::before { content: attr(data-label) }`:\n generated content is not reliably announced, and a label/value\n pair IS a description list. It also lets the values line up in\n columns, which matters for amounts. -->\n <dl class=\"folddt-card-grid\">\n @for (col of gridColumns(); track col.key) {\n <!-- A <div> around each pair is valid inside a <dl> and is\n what puts the label ABOVE its value in one grid cell. -->\n <div class=\"folddt-card-pair\">\n <dt>{{ col.label }}</dt>\n <dd\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n >\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{\n $implicit: row,\n index: i,\n }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </dd>\n </div>\n }\n </dl>\n }\n @if (expandable()) {\n <button\n type=\"button\"\n class=\"folddt-expand folddt-expand--card\"\n [attr.aria-expanded]=\"isRowExpanded(row, i)\"\n [attr.aria-controls]=\"detailId(row, i)\"\n [attr.aria-label]=\"\n isRowExpanded(row, i) ? l().collapseRow : l().expandRow\n \"\n (click)=\"toggleExpand(row, i)\"\n >\n <fold-icon\n [name]=\"isRowExpanded(row, i) ? 'chevron-up' : 'chevron-down'\"\n [size]=\"16\"\n />\n </button>\n @if (isRowExpanded(row, i)) {\n <!-- DANS la carte, et non sous la liste : c'est la m\u00EAme\n promesse que sur la table large \u2014 on ouvre une ligne sans\n quitter la place qu'on a mis du temps \u00E0 trouver. -->\n <div class=\"folddt-detail\" [id]=\"detailId(row, i)\">\n <ng-container\n [ngTemplateOutlet]=\"rowDetailTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </div>\n }\n }\n </div>\n </li>\n }\n </ul>\n }\n\n @if (loading()) {\n <div class=\"folddt-loading\">\n <fold-spinner [label]=\"l().loading\" />\n </div>\n } @else if (rows().length === 0 && empty(); as e) {\n <div class=\"folddt-empty\">\n <div class=\"folddt-empty-t\">{{ e.title }}</div>\n @if (e.subtitle) {\n <div class=\"folddt-empty-s\">{{ e.subtitle }}</div>\n }\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;min-height:0}.folddt-wrap{--folddt-sel-w: 0px;display:flex;flex-direction:column;flex:1 1 auto;min-height:0;overflow:hidden;border:1px solid var(--fold-color-border-subtle);border-radius:var(--fold-radius-lg);background:var(--fold-color-surface-sunken);box-shadow:var(--fold-shadow-md)}.folddt--select{--folddt-sel-w: 44px}.folddt-scroll{flex:1 1 auto;min-height:0;overflow:auto}.folddt-toolbar{padding:var(--fold-space-md) var(--fold-space-lg);border-bottom:1px solid var(--fold-color-border);color:var(--fold-color-text);background:color-mix(in srgb,var(--fold-color-surface-sunken) 50%,var(--fold-color-surface-card))}.folddt-toolbar:not(:has(*)){display:none}.folddt-toolbar--sunken{background:var(--fold-color-surface-sunken)}.folddt-toolbar--raised{background:var(--fold-color-surface-raised)}.folddt-toolbar--accent{background:var(--fold-color-primary);border-bottom-color:var(--fold-color-primary);color:var(--fold-color-on-primary)}.folddt{width:100%;border-collapse:separate;border-spacing:0;font-size:var(--fold-text-sm)}.folddt-caption{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.folddt thead th{position:sticky;top:0;z-index:2;padding:0;text-align:left;background:color-mix(in srgb,var(--fold-color-surface-sunken) 50%,var(--fold-color-surface-card));border-bottom:1px solid var(--fold-color-border)}.folddt-th-sort,.folddt-th-plain{display:inline-flex;align-items:center;padding:var(--fold-space-md) var(--fold-space-lg);color:var(--fold-color-text-muted);font-family:var(--fold-font-label);font-size:var(--fold-text-2xs);font-weight:var(--fold-weight-bold);text-transform:uppercase;letter-spacing:var(--fold-tracking-caps)}.folddt-th-sort{gap:var(--fold-space-sm);width:100%;border:0;background:transparent;cursor:pointer;transition:color var(--fold-motion-fast)}.folddt-th-sort:hover{color:var(--fold-color-text)}.folddt-th-sort.is-numeric,.folddt-th-sort.right{justify-content:flex-end}.folddt-th-plain.is-numeric,.folddt-th-plain.right{justify-content:flex-end;width:100%}.folddt-arrow{display:inline-flex;color:var(--fold-color-text-faded);transition:color var(--fold-motion-fast)}.folddt-arrow.on{color:var(--fold-color-primary-text)}.folddt-row .folddt-cell{background:var(--fold-data-table-row-bg, transparent)}.folddt-row{transition:background var(--fold-motion-fast)}.folddt-row.clickable{cursor:pointer}.folddt-row .folddt-cell{border-bottom:1px solid var(--fold-color-border-subtle)}.folddt-row:last-child .folddt-cell{border-bottom:0}.folddt-row:focus-visible{outline:2px solid var(--fold-color-primary-border);outline-offset:-2px}.folddt--zebra .folddt-row:nth-child(2n):not(.tone-warning):not(.tone-alert):not(.tone-success) .folddt-cell{background:var(--fold-color-surface-subtle)}.folddt--zebra .folddt-row .folddt-cell{border-bottom-color:transparent}.folddt--hover .folddt-row:hover .folddt-cell{background:var(--fold-data-table-row-hover-bg, var(--fold-color-surface-raised))}.folddt--hover .folddt-row.tone-warning:hover .folddt-cell{background:color-mix(in srgb,var(--fold-color-warning) 16%,transparent)}.folddt--hover .folddt-row.tone-alert:hover .folddt-cell{background:color-mix(in srgb,var(--fold-color-alert) 17%,transparent)}.folddt-cell{padding:var(--fold-space-md) var(--fold-space-lg);color:var(--fold-color-text);font-weight:inherit;text-align:left;white-space:nowrap;vertical-align:middle}.folddt-cell.is-numeric{text-align:right;font-variant-numeric:tabular-nums}.folddt-cell.right{text-align:right}.folddt-cell.center{text-align:center}.folddt-cell.truncate{max-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.folddt-row.tone-warning .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-warning)}.folddt-row.tone-warning .folddt-cell{background:color-mix(in srgb,var(--fold-color-warning) 10%,transparent)}.folddt-row.tone-alert .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-alert)}.folddt-row.tone-alert .folddt-cell{background:color-mix(in srgb,var(--fold-color-alert) 11%,transparent)}.folddt-row.tone-success .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-success)}.folddt-row.tone-success .folddt-cell{background:color-mix(in srgb,var(--fold-color-success) 9%,transparent)}.folddt-loading{display:flex;align-items:center;justify-content:center;padding:var(--fold-space-5xl) var(--fold-space-2xl)}.folddt-empty{padding:var(--fold-space-5xl) var(--fold-space-2xl);text-align:center}.folddt-empty-t{font-size:var(--fold-text-base);font-weight:var(--fold-weight-semibold);color:var(--fold-color-text)}.folddt-empty-s{font-size:var(--fold-text-sm);color:var(--fold-color-text-muted);margin-top:var(--fold-space-xs)}.folddt-cardlist{display:flex;flex-direction:column;margin:0;padding:0;list-style:none}.folddt-card{display:flex;gap:var(--fold-space-md);align-items:flex-start;padding:var(--fold-space-md) var(--fold-space-lg);background:var(--fold-color-surface-card);border:1px solid var(--fold-color-border);border-radius:var(--fold-radius-lg);box-shadow:var(--fold-shadow-sm)}.folddt-card-body{flex:1 1 auto;min-width:0}.folddt-card.tone-warning{border-inline-start:3px solid var(--fold-color-warning)}.folddt-card.tone-alert{border-inline-start:3px solid var(--fold-color-alert)}.folddt-card.tone-success{border-inline-start:3px solid var(--fold-color-success)}.folddt-card.is-selected{background:var(--fold-color-primary-surface);border-color:var(--fold-color-primary)}.folddt-card.is-bare,.folddt-card.is-bare.is-selected,.folddt-card.is-bare.tone-warning,.folddt-card.is-bare.tone-alert,.folddt-card.is-bare.tone-success{padding:0;background:none;border:0;border-radius:0;box-shadow:none}.folddt-select-h,.folddt-cell--select{width:var(--folddt-sel-w);padding-left:var(--fold-space-lg);padding-right:0;text-align:left;white-space:nowrap}.folddt-select-h{vertical-align:middle}.folddt-row.is-selected .folddt-cell{background:color-mix(in srgb,var(--fold-color-primary) 8%,transparent)}.folddt-row.is-selected .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-primary)}.folddt--compact .folddt-cell,.folddt--compact .folddt-th-sort,.folddt--compact .folddt-th-plain{padding:var(--fold-space-sm) var(--fold-space-md)}.folddt--compact .folddt-cell--select{padding-left:var(--fold-space-md);padding-right:0}.folddt--sticky-first .folddt-cell--select,.folddt--sticky-first .folddt-select-h{position:sticky;left:0;background:var(--fold-color-surface-sunken)}.folddt--sticky-first .folddt-select-h{z-index:3}.folddt--sticky-first .folddt-cell.is-primary{position:sticky;left:var(--folddt-sel-w);z-index:1;background:var(--fold-color-surface-sunken)}.folddt--sticky-first thead th.is-primary-h{position:sticky;left:var(--folddt-sel-w);z-index:3}.folddt--sticky-first .folddt-row.tone-warning .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-warning) 10%,var(--fold-color-surface-sunken))}.folddt--sticky-first .folddt-row.tone-alert .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-alert) 11%,var(--fold-color-surface-sunken))}.folddt--sticky-first .folddt-row.tone-success .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-success) 9%,var(--fold-color-surface-sunken))}.folddt--sticky-first .folddt-row.is-selected .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-primary) 8%,var(--fold-color-surface-sunken))}@media(prefers-reduced-motion:reduce){.folddt-row,.folddt-th-sort,.folddt-arrow{transition:none}}@media(forced-colors:active){.folddt-row.is-selected .folddt-cell:first-child,.folddt-row.tone-warning .folddt-cell:first-child,.folddt-row.tone-alert .folddt-cell:first-child,.folddt-row.tone-success .folddt-cell:first-child{border-inline-start:3px solid Highlight}.folddt-row:focus-visible{outline-color:Highlight}}.folddt-cardlist{gap:var(--fold-space-sm)}.folddt-card-overline{margin:0 0 var(--fold-space-xs);color:var(--fold-color-text-muted);font-size:var(--fold-text-xs);font-weight:var(--fold-weight-medium);overflow-wrap:anywhere}.folddt-card-identity{margin:0;color:var(--fold-color-text);font-size:var(--fold-text-base);font-weight:var(--fold-weight-semibold);letter-spacing:var(--fold-tracking-tight)}.folddt-card-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--fold-space-sm) var(--fold-space-md);margin:var(--fold-space-md) 0 0}.folddt-card-pair{min-width:0}.folddt-card-grid dt{color:var(--fold-color-text-muted);font-size:var(--fold-text-2xs);font-weight:var(--fold-weight-bold);letter-spacing:var(--fold-tracking-caps);text-transform:uppercase}.folddt-card-grid dd{margin:var(--fold-space-xs) 0 0;color:var(--fold-color-text);font-size:var(--fold-text-sm)}.folddt-card-grid dd.is-numeric{font-variant-numeric:tabular-nums;text-align:right}.folddt-card-grid dd.right{font-variant-numeric:tabular-nums}.folddt-detail-row>.folddt-detail{border-top:0;background:var(--fold-data-table-detail-bg, var(--fold-color-surface-sunken));box-shadow:inset 0 1px 0 var(--fold-color-border-subtle)}.folddt-detail{padding:var(--fold-data-table-detail-padding, var(--fold-space-md) var(--fold-space-lg))}.folddt-cardlist .folddt-detail{margin-top:var(--fold-space-sm);border-radius:var(--fold-radius-md);background:var(--fold-data-table-detail-bg, var(--fold-color-surface-sunken));padding:var(--fold-space-md)}.folddt-expand-h{width:1%}.folddt-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.folddt-cell--expand{width:1%;text-align:right}.folddt-expand{display:grid;place-items:center;width:32px;height:32px;padding:0;border:1px solid var(--fold-color-border);border-radius:var(--fold-radius-pill);background:var(--fold-color-surface-card);color:var(--fold-color-text-muted);cursor:pointer}.folddt-expand:hover{color:var(--fold-color-text)}.folddt-card{position:relative}.folddt-expand--card{position:absolute;top:var(--fold-space-sm);right:var(--fold-space-sm)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: FoldIconComponent, selector: "fold-icon", inputs: ["name", "size", "tone", "title"] }, { kind: "component", type: FoldSpinnerComponent, selector: "fold-spinner", inputs: ["size", "label"] }, { kind: "component", type: FoldCheckboxComponent, selector: "fold-checkbox", inputs: ["checked", "disabled", "touched", "errors", "indeterminate", "label", "ariaLabel", "hint", "required", "size"], outputs: ["checkedChange", "touchedChange"] }] });
6054
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: FoldDataTableComponent, isStandalone: true, selector: "fold-data-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: true, transformFunction: null }, rowKey: { classPropertyName: "rowKey", publicName: "rowKey", isSignal: true, isRequired: false, transformFunction: null }, rowTone: { classPropertyName: "rowTone", publicName: "rowTone", isSignal: true, isRequired: false, transformFunction: null }, rowNote: { classPropertyName: "rowNote", publicName: "rowNote", isSignal: true, isRequired: false, transformFunction: null }, sort: { classPropertyName: "sort", publicName: "sort", isSignal: true, isRequired: false, transformFunction: null }, empty: { classPropertyName: "empty", publicName: "empty", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, caption: { classPropertyName: "caption", publicName: "caption", isSignal: true, isRequired: false, transformFunction: null }, clickable: { classPropertyName: "clickable", publicName: "clickable", isSignal: true, isRequired: false, transformFunction: null }, zebra: { classPropertyName: "zebra", publicName: "zebra", isSignal: true, isRequired: false, transformFunction: null }, hover: { classPropertyName: "hover", publicName: "hover", isSignal: true, isRequired: false, transformFunction: null }, narrowLayout: { classPropertyName: "narrowLayout", publicName: "narrowLayout", isSignal: true, isRequired: false, transformFunction: null }, cardsAt: { classPropertyName: "cardsAt", publicName: "cardsAt", isSignal: true, isRequired: false, transformFunction: null }, rowCardChrome: { classPropertyName: "rowCardChrome", publicName: "rowCardChrome", isSignal: true, isRequired: false, transformFunction: null }, mobileLayout: { classPropertyName: "mobileLayout", publicName: "mobileLayout", isSignal: true, isRequired: false, transformFunction: null }, density: { classPropertyName: "density", publicName: "density", isSignal: true, isRequired: false, transformFunction: null }, stickyFirst: { classPropertyName: "stickyFirst", publicName: "stickyFirst", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, selectionLabel: { classPropertyName: "selectionLabel", publicName: "selectionLabel", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: false, transformFunction: null }, expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null }, expandMode: { classPropertyName: "expandMode", publicName: "expandMode", isSignal: true, isRequired: false, transformFunction: null }, toolbarSurface: { classPropertyName: "toolbarSurface", publicName: "toolbarSurface", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selected: "selectedChange", expanded: "expandedChange", sortChange: "sortChange", rowClick: "rowClick" }, queries: [{ propertyName: "cells", predicate: FoldDataTableCellDirective, isSignal: true }, { propertyName: "rowNoteTpl", first: true, predicate: FoldDataTableRowNoteDirective, descendants: true, isSignal: true }, { propertyName: "rowDetail", first: true, predicate: FoldDataTableRowDetailDirective, descendants: true, isSignal: true }, { propertyName: "rowCard", first: true, predicate: FoldDataTableRowCardDirective, descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"folddt-wrap\"\n [class.folddt--zebra]=\"zebra()\"\n [class.folddt--hover]=\"hover()\"\n [class.folddt--narrow]=\"isNarrow()\"\n [class.folddt--compact]=\"density() === 'compact'\"\n [class.folddt--sticky-first]=\"stickyFirst()\"\n [class.folddt--select]=\"selectable()\"\n>\n <div\n class=\"folddt-toolbar\"\n [class.folddt-toolbar--sunken]=\"toolbarSurface() === 'sunken'\"\n [class.folddt-toolbar--raised]=\"toolbarSurface() === 'raised'\"\n [class.folddt-toolbar--accent]=\"toolbarSurface() === 'accent'\"\n [attr.data-surface]=\"toolbarSurface() === 'accent' ? 'accent' : null\"\n >\n <ng-content select=\"[foldToolbar]\" />\n </div>\n @if (!cardMode()) {\n <div class=\"folddt-scroll\">\n <table class=\"folddt\" [attr.aria-colcount]=\"colCount()\">\n @if (caption(); as cap) {\n <caption class=\"folddt-caption\">\n {{\n cap\n }}\n </caption>\n }\n <thead>\n <tr>\n @if (selectable()) {\n <th scope=\"col\" class=\"folddt-select-h\">\n <fold-checkbox\n size=\"sm\"\n [ariaLabel]=\"l().selectAll\"\n [checked]=\"allSelected()\"\n [indeterminate]=\"someSelected()\"\n (checkedChange)=\"toggleAll()\"\n />\n </th>\n }\n @for (col of columns(); track col.key) {\n <th\n scope=\"col\"\n [class.is-primary-h]=\"col.key === primaryKey()\"\n [style.width]=\"col.width || null\"\n [attr.aria-sort]=\"col.sortable ? ariaSort(col.key) : null\"\n >\n @if (col.sortable) {\n <button\n type=\"button\"\n class=\"folddt-th-sort\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n [attr.aria-label]=\"l().sortBy(col.label)\"\n (click)=\"sortChange.emit(col.key)\"\n >\n <span>{{ col.label }}</span>\n <fold-icon\n class=\"folddt-arrow\"\n [class.on]=\"isSorted(col.key)\"\n [name]=\"sortIcon(col.key)\"\n [size]=\"14\"\n />\n </button>\n } @else {\n <span\n class=\"folddt-th-plain\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n >{{ col.label }}</span\n >\n }\n </th>\n }\n @if (expandable()) {\n <!-- Une colonne sans nom : son en-t\u00EAte est vide \u00C0 DESSEIN, mais\n pas muette \u2014 le libell\u00E9 part en texte masqu\u00E9, sinon la\n derni\u00E8re colonne est annonc\u00E9e \u00AB colonne 8 \u00BB. -->\n <th scope=\"col\" class=\"folddt-expand-h\">\n <span class=\"folddt-sr\">{{ l().expandRow }}</span>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of rows(); track keyOf(row, $index); let i = $index) {\n @let tone = toneOf(row);\n <tr\n class=\"folddt-row\"\n [class.tone-warning]=\"tone === 'warning'\"\n [class.tone-alert]=\"tone === 'alert'\"\n [class.tone-success]=\"tone === 'success'\"\n [class.clickable]=\"clickable()\"\n [class.is-selected]=\"selectable() && isRowSelected(row, i)\"\n [attr.tabindex]=\"rowTabIndex(row, i)\"\n [attr.aria-selected]=\"selectable() ? isRowSelected(row, i) : null\"\n (click)=\"onRowActivate(row)\"\n (focus)=\"onRowFocus(row, i)\"\n (keydown)=\"onRowKeydown($event, row)\"\n >\n @if (selectable()) {\n <td class=\"folddt-cell folddt-cell--select\">\n <fold-checkbox\n size=\"sm\"\n [ariaLabel]=\"labelFor(row)\"\n [checked]=\"isRowSelected(row, i)\"\n (click)=\"$event.stopPropagation()\"\n (checkedChange)=\"toggleRow(row, i)\"\n />\n </td>\n }\n @for (col of columns(); track col.key) {\n @if (col.key === primaryKey()) {\n <th\n scope=\"row\"\n class=\"folddt-cell is-primary\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n [class.truncate]=\"col.truncate\"\n [ngClass]=\"col.cellClass || ''\"\n [attr.data-label]=\"col.label\"\n >\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </th>\n } @else {\n <td\n class=\"folddt-cell\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n [class.truncate]=\"col.truncate\"\n [ngClass]=\"col.cellClass || ''\"\n [attr.data-label]=\"col.label\"\n >\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </td>\n }\n }\n @if (expandable()) {\n <td class=\"folddt-cell folddt-cell--expand\">\n <button\n type=\"button\"\n class=\"folddt-expand\"\n [attr.aria-expanded]=\"isRowExpanded(row, i)\"\n [attr.aria-controls]=\"detailId(row, i)\"\n [attr.aria-label]=\"\n isRowExpanded(row, i) ? l().collapseRow : l().expandRow\n \"\n (click)=\"$event.stopPropagation(); toggleExpand(row, i)\"\n >\n <fold-icon\n [name]=\"\n isRowExpanded(row, i) ? 'chevron-up' : 'chevron-down'\n \"\n [size]=\"16\"\n />\n </button>\n </td>\n }\n </tr>\n <!-- \uD83D\uDD34 **La note n'est pas un tiroir.** Elle est toujours l\u00E0, donc\n elle ne porte ni bascule, ni `aria-expanded`, ni identifiant \u00E0\n contr\u00F4ler : il n'y a rien \u00E0 r\u00E9v\u00E9ler. Comme la rang\u00E9e du tiroir\n elle reste hors du groupe \u00E0 navigation par fl\u00E8ches \u2014 un arr\u00EAt\n de plus pour une ligne qu'on lit sans la parcourir. -->\n @if (hasNote(row, i)) {\n <tr class=\"folddt-note-row\">\n <td class=\"folddt-note\" [attr.colspan]=\"colCount()\">\n <ng-container\n [ngTemplateOutlet]=\"rowNoteTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </td>\n </tr>\n }\n @if (expandable() && isRowExpanded(row, i)) {\n <!-- La rang\u00E9e du tiroir ne porte PAS de `tabindex` : elle reste\n hors du groupe \u00E0 navigation par fl\u00E8ches, que les helpers\n savent enjamber. Une rang\u00E9e focusable de plus ferait deux\n arr\u00EAts pour une seule ligne de tableau. -->\n <tr class=\"folddt-detail-row\">\n <td\n class=\"folddt-detail\"\n [id]=\"detailId(row, i)\"\n [attr.colspan]=\"colCount()\"\n >\n <ng-container\n [ngTemplateOutlet]=\"rowDetailTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </td>\n </tr>\n }\n }\n </tbody>\n </table>\n </div>\n } @else {\n <!-- `role=\"list\"` on a <ul> looks redundant and is not: `list-style: none`\n strips list semantics in Safari, which is exactly what the styling\n does. One list, one shell \u2014 the projected template supplies the\n CONTENT, the shell supplies the chrome (outline, tone, selection), so a\n consumer never reinvents them. -->\n <ul class=\"folddt-cardlist\" role=\"list\">\n @for (row of rows(); track keyOf(row, $index); let i = $index) {\n @let tone = toneOf(row);\n <li\n class=\"folddt-card\"\n [class.is-bare]=\"rowCardChrome() === 'none' && rowCardTemplate()\"\n [class.tone-warning]=\"tone === 'warning'\"\n [class.tone-alert]=\"tone === 'alert'\"\n [class.tone-success]=\"tone === 'success'\"\n [class.is-selected]=\"selectable() && isRowSelected(row, i)\"\n [attr.aria-selected]=\"selectable() ? isRowSelected(row, i) : null\"\n >\n @if (\n selectable() && !(rowCardChrome() === \"none\" && rowCardTemplate())\n ) {\n <fold-checkbox\n class=\"folddt-card-select\"\n size=\"sm\"\n [ariaLabel]=\"labelFor(row)\"\n [checked]=\"isRowSelected(row, i)\"\n (click)=\"$event.stopPropagation()\"\n (checkedChange)=\"toggleRow(row, i)\"\n />\n }\n <div class=\"folddt-card-body\">\n @if (rowCardTemplate(); as card) {\n <ng-container\n [ngTemplateOutlet]=\"card\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n @if (overlineColumn(); as col) {\n <p class=\"folddt-card-overline\">\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </p>\n }\n @if (identityColumn(); as col) {\n <p class=\"folddt-card-identity\">\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </p>\n }\n <!-- A <dl> and not a `::before { content: attr(data-label) }`:\n generated content is not reliably announced, and a label/value\n pair IS a description list. It also lets the values line up in\n columns, which matters for amounts. -->\n <dl class=\"folddt-card-grid\">\n @for (col of gridColumns(); track col.key) {\n <!-- A <div> around each pair is valid inside a <dl> and is\n what puts the label ABOVE its value in one grid cell. -->\n <div class=\"folddt-card-pair\">\n <dt>{{ col.label }}</dt>\n <dd\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n >\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{\n $implicit: row,\n index: i,\n }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </dd>\n </div>\n }\n </dl>\n }\n <!-- Dans la carte, la note suit les champs de la ligne : m\u00EAme\n promesse qu'en vue large, elle se lit avec la ligne et non\n ailleurs. -->\n @if (hasNote(row, i)) {\n <div class=\"folddt-note folddt-note--card\">\n <ng-container\n [ngTemplateOutlet]=\"rowNoteTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </div>\n }\n @if (expandable()) {\n <button\n type=\"button\"\n class=\"folddt-expand folddt-expand--card\"\n [attr.aria-expanded]=\"isRowExpanded(row, i)\"\n [attr.aria-controls]=\"detailId(row, i)\"\n [attr.aria-label]=\"\n isRowExpanded(row, i) ? l().collapseRow : l().expandRow\n \"\n (click)=\"toggleExpand(row, i)\"\n >\n <fold-icon\n [name]=\"isRowExpanded(row, i) ? 'chevron-up' : 'chevron-down'\"\n [size]=\"16\"\n />\n </button>\n @if (isRowExpanded(row, i)) {\n <!-- DANS la carte, et non sous la liste : c'est la m\u00EAme\n promesse que sur la table large \u2014 on ouvre une ligne sans\n quitter la place qu'on a mis du temps \u00E0 trouver. -->\n <div class=\"folddt-detail\" [id]=\"detailId(row, i)\">\n <ng-container\n [ngTemplateOutlet]=\"rowDetailTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </div>\n }\n }\n </div>\n </li>\n }\n </ul>\n }\n\n @if (loading()) {\n <div class=\"folddt-loading\">\n <fold-spinner [label]=\"l().loading\" />\n </div>\n } @else if (rows().length === 0 && empty(); as e) {\n <div class=\"folddt-empty\">\n <div class=\"folddt-empty-t\">{{ e.title }}</div>\n @if (e.subtitle) {\n <div class=\"folddt-empty-s\">{{ e.subtitle }}</div>\n }\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;min-height:0}.folddt-wrap{--folddt-sel-w: 0px;display:flex;flex-direction:column;flex:1 1 auto;min-height:0;overflow:hidden;border:1px solid var(--fold-color-border-subtle);border-radius:var(--fold-radius-lg);background:var(--fold-color-surface-sunken);box-shadow:var(--fold-shadow-md)}.folddt--select{--folddt-sel-w: 44px}.folddt-scroll{flex:1 1 auto;min-height:0;overflow:auto}.folddt-toolbar{padding:var(--fold-space-md) var(--fold-space-lg);border-bottom:1px solid var(--fold-color-border);color:var(--fold-color-text);background:color-mix(in srgb,var(--fold-color-surface-sunken) 50%,var(--fold-color-surface-card))}.folddt-toolbar:not(:has(*)){display:none}.folddt-toolbar--sunken{background:var(--fold-color-surface-sunken)}.folddt-toolbar--raised{background:var(--fold-color-surface-raised)}.folddt-toolbar--accent{background:var(--fold-color-primary);border-bottom-color:var(--fold-color-primary);color:var(--fold-color-on-primary)}.folddt{width:100%;border-collapse:separate;border-spacing:0;font-size:var(--fold-text-sm)}.folddt-caption{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.folddt thead th{position:sticky;top:0;z-index:2;padding:0;text-align:left;background:color-mix(in srgb,var(--fold-color-surface-sunken) 50%,var(--fold-color-surface-card));border-bottom:1px solid var(--fold-color-border)}.folddt-th-sort,.folddt-th-plain{display:inline-flex;align-items:center;padding:var(--fold-space-md) var(--fold-space-lg);color:var(--fold-color-text-muted);font-family:var(--fold-font-label);font-size:var(--fold-text-2xs);font-weight:var(--fold-weight-bold);text-transform:uppercase;letter-spacing:var(--fold-tracking-caps)}.folddt-th-sort{gap:var(--fold-space-sm);width:100%;border:0;background:transparent;cursor:pointer;transition:color var(--fold-motion-fast)}.folddt-th-sort:hover{color:var(--fold-color-text)}.folddt-th-sort.is-numeric,.folddt-th-sort.right{justify-content:flex-end}.folddt-th-plain.is-numeric,.folddt-th-plain.right{justify-content:flex-end;width:100%}.folddt-arrow{display:inline-flex;color:var(--fold-color-text-faded);transition:color var(--fold-motion-fast)}.folddt-arrow.on{color:var(--fold-color-primary-text)}.folddt-row .folddt-cell{background:var(--fold-data-table-row-bg, transparent)}.folddt-row{transition:background var(--fold-motion-fast)}.folddt-row.clickable{cursor:pointer}.folddt-row .folddt-cell{border-bottom:1px solid var(--fold-color-border-subtle)}.folddt-row:last-child .folddt-cell{border-bottom:0}.folddt-row:focus-visible{outline:2px solid var(--fold-color-primary-border);outline-offset:-2px}.folddt--zebra .folddt-row:nth-child(2n of.folddt-row):not(.tone-warning):not(.tone-alert):not(.tone-success) .folddt-cell{background:var(--fold-color-surface-subtle)}.folddt--zebra .folddt-row .folddt-cell{border-bottom-color:transparent}.folddt--hover .folddt-row:hover .folddt-cell{background:var(--fold-data-table-row-hover-bg, var(--fold-color-surface-raised))}.folddt--hover .folddt-row.tone-warning:hover .folddt-cell{background:color-mix(in srgb,var(--fold-color-warning) 16%,transparent)}.folddt--hover .folddt-row.tone-alert:hover .folddt-cell{background:color-mix(in srgb,var(--fold-color-alert) 17%,transparent)}.folddt-cell{padding:var(--fold-space-md) var(--fold-space-lg);color:var(--fold-color-text);font-weight:inherit;text-align:left;white-space:nowrap;vertical-align:middle}.folddt-cell.is-numeric{text-align:right;font-variant-numeric:tabular-nums}.folddt-cell.right{text-align:right}.folddt-cell.center{text-align:center}.folddt-cell.truncate{max-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.folddt-row.tone-warning .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-warning)}.folddt-row.tone-warning .folddt-cell{background:color-mix(in srgb,var(--fold-color-warning) 10%,transparent)}.folddt-row.tone-alert .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-alert)}.folddt-row.tone-alert .folddt-cell{background:color-mix(in srgb,var(--fold-color-alert) 11%,transparent)}.folddt-row.tone-success .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-success)}.folddt-row.tone-success .folddt-cell{background:color-mix(in srgb,var(--fold-color-success) 9%,transparent)}.folddt-loading{display:flex;align-items:center;justify-content:center;padding:var(--fold-space-5xl) var(--fold-space-2xl)}.folddt-empty{padding:var(--fold-space-5xl) var(--fold-space-2xl);text-align:center}.folddt-empty-t{font-size:var(--fold-text-base);font-weight:var(--fold-weight-semibold);color:var(--fold-color-text)}.folddt-empty-s{font-size:var(--fold-text-sm);color:var(--fold-color-text-muted);margin-top:var(--fold-space-xs)}.folddt-cardlist{display:flex;flex-direction:column;margin:0;padding:0;list-style:none}.folddt-card{display:flex;gap:var(--fold-space-md);align-items:flex-start;padding:var(--fold-space-md) var(--fold-space-lg);background:var(--fold-color-surface-card);border:1px solid var(--fold-color-border);border-radius:var(--fold-radius-lg);box-shadow:var(--fold-shadow-sm)}.folddt-card-body{flex:1 1 auto;min-width:0}.folddt-card.tone-warning{border-inline-start:3px solid var(--fold-color-warning)}.folddt-card.tone-alert{border-inline-start:3px solid var(--fold-color-alert)}.folddt-card.tone-success{border-inline-start:3px solid var(--fold-color-success)}.folddt-card.is-selected{background:var(--fold-color-primary-surface);border-color:var(--fold-color-primary)}.folddt-card.is-bare,.folddt-card.is-bare.is-selected,.folddt-card.is-bare.tone-warning,.folddt-card.is-bare.tone-alert,.folddt-card.is-bare.tone-success{padding:0;background:none;border:0;border-radius:0;box-shadow:none}.folddt-select-h,.folddt-cell--select{width:var(--folddt-sel-w);padding-left:var(--fold-space-lg);padding-right:0;text-align:left;white-space:nowrap}.folddt-select-h{vertical-align:middle}.folddt-row.is-selected .folddt-cell{background:color-mix(in srgb,var(--fold-color-primary) 8%,transparent)}.folddt-row.is-selected .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-primary)}.folddt--compact .folddt-cell,.folddt--compact .folddt-th-sort,.folddt--compact .folddt-th-plain{padding:var(--fold-space-sm) var(--fold-space-md)}.folddt--compact .folddt-cell--select{padding-left:var(--fold-space-md);padding-right:0}.folddt--sticky-first .folddt-cell--select,.folddt--sticky-first .folddt-select-h{position:sticky;left:0;background:var(--fold-color-surface-sunken)}.folddt--sticky-first .folddt-select-h{z-index:3}.folddt--sticky-first .folddt-cell.is-primary{position:sticky;left:var(--folddt-sel-w);z-index:1;background:var(--fold-color-surface-sunken)}.folddt--sticky-first thead th.is-primary-h{position:sticky;left:var(--folddt-sel-w);z-index:3}.folddt--sticky-first .folddt-row.tone-warning .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-warning) 10%,var(--fold-color-surface-sunken))}.folddt--sticky-first .folddt-row.tone-alert .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-alert) 11%,var(--fold-color-surface-sunken))}.folddt--sticky-first .folddt-row.tone-success .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-success) 9%,var(--fold-color-surface-sunken))}.folddt--sticky-first .folddt-row.is-selected .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-primary) 8%,var(--fold-color-surface-sunken))}@media(prefers-reduced-motion:reduce){.folddt-row,.folddt-th-sort,.folddt-arrow{transition:none}}@media(forced-colors:active){.folddt-row.is-selected .folddt-cell:first-child,.folddt-row.tone-warning .folddt-cell:first-child,.folddt-row.tone-alert .folddt-cell:first-child,.folddt-row.tone-success .folddt-cell:first-child{border-inline-start:3px solid Highlight}.folddt-row:focus-visible{outline-color:Highlight}}.folddt-cardlist{gap:var(--fold-space-sm)}.folddt-card-overline{margin:0 0 var(--fold-space-xs);color:var(--fold-color-text-muted);font-size:var(--fold-text-xs);font-weight:var(--fold-weight-medium);overflow-wrap:anywhere}.folddt-card-identity{margin:0;color:var(--fold-color-text);font-size:var(--fold-text-base);font-weight:var(--fold-weight-semibold);letter-spacing:var(--fold-tracking-tight)}.folddt-card-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--fold-space-sm) var(--fold-space-md);margin:var(--fold-space-md) 0 0}.folddt-card-pair{min-width:0}.folddt-card-grid dt{color:var(--fold-color-text-muted);font-size:var(--fold-text-2xs);font-weight:var(--fold-weight-bold);letter-spacing:var(--fold-tracking-caps);text-transform:uppercase}.folddt-card-grid dd{margin:var(--fold-space-xs) 0 0;color:var(--fold-color-text);font-size:var(--fold-text-sm)}.folddt-card-grid dd.is-numeric{font-variant-numeric:tabular-nums;text-align:right}.folddt-card-grid dd.right{font-variant-numeric:tabular-nums}.folddt-detail-row>.folddt-detail{border-top:0;background:var(--fold-data-table-detail-bg, var(--fold-color-surface-sunken));box-shadow:inset 0 1px 0 var(--fold-color-border-subtle)}.folddt-detail{padding:var(--fold-data-table-detail-padding, var(--fold-space-md) var(--fold-space-lg))}.folddt-note{padding:var(--fold-data-table-note-padding, 0 var(--fold-space-lg) var(--fold-space-sm))}.folddt-note-row>.folddt-note{border-top:0}.folddt-note--card{margin-top:var(--fold-space-sm)}.folddt-cardlist .folddt-detail{margin-top:var(--fold-space-sm);border-radius:var(--fold-radius-md);background:var(--fold-data-table-detail-bg, var(--fold-color-surface-sunken));padding:var(--fold-space-md)}.folddt-expand-h{width:1%}.folddt-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.folddt-cell--expand{width:1%;text-align:right}.folddt-expand{display:grid;place-items:center;width:32px;height:32px;padding:0;border:1px solid var(--fold-color-border);border-radius:var(--fold-radius-pill);background:var(--fold-color-surface-card);color:var(--fold-color-text-muted);cursor:pointer}.folddt-expand:hover{color:var(--fold-color-text)}.folddt-card{position:relative}.folddt-expand--card{position:absolute;top:var(--fold-space-sm);right:var(--fold-space-sm)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: FoldIconComponent, selector: "fold-icon", inputs: ["name", "size", "tone", "title"] }, { kind: "component", type: FoldSpinnerComponent, selector: "fold-spinner", inputs: ["size", "label"] }, { kind: "component", type: FoldCheckboxComponent, selector: "fold-checkbox", inputs: ["checked", "disabled", "touched", "errors", "indeterminate", "label", "ariaLabel", "hint", "required", "size"], outputs: ["checkedChange", "touchedChange"] }] });
5947
6055
  }
5948
6056
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FoldDataTableComponent, decorators: [{
5949
6057
  type: Component,
@@ -5953,8 +6061,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
5953
6061
  FoldIconComponent,
5954
6062
  FoldSpinnerComponent,
5955
6063
  FoldCheckboxComponent,
5956
- ], template: "<div\n class=\"folddt-wrap\"\n [class.folddt--zebra]=\"zebra()\"\n [class.folddt--hover]=\"hover()\"\n [class.folddt--narrow]=\"isNarrow()\"\n [class.folddt--compact]=\"density() === 'compact'\"\n [class.folddt--sticky-first]=\"stickyFirst()\"\n [class.folddt--select]=\"selectable()\"\n>\n <div\n class=\"folddt-toolbar\"\n [class.folddt-toolbar--sunken]=\"toolbarSurface() === 'sunken'\"\n [class.folddt-toolbar--raised]=\"toolbarSurface() === 'raised'\"\n [class.folddt-toolbar--accent]=\"toolbarSurface() === 'accent'\"\n [attr.data-surface]=\"toolbarSurface() === 'accent' ? 'accent' : null\"\n >\n <ng-content select=\"[foldToolbar]\" />\n </div>\n @if (!cardMode()) {\n <div class=\"folddt-scroll\">\n <table class=\"folddt\" [attr.aria-colcount]=\"colCount()\">\n @if (caption(); as cap) {\n <caption class=\"folddt-caption\">\n {{\n cap\n }}\n </caption>\n }\n <thead>\n <tr>\n @if (selectable()) {\n <th scope=\"col\" class=\"folddt-select-h\">\n <fold-checkbox\n size=\"sm\"\n [ariaLabel]=\"l().selectAll\"\n [checked]=\"allSelected()\"\n [indeterminate]=\"someSelected()\"\n (checkedChange)=\"toggleAll()\"\n />\n </th>\n }\n @for (col of columns(); track col.key) {\n <th\n scope=\"col\"\n [class.is-primary-h]=\"col.key === primaryKey()\"\n [style.width]=\"col.width || null\"\n [attr.aria-sort]=\"col.sortable ? ariaSort(col.key) : null\"\n >\n @if (col.sortable) {\n <button\n type=\"button\"\n class=\"folddt-th-sort\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n [attr.aria-label]=\"l().sortBy(col.label)\"\n (click)=\"sortChange.emit(col.key)\"\n >\n <span>{{ col.label }}</span>\n <fold-icon\n class=\"folddt-arrow\"\n [class.on]=\"isSorted(col.key)\"\n [name]=\"sortIcon(col.key)\"\n [size]=\"14\"\n />\n </button>\n } @else {\n <span\n class=\"folddt-th-plain\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n >{{ col.label }}</span\n >\n }\n </th>\n }\n @if (expandable()) {\n <!-- Une colonne sans nom : son en-t\u00EAte est vide \u00C0 DESSEIN, mais\n pas muette \u2014 le libell\u00E9 part en texte masqu\u00E9, sinon la\n derni\u00E8re colonne est annonc\u00E9e \u00AB colonne 8 \u00BB. -->\n <th scope=\"col\" class=\"folddt-expand-h\">\n <span class=\"folddt-sr\">{{ l().expandRow }}</span>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of rows(); track keyOf(row, $index); let i = $index) {\n @let tone = toneOf(row);\n <tr\n class=\"folddt-row\"\n [class.tone-warning]=\"tone === 'warning'\"\n [class.tone-alert]=\"tone === 'alert'\"\n [class.tone-success]=\"tone === 'success'\"\n [class.clickable]=\"clickable()\"\n [class.is-selected]=\"selectable() && isRowSelected(row, i)\"\n [attr.tabindex]=\"rowTabIndex(row, i)\"\n [attr.aria-selected]=\"selectable() ? isRowSelected(row, i) : null\"\n (click)=\"onRowActivate(row)\"\n (focus)=\"onRowFocus(row, i)\"\n (keydown)=\"onRowKeydown($event, row)\"\n >\n @if (selectable()) {\n <td class=\"folddt-cell folddt-cell--select\">\n <fold-checkbox\n size=\"sm\"\n [ariaLabel]=\"labelFor(row)\"\n [checked]=\"isRowSelected(row, i)\"\n (click)=\"$event.stopPropagation()\"\n (checkedChange)=\"toggleRow(row, i)\"\n />\n </td>\n }\n @for (col of columns(); track col.key) {\n @if (col.key === primaryKey()) {\n <th\n scope=\"row\"\n class=\"folddt-cell is-primary\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n [class.truncate]=\"col.truncate\"\n [ngClass]=\"col.cellClass || ''\"\n [attr.data-label]=\"col.label\"\n >\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </th>\n } @else {\n <td\n class=\"folddt-cell\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n [class.truncate]=\"col.truncate\"\n [ngClass]=\"col.cellClass || ''\"\n [attr.data-label]=\"col.label\"\n >\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </td>\n }\n }\n @if (expandable()) {\n <td class=\"folddt-cell folddt-cell--expand\">\n <button\n type=\"button\"\n class=\"folddt-expand\"\n [attr.aria-expanded]=\"isRowExpanded(row, i)\"\n [attr.aria-controls]=\"detailId(row, i)\"\n [attr.aria-label]=\"\n isRowExpanded(row, i) ? l().collapseRow : l().expandRow\n \"\n (click)=\"$event.stopPropagation(); toggleExpand(row, i)\"\n >\n <fold-icon\n [name]=\"\n isRowExpanded(row, i) ? 'chevron-up' : 'chevron-down'\n \"\n [size]=\"16\"\n />\n </button>\n </td>\n }\n </tr>\n @if (expandable() && isRowExpanded(row, i)) {\n <!-- La rang\u00E9e du tiroir ne porte PAS de `tabindex` : elle reste\n hors du groupe \u00E0 navigation par fl\u00E8ches, que les helpers\n savent enjamber. Une rang\u00E9e focusable de plus ferait deux\n arr\u00EAts pour une seule ligne de tableau. -->\n <tr class=\"folddt-detail-row\">\n <td\n class=\"folddt-detail\"\n [id]=\"detailId(row, i)\"\n [attr.colspan]=\"colCount()\"\n >\n <ng-container\n [ngTemplateOutlet]=\"rowDetailTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </td>\n </tr>\n }\n }\n </tbody>\n </table>\n </div>\n } @else {\n <!-- `role=\"list\"` on a <ul> looks redundant and is not: `list-style: none`\n strips list semantics in Safari, which is exactly what the styling\n does. One list, one shell \u2014 the projected template supplies the\n CONTENT, the shell supplies the chrome (outline, tone, selection), so a\n consumer never reinvents them. -->\n <ul class=\"folddt-cardlist\" role=\"list\">\n @for (row of rows(); track keyOf(row, $index); let i = $index) {\n @let tone = toneOf(row);\n <li\n class=\"folddt-card\"\n [class.is-bare]=\"rowCardChrome() === 'none' && rowCardTemplate()\"\n [class.tone-warning]=\"tone === 'warning'\"\n [class.tone-alert]=\"tone === 'alert'\"\n [class.tone-success]=\"tone === 'success'\"\n [class.is-selected]=\"selectable() && isRowSelected(row, i)\"\n [attr.aria-selected]=\"selectable() ? isRowSelected(row, i) : null\"\n >\n @if (\n selectable() && !(rowCardChrome() === \"none\" && rowCardTemplate())\n ) {\n <fold-checkbox\n class=\"folddt-card-select\"\n size=\"sm\"\n [ariaLabel]=\"labelFor(row)\"\n [checked]=\"isRowSelected(row, i)\"\n (click)=\"$event.stopPropagation()\"\n (checkedChange)=\"toggleRow(row, i)\"\n />\n }\n <div class=\"folddt-card-body\">\n @if (rowCardTemplate(); as card) {\n <ng-container\n [ngTemplateOutlet]=\"card\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n @if (overlineColumn(); as col) {\n <p class=\"folddt-card-overline\">\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </p>\n }\n @if (identityColumn(); as col) {\n <p class=\"folddt-card-identity\">\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </p>\n }\n <!-- A <dl> and not a `::before { content: attr(data-label) }`:\n generated content is not reliably announced, and a label/value\n pair IS a description list. It also lets the values line up in\n columns, which matters for amounts. -->\n <dl class=\"folddt-card-grid\">\n @for (col of gridColumns(); track col.key) {\n <!-- A <div> around each pair is valid inside a <dl> and is\n what puts the label ABOVE its value in one grid cell. -->\n <div class=\"folddt-card-pair\">\n <dt>{{ col.label }}</dt>\n <dd\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n >\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{\n $implicit: row,\n index: i,\n }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </dd>\n </div>\n }\n </dl>\n }\n @if (expandable()) {\n <button\n type=\"button\"\n class=\"folddt-expand folddt-expand--card\"\n [attr.aria-expanded]=\"isRowExpanded(row, i)\"\n [attr.aria-controls]=\"detailId(row, i)\"\n [attr.aria-label]=\"\n isRowExpanded(row, i) ? l().collapseRow : l().expandRow\n \"\n (click)=\"toggleExpand(row, i)\"\n >\n <fold-icon\n [name]=\"isRowExpanded(row, i) ? 'chevron-up' : 'chevron-down'\"\n [size]=\"16\"\n />\n </button>\n @if (isRowExpanded(row, i)) {\n <!-- DANS la carte, et non sous la liste : c'est la m\u00EAme\n promesse que sur la table large \u2014 on ouvre une ligne sans\n quitter la place qu'on a mis du temps \u00E0 trouver. -->\n <div class=\"folddt-detail\" [id]=\"detailId(row, i)\">\n <ng-container\n [ngTemplateOutlet]=\"rowDetailTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </div>\n }\n }\n </div>\n </li>\n }\n </ul>\n }\n\n @if (loading()) {\n <div class=\"folddt-loading\">\n <fold-spinner [label]=\"l().loading\" />\n </div>\n } @else if (rows().length === 0 && empty(); as e) {\n <div class=\"folddt-empty\">\n <div class=\"folddt-empty-t\">{{ e.title }}</div>\n @if (e.subtitle) {\n <div class=\"folddt-empty-s\">{{ e.subtitle }}</div>\n }\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;min-height:0}.folddt-wrap{--folddt-sel-w: 0px;display:flex;flex-direction:column;flex:1 1 auto;min-height:0;overflow:hidden;border:1px solid var(--fold-color-border-subtle);border-radius:var(--fold-radius-lg);background:var(--fold-color-surface-sunken);box-shadow:var(--fold-shadow-md)}.folddt--select{--folddt-sel-w: 44px}.folddt-scroll{flex:1 1 auto;min-height:0;overflow:auto}.folddt-toolbar{padding:var(--fold-space-md) var(--fold-space-lg);border-bottom:1px solid var(--fold-color-border);color:var(--fold-color-text);background:color-mix(in srgb,var(--fold-color-surface-sunken) 50%,var(--fold-color-surface-card))}.folddt-toolbar:not(:has(*)){display:none}.folddt-toolbar--sunken{background:var(--fold-color-surface-sunken)}.folddt-toolbar--raised{background:var(--fold-color-surface-raised)}.folddt-toolbar--accent{background:var(--fold-color-primary);border-bottom-color:var(--fold-color-primary);color:var(--fold-color-on-primary)}.folddt{width:100%;border-collapse:separate;border-spacing:0;font-size:var(--fold-text-sm)}.folddt-caption{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.folddt thead th{position:sticky;top:0;z-index:2;padding:0;text-align:left;background:color-mix(in srgb,var(--fold-color-surface-sunken) 50%,var(--fold-color-surface-card));border-bottom:1px solid var(--fold-color-border)}.folddt-th-sort,.folddt-th-plain{display:inline-flex;align-items:center;padding:var(--fold-space-md) var(--fold-space-lg);color:var(--fold-color-text-muted);font-family:var(--fold-font-label);font-size:var(--fold-text-2xs);font-weight:var(--fold-weight-bold);text-transform:uppercase;letter-spacing:var(--fold-tracking-caps)}.folddt-th-sort{gap:var(--fold-space-sm);width:100%;border:0;background:transparent;cursor:pointer;transition:color var(--fold-motion-fast)}.folddt-th-sort:hover{color:var(--fold-color-text)}.folddt-th-sort.is-numeric,.folddt-th-sort.right{justify-content:flex-end}.folddt-th-plain.is-numeric,.folddt-th-plain.right{justify-content:flex-end;width:100%}.folddt-arrow{display:inline-flex;color:var(--fold-color-text-faded);transition:color var(--fold-motion-fast)}.folddt-arrow.on{color:var(--fold-color-primary-text)}.folddt-row .folddt-cell{background:var(--fold-data-table-row-bg, transparent)}.folddt-row{transition:background var(--fold-motion-fast)}.folddt-row.clickable{cursor:pointer}.folddt-row .folddt-cell{border-bottom:1px solid var(--fold-color-border-subtle)}.folddt-row:last-child .folddt-cell{border-bottom:0}.folddt-row:focus-visible{outline:2px solid var(--fold-color-primary-border);outline-offset:-2px}.folddt--zebra .folddt-row:nth-child(2n):not(.tone-warning):not(.tone-alert):not(.tone-success) .folddt-cell{background:var(--fold-color-surface-subtle)}.folddt--zebra .folddt-row .folddt-cell{border-bottom-color:transparent}.folddt--hover .folddt-row:hover .folddt-cell{background:var(--fold-data-table-row-hover-bg, var(--fold-color-surface-raised))}.folddt--hover .folddt-row.tone-warning:hover .folddt-cell{background:color-mix(in srgb,var(--fold-color-warning) 16%,transparent)}.folddt--hover .folddt-row.tone-alert:hover .folddt-cell{background:color-mix(in srgb,var(--fold-color-alert) 17%,transparent)}.folddt-cell{padding:var(--fold-space-md) var(--fold-space-lg);color:var(--fold-color-text);font-weight:inherit;text-align:left;white-space:nowrap;vertical-align:middle}.folddt-cell.is-numeric{text-align:right;font-variant-numeric:tabular-nums}.folddt-cell.right{text-align:right}.folddt-cell.center{text-align:center}.folddt-cell.truncate{max-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.folddt-row.tone-warning .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-warning)}.folddt-row.tone-warning .folddt-cell{background:color-mix(in srgb,var(--fold-color-warning) 10%,transparent)}.folddt-row.tone-alert .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-alert)}.folddt-row.tone-alert .folddt-cell{background:color-mix(in srgb,var(--fold-color-alert) 11%,transparent)}.folddt-row.tone-success .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-success)}.folddt-row.tone-success .folddt-cell{background:color-mix(in srgb,var(--fold-color-success) 9%,transparent)}.folddt-loading{display:flex;align-items:center;justify-content:center;padding:var(--fold-space-5xl) var(--fold-space-2xl)}.folddt-empty{padding:var(--fold-space-5xl) var(--fold-space-2xl);text-align:center}.folddt-empty-t{font-size:var(--fold-text-base);font-weight:var(--fold-weight-semibold);color:var(--fold-color-text)}.folddt-empty-s{font-size:var(--fold-text-sm);color:var(--fold-color-text-muted);margin-top:var(--fold-space-xs)}.folddt-cardlist{display:flex;flex-direction:column;margin:0;padding:0;list-style:none}.folddt-card{display:flex;gap:var(--fold-space-md);align-items:flex-start;padding:var(--fold-space-md) var(--fold-space-lg);background:var(--fold-color-surface-card);border:1px solid var(--fold-color-border);border-radius:var(--fold-radius-lg);box-shadow:var(--fold-shadow-sm)}.folddt-card-body{flex:1 1 auto;min-width:0}.folddt-card.tone-warning{border-inline-start:3px solid var(--fold-color-warning)}.folddt-card.tone-alert{border-inline-start:3px solid var(--fold-color-alert)}.folddt-card.tone-success{border-inline-start:3px solid var(--fold-color-success)}.folddt-card.is-selected{background:var(--fold-color-primary-surface);border-color:var(--fold-color-primary)}.folddt-card.is-bare,.folddt-card.is-bare.is-selected,.folddt-card.is-bare.tone-warning,.folddt-card.is-bare.tone-alert,.folddt-card.is-bare.tone-success{padding:0;background:none;border:0;border-radius:0;box-shadow:none}.folddt-select-h,.folddt-cell--select{width:var(--folddt-sel-w);padding-left:var(--fold-space-lg);padding-right:0;text-align:left;white-space:nowrap}.folddt-select-h{vertical-align:middle}.folddt-row.is-selected .folddt-cell{background:color-mix(in srgb,var(--fold-color-primary) 8%,transparent)}.folddt-row.is-selected .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-primary)}.folddt--compact .folddt-cell,.folddt--compact .folddt-th-sort,.folddt--compact .folddt-th-plain{padding:var(--fold-space-sm) var(--fold-space-md)}.folddt--compact .folddt-cell--select{padding-left:var(--fold-space-md);padding-right:0}.folddt--sticky-first .folddt-cell--select,.folddt--sticky-first .folddt-select-h{position:sticky;left:0;background:var(--fold-color-surface-sunken)}.folddt--sticky-first .folddt-select-h{z-index:3}.folddt--sticky-first .folddt-cell.is-primary{position:sticky;left:var(--folddt-sel-w);z-index:1;background:var(--fold-color-surface-sunken)}.folddt--sticky-first thead th.is-primary-h{position:sticky;left:var(--folddt-sel-w);z-index:3}.folddt--sticky-first .folddt-row.tone-warning .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-warning) 10%,var(--fold-color-surface-sunken))}.folddt--sticky-first .folddt-row.tone-alert .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-alert) 11%,var(--fold-color-surface-sunken))}.folddt--sticky-first .folddt-row.tone-success .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-success) 9%,var(--fold-color-surface-sunken))}.folddt--sticky-first .folddt-row.is-selected .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-primary) 8%,var(--fold-color-surface-sunken))}@media(prefers-reduced-motion:reduce){.folddt-row,.folddt-th-sort,.folddt-arrow{transition:none}}@media(forced-colors:active){.folddt-row.is-selected .folddt-cell:first-child,.folddt-row.tone-warning .folddt-cell:first-child,.folddt-row.tone-alert .folddt-cell:first-child,.folddt-row.tone-success .folddt-cell:first-child{border-inline-start:3px solid Highlight}.folddt-row:focus-visible{outline-color:Highlight}}.folddt-cardlist{gap:var(--fold-space-sm)}.folddt-card-overline{margin:0 0 var(--fold-space-xs);color:var(--fold-color-text-muted);font-size:var(--fold-text-xs);font-weight:var(--fold-weight-medium);overflow-wrap:anywhere}.folddt-card-identity{margin:0;color:var(--fold-color-text);font-size:var(--fold-text-base);font-weight:var(--fold-weight-semibold);letter-spacing:var(--fold-tracking-tight)}.folddt-card-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--fold-space-sm) var(--fold-space-md);margin:var(--fold-space-md) 0 0}.folddt-card-pair{min-width:0}.folddt-card-grid dt{color:var(--fold-color-text-muted);font-size:var(--fold-text-2xs);font-weight:var(--fold-weight-bold);letter-spacing:var(--fold-tracking-caps);text-transform:uppercase}.folddt-card-grid dd{margin:var(--fold-space-xs) 0 0;color:var(--fold-color-text);font-size:var(--fold-text-sm)}.folddt-card-grid dd.is-numeric{font-variant-numeric:tabular-nums;text-align:right}.folddt-card-grid dd.right{font-variant-numeric:tabular-nums}.folddt-detail-row>.folddt-detail{border-top:0;background:var(--fold-data-table-detail-bg, var(--fold-color-surface-sunken));box-shadow:inset 0 1px 0 var(--fold-color-border-subtle)}.folddt-detail{padding:var(--fold-data-table-detail-padding, var(--fold-space-md) var(--fold-space-lg))}.folddt-cardlist .folddt-detail{margin-top:var(--fold-space-sm);border-radius:var(--fold-radius-md);background:var(--fold-data-table-detail-bg, var(--fold-color-surface-sunken));padding:var(--fold-space-md)}.folddt-expand-h{width:1%}.folddt-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.folddt-cell--expand{width:1%;text-align:right}.folddt-expand{display:grid;place-items:center;width:32px;height:32px;padding:0;border:1px solid var(--fold-color-border);border-radius:var(--fold-radius-pill);background:var(--fold-color-surface-card);color:var(--fold-color-text-muted);cursor:pointer}.folddt-expand:hover{color:var(--fold-color-text)}.folddt-card{position:relative}.folddt-expand--card{position:absolute;top:var(--fold-space-sm);right:var(--fold-space-sm)}\n"] }]
5957
- }], ctorParameters: () => [], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: true }] }], rowKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowKey", required: false }] }], rowTone: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowTone", required: false }] }], sort: [{ type: i0.Input, args: [{ isSignal: true, alias: "sort", required: false }] }], empty: [{ type: i0.Input, args: [{ isSignal: true, alias: "empty", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], caption: [{ type: i0.Input, args: [{ isSignal: true, alias: "caption", required: false }] }], clickable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clickable", required: false }] }], zebra: [{ type: i0.Input, args: [{ isSignal: true, alias: "zebra", required: false }] }], hover: [{ type: i0.Input, args: [{ isSignal: true, alias: "hover", required: false }] }], narrowLayout: [{ type: i0.Input, args: [{ isSignal: true, alias: "narrowLayout", required: false }] }], cardsAt: [{ type: i0.Input, args: [{ isSignal: true, alias: "cardsAt", required: false }] }], rowCardChrome: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowCardChrome", required: false }] }], mobileLayout: [{ type: i0.Input, args: [{ isSignal: true, alias: "mobileLayout", required: false }] }], density: [{ type: i0.Input, args: [{ isSignal: true, alias: "density", required: false }] }], stickyFirst: [{ type: i0.Input, args: [{ isSignal: true, alias: "stickyFirst", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }, { type: i0.Output, args: ["selectedChange"] }], selectionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionLabel", required: false }] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: false }] }], expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }, { type: i0.Output, args: ["expandedChange"] }], expandMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandMode", required: false }] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], cells: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => FoldDataTableCellDirective), { isSignal: true }] }], rowDetail: [{ type: i0.ContentChild, args: [i0.forwardRef(() => FoldDataTableRowDetailDirective), { isSignal: true }] }], rowCard: [{ type: i0.ContentChild, args: [i0.forwardRef(() => FoldDataTableRowCardDirective), { isSignal: true }] }], toolbarSurface: [{ type: i0.Input, args: [{ isSignal: true, alias: "toolbarSurface", required: false }] }] } });
6064
+ ], template: "<div\n class=\"folddt-wrap\"\n [class.folddt--zebra]=\"zebra()\"\n [class.folddt--hover]=\"hover()\"\n [class.folddt--narrow]=\"isNarrow()\"\n [class.folddt--compact]=\"density() === 'compact'\"\n [class.folddt--sticky-first]=\"stickyFirst()\"\n [class.folddt--select]=\"selectable()\"\n>\n <div\n class=\"folddt-toolbar\"\n [class.folddt-toolbar--sunken]=\"toolbarSurface() === 'sunken'\"\n [class.folddt-toolbar--raised]=\"toolbarSurface() === 'raised'\"\n [class.folddt-toolbar--accent]=\"toolbarSurface() === 'accent'\"\n [attr.data-surface]=\"toolbarSurface() === 'accent' ? 'accent' : null\"\n >\n <ng-content select=\"[foldToolbar]\" />\n </div>\n @if (!cardMode()) {\n <div class=\"folddt-scroll\">\n <table class=\"folddt\" [attr.aria-colcount]=\"colCount()\">\n @if (caption(); as cap) {\n <caption class=\"folddt-caption\">\n {{\n cap\n }}\n </caption>\n }\n <thead>\n <tr>\n @if (selectable()) {\n <th scope=\"col\" class=\"folddt-select-h\">\n <fold-checkbox\n size=\"sm\"\n [ariaLabel]=\"l().selectAll\"\n [checked]=\"allSelected()\"\n [indeterminate]=\"someSelected()\"\n (checkedChange)=\"toggleAll()\"\n />\n </th>\n }\n @for (col of columns(); track col.key) {\n <th\n scope=\"col\"\n [class.is-primary-h]=\"col.key === primaryKey()\"\n [style.width]=\"col.width || null\"\n [attr.aria-sort]=\"col.sortable ? ariaSort(col.key) : null\"\n >\n @if (col.sortable) {\n <button\n type=\"button\"\n class=\"folddt-th-sort\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n [attr.aria-label]=\"l().sortBy(col.label)\"\n (click)=\"sortChange.emit(col.key)\"\n >\n <span>{{ col.label }}</span>\n <fold-icon\n class=\"folddt-arrow\"\n [class.on]=\"isSorted(col.key)\"\n [name]=\"sortIcon(col.key)\"\n [size]=\"14\"\n />\n </button>\n } @else {\n <span\n class=\"folddt-th-plain\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n >{{ col.label }}</span\n >\n }\n </th>\n }\n @if (expandable()) {\n <!-- Une colonne sans nom : son en-t\u00EAte est vide \u00C0 DESSEIN, mais\n pas muette \u2014 le libell\u00E9 part en texte masqu\u00E9, sinon la\n derni\u00E8re colonne est annonc\u00E9e \u00AB colonne 8 \u00BB. -->\n <th scope=\"col\" class=\"folddt-expand-h\">\n <span class=\"folddt-sr\">{{ l().expandRow }}</span>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of rows(); track keyOf(row, $index); let i = $index) {\n @let tone = toneOf(row);\n <tr\n class=\"folddt-row\"\n [class.tone-warning]=\"tone === 'warning'\"\n [class.tone-alert]=\"tone === 'alert'\"\n [class.tone-success]=\"tone === 'success'\"\n [class.clickable]=\"clickable()\"\n [class.is-selected]=\"selectable() && isRowSelected(row, i)\"\n [attr.tabindex]=\"rowTabIndex(row, i)\"\n [attr.aria-selected]=\"selectable() ? isRowSelected(row, i) : null\"\n (click)=\"onRowActivate(row)\"\n (focus)=\"onRowFocus(row, i)\"\n (keydown)=\"onRowKeydown($event, row)\"\n >\n @if (selectable()) {\n <td class=\"folddt-cell folddt-cell--select\">\n <fold-checkbox\n size=\"sm\"\n [ariaLabel]=\"labelFor(row)\"\n [checked]=\"isRowSelected(row, i)\"\n (click)=\"$event.stopPropagation()\"\n (checkedChange)=\"toggleRow(row, i)\"\n />\n </td>\n }\n @for (col of columns(); track col.key) {\n @if (col.key === primaryKey()) {\n <th\n scope=\"row\"\n class=\"folddt-cell is-primary\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n [class.truncate]=\"col.truncate\"\n [ngClass]=\"col.cellClass || ''\"\n [attr.data-label]=\"col.label\"\n >\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </th>\n } @else {\n <td\n class=\"folddt-cell\"\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n [class.center]=\"col.align === 'center'\"\n [class.truncate]=\"col.truncate\"\n [ngClass]=\"col.cellClass || ''\"\n [attr.data-label]=\"col.label\"\n >\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </td>\n }\n }\n @if (expandable()) {\n <td class=\"folddt-cell folddt-cell--expand\">\n <button\n type=\"button\"\n class=\"folddt-expand\"\n [attr.aria-expanded]=\"isRowExpanded(row, i)\"\n [attr.aria-controls]=\"detailId(row, i)\"\n [attr.aria-label]=\"\n isRowExpanded(row, i) ? l().collapseRow : l().expandRow\n \"\n (click)=\"$event.stopPropagation(); toggleExpand(row, i)\"\n >\n <fold-icon\n [name]=\"\n isRowExpanded(row, i) ? 'chevron-up' : 'chevron-down'\n \"\n [size]=\"16\"\n />\n </button>\n </td>\n }\n </tr>\n <!-- \uD83D\uDD34 **La note n'est pas un tiroir.** Elle est toujours l\u00E0, donc\n elle ne porte ni bascule, ni `aria-expanded`, ni identifiant \u00E0\n contr\u00F4ler : il n'y a rien \u00E0 r\u00E9v\u00E9ler. Comme la rang\u00E9e du tiroir\n elle reste hors du groupe \u00E0 navigation par fl\u00E8ches \u2014 un arr\u00EAt\n de plus pour une ligne qu'on lit sans la parcourir. -->\n @if (hasNote(row, i)) {\n <tr class=\"folddt-note-row\">\n <td class=\"folddt-note\" [attr.colspan]=\"colCount()\">\n <ng-container\n [ngTemplateOutlet]=\"rowNoteTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </td>\n </tr>\n }\n @if (expandable() && isRowExpanded(row, i)) {\n <!-- La rang\u00E9e du tiroir ne porte PAS de `tabindex` : elle reste\n hors du groupe \u00E0 navigation par fl\u00E8ches, que les helpers\n savent enjamber. Une rang\u00E9e focusable de plus ferait deux\n arr\u00EAts pour une seule ligne de tableau. -->\n <tr class=\"folddt-detail-row\">\n <td\n class=\"folddt-detail\"\n [id]=\"detailId(row, i)\"\n [attr.colspan]=\"colCount()\"\n >\n <ng-container\n [ngTemplateOutlet]=\"rowDetailTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </td>\n </tr>\n }\n }\n </tbody>\n </table>\n </div>\n } @else {\n <!-- `role=\"list\"` on a <ul> looks redundant and is not: `list-style: none`\n strips list semantics in Safari, which is exactly what the styling\n does. One list, one shell \u2014 the projected template supplies the\n CONTENT, the shell supplies the chrome (outline, tone, selection), so a\n consumer never reinvents them. -->\n <ul class=\"folddt-cardlist\" role=\"list\">\n @for (row of rows(); track keyOf(row, $index); let i = $index) {\n @let tone = toneOf(row);\n <li\n class=\"folddt-card\"\n [class.is-bare]=\"rowCardChrome() === 'none' && rowCardTemplate()\"\n [class.tone-warning]=\"tone === 'warning'\"\n [class.tone-alert]=\"tone === 'alert'\"\n [class.tone-success]=\"tone === 'success'\"\n [class.is-selected]=\"selectable() && isRowSelected(row, i)\"\n [attr.aria-selected]=\"selectable() ? isRowSelected(row, i) : null\"\n >\n @if (\n selectable() && !(rowCardChrome() === \"none\" && rowCardTemplate())\n ) {\n <fold-checkbox\n class=\"folddt-card-select\"\n size=\"sm\"\n [ariaLabel]=\"labelFor(row)\"\n [checked]=\"isRowSelected(row, i)\"\n (click)=\"$event.stopPropagation()\"\n (checkedChange)=\"toggleRow(row, i)\"\n />\n }\n <div class=\"folddt-card-body\">\n @if (rowCardTemplate(); as card) {\n <ng-container\n [ngTemplateOutlet]=\"card\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n @if (overlineColumn(); as col) {\n <p class=\"folddt-card-overline\">\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </p>\n }\n @if (identityColumn(); as col) {\n <p class=\"folddt-card-identity\">\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </p>\n }\n <!-- A <dl> and not a `::before { content: attr(data-label) }`:\n generated content is not reliably announced, and a label/value\n pair IS a description list. It also lets the values line up in\n columns, which matters for amounts. -->\n <dl class=\"folddt-card-grid\">\n @for (col of gridColumns(); track col.key) {\n <!-- A <div> around each pair is valid inside a <dl> and is\n what puts the label ABOVE its value in one grid cell. -->\n <div class=\"folddt-card-pair\">\n <dt>{{ col.label }}</dt>\n <dd\n [class.is-numeric]=\"col.numeric\"\n [class.right]=\"col.align === 'right'\"\n >\n @if (cellTemplate(col.key); as cell) {\n <ng-container\n [ngTemplateOutlet]=\"cell\"\n [ngTemplateOutletContext]=\"{\n $implicit: row,\n index: i,\n }\"\n />\n } @else {\n {{ cellText(col, row) }}\n }\n </dd>\n </div>\n }\n </dl>\n }\n <!-- Dans la carte, la note suit les champs de la ligne : m\u00EAme\n promesse qu'en vue large, elle se lit avec la ligne et non\n ailleurs. -->\n @if (hasNote(row, i)) {\n <div class=\"folddt-note folddt-note--card\">\n <ng-container\n [ngTemplateOutlet]=\"rowNoteTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </div>\n }\n @if (expandable()) {\n <button\n type=\"button\"\n class=\"folddt-expand folddt-expand--card\"\n [attr.aria-expanded]=\"isRowExpanded(row, i)\"\n [attr.aria-controls]=\"detailId(row, i)\"\n [attr.aria-label]=\"\n isRowExpanded(row, i) ? l().collapseRow : l().expandRow\n \"\n (click)=\"toggleExpand(row, i)\"\n >\n <fold-icon\n [name]=\"isRowExpanded(row, i) ? 'chevron-up' : 'chevron-down'\"\n [size]=\"16\"\n />\n </button>\n @if (isRowExpanded(row, i)) {\n <!-- DANS la carte, et non sous la liste : c'est la m\u00EAme\n promesse que sur la table large \u2014 on ouvre une ligne sans\n quitter la place qu'on a mis du temps \u00E0 trouver. -->\n <div class=\"folddt-detail\" [id]=\"detailId(row, i)\">\n <ng-container\n [ngTemplateOutlet]=\"rowDetailTemplate()!\"\n [ngTemplateOutletContext]=\"{ $implicit: row, index: i }\"\n />\n </div>\n }\n }\n </div>\n </li>\n }\n </ul>\n }\n\n @if (loading()) {\n <div class=\"folddt-loading\">\n <fold-spinner [label]=\"l().loading\" />\n </div>\n } @else if (rows().length === 0 && empty(); as e) {\n <div class=\"folddt-empty\">\n <div class=\"folddt-empty-t\">{{ e.title }}</div>\n @if (e.subtitle) {\n <div class=\"folddt-empty-s\">{{ e.subtitle }}</div>\n }\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;min-height:0}.folddt-wrap{--folddt-sel-w: 0px;display:flex;flex-direction:column;flex:1 1 auto;min-height:0;overflow:hidden;border:1px solid var(--fold-color-border-subtle);border-radius:var(--fold-radius-lg);background:var(--fold-color-surface-sunken);box-shadow:var(--fold-shadow-md)}.folddt--select{--folddt-sel-w: 44px}.folddt-scroll{flex:1 1 auto;min-height:0;overflow:auto}.folddt-toolbar{padding:var(--fold-space-md) var(--fold-space-lg);border-bottom:1px solid var(--fold-color-border);color:var(--fold-color-text);background:color-mix(in srgb,var(--fold-color-surface-sunken) 50%,var(--fold-color-surface-card))}.folddt-toolbar:not(:has(*)){display:none}.folddt-toolbar--sunken{background:var(--fold-color-surface-sunken)}.folddt-toolbar--raised{background:var(--fold-color-surface-raised)}.folddt-toolbar--accent{background:var(--fold-color-primary);border-bottom-color:var(--fold-color-primary);color:var(--fold-color-on-primary)}.folddt{width:100%;border-collapse:separate;border-spacing:0;font-size:var(--fold-text-sm)}.folddt-caption{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.folddt thead th{position:sticky;top:0;z-index:2;padding:0;text-align:left;background:color-mix(in srgb,var(--fold-color-surface-sunken) 50%,var(--fold-color-surface-card));border-bottom:1px solid var(--fold-color-border)}.folddt-th-sort,.folddt-th-plain{display:inline-flex;align-items:center;padding:var(--fold-space-md) var(--fold-space-lg);color:var(--fold-color-text-muted);font-family:var(--fold-font-label);font-size:var(--fold-text-2xs);font-weight:var(--fold-weight-bold);text-transform:uppercase;letter-spacing:var(--fold-tracking-caps)}.folddt-th-sort{gap:var(--fold-space-sm);width:100%;border:0;background:transparent;cursor:pointer;transition:color var(--fold-motion-fast)}.folddt-th-sort:hover{color:var(--fold-color-text)}.folddt-th-sort.is-numeric,.folddt-th-sort.right{justify-content:flex-end}.folddt-th-plain.is-numeric,.folddt-th-plain.right{justify-content:flex-end;width:100%}.folddt-arrow{display:inline-flex;color:var(--fold-color-text-faded);transition:color var(--fold-motion-fast)}.folddt-arrow.on{color:var(--fold-color-primary-text)}.folddt-row .folddt-cell{background:var(--fold-data-table-row-bg, transparent)}.folddt-row{transition:background var(--fold-motion-fast)}.folddt-row.clickable{cursor:pointer}.folddt-row .folddt-cell{border-bottom:1px solid var(--fold-color-border-subtle)}.folddt-row:last-child .folddt-cell{border-bottom:0}.folddt-row:focus-visible{outline:2px solid var(--fold-color-primary-border);outline-offset:-2px}.folddt--zebra .folddt-row:nth-child(2n of.folddt-row):not(.tone-warning):not(.tone-alert):not(.tone-success) .folddt-cell{background:var(--fold-color-surface-subtle)}.folddt--zebra .folddt-row .folddt-cell{border-bottom-color:transparent}.folddt--hover .folddt-row:hover .folddt-cell{background:var(--fold-data-table-row-hover-bg, var(--fold-color-surface-raised))}.folddt--hover .folddt-row.tone-warning:hover .folddt-cell{background:color-mix(in srgb,var(--fold-color-warning) 16%,transparent)}.folddt--hover .folddt-row.tone-alert:hover .folddt-cell{background:color-mix(in srgb,var(--fold-color-alert) 17%,transparent)}.folddt-cell{padding:var(--fold-space-md) var(--fold-space-lg);color:var(--fold-color-text);font-weight:inherit;text-align:left;white-space:nowrap;vertical-align:middle}.folddt-cell.is-numeric{text-align:right;font-variant-numeric:tabular-nums}.folddt-cell.right{text-align:right}.folddt-cell.center{text-align:center}.folddt-cell.truncate{max-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.folddt-row.tone-warning .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-warning)}.folddt-row.tone-warning .folddt-cell{background:color-mix(in srgb,var(--fold-color-warning) 10%,transparent)}.folddt-row.tone-alert .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-alert)}.folddt-row.tone-alert .folddt-cell{background:color-mix(in srgb,var(--fold-color-alert) 11%,transparent)}.folddt-row.tone-success .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-success)}.folddt-row.tone-success .folddt-cell{background:color-mix(in srgb,var(--fold-color-success) 9%,transparent)}.folddt-loading{display:flex;align-items:center;justify-content:center;padding:var(--fold-space-5xl) var(--fold-space-2xl)}.folddt-empty{padding:var(--fold-space-5xl) var(--fold-space-2xl);text-align:center}.folddt-empty-t{font-size:var(--fold-text-base);font-weight:var(--fold-weight-semibold);color:var(--fold-color-text)}.folddt-empty-s{font-size:var(--fold-text-sm);color:var(--fold-color-text-muted);margin-top:var(--fold-space-xs)}.folddt-cardlist{display:flex;flex-direction:column;margin:0;padding:0;list-style:none}.folddt-card{display:flex;gap:var(--fold-space-md);align-items:flex-start;padding:var(--fold-space-md) var(--fold-space-lg);background:var(--fold-color-surface-card);border:1px solid var(--fold-color-border);border-radius:var(--fold-radius-lg);box-shadow:var(--fold-shadow-sm)}.folddt-card-body{flex:1 1 auto;min-width:0}.folddt-card.tone-warning{border-inline-start:3px solid var(--fold-color-warning)}.folddt-card.tone-alert{border-inline-start:3px solid var(--fold-color-alert)}.folddt-card.tone-success{border-inline-start:3px solid var(--fold-color-success)}.folddt-card.is-selected{background:var(--fold-color-primary-surface);border-color:var(--fold-color-primary)}.folddt-card.is-bare,.folddt-card.is-bare.is-selected,.folddt-card.is-bare.tone-warning,.folddt-card.is-bare.tone-alert,.folddt-card.is-bare.tone-success{padding:0;background:none;border:0;border-radius:0;box-shadow:none}.folddt-select-h,.folddt-cell--select{width:var(--folddt-sel-w);padding-left:var(--fold-space-lg);padding-right:0;text-align:left;white-space:nowrap}.folddt-select-h{vertical-align:middle}.folddt-row.is-selected .folddt-cell{background:color-mix(in srgb,var(--fold-color-primary) 8%,transparent)}.folddt-row.is-selected .folddt-cell:first-child{box-shadow:inset 3px 0 0 var(--fold-color-primary)}.folddt--compact .folddt-cell,.folddt--compact .folddt-th-sort,.folddt--compact .folddt-th-plain{padding:var(--fold-space-sm) var(--fold-space-md)}.folddt--compact .folddt-cell--select{padding-left:var(--fold-space-md);padding-right:0}.folddt--sticky-first .folddt-cell--select,.folddt--sticky-first .folddt-select-h{position:sticky;left:0;background:var(--fold-color-surface-sunken)}.folddt--sticky-first .folddt-select-h{z-index:3}.folddt--sticky-first .folddt-cell.is-primary{position:sticky;left:var(--folddt-sel-w);z-index:1;background:var(--fold-color-surface-sunken)}.folddt--sticky-first thead th.is-primary-h{position:sticky;left:var(--folddt-sel-w);z-index:3}.folddt--sticky-first .folddt-row.tone-warning .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-warning) 10%,var(--fold-color-surface-sunken))}.folddt--sticky-first .folddt-row.tone-alert .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-alert) 11%,var(--fold-color-surface-sunken))}.folddt--sticky-first .folddt-row.tone-success .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-success) 9%,var(--fold-color-surface-sunken))}.folddt--sticky-first .folddt-row.is-selected .folddt-cell.is-primary{background:color-mix(in srgb,var(--fold-color-primary) 8%,var(--fold-color-surface-sunken))}@media(prefers-reduced-motion:reduce){.folddt-row,.folddt-th-sort,.folddt-arrow{transition:none}}@media(forced-colors:active){.folddt-row.is-selected .folddt-cell:first-child,.folddt-row.tone-warning .folddt-cell:first-child,.folddt-row.tone-alert .folddt-cell:first-child,.folddt-row.tone-success .folddt-cell:first-child{border-inline-start:3px solid Highlight}.folddt-row:focus-visible{outline-color:Highlight}}.folddt-cardlist{gap:var(--fold-space-sm)}.folddt-card-overline{margin:0 0 var(--fold-space-xs);color:var(--fold-color-text-muted);font-size:var(--fold-text-xs);font-weight:var(--fold-weight-medium);overflow-wrap:anywhere}.folddt-card-identity{margin:0;color:var(--fold-color-text);font-size:var(--fold-text-base);font-weight:var(--fold-weight-semibold);letter-spacing:var(--fold-tracking-tight)}.folddt-card-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--fold-space-sm) var(--fold-space-md);margin:var(--fold-space-md) 0 0}.folddt-card-pair{min-width:0}.folddt-card-grid dt{color:var(--fold-color-text-muted);font-size:var(--fold-text-2xs);font-weight:var(--fold-weight-bold);letter-spacing:var(--fold-tracking-caps);text-transform:uppercase}.folddt-card-grid dd{margin:var(--fold-space-xs) 0 0;color:var(--fold-color-text);font-size:var(--fold-text-sm)}.folddt-card-grid dd.is-numeric{font-variant-numeric:tabular-nums;text-align:right}.folddt-card-grid dd.right{font-variant-numeric:tabular-nums}.folddt-detail-row>.folddt-detail{border-top:0;background:var(--fold-data-table-detail-bg, var(--fold-color-surface-sunken));box-shadow:inset 0 1px 0 var(--fold-color-border-subtle)}.folddt-detail{padding:var(--fold-data-table-detail-padding, var(--fold-space-md) var(--fold-space-lg))}.folddt-note{padding:var(--fold-data-table-note-padding, 0 var(--fold-space-lg) var(--fold-space-sm))}.folddt-note-row>.folddt-note{border-top:0}.folddt-note--card{margin-top:var(--fold-space-sm)}.folddt-cardlist .folddt-detail{margin-top:var(--fold-space-sm);border-radius:var(--fold-radius-md);background:var(--fold-data-table-detail-bg, var(--fold-color-surface-sunken));padding:var(--fold-space-md)}.folddt-expand-h{width:1%}.folddt-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.folddt-cell--expand{width:1%;text-align:right}.folddt-expand{display:grid;place-items:center;width:32px;height:32px;padding:0;border:1px solid var(--fold-color-border);border-radius:var(--fold-radius-pill);background:var(--fold-color-surface-card);color:var(--fold-color-text-muted);cursor:pointer}.folddt-expand:hover{color:var(--fold-color-text)}.folddt-card{position:relative}.folddt-expand--card{position:absolute;top:var(--fold-space-sm);right:var(--fold-space-sm)}\n"] }]
6065
+ }], ctorParameters: () => [], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: true }] }], rowKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowKey", required: false }] }], rowTone: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowTone", required: false }] }], rowNote: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowNote", required: false }] }], sort: [{ type: i0.Input, args: [{ isSignal: true, alias: "sort", required: false }] }], empty: [{ type: i0.Input, args: [{ isSignal: true, alias: "empty", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], caption: [{ type: i0.Input, args: [{ isSignal: true, alias: "caption", required: false }] }], clickable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clickable", required: false }] }], zebra: [{ type: i0.Input, args: [{ isSignal: true, alias: "zebra", required: false }] }], hover: [{ type: i0.Input, args: [{ isSignal: true, alias: "hover", required: false }] }], narrowLayout: [{ type: i0.Input, args: [{ isSignal: true, alias: "narrowLayout", required: false }] }], cardsAt: [{ type: i0.Input, args: [{ isSignal: true, alias: "cardsAt", required: false }] }], rowCardChrome: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowCardChrome", required: false }] }], mobileLayout: [{ type: i0.Input, args: [{ isSignal: true, alias: "mobileLayout", required: false }] }], density: [{ type: i0.Input, args: [{ isSignal: true, alias: "density", required: false }] }], stickyFirst: [{ type: i0.Input, args: [{ isSignal: true, alias: "stickyFirst", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }, { type: i0.Output, args: ["selectedChange"] }], selectionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionLabel", required: false }] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: false }] }], expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }, { type: i0.Output, args: ["expandedChange"] }], expandMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandMode", required: false }] }], sortChange: [{ type: i0.Output, args: ["sortChange"] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], cells: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => FoldDataTableCellDirective), { isSignal: true }] }], rowNoteTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => FoldDataTableRowNoteDirective), { isSignal: true }] }], rowDetail: [{ type: i0.ContentChild, args: [i0.forwardRef(() => FoldDataTableRowDetailDirective), { isSignal: true }] }], rowCard: [{ type: i0.ContentChild, args: [i0.forwardRef(() => FoldDataTableRowCardDirective), { isSignal: true }] }], toolbarSurface: [{ type: i0.Input, args: [{ isSignal: true, alias: "toolbarSurface", required: false }] }] } });
5958
6066
 
5959
6067
  /**
5960
6068
  * `[foldStickyColumn]` — turns its host into a sticky side column: a vertical
@@ -9293,23 +9401,54 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
9293
9401
  }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], optional: [{ type: i0.Input, args: [{ isSignal: true, alias: "optional", required: false }] }], optionalLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionalLabel", required: false }] }], info: [{ type: i0.Input, args: [{ isSignal: true, alias: "info", required: false }] }], infoLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "infoLabel", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], readOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readOnly", required: false }] }] } });
9294
9402
 
9295
9403
  /**
9296
- * `<fold-search>` — an {@link FoldInputComponent} that **debounces its emit**: it
9297
- * fires `searchChange` only once typing pauses for `delayMs`, so a fast typer
9298
- * triggers one query instead of one per keystroke. The delay is adjustable; the
9299
- * emitted term is trimmed and de-duplicated (no emit when the settled value is
9300
- * unchanged). A thin wrapper over the text input — the search *behaviour*, not a
9301
- * new control.
9404
+ * `<fold-search>` — a search box: the magnifier, the clear `×`, an optional
9405
+ * **announced result count**, and a **debounced emit**. `searchChange` fires only once typing pauses for
9406
+ * `delayMs`, so a fast typer triggers one query instead of one per keystroke;
9407
+ * the emitted term is trimmed and de-duplicated.
9408
+ *
9409
+ * `value` is a `model()`, and that is what makes it a control rather than a
9410
+ * one-way sensor. Bind it and the box becomes **steerable from outside** —
9411
+ * picking a filter elsewhere can empty the field, which a write-only search
9412
+ * cannot do: it would keep showing a term the results no longer honour.
9413
+ *
9414
+ * Two ways to use it, and they answer different questions:
9415
+ *
9416
+ * - `[(value)]` — the term as **state**, updated on every keystroke. Filtering
9417
+ * an array already in memory wants this; a debounce there only adds lag.
9418
+ * - `(searchChange)` — the term as an **event**, once it settles. A request to
9419
+ * a server wants this.
9420
+ *
9421
+ * They compose: bind both when a screen filters locally *and* refetches.
9422
+ * Writing `value` from outside never emits `searchChange` — whoever wrote it
9423
+ * already knows.
9302
9424
  *
9303
9425
  * @selector `fold-search`
9304
9426
  *
9305
9427
  * @example
9306
9428
  * ```html
9429
+ * <!-- Local filtering, instant, with the count beside the box -->
9430
+ * <fold-search
9431
+ * placeholder="Filter…"
9432
+ * [(value)]="term"
9433
+ * [resultCount]="rows().length"
9434
+ * resultLabel="rows" />
9435
+ *
9436
+ * <!-- Remote query, once typing settles -->
9307
9437
  * <fold-search
9308
9438
  * placeholder="Search name, email, job…"
9309
9439
  * (searchChange)="store.setSearch($event)" />
9310
9440
  * ```
9311
9441
  */
9312
9442
  class FoldSearchComponent {
9443
+ /**
9444
+ * The term in the box — the SOURCE of truth, not a copy of it.
9445
+ *
9446
+ * Two-way, so a screen can clear or preset it: choosing a category that
9447
+ * supersedes the search empties the field in the same gesture, instead of
9448
+ * leaving a stale term above results that ignore it.
9449
+ */
9450
+ value = model("", /* @ts-ignore */
9451
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
9313
9452
  placeholder = input("", /* @ts-ignore */
9314
9453
  ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
9315
9454
  size = input("md", /* @ts-ignore */
@@ -9318,18 +9457,74 @@ class FoldSearchComponent {
9318
9457
  * forms; `default` elsewhere). */
9319
9458
  variant = input("default", /* @ts-ignore */
9320
9459
  ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
9460
+ /**
9461
+ * Accessible name, when the design leaves no room for a visible label — the
9462
+ * magnifier is decorative and names nothing.
9463
+ */
9464
+ ariaLabel = input(undefined, /* @ts-ignore */
9465
+ ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
9466
+ /** The `×` that empties the box. On by default: it is what a search box is. */
9467
+ clearable = input(true, { ...(ngDevMode ? { debugName: "clearable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
9468
+ /** Accessible name of the clear button. Override it to translate. */
9469
+ clearLabel = input("Clear search", /* @ts-ignore */
9470
+ ...(ngDevMode ? [{ debugName: "clearLabel" }] : /* istanbul ignore next */ []));
9471
+ /**
9472
+ * How many results the term found — `null` (the default) shows nothing.
9473
+ *
9474
+ * It belongs here rather than beside the box because it is the ANSWER to what
9475
+ * the box asked, and because every screen that wrote it by hand forgot the
9476
+ * same thing: a count that changes under a search has to be **announced**.
9477
+ * It carries `role="status"` and `aria-live="polite"`, so a user who cannot
9478
+ * see the grid still learns that four hundred rows became three.
9479
+ */
9480
+ resultCount = input(null, /* @ts-ignore */
9481
+ ...(ngDevMode ? [{ debugName: "resultCount" }] : /* istanbul ignore next */ []));
9482
+ /**
9483
+ * The word after the number — « pièces », "results", "matches".
9484
+ *
9485
+ * A plain string and not a template: the count reads `12 pièces`, and a
9486
+ * language that needs another order or a plural rule formats the whole thing
9487
+ * upstream and passes it as {@link resultLabel} with `resultCount` left null…
9488
+ * which it cannot. So: this covers `<number> <word>`, and anything else stays
9489
+ * the consumer's own markup beside the box.
9490
+ */
9491
+ resultLabel = input("results", /* @ts-ignore */
9492
+ ...(ngDevMode ? [{ debugName: "resultLabel" }] : /* istanbul ignore next */ []));
9493
+ /**
9494
+ * Where the count sits: above the box, after it on the same line, or below.
9495
+ *
9496
+ * `end` and not `right` — the whole library lays out in **logical**
9497
+ * properties, so the count follows the reading direction instead of pinning
9498
+ * itself to a side of the screen.
9499
+ */
9500
+ placement = input("end", /* @ts-ignore */
9501
+ ...(ngDevMode ? [{ debugName: "placement" }] : /* istanbul ignore next */ []));
9321
9502
  /** Quiet period after the last keystroke before emitting, in ms. */
9322
9503
  delayMs = input(300, /* @ts-ignore */
9323
9504
  ...(ngDevMode ? [{ debugName: "delayMs" }] : /* istanbul ignore next */ []));
9324
9505
  /** Emits the trimmed term once typing pauses for `delayMs` (deduped). */
9325
9506
  searchChange = output();
9507
+ showCount = computed(() => this.resultCount() !== null, /* @ts-ignore */
9508
+ ...(ngDevMode ? [{ debugName: "showCount" }] : /* istanbul ignore next */ []));
9509
+ countText = computed(() => `${String(this.resultCount() ?? 0)} ${this.resultLabel()}`, /* @ts-ignore */
9510
+ ...(ngDevMode ? [{ debugName: "countText" }] : /* istanbul ignore next */ []));
9326
9511
  timer = null;
9327
9512
  lastEmitted = "";
9328
9513
  constructor() {
9329
9514
  // A pending timer that outlives the view would fire a stray emit.
9330
9515
  inject(DestroyRef).onDestroy(() => this.clear());
9331
9516
  }
9517
+ /**
9518
+ * The value moves **now**, the event waits.
9519
+ *
9520
+ * The box must show what was typed on the keystroke — deferring the text
9521
+ * itself would make the field feel broken — while the query it triggers is
9522
+ * what deserves the quiet period. Clearing settles like any other edit: the
9523
+ * empty term goes out after the same delay, so a consumer sees one contract
9524
+ * and not two.
9525
+ */
9332
9526
  onInput(value) {
9527
+ this.value.set(value);
9333
9528
  const term = value.trim();
9334
9529
  this.clear();
9335
9530
  this.timer = setTimeout(() => {
@@ -9346,28 +9541,14 @@ class FoldSearchComponent {
9346
9541
  }
9347
9542
  }
9348
9543
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FoldSearchComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
9349
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.8", type: FoldSearchComponent, isStandalone: true, selector: "fold-search", inputs: { placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, delayMs: { classPropertyName: "delayMs", publicName: "delayMs", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { searchChange: "searchChange" }, ngImport: i0, template: `
9350
- <fold-input
9351
- type="text"
9352
- [placeholder]="placeholder()"
9353
- [size]="size()"
9354
- [variant]="variant()"
9355
- (valueChange)="onInput($event)"
9356
- />
9357
- `, isInline: true, styles: [":host{display:block}\n"], dependencies: [{ kind: "component", type: FoldInputComponent, selector: "fold-input", inputs: ["value", "disabled", "touched", "errors", "type", "revealable", "revealLabel", "hideLabel", "size", "align", "variant", "label", "required", "optional", "optionalLabel", "info", "infoLabel", "ariaLabel", "hint", "placeholder", "readOnly", "autofocus", "autocomplete"], outputs: ["valueChange", "touchedChange"] }] });
9544
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: FoldSearchComponent, isStandalone: true, selector: "fold-search", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, clearLabel: { classPropertyName: "clearLabel", publicName: "clearLabel", isSignal: true, isRequired: false, transformFunction: null }, resultCount: { classPropertyName: "resultCount", publicName: "resultCount", isSignal: true, isRequired: false, transformFunction: null }, resultLabel: { classPropertyName: "resultLabel", publicName: "resultLabel", isSignal: true, isRequired: false, transformFunction: null }, placement: { classPropertyName: "placement", publicName: "placement", isSignal: true, isRequired: false, transformFunction: null }, delayMs: { classPropertyName: "delayMs", publicName: "delayMs", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", searchChange: "searchChange" }, host: { properties: { "class": "placement()" } }, ngImport: i0, template: "@if (showCount() && placement() === \"top\") {\n <p class=\"se-count\" role=\"status\" aria-live=\"polite\">{{ countText() }}</p>\n}\n\n<fold-input\n type=\"text\"\n leadingIcon=\"search\"\n [clearable]=\"clearable()\"\n [clearLabel]=\"clearLabel()\"\n [placeholder]=\"placeholder()\"\n [ariaLabel]=\"ariaLabel()\"\n [size]=\"size()\"\n [variant]=\"variant()\"\n [value]=\"value()\"\n (valueChange)=\"onInput($event)\"\n/>\n\n@if (showCount() && placement() !== \"top\") {\n <p class=\"se-count\" role=\"status\" aria-live=\"polite\">{{ countText() }}</p>\n}\n", styles: [":host{display:grid;gap:var(--fold-space-2xs)}:host(.end){grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:var(--fold-space-sm)}.se-count{margin:0;font-size:var(--fold-text-xs);color:var(--fold-color-text-muted);white-space:nowrap}:host(.top) .se-count,:host(.bottom) .se-count{justify-self:end}\n"], dependencies: [{ kind: "component", type: FoldInputComponent, selector: "fold-input", inputs: ["value", "disabled", "touched", "errors", "type", "revealable", "revealLabel", "hideLabel", "size", "align", "variant", "label", "required", "optional", "optionalLabel", "info", "infoLabel", "ariaLabel", "hint", "placeholder", "leadingIcon", "clearable", "clearLabel", "readOnly", "autofocus", "autocomplete"], outputs: ["valueChange", "touchedChange"] }] });
9358
9545
  }
9359
9546
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FoldSearchComponent, decorators: [{
9360
9547
  type: Component,
9361
- args: [{ selector: "fold-search", standalone: true, imports: [FoldInputComponent], template: `
9362
- <fold-input
9363
- type="text"
9364
- [placeholder]="placeholder()"
9365
- [size]="size()"
9366
- [variant]="variant()"
9367
- (valueChange)="onInput($event)"
9368
- />
9369
- `, styles: [":host{display:block}\n"] }]
9370
- }], ctorParameters: () => [], propDecorators: { placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], delayMs: [{ type: i0.Input, args: [{ isSignal: true, alias: "delayMs", required: false }] }], searchChange: [{ type: i0.Output, args: ["searchChange"] }] } });
9548
+ args: [{ selector: "fold-search", standalone: true, imports: [FoldInputComponent], host: {
9549
+ "[class]": "placement()",
9550
+ }, template: "@if (showCount() && placement() === \"top\") {\n <p class=\"se-count\" role=\"status\" aria-live=\"polite\">{{ countText() }}</p>\n}\n\n<fold-input\n type=\"text\"\n leadingIcon=\"search\"\n [clearable]=\"clearable()\"\n [clearLabel]=\"clearLabel()\"\n [placeholder]=\"placeholder()\"\n [ariaLabel]=\"ariaLabel()\"\n [size]=\"size()\"\n [variant]=\"variant()\"\n [value]=\"value()\"\n (valueChange)=\"onInput($event)\"\n/>\n\n@if (showCount() && placement() !== \"top\") {\n <p class=\"se-count\" role=\"status\" aria-live=\"polite\">{{ countText() }}</p>\n}\n", styles: [":host{display:grid;gap:var(--fold-space-2xs)}:host(.end){grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:var(--fold-space-sm)}.se-count{margin:0;font-size:var(--fold-text-xs);color:var(--fold-color-text-muted);white-space:nowrap}:host(.top) .se-count,:host(.bottom) .se-count{justify-self:end}\n"] }]
9551
+ }], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], clearLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearLabel", required: false }] }], resultCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "resultCount", required: false }] }], resultLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "resultLabel", required: false }] }], placement: [{ type: i0.Input, args: [{ isSignal: true, alias: "placement", required: false }] }], delayMs: [{ type: i0.Input, args: [{ isSignal: true, alias: "delayMs", required: false }] }], searchChange: [{ type: i0.Output, args: ["searchChange"] }] } });
9371
9552
 
9372
9553
  /**
9373
9554
  * `<fold-select>` — the dropdown sibling of {@link FoldInputComponent} and
@@ -10503,7 +10684,7 @@ class FoldPasswordFieldComponent {
10503
10684
  effect(() => this.validChange.emit(this.allValid()));
10504
10685
  }
10505
10686
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FoldPasswordFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
10506
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: FoldPasswordFieldComponent, isStandalone: true, selector: "fold-password-field", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, autocomplete: { classPropertyName: "autocomplete", publicName: "autocomplete", isSignal: true, isRequired: false, transformFunction: null }, revealable: { classPropertyName: "revealable", publicName: "revealable", isSignal: true, isRequired: false, transformFunction: null }, revealLabel: { classPropertyName: "revealLabel", publicName: "revealLabel", isSignal: true, isRequired: false, transformFunction: null }, hideLabel: { classPropertyName: "hideLabel", publicName: "hideLabel", isSignal: true, isRequired: false, transformFunction: null }, rules: { classPropertyName: "rules", publicName: "rules", isSignal: true, isRequired: false, transformFunction: null }, marker: { classPropertyName: "marker", publicName: "marker", isSignal: true, isRequired: false, transformFunction: null }, rulesLabel: { classPropertyName: "rulesLabel", publicName: "rulesLabel", isSignal: true, isRequired: false, transformFunction: null }, metLabel: { classPropertyName: "metLabel", publicName: "metLabel", isSignal: true, isRequired: false, transformFunction: null }, unmetLabel: { classPropertyName: "unmetLabel", publicName: "unmetLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange", validChange: "validChange" }, exportAs: ["foldPasswordField"], ngImport: i0, template: "<fold-input\n type=\"password\"\n [label]=\"label()\"\n [placeholder]=\"placeholder()\"\n [hint]=\"hint()\"\n [required]=\"required()\"\n [size]=\"size()\"\n [variant]=\"variant()\"\n [disabled]=\"disabled()\"\n [revealable]=\"revealable()\"\n [revealLabel]=\"revealLabel()\"\n [hideLabel]=\"hideLabel()\"\n [autocomplete]=\"autocomplete()\"\n [errors]=\"errors()\"\n [(value)]=\"value\"\n [(touched)]=\"touched\"\n/>\n\n<!-- Project into `[rules]` to redesign the checklist off the same state\n (`#pw=\"foldPasswordField\"` \u2192 `pw.checklist()`); otherwise the default list\n below is the fallback content. -->\n<ng-content select=\"[rules]\">\n @if (checklist().length) {\n <ul class=\"pw-rules\" [attr.aria-label]=\"rulesLabel()\" aria-live=\"polite\">\n @for (rule of checklist(); track rule.label) {\n <li class=\"pw-rule\" [class.is-met]=\"rule.met\">\n @if (marker() === \"check\") {\n <span class=\"pw-mark\" aria-hidden=\"true\">\n @if (rule.met) {\n <fold-icon name=\"check\" size=\"sm\" />\n }\n </span>\n } @else {\n <span class=\"pw-dot\" aria-hidden=\"true\"></span>\n }\n <span class=\"pw-rule-label\">{{ rule.label }}</span>\n <!-- The met/unmet word is real text (not just an attribute), so the\n aria-live region actually announces a rule flipping. -->\n <span class=\"pw-sr\"\n >\u2014 {{ rule.met ? metLabel() : unmetLabel() }}</span\n >\n </li>\n }\n </ul>\n }\n</ng-content>\n", styles: [":host{display:block}.pw-rules{list-style:none;margin:.5rem 0 0;padding:0;display:flex;flex-direction:column;gap:.25rem}.pw-rule{display:flex;align-items:center;gap:.45rem;font-size:var(--fold-text-xs);color:var(--fold-color-text-muted);transition:color var(--fold-motion-fast)}.pw-dot{flex:none;width:.5rem;height:.5rem;border-radius:var(--fold-radius-round);border:1.5px solid var(--fold-color-text-faded);box-sizing:border-box;transition:background var(--fold-motion-fast),border-color var(--fold-motion-fast)}.pw-rule.is-met{color:var(--fold-color-text)}.pw-rule.is-met .pw-dot{border-color:var(--fold-color-primary);background:var(--fold-color-primary)}.pw-mark{flex:none;width:.85rem;height:.85rem;display:grid;place-items:center;color:var(--fold-color-primary)}.pw-rule:not(.is-met) .pw-mark{border:1.5px solid var(--fold-color-text-faded);border-radius:var(--fold-radius-round);box-sizing:border-box}@media(forced-colors:active){.pw-rule.is-met .pw-dot{background:Highlight;border-color:Highlight}.pw-mark{color:Highlight}}.pw-sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}\n"], dependencies: [{ kind: "component", type: FoldInputComponent, selector: "fold-input", inputs: ["value", "disabled", "touched", "errors", "type", "revealable", "revealLabel", "hideLabel", "size", "align", "variant", "label", "required", "optional", "optionalLabel", "info", "infoLabel", "ariaLabel", "hint", "placeholder", "readOnly", "autofocus", "autocomplete"], outputs: ["valueChange", "touchedChange"] }, { kind: "component", type: FoldIconComponent, selector: "fold-icon", inputs: ["name", "size", "tone", "title"] }] });
10687
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: FoldPasswordFieldComponent, isStandalone: true, selector: "fold-password-field", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, autocomplete: { classPropertyName: "autocomplete", publicName: "autocomplete", isSignal: true, isRequired: false, transformFunction: null }, revealable: { classPropertyName: "revealable", publicName: "revealable", isSignal: true, isRequired: false, transformFunction: null }, revealLabel: { classPropertyName: "revealLabel", publicName: "revealLabel", isSignal: true, isRequired: false, transformFunction: null }, hideLabel: { classPropertyName: "hideLabel", publicName: "hideLabel", isSignal: true, isRequired: false, transformFunction: null }, rules: { classPropertyName: "rules", publicName: "rules", isSignal: true, isRequired: false, transformFunction: null }, marker: { classPropertyName: "marker", publicName: "marker", isSignal: true, isRequired: false, transformFunction: null }, rulesLabel: { classPropertyName: "rulesLabel", publicName: "rulesLabel", isSignal: true, isRequired: false, transformFunction: null }, metLabel: { classPropertyName: "metLabel", publicName: "metLabel", isSignal: true, isRequired: false, transformFunction: null }, unmetLabel: { classPropertyName: "unmetLabel", publicName: "unmetLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange", validChange: "validChange" }, exportAs: ["foldPasswordField"], ngImport: i0, template: "<fold-input\n type=\"password\"\n [label]=\"label()\"\n [placeholder]=\"placeholder()\"\n [hint]=\"hint()\"\n [required]=\"required()\"\n [size]=\"size()\"\n [variant]=\"variant()\"\n [disabled]=\"disabled()\"\n [revealable]=\"revealable()\"\n [revealLabel]=\"revealLabel()\"\n [hideLabel]=\"hideLabel()\"\n [autocomplete]=\"autocomplete()\"\n [errors]=\"errors()\"\n [(value)]=\"value\"\n [(touched)]=\"touched\"\n/>\n\n<!-- Project into `[rules]` to redesign the checklist off the same state\n (`#pw=\"foldPasswordField\"` \u2192 `pw.checklist()`); otherwise the default list\n below is the fallback content. -->\n<ng-content select=\"[rules]\">\n @if (checklist().length) {\n <ul class=\"pw-rules\" [attr.aria-label]=\"rulesLabel()\" aria-live=\"polite\">\n @for (rule of checklist(); track rule.label) {\n <li class=\"pw-rule\" [class.is-met]=\"rule.met\">\n @if (marker() === \"check\") {\n <span class=\"pw-mark\" aria-hidden=\"true\">\n @if (rule.met) {\n <fold-icon name=\"check\" size=\"sm\" />\n }\n </span>\n } @else {\n <span class=\"pw-dot\" aria-hidden=\"true\"></span>\n }\n <span class=\"pw-rule-label\">{{ rule.label }}</span>\n <!-- The met/unmet word is real text (not just an attribute), so the\n aria-live region actually announces a rule flipping. -->\n <span class=\"pw-sr\"\n >\u2014 {{ rule.met ? metLabel() : unmetLabel() }}</span\n >\n </li>\n }\n </ul>\n }\n</ng-content>\n", styles: [":host{display:block}.pw-rules{list-style:none;margin:.5rem 0 0;padding:0;display:flex;flex-direction:column;gap:.25rem}.pw-rule{display:flex;align-items:center;gap:.45rem;font-size:var(--fold-text-xs);color:var(--fold-color-text-muted);transition:color var(--fold-motion-fast)}.pw-dot{flex:none;width:.5rem;height:.5rem;border-radius:var(--fold-radius-round);border:1.5px solid var(--fold-color-text-faded);box-sizing:border-box;transition:background var(--fold-motion-fast),border-color var(--fold-motion-fast)}.pw-rule.is-met{color:var(--fold-color-text)}.pw-rule.is-met .pw-dot{border-color:var(--fold-color-primary);background:var(--fold-color-primary)}.pw-mark{flex:none;width:.85rem;height:.85rem;display:grid;place-items:center;color:var(--fold-color-primary)}.pw-rule:not(.is-met) .pw-mark{border:1.5px solid var(--fold-color-text-faded);border-radius:var(--fold-radius-round);box-sizing:border-box}@media(forced-colors:active){.pw-rule.is-met .pw-dot{background:Highlight;border-color:Highlight}.pw-mark{color:Highlight}}.pw-sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}\n"], dependencies: [{ kind: "component", type: FoldInputComponent, selector: "fold-input", inputs: ["value", "disabled", "touched", "errors", "type", "revealable", "revealLabel", "hideLabel", "size", "align", "variant", "label", "required", "optional", "optionalLabel", "info", "infoLabel", "ariaLabel", "hint", "placeholder", "leadingIcon", "clearable", "clearLabel", "readOnly", "autofocus", "autocomplete"], outputs: ["valueChange", "touchedChange"] }, { kind: "component", type: FoldIconComponent, selector: "fold-icon", inputs: ["name", "size", "tone", "title"] }] });
10507
10688
  }
10508
10689
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: FoldPasswordFieldComponent, decorators: [{
10509
10690
  type: Component,
@@ -14885,5 +15066,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
14885
15066
  * Generated bundle index. Do not edit.
14886
15067
  */
14887
15068
 
14888
- export { FOLD_AUTO_PALETTES, FOLD_BLUR_TOKENS, FOLD_BUILTIN_ICONS, FOLD_BUILTIN_ICON_CATEGORIES, FOLD_CALENDAR_DEFAULT_LABELS, FOLD_CALENDAR_FORMATS, FOLD_CALENDAR_LABELS, FOLD_COMMON_DEFAULT_LABELS, FOLD_COMMON_LABELS, FOLD_DATA_TABLE_DEFAULT_LABELS, FOLD_DATA_TABLE_LABELS, FOLD_DEFAULT_WEEKEND_DAYS, FOLD_FALLBACK_WEEK_INFO, FOLD_FONT_TOKENS, FOLD_INLINE_CONFIRM_DEFAULT_LABELS, FOLD_INLINE_CONFIRM_LABELS, FOLD_LEADING_TOKENS, FOLD_MINUTES_PER_DAY, FOLD_MOTION_TOKENS, FOLD_PAGINATOR_DEFAULT_LABELS, FOLD_PAGINATOR_LABELS, FOLD_PALETTE_DEFAULT, FOLD_PANEL_CLOSE_LABEL, FOLD_PANEL_DEFAULTS, FOLD_RADIUS_TOKENS, FOLD_SEMANTIC_COLOR_TOKENS, FOLD_SHADOW_TOKENS, FOLD_SPACE_TOKENS, FOLD_TEXT_TOKENS, FOLD_TOAST_CONFIG, FOLD_TRACKING_TOKENS, FOLD_WEIGHT_TOKENS, FoldAppShellComponent, FoldAsideLayoutComponent, FoldAvatarComponent, FoldAvatarDetailComponent, FoldAvatarListComponent, FoldBackLinkComponent, FoldBadgeComponent, FoldBreadcrumbComponent, FoldButtonComponent, FoldButtonIconComponent, FoldCalendarAgendaComponent, FoldCalendarChromeDirective, FoldCalendarDayComponent, FoldCalendarDayDirective, FoldCalendarEventDirective, FoldCalendarHeadingDirective, FoldCalendarListComponent, FoldCalendarMonthComponent, FoldCalendarOverflowDirective, FoldCalendarSourceFilterComponent, FoldCalendarTimegridComponent, FoldCalendarTitleDirective, FoldCalendarToolbarComponent, FoldCalendarWeekComponent, FoldCalloutComponent, FoldCardComponent, FoldCheckboxComponent, FoldChecklistComponent, FoldChoiceRowComponent, FoldContextCardComponent, FoldDangerZoneComponent, FoldDataTableCellDirective, FoldDataTableComponent, FoldDataTableRowCardDirective, FoldDataTableRowDetailDirective, FoldDateComponent, FoldDisclosureComponent, FoldDropdownComponent, FoldDropdownItemComponent, FoldElementTitleComponent, FoldElevatedDirective, FoldEmptyStateComponent, FoldFieldComponent, FoldFieldIdDirective, FoldFieldListComponent, FoldFieldsetComponent, FoldFileDropzoneComponent, FoldHeroCardComponent, FoldHeroSectionComponent, FoldIconComponent, FoldIconRegistry, FoldIdService, FoldInfoComponent, FoldInlineConfirmComponent, FoldInputComponent, FoldLinkComponent, FoldListboxComponent, FoldLoadingStateComponent, FoldMenuComponent, FoldMenuItemComponent, FoldMenuSectionComponent, FoldMenuSeparatorComponent, FoldMeterComponent, FoldMultiselectComponent, FoldNavGroupComponent, FoldNavLauncherComponent, FoldNavLayoutComponent, FoldNavTileComponent, FoldNumberInputComponent, FoldOptgroupComponent, FoldOptionComponent, FoldPageLayoutComponent, FoldPageSectionComponent, FoldPageTitleDirective, FoldPaginatorComponent, FoldPaletteRegistry, FoldPanelBodyComponent, FoldPanelComponentOutletDirective, FoldPanelFooterComponent, FoldPanelHeaderComponent, FoldPanelHostComponent, FoldPanelHostService, FoldPanelRef, FoldPanelToggle, FoldPasswordFieldComponent, FoldPopoverComponent, FoldPopoverTriggerDirective, FoldRangeSliderComponent, FoldRepeatPressDirective, FoldScrollRegionDirective, FoldSearchComponent, FoldSelectComponent, FoldSliderComponent, FoldSpinnerComponent, FoldStatusBadgeComponent, FoldStickyColumnDirective, FoldSurfaceDirective, FoldTabPanelComponent, FoldTabsComponent, FoldTextareaComponent, FoldTimeComponent, FoldTimelineComponent, FoldToastComponent, FoldToastContainerComponent, FoldToastService, FoldToggleIconComponent, FoldViewNavComponent, FoldViewToggleComponent, ScrollRegionRegistry, autoUpdate, computePlacement, foldAddDays, foldAddMinutes, foldAddMonths, foldBlurVar, foldBuildAgenda, foldBuildDay, foldBuildMonthGrid, foldBuildTimeGrid, foldBuildWeek, foldCalendarNextFocus, foldCardBandChrome, foldColorProperty, foldColorVar, foldCountActionable, foldDaysBetween, foldDefaultPasswordRules, foldEndOfMonth, foldEventsInRange, foldEventsOnDay, foldFilterBySource, foldFontVar, foldFromMinutes, foldFromNativeDate, foldFromTemporal, foldHashSeed, foldIsActionable, foldIsCalendarDate, foldIsCalendarTime, foldIsTimed, foldIsWeekend, foldIsoWeek, foldIsoWeekYear, foldLayOutOverlaps, foldLeadingVar, foldLocaleWeekInfo, foldMotionVar, foldRadiusVar, foldRangeForView, foldRegexRule, foldResolvePalette, foldShadowVar, foldShiftDate, foldSpaceVar, foldStartOfMonth, foldStartOfWeek, foldTextVar, foldToMinutes, foldToNativeDate, foldToday, foldTrackingVar, foldViewTitle, foldWeekdayIndex, foldWeekdayOf, foldWeightVar, isFoldSelectOptionGroup, observeElementWidth, provideFoldCalendarLabels, provideFoldCommonLabels, provideFoldDataTableLabels, provideFoldIcons, provideFoldInlineConfirmLabels, provideFoldPaginatorLabels, provideFoldPalette, provideFoldPanelDefaults, provideFoldPanelLabels, provideFoldToasts };
15069
+ export { FOLD_AUTO_PALETTES, FOLD_BLUR_TOKENS, FOLD_BUILTIN_ICONS, FOLD_BUILTIN_ICON_CATEGORIES, FOLD_CALENDAR_DEFAULT_LABELS, FOLD_CALENDAR_FORMATS, FOLD_CALENDAR_LABELS, FOLD_COMMON_DEFAULT_LABELS, FOLD_COMMON_LABELS, FOLD_DATA_TABLE_DEFAULT_LABELS, FOLD_DATA_TABLE_LABELS, FOLD_DEFAULT_WEEKEND_DAYS, FOLD_FALLBACK_WEEK_INFO, FOLD_FONT_TOKENS, FOLD_INLINE_CONFIRM_DEFAULT_LABELS, FOLD_INLINE_CONFIRM_LABELS, FOLD_LEADING_TOKENS, FOLD_MINUTES_PER_DAY, FOLD_MOTION_TOKENS, FOLD_PAGINATOR_DEFAULT_LABELS, FOLD_PAGINATOR_LABELS, FOLD_PALETTE_DEFAULT, FOLD_PANEL_CLOSE_LABEL, FOLD_PANEL_DEFAULTS, FOLD_RADIUS_TOKENS, FOLD_SEMANTIC_COLOR_TOKENS, FOLD_SHADOW_TOKENS, FOLD_SPACE_TOKENS, FOLD_TEXT_TOKENS, FOLD_TOAST_CONFIG, FOLD_TRACKING_TOKENS, FOLD_WEIGHT_TOKENS, FoldAppShellComponent, FoldAsideLayoutComponent, FoldAvatarComponent, FoldAvatarDetailComponent, FoldAvatarListComponent, FoldBackLinkComponent, FoldBadgeComponent, FoldBreadcrumbComponent, FoldButtonComponent, FoldButtonIconComponent, FoldCalendarAgendaComponent, FoldCalendarChromeDirective, FoldCalendarDayComponent, FoldCalendarDayDirective, FoldCalendarEventDirective, FoldCalendarHeadingDirective, FoldCalendarListComponent, FoldCalendarMonthComponent, FoldCalendarOverflowDirective, FoldCalendarSourceFilterComponent, FoldCalendarTimegridComponent, FoldCalendarTitleDirective, FoldCalendarToolbarComponent, FoldCalendarWeekComponent, FoldCalloutComponent, FoldCardComponent, FoldCheckboxComponent, FoldChecklistComponent, FoldChoiceRowComponent, FoldContextCardComponent, FoldDangerZoneComponent, FoldDataTableCellDirective, FoldDataTableComponent, FoldDataTableRowCardDirective, FoldDataTableRowDetailDirective, FoldDataTableRowNoteDirective, FoldDateComponent, FoldDisclosureComponent, FoldDropdownComponent, FoldDropdownItemComponent, FoldElementTitleComponent, FoldElevatedDirective, FoldEmptyStateComponent, FoldFieldComponent, FoldFieldIdDirective, FoldFieldListComponent, FoldFieldsetComponent, FoldFileDropzoneComponent, FoldHeroCardComponent, FoldHeroSectionComponent, FoldIconComponent, FoldIconRegistry, FoldIdService, FoldInfoComponent, FoldInlineConfirmComponent, FoldInputComponent, FoldLinkComponent, FoldListboxComponent, FoldLoadingStateComponent, FoldMenuComponent, FoldMenuItemComponent, FoldMenuSectionComponent, FoldMenuSeparatorComponent, FoldMeterComponent, FoldMultiselectComponent, FoldNavGroupComponent, FoldNavLauncherComponent, FoldNavLayoutComponent, FoldNavTileComponent, FoldNumberInputComponent, FoldOptgroupComponent, FoldOptionComponent, FoldPageLayoutComponent, FoldPageSectionComponent, FoldPageTitleDirective, FoldPaginatorComponent, FoldPaletteRegistry, FoldPanelBodyComponent, FoldPanelComponentOutletDirective, FoldPanelFooterComponent, FoldPanelHeaderComponent, FoldPanelHostComponent, FoldPanelHostService, FoldPanelRef, FoldPanelToggle, FoldPasswordFieldComponent, FoldPopoverComponent, FoldPopoverTriggerDirective, FoldRangeSliderComponent, FoldRepeatPressDirective, FoldScrollRegionDirective, FoldSearchComponent, FoldSelectComponent, FoldSliderComponent, FoldSpinnerComponent, FoldStatusBadgeComponent, FoldStickyColumnDirective, FoldSurfaceDirective, FoldTabPanelComponent, FoldTabsComponent, FoldTextareaComponent, FoldTimeComponent, FoldTimelineComponent, FoldToastComponent, FoldToastContainerComponent, FoldToastService, FoldToggleIconComponent, FoldViewNavComponent, FoldViewToggleComponent, ScrollRegionRegistry, autoUpdate, computePlacement, foldAddDays, foldAddMinutes, foldAddMonths, foldBlurVar, foldBuildAgenda, foldBuildDay, foldBuildMonthGrid, foldBuildTimeGrid, foldBuildWeek, foldCalendarNextFocus, foldCardBandChrome, foldColorProperty, foldColorVar, foldCountActionable, foldDaysBetween, foldDefaultPasswordRules, foldEndOfMonth, foldEventsInRange, foldEventsOnDay, foldFilterBySource, foldFontVar, foldFromMinutes, foldFromNativeDate, foldFromTemporal, foldHashSeed, foldIsActionable, foldIsCalendarDate, foldIsCalendarTime, foldIsTimed, foldIsWeekend, foldIsoWeek, foldIsoWeekYear, foldLayOutOverlaps, foldLeadingVar, foldLocaleWeekInfo, foldMotionVar, foldRadiusVar, foldRangeForView, foldRegexRule, foldResolvePalette, foldShadowVar, foldShiftDate, foldSpaceVar, foldStartOfMonth, foldStartOfWeek, foldTextVar, foldToMinutes, foldToNativeDate, foldToday, foldTrackingVar, foldViewTitle, foldWeekdayIndex, foldWeekdayOf, foldWeightVar, isFoldSelectOptionGroup, observeElementWidth, provideFoldCalendarLabels, provideFoldCommonLabels, provideFoldDataTableLabels, provideFoldIcons, provideFoldInlineConfirmLabels, provideFoldPaginatorLabels, provideFoldPalette, provideFoldPanelDefaults, provideFoldPanelLabels, provideFoldToasts };
14889
15070
  //# sourceMappingURL=fold-ng.mjs.map