forty-cdk 0.2.0 → 0.3.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 (220) hide show
  1. package/accordion/README.md +122 -0
  2. package/aspect-ratio/README.md +76 -0
  3. package/avatar/README.md +100 -0
  4. package/breadcrumbs/README.md +49 -0
  5. package/breakpoints/README.md +81 -0
  6. package/button/README.md +49 -0
  7. package/calendar/README.md +458 -0
  8. package/carousel/README.md +358 -0
  9. package/checkbox/README.md +146 -0
  10. package/combobox/README.md +535 -0
  11. package/context-menu/README.md +139 -0
  12. package/date-field/README.md +184 -0
  13. package/date-picker/README.md +338 -0
  14. package/dialog/README.md +388 -0
  15. package/disclosure/README.md +114 -0
  16. package/drag-drop/README.md +359 -0
  17. package/drawer/README.md +560 -0
  18. package/dropdown-menu/README.md +176 -0
  19. package/fesm2022/forty-cdk-accordion.mjs +348 -0
  20. package/fesm2022/forty-cdk-accordion.mjs.map +1 -0
  21. package/fesm2022/forty-cdk-aspect-ratio.mjs +74 -0
  22. package/fesm2022/forty-cdk-aspect-ratio.mjs.map +1 -0
  23. package/fesm2022/forty-cdk-avatar.mjs +308 -0
  24. package/fesm2022/forty-cdk-avatar.mjs.map +1 -0
  25. package/fesm2022/forty-cdk-breadcrumbs.mjs +125 -0
  26. package/fesm2022/forty-cdk-breadcrumbs.mjs.map +1 -0
  27. package/fesm2022/forty-cdk-breakpoints.mjs +117 -0
  28. package/fesm2022/forty-cdk-breakpoints.mjs.map +1 -0
  29. package/fesm2022/forty-cdk-button.mjs +134 -0
  30. package/fesm2022/forty-cdk-button.mjs.map +1 -0
  31. package/fesm2022/forty-cdk-calendar.mjs +2034 -0
  32. package/fesm2022/forty-cdk-calendar.mjs.map +1 -0
  33. package/fesm2022/forty-cdk-carousel.mjs +968 -0
  34. package/fesm2022/forty-cdk-carousel.mjs.map +1 -0
  35. package/fesm2022/forty-cdk-checkbox.mjs +226 -0
  36. package/fesm2022/forty-cdk-checkbox.mjs.map +1 -0
  37. package/fesm2022/forty-cdk-combobox.mjs +2596 -0
  38. package/fesm2022/forty-cdk-combobox.mjs.map +1 -0
  39. package/fesm2022/forty-cdk-context-menu.mjs +413 -0
  40. package/fesm2022/forty-cdk-context-menu.mjs.map +1 -0
  41. package/fesm2022/forty-cdk-core.mjs +9022 -0
  42. package/fesm2022/forty-cdk-core.mjs.map +1 -0
  43. package/fesm2022/forty-cdk-date-field.mjs +744 -0
  44. package/fesm2022/forty-cdk-date-field.mjs.map +1 -0
  45. package/fesm2022/forty-cdk-date-picker.mjs +1011 -0
  46. package/fesm2022/forty-cdk-date-picker.mjs.map +1 -0
  47. package/fesm2022/forty-cdk-dialog.mjs +707 -0
  48. package/fesm2022/forty-cdk-dialog.mjs.map +1 -0
  49. package/fesm2022/forty-cdk-disclosure.mjs +190 -0
  50. package/fesm2022/forty-cdk-disclosure.mjs.map +1 -0
  51. package/fesm2022/forty-cdk-drag-drop.mjs +1180 -0
  52. package/fesm2022/forty-cdk-drag-drop.mjs.map +1 -0
  53. package/fesm2022/forty-cdk-drawer.mjs +1641 -0
  54. package/fesm2022/forty-cdk-drawer.mjs.map +1 -0
  55. package/fesm2022/forty-cdk-dropdown-menu.mjs +350 -0
  56. package/fesm2022/forty-cdk-dropdown-menu.mjs.map +1 -0
  57. package/fesm2022/forty-cdk-field.mjs +425 -0
  58. package/fesm2022/forty-cdk-field.mjs.map +1 -0
  59. package/fesm2022/forty-cdk-fieldset.mjs +164 -0
  60. package/fesm2022/forty-cdk-fieldset.mjs.map +1 -0
  61. package/fesm2022/forty-cdk-file-upload.mjs +221 -0
  62. package/fesm2022/forty-cdk-file-upload.mjs.map +1 -0
  63. package/fesm2022/forty-cdk-hover-card.mjs +496 -0
  64. package/fesm2022/forty-cdk-hover-card.mjs.map +1 -0
  65. package/fesm2022/forty-cdk-input.mjs +274 -0
  66. package/fesm2022/forty-cdk-input.mjs.map +1 -0
  67. package/fesm2022/forty-cdk-internationalized-date.mjs +1 -1
  68. package/fesm2022/forty-cdk-internationalized-date.mjs.map +1 -1
  69. package/fesm2022/forty-cdk-listbox.mjs +1279 -0
  70. package/fesm2022/forty-cdk-listbox.mjs.map +1 -0
  71. package/fesm2022/forty-cdk-menu.mjs +1439 -0
  72. package/fesm2022/forty-cdk-menu.mjs.map +1 -0
  73. package/fesm2022/forty-cdk-menubar.mjs +787 -0
  74. package/fesm2022/forty-cdk-menubar.mjs.map +1 -0
  75. package/fesm2022/forty-cdk-meter.mjs +211 -0
  76. package/fesm2022/forty-cdk-meter.mjs.map +1 -0
  77. package/fesm2022/forty-cdk-navigation-menu.mjs +1145 -0
  78. package/fesm2022/forty-cdk-navigation-menu.mjs.map +1 -0
  79. package/fesm2022/forty-cdk-number-input.mjs +559 -0
  80. package/fesm2022/forty-cdk-number-input.mjs.map +1 -0
  81. package/fesm2022/forty-cdk-otp-input.mjs +527 -0
  82. package/fesm2022/forty-cdk-otp-input.mjs.map +1 -0
  83. package/fesm2022/forty-cdk-pagination.mjs +323 -0
  84. package/fesm2022/forty-cdk-pagination.mjs.map +1 -0
  85. package/fesm2022/forty-cdk-pane-resizer.mjs +297 -0
  86. package/fesm2022/forty-cdk-pane-resizer.mjs.map +1 -0
  87. package/fesm2022/forty-cdk-popover.mjs +698 -0
  88. package/fesm2022/forty-cdk-popover.mjs.map +1 -0
  89. package/fesm2022/forty-cdk-progress.mjs +226 -0
  90. package/fesm2022/forty-cdk-progress.mjs.map +1 -0
  91. package/fesm2022/forty-cdk-radio-group.mjs +378 -0
  92. package/fesm2022/forty-cdk-radio-group.mjs.map +1 -0
  93. package/fesm2022/forty-cdk-scroll-area.mjs +640 -0
  94. package/fesm2022/forty-cdk-scroll-area.mjs.map +1 -0
  95. package/fesm2022/forty-cdk-search.mjs +205 -0
  96. package/fesm2022/forty-cdk-search.mjs.map +1 -0
  97. package/fesm2022/forty-cdk-select.mjs +1661 -0
  98. package/fesm2022/forty-cdk-select.mjs.map +1 -0
  99. package/fesm2022/forty-cdk-separator.mjs +82 -0
  100. package/fesm2022/forty-cdk-separator.mjs.map +1 -0
  101. package/fesm2022/forty-cdk-signal-forms.mjs +97 -0
  102. package/fesm2022/forty-cdk-signal-forms.mjs.map +1 -0
  103. package/fesm2022/forty-cdk-slider.mjs +803 -0
  104. package/fesm2022/forty-cdk-slider.mjs.map +1 -0
  105. package/fesm2022/forty-cdk-stepper.mjs +886 -0
  106. package/fesm2022/forty-cdk-stepper.mjs.map +1 -0
  107. package/fesm2022/forty-cdk-switch.mjs +137 -0
  108. package/fesm2022/forty-cdk-switch.mjs.map +1 -0
  109. package/fesm2022/forty-cdk-table.mjs +1518 -0
  110. package/fesm2022/forty-cdk-table.mjs.map +1 -0
  111. package/fesm2022/forty-cdk-tabs.mjs +400 -0
  112. package/fesm2022/forty-cdk-tabs.mjs.map +1 -0
  113. package/fesm2022/forty-cdk-time-field.mjs +593 -0
  114. package/fesm2022/forty-cdk-time-field.mjs.map +1 -0
  115. package/fesm2022/forty-cdk-time-picker.mjs +1013 -0
  116. package/fesm2022/forty-cdk-time-picker.mjs.map +1 -0
  117. package/fesm2022/forty-cdk-toast.mjs +1153 -0
  118. package/fesm2022/forty-cdk-toast.mjs.map +1 -0
  119. package/fesm2022/forty-cdk-toggle.mjs +516 -0
  120. package/fesm2022/forty-cdk-toggle.mjs.map +1 -0
  121. package/fesm2022/forty-cdk-toolbar.mjs +374 -0
  122. package/fesm2022/forty-cdk-toolbar.mjs.map +1 -0
  123. package/fesm2022/forty-cdk-tooltip.mjs +672 -0
  124. package/fesm2022/forty-cdk-tooltip.mjs.map +1 -0
  125. package/fesm2022/forty-cdk-tree.mjs +2007 -0
  126. package/fesm2022/forty-cdk-tree.mjs.map +1 -0
  127. package/fesm2022/forty-cdk-virtualization.mjs +1 -1
  128. package/fesm2022/forty-cdk-virtualization.mjs.map +1 -1
  129. package/fesm2022/forty-cdk.mjs +0 -43310
  130. package/fesm2022/forty-cdk.mjs.map +1 -1
  131. package/field/README.md +97 -0
  132. package/fieldset/README.md +86 -0
  133. package/file-upload/README.md +73 -0
  134. package/hover-card/README.md +171 -0
  135. package/input/README.md +156 -0
  136. package/listbox/README.md +424 -0
  137. package/menu/README.md +181 -0
  138. package/menubar/README.md +140 -0
  139. package/meter/README.md +128 -0
  140. package/navigation-menu/README.md +253 -0
  141. package/number-input/README.md +171 -0
  142. package/otp-input/README.md +198 -0
  143. package/package.json +213 -1
  144. package/pagination/README.md +61 -0
  145. package/pane-resizer/README.md +136 -0
  146. package/popover/README.md +262 -0
  147. package/progress/README.md +115 -0
  148. package/radio-group/README.md +129 -0
  149. package/scroll-area/README.md +184 -0
  150. package/search/README.md +42 -0
  151. package/select/README.md +488 -0
  152. package/separator/README.md +84 -0
  153. package/signal-forms/README.md +72 -0
  154. package/slider/README.md +152 -0
  155. package/stepper/README.md +292 -0
  156. package/switch/README.md +116 -0
  157. package/table/README.md +769 -0
  158. package/tabs/README.md +130 -0
  159. package/time-field/README.md +157 -0
  160. package/time-picker/README.md +172 -0
  161. package/toast/README.md +398 -0
  162. package/toggle/README.md +224 -0
  163. package/toolbar/README.md +109 -0
  164. package/tooltip/README.md +274 -0
  165. package/tree/README.md +708 -0
  166. package/types/forty-cdk-accordion.d.ts +242 -0
  167. package/types/forty-cdk-aspect-ratio.d.ts +59 -0
  168. package/types/forty-cdk-avatar.d.ts +133 -0
  169. package/types/forty-cdk-breadcrumbs.d.ts +92 -0
  170. package/types/forty-cdk-breakpoints.d.ts +141 -0
  171. package/types/forty-cdk-button.d.ts +80 -0
  172. package/types/forty-cdk-calendar.d.ts +914 -0
  173. package/types/forty-cdk-carousel.d.ts +530 -0
  174. package/types/forty-cdk-checkbox.d.ts +141 -0
  175. package/types/forty-cdk-combobox.d.ts +1259 -0
  176. package/types/forty-cdk-context-menu.d.ts +313 -0
  177. package/types/forty-cdk-core.d.ts +5774 -0
  178. package/types/forty-cdk-date-field.d.ts +307 -0
  179. package/types/forty-cdk-date-picker.d.ts +622 -0
  180. package/types/forty-cdk-dialog.d.ts +546 -0
  181. package/types/forty-cdk-disclosure.d.ts +127 -0
  182. package/types/forty-cdk-drag-drop.d.ts +456 -0
  183. package/types/forty-cdk-drawer.d.ts +871 -0
  184. package/types/forty-cdk-dropdown-menu.d.ts +242 -0
  185. package/types/forty-cdk-field.d.ts +236 -0
  186. package/types/forty-cdk-fieldset.d.ts +119 -0
  187. package/types/forty-cdk-file-upload.d.ts +124 -0
  188. package/types/forty-cdk-hover-card.d.ts +320 -0
  189. package/types/forty-cdk-input.d.ts +169 -0
  190. package/types/forty-cdk-internationalized-date.d.ts +1 -1
  191. package/types/forty-cdk-listbox.d.ts +513 -0
  192. package/types/forty-cdk-menu.d.ts +629 -0
  193. package/types/forty-cdk-menubar.d.ts +451 -0
  194. package/types/forty-cdk-meter.d.ts +122 -0
  195. package/types/forty-cdk-navigation-menu.d.ts +514 -0
  196. package/types/forty-cdk-number-input.d.ts +319 -0
  197. package/types/forty-cdk-otp-input.d.ts +248 -0
  198. package/types/forty-cdk-pagination.d.ts +214 -0
  199. package/types/forty-cdk-pane-resizer.d.ts +145 -0
  200. package/types/forty-cdk-popover.d.ts +509 -0
  201. package/types/forty-cdk-progress.d.ts +143 -0
  202. package/types/forty-cdk-radio-group.d.ts +222 -0
  203. package/types/forty-cdk-scroll-area.d.ts +258 -0
  204. package/types/forty-cdk-search.d.ts +142 -0
  205. package/types/forty-cdk-select.d.ts +899 -0
  206. package/types/forty-cdk-separator.d.ts +59 -0
  207. package/types/forty-cdk-signal-forms.d.ts +58 -0
  208. package/types/forty-cdk-slider.d.ts +379 -0
  209. package/types/forty-cdk-stepper.d.ts +650 -0
  210. package/types/forty-cdk-switch.d.ts +87 -0
  211. package/types/forty-cdk-table.d.ts +723 -0
  212. package/types/forty-cdk-tabs.d.ts +235 -0
  213. package/types/forty-cdk-time-field.d.ts +307 -0
  214. package/types/forty-cdk-time-picker.d.ts +578 -0
  215. package/types/forty-cdk-toast.d.ts +598 -0
  216. package/types/forty-cdk-toggle.d.ts +310 -0
  217. package/types/forty-cdk-toolbar.d.ts +217 -0
  218. package/types/forty-cdk-tooltip.d.ts +436 -0
  219. package/types/forty-cdk-tree.d.ts +688 -0
  220. package/types/forty-cdk.d.ts +1 -19743
@@ -0,0 +1,899 @@
1
+ import * as _floating_ui_dom from '@floating-ui/dom';
2
+ import { ReferenceElement } from '@floating-ui/dom';
3
+ import * as _angular_core from '@angular/core';
4
+ import { InjectionToken, ModelSignal, Signal, Provider } from '@angular/core';
5
+ import { FormValueControl } from '@angular/forms/signals';
6
+ import { FloatingSide, FloatingAlign, WritingDirection, CollectionHandle, ListNavigationAction, VetoableNativeEvent, FormUiControlBase, VetoableEvent } from 'forty-cdk/core';
7
+ import * as forty_cdk_select from 'forty-cdk/select';
8
+
9
+ /**
10
+ * Why a select requested close. Mirrors the menu primitive vocabulary so
11
+ * downstream code that switches on close reasons stays consistent.
12
+ */
13
+ type ForSelectCloseReason = 'escape' | 'pointerDownOutside' | 'focusOutside' | 'select' | 'tab' | 'programmatic';
14
+ /**
15
+ * Where focus lands when the listbox opens. `'selected'` snaps to the first
16
+ * currently-selected enabled option (matches native `<select>`); falls back
17
+ * to `'first'` if no selection is enabled.
18
+ */
19
+ type ForSelectInitialFocus = 'first' | 'last' | 'selected';
20
+ /**
21
+ * Handle every `[forSelectOption]` registers with the root. The collection
22
+ * orders entries by DOM document order so groups, separators, and `@for`
23
+ * loops don't perturb keyboard navigation.
24
+ *
25
+ * Generic over the option value type `T` (default `unknown` at the contract
26
+ * level; `string` at the public root). The handle carries the raw value so
27
+ * the root can match it against `value()` via `isItemEqualToValue`.
28
+ */
29
+ interface ForSelectOptionHandle<T = unknown> extends CollectionHandle {
30
+ readonly value: Signal<T>;
31
+ /**
32
+ * The option's resolved display label as a reactive `Signal<string>` — the
33
+ * trimmed `textContent` of the host. The root folds it into a persisted
34
+ * snapshot so `selectedLabels` and closed-state typeahead resolve labels
35
+ * without peeking at `textContent` from inside a `computed`.
36
+ */
37
+ readonly label: Signal<string>;
38
+ readonly disabled: Signal<boolean>;
39
+ /** Stable host `id` — the activedescendant target in the virtualized path. */
40
+ readonly id: Signal<string>;
41
+ /**
42
+ * Zero-based absolute position in the full source data. Required in the
43
+ * virtualized path (drives the position snapshot + `aria-posinset`); `null`
44
+ * outside it.
45
+ */
46
+ readonly posInSet: Signal<number | null>;
47
+ }
48
+ /**
49
+ * Coordination contract owned by `[forSelect]`. Trigger, content, value,
50
+ * options, groups and separators all inject this token to read state and
51
+ * delegate behavior — they don't import the root class directly.
52
+ *
53
+ * Generic over the option value type `T` (default `string` at the public
54
+ * root). When a consumer binds object items the directive infers `T` from
55
+ * `[(value)]` and the per-piece signatures specialize accordingly. Items are
56
+ * compared via the consumer-provided `isItemEqualToValue` and serialized for
57
+ * the form's hidden inputs via `itemToFormValue`; option text labels are
58
+ * still read from the rendered `textContent`.
59
+ */
60
+ interface ForSelectContext<T = unknown> {
61
+ readonly value: ModelSignal<readonly T[]>;
62
+ readonly open: ModelSignal<boolean>;
63
+ readonly multiple: Signal<boolean>;
64
+ /**
65
+ * The select's effective disabled — its own `disabled` input OR'd with a
66
+ * surrounding disabled `[forFieldset]`. Trigger and options read this so a
67
+ * disabled select (or fieldset) is inert and exposes `aria-disabled`.
68
+ */
69
+ readonly effectiveDisabled: Signal<boolean>;
70
+ readonly readonly: Signal<boolean>;
71
+ readonly required: Signal<boolean>;
72
+ readonly invalid: Signal<boolean>;
73
+ readonly pending: Signal<boolean>;
74
+ /**
75
+ * When `true`, the listbox is a trapped / inert / scroll-locked modal
76
+ * surface (routed through `_internal/modal-shell`) instead of the anchored
77
+ * popover. Read once when `[forSelectContent]` mounts; all anchored-
78
+ * positioning state below is a no-op while modal.
79
+ */
80
+ readonly modal: Signal<boolean>;
81
+ readonly dismissible: Signal<boolean>;
82
+ readonly returnFocus: Signal<boolean>;
83
+ /**
84
+ * Positioning algorithm. `'popper'` (default) is standard floating-ui
85
+ * anchored placement; `'item-aligned'` overlays the listbox so the
86
+ * selected option's center aligns with the trigger's center (macOS-style
87
+ * native `<select>`). All `side`/`align`/`*Offset`/`sticky`/
88
+ * `hideWhenDetached`/`clipUntilPositioned`/`avoidCollisions` inputs are no-ops in
89
+ * `'item-aligned'` mode (only `collisionPadding` is honored).
90
+ */
91
+ readonly position: Signal<'popper' | 'item-aligned'>;
92
+ readonly side: Signal<FloatingSide | undefined>;
93
+ readonly align: Signal<FloatingAlign | undefined>;
94
+ readonly sideOffset: Signal<number>;
95
+ readonly alignOffset: Signal<number>;
96
+ readonly avoidCollisions: Signal<boolean>;
97
+ readonly collisionPadding: Signal<number>;
98
+ readonly arrowPadding: Signal<number>;
99
+ readonly sticky: Signal<'partial' | 'always' | false>;
100
+ readonly hideWhenDetached: Signal<boolean>;
101
+ readonly clipUntilPositioned: Signal<boolean>;
102
+ readonly loop: Signal<boolean>;
103
+ readonly orientation: Signal<'horizontal' | 'vertical'>;
104
+ readonly dir: Signal<WritingDirection>;
105
+ readonly selectionFollowsFocus: Signal<boolean>;
106
+ readonly placeholder: Signal<string>;
107
+ /** Where focus should land after the content mounts. Triggers set this before flipping `open`. */
108
+ readonly initialFocus: Signal<ForSelectInitialFocus>;
109
+ setInitialFocus(target: ForSelectInitialFocus): void;
110
+ readonly triggerId: Signal<string>;
111
+ readonly contentId: Signal<string>;
112
+ readonly ariaLabel: Signal<string | null>;
113
+ /** Compare two items for equality. Defaults to `===`; overridden for object values. */
114
+ readonly isItemEqualToValue: Signal<(a: T, b: T) => boolean>;
115
+ /** Serialize an item for the hidden input's `value` attribute. Defaults to `String(item)`. */
116
+ readonly itemToFormValue: Signal<(item: T) => string>;
117
+ /**
118
+ * Element floating-ui anchors the listbox against. Prefers an optional
119
+ * `[forSelectAnchor]` when registered, otherwise falls back to the trigger.
120
+ * Decoupled from `trigger` so the trigger keeps driving `aria-controls`,
121
+ * the click toggle, focus return, and its outside-pointer exemption
122
+ * regardless of where the listbox paints.
123
+ */
124
+ readonly anchor: Signal<ReferenceElement | null>;
125
+ /** The button trigger — exempt from outside-pointer checks and the focus-return target. */
126
+ readonly trigger: Signal<HTMLElement | null>;
127
+ registerTrigger(el: HTMLElement): void;
128
+ unregisterTrigger(el: HTMLElement): void;
129
+ /**
130
+ * Register / unregister an optional `[forSelectAnchor]` positioning element.
131
+ * At most one anchor per root; a second registration throws. Reference-based
132
+ * unregister, so an anchor torn down inside `@if` restores the trigger
133
+ * fallback cleanly.
134
+ */
135
+ registerAnchor(el: HTMLElement): void;
136
+ unregisterAnchor(el: HTMLElement): void;
137
+ /** The mounted `[forSelectContent]` element. */
138
+ readonly content: Signal<HTMLElement | null>;
139
+ registerContent(el: HTMLElement): void;
140
+ unregisterContent(el: HTMLElement): void;
141
+ registerOption(handle: ForSelectOptionHandle<T>): void;
142
+ unregisterOption(handle: ForSelectOptionHandle<T>): void;
143
+ /** All registered options in DOM order. */
144
+ readonly options: Signal<readonly ForSelectOptionHandle<T>[]>;
145
+ /** Resolved labels of the options whose value is in `value()`, in selection order. */
146
+ readonly selectedLabels: Signal<readonly string[]>;
147
+ /**
148
+ * Host element of the first enabled, currently-selected option, or `null`
149
+ * when no selection exists. Used by `position="item-aligned"` to anchor
150
+ * the listbox over the trigger; falls back to the first enabled option
151
+ * inside the listbox when this is `null`.
152
+ */
153
+ readonly selectedOptionEl: Signal<HTMLElement | null>;
154
+ isSelected(value: T): boolean;
155
+ /** Toggle in multi-mode, replace + close in single-mode. No-op on disabled / readonly. */
156
+ activate(value: T): void;
157
+ /** Move focus inside the open listbox in response to an arrow / Home / End key. */
158
+ navigate(currentOption: HTMLElement, action: ListNavigationAction): void;
159
+ /** Open-state typeahead: focus the first enabled option whose text matches the buffered prefix. */
160
+ handleTypeahead(event: KeyboardEvent): void;
161
+ /**
162
+ * Closed-state typeahead (single mode only). Selects the first matching
163
+ * option directly without opening the listbox — mirrors native `<select>`
164
+ * behavior. Returns `true` if the key was consumed by typeahead.
165
+ */
166
+ handleClosedTypeahead(event: KeyboardEvent): boolean;
167
+ focusFirstEnabledOption(): boolean;
168
+ focusLastEnabledOption(): boolean;
169
+ /** Focus the first enabled option whose value is currently selected. Returns `false` if none. */
170
+ focusSelectedOption(): boolean;
171
+ toggle(initialFocus?: ForSelectInitialFocus): void;
172
+ openMenu(initialFocus?: ForSelectInitialFocus): void;
173
+ closeMenu(reason: ForSelectCloseReason): void;
174
+ /**
175
+ * Reason of the most recent close, or `null` while the listbox is open
176
+ * (or before any close). Read by `[forSelectContent]` so `'tab'` closes
177
+ * skip the return-focus step — Tab needs the browser to advance focus
178
+ * from the trigger, and a re-focus would steal it back.
179
+ */
180
+ readonly lastCloseReason: Signal<ForSelectCloseReason | null>;
181
+ /**
182
+ * Commit the focused option's value (single mode) and close the listbox
183
+ * with reason `'tab'`. Moves focus to the trigger synchronously so the
184
+ * browser's Tab default action advances focus from there to the next
185
+ * (or previous) focusable in tab order. Multi-mode skips the value-set
186
+ * — selection toggles already happened via Space / Enter / click.
187
+ */
188
+ commitOnTab(value: T): void;
189
+ emitEscapeKeyDown(event: KeyboardEvent): void;
190
+ emitPointerDownOutside(veto: VetoableNativeEvent<PointerEvent>): void;
191
+ emitFocusOutside(veto: VetoableNativeEvent<FocusEvent>): void;
192
+ emitInteractOutside(veto: VetoableNativeEvent<PointerEvent | FocusEvent>): void;
193
+ /** Implicit close requested by the shell after an un-vetoed outside interaction. */
194
+ requestClose(reason: 'pointerDownOutside' | 'focusOutside'): void;
195
+ /** Modal-path Escape forwarder: emit only; the modal shell builds the veto and owns the close. */
196
+ forwardEscapeKeyDown(veto: VetoableNativeEvent<KeyboardEvent>): void;
197
+ /**
198
+ * Hooks into the auto-focus pipeline. Content fires these just before
199
+ * its imperative `.focus()` (open) or the trigger return-focus (close);
200
+ * `event.preventDefault()` skips the move. Returns `true` when the
201
+ * consumer vetoed.
202
+ */
203
+ emitAutoFocusOnOpen(): boolean;
204
+ emitAutoFocusOnClose(): boolean;
205
+ /**
206
+ * Full source length when virtualizing, `undefined` in the default
207
+ * DOM-focus path. Drives each option's `aria-setsize` / `aria-posinset`
208
+ * and the focus-model branch.
209
+ */
210
+ readonly totalCount: Signal<number | undefined>;
211
+ /**
212
+ * The active option's `id` in the virtualized activedescendant model,
213
+ * `null` in the default path. The content surface reflects it as
214
+ * `aria-activedescendant`; options read it for `data-highlighted`.
215
+ */
216
+ readonly activeDescendantId: Signal<string | null>;
217
+ /**
218
+ * Virtualized-path open hook. Called by `[forSelectContent]` after it
219
+ * focuses its own surface on open: seeds `aria-activedescendant` to the
220
+ * committed option (scrolling it into view via `(scrollToIndex)`), or the
221
+ * first enabled option when nothing is selected.
222
+ */
223
+ seedVirtualizedInitialFocus(): void;
224
+ /**
225
+ * Virtualized-path keyboard handler. Called by `[forSelectContent]`'s host
226
+ * keydown only when `totalCount()` is set: Arrow/Home/End navigation,
227
+ * Enter/Space activation of the active descendant, single-mode Tab commit,
228
+ * and typeahead — all in the activedescendant model.
229
+ */
230
+ handleVirtualizedKeydown(event: KeyboardEvent): void;
231
+ /**
232
+ * Called by an option on click in the virtualized path: moves
233
+ * `aria-activedescendant` to that option and returns DOM focus to the
234
+ * content surface. No-op in the default path.
235
+ */
236
+ notifyOptionClick(optionId: string): void;
237
+ /** Flip the `touched` model. Called by trigger on blur-to-outside and on dismiss events. */
238
+ markTouched(): void;
239
+ }
240
+ declare const FOR_SELECT_CONTEXT: InjectionToken<ForSelectContext<unknown>>;
241
+
242
+ /**
243
+ * Headless implementation of the [WAI-ARIA select-only combobox pattern](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/examples/combobox-select-only/).
244
+ * Implements `FormValueControl<readonly T[]>` from
245
+ * `@angular/forms/signals` for `[formField]` auto-wiring.
246
+ *
247
+ * Generic over the option value type `T` (default `string`). When the
248
+ * consumer binds object items the directive infers `T` from `[(value)]` and
249
+ * `[forSelectOption][value]`; object identity is resolved by the
250
+ * consumer-supplied `[isItemEqualToValue]` and the hidden inputs serialize
251
+ * via `[itemToFormValue]`. Option display text is read from the rendered
252
+ * `textContent`, so no separate label function is needed — supply the
253
+ * optional `[itemToLabel]` only when a pre-set object value must render its
254
+ * label before the listbox is ever opened (the documented `@if (open())`
255
+ * pattern).
256
+ *
257
+ * Selection is always modeled as `readonly T[]`:
258
+ * - In single mode (`multiple=false`, default), the array has 0 or 1 element
259
+ * and option activation closes the listbox.
260
+ * - In multi mode, option activation toggles and the listbox stays open.
261
+ *
262
+ * Typeahead has two modes mirroring native `<select>`:
263
+ * - **Closed trigger** (single mode only): printable keys select the matching
264
+ * option immediately without opening the listbox.
265
+ * - **Open listbox**: printable keys move focus to the first matching option
266
+ * (selection still requires Enter / Space / click).
267
+ */
268
+ declare class ForSelect<T = string> extends FormUiControlBase implements FormValueControl<readonly T[]>, ForSelectContext<T> {
269
+ #private;
270
+ /**
271
+ * Two-way bindable. Selected option values. Single-mode keeps 0 or 1
272
+ * element. The `model()` change emitter (`(valueChange)`) fires only on
273
+ * internal selection changes, never on consumer writes via `[(value)]`.
274
+ */
275
+ readonly value: _angular_core.ModelSignal<readonly T[]>;
276
+ /**
277
+ * Compare two items for equality. Defaults to `===`, which is the
278
+ * correct identity for primitive `T` (e.g. strings, numbers). Override
279
+ * when binding object items so the directive can locate selected entries
280
+ * by id (or any other stable key) instead of by reference:
281
+ * `[isItemEqualToValue]="(a, b) => a.id === b.id"`.
282
+ */
283
+ readonly isItemEqualToValue: _angular_core.InputSignal<(a: T, b: T) => boolean>;
284
+ /**
285
+ * Serialize an item for the hidden input that participates in native
286
+ * form submission. Defaults to identity for strings and to
287
+ * `JSON.stringify` for non-string items so the primitive works out of
288
+ * the box round-tripping objects. Override to emit a specific wire
289
+ * format — typically a per-item id — when the backend expects that:
290
+ * `[itemToFormValue]="(it) => it.id"`.
291
+ */
292
+ readonly itemToFormValue: _angular_core.InputSignal<(item: T) => string>;
293
+ /**
294
+ * Resolve the display label for an item without the listbox mounted.
295
+ * When set, {@link selectedLabels} (and therefore `[forSelectValue]`)
296
+ * renders this for any selected value, so a pre-set object value shows
297
+ * its label on first paint — before the listbox has ever been opened, in
298
+ * the documented `@if (forSelect.open())` pattern. Without it, object-value
299
+ * labels resolve from the rendered option `textContent`, which is only
300
+ * available once the content mounts; the serialized form value is shown as
301
+ * a last-resort fallback in the meantime: `[itemToLabel]="(c) => c.name"`.
302
+ *
303
+ * Defaults to `undefined` (string mode renders the value verbatim, so no
304
+ * label function is needed).
305
+ */
306
+ readonly itemToLabel: _angular_core.InputSignal<((item: T) => string) | undefined>;
307
+ /**
308
+ * Read-only single-select convenience view of {@link value}. Returns the
309
+ * sole value when exactly one is selected (regardless of `multiple`),
310
+ * otherwise `null` (zero, or 2+ selected). Lets single-select consumers
311
+ * read `selected()` instead of unwrapping `value()[0]`. The array-backed
312
+ * `value` model remains the source of truth and the `FormValueControl`
313
+ * contract; this is a derived accessor.
314
+ */
315
+ readonly selected: _angular_core.Signal<T | null>;
316
+ /**
317
+ * Two-way bindable. Whether the listbox is currently shown. The `model()`
318
+ * change emitter (`(openChange)`) fires only on internal transitions
319
+ * (trigger toggle, Escape, outside dismissal, single-mode option select),
320
+ * never on consumer writes via `[(open)]`.
321
+ */
322
+ readonly open: _angular_core.ModelSignal<boolean>;
323
+ readonly multiple: _angular_core.InputSignalWithTransform<boolean, unknown>;
324
+ /**
325
+ * Presentation mode. When `true`, `[forSelectContent]` mounts as a trapped /
326
+ * inert / scroll-locked modal surface (routed through `_internal/modal-shell`)
327
+ * instead of the default anchored popover — the batteries-included touch
328
+ * presentation a consumer opts into with `[modal]="isCoarsePointer()"`. The
329
+ * form-value wiring (`[(value)]`, `name`) is unchanged.
330
+ *
331
+ * Read once when the content mounts (the two shells are structurally
332
+ * different; switching at runtime would need a remount, and the surface
333
+ * mounts lazily via `@if (open())` well after `modal` settles). Every
334
+ * anchored-positioning input — `position`, `side`, `align`, `sideOffset`,
335
+ * `alignOffset`, `sticky`, `hideWhenDetached`, `clipUntilPositioned`, `avoidCollisions`,
336
+ * `collisionPadding`, `arrowPadding` — is a no-op in this mode. Default
337
+ * `false` (non-breaking). The swipe / snap-point sheet is deliberately not
338
+ * this mode — compose a `ForListbox` inside a `ForDrawer` for that.
339
+ */
340
+ readonly modal: _angular_core.InputSignalWithTransform<boolean, unknown>;
341
+ /**
342
+ * Positioning algorithm.
343
+ *
344
+ * - `'popper'` (default): standard floating-ui anchored placement using
345
+ * `side` / `align` / `sideOffset` / `alignOffset`, with `flip` + `shift`
346
+ * collision handling. Same path as Popover / DropdownMenu.
347
+ * - `'item-aligned'`: the listbox overlays the trigger so the selected
348
+ * option's vertical center aligns with the trigger's vertical center
349
+ * — visually the menu "snaps over" the trigger when opened, mirroring
350
+ * macOS native `<select>`. Falls back to the first enabled option when
351
+ * nothing is selected. `side`, `align`, `sideOffset`, `alignOffset`,
352
+ * `sticky`, `hideWhenDetached`, `clipUntilPositioned`, and `avoidCollisions` are ignored in
353
+ * this mode; only `collisionPadding` is honored.
354
+ */
355
+ readonly position: _angular_core.InputSignal<"popper" | "item-aligned">;
356
+ /**
357
+ * Side the listbox is anchored to. Defaults to `'bottom'`. Pair with
358
+ * `align` for the full positioning API. Ignored when
359
+ * `position="item-aligned"`.
360
+ */
361
+ readonly side: _angular_core.InputSignal<FloatingSide | undefined>;
362
+ /** Alignment along the chosen `side`. Defaults to `'start'`. */
363
+ readonly align: _angular_core.InputSignal<FloatingAlign | undefined>;
364
+ /**
365
+ * Gap (px) between trigger and listbox along the main axis. Default `4`.
366
+ * The default is read from
367
+ * `provideForSelectDefaults` for the surrounding scope.
368
+ */
369
+ readonly sideOffset: _angular_core.InputSignalWithTransform<number, unknown>;
370
+ /** Gap (px) along the cross axis. Default `0`. */
371
+ readonly alignOffset: _angular_core.InputSignalWithTransform<number, unknown>;
372
+ /** When `true` (default), `flip` and `shift` keep the listbox inside the viewport. */
373
+ readonly avoidCollisions: _angular_core.InputSignalWithTransform<boolean, unknown>;
374
+ /**
375
+ * Padding (px) applied uniformly to flip / shift / size. Default `8`.
376
+ * The default is read from `provideForSelectDefaults` for the surrounding
377
+ * scope.
378
+ */
379
+ readonly collisionPadding: _angular_core.InputSignalWithTransform<number, unknown>;
380
+ /** Padding (px) for the `arrow` middleware. Default `0`. */
381
+ readonly arrowPadding: _angular_core.InputSignalWithTransform<number, unknown>;
382
+ /** Stickiness behaviour for `shift`. Default `'partial'`. */
383
+ readonly sticky: _angular_core.InputSignal<false | "partial" | "always">;
384
+ /** When `true`, sets `data-detached=""` while the trigger is scrolled off-screen. */
385
+ readonly hideWhenDetached: _angular_core.InputSignalWithTransform<boolean, unknown>;
386
+ /**
387
+ * When `true` (default), the content is clipped until floating-ui resolves
388
+ * its first position, preventing a flash at the viewport corner. Set to
389
+ * `false` so a dramatic `animate.enter` plays from its first frame (the
390
+ * surface may flash briefly at the unresolved position while positioning
391
+ * computes).
392
+ */
393
+ readonly clipUntilPositioned: _angular_core.InputSignalWithTransform<boolean, unknown>;
394
+ readonly loop: _angular_core.InputSignalWithTransform<boolean, unknown>;
395
+ readonly orientation: _angular_core.InputSignal<"horizontal" | "vertical">;
396
+ /**
397
+ * Total number of items in the source data. When set, switches the listbox
398
+ * to the virtualized `aria-activedescendant` focus model and populates
399
+ * `aria-setsize` on each rendered option. Leave unset (default) for the
400
+ * standard DOM-focus model.
401
+ */
402
+ readonly totalCount: _angular_core.InputSignalWithTransform<number | undefined, unknown>;
403
+ /**
404
+ * Inclusive-exclusive `[start, end)` index range of the currently rendered
405
+ * options, provided by `injectVirtualizer`. Used to decide whether a
406
+ * navigation target is in the visible window.
407
+ */
408
+ readonly visibleRange: _angular_core.InputSignal<readonly [number, number] | undefined>;
409
+ /**
410
+ * Emitted when navigation (or open-time scroll-to-selected) reaches an
411
+ * option outside the rendered window. Pass to `injectVirtualizer`'s
412
+ * `scrollToIndex` so the correct option mounts.
413
+ */
414
+ readonly scrollToIndex: _angular_core.OutputEmitterRef<number>;
415
+ /**
416
+ * Writing direction. When unset (default `null`), the inherited ambient
417
+ * direction is resolved from the nearest ancestor carrying a `dir` attribute
418
+ * (or `<html dir>`), defaulting to `'ltr'`. An explicit `[dir]` always wins.
419
+ * The resolved value is reflected to the host `dir` attribute.
420
+ */
421
+ readonly _dirInput: _angular_core.InputSignal<WritingDirection | null>;
422
+ readonly dir: _angular_core.Signal<WritingDirection>;
423
+ /**
424
+ * Single-mode only. When true, arrow nav also selects the focused option
425
+ * while the listbox is open. APG calls this optional and recommends
426
+ * caution — leave off unless your UX truly benefits. Default `false`.
427
+ */
428
+ readonly selectionFollowsFocus: _angular_core.InputSignalWithTransform<boolean, unknown>;
429
+ /** Placeholder shown by `[forSelectValue]` when no option is selected. */
430
+ readonly placeholder: _angular_core.InputSignal<string>;
431
+ /** When true (default), Escape, pointer-down outside, and focus outside close the listbox. */
432
+ readonly dismissible: _angular_core.InputSignalWithTransform<boolean, unknown>;
433
+ /** When true (default), focus returns to the trigger on close. */
434
+ readonly returnFocus: _angular_core.InputSignalWithTransform<boolean, unknown>;
435
+ /** Manual `aria-label` on `[forSelectContent]` when the trigger isn't a meaningful name. */
436
+ readonly ariaLabel: _angular_core.InputSignal<string | null>;
437
+ readonly escapeKeyDown: _angular_core.OutputEmitterRef<VetoableNativeEvent<KeyboardEvent>>;
438
+ readonly pointerDownOutside: _angular_core.OutputEmitterRef<VetoableNativeEvent<PointerEvent>>;
439
+ readonly focusOutside: _angular_core.OutputEmitterRef<VetoableNativeEvent<FocusEvent>>;
440
+ readonly interactOutside: _angular_core.OutputEmitterRef<VetoableNativeEvent<PointerEvent | FocusEvent>>;
441
+ /**
442
+ * Fires just before the listbox sends focus to the selected option
443
+ * (or first / last enabled) on mount. Call `preventDefault()` on the
444
+ * emitted veto to skip the imperative focus move.
445
+ */
446
+ readonly autoFocusOnOpen: _angular_core.OutputEmitterRef<VetoableEvent>;
447
+ /**
448
+ * Fires just before focus returns to the trigger on unmount. Call
449
+ * `preventDefault()` on the veto to suppress the return-focus.
450
+ */
451
+ readonly autoFocusOnClose: _angular_core.OutputEmitterRef<VetoableEvent>;
452
+ readonly triggerId: _angular_core.WritableSignal<string>;
453
+ readonly contentId: _angular_core.WritableSignal<string>;
454
+ readonly initialFocus: _angular_core.Signal<ForSelectInitialFocus>;
455
+ readonly lastCloseReason: _angular_core.Signal<ForSelectCloseReason | null>;
456
+ readonly trigger: _angular_core.Signal<HTMLElement | null>;
457
+ /**
458
+ * Element floating-ui anchors the listbox against. Prefers an optional
459
+ * `[forSelectAnchor]` when registered, otherwise falls back to the trigger
460
+ * so existing selects without an anchor keep their behavior. Decoupled from
461
+ * `trigger` so the trigger keeps driving `aria-controls`, the click toggle,
462
+ * focus return, and its dismissal exemption regardless of where the listbox
463
+ * paints.
464
+ */
465
+ readonly anchor: _angular_core.Signal<_floating_ui_dom.ReferenceElement | null>;
466
+ readonly content: _angular_core.Signal<HTMLElement | null>;
467
+ readonly options: _angular_core.Signal<readonly ForSelectOptionHandle<T>[]>;
468
+ /** The active option's `id` in the virtualized path, `null` in the default path. */
469
+ readonly activeDescendantId: _angular_core.Signal<string | null>;
470
+ /**
471
+ * Trimmed display labels of the selected values, in selection order. Pure
472
+ * derivation: when `[itemToLabel]` is supplied it is authoritative; otherwise
473
+ * resolve from the persisted option snapshot, then the serialized form value
474
+ * so non-string items still render meaningfully on a cold cache.
475
+ *
476
+ * The snapshot's labels come from each option's reactive `label` signal,
477
+ * which reads the rendered `textContent`. `textContent` is not a signal, so a
478
+ * label whose rendered text changes without a value change does not self-heal
479
+ * here — supply `[itemToLabel]` for a pure signal derivation that observes
480
+ * label changes directly.
481
+ */
482
+ readonly selectedLabels: _angular_core.Signal<readonly string[]>;
483
+ readonly selectedOptionEl: _angular_core.Signal<HTMLElement | null>;
484
+ protected fieldLabelledElement(): HTMLElement | null;
485
+ protected fieldLabelledElementId(): string;
486
+ constructor();
487
+ setInitialFocus(target: ForSelectInitialFocus): void;
488
+ registerTrigger(el: HTMLElement): void;
489
+ unregisterTrigger(el: HTMLElement): void;
490
+ registerAnchor(el: HTMLElement): void;
491
+ unregisterAnchor(el: HTMLElement): void;
492
+ registerContent(el: HTMLElement): void;
493
+ unregisterContent(el: HTMLElement): void;
494
+ registerOption(handle: ForSelectOptionHandle<T>): void;
495
+ unregisterOption(handle: ForSelectOptionHandle<T>): void;
496
+ isSelected(v: T): boolean;
497
+ activate(v: T): void;
498
+ navigate(currentOption: HTMLElement, action: ListNavigationAction): void;
499
+ handleTypeahead(event: KeyboardEvent): void;
500
+ handleClosedTypeahead(event: KeyboardEvent): boolean;
501
+ focusFirstEnabledOption(): boolean;
502
+ focusLastEnabledOption(): boolean;
503
+ focusSelectedOption(): boolean;
504
+ toggle(initialFocus?: ForSelectInitialFocus): void;
505
+ openMenu(initialFocus?: ForSelectInitialFocus): void;
506
+ closeMenu(reason: ForSelectCloseReason): void;
507
+ commitOnTab(value: T): void;
508
+ emitEscapeKeyDown(event: KeyboardEvent): void;
509
+ /**
510
+ * Outside-interaction emit forwarders. The shared `#pendingOutsideVeto`
511
+ * reuse between the specific outside channels and the composite
512
+ * `interactOutside` lives in `injectOverlayShell`; these only fire the
513
+ * matching output with the veto the shell built.
514
+ */
515
+ emitPointerDownOutside(veto: VetoableNativeEvent<PointerEvent>): void;
516
+ emitFocusOutside(veto: VetoableNativeEvent<FocusEvent>): void;
517
+ emitInteractOutside(veto: VetoableNativeEvent<PointerEvent | FocusEvent>): void;
518
+ /** Modal-path Escape forwarder: emit only; the modal shell owns the close. */
519
+ forwardEscapeKeyDown(veto: VetoableNativeEvent<KeyboardEvent>): void;
520
+ /**
521
+ * Implicit close requested by the shell after an un-vetoed outside
522
+ * interaction. Marks the control touched (mirroring the trigger blur) and
523
+ * closes with the channel's reason.
524
+ */
525
+ requestClose(reason: 'pointerDownOutside' | 'focusOutside'): void;
526
+ emitAutoFocusOnOpen(): boolean;
527
+ emitAutoFocusOnClose(): boolean;
528
+ markTouched(): void;
529
+ seedVirtualizedInitialFocus(): void;
530
+ handleVirtualizedKeydown(event: KeyboardEvent): void;
531
+ notifyOptionClick(optionId: string): void;
532
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ForSelect<any>, never>;
533
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<ForSelect<any>, "[forSelect]", ["forSelect"], { "value": { "alias": "value"; "required": false; "isSignal": true; }; "isItemEqualToValue": { "alias": "isItemEqualToValue"; "required": false; "isSignal": true; }; "itemToFormValue": { "alias": "itemToFormValue"; "required": false; "isSignal": true; }; "itemToLabel": { "alias": "itemToLabel"; "required": false; "isSignal": true; }; "open": { "alias": "open"; "required": false; "isSignal": true; }; "multiple": { "alias": "multiple"; "required": false; "isSignal": true; }; "modal": { "alias": "modal"; "required": false; "isSignal": true; }; "position": { "alias": "position"; "required": false; "isSignal": true; }; "side": { "alias": "side"; "required": false; "isSignal": true; }; "align": { "alias": "align"; "required": false; "isSignal": true; }; "sideOffset": { "alias": "sideOffset"; "required": false; "isSignal": true; }; "alignOffset": { "alias": "alignOffset"; "required": false; "isSignal": true; }; "avoidCollisions": { "alias": "avoidCollisions"; "required": false; "isSignal": true; }; "collisionPadding": { "alias": "collisionPadding"; "required": false; "isSignal": true; }; "arrowPadding": { "alias": "arrowPadding"; "required": false; "isSignal": true; }; "sticky": { "alias": "sticky"; "required": false; "isSignal": true; }; "hideWhenDetached": { "alias": "hideWhenDetached"; "required": false; "isSignal": true; }; "clipUntilPositioned": { "alias": "clipUntilPositioned"; "required": false; "isSignal": true; }; "loop": { "alias": "loop"; "required": false; "isSignal": true; }; "orientation": { "alias": "orientation"; "required": false; "isSignal": true; }; "totalCount": { "alias": "totalCount"; "required": false; "isSignal": true; }; "visibleRange": { "alias": "visibleRange"; "required": false; "isSignal": true; }; "_dirInput": { "alias": "dir"; "required": false; "isSignal": true; }; "selectionFollowsFocus": { "alias": "selectionFollowsFocus"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "dismissible": { "alias": "dismissible"; "required": false; "isSignal": true; }; "returnFocus": { "alias": "returnFocus"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "open": "openChange"; "scrollToIndex": "scrollToIndex"; "escapeKeyDown": "escapeKeyDown"; "pointerDownOutside": "pointerDownOutside"; "focusOutside": "focusOutside"; "interactOutside": "interactOutside"; "autoFocusOnOpen": "autoFocusOnOpen"; "autoFocusOnClose": "autoFocusOnClose"; }, never, never, true, never>;
534
+ }
535
+
536
+ /**
537
+ * Optional positioning anchor. When present, `[forSelectContent]` is
538
+ * positioned against this element instead of `[forSelectTrigger]` — useful
539
+ * when the trigger lives inside a decorated field box (padding, prefix icon,
540
+ * clear / chevron buttons) and the listbox should match the visible field
541
+ * rather than the inner button.
542
+ *
543
+ * Only positioning changes: the trigger still owns `aria-controls`,
544
+ * `aria-expanded`, the click toggle, focus return on close, and its exemption
545
+ * from outside-pointer dismissal. If no anchor is registered the listbox falls
546
+ * back to anchoring against the trigger, so existing usages are unaffected.
547
+ *
548
+ * At most one `[forSelectAnchor]` may be registered per `[forSelect]`; a second
549
+ * one throws.
550
+ *
551
+ * ```html
552
+ * <div forSelect [(value)]="v">
553
+ * <div forSelectAnchor class="field-box">
554
+ * <icon />
555
+ * <button forSelectTrigger>…</button>
556
+ * <button class="clear">×</button>
557
+ * </div>
558
+ * @if (open()) {
559
+ * <div forSelectContent>…</div>
560
+ * }
561
+ * </div>
562
+ * ```
563
+ */
564
+ declare class ForSelectAnchor {
565
+ #private;
566
+ constructor();
567
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ForSelectAnchor, never>;
568
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<ForSelectAnchor, "[forSelectAnchor]", ["forSelectAnchor"], {}, {}, never, never, true, never>;
569
+ }
570
+
571
+ /**
572
+ * Combobox button that opens the listbox. Apply on a `<button>` so
573
+ * Space / Enter dispatch native click events that toggle via `(click)`.
574
+ *
575
+ * Wires APG select-only combobox attributes: `role="combobox"`,
576
+ * `aria-haspopup="listbox"`, `aria-expanded`, and `aria-controls` pointing
577
+ * to the listbox. The button is exempt from the listbox's dismissable
578
+ * layer — clicks on it route through `(click)` instead of triggering an
579
+ * outside-pointer dismissal race.
580
+ *
581
+ * The root is normally resolved via DI from the enclosing `[forSelect]`.
582
+ * When the trigger is declared inside an `ng-template` stamped into the root
583
+ * (e.g. via `ngTemplateOutlet`), DI resolves at the template's declaration
584
+ * site and misses the root — pass it explicitly through the selector input,
585
+ * `routerLink`-style: `[forSelectTrigger]="root"` with `#root="forSelect"`.
586
+ *
587
+ * Keyboard:
588
+ * - **Click / Enter / Space** — toggle (open focuses the selected option, or first).
589
+ * - **ArrowDown** — open + focus selected option (or first).
590
+ * - **ArrowUp** — open + focus selected option (or last when none selected).
591
+ * - **Typeahead** (single mode only) — printable keys select the matching
592
+ * option immediately without opening the listbox, mirroring native
593
+ * `<select>`. In multi mode the buffered key is ignored at the trigger;
594
+ * open the listbox first to typeahead-focus.
595
+ */
596
+ declare class ForSelectTrigger<T = unknown> {
597
+ #private;
598
+ /**
599
+ * Optional explicit reference to the `[forSelect]` root, named after the
600
+ * selector `routerLink`-style. The bare valueless attribute keeps resolving
601
+ * the enclosing root via DI; pass the root explicitly
602
+ * (`[forSelectTrigger]="root"`, with `#root="forSelect"`) when the trigger
603
+ * is declared in an `ng-template` stamped inside the root — DI resolves at
604
+ * the template's declaration site, so the enclosing root is invisible there.
605
+ * The empty string (what the valueless attribute yields) is treated as unset.
606
+ */
607
+ readonly forSelectTrigger: _angular_core.InputSignal<"" | ForSelectContext<T>>;
608
+ protected readonly ctx: _angular_core.Signal<ForSelectContext<T>>;
609
+ constructor();
610
+ protected onClick(): void;
611
+ protected onKeyDown(event: KeyboardEvent): void;
612
+ protected onFocusOut(event: FocusEvent): void;
613
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ForSelectTrigger<any>, never>;
614
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<ForSelectTrigger<any>, "[forSelectTrigger]", ["forSelectTrigger"], { "forSelectTrigger": { "alias": "forSelectTrigger"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
615
+ }
616
+
617
+ /**
618
+ * Renders the currently-selected option's text — or the configured
619
+ * placeholder when nothing is selected — into its host element via
620
+ * `textContent`. Apply on a `<span>` (or any inline element) inside
621
+ * `[forSelectTrigger]`:
622
+ *
623
+ * ```html
624
+ * <button forSelectTrigger>
625
+ * <span forSelectValue placeholder="Select fruit…"></span>
626
+ * </button>
627
+ * ```
628
+ *
629
+ * In multi mode the labels are joined by `separator` (default `', '`). For
630
+ * fully custom rendering, drop this directive and read
631
+ * `forSelect.selectedLabels()` / `forSelect.value()` from your template.
632
+ */
633
+ declare class ForSelectValue {
634
+ #private;
635
+ /** Text shown when nothing is selected. Falls back to `[forSelect][placeholder]`. */
636
+ readonly placeholder: _angular_core.InputSignal<string>;
637
+ /** Joiner for multi-mode label rendering. Default `', '`. */
638
+ readonly separator: _angular_core.InputSignal<string>;
639
+ protected readonly isPlaceholder: _angular_core.Signal<boolean>;
640
+ protected readonly displayText: _angular_core.Signal<string>;
641
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ForSelectValue, never>;
642
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<ForSelectValue, "[forSelectValue]", ["forSelectValue"], { "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "separator": { "alias": "separator"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
643
+ }
644
+
645
+ /**
646
+ * The listbox surface. Carries `role="listbox"`, is portaled to
647
+ * `document.body`, and is positioned by `@floating-ui/dom` against the
648
+ * trigger.
649
+ *
650
+ * Mount/unmount of the visible content is the consumer's responsibility —
651
+ * wrap with `@if (open())` so `animate.enter` / `animate.leave` fire on the
652
+ * natural mount cycle. While mounted, a `DismissableLayer` activates
653
+ * (Escape, pointer-down outside, focus outside); the trigger element is
654
+ * exempt from outside-pointer checks so trigger clicks toggle without
655
+ * dismissal racing.
656
+ *
657
+ * Initial focus is sent to the selected option (`'selected'`), the first
658
+ * enabled option (`'first'`), or the last enabled option (`'last'`)
659
+ * according to the trigger's hint. On destroy, focus returns to the
660
+ * trigger when `returnFocus` is true.
661
+ *
662
+ * The lifecycle is owned by one of the two shared shells, picked once on
663
+ * construction from `[forSelect].modal`:
664
+ *
665
+ * - **non-modal (default)** — `injectOverlayShell` anchors the listbox to the
666
+ * trigger and branches on `[forSelect].position`:
667
+ * - `'popper'` (default) — standard `injectFloating` path with full
668
+ * anchored placement (`side`, `align`, `sideOffset`,
669
+ * `alignOffset`, `flip`, `shift`, `arrow`, `hideWhenDetached`).
670
+ * - `'item-aligned'` — `injectItemAlignedPositioner` overlays the listbox so
671
+ * the selected option's center aligns with the trigger's center. The
672
+ * anchored-placement inputs are documented as no-ops in this mode.
673
+ * - **modal** — `injectModalShell` traps focus, inerts the background, and
674
+ * locks body scroll (a centered surface the consumer positions with CSS, not
675
+ * trigger-anchored). The batteries-included touch presentation. Same Escape /
676
+ * outside-pointer dismiss, `dismissible` / `returnFocus` / `ariaLabel`, and
677
+ * `autoFocusOnOpen` / `autoFocusOnClose` veto hooks; every anchored-
678
+ * positioning input is a no-op. `aria-modal="true"` is reflected as a hint —
679
+ * the real modality comes from the `inert` siblings the shell applies (the
680
+ * surface keeps `role="listbox"`, for which several screen readers ignore
681
+ * `aria-modal`).
682
+ *
683
+ * Mount/unmount of the visible content is the consumer's responsibility —
684
+ * wrap with `@if (open())` so `animate.enter` / `animate.leave` fire on the
685
+ * natural mount cycle.
686
+ */
687
+ declare class ForSelectContent {
688
+ #private;
689
+ protected readonly ctx: forty_cdk_select.ForSelectContext<unknown>;
690
+ constructor();
691
+ protected onKeyDown(event: KeyboardEvent): void;
692
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ForSelectContent, never>;
693
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<ForSelectContent, "[forSelectContent]", ["forSelectContent"], {}, {}, never, never, true, never>;
694
+ }
695
+
696
+ /**
697
+ * Injection key the `[forSelectIndicator]` uses to resolve its parent option,
698
+ * decoupled from the concrete `ForSelectOption` class. `ForSelectOption`
699
+ * provides itself under this token, so a design system wrapping the option by
700
+ * subclassing re-points it at the subclass with a single provider
701
+ * (`{ provide: FOR_SELECT_OPTION, useExisting: MtxSelectOption }`) and the
702
+ * indicator keeps resolving — see `docs/wrapping-form-primitives.md`.
703
+ */
704
+ declare const FOR_SELECT_OPTION: InjectionToken<ForSelectOption<string>>;
705
+ /**
706
+ * One option inside a `[forSelectContent]`. Apply on a `<button type="button">`
707
+ * so Space / Enter activation come from native button behavior — printable
708
+ * keys fall through to the listbox for typeahead matching.
709
+ *
710
+ * Generic over the option value type `T` (default `string`). Inferred from
711
+ * the `[value]` binding so consumers can pass either primitive ids or full
712
+ * objects (`[value]="city"` infers `T = City`); the parent `[forSelect]`
713
+ * must be parameterized over the same `T`. The parent's
714
+ * `[isItemEqualToValue]` decides how options are matched against the
715
+ * committed selection.
716
+ *
717
+ * Click activates: in single mode the value replaces `[(value)]` and the
718
+ * listbox closes; in multi mode the value toggles in/out and the listbox
719
+ * stays open.
720
+ *
721
+ * Keyboard while focused:
722
+ * - **Enter / Space** — activate (via native button click).
723
+ * - **ArrowDown / ArrowUp / Home / End** — move focus inside the listbox.
724
+ * - **Tab / Shift+Tab** — commit the focused option (single mode) and let
725
+ * the browser advance focus to the next / previous focusable, mirroring
726
+ * the WAI-ARIA select-only combobox pattern and native `<select>`.
727
+ * - **Escape** — close the listbox.
728
+ * - **Typeahead** — printable keys match by text content.
729
+ */
730
+ declare class ForSelectOption<T = string> {
731
+ #private;
732
+ /**
733
+ * Stable identifier serialized into `[(value)]` and the hidden input.
734
+ * Defaults to `string` for back-compat; bind an object to specialize the
735
+ * parent `[forSelect]` over a richer `T`. The parent's
736
+ * `[isItemEqualToValue]` decides how options are matched against the
737
+ * committed selection.
738
+ */
739
+ readonly value: _angular_core.InputSignal<T>;
740
+ readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
741
+ /**
742
+ * Zero-based absolute position of this option in the full source data.
743
+ * Required in the virtualized path — drives `aria-posinset` and the parent's
744
+ * position snapshot. Leave unset (default `null`) outside it.
745
+ */
746
+ readonly posInSet: _angular_core.InputSignal<number | null>;
747
+ readonly id: _angular_core.Signal<string>;
748
+ readonly selected: _angular_core.Signal<boolean>;
749
+ readonly effectiveDisabled: _angular_core.Signal<boolean>;
750
+ protected readonly ariaSetSize: _angular_core.Signal<string | null>;
751
+ protected readonly ariaPosInSet: _angular_core.Signal<string | null>;
752
+ /**
753
+ * True when this option is the active candidate — DOM-focused in the
754
+ * default path, or `aria-activedescendant` in the virtualized path.
755
+ * Reflected as `data-highlighted`.
756
+ */
757
+ readonly highlighted: _angular_core.Signal<boolean>;
758
+ constructor();
759
+ protected onClick(): void;
760
+ protected onFocus(): void;
761
+ protected onBlur(): void;
762
+ protected onKeyDown(event: KeyboardEvent): void;
763
+ protected onPointerDown(event: PointerEvent): void;
764
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ForSelectOption<any>, never>;
765
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<ForSelectOption<any>, "[forSelectOption]", ["forSelectOption"], { "value": { "alias": "value"; "required": true; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "posInSet": { "alias": "posInSet"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
766
+ }
767
+
768
+ /**
769
+ * Visibility helper inside a `[forSelectOption]`. The directive flips a
770
+ * `[hidden]` host binding so the consumer can keep the checkmark / icon
771
+ * inline without extra `@if` glue:
772
+ *
773
+ * ```html
774
+ * <button forSelectOption value="apple">
775
+ * <span forSelectIndicator>✓</span>
776
+ * Apple
777
+ * </button>
778
+ * ```
779
+ *
780
+ * Reflects the parent option's `data-state` (`"checked" | "unchecked"`) so
781
+ * the consumer can also style it from CSS. Visibility while unselected is
782
+ * enforced with an inline `display: none` (which beats any author `display`
783
+ * rule a consumer applies via a class) in addition to the `hidden` attribute
784
+ * that removes it from the a11y tree.
785
+ */
786
+ declare class ForSelectIndicator {
787
+ protected readonly option: ForSelectOption<string>;
788
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ForSelectIndicator, never>;
789
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<ForSelectIndicator, "[forSelectIndicator]", ["forSelectIndicator"], {}, {}, never, never, true, never>;
790
+ }
791
+
792
+ /**
793
+ * Optional grouping wrapper inside a `[forSelectContent]`. Renders
794
+ * `role="group"` and references the descendant `[forSelectGroupLabel]`
795
+ * (if any) via `aria-labelledby`. Options inside a group still register
796
+ * with the root listbox normally, so keyboard navigation traverses across
797
+ * groups in DOM order without special handling.
798
+ */
799
+ declare class ForSelectGroup {
800
+ #private;
801
+ /** The id of the registered group label (or `null` if none). */
802
+ readonly labelId: _angular_core.Signal<string | null>;
803
+ /** Called by `ForSelectGroupLabel` on mount. */
804
+ registerLabel(id: string): void;
805
+ /** Called by `ForSelectGroupLabel` on destroy. Idempotent. */
806
+ unregisterLabel(id: string): void;
807
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ForSelectGroup, never>;
808
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<ForSelectGroup, "[forSelectGroup]", ["forSelectGroup"], {}, {}, never, never, true, never>;
809
+ }
810
+
811
+ /**
812
+ * Visible label for a `[forSelectGroup]`. Generates a stable id and
813
+ * registers with its parent group so the group's `aria-labelledby` points
814
+ * at this element. Apply on whatever heading element fits the design
815
+ * (often `<div>` styled as a small caption).
816
+ */
817
+ declare class ForSelectGroupLabel {
818
+ /** Stable host id used by the parent group's `aria-labelledby`. */
819
+ readonly id: Signal<string>;
820
+ constructor();
821
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ForSelectGroupLabel, never>;
822
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<ForSelectGroupLabel, "[forSelectGroupLabel]", ["forSelectGroupLabel"], {}, {}, never, never, true, never>;
823
+ }
824
+
825
+ /**
826
+ * Decorative separator between options or groups inside a
827
+ * `[forSelectContent]`. Carries `role="separator"` and is intentionally not
828
+ * registered with the listbox's option collection, so keyboard navigation
829
+ * and typeahead skip it automatically.
830
+ */
831
+ declare class ForSelectSeparator {
832
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ForSelectSeparator, never>;
833
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<ForSelectSeparator, "[forSelectSeparator]", ["forSelectSeparator"], {}, {}, never, never, true, never>;
834
+ }
835
+
836
+ /**
837
+ * Defaults inherited by descendant selects in the surrounding injector
838
+ * scope. Configure with `provideForSelectDefaults` either at the
839
+ * application root or in any component's `providers` array; partial
840
+ * overrides merge with the parent scope.
841
+ */
842
+ interface ForSelectDefaults {
843
+ /**
844
+ * Distance (px) between the select trigger and the floating content
845
+ * along the resolved `side` axis.
846
+ */
847
+ sideOffset: number;
848
+ /**
849
+ * Padding (px) added to the viewport edges for collision-aware
850
+ * positioning. Higher values keep the floating content further from
851
+ * the edge when `flip` / `shift` runs.
852
+ */
853
+ collisionPadding: number;
854
+ }
855
+ /** Token holding the resolved select defaults for the current scope. */
856
+ declare const FOR_SELECT_DEFAULTS: _angular_core.InjectionToken<ForSelectDefaults>;
857
+ /**
858
+ * Configures forty-cdk select defaults for this injector scope. Partial
859
+ * overrides inherit unspecified keys from the parent scope (or library
860
+ * defaults at the root).
861
+ */
862
+ declare function provideForSelectDefaults(defaults?: Partial<ForSelectDefaults>): Provider[];
863
+
864
+ /**
865
+ * Exact public names of every `ForSelect` input, its models included. Spread it into the
866
+ * `inputs` array of a `hostDirectives` entry so a wrapper component re-exposes the
867
+ * primitive's full surface — the Signal Forms members `[formField]` binds among them —
868
+ * without hand-maintaining the list. Always spread into an inline object literal as shown
869
+ * below: the literal is what keeps the entry statically analyzable for consumers compiling
870
+ * against the published package. An anti-drift spec fails when this list no longer matches
871
+ * the directive's actual API. See `docs/wrapping-form-primitives.md` for both supported
872
+ * wrapping patterns.
873
+ *
874
+ * @example
875
+ * ```ts
876
+ * @Component({
877
+ * selector: 'div[mySelect]',
878
+ * template: '',
879
+ * hostDirectives: [
880
+ * {
881
+ * directive: ForSelect,
882
+ * inputs: [...FOR_SELECT_HOST_DIRECTIVE_INPUTS],
883
+ * outputs: [...FOR_SELECT_HOST_DIRECTIVE_OUTPUTS],
884
+ * },
885
+ * ],
886
+ * })
887
+ * export class MySelect {}
888
+ * ```
889
+ */
890
+ declare const FOR_SELECT_HOST_DIRECTIVE_INPUTS: readonly ["value", "open", "align", "alignOffset", "ariaLabel", "arrowPadding", "avoidCollisions", "clipUntilPositioned", "collisionPadding", "dir", "dirty", "disabled", "dismissible", "errors", "hideWhenDetached", "invalid", "isItemEqualToValue", "itemToFormValue", "itemToLabel", "loop", "modal", "multiple", "name", "orientation", "pending", "placeholder", "position", "readonly", "required", "returnFocus", "selectionFollowsFocus", "side", "sideOffset", "sticky", "totalCount", "touched", "visibleRange"];
891
+ /**
892
+ * Exact public names of every `ForSelect` output, the Signal Forms `touch` output
893
+ * included. Spread it into the `outputs` array of the same `hostDirectives` entry as
894
+ * {@link FOR_SELECT_HOST_DIRECTIVE_INPUTS}.
895
+ */
896
+ declare const FOR_SELECT_HOST_DIRECTIVE_OUTPUTS: readonly ["valueChange", "openChange", "escapeKeyDown", "pointerDownOutside", "focusOutside", "interactOutside", "autoFocusOnOpen", "autoFocusOnClose", "scrollToIndex", "touchedChange", "touch"];
897
+
898
+ export { FOR_SELECT_CONTEXT, FOR_SELECT_DEFAULTS, FOR_SELECT_HOST_DIRECTIVE_INPUTS, FOR_SELECT_HOST_DIRECTIVE_OUTPUTS, FOR_SELECT_OPTION, ForSelect, ForSelectAnchor, ForSelectContent, ForSelectGroup, ForSelectGroupLabel, ForSelectIndicator, ForSelectOption, ForSelectSeparator, ForSelectTrigger, ForSelectValue, provideForSelectDefaults };
899
+ export type { ForSelectCloseReason, ForSelectContext, ForSelectDefaults, ForSelectInitialFocus, ForSelectOptionHandle };