yukit-web 0.6.0 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -17,17 +17,16 @@ Angular UI component library for Yurest web applications. Built on [Spartan](htt
17
17
 
18
18
  ## Requirements
19
19
 
20
- | Dependency | Version | Notes |
21
- | :---------------------------------------------------------------- | :------ | :------------------------------- |
22
- | [Angular](https://angular.dev/) | 21+ | Standalone APIs, signal inputs |
23
- | [Tailwind CSS](https://tailwindcss.com/) | v4 | Required — see [Setup](#setup) |
24
- | [`@spartan-ng/brain`](https://spartan.ng) | ^1.3.0 | Headless primitives |
25
- | [`@angular/cdk`](https://material.angular.dev/cdk/categories) | ^21.0.0 | Overlays, a11y |
26
- | [`@ng-icons/core`](https://ng-icons.github.io/ng-icons/) + lucide | ^32.2.0 | Icons |
27
- | [`@tanstack/angular-table`](https://tanstack.com/table) | ^9.0.0 | `<yuw-datatable>` |
28
- | `embla-carousel-angular` | ^21.0.0 | Carousel primitives |
29
- | `ngx-scrollbar` | ^19.1.5 | Scroll areas |
30
- | `d3-scale` + `d3-shape` | ^4 / ^3 | Optional, only for `<yuw-chart>` |
20
+ | Dependency | Version | Notes |
21
+ | :---------------------------------------------------------------- | :------ | :----------------------------- |
22
+ | [Angular](https://angular.dev/) | 21+ | Standalone APIs, signal inputs |
23
+ | [Tailwind CSS](https://tailwindcss.com/) | v4 | Required — see [Setup](#setup) |
24
+ | [`@spartan-ng/brain`](https://spartan.ng) | ^1.3.0 | Headless primitives |
25
+ | [`@angular/cdk`](https://material.angular.dev/cdk/categories) | ^21.0.0 | Overlays, a11y |
26
+ | [`@ng-icons/core`](https://ng-icons.github.io/ng-icons/) + lucide | ^32.2.0 | Icons |
27
+ | [`@tanstack/angular-table`](https://tanstack.com/table) | ^9.0.0 | `<yuw-datatable>` |
28
+ | `embla-carousel-angular` | ^21.0.0 | Carousel primitives |
29
+ | `ngx-scrollbar` | ^19.1.5 | Scroll areas |
31
30
 
32
31
  ## Installation
33
32
 
@@ -45,12 +44,6 @@ npm install -D tailwindcss @tailwindcss/postcss tw-animate-css
45
44
 
46
45
  `tw-animate-css` is required because `@spartan-ng/brain/hlm-tailwind-preset.css` imports it.
47
46
 
48
- Apps that draw [charts](#chart) also install their two geometry packages, which no other component needs:
49
-
50
- ```bash
51
- npm install d3-scale d3-shape
52
- ```
53
-
54
47
  ## Setup
55
48
 
56
49
  `yukit-web` does **not** ship compiled component CSS. Its templates carry Tailwind utility classes,
@@ -170,7 +163,6 @@ behave like any other Tailwind color:
170
163
  | `--warning` / `--warning-foreground` | `bg-warning`, `text-warning-foreground`, … |
171
164
  | `--info` / `--info-foreground` | `bg-info`, `text-info-foreground`, … |
172
165
  | `--destructive-foreground` | `text-destructive-foreground` — Spartan defines only `--destructive` and hardcodes `text-white`; Yurest names a contrast color, so the pair is completed. |
173
- | `--chart-1` … `--chart-8` | `bg-chart-1`, `fill-chart-3`, … — the series palette of [`<yuw-chart>`](#chart), each at least 3:1 against the page in light and dark mode. |
174
166
 
175
167
  To override a token, redefine it in your own `:root` _after_ importing the theme.
176
168
 
@@ -305,7 +297,6 @@ neither source silently overrides the other.
305
297
  | [Empty](#empty) | `[yuwEmpty]` | `YuwEmptyImports` |
306
298
  | [Skeleton](#skeleton) | `[yuwSkeleton]` | `YuwSkeletonDirective` |
307
299
  | [Spinner](#spinner) | `yuw-spinner` | `YuwSpinnerComponent` |
308
- | [Chart](#chart) | `yuw-chart` | `YuwChartComponent` (`yukit-web/chart`) |
309
300
  | **Navigation** | | |
310
301
  | [Accordion](#accordion) | `yuw-accordion` | `YuwAccordionImports` |
311
302
  | [Breadcrumb](#breadcrumb) | `yuw-breadcrumb` | `YuwBreadcrumbComponent` |
@@ -1077,84 +1068,6 @@ The spinner inherits its size from the container's font size — wrap it in `tex
1077
1068
 
1078
1069
  ---
1079
1070
 
1080
- ### Chart
1081
-
1082
- Bar, line, area, pie and donut charts drawn as SVG, modelled on shadcn/ui's chart: a `config` names
1083
- each series, gives it a label and a color token, and the tooltip and legend read the same config.
1084
- It lives in its own entry point, so apps that draw no chart never load it nor its `d3-scale` /
1085
- `d3-shape` peers:
1086
-
1087
- ```ts
1088
- import { YuwChartComponent, type YuwChartConfigDto, yuwChartColorAt } from 'yukit-web/chart';
1089
- ```
1090
-
1091
- ```ts
1092
- protected readonly config: YuwChartConfigDto = {
1093
- food: { label: this.translate('purchases.food'), color: 'chart-1' },
1094
- drinks: { label: this.translate('purchases.drinks'), color: 'chart-2' },
1095
- };
1096
- protected readonly rows = [
1097
- { month: '2026-01-01', food: 4200, drinks: 1800 },
1098
- { month: '2026-02-01', food: 3900, drinks: 1650 },
1099
- ];
1100
- protected readonly euros = (value: number) => this.currency.format(value);
1101
- protected readonly month = (value: unknown) => this.monthFormat.format(new Date(String(value)));
1102
- ```
1103
-
1104
- ```html
1105
- <yuw-chart
1106
- kind="bar-stacked"
1107
- class="h-80"
1108
- ariaLabel="Purchases per month"
1109
- emptyText="No purchases in this period"
1110
- categoryKey="month"
1111
- categoryLabel="Month"
1112
- [config]="config"
1113
- [data]="rows"
1114
- [valueFormat]="euros"
1115
- [categoryFormat]="month"
1116
- />
1117
-
1118
- <yuw-chart kind="donut" ariaLabel="Purchases by provider" emptyText="No purchases" [config]="config" [data]="rows" />
1119
- ```
1120
-
1121
- - **Kinds** (`YuwChartKindDto`): `bar`, `bar-stacked`, `bar-horizontal`, `bar-horizontal-stacked`,
1122
- `line`, `area`, `area-stacked`, `pie`, `donut`. Bars group their series unless the kind is
1123
- stacked. Pie and donut draw one slice per series, summing it across every row, so the rows of a
1124
- stacked bar chart give the donut of its totals; for a distribution, pass one row.
1125
- - **Colors** are the `chart-1` … `chart-8` theme tokens, applied as `var(--chart-n)`, so dark mode
1126
- recolors with no redraw. `yuwChartColorAt(index)` cycles through them for a config built from
1127
- data, such as one series per provider.
1128
- - **Formatting is yours.** `valueFormat` and `categoryFormat` turn numbers and categories into the
1129
- text of axes, tooltips and the accessible table; the library hardcodes no locale or currency.
1130
- - **Missing values** (anything that is not a finite number) are gaps, never zeros.
1131
- - **Size**: the chart fills its root, `h-72` by default; set the height with `class`. It redraws
1132
- when its box resizes and draws nothing on the server, where only the accessible table renders.
1133
- - **Accessibility**: the chart is a named figure (`ariaLabel`, optional `description`) with a
1134
- visually hidden data table. The plot is focusable: the arrow keys, Home and End move the tooltip
1135
- across categories or slices, Escape hides it, and the active one is announced politely.
1136
- Transitions respect `prefers-reduced-motion`.
1137
-
1138
- #### Inputs
1139
-
1140
- | Input | Type | Default |
1141
- | :--------------- | :---------------------------------------------------------- | :---------- |
1142
- | `ariaLabel` | `string` — **required**, the accessible name | — |
1143
- | `config` | `YuwChartConfigDto` — **required** | — |
1144
- | `data` | `YuwChartRowDto[]` — **required** | — |
1145
- | `emptyText` | `string` — **required** | — |
1146
- | `kind` | `YuwChartKindDto` | `'bar'` |
1147
- | `categoryKey` | `string|undefined` — cartesian kinds | `undefined` |
1148
- | `categoryLabel` | `string|undefined` — category column header, for the table | `undefined` |
1149
- | `categoryFormat` | `(category: unknown) => string` — cartesian kinds | `String` |
1150
- | `valueFormat` | `(value: number) => string` | `String` |
1151
- | `description` | `string|undefined` — accessible description | `undefined` |
1152
- | `legend` | `boolean` | `true` |
1153
- | `loading` | `boolean` — renders a skeleton and sets `aria-busy` | `false` |
1154
- | `class` | `string` — merged last onto the root | `''` |
1155
-
1156
- ---
1157
-
1158
1071
  ### Accordion
1159
1072
 
1160
1073
  ```html
@@ -12,7 +12,7 @@ import { HlmDropdownMenuTrigger, HlmDropdownMenuCheckboxIndicator, HlmDropdownMe
12
12
  import { cva } from 'class-variance-authority';
13
13
  import { NgTemplateOutlet, DOCUMENT } from '@angular/common';
14
14
  import * as i1 from '@spartan-ng/brain/tooltip';
15
- import { provideBrnTooltipDefaultOptions, BrnTooltip } from '@spartan-ng/brain/tooltip';
15
+ import { BrnTooltip, provideBrnTooltipDefaultOptions } from '@spartan-ng/brain/tooltip';
16
16
  import { tooltipPositionVariants, DEFAULT_TOOLTIP_CONTENT_CLASSES, DEFAULT_TOOLTIP_SVG_CLASS } from 'yukit-web/helm/tooltip';
17
17
  import { NgIcon, provideIcons } from '@ng-icons/core';
18
18
  import { lucideX, lucideChevronRight, lucideChevronLeft, lucideUpload, lucideSearch, lucideEyeOff, lucideEye, lucideChevronsUpDown, lucideChevronUp, lucideChevronDown, lucidePencil, lucideCheck, lucideMinus, lucideCopy, lucideTrash2, lucideSave, lucideArrowLeft, lucideArchiveRestore, lucidePlus, lucideSettings2, lucideList, lucideLayoutGrid, lucideDownload, lucideEllipsis, lucideStar } from '@ng-icons/lucide';
@@ -26,6 +26,7 @@ import * as i1$3 from '@spartan-ng/brain/combobox';
26
26
  import { BrnComboboxTrigger, BrnComboboxAnchor, BrnComboboxPopoverTrigger, BrnComboboxMultiple, BrnCombobox } from '@spartan-ng/brain/combobox';
27
27
  import * as i1$4 from 'yukit-web/helm/combobox';
28
28
  import { HlmComboboxContent, HlmComboboxImports } from 'yukit-web/helm/combobox';
29
+ import { BrnAccordionItem } from '@spartan-ng/brain/accordion';
29
30
  import { HlmAccordion, HlmAccordionItem, HlmAccordionTrigger, HlmAccordionContent } from 'yukit-web/helm/accordion';
30
31
  import { HlmField, HlmFieldDescription } from 'yukit-web/helm/field';
31
32
  import { HlmInput } from 'yukit-web/helm/input';
@@ -747,6 +748,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
747
748
  * Brain tooltip config default (`100`).
748
749
  * - `tooltipDisabled`: Disables the tooltip entirely.
749
750
  *
751
+ * Focus opens it only when it is keyboard focus (`:focus-visible`). Brain opens on any `focus`, so a
752
+ * dialog or sheet autofocusing its first tabbable element on open would pop the tooltip unasked.
753
+ * Brain has no public way to cancel a show, so a non-keyboard focus suppresses it through
754
+ * `mutableTooltipDisabled`, which Brain checks once the show delay elapses; blur and hover give the
755
+ * `tooltipDisabled` input back.
756
+ *
750
757
  * Usage:
751
758
  * ```html
752
759
  * <button yuwTooltip="Save changes" hlmBtn>Save</button>
@@ -754,8 +761,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
754
761
  * ```
755
762
  */
756
763
  class YuwTooltipDirective {
764
+ constructor() {
765
+ this.host = inject(ElementRef);
766
+ this.tooltip = inject(BrnTooltip);
767
+ }
768
+ restore() {
769
+ this.tooltip.mutableTooltipDisabled.set(this.tooltip.tooltipDisabled());
770
+ }
771
+ suppressUnlessKeyboardFocus() {
772
+ if (!this.host.nativeElement.matches(':focus-visible')) {
773
+ this.tooltip.mutableTooltipDisabled.set(true);
774
+ }
775
+ }
757
776
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: YuwTooltipDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
758
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.22", type: YuwTooltipDirective, isStandalone: true, selector: "[yuwTooltip]", providers: [
777
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.22", type: YuwTooltipDirective, isStandalone: true, selector: "[yuwTooltip]", host: { listeners: { "focus": "suppressUnlessKeyboardFocus()", "blur": "restore()", "pointerenter": "restore()" } }, providers: [
759
778
  provideBrnTooltipDefaultOptions({
760
779
  svgClasses: DEFAULT_TOOLTIP_SVG_CLASS,
761
780
  tooltipContentClasses: DEFAULT_TOOLTIP_CONTENT_CLASSES,
@@ -780,6 +799,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
780
799
  inputs: ['brnTooltip: yuwTooltip', 'position', 'hideDelay', 'showDelay', 'tooltipDisabled'],
781
800
  },
782
801
  ],
802
+ host: {
803
+ '(focus)': 'suppressUnlessKeyboardFocus()',
804
+ '(blur)': 'restore()',
805
+ '(pointerenter)': 'restore()',
806
+ },
783
807
  }]
784
808
  }] });
785
809
 
@@ -1442,6 +1466,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
1442
1466
  }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-template #footer>\n <ng-content select=\"[yuwComboboxFooter]\" />\n</ng-template>\n\n<ng-template #itemContent let-option>\n @if (itemTemplate(); as custom) {\n <ng-container\n [ngTemplateOutlet]=\"custom.templateRef\"\n [ngTemplateOutletContext]=\"{\n $implicit: option,\n option: option,\n selected: _selectedValues().has(option.value),\n }\"\n />\n } @else {\n {{ option.label }}\n }\n</ng-template>\n\n@if (multiple()) {\n <hlm-combobox-multiple\n [disabled]=\"_disabled()\"\n [value]=\"_multipleValue()\"\n (valueChange)=\"onValueChange($event)\"\n [(search)]=\"search\"\n [itemToString]=\"_itemToString\"\n (focusout)=\"_onFocusOut($event)\"\n >\n @if (triggerTemplate(); as trigger) {\n <yuw-button\n yuwComboboxTriggerButton\n [color]=\"triggerColor()\"\n [variant]=\"triggerVariant()\"\n [size]=\"triggerSize()\"\n [class]=\"triggerClass()\"\n [ariaLabel]=\"triggerAriaLabel()\"\n [disabled]=\"_disabled()\"\n >\n <ng-container [ngTemplateOutlet]=\"trigger.templateRef\" [ngTemplateOutletContext]=\"_triggerContext()\" />\n </yuw-button>\n } @else {\n <hlm-combobox-chips [forceInvalid]=\"invalid()\" [class]=\"_chipsClass()\">\n @for (chip of _selectedChips(); track chip.value) {\n <hlm-combobox-chip [value]=\"chip.value\">{{ chip.label }}</hlm-combobox-chip>\n }\n <input hlmComboboxChipInput [id]=\"_controlId()\" [placeholder]=\"placeholder() ?? ''\" />\n </hlm-combobox-chips>\n }\n\n <hlm-combobox-content *hlmComboboxPortal [class]=\"_contentClass()\">\n @if (_searchInPanel()) {\n <hlm-combobox-input\n [placeholder]=\"searchPlaceholder() ?? ''\"\n [triggerAriaLabel]=\"triggerAriaLabel()\"\n [showTrigger]=\"false\"\n />\n }\n <div hlmComboboxList>\n @for (option of options(); track option.value) {\n <hlm-combobox-item [value]=\"option.value\" [disabled]=\"option.disabled ?? false\">\n <ng-container [ngTemplateOutlet]=\"itemContent\" [ngTemplateOutletContext]=\"{ $implicit: option }\" />\n </hlm-combobox-item>\n }\n </div>\n <hlm-combobox-empty>{{ emptyText() ?? '' }}</hlm-combobox-empty>\n <ng-container [ngTemplateOutlet]=\"footer\" />\n </hlm-combobox-content>\n </hlm-combobox-multiple>\n} @else {\n <hlm-combobox\n [disabled]=\"_disabled()\"\n [value]=\"_singleValue()\"\n (valueChange)=\"onValueChange($event)\"\n [(search)]=\"search\"\n [itemToString]=\"_itemToString\"\n (focusout)=\"_onFocusOut($event)\"\n >\n @if (triggerTemplate(); as trigger) {\n <yuw-button\n yuwComboboxTriggerButton\n [color]=\"triggerColor()\"\n [variant]=\"triggerVariant()\"\n [size]=\"triggerSize()\"\n [class]=\"triggerClass()\"\n [ariaLabel]=\"triggerAriaLabel()\"\n [disabled]=\"_disabled()\"\n >\n <ng-container [ngTemplateOutlet]=\"trigger.templateRef\" [ngTemplateOutletContext]=\"_triggerContext()\" />\n </yuw-button>\n } @else if (readonlyTrigger()) {\n <hlm-combobox-trigger\n [buttonId]=\"_controlId()\"\n [forceInvalid]=\"invalid()\"\n [class]=\"_triggerClass()\"\n class=\"w-full justify-between items-center\"\n >\n <hlm-combobox-value class=\"min-w-0 truncate\" [placeholder]=\"placeholder() ?? ''\" />\n </hlm-combobox-trigger>\n } @else {\n <hlm-combobox-input\n [inputId]=\"_controlId()\"\n [placeholder]=\"placeholder() ?? ''\"\n [showClear]=\"_clearVisible()\"\n [clearAriaLabel]=\"clearAriaLabel() ?? ''\"\n [triggerAriaLabel]=\"triggerAriaLabel()\"\n [forceInvalid]=\"invalid()\"\n [class]=\"_fieldClass()\"\n />\n }\n\n <hlm-combobox-content *hlmComboboxPortal [class]=\"_contentClass()\">\n @if (_searchInPanel()) {\n <hlm-combobox-input\n [placeholder]=\"searchPlaceholder() ?? ''\"\n [showClear]=\"_clearVisible()\"\n [clearAriaLabel]=\"clearAriaLabel() ?? ''\"\n [triggerAriaLabel]=\"triggerAriaLabel()\"\n [showTrigger]=\"false\"\n />\n }\n <div hlmComboboxList>\n @for (option of options(); track option.value) {\n <hlm-combobox-item [value]=\"option.value\" [disabled]=\"option.disabled ?? false\">\n <ng-container [ngTemplateOutlet]=\"itemContent\" [ngTemplateOutletContext]=\"{ $implicit: option }\" />\n </hlm-combobox-item>\n }\n </div>\n <hlm-combobox-empty>{{ emptyText() ?? '' }}</hlm-combobox-empty>\n <ng-container [ngTemplateOutlet]=\"footer\" />\n </hlm-combobox-content>\n </hlm-combobox>\n}\n" }]
1443
1467
  }], ctorParameters: () => [], propDecorators: { _multipleBox: [{ type: i0.ViewChild, args: [i0.forwardRef(() => BrnComboboxMultiple), { isSignal: true }] }], _panel: [{ type: i0.ViewChild, args: [i0.forwardRef(() => HlmComboboxContent), { ...{ read: ElementRef }, isSignal: true }] }], _singleBox: [{ type: i0.ViewChild, args: [i0.forwardRef(() => BrnCombobox), { isSignal: true }] }], itemTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => YuwComboboxItemDirective), { isSignal: true }] }], triggerTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => YuwComboboxTriggerDirective), { isSignal: true }] }], clearAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearAriaLabel", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], inputId: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputId", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], keepValueOnEscape: [{ type: i0.Input, args: [{ isSignal: true, alias: "keepValueOnEscape", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], readonlyTrigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonlyTrigger", required: false }] }], search: [{ type: i0.Input, args: [{ isSignal: true, alias: "search", required: false }] }, { type: i0.Output, args: ["searchChange"] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], triggerAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerAriaLabel", required: true }] }], triggerClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerClass", required: false }] }], triggerColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerColor", required: false }] }], triggerSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerSize", required: false }] }], triggerVariant: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerVariant", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }] } });
1444
1468
 
1469
+ /**
1470
+ * Open state of the sheet a piece of content is declared in. `<yuw-sheet>` and `<yuws-form-sheet>` provide it, so
1471
+ * content projected into either can react to the panel opening or closing without knowing which one it sits in.
1472
+ */
1473
+ class YuwSheetOpenState {
1474
+ }
1475
+
1445
1476
  /**
1446
1477
  * Container directive for collapsible accordion items.
1447
1478
  *
@@ -1452,6 +1483,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
1452
1483
  * Direct child items (`yuw-accordion-item`) can be declared statically or rendered dynamically
1453
1484
  * using `@for`.
1454
1485
  *
1486
+ * Inputs:
1487
+ * - `collapseWithSheet`: Inside a `<yuw-sheet>` or `<yuws-form-sheet>`, collapses every item whenever the sheet opens,
1488
+ * so each opening starts folded. Ignored outside a sheet. Default is `false`. It folds on opening and never on
1489
+ * closing: a height transition cut short by the sheet detaching leaves Chrome rendering the content 0 tall on every
1490
+ * later opening.
1491
+ *
1455
1492
  * Extends `HlmAccordion` (instead of re-applying `BrnAccordion` and copying the helm's classes
1456
1493
  * by hand) so the helm's `data-slot`, classes and its `BrnAccordion` host directive — including
1457
1494
  * the forwarded `type`/`orientation` inputs — are all inherited. Forwarding those inputs through
@@ -1460,15 +1497,30 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
1460
1497
  * `BrnAccordion`.
1461
1498
  */
1462
1499
  class YuwAccordion extends HlmAccordion {
1463
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: YuwAccordion, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
1464
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.22", type: YuwAccordion, isStandalone: true, selector: "yuw-accordion", usesInheritance: true, ngImport: i0 }); }
1500
+ constructor() {
1501
+ super();
1502
+ this._sheet = inject(YuwSheetOpenState, { optional: true });
1503
+ this._items = contentChildren(BrnAccordionItem, { ...(ngDevMode ? { debugName: "_items" } : /* istanbul ignore next */ {}), descendants: true });
1504
+ this.collapseWithSheet = input(false, { ...(ngDevMode ? { debugName: "collapseWithSheet" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1505
+ effect(() => {
1506
+ const sheet = this._sheet;
1507
+ if (!sheet || !this.collapseWithSheet()) {
1508
+ return;
1509
+ }
1510
+ if (sheet.open()) {
1511
+ untracked(() => this._items().forEach((item) => item.close()));
1512
+ }
1513
+ });
1514
+ }
1515
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: YuwAccordion, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1516
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "21.2.22", type: YuwAccordion, isStandalone: true, selector: "yuw-accordion", inputs: { collapseWithSheet: { classPropertyName: "collapseWithSheet", publicName: "collapseWithSheet", isSignal: true, isRequired: false, transformFunction: null } }, queries: [{ propertyName: "_items", predicate: BrnAccordionItem, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0 }); }
1465
1517
  }
1466
1518
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: YuwAccordion, decorators: [{
1467
1519
  type: Directive,
1468
1520
  args: [{
1469
1521
  selector: 'yuw-accordion',
1470
1522
  }]
1471
- }] });
1523
+ }], ctorParameters: () => [], propDecorators: { _items: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => BrnAccordionItem), { ...{ descendants: true }, isSignal: true }] }], collapseWithSheet: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapseWithSheet", required: false }] }] } });
1472
1524
 
1473
1525
  /**
1474
1526
  * Directive representing an individual section/item within a `yuw-accordion`.
@@ -1503,20 +1555,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
1503
1555
  * Inputs:
1504
1556
  * - `triggerClass`: Extra classes for the inner trigger `<button>`; the helm merges them last
1505
1557
  * (via tailwind-merge), so they win over its defaults.
1558
+ * - `underline`: Underlines the label on hover, as the helm does. Set `underline="false"` for a header whose content
1559
+ * is more than a line of text. Default is `true`.
1506
1560
  */
1507
1561
  class YuwAccordionTriggerComponent {
1508
1562
  constructor() {
1509
1563
  this.triggerClass = input('', ...(ngDevMode ? [{ debugName: "triggerClass" }] : /* istanbul ignore next */ []));
1564
+ this.underline = input(true, { ...(ngDevMode ? { debugName: "underline" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1565
+ this._triggerClass = computed(() => cn(!this.underline() && 'hover:no-underline', this.triggerClass()), ...(ngDevMode ? [{ debugName: "_triggerClass" }] : /* istanbul ignore next */ []));
1510
1566
  }
1511
1567
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: YuwAccordionTriggerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1512
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.22", type: YuwAccordionTriggerComponent, isStandalone: true, selector: "yuw-accordion-trigger", inputs: { triggerClass: { classPropertyName: "triggerClass", publicName: "triggerClass", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "contents" }, ngImport: i0, template: "<hlm-accordion-trigger [triggerClass]=\"triggerClass()\">\n <ng-content />\n</hlm-accordion-trigger>\n", dependencies: [{ kind: "component", type: HlmAccordionTrigger, selector: "hlm-accordion-trigger", inputs: ["triggerClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1568
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.22", type: YuwAccordionTriggerComponent, isStandalone: true, selector: "yuw-accordion-trigger", inputs: { triggerClass: { classPropertyName: "triggerClass", publicName: "triggerClass", isSignal: true, isRequired: false, transformFunction: null }, underline: { classPropertyName: "underline", publicName: "underline", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "contents" }, ngImport: i0, template: "<hlm-accordion-trigger [triggerClass]=\"_triggerClass()\">\n <ng-content />\n</hlm-accordion-trigger>\n", dependencies: [{ kind: "component", type: HlmAccordionTrigger, selector: "hlm-accordion-trigger", inputs: ["triggerClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1513
1569
  }
1514
1570
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: YuwAccordionTriggerComponent, decorators: [{
1515
1571
  type: Component,
1516
1572
  args: [{ selector: 'yuw-accordion-trigger', imports: [HlmAccordionTrigger], host: {
1517
1573
  class: 'contents',
1518
- }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<hlm-accordion-trigger [triggerClass]=\"triggerClass()\">\n <ng-content />\n</hlm-accordion-trigger>\n" }]
1519
- }], propDecorators: { triggerClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerClass", required: false }] }] } });
1574
+ }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<hlm-accordion-trigger [triggerClass]=\"_triggerClass()\">\n <ng-content />\n</hlm-accordion-trigger>\n" }]
1575
+ }], propDecorators: { triggerClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerClass", required: false }] }], underline: [{ type: i0.Input, args: [{ isSignal: true, alias: "underline", required: false }] }] } });
1520
1576
 
1521
1577
  /**
1522
1578
  * Collapsible panel container for a `yuw-accordion-item`.
@@ -2006,7 +2062,7 @@ class YuwSheetComponent {
2006
2062
  this.open.set(state === 'open');
2007
2063
  }
2008
2064
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: YuwSheetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2009
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: YuwSheetComponent, isStandalone: true, selector: "yuw-sheet", inputs: { ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, ariaModal: { classPropertyName: "ariaModal", publicName: "ariaModal", isSignal: true, isRequired: false, transformFunction: null }, bodyClass: { classPropertyName: "bodyClass", publicName: "bodyClass", isSignal: true, isRequired: false, transformFunction: null }, closeLabel: { classPropertyName: "closeLabel", publicName: "closeLabel", isSignal: true, isRequired: false, transformFunction: null }, closeOnOutsidePointerEvents: { classPropertyName: "closeOnOutsidePointerEvents", publicName: "closeOnOutsidePointerEvents", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, overlayClass: { classPropertyName: "overlayClass", publicName: "overlayClass", isSignal: true, isRequired: false, transformFunction: null }, panelClass: { classPropertyName: "panelClass", publicName: "panelClass", isSignal: true, isRequired: false, transformFunction: null }, scrollStrategy: { classPropertyName: "scrollStrategy", publicName: "scrollStrategy", isSignal: true, isRequired: false, transformFunction: null }, showTrigger: { classPropertyName: "showTrigger", publicName: "showTrigger", isSignal: true, isRequired: false, transformFunction: null }, side: { classPropertyName: "side", publicName: "side", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, triggerSize: { classPropertyName: "triggerSize", publicName: "triggerSize", isSignal: true, isRequired: false, transformFunction: null }, triggerVariant: { classPropertyName: "triggerVariant", publicName: "triggerVariant", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange" }, host: { classAttribute: "contents" }, providers: [provideIcons({ lucideX })], queries: [{ propertyName: "hasFooter", first: true, predicate: YuwSheetFooterDirective, descendants: true, isSignal: true }, { propertyName: "hasHeader", first: true, predicate: YuwSheetHeaderDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "sheet", first: true, predicate: HlmSheet, descendants: true, isSignal: true }], ngImport: i0, template: "<hlm-sheet\n [side]=\"side()\"\n [state]=\"_sheetState()\"\n [aria-label]=\"ariaLabel()\"\n [aria-modal]=\"ariaModal()\"\n [scrollStrategy]=\"scrollStrategy()\"\n [closeOnOutsidePointerEvents]=\"closeOnOutsidePointerEvents()\"\n (stateChanged)=\"onStateChanged($event)\"\n>\n @if (showTrigger()) {\n <yuw-button yuwSheetTriggerButton [variant]=\"triggerVariant()\" [size]=\"triggerSize()\">\n <ng-content select=\"[yuwSheetTrigger]\" />\n </yuw-button>\n }\n\n <hlm-sheet-content *hlmSheetPortal [showCloseButton]=\"false\" [class]=\"panelClass()\">\n @if (title() || description()) {\n <div hlmSheetHeader>\n @if (title()) {\n <h2 hlmSheetTitle>{{ title() }}</h2>\n }\n @if (description()) {\n <p hlmSheetDescription>{{ description() }}</p>\n }\n </div>\n }\n\n @if (hasHeader()) {\n <div class=\"flex items-start gap-3 px-4 pt-6\">\n <div class=\"min-w-0 flex-1\">\n <ng-content select=\"[yuwSheetHeader]\" />\n </div>\n @if (closeLabel()) {\n <ng-container [ngTemplateOutlet]=\"closeButton\" />\n }\n </div>\n }\n\n <div [class]=\"_bodyClass()\">\n <ng-content />\n </div>\n\n @if (hasFooter()) {\n <div hlmSheetFooter>\n <ng-content select=\"[yuwSheetFooter]\" />\n </div>\n }\n\n @if (closeLabel() && !hasHeader()) {\n <div class=\"absolute inset-e-3 top-3\">\n <ng-container [ngTemplateOutlet]=\"closeButton\" />\n </div>\n }\n\n <ng-template #closeButton>\n <yuw-button yuwSheetClose variant=\"ghost\" size=\"icon-sm\">\n <ng-icon name=\"lucideX\" />\n <span class=\"sr-only\">{{ closeLabel() }}</span>\n </yuw-button>\n </ng-template>\n </hlm-sheet-content>\n</hlm-sheet>\n", dependencies: [{ kind: "component", type: i1$9.HlmSheet, selector: "hlm-sheet", exportAs: ["hlmSheet"] }, { kind: "component", type: i1$9.HlmSheetContent, selector: "hlm-sheet-content", inputs: ["showCloseButton"] }, { kind: "directive", type: i1$9.HlmSheetDescription, selector: "[hlmSheetDescription]" }, { kind: "directive", type: i1$9.HlmSheetFooter, selector: "[hlmSheetFooter],hlm-sheet-footer" }, { kind: "directive", type: i1$9.HlmSheetHeader, selector: "[hlmSheetHeader],hlm-sheet-header" }, { kind: "directive", type: i1$9.HlmSheetPortal, selector: "[hlmSheetPortal]" }, { kind: "directive", type: i1$9.HlmSheetTitle, selector: "[hlmSheetTitle]" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: YuwButtonComponent, selector: "yuw-button", inputs: ["animationDisabled", "ariaLabel", "color", "disabled", "href", "size", "target", "transparent", "type", "class", "variant", "yuwDropdownMenuTrigger"], outputs: ["clicked"] }, { kind: "directive", type: YuwSheetTriggerDirective, selector: "yuw-button[yuwSheetTriggerButton]" }, { kind: "directive", type: YuwSheetCloseDirective, selector: "yuw-button[yuwSheetClose]" }, { kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2065
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: YuwSheetComponent, isStandalone: true, selector: "yuw-sheet", inputs: { ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, ariaModal: { classPropertyName: "ariaModal", publicName: "ariaModal", isSignal: true, isRequired: false, transformFunction: null }, bodyClass: { classPropertyName: "bodyClass", publicName: "bodyClass", isSignal: true, isRequired: false, transformFunction: null }, closeLabel: { classPropertyName: "closeLabel", publicName: "closeLabel", isSignal: true, isRequired: false, transformFunction: null }, closeOnOutsidePointerEvents: { classPropertyName: "closeOnOutsidePointerEvents", publicName: "closeOnOutsidePointerEvents", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, overlayClass: { classPropertyName: "overlayClass", publicName: "overlayClass", isSignal: true, isRequired: false, transformFunction: null }, panelClass: { classPropertyName: "panelClass", publicName: "panelClass", isSignal: true, isRequired: false, transformFunction: null }, scrollStrategy: { classPropertyName: "scrollStrategy", publicName: "scrollStrategy", isSignal: true, isRequired: false, transformFunction: null }, showTrigger: { classPropertyName: "showTrigger", publicName: "showTrigger", isSignal: true, isRequired: false, transformFunction: null }, side: { classPropertyName: "side", publicName: "side", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, triggerSize: { classPropertyName: "triggerSize", publicName: "triggerSize", isSignal: true, isRequired: false, transformFunction: null }, triggerVariant: { classPropertyName: "triggerVariant", publicName: "triggerVariant", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange" }, host: { classAttribute: "contents" }, providers: [provideIcons({ lucideX }), { provide: YuwSheetOpenState, useExisting: YuwSheetComponent }], queries: [{ propertyName: "hasFooter", first: true, predicate: YuwSheetFooterDirective, descendants: true, isSignal: true }, { propertyName: "hasHeader", first: true, predicate: YuwSheetHeaderDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "sheet", first: true, predicate: HlmSheet, descendants: true, isSignal: true }], ngImport: i0, template: "<hlm-sheet\n [side]=\"side()\"\n [state]=\"_sheetState()\"\n [aria-label]=\"ariaLabel()\"\n [aria-modal]=\"ariaModal()\"\n [scrollStrategy]=\"scrollStrategy()\"\n [closeOnOutsidePointerEvents]=\"closeOnOutsidePointerEvents()\"\n (stateChanged)=\"onStateChanged($event)\"\n>\n @if (showTrigger()) {\n <yuw-button yuwSheetTriggerButton [variant]=\"triggerVariant()\" [size]=\"triggerSize()\">\n <ng-content select=\"[yuwSheetTrigger]\" />\n </yuw-button>\n }\n\n <hlm-sheet-content *hlmSheetPortal [showCloseButton]=\"false\" [class]=\"panelClass()\">\n @if (title() || description()) {\n <div hlmSheetHeader>\n @if (title()) {\n <h2 hlmSheetTitle>{{ title() }}</h2>\n }\n @if (description()) {\n <p hlmSheetDescription>{{ description() }}</p>\n }\n </div>\n }\n\n @if (hasHeader()) {\n <div class=\"flex items-start gap-3 px-4 pt-6\">\n <div class=\"min-w-0 flex-1\">\n <ng-content select=\"[yuwSheetHeader]\" />\n </div>\n @if (closeLabel()) {\n <ng-container [ngTemplateOutlet]=\"closeButton\" />\n }\n </div>\n }\n\n <div [class]=\"_bodyClass()\">\n <ng-content />\n </div>\n\n @if (hasFooter()) {\n <div hlmSheetFooter>\n <ng-content select=\"[yuwSheetFooter]\" />\n </div>\n }\n\n @if (closeLabel() && !hasHeader()) {\n <div class=\"absolute inset-e-3 top-3\">\n <ng-container [ngTemplateOutlet]=\"closeButton\" />\n </div>\n }\n\n <ng-template #closeButton>\n <yuw-button yuwSheetClose variant=\"ghost\" size=\"icon-sm\">\n <ng-icon name=\"lucideX\" />\n <span class=\"sr-only\">{{ closeLabel() }}</span>\n </yuw-button>\n </ng-template>\n </hlm-sheet-content>\n</hlm-sheet>\n", dependencies: [{ kind: "component", type: i1$9.HlmSheet, selector: "hlm-sheet", exportAs: ["hlmSheet"] }, { kind: "component", type: i1$9.HlmSheetContent, selector: "hlm-sheet-content", inputs: ["showCloseButton"] }, { kind: "directive", type: i1$9.HlmSheetDescription, selector: "[hlmSheetDescription]" }, { kind: "directive", type: i1$9.HlmSheetFooter, selector: "[hlmSheetFooter],hlm-sheet-footer" }, { kind: "directive", type: i1$9.HlmSheetHeader, selector: "[hlmSheetHeader],hlm-sheet-header" }, { kind: "directive", type: i1$9.HlmSheetPortal, selector: "[hlmSheetPortal]" }, { kind: "directive", type: i1$9.HlmSheetTitle, selector: "[hlmSheetTitle]" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: YuwButtonComponent, selector: "yuw-button", inputs: ["animationDisabled", "ariaLabel", "color", "disabled", "href", "size", "target", "transparent", "type", "class", "variant", "yuwDropdownMenuTrigger"], outputs: ["clicked"] }, { kind: "directive", type: YuwSheetTriggerDirective, selector: "yuw-button[yuwSheetTriggerButton]" }, { kind: "directive", type: YuwSheetCloseDirective, selector: "yuw-button[yuwSheetClose]" }, { kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2010
2066
  }
2011
2067
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: YuwSheetComponent, decorators: [{
2012
2068
  type: Component,
@@ -2017,7 +2073,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImpo
2017
2073
  YuwSheetTriggerDirective,
2018
2074
  YuwSheetCloseDirective,
2019
2075
  NgIcon,
2020
- ], providers: [provideIcons({ lucideX })], host: {
2076
+ ], providers: [provideIcons({ lucideX }), { provide: YuwSheetOpenState, useExisting: YuwSheetComponent }], host: {
2021
2077
  class: 'contents',
2022
2078
  }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<hlm-sheet\n [side]=\"side()\"\n [state]=\"_sheetState()\"\n [aria-label]=\"ariaLabel()\"\n [aria-modal]=\"ariaModal()\"\n [scrollStrategy]=\"scrollStrategy()\"\n [closeOnOutsidePointerEvents]=\"closeOnOutsidePointerEvents()\"\n (stateChanged)=\"onStateChanged($event)\"\n>\n @if (showTrigger()) {\n <yuw-button yuwSheetTriggerButton [variant]=\"triggerVariant()\" [size]=\"triggerSize()\">\n <ng-content select=\"[yuwSheetTrigger]\" />\n </yuw-button>\n }\n\n <hlm-sheet-content *hlmSheetPortal [showCloseButton]=\"false\" [class]=\"panelClass()\">\n @if (title() || description()) {\n <div hlmSheetHeader>\n @if (title()) {\n <h2 hlmSheetTitle>{{ title() }}</h2>\n }\n @if (description()) {\n <p hlmSheetDescription>{{ description() }}</p>\n }\n </div>\n }\n\n @if (hasHeader()) {\n <div class=\"flex items-start gap-3 px-4 pt-6\">\n <div class=\"min-w-0 flex-1\">\n <ng-content select=\"[yuwSheetHeader]\" />\n </div>\n @if (closeLabel()) {\n <ng-container [ngTemplateOutlet]=\"closeButton\" />\n }\n </div>\n }\n\n <div [class]=\"_bodyClass()\">\n <ng-content />\n </div>\n\n @if (hasFooter()) {\n <div hlmSheetFooter>\n <ng-content select=\"[yuwSheetFooter]\" />\n </div>\n }\n\n @if (closeLabel() && !hasHeader()) {\n <div class=\"absolute inset-e-3 top-3\">\n <ng-container [ngTemplateOutlet]=\"closeButton\" />\n </div>\n }\n\n <ng-template #closeButton>\n <yuw-button yuwSheetClose variant=\"ghost\" size=\"icon-sm\">\n <ng-icon name=\"lucideX\" />\n <span class=\"sr-only\">{{ closeLabel() }}</span>\n </yuw-button>\n </ng-template>\n </hlm-sheet-content>\n</hlm-sheet>\n" }]
2023
2079
  }], ctorParameters: () => [], propDecorators: { hasFooter: [{ type: i0.ContentChild, args: [i0.forwardRef(() => YuwSheetFooterDirective), { isSignal: true }] }], hasHeader: [{ type: i0.ContentChild, args: [i0.forwardRef(() => YuwSheetHeaderDirective), { isSignal: true }] }], sheet: [{ type: i0.ViewChild, args: [i0.forwardRef(() => HlmSheet), { isSignal: true }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], ariaModal: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaModal", required: false }] }], bodyClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "bodyClass", required: false }] }], closeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeLabel", required: false }] }], closeOnOutsidePointerEvents: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnOutsidePointerEvents", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], overlayClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "overlayClass", required: false }] }], panelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelClass", required: false }] }], scrollStrategy: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollStrategy", required: false }] }], showTrigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTrigger", required: false }] }], side: [{ type: i0.Input, args: [{ isSignal: true, alias: "side", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], triggerSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerSize", required: false }] }], triggerVariant: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerVariant", required: false }] }] } });
@@ -5164,7 +5220,7 @@ const yuwStepIndicatorVariants = cva('flex size-8 shrink-0 items-center justify-
5164
5220
  },
5165
5221
  },
5166
5222
  });
5167
- const yuwStepTriggerVariants = cva('flex items-center gap-3 rounded-md text-left outline-none transition-colors focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-default', {
5223
+ const yuwStepTriggerVariants = cva('flex items-center gap-3 rounded-full text-left outline-none transition-colors focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-default', {
5168
5224
  variants: {
5169
5225
  state: {
5170
5226
  completed: 'text-(--neutrals-element-high)',
@@ -5213,6 +5269,15 @@ const yuwStepVariants = cva('flex', {
5213
5269
  },
5214
5270
  },
5215
5271
  });
5272
+ /** Entrance of a step's panel, sliding in from the side the user moved towards; off for reduced motion. */
5273
+ const yuwStepPanelVariants = cva('min-w-0 flex-1 animate-in fade-in duration-200 motion-reduce:animate-none', {
5274
+ variants: {
5275
+ direction: {
5276
+ forward: 'slide-in-from-right-2',
5277
+ backward: 'slide-in-from-left-2',
5278
+ },
5279
+ },
5280
+ });
5216
5281
 
5217
5282
  const TOOLTIP_POSITION = {
5218
5283
  horizontal: 'top',
@@ -5223,7 +5288,8 @@ const TOOLTIP_POSITION = {
5223
5288
  *
5224
5289
  * Steps come from the `steps` input; each panel is an `<ng-template yuwStepPanel="<id>">` whose id matches a step.
5225
5290
  * A horizontal header that does not fit scrolls sideways (touch, trackpad, mouse wheel or drag), its edges fading out.
5226
- * Only the active panel is rendered, so state that must survive a step change belongs to the parent (a form group).
5291
+ * Only the active panel is rendered, so state that must survive a step change belongs to the parent (a form group). It
5292
+ * slides in from the side the user moved towards, through `tw-animate-css`, which the Spartan preset already requires.
5227
5293
  * Navigation buttons are the consumer's: grab the stepper with a template reference and call `next()` / `previous()`,
5228
5294
  * disabling them with `hasNext()` / `hasPrevious()`.
5229
5295
  *
@@ -5237,6 +5303,10 @@ const TOOLTIP_POSITION = {
5237
5303
  * - `color`: Accent of the active and completed steps (any `YuwColorDto`). Default is `'primary'`.
5238
5304
  * - `class`: Extra classes merged last onto the root element.
5239
5305
  *
5306
+ * Outputs:
5307
+ * - `stepChange`: Emits the step the user moved to (`YuwStepChangeDto`, the step and its index), from the header or
5308
+ * `next()` / `previous()`. Not emitted when the parent sets `activeStep` itself.
5309
+ *
5240
5310
  * Content:
5241
5311
  * - `<ng-template yuwStepIndicator let-state let-step="step" let-index="index">` replaces the number/check inside
5242
5312
  * every indicator.
@@ -5264,9 +5334,11 @@ class YuwStepperComponent {
5264
5334
  this.orientation = input('horizontal', ...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
5265
5335
  this.steps = input.required(...(ngDevMode ? [{ debugName: "steps" }] : /* istanbul ignore next */ []));
5266
5336
  this.userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : /* istanbul ignore next */ {}), alias: 'class' });
5337
+ this.stepChange = output();
5267
5338
  this._activePanel = computed(() => {
5268
5339
  const active = this.activeStep();
5269
- return this.panels().find((panel) => panel.stepId() === active)?.templateRef;
5340
+ const panel = this.panels().find((candidate) => candidate.stepId() === active);
5341
+ return panel ? [{ id: active, templateRef: panel.templateRef }] : [];
5270
5342
  }, ...(ngDevMode ? [{ debugName: "_activePanel" }] : /* istanbul ignore next */ []));
5271
5343
  this._activeTriggerId = computed(() => `${this._idPrefix}-${this.activeStep()}`, ...(ngDevMode ? [{ debugName: "_activeTriggerId" }] : /* istanbul ignore next */ []));
5272
5344
  this.activeIndex = computed(() => this.steps().findIndex((step) => step.id === this.activeStep()), ...(ngDevMode ? [{ debugName: "activeIndex" }] : /* istanbul ignore next */ []));
@@ -5283,6 +5355,11 @@ class YuwStepperComponent {
5283
5355
  }, ...(ngDevMode ? [{ debugName: "_items" }] : /* istanbul ignore next */ []));
5284
5356
  this._labelClass = computed(() => (this.iconOnly() ? 'sr-only' : 'flex flex-col'), ...(ngDevMode ? [{ debugName: "_labelClass" }] : /* istanbul ignore next */ []));
5285
5357
  this._listClass = computed(() => yuwStepListVariants({ orientation: this.orientation() }), ...(ngDevMode ? [{ debugName: "_listClass" }] : /* istanbul ignore next */ []));
5358
+ this._panelClass = linkedSignal({ ...(ngDevMode ? { debugName: "_panelClass" } : /* istanbul ignore next */ {}), source: () => this.activeIndex(),
5359
+ computation: (index, previous) => {
5360
+ const direction = previous && index < previous.source ? 'backward' : 'forward';
5361
+ return yuwStepPanelVariants({ direction });
5362
+ } });
5286
5363
  this._rootClass = computed(() => cn(yuwStepperLayoutVariants({ orientation: this.orientation() }), this.userClass()), ...(ngDevMode ? [{ debugName: "_rootClass" }] : /* istanbul ignore next */ []));
5287
5364
  this._stepClass = computed(() => yuwStepVariants({ orientation: this.orientation() }), ...(ngDevMode ? [{ debugName: "_stepClass" }] : /* istanbul ignore next */ []));
5288
5365
  this._tooltipPosition = computed(() => TOOLTIP_POSITION[this.orientation()], ...(ngDevMode ? [{ debugName: "_tooltipPosition" }] : /* istanbul ignore next */ []));
@@ -5301,12 +5378,16 @@ class YuwStepperComponent {
5301
5378
  this._goTo(this._neighbour(-1));
5302
5379
  }
5303
5380
  select(id) {
5304
- this.activeStep.set(id);
5381
+ this._goTo(id);
5305
5382
  }
5306
5383
  _goTo(id) {
5307
- if (id !== undefined) {
5308
- this.activeStep.set(id);
5384
+ const index = this.steps().findIndex((step) => step.id === id);
5385
+ const step = this.steps()[index];
5386
+ if (!step || step.id === this.activeStep()) {
5387
+ return;
5309
5388
  }
5389
+ this.activeStep.set(step.id);
5390
+ this.stepChange.emit({ step, index });
5310
5391
  }
5311
5392
  /** Closest reachable step in `direction`, skipping disabled ones. */
5312
5393
  _neighbour(direction) {
@@ -5338,14 +5419,14 @@ class YuwStepperComponent {
5338
5419
  });
5339
5420
  }
5340
5421
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: YuwStepperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5341
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: YuwStepperComponent, isStandalone: true, selector: "yuw-stepper", inputs: { activeStep: { classPropertyName: "activeStep", publicName: "activeStep", isSignal: true, isRequired: true, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, iconOnly: { classPropertyName: "iconOnly", publicName: "iconOnly", isSignal: true, isRequired: false, transformFunction: null }, linear: { classPropertyName: "linear", publicName: "linear", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, steps: { classPropertyName: "steps", publicName: "steps", isSignal: true, isRequired: true, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeStep: "activeStepChange" }, host: { classAttribute: "contents" }, providers: [provideIcons({ lucideCheck })], queries: [{ propertyName: "indicator", first: true, predicate: YuwStepIndicatorDirective, descendants: true, isSignal: true }, { propertyName: "panels", predicate: YuwStepPanelDirective, isSignal: true }], viewQueries: [{ propertyName: "_list", first: true, predicate: ["list"], descendants: true, isSignal: true }], ngImport: i0, template: "<div [class]=\"_rootClass()\">\n <ol #list yuwMouseScrollX [class]=\"_listClass()\" [attr.data-yuw-color]=\"color()\">\n @for (item of _items(); track item.step.id; let last = $last) {\n <li [class]=\"_stepClass()\">\n <button\n type=\"button\"\n [id]=\"item.triggerId\"\n [class]=\"item.triggerClass\"\n [disabled]=\"!item.reachable\"\n [attr.aria-current]=\"item.ariaCurrent\"\n [yuwTooltip]=\"item.step.label\"\n [tooltipDisabled]=\"!iconOnly()\"\n [position]=\"_tooltipPosition()\"\n (click)=\"select(item.step.id)\"\n >\n <span [class]=\"item.indicatorClass\">\n @if (indicator(); as custom) {\n <ng-container [ngTemplateOutlet]=\"custom.templateRef\" [ngTemplateOutletContext]=\"item.context\" />\n } @else if (item.state === 'completed') {\n <ng-icon name=\"lucideCheck\" aria-hidden=\"true\" />\n } @else {\n {{ item.index + 1 }}\n }\n </span>\n <span [class]=\"_labelClass()\">\n <span class=\"text-sm font-medium\">{{ item.step.label }}</span>\n @if (item.step.description) {\n <span class=\"text-xs text-muted-foreground\">{{ item.step.description }}</span>\n }\n </span>\n </button>\n @if (!last) {\n <span [class]=\"item.separatorClass\" aria-hidden=\"true\"></span>\n }\n </li>\n }\n </ol>\n\n @if (_activePanel(); as panel) {\n <div role=\"region\" class=\"min-w-0 flex-1\" [attr.aria-labelledby]=\"_activeTriggerId()\">\n <ng-container [ngTemplateOutlet]=\"panel\" />\n </div>\n }\n</div>\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "directive", type: YuwMouseScrollXDirective, selector: "[yuwMouseScrollX]" }, { kind: "directive", type: YuwTooltipDirective, selector: "[yuwTooltip]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5422
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: YuwStepperComponent, isStandalone: true, selector: "yuw-stepper", inputs: { activeStep: { classPropertyName: "activeStep", publicName: "activeStep", isSignal: true, isRequired: true, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, iconOnly: { classPropertyName: "iconOnly", publicName: "iconOnly", isSignal: true, isRequired: false, transformFunction: null }, linear: { classPropertyName: "linear", publicName: "linear", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, steps: { classPropertyName: "steps", publicName: "steps", isSignal: true, isRequired: true, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeStep: "activeStepChange", stepChange: "stepChange" }, host: { classAttribute: "contents" }, providers: [provideIcons({ lucideCheck })], queries: [{ propertyName: "indicator", first: true, predicate: YuwStepIndicatorDirective, descendants: true, isSignal: true }, { propertyName: "panels", predicate: YuwStepPanelDirective, isSignal: true }], viewQueries: [{ propertyName: "_list", first: true, predicate: ["list"], descendants: true, isSignal: true }], ngImport: i0, template: "<div [class]=\"_rootClass()\">\n <ol #list yuwMouseScrollX [class]=\"_listClass()\" [attr.data-yuw-color]=\"color()\">\n @for (item of _items(); track item.step.id; let last = $last) {\n <li [class]=\"_stepClass()\">\n <button\n type=\"button\"\n [id]=\"item.triggerId\"\n [class]=\"item.triggerClass\"\n [disabled]=\"!item.reachable\"\n [attr.aria-current]=\"item.ariaCurrent\"\n [yuwTooltip]=\"item.step.label\"\n [tooltipDisabled]=\"!iconOnly()\"\n [position]=\"_tooltipPosition()\"\n (click)=\"select(item.step.id)\"\n >\n <span [class]=\"item.indicatorClass\">\n @if (indicator(); as custom) {\n <ng-container [ngTemplateOutlet]=\"custom.templateRef\" [ngTemplateOutletContext]=\"item.context\" />\n } @else if (item.state === 'completed') {\n <ng-icon name=\"lucideCheck\" aria-hidden=\"true\" />\n } @else {\n {{ item.index + 1 }}\n }\n </span>\n <span [class]=\"_labelClass()\">\n <span class=\"text-sm font-medium\">{{ item.step.label }}</span>\n @if (item.step.description) {\n <span class=\"text-xs text-muted-foreground\">{{ item.step.description }}</span>\n }\n </span>\n </button>\n @if (!last) {\n <span [class]=\"item.separatorClass\" aria-hidden=\"true\"></span>\n }\n </li>\n }\n </ol>\n\n @for (panel of _activePanel(); track panel.id) {\n <div role=\"region\" [class]=\"_panelClass()\" [attr.aria-labelledby]=\"_activeTriggerId()\">\n <ng-container [ngTemplateOutlet]=\"panel.templateRef\" />\n </div>\n }\n</div>\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "directive", type: YuwMouseScrollXDirective, selector: "[yuwMouseScrollX]" }, { kind: "directive", type: YuwTooltipDirective, selector: "[yuwTooltip]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5342
5423
  }
5343
5424
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: YuwStepperComponent, decorators: [{
5344
5425
  type: Component,
5345
5426
  args: [{ selector: 'yuw-stepper', imports: [NgTemplateOutlet, NgIcon, YuwMouseScrollXDirective, YuwTooltipDirective], providers: [provideIcons({ lucideCheck })], host: {
5346
5427
  class: 'contents',
5347
- }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class]=\"_rootClass()\">\n <ol #list yuwMouseScrollX [class]=\"_listClass()\" [attr.data-yuw-color]=\"color()\">\n @for (item of _items(); track item.step.id; let last = $last) {\n <li [class]=\"_stepClass()\">\n <button\n type=\"button\"\n [id]=\"item.triggerId\"\n [class]=\"item.triggerClass\"\n [disabled]=\"!item.reachable\"\n [attr.aria-current]=\"item.ariaCurrent\"\n [yuwTooltip]=\"item.step.label\"\n [tooltipDisabled]=\"!iconOnly()\"\n [position]=\"_tooltipPosition()\"\n (click)=\"select(item.step.id)\"\n >\n <span [class]=\"item.indicatorClass\">\n @if (indicator(); as custom) {\n <ng-container [ngTemplateOutlet]=\"custom.templateRef\" [ngTemplateOutletContext]=\"item.context\" />\n } @else if (item.state === 'completed') {\n <ng-icon name=\"lucideCheck\" aria-hidden=\"true\" />\n } @else {\n {{ item.index + 1 }}\n }\n </span>\n <span [class]=\"_labelClass()\">\n <span class=\"text-sm font-medium\">{{ item.step.label }}</span>\n @if (item.step.description) {\n <span class=\"text-xs text-muted-foreground\">{{ item.step.description }}</span>\n }\n </span>\n </button>\n @if (!last) {\n <span [class]=\"item.separatorClass\" aria-hidden=\"true\"></span>\n }\n </li>\n }\n </ol>\n\n @if (_activePanel(); as panel) {\n <div role=\"region\" class=\"min-w-0 flex-1\" [attr.aria-labelledby]=\"_activeTriggerId()\">\n <ng-container [ngTemplateOutlet]=\"panel\" />\n </div>\n }\n</div>\n" }]
5348
- }], ctorParameters: () => [], propDecorators: { _list: [{ type: i0.ViewChild, args: ['list', { isSignal: true }] }], indicator: [{ type: i0.ContentChild, args: [i0.forwardRef(() => YuwStepIndicatorDirective), { isSignal: true }] }], panels: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => YuwStepPanelDirective), { isSignal: true }] }], activeStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeStep", required: true }] }, { type: i0.Output, args: ["activeStepChange"] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], iconOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconOnly", required: false }] }], linear: [{ type: i0.Input, args: [{ isSignal: true, alias: "linear", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], steps: [{ type: i0.Input, args: [{ isSignal: true, alias: "steps", required: true }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
5428
+ }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class]=\"_rootClass()\">\n <ol #list yuwMouseScrollX [class]=\"_listClass()\" [attr.data-yuw-color]=\"color()\">\n @for (item of _items(); track item.step.id; let last = $last) {\n <li [class]=\"_stepClass()\">\n <button\n type=\"button\"\n [id]=\"item.triggerId\"\n [class]=\"item.triggerClass\"\n [disabled]=\"!item.reachable\"\n [attr.aria-current]=\"item.ariaCurrent\"\n [yuwTooltip]=\"item.step.label\"\n [tooltipDisabled]=\"!iconOnly()\"\n [position]=\"_tooltipPosition()\"\n (click)=\"select(item.step.id)\"\n >\n <span [class]=\"item.indicatorClass\">\n @if (indicator(); as custom) {\n <ng-container [ngTemplateOutlet]=\"custom.templateRef\" [ngTemplateOutletContext]=\"item.context\" />\n } @else if (item.state === 'completed') {\n <ng-icon name=\"lucideCheck\" aria-hidden=\"true\" />\n } @else {\n {{ item.index + 1 }}\n }\n </span>\n <span [class]=\"_labelClass()\">\n <span class=\"text-sm font-medium\">{{ item.step.label }}</span>\n @if (item.step.description) {\n <span class=\"text-xs text-muted-foreground\">{{ item.step.description }}</span>\n }\n </span>\n </button>\n @if (!last) {\n <span [class]=\"item.separatorClass\" aria-hidden=\"true\"></span>\n }\n </li>\n }\n </ol>\n\n @for (panel of _activePanel(); track panel.id) {\n <div role=\"region\" [class]=\"_panelClass()\" [attr.aria-labelledby]=\"_activeTriggerId()\">\n <ng-container [ngTemplateOutlet]=\"panel.templateRef\" />\n </div>\n }\n</div>\n" }]
5429
+ }], ctorParameters: () => [], propDecorators: { _list: [{ type: i0.ViewChild, args: ['list', { isSignal: true }] }], indicator: [{ type: i0.ContentChild, args: [i0.forwardRef(() => YuwStepIndicatorDirective), { isSignal: true }] }], panels: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => YuwStepPanelDirective), { isSignal: true }] }], activeStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeStep", required: true }] }, { type: i0.Output, args: ["activeStepChange"] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], iconOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconOnly", required: false }] }], linear: [{ type: i0.Input, args: [{ isSignal: true, alias: "linear", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], steps: [{ type: i0.Input, args: [{ isSignal: true, alias: "steps", required: true }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], stepChange: [{ type: i0.Output, args: ["stepChange"] }] } });
5349
5430
 
5350
5431
  /**
5351
5432
  * Container directive for a single file attachment card.
@@ -7383,11 +7464,17 @@ class YuwsFormSheetComponent {
7383
7464
  }
7384
7465
  }
7385
7466
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: YuwsFormSheetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
7386
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: YuwsFormSheetComponent, isStandalone: true, selector: "yuws-form-sheet", inputs: { backLabel: { classPropertyName: "backLabel", publicName: "backLabel", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, hideFooter: { classPropertyName: "hideFooter", publicName: "hideFooter", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: true, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: true, transformFunction: null }, panelClass: { classPropertyName: "panelClass", publicName: "panelClass", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, removeDisabled: { classPropertyName: "removeDisabled", publicName: "removeDisabled", isSignal: true, isRequired: false, transformFunction: null }, removeLabel: { classPropertyName: "removeLabel", publicName: "removeLabel", isSignal: true, isRequired: false, transformFunction: null }, restoreLabel: { classPropertyName: "restoreLabel", publicName: "restoreLabel", isSignal: true, isRequired: false, transformFunction: null }, saveDisabled: { classPropertyName: "saveDisabled", publicName: "saveDisabled", isSignal: true, isRequired: false, transformFunction: null }, saving: { classPropertyName: "saving", publicName: "saving", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { open: "openChange", back: "back", remove: "remove", restore: "restore", save: "save" }, providers: [provideIcons({ lucideArchiveRestore, lucideArrowLeft, lucideSave, lucideTrash2, lucideX })], ngImport: i0, template: "<yuw-sheet\n side=\"right\"\n [showTrigger]=\"false\"\n [panelClass]=\"panelClass()\"\n bodyClass=\"scroll-fade-y\"\n [title]=\"backLabel() ? undefined : title()\"\n [closeLabel]=\"backLabel() ? undefined : labels().close\"\n [(open)]=\"open\"\n>\n @if (backLabel(); as label) {\n <div yuwSheetHeader class=\"-ml-2 -mt-3 flex items-center gap-1 pb-3\">\n <yuw-button type=\"button\" variant=\"ghost\" size=\"icon-sm\" [ariaLabel]=\"label\" (clicked)=\"back.emit()\">\n <ng-icon name=\"lucideArrowLeft\" size=\"16\" />\n </yuw-button>\n <h2 class=\"text-base font-medium text-foreground\">{{ title() }}</h2>\n </div>\n }\n\n <ng-content />\n\n <div\n yuwSheetFooter\n class=\"flex flex-wrap items-center justify-between gap-2\"\n [style.display]=\"hideFooter() ? 'none' : null\"\n [attr.aria-busy]=\"saving()\"\n >\n @if (errorMessage(); as message) {\n <p role=\"alert\" class=\"w-full rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive\">{{ message }}</p>\n }\n\n @if (removeLabel(); as label) {\n <yuw-button\n variant=\"ghost\"\n color=\"destructive\"\n class=\"gap-2\"\n [disabled]=\"removeDisabled() || saving()\"\n (clicked)=\"remove.emit()\"\n >\n <ng-icon name=\"lucideTrash2\" size=\"16\" />\n {{ label }}\n </yuw-button>\n }\n\n <span class=\"ms-auto flex gap-2\">\n <yuw-button variant=\"outline\" (clicked)=\"onCancel()\">\n <ng-icon name=\"lucideX\" size=\"16\" />\n {{ labels().cancel }}\n </yuw-button>\n @if (restoreLabel(); as label) {\n <yuw-button color=\"primary\" [disabled]=\"saving()\" (clicked)=\"restore.emit()\">\n <ng-icon name=\"lucideArchiveRestore\" size=\"16\" />\n {{ label }}\n </yuw-button>\n }\n @if (!readonly()) {\n <yuw-button color=\"primary\" [disabled]=\"saveDisabled() || saving()\" (clicked)=\"save.emit()\">\n <ng-icon name=\"lucideSave\" size=\"16\" />\n {{ labels().save }}\n </yuw-button>\n }\n </span>\n </div>\n</yuw-sheet>\n", dependencies: [{ kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "component", type: YuwButtonComponent, selector: "yuw-button", inputs: ["animationDisabled", "ariaLabel", "color", "disabled", "href", "size", "target", "transparent", "type", "class", "variant", "yuwDropdownMenuTrigger"], outputs: ["clicked"] }, { kind: "component", type: YuwSheetComponent, selector: "yuw-sheet", inputs: ["ariaLabel", "ariaModal", "bodyClass", "closeLabel", "closeOnOutsidePointerEvents", "description", "open", "overlayClass", "panelClass", "scrollStrategy", "showTrigger", "side", "title", "triggerSize", "triggerVariant"], outputs: ["openChange"] }, { kind: "directive", type: YuwSheetFooterDirective, selector: "[yuwSheetFooter]" }, { kind: "directive", type: YuwSheetHeaderDirective, selector: "[yuwSheetHeader]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
7467
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.22", type: YuwsFormSheetComponent, isStandalone: true, selector: "yuws-form-sheet", inputs: { backLabel: { classPropertyName: "backLabel", publicName: "backLabel", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, hideFooter: { classPropertyName: "hideFooter", publicName: "hideFooter", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: true, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: true, transformFunction: null }, panelClass: { classPropertyName: "panelClass", publicName: "panelClass", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, removeDisabled: { classPropertyName: "removeDisabled", publicName: "removeDisabled", isSignal: true, isRequired: false, transformFunction: null }, removeLabel: { classPropertyName: "removeLabel", publicName: "removeLabel", isSignal: true, isRequired: false, transformFunction: null }, restoreLabel: { classPropertyName: "restoreLabel", publicName: "restoreLabel", isSignal: true, isRequired: false, transformFunction: null }, saveDisabled: { classPropertyName: "saveDisabled", publicName: "saveDisabled", isSignal: true, isRequired: false, transformFunction: null }, saving: { classPropertyName: "saving", publicName: "saving", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { open: "openChange", back: "back", remove: "remove", restore: "restore", save: "save" }, providers: [
7468
+ provideIcons({ lucideArchiveRestore, lucideArrowLeft, lucideSave, lucideTrash2, lucideX }),
7469
+ { provide: YuwSheetOpenState, useExisting: YuwsFormSheetComponent },
7470
+ ], ngImport: i0, template: "<yuw-sheet\n side=\"right\"\n [showTrigger]=\"false\"\n [panelClass]=\"panelClass()\"\n bodyClass=\"scroll-fade-y\"\n [title]=\"backLabel() ? undefined : title()\"\n [closeLabel]=\"backLabel() ? undefined : labels().close\"\n [(open)]=\"open\"\n>\n @if (backLabel(); as label) {\n <div yuwSheetHeader class=\"-ml-2 -mt-3 flex items-center gap-1 pb-3\">\n <yuw-button type=\"button\" variant=\"ghost\" size=\"icon-sm\" [ariaLabel]=\"label\" (clicked)=\"back.emit()\">\n <ng-icon name=\"lucideArrowLeft\" size=\"16\" />\n </yuw-button>\n <h2 class=\"text-base font-medium text-foreground\">{{ title() }}</h2>\n </div>\n }\n\n <ng-content />\n\n <div\n yuwSheetFooter\n class=\"flex flex-wrap items-center justify-between gap-2\"\n [style.display]=\"hideFooter() ? 'none' : null\"\n [attr.aria-busy]=\"saving()\"\n >\n @if (errorMessage(); as message) {\n <p role=\"alert\" class=\"w-full rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive\">{{ message }}</p>\n }\n\n @if (removeLabel(); as label) {\n <yuw-button\n variant=\"ghost\"\n color=\"destructive\"\n class=\"gap-2\"\n [disabled]=\"removeDisabled() || saving()\"\n (clicked)=\"remove.emit()\"\n >\n <ng-icon name=\"lucideTrash2\" size=\"16\" />\n {{ label }}\n </yuw-button>\n }\n\n <span class=\"ms-auto flex gap-2\">\n <yuw-button variant=\"outline\" (clicked)=\"onCancel()\">\n <ng-icon name=\"lucideX\" size=\"16\" />\n {{ labels().cancel }}\n </yuw-button>\n @if (restoreLabel(); as label) {\n <yuw-button color=\"primary\" [disabled]=\"saving()\" (clicked)=\"restore.emit()\">\n <ng-icon name=\"lucideArchiveRestore\" size=\"16\" />\n {{ label }}\n </yuw-button>\n }\n @if (!readonly()) {\n <yuw-button color=\"primary\" [disabled]=\"saveDisabled() || saving()\" (clicked)=\"save.emit()\">\n <ng-icon name=\"lucideSave\" size=\"16\" />\n {{ labels().save }}\n </yuw-button>\n }\n </span>\n </div>\n</yuw-sheet>\n", dependencies: [{ kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }, { kind: "component", type: YuwButtonComponent, selector: "yuw-button", inputs: ["animationDisabled", "ariaLabel", "color", "disabled", "href", "size", "target", "transparent", "type", "class", "variant", "yuwDropdownMenuTrigger"], outputs: ["clicked"] }, { kind: "component", type: YuwSheetComponent, selector: "yuw-sheet", inputs: ["ariaLabel", "ariaModal", "bodyClass", "closeLabel", "closeOnOutsidePointerEvents", "description", "open", "overlayClass", "panelClass", "scrollStrategy", "showTrigger", "side", "title", "triggerSize", "triggerVariant"], outputs: ["openChange"] }, { kind: "directive", type: YuwSheetFooterDirective, selector: "[yuwSheetFooter]" }, { kind: "directive", type: YuwSheetHeaderDirective, selector: "[yuwSheetHeader]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
7387
7471
  }
7388
7472
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.22", ngImport: i0, type: YuwsFormSheetComponent, decorators: [{
7389
7473
  type: Component,
7390
- args: [{ selector: 'yuws-form-sheet', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgIcon, YuwButtonComponent, YuwSheetComponent, YuwSheetFooterDirective, YuwSheetHeaderDirective], providers: [provideIcons({ lucideArchiveRestore, lucideArrowLeft, lucideSave, lucideTrash2, lucideX })], template: "<yuw-sheet\n side=\"right\"\n [showTrigger]=\"false\"\n [panelClass]=\"panelClass()\"\n bodyClass=\"scroll-fade-y\"\n [title]=\"backLabel() ? undefined : title()\"\n [closeLabel]=\"backLabel() ? undefined : labels().close\"\n [(open)]=\"open\"\n>\n @if (backLabel(); as label) {\n <div yuwSheetHeader class=\"-ml-2 -mt-3 flex items-center gap-1 pb-3\">\n <yuw-button type=\"button\" variant=\"ghost\" size=\"icon-sm\" [ariaLabel]=\"label\" (clicked)=\"back.emit()\">\n <ng-icon name=\"lucideArrowLeft\" size=\"16\" />\n </yuw-button>\n <h2 class=\"text-base font-medium text-foreground\">{{ title() }}</h2>\n </div>\n }\n\n <ng-content />\n\n <div\n yuwSheetFooter\n class=\"flex flex-wrap items-center justify-between gap-2\"\n [style.display]=\"hideFooter() ? 'none' : null\"\n [attr.aria-busy]=\"saving()\"\n >\n @if (errorMessage(); as message) {\n <p role=\"alert\" class=\"w-full rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive\">{{ message }}</p>\n }\n\n @if (removeLabel(); as label) {\n <yuw-button\n variant=\"ghost\"\n color=\"destructive\"\n class=\"gap-2\"\n [disabled]=\"removeDisabled() || saving()\"\n (clicked)=\"remove.emit()\"\n >\n <ng-icon name=\"lucideTrash2\" size=\"16\" />\n {{ label }}\n </yuw-button>\n }\n\n <span class=\"ms-auto flex gap-2\">\n <yuw-button variant=\"outline\" (clicked)=\"onCancel()\">\n <ng-icon name=\"lucideX\" size=\"16\" />\n {{ labels().cancel }}\n </yuw-button>\n @if (restoreLabel(); as label) {\n <yuw-button color=\"primary\" [disabled]=\"saving()\" (clicked)=\"restore.emit()\">\n <ng-icon name=\"lucideArchiveRestore\" size=\"16\" />\n {{ label }}\n </yuw-button>\n }\n @if (!readonly()) {\n <yuw-button color=\"primary\" [disabled]=\"saveDisabled() || saving()\" (clicked)=\"save.emit()\">\n <ng-icon name=\"lucideSave\" size=\"16\" />\n {{ labels().save }}\n </yuw-button>\n }\n </span>\n </div>\n</yuw-sheet>\n" }]
7474
+ args: [{ selector: 'yuws-form-sheet', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgIcon, YuwButtonComponent, YuwSheetComponent, YuwSheetFooterDirective, YuwSheetHeaderDirective], providers: [
7475
+ provideIcons({ lucideArchiveRestore, lucideArrowLeft, lucideSave, lucideTrash2, lucideX }),
7476
+ { provide: YuwSheetOpenState, useExisting: YuwsFormSheetComponent },
7477
+ ], template: "<yuw-sheet\n side=\"right\"\n [showTrigger]=\"false\"\n [panelClass]=\"panelClass()\"\n bodyClass=\"scroll-fade-y\"\n [title]=\"backLabel() ? undefined : title()\"\n [closeLabel]=\"backLabel() ? undefined : labels().close\"\n [(open)]=\"open\"\n>\n @if (backLabel(); as label) {\n <div yuwSheetHeader class=\"-ml-2 -mt-3 flex items-center gap-1 pb-3\">\n <yuw-button type=\"button\" variant=\"ghost\" size=\"icon-sm\" [ariaLabel]=\"label\" (clicked)=\"back.emit()\">\n <ng-icon name=\"lucideArrowLeft\" size=\"16\" />\n </yuw-button>\n <h2 class=\"text-base font-medium text-foreground\">{{ title() }}</h2>\n </div>\n }\n\n <ng-content />\n\n <div\n yuwSheetFooter\n class=\"flex flex-wrap items-center justify-between gap-2\"\n [style.display]=\"hideFooter() ? 'none' : null\"\n [attr.aria-busy]=\"saving()\"\n >\n @if (errorMessage(); as message) {\n <p role=\"alert\" class=\"w-full rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive\">{{ message }}</p>\n }\n\n @if (removeLabel(); as label) {\n <yuw-button\n variant=\"ghost\"\n color=\"destructive\"\n class=\"gap-2\"\n [disabled]=\"removeDisabled() || saving()\"\n (clicked)=\"remove.emit()\"\n >\n <ng-icon name=\"lucideTrash2\" size=\"16\" />\n {{ label }}\n </yuw-button>\n }\n\n <span class=\"ms-auto flex gap-2\">\n <yuw-button variant=\"outline\" (clicked)=\"onCancel()\">\n <ng-icon name=\"lucideX\" size=\"16\" />\n {{ labels().cancel }}\n </yuw-button>\n @if (restoreLabel(); as label) {\n <yuw-button color=\"primary\" [disabled]=\"saving()\" (clicked)=\"restore.emit()\">\n <ng-icon name=\"lucideArchiveRestore\" size=\"16\" />\n {{ label }}\n </yuw-button>\n }\n @if (!readonly()) {\n <yuw-button color=\"primary\" [disabled]=\"saveDisabled() || saving()\" (clicked)=\"save.emit()\">\n <ng-icon name=\"lucideSave\" size=\"16\" />\n {{ labels().save }}\n </yuw-button>\n }\n </span>\n </div>\n</yuw-sheet>\n" }]
7391
7478
  }], propDecorators: { backLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "backLabel", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], hideFooter: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideFooter", required: false }] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: true }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: true }] }, { type: i0.Output, args: ["openChange"] }], panelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelClass", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], removeDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "removeDisabled", required: false }] }], removeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "removeLabel", required: false }] }], restoreLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "restoreLabel", required: false }] }], saveDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "saveDisabled", required: false }] }], saving: [{ type: i0.Input, args: [{ isSignal: true, alias: "saving", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], back: [{ type: i0.Output, args: ["back"] }], remove: [{ type: i0.Output, args: ["remove"] }], restore: [{ type: i0.Output, args: ["restore"] }], save: [{ type: i0.Output, args: ["save"] }] } });
7392
7479
 
7393
7480
  /**