forty-cdk 0.16.0 → 0.18.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.
Files changed (118) hide show
  1. package/LICENSE +21 -21
  2. package/accordion/README.md +1 -1
  3. package/carousel/README.md +1 -1
  4. package/combobox/README.md +1 -0
  5. package/context-menu/README.md +18 -0
  6. package/date-picker/README.md +5 -2
  7. package/disclosure/README.md +1 -1
  8. package/dropdown-menu/README.md +16 -0
  9. package/fesm2022/forty-cdk-accordion.mjs +34 -4
  10. package/fesm2022/forty-cdk-accordion.mjs.map +1 -1
  11. package/fesm2022/forty-cdk-carousel.mjs +34 -4
  12. package/fesm2022/forty-cdk-carousel.mjs.map +1 -1
  13. package/fesm2022/forty-cdk-combobox.mjs +3 -3
  14. package/fesm2022/forty-cdk-combobox.mjs.map +1 -1
  15. package/fesm2022/forty-cdk-context-menu.mjs +108 -40
  16. package/fesm2022/forty-cdk-context-menu.mjs.map +1 -1
  17. package/fesm2022/forty-cdk-core.mjs +347 -26
  18. package/fesm2022/forty-cdk-core.mjs.map +1 -1
  19. package/fesm2022/forty-cdk-date-field.mjs +7 -2
  20. package/fesm2022/forty-cdk-date-field.mjs.map +1 -1
  21. package/fesm2022/forty-cdk-date-picker.mjs +44 -8
  22. package/fesm2022/forty-cdk-date-picker.mjs.map +1 -1
  23. package/fesm2022/forty-cdk-date-range-field.mjs +7 -2
  24. package/fesm2022/forty-cdk-date-range-field.mjs.map +1 -1
  25. package/fesm2022/forty-cdk-dialog.mjs +7 -6
  26. package/fesm2022/forty-cdk-dialog.mjs.map +1 -1
  27. package/fesm2022/forty-cdk-disclosure.mjs +5 -3
  28. package/fesm2022/forty-cdk-disclosure.mjs.map +1 -1
  29. package/fesm2022/forty-cdk-drawer.mjs +7 -6
  30. package/fesm2022/forty-cdk-drawer.mjs.map +1 -1
  31. package/fesm2022/forty-cdk-dropdown-menu.mjs +90 -21
  32. package/fesm2022/forty-cdk-dropdown-menu.mjs.map +1 -1
  33. package/fesm2022/forty-cdk-input.mjs +2 -4
  34. package/fesm2022/forty-cdk-input.mjs.map +1 -1
  35. package/fesm2022/forty-cdk-listbox.mjs +2 -1
  36. package/fesm2022/forty-cdk-listbox.mjs.map +1 -1
  37. package/fesm2022/forty-cdk-menu.mjs +321 -37
  38. package/fesm2022/forty-cdk-menu.mjs.map +1 -1
  39. package/fesm2022/forty-cdk-menubar.mjs +76 -17
  40. package/fesm2022/forty-cdk-menubar.mjs.map +1 -1
  41. package/fesm2022/forty-cdk-navigation-menu.mjs +141 -23
  42. package/fesm2022/forty-cdk-navigation-menu.mjs.map +1 -1
  43. package/fesm2022/forty-cdk-number-input.mjs +1 -2
  44. package/fesm2022/forty-cdk-number-input.mjs.map +1 -1
  45. package/fesm2022/forty-cdk-otp-input.mjs +6 -5
  46. package/fesm2022/forty-cdk-otp-input.mjs.map +1 -1
  47. package/fesm2022/forty-cdk-popover.mjs +5 -3
  48. package/fesm2022/forty-cdk-popover.mjs.map +1 -1
  49. package/fesm2022/forty-cdk-radio-group.mjs +43 -7
  50. package/fesm2022/forty-cdk-radio-group.mjs.map +1 -1
  51. package/fesm2022/forty-cdk-search.mjs +1 -2
  52. package/fesm2022/forty-cdk-search.mjs.map +1 -1
  53. package/fesm2022/forty-cdk-select.mjs +25 -9
  54. package/fesm2022/forty-cdk-select.mjs.map +1 -1
  55. package/fesm2022/forty-cdk-slider.mjs +6 -2
  56. package/fesm2022/forty-cdk-slider.mjs.map +1 -1
  57. package/fesm2022/forty-cdk-table.mjs +512 -75
  58. package/fesm2022/forty-cdk-table.mjs.map +1 -1
  59. package/fesm2022/forty-cdk-tabs.mjs +42 -24
  60. package/fesm2022/forty-cdk-tabs.mjs.map +1 -1
  61. package/fesm2022/forty-cdk-time-field.mjs +7 -2
  62. package/fesm2022/forty-cdk-time-field.mjs.map +1 -1
  63. package/fesm2022/forty-cdk-time-picker.mjs +37 -5
  64. package/fesm2022/forty-cdk-time-picker.mjs.map +1 -1
  65. package/fesm2022/forty-cdk-time-range-field.mjs +7 -2
  66. package/fesm2022/forty-cdk-time-range-field.mjs.map +1 -1
  67. package/fesm2022/forty-cdk-toast.mjs +34 -4
  68. package/fesm2022/forty-cdk-toast.mjs.map +1 -1
  69. package/fesm2022/forty-cdk-toggle.mjs +8 -5
  70. package/fesm2022/forty-cdk-toggle.mjs.map +1 -1
  71. package/fesm2022/forty-cdk-toolbar.mjs +5 -1
  72. package/fesm2022/forty-cdk-toolbar.mjs.map +1 -1
  73. package/fesm2022/forty-cdk-virtualization.mjs +5 -4
  74. package/fesm2022/forty-cdk-virtualization.mjs.map +1 -1
  75. package/input/README.md +4 -3
  76. package/listbox/README.md +1 -0
  77. package/menu/README.md +94 -3
  78. package/menubar/README.md +17 -17
  79. package/navigation-menu/README.md +3 -3
  80. package/number-input/README.md +2 -1
  81. package/otp-input/README.md +3 -1
  82. package/package.json +1 -1
  83. package/popover/README.md +3 -3
  84. package/radio-group/README.md +1 -1
  85. package/search/README.md +4 -2
  86. package/select/README.md +3 -1
  87. package/table/README.md +12 -1
  88. package/tabs/README.md +1 -1
  89. package/time-picker/README.md +21 -0
  90. package/toast/README.md +1 -1
  91. package/toggle/README.md +4 -3
  92. package/types/forty-cdk-accordion.d.ts +47 -9
  93. package/types/forty-cdk-carousel.d.ts +72 -27
  94. package/types/forty-cdk-context-menu.d.ts +76 -12
  95. package/types/forty-cdk-core.d.ts +266 -34
  96. package/types/forty-cdk-date-field.d.ts +5 -0
  97. package/types/forty-cdk-date-picker.d.ts +32 -6
  98. package/types/forty-cdk-date-range-field.d.ts +5 -0
  99. package/types/forty-cdk-dialog.d.ts +6 -4
  100. package/types/forty-cdk-disclosure.d.ts +4 -1
  101. package/types/forty-cdk-drawer.d.ts +6 -4
  102. package/types/forty-cdk-dropdown-menu.d.ts +59 -9
  103. package/types/forty-cdk-menu.d.ts +260 -17
  104. package/types/forty-cdk-menubar.d.ts +57 -13
  105. package/types/forty-cdk-navigation-menu.d.ts +142 -36
  106. package/types/forty-cdk-otp-input.d.ts +4 -3
  107. package/types/forty-cdk-popover.d.ts +4 -1
  108. package/types/forty-cdk-radio-group.d.ts +34 -19
  109. package/types/forty-cdk-select.d.ts +22 -5
  110. package/types/forty-cdk-shared.d.ts +1 -1
  111. package/types/forty-cdk-slider.d.ts +4 -0
  112. package/types/forty-cdk-table.d.ts +196 -26
  113. package/types/forty-cdk-tabs.d.ts +72 -16
  114. package/types/forty-cdk-time-field.d.ts +5 -0
  115. package/types/forty-cdk-time-picker.d.ts +26 -0
  116. package/types/forty-cdk-time-range-field.d.ts +5 -0
  117. package/types/forty-cdk-toast.d.ts +58 -17
  118. package/types/forty-cdk-toggle.d.ts +4 -1
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 tutkli
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 tutkli
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -134,4 +134,4 @@ forty-cdk ships no styles. Add your own class to each piece — the `for*` selec
134
134
 
135
135
  ## Wrapping in a design system
136
136
 
137
- Subclassing the root is the supported pattern; the subclass must re-provide `FOR_ACCORDION_CONTEXT` because Angular does not inherit a directive's `providers`, and every projected piece resolves its context through it. See [Wrapping non-form roots](../../../docs/wrapping-non-form-roots.md).
137
+ Subclassing the root is the supported pattern; the subclass must spread `provideForAccordion(MyRoot)` into its own `providers` because Angular does not inherit a directive's `providers`, and every projected piece resolves its context through it. Re-providing `FOR_ACCORDION_CONTEXT` by hand is not enough: the root also provides an unexported registration token the wrapper cannot name. See [Wrapping non-form roots](../../../docs/wrapping-non-form-roots.md).
@@ -426,4 +426,4 @@ The example CSS above is LTR-only by default.
426
426
 
427
427
  ## Wrapping in a design system
428
428
 
429
- Subclassing the root is the supported pattern; the subclass must re-provide `FOR_CAROUSEL_CONTEXT` because Angular does not inherit a directive's `providers`, and every projected piece resolves its context through it. See [Wrapping non-form roots](../../../docs/wrapping-non-form-roots.md).
429
+ Subclassing the root is the supported pattern; the subclass must spread `provideForCarousel(MyRoot)` into its own `providers` because Angular does not inherit a directive's `providers`, and every projected piece resolves its context through it. Re-providing `FOR_CAROUSEL_CONTEXT` by hand is not enough: the root also provides an unexported registration token the wrapper cannot name. See [Wrapping non-form roots](../../../docs/wrapping-non-form-roots.md).
@@ -118,6 +118,7 @@ Input tables are not yet tabulated for this primitive. See the feature sections
118
118
  | ------------------------ | ------------------ | ------------------------------------------------------------------- |
119
119
  | `[forCombobox]` | `data-state` | `open` \| `closed` |
120
120
  | `[forCombobox]` | `data-disabled` | present / absent |
121
+ | `[forCombobox]` | `data-readonly` | present / absent |
121
122
  | `[forComboboxInput]` | `data-state` | `open` \| `closed` |
122
123
  | `[forComboboxInput]` | `data-disabled` | present / absent |
123
124
  | `[forComboboxContent]` | `data-state` | `open` \| `closed` |
@@ -95,6 +95,24 @@ Angular resolves `ng-template` DI at the template's **declaration** site, not wh
95
95
  </ng-template>
96
96
  ```
97
97
 
98
+ ### Sharing one menu with a second opener
99
+
100
+ `[forContextMenu]` is a **single-opener preset**: one root, one right-click region. When the same actions must also be reachable another way — the canonical case being a table row with a right-click region _and_ a kebab button — bind the trigger to a `[forMenu]` root instead, which drives one `[forMenuContent]` block from any number of openers. See [Shared openers](../menu/README.md#shared-openers-formenu).
101
+
102
+ The same explicit-reference input carries it, and here the binding is **required** rather than optional: the trigger resolves `FOR_CONTEXT_MENU_CONTEXT`, which `[forMenu]` deliberately does not provide (`forty-cdk/menu` must not depend on `forty-cdk/context-menu`).
103
+
104
+ ```html
105
+ <tr forMenu #row="forMenu" [(open)]="open" ariaLabel="Row actions">
106
+ <td [forContextMenuTrigger]="row">…cells…</td>
107
+ <td>
108
+ <button [forDropdownMenuTrigger]="row" [menuPositioning]="{ sideOffset: 4 }">⋮</button>
109
+ </td>
110
+ <!-- one content block, no duplication -->
111
+ </tr>
112
+ ```
113
+
114
+ Both triggers carry `[menuPositioning]`, a partial `{ side, align, sideOffset, alignOffset }` override applied only to the opens that trigger drives, with each omitted key falling back to the root's input. It exists because a shared root cannot pick offsets that suit heterogeneous openers: the region above keeps the root's `sideOffset` of `0` — flush at the cursor, which is what a pointer-anchored menu wants — while the sibling button opener asks for the 4px of clearance a menu button wants. Under a `[forContextMenu]` root it resolves the same way, where it is simply a per-trigger spelling of the root's inputs. See [Per-opener positioning](../menu/README.md#per-opener-positioning).
115
+
98
116
  ## API
99
117
 
100
118
  ### `ForContextMenu`
@@ -171,8 +171,10 @@ Plus the shared `FormUiControl` inputs from the base (`disabled`, `readonly`, `r
171
171
  | ------------------------ | ------------------ | ------------------ |
172
172
  | `[forDatePicker]` | `data-state` | `open` \| `closed` |
173
173
  | `[forDatePicker]` | `data-disabled` | present \| absent |
174
+ | `[forDatePicker]` | `data-readonly` | present \| absent |
174
175
  | `[forDatePickerTrigger]` | `data-state` | `open` \| `closed` |
175
176
  | `[forDatePickerTrigger]` | `data-disabled` | present \| absent |
177
+ | `[forDatePickerTrigger]` | `data-readonly` | present \| absent |
176
178
  | `[forDatePickerContent]` | `data-state` | `open` \| `closed` |
177
179
  | `[forDatePickerValue]` | `data-placeholder` | present \| absent |
178
180
 
@@ -333,9 +335,10 @@ Inside the surface, the projected `ForCalendar` owns the full grid keyboard map
333
335
 
334
336
  Implements the [WAI-ARIA Date Picker Dialog pattern](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/examples/datepicker-dialog/).
335
337
 
336
- - **`aria-haspopup="dialog"`** on the trigger, with `aria-expanded` reflecting `open()` and `aria-controls` pointing at the surface while open.
338
+ - **`role="combobox"`** on the trigger with **`aria-haspopup="dialog"`**, `aria-expanded` reflecting `open()`, and `aria-controls` pointing at the surface while open — the same shape `[forSelectTrigger]` / `[forTimePickerTrigger]` ship, with the `dialog` popup token ARIA 1.2 allows for a combobox surface. The role is also what makes the form-control ARIA below legal: `role="button"` supports neither `aria-readonly` nor `aria-required`.
337
339
  - **`role="dialog"`** on the surface, named by `[ariaLabel]` (or `aria-labelledby` the trigger when no label is set). `aria-modal="true"` only in modal mode (truthy-only).
338
- - **Form-control ARIA** (`aria-disabled` / `aria-readonly` / `aria-required` / `aria-invalid` / `aria-busy`) is reflected on the focusable trigger so assistive tech announces validity on the element that takes focus.
340
+ - **Form-control ARIA** (`aria-readonly` / `aria-required` / `aria-invalid` / `aria-busy`) is reflected on the focusable trigger so assistive tech announces validity on the element that takes focus, alongside the `data-readonly` styling hook. The disabled state is the exception: it reflects through the native `disabled` attribute alone (plus `data-disabled`), never `aria-disabled` — one channel per #561 D2.
341
+ - **Inside a `[forField]` the labelled element is the trigger**, not the `[forDatePicker]` / `[forDateRangePicker]` wrapper: the field's `controlId` and its `aria-labelledby` / `aria-describedby` / `aria-errormessage` land on `[forDatePickerTrigger]`, so `[forLabel]`'s `for` points at the element that takes focus, clicking a non-`<label>` `[forLabel]` opens the surface, and Signal Forms' focus-on-error reaches the trigger. `role="combobox"` takes its name from the author, so this is the channel that names the control — the root's `[ariaLabel]` names the `role="dialog"` surface instead.
339
342
  - **Focus management**: focus enters the surface on open (the calendar's roving cell in non-modal mode) and returns to the trigger on close, both vetoable via `(autoFocusOnOpen)` / `(autoFocusOnClose)`.
340
343
  - **Dismissal**: Escape (`(escapeKeyDown)`) and outside-pointer (`(pointerDownOutside)` / `(interactOutside)`) close the surface, each vetoable.
341
344
 
@@ -76,7 +76,7 @@ The library ships no styles. Hide animations / transitions can be driven off `da
76
76
  | `data-state` | `open` \| `closed` |
77
77
  | `data-disabled` | present \| absent |
78
78
 
79
- Reflects on its host: `id`, `aria-expanded`, `aria-controls`, `disabled`, `data-state`. Toggles the state on click. The disabled reflection (`disabled`, `aria-disabled`, `data-disabled`) and the click guard follow the effective state — the trigger's own `disabled` OR the root's.
79
+ Reflects on its host: `id`, `aria-expanded`, `aria-controls`, `disabled`, `data-state`. Toggles the state on click. The disabled reflection (the native `disabled` attribute plus `data-disabled`; no `aria-disabled`, single channel per #561 D2) and the click guard follow the effective state — the trigger's own `disabled` OR the root's.
80
80
 
81
81
  `aria-controls` is emitted only while open — mirroring the overlay triggers' open-only gating — so the reference never dangles at an unmounted panel under the recommended `@if (open())` mount pattern.
82
82
 
@@ -113,6 +113,22 @@ Angular resolves `ng-template` DI at the template's **declaration** site, not wh
113
113
  </ng-template>
114
114
  ```
115
115
 
116
+ ### Sharing one menu with a second opener
117
+
118
+ `[forDropdownMenu]` is a **single-opener preset**: one root, one button trigger. When the same actions must also be reachable another way — the canonical case being a table row with a kebab button _and_ a right-click region over the whole row — bind the trigger to a `[forMenu]` root instead, which drives one `[forMenuContent]` block from any number of openers. See [Shared openers](../menu/README.md#shared-openers-formenu).
119
+
120
+ ```html
121
+ <tr forMenu #row="forMenu" [(open)]="open" ariaLabel="Row actions">
122
+ <td [forContextMenuTrigger]="row">…cells…</td>
123
+ <td>
124
+ <button [forDropdownMenuTrigger]="row" [menuPositioning]="{ sideOffset: 4 }">⋮</button>
125
+ </td>
126
+ <!-- one content block, no duplication -->
127
+ </tr>
128
+ ```
129
+
130
+ `[menuPositioning]` is the trigger's own placement override — a partial `{ side, align, sideOffset, alignOffset }`, each key falling back to the root's input when omitted. It exists because a shared root cannot pick offsets that suit heterogeneous openers: the `sideOffset: 4` above keeps the button-opened menu clear of the button while a sibling right-click region still opens flush at the cursor. Under a `[forDropdownMenu]` root it resolves the same way, where it is simply a per-trigger spelling of the root's inputs. See [Per-opener positioning](../menu/README.md#per-opener-positioning).
131
+
116
132
  ## API
117
133
 
118
134
  ### `ForDropdownMenu`
@@ -4,8 +4,10 @@ import { Collection, injectTextDirection, moveIndex, IdGenerator, adoptHostId, h
4
4
 
5
5
  const FOR_ACCORDION_CONTEXT = new InjectionToken('FOR_ACCORDION_CONTEXT');
6
6
  const FOR_ACCORDION_ITEM_CONTEXT = new InjectionToken('FOR_ACCORDION_ITEM_CONTEXT');
7
+ /** DI token carrying the internal {@link AccordionContext}. Provided by `[forAccordion]`. */
8
+ const ACCORDION_CONTEXT = new InjectionToken('ACCORDION_CONTEXT');
7
9
  function injectAccordionContext(piece) {
8
- const ctx = inject(FOR_ACCORDION_CONTEXT, { optional: true });
10
+ const ctx = inject(ACCORDION_CONTEXT, { optional: true });
9
11
  if (!ctx) {
10
12
  throw new Error(`[forty-cdk/accordion] ${piece} must be used inside a [forAccordion] element.`);
11
13
  }
@@ -138,7 +140,7 @@ class ForAccordion {
138
140
  this.#triggers.unregister(handle);
139
141
  }
140
142
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: ForAccordion, deps: [], target: i0.ɵɵFactoryTarget.Directive });
141
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: ForAccordion, isStandalone: true, selector: "[forAccordion]", inputs: { multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, _dirInput: { classPropertyName: "_dirInput", publicName: "dir", isSignal: true, isRequired: false, transformFunction: null }, loop: { classPropertyName: "loop", publicName: "loop", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { properties: { "attr.data-orientation": "orientation()", "attr.data-disabled": "disabled() ? \"\" : null", "attr.dir": "dir()" } }, providers: [{ provide: FOR_ACCORDION_CONTEXT, useExisting: ForAccordion }], exportAs: ["forAccordion"], ngImport: i0 });
143
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: ForAccordion, isStandalone: true, selector: "[forAccordion]", inputs: { multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, _dirInput: { classPropertyName: "_dirInput", publicName: "dir", isSignal: true, isRequired: false, transformFunction: null }, loop: { classPropertyName: "loop", publicName: "loop", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { properties: { "attr.data-orientation": "orientation()", "attr.data-disabled": "disabled() ? \"\" : null", "attr.dir": "dir()" } }, providers: provideForAccordion(ForAccordion), exportAs: ["forAccordion"], ngImport: i0 });
142
144
  }
143
145
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: ForAccordion, decorators: [{
144
146
  type: Directive,
@@ -150,9 +152,37 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
150
152
  '[attr.data-disabled]': 'disabled() ? "" : null',
151
153
  '[attr.dir]': 'dir()',
152
154
  },
153
- providers: [{ provide: FOR_ACCORDION_CONTEXT, useExisting: ForAccordion }],
155
+ providers: provideForAccordion(ForAccordion),
154
156
  }]
155
157
  }], propDecorators: { multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], collapsible: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsible", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], _dirInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }], loop: [{ type: i0.Input, args: [{ isSignal: true, alias: "loop", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }] } });
158
+ /**
159
+ * The providers a `[forAccordion]` root installs: the public
160
+ * {@link FOR_ACCORDION_CONTEXT}, aliased to `root`, plus the internal
161
+ * coordination token the accordion's pieces resolve.
162
+ *
163
+ * `ForAccordion` declares its own providers through this helper, so a wrapper
164
+ * that **subclasses** the root has a single call to keep in step with it. That
165
+ * matters because Angular does not inherit a directive's `providers`: a subclass
166
+ * carrying its own `@Directive` metadata replaces the array wholesale, so
167
+ * re-providing `FOR_ACCORDION_CONTEXT` alone leaves the internal token absent
168
+ * and every piece orphans with the "must be used inside a [forAccordion]
169
+ * element" error. That token is deliberately unnameable outside the library
170
+ * ([#1399](https://github.com/tutkli/forty-cdk/issues/1399)), which is why the
171
+ * wrapper cannot list it by hand.
172
+ *
173
+ * ```ts
174
+ * providers: provideForAccordion(MyAccordion),
175
+ * ```
176
+ *
177
+ * Wrapping through `hostDirectives: [ForAccordion]` needs none of this — a host
178
+ * directive brings its own providers to the element.
179
+ */
180
+ function provideForAccordion(root) {
181
+ return [
182
+ { provide: FOR_ACCORDION_CONTEXT, useExisting: root },
183
+ { provide: ACCORDION_CONTEXT, useExisting: root },
184
+ ];
185
+ }
156
186
 
157
187
  /**
158
188
  * One section of a `ForAccordion`. Owns the unique `value` identifying this
@@ -354,5 +384,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
354
384
  * Generated bundle index. Do not edit.
355
385
  */
356
386
 
357
- export { FOR_ACCORDION_CONTEXT, FOR_ACCORDION_ITEM_CONTEXT, ForAccordion, ForAccordionContent, ForAccordionItem, ForAccordionTrigger };
387
+ export { FOR_ACCORDION_CONTEXT, FOR_ACCORDION_ITEM_CONTEXT, ForAccordion, ForAccordionContent, ForAccordionItem, ForAccordionTrigger, provideForAccordion };
358
388
  //# sourceMappingURL=forty-cdk-accordion.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"forty-cdk-accordion.mjs","sources":["../../../projects/forty-cdk/accordion/src/accordion-context.ts","../../../projects/forty-cdk/accordion/src/accordion.ts","../../../projects/forty-cdk/accordion/src/accordion-item.ts","../../../projects/forty-cdk/accordion/src/accordion-trigger.ts","../../../projects/forty-cdk/accordion/src/accordion-content.ts","../../../projects/forty-cdk/accordion/src/forty-cdk-accordion.ts"],"sourcesContent":["import { inject, InjectionToken, type Signal } from '@angular/core';\n\nimport { type ListNavigationAction, type WritingDirection } from 'forty-cdk/core';\n\n/**\n * Registry entry for one `ForAccordionTrigger`. Triggers register their host\n * element so the root can drive keyboard navigation over its own triggers\n * without an unscoped DOM query that would leak into nested accordions.\n */\nexport interface ForAccordionTriggerHandle {\n readonly host: HTMLElement;\n readonly disabled: Signal<boolean>;\n}\n\n/**\n * Coordination contract owned by the `ForAccordion` root.\n * Items derive their state from this context; triggers route clicks and\n * keyboard navigation through it.\n */\nexport interface ForAccordionContext {\n readonly multiple: Signal<boolean>;\n readonly collapsible: Signal<boolean>;\n /** Whether the whole accordion is disabled; each item ORs this into its own disabled state. */\n readonly disabled: Signal<boolean>;\n readonly orientation: Signal<'horizontal' | 'vertical'>;\n readonly dir: Signal<WritingDirection>;\n isExpanded(itemValue: string): boolean;\n toggle(itemValue: string): void;\n /** Whether the given item is allowed to collapse right now. */\n canCollapse(itemValue: string): boolean;\n /**\n * Focus a sibling trigger relative to the one currently focused. Disabled\n * triggers are skipped. `currentTrigger` is the element from which the\n * keyboard event originated. Navigation stays within this accordion's own\n * registered triggers, so a nested accordion does not cross-contaminate.\n */\n focusByOffset(currentTrigger: HTMLElement, action: ListNavigationAction): void;\n registerTrigger(handle: ForAccordionTriggerHandle): void;\n unregisterTrigger(handle: ForAccordionTriggerHandle): void;\n}\n\n/**\n * Per-item state contract. Provided by `ForAccordionItem`, consumed by\n * its `ForAccordionTrigger` and `ForAccordionContent`.\n */\nexport interface ForAccordionItemContext {\n readonly expanded: Signal<boolean>;\n readonly disabled: Signal<boolean>;\n readonly value: Signal<string>;\n readonly triggerId: Signal<string>;\n readonly contentId: Signal<string>;\n /** Adopts a consumer-set static `id` on the trigger host into `triggerId`. */\n adoptTriggerId(el: HTMLElement): void;\n /** Adopts a consumer-set static `id` on the content host into `contentId`. */\n adoptContentId(el: HTMLElement): void;\n toggle(): void;\n}\n\nexport const FOR_ACCORDION_CONTEXT = new InjectionToken<ForAccordionContext>(\n 'FOR_ACCORDION_CONTEXT',\n);\n\nexport const FOR_ACCORDION_ITEM_CONTEXT = new InjectionToken<ForAccordionItemContext>(\n 'FOR_ACCORDION_ITEM_CONTEXT',\n);\n\nexport function injectAccordionContext(piece: string): ForAccordionContext {\n const ctx = inject(FOR_ACCORDION_CONTEXT, { optional: true });\n if (!ctx) {\n throw new Error(`[forty-cdk/accordion] ${piece} must be used inside a [forAccordion] element.`);\n }\n return ctx;\n}\n\nexport function injectAccordionItemContext(piece: string): ForAccordionItemContext {\n const ctx = inject(FOR_ACCORDION_ITEM_CONTEXT, { optional: true });\n if (!ctx) {\n throw new Error(\n `[forty-cdk/accordion] ${piece} must be used inside a [forAccordionItem] element.`,\n );\n }\n return ctx;\n}\n","import { booleanAttribute, Directive, input, model } from '@angular/core';\n\nimport {\n Collection,\n type ListNavigationAction,\n moveIndex,\n type WritingDirection,\n injectTextDirection,\n} from 'forty-cdk/core';\nimport {\n FOR_ACCORDION_CONTEXT,\n type ForAccordionContext,\n type ForAccordionTriggerHandle,\n} from './accordion-context';\n\n/**\n * Root of the Accordion primitive. Holds the open value(s) and orchestrates\n * single/multiple expansion, collapse rules, and keyboard navigation between\n * triggers.\n *\n * Implements the [WAI-ARIA Accordion pattern](https://www.w3.org/WAI/ARIA/apg/patterns/accordion/).\n *\n * State is modeled as `value: readonly string[]` regardless of mode:\n * - In single mode (`multiple=false`, default), the array has 0 or 1 element.\n * - In multiple mode, any number of items can be open.\n *\n * @example\n * ```html\n * <div forAccordion [(value)]=\"open\" collapsible>\n * <div forAccordionItem value=\"a\">\n * <h3><button type=\"button\" forAccordionTrigger>A</button></h3>\n * <section forAccordionContent>...</section>\n * </div>\n * <div forAccordionItem value=\"b\">...</div>\n * </div>\n * ```\n */\n@Directive({\n selector: '[forAccordion]',\n exportAs: 'forAccordion',\n host: {\n '[attr.data-orientation]': 'orientation()',\n '[attr.data-disabled]': 'disabled() ? \"\" : null',\n '[attr.dir]': 'dir()',\n },\n providers: [{ provide: FOR_ACCORDION_CONTEXT, useExisting: ForAccordion }],\n})\nexport class ForAccordion implements ForAccordionContext {\n readonly #triggers = new Collection<ForAccordionTriggerHandle>();\n\n /** When true, multiple items can be expanded simultaneously. */\n readonly multiple = input(false, { transform: booleanAttribute });\n\n /**\n * When true, the whole accordion is disabled: every item's trigger reflects\n * the native `disabled` attribute (dropped from the Tab order and skipped by\n * arrow-key navigation) and cannot toggle. Composes with a per-item\n * `[disabled]` — an item is effectively disabled when either is set. Mirrors\n * the root `disabled` on `ForTabs` / `ForStepper` / `ForDisclosure`.\n */\n readonly disabled = input(false, { transform: booleanAttribute });\n\n /**\n * Single mode only: when true, the open item can be collapsed by clicking\n * its trigger. When false, exactly one item stays open at all times once\n * any has been opened.\n */\n readonly collapsible = input(false, { transform: booleanAttribute });\n\n /**\n * Layout direction of the trigger list. `'vertical'` (default) maps\n * ArrowUp/Down to prev/next; `'horizontal'` maps ArrowLeft/Right (with RTL\n * swap when `dir='rtl'`).\n */\n readonly orientation = input<'horizontal' | 'vertical'>('vertical');\n\n /**\n * Writing direction. Only relevant when `orientation='horizontal'`. When\n * unset (default `null`), the inherited ambient direction is resolved from\n * the nearest ancestor carrying a `dir` attribute (or `<html dir>`),\n * defaulting to `'ltr'`. An explicit `[dir]` always wins. The resolved\n * value is reflected to the host `dir` attribute and drives arrow-key\n * semantics.\n */\n readonly _dirInput = input<WritingDirection | null>(null, { alias: 'dir' });\n readonly dir = injectTextDirection(this._dirInput);\n\n /**\n * When true (default), arrow navigation between triggers wraps at the ends —\n * moving past the last trigger focuses the first and vice versa. Set `false`\n * to stop at the boundaries. Mirrors the `loop` input on `ForTabs` and\n * `ForListbox`.\n */\n readonly loop = input(true, { transform: booleanAttribute });\n\n /**\n * Two-way bindable. List of currently expanded item values. In single\n * mode the array has 0 or 1 element. The `model()` change emitter\n * (`(valueChange)`) fires only on internal toggles, never on consumer\n * writes via `[(value)]` — observe transitions without binding back.\n */\n readonly value = model<readonly string[]>([]);\n\n isExpanded(itemValue: string): boolean {\n return this.value().includes(itemValue);\n }\n\n toggle(itemValue: string): void {\n const current = this.value();\n const isOpen = current.includes(itemValue);\n\n if (isOpen) {\n if (!this.canCollapse(itemValue)) {\n return;\n }\n this.value.set(current.filter((v) => v !== itemValue));\n return;\n }\n\n if (this.multiple()) {\n this.value.set([...current, itemValue]);\n } else {\n this.value.set([itemValue]);\n }\n }\n\n canCollapse(_itemValue: string): boolean {\n return this.multiple() || this.collapsible();\n }\n\n focusByOffset(currentTrigger: HTMLElement, action: ListNavigationAction): void {\n const triggers = this.#triggers.items();\n if (triggers.length === 0) {\n return;\n }\n const currentIndex = triggers.findIndex((t) => t.host === currentTrigger);\n if (currentIndex === -1 && action !== 'first' && action !== 'last') {\n return;\n }\n const next = moveIndex(currentIndex < 0 ? 0 : currentIndex, triggers.length, action, {\n loop: this.loop(),\n isDisabled: (i) => triggers[i]?.disabled() ?? false,\n });\n if (next !== null) {\n triggers[next]?.host.focus();\n }\n }\n\n registerTrigger(handle: ForAccordionTriggerHandle): void {\n this.#triggers.register(handle);\n }\n\n unregisterTrigger(handle: ForAccordionTriggerHandle): void {\n this.#triggers.unregister(handle);\n }\n}\n","import { booleanAttribute, computed, Directive, inject, input, signal } from '@angular/core';\n\nimport { adoptHostId, IdGenerator } from 'forty-cdk/core';\nimport {\n FOR_ACCORDION_ITEM_CONTEXT,\n type ForAccordionItemContext,\n injectAccordionContext,\n} from './accordion-context';\n\n/**\n * One section of a `ForAccordion`. Owns the unique `value` identifying this\n * item to the root and exposes the per-item context that the trigger and\n * content read.\n */\n@Directive({\n selector: '[forAccordionItem]',\n exportAs: 'forAccordionItem',\n host: {\n '[attr.data-state]': 'expanded() ? \"open\" : \"closed\"',\n '[attr.data-disabled]': 'disabled() ? \"\" : null',\n '[attr.data-orientation]': 'parent.orientation()',\n },\n providers: [{ provide: FOR_ACCORDION_ITEM_CONTEXT, useExisting: ForAccordionItem }],\n})\nexport class ForAccordionItem implements ForAccordionItemContext {\n protected readonly parent = injectAccordionContext('ForAccordionItem');\n readonly #idGen = inject(IdGenerator);\n\n /** Unique identifier of this item within the accordion. Required. */\n readonly value = input.required<string>();\n\n /**\n * When true, this item's trigger ignores clicks and reflects the native\n * `disabled` attribute (not `aria-disabled`): dropped from the Tab order and\n * skipped by arrow-key navigation, but kept in the accessibility tree so\n * screen readers still announce it. See `ForAccordionTrigger` for the\n * rationale (rule #561 D2). Bind via `[disabled]`; read the composed\n * {@link disabled} for state.\n */\n readonly disabledInput = input(false, { transform: booleanAttribute, alias: 'disabled' });\n\n /**\n * Effective disabled: this item's own `[disabled]` OR'd with the root\n * `[forAccordion]`'s `disabled`. Everything that gates on the item's disabled\n * state — native attribute reflection, trigger click, arrow-navigation skip,\n * `data-disabled` — reads this, so disabling the whole accordion disables\n * every item.\n */\n readonly disabled = computed(() => this.disabledInput() || this.parent.disabled());\n\n readonly #triggerId = signal(this.#idGen.next('for-accordion-trigger'));\n readonly #contentId = signal(this.#idGen.next('for-accordion-content'));\n\n readonly triggerId = this.#triggerId.asReadonly();\n readonly contentId = this.#contentId.asReadonly();\n\n readonly expanded = computed(() => this.parent.isExpanded(this.value()));\n\n /**\n * Adopts a consumer-set static `id` on the `[forAccordionTrigger]` host into\n * `triggerId` (preserving anchors / external `aria-labelledby` references /\n * label `for`) instead of letting the `[id]` host binding clobber it.\n */\n adoptTriggerId(el: HTMLElement): void {\n adoptHostId(el, this.#triggerId);\n }\n\n /** Adopts a consumer-set static `id` on the content host into `contentId`. */\n adoptContentId(el: HTMLElement): void {\n adoptHostId(el, this.#contentId);\n }\n\n toggle(): void {\n if (this.disabled()) {\n return;\n }\n this.parent.toggle(this.value());\n }\n}\n","import { computed, Directive, ElementRef, inject } from '@angular/core';\n\nimport {\n hostButtonType,\n registerHandle,\n reflectDisabled,\n resolveListNavigation,\n} from 'forty-cdk/core';\nimport { injectAccordionContext, injectAccordionItemContext } from './accordion-context';\n\n/**\n * Header button for a `ForAccordionItem`. Apply on a `<button>` wrapped in a\n * heading element (`<h2>`–`<h6>`) so APG landmark navigation works. The\n * directive host-binds `type=\"button\"` so a trigger inside a `<form>` never\n * submits it on toggle.\n *\n * Handles ARIA wiring, click-to-toggle, and the recommended keyboard\n * navigation (ArrowDown / ArrowUp / Home / End).\n *\n * `aria-controls` is emitted only while the item is expanded — mirroring the\n * overlay triggers' open-only gating — so the reference never dangles at an\n * unmounted panel under the recommended `@if (item.expanded())` mount pattern.\n */\n@Directive({\n selector: '[forAccordionTrigger]',\n exportAs: 'forAccordionTrigger',\n host: {\n '[attr.type]': 'buttonType()',\n '[id]': 'item.triggerId()',\n '[attr.aria-expanded]': 'item.expanded() ? \"true\" : \"false\"',\n '[attr.aria-controls]': 'item.expanded() ? item.contentId() : null',\n '[attr.aria-disabled]': 'ariaDisabled() ? \"true\" : null',\n '[attr.data-state]': 'item.expanded() ? \"open\" : \"closed\"',\n '[attr.data-disabled]': 'item.disabled() ? \"\" : null',\n '[attr.data-orientation]': 'parent.orientation()',\n '(click)': 'item.toggle()',\n '(keydown)': 'onKeyDown($event)',\n },\n})\nexport class ForAccordionTrigger {\n protected readonly buttonType = hostButtonType();\n\n readonly #host = inject<ElementRef<HTMLElement>>(ElementRef);\n protected readonly parent = injectAccordionContext('ForAccordionTrigger');\n protected readonly item = injectAccordionItemContext('ForAccordionTrigger');\n\n /**\n * APG: aria-disabled is true only when the panel is open AND the accordion\n * disallows collapse. A real `disabled` item is reflected via the native\n * `disabled` attribute instead — the sanctioned exception in rule #561 (D2):\n * the trigger is a real single-purpose `<button>`, not a roving collection\n * item (every trigger stays independently in the Tab order; the arrow-key\n * navigation is an APG-optional enhancement layered on top, not a\n * roving-tabindex collection), so native `disabled` is correct here. The\n * button stays in the accessibility tree — screen readers still announce it\n * as unavailable in browse mode — while being dropped from the Tab order and\n * the arrow-key navigation (which `focusByOffset` already skips), keeping\n * disabled triggers uniformly unreachable. The APG Accordion pattern does not\n * require disabled headers to remain focusable.\n */\n protected readonly ariaDisabled = computed(() => {\n if (this.item.disabled()) {\n return false;\n }\n return this.item.expanded() && !this.parent.canCollapse(this.item.value());\n });\n\n constructor() {\n this.item.adoptTriggerId(this.#host.nativeElement);\n const handle = {\n host: this.#host.nativeElement,\n disabled: this.item.disabled,\n };\n registerHandle(\n handle,\n (h) => this.parent.registerTrigger(h),\n (h) => this.parent.unregisterTrigger(h),\n );\n reflectDisabled(this.item.disabled);\n }\n\n protected onKeyDown(event: KeyboardEvent): void {\n const action = resolveListNavigation(event, {\n orientation: this.parent.orientation(),\n dir: this.parent.dir(),\n });\n if (!action) {\n return;\n }\n event.preventDefault();\n this.parent.focusByOffset(this.#host.nativeElement, action);\n }\n}\n","import { Directive, ElementRef, inject } from '@angular/core';\n\nimport { hostLabelledBy } from 'forty-cdk/core';\nimport { injectAccordionContext, injectAccordionItemContext } from './accordion-context';\n\n/**\n * Panel revealed by a `ForAccordionTrigger`. The directive does not manage\n * DOM presence — wrap with `@if (item.expanded())` so panels mount and\n * unmount with the expanded state and `animate.enter` / `animate.leave`\n * work natively. If the consumer prefers to keep the panel mounted (for\n * CSS-only transitions or to preserve internal state), the directive\n * reflects `aria-hidden=\"true\"` and `inert` while closed so the panel is\n * removed from the accessibility tree and focus order automatically.\n *\n * APG note: `role=\"region\"` adds the panel to the landmark navigation tree.\n * If the accordion has 6+ simultaneously expandable panels, consider not\n * using region — the directive will gain an opt-out input when this comes up\n * in real usage.\n */\n@Directive({\n selector: '[forAccordionContent]',\n exportAs: 'forAccordionContent',\n host: {\n '[id]': 'item.contentId()',\n '[attr.role]': '\"region\"',\n '[attr.aria-labelledby]': 'labelledBy()',\n '[attr.aria-hidden]': 'item.expanded() ? null : \"true\"',\n '[attr.inert]': 'item.expanded() ? null : \"\"',\n '[attr.data-state]': 'item.expanded() ? \"open\" : \"closed\"',\n '[attr.data-disabled]': 'item.disabled() ? \"\" : null',\n '[attr.data-orientation]': 'parent.orientation()',\n },\n})\nexport class ForAccordionContent {\n protected readonly parent = injectAccordionContext('ForAccordionContent');\n protected readonly item = injectAccordionItemContext('ForAccordionContent');\n\n protected readonly labelledBy = hostLabelledBy(() => this.item.triggerId());\n\n constructor() {\n this.item.adoptContentId(inject<ElementRef<HTMLElement>>(ElementRef).nativeElement);\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"forty-cdk-accordion.mjs","sources":["../../../projects/forty-cdk/accordion/src/accordion-context.ts","../../../projects/forty-cdk/accordion/src/accordion.ts","../../../projects/forty-cdk/accordion/src/accordion-item.ts","../../../projects/forty-cdk/accordion/src/accordion-trigger.ts","../../../projects/forty-cdk/accordion/src/accordion-content.ts","../../../projects/forty-cdk/accordion/src/forty-cdk-accordion.ts"],"sourcesContent":["import { inject, InjectionToken, type Signal } from '@angular/core';\n\nimport { type ListNavigationAction, type WritingDirection } from 'forty-cdk/core';\n\n/**\n * Registry entry for one `ForAccordionTrigger`. Triggers register their host\n * element so the root can drive keyboard navigation over its own triggers\n * without an unscoped DOM query that would leak into nested accordions.\n *\n * Part of the registration protocol, so it is never exported from\n * `public-api.ts` — see {@link AccordionContext}.\n */\nexport interface ForAccordionTriggerHandle {\n readonly host: HTMLElement;\n readonly disabled: Signal<boolean>;\n}\n\n/**\n * Coordination contract owned by the `ForAccordion` root.\n * Items derive their state from this context; triggers route clicks and\n * keyboard navigation through it.\n */\nexport interface ForAccordionContext {\n readonly multiple: Signal<boolean>;\n readonly collapsible: Signal<boolean>;\n /** Whether the whole accordion is disabled; each item ORs this into its own disabled state. */\n readonly disabled: Signal<boolean>;\n readonly orientation: Signal<'horizontal' | 'vertical'>;\n readonly dir: Signal<WritingDirection>;\n isExpanded(itemValue: string): boolean;\n toggle(itemValue: string): void;\n /** Whether the given item is allowed to collapse right now. */\n canCollapse(itemValue: string): boolean;\n /**\n * Focus a sibling trigger relative to the one currently focused. Disabled\n * triggers are skipped. `currentTrigger` is the element from which the\n * keyboard event originated. Navigation stays within this accordion's own\n * registered triggers, so a nested accordion does not cross-contaminate.\n */\n focusByOffset(currentTrigger: HTMLElement, action: ListNavigationAction): void;\n}\n\n/**\n * Per-item state contract. Provided by `ForAccordionItem`, consumed by\n * its `ForAccordionTrigger` and `ForAccordionContent`.\n */\nexport interface ForAccordionItemContext {\n readonly expanded: Signal<boolean>;\n readonly disabled: Signal<boolean>;\n readonly value: Signal<string>;\n readonly triggerId: Signal<string>;\n readonly contentId: Signal<string>;\n /** Adopts a consumer-set static `id` on the trigger host into `triggerId`. */\n adoptTriggerId(el: HTMLElement): void;\n /** Adopts a consumer-set static `id` on the content host into `contentId`. */\n adoptContentId(el: HTMLElement): void;\n toggle(): void;\n}\n\nexport const FOR_ACCORDION_CONTEXT = new InjectionToken<ForAccordionContext>(\n 'FOR_ACCORDION_CONTEXT',\n);\n\nexport const FOR_ACCORDION_ITEM_CONTEXT = new InjectionToken<ForAccordionItemContext>(\n 'FOR_ACCORDION_ITEM_CONTEXT',\n);\n\n/**\n * The accordion's internal coordination surface: everything\n * {@link ForAccordionContext} publishes plus the trigger-registration protocol\n * the root drives keyboard navigation from.\n *\n * Never exported from `public-api.ts`. `[forAccordion]` provides it alongside\n * {@link FOR_ACCORDION_CONTEXT} on the same object, so a consumer who injects\n * the public token gets the read surface while the pieces get the wiring\n * protocol.\n */\nexport interface AccordionContext extends ForAccordionContext {\n registerTrigger(handle: ForAccordionTriggerHandle): void;\n unregisterTrigger(handle: ForAccordionTriggerHandle): void;\n}\n\n/** DI token carrying the internal {@link AccordionContext}. Provided by `[forAccordion]`. */\nexport const ACCORDION_CONTEXT = new InjectionToken<AccordionContext>('ACCORDION_CONTEXT');\n\nexport function injectAccordionContext(piece: string): AccordionContext {\n const ctx = inject(ACCORDION_CONTEXT, { optional: true });\n if (!ctx) {\n throw new Error(`[forty-cdk/accordion] ${piece} must be used inside a [forAccordion] element.`);\n }\n return ctx;\n}\n\nexport function injectAccordionItemContext(piece: string): ForAccordionItemContext {\n const ctx = inject(FOR_ACCORDION_ITEM_CONTEXT, { optional: true });\n if (!ctx) {\n throw new Error(\n `[forty-cdk/accordion] ${piece} must be used inside a [forAccordionItem] element.`,\n );\n }\n return ctx;\n}\n","import { booleanAttribute, Directive, input, model, type Provider, type Type } from '@angular/core';\n\nimport {\n Collection,\n type ListNavigationAction,\n moveIndex,\n type WritingDirection,\n injectTextDirection,\n} from 'forty-cdk/core';\nimport {\n ACCORDION_CONTEXT,\n FOR_ACCORDION_CONTEXT,\n type ForAccordionContext,\n type ForAccordionTriggerHandle,\n} from './accordion-context';\n\n/**\n * Root of the Accordion primitive. Holds the open value(s) and orchestrates\n * single/multiple expansion, collapse rules, and keyboard navigation between\n * triggers.\n *\n * Implements the [WAI-ARIA Accordion pattern](https://www.w3.org/WAI/ARIA/apg/patterns/accordion/).\n *\n * State is modeled as `value: readonly string[]` regardless of mode:\n * - In single mode (`multiple=false`, default), the array has 0 or 1 element.\n * - In multiple mode, any number of items can be open.\n *\n * @example\n * ```html\n * <div forAccordion [(value)]=\"open\" collapsible>\n * <div forAccordionItem value=\"a\">\n * <h3><button type=\"button\" forAccordionTrigger>A</button></h3>\n * <section forAccordionContent>...</section>\n * </div>\n * <div forAccordionItem value=\"b\">...</div>\n * </div>\n * ```\n */\n@Directive({\n selector: '[forAccordion]',\n exportAs: 'forAccordion',\n host: {\n '[attr.data-orientation]': 'orientation()',\n '[attr.data-disabled]': 'disabled() ? \"\" : null',\n '[attr.dir]': 'dir()',\n },\n providers: provideForAccordion(ForAccordion),\n})\nexport class ForAccordion implements ForAccordionContext {\n readonly #triggers = new Collection<ForAccordionTriggerHandle>();\n\n /** When true, multiple items can be expanded simultaneously. */\n readonly multiple = input(false, { transform: booleanAttribute });\n\n /**\n * When true, the whole accordion is disabled: every item's trigger reflects\n * the native `disabled` attribute (dropped from the Tab order and skipped by\n * arrow-key navigation) and cannot toggle. Composes with a per-item\n * `[disabled]` — an item is effectively disabled when either is set. Mirrors\n * the root `disabled` on `ForTabs` / `ForStepper` / `ForDisclosure`.\n */\n readonly disabled = input(false, { transform: booleanAttribute });\n\n /**\n * Single mode only: when true, the open item can be collapsed by clicking\n * its trigger. When false, exactly one item stays open at all times once\n * any has been opened.\n */\n readonly collapsible = input(false, { transform: booleanAttribute });\n\n /**\n * Layout direction of the trigger list. `'vertical'` (default) maps\n * ArrowUp/Down to prev/next; `'horizontal'` maps ArrowLeft/Right (with RTL\n * swap when `dir='rtl'`).\n */\n readonly orientation = input<'horizontal' | 'vertical'>('vertical');\n\n /**\n * Writing direction. Only relevant when `orientation='horizontal'`. When\n * unset (default `null`), the inherited ambient direction is resolved from\n * the nearest ancestor carrying a `dir` attribute (or `<html dir>`),\n * defaulting to `'ltr'`. An explicit `[dir]` always wins. The resolved\n * value is reflected to the host `dir` attribute and drives arrow-key\n * semantics.\n */\n readonly _dirInput = input<WritingDirection | null>(null, { alias: 'dir' });\n readonly dir = injectTextDirection(this._dirInput);\n\n /**\n * When true (default), arrow navigation between triggers wraps at the ends —\n * moving past the last trigger focuses the first and vice versa. Set `false`\n * to stop at the boundaries. Mirrors the `loop` input on `ForTabs` and\n * `ForListbox`.\n */\n readonly loop = input(true, { transform: booleanAttribute });\n\n /**\n * Two-way bindable. List of currently expanded item values. In single\n * mode the array has 0 or 1 element. The `model()` change emitter\n * (`(valueChange)`) fires only on internal toggles, never on consumer\n * writes via `[(value)]` — observe transitions without binding back.\n */\n readonly value = model<readonly string[]>([]);\n\n isExpanded(itemValue: string): boolean {\n return this.value().includes(itemValue);\n }\n\n toggle(itemValue: string): void {\n const current = this.value();\n const isOpen = current.includes(itemValue);\n\n if (isOpen) {\n if (!this.canCollapse(itemValue)) {\n return;\n }\n this.value.set(current.filter((v) => v !== itemValue));\n return;\n }\n\n if (this.multiple()) {\n this.value.set([...current, itemValue]);\n } else {\n this.value.set([itemValue]);\n }\n }\n\n canCollapse(_itemValue: string): boolean {\n return this.multiple() || this.collapsible();\n }\n\n focusByOffset(currentTrigger: HTMLElement, action: ListNavigationAction): void {\n const triggers = this.#triggers.items();\n if (triggers.length === 0) {\n return;\n }\n const currentIndex = triggers.findIndex((t) => t.host === currentTrigger);\n if (currentIndex === -1 && action !== 'first' && action !== 'last') {\n return;\n }\n const next = moveIndex(currentIndex < 0 ? 0 : currentIndex, triggers.length, action, {\n loop: this.loop(),\n isDisabled: (i) => triggers[i]?.disabled() ?? false,\n });\n if (next !== null) {\n triggers[next]?.host.focus();\n }\n }\n\n private registerTrigger(handle: ForAccordionTriggerHandle): void {\n this.#triggers.register(handle);\n }\n\n private unregisterTrigger(handle: ForAccordionTriggerHandle): void {\n this.#triggers.unregister(handle);\n }\n}\n\n/**\n * The providers a `[forAccordion]` root installs: the public\n * {@link FOR_ACCORDION_CONTEXT}, aliased to `root`, plus the internal\n * coordination token the accordion's pieces resolve.\n *\n * `ForAccordion` declares its own providers through this helper, so a wrapper\n * that **subclasses** the root has a single call to keep in step with it. That\n * matters because Angular does not inherit a directive's `providers`: a subclass\n * carrying its own `@Directive` metadata replaces the array wholesale, so\n * re-providing `FOR_ACCORDION_CONTEXT` alone leaves the internal token absent\n * and every piece orphans with the \"must be used inside a [forAccordion]\n * element\" error. That token is deliberately unnameable outside the library\n * ([#1399](https://github.com/tutkli/forty-cdk/issues/1399)), which is why the\n * wrapper cannot list it by hand.\n *\n * ```ts\n * providers: provideForAccordion(MyAccordion),\n * ```\n *\n * Wrapping through `hostDirectives: [ForAccordion]` needs none of this — a host\n * directive brings its own providers to the element.\n */\nexport function provideForAccordion(root: Type<ForAccordion>): Provider[] {\n return [\n { provide: FOR_ACCORDION_CONTEXT, useExisting: root },\n { provide: ACCORDION_CONTEXT, useExisting: root },\n ];\n}\n","import { booleanAttribute, computed, Directive, inject, input, signal } from '@angular/core';\n\nimport { adoptHostId, IdGenerator } from 'forty-cdk/core';\nimport {\n FOR_ACCORDION_ITEM_CONTEXT,\n type ForAccordionItemContext,\n injectAccordionContext,\n} from './accordion-context';\n\n/**\n * One section of a `ForAccordion`. Owns the unique `value` identifying this\n * item to the root and exposes the per-item context that the trigger and\n * content read.\n */\n@Directive({\n selector: '[forAccordionItem]',\n exportAs: 'forAccordionItem',\n host: {\n '[attr.data-state]': 'expanded() ? \"open\" : \"closed\"',\n '[attr.data-disabled]': 'disabled() ? \"\" : null',\n '[attr.data-orientation]': 'parent.orientation()',\n },\n providers: [{ provide: FOR_ACCORDION_ITEM_CONTEXT, useExisting: ForAccordionItem }],\n})\nexport class ForAccordionItem implements ForAccordionItemContext {\n protected readonly parent = injectAccordionContext('ForAccordionItem');\n readonly #idGen = inject(IdGenerator);\n\n /** Unique identifier of this item within the accordion. Required. */\n readonly value = input.required<string>();\n\n /**\n * When true, this item's trigger ignores clicks and reflects the native\n * `disabled` attribute (not `aria-disabled`): dropped from the Tab order and\n * skipped by arrow-key navigation, but kept in the accessibility tree so\n * screen readers still announce it. See `ForAccordionTrigger` for the\n * rationale (rule #561 D2). Bind via `[disabled]`; read the composed\n * {@link disabled} for state.\n */\n readonly disabledInput = input(false, { transform: booleanAttribute, alias: 'disabled' });\n\n /**\n * Effective disabled: this item's own `[disabled]` OR'd with the root\n * `[forAccordion]`'s `disabled`. Everything that gates on the item's disabled\n * state — native attribute reflection, trigger click, arrow-navigation skip,\n * `data-disabled` — reads this, so disabling the whole accordion disables\n * every item.\n */\n readonly disabled = computed(() => this.disabledInput() || this.parent.disabled());\n\n readonly #triggerId = signal(this.#idGen.next('for-accordion-trigger'));\n readonly #contentId = signal(this.#idGen.next('for-accordion-content'));\n\n readonly triggerId = this.#triggerId.asReadonly();\n readonly contentId = this.#contentId.asReadonly();\n\n readonly expanded = computed(() => this.parent.isExpanded(this.value()));\n\n /**\n * Adopts a consumer-set static `id` on the `[forAccordionTrigger]` host into\n * `triggerId` (preserving anchors / external `aria-labelledby` references /\n * label `for`) instead of letting the `[id]` host binding clobber it.\n */\n adoptTriggerId(el: HTMLElement): void {\n adoptHostId(el, this.#triggerId);\n }\n\n /** Adopts a consumer-set static `id` on the content host into `contentId`. */\n adoptContentId(el: HTMLElement): void {\n adoptHostId(el, this.#contentId);\n }\n\n toggle(): void {\n if (this.disabled()) {\n return;\n }\n this.parent.toggle(this.value());\n }\n}\n","import { computed, Directive, ElementRef, inject } from '@angular/core';\n\nimport {\n hostButtonType,\n registerHandle,\n reflectDisabled,\n resolveListNavigation,\n} from 'forty-cdk/core';\nimport { injectAccordionContext, injectAccordionItemContext } from './accordion-context';\n\n/**\n * Header button for a `ForAccordionItem`. Apply on a `<button>` wrapped in a\n * heading element (`<h2>`–`<h6>`) so APG landmark navigation works. The\n * directive host-binds `type=\"button\"` so a trigger inside a `<form>` never\n * submits it on toggle.\n *\n * Handles ARIA wiring, click-to-toggle, and the recommended keyboard\n * navigation (ArrowDown / ArrowUp / Home / End).\n *\n * `aria-controls` is emitted only while the item is expanded — mirroring the\n * overlay triggers' open-only gating — so the reference never dangles at an\n * unmounted panel under the recommended `@if (item.expanded())` mount pattern.\n */\n@Directive({\n selector: '[forAccordionTrigger]',\n exportAs: 'forAccordionTrigger',\n host: {\n '[attr.type]': 'buttonType()',\n '[id]': 'item.triggerId()',\n '[attr.aria-expanded]': 'item.expanded() ? \"true\" : \"false\"',\n '[attr.aria-controls]': 'item.expanded() ? item.contentId() : null',\n '[attr.aria-disabled]': 'ariaDisabled() ? \"true\" : null',\n '[attr.data-state]': 'item.expanded() ? \"open\" : \"closed\"',\n '[attr.data-disabled]': 'item.disabled() ? \"\" : null',\n '[attr.data-orientation]': 'parent.orientation()',\n '(click)': 'item.toggle()',\n '(keydown)': 'onKeyDown($event)',\n },\n})\nexport class ForAccordionTrigger {\n protected readonly buttonType = hostButtonType();\n\n readonly #host = inject<ElementRef<HTMLElement>>(ElementRef);\n protected readonly parent = injectAccordionContext('ForAccordionTrigger');\n protected readonly item = injectAccordionItemContext('ForAccordionTrigger');\n\n /**\n * APG: aria-disabled is true only when the panel is open AND the accordion\n * disallows collapse. A real `disabled` item is reflected via the native\n * `disabled` attribute instead — the sanctioned exception in rule #561 (D2):\n * the trigger is a real single-purpose `<button>`, not a roving collection\n * item (every trigger stays independently in the Tab order; the arrow-key\n * navigation is an APG-optional enhancement layered on top, not a\n * roving-tabindex collection), so native `disabled` is correct here. The\n * button stays in the accessibility tree — screen readers still announce it\n * as unavailable in browse mode — while being dropped from the Tab order and\n * the arrow-key navigation (which `focusByOffset` already skips), keeping\n * disabled triggers uniformly unreachable. The APG Accordion pattern does not\n * require disabled headers to remain focusable.\n */\n protected readonly ariaDisabled = computed(() => {\n if (this.item.disabled()) {\n return false;\n }\n return this.item.expanded() && !this.parent.canCollapse(this.item.value());\n });\n\n constructor() {\n this.item.adoptTriggerId(this.#host.nativeElement);\n const handle = {\n host: this.#host.nativeElement,\n disabled: this.item.disabled,\n };\n registerHandle(\n handle,\n (h) => this.parent.registerTrigger(h),\n (h) => this.parent.unregisterTrigger(h),\n );\n reflectDisabled(this.item.disabled);\n }\n\n protected onKeyDown(event: KeyboardEvent): void {\n const action = resolveListNavigation(event, {\n orientation: this.parent.orientation(),\n dir: this.parent.dir(),\n });\n if (!action) {\n return;\n }\n event.preventDefault();\n this.parent.focusByOffset(this.#host.nativeElement, action);\n }\n}\n","import { Directive, ElementRef, inject } from '@angular/core';\n\nimport { hostLabelledBy } from 'forty-cdk/core';\nimport { injectAccordionContext, injectAccordionItemContext } from './accordion-context';\n\n/**\n * Panel revealed by a `ForAccordionTrigger`. The directive does not manage\n * DOM presence — wrap with `@if (item.expanded())` so panels mount and\n * unmount with the expanded state and `animate.enter` / `animate.leave`\n * work natively. If the consumer prefers to keep the panel mounted (for\n * CSS-only transitions or to preserve internal state), the directive\n * reflects `aria-hidden=\"true\"` and `inert` while closed so the panel is\n * removed from the accessibility tree and focus order automatically.\n *\n * APG note: `role=\"region\"` adds the panel to the landmark navigation tree.\n * If the accordion has 6+ simultaneously expandable panels, consider not\n * using region — the directive will gain an opt-out input when this comes up\n * in real usage.\n */\n@Directive({\n selector: '[forAccordionContent]',\n exportAs: 'forAccordionContent',\n host: {\n '[id]': 'item.contentId()',\n '[attr.role]': '\"region\"',\n '[attr.aria-labelledby]': 'labelledBy()',\n '[attr.aria-hidden]': 'item.expanded() ? null : \"true\"',\n '[attr.inert]': 'item.expanded() ? null : \"\"',\n '[attr.data-state]': 'item.expanded() ? \"open\" : \"closed\"',\n '[attr.data-disabled]': 'item.disabled() ? \"\" : null',\n '[attr.data-orientation]': 'parent.orientation()',\n },\n})\nexport class ForAccordionContent {\n protected readonly parent = injectAccordionContext('ForAccordionContent');\n protected readonly item = injectAccordionItemContext('ForAccordionContent');\n\n protected readonly labelledBy = hostLabelledBy(() => this.item.triggerId());\n\n constructor() {\n this.item.adoptContentId(inject<ElementRef<HTMLElement>>(ElementRef).nativeElement);\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -5,8 +5,10 @@ import { createDefaults, hostAriaLabel, injectTextDirection, RovingTabindex, inj
5
5
 
6
6
  /** DI token providing the carousel context to descendant pieces. */
7
7
  const FOR_CAROUSEL_CONTEXT = new InjectionToken('FOR_CAROUSEL_CONTEXT');
8
+ /** DI token carrying the internal {@link CarouselContext}. Provided by `[forCarousel]`. */
9
+ const CAROUSEL_CONTEXT = new InjectionToken('CAROUSEL_CONTEXT');
8
10
  function injectCarouselContext(piece) {
9
- const ctx = inject(FOR_CAROUSEL_CONTEXT, { optional: true });
11
+ const ctx = inject(CAROUSEL_CONTEXT, { optional: true });
10
12
  if (!ctx) {
11
13
  throw new Error(`[forty-cdk/carousel] ${piece} must be used inside a [forCarousel] element.`);
12
14
  }
@@ -399,7 +401,7 @@ class ForCarousel {
399
401
  }
400
402
  }
401
403
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: ForCarousel, deps: [], target: i0.ɵɵFactoryTarget.Directive });
402
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: ForCarousel, isStandalone: true, selector: "[forCarousel]", inputs: { activeIndex: { classPropertyName: "activeIndex", publicName: "activeIndex", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, loop: { classPropertyName: "loop", publicName: "loop", isSignal: true, isRequired: false, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, slidesPerView: { classPropertyName: "slidesPerView", publicName: "slidesPerView", isSignal: true, isRequired: false, transformFunction: null }, containScroll: { classPropertyName: "containScroll", publicName: "containScroll", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, autoplay: { classPropertyName: "autoplay", publicName: "autoplay", isSignal: true, isRequired: false, transformFunction: null }, autoplayInterval: { classPropertyName: "autoplayInterval", publicName: "autoplayInterval", isSignal: true, isRequired: false, transformFunction: null }, _dirInput: { classPropertyName: "_dirInput", publicName: "dir", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeIndex: "activeIndexChange" }, host: { attributes: { "role": "group", "aria-roledescription": "carousel" }, listeners: { "pointerenter": "onAutoplayPause(\"hover\")", "pointerleave": "onAutoplayResume(\"hover\")", "focusin": "onAutoplayPause(\"focus\")", "focusout": "onAutoplayFocusOut($event)" }, properties: { "attr.aria-label": "resolvedAriaLabel()", "attr.data-orientation": "orientation()", "attr.data-align": "align()", "attr.dir": "dir()", "style.--for-carousel-offset": "offset()", "style.--for-carousel-active-index": "activeIndex()", "style.--for-carousel-slide-count": "slideCount()", "style.--for-carousel-slides-per-view": "slidesPerView()", "style.--for-carousel-viewport-width": "viewportWidth()", "style.--for-carousel-viewport-height": "viewportHeight()", "attr.data-autoplay": "autoplay() ? \"\" : null", "attr.data-rotating": "rotating() ? \"\" : null" } }, providers: [{ provide: FOR_CAROUSEL_CONTEXT, useExisting: ForCarousel }], exportAs: ["forCarousel"], ngImport: i0 });
404
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: ForCarousel, isStandalone: true, selector: "[forCarousel]", inputs: { activeIndex: { classPropertyName: "activeIndex", publicName: "activeIndex", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, loop: { classPropertyName: "loop", publicName: "loop", isSignal: true, isRequired: false, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, slidesPerView: { classPropertyName: "slidesPerView", publicName: "slidesPerView", isSignal: true, isRequired: false, transformFunction: null }, containScroll: { classPropertyName: "containScroll", publicName: "containScroll", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, autoplay: { classPropertyName: "autoplay", publicName: "autoplay", isSignal: true, isRequired: false, transformFunction: null }, autoplayInterval: { classPropertyName: "autoplayInterval", publicName: "autoplayInterval", isSignal: true, isRequired: false, transformFunction: null }, _dirInput: { classPropertyName: "_dirInput", publicName: "dir", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeIndex: "activeIndexChange" }, host: { attributes: { "role": "group", "aria-roledescription": "carousel" }, listeners: { "pointerenter": "onAutoplayPause(\"hover\")", "pointerleave": "onAutoplayResume(\"hover\")", "focusin": "onAutoplayPause(\"focus\")", "focusout": "onAutoplayFocusOut($event)" }, properties: { "attr.aria-label": "resolvedAriaLabel()", "attr.data-orientation": "orientation()", "attr.data-align": "align()", "attr.dir": "dir()", "style.--for-carousel-offset": "offset()", "style.--for-carousel-active-index": "activeIndex()", "style.--for-carousel-slide-count": "slideCount()", "style.--for-carousel-slides-per-view": "slidesPerView()", "style.--for-carousel-viewport-width": "viewportWidth()", "style.--for-carousel-viewport-height": "viewportHeight()", "attr.data-autoplay": "autoplay() ? \"\" : null", "attr.data-rotating": "rotating() ? \"\" : null" } }, providers: provideForCarousel(ForCarousel), exportAs: ["forCarousel"], ngImport: i0 });
403
405
  }
404
406
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: ForCarousel, decorators: [{
405
407
  type: Directive,
@@ -426,9 +428,37 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
426
428
  '(focusin)': 'onAutoplayPause("focus")',
427
429
  '(focusout)': 'onAutoplayFocusOut($event)',
428
430
  },
429
- providers: [{ provide: FOR_CAROUSEL_CONTEXT, useExisting: ForCarousel }],
431
+ providers: provideForCarousel(ForCarousel),
430
432
  }]
431
433
  }], ctorParameters: () => [], propDecorators: { activeIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeIndex", required: false }] }, { type: i0.Output, args: ["activeIndexChange"] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], loop: [{ type: i0.Input, args: [{ isSignal: true, alias: "loop", required: false }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], slidesPerView: [{ type: i0.Input, args: [{ isSignal: true, alias: "slidesPerView", required: false }] }], containScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "containScroll", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], autoplay: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoplay", required: false }] }], autoplayInterval: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoplayInterval", required: false }] }], _dirInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }] } });
434
+ /**
435
+ * The providers a `[forCarousel]` root installs: the public
436
+ * {@link FOR_CAROUSEL_CONTEXT}, aliased to `root`, plus the internal
437
+ * coordination token the carousel's pieces resolve.
438
+ *
439
+ * `ForCarousel` declares its own providers through this helper, so a wrapper
440
+ * that **subclasses** the root has a single call to keep in step with it. That
441
+ * matters because Angular does not inherit a directive's `providers`: a subclass
442
+ * carrying its own `@Directive` metadata replaces the array wholesale, so
443
+ * re-providing `FOR_CAROUSEL_CONTEXT` alone leaves the internal token absent and
444
+ * every piece orphans with the "must be used inside a [forCarousel] element"
445
+ * error. That token is deliberately unnameable outside the library
446
+ * ([#1399](https://github.com/tutkli/forty-cdk/issues/1399)), which is why the
447
+ * wrapper cannot list it by hand.
448
+ *
449
+ * ```ts
450
+ * providers: provideForCarousel(MyCarousel),
451
+ * ```
452
+ *
453
+ * Wrapping through `hostDirectives: [ForCarousel]` needs none of this — a host
454
+ * directive brings its own providers to the element.
455
+ */
456
+ function provideForCarousel(root) {
457
+ return [
458
+ { provide: FOR_CAROUSEL_CONTEXT, useExisting: root },
459
+ { provide: CAROUSEL_CONTEXT, useExisting: root },
460
+ ];
461
+ }
432
462
 
433
463
  /**
434
464
  * Clips the visible window of the carousel track. Acts as the APG-mandated
@@ -1028,5 +1058,5 @@ function resolveDragIndex(activeIndex, slidesDragged, velocityTowardNext) {
1028
1058
  * Generated bundle index. Do not edit.
1029
1059
  */
1030
1060
 
1031
- export { FOR_CAROUSEL_CONTEXT, FOR_CAROUSEL_DEFAULTS, ForCarousel, ForCarouselDrag, ForCarouselIndicator, ForCarouselIndicators, ForCarouselNext, ForCarouselPrevious, ForCarouselRotationControl, ForCarouselSlide, ForCarouselTrack, ForCarouselViewport, provideForCarouselDefaults };
1061
+ export { FOR_CAROUSEL_CONTEXT, FOR_CAROUSEL_DEFAULTS, ForCarousel, ForCarouselDrag, ForCarouselIndicator, ForCarouselIndicators, ForCarouselNext, ForCarouselPrevious, ForCarouselRotationControl, ForCarouselSlide, ForCarouselTrack, ForCarouselViewport, provideForCarousel, provideForCarouselDefaults };
1032
1062
  //# sourceMappingURL=forty-cdk-carousel.mjs.map