@radix-ng/primitives 1.0.0-beta.3 → 1.0.0-beta.5
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.
- package/README.md +1 -1
- package/fesm2022/radix-ng-primitives-accordion.mjs +5 -3
- package/fesm2022/radix-ng-primitives-accordion.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-alert-dialog.mjs +3 -2
- package/fesm2022/radix-ng-primitives-alert-dialog.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-autocomplete.mjs +617 -659
- package/fesm2022/radix-ng-primitives-autocomplete.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-calendar.mjs +5 -3
- package/fesm2022/radix-ng-primitives-calendar.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-checkbox.mjs +33 -18
- package/fesm2022/radix-ng-primitives-checkbox.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-combobox.mjs +1305 -572
- package/fesm2022/radix-ng-primitives-combobox.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-config.mjs +13 -4
- package/fesm2022/radix-ng-primitives-config.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-context-menu.mjs +51 -10
- package/fesm2022/radix-ng-primitives-context-menu.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-core.mjs +1352 -64
- package/fesm2022/radix-ng-primitives-core.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-date-field.mjs +5 -3
- package/fesm2022/radix-ng-primitives-date-field.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-dialog.mjs +290 -120
- package/fesm2022/radix-ng-primitives-dialog.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-direction-provider.mjs +70 -0
- package/fesm2022/radix-ng-primitives-direction-provider.mjs.map +1 -0
- package/fesm2022/radix-ng-primitives-dismissable-layer.mjs +519 -184
- package/fesm2022/radix-ng-primitives-dismissable-layer.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-drawer.mjs +3 -3
- package/fesm2022/radix-ng-primitives-drawer.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-editable.mjs +12 -7
- package/fesm2022/radix-ng-primitives-editable.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-field.mjs +3 -2
- package/fesm2022/radix-ng-primitives-field.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-floating-focus-manager.mjs +803 -0
- package/fesm2022/radix-ng-primitives-floating-focus-manager.mjs.map +1 -0
- package/fesm2022/radix-ng-primitives-focus-scope.mjs +305 -70
- package/fesm2022/radix-ng-primitives-focus-scope.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-menu.mjs +893 -289
- package/fesm2022/radix-ng-primitives-menu.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-menubar.mjs +32 -4
- package/fesm2022/radix-ng-primitives-menubar.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-navigation-menu.mjs +144 -159
- package/fesm2022/radix-ng-primitives-navigation-menu.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-number-field.mjs +7 -2
- package/fesm2022/radix-ng-primitives-number-field.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-popover.mjs +284 -212
- package/fesm2022/radix-ng-primitives-popover.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-popper.mjs +94 -51
- package/fesm2022/radix-ng-primitives-popper.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-presence.mjs +1 -1
- package/fesm2022/radix-ng-primitives-presence.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-preview-card.mjs +141 -173
- package/fesm2022/radix-ng-primitives-preview-card.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-radio.mjs +19 -14
- package/fesm2022/radix-ng-primitives-radio.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-roving-focus.mjs +4 -2
- package/fesm2022/radix-ng-primitives-roving-focus.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-scroll-area.mjs +5 -4
- package/fesm2022/radix-ng-primitives-scroll-area.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-select.mjs +241 -164
- package/fesm2022/radix-ng-primitives-select.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-slider.mjs +262 -29
- package/fesm2022/radix-ng-primitives-slider.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-stepper.mjs +16 -10
- package/fesm2022/radix-ng-primitives-stepper.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-switch.mjs +10 -5
- package/fesm2022/radix-ng-primitives-switch.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-tabs.mjs +15 -10
- package/fesm2022/radix-ng-primitives-tabs.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-time-field.mjs +5 -3
- package/fesm2022/radix-ng-primitives-time-field.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-toast.mjs +15 -36
- package/fesm2022/radix-ng-primitives-toast.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-toggle-group.mjs +14 -7
- package/fesm2022/radix-ng-primitives-toggle-group.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-toggle.mjs +12 -6
- package/fesm2022/radix-ng-primitives-toggle.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-toolbar.mjs +5 -3
- package/fesm2022/radix-ng-primitives-toolbar.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-tooltip.mjs +251 -143
- package/fesm2022/radix-ng-primitives-tooltip.mjs.map +1 -1
- package/package.json +10 -1
- package/types/radix-ng-primitives-accordion.d.ts +4 -3
- package/types/radix-ng-primitives-autocomplete.d.ts +217 -152
- package/types/radix-ng-primitives-calendar.d.ts +5 -3
- package/types/radix-ng-primitives-checkbox.d.ts +27 -15
- package/types/radix-ng-primitives-combobox.d.ts +672 -283
- package/types/radix-ng-primitives-config.d.ts +1 -1
- package/types/radix-ng-primitives-context-menu.d.ts +15 -5
- package/types/radix-ng-primitives-core.d.ts +764 -14
- package/types/radix-ng-primitives-date-field.d.ts +3 -2
- package/types/radix-ng-primitives-dialog.d.ts +88 -32
- package/types/radix-ng-primitives-direction-provider.d.ts +41 -0
- package/types/radix-ng-primitives-dismissable-layer.d.ts +147 -99
- package/types/radix-ng-primitives-editable.d.ts +11 -5
- package/types/radix-ng-primitives-field.d.ts +1 -0
- package/types/radix-ng-primitives-floating-focus-manager.d.ts +272 -0
- package/types/radix-ng-primitives-focus-scope.d.ts +132 -1
- package/types/radix-ng-primitives-menu.d.ts +192 -103
- package/types/radix-ng-primitives-navigation-menu.d.ts +37 -75
- package/types/radix-ng-primitives-number-field.d.ts +8 -3
- package/types/radix-ng-primitives-popover.d.ts +71 -92
- package/types/radix-ng-primitives-popper.d.ts +39 -9
- package/types/radix-ng-primitives-preview-card.d.ts +39 -72
- package/types/radix-ng-primitives-radio.d.ts +13 -6
- package/types/radix-ng-primitives-roving-focus.d.ts +7 -6
- package/types/radix-ng-primitives-scroll-area.d.ts +2 -2
- package/types/radix-ng-primitives-select.d.ts +142 -109
- package/types/radix-ng-primitives-slider.d.ts +64 -12
- package/types/radix-ng-primitives-stepper.d.ts +15 -7
- package/types/radix-ng-primitives-switch.d.ts +10 -4
- package/types/radix-ng-primitives-tabs.d.ts +12 -6
- package/types/radix-ng-primitives-time-field.d.ts +3 -2
- package/types/radix-ng-primitives-toast.d.ts +7 -7
- package/types/radix-ng-primitives-toggle-group.d.ts +15 -8
- package/types/radix-ng-primitives-toggle.d.ts +10 -3
- package/types/radix-ng-primitives-toolbar.d.ts +3 -2
- package/types/radix-ng-primitives-tooltip.d.ts +61 -80
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, model,
|
|
3
|
-
import
|
|
2
|
+
import { inject, model, signal, computed, ElementRef, input, booleanAttribute, output, untracked, effect, Directive, InjectionToken, Injector, DestroyRef, afterNextRender, linkedSignal, isDevMode, forwardRef } from '@angular/core';
|
|
3
|
+
import * as i3 from '@radix-ng/primitives/core';
|
|
4
|
+
import { isEqual, getActiveElement, createContext, injectId, createFloatingRootContext, useTransitionStatus, isNullish, createCancelableChangeEventDetails, provideFloatingTree, provideFloatingRootContext, RDX_FLOATING_ROOT_CONTEXT, RDX_FLOATING_REGISTRATION, useListHighlight, useAnchoredScrollLock, RdxFloatingNodeRegistration, handleAndDispatchCustomEvent, rdxDevError, setupInternalBackdrop } from '@radix-ng/primitives/core';
|
|
5
|
+
import { injectDirection } from '@radix-ng/primitives/direction-provider';
|
|
6
|
+
import * as i2 from '@radix-ng/primitives/floating-focus-manager';
|
|
7
|
+
import { getInteractionTypeFromEvent, provideFloatingFocusManagerConfig, RdxFloatingFocusManager, createRdxTriggerInteraction } from '@radix-ng/primitives/floating-focus-manager';
|
|
4
8
|
import * as i1 from '@radix-ng/primitives/popper';
|
|
5
|
-
import { RdxPopper, RdxPopperContent, RdxPopperContentWrapper, RdxPopperAnchor } from '@radix-ng/primitives/popper';
|
|
9
|
+
import { RdxPopper, RdxPopperContent, RdxPopperContentWrapper, legacyPopperVars, provideRdxPopperContentWrapper, provideRdxPopperContentConfig, RdxPopperAnchor } from '@radix-ng/primitives/popper';
|
|
6
10
|
import * as i4 from '@radix-ng/primitives/collection';
|
|
7
11
|
import { RdxCollectionProvider, RdxCollectionItem } from '@radix-ng/primitives/collection';
|
|
8
|
-
import {
|
|
9
|
-
import * as i3 from '@radix-ng/primitives/dismissable-layer';
|
|
10
|
-
import { RdxDismissableLayer, provideRdxDismissableLayerConfig } from '@radix-ng/primitives/dismissable-layer';
|
|
11
|
-
import * as i2 from '@radix-ng/primitives/focus-scope';
|
|
12
|
-
import { RdxFocusScope } from '@radix-ng/primitives/focus-scope';
|
|
12
|
+
import { RdxDismiss } from '@radix-ng/primitives/dismissable-layer';
|
|
13
13
|
import * as i1$1 from '@radix-ng/primitives/portal';
|
|
14
14
|
import { RdxPortalPresence } from '@radix-ng/primitives/portal';
|
|
15
15
|
import { provideRdxPresenceContext } from '@radix-ng/primitives/presence';
|
|
@@ -58,13 +58,17 @@ const context$2 = () => {
|
|
|
58
58
|
triggerElement: context.triggerElement,
|
|
59
59
|
valueElement: context.valueElement,
|
|
60
60
|
triggerPointerDownPosRef: context.triggerPointerDownPosRef,
|
|
61
|
-
contentId:
|
|
61
|
+
contentId: context.contentId,
|
|
62
62
|
dir: context.dir,
|
|
63
63
|
value: context.value,
|
|
64
64
|
multiple: context.multiple,
|
|
65
65
|
isItemEqualToValue: context.isItemEqualToValue,
|
|
66
66
|
itemToStringLabel: context.itemToStringLabel,
|
|
67
67
|
open: context.open,
|
|
68
|
+
openedByTouch: context.openedByTouch,
|
|
69
|
+
openMethod: context.openMethod,
|
|
70
|
+
openInteractionType: context.openInteractionType,
|
|
71
|
+
closeInteractionType: context.closeInteractionType,
|
|
68
72
|
disabled: context.disabled,
|
|
69
73
|
modal: context.modal,
|
|
70
74
|
isEmptyModelValue: context.isEmptyModelValue,
|
|
@@ -84,32 +88,49 @@ const context$2 = () => {
|
|
|
84
88
|
context.optionsSet().delete(existingOption);
|
|
85
89
|
}
|
|
86
90
|
},
|
|
87
|
-
onValueChange: context.
|
|
91
|
+
onValueChange: (value, reason, event) => context.setValue(value, reason, event),
|
|
88
92
|
onTriggerChange: (node) => {
|
|
89
93
|
context.triggerElement.set(node.nativeElement);
|
|
90
94
|
},
|
|
91
95
|
onValueElementChange: (node) => {
|
|
92
96
|
context.valueElement.set(node);
|
|
93
97
|
},
|
|
94
|
-
onOpenChange: (value) =>
|
|
95
|
-
context.open.set(value);
|
|
96
|
-
}
|
|
98
|
+
onOpenChange: (value, reason, event) => context.setOpen(value, reason, event)
|
|
97
99
|
};
|
|
98
100
|
};
|
|
99
101
|
const [injectSelectRootContext, provideSelectRootContext] = createContext('RdxSelectRootContext', 'components/select');
|
|
100
102
|
class RdxSelectRoot {
|
|
101
103
|
constructor() {
|
|
104
|
+
this.contentId = injectId('rdx-select-content-');
|
|
102
105
|
this.open = model(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
|
|
106
|
+
/** Whether the current open was initiated by **touch** (ADR 0016 §3 — gates the anchored scroll lock). */
|
|
107
|
+
this.openedByTouch = signal(false, ...(ngDevMode ? [{ debugName: "openedByTouch" }] : /* istanbul ignore next */ []));
|
|
108
|
+
/** How the select was opened. Base UI names this state `openMethod`. */
|
|
109
|
+
this.openInteractionType = signal(null, ...(ngDevMode ? [{ debugName: "openInteractionType" }] : /* istanbul ignore next */ []));
|
|
110
|
+
/** How the select was closed. */
|
|
111
|
+
this.closeInteractionType = signal(null, ...(ngDevMode ? [{ debugName: "closeInteractionType" }] : /* istanbul ignore next */ []));
|
|
112
|
+
/** Public Base UI-aligned alias for the open interaction type. */
|
|
113
|
+
this.openMethod = computed(() => this.openInteractionType(), ...(ngDevMode ? [{ debugName: "openMethod" }] : /* istanbul ignore next */ []));
|
|
114
|
+
/** Per-popup floating root context (ADR 0015) — `open` / `triggers` / reference for the dismissal engine. */
|
|
115
|
+
this.floatingContext = createFloatingRootContext({
|
|
116
|
+
ownerDocument: inject(ElementRef).nativeElement.ownerDocument,
|
|
117
|
+
open: () => this.open()
|
|
118
|
+
});
|
|
103
119
|
this.value = model(...(ngDevMode ? [undefined, { debugName: "value" }] : /* istanbul ignore next */ []));
|
|
104
120
|
this.multiple = input(false, { ...(ngDevMode ? { debugName: "multiple" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
105
121
|
this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
106
122
|
/** Whether the popup is modal: locks page scroll and makes outside content inert while open. */
|
|
107
123
|
this.modal = input(true, { ...(ngDevMode ? { debugName: "modal" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
108
|
-
this.
|
|
124
|
+
this.dirInput = input(undefined, { ...(ngDevMode ? { debugName: "dirInput" } : /* istanbul ignore next */ {}), alias: 'dir' });
|
|
125
|
+
this.dir = injectDirection(this.dirInput);
|
|
109
126
|
/** How item values are compared for equality — a function `(a, b) => boolean` or an object key. */
|
|
110
127
|
this.isItemEqualToValue = input(...(ngDevMode ? [undefined, { debugName: "isItemEqualToValue" }] : /* istanbul ignore next */ []));
|
|
111
128
|
/** Converts a value to its display label (used by `RdxSelectValue`). */
|
|
112
129
|
this.itemToStringLabel = input(...(ngDevMode ? [undefined, { debugName: "itemToStringLabel" }] : /* istanbul ignore next */ []));
|
|
130
|
+
/** Emits before an open-state change is committed; call `eventDetails.cancel()` to veto it. */
|
|
131
|
+
this.onOpenChange = output();
|
|
132
|
+
/** Emits before a value change is committed; call `eventDetails.cancel()` to veto it. */
|
|
133
|
+
this.onValueChange = output();
|
|
113
134
|
/** Emits after the open/close transition (including any exit animation) finishes. */
|
|
114
135
|
this.onOpenChangeComplete = output();
|
|
115
136
|
this.transition = useTransitionStatus((open) => this.onOpenChangeComplete.emit(open));
|
|
@@ -150,34 +171,89 @@ class RdxSelectRoot {
|
|
|
150
171
|
previousOpen = open;
|
|
151
172
|
untracked(() => this.transition.start(open));
|
|
152
173
|
});
|
|
174
|
+
// A fresh open starts non-touch; the trigger flips it on a touch open. Reset whenever it closes.
|
|
175
|
+
effect(() => {
|
|
176
|
+
if (!this.open()) {
|
|
177
|
+
untracked(() => this.openedByTouch.set(false));
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
// Bridge the trigger into the floating context: the dismissal capability treats a press on the
|
|
181
|
+
// trigger (the reference) as "inside", and uses it for positioning containment (ADR 0015).
|
|
182
|
+
effect((onCleanup) => {
|
|
183
|
+
const trigger = this.triggerElement();
|
|
184
|
+
this.floatingContext.setReferenceElement(trigger);
|
|
185
|
+
if (trigger) {
|
|
186
|
+
this.floatingContext.triggers.add(trigger);
|
|
187
|
+
onCleanup(() => this.floatingContext.triggers.delete(trigger));
|
|
188
|
+
}
|
|
189
|
+
});
|
|
153
190
|
}
|
|
154
191
|
getOption(value) {
|
|
155
192
|
return Array.from(this.optionsSet()).find((option) => valueComparator(value, option.value, this.isItemEqualToValue()));
|
|
156
193
|
}
|
|
157
|
-
|
|
194
|
+
setValue(value, reason = 'none', event = new Event('select.value-change')) {
|
|
195
|
+
const nextValue = this.multiple()
|
|
196
|
+
? (() => {
|
|
197
|
+
const current = this.value();
|
|
198
|
+
const array = Array.isArray(current) ? [...current] : [];
|
|
199
|
+
const index = array.findIndex((i) => compare(i, value, this.isItemEqualToValue()));
|
|
200
|
+
index === -1 ? array.push(value) : array.splice(index, 1);
|
|
201
|
+
return [...array];
|
|
202
|
+
})()
|
|
203
|
+
: value;
|
|
204
|
+
const { eventDetails } = createCancelableChangeEventDetails(reason, event, this.triggerElement() ?? undefined);
|
|
205
|
+
this.onValueChange.emit({ value: nextValue, eventDetails });
|
|
206
|
+
if (eventDetails.isCanceled()) {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
158
209
|
if (this.multiple()) {
|
|
159
|
-
|
|
160
|
-
const array = Array.isArray(current) ? [...current] : [];
|
|
161
|
-
const index = array.findIndex((i) => compare(i, value, this.isItemEqualToValue()));
|
|
162
|
-
index === -1 ? array.push(value) : array.splice(index, 1);
|
|
163
|
-
this.value.set([...array]);
|
|
210
|
+
this.value.set(nextValue);
|
|
164
211
|
}
|
|
165
212
|
else {
|
|
166
|
-
this.value.set(
|
|
213
|
+
this.value.set(nextValue);
|
|
167
214
|
}
|
|
215
|
+
return true;
|
|
216
|
+
}
|
|
217
|
+
setOpen(open, reason = 'none', event) {
|
|
218
|
+
const resolvedEvent = event ?? new Event('select.open-change');
|
|
219
|
+
const interactionType = getInteractionTypeFromEvent(event);
|
|
220
|
+
const { eventDetails } = createCancelableChangeEventDetails(reason, resolvedEvent, this.triggerElement() ?? undefined);
|
|
221
|
+
this.onOpenChange.emit({ open, eventDetails });
|
|
222
|
+
if (eventDetails.isCanceled()) {
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
this.open.set(open);
|
|
226
|
+
if (open) {
|
|
227
|
+
this.openedByTouch.set(event?.pointerType === 'touch');
|
|
228
|
+
this.openInteractionType.set(interactionType);
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
this.closeInteractionType.set(interactionType);
|
|
232
|
+
}
|
|
233
|
+
return true;
|
|
168
234
|
}
|
|
169
235
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectRoot, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
170
|
-
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 }, modal: { classPropertyName: "modal", publicName: "modal", isSignal: true, isRequired: false, transformFunction: null },
|
|
236
|
+
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 }, modal: { classPropertyName: "modal", publicName: "modal", isSignal: true, isRequired: false, transformFunction: null }, dirInput: { classPropertyName: "dirInput", publicName: "dir", isSignal: true, isRequired: false, transformFunction: null }, isItemEqualToValue: { classPropertyName: "isItemEqualToValue", publicName: "isItemEqualToValue", isSignal: true, isRequired: false, transformFunction: null }, itemToStringLabel: { classPropertyName: "itemToStringLabel", publicName: "itemToStringLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", value: "valueChange", onOpenChange: "onOpenChange", onValueChange: "onValueChange", onOpenChangeComplete: "onOpenChangeComplete" }, providers: [
|
|
237
|
+
provideSelectRootContext(context$2),
|
|
238
|
+
// New floating foundation (ADR 0015/0017) — the dismissal capability reads this shared context.
|
|
239
|
+
provideFloatingTree(),
|
|
240
|
+
provideFloatingRootContext(() => inject(RdxSelectRoot).floatingContext)
|
|
241
|
+
], exportAs: ["rdxSelectRoot"], hostDirectives: [{ directive: i1.RdxPopper }], ngImport: i0 }); }
|
|
171
242
|
}
|
|
172
243
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectRoot, decorators: [{
|
|
173
244
|
type: Directive,
|
|
174
245
|
args: [{
|
|
175
246
|
selector: '[rdxSelectRoot]',
|
|
176
247
|
exportAs: 'rdxSelectRoot',
|
|
177
|
-
providers: [
|
|
248
|
+
providers: [
|
|
249
|
+
provideSelectRootContext(context$2),
|
|
250
|
+
// New floating foundation (ADR 0015/0017) — the dismissal capability reads this shared context.
|
|
251
|
+
provideFloatingTree(),
|
|
252
|
+
provideFloatingRootContext(() => inject(RdxSelectRoot).floatingContext)
|
|
253
|
+
],
|
|
178
254
|
hostDirectives: [RdxPopper]
|
|
179
255
|
}]
|
|
180
|
-
}], ctorParameters: () => [], 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 }] }], modal: [{ type: i0.Input, args: [{ isSignal: true, alias: "modal", required: false }] }],
|
|
256
|
+
}], ctorParameters: () => [], 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 }] }], modal: [{ type: i0.Input, args: [{ isSignal: true, alias: "modal", required: false }] }], dirInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "dir", required: false }] }], isItemEqualToValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "isItemEqualToValue", required: false }] }], itemToStringLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemToStringLabel", required: false }] }], onOpenChange: [{ type: i0.Output, args: ["onOpenChange"] }], onValueChange: [{ type: i0.Output, args: ["onValueChange"] }], onOpenChangeComplete: [{ type: i0.Output, args: ["onOpenChangeComplete"] }] } });
|
|
181
257
|
|
|
182
258
|
/**
|
|
183
259
|
* An overlay rendered beneath the popup in `modal` mode. Place it inside the portal/presence; style
|
|
@@ -312,7 +388,8 @@ const RDX_SELECT_POSITIONER_TOKEN = new InjectionToken('RDX_SELECT_POSITIONER_TO
|
|
|
312
388
|
*/
|
|
313
389
|
class RdxSelectPopup {
|
|
314
390
|
constructor() {
|
|
315
|
-
this.
|
|
391
|
+
this.floatingContext = inject(RDX_FLOATING_ROOT_CONTEXT);
|
|
392
|
+
this.registration = inject(RDX_FLOATING_REGISTRATION, { optional: true });
|
|
316
393
|
this.currentElement = inject(ElementRef);
|
|
317
394
|
this.collection = inject(RdxCollectionProvider);
|
|
318
395
|
this.injector = inject(Injector);
|
|
@@ -347,12 +424,12 @@ class RdxSelectPopup {
|
|
|
347
424
|
* Event handler called when the escape key is down.
|
|
348
425
|
* Can be prevented.
|
|
349
426
|
*/
|
|
350
|
-
this.escapeKeyDown =
|
|
427
|
+
this.escapeKeyDown = output();
|
|
351
428
|
/**
|
|
352
|
-
* Event handler called when a `pointerdown` event happens outside of the
|
|
429
|
+
* Event handler called when a `pointerdown` event happens outside of the popup.
|
|
353
430
|
* Can be prevented.
|
|
354
431
|
*/
|
|
355
|
-
this.pointerDownOutside =
|
|
432
|
+
this.pointerDownOutside = output();
|
|
356
433
|
this.content = signal(null, ...(ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []));
|
|
357
434
|
/**
|
|
358
435
|
* The positioner — now an **ancestor** element — provides {@link RDX_SELECT_POSITIONER_TOKEN}
|
|
@@ -383,27 +460,34 @@ class RdxSelectPopup {
|
|
|
383
460
|
item.element.scrollIntoView?.({ block: 'nearest' });
|
|
384
461
|
}
|
|
385
462
|
});
|
|
386
|
-
// Lock page scroll while
|
|
387
|
-
|
|
463
|
+
// Activation policy (ADR 0016 §2 + §3). Lock page scroll while the popup is OPEN and either modal
|
|
464
|
+
// **or** item-aligned — Base UI `(alignItemWithTriggerActive || modal) && open` (AC #3): an
|
|
465
|
+
// item-aligned select overlays the trigger, so the page must not scroll behind it even when
|
|
466
|
+
// `modal === false`. The gate keys on `open` (not mounted) so it releases at close-start. A
|
|
467
|
+
// **touch** open never uses item-aligned mode (the positioner falls back), so the lock there is
|
|
468
|
+
// driven by `modal` alone and the anchored helper only engages when the popup is viewport-width (§3).
|
|
469
|
+
const itemAlignedActive = computed(() => this.positioner?.alignItemWithTriggerActive?.() ?? false, ...(ngDevMode ? [{ debugName: "itemAlignedActive" }] : /* istanbul ignore next */ []));
|
|
470
|
+
useAnchoredScrollLock(computed(() => (itemAlignedActive() || this.rootContext.modal()) && this.rootContext.open()), {
|
|
471
|
+
touchOpen: () => this.rootContext.openedByTouch(),
|
|
472
|
+
element: () => this.currentElement.nativeElement
|
|
473
|
+
});
|
|
388
474
|
// The popup's animation determines when the open/close transition (onOpenChangeComplete) is done.
|
|
389
475
|
const unregisterTransition = this.rootContext.registerTransitionElement(this.currentElement.nativeElement);
|
|
390
476
|
inject(DestroyRef).onDestroy(unregisterTransition);
|
|
391
|
-
|
|
392
|
-
this.
|
|
393
|
-
|
|
477
|
+
// The popup (listbox) is this layer's floating element — the inside surface for containment.
|
|
478
|
+
this.floatingContext.setFloatingElement(this.currentElement.nativeElement);
|
|
479
|
+
// Dismissal (ADR 0015): Escape or an outside press closes the select. Focus-out does NOT close it
|
|
480
|
+
// — the listbox holds focus while open (items are navigated virtually), so a focus-out is not a
|
|
481
|
+
// dismissal (the legacy preventDefaulted it too).
|
|
482
|
+
new RdxDismiss(this.floatingContext, () => this.registration?.node() ?? null, {
|
|
483
|
+
escapeKey: () => true,
|
|
484
|
+
outsidePress: () => true,
|
|
485
|
+
focusOutside: () => false,
|
|
486
|
+
onEscapeKeyDown: (event) => this.escapeKeyDown.emit(event),
|
|
487
|
+
onPointerDownOutside: (event) => this.pointerDownOutside.emit(event),
|
|
488
|
+
onDismiss: (reason, event) => this.rootContext.onOpenChange(false, reason === 'escape-key' ? 'escape-key' : reason === 'focus-outside' ? 'focus-out' : 'outside-press', event)
|
|
489
|
+
});
|
|
394
490
|
afterNextRender(() => {
|
|
395
|
-
focusScope.unmountAutoFocus.subscribe((event) => {
|
|
396
|
-
if (event.defaultPrevented)
|
|
397
|
-
return;
|
|
398
|
-
this.rootContext.triggerElement()?.focus({ preventScroll: true });
|
|
399
|
-
event.preventDefault();
|
|
400
|
-
});
|
|
401
|
-
// Focus the popup itself (not an item) — the listbox is the focus owner; items are
|
|
402
|
-
// navigated virtually via aria-activedescendant.
|
|
403
|
-
focusScope.mountAutoFocus.subscribe((event) => {
|
|
404
|
-
event.preventDefault();
|
|
405
|
-
this.content()?.focus({ preventScroll: true });
|
|
406
|
-
});
|
|
407
491
|
// The popup is now the listbox host itself (no longer the positioner's first child).
|
|
408
492
|
this.content.set(this.currentElement.nativeElement);
|
|
409
493
|
});
|
|
@@ -427,8 +511,9 @@ class RdxSelectPopup {
|
|
|
427
511
|
}
|
|
428
512
|
else {
|
|
429
513
|
// otherwise, if the event was outside the content, close.
|
|
430
|
-
if (!this.content()?.contains(event.target))
|
|
431
|
-
this.rootContext.onOpenChange(false);
|
|
514
|
+
if (!this.content()?.contains(event.target)) {
|
|
515
|
+
this.rootContext.onOpenChange(false, 'outside-press', event);
|
|
516
|
+
}
|
|
432
517
|
}
|
|
433
518
|
document.removeEventListener('pointermove', handlePointerMove);
|
|
434
519
|
this.rootContext.triggerPointerDownPosRef.set(null);
|
|
@@ -447,6 +532,21 @@ class RdxSelectPopup {
|
|
|
447
532
|
});
|
|
448
533
|
});
|
|
449
534
|
});
|
|
535
|
+
effect((onCleanup) => {
|
|
536
|
+
if (!itemAlignedActive() || !this.rootContext.open()) {
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
const popup = this.content();
|
|
540
|
+
const view = popup?.ownerDocument.defaultView;
|
|
541
|
+
if (!view) {
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
const handleResize = (event) => {
|
|
545
|
+
this.rootContext.onOpenChange(false, 'window-resize', event);
|
|
546
|
+
};
|
|
547
|
+
view.addEventListener('resize', handleResize);
|
|
548
|
+
onCleanup(() => view.removeEventListener('resize', handleResize));
|
|
549
|
+
});
|
|
450
550
|
}
|
|
451
551
|
/** Highlights the selected item (or the first enabled one) when the popup opens. */
|
|
452
552
|
highlightSelectedItem() {
|
|
@@ -481,9 +581,10 @@ class RdxSelectPopup {
|
|
|
481
581
|
event.preventDefault();
|
|
482
582
|
const item = this.highlight.highlightedItem();
|
|
483
583
|
if (item && !item.disabled()) {
|
|
484
|
-
this.rootContext.onValueChange(item.value());
|
|
485
|
-
if (!this.rootContext.multiple())
|
|
486
|
-
this.rootContext.onOpenChange(false);
|
|
584
|
+
this.rootContext.onValueChange(item.value(), 'item-press', event);
|
|
585
|
+
if (!this.rootContext.multiple()) {
|
|
586
|
+
this.rootContext.onOpenChange(false, 'item-press', event);
|
|
587
|
+
}
|
|
487
588
|
}
|
|
488
589
|
return;
|
|
489
590
|
}
|
|
@@ -509,23 +610,46 @@ class RdxSelectPopup {
|
|
|
509
610
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectPopup, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
510
611
|
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxSelectPopup, isStandalone: true, selector: "[rdxSelectPopup]", outputs: { escapeKeyDown: "escapeKeyDown", pointerDownOutside: "pointerDownOutside" }, host: { attributes: { "role": "listbox", "tabindex": "-1" }, listeners: { "keydown": "handleKeyDown($event)" }, properties: { "id": "rootContext.contentId", "attr.aria-activedescendant": "highlight.activeId()", "attr.aria-multiselectable": "rootContext.multiple() ? \"true\" : undefined", "attr.data-state": "rootContext.open() ? \"open\" : \"closed\"", "attr.data-open": "rootContext.open() ? \"\" : undefined", "attr.data-closed": "rootContext.open() ? undefined : \"\"", "attr.data-starting-style": "rootContext.transitionStatus() === \"starting\" ? \"\" : undefined", "attr.data-ending-style": "rootContext.transitionStatus() === \"ending\" ? \"\" : undefined", "dir": "rootContext.dir()", "style": "{\n display: 'flex',\n flexDirection: 'column',\n outline: 'none'\n }" } }, providers: [
|
|
511
612
|
provideSelectPopupContext(context$1),
|
|
512
|
-
|
|
613
|
+
provideFloatingFocusManagerConfig(() => {
|
|
614
|
+
const rootContext = injectSelectRootContext();
|
|
615
|
+
const host = inject(ElementRef).nativeElement;
|
|
513
616
|
return {
|
|
514
|
-
|
|
617
|
+
modal: () => false,
|
|
618
|
+
enabled: () => rootContext.open() || rootContext.transitionStatus() === 'ending',
|
|
619
|
+
closeOnFocusOut: () => false,
|
|
620
|
+
// The listbox owns DOM focus; items are navigated virtually through aria-activedescendant.
|
|
621
|
+
initialFocus: () => host,
|
|
622
|
+
restoreFocus: () => true,
|
|
623
|
+
openInteractionType: () => rootContext.openInteractionType(),
|
|
624
|
+
closeInteractionType: () => rootContext.closeInteractionType()
|
|
515
625
|
};
|
|
516
626
|
})
|
|
517
|
-
], hostDirectives: [{ directive: i1.RdxPopperContent }, { directive: i2.
|
|
627
|
+
], hostDirectives: [{ directive: i1.RdxPopperContent }, { directive: i2.RdxFloatingFocusManager, inputs: ["returnFocus", "finalFocus"] }, { directive: i3.RdxFloatingNodeRegistration }, { directive: i4.RdxCollectionProvider }], ngImport: i0 }); }
|
|
518
628
|
}
|
|
519
629
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectPopup, decorators: [{
|
|
520
630
|
type: Directive,
|
|
521
631
|
args: [{
|
|
522
632
|
selector: '[rdxSelectPopup]',
|
|
523
|
-
hostDirectives: [
|
|
633
|
+
hostDirectives: [
|
|
634
|
+
RdxPopperContent,
|
|
635
|
+
{ directive: RdxFloatingFocusManager, inputs: ['returnFocus: finalFocus'] },
|
|
636
|
+
RdxFloatingNodeRegistration,
|
|
637
|
+
RdxCollectionProvider
|
|
638
|
+
],
|
|
524
639
|
providers: [
|
|
525
640
|
provideSelectPopupContext(context$1),
|
|
526
|
-
|
|
641
|
+
provideFloatingFocusManagerConfig(() => {
|
|
642
|
+
const rootContext = injectSelectRootContext();
|
|
643
|
+
const host = inject(ElementRef).nativeElement;
|
|
527
644
|
return {
|
|
528
|
-
|
|
645
|
+
modal: () => false,
|
|
646
|
+
enabled: () => rootContext.open() || rootContext.transitionStatus() === 'ending',
|
|
647
|
+
closeOnFocusOut: () => false,
|
|
648
|
+
// The listbox owns DOM focus; items are navigated virtually through aria-activedescendant.
|
|
649
|
+
initialFocus: () => host,
|
|
650
|
+
restoreFocus: () => true,
|
|
651
|
+
openInteractionType: () => rootContext.openInteractionType(),
|
|
652
|
+
closeInteractionType: () => rootContext.closeInteractionType()
|
|
529
653
|
};
|
|
530
654
|
})
|
|
531
655
|
],
|
|
@@ -594,9 +718,9 @@ class RdxSelectItem {
|
|
|
594
718
|
handleAndDispatchCustomEvent(this.SELECT_SELECT, async (event) => {
|
|
595
719
|
if (event.defaultPrevented)
|
|
596
720
|
return;
|
|
597
|
-
this.rootContext.onValueChange(this.value());
|
|
721
|
+
this.rootContext.onValueChange(this.value(), 'item-press', event.detail.originalEvent);
|
|
598
722
|
if (!this.rootContext.multiple()) {
|
|
599
|
-
this.rootContext.onOpenChange(false);
|
|
723
|
+
this.rootContext.onOpenChange(false, 'item-press', event.detail.originalEvent);
|
|
600
724
|
}
|
|
601
725
|
}, eventDetail);
|
|
602
726
|
}
|
|
@@ -773,9 +897,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
773
897
|
class RdxSelectPortalMisuseGuard {
|
|
774
898
|
constructor() {
|
|
775
899
|
if (isDevMode()) {
|
|
776
|
-
|
|
900
|
+
rdxDevError('select/portal-on-element', '`rdxSelectPortal` is now a structural directive. ' +
|
|
777
901
|
'Use `*rdxSelectPortal` on the popup element or `<ng-template rdxSelectPortal>`. ' +
|
|
778
|
-
'rdxSelectPortalPresence has been removed.
|
|
902
|
+
'rdxSelectPortalPresence has been removed.', 'components/select');
|
|
779
903
|
}
|
|
780
904
|
}
|
|
781
905
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectPortalMisuseGuard, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
@@ -788,112 +912,53 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
788
912
|
}]
|
|
789
913
|
}], ctorParameters: () => [] });
|
|
790
914
|
|
|
791
|
-
|
|
915
|
+
/**
|
|
916
|
+
* Positions the select popup against the trigger using the popper engine.
|
|
917
|
+
*
|
|
918
|
+
* A "thin" positioner (ADR 0012): it inherits the full popper positioning surface — the inputs
|
|
919
|
+
* (`side`, `sideOffset`, `align`, …), the `placed` output, and the host bindings — from
|
|
920
|
+
* {@link RdxPopperContentWrapper}, and declares select's Base UI-aligned defaults via the config
|
|
921
|
+
* provider. It also satisfies {@link RdxPositionerImpl} (via the inherited `placed`) so the popup can
|
|
922
|
+
* resolve it through {@link RDX_SELECT_POSITIONER_TOKEN}, the same as the item-aligned positioner.
|
|
923
|
+
*/
|
|
924
|
+
class RdxSelectPositioner extends RdxPopperContentWrapper {
|
|
792
925
|
constructor() {
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
this.align = input('start', ...(ngDevMode ? [{ debugName: "align" }] : /* istanbul ignore next */ []));
|
|
806
|
-
/**
|
|
807
|
-
* An offset in pixels from the `start` or `end` alignment options.
|
|
808
|
-
*/
|
|
809
|
-
this.alignOffset = input(0, { ...(ngDevMode ? { debugName: "alignOffset" } : /* istanbul ignore next */ {}), transform: numberAttribute });
|
|
810
|
-
/**
|
|
811
|
-
* The padding between the arrow and the edges of the content.
|
|
812
|
-
* If your content has border-radius, this will prevent it from overflowing the corners.
|
|
813
|
-
*/
|
|
814
|
-
this.arrowPadding = input(0, { ...(ngDevMode ? { debugName: "arrowPadding" } : /* istanbul ignore next */ {}), transform: numberAttribute });
|
|
815
|
-
/**
|
|
816
|
-
* When `true`, overrides the `side` and `align` preferences to prevent collisions with boundary edges.
|
|
817
|
-
*/
|
|
818
|
-
this.avoidCollisions = input(true, { ...(ngDevMode ? { debugName: "avoidCollisions" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
819
|
-
/**
|
|
820
|
-
* The element used as the collision boundary.
|
|
821
|
-
* By default this is the viewport, though you can provide additional element(s) to be included in this check.
|
|
822
|
-
*/
|
|
823
|
-
this.collisionBoundary = input(...(ngDevMode ? [undefined, { debugName: "collisionBoundary" }] : /* istanbul ignore next */ []));
|
|
824
|
-
/**
|
|
825
|
-
* The distance in pixels from the boundary edges where collision detection should occur.
|
|
826
|
-
* Accepts a number (same for all sides), or a partial padding object, for example: `{ top: 20, left: 20 }`.
|
|
827
|
-
*/
|
|
828
|
-
this.collisionPadding = input(0, ...(ngDevMode ? [{ debugName: "collisionPadding" }] : /* istanbul ignore next */ []));
|
|
829
|
-
/**
|
|
830
|
-
* The sticky behavior on the `align` axis.
|
|
831
|
-
* - `partial` will keep the content in the boundary as long as the trigger is at least partially in the boundary
|
|
832
|
-
* - `always` will keep the content in the boundary regardless.
|
|
833
|
-
*/
|
|
834
|
-
this.sticky = input('partial', ...(ngDevMode ? [{ debugName: "sticky" }] : /* istanbul ignore next */ []));
|
|
835
|
-
/**
|
|
836
|
-
* Whether to hide the content when the trigger becomes fully occluded.
|
|
837
|
-
*/
|
|
838
|
-
this.hideWhenDetached = input(false, { ...(ngDevMode ? { debugName: "hideWhenDetached" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
839
|
-
/**
|
|
840
|
-
* Whether to update the position of the floating element on every animation frame if required.
|
|
841
|
-
*/
|
|
842
|
-
this.updatePositionStrategy = input('always', ...(ngDevMode ? [{ debugName: "updatePositionStrategy" }] : /* istanbul ignore next */ []));
|
|
843
|
-
/**
|
|
844
|
-
* Emits when the element is placed.
|
|
845
|
-
*/
|
|
846
|
-
this.placed = outputFromObservable(outputToObservable(inject(RdxPopperContentWrapper).placed));
|
|
926
|
+
super();
|
|
927
|
+
this.positionerStyle = { boxSizing: 'border-box', ...legacyPopperVars('select') };
|
|
928
|
+
const rootContext = injectSelectRootContext();
|
|
929
|
+
const injector = inject(Injector);
|
|
930
|
+
const host = inject(ElementRef).nativeElement;
|
|
931
|
+
// Modal select isolates the background with an internal backdrop (finding #1 / Base UI) instead of
|
|
932
|
+
// a global pointer lock; the trigger stays clickable through a cutout (toggle-close).
|
|
933
|
+
afterNextRender(() => setupInternalBackdrop(host, injector, {
|
|
934
|
+
isOpen: () => rootContext.open(),
|
|
935
|
+
shouldRender: () => rootContext.modal(),
|
|
936
|
+
cutout: () => rootContext.triggerElement()
|
|
937
|
+
}));
|
|
847
938
|
}
|
|
848
939
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectPositioner, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
849
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
], 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 }); }
|
|
940
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxSelectPositioner, isStandalone: true, selector: "[rdxSelectPositioner]", host: { properties: { "style": "positionerStyle" } }, providers: [
|
|
941
|
+
...provideRdxPopperContentWrapper(RdxSelectPositioner),
|
|
942
|
+
provideRdxPopperContentConfig({ align: 'start', updatePositionStrategy: 'always' }),
|
|
943
|
+
{ provide: RDX_SELECT_POSITIONER_TOKEN, useExisting: forwardRef(() => RdxSelectPositioner) }
|
|
944
|
+
], usesInheritance: true, ngImport: i0 }); }
|
|
855
945
|
}
|
|
856
946
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectPositioner, decorators: [{
|
|
857
947
|
type: Directive,
|
|
858
948
|
args: [{
|
|
859
949
|
selector: '[rdxSelectPositioner]',
|
|
860
950
|
providers: [
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
}
|
|
865
|
-
],
|
|
866
|
-
hostDirectives: [
|
|
867
|
-
{
|
|
868
|
-
directive: RdxPopperContentWrapper,
|
|
869
|
-
inputs: [
|
|
870
|
-
'side',
|
|
871
|
-
'sideOffset',
|
|
872
|
-
'align',
|
|
873
|
-
'alignOffset',
|
|
874
|
-
'arrowPadding',
|
|
875
|
-
'avoidCollisions',
|
|
876
|
-
'collisionBoundary',
|
|
877
|
-
'collisionPadding',
|
|
878
|
-
'sticky',
|
|
879
|
-
'hideWhenDetached',
|
|
880
|
-
'updatePositionStrategy'
|
|
881
|
-
]
|
|
882
|
-
}
|
|
951
|
+
...provideRdxPopperContentWrapper(RdxSelectPositioner),
|
|
952
|
+
provideRdxPopperContentConfig({ align: 'start', updatePositionStrategy: 'always' }),
|
|
953
|
+
{ provide: RDX_SELECT_POSITIONER_TOKEN, useExisting: forwardRef(() => RdxSelectPositioner) }
|
|
883
954
|
],
|
|
884
955
|
host: {
|
|
885
|
-
//
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
'--radix-select-content-transform-origin': 'var(--radix-popper-transform-origin)',
|
|
889
|
-
'--radix-select-content-available-width': 'var(--radix-popper-available-width)',
|
|
890
|
-
'--radix-select-content-available-height': 'var(--radix-popper-available-height)',
|
|
891
|
-
'--radix-select-trigger-width': 'var(--radix-popper-anchor-width)',
|
|
892
|
-
'--radix-select-trigger-height': 'var(--radix-popper-anchor-height)',
|
|
893
|
-
}`
|
|
956
|
+
// The unified vars + placement attrs come from the wrapper (ADR 0012); only `box-sizing` and
|
|
957
|
+
// the deprecated `--radix-select-*` aliases (still consumed by demos) remain here.
|
|
958
|
+
'[style]': 'positionerStyle'
|
|
894
959
|
}
|
|
895
960
|
}]
|
|
896
|
-
}],
|
|
961
|
+
}], ctorParameters: () => [] });
|
|
897
962
|
|
|
898
963
|
/**
|
|
899
964
|
* A visual divider between groups of items.
|
|
@@ -926,6 +991,13 @@ class RdxSelectTrigger {
|
|
|
926
991
|
this.id = input(injectId('rdx-select-trigger-'), ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
927
992
|
this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
928
993
|
this.isDisabled = computed(() => this.rootContext.disabled() || this.disabled() || Boolean(this.fieldRootContext?.disabledState()), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
|
|
994
|
+
this.triggerInteraction = createRdxTriggerInteraction({
|
|
995
|
+
trigger: () => this.elementRef.nativeElement,
|
|
996
|
+
activeTrigger: () => this.rootContext.triggerElement(),
|
|
997
|
+
open: () => this.rootContext.open(),
|
|
998
|
+
disabled: () => this.isDisabled(),
|
|
999
|
+
contentId: () => this.rootContext.contentId
|
|
1000
|
+
});
|
|
929
1001
|
this.invalidState = computed(() => Boolean(this.fieldRootContext?.invalidState()), ...(ngDevMode ? [{ debugName: "invalidState" }] : /* istanbul ignore next */ []));
|
|
930
1002
|
this.requiredState = computed(() => Boolean(this.fieldRootContext?.requiredState()), ...(ngDevMode ? [{ debugName: "requiredState" }] : /* istanbul ignore next */ []));
|
|
931
1003
|
this.filledState = computed(() => !this.rootContext.isEmptyModelValue() || Boolean(this.fieldRootContext?.filledState()), ...(ngDevMode ? [{ debugName: "filledState" }] : /* istanbul ignore next */ []));
|
|
@@ -947,18 +1019,20 @@ class RdxSelectTrigger {
|
|
|
947
1019
|
this.fieldRootContext?.setFilled(!this.rootContext.isEmptyModelValue());
|
|
948
1020
|
});
|
|
949
1021
|
}
|
|
950
|
-
handleOpen() {
|
|
1022
|
+
handleOpen(reason, event) {
|
|
951
1023
|
if (!this.isDisabled()) {
|
|
952
|
-
this.rootContext.onOpenChange(true);
|
|
1024
|
+
return this.rootContext.onOpenChange(true, reason, event);
|
|
953
1025
|
}
|
|
1026
|
+
return false;
|
|
954
1027
|
}
|
|
955
1028
|
handlePointerOpen(event) {
|
|
956
1029
|
const pointerEvent = event;
|
|
957
|
-
this.handleOpen()
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
1030
|
+
if (this.handleOpen('trigger-press', event)) {
|
|
1031
|
+
this.rootContext.triggerPointerDownPosRef.set({
|
|
1032
|
+
x: Math.round(pointerEvent.pageX),
|
|
1033
|
+
y: Math.round(pointerEvent.pageY)
|
|
1034
|
+
});
|
|
1035
|
+
}
|
|
962
1036
|
}
|
|
963
1037
|
onClickHandler(event) {
|
|
964
1038
|
// Whilst browsers generally have no issue focusing the trigger when clicking
|
|
@@ -970,6 +1044,7 @@ class RdxSelectTrigger {
|
|
|
970
1044
|
}
|
|
971
1045
|
onPointerDown(event) {
|
|
972
1046
|
const pointerEvent = event;
|
|
1047
|
+
this.triggerInteraction.recordPointerDown(pointerEvent);
|
|
973
1048
|
if (pointerEvent.pointerType === 'touch')
|
|
974
1049
|
return event.preventDefault();
|
|
975
1050
|
// prevent implicit pointer capture
|
|
@@ -996,7 +1071,8 @@ class RdxSelectTrigger {
|
|
|
996
1071
|
onKeydown(event) {
|
|
997
1072
|
const keyEvent = event;
|
|
998
1073
|
if (OPEN_KEYS.includes(keyEvent.key)) {
|
|
999
|
-
|
|
1074
|
+
const reason = keyEvent.key === 'ArrowUp' || keyEvent.key === 'ArrowDown' ? 'list-navigation' : 'trigger-press';
|
|
1075
|
+
this.handleOpen(reason, event);
|
|
1000
1076
|
event.preventDefault();
|
|
1001
1077
|
}
|
|
1002
1078
|
}
|
|
@@ -1008,7 +1084,7 @@ class RdxSelectTrigger {
|
|
|
1008
1084
|
this.fieldRootContext?.setTouched(true);
|
|
1009
1085
|
}
|
|
1010
1086
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectTrigger, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1011
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxSelectTrigger, isStandalone: true, selector: "button[rdxSelectTrigger]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, 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)", "focus": "onFocus()", "blur": "onBlur()" }, properties: { "attr.id": "id()", "attr.aria-describedby": "describedBy()", "attr.aria-invalid": "invalidState() ? \"true\" : undefined", "attr.aria-required": "requiredState() ? \"true\" : undefined", "attr.disabled": "isDisabled() ? \"\" : undefined", "dir": "rootContext.dir()", "attr.data-state": "
|
|
1087
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxSelectTrigger, isStandalone: true, selector: "button[rdxSelectTrigger]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, 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)", "focus": "onFocus()", "blur": "onBlur()" }, properties: { "attr.id": "id()", "attr.aria-describedby": "describedBy()", "attr.aria-controls": "triggerInteraction.ariaControls()", "attr.aria-invalid": "invalidState() ? \"true\" : undefined", "attr.aria-required": "requiredState() ? \"true\" : undefined", "attr.disabled": "isDisabled() ? \"\" : undefined", "dir": "rootContext.dir()", "attr.data-state": "triggerInteraction.dataState()", "attr.data-popup-open": "triggerInteraction.dataPopupOpen()", "attr.data-placeholder": "dataAttr(rootContext.isEmptyModelValue())", "attr.data-disabled": "dataAttr(isDisabled())", "attr.data-invalid": "dataAttr(invalidState())", "attr.data-valid": "dataAttr(!invalidState())", "attr.data-required": "dataAttr(requiredState())", "attr.data-filled": "dataAttr(filledState())", "attr.data-focused": "dataAttr(focusedState())" } }, hostDirectives: [{ directive: i1.RdxPopperAnchor }], ngImport: i0 }); }
|
|
1012
1088
|
}
|
|
1013
1089
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxSelectTrigger, decorators: [{
|
|
1014
1090
|
type: Directive,
|
|
@@ -1020,12 +1096,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
1020
1096
|
type: 'button',
|
|
1021
1097
|
'[attr.id]': 'id()',
|
|
1022
1098
|
'[attr.aria-describedby]': 'describedBy()',
|
|
1099
|
+
'[attr.aria-controls]': 'triggerInteraction.ariaControls()',
|
|
1023
1100
|
'[attr.aria-invalid]': 'invalidState() ? "true" : undefined',
|
|
1024
1101
|
'[attr.aria-required]': 'requiredState() ? "true" : undefined',
|
|
1025
1102
|
'[attr.disabled]': 'isDisabled() ? "" : undefined',
|
|
1026
1103
|
'[dir]': 'rootContext.dir()',
|
|
1027
|
-
'[attr.data-state]': '
|
|
1028
|
-
'[attr.data-popup-open]': '
|
|
1104
|
+
'[attr.data-state]': 'triggerInteraction.dataState()',
|
|
1105
|
+
'[attr.data-popup-open]': 'triggerInteraction.dataPopupOpen()',
|
|
1029
1106
|
'[attr.data-placeholder]': 'dataAttr(rootContext.isEmptyModelValue())',
|
|
1030
1107
|
'[attr.data-disabled]': 'dataAttr(isDisabled())',
|
|
1031
1108
|
'[attr.data-invalid]': 'dataAttr(invalidState())',
|