@radix-ng/primitives 1.0.0-beta.2 → 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 (45) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +76 -6
  3. package/fesm2022/radix-ng-primitives-alert-dialog.mjs +30 -24
  4. package/fesm2022/radix-ng-primitives-alert-dialog.mjs.map +1 -1
  5. package/fesm2022/radix-ng-primitives-autocomplete.mjs +1786 -0
  6. package/fesm2022/radix-ng-primitives-autocomplete.mjs.map +1 -0
  7. package/fesm2022/radix-ng-primitives-combobox.mjs +107 -47
  8. package/fesm2022/radix-ng-primitives-combobox.mjs.map +1 -1
  9. package/fesm2022/radix-ng-primitives-dialog.mjs +43 -45
  10. package/fesm2022/radix-ng-primitives-dialog.mjs.map +1 -1
  11. package/fesm2022/radix-ng-primitives-drawer.mjs +153 -63
  12. package/fesm2022/radix-ng-primitives-drawer.mjs.map +1 -1
  13. package/fesm2022/radix-ng-primitives-menu.mjs +40 -20
  14. package/fesm2022/radix-ng-primitives-menu.mjs.map +1 -1
  15. package/fesm2022/radix-ng-primitives-navigation-menu.mjs +38 -54
  16. package/fesm2022/radix-ng-primitives-navigation-menu.mjs.map +1 -1
  17. package/fesm2022/radix-ng-primitives-popover.mjs +35 -50
  18. package/fesm2022/radix-ng-primitives-popover.mjs.map +1 -1
  19. package/fesm2022/radix-ng-primitives-popper.mjs +11 -5
  20. package/fesm2022/radix-ng-primitives-popper.mjs.map +1 -1
  21. package/fesm2022/radix-ng-primitives-portal.mjs +107 -17
  22. package/fesm2022/radix-ng-primitives-portal.mjs.map +1 -1
  23. package/fesm2022/radix-ng-primitives-presence.mjs +262 -79
  24. package/fesm2022/radix-ng-primitives-presence.mjs.map +1 -1
  25. package/fesm2022/radix-ng-primitives-preview-card.mjs +36 -50
  26. package/fesm2022/radix-ng-primitives-preview-card.mjs.map +1 -1
  27. package/fesm2022/radix-ng-primitives-select.mjs +106 -92
  28. package/fesm2022/radix-ng-primitives-select.mjs.map +1 -1
  29. package/fesm2022/radix-ng-primitives-tooltip.mjs +37 -40
  30. package/fesm2022/radix-ng-primitives-tooltip.mjs.map +1 -1
  31. package/package.json +5 -1
  32. package/types/radix-ng-primitives-alert-dialog.d.ts +17 -11
  33. package/types/radix-ng-primitives-autocomplete.d.ts +596 -0
  34. package/types/radix-ng-primitives-combobox.d.ts +61 -16
  35. package/types/radix-ng-primitives-dialog.d.ts +32 -25
  36. package/types/radix-ng-primitives-drawer.d.ts +49 -22
  37. package/types/radix-ng-primitives-menu.d.ts +19 -10
  38. package/types/radix-ng-primitives-navigation-menu.d.ts +24 -26
  39. package/types/radix-ng-primitives-popover.d.ts +23 -23
  40. package/types/radix-ng-primitives-popper.d.ts +7 -1
  41. package/types/radix-ng-primitives-portal.d.ts +53 -8
  42. package/types/radix-ng-primitives-presence.d.ts +98 -17
  43. package/types/radix-ng-primitives-preview-card.d.ts +24 -23
  44. package/types/radix-ng-primitives-select.d.ts +52 -55
  45. package/types/radix-ng-primitives-tooltip.d.ts +26 -19
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Directive, inject, Injector, model, input, booleanAttribute, computed, numberAttribute, output, signal, effect, untracked, isDevMode, ElementRef, DestroyRef, afterNextRender, NgModule } from '@angular/core';
2
+ import { Directive, inject, booleanAttribute, Injector, model, input, computed, numberAttribute, output, signal, effect, untracked, isDevMode, ElementRef, DestroyRef, afterNextRender, afterRenderEffect, NgModule } from '@angular/core';
3
3
  import * as i1 from '@radix-ng/primitives/popper';
4
4
  import { RdxPopperAnchor, RdxPopperArrow, RdxPopper, injectPopperContentWrapperContext, RdxPopperContent, RdxPopperContentWrapper } from '@radix-ng/primitives/popper';
5
5
  import { NG_VALUE_ACCESSOR } from '@angular/forms';
@@ -8,9 +8,8 @@ import * as i1$1 from '@radix-ng/primitives/dismissable-layer';
8
8
  import { RdxDismissableLayerBranch, RdxDismissableLayer, provideRdxDismissableLayerConfig } from '@radix-ng/primitives/dismissable-layer';
9
9
  import { injectFieldRootContext } from '@radix-ng/primitives/field';
10
10
  import * as i1$2 from '@radix-ng/primitives/portal';
11
- import { RdxPortal } from '@radix-ng/primitives/portal';
12
- import * as i1$3 from '@radix-ng/primitives/presence';
13
- import { provideRdxPresenceContext, RdxPresenceDirective } from '@radix-ng/primitives/presence';
11
+ import { RdxPortalPresence } from '@radix-ng/primitives/portal';
12
+ import { provideRdxPresenceContext } from '@radix-ng/primitives/presence';
14
13
 
15
14
  /**
16
15
  * Optional positioning anchor for the popup. Put it on the element the popup should align to — for
@@ -93,6 +92,8 @@ const context = () => {
93
92
  highlightIndex: (index, reason) => root.highlightIndex(index, reason),
94
93
  setHighlight: (item, reason) => root.setHighlight(item, reason),
95
94
  clearHighlight: () => root.clearHighlightState(),
95
+ highlightItemOnHover: root.highlightItemOnHover,
96
+ keepHighlight: root.keepHighlight,
96
97
  inputElement: root.inputElement.asReadonly(),
97
98
  setInputElement: (el) => root.inputElement.set(el),
98
99
  registerTrigger: (el) => (root.triggerElement = el),
@@ -115,6 +116,17 @@ const context = () => {
115
116
  };
116
117
  };
117
118
  const [injectComboboxRootContext, provideComboboxRootContext] = createContext('RdxComboboxRootContext', 'components/combobox');
119
+ /**
120
+ * `autoHighlight` transform: pass the `'always'` / `'input-change'` string modes through verbatim,
121
+ * coerce everything else as a boolean attribute (so the bare `autoHighlight` attribute reads `true`).
122
+ *
123
+ * Kept as a named module-level function rather than an inline `transform` arrow: compodoc 1.2.1
124
+ * (the metadata source for the API contract and Storybook ArgTypes) hangs parsing an inline arrow
125
+ * combined with explicit generic union type arguments on `input()`. A plain function reference sidesteps it.
126
+ */
127
+ function coerceAutoHighlight(value) {
128
+ return value === 'always' || value === 'input-change' ? value : booleanAttribute(value);
129
+ }
118
130
  /**
119
131
  * Root of a Combobox — a filterable select. Owns selection, input text, open state, filtering, and
120
132
  * highlight-model navigation, and exposes them to the parts through {@link RdxComboboxRootContext}.
@@ -161,10 +173,10 @@ class RdxComboboxRoot {
161
173
  /**
162
174
  * Auto-highlight behavior:
163
175
  * - `false` (default): never auto-highlight;
164
- * - `true` / `'input-change'`: highlight the first match as the query changes;
176
+ * - `true` (also the bare `autoHighlight` attribute) / `'input-change'`: highlight the first match as the query changes;
165
177
  * - `'always'`: keep the first navigable item highlighted whenever the popup is open.
166
178
  */
167
- this.autoHighlight = input(false, ...(ngDevMode ? [{ debugName: "autoHighlight" }] : /* istanbul ignore next */ []));
179
+ this.autoHighlight = input(false, { ...(ngDevMode ? { debugName: "autoHighlight" } : /* istanbul ignore next */ {}), transform: coerceAutoHighlight });
168
180
  /** Resolved auto-highlight mode. */
169
181
  this.autoHighlightMode = computed(() => {
170
182
  const value = this.autoHighlight();
@@ -176,6 +188,18 @@ class RdxComboboxRoot {
176
188
  }
177
189
  return 'off';
178
190
  }, ...(ngDevMode ? [{ debugName: "autoHighlightMode" }] : /* istanbul ignore next */ []));
191
+ /**
192
+ * Whether moving the pointer over an item highlights it. `true` (default) paints `data-highlighted`
193
+ * on hover; `false` suppresses hover-driven highlight entirely, letting CSS `:hover` stay distinct
194
+ * from the `data-highlighted` (keyboard) state. Clicking an item still selects it.
195
+ */
196
+ this.highlightItemOnHover = input(true, { ...(ngDevMode ? { debugName: "highlightItemOnHover" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
197
+ /**
198
+ * Whether a pointer-driven highlight is kept when the cursor leaves the list. `false` (default)
199
+ * clears the highlight on pointer-leave; `true` retains the last hovered item highlighted. Keyboard
200
+ * navigation and auto-highlight are unaffected.
201
+ */
202
+ this.keepHighlight = input(false, { ...(ngDevMode ? { debugName: "keepHighlight" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
179
203
  /** Whether clicking the input opens the popup. */
180
204
  this.openOnInputClick = input(true, { ...(ngDevMode ? { debugName: "openOnInputClick" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
181
205
  /** Whether the popup is modal: locks page scroll and makes outside content inert while open. */
@@ -779,7 +803,7 @@ class RdxComboboxRoot {
779
803
  this.cvaDisabled.set(isDisabled);
780
804
  }
781
805
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxComboboxRoot, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
782
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxComboboxRoot, isStandalone: true, selector: "[rdxComboboxRoot]", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, defaultValue: { classPropertyName: "defaultValue", publicName: "defaultValue", isSignal: true, isRequired: false, transformFunction: null }, inputValue: { classPropertyName: "inputValue", publicName: "inputValue", 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 }, multipleInput: { classPropertyName: "multipleInput", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, selectionMode: { classPropertyName: "selectionMode", publicName: "selectionMode", isSignal: true, isRequired: false, transformFunction: null }, fillInputOnItemPress: { classPropertyName: "fillInputOnItemPress", publicName: "fillInputOnItemPress", 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 }, 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 }, 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 }, itemToStringLabel: { classPropertyName: "itemToStringLabel", publicName: "itemToStringLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", inputValue: "inputValueChange", open: "openChange", onValueChange: "onValueChange", onInputValueChange: "onInputValueChange", onOpenChange: "onOpenChange", onItemHighlighted: "onItemHighlighted", onOpenChangeComplete: "onOpenChangeComplete" }, host: { properties: { "attr.data-disabled": "disabledState() ? \"\" : undefined" } }, providers: [
806
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxComboboxRoot, isStandalone: true, selector: "[rdxComboboxRoot]", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, defaultValue: { classPropertyName: "defaultValue", publicName: "defaultValue", isSignal: true, isRequired: false, transformFunction: null }, inputValue: { classPropertyName: "inputValue", publicName: "inputValue", 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 }, multipleInput: { classPropertyName: "multipleInput", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, selectionMode: { classPropertyName: "selectionMode", publicName: "selectionMode", isSignal: true, isRequired: false, transformFunction: null }, fillInputOnItemPress: { classPropertyName: "fillInputOnItemPress", publicName: "fillInputOnItemPress", 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 }, 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 }, itemToStringLabel: { classPropertyName: "itemToStringLabel", publicName: "itemToStringLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", inputValue: "inputValueChange", open: "openChange", onValueChange: "onValueChange", onInputValueChange: "onInputValueChange", onOpenChange: "onOpenChange", onItemHighlighted: "onItemHighlighted", onOpenChangeComplete: "onOpenChangeComplete" }, host: { properties: { "attr.data-disabled": "disabledState() ? \"\" : undefined" } }, providers: [
783
807
  provideComboboxRootContext(context),
784
808
  { provide: NG_VALUE_ACCESSOR, useExisting: RdxComboboxRoot, multi: true }
785
809
  ], exportAs: ["rdxComboboxRoot"], hostDirectives: [{ directive: i1.RdxPopper }], ngImport: i0 }); }
@@ -798,7 +822,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
798
822
  '[attr.data-disabled]': 'disabledState() ? "" : undefined'
799
823
  }
800
824
  }]
801
- }], 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 }] }], inputValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputValue", required: false }] }, { type: i0.Output, args: ["inputValueChange"] }], 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 }] }], multipleInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], selectionMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionMode", required: false }] }], fillInputOnItemPress: [{ type: i0.Input, args: [{ isSignal: true, alias: "fillInputOnItemPress", 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 }] }], 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 }] }], 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 }] }], itemToStringLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemToStringLabel", required: false }] }], onValueChange: [{ type: i0.Output, args: ["onValueChange"] }], onInputValueChange: [{ type: i0.Output, args: ["onInputValueChange"] }], onOpenChange: [{ type: i0.Output, args: ["onOpenChange"] }], onItemHighlighted: [{ type: i0.Output, args: ["onItemHighlighted"] }], onOpenChangeComplete: [{ type: i0.Output, args: ["onOpenChangeComplete"] }] } });
825
+ }], 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 }] }], inputValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputValue", required: false }] }, { type: i0.Output, args: ["inputValueChange"] }], 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 }] }], multipleInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], selectionMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionMode", required: false }] }], fillInputOnItemPress: [{ type: i0.Input, args: [{ isSignal: true, alias: "fillInputOnItemPress", 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 }] }], 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 }] }], itemToStringLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemToStringLabel", required: false }] }], onValueChange: [{ type: i0.Output, args: ["onValueChange"] }], onInputValueChange: [{ type: i0.Output, args: ["onInputValueChange"] }], onOpenChange: [{ type: i0.Output, args: ["onOpenChange"] }], onItemHighlighted: [{ type: i0.Output, args: ["onItemHighlighted"] }], onOpenChangeComplete: [{ type: i0.Output, args: ["onOpenChangeComplete"] }] } });
802
826
 
803
827
  /**
804
828
  * An overlay rendered beneath the popup in `modal` mode. Place it inside the portal/presence; style
@@ -1414,6 +1438,13 @@ class RdxComboboxItem {
1414
1438
  this.rootContext.unregisterItem(this);
1415
1439
  this.group?.unregisterItem(this);
1416
1440
  });
1441
+ // Keep the highlighted option in view while navigating a scrollable popup. `block: 'nearest'`
1442
+ // makes hover a no-op (the item is already visible) and only scrolls on keyboard navigation.
1443
+ afterRenderEffect(() => {
1444
+ if (!this.virtualized() && this.isHighlighted()) {
1445
+ this.element.scrollIntoView({ block: 'nearest' });
1446
+ }
1447
+ });
1417
1448
  }
1418
1449
  onPointerDown(event) {
1419
1450
  // Keep focus on the input; prevent the item from stealing focus on pointer/mouse down.
@@ -1429,6 +1460,10 @@ class RdxComboboxItem {
1429
1460
  }
1430
1461
  }
1431
1462
  onPointerMove() {
1463
+ // Hover highlighting disabled: leave `data-highlighted` to keyboard/auto-highlight only.
1464
+ if (!this.rootContext.highlightItemOnHover()) {
1465
+ return;
1466
+ }
1432
1467
  // Ignore the first move after keyboard navigation: arrow keys scroll the list under a still
1433
1468
  // cursor, and the resulting pointer event must not yank the highlight off the keyboard target.
1434
1469
  if (this.rootContext.isKeyboardActive()) {
@@ -1445,8 +1480,24 @@ class RdxComboboxItem {
1445
1480
  this.rootContext.setHighlight(this, 'pointer');
1446
1481
  }
1447
1482
  }
1483
+ // Clear a pointer-driven highlight when the cursor leaves the list (unless `keepHighlight`).
1484
+ // Moving to another element inside the list keeps it (the next item's move re-highlights).
1485
+ onPointerLeave(event) {
1486
+ if (event.pointerType === 'touch' ||
1487
+ !this.rootContext.open() ||
1488
+ !this.rootContext.highlightItemOnHover() ||
1489
+ this.rootContext.keepHighlight()) {
1490
+ return;
1491
+ }
1492
+ const related = event.relatedTarget;
1493
+ const list = related && document.getElementById(this.rootContext.listId);
1494
+ if (list && list.contains(related)) {
1495
+ return;
1496
+ }
1497
+ this.rootContext.clearHighlight();
1498
+ }
1448
1499
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxComboboxItem, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1449
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxComboboxItem, isStandalone: true, selector: "[rdxComboboxItem]", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, 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()" }, 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: ["rdxComboboxItem"], ngImport: i0 }); }
1500
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxComboboxItem, isStandalone: true, selector: "[rdxComboboxItem]", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, 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: ["rdxComboboxItem"], ngImport: i0 }); }
1450
1501
  }
1451
1502
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxComboboxItem, decorators: [{
1452
1503
  type: Directive,
@@ -1469,7 +1520,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1469
1520
  '(pointerdown)': 'onPointerDown($event)',
1470
1521
  '(mousedown)': 'onPointerDown($event)',
1471
1522
  '(pointerup)': 'onPointerUp()',
1472
- '(pointermove)': 'onPointerMove()'
1523
+ '(pointermove)': 'onPointerMove()',
1524
+ '(pointerleave)': 'onPointerLeave($event)'
1473
1525
  }
1474
1526
  }]
1475
1527
  }], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], 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 }] }] } });
@@ -1573,18 +1625,17 @@ class RdxComboboxPopup {
1573
1625
  // is handled by the input (which calls preventDefault), so the layer won't dismiss for it.
1574
1626
  this.dismissableLayer.dismiss.subscribe(() => this.rootContext.closePopup(true));
1575
1627
  // For the "input inside the popup" pattern, move focus to the input once the popup is
1576
- // positioned. Focusing earlier fails in the browser: the portal `appendChild` blurs the
1577
- // input and an unplaced popup isn't yet visible/focusable.
1578
- effect(() => {
1628
+ // positioned. Use `afterRenderEffect` (not `effect`): when `isPositioned` flips true the
1629
+ // popup's final position/visibility is applied in the *following* render, so a synchronous
1630
+ // `effect` would call `focus()` while the element is still unfocusable and silently no-op.
1631
+ afterRenderEffect(() => {
1579
1632
  if (!this.popper.isPositioned() || !this.rootContext.open()) {
1580
1633
  return;
1581
1634
  }
1582
1635
  const input = this.rootContext.inputElement();
1583
1636
  if (input && input.closest('[rdxComboboxPopup]')) {
1584
- untracked(() => {
1585
- input.focus();
1586
- input.select();
1587
- });
1637
+ input.focus();
1638
+ input.select();
1588
1639
  }
1589
1640
  });
1590
1641
  }
@@ -1615,51 +1666,60 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1615
1666
  }], ctorParameters: () => [] });
1616
1667
 
1617
1668
  /**
1618
- * Teleports the popup into a container (default `document.body`).
1669
+ * Structural directive that teleports the combobox popup into a container (default `document.body`)
1670
+ * while the combobox is open, and keeps it mounted until any CSS exit `@keyframes` finishes.
1671
+ *
1672
+ * Apply it with the `*` microsyntax on the positioner —
1673
+ * `<div *rdxComboboxPortal rdxComboboxPositioner>` — or as an explicit `<ng-template rdxComboboxPortal>`.
1674
+ * For a custom container use the explicit form with `[container]`.
1619
1675
  *
1620
1676
  * @group Components
1621
1677
  */
1622
1678
  class RdxComboboxPortal {
1679
+ constructor() {
1680
+ /**
1681
+ * Optional container to portal the content into. Defaults to `document.body`. Declared here (and
1682
+ * forwarded to the composed {@link RdxPortalPresence}) so the autocomplete portal can re-expose it
1683
+ * through its own `hostDirectives`.
1684
+ */
1685
+ this.container = input(...(ngDevMode ? [undefined, { debugName: "container" }] : /* istanbul ignore next */ []));
1686
+ }
1623
1687
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxComboboxPortal, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1624
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxComboboxPortal, isStandalone: true, selector: "[rdxComboboxPortal]", exportAs: ["rdxComboboxPortal"], hostDirectives: [{ directive: i1$2.RdxPortal, inputs: ["container", "container"] }], ngImport: i0 }); }
1688
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxComboboxPortal, isStandalone: true, selector: "ng-template[rdxComboboxPortal]", inputs: { container: { classPropertyName: "container", publicName: "container", isSignal: true, isRequired: false, transformFunction: null } }, providers: [provideRdxPresenceContext(() => ({ present: injectComboboxRootContext().open }))], exportAs: ["rdxComboboxPortal"], hostDirectives: [{ directive: i1$2.RdxPortalPresence, inputs: ["container", "container"] }], ngImport: i0 }); }
1625
1689
  }
1626
1690
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxComboboxPortal, decorators: [{
1627
1691
  type: Directive,
1628
1692
  args: [{
1629
- selector: '[rdxComboboxPortal]',
1693
+ selector: 'ng-template[rdxComboboxPortal]',
1630
1694
  exportAs: 'rdxComboboxPortal',
1631
- hostDirectives: [{ directive: RdxPortal, inputs: ['container'] }]
1695
+ hostDirectives: [{ directive: RdxPortalPresence, inputs: ['container'] }],
1696
+ providers: [provideRdxPresenceContext(() => ({ present: injectComboboxRootContext().open }))]
1632
1697
  }]
1633
- }] });
1634
-
1698
+ }], propDecorators: { container: [{ type: i0.Input, args: [{ isSignal: true, alias: "container", required: false }] }] } });
1635
1699
  /**
1636
- * Wraps the popup template in {@link RdxPresenceDirective} so it mounts/unmounts with the open state
1637
- * and can run enter/leave animations.
1700
+ * Dev-mode guard: `rdxComboboxPortal` used to be an attribute directive on a `<div>`. It is now
1701
+ * structural, so the old `<div rdxComboboxPortal>` markup would silently stop portaling — fail loudly
1702
+ * instead.
1638
1703
  *
1639
1704
  * @group Components
1640
1705
  */
1641
- class RdxComboboxPortalPresence {
1642
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxComboboxPortalPresence, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1643
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxComboboxPortalPresence, isStandalone: true, selector: "ng-template[rdxComboboxPortalPresence]", providers: [
1644
- provideRdxPresenceContext(() => {
1645
- const context = injectComboboxRootContext();
1646
- return { present: context.open };
1647
- })
1648
- ], hostDirectives: [{ directive: i1$3.RdxPresenceDirective }], ngImport: i0 }); }
1706
+ class RdxComboboxPortalMisuseGuard {
1707
+ constructor() {
1708
+ if (isDevMode()) {
1709
+ throw new Error('[rdxComboboxPortal] is now a structural directive. ' +
1710
+ 'Use `*rdxComboboxPortal` on the positioner element or `<ng-template rdxComboboxPortal>`. ' +
1711
+ 'rdxComboboxPortalPresence has been removed. See https://radix-ng.com/components/combobox.md');
1712
+ }
1713
+ }
1714
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxComboboxPortalMisuseGuard, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1715
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxComboboxPortalMisuseGuard, isStandalone: true, selector: "[rdxComboboxPortal]:not(ng-template)", ngImport: i0 }); }
1649
1716
  }
1650
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxComboboxPortalPresence, decorators: [{
1717
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxComboboxPortalMisuseGuard, decorators: [{
1651
1718
  type: Directive,
1652
1719
  args: [{
1653
- selector: 'ng-template[rdxComboboxPortalPresence]',
1654
- hostDirectives: [RdxPresenceDirective],
1655
- providers: [
1656
- provideRdxPresenceContext(() => {
1657
- const context = injectComboboxRootContext();
1658
- return { present: context.open };
1659
- })
1660
- ]
1720
+ selector: '[rdxComboboxPortal]:not(ng-template)'
1661
1721
  }]
1662
- }] });
1722
+ }], ctorParameters: () => [] });
1663
1723
 
1664
1724
  /**
1665
1725
  * Positions the popup relative to the input anchor using the popper engine. Re-exposes the popper
@@ -1840,7 +1900,7 @@ const _importsCombobox = [
1840
1900
  RdxComboboxIcon,
1841
1901
  RdxComboboxClear,
1842
1902
  RdxComboboxPortal,
1843
- RdxComboboxPortalPresence,
1903
+ RdxComboboxPortalMisuseGuard,
1844
1904
  RdxComboboxBackdrop,
1845
1905
  RdxComboboxPositioner,
1846
1906
  RdxComboboxPopup,
@@ -1867,7 +1927,7 @@ class RdxComboboxModule {
1867
1927
  RdxComboboxIcon,
1868
1928
  RdxComboboxClear,
1869
1929
  RdxComboboxPortal,
1870
- RdxComboboxPortalPresence,
1930
+ RdxComboboxPortalMisuseGuard,
1871
1931
  RdxComboboxBackdrop,
1872
1932
  RdxComboboxPositioner,
1873
1933
  RdxComboboxPopup,
@@ -1890,7 +1950,7 @@ class RdxComboboxModule {
1890
1950
  RdxComboboxIcon,
1891
1951
  RdxComboboxClear,
1892
1952
  RdxComboboxPortal,
1893
- RdxComboboxPortalPresence,
1953
+ RdxComboboxPortalMisuseGuard,
1894
1954
  RdxComboboxBackdrop,
1895
1955
  RdxComboboxPositioner,
1896
1956
  RdxComboboxPopup,
@@ -1919,5 +1979,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1919
1979
  * Generated bundle index. Do not edit.
1920
1980
  */
1921
1981
 
1922
- export { RdxComboboxAnchor, RdxComboboxArrow, RdxComboboxBackdrop, RdxComboboxChip, RdxComboboxChipRemove, RdxComboboxChips, RdxComboboxClear, RdxComboboxEmpty, RdxComboboxGroup, RdxComboboxGroupLabel, RdxComboboxIcon, RdxComboboxInput, RdxComboboxItem, RdxComboboxItemIndicator, RdxComboboxLabel, RdxComboboxList, RdxComboboxModule, RdxComboboxPopup, RdxComboboxPortal, RdxComboboxPortalPresence, RdxComboboxPositioner, RdxComboboxRoot, RdxComboboxStatus, RdxComboboxTrigger, RdxComboboxValue, _importsCombobox, injectComboboxChipContext, injectComboboxGroupContext, injectComboboxItemContext, injectComboboxRootContext, provideComboboxChipContext, provideComboboxGroupContext, provideComboboxItemContext, provideComboboxRootContext };
1982
+ export { RdxComboboxAnchor, RdxComboboxArrow, RdxComboboxBackdrop, RdxComboboxChip, RdxComboboxChipRemove, RdxComboboxChips, RdxComboboxClear, RdxComboboxEmpty, RdxComboboxGroup, RdxComboboxGroupLabel, RdxComboboxIcon, RdxComboboxInput, RdxComboboxItem, RdxComboboxItemIndicator, RdxComboboxLabel, RdxComboboxList, RdxComboboxModule, RdxComboboxPopup, RdxComboboxPortal, RdxComboboxPortalMisuseGuard, RdxComboboxPositioner, RdxComboboxRoot, RdxComboboxStatus, RdxComboboxTrigger, RdxComboboxValue, _importsCombobox, injectComboboxChipContext, injectComboboxGroupContext, injectComboboxItemContext, injectComboboxRootContext, provideComboboxChipContext, provideComboboxGroupContext, provideComboboxItemContext, provideComboboxRootContext };
1923
1983
  //# sourceMappingURL=radix-ng-primitives-combobox.mjs.map