@jobber/components 8.23.0 → 8.23.1

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 (134) hide show
  1. package/dist/Autocomplete/index.cjs +1 -1
  2. package/dist/Autocomplete/index.mjs +1 -1
  3. package/dist/Card/index.cjs +4 -4
  4. package/dist/Card/index.mjs +4 -4
  5. package/dist/Chip/index.cjs +1 -1
  6. package/dist/Chip/index.mjs +1 -1
  7. package/dist/Chips/InternalChipDismissible/hooks/index.cjs +1 -1
  8. package/dist/Chips/InternalChipDismissible/hooks/index.mjs +1 -1
  9. package/dist/Chips/InternalChipDismissible/index.cjs +1 -1
  10. package/dist/Chips/InternalChipDismissible/index.mjs +1 -1
  11. package/dist/Chips/index.cjs +1 -1
  12. package/dist/Chips/index.mjs +1 -1
  13. package/dist/ComboboxChipRemove-cjs.js +668 -379
  14. package/dist/ComboboxChipRemove-es.js +508 -219
  15. package/dist/ConfirmationModal/index.cjs +1 -1
  16. package/dist/ConfirmationModal/index.mjs +1 -1
  17. package/dist/DataDump/index.cjs +4 -4
  18. package/dist/DataDump/index.mjs +4 -4
  19. package/dist/DataList/components/DataListActions/index.cjs +1 -1
  20. package/dist/DataList/components/DataListActions/index.mjs +1 -1
  21. package/dist/DataList/components/DataListBulkActions/index.cjs +1 -1
  22. package/dist/DataList/components/DataListBulkActions/index.mjs +1 -1
  23. package/dist/DataList/components/DataListFilters/components/DataListSort/index.cjs +1 -1
  24. package/dist/DataList/components/DataListFilters/components/DataListSort/index.mjs +1 -1
  25. package/dist/DataList/components/DataListFilters/index.cjs +1 -1
  26. package/dist/DataList/components/DataListFilters/index.mjs +1 -1
  27. package/dist/DataList/components/DataListHeader/index.cjs +1 -1
  28. package/dist/DataList/components/DataListHeader/index.mjs +1 -1
  29. package/dist/DataList/components/DataListItem/index.cjs +1 -1
  30. package/dist/DataList/components/DataListItem/index.mjs +1 -1
  31. package/dist/DataList/components/DataListItemActions/index.cjs +1 -1
  32. package/dist/DataList/components/DataListItemActions/index.mjs +1 -1
  33. package/dist/DataList/components/DataListItemActionsOverflow/index.cjs +1 -1
  34. package/dist/DataList/components/DataListItemActionsOverflow/index.mjs +1 -1
  35. package/dist/DataList/components/DataListItems/index.cjs +1 -1
  36. package/dist/DataList/components/DataListItems/index.mjs +1 -1
  37. package/dist/DataList/components/DataListLayout/index.cjs +1 -1
  38. package/dist/DataList/components/DataListLayout/index.mjs +1 -1
  39. package/dist/DataList/components/DataListLayoutActions/index.cjs +1 -1
  40. package/dist/DataList/components/DataListLayoutActions/index.mjs +1 -1
  41. package/dist/DataList/index.cjs +1 -1
  42. package/dist/DataList/index.mjs +1 -1
  43. package/dist/DatePicker/index.cjs +1 -1
  44. package/dist/DatePicker/index.mjs +1 -1
  45. package/dist/Dialog/index.cjs +3 -3
  46. package/dist/Dialog/index.mjs +3 -3
  47. package/dist/DrawerDescription-cjs.js +32 -33
  48. package/dist/DrawerDescription-es.js +19 -20
  49. package/dist/DrawerTitle-cjs.js +7 -5
  50. package/dist/DrawerTitle-es.js +7 -5
  51. package/dist/FilterPicker/components/FilterPickerActivator/index.cjs +1 -1
  52. package/dist/FilterPicker/components/FilterPickerActivator/index.mjs +1 -1
  53. package/dist/FilterPicker/components/FilterPickerContent/index.cjs +1 -1
  54. package/dist/FilterPicker/components/FilterPickerContent/index.mjs +1 -1
  55. package/dist/FilterPicker/components/FilterPickerTrigger/index.cjs +1 -1
  56. package/dist/FilterPicker/components/FilterPickerTrigger/index.mjs +1 -1
  57. package/dist/FilterPicker/index.cjs +1 -1
  58. package/dist/FilterPicker/index.mjs +1 -1
  59. package/dist/FormFieldWrapper-cjs.js +2 -2
  60. package/dist/FormFieldWrapper-es.js +2 -2
  61. package/dist/FormatFile/index.cjs +1 -1
  62. package/dist/FormatFile/index.mjs +1 -1
  63. package/dist/Gallery/index.cjs +1 -1
  64. package/dist/Gallery/index.mjs +1 -1
  65. package/dist/InputDate/index.cjs +1 -1
  66. package/dist/InputDate/index.mjs +1 -1
  67. package/dist/InputNumberExperimental-cjs.js +319 -102
  68. package/dist/InputNumberExperimental-es.js +321 -104
  69. package/dist/LightBox/index.cjs +1 -1
  70. package/dist/LightBox/index.mjs +1 -1
  71. package/dist/Menu/index.cjs +4 -4
  72. package/dist/Menu/index.mjs +4 -4
  73. package/dist/MenuSubmenuTrigger-cjs.js +545 -498
  74. package/dist/MenuSubmenuTrigger-es.js +490 -443
  75. package/dist/Modal/index.cjs +1 -1
  76. package/dist/Modal/index.mjs +1 -1
  77. package/dist/NumberFieldInput-cjs.js +609 -496
  78. package/dist/NumberFieldInput-es.js +612 -498
  79. package/dist/Page/index.cjs +4 -4
  80. package/dist/Page/index.mjs +4 -4
  81. package/dist/Popover/index.cjs +1 -1
  82. package/dist/Popover/index.mjs +1 -1
  83. package/dist/ScrollAreaViewport-cjs.js +326 -601
  84. package/dist/ScrollAreaViewport-es.js +278 -548
  85. package/dist/SelectGroupLabel-cjs.js +494 -528
  86. package/dist/SelectGroupLabel-es.js +411 -445
  87. package/dist/Separator-cjs.js +1 -0
  88. package/dist/Separator-es.js +1 -0
  89. package/dist/Tooltip/index.cjs +1 -1
  90. package/dist/Tooltip/index.mjs +1 -1
  91. package/dist/docs/InputTime/InputTime.md +8 -0
  92. package/dist/docs/SelectPrimitive/SelectPrimitive.md +38 -25
  93. package/dist/floating-ui.react-cjs.js +586 -10
  94. package/dist/floating-ui.react-dom-cjs.js +92 -92
  95. package/dist/floating-ui.react-dom-es.js +1 -1
  96. package/dist/floating-ui.react-es.js +580 -4
  97. package/dist/floating-ui.utils-cjs.js +159 -0
  98. package/dist/floating-ui.utils-es.js +136 -0
  99. package/dist/index.cjs +4 -4
  100. package/dist/index.mjs +4 -4
  101. package/dist/{ToolbarRootContext-cjs.js → isElementDisabled-cjs.js} +5 -0
  102. package/dist/{ToolbarRootContext-es.js → isElementDisabled-es.js} +5 -1
  103. package/dist/primitives/BottomSheet/index.cjs +3 -3
  104. package/dist/primitives/BottomSheet/index.mjs +3 -3
  105. package/dist/primitives/ComboboxPrimitive/index.cjs +2 -2
  106. package/dist/primitives/ComboboxPrimitive/index.mjs +2 -2
  107. package/dist/primitives/InputNumberExperimental/index.cjs +1 -1
  108. package/dist/primitives/InputNumberExperimental/index.mjs +1 -1
  109. package/dist/primitives/SelectPrimitive/index.cjs +5 -5
  110. package/dist/primitives/SelectPrimitive/index.mjs +5 -5
  111. package/dist/primitives/index.cjs +4 -4
  112. package/dist/primitives/index.mjs +4 -4
  113. package/dist/resolveAriaLabelledBy-cjs.js +5 -0
  114. package/dist/resolveAriaLabelledBy-es.js +5 -1
  115. package/dist/{CSPContext-cjs.js → scrollEdges-cjs.js} +30 -2
  116. package/dist/{CSPContext-es.js → scrollEdges-es.js} +28 -3
  117. package/dist/styles.css +9 -3
  118. package/dist/unstyledPrimitives/index.cjs +1217 -639
  119. package/dist/unstyledPrimitives/index.mjs +1163 -585
  120. package/dist/useButton-cjs.js +283 -317
  121. package/dist/useButton-es.js +277 -298
  122. package/dist/useCompositeListItem-cjs.js +328 -279
  123. package/dist/useCompositeListItem-es.js +293 -246
  124. package/dist/useLabel-cjs.js +11 -1
  125. package/dist/useLabel-es.js +11 -2
  126. package/dist/useLabelableId-cjs.js +37 -91
  127. package/dist/useLabelableId-es.js +37 -90
  128. package/dist/useRenderElement-cjs.js +81 -26
  129. package/dist/useRenderElement-es.js +81 -27
  130. package/dist/{InternalBackdrop-cjs.js → useScrollLock-cjs.js} +1286 -1220
  131. package/dist/{InternalBackdrop-es.js → useScrollLock-es.js} +1250 -1207
  132. package/package.json +3 -3
  133. package/dist/index.esm-cjs.js +0 -738
  134. package/dist/index.esm-es.js +0 -712
@@ -1,176 +1,22 @@
1
1
  import * as React from 'react';
2
- import { E as EMPTY_OBJECT, a as useRefWithInit, f as formatErrorMessage, u as useRenderElement } from './useRenderElement-es.js';
3
- import { a as FloatingRootStore, P as PopupTriggerMap, o as createSelector, u as useFloatingParentNodeId, y as FloatingPortal, I as InternalBackdrop, A as inertValue, q as useOpenInteractionType, t as useDismiss, z as useScrollLock, v as useInteractions, R as ReactStore, w as useOnFirstRender, s as useClick, E as CLICK_TRIGGER_IDENTIFIER, G as triggerOpenStateMapping, p as popupStateMapping, C as CommonPopupDataAttributes, F as FloatingFocusManager, n as useDirection } from './InternalBackdrop-es.js';
4
- import { b as useStableCallback, a as useIsoLayoutEffect, k as useTransitionStatus, f as useOpenChangeComplete, l as useId, m as getFloatingFocusElement, d as createChangeEventDetails, i as imperativeAction, g as getTarget, r as contains, u as useBaseUiId, c as useButton, t as transitionStatusMapping, o as ownerDocument, E as useControlled, G as none, _ as isAndroid, $ as closeWatcher, h as useTimeout, X as isWebKit } from './useButton-es.js';
5
- import { C as COMPOSITE_KEYS, u as useCSPContext, s as styleDisableScrollbar } from './CSPContext-es.js';
2
+ import { E as EMPTY_OBJECT, f as formatErrorMessage, u as useRenderElement } from './useRenderElement-es.js';
3
+ import { b as FloatingRootStore, P as PopupTriggerMap, t as createSelector, E as FloatingPortal, I as InternalBackdrop, G as inertValue, K as usePopupRootSync, L as useImplicitActiveTrigger, M as useOpenStateTransitions, y as useDismiss, s as useScrollLock, N as usePopupInteractionProps, R as ReactStore, O as setPopupOpenState, Q as usePopupStore, z as useOnFirstRender, T as useTriggerDataForwarding, x as useClick, U as useOpenMethodTriggerProps, V as CLICK_TRIGGER_IDENTIFIER, W as triggerOpenStateMapping, p as popupStateMapping, C as CommonPopupDataAttributes, F as FOCUSABLE_POPUP_PROPS, a as FloatingFocusManager, r as useDirection, J as webkit } from './useScrollLock-es.js';
4
+ import { d as createChangeEventDetails, i as imperativeAction, g as getTarget, q as contains, u as useBaseUiId, c as useButton, t as transitionStatusMapping, b as useStableCallback, o as ownerDocument, a as useIsoLayoutEffect, S as SafeReact, j as error, f as useOpenChangeComplete, z as useControlled, C as none, l as useId, W as android, B as addEventListener, X as closeWatcher, h as useTimeout } from './useButton-es.js';
5
+ import { C as COMPOSITE_KEYS, u as useCSPContext, s as styleDisableScrollbar, n as normalizeScrollOffset } from './scrollEdges-es.js';
6
6
  import { c as clamp } from './clamp-es.js';
7
7
  import { jsx, jsxs } from 'react/jsx-runtime';
8
- import { b as isElement, o as getWindow } from './floating-ui.utils.dom-es.js';
9
-
10
- /**
11
- * Returns a callback ref that registers/unregisters the trigger element in the store.
12
- *
13
- * @param store The Store instance where the trigger should be registered.
14
- */
15
- function useTriggerRegistration(id, store) {
16
- // Keep track of the currently registered element to unregister it on unmount or id change.
17
- const registeredElementIdRef = React.useRef(null);
18
- const registeredElementRef = React.useRef(null);
19
- return React.useCallback(element => {
20
- if (id === undefined) {
21
- return;
22
- }
23
- if (registeredElementIdRef.current !== null) {
24
- const registeredId = registeredElementIdRef.current;
25
- const registeredElement = registeredElementRef.current;
26
- const currentElement = store.context.triggerElements.getById(registeredId);
27
- if (registeredElement && currentElement === registeredElement) {
28
- store.context.triggerElements.delete(registeredId);
29
- }
30
- registeredElementIdRef.current = null;
31
- registeredElementRef.current = null;
32
- }
33
- if (element !== null) {
34
- registeredElementIdRef.current = id;
35
- registeredElementRef.current = element;
36
- store.context.triggerElements.add(id, element);
37
- }
38
- }, [store, id]);
39
- }
40
-
41
- /**
42
- * Sets up trigger data forwarding to the store.
43
- *
44
- * @param triggerId Id of the trigger.
45
- * @param triggerElement The trigger DOM element.
46
- * @param store The Store instance managing the popup state.
47
- * @param stateUpdates An object with state updates to apply when the trigger is active.
48
- */
49
- function useTriggerDataForwarding(triggerId, triggerElementRef, store, stateUpdates) {
50
- const isMountedByThisTrigger = store.useState('isMountedByTrigger', triggerId);
51
- const baseRegisterTrigger = useTriggerRegistration(triggerId, store);
52
- const registerTrigger = useStableCallback(element => {
53
- baseRegisterTrigger(element);
54
- if (!element || !store.select('open')) {
55
- return;
56
- }
57
- const activeTriggerId = store.select('activeTriggerId');
58
- if (activeTriggerId === triggerId) {
59
- store.update({
60
- activeTriggerElement: element,
61
- ...stateUpdates
62
- });
63
- return;
64
- }
65
- if (activeTriggerId == null) {
66
- // This runs when popup is open, but no active trigger is set.
67
- // It can happen when using controlled mode and the trigger is mounted after opening or if `triggerId` prop is not set explicitly.
68
- // In such cases the first trigger to run this code becomes the active trigger (store.select('activeTriggerId') should not return null after that).
69
- // This is mostly for compatibility with contained triggers where no explicit `triggerId` was required in controlled mode.
70
- store.update({
71
- activeTriggerId: triggerId,
72
- activeTriggerElement: element,
73
- ...stateUpdates
74
- });
75
- }
76
- });
77
- useIsoLayoutEffect(() => {
78
- if (isMountedByThisTrigger) {
79
- store.update({
80
- activeTriggerElement: triggerElementRef.current,
81
- ...stateUpdates
82
- });
83
- }
84
- // eslint-disable-next-line react-hooks/exhaustive-deps
85
- }, [isMountedByThisTrigger, store, triggerElementRef, ...Object.values(stateUpdates)]);
86
- return {
87
- registerTrigger,
88
- isMountedByThisTrigger
89
- };
90
- }
91
- /**
92
- * Ensures that when there's only one trigger element registered, it is set as the active trigger.
93
- * This allows controlled popups to work correctly without an explicit triggerId, maintaining compatibility
94
- * with the contained triggers.
95
- *
96
- * This should be called on the Root part.
97
- *
98
- * @param open Whether the popup is open.
99
- * @param store The Store instance managing the popup state.
100
- */
101
- function useImplicitActiveTrigger(store) {
102
- const open = store.useState('open');
103
- useIsoLayoutEffect(() => {
104
- if (open && !store.select('activeTriggerId') && store.context.triggerElements.size === 1) {
105
- const iteratorResult = store.context.triggerElements.entries().next();
106
- if (!iteratorResult.done) {
107
- const [implicitTriggerId, implicitTriggerElement] = iteratorResult.value;
108
- store.update({
109
- activeTriggerId: implicitTriggerId,
110
- activeTriggerElement: implicitTriggerElement
111
- });
112
- }
113
- }
114
- }, [open, store]);
115
- }
116
-
117
- /**
118
- * Mangages the mounted state of the popup.
119
- * Sets up the transition status listeners and handles unmounting when needed.
120
- * Updates the `mounted` and `transitionStatus` states in the store.
121
- *
122
- * @param open Whether the popup is open.
123
- * @param store The Store instance managing the popup state.
124
- * @param onUnmount Optional callback to be called when the popup is unmounted.
125
- *
126
- * @returns A function to forcibly unmount the popup.
127
- */
128
- function useOpenStateTransitions(open, store, onUnmount) {
129
- const {
130
- mounted,
131
- setMounted,
132
- transitionStatus
133
- } = useTransitionStatus(open);
134
- store.useSyncedValues({
135
- mounted,
136
- transitionStatus
137
- });
138
- const forceUnmount = useStableCallback(() => {
139
- setMounted(false);
140
- store.update({
141
- activeTriggerId: null,
142
- activeTriggerElement: null,
143
- mounted: false
144
- });
145
- onUnmount?.();
146
- store.context.onOpenChangeComplete?.(false);
147
- });
148
- const preventUnmountingOnClose = store.useState('preventUnmountingOnClose');
149
- useOpenChangeComplete({
150
- enabled: !preventUnmountingOnClose,
151
- open,
152
- ref: store.context.popupRef,
153
- onComplete() {
154
- if (!open) {
155
- forceUnmount();
156
- }
157
- }
158
- });
159
- return {
160
- forceUnmount,
161
- transitionStatus
162
- };
163
- }
8
+ import { o as getWindow } from './floating-ui.utils.dom-es.js';
164
9
 
165
10
  function getEmptyRootContext() {
166
11
  return new FloatingRootStore({
167
12
  open: false,
13
+ transitionStatus: undefined,
168
14
  floatingElement: null,
169
15
  referenceElement: null,
170
16
  triggerElements: new PopupTriggerMap(),
171
- floatingId: '',
17
+ floatingId: undefined,
18
+ syncOnly: false,
172
19
  nested: false,
173
- noEmit: false,
174
20
  onOpenChange: undefined
175
21
  });
176
22
  }
@@ -184,8 +30,10 @@ function createInitialPopupStoreState() {
184
30
  open: false,
185
31
  openProp: undefined,
186
32
  mounted: false,
187
- transitionStatus: 'idle',
33
+ transitionStatus: undefined,
188
34
  floatingRootContext: getEmptyRootContext(),
35
+ floatingId: undefined,
36
+ triggerCount: 0,
189
37
  preventUnmountingOnClose: false,
190
38
  payload: undefined,
191
39
  activeTriggerId: null,
@@ -198,16 +46,45 @@ function createInitialPopupStoreState() {
198
46
  popupProps: EMPTY_OBJECT
199
47
  };
200
48
  }
49
+ function createPopupFloatingRootContext(triggerElements, floatingId, nested = false) {
50
+ return new FloatingRootStore({
51
+ open: false,
52
+ transitionStatus: undefined,
53
+ floatingElement: null,
54
+ referenceElement: null,
55
+ triggerElements,
56
+ floatingId,
57
+ syncOnly: true,
58
+ nested,
59
+ onOpenChange: undefined
60
+ });
61
+ }
201
62
  const activeTriggerIdSelector = createSelector(state => state.triggerIdProp ?? state.activeTriggerId);
63
+ const openSelector = createSelector(state => state.openProp ?? state.open);
64
+ const popupIdSelector = createSelector(state => {
65
+ const popupId = state.popupElement?.id ?? state.floatingId;
66
+ return popupId || undefined;
67
+ });
68
+ function triggerOwnsOpenPopup(state, triggerId) {
69
+ return triggerId !== undefined && openSelector(state) && activeTriggerIdSelector(state) === triggerId;
70
+ }
71
+ function triggerOwnsOpenPopupOrIsOnlyTrigger(state, triggerId) {
72
+ if (triggerOwnsOpenPopup(state, triggerId)) {
73
+ return true;
74
+ }
75
+ return triggerId !== undefined && openSelector(state) && activeTriggerIdSelector(state) == null && state.triggerCount === 1;
76
+ }
202
77
  const popupStoreSelectors = {
203
- open: createSelector(state => state.openProp ?? state.open),
78
+ open: openSelector,
204
79
  mounted: createSelector(state => state.mounted),
205
80
  transitionStatus: createSelector(state => state.transitionStatus),
206
81
  floatingRootContext: createSelector(state => state.floatingRootContext),
82
+ triggerCount: createSelector(state => state.triggerCount),
207
83
  preventUnmountingOnClose: createSelector(state => state.preventUnmountingOnClose),
208
84
  payload: createSelector(state => state.payload),
209
85
  activeTriggerId: activeTriggerIdSelector,
210
86
  activeTriggerElement: createSelector(state => state.mounted ? state.activeTriggerElement : null),
87
+ popupId: popupIdSelector,
211
88
  /**
212
89
  * Whether the trigger with the given ID was used to open the popup.
213
90
  */
@@ -215,175 +92,23 @@ const popupStoreSelectors = {
215
92
  /**
216
93
  * Whether the popup is open and was activated by a trigger with the given ID.
217
94
  */
218
- isOpenedByTrigger: createSelector((state, triggerId) => triggerId !== undefined && activeTriggerIdSelector(state) === triggerId && state.open),
95
+ isOpenedByTrigger: createSelector((state, triggerId) => triggerOwnsOpenPopup(state, triggerId)),
219
96
  /**
220
97
  * Whether the popup is mounted and was activated by a trigger with the given ID.
221
98
  */
222
99
  isMountedByTrigger: createSelector((state, triggerId) => triggerId !== undefined && activeTriggerIdSelector(state) === triggerId && state.mounted),
223
100
  triggerProps: createSelector((state, isActive) => isActive ? state.activeTriggerProps : state.inactiveTriggerProps),
101
+ /**
102
+ * Popup id for the trigger that currently owns the open popup.
103
+ */
104
+ triggerPopupId: createSelector((state, triggerId) => triggerOwnsOpenPopupOrIsOnlyTrigger(state, triggerId) ? popupIdSelector(state) : undefined),
224
105
  popupProps: createSelector(state => state.popupProps),
225
106
  popupElement: createSelector(state => state.popupElement),
226
107
  positionerElement: createSelector(state => state.positionerElement)
227
108
  };
228
109
 
229
- /**
230
- * Initializes a FloatingRootStore that is kept in sync with the provided PopupStore.
231
- * The new instance is created only once and updated on every render.
232
- */
233
- function useSyncedFloatingRootContext(options) {
234
- const {
235
- popupStore,
236
- noEmit = false,
237
- treatPopupAsFloatingElement = false,
238
- onOpenChange
239
- } = options;
240
- const floatingId = useId();
241
- const nested = useFloatingParentNodeId() != null;
242
- const open = popupStore.useState('open');
243
- const referenceElement = popupStore.useState('activeTriggerElement');
244
- const floatingElement = popupStore.useState(treatPopupAsFloatingElement ? 'popupElement' : 'positionerElement');
245
- const triggerElements = popupStore.context.triggerElements;
246
- const store = useRefWithInit(() => new FloatingRootStore({
247
- open,
248
- referenceElement,
249
- floatingElement,
250
- triggerElements,
251
- onOpenChange,
252
- floatingId,
253
- nested,
254
- noEmit
255
- })).current;
256
- useIsoLayoutEffect(() => {
257
- const valuesToSync = {
258
- open,
259
- floatingId,
260
- referenceElement,
261
- floatingElement
262
- };
263
- if (isElement(referenceElement)) {
264
- valuesToSync.domReferenceElement = referenceElement;
265
- }
266
- if (store.state.positionReference === store.state.referenceElement) {
267
- valuesToSync.positionReference = referenceElement;
268
- }
269
- store.update(valuesToSync);
270
- }, [open, floatingId, referenceElement, floatingElement, store]);
271
-
272
- // TODO: When `setOpen` is a part of the PopupStore API, we don't need to sync it.
273
- store.context.onOpenChange = onOpenChange;
274
- store.context.nested = nested;
275
- store.context.noEmit = noEmit;
276
- return store;
277
- }
278
-
279
- const componentRoleToAriaRoleMap = new Map([['select', 'listbox'], ['combobox', 'listbox'], ['label', false]]);
280
-
281
- /**
282
- * Adds base screen reader props to the reference and floating elements for a
283
- * given floating element `role`.
284
- * @see https://floating-ui.com/docs/useRole
285
- */
286
- function useRole(context, props = {}) {
287
- const store = 'rootStore' in context ? context.rootStore : context;
288
- const open = store.useState('open');
289
- const defaultFloatingId = store.useState('floatingId');
290
- const domReference = store.useState('domReferenceElement');
291
- const floatingElement = store.useState('floatingElement');
292
- const {
293
- role = 'dialog'
294
- } = props;
295
- const defaultReferenceId = useId();
296
- const referenceId = domReference?.id || defaultReferenceId;
297
- const floatingId = React.useMemo(() => getFloatingFocusElement(floatingElement)?.id || defaultFloatingId, [floatingElement, defaultFloatingId]);
298
- const ariaRole = componentRoleToAriaRoleMap.get(role) ?? role;
299
- const parentId = useFloatingParentNodeId();
300
- const isNested = parentId != null;
301
- const trigger = React.useMemo(() => {
302
- if (ariaRole === 'tooltip' || role === 'label') {
303
- return EMPTY_OBJECT;
304
- }
305
- return {
306
- 'aria-haspopup': ariaRole === 'alertdialog' ? 'dialog' : ariaRole,
307
- 'aria-expanded': 'false',
308
- ...(ariaRole === 'listbox' && {
309
- role: 'combobox'
310
- }),
311
- ...(ariaRole === 'menu' && isNested && {
312
- role: 'menuitem'
313
- }),
314
- ...(role === 'select' && {
315
- 'aria-autocomplete': 'none'
316
- }),
317
- ...(role === 'combobox' && {
318
- 'aria-autocomplete': 'list'
319
- })
320
- };
321
- }, [ariaRole, isNested, role]);
322
- const reference = React.useMemo(() => {
323
- if (ariaRole === 'tooltip' || role === 'label') {
324
- return {
325
- [`aria-${role === 'label' ? 'labelledby' : 'describedby'}`]: open ? floatingId : undefined
326
- };
327
- }
328
- const triggerProps = trigger;
329
- return {
330
- ...triggerProps,
331
- 'aria-expanded': open ? 'true' : 'false',
332
- 'aria-controls': open ? floatingId : undefined,
333
- ...(ariaRole === 'menu' && {
334
- id: referenceId
335
- })
336
- };
337
- }, [ariaRole, floatingId, open, referenceId, role, trigger]);
338
- const floating = React.useMemo(() => {
339
- const floatingProps = {
340
- id: floatingId,
341
- ...(ariaRole && {
342
- role: ariaRole
343
- })
344
- };
345
- if (ariaRole === 'tooltip' || role === 'label') {
346
- return floatingProps;
347
- }
348
- return {
349
- ...floatingProps,
350
- ...(ariaRole === 'menu' && {
351
- 'aria-labelledby': referenceId
352
- })
353
- };
354
- }, [ariaRole, floatingId, referenceId, role]);
355
- const item = React.useCallback(({
356
- active,
357
- selected
358
- }) => {
359
- const commonProps = {
360
- role: 'option',
361
- ...(active && {
362
- id: `${floatingId}-fui-option`
363
- })
364
- };
365
-
366
- // For `menu`, we are unable to tell if the item is a `menuitemradio`
367
- // or `menuitemcheckbox`. For backwards-compatibility reasons, also
368
- // avoid defaulting to `menuitem` as it may overwrite custom role props.
369
- switch (role) {
370
- case 'select':
371
- case 'combobox':
372
- return {
373
- ...commonProps,
374
- 'aria-selected': selected
375
- };
376
- }
377
- return {};
378
- }, [floatingId, role]);
379
- return React.useMemo(() => ({
380
- reference,
381
- floating,
382
- item,
383
- trigger
384
- }), [reference, floating, trigger, item]);
385
- }
386
-
110
+ const IsDrawerContext = /*#__PURE__*/React.createContext(false);
111
+ if (process.env.NODE_ENV !== "production") IsDrawerContext.displayName = "IsDrawerContext";
387
112
  const DialogRootContext = /*#__PURE__*/React.createContext(undefined);
388
113
  if (process.env.NODE_ENV !== "production") DialogRootContext.displayName = "DialogRootContext";
389
114
  function useDialogRootContext(optional) {
@@ -436,44 +161,35 @@ if (process.env.NODE_ENV !== "production") DialogPortal.displayName = "DialogPor
436
161
  function useDialogRoot(params) {
437
162
  const {
438
163
  store,
439
- parentContext,
440
164
  actionsRef
441
165
  } = params;
442
166
  const open = store.useState('open');
443
- const disablePointerDismissal = store.useState('disablePointerDismissal');
444
- const modal = store.useState('modal');
445
- const popupElement = store.useState('popupElement');
446
- const {
447
- openMethod,
448
- triggerProps
449
- } = useOpenInteractionType(open);
167
+ usePopupRootSync(store, open);
450
168
  useImplicitActiveTrigger(store);
451
169
  const {
452
170
  forceUnmount
453
171
  } = useOpenStateTransitions(open, store);
454
- const createDialogEventDetails = useStableCallback(reason => {
455
- const details = createChangeEventDetails(reason);
456
- details.preventUnmountOnClose = () => {
457
- store.set('preventUnmountingOnClose', true);
458
- };
459
- return details;
460
- });
461
172
  const handleImperativeClose = React.useCallback(() => {
462
- store.setOpen(false, createDialogEventDetails(imperativeAction));
463
- }, [store, createDialogEventDetails]);
173
+ store.setOpen(false, createChangeEventDetails(imperativeAction));
174
+ }, [store]);
464
175
  React.useImperativeHandle(actionsRef, () => ({
465
176
  unmount: forceUnmount,
466
177
  close: handleImperativeClose
467
178
  }), [forceUnmount, handleImperativeClose]);
468
- const floatingRootContext = useSyncedFloatingRootContext({
469
- popupStore: store,
470
- onOpenChange: store.setOpen,
471
- treatPopupAsFloatingElement: true,
472
- noEmit: true
473
- });
179
+ }
180
+ function DialogInteractions({
181
+ store,
182
+ parentContext,
183
+ isDrawer
184
+ }) {
185
+ const open = store.useState('open');
186
+ const disablePointerDismissal = store.useState('disablePointerDismissal');
187
+ const modal = store.useState('modal');
188
+ const popupElement = store.useState('popupElement');
189
+ const floatingRootContext = store.useState('floatingRootContext');
474
190
  const [ownNestedOpenDialogs, setOwnNestedOpenDialogs] = React.useState(0);
191
+ const [ownNestedOpenDrawers, setOwnNestedOpenDrawers] = React.useState(0);
475
192
  const isTopmost = ownNestedOpenDialogs === 0;
476
- const role = useRole(floatingRootContext);
477
193
  const dismiss = useDismiss(floatingRootContext, {
478
194
  outsidePressEvent() {
479
195
  if (store.context.internalBackdropRef.current || store.context.backdropRef.current) {
@@ -501,12 +217,11 @@ function useDialogRoot(params) {
501
217
  }
502
218
  const target = getTarget(event);
503
219
  if (isTopmost && !disablePointerDismissal) {
504
- const eventTarget = target;
505
220
  // Only close if the click occurred on the dialog's owning backdrop.
506
221
  // This supports multiple modal dialogs that aren't nested in the React tree:
507
222
  // https://github.com/mui/base-ui/issues/1320
508
223
  if (modal) {
509
- return store.context.internalBackdropRef.current || store.context.backdropRef.current ? store.context.internalBackdropRef.current === eventTarget || store.context.backdropRef.current === eventTarget || contains(eventTarget, popupElement) && !eventTarget?.hasAttribute('data-base-ui-portal') : true;
224
+ return store.context.internalBackdropRef.current || store.context.backdropRef.current ? store.context.internalBackdropRef.current === target || store.context.backdropRef.current === target || contains(target, popupElement) && !target?.hasAttribute('data-base-ui-portal') : true;
510
225
  }
511
226
  return true;
512
227
  }
@@ -515,24 +230,21 @@ function useDialogRoot(params) {
515
230
  escapeKey: isTopmost
516
231
  });
517
232
  useScrollLock(open && modal === true, popupElement);
518
- const {
519
- getReferenceProps,
520
- getFloatingProps,
521
- getTriggerProps
522
- } = useInteractions([role, dismiss]);
523
233
 
524
- // Listen for nested open/close events on this store to maintain the count
525
- store.useContextCallback('onNestedDialogOpen', ownChildrenCount => {
526
- setOwnNestedOpenDialogs(ownChildrenCount + 1);
234
+ // Listen for nested open/close events on this store to maintain the counts.
235
+ store.useContextCallback('onNestedDialogOpen', (dialogCount, drawerCount) => {
236
+ setOwnNestedOpenDialogs(dialogCount);
237
+ setOwnNestedOpenDrawers(drawerCount);
527
238
  });
528
239
  store.useContextCallback('onNestedDialogClose', () => {
529
240
  setOwnNestedOpenDialogs(0);
241
+ setOwnNestedOpenDrawers(0);
530
242
  });
531
243
 
532
244
  // Notify parent of our open/close state using parent callbacks, if any
533
245
  React.useEffect(() => {
534
246
  if (parentContext?.onNestedDialogOpen && open) {
535
- parentContext.onNestedDialogOpen(ownNestedOpenDialogs);
247
+ parentContext.onNestedDialogOpen(ownNestedOpenDialogs + 1, ownNestedOpenDrawers + (isDrawer ? 1 : 0));
536
248
  }
537
249
  if (parentContext?.onNestedDialogClose && !open) {
538
250
  parentContext.onNestedDialogClose();
@@ -542,18 +254,20 @@ function useDialogRoot(params) {
542
254
  parentContext.onNestedDialogClose();
543
255
  }
544
256
  };
545
- }, [open, parentContext, ownNestedOpenDialogs]);
546
- const activeTriggerProps = React.useMemo(() => getReferenceProps(triggerProps), [getReferenceProps, triggerProps]);
547
- const inactiveTriggerProps = React.useMemo(() => getTriggerProps(triggerProps), [getTriggerProps, triggerProps]);
548
- const popupProps = React.useMemo(() => getFloatingProps(), [getFloatingProps]);
549
- store.useSyncedValues({
550
- openMethod,
257
+ }, [isDrawer, open, ownNestedOpenDialogs, ownNestedOpenDrawers, parentContext]);
258
+ const activeTriggerProps = dismiss.reference ?? EMPTY_OBJECT;
259
+ const inactiveTriggerProps = dismiss.trigger ?? EMPTY_OBJECT;
260
+ // Consumers (DialogPopup/DrawerPopup) already spread `FOCUSABLE_POPUP_PROPS`
261
+ // directly, so the popup props only need to carry the dismiss handlers.
262
+ const popupProps = dismiss.floating ?? EMPTY_OBJECT;
263
+ usePopupInteractionProps(store, {
551
264
  activeTriggerProps,
552
265
  inactiveTriggerProps,
553
266
  popupProps,
554
- floatingRootContext,
555
- nestedOpenDialogCount: ownNestedOpenDialogs
267
+ nestedOpenDialogCount: ownNestedOpenDialogs,
268
+ nestedOpenDrawerCount: ownNestedOpenDrawers
556
269
  });
270
+ return null;
557
271
  }
558
272
 
559
273
  const selectors = {
@@ -561,6 +275,7 @@ const selectors = {
561
275
  modal: createSelector(state => state.modal),
562
276
  nested: createSelector(state => state.nested),
563
277
  nestedOpenDialogCount: createSelector(state => state.nestedOpenDialogCount),
278
+ nestedOpenDrawerCount: createSelector(state => state.nestedOpenDrawerCount),
564
279
  disablePointerDismissal: createSelector(state => state.disablePointerDismissal),
565
280
  openMethod: createSelector(state => state.openMethod),
566
281
  descriptionElementId: createSelector(state => state.descriptionElementId),
@@ -569,15 +284,18 @@ const selectors = {
569
284
  role: createSelector(state => state.role)
570
285
  };
571
286
  class DialogStore extends ReactStore {
572
- constructor(initialState) {
573
- super(createInitialState(initialState), {
287
+ constructor(initialState, floatingId, nested = false) {
288
+ const triggerElements = new PopupTriggerMap();
289
+ const state = createInitialState(initialState);
290
+ state.floatingRootContext = createPopupFloatingRootContext(triggerElements, floatingId, nested);
291
+ super(state, {
574
292
  popupRef: /*#__PURE__*/React.createRef(),
575
293
  backdropRef: /*#__PURE__*/React.createRef(),
576
294
  internalBackdropRef: /*#__PURE__*/React.createRef(),
577
295
  outsidePressEnabledRef: {
578
296
  current: true
579
297
  },
580
- triggerElements: new PopupTriggerMap(),
298
+ triggerElements,
581
299
  onOpenChange: undefined,
582
300
  onOpenChangeComplete: undefined
583
301
  }, selectors);
@@ -595,26 +313,20 @@ class DialogStore extends ReactStore {
595
313
  if (eventDetails.isCanceled) {
596
314
  return;
597
315
  }
598
- const details = {
599
- open: nextOpen,
600
- nativeEvent: eventDetails.event,
601
- reason: eventDetails.reason,
602
- nested: this.state.nested
603
- };
604
- this.state.floatingRootContext.context.events?.emit('openchange', details);
316
+ this.state.floatingRootContext.dispatchOpenChange(nextOpen, eventDetails);
605
317
  const updatedState = {
606
318
  open: nextOpen
607
319
  };
608
-
609
- // If a popup is closing, the `trigger` may be null.
610
- // We want to keep the previous value so that exit animations are played and focus is returned correctly.
611
- const newTriggerId = eventDetails.trigger?.id ?? null;
612
- if (newTriggerId || nextOpen) {
613
- updatedState.activeTriggerId = newTriggerId;
614
- updatedState.activeTriggerElement = eventDetails.trigger ?? null;
615
- }
320
+ setPopupOpenState(updatedState, nextOpen, eventDetails.trigger);
616
321
  this.update(updatedState);
617
322
  };
323
+ static useStore(externalStore, initialState) {
324
+ /* eslint-disable react-hooks/rules-of-hooks */
325
+ const store = usePopupStore(externalStore, (floatingId, nested) => new DialogStore(initialState, floatingId, nested), true).store;
326
+ /* eslint-enable react-hooks/rules-of-hooks */
327
+
328
+ return store;
329
+ }
618
330
  }
619
331
  function createInitialState(initialState = {}) {
620
332
  return {
@@ -628,82 +340,105 @@ function createInitialState(initialState = {}) {
628
340
  openMethod: null,
629
341
  nested: false,
630
342
  nestedOpenDialogCount: 0,
343
+ nestedOpenDrawerCount: 0,
631
344
  role: 'dialog',
632
345
  ...initialState
633
346
  };
634
347
  }
635
348
 
636
- /**
637
- * Groups all parts of the dialog.
638
- * Doesn’t render its own HTML element.
639
- *
640
- * Documentation: [Base UI Dialog](https://base-ui.com/react/components/dialog)
641
- */
642
- function DialogRoot(props) {
349
+ function useRenderDialogRoot(props, mode = 'dialog') {
643
350
  const {
644
351
  children,
645
352
  open: openProp,
646
353
  defaultOpen = false,
647
354
  onOpenChange,
648
355
  onOpenChangeComplete,
649
- disablePointerDismissal = false,
650
- modal = true,
356
+ disablePointerDismissal: disablePointerDismissalProp = false,
357
+ modal: modalProp = true,
651
358
  actionsRef,
652
359
  handle,
653
360
  triggerId: triggerIdProp,
654
361
  defaultTriggerId: defaultTriggerIdProp = null
655
362
  } = props;
363
+ const isDrawer = mode === 'drawer';
364
+ const isAlertDialog = mode === 'alert-dialog';
365
+ const modal = isAlertDialog ? true : modalProp;
366
+ const disablePointerDismissal = isAlertDialog || disablePointerDismissalProp;
367
+ const role = isAlertDialog ? 'alertdialog' : 'dialog';
656
368
  const parentDialogRootContext = useDialogRootContext(true);
657
369
  const nested = Boolean(parentDialogRootContext);
658
- const store = useRefWithInit(() => {
659
- return handle?.store ?? new DialogStore({
660
- open: defaultOpen,
661
- openProp,
662
- activeTriggerId: defaultTriggerIdProp,
663
- triggerIdProp,
664
- modal,
665
- disablePointerDismissal,
666
- nested
667
- });
668
- }).current;
370
+ const rootState = {
371
+ modal,
372
+ disablePointerDismissal,
373
+ nested,
374
+ role
375
+ };
376
+ const store = DialogStore.useStore(handle?.store, {
377
+ open: defaultOpen,
378
+ openProp,
379
+ activeTriggerId: defaultTriggerIdProp,
380
+ triggerIdProp,
381
+ ...rootState
382
+ });
669
383
 
670
384
  // Support initially open state when uncontrolled
671
385
  useOnFirstRender(() => {
672
- if (openProp === undefined && store.state.open === false && defaultOpen === true) {
673
- store.update({
674
- open: true,
675
- activeTriggerId: defaultTriggerIdProp
676
- });
386
+ const nextState = openProp === undefined && store.state.open === false && defaultOpen === true ? {
387
+ open: true,
388
+ activeTriggerId: defaultTriggerIdProp
389
+ } : null;
390
+ if (isAlertDialog) {
391
+ // Handles can reuse plain Dialog stores; alert dialog invariants must exist immediately.
392
+ store.update(nextState ? {
393
+ ...rootState,
394
+ ...nextState
395
+ } : rootState);
396
+ } else if (nextState) {
397
+ store.update(nextState);
677
398
  }
678
399
  });
679
400
  store.useControlledProp('openProp', openProp);
680
401
  store.useControlledProp('triggerIdProp', triggerIdProp);
681
- store.useSyncedValues({
682
- disablePointerDismissal,
683
- nested,
684
- modal
685
- });
402
+ store.useSyncedValues(rootState);
686
403
  store.useContextCallback('onOpenChange', onOpenChange);
687
404
  store.useContextCallback('onOpenChangeComplete', onOpenChangeComplete);
405
+ const open = store.useState('open');
406
+ const mounted = store.useState('mounted');
688
407
  const payload = store.useState('payload');
689
408
  useDialogRoot({
690
409
  store,
691
- actionsRef,
692
- parentContext: parentDialogRootContext?.store.context,
693
- onOpenChange,
694
- triggerIdProp
410
+ actionsRef
695
411
  });
412
+ const shouldRenderInteractions = open || mounted;
696
413
  const contextValue = React.useMemo(() => ({
697
414
  store
698
415
  }), [store]);
699
- return /*#__PURE__*/jsx(DialogRootContext.Provider, {
700
- value: contextValue,
701
- children: typeof children === 'function' ? children({
702
- payload
703
- }) : children
416
+ return /*#__PURE__*/jsx(IsDrawerContext.Provider, {
417
+ value: false,
418
+ children: /*#__PURE__*/jsxs(DialogRootContext.Provider, {
419
+ value: contextValue,
420
+ children: [shouldRenderInteractions && /*#__PURE__*/jsx(DialogInteractions, {
421
+ store: store,
422
+ parentContext: parentDialogRootContext?.store.context,
423
+ isDrawer: isDrawer
424
+ }), typeof children === 'function' ? children({
425
+ payload
426
+ }) : children]
427
+ })
704
428
  });
705
429
  }
706
430
 
431
+ /**
432
+ * Groups all parts of the dialog.
433
+ * Doesn't render its own HTML element.
434
+ *
435
+ * Documentation: [Base UI Dialog](https://base-ui.com/react/components/dialog)
436
+ */
437
+ function DialogRoot(props) {
438
+ const mode = React.useContext(IsDrawerContext) ? 'drawer' : 'dialog';
439
+ return useRenderDialogRoot(props, mode);
440
+ }
441
+
707
442
  /**
708
443
  * A button that opens the dialog.
709
444
  * Renders a `<button>` element.
@@ -714,6 +449,7 @@ const DialogTrigger = /*#__PURE__*/React.forwardRef(function DialogTrigger(compo
714
449
  const {
715
450
  render,
716
451
  className,
452
+ style,
717
453
  disabled = false,
718
454
  nativeButton = true,
719
455
  id: idProp,
@@ -729,6 +465,7 @@ const DialogTrigger = /*#__PURE__*/React.forwardRef(function DialogTrigger(compo
729
465
  const thisTriggerId = useBaseUiId(idProp);
730
466
  const floatingContext = store.useState('floatingRootContext');
731
467
  const isOpenedByThisTrigger = store.useState('isOpenedByTrigger', thisTriggerId);
468
+ const popupId = store.useState('triggerPopupId', thisTriggerId);
732
469
  const triggerElementRef = React.useRef(null);
733
470
  const {
734
471
  registerTrigger,
@@ -746,7 +483,9 @@ const DialogTrigger = /*#__PURE__*/React.forwardRef(function DialogTrigger(compo
746
483
  const click = useClick(floatingContext, {
747
484
  enabled: floatingContext != null
748
485
  });
749
- const localInteractionProps = useInteractions([click]);
486
+ const interactionTypeProps = useOpenMethodTriggerProps(() => store.select('open'), interactionType => {
487
+ store.set('openMethod', interactionType);
488
+ });
750
489
  const state = {
751
490
  disabled,
752
491
  open: isOpenedByThisTrigger
@@ -755,9 +494,12 @@ const DialogTrigger = /*#__PURE__*/React.forwardRef(function DialogTrigger(compo
755
494
  return useRenderElement('button', componentProps, {
756
495
  state,
757
496
  ref: [buttonRef, forwardedRef, registerTrigger, triggerElementRef],
758
- props: [localInteractionProps.getReferenceProps(), rootTriggerProps, {
497
+ props: [click.reference, rootTriggerProps, interactionTypeProps, {
759
498
  [CLICK_TRIGGER_IDENTIFIER]: '',
760
- id: thisTriggerId
499
+ id: thisTriggerId,
500
+ 'aria-haspopup': 'dialog',
501
+ 'aria-expanded': isOpenedByThisTrigger,
502
+ 'aria-controls': popupId
761
503
  }, elementProps, getButtonProps],
762
504
  stateAttributesMapping: triggerOpenStateMapping
763
505
  });
@@ -827,6 +569,7 @@ const DrawerBackdrop = /*#__PURE__*/React.forwardRef(function DrawerBackdrop(com
827
569
  const {
828
570
  render,
829
571
  className,
572
+ style,
830
573
  forceRender = false,
831
574
  ...elementProps
832
575
  } = componentProps;
@@ -873,6 +616,7 @@ const DrawerContent = /*#__PURE__*/React.forwardRef(function DrawerContent(compo
873
616
  const {
874
617
  render,
875
618
  className,
619
+ style,
876
620
  ...elementProps
877
621
  } = componentProps;
878
622
  useDialogRootContext();
@@ -947,6 +691,17 @@ function useDrawerRootContext(optional) {
947
691
  return drawerRootContext;
948
692
  }
949
693
 
694
+ /**
695
+ * Resolves the vertical swipe movement for a snap point, applying square-root damping once the drag
696
+ * overshoots the fully-open edge (`nextOffset < 0`) so the popup resists travelling past it.
697
+ */
698
+ function getSnapPointSwipeMovement(baseOffset, movementValue) {
699
+ const nextOffset = baseOffset + movementValue;
700
+ if (nextOffset >= 0) {
701
+ return movementValue;
702
+ }
703
+ return -Math.sqrt(-nextOffset) - baseOffset;
704
+ }
950
705
  function resolveSnapPointValue(snapPoint, viewportHeight, rootFontSize) {
951
706
  if (!Number.isFinite(viewportHeight) || viewportHeight <= 0) {
952
707
  return null;
@@ -1100,7 +855,6 @@ let drawerSwipeVarsRegistered = false;
1100
855
  /**
1101
856
  * Removes inheritance of high-frequency drawer swipe CSS variables, which
1102
857
  * reduces style recalculation cost in complex drawers with deep subtrees.
1103
- * Child elements that need these values can still opt-in by using `inherit`.
1104
858
  * See https://motion.dev/blog/web-animation-performance-tier-list
1105
859
  * under the "Improving CSS variable performance" section.
1106
860
  */
@@ -1188,15 +942,17 @@ const stateAttributesMapping = {
1188
942
  */
1189
943
  const DrawerPopup = /*#__PURE__*/React.forwardRef(function DrawerPopup(componentProps, forwardedRef) {
1190
944
  const {
945
+ render,
1191
946
  className,
947
+ style,
1192
948
  finalFocus,
1193
949
  initialFocus,
1194
- render,
1195
950
  ...elementProps
1196
951
  } = componentProps;
1197
952
  const {
1198
953
  store
1199
954
  } = useDialogRootContext();
955
+ const popupRef = store.context.popupRef;
1200
956
  const {
1201
957
  swipeDirection,
1202
958
  frontmostHeight,
@@ -1214,26 +970,39 @@ const DrawerPopup = /*#__PURE__*/React.forwardRef(function DrawerPopup(component
1214
970
  const modal = store.useState('modal');
1215
971
  const mounted = store.useState('mounted');
1216
972
  const nested = store.useState('nested');
1217
- const nestedOpenDialogCount = store.useState('nestedOpenDialogCount');
973
+ const nestedOpenDrawerCount = store.useState('nestedOpenDrawerCount');
1218
974
  const transitionStatus = store.useState('transitionStatus');
1219
975
  const open = store.useState('open');
1220
976
  const openMethod = store.useState('openMethod');
1221
977
  const titleElementId = store.useState('titleElementId');
1222
978
  const role = store.useState('role');
1223
- const nestedDrawerOpen = nestedOpenDialogCount > 0;
979
+ const floatingId = floatingRootContext.useState('floatingId');
980
+ const popupId = elementProps.id ?? floatingId;
1224
981
  const swipe = useDrawerViewportContext();
1225
- const swiping = swipe?.swiping ?? false;
1226
- const swipeStrength = swipe?.swipeStrength ?? null;
982
+ useDialogPortalContext();
1227
983
  const {
1228
984
  snapPoints,
1229
985
  activeSnapPoint,
1230
986
  activeSnapPointOffset
1231
987
  } = useDrawerSnapPoints();
1232
- useDialogPortalContext();
988
+ const nestedDrawerOpen = nestedOpenDrawerCount > 0;
989
+ const swiping = swipe?.swiping ?? false;
990
+ const swipeStrength = swipe?.swipeStrength ?? null;
1233
991
  const [popupHeight, setPopupHeight] = React.useState(0);
1234
992
  const popupHeightRef = React.useRef(0);
993
+ if (process.env.NODE_ENV !== 'production') {
994
+ // eslint-disable-next-line react-hooks/rules-of-hooks
995
+ React.useEffect(() => {
996
+ if (swipe) {
997
+ return;
998
+ }
999
+ const ownerStackMessage = SafeReact.captureOwnerStack?.() || '';
1000
+ const message = '<Drawer.Popup> expected to be rendered within <Drawer.Viewport>. Omitting the ' + 'viewport disables drawer swipe handling and touch scroll locking. Wrap ' + '<Drawer.Popup> in <Drawer.Viewport>.';
1001
+ error(`${message}${ownerStackMessage}`);
1002
+ }, [swipe]);
1003
+ }
1235
1004
  const measureHeight = useStableCallback(() => {
1236
- const popupElement = store.context.popupRef.current;
1005
+ const popupElement = popupRef.current;
1237
1006
  if (!popupElement) {
1238
1007
  return;
1239
1008
  }
@@ -1265,7 +1034,7 @@ const DrawerPopup = /*#__PURE__*/React.forwardRef(function DrawerPopup(component
1265
1034
  onPopupHeightChange(0);
1266
1035
  return undefined;
1267
1036
  }
1268
- const popupElement = store.context.popupRef.current;
1037
+ const popupElement = popupRef.current;
1269
1038
  if (!popupElement) {
1270
1039
  return undefined;
1271
1040
  }
@@ -1279,9 +1048,8 @@ const DrawerPopup = /*#__PURE__*/React.forwardRef(function DrawerPopup(component
1279
1048
  return () => {
1280
1049
  resizeObserver.disconnect();
1281
1050
  };
1282
- }, [measureHeight, mounted, nestedDrawerOpen, onPopupHeightChange, store.context.popupRef]);
1051
+ }, [measureHeight, mounted, nestedDrawerOpen, onPopupHeightChange, popupRef]);
1283
1052
  useIsoLayoutEffect(() => {
1284
- const popupRef = store.context.popupRef;
1285
1053
  const syncNestedSwipeProgress = () => {
1286
1054
  const popupElement = popupRef.current;
1287
1055
  if (!popupElement) {
@@ -1296,14 +1064,14 @@ const DrawerPopup = /*#__PURE__*/React.forwardRef(function DrawerPopup(component
1296
1064
  };
1297
1065
  syncNestedSwipeProgress();
1298
1066
  const unsubscribe = nestedSwipeProgressStore.subscribe(syncNestedSwipeProgress);
1067
+ const popupElement = popupRef.current;
1299
1068
  return () => {
1300
1069
  unsubscribe();
1301
- const popupElement = popupRef.current;
1302
1070
  if (popupElement) {
1303
1071
  popupElement.style.setProperty(DrawerBackdropCssVars.swipeProgress, '0');
1304
1072
  }
1305
1073
  };
1306
- }, [nestedSwipeProgressStore, store.context.popupRef]);
1074
+ }, [nestedSwipeProgressStore, popupRef]);
1307
1075
  React.useEffect(() => {
1308
1076
  if (!open) {
1309
1077
  return undefined;
@@ -1325,14 +1093,15 @@ const DrawerPopup = /*#__PURE__*/React.forwardRef(function DrawerPopup(component
1325
1093
  }, [notifyParentHasNestedDrawer, open, transitionStatus]);
1326
1094
  useOpenChangeComplete({
1327
1095
  open,
1328
- ref: store.context.popupRef,
1096
+ ref: popupRef,
1329
1097
  onComplete() {
1330
1098
  if (open) {
1331
1099
  store.context.onOpenChangeComplete?.(true);
1332
1100
  }
1333
1101
  }
1334
1102
  });
1335
- const resolvedInitialFocus = initialFocus === undefined ? store.context.popupRef : initialFocus;
1103
+ const resolvedInitialFocus = initialFocus === undefined ? popupRef : initialFocus;
1104
+ const setPopupElement = store.useStateSetter('popupElement');
1336
1105
  const state = {
1337
1106
  open,
1338
1107
  nested,
@@ -1357,16 +1126,11 @@ const DrawerPopup = /*#__PURE__*/React.forwardRef(function DrawerPopup(component
1357
1126
  if (shouldApplySnapPoints && swipeDirection === 'down') {
1358
1127
  const baseOffset = activeSnapPointOffset ?? 0;
1359
1128
  const movementValue = Number.parseFloat(String(dragStyles[DrawerPopupCssVars.swipeMovementY] ?? 0));
1360
- const nextOffset = Number.isFinite(movementValue) ? baseOffset + movementValue : baseOffset;
1361
- const shouldDamp = nextOffset < 0;
1362
- if (swiping && shouldDamp && Number.isFinite(movementValue)) {
1363
- const overshoot = Math.abs(nextOffset);
1364
- const dampedOffset = -Math.sqrt(overshoot);
1365
- const dampedMovement = dampedOffset - baseOffset;
1129
+ if (swiping && Number.isFinite(movementValue)) {
1366
1130
  dragStyles = {
1367
1131
  ...dragStyles,
1368
1132
  transform: undefined,
1369
- [DrawerPopupCssVars.swipeMovementY]: `${dampedMovement}px`
1133
+ [DrawerPopupCssVars.swipeMovementY]: `${getSnapPointSwipeMovement(baseOffset, movementValue)}px`
1370
1134
  };
1371
1135
  } else {
1372
1136
  dragStyles = {
@@ -1378,10 +1142,11 @@ const DrawerPopup = /*#__PURE__*/React.forwardRef(function DrawerPopup(component
1378
1142
  const element = useRenderElement('div', componentProps, {
1379
1143
  state,
1380
1144
  props: [rootPopupProps, {
1145
+ id: popupId,
1381
1146
  'aria-labelledby': titleElementId,
1382
1147
  'aria-describedby': descriptionElementId,
1383
1148
  role,
1384
- tabIndex: -1,
1149
+ ...FOCUSABLE_POPUP_PROPS,
1385
1150
  hidden: !mounted,
1386
1151
  onKeyDown(event) {
1387
1152
  if (COMPOSITE_KEYS.has(event.key)) {
@@ -1391,14 +1156,14 @@ const DrawerPopup = /*#__PURE__*/React.forwardRef(function DrawerPopup(component
1391
1156
  style: {
1392
1157
  ...dragStyles,
1393
1158
  [DrawerBackdropCssVars.swipeProgress]: '0',
1394
- [DrawerPopupCssVars.nestedDrawers]: nestedOpenDialogCount,
1159
+ [DrawerPopupCssVars.nestedDrawers]: nestedOpenDrawerCount,
1395
1160
  [DrawerPopupCssVars.height]: popupHeightCssVarValue,
1396
1161
  [DrawerPopupCssVars.snapPointOffset]: typeof snapPointOffsetValue === 'number' ? `${snapPointOffsetValue}px` : '0px',
1397
1162
  [DrawerPopupCssVars.frontmostHeight]: frontmostHeight ? `${frontmostHeight}px` : undefined,
1398
1163
  [DrawerPopupCssVars.swipeStrength]: typeof swipeStrength === 'number' && Number.isFinite(swipeStrength) && swipeStrength > 0 ? `${swipeStrength}` : '1'
1399
1164
  }
1400
1165
  }, elementProps],
1401
- ref: [forwardedRef, store.context.popupRef, store.useStateSetter('popupElement')],
1166
+ ref: [forwardedRef, popupRef, setPopupElement],
1402
1167
  stateAttributesMapping
1403
1168
  });
1404
1169
  return /*#__PURE__*/jsx(FloatingFocusManager, {
@@ -1449,9 +1214,8 @@ function DrawerRoot(props) {
1449
1214
  snapPoints,
1450
1215
  snapPoint: snapPointProp,
1451
1216
  defaultSnapPoint,
1452
- onSnapPointChange: onSnapPointChangeProp
1217
+ onSnapPointChange
1453
1218
  } = props;
1454
- const onSnapPointChange = useStableCallback(onSnapPointChangeProp);
1455
1219
  const parentDrawerRootContext = useDrawerRootContext(true);
1456
1220
  const notifyParentSwipeProgressChange = parentDrawerRootContext?.onNestedSwipeProgressChange;
1457
1221
  const notifyParentFrontmostHeight = parentDrawerRootContext?.onNestedFrontmostHeightChange;
@@ -1556,18 +1320,21 @@ function DrawerRoot(props) {
1556
1320
  });
1557
1321
  return /*#__PURE__*/jsx(DrawerRootContext.Provider, {
1558
1322
  value: contextValue,
1559
- children: /*#__PURE__*/jsx(DialogRoot, {
1560
- open: openProp,
1561
- defaultOpen: defaultOpen,
1562
- onOpenChange: handleOpenChange,
1563
- onOpenChangeComplete: onOpenChangeComplete,
1564
- disablePointerDismissal: disablePointerDismissal,
1565
- modal: modal,
1566
- actionsRef: actionsRef,
1567
- handle: handle,
1568
- triggerId: triggerIdProp,
1569
- defaultTriggerId: defaultTriggerIdProp,
1570
- children: resolvedChildren
1323
+ children: /*#__PURE__*/jsx(IsDrawerContext.Provider, {
1324
+ value: true,
1325
+ children: /*#__PURE__*/jsx(DialogRoot, {
1326
+ open: openProp,
1327
+ defaultOpen: defaultOpen,
1328
+ onOpenChange: handleOpenChange,
1329
+ onOpenChangeComplete: onOpenChangeComplete,
1330
+ disablePointerDismissal: disablePointerDismissal,
1331
+ modal: modal,
1332
+ actionsRef: actionsRef,
1333
+ handle: handle,
1334
+ triggerId: triggerIdProp,
1335
+ defaultTriggerId: defaultTriggerIdProp,
1336
+ children: resolvedChildren
1337
+ })
1571
1338
  })
1572
1339
  });
1573
1340
  }
@@ -1597,10 +1364,12 @@ function createNestedSwipeProgressStore() {
1597
1364
  function DrawerProviderReporter() {
1598
1365
  const drawerId = useId();
1599
1366
  const providerContext = useDrawerProviderContext();
1600
- const dialogRootContext = useDialogRootContext(false);
1601
- const open = dialogRootContext.store.useState('open');
1602
- const nestedOpenDialogCount = dialogRootContext.store.useState('nestedOpenDialogCount');
1603
- const popupElement = dialogRootContext.store.useState('popupElement');
1367
+ const {
1368
+ store
1369
+ } = useDialogRootContext(false);
1370
+ const open = store.useState('open');
1371
+ const nestedOpenDialogCount = store.useState('nestedOpenDialogCount');
1372
+ const popupElement = store.useState('popupElement');
1604
1373
  const isTopmost = nestedOpenDialogCount === 0;
1605
1374
  React.useEffect(() => {
1606
1375
  if (!providerContext || drawerId == null) {
@@ -1619,7 +1388,7 @@ function DrawerProviderReporter() {
1619
1388
  React.useEffect(() => {
1620
1389
  // CloseWatcher enables the Android back gesture (Chromium-only).
1621
1390
  // Keep this Android-only for now to avoid interfering with Escape/nesting semantics on desktop due to `useDismiss`.
1622
- if (!open || !isTopmost || !isAndroid) {
1391
+ if (!open || !isTopmost || !android) {
1623
1392
  return undefined;
1624
1393
  }
1625
1394
  const win = getWindow(popupElement);
@@ -1628,18 +1397,18 @@ function DrawerProviderReporter() {
1628
1397
  return undefined;
1629
1398
  }
1630
1399
  function handleCloseWatcher(event) {
1631
- if (!dialogRootContext.store.select('open')) {
1400
+ if (!store.select('open')) {
1632
1401
  return;
1633
1402
  }
1634
- dialogRootContext.store.setOpen(false, createChangeEventDetails(closeWatcher, event));
1403
+ store.setOpen(false, createChangeEventDetails(closeWatcher, event));
1635
1404
  }
1636
1405
  const closeWatcher$1 = new CloseWatcherCtor();
1637
- closeWatcher$1.addEventListener('close', handleCloseWatcher);
1406
+ const unsubscribe = addEventListener(closeWatcher$1, 'close', handleCloseWatcher);
1638
1407
  return () => {
1639
- closeWatcher$1.removeEventListener('close', handleCloseWatcher);
1408
+ unsubscribe();
1640
1409
  closeWatcher$1.destroy();
1641
1410
  };
1642
- }, [dialogRootContext.store, isTopmost, open, popupElement]);
1411
+ }, [store, isTopmost, open, popupElement]);
1643
1412
  return null;
1644
1413
  }
1645
1414
 
@@ -1818,9 +1587,15 @@ const ScrollAreaRoot = /*#__PURE__*/React.forwardRef(function ScrollAreaRoot(com
1818
1587
  render,
1819
1588
  className,
1820
1589
  overflowEdgeThreshold: overflowEdgeThresholdProp,
1590
+ style,
1821
1591
  ...elementProps
1822
1592
  } = componentProps;
1823
- const overflowEdgeThreshold = normalizeOverflowEdgeThreshold(overflowEdgeThresholdProp);
1593
+ const {
1594
+ xStart,
1595
+ xEnd,
1596
+ yStart,
1597
+ yEnd
1598
+ } = normalizeOverflowEdgeThreshold(overflowEdgeThresholdProp);
1824
1599
  const rootId = useBaseUiId();
1825
1600
  const scrollYTimeout = useTimeout();
1826
1601
  const scrollXTimeout = useTimeout();
@@ -1928,10 +1703,13 @@ const ScrollAreaRoot = /*#__PURE__*/React.forwardRef(function ScrollAreaRoot(com
1928
1703
  });
1929
1704
  const handlePointerUp = useStableCallback(event => {
1930
1705
  thumbDraggingRef.current = false;
1931
- if (thumbYRef.current && currentOrientationRef.current === 'vertical') {
1706
+
1707
+ // `pointercancel` releases capture implicitly, so guard against releasing a
1708
+ // capture we no longer hold (which would throw).
1709
+ if (thumbYRef.current && currentOrientationRef.current === 'vertical' && thumbYRef.current.hasPointerCapture(event.pointerId)) {
1932
1710
  thumbYRef.current.releasePointerCapture(event.pointerId);
1933
1711
  }
1934
- if (thumbXRef.current && currentOrientationRef.current === 'horizontal') {
1712
+ if (thumbXRef.current && currentOrientationRef.current === 'horizontal' && thumbXRef.current.hasPointerCapture(event.pointerId)) {
1935
1713
  thumbXRef.current.releasePointerCapture(event.pointerId);
1936
1714
  }
1937
1715
  });
@@ -2006,8 +1784,13 @@ const ScrollAreaRoot = /*#__PURE__*/React.forwardRef(function ScrollAreaRoot(com
2006
1784
  overflowEdges,
2007
1785
  setOverflowEdges,
2008
1786
  viewportState: state,
2009
- overflowEdgeThreshold
2010
- }), [handlePointerDown, handlePointerMove, handlePointerUp, handleScroll, cornerSize, thumbSize, hasMeasuredScrollbar, touchModality, scrollingX, setScrollingX, scrollingY, setScrollingY, hovering, setHovering, rootId, hiddenState, overflowEdges, state, overflowEdgeThreshold]);
1787
+ overflowEdgeThreshold: {
1788
+ xStart,
1789
+ xEnd,
1790
+ yStart,
1791
+ yEnd
1792
+ }
1793
+ }), [handlePointerDown, handlePointerMove, handlePointerUp, handleScroll, cornerSize, thumbSize, hasMeasuredScrollbar, touchModality, scrollingX, setScrollingX, scrollingY, setScrollingY, hovering, setHovering, rootId, hiddenState, overflowEdges, state, xStart, xEnd, yStart, yEnd]);
2011
1794
  return /*#__PURE__*/jsxs(ScrollAreaRootContext.Provider, {
2012
1795
  value: contextValue,
2013
1796
  children: [!disableStyleElements && styleDisableScrollbar.getElement(nonce), element]
@@ -2042,27 +1825,6 @@ function useScrollAreaViewportContext() {
2042
1825
  return context;
2043
1826
  }
2044
1827
 
2045
- /**
2046
- * Executes a callback when an element becomes visible.
2047
- */
2048
- function onVisible(element, callback) {
2049
- if (typeof IntersectionObserver === 'undefined') {
2050
- return () => {};
2051
- }
2052
- const observer = new IntersectionObserver(entries => {
2053
- entries.forEach(entry => {
2054
- if (entry.intersectionRatio > 0) {
2055
- callback();
2056
- observer.disconnect();
2057
- }
2058
- });
2059
- });
2060
- observer.observe(element);
2061
- return () => {
2062
- observer.disconnect();
2063
- };
2064
- }
2065
-
2066
1828
  let ScrollAreaViewportCssVars = /*#__PURE__*/function (ScrollAreaViewportCssVars) {
2067
1829
  /**
2068
1830
  * The distance from the horizontal start edge in pixels.
@@ -2087,30 +1849,7 @@ let ScrollAreaViewportCssVars = /*#__PURE__*/function (ScrollAreaViewportCssVars
2087
1849
  return ScrollAreaViewportCssVars;
2088
1850
  }({});
2089
1851
 
2090
- const SCROLL_EDGE_TOLERANCE_PX = 1;
2091
- function normalizeScrollOffset(value, max) {
2092
- if (max <= 0) {
2093
- return 0;
2094
- }
2095
- const clamped = clamp(value, 0, max);
2096
- const startDistance = clamped;
2097
- const endDistance = max - clamped;
2098
- const withinStartTolerance = startDistance <= SCROLL_EDGE_TOLERANCE_PX;
2099
- const withinEndTolerance = endDistance <= SCROLL_EDGE_TOLERANCE_PX;
2100
- if (withinStartTolerance && withinEndTolerance) {
2101
- return startDistance <= endDistance ? 0 : max;
2102
- }
2103
- if (withinStartTolerance) {
2104
- return 0;
2105
- }
2106
- if (withinEndTolerance) {
2107
- return max;
2108
- }
2109
- return clamped;
2110
- }
2111
-
2112
1852
  let scrollAreaOverflowVarsRegistered = false;
2113
- const HAS_RESIZE_OBSERVER = typeof ResizeObserver !== 'undefined';
2114
1853
 
2115
1854
  /**
2116
1855
  * Removes inheritance of the scroll area overflow CSS variables, which
@@ -2124,7 +1863,7 @@ function removeCSSVariableInheritance() {
2124
1863
  if (scrollAreaOverflowVarsRegistered ||
2125
1864
  // When `inherits: false`, specifying `inherit` on child elements doesn't work
2126
1865
  // in Safari. To let CSS features work correctly, this optimization must be skipped.
2127
- isWebKit) {
1866
+ webkit) {
2128
1867
  return;
2129
1868
  }
2130
1869
  if (typeof CSS !== 'undefined' && 'registerProperty' in CSS) {
@@ -2154,6 +1893,7 @@ const ScrollAreaViewport = /*#__PURE__*/React.forwardRef(function ScrollAreaView
2154
1893
  const {
2155
1894
  render,
2156
1895
  className,
1896
+ style,
2157
1897
  ...elementProps
2158
1898
  } = componentProps;
2159
1899
  const {
@@ -2323,20 +2063,15 @@ const ScrollAreaViewport = /*#__PURE__*/React.forwardRef(function ScrollAreaView
2323
2063
  });
2324
2064
  useIsoLayoutEffect(() => {
2325
2065
  if (!viewportRef.current) {
2326
- return undefined;
2066
+ return;
2327
2067
  }
2328
2068
  removeCSSVariableInheritance();
2329
- if (HAS_RESIZE_OBSERVER) {
2330
- return undefined;
2331
- }
2332
- return onVisible(viewportRef.current, () => {
2333
- computeThumbPosition();
2334
- });
2335
- }, [computeThumbPosition, viewportRef]);
2069
+ }, [viewportRef]);
2336
2070
  useIsoLayoutEffect(() => {
2337
- // Wait for scrollbar and thumb refs after hidden-state toggles, and refresh math on direction flips.
2071
+ // Wait for scrollbar and thumb refs after hidden-state toggles, refresh math on direction
2072
+ // flips, and re-evaluate overflow edges when the threshold changes.
2338
2073
  queueMicrotask(computeThumbPosition);
2339
- }, [computeThumbPosition, hiddenState, direction]);
2074
+ }, [computeThumbPosition, hiddenState, direction, overflowEdgeThreshold.xStart, overflowEdgeThreshold.xEnd, overflowEdgeThreshold.yStart, overflowEdgeThreshold.yEnd]);
2340
2075
  useIsoLayoutEffect(() => {
2341
2076
  // `onMouseEnter` doesn't fire upon load, so we need to check if the viewport is already
2342
2077
  // being hovered.
@@ -2344,13 +2079,13 @@ const ScrollAreaViewport = /*#__PURE__*/React.forwardRef(function ScrollAreaView
2344
2079
  setHovering(true);
2345
2080
  }
2346
2081
  }, [viewportRef, setHovering]);
2347
- React.useEffect(() => {
2082
+ useIsoLayoutEffect(() => {
2348
2083
  const viewport = viewportRef.current;
2349
- if (!HAS_RESIZE_OBSERVER || !viewport) {
2084
+ if (typeof ResizeObserver === 'undefined' || !viewport) {
2350
2085
  return undefined;
2351
2086
  }
2352
2087
  let hasInitialized = false;
2353
- const ro = new ResizeObserver(() => {
2088
+ const resizeObserver = new ResizeObserver(() => {
2354
2089
  // Avoid duplicate mount-time recompute when observer data matches what the mount
2355
2090
  // scheduling pass already measured. If dimensions changed before the first observer
2356
2091
  // delivery, keep the recompute so overflow transitions stay in sync.
@@ -2363,15 +2098,10 @@ const ScrollAreaViewport = /*#__PURE__*/React.forwardRef(function ScrollAreaView
2363
2098
  }
2364
2099
  computeThumbPosition();
2365
2100
  });
2366
- ro.observe(viewport);
2101
+ resizeObserver.observe(viewport);
2367
2102
 
2368
- // If there are animations in the viewport, wait for them to finish and then recompute the thumb position.
2369
- // This is necessary when the viewport contains a Dialog that is animating its popup on open
2370
- // and the popup is using a transform for the animation, which affects the size of the viewport.
2371
- // Without this, the thumb position will be incorrect until scrolling (i.e. if the scrollbar shows
2372
- // on hover, the thumb has an incorrect size).
2373
- // We assume the user is using `onOpenChangeComplete` to hide the scrollbar
2374
- // until animations complete because otherwise the scrollbar would show the thumb resizing mid-animation.
2103
+ // Wait for subtree animations to finish, then recompute thumb geometry that
2104
+ // may have been affected by transform-based animations.
2375
2105
  waitForAnimationsTimeout.start(0, () => {
2376
2106
  const animations = viewport.getAnimations({
2377
2107
  subtree: true
@@ -2382,7 +2112,7 @@ const ScrollAreaViewport = /*#__PURE__*/React.forwardRef(function ScrollAreaView
2382
2112
  Promise.allSettled(animations.map(animation => animation.finished)).then(computeThumbPosition).catch(() => {});
2383
2113
  });
2384
2114
  return () => {
2385
- ro.disconnect();
2115
+ resizeObserver.disconnect();
2386
2116
  waitForAnimationsTimeout.clear();
2387
2117
  };
2388
2118
  }, [computeThumbPosition, viewportRef, waitForAnimationsTimeout]);
@@ -2470,4 +2200,4 @@ function mergeHiddenState(prevState, nextState) {
2470
2200
  return nextState;
2471
2201
  }
2472
2202
 
2473
- export { useDrawerSnapPoints as A, DrawerViewportContext as B, DRAWER_CONTENT_ATTRIBUTE as C, DrawerTrigger as D, useScrollAreaRootContext as E, getOffset as F, ScrollAreaRootCssVars as G, scrollAreaStateAttributesMapping as H, useScrollAreaViewportContext as I, ScrollAreaRoot as S, DrawerRoot as a, DrawerPortal as b, DrawerBackdrop as c, DrawerPopup as d, ScrollAreaViewport as e, DrawerContent as f, DialogRoot as g, DialogTrigger as h, DialogPortal as i, useDialogPortalContext as j, DialogStore as k, createInitialPopupStoreState as l, useImplicitActiveTrigger as m, useOpenStateTransitions as n, useSyncedFloatingRootContext as o, popupStoreSelectors as p, useRole as q, useTriggerDataForwarding as r, useTriggerRegistration as s, useDrawerProviderContext as t, useDialogRootContext as u, DrawerBackdropCssVars as v, DrawerPopupCssVars as w, DrawerProviderContext as x, useDrawerRootContext as y, DrawerPopupDataAttributes as z };
2203
+ export { ScrollAreaRootCssVars as A, scrollAreaStateAttributesMapping as B, useScrollAreaViewportContext as C, DrawerTrigger as D, ScrollAreaRoot as S, DrawerRoot as a, DrawerPortal as b, DrawerBackdrop as c, DrawerPopup as d, ScrollAreaViewport as e, DrawerContent as f, DialogRoot as g, DialogTrigger as h, DialogPortal as i, useDialogPortalContext as j, DialogStore as k, createInitialPopupStoreState as l, useDrawerProviderContext as m, DrawerBackdropCssVars as n, DrawerPopupCssVars as o, popupStoreSelectors as p, DrawerProviderContext as q, useDrawerRootContext as r, DrawerPopupDataAttributes as s, useDrawerSnapPoints as t, useDialogRootContext as u, getSnapPointSwipeMovement as v, DrawerViewportContext as w, DRAWER_CONTENT_ATTRIBUTE as x, useScrollAreaRootContext as y, getOffset as z };