@radix-ng/primitives 1.0.0-beta.1 → 1.0.0-beta.3

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 (107) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +76 -6
  3. package/fesm2022/radix-ng-primitives-accordion.mjs +2 -2
  4. package/fesm2022/radix-ng-primitives-accordion.mjs.map +1 -1
  5. package/fesm2022/radix-ng-primitives-alert-dialog.mjs +30 -24
  6. package/fesm2022/radix-ng-primitives-alert-dialog.mjs.map +1 -1
  7. package/fesm2022/radix-ng-primitives-autocomplete.mjs +1786 -0
  8. package/fesm2022/radix-ng-primitives-autocomplete.mjs.map +1 -0
  9. package/fesm2022/radix-ng-primitives-calendar.mjs +14 -1
  10. package/fesm2022/radix-ng-primitives-calendar.mjs.map +1 -1
  11. package/fesm2022/radix-ng-primitives-checkbox.mjs +2 -2
  12. package/fesm2022/radix-ng-primitives-checkbox.mjs.map +1 -1
  13. package/fesm2022/radix-ng-primitives-collapsible.mjs +1 -1
  14. package/fesm2022/radix-ng-primitives-collapsible.mjs.map +1 -1
  15. package/fesm2022/radix-ng-primitives-combobox.mjs +1983 -0
  16. package/fesm2022/radix-ng-primitives-combobox.mjs.map +1 -0
  17. package/fesm2022/radix-ng-primitives-context-menu.mjs +1 -1
  18. package/fesm2022/radix-ng-primitives-context-menu.mjs.map +1 -1
  19. package/fesm2022/radix-ng-primitives-core.mjs +480 -469
  20. package/fesm2022/radix-ng-primitives-core.mjs.map +1 -1
  21. package/fesm2022/radix-ng-primitives-cropper.mjs +1 -1
  22. package/fesm2022/radix-ng-primitives-cropper.mjs.map +1 -1
  23. package/fesm2022/radix-ng-primitives-date-field.mjs +11 -0
  24. package/fesm2022/radix-ng-primitives-date-field.mjs.map +1 -1
  25. package/fesm2022/radix-ng-primitives-dialog.mjs +44 -46
  26. package/fesm2022/radix-ng-primitives-dialog.mjs.map +1 -1
  27. package/fesm2022/radix-ng-primitives-drawer.mjs +154 -64
  28. package/fesm2022/radix-ng-primitives-drawer.mjs.map +1 -1
  29. package/fesm2022/radix-ng-primitives-editable.mjs +1 -1
  30. package/fesm2022/radix-ng-primitives-editable.mjs.map +1 -1
  31. package/fesm2022/radix-ng-primitives-field.mjs +86 -6
  32. package/fesm2022/radix-ng-primitives-field.mjs.map +1 -1
  33. package/fesm2022/radix-ng-primitives-fieldset.mjs +1 -1
  34. package/fesm2022/radix-ng-primitives-fieldset.mjs.map +1 -1
  35. package/fesm2022/radix-ng-primitives-focus-scope.mjs +1 -1
  36. package/fesm2022/radix-ng-primitives-focus-scope.mjs.map +1 -1
  37. package/fesm2022/radix-ng-primitives-form.mjs +207 -0
  38. package/fesm2022/radix-ng-primitives-form.mjs.map +1 -0
  39. package/fesm2022/radix-ng-primitives-input.mjs +85 -4
  40. package/fesm2022/radix-ng-primitives-input.mjs.map +1 -1
  41. package/fesm2022/radix-ng-primitives-menu.mjs +44 -24
  42. package/fesm2022/radix-ng-primitives-menu.mjs.map +1 -1
  43. package/fesm2022/radix-ng-primitives-menubar.mjs +1 -1
  44. package/fesm2022/radix-ng-primitives-menubar.mjs.map +1 -1
  45. package/fesm2022/radix-ng-primitives-meter.mjs +1 -1
  46. package/fesm2022/radix-ng-primitives-meter.mjs.map +1 -1
  47. package/fesm2022/radix-ng-primitives-navigation-menu.mjs +39 -55
  48. package/fesm2022/radix-ng-primitives-navigation-menu.mjs.map +1 -1
  49. package/fesm2022/radix-ng-primitives-number-field.mjs +2 -2
  50. package/fesm2022/radix-ng-primitives-number-field.mjs.map +1 -1
  51. package/fesm2022/radix-ng-primitives-popover.mjs +36 -51
  52. package/fesm2022/radix-ng-primitives-popover.mjs.map +1 -1
  53. package/fesm2022/radix-ng-primitives-popper.mjs +12 -6
  54. package/fesm2022/radix-ng-primitives-popper.mjs.map +1 -1
  55. package/fesm2022/radix-ng-primitives-portal.mjs +107 -17
  56. package/fesm2022/radix-ng-primitives-portal.mjs.map +1 -1
  57. package/fesm2022/radix-ng-primitives-presence.mjs +262 -79
  58. package/fesm2022/radix-ng-primitives-presence.mjs.map +1 -1
  59. package/fesm2022/radix-ng-primitives-preview-card.mjs +37 -51
  60. package/fesm2022/radix-ng-primitives-preview-card.mjs.map +1 -1
  61. package/fesm2022/radix-ng-primitives-progress.mjs +1 -1
  62. package/fesm2022/radix-ng-primitives-progress.mjs.map +1 -1
  63. package/fesm2022/radix-ng-primitives-roving-focus.mjs +1 -1
  64. package/fesm2022/radix-ng-primitives-roving-focus.mjs.map +1 -1
  65. package/fesm2022/radix-ng-primitives-scroll-area.mjs +3 -3
  66. package/fesm2022/radix-ng-primitives-scroll-area.mjs.map +1 -1
  67. package/fesm2022/radix-ng-primitives-select.mjs +469 -258
  68. package/fesm2022/radix-ng-primitives-select.mjs.map +1 -1
  69. package/fesm2022/radix-ng-primitives-slider.mjs +1 -1
  70. package/fesm2022/radix-ng-primitives-slider.mjs.map +1 -1
  71. package/fesm2022/radix-ng-primitives-switch.mjs +3 -2
  72. package/fesm2022/radix-ng-primitives-switch.mjs.map +1 -1
  73. package/fesm2022/radix-ng-primitives-tabs.mjs +1 -1
  74. package/fesm2022/radix-ng-primitives-tabs.mjs.map +1 -1
  75. package/fesm2022/radix-ng-primitives-time-field.mjs +27 -3
  76. package/fesm2022/radix-ng-primitives-time-field.mjs.map +1 -1
  77. package/fesm2022/radix-ng-primitives-toast.mjs +1 -1
  78. package/fesm2022/radix-ng-primitives-toast.mjs.map +1 -1
  79. package/fesm2022/radix-ng-primitives-toggle-group.mjs +1 -1
  80. package/fesm2022/radix-ng-primitives-toggle-group.mjs.map +1 -1
  81. package/fesm2022/radix-ng-primitives-toolbar.mjs +2 -2
  82. package/fesm2022/radix-ng-primitives-toolbar.mjs.map +1 -1
  83. package/fesm2022/radix-ng-primitives-tooltip.mjs +39 -42
  84. package/fesm2022/radix-ng-primitives-tooltip.mjs.map +1 -1
  85. package/package.json +13 -1
  86. package/schematics/ng-add/index.js +57 -0
  87. package/schematics/ng-add/index.js.map +1 -1
  88. package/schematics/ng-add/schema.d.ts +1 -0
  89. package/schematics/ng-add/schema.json +6 -0
  90. package/types/radix-ng-primitives-alert-dialog.d.ts +17 -11
  91. package/types/radix-ng-primitives-autocomplete.d.ts +596 -0
  92. package/types/radix-ng-primitives-combobox.d.ts +1310 -0
  93. package/types/radix-ng-primitives-core.d.ts +148 -56
  94. package/types/radix-ng-primitives-dialog.d.ts +32 -25
  95. package/types/radix-ng-primitives-drawer.d.ts +49 -22
  96. package/types/radix-ng-primitives-field.d.ts +71 -2
  97. package/types/radix-ng-primitives-form.d.ts +124 -0
  98. package/types/radix-ng-primitives-input.d.ts +75 -5
  99. package/types/radix-ng-primitives-menu.d.ts +19 -10
  100. package/types/radix-ng-primitives-navigation-menu.d.ts +24 -26
  101. package/types/radix-ng-primitives-popover.d.ts +23 -23
  102. package/types/radix-ng-primitives-popper.d.ts +7 -1
  103. package/types/radix-ng-primitives-portal.d.ts +53 -8
  104. package/types/radix-ng-primitives-presence.d.ts +98 -17
  105. package/types/radix-ng-primitives-preview-card.d.ts +24 -23
  106. package/types/radix-ng-primitives-select.d.ts +294 -137
  107. package/types/radix-ng-primitives-tooltip.d.ts +26 -19
@@ -0,0 +1,1786 @@
1
+ import * as i0 from '@angular/core';
2
+ import { Directive, inject, booleanAttribute, Injector, model, input, computed, numberAttribute, output, signal, effect, untracked, isDevMode, ElementRef, afterNextRender, afterRenderEffect, DestroyRef, NgModule } from '@angular/core';
3
+ import * as i1 from '@radix-ng/primitives/combobox';
4
+ import { RdxComboboxAnchor, RdxComboboxBackdrop, provideComboboxRootContext, RdxComboboxEmpty, RdxComboboxGroup, RdxComboboxGroupLabel, RdxComboboxIcon, injectComboboxRootContext, injectComboboxGroupContext, provideComboboxItemContext, RdxComboboxItemIndicator, RdxComboboxLabel, RdxComboboxPortal, RdxComboboxStatus, RdxComboboxTrigger } from '@radix-ng/primitives/combobox';
5
+ import * as i1$1 from '@radix-ng/primitives/popper';
6
+ import { RdxPopperArrow, RdxPopper, RdxPopperAnchor, injectPopperContentWrapperContext, RdxPopperContent, RdxPopperContentWrapper } from '@radix-ng/primitives/popper';
7
+ import * as i2 from '@radix-ng/primitives/dismissable-layer';
8
+ import { RdxDismissableLayerBranch, RdxDismissableLayer, provideRdxDismissableLayerConfig } from '@radix-ng/primitives/dismissable-layer';
9
+ import { NG_VALUE_ACCESSOR } from '@angular/forms';
10
+ import { useTransitionStatus, injectId, useFilter, useListHighlight, isItemEqualToValue, itemToStringLabel, useScrollLock } from '@radix-ng/primitives/core';
11
+ import { injectFieldRootContext } from '@radix-ng/primitives/field';
12
+
13
+ /**
14
+ * Optional positioning anchor for the popup. Put it on the element the popup should align to — for
15
+ * example a wrapper that holds the input plus an icon/clear button. When present it takes precedence
16
+ * over the input. Reuses the combobox anchor behavior.
17
+ *
18
+ * @group Components
19
+ */
20
+ class RdxAutocompleteAnchor {
21
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteAnchor, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
22
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxAutocompleteAnchor, isStandalone: true, selector: "[rdxAutocompleteAnchor]", exportAs: ["rdxAutocompleteAnchor"], hostDirectives: [{ directive: i1.RdxComboboxAnchor }], ngImport: i0 }); }
23
+ }
24
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteAnchor, decorators: [{
25
+ type: Directive,
26
+ args: [{
27
+ selector: '[rdxAutocompleteAnchor]',
28
+ exportAs: 'rdxAutocompleteAnchor',
29
+ hostDirectives: [RdxComboboxAnchor]
30
+ }]
31
+ }] });
32
+
33
+ /**
34
+ * An optional arrow that points from the popup to the anchor. Composes the popper arrow directly
35
+ * (the same building block the combobox arrow uses).
36
+ *
37
+ * @group Components
38
+ */
39
+ class RdxAutocompleteArrow {
40
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteArrow, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
41
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxAutocompleteArrow, isStandalone: true, selector: "[rdxAutocompleteArrow]", exportAs: ["rdxAutocompleteArrow"], hostDirectives: [{ directive: i1$1.RdxPopperArrow, inputs: ["width", "width", "height", "height"] }], ngImport: i0 }); }
42
+ }
43
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteArrow, decorators: [{
44
+ type: Directive,
45
+ args: [{
46
+ selector: '[rdxAutocompleteArrow]',
47
+ exportAs: 'rdxAutocompleteArrow',
48
+ hostDirectives: [{ directive: RdxPopperArrow, inputs: ['width', 'height'] }]
49
+ }]
50
+ }] });
51
+
52
+ /**
53
+ * An overlay rendered beneath the popup in `modal` mode. Exposes `data-open` / `data-closed` for
54
+ * animation. Reuses the combobox backdrop.
55
+ *
56
+ * @group Components
57
+ */
58
+ class RdxAutocompleteBackdrop {
59
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteBackdrop, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
60
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxAutocompleteBackdrop, isStandalone: true, selector: "[rdxAutocompleteBackdrop]", exportAs: ["rdxAutocompleteBackdrop"], hostDirectives: [{ directive: i1.RdxComboboxBackdrop }], ngImport: i0 }); }
61
+ }
62
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteBackdrop, decorators: [{
63
+ type: Directive,
64
+ args: [{
65
+ selector: '[rdxAutocompleteBackdrop]',
66
+ exportAs: 'rdxAutocompleteBackdrop',
67
+ hostDirectives: [RdxComboboxBackdrop]
68
+ }]
69
+ }] });
70
+
71
+ /**
72
+ * Builds the {@link RdxComboboxRootContext} the autocomplete parts consume. Autocomplete reuses the
73
+ * combobox parts (List, Popup, Positioner, Item, …) verbatim, so the root exposes the exact combobox
74
+ * context shape — configured for a single-value, `selectionMode: 'none'` control whose value is the
75
+ * input string. Autocomplete-specific state (mode, inline completion, grid) is read by the local
76
+ * parts via direct injection of {@link RdxAutocompleteRoot}.
77
+ */
78
+ const context = () => {
79
+ const root = inject(RdxAutocompleteRoot);
80
+ return {
81
+ listId: root.listId,
82
+ labelId: root.labelId,
83
+ setLabelId: (id) => root.labelId.set(id),
84
+ dir: root.dir,
85
+ value: root.value,
86
+ inputValue: root.value,
87
+ open: root.open,
88
+ multiple: root.alwaysFalse,
89
+ selectionMode: root.noneMode,
90
+ disabledState: root.disabledState,
91
+ readonly: root.readOnly,
92
+ requiredState: root.requiredState,
93
+ openOnInputClick: root.openOnInputClick,
94
+ modal: root.modal,
95
+ virtualized: root.virtualized,
96
+ filteredItems: root.filteredItems,
97
+ highlightedItem: root.highlightedItem,
98
+ highlightedIndex: root.highlightedIndex.asReadonly(),
99
+ activeId: root.activeId,
100
+ itemId: (index) => root.itemId(index),
101
+ isKeyboardActive: () => root.isKeyboardActive(),
102
+ setKeyboardActive: (value) => root.setKeyboardActive(value),
103
+ transitionStatus: root.transitionStatus,
104
+ registerTransitionElement: root.registerTransitionElement,
105
+ visibleCount: root.visibleCount,
106
+ isVisible: (item) => root.isVisible(item),
107
+ isSelected: (value) => root.isSelectedValue(value),
108
+ registerItem: (item) => root.registerItem(item),
109
+ unregisterItem: (item) => root.unregisterItem(item),
110
+ highlight: root.highlight,
111
+ highlightNext: () => root.moveDown(),
112
+ highlightPrevious: () => root.moveUp(),
113
+ highlightFirst: () => root.highlightFirst('keyboard'),
114
+ highlightLast: () => root.highlightLast('keyboard'),
115
+ highlightIndex: (index, reason) => root.highlightIndex(index, reason),
116
+ setHighlight: (item, reason) => root.setHighlight(item, reason),
117
+ clearHighlight: () => root.clearHighlightState(),
118
+ highlightItemOnHover: root.highlightItemOnHover,
119
+ keepHighlight: root.keepHighlight,
120
+ inputElement: root.inputElement.asReadonly(),
121
+ setInputElement: (el) => root.inputElement.set(el),
122
+ registerTrigger: (el) => (root.triggerElement = el),
123
+ focusInput: () => root.focusInput(),
124
+ openPopup: () => root.setOpen(true),
125
+ openForBrowse: () => root.openForBrowse(),
126
+ closePopup: (revert = true) => root.closePopup(revert),
127
+ setInputValue: (value) => root.setQuery(value),
128
+ openAndHighlight: (edge) => root.openAndHighlight(edge),
129
+ select: (item) => root.handleSelect(item),
130
+ selectIndex: (index) => root.selectIndex(index),
131
+ selectHighlighted: () => root.selectHighlighted(),
132
+ clearSelection: () => root.clearValue(),
133
+ removeValue: () => undefined,
134
+ removeLastValue: () => undefined,
135
+ registerChipsNav: () => undefined,
136
+ focusLastChip: () => false,
137
+ labelFor: (value) => root.labelFor(value),
138
+ markAsTouched: () => root.markAsTouched()
139
+ };
140
+ };
141
+ /**
142
+ * `autoHighlight` transform: pass `'always'` through verbatim, coerce everything else as a boolean
143
+ * attribute (so the bare `autoHighlight` attribute reads `true`).
144
+ *
145
+ * Kept as a named module-level function rather than an inline `transform` arrow: compodoc 1.2.1
146
+ * (the metadata source for the API contract and Storybook ArgTypes) hangs parsing an inline arrow
147
+ * combined with explicit generic union type arguments on `input()`. A plain function reference sidesteps it.
148
+ */
149
+ function coerceAutoHighlight(value) {
150
+ return value === 'always' ? 'always' : booleanAttribute(value);
151
+ }
152
+ /**
153
+ * Root of an Autocomplete — a text input with a filtered list of suggestions. Built on the combobox
154
+ * engine with `selectionMode: 'none'`, so its value **is** the input string: typing, selecting an
155
+ * item, or clearing all change a single string value. Owns input text, open state, filtering, inline
156
+ * completion, and highlight-model navigation, and provides them to the combobox parts. Implements
157
+ * `ControlValueAccessor` (the form value is the input string).
158
+ *
159
+ * @group Components
160
+ */
161
+ class RdxAutocompleteRoot {
162
+ constructor() {
163
+ this.injector = inject(Injector);
164
+ /** The input text. This is the form value (controlled / uncontrolled via {@link defaultValue}). */
165
+ this.value = model('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
166
+ /** Initial input text when uncontrolled. */
167
+ this.defaultValue = input(...(ngDevMode ? [undefined, { debugName: "defaultValue" }] : /* istanbul ignore next */ []));
168
+ /** Whether the popup is open. */
169
+ this.open = model(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
170
+ /** Initial open state when uncontrolled. */
171
+ this.defaultOpen = input(false, { ...(ngDevMode ? { debugName: "defaultOpen" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
172
+ /** Filtering / inline-completion behavior. See {@link AutocompleteMode}. */
173
+ this.mode = input('list', ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
174
+ /** Text direction. */
175
+ this.dir = input('ltr', ...(ngDevMode ? [{ debugName: "dir" }] : /* istanbul ignore next */ []));
176
+ /** Whether the autocomplete is disabled. */
177
+ this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
178
+ /** Whether the autocomplete is read-only. */
179
+ this.readOnly = input(false, { ...(ngDevMode ? { debugName: "readOnly" } : /* istanbul ignore next */ {}), alias: 'readOnly', transform: booleanAttribute });
180
+ /** Whether a value is required (for forms). */
181
+ this.required = input(false, { ...(ngDevMode ? { debugName: "required" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
182
+ /** Whether keyboard navigation wraps at the list boundaries. */
183
+ this.loopFocus = input(true, { ...(ngDevMode ? { debugName: "loopFocus" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
184
+ /**
185
+ * Auto-highlight behavior (matches Base UI):
186
+ * - `false` (default): never auto-highlight;
187
+ * - `true` (also the bare `autoHighlight` attribute): highlight the first match as the query changes;
188
+ * - `'always'`: keep the first navigable item highlighted whenever the popup is open.
189
+ */
190
+ this.autoHighlight = input(false, { ...(ngDevMode ? { debugName: "autoHighlight" } : /* istanbul ignore next */ {}), transform: coerceAutoHighlight });
191
+ /** Resolved auto-highlight mode. */
192
+ this.autoHighlightMode = computed(() => {
193
+ const value = this.autoHighlight();
194
+ if (value === 'always') {
195
+ return 'always';
196
+ }
197
+ if (value === true) {
198
+ return 'input-change';
199
+ }
200
+ return 'off';
201
+ }, ...(ngDevMode ? [{ debugName: "autoHighlightMode" }] : /* istanbul ignore next */ []));
202
+ /**
203
+ * Whether moving the pointer over an item highlights it. `true` (default) paints `data-highlighted`
204
+ * on hover; `false` suppresses hover-driven highlight entirely, letting CSS `:hover` stay distinct
205
+ * from the `data-highlighted` (keyboard) state. Clicking an item still selects it.
206
+ */
207
+ this.highlightItemOnHover = input(true, { ...(ngDevMode ? { debugName: "highlightItemOnHover" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
208
+ /**
209
+ * Whether a pointer-driven highlight is kept when the cursor leaves the list. `false` (default)
210
+ * clears the highlight on pointer-leave; `true` retains the last hovered item highlighted. Keyboard
211
+ * navigation and auto-highlight are unaffected.
212
+ */
213
+ this.keepHighlight = input(false, { ...(ngDevMode ? { debugName: "keepHighlight" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
214
+ /** Whether clicking the input opens the popup. Defaults to `false` (Base UI default). */
215
+ this.openOnInputClick = input(false, { ...(ngDevMode ? { debugName: "openOnInputClick" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
216
+ /** Whether the popup is modal: locks page scroll and makes outside content inert while open. */
217
+ this.modal = input(false, { ...(ngDevMode ? { debugName: "modal" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
218
+ /** Whether selecting an item requests submit of the closest form. */
219
+ this.submitOnItemClick = input(false, { ...(ngDevMode ? { debugName: "submitOnItemClick" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
220
+ /** Whether the list is laid out as a 2D grid (enables row/column arrow navigation). */
221
+ this.grid = input(false, { ...(ngDevMode ? { debugName: "grid" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
222
+ /**
223
+ * Filter applied to items against the input query (only when {@link mode} is `'list'` / `'both'`).
224
+ * - `undefined` (default): locale-aware "contains" via {@link useFilter};
225
+ * - a function: custom matching;
226
+ * - `null`: built-in filtering disabled (the consumer controls which items exist).
227
+ */
228
+ this.filter = input(undefined, ...(ngDevMode ? [{ debugName: "filter" }] : /* istanbul ignore next */ []));
229
+ /** Maximum number of matching items to show. `-1` (default) means no limit. */
230
+ this.limit = input(-1, { ...(ngDevMode ? { debugName: "limit" } : /* istanbul ignore next */ {}), transform: numberAttribute });
231
+ /**
232
+ * The full set of item values, used as the source of truth for filtering and navigation in
233
+ * {@link virtualized} mode (where only a window of `RdxAutocompleteItem` is mounted).
234
+ */
235
+ this.items = input(...(ngDevMode ? [undefined, { debugName: "items" }] : /* istanbul ignore next */ []));
236
+ /** Whether the list is externally virtualized (navigation runs over {@link items} by index). */
237
+ this.virtualized = input(false, { ...(ngDevMode ? { debugName: "virtualized" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
238
+ /** How item values are compared for equality (function or object key). */
239
+ this.by = input(...(ngDevMode ? [undefined, { debugName: "by" }] : /* istanbul ignore next */ []));
240
+ /** Converts an item value to its string label (filter text + input text on selection). */
241
+ this.itemToStringValue = input(...(ngDevMode ? [undefined, { debugName: "itemToStringValue" }] : /* istanbul ignore next */ []));
242
+ /** Emits when the input value changes (typing, selection, or clear), with the reason. */
243
+ this.onValueChange = output();
244
+ /** Emits when the popup opens or closes. */
245
+ this.onOpenChange = output();
246
+ /** Emits as the highlight moves, with the item's value, its index in {@link filteredItems}, and the reason. */
247
+ this.onItemHighlighted = output();
248
+ /** Emits after the open/close transition (including any exit animation) finishes. */
249
+ this.onOpenChangeComplete = output();
250
+ this.transition = useTransitionStatus((open) => this.onOpenChangeComplete.emit(open));
251
+ /** Open/close transition phase, for `data-starting-style` / `data-ending-style`. */
252
+ this.transitionStatus = this.transition.status;
253
+ /** Registers the popup element whose animation determines transition completion. */
254
+ this.registerTransitionElement = this.transition.registerElement;
255
+ this.listId = injectId('rdx-autocomplete-list-');
256
+ this.labelId = signal(undefined, ...(ngDevMode ? [{ debugName: "labelId" }] : /* istanbul ignore next */ []));
257
+ this.inputElement = signal(null, ...(ngDevMode ? [{ debugName: "inputElement" }] : /* istanbul ignore next */ []));
258
+ /** Constant signals exposed to the combobox context (autocomplete is always single-value). */
259
+ this.alwaysFalse = signal(false, ...(ngDevMode ? [{ debugName: "alwaysFalse" }] : /* istanbul ignore next */ []));
260
+ this.noneMode = signal('none', ...(ngDevMode ? [{ debugName: "noneMode" }] : /* istanbul ignore next */ []));
261
+ this.cvaDisabled = signal(false, ...(ngDevMode ? [{ debugName: "cvaDisabled" }] : /* istanbul ignore next */ []));
262
+ this.disabledState = computed(() => this.disabled() || this.cvaDisabled(), ...(ngDevMode ? [{ debugName: "disabledState" }] : /* istanbul ignore next */ []));
263
+ this.requiredState = computed(() => this.required(), ...(ngDevMode ? [{ debugName: "requiredState" }] : /* istanbul ignore next */ []));
264
+ this.defaultFilter = useFilter();
265
+ /** Whether built-in filtering applies in the current mode. */
266
+ this.filteringMode = computed(() => this.mode() === 'list' || this.mode() === 'both', ...(ngDevMode ? [{ debugName: "filteringMode" }] : /* istanbul ignore next */ []));
267
+ /** Whether inline completion applies in the current mode. */
268
+ this.inlineMode = computed(() => this.mode() === 'both' || this.mode() === 'inline', ...(ngDevMode ? [{ debugName: "inlineMode" }] : /* istanbul ignore next */ []));
269
+ /**
270
+ * Whether the input text is a fresh user query rather than a committed selection's label. While
271
+ * `false` (just opened, or showing a committed selection), the list is unfiltered so the user can
272
+ * browse; it flips `true` on the first keystroke.
273
+ */
274
+ this.typed = signal(false, ...(ngDevMode ? [{ debugName: "typed" }] : /* istanbul ignore next */ []));
275
+ /** The text the user actually typed, used as the filter query. */
276
+ this.query = computed(() => (this.typed() ? (this.value() ?? '') : ''), ...(ngDevMode ? [{ debugName: "query" }] : /* istanbul ignore next */ []));
277
+ /** Transient inline-completion preview (the active item's label), or `null`. */
278
+ this.inlinePreview = signal(null, ...(ngDevMode ? [{ debugName: "inlinePreview" }] : /* istanbul ignore next */ []));
279
+ /** What the input element displays: the inline preview if any, else the committed value. */
280
+ this.displayValue = computed(() => this.inlinePreview() ?? this.value() ?? '', ...(ngDevMode ? [{ debugName: "displayValue" }] : /* istanbul ignore next */ []));
281
+ /** Suppresses inline completion for the current edit (set while a delete key is pressed). */
282
+ this.suppressInline = false;
283
+ this._items = signal([], ...(ngDevMode ? [{ debugName: "_items" }] : /* istanbul ignore next */ []));
284
+ /** Registered items, sorted into DOM order. */
285
+ this.orderedItems = computed(() => [...this._items()].sort((a, b) => domOrder(a.element, b.element)), ...(ngDevMode ? [{ debugName: "orderedItems" }] : /* istanbul ignore next */ []));
286
+ /** Matching items in DOM order, capped at `limit`. The set of items the list shows. */
287
+ this.visibleItems = computed(() => {
288
+ const matching = this.orderedItems().filter((item) => this.matchesFilter(item));
289
+ const limit = this.limit();
290
+ return limit >= 0 ? matching.slice(0, limit) : matching;
291
+ }, ...(ngDevMode ? [{ debugName: "visibleItems" }] : /* istanbul ignore next */ []));
292
+ this.visibleSet = computed(() => new Set(this.visibleItems()), ...(ngDevMode ? [{ debugName: "visibleSet" }] : /* istanbul ignore next */ []));
293
+ /** The filtered item values an external virtualizer should render. */
294
+ this.filteredItems = computed(() => {
295
+ const data = this.items();
296
+ if (data === undefined) {
297
+ return this.visibleItems().map((item) => item.value());
298
+ }
299
+ const limit = this.limit();
300
+ const cap = (arr) => (limit >= 0 ? arr.slice(0, limit) : arr);
301
+ if (!this.filteringMode()) {
302
+ return cap(data);
303
+ }
304
+ const filter = this.filter();
305
+ if (filter === null) {
306
+ return cap(data);
307
+ }
308
+ const query = this.query();
309
+ if (!query) {
310
+ return cap(data);
311
+ }
312
+ const matcher = filter ?? this.defaultFilter.contains;
313
+ return cap(data.filter((value) => matcher(this.textFor(value), query, value)));
314
+ }, ...(ngDevMode ? [{ debugName: "filteredItems" }] : /* istanbul ignore next */ []));
315
+ this.visibleCount = computed(() => this.virtualized() ? this.filteredItems().length : this.visibleItems().length, ...(ngDevMode ? [{ debugName: "visibleCount" }] : /* istanbul ignore next */ []));
316
+ this.highlight = useListHighlight({
317
+ items: this.orderedItems,
318
+ isNavigable: (item) => this.isVisible(item) && !item.disabled(),
319
+ getId: (item) => item.id,
320
+ loop: this.loopFocus,
321
+ injector: this.injector
322
+ });
323
+ this.highlightedItem = this.highlight.highlightedItem;
324
+ /** Highlighted index into {@link filteredItems} in virtualized mode (`-1` when cleared). */
325
+ this.highlightedIndex = signal(-1, ...(ngDevMode ? [{ debugName: "highlightedIndex" }] : /* istanbul ignore next */ []));
326
+ /** Why the highlight last moved; read when emitting {@link onItemHighlighted}. */
327
+ this.highlightReason = signal('none', ...(ngDevMode ? [{ debugName: "highlightReason" }] : /* istanbul ignore next */ []));
328
+ this.activeId = computed(() => {
329
+ if (this.virtualized()) {
330
+ const index = this.highlightedIndex();
331
+ return index >= 0 ? this.itemId(index) : undefined;
332
+ }
333
+ return this.highlight.activeId();
334
+ }, ...(ngDevMode ? [{ debugName: "activeId" }] : /* istanbul ignore next */ []));
335
+ /**
336
+ * What to highlight once the list has mounted (items register asynchronously after opening):
337
+ * an end edge, or `'first-match'` (the first item whose label starts with the query — used by
338
+ * auto-highlight so inline completion lands on a real prefix match even when the list is static).
339
+ */
340
+ this.pendingHighlightEdge = signal(null, ...(ngDevMode ? [{ debugName: "pendingHighlightEdge" }] : /* istanbul ignore next */ []));
341
+ this.keyboardActive = false;
342
+ /** The trigger element, used as a focus fallback when the input lives inside the popup. */
343
+ this.triggerElement = null;
344
+ // Apply uncontrolled defaults once.
345
+ effect(() => {
346
+ const initial = this.defaultValue();
347
+ if (initial !== undefined && untracked(this.value) === '') {
348
+ this.value.set(initial);
349
+ }
350
+ });
351
+ effect(() => {
352
+ if (untracked(this.open) === false && this.defaultOpen()) {
353
+ this.open.set(true);
354
+ }
355
+ });
356
+ // Emit open changes and drive the open/close transition (skip the initial run).
357
+ let previousOpen = untracked(this.open);
358
+ effect(() => {
359
+ const open = this.open();
360
+ if (open === previousOpen) {
361
+ return;
362
+ }
363
+ previousOpen = open;
364
+ untracked(() => {
365
+ this.onOpenChange.emit(open);
366
+ this.transition.start(open);
367
+ });
368
+ });
369
+ // Emit highlight changes (skip the initial run).
370
+ let highlightInitialized = false;
371
+ effect(() => {
372
+ const item = this.highlightedItem();
373
+ const index = this.highlightedIndex();
374
+ if (!highlightInitialized) {
375
+ highlightInitialized = true;
376
+ return;
377
+ }
378
+ untracked(() => {
379
+ const reason = this.highlightReason();
380
+ if (this.virtualized()) {
381
+ const value = index >= 0 ? (this.filteredItems()[index] ?? null) : null;
382
+ this.onItemHighlighted.emit({ value, index, reason });
383
+ }
384
+ else {
385
+ const value = item ? item.value() : null;
386
+ const itemIndex = item ? this.visibleItems().indexOf(item) : -1;
387
+ this.onItemHighlighted.emit({ value, index: itemIndex, reason });
388
+ }
389
+ });
390
+ });
391
+ // Inline completion: mirror the active item's label into the input (with the completed suffix
392
+ // selected by the input directive). Recomputes whenever the highlight or query changes.
393
+ effect(() => {
394
+ const item = this.highlightedItem();
395
+ const query = this.query();
396
+ const reason = this.highlightReason();
397
+ untracked(() => this.recomputeInlinePreview(item, query, reason));
398
+ });
399
+ // Apply a deferred open-edge highlight once items (DOM refs) or filtered data have registered.
400
+ effect(() => {
401
+ const edge = this.pendingHighlightEdge();
402
+ const count = this.virtualized() ? this.filteredItems().length : this.orderedItems().length;
403
+ if (!this.open() || edge === null || count === 0) {
404
+ return;
405
+ }
406
+ untracked(() => {
407
+ this.highlightReason.set('none');
408
+ if (this.virtualized()) {
409
+ this.highlightedIndex.set(this.resolveVirtualizedEdge(edge, count));
410
+ }
411
+ else if (edge === 'last') {
412
+ this.highlight.last();
413
+ }
414
+ else if (edge === 'first-match') {
415
+ this.highlight.set(this.firstMatchItem() ?? this.firstVisibleNavigable());
416
+ }
417
+ else {
418
+ this.highlight.first();
419
+ }
420
+ this.pendingHighlightEdge.set(null);
421
+ });
422
+ });
423
+ // autoHighlight 'always': keep the first navigable item highlighted whenever the popup is open.
424
+ effect(() => {
425
+ this.orderedItems();
426
+ this.visibleCount();
427
+ if (this.autoHighlightMode() === 'always' && this.open()) {
428
+ untracked(() => {
429
+ if (this.virtualized()) {
430
+ const length = this.filteredItems().length;
431
+ const index = this.highlightedIndex();
432
+ if ((index < 0 || index >= length) && length > 0) {
433
+ this.highlightReason.set('none');
434
+ this.highlightedIndex.set(0);
435
+ }
436
+ }
437
+ else if (this.highlightedItem() === null) {
438
+ this.highlightReason.set('none');
439
+ this.highlight.first();
440
+ }
441
+ });
442
+ }
443
+ });
444
+ // Virtualized self-heal: clear a highlight that filtering pushed out of range.
445
+ effect(() => {
446
+ if (!this.virtualized()) {
447
+ return;
448
+ }
449
+ const length = this.filteredItems().length;
450
+ untracked(() => {
451
+ const index = this.highlightedIndex();
452
+ if (index >= length && index !== -1) {
453
+ this.highlightReason.set('none');
454
+ this.highlightedIndex.set(-1);
455
+ }
456
+ });
457
+ });
458
+ // Virtualized object values can't be labelled from the DOM — warn once in dev.
459
+ if (isDevMode()) {
460
+ let warned = false;
461
+ effect(() => {
462
+ if (warned || !this.virtualized() || this.itemToStringValue()) {
463
+ return;
464
+ }
465
+ if (this.items()?.some((value) => value !== null && typeof value === 'object')) {
466
+ warned = true;
467
+ console.warn('[rdxAutocompleteRoot] `virtualized` with object item values needs `itemToStringValue` ' +
468
+ 'to render correct labels; falling back to a generic label.');
469
+ }
470
+ });
471
+ }
472
+ }
473
+ recomputeInlinePreview(item, query, reason) {
474
+ // Pointer hover must not rewrite the input (matches Base UI); only typing / keyboard nav complete it.
475
+ if (!this.inlineMode() || this.suppressInline || !item || reason === 'pointer') {
476
+ this.inlinePreview.set(null);
477
+ return;
478
+ }
479
+ const label = item.textValue();
480
+ if (label && query && label.toLowerCase().startsWith(query.toLowerCase())) {
481
+ // Type-ahead: keep the typed prefix (preserving its casing) and complete the rest.
482
+ this.inlinePreview.set(query + label.slice(query.length));
483
+ return;
484
+ }
485
+ // Keyboard navigation to an item that doesn't prefix-match the query: show its full label so the
486
+ // input reflects the highlighted option. Typing (reason 'none') never jumps to a non-prefix label.
487
+ if (reason === 'keyboard' && label) {
488
+ this.inlinePreview.set(label);
489
+ return;
490
+ }
491
+ this.inlinePreview.set(null);
492
+ }
493
+ setSuppressInline(value) {
494
+ this.suppressInline = value;
495
+ }
496
+ /** Opens the popup for browsing (resets the query to "pristine" and selects the input text). */
497
+ openForBrowse() {
498
+ if (!this.open()) {
499
+ this.typed.set(false);
500
+ }
501
+ this.setOpen(true);
502
+ this.selectInputText();
503
+ if (this.autoHighlightMode() === 'always') {
504
+ this.pendingHighlightEdge.set('first');
505
+ }
506
+ }
507
+ /** Opens the popup and highlights the given edge once the list mounts. */
508
+ openAndHighlight(edge) {
509
+ if (!this.open()) {
510
+ this.typed.set(false);
511
+ }
512
+ this.setOpen(true);
513
+ this.selectInputText();
514
+ this.pendingHighlightEdge.set(edge);
515
+ }
516
+ /** Whether the item matches the active query (ignores the `limit` cap). */
517
+ matchesFilter(item) {
518
+ if (!this.filteringMode()) {
519
+ return true;
520
+ }
521
+ const filter = this.filter();
522
+ if (filter === null) {
523
+ return true;
524
+ }
525
+ const query = this.query();
526
+ const matcher = filter ?? this.defaultFilter.contains;
527
+ return matcher(item.textValue(), query, item.value());
528
+ }
529
+ /** Whether the item is shown in the list (matches the query and is within `limit`). */
530
+ isVisible(item) {
531
+ return this.visibleSet().has(item);
532
+ }
533
+ /** The first visible, navigable item whose label starts with the query (for inline completion). */
534
+ firstMatchItem() {
535
+ const query = this.query();
536
+ if (!query) {
537
+ return null;
538
+ }
539
+ const lower = query.toLowerCase();
540
+ return (this.visibleItems().find((item) => !item.disabled() && item.textValue().toLowerCase().startsWith(lower)) ??
541
+ null);
542
+ }
543
+ /** The first visible, navigable item (auto-highlight fallback when no prefix match exists). */
544
+ firstVisibleNavigable() {
545
+ return this.visibleItems().find((item) => !item.disabled()) ?? null;
546
+ }
547
+ /** Resolves a pending edge to a virtualized index. */
548
+ resolveVirtualizedEdge(edge, count) {
549
+ if (edge === 'last') {
550
+ return count - 1;
551
+ }
552
+ if (edge === 'first-match') {
553
+ const query = this.query();
554
+ if (query) {
555
+ const lower = query.toLowerCase();
556
+ const index = this.filteredItems().findIndex((value) => this.textFor(value).toLowerCase().startsWith(lower));
557
+ if (index >= 0) {
558
+ return index;
559
+ }
560
+ }
561
+ }
562
+ return 0;
563
+ }
564
+ isKeyboardActive() {
565
+ return this.keyboardActive;
566
+ }
567
+ setKeyboardActive(value) {
568
+ this.keyboardActive = value;
569
+ }
570
+ /** Whether the item's value/label matches the current input value (combobox context contract). */
571
+ isSelectedValue(value) {
572
+ const current = this.value();
573
+ if (!current) {
574
+ return false;
575
+ }
576
+ return value === current || isItemEqualToValue(value, current, this.by());
577
+ }
578
+ registerItem(item) {
579
+ this._items.update((items) => [...items, item]);
580
+ }
581
+ unregisterItem(item) {
582
+ this._items.update((items) => items.filter((i) => i !== item));
583
+ }
584
+ setOpen(open) {
585
+ if (this.disabledState() || this.readOnly()) {
586
+ return;
587
+ }
588
+ this.open.set(open);
589
+ }
590
+ closePopup(revert = true) {
591
+ if (!this.open()) {
592
+ return;
593
+ }
594
+ this.open.set(false);
595
+ this.clearHighlightState();
596
+ this.inlinePreview.set(null);
597
+ if (revert) {
598
+ this.typed.set(false);
599
+ }
600
+ this.markAsTouched();
601
+ }
602
+ /** Updates the input text from user typing (marks it a fresh query, emits change). */
603
+ setQuery(value) {
604
+ this.commitValue(value, 'input-change');
605
+ this.typed.set(true);
606
+ // Inline modes (`both` / `inline`) implicitly highlight the first prefix match so the input can
607
+ // be inline-completed even without an explicit `autoHighlight`.
608
+ if (this.autoHighlightMode() !== 'off' || (this.inlineMode() && value.length > 0)) {
609
+ this.pendingHighlightEdge.set('first-match');
610
+ }
611
+ }
612
+ /** Selects all input text so the next keystroke replaces a committed label. */
613
+ selectInputText() {
614
+ this.inputElement()?.select();
615
+ }
616
+ labelFor(value) {
617
+ const custom = this.itemToStringValue();
618
+ if (custom) {
619
+ return custom(value);
620
+ }
621
+ const item = this.orderedItems().find((i) => isItemEqualToValue(i.value(), value, this.by()));
622
+ return item ? item.textValue() : itemToStringLabel(value);
623
+ }
624
+ /** Label text for a raw item value (virtualized mode, no DOM element to read from). */
625
+ textFor(value) {
626
+ const custom = this.itemToStringValue();
627
+ return custom ? custom(value) : itemToStringLabel(value);
628
+ }
629
+ /** Deterministic id for the item at `index` in virtualized mode (matches `aria-activedescendant`). */
630
+ itemId(index) {
631
+ return `${this.listId}-item-${index}`;
632
+ }
633
+ handleSelect(item) {
634
+ if (this.disabledState() || this.readOnly() || item.disabled()) {
635
+ return;
636
+ }
637
+ this.commitSelection(item.textValue() || this.labelFor(item.value()));
638
+ }
639
+ /** Selects the filtered item at `index` (virtualized mode). */
640
+ selectIndex(index) {
641
+ if (this.disabledState() || this.readOnly()) {
642
+ return;
643
+ }
644
+ const value = this.filteredItems()[index];
645
+ if (value === undefined) {
646
+ return;
647
+ }
648
+ this.commitSelection(this.labelFor(value));
649
+ }
650
+ /** Commits a selection: the input value becomes the item's label, the popup closes. */
651
+ commitSelection(label) {
652
+ this.inlinePreview.set(null);
653
+ this.commitValue(label, 'item-press');
654
+ this.typed.set(false);
655
+ this.open.set(false);
656
+ this.clearHighlightState();
657
+ this.restoreFocusAfterSelect();
658
+ this.maybeSubmit();
659
+ }
660
+ maybeSubmit() {
661
+ if (this.submitOnItemClick()) {
662
+ this.inputElement()?.form?.requestSubmit?.();
663
+ }
664
+ }
665
+ selectHighlighted() {
666
+ if (this.virtualized()) {
667
+ const index = this.highlightedIndex();
668
+ if (index >= 0) {
669
+ this.selectIndex(index);
670
+ }
671
+ return;
672
+ }
673
+ const item = this.highlightedItem();
674
+ if (item) {
675
+ this.handleSelect(item);
676
+ }
677
+ }
678
+ // --- Highlight navigation facade (mode-aware: index-based when virtualized, grid-aware, else DOM-ref) ---
679
+ moveDown() {
680
+ this.highlightReason.set('keyboard');
681
+ if (this.virtualized()) {
682
+ this.stepIndex(1);
683
+ }
684
+ else if (this.grid()) {
685
+ this.gridVertical(1);
686
+ }
687
+ else {
688
+ this.highlight.next();
689
+ }
690
+ }
691
+ moveUp() {
692
+ this.highlightReason.set('keyboard');
693
+ if (this.virtualized()) {
694
+ this.stepIndex(-1);
695
+ }
696
+ else if (this.grid()) {
697
+ this.gridVertical(-1);
698
+ }
699
+ else {
700
+ this.highlight.previous();
701
+ }
702
+ }
703
+ /** Grid: move to the next cell in DOM order. Non-grid: no-op (caret movement). */
704
+ moveRight() {
705
+ if (!this.grid() || this.virtualized()) {
706
+ return;
707
+ }
708
+ this.highlightReason.set('keyboard');
709
+ this.highlight.next();
710
+ }
711
+ moveLeft() {
712
+ if (!this.grid() || this.virtualized()) {
713
+ return;
714
+ }
715
+ this.highlightReason.set('keyboard');
716
+ this.highlight.previous();
717
+ }
718
+ highlightFirst(reason = 'keyboard') {
719
+ this.highlightReason.set(reason);
720
+ if (this.virtualized()) {
721
+ this.highlightedIndex.set(this.filteredItems().length > 0 ? 0 : -1);
722
+ }
723
+ else {
724
+ this.highlight.first();
725
+ }
726
+ }
727
+ highlightLast(reason = 'keyboard') {
728
+ this.highlightReason.set(reason);
729
+ if (this.virtualized()) {
730
+ const length = this.filteredItems().length;
731
+ this.highlightedIndex.set(length > 0 ? length - 1 : -1);
732
+ }
733
+ else {
734
+ this.highlight.last();
735
+ }
736
+ }
737
+ highlightIndex(index, reason) {
738
+ if (index < 0 || index >= this.filteredItems().length) {
739
+ return;
740
+ }
741
+ this.highlightReason.set(reason);
742
+ this.highlightedIndex.set(index);
743
+ }
744
+ setHighlight(item, reason) {
745
+ this.highlightReason.set(reason);
746
+ this.highlight.set(item);
747
+ }
748
+ clearHighlightState() {
749
+ this.highlight.clear();
750
+ this.highlightedIndex.set(-1);
751
+ }
752
+ stepIndex(direction) {
753
+ const length = this.filteredItems().length;
754
+ if (length === 0) {
755
+ this.highlightedIndex.set(-1);
756
+ return;
757
+ }
758
+ const current = this.highlightedIndex();
759
+ if (current < 0) {
760
+ this.highlightedIndex.set(direction === 1 ? 0 : length - 1);
761
+ return;
762
+ }
763
+ let next = current + direction;
764
+ const loop = this.loopFocus();
765
+ if (next < 0) {
766
+ next = loop ? length - 1 : 0;
767
+ }
768
+ else if (next >= length) {
769
+ next = loop ? 0 : length - 1;
770
+ }
771
+ this.highlightedIndex.set(next);
772
+ }
773
+ /** Grid vertical move: keep the column index, jump to the adjacent row. */
774
+ gridVertical(direction) {
775
+ const rows = this.gridRows();
776
+ if (rows.length === 0) {
777
+ return;
778
+ }
779
+ const current = this.highlightedItem();
780
+ if (!current) {
781
+ const row = direction === 1 ? rows[0] : rows[rows.length - 1];
782
+ this.highlight.set(row[0] ?? null);
783
+ return;
784
+ }
785
+ let rowIndex = rows.findIndex((row) => row.includes(current));
786
+ const col = rowIndex >= 0 ? rows[rowIndex].indexOf(current) : 0;
787
+ const loop = this.loopFocus();
788
+ rowIndex += direction;
789
+ if (rowIndex < 0) {
790
+ rowIndex = loop ? rows.length - 1 : 0;
791
+ }
792
+ else if (rowIndex >= rows.length) {
793
+ rowIndex = loop ? 0 : rows.length - 1;
794
+ }
795
+ const targetRow = rows[rowIndex];
796
+ this.highlight.set(targetRow[Math.min(col, targetRow.length - 1)] ?? null);
797
+ }
798
+ /** Visible items grouped into rows by their nearest `[rdxAutocompleteRow]` ancestor (DOM order). */
799
+ gridRows() {
800
+ const rows = new Map();
801
+ for (const item of this.visibleItems()) {
802
+ const key = item.element.closest('[rdxAutocompleteRow]');
803
+ const bucket = rows.get(key);
804
+ if (bucket) {
805
+ bucket.push(item);
806
+ }
807
+ else {
808
+ rows.set(key, [item]);
809
+ }
810
+ }
811
+ return [...rows.values()];
812
+ }
813
+ clearValue() {
814
+ this.commitValue('', 'input-clear');
815
+ this.typed.set(true);
816
+ this.inlinePreview.set(null);
817
+ this.focusInput();
818
+ }
819
+ focusInput() {
820
+ this.inputElement()?.focus();
821
+ }
822
+ restoreFocusAfterSelect() {
823
+ const input = this.inputElement();
824
+ if (input && !input.closest('[rdxAutocompletePopup]')) {
825
+ input.focus();
826
+ }
827
+ else {
828
+ this.triggerElement?.focus();
829
+ }
830
+ }
831
+ markAsTouched() {
832
+ this.onTouched?.();
833
+ }
834
+ commitValue(value, reason) {
835
+ this.value.set(value);
836
+ this.onValueChange.emit({ value, reason });
837
+ this.onChange?.(value);
838
+ }
839
+ // ControlValueAccessor (the form value is the input string)
840
+ writeValue(value) {
841
+ untracked(() => this.value.set(value ?? ''));
842
+ }
843
+ registerOnChange(fn) {
844
+ this.onChange = fn;
845
+ }
846
+ registerOnTouched(fn) {
847
+ this.onTouched = fn;
848
+ }
849
+ setDisabledState(isDisabled) {
850
+ this.cvaDisabled.set(isDisabled);
851
+ }
852
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteRoot, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
853
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxAutocompleteRoot, isStandalone: true, selector: "[rdxAutocompleteRoot]", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, defaultValue: { classPropertyName: "defaultValue", publicName: "defaultValue", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, defaultOpen: { classPropertyName: "defaultOpen", publicName: "defaultOpen", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, dir: { classPropertyName: "dir", publicName: "dir", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readOnly: { classPropertyName: "readOnly", publicName: "readOnly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, loopFocus: { classPropertyName: "loopFocus", publicName: "loopFocus", isSignal: true, isRequired: false, transformFunction: null }, autoHighlight: { classPropertyName: "autoHighlight", publicName: "autoHighlight", isSignal: true, isRequired: false, transformFunction: null }, highlightItemOnHover: { classPropertyName: "highlightItemOnHover", publicName: "highlightItemOnHover", isSignal: true, isRequired: false, transformFunction: null }, keepHighlight: { classPropertyName: "keepHighlight", publicName: "keepHighlight", isSignal: true, isRequired: false, transformFunction: null }, openOnInputClick: { classPropertyName: "openOnInputClick", publicName: "openOnInputClick", isSignal: true, isRequired: false, transformFunction: null }, modal: { classPropertyName: "modal", publicName: "modal", isSignal: true, isRequired: false, transformFunction: null }, submitOnItemClick: { classPropertyName: "submitOnItemClick", publicName: "submitOnItemClick", isSignal: true, isRequired: false, transformFunction: null }, grid: { classPropertyName: "grid", publicName: "grid", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, limit: { classPropertyName: "limit", publicName: "limit", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, virtualized: { classPropertyName: "virtualized", publicName: "virtualized", isSignal: true, isRequired: false, transformFunction: null }, by: { classPropertyName: "by", publicName: "by", isSignal: true, isRequired: false, transformFunction: null }, itemToStringValue: { classPropertyName: "itemToStringValue", publicName: "itemToStringValue", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", open: "openChange", onValueChange: "onValueChange", onOpenChange: "onOpenChange", onItemHighlighted: "onItemHighlighted", onOpenChangeComplete: "onOpenChangeComplete" }, host: { properties: { "attr.data-disabled": "disabledState() ? \"\" : undefined" } }, providers: [
854
+ provideComboboxRootContext(context),
855
+ { provide: NG_VALUE_ACCESSOR, useExisting: RdxAutocompleteRoot, multi: true }
856
+ ], exportAs: ["rdxAutocompleteRoot"], hostDirectives: [{ directive: i1$1.RdxPopper }], ngImport: i0 }); }
857
+ }
858
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteRoot, decorators: [{
859
+ type: Directive,
860
+ args: [{
861
+ selector: '[rdxAutocompleteRoot]',
862
+ exportAs: 'rdxAutocompleteRoot',
863
+ providers: [
864
+ provideComboboxRootContext(context),
865
+ { provide: NG_VALUE_ACCESSOR, useExisting: RdxAutocompleteRoot, multi: true }
866
+ ],
867
+ hostDirectives: [RdxPopper],
868
+ host: {
869
+ '[attr.data-disabled]': 'disabledState() ? "" : undefined'
870
+ }
871
+ }]
872
+ }], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], defaultValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValue", required: false }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], defaultOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultOpen", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], dir: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readOnly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], loopFocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "loopFocus", required: false }] }], autoHighlight: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoHighlight", required: false }] }], highlightItemOnHover: [{ type: i0.Input, args: [{ isSignal: true, alias: "highlightItemOnHover", required: false }] }], keepHighlight: [{ type: i0.Input, args: [{ isSignal: true, alias: "keepHighlight", required: false }] }], openOnInputClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "openOnInputClick", required: false }] }], modal: [{ type: i0.Input, args: [{ isSignal: true, alias: "modal", required: false }] }], submitOnItemClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "submitOnItemClick", required: false }] }], grid: [{ type: i0.Input, args: [{ isSignal: true, alias: "grid", required: false }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }], limit: [{ type: i0.Input, args: [{ isSignal: true, alias: "limit", required: false }] }], items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], virtualized: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualized", required: false }] }], by: [{ type: i0.Input, args: [{ isSignal: true, alias: "by", required: false }] }], itemToStringValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemToStringValue", required: false }] }], onValueChange: [{ type: i0.Output, args: ["onValueChange"] }], onOpenChange: [{ type: i0.Output, args: ["onOpenChange"] }], onItemHighlighted: [{ type: i0.Output, args: ["onItemHighlighted"] }], onOpenChangeComplete: [{ type: i0.Output, args: ["onOpenChangeComplete"] }] } });
873
+ /** DOM-order comparator for two elements (precedes → -1, follows → 1). */
874
+ function domOrder(a, b) {
875
+ const position = a.compareDocumentPosition(b);
876
+ if (position & Node.DOCUMENT_POSITION_FOLLOWING) {
877
+ return -1;
878
+ }
879
+ if (position & Node.DOCUMENT_POSITION_PRECEDING) {
880
+ return 1;
881
+ }
882
+ return 0;
883
+ }
884
+
885
+ /**
886
+ * Clears the input value. Hidden when there is nothing to clear.
887
+ *
888
+ * @group Components
889
+ */
890
+ class RdxAutocompleteClear {
891
+ constructor() {
892
+ this.root = inject(RdxAutocompleteRoot);
893
+ this.isEmpty = computed(() => !this.root.value(), ...(ngDevMode ? [{ debugName: "isEmpty" }] : /* istanbul ignore next */ []));
894
+ }
895
+ onClick() {
896
+ this.root.clearValue();
897
+ }
898
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteClear, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
899
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxAutocompleteClear, isStandalone: true, selector: "button[rdxAutocompleteClear]", host: { attributes: { "type": "button", "tabindex": "-1", "aria-label": "Clear" }, listeners: { "click": "onClick()" }, properties: { "hidden": "isEmpty()", "attr.disabled": "root.disabledState() ? \"\" : undefined" } }, exportAs: ["rdxAutocompleteClear"], hostDirectives: [{ directive: i2.RdxDismissableLayerBranch }], ngImport: i0 }); }
900
+ }
901
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteClear, decorators: [{
902
+ type: Directive,
903
+ args: [{
904
+ selector: 'button[rdxAutocompleteClear]',
905
+ exportAs: 'rdxAutocompleteClear',
906
+ hostDirectives: [RdxDismissableLayerBranch],
907
+ host: {
908
+ type: 'button',
909
+ tabindex: '-1',
910
+ 'aria-label': 'Clear',
911
+ '[hidden]': 'isEmpty()',
912
+ '[attr.disabled]': 'root.disabledState() ? "" : undefined',
913
+ '(click)': 'onClick()'
914
+ }
915
+ }]
916
+ }] });
917
+
918
+ /**
919
+ * Shown only when no items match the current query. Reuses the combobox empty part.
920
+ *
921
+ * @group Components
922
+ */
923
+ class RdxAutocompleteEmpty {
924
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteEmpty, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
925
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxAutocompleteEmpty, isStandalone: true, selector: "[rdxAutocompleteEmpty]", exportAs: ["rdxAutocompleteEmpty"], hostDirectives: [{ directive: i1.RdxComboboxEmpty }], ngImport: i0 }); }
926
+ }
927
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteEmpty, decorators: [{
928
+ type: Directive,
929
+ args: [{
930
+ selector: '[rdxAutocompleteEmpty]',
931
+ exportAs: 'rdxAutocompleteEmpty',
932
+ hostDirectives: [RdxComboboxEmpty]
933
+ }]
934
+ }] });
935
+
936
+ /**
937
+ * Groups related options under a shared label. Hides itself when all of its items are filtered out.
938
+ * Reuses the combobox group (and exposes the combobox group context for the label + items).
939
+ *
940
+ * @group Components
941
+ */
942
+ class RdxAutocompleteGroup {
943
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteGroup, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
944
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxAutocompleteGroup, isStandalone: true, selector: "[rdxAutocompleteGroup]", exportAs: ["rdxAutocompleteGroup"], hostDirectives: [{ directive: i1.RdxComboboxGroup }], ngImport: i0 }); }
945
+ }
946
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteGroup, decorators: [{
947
+ type: Directive,
948
+ args: [{
949
+ selector: '[rdxAutocompleteGroup]',
950
+ exportAs: 'rdxAutocompleteGroup',
951
+ hostDirectives: [RdxComboboxGroup]
952
+ }]
953
+ }] });
954
+
955
+ /**
956
+ * Accessible label for a {@link RdxAutocompleteGroup}. Wires itself up via `aria-labelledby`. Reuses
957
+ * the combobox group label.
958
+ *
959
+ * @group Components
960
+ */
961
+ class RdxAutocompleteGroupLabel {
962
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteGroupLabel, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
963
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxAutocompleteGroupLabel, isStandalone: true, selector: "[rdxAutocompleteGroupLabel]", exportAs: ["rdxAutocompleteGroupLabel"], hostDirectives: [{ directive: i1.RdxComboboxGroupLabel }], ngImport: i0 }); }
964
+ }
965
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteGroupLabel, decorators: [{
966
+ type: Directive,
967
+ args: [{
968
+ selector: '[rdxAutocompleteGroupLabel]',
969
+ exportAs: 'rdxAutocompleteGroupLabel',
970
+ hostDirectives: [RdxComboboxGroupLabel]
971
+ }]
972
+ }] });
973
+
974
+ /**
975
+ * Decorative icon inside the trigger. Hidden from assistive technology. Reuses the combobox icon.
976
+ *
977
+ * @group Components
978
+ */
979
+ class RdxAutocompleteIcon {
980
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteIcon, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
981
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxAutocompleteIcon, isStandalone: true, selector: "[rdxAutocompleteIcon]", exportAs: ["rdxAutocompleteIcon"], hostDirectives: [{ directive: i1.RdxComboboxIcon }], ngImport: i0 }); }
982
+ }
983
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteIcon, decorators: [{
984
+ type: Directive,
985
+ args: [{
986
+ selector: '[rdxAutocompleteIcon]',
987
+ exportAs: 'rdxAutocompleteIcon',
988
+ hostDirectives: [RdxComboboxIcon]
989
+ }]
990
+ }] });
991
+
992
+ const attr$1 = (value) => (value ? '' : undefined);
993
+ /**
994
+ * The autocomplete text input. Holds DOM focus at all times; the highlighted option is referenced via
995
+ * `aria-activedescendant`. In `both` / `inline` modes it shows the active item's inline completion
996
+ * with the completed suffix selected. Integrates with Field for labeling and validation state.
997
+ *
998
+ * @group Components
999
+ */
1000
+ class RdxAutocompleteInput {
1001
+ constructor() {
1002
+ this.root = inject(RdxAutocompleteRoot);
1003
+ this.element = inject(ElementRef).nativeElement;
1004
+ this.fieldRootContext = injectFieldRootContext(true);
1005
+ /** The input id; Field labels and descriptions reference it for accessible relationships. */
1006
+ this.id = input(injectId('rdx-autocomplete-input-'), ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
1007
+ /** Marks the input as invalid independently of any Field state. */
1008
+ this.invalid = input(false, { ...(ngDevMode ? { debugName: "invalid" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1009
+ // Mirrors the configured mode (matches Base UI): 'list' | 'both' | 'inline' | 'none' — all valid
1010
+ // `aria-autocomplete` tokens. Must reflect the static mechanism, not the transient inline preview.
1011
+ this.ariaAutocomplete = computed(() => this.root.mode(), ...(ngDevMode ? [{ debugName: "ariaAutocomplete" }] : /* istanbul ignore next */ []));
1012
+ this.invalidState = computed(() => this.invalid() || Boolean(this.fieldRootContext?.invalidState()), ...(ngDevMode ? [{ debugName: "invalidState" }] : /* istanbul ignore next */ []));
1013
+ this.disabledState = computed(() => this.root.disabledState() || Boolean(this.fieldRootContext?.disabledState()), ...(ngDevMode ? [{ debugName: "disabledState" }] : /* istanbul ignore next */ []));
1014
+ this.requiredState = computed(() => this.root.requiredState() || Boolean(this.fieldRootContext?.requiredState()), ...(ngDevMode ? [{ debugName: "requiredState" }] : /* istanbul ignore next */ []));
1015
+ this.filledState = computed(() => Boolean(this.root.value()) || Boolean(this.fieldRootContext?.filledState()), ...(ngDevMode ? [{ debugName: "filledState" }] : /* istanbul ignore next */ []));
1016
+ this.focusedState = computed(() => Boolean(this.fieldRootContext?.focusedState()), ...(ngDevMode ? [{ debugName: "focusedState" }] : /* istanbul ignore next */ []));
1017
+ this.describedBy = computed(() => {
1018
+ if (!this.fieldRootContext) {
1019
+ return undefined;
1020
+ }
1021
+ const ids = [
1022
+ ...this.fieldRootContext.descriptionIds(),
1023
+ ...(this.fieldRootContext.invalidState() ? this.fieldRootContext.errorIds() : [])
1024
+ ];
1025
+ return ids.length ? ids.join(' ') : undefined;
1026
+ }, ...(ngDevMode ? [{ debugName: "describedBy" }] : /* istanbul ignore next */ []));
1027
+ /** Whether an IME composition is in progress (CJK). While composing, don't filter or select. */
1028
+ this.composing = false;
1029
+ this.dataAttr = attr$1;
1030
+ this.root.inputElement.set(this.element);
1031
+ afterNextRender(() => {
1032
+ this.fieldRootContext?.setControlId(this.id());
1033
+ });
1034
+ // Select the completed part of an inline preview so the next keystroke replaces it: the suffix
1035
+ // after the typed prefix when the label prefix-matches, otherwise the whole navigated label.
1036
+ afterRenderEffect(() => {
1037
+ const preview = this.root.inlinePreview();
1038
+ if (preview === null) {
1039
+ return;
1040
+ }
1041
+ const query = this.root.query();
1042
+ const start = query && preview.toLowerCase().startsWith(query.toLowerCase()) ? query.length : 0;
1043
+ this.element.setSelectionRange(start, preview.length);
1044
+ });
1045
+ inject(DestroyRef).onDestroy(() => {
1046
+ if (this.root.inputElement() === this.element) {
1047
+ this.root.inputElement.set(null);
1048
+ }
1049
+ });
1050
+ }
1051
+ onInput(event) {
1052
+ if (this.composing || event.isComposing) {
1053
+ return;
1054
+ }
1055
+ this.commitInput(event.target.value);
1056
+ }
1057
+ onCompositionEnd(event) {
1058
+ this.composing = false;
1059
+ this.commitInput(event.target.value);
1060
+ }
1061
+ commitInput(value) {
1062
+ if (!this.root.open()) {
1063
+ this.root.setOpen(true);
1064
+ }
1065
+ this.root.setQuery(value);
1066
+ }
1067
+ onClick() {
1068
+ if (this.root.openOnInputClick()) {
1069
+ this.root.openForBrowse();
1070
+ }
1071
+ }
1072
+ onFocus() {
1073
+ this.fieldRootContext?.setFocused(true);
1074
+ }
1075
+ onBlur() {
1076
+ this.fieldRootContext?.setFocused(false);
1077
+ this.fieldRootContext?.setTouched(true);
1078
+ }
1079
+ onKeydown(event) {
1080
+ if (event.isComposing || this.composing) {
1081
+ return;
1082
+ }
1083
+ // Backspace / Delete must never re-add an inline completion for the resulting edit.
1084
+ this.root.setSuppressInline(event.key === 'Backspace' || event.key === 'Delete');
1085
+ if (event.ctrlKey || event.metaKey || event.altKey || event.shiftKey) {
1086
+ return;
1087
+ }
1088
+ const open = this.root.open();
1089
+ switch (event.key) {
1090
+ case 'ArrowDown':
1091
+ event.preventDefault();
1092
+ this.root.setKeyboardActive(true);
1093
+ if (!open) {
1094
+ this.root.openAndHighlight('first');
1095
+ }
1096
+ else {
1097
+ this.root.moveDown();
1098
+ }
1099
+ break;
1100
+ case 'ArrowUp':
1101
+ event.preventDefault();
1102
+ this.root.setKeyboardActive(true);
1103
+ if (!open) {
1104
+ this.root.openAndHighlight('last');
1105
+ }
1106
+ else {
1107
+ this.root.moveUp();
1108
+ }
1109
+ break;
1110
+ case 'ArrowRight':
1111
+ if (open && this.root.grid()) {
1112
+ event.preventDefault();
1113
+ this.root.setKeyboardActive(true);
1114
+ this.root.moveRight();
1115
+ }
1116
+ break;
1117
+ case 'ArrowLeft':
1118
+ if (open && this.root.grid()) {
1119
+ event.preventDefault();
1120
+ this.root.setKeyboardActive(true);
1121
+ this.root.moveLeft();
1122
+ }
1123
+ break;
1124
+ case 'Enter':
1125
+ if (open) {
1126
+ const hasHighlight = this.root.virtualized()
1127
+ ? this.root.highlightedIndex() >= 0
1128
+ : this.root.highlightedItem() !== null;
1129
+ if (hasHighlight) {
1130
+ event.preventDefault();
1131
+ this.root.selectHighlighted();
1132
+ }
1133
+ else if (!this.root.inlineMode()) {
1134
+ // Non-inline: close and let native form submission proceed. Inline modes keep the
1135
+ // popup open on Enter without a highlight (matches Base UI).
1136
+ this.root.closePopup(true);
1137
+ }
1138
+ }
1139
+ break;
1140
+ case 'Escape':
1141
+ if (open) {
1142
+ event.preventDefault();
1143
+ this.root.closePopup(true);
1144
+ }
1145
+ break;
1146
+ case 'Tab':
1147
+ if (open) {
1148
+ this.root.closePopup(true);
1149
+ }
1150
+ break;
1151
+ }
1152
+ }
1153
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteInput, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1154
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxAutocompleteInput, isStandalone: true, selector: "input[rdxAutocompleteInput]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "combobox", "autocomplete": "off" }, listeners: { "input": "onInput($event)", "click": "onClick()", "focus": "onFocus()", "blur": "onBlur()", "keydown": "onKeydown($event)", "compositionstart": "composing = true", "compositionend": "onCompositionEnd($event)" }, properties: { "attr.aria-autocomplete": "ariaAutocomplete()", "attr.id": "id()", "attr.aria-expanded": "root.open()", "attr.aria-controls": "root.listId", "attr.aria-labelledby": "root.labelId()", "attr.aria-activedescendant": "root.activeId()", "attr.aria-describedby": "describedBy()", "attr.aria-invalid": "invalidState() ? \"true\" : undefined", "attr.aria-required": "requiredState() ? \"true\" : undefined", "attr.aria-disabled": "disabledState() ? \"true\" : undefined", "attr.disabled": "disabledState() ? \"\" : undefined", "attr.readonly": "root.readOnly() ? \"\" : undefined", "attr.required": "requiredState() ? \"\" : undefined", "value": "root.displayValue()", "attr.data-popup-open": "dataAttr(root.open())", "attr.data-list-empty": "dataAttr(root.visibleCount() === 0)", "attr.data-invalid": "dataAttr(invalidState())", "attr.data-valid": "dataAttr(!invalidState())", "attr.data-disabled": "dataAttr(disabledState())", "attr.data-required": "dataAttr(requiredState())", "attr.data-filled": "dataAttr(filledState())", "attr.data-focused": "dataAttr(focusedState())" } }, exportAs: ["rdxAutocompleteInput"], hostDirectives: [{ directive: i1$1.RdxPopperAnchor }, { directive: i2.RdxDismissableLayerBranch }], ngImport: i0 }); }
1155
+ }
1156
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteInput, decorators: [{
1157
+ type: Directive,
1158
+ args: [{
1159
+ selector: 'input[rdxAutocompleteInput]',
1160
+ exportAs: 'rdxAutocompleteInput',
1161
+ hostDirectives: [RdxPopperAnchor, RdxDismissableLayerBranch],
1162
+ host: {
1163
+ role: 'combobox',
1164
+ autocomplete: 'off',
1165
+ '[attr.aria-autocomplete]': 'ariaAutocomplete()',
1166
+ '[attr.id]': 'id()',
1167
+ '[attr.aria-expanded]': 'root.open()',
1168
+ '[attr.aria-controls]': 'root.listId',
1169
+ '[attr.aria-labelledby]': 'root.labelId()',
1170
+ '[attr.aria-activedescendant]': 'root.activeId()',
1171
+ '[attr.aria-describedby]': 'describedBy()',
1172
+ '[attr.aria-invalid]': 'invalidState() ? "true" : undefined',
1173
+ '[attr.aria-required]': 'requiredState() ? "true" : undefined',
1174
+ '[attr.aria-disabled]': 'disabledState() ? "true" : undefined',
1175
+ '[attr.disabled]': 'disabledState() ? "" : undefined',
1176
+ '[attr.readonly]': 'root.readOnly() ? "" : undefined',
1177
+ '[attr.required]': 'requiredState() ? "" : undefined',
1178
+ '[value]': 'root.displayValue()',
1179
+ '[attr.data-popup-open]': 'dataAttr(root.open())',
1180
+ '[attr.data-list-empty]': 'dataAttr(root.visibleCount() === 0)',
1181
+ '[attr.data-invalid]': 'dataAttr(invalidState())',
1182
+ '[attr.data-valid]': 'dataAttr(!invalidState())',
1183
+ '[attr.data-disabled]': 'dataAttr(disabledState())',
1184
+ '[attr.data-required]': 'dataAttr(requiredState())',
1185
+ '[attr.data-filled]': 'dataAttr(filledState())',
1186
+ '[attr.data-focused]': 'dataAttr(focusedState())',
1187
+ '(input)': 'onInput($event)',
1188
+ '(click)': 'onClick()',
1189
+ '(focus)': 'onFocus()',
1190
+ '(blur)': 'onBlur()',
1191
+ '(keydown)': 'onKeydown($event)',
1192
+ '(compositionstart)': 'composing = true',
1193
+ '(compositionend)': 'onCompositionEnd($event)'
1194
+ }
1195
+ }]
1196
+ }], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }] } });
1197
+
1198
+ const attr = (value) => (value ? '' : undefined);
1199
+ /**
1200
+ * Optional wrapper around the input and its adornments (icon, clear, trigger). Mirrors the input's
1201
+ * state via `data-*` so the whole group can be styled together (focus ring, disabled, etc.).
1202
+ *
1203
+ * @group Components
1204
+ */
1205
+ class RdxAutocompleteInputGroup {
1206
+ constructor() {
1207
+ this.root = inject(RdxAutocompleteRoot);
1208
+ this.dataAttr = attr;
1209
+ }
1210
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteInputGroup, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1211
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxAutocompleteInputGroup, isStandalone: true, selector: "[rdxAutocompleteInputGroup]", host: { properties: { "attr.data-popup-open": "dataAttr(root.open())", "attr.data-disabled": "dataAttr(root.disabledState())", "attr.data-required": "dataAttr(root.requiredState())", "attr.data-filled": "dataAttr(!!root.value())" } }, exportAs: ["rdxAutocompleteInputGroup"], ngImport: i0 }); }
1212
+ }
1213
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteInputGroup, decorators: [{
1214
+ type: Directive,
1215
+ args: [{
1216
+ selector: '[rdxAutocompleteInputGroup]',
1217
+ exportAs: 'rdxAutocompleteInputGroup',
1218
+ host: {
1219
+ '[attr.data-popup-open]': 'dataAttr(root.open())',
1220
+ '[attr.data-disabled]': 'dataAttr(root.disabledState())',
1221
+ '[attr.data-required]': 'dataAttr(root.requiredState())',
1222
+ '[attr.data-filled]': 'dataAttr(!!root.value())'
1223
+ }
1224
+ }]
1225
+ }] });
1226
+
1227
+ const itemContext = () => {
1228
+ const item = inject(RdxAutocompleteItem);
1229
+ return {
1230
+ isSelected: item.isSelected,
1231
+ isHighlighted: item.isHighlighted,
1232
+ disabled: item.disabled,
1233
+ value: item.value
1234
+ };
1235
+ };
1236
+ /**
1237
+ * A selectable suggestion. Registers itself with the root for filtering and navigation. Highlight is
1238
+ * virtual (`data-highlighted` + `aria-activedescendant` on the input) — items never take DOM focus.
1239
+ * Selecting an item writes its text into the input. Unlike the combobox item, the `value` is optional;
1240
+ * when omitted, selection falls back to the option's text content (autocomplete's value is the input string).
1241
+ *
1242
+ * @group Components
1243
+ */
1244
+ class RdxAutocompleteItem {
1245
+ constructor() {
1246
+ this.rootContext = injectComboboxRootContext();
1247
+ this.element = inject(ElementRef).nativeElement;
1248
+ this.id = injectId('rdx-autocomplete-item-');
1249
+ /** The option's value. When omitted, selecting the item writes its text content into the input. */
1250
+ this.value = input('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
1251
+ /** Explicit text matched against the query and written to the input. Defaults to text content. */
1252
+ this.textValueInput = input('', { ...(ngDevMode ? { debugName: "textValueInput" } : /* istanbul ignore next */ {}), alias: 'textValue' });
1253
+ /** Whether the option is disabled. */
1254
+ this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1255
+ /** The option's index in the list. Required in virtualized mode. */
1256
+ this.index = input(...(ngDevMode ? [undefined, { debugName: "index" }] : /* istanbul ignore next */ []));
1257
+ this.virtualized = this.rootContext.virtualized;
1258
+ this.autoTextValue = signal('', ...(ngDevMode ? [{ debugName: "autoTextValue" }] : /* istanbul ignore next */ []));
1259
+ this.textValue = computed(() => this.textValueInput() || this.autoTextValue(), ...(ngDevMode ? [{ debugName: "textValue" }] : /* istanbul ignore next */ []));
1260
+ this.elementId = computed(() => this.virtualized() ? this.rootContext.itemId(this.index() ?? -1) : this.id, ...(ngDevMode ? [{ debugName: "elementId" }] : /* istanbul ignore next */ []));
1261
+ this.ariaSetSize = computed(() => this.virtualized() ? this.rootContext.filteredItems().length : undefined, ...(ngDevMode ? [{ debugName: "ariaSetSize" }] : /* istanbul ignore next */ []));
1262
+ this.ariaPosInSet = computed(() => (this.virtualized() ? (this.index() ?? -1) + 1 : undefined), ...(ngDevMode ? [{ debugName: "ariaPosInSet" }] : /* istanbul ignore next */ []));
1263
+ this.isVisible = computed(() => (this.virtualized() ? true : this.rootContext.isVisible(this)), ...(ngDevMode ? [{ debugName: "isVisible" }] : /* istanbul ignore next */ []));
1264
+ this.isSelected = computed(() => this.rootContext.isSelected(this.value()), ...(ngDevMode ? [{ debugName: "isSelected" }] : /* istanbul ignore next */ []));
1265
+ this.isHighlighted = computed(() => this.virtualized()
1266
+ ? this.rootContext.highlightedIndex() === this.index()
1267
+ : this.rootContext.highlightedItem() === this, ...(ngDevMode ? [{ debugName: "isHighlighted" }] : /* istanbul ignore next */ []));
1268
+ this.group = injectComboboxGroupContext(true);
1269
+ const destroyRef = inject(DestroyRef);
1270
+ afterNextRender(() => {
1271
+ if (this.virtualized()) {
1272
+ return;
1273
+ }
1274
+ if (!this.textValueInput()) {
1275
+ const clone = this.element.cloneNode(true);
1276
+ clone.querySelectorAll('[rdxAutocompleteItemIndicator]').forEach((node) => node.remove());
1277
+ this.autoTextValue.set(clone.textContent?.trim() ?? '');
1278
+ }
1279
+ this.rootContext.registerItem(this);
1280
+ this.group?.registerItem(this);
1281
+ });
1282
+ destroyRef.onDestroy(() => {
1283
+ if (this.virtualized()) {
1284
+ return;
1285
+ }
1286
+ this.rootContext.unregisterItem(this);
1287
+ this.group?.unregisterItem(this);
1288
+ });
1289
+ // Keep the highlighted option in view while navigating a scrollable popup. `block: 'nearest'`
1290
+ // makes hover a no-op (the item is already visible) and only scrolls on keyboard navigation.
1291
+ afterRenderEffect(() => {
1292
+ if (!this.virtualized() && this.isHighlighted()) {
1293
+ this.element.scrollIntoView({ block: 'nearest' });
1294
+ }
1295
+ });
1296
+ }
1297
+ onPointerDown(event) {
1298
+ event.preventDefault();
1299
+ this.rootContext.setKeyboardActive(false);
1300
+ }
1301
+ onPointerUp() {
1302
+ if (this.virtualized()) {
1303
+ this.rootContext.selectIndex(this.index() ?? -1);
1304
+ }
1305
+ else {
1306
+ this.rootContext.select(this);
1307
+ }
1308
+ }
1309
+ onPointerMove() {
1310
+ // Hover highlighting disabled: leave `data-highlighted` to keyboard/auto-highlight only.
1311
+ if (!this.rootContext.highlightItemOnHover()) {
1312
+ return;
1313
+ }
1314
+ if (this.rootContext.isKeyboardActive()) {
1315
+ this.rootContext.setKeyboardActive(false);
1316
+ return;
1317
+ }
1318
+ if (this.disabled()) {
1319
+ return;
1320
+ }
1321
+ if (this.virtualized()) {
1322
+ this.rootContext.highlightIndex(this.index() ?? -1, 'pointer');
1323
+ }
1324
+ else if (this.isVisible()) {
1325
+ this.rootContext.setHighlight(this, 'pointer');
1326
+ }
1327
+ }
1328
+ // Clear a pointer-driven highlight when the cursor leaves the list (unless `keepHighlight`).
1329
+ // Moving to another element inside the list keeps it (the next item's move re-highlights).
1330
+ onPointerLeave(event) {
1331
+ if (event.pointerType === 'touch' ||
1332
+ !this.rootContext.open() ||
1333
+ !this.rootContext.highlightItemOnHover() ||
1334
+ this.rootContext.keepHighlight()) {
1335
+ return;
1336
+ }
1337
+ const related = event.relatedTarget;
1338
+ const list = related && document.getElementById(this.rootContext.listId);
1339
+ if (list && list.contains(related)) {
1340
+ return;
1341
+ }
1342
+ this.rootContext.clearHighlight();
1343
+ }
1344
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteItem, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1345
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxAutocompleteItem, isStandalone: true, selector: "[rdxAutocompleteItem]", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, textValueInput: { classPropertyName: "textValueInput", publicName: "textValue", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, index: { classPropertyName: "index", publicName: "index", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "option" }, listeners: { "pointerdown": "onPointerDown($event)", "mousedown": "onPointerDown($event)", "pointerup": "onPointerUp()", "pointermove": "onPointerMove()", "pointerleave": "onPointerLeave($event)" }, properties: { "attr.id": "elementId()", "attr.aria-selected": "isSelected()", "attr.aria-disabled": "disabled() ? \"true\" : undefined", "attr.aria-setsize": "ariaSetSize()", "attr.aria-posinset": "ariaPosInSet()", "attr.data-selected": "isSelected() ? \"\" : undefined", "attr.data-highlighted": "isHighlighted() ? \"\" : undefined", "attr.data-disabled": "disabled() ? \"\" : undefined", "hidden": "!isVisible()", "attr.data-hidden": "isVisible() ? undefined : \"\"" } }, providers: [provideComboboxItemContext(itemContext)], exportAs: ["rdxAutocompleteItem"], ngImport: i0 }); }
1346
+ }
1347
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteItem, decorators: [{
1348
+ type: Directive,
1349
+ args: [{
1350
+ selector: '[rdxAutocompleteItem]',
1351
+ exportAs: 'rdxAutocompleteItem',
1352
+ providers: [provideComboboxItemContext(itemContext)],
1353
+ host: {
1354
+ role: 'option',
1355
+ '[attr.id]': 'elementId()',
1356
+ '[attr.aria-selected]': 'isSelected()',
1357
+ '[attr.aria-disabled]': 'disabled() ? "true" : undefined',
1358
+ '[attr.aria-setsize]': 'ariaSetSize()',
1359
+ '[attr.aria-posinset]': 'ariaPosInSet()',
1360
+ '[attr.data-selected]': 'isSelected() ? "" : undefined',
1361
+ '[attr.data-highlighted]': 'isHighlighted() ? "" : undefined',
1362
+ '[attr.data-disabled]': 'disabled() ? "" : undefined',
1363
+ '[hidden]': '!isVisible()',
1364
+ '[attr.data-hidden]': 'isVisible() ? undefined : ""',
1365
+ '(pointerdown)': 'onPointerDown($event)',
1366
+ '(mousedown)': 'onPointerDown($event)',
1367
+ '(pointerup)': 'onPointerUp()',
1368
+ '(pointermove)': 'onPointerMove()',
1369
+ '(pointerleave)': 'onPointerLeave($event)'
1370
+ }
1371
+ }]
1372
+ }], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], textValueInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "textValue", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], index: [{ type: i0.Input, args: [{ isSignal: true, alias: "index", required: false }] }] } });
1373
+
1374
+ /**
1375
+ * Renders only when its item is selected (e.g. a checkmark). Reuses the combobox item indicator,
1376
+ * which reads the item context provided by {@link RdxAutocompleteItem}.
1377
+ *
1378
+ * @group Components
1379
+ */
1380
+ class RdxAutocompleteItemIndicator {
1381
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteItemIndicator, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1382
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxAutocompleteItemIndicator, isStandalone: true, selector: "[rdxAutocompleteItemIndicator]", exportAs: ["rdxAutocompleteItemIndicator"], hostDirectives: [{ directive: i1.RdxComboboxItemIndicator }], ngImport: i0 }); }
1383
+ }
1384
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteItemIndicator, decorators: [{
1385
+ type: Directive,
1386
+ args: [{
1387
+ selector: '[rdxAutocompleteItemIndicator]',
1388
+ exportAs: 'rdxAutocompleteItemIndicator',
1389
+ hostDirectives: [RdxComboboxItemIndicator]
1390
+ }]
1391
+ }] });
1392
+
1393
+ /**
1394
+ * An accessible label for the autocomplete. Registers its id so the input (and trigger) reference it
1395
+ * via `aria-labelledby`. Reuses the combobox label behavior.
1396
+ *
1397
+ * @group Components
1398
+ */
1399
+ class RdxAutocompleteLabel {
1400
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteLabel, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1401
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxAutocompleteLabel, isStandalone: true, selector: "[rdxAutocompleteLabel]", exportAs: ["rdxAutocompleteLabel"], hostDirectives: [{ directive: i1.RdxComboboxLabel }], ngImport: i0 }); }
1402
+ }
1403
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteLabel, decorators: [{
1404
+ type: Directive,
1405
+ args: [{
1406
+ selector: '[rdxAutocompleteLabel]',
1407
+ exportAs: 'rdxAutocompleteLabel',
1408
+ hostDirectives: [RdxComboboxLabel]
1409
+ }]
1410
+ }] });
1411
+
1412
+ /**
1413
+ * The listbox (or grid) container for suggestions. Carries the id referenced by the input's
1414
+ * `aria-controls`, and switches its role to `grid` when the root has `grid` enabled.
1415
+ *
1416
+ * @group Components
1417
+ */
1418
+ class RdxAutocompleteList {
1419
+ constructor() {
1420
+ this.root = inject(RdxAutocompleteRoot);
1421
+ }
1422
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteList, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1423
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxAutocompleteList, isStandalone: true, selector: "[rdxAutocompleteList]", host: { properties: { "attr.role": "root.grid() ? \"grid\" : \"listbox\"", "attr.id": "root.listId" } }, exportAs: ["rdxAutocompleteList"], ngImport: i0 }); }
1424
+ }
1425
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteList, decorators: [{
1426
+ type: Directive,
1427
+ args: [{
1428
+ selector: '[rdxAutocompleteList]',
1429
+ exportAs: 'rdxAutocompleteList',
1430
+ host: {
1431
+ '[attr.role]': 'root.grid() ? "grid" : "listbox"',
1432
+ '[attr.id]': 'root.listId'
1433
+ }
1434
+ }]
1435
+ }] });
1436
+
1437
+ /**
1438
+ * The popup surface. Composes the popper content (for `data-side` / `data-align`) and a dismissable
1439
+ * layer for outside-dismiss. It does **not** trap focus — focus stays in the input throughout. When
1440
+ * the input lives **inside** the popup (the "input in popup" / emoji-picker pattern), it moves focus
1441
+ * to the input once the popup is positioned.
1442
+ *
1443
+ * @group Components
1444
+ */
1445
+ class RdxAutocompletePopup {
1446
+ constructor() {
1447
+ this.root = inject(RdxAutocompleteRoot);
1448
+ this.dismissableLayer = inject(RdxDismissableLayer);
1449
+ this.popper = injectPopperContentWrapperContext();
1450
+ this.element = inject(ElementRef).nativeElement;
1451
+ useScrollLock(this.root.modal);
1452
+ const unregister = this.root.registerTransitionElement(this.element);
1453
+ inject(DestroyRef).onDestroy(unregister);
1454
+ this.dismissableLayer.dismiss.subscribe(() => this.root.closePopup(true));
1455
+ // For the "input inside the popup" pattern, move focus to the input once positioned. Use
1456
+ // `afterRenderEffect` (not `effect`): when `isPositioned` flips true the popup's final
1457
+ // position/visibility is applied in the *following* render, so a synchronous `effect` would
1458
+ // call `focus()` while the element is still unfocusable and silently no-op. Running after the
1459
+ // render guarantees the input is focusable.
1460
+ afterRenderEffect(() => {
1461
+ if (!this.popper.isPositioned() || !this.root.open()) {
1462
+ return;
1463
+ }
1464
+ const input = this.root.inputElement();
1465
+ if (input && input.closest('[rdxAutocompletePopup]')) {
1466
+ input.focus();
1467
+ input.select();
1468
+ }
1469
+ });
1470
+ }
1471
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompletePopup, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1472
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxAutocompletePopup, isStandalone: true, selector: "[rdxAutocompletePopup]", host: { properties: { "attr.data-state": "root.open() ? \"open\" : \"closed\"", "attr.data-open": "root.open() ? \"\" : undefined", "attr.data-closed": "root.open() ? undefined : \"\"", "attr.data-starting-style": "root.transitionStatus() === \"starting\" ? \"\" : undefined", "attr.data-ending-style": "root.transitionStatus() === \"ending\" ? \"\" : undefined" } }, providers: [
1473
+ provideRdxDismissableLayerConfig(() => ({
1474
+ disableOutsidePointerEvents: inject(RdxAutocompleteRoot).modal
1475
+ }))
1476
+ ], exportAs: ["rdxAutocompletePopup"], hostDirectives: [{ directive: i1$1.RdxPopperContent }, { directive: i2.RdxDismissableLayer }], ngImport: i0 }); }
1477
+ }
1478
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompletePopup, decorators: [{
1479
+ type: Directive,
1480
+ args: [{
1481
+ selector: '[rdxAutocompletePopup]',
1482
+ exportAs: 'rdxAutocompletePopup',
1483
+ hostDirectives: [RdxPopperContent, RdxDismissableLayer],
1484
+ providers: [
1485
+ provideRdxDismissableLayerConfig(() => ({
1486
+ disableOutsidePointerEvents: inject(RdxAutocompleteRoot).modal
1487
+ }))
1488
+ ],
1489
+ host: {
1490
+ '[attr.data-state]': 'root.open() ? "open" : "closed"',
1491
+ '[attr.data-open]': 'root.open() ? "" : undefined',
1492
+ '[attr.data-closed]': 'root.open() ? undefined : ""',
1493
+ '[attr.data-starting-style]': 'root.transitionStatus() === "starting" ? "" : undefined',
1494
+ '[attr.data-ending-style]': 'root.transitionStatus() === "ending" ? "" : undefined'
1495
+ }
1496
+ }]
1497
+ }], ctorParameters: () => [] });
1498
+
1499
+ /**
1500
+ * Structural directive that teleports the autocomplete popup into a container (default
1501
+ * `document.body`) while the autocomplete is open, keeping it mounted until any CSS exit `@keyframes`
1502
+ * finishes. Composes the structural {@link RdxComboboxPortal} (which reads the open state from the
1503
+ * combobox root context provided by `RdxAutocompleteRoot`).
1504
+ *
1505
+ * Apply it with the `*` microsyntax on the positioner —
1506
+ * `<div *rdxAutocompletePortal rdxAutocompletePositioner>` — or as an explicit
1507
+ * `<ng-template rdxAutocompletePortal>`. For a custom container use the explicit form with `[container]`.
1508
+ *
1509
+ * @group Components
1510
+ */
1511
+ class RdxAutocompletePortal {
1512
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompletePortal, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1513
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxAutocompletePortal, isStandalone: true, selector: "ng-template[rdxAutocompletePortal]", exportAs: ["rdxAutocompletePortal"], hostDirectives: [{ directive: i1.RdxComboboxPortal, inputs: ["container", "container"] }], ngImport: i0 }); }
1514
+ }
1515
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompletePortal, decorators: [{
1516
+ type: Directive,
1517
+ args: [{
1518
+ selector: 'ng-template[rdxAutocompletePortal]',
1519
+ exportAs: 'rdxAutocompletePortal',
1520
+ hostDirectives: [{ directive: RdxComboboxPortal, inputs: ['container'] }]
1521
+ }]
1522
+ }] });
1523
+ /**
1524
+ * Dev-mode guard: `rdxAutocompletePortal` is now structural, so the old `<div rdxAutocompletePortal>`
1525
+ * markup would silently stop portaling — fail loudly instead.
1526
+ *
1527
+ * @group Components
1528
+ */
1529
+ class RdxAutocompletePortalMisuseGuard {
1530
+ constructor() {
1531
+ if (isDevMode()) {
1532
+ throw new Error('[rdxAutocompletePortal] is now a structural directive. ' +
1533
+ 'Use `*rdxAutocompletePortal` on the positioner element or `<ng-template rdxAutocompletePortal>`. ' +
1534
+ 'rdxAutocompletePortalPresence has been removed. See https://radix-ng.com/components/autocomplete.md');
1535
+ }
1536
+ }
1537
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompletePortalMisuseGuard, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1538
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxAutocompletePortalMisuseGuard, isStandalone: true, selector: "[rdxAutocompletePortal]:not(ng-template)", ngImport: i0 }); }
1539
+ }
1540
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompletePortalMisuseGuard, decorators: [{
1541
+ type: Directive,
1542
+ args: [{
1543
+ selector: '[rdxAutocompletePortal]:not(ng-template)'
1544
+ }]
1545
+ }], ctorParameters: () => [] });
1546
+
1547
+ /**
1548
+ * Positions the popup relative to the input anchor using the popper engine. Composes the popper
1549
+ * content wrapper directly (the same building block the combobox positioner uses) and re-exposes its
1550
+ * positioning inputs.
1551
+ *
1552
+ * @group Components
1553
+ */
1554
+ class RdxAutocompletePositioner {
1555
+ constructor() {
1556
+ this.side = input('bottom', ...(ngDevMode ? [{ debugName: "side" }] : /* istanbul ignore next */ []));
1557
+ this.sideOffset = input(4, { ...(ngDevMode ? { debugName: "sideOffset" } : /* istanbul ignore next */ {}), transform: numberAttribute });
1558
+ this.align = input('start', ...(ngDevMode ? [{ debugName: "align" }] : /* istanbul ignore next */ []));
1559
+ this.alignOffset = input(0, { ...(ngDevMode ? { debugName: "alignOffset" } : /* istanbul ignore next */ {}), transform: numberAttribute });
1560
+ this.arrowPadding = input(0, { ...(ngDevMode ? { debugName: "arrowPadding" } : /* istanbul ignore next */ {}), transform: numberAttribute });
1561
+ this.avoidCollisions = input(true, { ...(ngDevMode ? { debugName: "avoidCollisions" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1562
+ this.collisionBoundary = input(...(ngDevMode ? [undefined, { debugName: "collisionBoundary" }] : /* istanbul ignore next */ []));
1563
+ this.collisionPadding = input(0, ...(ngDevMode ? [{ debugName: "collisionPadding" }] : /* istanbul ignore next */ []));
1564
+ this.sticky = input('partial', ...(ngDevMode ? [{ debugName: "sticky" }] : /* istanbul ignore next */ []));
1565
+ this.hideWhenDetached = input(false, { ...(ngDevMode ? { debugName: "hideWhenDetached" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1566
+ this.updatePositionStrategy = input('optimized', ...(ngDevMode ? [{ debugName: "updatePositionStrategy" }] : /* istanbul ignore next */ []));
1567
+ }
1568
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompletePositioner, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1569
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxAutocompletePositioner, isStandalone: true, selector: "[rdxAutocompletePositioner]", inputs: { side: { classPropertyName: "side", publicName: "side", isSignal: true, isRequired: false, transformFunction: null }, sideOffset: { classPropertyName: "sideOffset", publicName: "sideOffset", isSignal: true, isRequired: false, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, alignOffset: { classPropertyName: "alignOffset", publicName: "alignOffset", isSignal: true, isRequired: false, transformFunction: null }, arrowPadding: { classPropertyName: "arrowPadding", publicName: "arrowPadding", isSignal: true, isRequired: false, transformFunction: null }, avoidCollisions: { classPropertyName: "avoidCollisions", publicName: "avoidCollisions", isSignal: true, isRequired: false, transformFunction: null }, collisionBoundary: { classPropertyName: "collisionBoundary", publicName: "collisionBoundary", isSignal: true, isRequired: false, transformFunction: null }, collisionPadding: { classPropertyName: "collisionPadding", publicName: "collisionPadding", isSignal: true, isRequired: false, transformFunction: null }, sticky: { classPropertyName: "sticky", publicName: "sticky", isSignal: true, isRequired: false, transformFunction: null }, hideWhenDetached: { classPropertyName: "hideWhenDetached", publicName: "hideWhenDetached", isSignal: true, isRequired: false, transformFunction: null }, updatePositionStrategy: { classPropertyName: "updatePositionStrategy", publicName: "updatePositionStrategy", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style": "{\n 'boxSizing': 'border-box',\n '--radix-autocomplete-content-transform-origin': 'var(--radix-popper-transform-origin)',\n '--radix-autocomplete-content-available-width': 'var(--radix-popper-available-width)',\n '--radix-autocomplete-content-available-height': 'var(--radix-popper-available-height)',\n '--radix-autocomplete-trigger-width': 'var(--radix-popper-anchor-width)',\n '--radix-autocomplete-trigger-height': 'var(--radix-popper-anchor-height)'\n }" } }, exportAs: ["rdxAutocompletePositioner"], hostDirectives: [{ directive: i1$1.RdxPopperContentWrapper, inputs: ["side", "side", "sideOffset", "sideOffset", "align", "align", "alignOffset", "alignOffset", "arrowPadding", "arrowPadding", "avoidCollisions", "avoidCollisions", "collisionBoundary", "collisionBoundary", "collisionPadding", "collisionPadding", "sticky", "sticky", "hideWhenDetached", "hideWhenDetached", "updatePositionStrategy", "updatePositionStrategy"] }], ngImport: i0 }); }
1570
+ }
1571
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompletePositioner, decorators: [{
1572
+ type: Directive,
1573
+ args: [{
1574
+ selector: '[rdxAutocompletePositioner]',
1575
+ exportAs: 'rdxAutocompletePositioner',
1576
+ hostDirectives: [
1577
+ {
1578
+ directive: RdxPopperContentWrapper,
1579
+ inputs: [
1580
+ 'side',
1581
+ 'sideOffset',
1582
+ 'align',
1583
+ 'alignOffset',
1584
+ 'arrowPadding',
1585
+ 'avoidCollisions',
1586
+ 'collisionBoundary',
1587
+ 'collisionPadding',
1588
+ 'sticky',
1589
+ 'hideWhenDetached',
1590
+ 'updatePositionStrategy'
1591
+ ]
1592
+ }
1593
+ ],
1594
+ host: {
1595
+ '[style]': `{
1596
+ 'boxSizing': 'border-box',
1597
+ '--radix-autocomplete-content-transform-origin': 'var(--radix-popper-transform-origin)',
1598
+ '--radix-autocomplete-content-available-width': 'var(--radix-popper-available-width)',
1599
+ '--radix-autocomplete-content-available-height': 'var(--radix-popper-available-height)',
1600
+ '--radix-autocomplete-trigger-width': 'var(--radix-popper-anchor-width)',
1601
+ '--radix-autocomplete-trigger-height': 'var(--radix-popper-anchor-height)'
1602
+ }`
1603
+ }
1604
+ }]
1605
+ }], propDecorators: { side: [{ type: i0.Input, args: [{ isSignal: true, alias: "side", required: false }] }], sideOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "sideOffset", required: false }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], alignOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "alignOffset", required: false }] }], arrowPadding: [{ type: i0.Input, args: [{ isSignal: true, alias: "arrowPadding", required: false }] }], avoidCollisions: [{ type: i0.Input, args: [{ isSignal: true, alias: "avoidCollisions", required: false }] }], collisionBoundary: [{ type: i0.Input, args: [{ isSignal: true, alias: "collisionBoundary", required: false }] }], collisionPadding: [{ type: i0.Input, args: [{ isSignal: true, alias: "collisionPadding", required: false }] }], sticky: [{ type: i0.Input, args: [{ isSignal: true, alias: "sticky", required: false }] }], hideWhenDetached: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideWhenDetached", required: false }] }], updatePositionStrategy: [{ type: i0.Input, args: [{ isSignal: true, alias: "updatePositionStrategy", required: false }] }] } });
1606
+
1607
+ /**
1608
+ * A row in a grid-layout autocomplete list. Groups the items in one row so the root can navigate by
1609
+ * row (ArrowUp / ArrowDown) and within a row (ArrowLeft / ArrowRight). Only meaningful when the root
1610
+ * has `grid` enabled; the root resolves an item's row from its nearest `[rdxAutocompleteRow]` ancestor.
1611
+ *
1612
+ * @group Components
1613
+ */
1614
+ class RdxAutocompleteRow {
1615
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteRow, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1616
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxAutocompleteRow, isStandalone: true, selector: "[rdxAutocompleteRow]", host: { attributes: { "role": "row" } }, exportAs: ["rdxAutocompleteRow"], ngImport: i0 }); }
1617
+ }
1618
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteRow, decorators: [{
1619
+ type: Directive,
1620
+ args: [{
1621
+ selector: '[rdxAutocompleteRow]',
1622
+ exportAs: 'rdxAutocompleteRow',
1623
+ host: {
1624
+ role: 'row'
1625
+ }
1626
+ }]
1627
+ }] });
1628
+
1629
+ /**
1630
+ * A polite live region for async status (loading, result counts) announced without moving focus.
1631
+ * Reuses the combobox status region.
1632
+ *
1633
+ * @group Components
1634
+ */
1635
+ class RdxAutocompleteStatus {
1636
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteStatus, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1637
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxAutocompleteStatus, isStandalone: true, selector: "[rdxAutocompleteStatus]", exportAs: ["rdxAutocompleteStatus"], hostDirectives: [{ directive: i1.RdxComboboxStatus }], ngImport: i0 }); }
1638
+ }
1639
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteStatus, decorators: [{
1640
+ type: Directive,
1641
+ args: [{
1642
+ selector: '[rdxAutocompleteStatus]',
1643
+ exportAs: 'rdxAutocompleteStatus',
1644
+ hostDirectives: [RdxComboboxStatus]
1645
+ }]
1646
+ }] });
1647
+
1648
+ /**
1649
+ * Toggles the autocomplete popup. Carries `tabindex="-1"` so it never steals focus from the input.
1650
+ * Reuses the combobox trigger behavior.
1651
+ *
1652
+ * @group Components
1653
+ */
1654
+ class RdxAutocompleteTrigger {
1655
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteTrigger, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1656
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxAutocompleteTrigger, isStandalone: true, selector: "button[rdxAutocompleteTrigger]", exportAs: ["rdxAutocompleteTrigger"], hostDirectives: [{ directive: i1.RdxComboboxTrigger }], ngImport: i0 }); }
1657
+ }
1658
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteTrigger, decorators: [{
1659
+ type: Directive,
1660
+ args: [{
1661
+ selector: 'button[rdxAutocompleteTrigger]',
1662
+ exportAs: 'rdxAutocompleteTrigger',
1663
+ hostDirectives: [RdxComboboxTrigger]
1664
+ }]
1665
+ }] });
1666
+
1667
+ /**
1668
+ * Renders the current input value as text. Useful for a read-only display of the committed value.
1669
+ * Read `slotText()` in the template. Exposes `data-placeholder` while the value is empty.
1670
+ *
1671
+ * @example
1672
+ * <span #value="rdxAutocompleteValue" rdxAutocompleteValue placeholder="Empty">{{ value.slotText() }}</span>
1673
+ *
1674
+ * @group Components
1675
+ */
1676
+ class RdxAutocompleteValue {
1677
+ constructor() {
1678
+ this.root = inject(RdxAutocompleteRoot);
1679
+ /** Text shown when the value is empty. */
1680
+ this.placeholder = input(...(ngDevMode ? [undefined, { debugName: "placeholder" }] : /* istanbul ignore next */ []));
1681
+ this.isEmpty = computed(() => !this.root.value(), ...(ngDevMode ? [{ debugName: "isEmpty" }] : /* istanbul ignore next */ []));
1682
+ /** The current input value, or the `placeholder` when empty. */
1683
+ this.slotText = computed(() => this.root.value() || (this.placeholder() ?? ''), ...(ngDevMode ? [{ debugName: "slotText" }] : /* istanbul ignore next */ []));
1684
+ }
1685
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteValue, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1686
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxAutocompleteValue, isStandalone: true, selector: "[rdxAutocompleteValue]", inputs: { placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-placeholder": "isEmpty() ? \"\" : undefined" } }, exportAs: ["rdxAutocompleteValue"], ngImport: i0 }); }
1687
+ }
1688
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteValue, decorators: [{
1689
+ type: Directive,
1690
+ args: [{
1691
+ selector: '[rdxAutocompleteValue]',
1692
+ exportAs: 'rdxAutocompleteValue',
1693
+ host: {
1694
+ '[attr.data-placeholder]': 'isEmpty() ? "" : undefined'
1695
+ }
1696
+ }]
1697
+ }], propDecorators: { placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }] } });
1698
+
1699
+ const _importsAutocomplete = [
1700
+ RdxAutocompleteRoot,
1701
+ RdxAutocompleteAnchor,
1702
+ RdxAutocompleteLabel,
1703
+ RdxAutocompleteInputGroup,
1704
+ RdxAutocompleteInput,
1705
+ RdxAutocompleteValue,
1706
+ RdxAutocompleteTrigger,
1707
+ RdxAutocompleteIcon,
1708
+ RdxAutocompleteClear,
1709
+ RdxAutocompletePortal,
1710
+ RdxAutocompletePortalMisuseGuard,
1711
+ RdxAutocompleteBackdrop,
1712
+ RdxAutocompletePositioner,
1713
+ RdxAutocompletePopup,
1714
+ RdxAutocompleteArrow,
1715
+ RdxAutocompleteList,
1716
+ RdxAutocompleteRow,
1717
+ RdxAutocompleteItem,
1718
+ RdxAutocompleteItemIndicator,
1719
+ RdxAutocompleteGroup,
1720
+ RdxAutocompleteGroupLabel,
1721
+ RdxAutocompleteEmpty,
1722
+ RdxAutocompleteStatus
1723
+ ];
1724
+ class RdxAutocompleteModule {
1725
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
1726
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteModule, imports: [RdxAutocompleteRoot,
1727
+ RdxAutocompleteAnchor,
1728
+ RdxAutocompleteLabel,
1729
+ RdxAutocompleteInputGroup,
1730
+ RdxAutocompleteInput,
1731
+ RdxAutocompleteValue,
1732
+ RdxAutocompleteTrigger,
1733
+ RdxAutocompleteIcon,
1734
+ RdxAutocompleteClear,
1735
+ RdxAutocompletePortal,
1736
+ RdxAutocompletePortalMisuseGuard,
1737
+ RdxAutocompleteBackdrop,
1738
+ RdxAutocompletePositioner,
1739
+ RdxAutocompletePopup,
1740
+ RdxAutocompleteArrow,
1741
+ RdxAutocompleteList,
1742
+ RdxAutocompleteRow,
1743
+ RdxAutocompleteItem,
1744
+ RdxAutocompleteItemIndicator,
1745
+ RdxAutocompleteGroup,
1746
+ RdxAutocompleteGroupLabel,
1747
+ RdxAutocompleteEmpty,
1748
+ RdxAutocompleteStatus], exports: [RdxAutocompleteRoot,
1749
+ RdxAutocompleteAnchor,
1750
+ RdxAutocompleteLabel,
1751
+ RdxAutocompleteInputGroup,
1752
+ RdxAutocompleteInput,
1753
+ RdxAutocompleteValue,
1754
+ RdxAutocompleteTrigger,
1755
+ RdxAutocompleteIcon,
1756
+ RdxAutocompleteClear,
1757
+ RdxAutocompletePortal,
1758
+ RdxAutocompletePortalMisuseGuard,
1759
+ RdxAutocompleteBackdrop,
1760
+ RdxAutocompletePositioner,
1761
+ RdxAutocompletePopup,
1762
+ RdxAutocompleteArrow,
1763
+ RdxAutocompleteList,
1764
+ RdxAutocompleteRow,
1765
+ RdxAutocompleteItem,
1766
+ RdxAutocompleteItemIndicator,
1767
+ RdxAutocompleteGroup,
1768
+ RdxAutocompleteGroupLabel,
1769
+ RdxAutocompleteEmpty,
1770
+ RdxAutocompleteStatus] }); }
1771
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteModule }); }
1772
+ }
1773
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxAutocompleteModule, decorators: [{
1774
+ type: NgModule,
1775
+ args: [{
1776
+ imports: [..._importsAutocomplete],
1777
+ exports: [..._importsAutocomplete]
1778
+ }]
1779
+ }] });
1780
+
1781
+ /**
1782
+ * Generated bundle index. Do not edit.
1783
+ */
1784
+
1785
+ export { RdxAutocompleteAnchor, RdxAutocompleteArrow, RdxAutocompleteBackdrop, RdxAutocompleteClear, RdxAutocompleteEmpty, RdxAutocompleteGroup, RdxAutocompleteGroupLabel, RdxAutocompleteIcon, RdxAutocompleteInput, RdxAutocompleteInputGroup, RdxAutocompleteItem, RdxAutocompleteItemIndicator, RdxAutocompleteLabel, RdxAutocompleteList, RdxAutocompleteModule, RdxAutocompletePopup, RdxAutocompletePortal, RdxAutocompletePortalMisuseGuard, RdxAutocompletePositioner, RdxAutocompleteRoot, RdxAutocompleteRow, RdxAutocompleteStatus, RdxAutocompleteTrigger, RdxAutocompleteValue, _importsAutocomplete };
1786
+ //# sourceMappingURL=radix-ng-primitives-autocomplete.mjs.map