@radix-ng/primitives 0.51.0 → 1.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/fesm2022/radix-ng-primitives-accordion.mjs +105 -38
  2. package/fesm2022/radix-ng-primitives-accordion.mjs.map +1 -1
  3. package/fesm2022/radix-ng-primitives-alert-dialog.mjs +221 -129
  4. package/fesm2022/radix-ng-primitives-alert-dialog.mjs.map +1 -1
  5. package/fesm2022/radix-ng-primitives-arrow.mjs +20 -4
  6. package/fesm2022/radix-ng-primitives-arrow.mjs.map +1 -1
  7. package/fesm2022/radix-ng-primitives-aspect-ratio.mjs.map +1 -1
  8. package/fesm2022/radix-ng-primitives-avatar.mjs +54 -61
  9. package/fesm2022/radix-ng-primitives-avatar.mjs.map +1 -1
  10. package/fesm2022/radix-ng-primitives-button.mjs +123 -0
  11. package/fesm2022/radix-ng-primitives-button.mjs.map +1 -0
  12. package/fesm2022/radix-ng-primitives-calendar.mjs.map +1 -1
  13. package/fesm2022/radix-ng-primitives-checkbox.mjs +378 -54
  14. package/fesm2022/radix-ng-primitives-checkbox.mjs.map +1 -1
  15. package/fesm2022/radix-ng-primitives-collapsible.mjs +182 -81
  16. package/fesm2022/radix-ng-primitives-collapsible.mjs.map +1 -1
  17. package/fesm2022/radix-ng-primitives-collection.mjs +40 -57
  18. package/fesm2022/radix-ng-primitives-collection.mjs.map +1 -1
  19. package/fesm2022/radix-ng-primitives-config.mjs.map +1 -1
  20. package/fesm2022/radix-ng-primitives-context-menu.mjs +140 -424
  21. package/fesm2022/radix-ng-primitives-context-menu.mjs.map +1 -1
  22. package/fesm2022/radix-ng-primitives-core.mjs +735 -744
  23. package/fesm2022/radix-ng-primitives-core.mjs.map +1 -1
  24. package/fesm2022/radix-ng-primitives-cropper.mjs +1 -0
  25. package/fesm2022/radix-ng-primitives-cropper.mjs.map +1 -1
  26. package/fesm2022/radix-ng-primitives-date-field.mjs +51 -45
  27. package/fesm2022/radix-ng-primitives-date-field.mjs.map +1 -1
  28. package/fesm2022/radix-ng-primitives-dialog.mjs +655 -327
  29. package/fesm2022/radix-ng-primitives-dialog.mjs.map +1 -1
  30. package/fesm2022/radix-ng-primitives-dismissable-layer.mjs +70 -46
  31. package/fesm2022/radix-ng-primitives-dismissable-layer.mjs.map +1 -1
  32. package/fesm2022/radix-ng-primitives-drawer.mjs +1059 -0
  33. package/fesm2022/radix-ng-primitives-drawer.mjs.map +1 -0
  34. package/fesm2022/radix-ng-primitives-editable.mjs.map +1 -1
  35. package/fesm2022/radix-ng-primitives-field.mjs +363 -0
  36. package/fesm2022/radix-ng-primitives-field.mjs.map +1 -0
  37. package/fesm2022/radix-ng-primitives-fieldset.mjs +79 -0
  38. package/fesm2022/radix-ng-primitives-fieldset.mjs.map +1 -0
  39. package/fesm2022/radix-ng-primitives-focus-scope.mjs +23 -8
  40. package/fesm2022/radix-ng-primitives-focus-scope.mjs.map +1 -1
  41. package/fesm2022/radix-ng-primitives-input.mjs +172 -0
  42. package/fesm2022/radix-ng-primitives-input.mjs.map +1 -0
  43. package/fesm2022/radix-ng-primitives-label.mjs +6 -6
  44. package/fesm2022/radix-ng-primitives-label.mjs.map +1 -1
  45. package/fesm2022/radix-ng-primitives-menu.mjs +1480 -344
  46. package/fesm2022/radix-ng-primitives-menu.mjs.map +1 -1
  47. package/fesm2022/radix-ng-primitives-menubar.mjs +290 -162
  48. package/fesm2022/radix-ng-primitives-menubar.mjs.map +1 -1
  49. package/fesm2022/radix-ng-primitives-meter.mjs +271 -0
  50. package/fesm2022/radix-ng-primitives-meter.mjs.map +1 -0
  51. package/fesm2022/radix-ng-primitives-navigation-menu.mjs +1052 -1553
  52. package/fesm2022/radix-ng-primitives-navigation-menu.mjs.map +1 -1
  53. package/fesm2022/radix-ng-primitives-number-field.mjs +1102 -367
  54. package/fesm2022/radix-ng-primitives-number-field.mjs.map +1 -1
  55. package/fesm2022/radix-ng-primitives-pagination.mjs.map +1 -1
  56. package/fesm2022/radix-ng-primitives-popover.mjs +978 -989
  57. package/fesm2022/radix-ng-primitives-popover.mjs.map +1 -1
  58. package/fesm2022/radix-ng-primitives-popper.mjs +91 -41
  59. package/fesm2022/radix-ng-primitives-popper.mjs.map +1 -1
  60. package/fesm2022/radix-ng-primitives-portal.mjs +34 -10
  61. package/fesm2022/radix-ng-primitives-portal.mjs.map +1 -1
  62. package/fesm2022/radix-ng-primitives-presence.mjs +134 -246
  63. package/fesm2022/radix-ng-primitives-presence.mjs.map +1 -1
  64. package/fesm2022/radix-ng-primitives-preview-card.mjs +997 -0
  65. package/fesm2022/radix-ng-primitives-preview-card.mjs.map +1 -0
  66. package/fesm2022/radix-ng-primitives-progress.mjs +223 -84
  67. package/fesm2022/radix-ng-primitives-progress.mjs.map +1 -1
  68. package/fesm2022/radix-ng-primitives-radio.mjs +191 -51
  69. package/fesm2022/radix-ng-primitives-radio.mjs.map +1 -1
  70. package/fesm2022/radix-ng-primitives-roving-focus.mjs +96 -50
  71. package/fesm2022/radix-ng-primitives-roving-focus.mjs.map +1 -1
  72. package/fesm2022/radix-ng-primitives-select.mjs +791 -509
  73. package/fesm2022/radix-ng-primitives-select.mjs.map +1 -1
  74. package/fesm2022/radix-ng-primitives-separator.mjs +12 -35
  75. package/fesm2022/radix-ng-primitives-separator.mjs.map +1 -1
  76. package/fesm2022/radix-ng-primitives-slider.mjs +969 -717
  77. package/fesm2022/radix-ng-primitives-slider.mjs.map +1 -1
  78. package/fesm2022/radix-ng-primitives-stepper.mjs +15 -19
  79. package/fesm2022/radix-ng-primitives-stepper.mjs.map +1 -1
  80. package/fesm2022/radix-ng-primitives-switch.mjs +125 -113
  81. package/fesm2022/radix-ng-primitives-switch.mjs.map +1 -1
  82. package/fesm2022/radix-ng-primitives-tabs.mjs +381 -108
  83. package/fesm2022/radix-ng-primitives-tabs.mjs.map +1 -1
  84. package/fesm2022/radix-ng-primitives-time-field.mjs +55 -46
  85. package/fesm2022/radix-ng-primitives-time-field.mjs.map +1 -1
  86. package/fesm2022/radix-ng-primitives-toggle-group.mjs +121 -247
  87. package/fesm2022/radix-ng-primitives-toggle-group.mjs.map +1 -1
  88. package/fesm2022/radix-ng-primitives-toggle.mjs +98 -61
  89. package/fesm2022/radix-ng-primitives-toggle.mjs.map +1 -1
  90. package/fesm2022/radix-ng-primitives-toolbar.mjs +303 -92
  91. package/fesm2022/radix-ng-primitives-toolbar.mjs.map +1 -1
  92. package/fesm2022/radix-ng-primitives-tooltip.mjs +690 -1071
  93. package/fesm2022/radix-ng-primitives-tooltip.mjs.map +1 -1
  94. package/fesm2022/radix-ng-primitives-visually-hidden.mjs +25 -66
  95. package/fesm2022/radix-ng-primitives-visually-hidden.mjs.map +1 -1
  96. package/meter/README.md +3 -0
  97. package/navigation-menu/README.md +2 -1
  98. package/package.json +31 -18
  99. package/portal/README.md +2 -0
  100. package/preview-card/README.md +3 -0
  101. package/schematics/collection.json +1 -0
  102. package/schematics/ng-add/index.d.ts +3 -2
  103. package/schematics/ng-add/index.js +62 -31
  104. package/schematics/ng-add/index.js.map +1 -1
  105. package/schematics/ng-add/package-config.d.ts +4 -2
  106. package/schematics/ng-add/package-config.js +10 -2
  107. package/schematics/ng-add/package-config.js.map +1 -1
  108. package/schematics/ng-add/schema.d.ts +3 -0
  109. package/schematics/ng-add/schema.js +3 -0
  110. package/schematics/ng-add/schema.js.map +1 -0
  111. package/schematics/ng-add/schema.json +14 -0
  112. package/select/README.md +2 -0
  113. package/types/radix-ng-primitives-accordion.d.ts +48 -14
  114. package/types/radix-ng-primitives-alert-dialog.d.ts +95 -38
  115. package/types/radix-ng-primitives-arrow.d.ts +1 -1
  116. package/types/radix-ng-primitives-aspect-ratio.d.ts +1 -1
  117. package/types/radix-ng-primitives-avatar.d.ts +7 -11
  118. package/types/radix-ng-primitives-button.d.ts +73 -0
  119. package/types/radix-ng-primitives-calendar.d.ts +1 -2
  120. package/types/radix-ng-primitives-checkbox.d.ts +201 -32
  121. package/types/radix-ng-primitives-collapsible.d.ts +112 -39
  122. package/types/radix-ng-primitives-collection.d.ts +38 -34
  123. package/types/radix-ng-primitives-config.d.ts +1 -1
  124. package/types/radix-ng-primitives-context-menu.d.ts +60 -116
  125. package/types/radix-ng-primitives-core.d.ts +307 -236
  126. package/types/radix-ng-primitives-cropper.d.ts +2 -2
  127. package/types/radix-ng-primitives-date-field.d.ts +38 -23
  128. package/types/radix-ng-primitives-dialog.d.ts +282 -165
  129. package/types/radix-ng-primitives-dismissable-layer.d.ts +15 -7
  130. package/types/radix-ng-primitives-drawer.d.ts +448 -0
  131. package/types/radix-ng-primitives-editable.d.ts +1 -1
  132. package/types/radix-ng-primitives-field.d.ts +373 -0
  133. package/types/radix-ng-primitives-fieldset.d.ts +48 -0
  134. package/types/radix-ng-primitives-focus-scope.d.ts +13 -5
  135. package/types/radix-ng-primitives-input.d.ts +87 -0
  136. package/types/radix-ng-primitives-label.d.ts +0 -1
  137. package/types/radix-ng-primitives-menu.d.ts +572 -99
  138. package/types/radix-ng-primitives-menubar.d.ts +60 -50
  139. package/types/radix-ng-primitives-meter.d.ts +193 -0
  140. package/types/radix-ng-primitives-navigation-menu.d.ts +422 -340
  141. package/types/radix-ng-primitives-number-field.d.ts +405 -145
  142. package/types/radix-ng-primitives-pagination.d.ts +2 -2
  143. package/types/radix-ng-primitives-popover.d.ts +365 -351
  144. package/types/radix-ng-primitives-popper.d.ts +49 -9
  145. package/types/radix-ng-primitives-portal.d.ts +14 -6
  146. package/types/radix-ng-primitives-presence.d.ts +28 -76
  147. package/types/radix-ng-primitives-preview-card.d.ts +359 -0
  148. package/types/radix-ng-primitives-progress.d.ts +174 -48
  149. package/types/radix-ng-primitives-radio.d.ts +55 -25
  150. package/types/radix-ng-primitives-roving-focus.d.ts +30 -21
  151. package/types/radix-ng-primitives-select.d.ts +475 -177
  152. package/types/radix-ng-primitives-separator.d.ts +7 -32
  153. package/types/radix-ng-primitives-slider.d.ts +315 -201
  154. package/types/radix-ng-primitives-stepper.d.ts +5 -7
  155. package/types/radix-ng-primitives-switch.d.ts +86 -71
  156. package/types/radix-ng-primitives-tabs.d.ts +213 -79
  157. package/types/radix-ng-primitives-time-field.d.ts +42 -27
  158. package/types/radix-ng-primitives-toggle-group.d.ts +85 -164
  159. package/types/radix-ng-primitives-toggle.d.ts +43 -53
  160. package/types/radix-ng-primitives-toolbar.d.ts +163 -38
  161. package/types/radix-ng-primitives-tooltip.d.ts +347 -384
  162. package/types/radix-ng-primitives-visually-hidden.d.ts +19 -19
  163. package/dropdown-menu/README.md +0 -1
  164. package/fesm2022/radix-ng-primitives-dropdown-menu.mjs +0 -581
  165. package/fesm2022/radix-ng-primitives-dropdown-menu.mjs.map +0 -1
  166. package/fesm2022/radix-ng-primitives-hover-card.mjs +0 -1238
  167. package/fesm2022/radix-ng-primitives-hover-card.mjs.map +0 -1
  168. package/fesm2022/radix-ng-primitives-select2.mjs +0 -897
  169. package/fesm2022/radix-ng-primitives-select2.mjs.map +0 -1
  170. package/fesm2022/radix-ng-primitives-tooltip2.mjs +0 -735
  171. package/fesm2022/radix-ng-primitives-tooltip2.mjs.map +0 -1
  172. package/hover-card/README.md +0 -3
  173. package/select2/README.md +0 -3
  174. package/tooltip2/README.md +0 -3
  175. package/types/radix-ng-primitives-dropdown-menu.d.ts +0 -171
  176. package/types/radix-ng-primitives-hover-card.d.ts +0 -471
  177. package/types/radix-ng-primitives-select2.d.ts +0 -511
  178. package/types/radix-ng-primitives-tooltip2.d.ts +0 -325
@@ -1,617 +1,899 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, Input, Component, NgZone, ElementRef, contentChild, Directive, ChangeDetectorRef, DestroyRef, forwardRef, contentChildren, viewChild, signal, computed, EventEmitter, booleanAttribute, Output, ContentChildren, NgModule } from '@angular/core';
3
- import { ActiveDescendantKeyManager } from '@angular/cdk/a11y';
4
- import { Directionality } from '@angular/cdk/bidi';
5
- import { Subscription, defer, merge, take, switchMap, delay, Subject, startWith, pairwise } from 'rxjs';
6
- import { ENTER, SPACE } from '@angular/cdk/keycodes';
7
- import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
8
- import { SelectionModel } from '@angular/cdk/collections';
9
- import * as i1 from '@angular/cdk/overlay';
10
- import { Overlay, CdkConnectedOverlay, OverlayModule } from '@angular/cdk/overlay';
2
+ import { inject, model, input, booleanAttribute, computed, signal, Directive, InjectionToken, ElementRef, afterNextRender, effect, ContentChild, linkedSignal, DestroyRef, numberAttribute, forwardRef } from '@angular/core';
3
+ import { outputFromObservable, outputToObservable } from '@angular/core/rxjs-interop';
4
+ import * as i3 from '@radix-ng/primitives/collection';
5
+ import { RdxCollectionProvider, RdxCollectionItem } from '@radix-ng/primitives/collection';
6
+ import { isEqual, getActiveElement, createContext, isNullish, injectId, handleAndDispatchCustomEvent } from '@radix-ng/primitives/core';
7
+ import * as i2 from '@radix-ng/primitives/dismissable-layer';
8
+ import { RdxDismissableLayer, provideRdxDismissableLayerConfig } from '@radix-ng/primitives/dismissable-layer';
9
+ import * as i1$1 from '@radix-ng/primitives/focus-scope';
10
+ import { RdxFocusScope } from '@radix-ng/primitives/focus-scope';
11
+ import * as i1 from '@radix-ng/primitives/popper';
12
+ import { RdxPopper, RdxPopperContent, RdxPopperContentWrapper, RdxPopperAnchor } from '@radix-ng/primitives/popper';
13
+ import * as i1$2 from '@radix-ng/primitives/portal';
14
+ import { RdxPortal } from '@radix-ng/primitives/portal';
15
+ import * as i1$3 from '@radix-ng/primitives/presence';
16
+ import { provideRdxPresenceContext, RdxPresenceDirective } from '@radix-ng/primitives/presence';
11
17
 
12
- class RdxSelectValueDirective {
13
- constructor() {
14
- this.select = inject(RdxSelectComponent);
18
+ const OPEN_KEYS = [' ', 'Enter', 'ArrowUp', 'ArrowDown'];
19
+ const SELECTION_KEYS = [' ', 'Enter'];
20
+ const CONTENT_MARGIN = 10;
21
+ function valueComparator(value, currentValue, comparator) {
22
+ if (value === undefined)
23
+ return false;
24
+ else if (Array.isArray(value))
25
+ return value.some((val) => compare(val, currentValue, comparator));
26
+ else
27
+ return compare(value, currentValue, comparator);
28
+ }
29
+ function compare(value, currentValue, comparator) {
30
+ if (value === undefined || currentValue === undefined)
31
+ return false;
32
+ if (typeof value === 'string')
33
+ return value === currentValue;
34
+ if (typeof comparator === 'function')
35
+ return comparator(value, currentValue);
36
+ if (typeof comparator === 'string')
37
+ return value?.[comparator] === currentValue?.[comparator];
38
+ return isEqual(value, currentValue);
39
+ }
40
+ function shouldShowPlaceholder(value) {
41
+ return value === undefined || value === null || value === '' || (Array.isArray(value) && value.length === 0);
42
+ }
43
+ function focusFirst(candidates) {
44
+ const PREVIOUSLY_FOCUSED_ELEMENT = getActiveElement();
45
+ for (const candidate of candidates) {
46
+ // if focus is already where we want to go, we don't want to keep going through the candidates
47
+ if (candidate === PREVIOUSLY_FOCUSED_ELEMENT)
48
+ return;
49
+ candidate.focus();
50
+ if (getActiveElement() !== PREVIOUSLY_FOCUSED_ELEMENT)
51
+ return;
15
52
  }
16
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectValueDirective, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
17
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.9", type: RdxSelectValueDirective, isStandalone: true, selector: "[rdxSelectValue]", inputs: { placeholder: "placeholder" }, exportAs: ["rdxSelectValue"], ngImport: i0, template: `
18
- {{ select.selectionModel.isEmpty() ? placeholder : select.selected }}
19
- `, isInline: true, styles: [":host{pointer-events:none}\n"] }); }
20
53
  }
21
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectValueDirective, decorators: [{
22
- type: Component,
23
- args: [{ selector: '[rdxSelectValue]', standalone: true, exportAs: 'rdxSelectValue', template: `
24
- {{ select.selectionModel.isEmpty() ? placeholder : select.selected }}
25
- `, styles: [":host{pointer-events:none}\n"] }]
26
- }], propDecorators: { placeholder: [{
27
- type: Input
28
- }] } });
29
54
 
30
- class RdxSelectTriggerDirective {
55
+ const context$2 = () => {
56
+ const context = inject(RdxSelectRoot);
57
+ return {
58
+ triggerElement: context.triggerElement,
59
+ valueElement: context.valueElement,
60
+ triggerPointerDownPosRef: context.triggerPointerDownPosRef,
61
+ contentId: '',
62
+ dir: context.dir,
63
+ value: context.value,
64
+ multiple: context.multiple,
65
+ by: context.by,
66
+ open: context.open,
67
+ disabled: context.disabled,
68
+ optionsSet: context.optionsSet,
69
+ onOptionAdd: (option) => {
70
+ const existingOption = context.getOption(option());
71
+ if (existingOption) {
72
+ context.optionsSet().delete(existingOption);
73
+ }
74
+ context.optionsSet().add(option());
75
+ },
76
+ onOptionRemove: (option) => {
77
+ const existingOption = context.getOption(option());
78
+ if (existingOption) {
79
+ context.optionsSet().delete(existingOption);
80
+ }
81
+ },
82
+ onValueChange: context.handleValueChange,
83
+ onTriggerChange: (node) => {
84
+ context.triggerElement.set(node.nativeElement);
85
+ },
86
+ onValueElementChange: (node) => {
87
+ context.valueElement.set(node);
88
+ },
89
+ onOpenChange: (value) => {
90
+ context.open.set(value);
91
+ }
92
+ };
93
+ };
94
+ const [injectSelectRootContext, provideSelectRootContext] = createContext('RdxSelectRootContext');
95
+ class RdxSelectRoot {
31
96
  constructor() {
32
- this.ngZone = inject(NgZone);
33
- this.nativeElement = inject(ElementRef).nativeElement;
34
- this.select = inject(RdxSelectComponent);
35
- this.value = contentChild.required(RdxSelectValueDirective);
36
- }
37
- ngAfterViewInit() {
38
- this.select.triggerSize.set([this.nativeElement.offsetWidth, this.nativeElement.offsetHeight]);
39
- this.observeTriggerResize();
40
- }
41
- ngOnDestroy() {
42
- this.resizeObserver?.disconnect();
43
- this.resizeObserver = null;
44
- }
45
- focus() {
46
- this.nativeElement.focus();
47
- }
48
- observeTriggerResize() {
49
- if (typeof ResizeObserver === 'undefined' || !ResizeObserver) {
50
- return;
97
+ this.open = model(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
98
+ this.value = model(...(ngDevMode ? [undefined, { debugName: "value" }] : /* istanbul ignore next */ []));
99
+ this.multiple = input(false, { ...(ngDevMode ? { debugName: "multiple" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
100
+ this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
101
+ this.dir = input('ltr', ...(ngDevMode ? [{ debugName: "dir" }] : /* istanbul ignore next */ []));
102
+ /** Use this to compare objects by a particular field, or pass your own comparison function for complete control over how objects are compared. */
103
+ this.by = input(...(ngDevMode ? [undefined, { debugName: "by" }] : /* istanbul ignore next */ []));
104
+ this.isEmptyModelValue = computed(() => {
105
+ if (this.multiple() && Array.isArray(this.value())) {
106
+ return Array(this.value())?.length === 0;
107
+ }
108
+ else {
109
+ return isNullish(this.value());
110
+ }
111
+ }, ...(ngDevMode ? [{ debugName: "isEmptyModelValue" }] : /* istanbul ignore next */ []));
112
+ this.optionsSet = signal(new Set(), ...(ngDevMode ? [{ debugName: "optionsSet" }] : /* istanbul ignore next */ []));
113
+ // The native `select` only associates the correct default value if the corresponding
114
+ // `option` is rendered as a child **at the same time** as itself.
115
+ // Because it might take a few renders for our items to gather the information to build
116
+ // the native `option`(s), we generate a key on the `select` to make sure Vue re-builds it
117
+ // each time the options change.
118
+ this.nativeSelectKey = computed(() => {
119
+ return Array.from(this.optionsSet())
120
+ .map((option) => option.value)
121
+ .join(';');
122
+ }, ...(ngDevMode ? [{ debugName: "nativeSelectKey" }] : /* istanbul ignore next */ []));
123
+ this.triggerElement = signal(null, ...(ngDevMode ? [{ debugName: "triggerElement" }] : /* istanbul ignore next */ []));
124
+ this.valueElement = signal(null, ...(ngDevMode ? [{ debugName: "valueElement" }] : /* istanbul ignore next */ []));
125
+ this.triggerPointerDownPosRef = signal({
126
+ x: 0,
127
+ y: 0
128
+ }, ...(ngDevMode ? [{ debugName: "triggerPointerDownPosRef" }] : /* istanbul ignore next */ []));
129
+ }
130
+ getOption(value) {
131
+ return Array.from(this.optionsSet()).find((option) => valueComparator(value, option.value, this.by()));
132
+ }
133
+ handleValueChange(value) {
134
+ if (this.multiple()) {
135
+ const array = Array.isArray(this.value()) ? [...Array(this.value())] : [];
136
+ const index = array.findIndex((i) => compare(i, value, this.by()));
137
+ index === -1 ? array.push(value) : array.splice(index, 1);
138
+ this.value.set([...array]);
139
+ }
140
+ else {
141
+ this.value.set(value);
51
142
  }
52
- this.ngZone.runOutsideAngular(() => {
53
- this.resizeObserver = new ResizeObserver(() => {
54
- this.select.triggerSize.set([this.nativeElement.offsetWidth, this.nativeElement.offsetHeight]);
55
- });
56
- this.resizeObserver.observe(this.nativeElement);
57
- });
58
143
  }
59
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
60
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "21.2.9", type: RdxSelectTriggerDirective, isStandalone: true, selector: "[rdxSelectTrigger]", host: { properties: { "attr.type": "\"button\"", "attr.role": "\"combobox\"", "attr.aria-autocomplete": "\"none\"", "attr.dir": "select.dir?.value", "attr.aria-expanded": "select.open", "attr.aria-required": "select.required", "attr.disabled": "select.disabled ? \"\" : null", "attr.data-disabled": "select.disabled ? \"\" : null", "attr.data-state": "select.open ? 'open': 'closed'", "attr.data-placeholder": "value().placeholder || null" } }, queries: [{ propertyName: "value", first: true, predicate: RdxSelectValueDirective, descendants: true, isSignal: true }], ngImport: i0 }); }
144
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectRoot, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
145
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxSelectRoot, isStandalone: true, selector: "[rdxSelectRoot]", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, dir: { classPropertyName: "dir", publicName: "dir", isSignal: true, isRequired: false, transformFunction: null }, by: { classPropertyName: "by", publicName: "by", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", value: "valueChange" }, providers: [provideSelectRootContext(context$2)], exportAs: ["rdxSelectRoot"], hostDirectives: [{ directive: i1.RdxPopper }], ngImport: i0 }); }
61
146
  }
62
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectTriggerDirective, decorators: [{
147
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectRoot, decorators: [{
63
148
  type: Directive,
64
149
  args: [{
65
- selector: '[rdxSelectTrigger]',
66
- standalone: true,
67
- host: {
68
- '[attr.type]': '"button"',
69
- '[attr.role]': '"combobox"',
70
- '[attr.aria-autocomplete]': '"none"',
71
- '[attr.dir]': 'select.dir?.value',
72
- '[attr.aria-expanded]': 'select.open',
73
- '[attr.aria-required]': 'select.required',
74
- '[attr.disabled]': 'select.disabled ? "" : null',
75
- '[attr.data-disabled]': 'select.disabled ? "" : null',
76
- '[attr.data-state]': "select.open ? 'open': 'closed'",
77
- '[attr.data-placeholder]': 'value().placeholder || null'
78
- }
150
+ selector: '[rdxSelectRoot]',
151
+ exportAs: 'rdxSelectRoot',
152
+ providers: [provideSelectRootContext(context$2)],
153
+ hostDirectives: [RdxPopper]
79
154
  }]
80
- }], propDecorators: { value: [{ type: i0.ContentChild, args: [i0.forwardRef(() => RdxSelectValueDirective), { isSignal: true }] }] } });
155
+ }], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], dir: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }], by: [{ type: i0.Input, args: [{ isSignal: true, alias: "by", required: false }] }] } });
81
156
 
82
- let nextId$1 = 0;
83
- class RdxSelectComponent {
84
- constructor() {
85
- this.overlay = inject(Overlay);
86
- this.elementRef = inject(ElementRef);
87
- this.changeDetectorRef = inject(ChangeDetectorRef);
88
- this.destroyRef = inject(DestroyRef);
89
- this.ngZone = inject(NgZone);
90
- this.trigger = contentChild.required(RdxSelectTriggerDirective);
91
- this.content = contentChild.required(forwardRef(() => RdxSelectContentDirective));
92
- this.items = contentChildren(forwardRef(() => RdxSelectItemDirective), { ...(ngDevMode ? { debugName: "items" } : /* istanbul ignore next */ {}), descendants: true });
93
- this.overlayDir = viewChild.required(CdkConnectedOverlay);
94
- /**
95
- * Tuple type for the trigger element size. Set by the trigger element itself.
96
- * The first element is the width and the second element is the height.
97
- * @returns The size of the trigger element.
98
- */
99
- this.triggerSize = signal([0, 0], ...(ngDevMode ? [{ debugName: "triggerSize" }] : /* istanbul ignore next */ []));
100
- /**
101
- * The width of the trigger element.
102
- * @returns The width of the trigger element.
103
- */
104
- this.triggerWidth = computed(() => this.triggerSize()[0], ...(ngDevMode ? [{ debugName: "triggerWidth" }] : /* istanbul ignore next */ []));
105
- /**
106
- * This position config ensures that the top "start" corner of the overlay
107
- * is aligned with the top "start" of the origin by default (overlapping
108
- * the trigger completely). If the panel cannot fit below the trigger, it
109
- * will fall back to a position above the trigger.
110
- */
111
- this.positions = [
112
- {
113
- originX: 'start',
114
- originY: 'bottom',
115
- overlayX: 'start',
116
- overlayY: 'top'
117
- },
118
- {
119
- originX: 'start',
120
- originY: 'top',
121
- overlayX: 'start',
122
- overlayY: 'bottom'
157
+ const context$1 = () => {
158
+ const context = inject(RdxSelectContent);
159
+ return {
160
+ content: context.content,
161
+ viewport: context.viewport,
162
+ isPositioned: context.isPositioned,
163
+ selectedItem: context.selectedItem,
164
+ selectedItemText: context.selectedItemText,
165
+ onViewportChange: (node) => {
166
+ context.viewport.set(node);
167
+ },
168
+ onItemLeave: () => {
169
+ context.content()?.focus();
170
+ },
171
+ itemRefCallback: (node, value, disabled) => {
172
+ const isFirstValidItem = !context.firstValidItemFoundRef() && !disabled;
173
+ const isSelectedItem = valueComparator(context.rootContext.value(), value, context.rootContext.by());
174
+ if (isSelectedItem || isFirstValidItem) {
175
+ context.selectedItem.set(node);
123
176
  }
124
- ];
125
- this.closeSubscription = Subscription.EMPTY;
126
- /**
127
- * @ignore
128
- */
129
- this.dir = inject(Directionality, { optional: true });
177
+ if (isFirstValidItem) {
178
+ context.firstValidItemFoundRef.set(true);
179
+ }
180
+ },
181
+ itemTextRefCallback: (node, value, disabled) => {
182
+ const isFirstValidItem = !context.firstValidItemFoundRef() && !disabled;
183
+ const isSelectedItem = valueComparator(context.rootContext.value(), value, context.rootContext.by());
184
+ if (isSelectedItem || isFirstValidItem) {
185
+ context.selectedItemText.set(node);
186
+ }
187
+ }
188
+ };
189
+ };
190
+ const [injectSelectContentContext, provideSelectContentContext] = createContext('RdxSelectContent');
191
+ const RDX_SELECT_POSITIONER_TOKEN = new InjectionToken('RDX_SELECT_POSITIONER_TOKEN');
192
+ class RdxSelectContent {
193
+ set positioner(port) {
194
+ if (port) {
195
+ port.placed.subscribe(() => {
196
+ this.focusSelectedItem();
197
+ this.isPositioned.set(true);
198
+ });
199
+ }
200
+ }
201
+ constructor() {
202
+ this.dismissableLayer = inject(RdxDismissableLayer);
203
+ this.currentElement = inject(ElementRef);
204
+ this.collection = inject(RdxCollectionProvider);
205
+ this.rootContext = injectSelectRootContext();
206
+ this.selectedItem = signal(undefined, ...(ngDevMode ? [{ debugName: "selectedItem" }] : /* istanbul ignore next */ []));
207
+ this.selectedItemText = signal(undefined, ...(ngDevMode ? [{ debugName: "selectedItemText" }] : /* istanbul ignore next */ []));
208
+ this.firstValidItemFoundRef = signal(false, ...(ngDevMode ? [{ debugName: "firstValidItemFoundRef" }] : /* istanbul ignore next */ []));
209
+ this.viewport = signal(undefined, ...(ngDevMode ? [{ debugName: "viewport" }] : /* istanbul ignore next */ []));
210
+ this.isPositioned = signal(false, ...(ngDevMode ? [{ debugName: "isPositioned" }] : /* istanbul ignore next */ []));
130
211
  /**
131
- * @ignore
212
+ * Event handler called when the escape key is down.
213
+ * Can be prevented.
132
214
  */
133
- this.id = `rdx-select-${nextId$1++}`;
134
- this.open = false;
215
+ this.escapeKeyDown = outputFromObservable(outputToObservable(this.dismissableLayer.escapeKeyDown));
135
216
  /**
136
- * The overlay width will be set to the trigger width if this is true.
137
- * Otherwise, the overlay width will be set to the width of the content.
217
+ * Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`.
218
+ * Can be prevented.
138
219
  */
139
- this.matchTriggerWidth = false;
140
- this.onValueChange = new EventEmitter();
141
- this.onOpenChange = new EventEmitter();
142
- this.optionSelectionChanges = defer(() => {
143
- const content = this.content();
144
- if (content.options) {
145
- return merge(...content.options.map((option) => option.onSelectionChange));
146
- }
147
- return this.ngZone.onStable.asObservable().pipe(take(1), switchMap(() => this.optionSelectionChanges));
220
+ this.pointerDownOutside = outputFromObservable(outputToObservable(this.dismissableLayer.pointerDownOutside));
221
+ this.content = signal(null, ...(ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []));
222
+ this.dismissableLayer.focusOutside.subscribe((e) => e.preventDefault());
223
+ this.dismissableLayer.dismiss.subscribe(() => this.rootContext.onOpenChange(false));
224
+ const focusScope = inject(RdxFocusScope);
225
+ afterNextRender(() => {
226
+ focusScope.unmountAutoFocus.subscribe((event) => {
227
+ if (event.defaultPrevented)
228
+ return;
229
+ this.rootContext.triggerElement()?.focus({ preventScroll: true });
230
+ event.preventDefault();
231
+ });
232
+ focusScope.mountAutoFocus.subscribe((event) => {
233
+ event.preventDefault();
234
+ });
235
+ this.content.set(this.currentElement.nativeElement.firstElementChild);
148
236
  });
149
- }
150
- /**
151
- * The controlled value of the item to expand
152
- */
153
- set value(value) {
154
- if (this._value !== value) {
155
- this._value = value;
156
- this.selectValue(value);
157
- this.changeDetectorRef.markForCheck();
158
- }
159
- }
160
- get value() {
161
- return this._value ?? this.defaultValue;
162
- }
163
- get selected() {
164
- return this.selectionModel.selected[0].viewValue || null;
165
- }
166
- ngOnInit() {
167
- this.selectionModel = new SelectionModel();
168
- this.selectionModel.changed.subscribe((changes) => {
169
- if (changes.added.length) {
170
- this.onValueChange.emit(this.selectionModel.selected[0].value);
237
+ effect((onCleanup) => {
238
+ if (!this.content())
239
+ return;
240
+ let pointerMoveDelta = { x: 0, y: 0 };
241
+ const handlePointerMove = (event) => {
242
+ pointerMoveDelta = {
243
+ x: Math.abs(Math.round(event.pageX) - (this.rootContext.triggerPointerDownPosRef()?.x ?? 0)),
244
+ y: Math.abs(Math.round(event.pageY) - (this.rootContext.triggerPointerDownPosRef()?.y ?? 0))
245
+ };
246
+ };
247
+ const handlePointerUp = (event) => {
248
+ // Prevent options from being untappable on touch devices
249
+ if (event.pointerType === 'touch')
250
+ return;
251
+ // If the pointer hasn't moved by a certain threshold then we prevent selecting item on `pointerup`.
252
+ if (pointerMoveDelta.x <= 10 && pointerMoveDelta.y <= 10) {
253
+ event.preventDefault();
254
+ }
255
+ else {
256
+ // otherwise, if the event was outside the content, close.
257
+ if (!this.content()?.contains(event.target))
258
+ this.rootContext.onOpenChange(false);
259
+ }
260
+ document.removeEventListener('pointermove', handlePointerMove);
261
+ this.rootContext.triggerPointerDownPosRef.set(null);
262
+ };
263
+ if (this.rootContext.triggerPointerDownPosRef() !== null) {
264
+ document.addEventListener('pointermove', handlePointerMove);
265
+ document.addEventListener('pointerup', handlePointerUp, {
266
+ capture: true,
267
+ once: true
268
+ });
171
269
  }
172
- if (changes.removed.length) {
173
- changes.removed.forEach((item) => (item.selected = false));
174
- }
175
- });
176
- }
177
- ngAfterContentInit() {
178
- this.selectDefaultValue();
179
- this.optionSelectionChanges.subscribe((event) => {
180
- this.selectionModel.clear();
181
- this.selectionModel.select(event.source);
182
- this.close();
183
- this.trigger().focus();
184
- });
185
- this.content().keyManager.tabOut.subscribe(() => {
186
- if (this.open)
187
- this.close();
270
+ onCleanup(() => {
271
+ document.removeEventListener('pointermove', handlePointerMove);
272
+ document.removeEventListener('pointerup', handlePointerUp, {
273
+ capture: true
274
+ });
275
+ });
188
276
  });
189
- if (this.defaultOpen) {
190
- this.openPanel();
191
- }
192
- }
193
- /**
194
- * Callback that is invoked when the overlay panel has been attached.
195
- */
196
- onAttached() {
197
- this.closeSubscription = this.closingActions()
198
- .pipe(takeUntilDestroyed(this.destroyRef))
199
- .pipe(delay(0))
200
- .subscribe(() => this.close());
201
277
  }
202
- onDetach() {
203
- this.close();
204
- this.closeSubscription.unsubscribe();
205
- }
206
- /** Toggles the overlay panel open or closed. */
207
- toggle() {
208
- if (this.open) {
209
- this.close();
210
- }
211
- else {
212
- this.openPanel();
278
+ focusSelectedItem() {
279
+ if (this.selectedItem() && this.content()) {
280
+ focusFirst([this.selectedItem(), this.content()]);
213
281
  }
214
282
  }
215
- openPanel() {
216
- this.open = true;
217
- this.onOpenChange.emit(this.open);
218
- }
219
- close() {
220
- this.open = false;
221
- this.onOpenChange.emit(this.open);
222
- }
223
- updateActiveItem(item) {
224
- this.content().keyManager.updateActiveItem(item);
225
- }
226
- selectDefaultValue() {
227
- if (!this.defaultValue)
228
- return;
229
- this.selectValue(this.defaultValue);
230
- }
231
- selectValue(value) {
232
- const option = this.content()?.options.find((option) => option.value === value);
233
- if (option) {
234
- option.selected = true;
235
- option.highlighted = true;
236
- this.selectionModel.select(option);
237
- this.updateActiveItem(option);
283
+ handleKeyDown(event) {
284
+ const keyEvent = event;
285
+ // select should not be navigated using tab key so we prevent it
286
+ if (keyEvent.key === 'Tab')
287
+ event.preventDefault();
288
+ if (['ArrowUp', 'ArrowDown', 'Home', 'End'].includes(keyEvent.key)) {
289
+ const collectionItems = this.collection.items().map((i) => i.element);
290
+ let candidateNodes = [...collectionItems];
291
+ if (['ArrowUp', 'End'].includes(keyEvent.key))
292
+ candidateNodes = candidateNodes.slice().reverse();
293
+ if (['ArrowUp', 'ArrowDown'].includes(keyEvent.key)) {
294
+ const currentElement = event.target;
295
+ const currentIndex = candidateNodes.indexOf(currentElement);
296
+ candidateNodes = candidateNodes.slice(currentIndex + 1);
297
+ }
298
+ setTimeout(() => focusFirst(candidateNodes));
299
+ event.preventDefault();
238
300
  }
239
301
  }
240
- closingActions() {
241
- return merge(this.overlayDir().overlayRef.outsidePointerEvents(), this.overlayDir().overlayRef.detachments());
242
- }
243
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
244
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.9", type: RdxSelectComponent, isStandalone: true, selector: "[rdxSelect]", inputs: { defaultValue: "defaultValue", name: "name", defaultOpen: ["defaultOpen", "defaultOpen", booleanAttribute], open: ["open", "open", booleanAttribute], disabled: ["disabled", "disabled", booleanAttribute], required: ["required", "required", booleanAttribute], matchTriggerWidth: ["matchTriggerWidth", "matchTriggerWidth", booleanAttribute], value: "value" }, outputs: { onValueChange: "onValueChange", onOpenChange: "onOpenChange" }, host: { listeners: { "click": "toggle()", "keydown": "content().keyManager.onKeydown($event)" }, properties: { "style.--radix-select-trigger-width.px": "triggerSize()[0]", "style.--radix-select-trigger-height.px": "triggerSize()[1]" } }, queries: [{ propertyName: "trigger", first: true, predicate: RdxSelectTriggerDirective, descendants: true, isSignal: true }, { propertyName: "content", first: true, predicate: i0.forwardRef(() => RdxSelectContentDirective), descendants: true, isSignal: true }, { propertyName: "items", predicate: i0.forwardRef(() => RdxSelectItemDirective), descendants: true, isSignal: true }], viewQueries: [{ propertyName: "overlayDir", first: true, predicate: CdkConnectedOverlay, descendants: true, isSignal: true }], ngImport: i0, template: `
245
- <ng-content select="[rdxSelectTrigger]" />
246
-
247
- <ng-template
248
- [cdkConnectedOverlayOpen]="open"
249
- [cdkConnectedOverlayOrigin]="elementRef"
250
- [cdkConnectedOverlayPositions]="positions"
251
- [cdkConnectedOverlayScrollStrategy]="overlay.scrollStrategies.reposition()"
252
- [cdkConnectedOverlayMinWidth]="triggerWidth() > 0 ? triggerWidth() : 'auto'"
253
- [cdkConnectedOverlayWidth]="matchTriggerWidth ? triggerWidth() : 'auto'"
254
- (attach)="onAttached()"
255
- (backdropClick)="close()"
256
- (detach)="onDetach()"
257
- cdkConnectedOverlayLockPosition
258
- cdkConnectedOverlayHasBackdrop
259
- cdkConnectedOverlayBackdropClass="cdk-overlay-transparent-backdrop"
260
- cdkConnectedOverlay
261
- >
262
- <ng-content select="[rdxSelectContent]" />
263
- </ng-template>
264
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i1.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }] }); }
302
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectContent, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
303
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxSelectContent, isStandalone: true, selector: "[rdxSelectContent]", outputs: { escapeKeyDown: "escapeKeyDown", pointerDownOutside: "pointerDownOutside" }, host: { attributes: { "role": "listbox" }, listeners: { "keydown": "handleKeyDown($event)" }, properties: { "attr.data-state": "rootContext.open() ? \"open\" : \"closed\"", "dir": "rootContext.dir()", "style": "{\n display: 'flex',\n flexDirection: 'column',\n outline: 'none'\n }" } }, providers: [
304
+ provideSelectContentContext(context$1),
305
+ provideRdxDismissableLayerConfig(() => {
306
+ return {
307
+ disableOutsidePointerEvents: signal(true)
308
+ };
309
+ })
310
+ ], queries: [{ propertyName: "positioner", first: true, predicate: RDX_SELECT_POSITIONER_TOKEN, descendants: true }], hostDirectives: [{ directive: i1$1.RdxFocusScope }, { directive: i2.RdxDismissableLayer }, { directive: i3.RdxCollectionProvider }], ngImport: i0 }); }
265
311
  }
266
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectComponent, decorators: [{
267
- type: Component,
312
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectContent, decorators: [{
313
+ type: Directive,
268
314
  args: [{
269
- selector: '[rdxSelect]',
270
- template: `
271
- <ng-content select="[rdxSelectTrigger]" />
272
-
273
- <ng-template
274
- [cdkConnectedOverlayOpen]="open"
275
- [cdkConnectedOverlayOrigin]="elementRef"
276
- [cdkConnectedOverlayPositions]="positions"
277
- [cdkConnectedOverlayScrollStrategy]="overlay.scrollStrategies.reposition()"
278
- [cdkConnectedOverlayMinWidth]="triggerWidth() > 0 ? triggerWidth() : 'auto'"
279
- [cdkConnectedOverlayWidth]="matchTriggerWidth ? triggerWidth() : 'auto'"
280
- (attach)="onAttached()"
281
- (backdropClick)="close()"
282
- (detach)="onDetach()"
283
- cdkConnectedOverlayLockPosition
284
- cdkConnectedOverlayHasBackdrop
285
- cdkConnectedOverlayBackdropClass="cdk-overlay-transparent-backdrop"
286
- cdkConnectedOverlay
287
- >
288
- <ng-content select="[rdxSelectContent]" />
289
- </ng-template>
290
- `,
315
+ selector: '[rdxSelectContent]',
316
+ hostDirectives: [RdxFocusScope, RdxDismissableLayer, RdxCollectionProvider],
317
+ providers: [
318
+ provideSelectContentContext(context$1),
319
+ provideRdxDismissableLayerConfig(() => {
320
+ return {
321
+ disableOutsidePointerEvents: signal(true)
322
+ };
323
+ })
324
+ ],
291
325
  host: {
292
- '[style.--radix-select-trigger-width.px]': 'triggerSize()[0]',
293
- '[style.--radix-select-trigger-height.px]': 'triggerSize()[1]',
294
- '(click)': 'toggle()',
295
- '(keydown)': 'content().keyManager.onKeydown($event)'
296
- },
297
- imports: [OverlayModule]
326
+ role: 'listbox',
327
+ '[attr.data-state]': 'rootContext.open() ? "open" : "closed"',
328
+ '[dir]': 'rootContext.dir()',
329
+ '(keydown)': 'handleKeyDown($event)',
330
+ '[style]': `{
331
+ display: 'flex',
332
+ flexDirection: 'column',
333
+ outline: 'none'
334
+ }`
335
+ }
298
336
  }]
299
- }], propDecorators: { trigger: [{ type: i0.ContentChild, args: [i0.forwardRef(() => RdxSelectTriggerDirective), { isSignal: true }] }], content: [{ type: i0.ContentChild, args: [forwardRef(() => RdxSelectContentDirective), { isSignal: true }] }], items: [{ type: i0.ContentChildren, args: [forwardRef(() => RdxSelectItemDirective), { ...{ descendants: true }, isSignal: true }] }], overlayDir: [{ type: i0.ViewChild, args: [i0.forwardRef(() => CdkConnectedOverlay), { isSignal: true }] }], defaultValue: [{
300
- type: Input
301
- }], name: [{
302
- type: Input
303
- }], defaultOpen: [{
304
- type: Input,
305
- args: [{ transform: booleanAttribute }]
306
- }], open: [{
307
- type: Input,
308
- args: [{ transform: booleanAttribute }]
309
- }], disabled: [{
310
- type: Input,
311
- args: [{ transform: booleanAttribute }]
312
- }], required: [{
313
- type: Input,
314
- args: [{ transform: booleanAttribute }]
315
- }], matchTriggerWidth: [{
316
- type: Input,
317
- args: [{ transform: booleanAttribute }]
318
- }], value: [{
319
- type: Input
320
- }], onValueChange: [{
321
- type: Output
322
- }], onOpenChange: [{
323
- type: Output
337
+ }], ctorParameters: () => [], propDecorators: { escapeKeyDown: [{ type: i0.Output, args: ["escapeKeyDown"] }], pointerDownOutside: [{ type: i0.Output, args: ["pointerDownOutside"] }], positioner: [{
338
+ type: ContentChild,
339
+ args: [RDX_SELECT_POSITIONER_TOKEN, { descendants: true }]
324
340
  }] } });
325
341
 
326
- let nextId = 0;
327
- class RdxSelectItemChange {
328
- constructor(source) {
329
- this.source = source;
342
+ class RdxSelectGroup {
343
+ constructor() {
344
+ this.id = injectId('rdx-select-group-');
330
345
  }
346
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectGroup, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
347
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxSelectGroup, isStandalone: true, selector: "[rdxSelectGroup]", host: { attributes: { "role": "group" }, properties: { "attr.aria-labelledby": "id" } }, exportAs: ["rdxSelectGroup"], ngImport: i0 }); }
331
348
  }
332
- class RdxSelectItemDirective {
333
- get dataState() {
334
- return this.selected ? 'checked' : 'unchecked';
335
- }
336
- set value(value) {
337
- this._value = value;
338
- }
339
- get value() {
340
- return this._value || this.id;
341
- }
342
- /** Whether the SelectItem is disabled. */
343
- set disabled(value) {
344
- this._disabled = value;
345
- }
346
- get disabled() {
347
- return this._disabled;
349
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectGroup, decorators: [{
350
+ type: Directive,
351
+ args: [{
352
+ selector: '[rdxSelectGroup]',
353
+ exportAs: 'rdxSelectGroup',
354
+ host: {
355
+ role: 'group',
356
+ '[attr.aria-labelledby]': 'id'
357
+ }
358
+ }]
359
+ }] });
360
+
361
+ const context = () => {
362
+ const context = inject(RdxSelectItem);
363
+ return {
364
+ value: context.value,
365
+ disabled: context.disabled,
366
+ isSelected: context.isSelected,
367
+ textId: context.textId,
368
+ onItemTextChange: (node) => {
369
+ context.textValue$.set(((context.textValue$() || node.textContent) ?? '').trim());
370
+ }
371
+ };
372
+ };
373
+ const [injectSelectItemContext, provideSelectItemContext] = createContext('RdxSelectItemContext');
374
+ class RdxSelectItem {
375
+ constructor() {
376
+ this.rootContext = injectSelectRootContext();
377
+ this.contentContext = injectSelectContentContext();
378
+ this.currentElement = inject(ElementRef);
379
+ this.value = input(...(ngDevMode ? [undefined, { debugName: "value" }] : /* istanbul ignore next */ []));
380
+ this.textValue = input('', ...(ngDevMode ? [{ debugName: "textValue" }] : /* istanbul ignore next */ []));
381
+ this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
382
+ this.textValue$ = linkedSignal(this.textValue, ...(ngDevMode ? [{ debugName: "textValue$" }] : /* istanbul ignore next */ []));
383
+ this.isSelected = computed(() => valueComparator(this.rootContext.value(), this.value(), this.rootContext.by()), ...(ngDevMode ? [{ debugName: "isSelected" }] : /* istanbul ignore next */ []));
384
+ this.isFocused = signal(false, ...(ngDevMode ? [{ debugName: "isFocused" }] : /* istanbul ignore next */ []));
385
+ this.textId = injectId('rdx-select-item-text-');
386
+ this.afterNextRender = afterNextRender(() => {
387
+ this.contentContext.itemRefCallback(this.currentElement.nativeElement, this.value(), this.disabled());
388
+ });
389
+ this.SELECT_SELECT = 'select.select';
348
390
  }
349
- get viewValue() {
350
- return this.textValue ?? this.nativeElement.textContent;
391
+ onPointerDown(event) {
392
+ event.currentTarget.focus({ preventScroll: true });
351
393
  }
352
- constructor() {
353
- this.select = inject(RdxSelectComponent);
354
- this.content = inject(RdxSelectContentDirective);
355
- this.onSelectionChange = new EventEmitter();
356
- this.nativeElement = inject(ElementRef).nativeElement;
357
- this.highlighted = false;
358
- /**
359
- * The unique SelectItem id.
360
- * @ignore
361
- */
362
- this.id = `rdx-select-item-${nextId++}`;
363
- this.textValue = null;
364
- this.content.highlighted.pipe(takeUntilDestroyed()).subscribe((value) => {
365
- if (value !== this) {
366
- this.highlighted = false;
394
+ onPointerUp(event) {
395
+ if (event.defaultPrevented)
396
+ return;
397
+ const eventDetail = { originalEvent: event, value: this.value() };
398
+ handleAndDispatchCustomEvent(this.SELECT_SELECT, async (event) => {
399
+ if (event.defaultPrevented)
400
+ return;
401
+ this.rootContext.onValueChange(this.value());
402
+ if (!this.rootContext.multiple()) {
403
+ this.rootContext.onOpenChange(false);
367
404
  }
368
- });
405
+ }, eventDetail);
369
406
  }
370
- /** Gets the label to be used when determining whether the option should be focused.
371
- * @ignore
372
- */
373
- getLabel() {
374
- return this.viewValue;
407
+ onPointerLeave(event) {
408
+ if (event.defaultPrevented)
409
+ return;
410
+ if (event.currentTarget === getActiveElement())
411
+ this.contentContext.onItemLeave?.();
375
412
  }
376
- /**
377
- * `Selects the option while indicating the selection came from the user. Used to
378
- * determine if the select's view -> model callback should be invoked.`
379
- * @ignore
380
- */
381
- selectViaInteraction() {
382
- if (!this.disabled) {
383
- this.selected = true;
384
- this.onSelectionChange.emit(new RdxSelectItemChange(this));
413
+ onPointerMove(event) {
414
+ if (event.defaultPrevented)
415
+ return;
416
+ if (this.disabled()) {
417
+ this.contentContext.onItemLeave?.();
385
418
  }
386
- }
387
- /** @ignore */
388
- handleKeydown(event) {
389
- if (event.keyCode === ENTER || event.keyCode === SPACE) {
390
- this.selectViaInteraction();
391
- // Prevent the page from scrolling down and form submits.
392
- event.preventDefault();
393
- event.stopPropagation();
419
+ else {
420
+ // even though safari doesn't support this option, it's acceptable
421
+ // as it only means it might scroll a few pixels when using the pointer.
422
+ event.currentTarget?.focus({ preventScroll: true });
394
423
  }
395
424
  }
396
- /** @ignore */
397
- setActiveStyles() {
398
- this.highlighted = true;
399
- this.nativeElement.focus({ preventScroll: true });
400
- }
401
- /** @ignore */
402
- setInactiveStyles() {
403
- this.highlighted = false;
425
+ handleKeyDown(event) {
426
+ const keyEvent = event;
427
+ if (event.defaultPrevented)
428
+ return;
429
+ if (SELECTION_KEYS.includes(keyEvent.key))
430
+ this.handleSelectCustomEvent(keyEvent);
431
+ // prevent page scroll if using the space key to select an item
432
+ if (keyEvent.key === ' ')
433
+ event.preventDefault();
404
434
  }
405
- onPointerMove() {
406
- if (!this.highlighted) {
407
- this.nativeElement.focus({ preventScroll: true });
408
- this.select.updateActiveItem(this);
409
- }
435
+ async handleSelectCustomEvent(event) {
436
+ if (event.defaultPrevented)
437
+ return;
438
+ const eventDetail = { originalEvent: event, value: this.value() };
439
+ handleAndDispatchCustomEvent(this.SELECT_SELECT, async (event) => {
440
+ if (event.defaultPrevented)
441
+ return;
442
+ if (!this.disabled()) {
443
+ this.rootContext.onValueChange(this.value());
444
+ if (!this.rootContext.multiple())
445
+ this.rootContext.onOpenChange(false);
446
+ }
447
+ }, eventDetail);
410
448
  }
411
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectItemDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
412
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "21.2.9", type: RdxSelectItemDirective, isStandalone: true, selector: "[rdxSelectItem]", inputs: { value: "value", textValue: "textValue", disabled: ["disabled", "disabled", booleanAttribute] }, host: { listeners: { "focus": "content.highlighted.next(this)", "click": "selectViaInteraction()", "keydown": "handleKeydown($event)", "pointermove": "onPointerMove()" }, properties: { "attr.role": "\"option\"", "attr.data-state": "dataState", "attr.aria-selected": "selected", "attr.data-disabled": "disabled || null", "attr.data-highlighted": "highlighted || null", "attr.tabindex": "-1" } }, exportAs: ["rdxSelectItem"], ngImport: i0 }); }
449
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectItem, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
450
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxSelectItem, isStandalone: true, selector: "[rdxSelectItem]", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, textValue: { classPropertyName: "textValue", publicName: "textValue", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "option" }, listeners: { "focus": "isFocused.set(true)", "blur": "isFocused.set(false)", "pointerdown": "onPointerDown($event)", "pointerup": "onPointerUp($event)", "pointerleave": "onPointerLeave($event)", "pointermove": "onPointerMove($event)", "keydown": "handleKeyDown($event)" }, properties: { "attr.tabindex": "disabled() ? undefined : -1", "attr.aria-selected": "isSelected() ? \"checked\" : \"unchecked\"", "attr.data-state": "isSelected() ? \"checked\" : \"unchecked\"", "attr.data-highlighted": "isFocused() ? \"\" : undefined" } }, providers: [provideSelectItemContext(context)], hostDirectives: [{ directive: i3.RdxCollectionItem, inputs: ["value", "value"] }], ngImport: i0 }); }
413
451
  }
414
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectItemDirective, decorators: [{
452
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectItem, decorators: [{
415
453
  type: Directive,
416
454
  args: [{
417
455
  selector: '[rdxSelectItem]',
418
- standalone: true,
419
- exportAs: 'rdxSelectItem',
456
+ providers: [provideSelectItemContext(context)],
457
+ hostDirectives: [
458
+ {
459
+ directive: RdxCollectionItem,
460
+ inputs: ['value']
461
+ }
462
+ ],
420
463
  host: {
421
- '[attr.role]': '"option"',
422
- '[attr.data-state]': 'dataState',
423
- '[attr.aria-selected]': 'selected',
424
- '[attr.data-disabled]': 'disabled || null',
425
- '[attr.data-highlighted]': 'highlighted || null',
426
- '[attr.tabindex]': '-1',
427
- '(focus)': 'content.highlighted.next(this)',
428
- '(click)': 'selectViaInteraction()',
429
- '(keydown)': 'handleKeydown($event)',
430
- '(pointermove)': 'onPointerMove()'
464
+ role: 'option',
465
+ '[attr.tabindex]': 'disabled() ? undefined : -1',
466
+ '[attr.aria-selected]': 'isSelected() ? "checked" : "unchecked"',
467
+ '[attr.data-state]': 'isSelected() ? "checked" : "unchecked"',
468
+ '[attr.data-highlighted]': 'isFocused() ? "" : undefined',
469
+ '(focus)': 'isFocused.set(true)',
470
+ '(blur)': 'isFocused.set(false)',
471
+ '(pointerdown)': 'onPointerDown($event)',
472
+ '(pointerup)': 'onPointerUp($event)',
473
+ '(pointerleave)': 'onPointerLeave($event)',
474
+ '(pointermove)': 'onPointerMove($event)',
475
+ '(keydown)': 'handleKeyDown($event)'
431
476
  }
432
477
  }]
433
- }], ctorParameters: () => [], propDecorators: { value: [{
434
- type: Input
435
- }], textValue: [{
436
- type: Input
437
- }], disabled: [{
438
- type: Input,
439
- args: [{ transform: booleanAttribute }]
440
- }] } });
478
+ }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], textValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "textValue", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
441
479
 
442
- class RdxSelectContentDirective {
480
+ class RdxSelectItemIndicator {
443
481
  constructor() {
444
- this.destroyRef = inject(DestroyRef);
445
- this.dir = inject(Directionality, { optional: true });
446
- this.select = inject(RdxSelectComponent);
447
- this.highlighted = new Subject();
448
- this.highlighted.pipe(startWith(null), pairwise()).subscribe(([prev, item]) => {
449
- if (prev) {
450
- prev.highlighted = false;
451
- }
452
- if (item) {
453
- item.highlighted = true;
454
- }
455
- });
456
- }
457
- initKeyManager() {
458
- return new ActiveDescendantKeyManager(this.options)
459
- .withTypeAhead()
460
- .withVerticalOrientation()
461
- .withHorizontalOrientation(this.dir?.value ?? 'ltr');
462
- }
463
- ngAfterContentInit() {
464
- this.keyManager = this.initKeyManager();
482
+ this.itemContext = injectSelectItemContext();
465
483
  }
466
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectContentDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
467
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxSelectContentDirective, isStandalone: true, selector: "[rdxSelectContent]", host: { listeners: { "keydown": "keyManager.onKeydown($event)" }, properties: { "attr.role": "\"listbox\"", "attr.data-state": "select.open ? 'open': 'closed'", "attr.data-side": "true", "attr.data-align": "true" } }, queries: [{ propertyName: "options", predicate: RdxSelectItemDirective, descendants: true }], exportAs: ["rdxSelectContent"], ngImport: i0 }); }
484
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectItemIndicator, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
485
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxSelectItemIndicator, isStandalone: true, selector: "[rdxSelectItemIndicator]", host: { properties: { "attr.aria-hidden": "true", "hidden": "!itemContext.isSelected()" } }, ngImport: i0 }); }
468
486
  }
469
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectContentDirective, decorators: [{
487
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectItemIndicator, decorators: [{
470
488
  type: Directive,
471
489
  args: [{
472
- selector: '[rdxSelectContent]',
473
- standalone: true,
474
- exportAs: 'rdxSelectContent',
490
+ selector: '[rdxSelectItemIndicator]',
475
491
  host: {
476
- '[attr.role]': '"listbox"',
477
- '[attr.data-state]': "select.open ? 'open': 'closed'",
478
- '[attr.data-side]': 'true',
479
- '[attr.data-align]': 'true',
480
- '(keydown)': 'keyManager.onKeydown($event)'
492
+ '[attr.aria-hidden]': 'true',
493
+ '[hidden]': '!itemContext.isSelected()'
481
494
  }
482
495
  }]
483
- }], ctorParameters: () => [], propDecorators: { options: [{
484
- type: ContentChildren,
485
- args: [RdxSelectItemDirective, { descendants: true }]
486
- }] } });
496
+ }] });
487
497
 
488
- class RdxSelectGroupDirective {
489
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectGroupDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
490
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxSelectGroupDirective, isStandalone: true, selector: "[rdxSelectGroup]", host: { properties: { "attr.role": "\"group\"" } }, exportAs: ["rdxSelectGroup"], ngImport: i0 }); }
498
+ class RdxSelectItemText {
499
+ constructor() {
500
+ this.elementRef = inject((ElementRef));
501
+ this.rootContext = injectSelectRootContext();
502
+ this.contentContext = injectSelectContentContext();
503
+ this.itemContext = injectSelectItemContext();
504
+ this.optionProps = computed(() => {
505
+ return {
506
+ value: this.itemContext.value(),
507
+ disabled: this.itemContext.disabled(),
508
+ textContent: this.elementRef.nativeElement.textContent ?? this.itemContext.value()?.toString() ?? ''
509
+ };
510
+ }, ...(ngDevMode ? [{ debugName: "optionProps" }] : /* istanbul ignore next */ []));
511
+ afterNextRender(() => {
512
+ this.itemContext.onItemTextChange(this.elementRef.nativeElement);
513
+ this.contentContext.itemTextRefCallback(this.elementRef.nativeElement, this.itemContext.value(), this.itemContext.disabled());
514
+ this.rootContext.onOptionAdd(this.optionProps);
515
+ });
516
+ const destroyRef = inject(DestroyRef);
517
+ destroyRef.onDestroy(() => {
518
+ this.rootContext.onOptionRemove(this.optionProps);
519
+ });
520
+ }
521
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectItemText, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
522
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxSelectItemText, isStandalone: true, selector: "[rdxSelectItemText]", host: { properties: { "id": "itemContext.textId" } }, ngImport: i0 }); }
491
523
  }
492
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectGroupDirective, decorators: [{
524
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectItemText, decorators: [{
493
525
  type: Directive,
494
526
  args: [{
495
- selector: '[rdxSelectGroup]',
496
- standalone: true,
497
- exportAs: 'rdxSelectGroup',
527
+ selector: '[rdxSelectItemText]',
498
528
  host: {
499
- '[attr.role]': '"group"'
529
+ '[id]': 'itemContext.textId'
500
530
  }
501
531
  }]
532
+ }], ctorParameters: () => [] });
533
+
534
+ class RdxSelectLabel {
535
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectLabel, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
536
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxSelectLabel, isStandalone: true, selector: "[rdxSelectLabel]", ngImport: i0 }); }
537
+ }
538
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectLabel, decorators: [{
539
+ type: Directive,
540
+ args: [{
541
+ selector: '[rdxSelectLabel]',
542
+ host: {}
543
+ }]
502
544
  }] });
503
545
 
504
- class RdxSelectIconDirective {
505
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectIconDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
506
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxSelectIconDirective, isStandalone: true, selector: "[rdxSelectIcon]", host: { properties: { "attr.aria-hidden": "true" } }, exportAs: ["rdxSelectIcon"], ngImport: i0 }); }
546
+ class RdxSelectPopperPositionContent {
547
+ constructor() {
548
+ this.rootContext = injectSelectRootContext();
549
+ }
550
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectPopperPositionContent, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
551
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxSelectPopperPositionContent, isStandalone: true, selector: "[rdxSelectPopperPositionContent]", host: { attributes: { "role": "listbox" }, properties: { "id": "rootContext.contentId" } }, hostDirectives: [{ directive: i1.RdxPopperContent }], ngImport: i0 }); }
507
552
  }
508
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectIconDirective, decorators: [{
553
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectPopperPositionContent, decorators: [{
509
554
  type: Directive,
510
555
  args: [{
511
- selector: '[rdxSelectIcon]',
512
- standalone: true,
513
- exportAs: 'rdxSelectIcon',
556
+ selector: '[rdxSelectPopperPositionContent]',
557
+ hostDirectives: [RdxPopperContent],
514
558
  host: {
515
- '[attr.aria-hidden]': 'true'
559
+ role: 'listbox',
560
+ '[id]': 'rootContext.contentId'
516
561
  }
517
562
  }]
518
563
  }] });
519
564
 
520
- class RdxSelectItemIndicatorDirective {
565
+ class RdxSelectPopperPositionWrapper {
521
566
  constructor() {
522
- this.item = inject(RdxSelectItemDirective);
567
+ /**
568
+ * The preferred side of the anchor to render against when open.
569
+ * Will be reversed when collisions occur and avoidCollisions is enabled.
570
+ */
571
+ this.side = input('bottom', ...(ngDevMode ? [{ debugName: "side" }] : /* istanbul ignore next */ []));
572
+ /**
573
+ * The distance in pixels from the anchor.
574
+ */
575
+ this.sideOffset = input(0, { ...(ngDevMode ? { debugName: "sideOffset" } : /* istanbul ignore next */ {}), transform: numberAttribute });
576
+ /**
577
+ * The preferred alignment against the anchor. May change when collisions occur.
578
+ */
579
+ this.align = input('start', ...(ngDevMode ? [{ debugName: "align" }] : /* istanbul ignore next */ []));
580
+ /**
581
+ * An offset in pixels from the `start` or `end` alignment options.
582
+ */
583
+ this.alignOffset = input(0, { ...(ngDevMode ? { debugName: "alignOffset" } : /* istanbul ignore next */ {}), transform: numberAttribute });
584
+ /**
585
+ * The padding between the arrow and the edges of the content.
586
+ * If your content has border-radius, this will prevent it from overflowing the corners.
587
+ */
588
+ this.arrowPadding = input(0, { ...(ngDevMode ? { debugName: "arrowPadding" } : /* istanbul ignore next */ {}), transform: numberAttribute });
589
+ /**
590
+ * When `true`, overrides the `side` and `align` preferences to prevent collisions with boundary edges.
591
+ */
592
+ this.avoidCollisions = input(true, { ...(ngDevMode ? { debugName: "avoidCollisions" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
593
+ /**
594
+ * The element used as the collision boundary.
595
+ * By default this is the viewport, though you can provide additional element(s) to be included in this check.
596
+ */
597
+ this.collisionBoundary = input(...(ngDevMode ? [undefined, { debugName: "collisionBoundary" }] : /* istanbul ignore next */ []));
598
+ /**
599
+ * The distance in pixels from the boundary edges where collision detection should occur.
600
+ * Accepts a number (same for all sides), or a partial padding object, for example: `{ top: 20, left: 20 }`.
601
+ */
602
+ this.collisionPadding = input(0, ...(ngDevMode ? [{ debugName: "collisionPadding" }] : /* istanbul ignore next */ []));
603
+ /**
604
+ * The sticky behavior on the `align` axis.
605
+ * - `partial` will keep the content in the boundary as long as the trigger is at least partially in the boundary
606
+ * - `always` will keep the content in the boundary regardless.
607
+ */
608
+ this.sticky = input('partial', ...(ngDevMode ? [{ debugName: "sticky" }] : /* istanbul ignore next */ []));
609
+ /**
610
+ * Whether to hide the content when the trigger becomes fully occluded.
611
+ */
612
+ this.hideWhenDetached = input(false, { ...(ngDevMode ? { debugName: "hideWhenDetached" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
613
+ /**
614
+ * Whether to update the position of the floating element on every animation frame if required.
615
+ */
616
+ this.updatePositionStrategy = input('always', ...(ngDevMode ? [{ debugName: "updatePositionStrategy" }] : /* istanbul ignore next */ []));
617
+ /**
618
+ * Emits when the element is placed.
619
+ */
620
+ this.placed = outputFromObservable(outputToObservable(inject(RdxPopperContentWrapper).placed));
523
621
  }
524
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectItemIndicatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
525
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxSelectItemIndicatorDirective, isStandalone: true, selector: "[rdxSelectItemIndicator]", host: { properties: { "attr.aria-hidden": "true", "style.display": "item.selected ? \"\" : \"none\"" } }, exportAs: ["rdxSelectItemIndicator"], ngImport: i0 }); }
622
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectPopperPositionWrapper, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
623
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxSelectPopperPositionWrapper, isStandalone: true, selector: "[rdxSelectPopperPositionWrapper]", 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 } }, outputs: { placed: "placed" }, host: { properties: { "style": "{\n 'boxSizing': 'border-box',\n '--radix-tooltip-content-transform-origin': 'var(--radix-popper-transform-origin)',\n '--radix-tooltip-content-available-width': 'var(--radix-popper-available-width)',\n '--radix-tooltip-content-available-height': 'var(--radix-popper-available-height)',\n '--radix-tooltip-trigger-width': 'var(--radix-popper-anchor-width)',\n '--radix-tooltip-trigger-height': 'var(--radix-popper-anchor-height)',\n }" } }, providers: [
624
+ {
625
+ provide: RDX_SELECT_POSITIONER_TOKEN,
626
+ useExisting: forwardRef(() => RdxSelectPopperPositionWrapper)
627
+ }
628
+ ], hostDirectives: [{ directive: i1.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 }); }
526
629
  }
527
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectItemIndicatorDirective, decorators: [{
630
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectPopperPositionWrapper, decorators: [{
528
631
  type: Directive,
529
632
  args: [{
530
- selector: '[rdxSelectItemIndicator]',
531
- standalone: true,
532
- exportAs: 'rdxSelectItemIndicator',
633
+ selector: '[rdxSelectPopperPositionWrapper]',
634
+ providers: [
635
+ {
636
+ provide: RDX_SELECT_POSITIONER_TOKEN,
637
+ useExisting: forwardRef(() => RdxSelectPopperPositionWrapper)
638
+ }
639
+ ],
640
+ hostDirectives: [
641
+ {
642
+ directive: RdxPopperContentWrapper,
643
+ inputs: [
644
+ 'side',
645
+ 'sideOffset',
646
+ 'align',
647
+ 'alignOffset',
648
+ 'arrowPadding',
649
+ 'avoidCollisions',
650
+ 'collisionBoundary',
651
+ 'collisionPadding',
652
+ 'sticky',
653
+ 'hideWhenDetached',
654
+ 'updatePositionStrategy'
655
+ ]
656
+ }
657
+ ],
533
658
  host: {
534
- '[attr.aria-hidden]': 'true',
535
- '[style.display]': 'item.selected ? "" : "none"'
659
+ // re-namespace exposed content custom properties
660
+ '[style]': `{
661
+ 'boxSizing': 'border-box',
662
+ '--radix-tooltip-content-transform-origin': 'var(--radix-popper-transform-origin)',
663
+ '--radix-tooltip-content-available-width': 'var(--radix-popper-available-width)',
664
+ '--radix-tooltip-content-available-height': 'var(--radix-popper-available-height)',
665
+ '--radix-tooltip-trigger-width': 'var(--radix-popper-anchor-width)',
666
+ '--radix-tooltip-trigger-height': 'var(--radix-popper-anchor-height)',
667
+ }`
536
668
  }
537
669
  }]
538
- }] });
670
+ }], 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 }] }], placed: [{ type: i0.Output, args: ["placed"] }] } });
539
671
 
540
- class RdxSelectLabelDirective {
541
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectLabelDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
542
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxSelectLabelDirective, isStandalone: true, selector: "[rdxSelectLabel]", exportAs: ["rdxSelectLabel"], ngImport: i0 }); }
672
+ class RdxSelectPortal {
673
+ constructor() {
674
+ /**
675
+ * Optional container to portal the content into. Defaults to `document.body` when not set.
676
+ */
677
+ this.container = input(...(ngDevMode ? [undefined, { debugName: "container" }] : /* istanbul ignore next */ []));
678
+ }
679
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectPortal, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
680
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxSelectPortal, isStandalone: true, selector: "[rdxSelectPortal]", inputs: { container: { classPropertyName: "container", publicName: "container", isSignal: true, isRequired: false, transformFunction: null } }, hostDirectives: [{ directive: i1$2.RdxPortal, inputs: ["container", "container"] }], ngImport: i0 }); }
543
681
  }
544
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectLabelDirective, decorators: [{
682
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectPortal, decorators: [{
545
683
  type: Directive,
546
684
  args: [{
547
- selector: '[rdxSelectLabel]',
548
- standalone: true,
549
- exportAs: 'rdxSelectLabel'
685
+ selector: '[rdxSelectPortal]',
686
+ hostDirectives: [
687
+ {
688
+ directive: RdxPortal,
689
+ inputs: ['container']
690
+ }
691
+ ]
692
+ }]
693
+ }], propDecorators: { container: [{ type: i0.Input, args: [{ isSignal: true, alias: "container", required: false }] }] } });
694
+
695
+ class RdxSelectPortalPresence {
696
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectPortalPresence, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
697
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxSelectPortalPresence, isStandalone: true, selector: "ng-template[rdxSelectPortalPresence]", providers: [
698
+ provideRdxPresenceContext(() => {
699
+ const context = injectSelectRootContext();
700
+ return { present: context.open };
701
+ })
702
+ ], hostDirectives: [{ directive: i1$3.RdxPresenceDirective }], ngImport: i0 }); }
703
+ }
704
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectPortalPresence, decorators: [{
705
+ type: Directive,
706
+ args: [{
707
+ selector: 'ng-template[rdxSelectPortalPresence]',
708
+ hostDirectives: [RdxPresenceDirective],
709
+ providers: [
710
+ provideRdxPresenceContext(() => {
711
+ const context = injectSelectRootContext();
712
+ return { present: context.open };
713
+ })
714
+ ]
550
715
  }]
551
716
  }] });
552
717
 
553
- class RdxSelectSeparatorDirective {
554
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectSeparatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
555
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxSelectSeparatorDirective, isStandalone: true, selector: "[rdxSelectSeparator]", host: { properties: { "attr.aria-hidden": "true" } }, exportAs: ["rdxSelectSeparator"], ngImport: i0 }); }
718
+ class RdxSelectTrigger {
719
+ constructor() {
720
+ this.rootContext = injectSelectRootContext();
721
+ this.elementRef = inject(ElementRef);
722
+ this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
723
+ this.isDisabled = computed(() => this.rootContext.disabled() || this.disabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
724
+ afterNextRender(() => {
725
+ this.rootContext.onTriggerChange(this.elementRef);
726
+ });
727
+ }
728
+ handleOpen() {
729
+ if (!this.isDisabled()) {
730
+ this.rootContext.onOpenChange(true);
731
+ }
732
+ }
733
+ handlePointerOpen(event) {
734
+ const pointerEvent = event;
735
+ this.handleOpen();
736
+ this.rootContext.triggerPointerDownPosRef.set({
737
+ x: Math.round(pointerEvent.pageX),
738
+ y: Math.round(pointerEvent.pageY)
739
+ });
740
+ }
741
+ onClickHandler(event) {
742
+ // Whilst browsers generally have no issue focusing the trigger when clicking
743
+ // on a label, Safari seems to struggle with the fact that there's no `onClick`.
744
+ // We force `focus` in this case. Note: this doesn't create any other side-effect
745
+ // because we are preventing default in `onPointerDown` so effectively
746
+ // this only runs for a label 'click'
747
+ event?.currentTarget?.focus();
748
+ }
749
+ onPointerDown(event) {
750
+ const pointerEvent = event;
751
+ if (pointerEvent.pointerType === 'touch')
752
+ return event.preventDefault();
753
+ // prevent implicit pointer capture
754
+ // https://www.w3.org/TR/pointerevents3/#implicit-pointer-capture
755
+ const target = event.target;
756
+ if (target.hasPointerCapture(pointerEvent.pointerId)) {
757
+ target.releasePointerCapture(pointerEvent.pointerId);
758
+ }
759
+ // only call handler if it's the left button (mousedown gets triggered by all mouse buttons)
760
+ // but not when the control key is pressed (avoiding MacOS right click)
761
+ if (pointerEvent.button === 0 && pointerEvent.ctrlKey === false) {
762
+ this.handlePointerOpen(event);
763
+ // prevent trigger from stealing focus from the active item after opening.
764
+ event.preventDefault();
765
+ }
766
+ }
767
+ onPointerUp(event) {
768
+ const pointerEvent = event;
769
+ event.preventDefault();
770
+ // Only open on pointer up when using touch devices
771
+ if (pointerEvent.pointerType === 'touch')
772
+ this.handlePointerOpen(event);
773
+ }
774
+ onKeydown(event) {
775
+ const keyEvent = event;
776
+ if (OPEN_KEYS.includes(keyEvent.key)) {
777
+ this.handleOpen();
778
+ event.preventDefault();
779
+ }
780
+ }
781
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectTrigger, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
782
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxSelectTrigger, isStandalone: true, selector: "button[rdxSelectTrigger]", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "combobox", "type": "button" }, listeners: { "click": "onClickHandler($event)", "pointerdown": "onPointerDown($event)", "pointerup": "onPointerUp($event)", "keydown": "onKeydown($event)" }, properties: { "attr.disabled": "isDisabled() ? \"\" : undefined", "dir": "rootContext.dir()", "attr.data-state": "rootContext.open() ? \"open\" : \"closed\"", "attr.data-disabled": "isDisabled() ? \"\" : undefined" } }, hostDirectives: [{ directive: i1.RdxPopperAnchor }], ngImport: i0 }); }
783
+ }
784
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectTrigger, decorators: [{
785
+ type: Directive,
786
+ args: [{
787
+ selector: 'button[rdxSelectTrigger]',
788
+ hostDirectives: [RdxPopperAnchor],
789
+ host: {
790
+ role: 'combobox',
791
+ type: 'button',
792
+ '[attr.disabled]': 'isDisabled() ? "" : undefined',
793
+ '[dir]': 'rootContext.dir()',
794
+ '[attr.data-state]': 'rootContext.open() ? "open" : "closed"',
795
+ '[attr.data-disabled]': 'isDisabled() ? "" : undefined',
796
+ '(click)': 'onClickHandler($event)',
797
+ '(pointerdown)': 'onPointerDown($event)',
798
+ '(pointerup)': 'onPointerUp($event)',
799
+ '(keydown)': 'onKeydown($event)'
800
+ }
801
+ }]
802
+ }], ctorParameters: () => [], propDecorators: { disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
803
+
804
+ class RdxSelectValue {
805
+ constructor() {
806
+ this.rootContext = injectSelectRootContext();
807
+ this.elementRef = inject(ElementRef);
808
+ this.placeholder = input(...(ngDevMode ? [undefined, { debugName: "placeholder" }] : /* istanbul ignore next */ []));
809
+ this.slotText = computed(() => {
810
+ return this.selectedLabel().length ? this.selectedLabel().join(', ') : this.placeholder();
811
+ }, ...(ngDevMode ? [{ debugName: "slotText" }] : /* istanbul ignore next */ []));
812
+ this.selectedLabel = computed(() => {
813
+ // eslint-disable-next-line no-useless-assignment
814
+ let list = [];
815
+ const options = Array.from(this.rootContext.optionsSet());
816
+ const getOption = (value) => options.find((option) => valueComparator(value, option.value, this.rootContext.by()));
817
+ if (Array.isArray(this.rootContext.value())) {
818
+ list = Array(this.rootContext.value()).map((value) => getOption(value)?.textContent ?? '');
819
+ }
820
+ else {
821
+ list = [getOption(this.rootContext.value())?.textContent ?? ''];
822
+ }
823
+ return list.filter(Boolean);
824
+ }, ...(ngDevMode ? [{ debugName: "selectedLabel" }] : /* istanbul ignore next */ []));
825
+ afterNextRender(() => {
826
+ this.rootContext.valueElement.set(this.elementRef.nativeElement);
827
+ });
828
+ }
829
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectValue, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
830
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxSelectValue, isStandalone: true, selector: "span[rdxSelectValue]", inputs: { placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.pointer-events": "\"none\"" } }, exportAs: ["rdxSelectedValue"], ngImport: i0 }); }
556
831
  }
557
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectSeparatorDirective, decorators: [{
832
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectValue, decorators: [{
558
833
  type: Directive,
559
834
  args: [{
560
- selector: '[rdxSelectSeparator]',
561
- standalone: true,
562
- exportAs: 'rdxSelectSeparator',
835
+ selector: 'span[rdxSelectValue]',
836
+ exportAs: 'rdxSelectedValue',
563
837
  host: {
564
- '[attr.aria-hidden]': 'true'
838
+ '[style.pointer-events]': '"none"'
565
839
  }
566
840
  }]
567
- }] });
841
+ }], ctorParameters: () => [], propDecorators: { placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }] } });
568
842
 
569
- const _imports = [
570
- RdxSelectContentDirective,
571
- RdxSelectGroupDirective,
572
- RdxSelectItemDirective,
573
- RdxSelectItemIndicatorDirective,
574
- RdxSelectLabelDirective,
575
- RdxSelectComponent,
576
- RdxSelectSeparatorDirective,
577
- RdxSelectTriggerDirective,
578
- RdxSelectValueDirective,
579
- RdxSelectIconDirective
580
- ];
581
- class RdxSelectModule {
582
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
583
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectModule, imports: [RdxSelectContentDirective,
584
- RdxSelectGroupDirective,
585
- RdxSelectItemDirective,
586
- RdxSelectItemIndicatorDirective,
587
- RdxSelectLabelDirective,
588
- RdxSelectComponent,
589
- RdxSelectSeparatorDirective,
590
- RdxSelectTriggerDirective,
591
- RdxSelectValueDirective,
592
- RdxSelectIconDirective], exports: [RdxSelectContentDirective,
593
- RdxSelectGroupDirective,
594
- RdxSelectItemDirective,
595
- RdxSelectItemIndicatorDirective,
596
- RdxSelectLabelDirective,
597
- RdxSelectComponent,
598
- RdxSelectSeparatorDirective,
599
- RdxSelectTriggerDirective,
600
- RdxSelectValueDirective,
601
- RdxSelectIconDirective] }); }
602
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectModule, imports: [RdxSelectComponent] }); }
843
+ class RdxSelectViewport {
844
+ constructor() {
845
+ this.contentContext = injectSelectContentContext();
846
+ this.elementRef = inject((ElementRef));
847
+ this.prevScrollTopRef = signal(0, ...(ngDevMode ? [{ debugName: "prevScrollTopRef" }] : /* istanbul ignore next */ []));
848
+ afterNextRender(() => {
849
+ this.contentContext?.onViewportChange(this.elementRef.nativeElement);
850
+ });
851
+ }
852
+ handleScroll(event) {
853
+ const viewport = event.currentTarget;
854
+ this.prevScrollTopRef.set(viewport.scrollTop);
855
+ }
856
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectViewport, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
857
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxSelectViewport, isStandalone: true, selector: "[rdxSelectViewport]", host: { attributes: { "role": "presentation" }, listeners: { "scroll": "handleScroll($event)" }, properties: { "attr.data-rdx-select-viewport": "\"\"", "style": "{\n position: 'relative',\n flex: 1,\n overflow: 'hidden auto',\n scrollbarWidth: 'none'\n }" } }, ngImport: i0 }); }
603
858
  }
604
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectModule, decorators: [{
605
- type: NgModule,
859
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectViewport, decorators: [{
860
+ type: Directive,
606
861
  args: [{
607
- imports: [..._imports],
608
- exports: [..._imports]
862
+ selector: '[rdxSelectViewport]',
863
+ host: {
864
+ role: 'presentation',
865
+ '[attr.data-rdx-select-viewport]': '""',
866
+ '[style]': `{
867
+ position: 'relative',
868
+ flex: 1,
869
+ overflow: 'hidden auto',
870
+ scrollbarWidth: 'none'
871
+ }`,
872
+ '(scroll)': 'handleScroll($event)'
873
+ }
609
874
  }]
610
- }] });
875
+ }], ctorParameters: () => [] });
876
+
877
+ const _importsSelect = [
878
+ RdxSelectRoot,
879
+ RdxSelectPortal,
880
+ RdxSelectTrigger,
881
+ RdxSelectValue,
882
+ RdxSelectContent,
883
+ RdxSelectViewport,
884
+ RdxSelectItemIndicator,
885
+ RdxSelectItem,
886
+ RdxSelectItemText,
887
+ RdxSelectLabel,
888
+ RdxSelectGroup,
889
+ RdxSelectPopperPositionContent,
890
+ RdxSelectPopperPositionWrapper,
891
+ RdxSelectPortalPresence
892
+ ];
611
893
 
612
894
  /**
613
895
  * Generated bundle index. Do not edit.
614
896
  */
615
897
 
616
- export { RdxSelectComponent, RdxSelectContentDirective, RdxSelectGroupDirective, RdxSelectIconDirective, RdxSelectItemChange, RdxSelectItemDirective, RdxSelectItemIndicatorDirective, RdxSelectLabelDirective, RdxSelectModule, RdxSelectSeparatorDirective, RdxSelectTriggerDirective, RdxSelectValueDirective };
898
+ export { CONTENT_MARGIN, OPEN_KEYS, RDX_SELECT_POSITIONER_TOKEN, RdxSelectContent, RdxSelectGroup, RdxSelectItem, RdxSelectItemIndicator, RdxSelectItemText, RdxSelectLabel, RdxSelectPopperPositionContent, RdxSelectPopperPositionWrapper, RdxSelectPortal, RdxSelectPortalPresence, RdxSelectRoot, RdxSelectTrigger, RdxSelectValue, RdxSelectViewport, SELECTION_KEYS, _importsSelect, compare, focusFirst, injectSelectContentContext, injectSelectItemContext, injectSelectRootContext, provideSelectContentContext, provideSelectItemContext, provideSelectRootContext, shouldShowPlaceholder, valueComparator };
617
899
  //# sourceMappingURL=radix-ng-primitives-select.mjs.map