@jobber/components 9.6.0 → 9.6.2

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 (187) hide show
  1. package/dist/ActivityIndicator-cjs.js +1 -0
  2. package/dist/ActivityIndicator-es.js +1 -0
  3. package/dist/Autocomplete/index.cjs +2 -0
  4. package/dist/Autocomplete/index.mjs +2 -0
  5. package/dist/Autocomplete-cjs.js +6 -4
  6. package/dist/Autocomplete-es.js +3 -1
  7. package/dist/Banner-cjs.js +1 -0
  8. package/dist/Banner-es.js +1 -0
  9. package/dist/Card/index.cjs +2 -1
  10. package/dist/Card/index.mjs +2 -1
  11. package/dist/Chip/index.cjs +2 -0
  12. package/dist/Chip/index.mjs +2 -0
  13. package/dist/Chip-cjs.js +1 -0
  14. package/dist/Chip-es.js +1 -0
  15. package/dist/Chips/InternalChipDismissible/hooks/index.cjs +2 -0
  16. package/dist/Chips/InternalChipDismissible/hooks/index.mjs +2 -0
  17. package/dist/Chips/InternalChipDismissible/index.cjs +2 -0
  18. package/dist/Chips/InternalChipDismissible/index.mjs +2 -0
  19. package/dist/Chips/index.cjs +2 -0
  20. package/dist/Chips/index.mjs +2 -0
  21. package/dist/Combobox/index.cjs +4 -2
  22. package/dist/Combobox/index.mjs +4 -2
  23. package/dist/{ComboboxSeparator-cjs.js → ComboboxChipRemove-cjs.js} +455 -501
  24. package/dist/{ComboboxSeparator-es.js → ComboboxChipRemove-es.js} +456 -500
  25. package/dist/ComboboxPrimitive-cjs.js +30 -29
  26. package/dist/ComboboxPrimitive-es.js +3 -2
  27. package/dist/ConfirmationModal/index.cjs +2 -0
  28. package/dist/ConfirmationModal/index.mjs +2 -0
  29. package/dist/ConfirmationModal-cjs.js +1 -0
  30. package/dist/ConfirmationModal-es.js +1 -0
  31. package/dist/DataDump/index.cjs +2 -1
  32. package/dist/DataDump/index.mjs +2 -1
  33. package/dist/DataDump-cjs.js +1 -0
  34. package/dist/DataDump-es.js +1 -0
  35. package/dist/DataList/components/DataListActions/index.cjs +2 -0
  36. package/dist/DataList/components/DataListActions/index.mjs +2 -0
  37. package/dist/DataList/components/DataListBulkActions/index.cjs +2 -0
  38. package/dist/DataList/components/DataListBulkActions/index.mjs +2 -0
  39. package/dist/DataList/components/DataListFilters/components/DataListSort/index.cjs +2 -0
  40. package/dist/DataList/components/DataListFilters/components/DataListSort/index.mjs +2 -0
  41. package/dist/DataList/components/DataListFilters/index.cjs +2 -0
  42. package/dist/DataList/components/DataListFilters/index.mjs +2 -0
  43. package/dist/DataList/components/DataListHeader/index.cjs +2 -0
  44. package/dist/DataList/components/DataListHeader/index.mjs +2 -0
  45. package/dist/DataList/components/DataListItem/index.cjs +2 -0
  46. package/dist/DataList/components/DataListItem/index.mjs +2 -0
  47. package/dist/DataList/components/DataListItemActions/index.cjs +2 -0
  48. package/dist/DataList/components/DataListItemActions/index.mjs +2 -0
  49. package/dist/DataList/components/DataListItemActionsOverflow/index.cjs +2 -0
  50. package/dist/DataList/components/DataListItemActionsOverflow/index.mjs +2 -0
  51. package/dist/DataList/components/DataListItems/index.cjs +2 -0
  52. package/dist/DataList/components/DataListItems/index.mjs +2 -0
  53. package/dist/DataList/components/DataListLayout/index.cjs +2 -0
  54. package/dist/DataList/components/DataListLayout/index.mjs +2 -0
  55. package/dist/DataList/components/DataListLayoutActions/index.cjs +2 -0
  56. package/dist/DataList/components/DataListLayoutActions/index.mjs +2 -0
  57. package/dist/DataList/index.cjs +2 -0
  58. package/dist/DataList/index.mjs +2 -0
  59. package/dist/DataTable-cjs.js +1 -0
  60. package/dist/DataTable-es.js +1 -0
  61. package/dist/DatePicker/index.cjs +2 -0
  62. package/dist/DatePicker/index.mjs +2 -0
  63. package/dist/DatePicker-cjs.js +8 -7
  64. package/dist/DatePicker-es.js +6 -5
  65. package/dist/Dialog/index.cjs +2 -1
  66. package/dist/Dialog/index.mjs +2 -1
  67. package/dist/DrawerDescription-cjs.js +99 -268
  68. package/dist/DrawerDescription-es.js +103 -270
  69. package/dist/DrawerGrid-cjs.js +1 -0
  70. package/dist/DrawerGrid-es.js +1 -0
  71. package/dist/DrawerTitle-cjs.js +6 -2
  72. package/dist/DrawerTitle-es.js +7 -3
  73. package/dist/FeatureSwitch-cjs.js +1 -0
  74. package/dist/FeatureSwitch-es.js +1 -0
  75. package/dist/FieldDescription-cjs.js +181 -184
  76. package/dist/FieldDescription-es.js +184 -187
  77. package/dist/FilterPicker/components/FilterPickerActivator/index.cjs +2 -0
  78. package/dist/FilterPicker/components/FilterPickerActivator/index.mjs +2 -0
  79. package/dist/FilterPicker/components/FilterPickerContent/index.cjs +2 -0
  80. package/dist/FilterPicker/components/FilterPickerContent/index.mjs +2 -0
  81. package/dist/FilterPicker/components/FilterPickerTrigger/index.cjs +2 -0
  82. package/dist/FilterPicker/components/FilterPickerTrigger/index.mjs +2 -0
  83. package/dist/FilterPicker/index.cjs +2 -0
  84. package/dist/FilterPicker/index.mjs +2 -0
  85. package/dist/FilterPickerContent-cjs.js +5 -4
  86. package/dist/FilterPickerContent-es.js +2 -1
  87. package/dist/FormFieldWrapper-cjs.js +1 -0
  88. package/dist/FormFieldWrapper-es.js +1 -0
  89. package/dist/FormatFile/index.cjs +2 -0
  90. package/dist/FormatFile/index.mjs +2 -0
  91. package/dist/FormatFile-cjs.js +1 -0
  92. package/dist/FormatFile-es.js +1 -0
  93. package/dist/Gallery/index.cjs +2 -0
  94. package/dist/Gallery/index.mjs +2 -0
  95. package/dist/InputAvatar-cjs.js +1 -0
  96. package/dist/InputAvatar-es.js +1 -0
  97. package/dist/InputDate/index.cjs +2 -0
  98. package/dist/InputDate/index.mjs +2 -0
  99. package/dist/InputDate-cjs.js +1 -0
  100. package/dist/InputDate-es.js +1 -0
  101. package/dist/InputNumber/index.cjs +2 -1
  102. package/dist/InputNumber/index.mjs +2 -1
  103. package/dist/InternalChipDismissible-cjs.js +1 -0
  104. package/dist/InternalChipDismissible-es.js +1 -0
  105. package/dist/LightBox/index.cjs +2 -0
  106. package/dist/LightBox/index.mjs +2 -0
  107. package/dist/LightBox-cjs.js +1 -0
  108. package/dist/LightBox-es.js +1 -0
  109. package/dist/Menu/index.cjs +2 -1
  110. package/dist/Menu/index.mjs +2 -1
  111. package/dist/Menu-cjs.js +6 -4
  112. package/dist/Menu-es.js +3 -1
  113. package/dist/MenuSubmenuTrigger-cjs.js +164 -206
  114. package/dist/MenuSubmenuTrigger-es.js +152 -194
  115. package/dist/Modal/index.cjs +3 -1
  116. package/dist/Modal/index.mjs +4 -2
  117. package/dist/NumberFieldInput-cjs.js +308 -187
  118. package/dist/NumberFieldInput-es.js +308 -187
  119. package/dist/Page/index.cjs +2 -1
  120. package/dist/Page/index.mjs +2 -1
  121. package/dist/Page-cjs.js +1 -0
  122. package/dist/Page-es.js +1 -0
  123. package/dist/Popover/index.cjs +2 -0
  124. package/dist/Popover/index.mjs +2 -0
  125. package/dist/Popover-cjs.js +9 -7
  126. package/dist/Popover-es.js +3 -1
  127. package/dist/ProgressBar-cjs.js +1 -0
  128. package/dist/ProgressBar-es.js +1 -0
  129. package/dist/ScrollAreaViewport-cjs.js +1093 -747
  130. package/dist/ScrollAreaViewport-es.js +1081 -734
  131. package/dist/Select/index.cjs +2 -1
  132. package/dist/Select/index.mjs +2 -1
  133. package/dist/SelectGroupLabel-cjs.js +306 -207
  134. package/dist/SelectGroupLabel-es.js +302 -203
  135. package/dist/SideDrawer-cjs.js +1 -0
  136. package/dist/SideDrawer-es.js +1 -0
  137. package/dist/Spinner-cjs.js +1 -0
  138. package/dist/Spinner-es.js +1 -0
  139. package/dist/Tooltip/index.cjs +2 -0
  140. package/dist/Tooltip/index.mjs +2 -0
  141. package/dist/Tooltip-cjs.js +7 -6
  142. package/dist/Tooltip-es.js +2 -1
  143. package/dist/dialogReturnFocus-cjs.js +1 -1
  144. package/dist/dialogReturnFocus-es.js +2 -2
  145. package/dist/floating-ui.react-cjs.js +192 -2564
  146. package/dist/floating-ui.react-dom-cjs.js +2103 -0
  147. package/dist/floating-ui.react-dom-es.js +2072 -0
  148. package/dist/floating-ui.react-es.js +156 -2519
  149. package/dist/floating-ui.utils-cjs.js +342 -0
  150. package/dist/floating-ui.utils-es.js +300 -0
  151. package/dist/index.cjs +4 -3
  152. package/dist/index.mjs +4 -3
  153. package/dist/primitives/BottomSheet/index.cjs +1 -1
  154. package/dist/primitives/BottomSheet/index.mjs +1 -1
  155. package/dist/primitives/ComboboxPrimitive/index.cjs +4 -2
  156. package/dist/primitives/ComboboxPrimitive/index.mjs +4 -2
  157. package/dist/primitives/SelectPrimitive/index.cjs +2 -0
  158. package/dist/primitives/SelectPrimitive/index.mjs +2 -0
  159. package/dist/primitives/index.cjs +3 -2
  160. package/dist/primitives/index.mjs +3 -2
  161. package/dist/scrollEdges-cjs.js +11 -1
  162. package/dist/scrollEdges-es.js +11 -1
  163. package/dist/sharedHelpers/i18n/index.cjs +1 -0
  164. package/dist/sharedHelpers/i18n/index.d.ts +1 -0
  165. package/dist/sharedHelpers/i18n/index.mjs +1 -1
  166. package/dist/sharedHelpers/i18n/releasedLanguages.d.ts +12 -0
  167. package/dist/sharedHelpers/i18n/useReleasedLocale.d.ts +6 -0
  168. package/dist/showToast-cjs.js +1 -1
  169. package/dist/showToast-es.js +1 -1
  170. package/dist/testUtils/releasedLanguages.d.ts +16 -0
  171. package/dist/unstyledPrimitives/index.cjs +478 -720
  172. package/dist/unstyledPrimitives/index.mjs +421 -663
  173. package/dist/useAtlantisI18n-cjs.js +44 -11
  174. package/dist/useAtlantisI18n-es.js +44 -12
  175. package/dist/useCompositeListItem-cjs.js +361 -2108
  176. package/dist/useCompositeListItem-es.js +331 -2076
  177. package/dist/useLabel-cjs.js +3 -2
  178. package/dist/useLabel-es.js +3 -2
  179. package/dist/useRenderElement-cjs.js +7 -9
  180. package/dist/useRenderElement-es.js +7 -9
  181. package/dist/useScrollLock-cjs.js +344 -819
  182. package/dist/useScrollLock-es.js +296 -732
  183. package/dist/useScrollToActive-cjs.js +5 -4
  184. package/dist/useScrollToActive-es.js +2 -1
  185. package/package.json +3 -3
  186. package/dist/scrollable-cjs.js +0 -58
  187. package/dist/scrollable-es.js +0 -54
@@ -1,21 +1,22 @@
1
1
  import * as React from 'react';
2
- import { B as useCoreFilter, D as AriaCombobox, E as useComboboxInputValueContext, e as ComboboxTrigger, d as ComboboxInputGroup, p as ComboboxItem, L as ListboxSeparator, l as ComboboxArrow, i as ComboboxBackdrop, x as ComboboxClear, v as ComboboxCollection, w as ComboboxEmpty, n as ComboboxGroup, o as ComboboxGroupLabel, m as ComboboxIcon, c as ComboboxInput, f as ComboboxList, k as ComboboxPopup, h as ComboboxPortal, j as ComboboxPositioner, u as ComboboxRow, g as ComboboxStatus, A as useFilteredItems, s as ComboboxChip, t as ComboboxChipRemove, r as ComboboxChips, q as ComboboxItemIndicator, a as ComboboxLabel, C as ComboboxRoot, y as ComboboxSeparator, b as ComboboxValue, z as useComboboxFilter } from '../ComboboxSeparator-es.js';
3
- import { n as stringifyAsLabel, A as useCompositeListItem, M as DEFAULT_SIDES, b as useFieldRootContext, f as fieldValidityMapping, K as getDefaultLabelId } from '../useCompositeListItem-es.js';
2
+ import { A as useCoreFilter, B as AriaCombobox, D as useComboboxInputValueContext, e as ComboboxTrigger, d as ComboboxInputGroup, p as ComboboxItem, l as ComboboxArrow, i as ComboboxBackdrop, x as ComboboxClear, v as ComboboxCollection, w as ComboboxEmpty, n as ComboboxGroup, o as ComboboxGroupLabel, m as ComboboxIcon, c as ComboboxInput, f as ComboboxList, k as ComboboxPopup, h as ComboboxPortal, j as ComboboxPositioner, u as ComboboxRow, g as ComboboxStatus, z as useFilteredItems, s as ComboboxChip, t as ComboboxChipRemove, r as ComboboxChips, q as ComboboxItemIndicator, a as ComboboxLabel, C as ComboboxRoot, b as ComboboxValue, y as useComboboxFilter } from '../ComboboxChipRemove-es.js';
3
+ import { m as stringifyAsLabel, z as useCompositeListItem, b as useFieldRootContext, f as fieldValidityMapping, J as getDefaultLabelId } from '../useCompositeListItem-es.js';
4
4
  import { jsx, jsxs } from 'react/jsx-runtime';
5
- import { bX as pointer, c as useIsoLayoutEffect, d as useStableCallback, bf as CommonPopupDataAttributes, u as useBaseUiId, bS as useTriggerRegistration, o as ownerDocument, h as createChangeEventDetails, bj as swipe, ac as isVirtualClick, a8 as useAnimationFrame, q as useTimeout, I as getWindow, y as addEventListener, D as activeElement, g as getComputedStyle, a0 as contains, e as getTarget, i as isHTMLElement, bv as isInteractiveElement, b as getParentNode, a6 as popupStateMapping, v as useControlled, ad as itemPress, s as useTransitionStatus, l as useOpenChangeComplete, aw as round, bz as useAnimationsFinished, af as getSide, a7 as useDirection, a4 as inertValue, bm as mergeCleanups, bY as gecko, b$ as scrub, a9 as webkit, G as createGenericEventDetails, U as useStore, be as triggerOpenStateMapping, t as transitionStatusMapping, p as popupTransitionStateMapping } from '../useScrollLock-es.js';
6
- import { b as DialogBackdrop, d as DialogDescription, f as DialogHandle, c as DialogPopup, a as DialogRoot, e as createDialogHandle, D as DrawerDescription, B as BasePopupHandle } from '../DrawerDescription-es.js';
5
+ import { bn as pointer, a as useIsoLayoutEffect, b as useStableCallback, C as CommonPopupDataAttributes, k as useTimeout, u as useBaseUiId, b7 as useTriggerRegistration, d as createChangeEventDetails, bh as swipe, a5 as useAnimationFrame, o as ownerDocument, s as addEventListener, D as activeElement, _ as contains, g as getTarget, aG as isInteractiveElement, p as popupStateMapping, n as useControlled, a9 as itemPress, m as useTransitionStatus, f as useOpenChangeComplete, aJ as useAnimationsFinished, a4 as useDirection, a2 as inertValue, ax as mergeCleanups, bk as gecko, bo as scrub, a6 as webkit, E as createGenericEventDetails, P as useStore, b8 as triggerOpenStateMapping, t as transitionStatusMapping } from '../useScrollLock-es.js';
6
+ import { S as Separator } from '../Separator-es.js';
7
+ import { a as DialogBackdrop, c as DialogDescription, e as DialogHandle, b as DialogPopup, d as createDialogHandle, D as DrawerDescription } from '../DrawerDescription-es.js';
7
8
  import { c as DialogClose, b as DialogTitle, a as DrawerClose, D as DrawerTitle } from '../DrawerTitle-es.js';
8
- import { i as DialogPortal, h as DialogTrigger, j as DialogViewport, r as useDrawerProviderContext, s as DrawerBackdropCssVars, t as DrawerPopupCssVars, v as DrawerProviderContext, u as useDialogRootContext, w as useDrawerRootContext, x as useSwipeDismiss, y as getDisplacement, z as DrawerPopupDataAttributes, A as getElementTransform, B as DrawerVirtualKeyboardContext, C as getElementAtPoint, c as DrawerBackdrop, g as DrawerContent, e as DrawerPopup, b as DrawerPortal, a as DrawerRoot, D as DrawerTrigger, d as DrawerViewport, E as useScrollAreaRootContext, F as getOffset, G as scrollAreaStateAttributesMapping, H as useScrollAreaViewportContext, S as ScrollAreaRoot, f as ScrollAreaViewport } from '../ScrollAreaViewport-es.js';
9
- import { u as useRenderElement, N as NOOP, f as formatErrorMessage, E as EMPTY_OBJECT } from '../useRenderElement-es.js';
9
+ import { j as DialogPortal, h as DialogRoot, i as DialogTrigger, k as DialogViewport, o as useDrawerProviderContext, q as DrawerBackdropCssVars, r as DrawerPopupCssVars, s as DrawerProviderContext, u as useDialogRootContext, t as useDrawerRootContext, v as useSwipeDismiss, w as getDisplacement, x as DrawerPopupDataAttributes, y as getElementTransform, z as DrawerVirtualKeyboardContext, A as getElementAtPoint, B as findScrollableTouchTarget, c as DrawerBackdrop, g as DrawerContent, e as DrawerPopup, b as DrawerPortal, a as DrawerRoot, D as DrawerTrigger, d as DrawerViewport, C as useScrollAreaRootContext, E as getOffset, F as ScrollAreaRootCssVars, G as scrollAreaStateAttributesMapping, H as useScrollAreaViewportContext, S as ScrollAreaRoot, f as ScrollAreaViewport } from '../ScrollAreaViewport-es.js';
10
+ import { u as useRenderElement, f as formatErrorMessage, N as NOOP, E as EMPTY_OBJECT } from '../useRenderElement-es.js';
11
+ import { K as getWindow, h as getComputedStyle, i as isHTMLElement, e as getParentNode, G as round } from '../floating-ui.utils-es.js';
10
12
  import { c as clamp, g as getMaxScrollOffset, n as normalizeScrollOffset, S as SCROLL_EDGE_TOLERANCE_PX } from '../scrollEdges-es.js';
11
- import { f as findScrollableTouchTarget } from '../scrollable-es.js';
12
- import { u as useMenuRootContext, o as useMenuPositionerContext, p as useMenuItem, R as REGULAR_ITEM, q as itemMapping, r as createNullMenuStore, h as MenuBackdrop, l as MenuGroup, n as MenuGroupLabel, b as MenuItem, a as MenuLinkItem, j as MenuPopup, g as MenuPortal, i as MenuPositioner, k as MenuRadioGroup, c as MenuRadioItem, d as MenuRadioItemIndicator, f as MenuRoot, m as MenuSubmenuRoot, e as MenuSubmenuTrigger, M as MenuTrigger } from '../MenuSubmenuTrigger-es.js';
13
+ import { u as useMenuRootContext, o as useMenuPositionerContext, p as useMenuItem, R as REGULAR_ITEM, q as itemMapping, r as MenuStore, h as MenuBackdrop, l as MenuGroup, n as MenuGroupLabel, b as MenuItem, a as MenuLinkItem, j as MenuPopup, g as MenuPortal, i as MenuPositioner, k as MenuRadioGroup, c as MenuRadioItem, d as MenuRadioItemIndicator, f as MenuRoot, m as MenuSubmenuRoot, e as MenuSubmenuTrigger, M as MenuTrigger } from '../MenuSubmenuTrigger-es.js';
13
14
  import * as ReactDOM from 'react-dom';
14
15
  import { m as usePreviousValue, n as useSelectRootContext, s as selectors, o as useSelectPositionerContext, j as SelectGroup, k as SelectGroupLabel, g as SelectItem, i as SelectItemIndicator, h as SelectItemText, f as SelectList, e as SelectPopup, a as SelectPortal, d as SelectPositioner, S as SelectRoot, b as SelectTrigger, c as SelectValue } from '../SelectGroupLabel-es.js';
15
- import { S as Separator } from '../Separator-es.js';
16
- import { u as useNumberFieldRootContext, s as stateAttributesMapping$4, d as NumberFieldDecrement, a as NumberFieldGroup, c as NumberFieldIncrement, b as NumberFieldInput, N as NumberFieldRoot } from '../NumberFieldInput-es.js';
16
+ import { u as useNumberFieldRootContext, s as stateAttributesMapping$6, d as NumberFieldDecrement, a as NumberFieldGroup, c as NumberFieldIncrement, b as NumberFieldInput, N as NumberFieldRoot } from '../NumberFieldInput-es.js';
17
17
  import { u as useLabel } from '../useLabel-es.js';
18
18
  import '../stringifyLocale-es.js';
19
+ import '../floating-ui.react-dom-es.js';
19
20
 
20
21
  function AutocompleteRoot(props) {
21
22
  const {
@@ -50,9 +51,7 @@ function AutocompleteRoot(props) {
50
51
  } else {
51
52
  resolvedInputValue = internalValue;
52
53
  }
53
- const collator = useCoreFilter({
54
- locale: other.locale
55
- });
54
+ const collator = useCoreFilter();
56
55
  const baseFilter = React.useMemo(() => {
57
56
  if (other.filter !== undefined) {
58
57
  return other.filter;
@@ -85,7 +84,15 @@ function AutocompleteRoot(props) {
85
84
  if (eventDetails.reason === pointer) {
86
85
  return;
87
86
  }
88
- setInlineInputValue(enableInline && highlightedValue != null ? stringifyAsLabel(highlightedValue, itemToStringValue) : '');
87
+ if (enableInline) {
88
+ if (highlightedValue == null) {
89
+ setInlineInputValue('');
90
+ } else {
91
+ setInlineInputValue(stringifyAsLabel(highlightedValue, itemToStringValue));
92
+ }
93
+ } else {
94
+ setInlineInputValue('');
95
+ }
89
96
  }
90
97
  return /*#__PURE__*/jsx(AriaCombobox, {
91
98
  ...other,
@@ -144,14 +151,6 @@ const AutocompleteInputGroup = ComboboxInputGroup;
144
151
  */
145
152
  const AutocompleteItem = ComboboxItem;
146
153
 
147
- /**
148
- * A visual separator between items or groups.
149
- * Renders a `<div>` element.
150
- *
151
- * Documentation: [Base UI Autocomplete](https://base-ui.com/react/components/autocomplete)
152
- */
153
- const AutocompleteSeparator = ListboxSeparator;
154
-
155
154
  var index_parts$7 = /*#__PURE__*/Object.freeze({
156
155
  __proto__: null,
157
156
  Arrow: ComboboxArrow,
@@ -171,7 +170,7 @@ var index_parts$7 = /*#__PURE__*/Object.freeze({
171
170
  Positioner: ComboboxPositioner,
172
171
  Root: AutocompleteRoot,
173
172
  Row: ComboboxRow,
174
- Separator: AutocompleteSeparator,
173
+ Separator: Separator,
175
174
  Status: ComboboxStatus,
176
175
  Trigger: AutocompleteTrigger,
177
176
  Value: AutocompleteValue,
@@ -194,7 +193,7 @@ var index_parts$6 = /*#__PURE__*/Object.freeze({
194
193
  createHandle: createDialogHandle
195
194
  });
196
195
 
197
- const stateAttributesMapping$3 = {
196
+ const stateAttributesMapping$5 = {
198
197
  active(value) {
199
198
  if (value) {
200
199
  return {
@@ -265,12 +264,12 @@ const DrawerIndent = /*#__PURE__*/React.forwardRef(function DrawerIndent(compone
265
264
  [DrawerBackdropCssVars.swipeProgress]: '0'
266
265
  }
267
266
  }, elementProps],
268
- stateAttributesMapping: stateAttributesMapping$3
267
+ stateAttributesMapping: stateAttributesMapping$5
269
268
  });
270
269
  });
271
270
  if (process.env.NODE_ENV !== "production") DrawerIndent.displayName = "DrawerIndent";
272
271
 
273
- const stateAttributesMapping$2 = {
272
+ const stateAttributesMapping$4 = {
274
273
  active(value) {
275
274
  if (value) {
276
275
  return {
@@ -305,7 +304,7 @@ const DrawerIndentBackground = /*#__PURE__*/React.forwardRef(function DrawerInde
305
304
  ref: forwardedRef,
306
305
  state,
307
306
  props: elementProps,
308
- stateAttributesMapping: stateAttributesMapping$2
307
+ stateAttributesMapping: stateAttributesMapping$4
309
308
  });
310
309
  });
311
310
  if (process.env.NODE_ENV !== "production") DrawerIndentBackground.displayName = "DrawerIndentBackground";
@@ -314,26 +313,37 @@ function DrawerProvider(props) {
314
313
  const {
315
314
  children
316
315
  } = props;
317
- const [openDrawers, setOpenDrawers] = React.useState(() => new Set());
316
+ const [openById, setOpenById] = React.useState(() => new Map());
318
317
  const [visualStateStore] = React.useState(createVisualStateStore);
319
- const setDrawerOpen = useStableCallback((drawer, open) => {
320
- setOpenDrawers(prev => {
321
- if (prev.has(drawer) === open) {
318
+ const setDrawerOpen = useStableCallback((drawerId, open) => {
319
+ setOpenById(prev => {
320
+ const prevOpen = prev.get(drawerId);
321
+ if (prevOpen === open) {
322
322
  return prev;
323
323
  }
324
- const next = new Set(prev);
325
- if (open) {
326
- next.add(drawer);
327
- } else {
328
- next.delete(drawer);
329
- }
324
+ const next = new Map(prev);
325
+ next.set(drawerId, open);
330
326
  return next;
331
327
  });
332
328
  });
333
- const removeDrawer = useStableCallback(drawer => {
334
- setDrawerOpen(drawer, false);
329
+ const removeDrawer = useStableCallback(drawerId => {
330
+ setOpenById(prev => {
331
+ if (!prev.has(drawerId)) {
332
+ return prev;
333
+ }
334
+ const next = new Map(prev);
335
+ next.delete(drawerId);
336
+ return next;
337
+ });
335
338
  });
336
- const active = openDrawers.size > 0;
339
+ const active = React.useMemo(() => {
340
+ for (const open of openById.values()) {
341
+ if (open) {
342
+ return true;
343
+ }
344
+ }
345
+ return false;
346
+ }, [openById]);
337
347
  const contextValue = React.useMemo(() => ({
338
348
  setDrawerOpen,
339
349
  removeDrawer,
@@ -423,7 +433,7 @@ const SWIPE_AREA_SWIPING_HOOK = {
423
433
  const SWIPE_AREA_DISABLED_HOOK = {
424
434
  [DrawerSwipeAreaDataAttributes.disabled]: ''
425
435
  };
426
- const stateAttributesMapping$1 = {
436
+ const stateAttributesMapping$3 = {
427
437
  open(value) {
428
438
  return value ? SWIPE_AREA_OPEN_HOOK : SWIPE_AREA_CLOSED_HOOK;
429
439
  },
@@ -431,9 +441,9 @@ const stateAttributesMapping$1 = {
431
441
  return value ? SWIPE_AREA_SWIPING_HOOK : null;
432
442
  },
433
443
  swipeDirection(value) {
434
- return {
444
+ return value ? {
435
445
  [DrawerSwipeAreaDataAttributes.swipeDirection]: value
436
- };
446
+ } : null;
437
447
  },
438
448
  disabled(value) {
439
449
  return value ? SWIPE_AREA_DISABLED_HOOK : null;
@@ -464,14 +474,16 @@ const DrawerSwipeArea = /*#__PURE__*/React.forwardRef(function DrawerSwipeArea(c
464
474
  swipeDirection: swipeDirectionProp,
465
475
  ...elementProps
466
476
  } = componentProps;
467
- const store = useDialogRootContext();
477
+ const {
478
+ store
479
+ } = useDialogRootContext();
468
480
  const {
469
481
  swipeDirection,
470
- frontmostHeight,
471
- swipeAreaActiveRef
482
+ frontmostHeight
472
483
  } = useDrawerRootContext();
473
484
  const providerContext = useDrawerProviderContext();
474
485
  const [swipeActive, setSwipeActive] = React.useState(false);
486
+ const releaseDismissTimeout = useTimeout();
475
487
  const swipeAreaRef = React.useRef(null);
476
488
  const swipeStartEventRef = React.useRef(null);
477
489
  const openedBySwipeRef = React.useRef(false);
@@ -481,10 +493,7 @@ const DrawerSwipeArea = /*#__PURE__*/React.forwardRef(function DrawerSwipeArea(c
481
493
  });
482
494
  const closedOffsetRef = React.useRef(null);
483
495
  const appliedSwipeStylesRef = React.useRef(false);
484
- const swipePopupElementRef = React.useRef(null);
485
- const swipeBackdropElementRef = React.useRef(null);
486
496
  const popupTransitionRef = React.useRef(null);
487
- const releaseGuardCleanupRef = React.useRef(NOOP);
488
497
  const swipeAreaId = useBaseUiId(componentProps.id);
489
498
  const registerTrigger = useTriggerRegistration(swipeAreaId, store);
490
499
  const open = store.useState('open');
@@ -496,40 +505,21 @@ const DrawerSwipeArea = /*#__PURE__*/React.forwardRef(function DrawerSwipeArea(c
496
505
  const dismissDirection = oppositeSwipeDirection[resolvedSwipeDirection];
497
506
  const enabled = !disabled && (!open || swipeActive);
498
507
  function disableDismissForSwipe() {
499
- releaseGuardCleanupRef.current();
508
+ releaseDismissTimeout.clear();
500
509
  store.context.outsidePressEnabledRef.current = false;
501
510
  }
502
- const enableDismissAfterRelease = useStableCallback(() => {
503
- releaseGuardCleanupRef.current();
504
- const doc = ownerDocument(swipeAreaRef.current);
505
- function restore(event) {
506
- // The gesture's trailing release click is the one physical click with no `pointerdown` of
507
- // its own. Ignore it and keep waiting, so it cannot dismiss the drawer it just opened,
508
- // while a click-only activation (keyboard or assistive tech) still re-enables in time.
509
- if (event?.type === 'click' && event.detail !== 0 && !isVirtualClick(event)) {
510
- return;
511
- }
512
- releaseGuardCleanupRef.current = NOOP;
513
- doc.removeEventListener('pointerdown', restore, true);
514
- doc.removeEventListener('click', restore, true);
511
+ function enableDismissAfterRelease() {
512
+ // Safari can dispatch outside-press for the same swipe-open gesture
513
+ // after release, so defer re-enabling dismissal to the next macrotask.
514
+ releaseDismissTimeout.start(0, () => {
515
515
  store.context.outsidePressEnabledRef.current = true;
516
+ });
517
+ }
518
+ function resolvePopupSize() {
519
+ const popupElement = store.context.popupRef.current;
520
+ if (!popupElement) {
521
+ return null;
516
522
  }
517
-
518
- // The pointerup that ends a swipe-open gesture synthesizes a `click`. When the drag released
519
- // outside the popup (e.g. it was dragged past the popup's size), that click would be treated as
520
- // an outside press and immediately dismiss the drawer that was just opened. Keep outside-press
521
- // dismissal disabled until the next interaction that isn't that release click: a deliberate
522
- // outside press starts with a `pointerdown`, and a click-only activation (keyboard or
523
- // assistive tech) is distinguishable from a physical release. This is deterministic, unlike
524
- // re-enabling on a timer that can race the synthesized click and dismiss at random.
525
- //
526
- // `restore` runs in document capture, ahead of floating-ui's own outside-press check (which
527
- // happens on the event target, after capture), so the triggering press still dismisses.
528
- releaseGuardCleanupRef.current = restore;
529
- doc.addEventListener('pointerdown', restore, true);
530
- doc.addEventListener('click', restore, true);
531
- });
532
- function getPopupSize(popupElement) {
533
523
  const isHorizontal = dismissDirection === 'left' || dismissDirection === 'right';
534
524
  const size = isHorizontal ? popupElement.offsetWidth : popupElement.offsetHeight;
535
525
  if (size <= 0) {
@@ -537,15 +527,15 @@ const DrawerSwipeArea = /*#__PURE__*/React.forwardRef(function DrawerSwipeArea(c
537
527
  }
538
528
  return size;
539
529
  }
540
- function resolvePopupSize() {
541
- const popupElement = store.context.popupRef.current;
542
- return popupElement ? getPopupSize(popupElement) : null;
543
- }
544
- function resolveClosedOffset(popupElement) {
545
- const offset = getPopupSize(popupElement);
530
+ function resolveClosedOffset() {
531
+ const offset = resolvePopupSize();
546
532
  if (offset == null) {
547
533
  return null;
548
534
  }
535
+ const popupElement = store.context.popupRef.current;
536
+ if (!popupElement) {
537
+ return offset;
538
+ }
549
539
  const isHorizontal = dismissDirection === 'left' || dismissDirection === 'right';
550
540
  const transform = getElementTransform(popupElement);
551
541
  const transformOffset = isHorizontal ? transform.x : transform.y;
@@ -562,6 +552,9 @@ const DrawerSwipeArea = /*#__PURE__*/React.forwardRef(function DrawerSwipeArea(c
562
552
  return popupSize * DEFAULT_SWIPE_OPEN_RATIO;
563
553
  }
564
554
  function applySwipeMovement() {
555
+ if (!swipeActive) {
556
+ return;
557
+ }
565
558
  const popupElement = store.context.popupRef.current;
566
559
  if (!popupElement) {
567
560
  return;
@@ -570,10 +563,10 @@ const DrawerSwipeArea = /*#__PURE__*/React.forwardRef(function DrawerSwipeArea(c
570
563
  return;
571
564
  }
572
565
  if (closedOffsetRef.current == null) {
573
- closedOffsetRef.current = resolveClosedOffset(popupElement);
566
+ closedOffsetRef.current = resolveClosedOffset();
574
567
  }
575
568
  const closedOffset = closedOffsetRef.current;
576
- if (closedOffset === null) {
569
+ if (!closedOffset || !Number.isFinite(closedOffset) || closedOffset <= 0) {
577
570
  return;
578
571
  }
579
572
  const {
@@ -594,7 +587,6 @@ const DrawerSwipeArea = /*#__PURE__*/React.forwardRef(function DrawerSwipeArea(c
594
587
  popupElement.style.setProperty(DrawerPopupCssVars.swipeMovementX, `${movementX}px`);
595
588
  popupElement.style.setProperty(DrawerPopupCssVars.swipeMovementY, `${movementY}px`);
596
589
  popupElement.setAttribute(DrawerPopupDataAttributes.swiping, '');
597
- swipePopupElementRef.current = popupElement;
598
590
  if (popupTransitionRef.current === null) {
599
591
  popupTransitionRef.current = popupElement.style.transition;
600
592
  }
@@ -602,7 +594,6 @@ const DrawerSwipeArea = /*#__PURE__*/React.forwardRef(function DrawerSwipeArea(c
602
594
  const backdropElement = store.context.backdropRef.current;
603
595
  if (backdropElement) {
604
596
  backdropElement.setAttribute(DrawerPopupDataAttributes.swiping, '');
605
- swipeBackdropElementRef.current = backdropElement;
606
597
  backdropElement.style.setProperty(DrawerBackdropCssVars.swipeProgress, `${backdropProgress}`);
607
598
  if (openProgress > 0 && frontmostHeight > 0) {
608
599
  backdropElement.style.setProperty(DrawerPopupCssVars.height, `${frontmostHeight}px`);
@@ -615,11 +606,10 @@ const DrawerSwipeArea = /*#__PURE__*/React.forwardRef(function DrawerSwipeArea(c
615
606
  frontmostHeight: openProgress > 0 ? frontmostHeight : 0
616
607
  });
617
608
  appliedSwipeStylesRef.current = true;
618
- swipeAreaActiveRef.current = true;
619
609
  }
620
610
  const clearSwipeStyles = useStableCallback(() => {
621
- const popupElement = swipePopupElementRef.current;
622
- if (popupElement) {
611
+ const popupElement = store.context.popupRef.current;
612
+ if (popupElement && appliedSwipeStylesRef.current) {
623
613
  popupElement.style.removeProperty(DrawerPopupCssVars.swipeMovementX);
624
614
  popupElement.style.removeProperty(DrawerPopupCssVars.swipeMovementY);
625
615
  popupElement.removeAttribute(DrawerPopupDataAttributes.swiping);
@@ -628,7 +618,7 @@ const DrawerSwipeArea = /*#__PURE__*/React.forwardRef(function DrawerSwipeArea(c
628
618
  popupElement.style.transition = popupTransitionRef.current;
629
619
  popupTransitionRef.current = null;
630
620
  }
631
- const backdropElement = swipeBackdropElementRef.current;
621
+ const backdropElement = store.context.backdropRef.current;
632
622
  if (backdropElement) {
633
623
  backdropElement.removeAttribute(DrawerPopupDataAttributes.swiping);
634
624
  backdropElement.style.setProperty(DrawerBackdropCssVars.swipeProgress, '0');
@@ -639,16 +629,19 @@ const DrawerSwipeArea = /*#__PURE__*/React.forwardRef(function DrawerSwipeArea(c
639
629
  frontmostHeight: 0
640
630
  });
641
631
  appliedSwipeStylesRef.current = false;
642
- swipePopupElementRef.current = null;
643
- swipeBackdropElementRef.current = null;
644
- swipeAreaActiveRef.current = false;
645
632
  });
646
633
  function openDrawer(event) {
634
+ if (store.select('open')) {
635
+ return;
636
+ }
647
637
  openedBySwipeRef.current = true;
648
- store.setOpen(true, createChangeEventDetails(swipe, event, swipeAreaRef.current));
638
+ store.setOpen(true, createChangeEventDetails(swipe, event, swipeAreaRef.current ?? undefined));
649
639
  }
650
640
  function closeDrawer(event) {
651
- store.setOpen(false, createChangeEventDetails(swipe, event, swipeAreaRef.current));
641
+ if (!store.select('open')) {
642
+ return;
643
+ }
644
+ store.setOpen(false, createChangeEventDetails(swipe, event, swipeAreaRef.current ?? undefined));
652
645
  }
653
646
  function resetSwipeInteractionState() {
654
647
  swipeStartEventRef.current = null;
@@ -691,10 +684,10 @@ const DrawerSwipeArea = /*#__PURE__*/React.forwardRef(function DrawerSwipeArea(c
691
684
  return;
692
685
  }
693
686
  const displacement = getDisplacement(resolvedSwipeDirection, details.deltaX, details.deltaY);
694
- if (!openedBySwipeRef.current && displacement < MIN_SWIPE_START_DISTANCE) {
687
+ if (displacement < MIN_SWIPE_START_DISTANCE && !openedBySwipeRef.current) {
695
688
  return;
696
689
  }
697
- if (!openedBySwipeRef.current && !store.select('open')) {
690
+ if (!openedBySwipeRef.current) {
698
691
  openDrawer(swipeStartEventRef.current);
699
692
  }
700
693
  applySwipeMovement();
@@ -710,14 +703,14 @@ const DrawerSwipeArea = /*#__PURE__*/React.forwardRef(function DrawerSwipeArea(c
710
703
  const displacement = getDisplacement(resolvedSwipeDirection, deltaX, deltaY);
711
704
  const releaseVelocity = getDisplacement(resolvedSwipeDirection, releaseVelocityX, releaseVelocityY);
712
705
  const threshold = resolveSwipeOpenThreshold();
713
- const hasEnoughDistance = displacement >= threshold;
706
+ const hasEnoughDistance = threshold != null && displacement >= threshold;
714
707
  const hasEnoughVelocity = releaseVelocity >= VELOCITY_THRESHOLD;
715
- const shouldOpen = direction === resolvedSwipeDirection && (hasEnoughDistance || hasEnoughVelocity) && !disabled;
708
+ const shouldOpen = threshold != null && direction === resolvedSwipeDirection && (hasEnoughDistance || hasEnoughVelocity) && !disabled;
716
709
  if (shouldOpen) {
717
710
  if (!store.select('open')) {
718
711
  openDrawer(event);
719
712
  }
720
- } else if (openedBySwipeRef.current && store.select('open')) {
713
+ } else if (openedBySwipeRef.current) {
721
714
  closeDrawer(event);
722
715
  }
723
716
  finishSwipeInteraction();
@@ -728,29 +721,16 @@ const DrawerSwipeArea = /*#__PURE__*/React.forwardRef(function DrawerSwipeArea(c
728
721
  const swipePointerProps = swipe$1.getPointerProps();
729
722
  const swipeTouchProps = swipe$1.getTouchProps();
730
723
  const resetSwipe = swipe$1.reset;
731
-
732
- // The commit that opens the drawer re-renders the popup, resetting `--swipe-movement-*` to `0px`
733
- // (the viewport isn't swiping). Re-assert after the DOM mutation but before paint. No deps: must
734
- // run on every commit the swipe area participates in.
735
- useIsoLayoutEffect(() => {
736
- if (swipeActive && appliedSwipeStylesRef.current) {
737
- applySwipeMovement();
738
- }
739
- });
740
- useIsoLayoutEffect(() => {
724
+ React.useEffect(() => {
741
725
  if (!enabled) {
742
- if (swipeActive) {
743
- enableDismissAfterRelease();
744
- }
745
726
  resetSwipe();
746
727
  resetDragDelta();
747
728
  clearSwipeStyles();
748
729
  resetSwipeInteractionState();
749
730
  }
750
- }, [clearSwipeStyles, enableDismissAfterRelease, enabled, resetDragDelta, resetSwipe, swipeActive]);
731
+ }, [clearSwipeStyles, enabled, resetDragDelta, resetSwipe]);
751
732
  React.useEffect(() => {
752
733
  return () => {
753
- releaseGuardCleanupRef.current();
754
734
  store.context.outsidePressEnabledRef.current = true;
755
735
  };
756
736
  }, [store]);
@@ -763,7 +743,7 @@ const DrawerSwipeArea = /*#__PURE__*/React.forwardRef(function DrawerSwipeArea(c
763
743
  return useRenderElement('div', componentProps, {
764
744
  state,
765
745
  ref: [forwardedRef, swipeAreaRef, registerTrigger],
766
- stateAttributesMapping: stateAttributesMapping$1,
746
+ stateAttributesMapping: stateAttributesMapping$3,
767
747
  props: [{
768
748
  role: 'presentation',
769
749
  'aria-hidden': true,
@@ -823,15 +803,6 @@ const KEYBOARD_VISIBILITY_MARGIN = 16;
823
803
  // keyboard overlap, so the field can be scrolled clear of the keyboard instead of
824
804
  // ending up flush against it. Only applied when there is actual overlap.
825
805
  const KEYBOARD_SCROLL_SLACK = 48;
826
- // Cadence of the settle-watching realign passes after focus moves with the keyboard open:
827
- // long enough for a smooth scroll to show progress between passes, short enough to recover
828
- // quickly from a scroll canceled by WebKit's reveal; the pass count covers CSS transitions
829
- // reacting to the focus change (e.g. a 260ms footer resize) with room to spare.
830
- const KEYBOARD_REALIGN_INTERVAL = 150;
831
- const KEYBOARD_REALIGN_MAX_PASSES = 4;
832
- // Frames the alignment waits for the scroll destination to stop moving (layout reacting to
833
- // the focus change, e.g. a footer resizing over a CSS transition) before scrolling anyway.
834
- const KEYBOARD_SETTLE_FRAME_LIMIT = 60;
835
806
  const INPUT_TAP_MOVE_THRESHOLD = 10;
836
807
  const INPUT_TAP_HIT_SLOP = 16;
837
808
  const KEYBOARD_INPUT_TYPES = new Set(['email', 'number', 'password', 'search', 'tel', 'text', 'url']);
@@ -855,10 +826,11 @@ function DrawerVirtualKeyboardProvider(props) {
855
826
  const {
856
827
  children
857
828
  } = props;
858
- const store = useDialogRootContext();
829
+ const {
830
+ store
831
+ } = useDialogRootContext();
859
832
  const open = store.useState('open');
860
833
  const mounted = store.useState('mounted');
861
- const modal = store.useState('modal');
862
834
  const nestedOpenDialogCount = store.useState('nestedOpenDialogCount');
863
835
  const viewportElement = store.useState('viewportElement');
864
836
 
@@ -871,9 +843,7 @@ function DrawerVirtualKeyboardProvider(props) {
871
843
  const keyboardTouchStartRef = React.useRef(null);
872
844
  const focusedKeyboardTargetRef = React.useRef(null);
873
845
  const keyboardScrollAdjustmentRef = React.useRef(null);
874
- const programmaticKeyboardFocusRef = React.useRef(false);
875
846
  const keyboardFocusFrame = useAnimationFrame();
876
- const keyboardRealignTimeout = useTimeout();
877
847
  const restoreKeyboardScrollAdjustment = useStableCallback(() => {
878
848
  const adjustment = keyboardScrollAdjustmentRef.current;
879
849
  if (!adjustment) {
@@ -941,100 +911,46 @@ function DrawerVirtualKeyboardProvider(props) {
941
911
  const doc = ownerDocument(rootElement);
942
912
  const win = getWindow(rootElement);
943
913
  const visualViewport = win.visualViewport;
944
-
945
- // Alignment scroll bookkeeping: destination stability, whether a scroll was issued,
946
- // and the last observed progress so delayed passes can distinguish moving from stalled.
947
- let keyboardScrollElement = null;
948
- let keyboardScrollDestination = 0;
949
- let keyboardScrollChecks = 0;
950
- let keyboardScrollObserved = -1;
951
914
  const setDrawerKeyboardInset = inset => {
952
915
  rootElement.style.setProperty(DrawerViewportCssVars.keyboardInset, `${Math.max(0, Math.ceil(inset))}px`);
953
916
  };
917
+ const resetDrawerKeyboardInset = () => {
918
+ setDrawerKeyboardInset(0);
919
+ };
954
920
  const clearFocusedKeyboardTarget = () => {
955
921
  focusedKeyboardTargetRef.current = null;
956
- keyboardScrollElement = null;
957
- setDrawerKeyboardInset(0);
922
+ resetDrawerKeyboardInset();
958
923
  restoreKeyboardScrollAdjustment();
959
924
  keyboardFocusFrame.cancel();
960
- keyboardRealignTimeout.clear();
961
- };
962
-
963
- // WebKit's native reveal scroll can move the page even while the scroll lock hides
964
- // overflow (e.g. when the software keyboard's previous/next field arrows move focus).
965
- // While the drawer is modal, any window scroll during keyboard interaction is spurious,
966
- // so pin the page to the position it had when the drawer opened.
967
- const baseScrollX = win.scrollX;
968
- const baseScrollY = win.scrollY;
969
- const restoreWindowScroll = () => {
970
- if (modal !== true || nestedDrawerOpen || !focusedKeyboardTargetRef.current || getKeyboardVisualViewport(win) == null) {
971
- return false;
972
- }
973
- if (win.scrollX !== baseScrollX || win.scrollY !== baseScrollY) {
974
- // Force an instant jump: the two-argument form defaults `behavior` to `auto`, which
975
- // obeys the page's `scroll-behavior`, so a global `scroll-behavior: smooth` would
976
- // animate the restore. The measurements that follow assume the page is already back
977
- // at rest, and a smooth restore also re-emits `scroll`, re-entering this handler.
978
- win.scrollTo({
979
- left: baseScrollX,
980
- top: baseScrollY,
981
- behavior: 'instant'
982
- });
983
- return true;
984
- }
985
- return false;
986
- };
987
-
988
- // Focus moved by the drawer itself goes through `focusKeyboardInputWithoutPageScroll`,
989
- // but native focus changes (the iOS keyboard's previous/next field arrows) commit
990
- // WebKit's reveal scroll before `focusin` reaches us — cancelling it afterwards
991
- // visibly jitters the sheet. `focusout` on the outgoing field fires before focus
992
- // lands, so override the incoming field's geometry there and restore it in `focusin`.
993
- let restorePreemptedFocus = null;
994
- const consumePreemptedFocus = () => {
995
- restorePreemptedFocus?.();
996
- restorePreemptedFocus = null;
997
- };
998
- const preemptFocusReveal = (target, keyboardViewport) => {
999
- consumePreemptedFocus();
1000
-
1001
- // Native focus carries no preventScroll, so a fake off-screen rect would make WebKit
1002
- // scroll the drawer's own scroll containers thousands of pixels chasing it. Presenting
1003
- // the field as already centered in the visible band above the keyboard instead makes
1004
- // both the in-page reveal and the viewport pan no-ops.
1005
- const rect = target.getBoundingClientRect();
1006
- restorePreemptedFocus = overrideGeometryDuringFocus(target, (keyboardViewport.top + keyboardViewport.bottom - rect.top - rect.bottom) / 2);
1007
925
  };
1008
926
  const alignFocusedKeyboardTarget = () => {
1009
- // If focus never lands on a preempted target, the focusout-scheduled alignment still
1010
- // restores it on the next frame before paint.
1011
- consumePreemptedFocus();
1012
927
  const target = focusedKeyboardTargetRef.current;
1013
928
  // If the focused field is removed from the DOM without firing `focusout` (e.g. it is
1014
929
  // conditionally rendered away), any applied scroll slack is restored here on the next
1015
930
  // focus/viewport event or when the drawer closes. This self-corrects rather than
1016
931
  // tracking each field's lifecycle.
1017
932
  if (nestedDrawerOpen || !target || !contains(rootElement, target)) {
1018
- setDrawerKeyboardInset(0);
933
+ resetDrawerKeyboardInset();
1019
934
  restoreKeyboardScrollAdjustment();
1020
935
  return;
1021
936
  }
1022
-
1023
- // Undo any reveal scroll WebKit applied to the locked page before measuring, so the
1024
- // keyboard inset and alignment are computed against the resting viewport.
1025
- restoreWindowScroll();
1026
937
  const keyboardViewport = getKeyboardVisualViewport(win);
1027
938
  if (!keyboardViewport) {
1028
- setDrawerKeyboardInset(0);
939
+ resetDrawerKeyboardInset();
1029
940
  restoreKeyboardScrollAdjustment();
1030
941
  return;
1031
942
  }
1032
- setDrawerKeyboardInset(Math.max(0, win.innerHeight - keyboardViewport.bottom));
943
+ setDrawerKeyboardInset(getDrawerKeyboardInset(win, keyboardViewport));
1033
944
  const scrollTarget = findKeyboardScrollTarget(target, rootElement);
1034
945
  if (!scrollTarget) {
1035
946
  restoreKeyboardScrollAdjustment();
1036
947
  return;
1037
948
  }
949
+ if (!scrollTarget.isConnected || !contains(rootElement, scrollTarget)) {
950
+ resetDrawerKeyboardInset();
951
+ restoreKeyboardScrollAdjustment();
952
+ return;
953
+ }
1038
954
  const scrollTargetRect = scrollTarget.getBoundingClientRect();
1039
955
  const clippedBottom = Math.min(scrollTargetRect.bottom, keyboardViewport.bottom);
1040
956
  const overlap = Math.max(0, scrollTargetRect.bottom - keyboardViewport.bottom);
@@ -1050,70 +966,14 @@ function DrawerVirtualKeyboardProvider(props) {
1050
966
  return;
1051
967
  }
1052
968
  const targetRect = target.getBoundingClientRect();
1053
- const nextScrollTop = scrollTarget.scrollTop + (targetRect.top + targetRect.bottom - visibleTop - visibleBottom) / 2;
1054
- const destination = Math.round(clamp(nextScrollTop, 0, maxScrollTop));
1055
- const settled = keyboardScrollElement === scrollTarget && Math.abs(keyboardScrollDestination - destination) <= 1;
1056
- if (!settled) {
1057
- // Commit the scroll only once the destination holds across two consecutive checks.
1058
- // Layout may still be reacting to the focus change (e.g. a footer sized by
1059
- // `:focus-within` resizing over a transition), and scrolling toward a
1060
- // mid-transition destination overshoots, then visibly pulls back once corrected.
1061
- // The destination is scroll-position-invariant, so an in-flight scroll of the
1062
- // container itself never defers the commit.
1063
- const checks = keyboardScrollElement === scrollTarget ? keyboardScrollChecks + 1 : 1;
1064
- keyboardScrollElement = scrollTarget;
1065
- keyboardScrollDestination = destination;
1066
- keyboardScrollChecks = checks;
1067
- keyboardScrollObserved = -1;
1068
- // Re-check next frame; give up and scroll anyway if layout never settles.
1069
- if (checks <= KEYBOARD_SETTLE_FRAME_LIMIT) {
1070
- keyboardFocusFrame.request(alignFocusedKeyboardTarget);
1071
- return;
1072
- }
1073
- } else if (keyboardScrollObserved >= 0) {
1074
- // A scroll toward this destination is already out. Leave it alone while it has
1075
- // arrived or is still progressing — re-issuing restarts the smooth-scroll easing
1076
- // curve, a visible stutter on every realign pass — and re-issue only when it
1077
- // stalled short (WebKit cancels in-flight smooth scrolls when its native reveal
1078
- // for the focus resolves).
1079
- const current = scrollTarget.scrollTop;
1080
- if (Math.abs(current - destination) <= 1) {
1081
- return;
1082
- }
1083
- if (current !== keyboardScrollObserved) {
1084
- keyboardScrollObserved = current;
1085
- return;
1086
- }
1087
- }
1088
- keyboardScrollElement = scrollTarget;
1089
- keyboardScrollDestination = destination;
1090
- keyboardScrollChecks = 0;
1091
- keyboardScrollObserved = scrollTarget.scrollTop;
1092
- animateKeyboardScroll(scrollTarget, destination);
969
+ const targetCenter = (targetRect.top + targetRect.bottom) / 2;
970
+ const visibleCenter = (visibleTop + visibleBottom) / 2;
971
+ const nextScrollTop = scrollTarget.scrollTop + targetCenter - visibleCenter;
972
+ animateKeyboardScroll(scrollTarget, clamp(nextScrollTop, 0, maxScrollTop));
1093
973
  };
1094
974
  const scheduleKeyboardFocusAlignment = () => {
1095
975
  keyboardFocusFrame.request(alignFocusedKeyboardTarget);
1096
976
  };
1097
-
1098
- // When focus moves with the keyboard already up, no viewport resize events follow to
1099
- // re-run alignment, and the single frame-scheduled pass is unreliable: WebKit resolves
1100
- // the reveal for the focus asynchronously (a UI-process round trip) and cancels any
1101
- // in-flight scroll the pass started when it lands, and layout reacting to the focus
1102
- // change (e.g. a footer sized by `:focus-within` and the keyboard inset) settles only
1103
- // after its transition, so the pass measures stale geometry. Re-align on an interval
1104
- // until both settle; the alignment's scroll bookkeeping observes before re-issuing,
1105
- // so passes that find the scroll on course are inert.
1106
- const scheduleDelayedKeyboardRealign = () => {
1107
- let remainingPasses = KEYBOARD_REALIGN_MAX_PASSES;
1108
- const realign = () => {
1109
- alignFocusedKeyboardTarget();
1110
- remainingPasses -= 1;
1111
- if (remainingPasses > 0) {
1112
- keyboardRealignTimeout.start(KEYBOARD_REALIGN_INTERVAL, realign);
1113
- }
1114
- };
1115
- keyboardRealignTimeout.start(KEYBOARD_REALIGN_INTERVAL, realign);
1116
- };
1117
977
  const captureFocusedKeyboardTarget = eventTarget => {
1118
978
  if (nestedDrawerOpen) {
1119
979
  return false;
@@ -1125,56 +985,16 @@ function DrawerVirtualKeyboardProvider(props) {
1125
985
  if (!target || !contains(rootElement, target)) {
1126
986
  return false;
1127
987
  }
1128
-
1129
- // A new field starts a fresh alignment; the scroll bookkeeping must not carry
1130
- // over from the previous field's scroll.
1131
- if (focusedKeyboardTargetRef.current !== target) {
1132
- keyboardScrollElement = null;
1133
- }
1134
988
  focusedKeyboardTargetRef.current = target;
1135
989
  return true;
1136
990
  };
1137
991
  const handleFocusIn = event => {
1138
- // The programmatic transition is over once focus lands, which happens before
1139
- // `.focus()` returns. Any later `focusout` is the consumer's own — an `onFocus`
1140
- // handler that blurs or moves focus — and must be reconciled rather than
1141
- // suppressed, so stop suppressing here instead of waiting for `.focus()` to return.
1142
- programmaticKeyboardFocusRef.current = false;
1143
- consumePreemptedFocus();
1144
- if (!captureFocusedKeyboardTarget(getTarget(event))) {
1145
- // Focus landed outside any drawer keyboard input. The `focusout` on the previous
1146
- // field normally clears the tracked target, but the tap path suppresses that
1147
- // `focusout` via `programmaticKeyboardFocusRef`, so a consumer `onFocus` handler that
1148
- // redirects focus out of the drawer would otherwise leave a stale target holding its
1149
- // inset, slack, and pending realign. Reconcile against the real focus here.
1150
- // A handler that ends focus entirely emits no `focusin` to reconcile from; that case
1151
- // is covered by clearing the suppression flag above so its `focusout` is handled.
1152
- clearFocusedKeyboardTarget();
1153
- return;
1154
- }
1155
-
1156
- // Covers every way focus can land with the keyboard already up: native moves (the
1157
- // keyboard's previous/next arrows) and the tap path (which suppresses `focusout`
1158
- // handling via the programmatic flag).
1159
- if (getKeyboardVisualViewport(win) != null) {
1160
- scheduleDelayedKeyboardRealign();
992
+ if (captureFocusedKeyboardTarget(getTarget(event))) {
993
+ scheduleKeyboardFocusAlignment();
1161
994
  }
1162
- scheduleKeyboardFocusAlignment();
1163
995
  };
1164
996
  const handleFocusOut = event => {
1165
- // The blur inside `focusKeyboardInputWithoutPageScroll` is followed synchronously by
1166
- // a re-focus; clearing state here would drop the keyboard inset for a frame.
1167
- if (programmaticKeyboardFocusRef.current) {
1168
- return;
1169
- }
1170
997
  if (captureFocusedKeyboardTarget(event.relatedTarget)) {
1171
- const target = focusedKeyboardTargetRef.current;
1172
- const keyboardViewport = getKeyboardVisualViewport(win);
1173
- // The delayed realign passes are scheduled by the `focusin` that follows once
1174
- // focus lands on the captured target.
1175
- if (target && keyboardViewport) {
1176
- preemptFocusReveal(target, keyboardViewport);
1177
- }
1178
998
  scheduleKeyboardFocusAlignment();
1179
999
  return;
1180
1000
  }
@@ -1189,36 +1009,25 @@ function DrawerVirtualKeyboardProvider(props) {
1189
1009
  if (visualViewport) {
1190
1010
  cleanupListeners.push(addEventListener(visualViewport, 'resize', handleViewportUpdate), addEventListener(visualViewport, 'scroll', handleViewportUpdate));
1191
1011
  }
1192
- const handleWindowScroll = () => {
1193
- if (restoreWindowScroll()) {
1194
- // Recompute the keyboard inset once the page is back at rest; measurements taken
1195
- // mid-reveal (a non-zero visual viewport offset) inflate it and push the popup up.
1196
- scheduleKeyboardFocusAlignment();
1197
- }
1198
- };
1199
-
1200
- // Once the user puts a finger down they own the scroll position. Stop both the frame settle
1201
- // loop, which can center after changing layout settles, and the delayed passes, which can't
1202
- // distinguish a user scroll from a reveal scroll WebKit canceled. A later focus or viewport
1203
- // change reschedules alignment if it's still needed.
1204
- const cancelKeyboardRealignOnPointerDown = () => {
1205
- keyboardFocusFrame.cancel();
1206
- keyboardRealignTimeout.clear();
1207
- keyboardScrollElement = null;
1208
- };
1209
- cleanupListeners.push(addEventListener(doc, 'focusin', handleFocusIn, true), addEventListener(doc, 'focusout', handleFocusOut, true), addEventListener(win, 'scroll', handleWindowScroll), addEventListener(doc, 'pointerdown', cancelKeyboardRealignOnPointerDown, true));
1012
+ cleanupListeners.push(addEventListener(doc, 'focusin', handleFocusIn, true), addEventListener(doc, 'focusout', handleFocusOut, true));
1210
1013
  if (captureFocusedKeyboardTarget(activeElement(doc))) {
1211
1014
  scheduleKeyboardFocusAlignment();
1212
1015
  }
1213
1016
  return () => {
1214
1017
  cleanupListeners.forEach(cleanup => cleanup());
1215
- consumePreemptedFocus();
1216
1018
  clearFocusedKeyboardTarget();
1217
1019
  rootElement.style.removeProperty(DrawerViewportCssVars.keyboardInset);
1218
1020
  };
1219
- }, [animateKeyboardScroll, keyboardFocusFrame, keyboardRealignTimeout, modal, mounted, nestedDrawerOpen, open, restoreKeyboardScrollAdjustment, rootElement, setKeyboardScrollSlack]);
1021
+ }, [animateKeyboardScroll, keyboardFocusFrame, mounted, nestedDrawerOpen, open, restoreKeyboardScrollAdjustment, rootElement, setKeyboardScrollSlack]);
1220
1022
  const onTouchStart = useStableCallback(event => {
1023
+ if (!open || !mounted || nestedDrawerOpen) {
1024
+ resetTouchTrackingState();
1025
+ return;
1026
+ }
1221
1027
  const touch = event.touches[0];
1028
+ if (!touch) {
1029
+ return;
1030
+ }
1222
1031
  pendingKeyboardFocusMovedRef.current = false;
1223
1032
  keyboardTouchStartRef.current = {
1224
1033
  x: touch.clientX,
@@ -1244,9 +1053,9 @@ function DrawerVirtualKeyboardProvider(props) {
1244
1053
  return;
1245
1054
  }
1246
1055
  const touch = event.changedTouches[0] ?? event.touches[0];
1247
- const root = rootElement.getRootNode();
1056
+ const doc = ownerDocument(event.currentTarget);
1248
1057
  const nativeEventTarget = getTarget(event.nativeEvent);
1249
- const pointTarget = touch ? resolveKeyboardTouchTargetFromPoint(root, touch.clientX, touch.clientY) : null;
1058
+ const pointTarget = touch ? resolveKeyboardTouchTargetFromPoint(doc, touch.clientX, touch.clientY) : null;
1250
1059
 
1251
1060
  // The lift point landed on another interactive/label element; let its native tap
1252
1061
  // through instead of stealing it for the touchstart input.
@@ -1275,24 +1084,15 @@ function DrawerVirtualKeyboardProvider(props) {
1275
1084
 
1276
1085
  // Already focused with the keyboard up: let the native tap through so it can
1277
1086
  // reposition the caret, rather than blurring and re-focusing the same input.
1278
- if (activeElement(ownerDocument(keyboardFocusTarget)) === keyboardFocusTarget && (!win.visualViewport || getKeyboardVisualViewport(win) != null)) {
1087
+ if (activeElement(ownerDocument(keyboardFocusTarget)) === keyboardFocusTarget && isKeyboardVisualViewportOpen(win)) {
1279
1088
  resetTouchTrackingState();
1280
1089
  return;
1281
1090
  }
1282
1091
 
1283
1092
  // iOS only opens the software keyboard when focus happens synchronously
1284
- // inside the touch gesture. The flag suppresses the `focusout` cleanup the
1285
- // intermediate blur would otherwise trigger, so the keyboard inset isn't
1286
- // dropped for a frame between the blur and the re-focus. It is cleared by the
1287
- // `focusin` that lands, so only that blur is suppressed; the `finally` is the
1288
- // backstop for a target that never takes focus.
1093
+ // inside the touch gesture.
1289
1094
  event.preventDefault();
1290
- programmaticKeyboardFocusRef.current = true;
1291
- try {
1292
- focusKeyboardInputWithoutPageScroll(keyboardFocusTarget);
1293
- } finally {
1294
- programmaticKeyboardFocusRef.current = false;
1295
- }
1095
+ focusKeyboardInputWithoutPageScroll(keyboardFocusTarget);
1296
1096
  // Preventing the touchend default also suppresses the compatibility mouse
1297
1097
  // events, including `click`; redispatch an untrusted replacement on the
1298
1098
  // original tap target so click handlers still run with the tap coordinates.
@@ -1337,16 +1137,13 @@ function resolveKeyboardInputTarget(target) {
1337
1137
  return isHTMLElement(control) && isKeyboardInputElement(control) ? control : null;
1338
1138
  }
1339
1139
  function resolveKeyboardTouchTarget(target) {
1340
- if (!isHTMLElement(target)) {
1341
- return null;
1342
- }
1343
1140
  const focusTarget = resolveKeyboardInputTarget(target);
1344
1141
  if (!focusTarget) {
1345
1142
  return null;
1346
1143
  }
1347
1144
  return {
1348
1145
  focusTarget,
1349
- clickTarget: target
1146
+ clickTarget: isHTMLElement(target) ? target : focusTarget
1350
1147
  };
1351
1148
  }
1352
1149
 
@@ -1359,16 +1156,14 @@ function getContentEditableHost(element) {
1359
1156
  }
1360
1157
  return host;
1361
1158
  }
1362
- function resolveKeyboardTouchTargetFromPoint(root, clientX, clientY) {
1363
- const exactTarget = getElementAtPoint(root, clientX, clientY);
1364
- if (isHTMLElement(exactTarget)) {
1365
- const exactKeyboardTarget = resolveKeyboardInputTarget(exactTarget);
1366
- if (exactKeyboardTarget) {
1367
- return {
1368
- focusTarget: exactKeyboardTarget,
1369
- clickTarget: exactTarget
1370
- };
1371
- }
1159
+ function resolveKeyboardTouchTargetFromPoint(doc, clientX, clientY) {
1160
+ const exactTarget = getElementAtPoint(doc, clientX, clientY);
1161
+ const exactKeyboardTarget = resolveKeyboardInputTarget(exactTarget);
1162
+ if (exactKeyboardTarget) {
1163
+ return {
1164
+ focusTarget: exactKeyboardTarget,
1165
+ clickTarget: isHTMLElement(exactTarget) ? exactTarget : exactKeyboardTarget
1166
+ };
1372
1167
  }
1373
1168
 
1374
1169
  // Probing nearby points compensates for iOS retargeting taps while the page reacts
@@ -1381,7 +1176,7 @@ function resolveKeyboardTouchTargetFromPoint(root, clientX, clientY) {
1381
1176
  return KEYBOARD_TAP_BLOCKED;
1382
1177
  }
1383
1178
  for (const [offsetX, offsetY] of [[0, INPUT_TAP_HIT_SLOP], [0, -INPUT_TAP_HIT_SLOP], [INPUT_TAP_HIT_SLOP, 0], [-INPUT_TAP_HIT_SLOP, 0]]) {
1384
- const keyboardTarget = resolveKeyboardInputTarget(getElementAtPoint(root, clientX + offsetX, clientY + offsetY));
1179
+ const keyboardTarget = resolveKeyboardInputTarget(getElementAtPoint(doc, clientX + offsetX, clientY + offsetY));
1385
1180
  if (keyboardTarget) {
1386
1181
  return {
1387
1182
  focusTarget: keyboardTarget,
@@ -1405,10 +1200,15 @@ function dispatchKeyboardClick(target, touch) {
1405
1200
  }
1406
1201
  function focusKeyboardInputWithoutPageScroll(target) {
1407
1202
  const wasFocused = activeElement(ownerDocument(target)) === target;
1203
+ const previousOpacity = target.style.opacity;
1204
+ const previousTransform = target.style.transform;
1205
+ const previousTransition = target.style.transition;
1206
+
1408
1207
  // iOS Safari can still scroll the page for transformed sheets even with preventScroll.
1409
- // Move the input off-screen only for the synchronous focus call; `preventScroll`
1410
- // suppresses the in-page ancestor scrolling that would otherwise chase the fake rect.
1411
- const restoreStyles = overrideGeometryDuringFocus(target, -2000);
1208
+ // Move the input off-screen only for the synchronous focus call.
1209
+ target.style.transition = 'none';
1210
+ target.style.opacity = '0';
1211
+ target.style.transform = 'translateY(-2000px)';
1412
1212
  try {
1413
1213
  if (wasFocused) {
1414
1214
  target.blur();
@@ -1417,25 +1217,10 @@ function focusKeyboardInputWithoutPageScroll(target) {
1417
1217
  preventScroll: true
1418
1218
  });
1419
1219
  } finally {
1420
- restoreStyles();
1421
- }
1422
- }
1423
-
1424
- // Overrides the painted geometry WebKit samples when an element gains focus. The rect is
1425
- // hidden (opacity) rather than detached so layout is unaffected; the caller must restore
1426
- // synchronously before the next paint.
1427
- function overrideGeometryDuringFocus(target, translateY) {
1428
- const previousOpacity = target.style.opacity;
1429
- const previousTransform = target.style.transform;
1430
- const previousTransition = target.style.transition;
1431
- target.style.transition = 'none';
1432
- target.style.opacity = '0';
1433
- target.style.transform = `translateY(${translateY}px)`;
1434
- return () => {
1435
1220
  target.style.opacity = previousOpacity;
1436
1221
  target.style.transform = previousTransform;
1437
1222
  target.style.transition = previousTransition;
1438
- };
1223
+ }
1439
1224
  }
1440
1225
  function findKeyboardScrollTarget(target, root) {
1441
1226
  // Start at the parent: scrolling the focused field's own content (an overflowing
@@ -1463,22 +1248,11 @@ function getKeyboardVisualViewport(win) {
1463
1248
  bottom: Math.min(win.innerHeight, top + visualViewport.height)
1464
1249
  };
1465
1250
  }
1466
-
1467
- /**
1468
- * Controls a Drawer imperatively and associates detached `Drawer.Trigger` components with a
1469
- * `Drawer.Root`. Create one with `Drawer.createHandle()` and pass it to the `handle` prop of the
1470
- * root and of any triggers rendered outside of it.
1471
- *
1472
- * The imperative methods take effect only while a root using this handle is mounted; calls made
1473
- * before a root attaches (or after it unmounts) are ignored.
1474
- */
1475
- class DrawerHandle extends DialogHandle {}
1476
-
1477
- /**
1478
- * Creates a new handle to connect a Drawer.Root with detached Drawer.Trigger components.
1479
- */
1480
- function createDrawerHandle() {
1481
- return new DrawerHandle();
1251
+ function getDrawerKeyboardInset(win, keyboardViewport) {
1252
+ return Math.max(0, win.innerHeight - keyboardViewport.bottom);
1253
+ }
1254
+ function isKeyboardVisualViewportOpen(win) {
1255
+ return !win.visualViewport || getKeyboardVisualViewport(win) != null;
1482
1256
  }
1483
1257
 
1484
1258
  var index_parts$5 = /*#__PURE__*/Object.freeze({
@@ -1487,7 +1261,7 @@ var index_parts$5 = /*#__PURE__*/Object.freeze({
1487
1261
  Close: DrawerClose,
1488
1262
  Content: DrawerContent,
1489
1263
  Description: DrawerDescription,
1490
- Handle: DrawerHandle,
1264
+ Handle: DialogHandle,
1491
1265
  Indent: DrawerIndent,
1492
1266
  IndentBackground: DrawerIndentBackground,
1493
1267
  Popup: DrawerPopup,
@@ -1499,7 +1273,7 @@ var index_parts$5 = /*#__PURE__*/Object.freeze({
1499
1273
  Trigger: DrawerTrigger,
1500
1274
  Viewport: DrawerViewport,
1501
1275
  VirtualKeyboardProvider: DrawerVirtualKeyboardProvider,
1502
- createHandle: createDrawerHandle
1276
+ createHandle: createDialogHandle
1503
1277
  });
1504
1278
 
1505
1279
  /**
@@ -1568,7 +1342,7 @@ const MenuCheckboxItem = /*#__PURE__*/React.forwardRef(function MenuCheckboxItem
1568
1342
  id: idProp,
1569
1343
  label,
1570
1344
  nativeButton = false,
1571
- disabled: disabledProp = false,
1345
+ disabled = false,
1572
1346
  closeOnClick = false,
1573
1347
  checked: checkedProp,
1574
1348
  defaultChecked,
@@ -1577,7 +1351,6 @@ const MenuCheckboxItem = /*#__PURE__*/React.forwardRef(function MenuCheckboxItem
1577
1351
  ...elementProps
1578
1352
  } = componentProps;
1579
1353
  const listItem = useCompositeListItem({
1580
- guess: true,
1581
1354
  label
1582
1355
  });
1583
1356
  const menuPositionerContext = useMenuPositionerContext(true);
@@ -1585,8 +1358,6 @@ const MenuCheckboxItem = /*#__PURE__*/React.forwardRef(function MenuCheckboxItem
1585
1358
  const {
1586
1359
  store
1587
1360
  } = useMenuRootContext();
1588
- const rootDisabled = store.useState('disabled');
1589
- const disabled = disabledProp || rootDisabled;
1590
1361
  const highlighted = store.useState('isActive', listItem.index);
1591
1362
  const itemProps = store.useState('itemProps');
1592
1363
  const [checked, setChecked] = useControlled({
@@ -1615,7 +1386,7 @@ const MenuCheckboxItem = /*#__PURE__*/React.forwardRef(function MenuCheckboxItem
1615
1386
  }), [disabled, highlighted, checked]);
1616
1387
  function handleClick(event) {
1617
1388
  const details = createChangeEventDetails(itemPress, event.nativeEvent, undefined, {
1618
- preventUnmountOnClose: NOOP
1389
+ preventUnmountOnClose() {}
1619
1390
  });
1620
1391
  onCheckedChange?.(!checked, details);
1621
1392
  if (details.isCanceled) {
@@ -1658,7 +1429,6 @@ const MenuCheckboxItemIndicator = /*#__PURE__*/React.forwardRef(function MenuChe
1658
1429
  const indicatorRef = React.useRef(null);
1659
1430
  const {
1660
1431
  transitionStatus,
1661
- mounted,
1662
1432
  setMounted
1663
1433
  } = useTransitionStatus(item.checked);
1664
1434
  useOpenChangeComplete({
@@ -1684,7 +1454,7 @@ const MenuCheckboxItemIndicator = /*#__PURE__*/React.forwardRef(function MenuChe
1684
1454
  'aria-hidden': true,
1685
1455
  ...elementProps
1686
1456
  },
1687
- enabled: keepMounted || mounted
1457
+ enabled: keepMounted || item.checked
1688
1458
  });
1689
1459
  return element;
1690
1460
  });
@@ -1724,14 +1494,30 @@ function usePopupAutoResize(parameters) {
1724
1494
  side,
1725
1495
  direction
1726
1496
  } = parameters;
1727
- const runOnceAnimationsFinish = useAnimationsFinished(popupElement, true);
1497
+ const runOnceAnimationsFinish = useAnimationsFinished(popupElement, true, false);
1728
1498
  const animationFrame = useAnimationFrame();
1729
1499
  const committedDimensionsRef = React.useRef(null);
1730
1500
  const isInitialRenderRef = React.useRef(true);
1731
1501
  const restoreAnchoringStylesRef = React.useRef(NOOP);
1732
1502
  const onMeasureLayout = useStableCallback(onMeasureLayoutParam);
1733
1503
  const onMeasureLayoutComplete = useStableCallback(onMeasureLayoutCompleteParam);
1734
- const anchoringStyles = React.useMemo(() => getPopupAnchoringStyles(side, direction), [side, direction]);
1504
+ const anchoringStyles = React.useMemo(() => {
1505
+ // Ensure popup size transitions correctly when anchored to `bottom` (side=top) or `right` (side=left).
1506
+ let isOriginSide = side === 'top';
1507
+ let isPhysicalLeft = side === 'left';
1508
+ if (direction === 'rtl') {
1509
+ isOriginSide = isOriginSide || side === 'inline-end';
1510
+ isPhysicalLeft = isPhysicalLeft || side === 'inline-end';
1511
+ } else {
1512
+ isOriginSide = isOriginSide || side === 'inline-start';
1513
+ isPhysicalLeft = isPhysicalLeft || side === 'inline-start';
1514
+ }
1515
+ return isOriginSide ? {
1516
+ position: 'absolute',
1517
+ [side === 'top' ? 'bottom' : 'top']: '0',
1518
+ [isPhysicalLeft ? 'right' : 'left']: '0'
1519
+ } : EMPTY_OBJECT;
1520
+ }, [side, direction]);
1735
1521
  useIsoLayoutEffect(() => {
1736
1522
  // Reset the state when the popup is closed.
1737
1523
  if (!mounted) {
@@ -1807,19 +1593,6 @@ function usePopupAutoResize(parameters) {
1807
1593
  };
1808
1594
  }, [content, popupElement, positionerElement, runOnceAnimationsFinish, animationFrame, mounted, onMeasureLayout, onMeasureLayoutComplete, anchoringStyles]);
1809
1595
  }
1810
- function getPopupAnchoringStyles(side, direction) {
1811
- // Ensure popup size transitions correctly when anchored to `bottom` (side=top) or `right` (side=left).
1812
- const isPhysicalTop = side === 'top';
1813
- const isPhysicalLeft = side === 'left' || side === (direction === 'rtl' ? 'inline-end' : 'inline-start');
1814
- if (!isPhysicalTop && !isPhysicalLeft) {
1815
- return EMPTY_OBJECT;
1816
- }
1817
- return {
1818
- position: 'absolute',
1819
- [isPhysicalTop ? 'bottom' : 'top']: '0',
1820
- [isPhysicalLeft ? 'right' : 'left']: '0'
1821
- };
1822
- }
1823
1596
  function overrideElementStyle(element, property, value) {
1824
1597
  const originalValue = element.style.getPropertyValue(property);
1825
1598
  element.style.setProperty(property, value);
@@ -1849,80 +1622,6 @@ function setPositionerCssSize(positionerElement, size) {
1849
1622
  positionerElement.style.setProperty('--positioner-height', height);
1850
1623
  }
1851
1624
 
1852
- const adaptiveOrigin = {
1853
- name: 'adaptiveOrigin',
1854
- async fn(state) {
1855
- const {
1856
- x: rawX,
1857
- y: rawY,
1858
- rects: {
1859
- floating: floatRect
1860
- },
1861
- elements: {
1862
- floating
1863
- },
1864
- platform,
1865
- strategy,
1866
- placement
1867
- } = state;
1868
- const win = getWindow(floating);
1869
- const styles = win.getComputedStyle(floating);
1870
- const hasTransition = styles.transitionDuration !== '0s' && styles.transitionDuration !== '';
1871
- if (!hasTransition) {
1872
- return {
1873
- x: rawX,
1874
- y: rawY,
1875
- data: DEFAULT_SIDES
1876
- };
1877
- }
1878
- const offsetParent = await platform.getOffsetParent?.(floating);
1879
- let offsetDimensions = {
1880
- width: 0,
1881
- height: 0
1882
- };
1883
-
1884
- // For fixed strategy, prefer visualViewport if available
1885
- if (strategy === 'fixed' && win?.visualViewport) {
1886
- offsetDimensions = {
1887
- width: win.visualViewport.width,
1888
- height: win.visualViewport.height
1889
- };
1890
- } else if (offsetParent === win) {
1891
- const doc = ownerDocument(floating);
1892
- offsetDimensions = {
1893
- width: doc.documentElement.clientWidth,
1894
- height: doc.documentElement.clientHeight
1895
- };
1896
- } else if (await platform.isElement?.(offsetParent)) {
1897
- offsetDimensions = await platform.getDimensions(offsetParent);
1898
- }
1899
- const currentSide = getSide(placement);
1900
- let x = rawX;
1901
- let y = rawY;
1902
- if (currentSide === 'left') {
1903
- x = offsetDimensions.width - (rawX + floatRect.width);
1904
- }
1905
- if (currentSide === 'top') {
1906
- y = offsetDimensions.height - (rawY + floatRect.height);
1907
- }
1908
- const sideX = currentSide === 'left' ? 'right' : DEFAULT_SIDES.sideX;
1909
- const sideY = currentSide === 'top' ? 'bottom' : DEFAULT_SIDES.sideY;
1910
- return {
1911
- x,
1912
- y,
1913
- data: {
1914
- sideX,
1915
- sideY
1916
- }
1917
- };
1918
- }
1919
- };
1920
-
1921
- const popupViewportStateMapping = {
1922
- activationDirection: value => value ? {
1923
- 'data-activation-direction': value
1924
- } : null
1925
- };
1926
1625
  /**
1927
1626
  * Builds morphing viewport containers for popups that animate between trigger-based content.
1928
1627
  * Handles previous-content snapshots, auto-resize, and state attributes for transitions.
@@ -1931,6 +1630,7 @@ function usePopupViewport(parameters) {
1931
1630
  const {
1932
1631
  store,
1933
1632
  side,
1633
+ cssVars,
1934
1634
  children
1935
1635
  } = parameters;
1936
1636
  const direction = useDirection();
@@ -1950,15 +1650,14 @@ function usePopupViewport(parameters) {
1950
1650
  const [newTriggerOffset, setNewTriggerOffset] = React.useState(null);
1951
1651
  const currentContainerRef = React.useRef(null);
1952
1652
  const previousContainerRef = React.useRef(null);
1953
- const onAnimationsFinished = useAnimationsFinished(currentContainerRef, true);
1653
+ const onAnimationsFinished = useAnimationsFinished(currentContainerRef, true, false);
1954
1654
  const cleanupFrame = useAnimationFrame();
1955
- const cleanupControllerRef = React.useRef(null);
1956
1655
  const [previousContentDimensions, setPreviousContentDimensions] = React.useState(null);
1957
1656
  const [showStartingStyleAttribute, setShowStartingStyleAttribute] = React.useState(false);
1958
1657
  useIsoLayoutEffect(() => {
1959
- store.set('adaptiveOrigin', adaptiveOrigin);
1658
+ store.set('hasViewport', true);
1960
1659
  return () => {
1961
- store.set('adaptiveOrigin', undefined);
1660
+ store.set('hasViewport', false);
1962
1661
  };
1963
1662
  }, [store]);
1964
1663
  const handleMeasureLayout = useStableCallback(() => {
@@ -1974,16 +1673,6 @@ function usePopupViewport(parameters) {
1974
1673
  setPreviousContentDimensions(previousDimensions);
1975
1674
  }
1976
1675
  });
1977
- const armViewportCleanup = useStableCallback(() => {
1978
- cleanupControllerRef.current?.abort();
1979
- const controller = new AbortController();
1980
- cleanupControllerRef.current = controller;
1981
- onAnimationsFinished(() => {
1982
- setPreviousContentNode(null);
1983
- setPreviousContentDimensions(null);
1984
- capturedNodeRef.current = null;
1985
- }, controller.signal);
1986
- });
1987
1676
  const lastHandledTriggerRef = React.useRef(null);
1988
1677
  useIsoLayoutEffect(() => {
1989
1678
  if (!open || !mounted) {
@@ -2001,33 +1690,19 @@ function usePopupViewport(parameters) {
2001
1690
  // so we can pass it to the style hook for animation purposes.
2002
1691
  const offset = calculateRelativePosition(previousActiveTrigger, activeTrigger);
2003
1692
  setNewTriggerOffset(offset);
1693
+ cleanupFrame.request(() => {
1694
+ ReactDOM.flushSync(() => {
1695
+ setShowStartingStyleAttribute(false);
1696
+ });
1697
+ onAnimationsFinished(() => {
1698
+ setPreviousContentNode(null);
1699
+ setPreviousContentDimensions(null);
1700
+ capturedNodeRef.current = null;
1701
+ });
1702
+ });
2004
1703
  lastHandledTriggerRef.current = activeTrigger;
2005
1704
  }
2006
- }, [activeTrigger, previousActiveTrigger]);
2007
-
2008
- // Arm cleanup after a trigger change, and re-arm it if the current container remounts
2009
- // mid-transition when a lagging payload bumps `currentContentKey`. The remount discards
2010
- // the running entry animation (and with transition-style CSS the replacement mounts at
2011
- // final styles with no animation at all), so re-run the starting-style choreography —
2012
- // otherwise the watcher either strands or fires before the previous container's exit
2013
- // animation finishes.
2014
- useIsoLayoutEffect(() => {
2015
- if (previousContentNode == null) {
2016
- return;
2017
- }
2018
-
2019
- // Abort the stale watcher synchronously. The remount cancels the old container's
2020
- // animations, and the resulting promise rejection would otherwise run the cleanup
2021
- // in a microtask before the re-armed watcher below is in place.
2022
- cleanupControllerRef.current?.abort();
2023
- setShowStartingStyleAttribute(true);
2024
- cleanupFrame.request(() => {
2025
- ReactDOM.flushSync(() => {
2026
- setShowStartingStyleAttribute(false);
2027
- });
2028
- armViewportCleanup();
2029
- });
2030
- }, [currentContentKey, previousContentNode, armViewportCleanup, cleanupFrame]);
1705
+ }, [activeTrigger, previousActiveTrigger, previousContentNode, onAnimationsFinished, cleanupFrame]);
2031
1706
 
2032
1707
  // Capture a clone of the current content DOM subtree when not transitioning.
2033
1708
  // We can't store previous React nodes as they may be stateful; instead we capture DOM clones for visual continuity.
@@ -2064,8 +1739,8 @@ function usePopupViewport(parameters) {
2064
1739
  ref: previousContainerRef,
2065
1740
  style: {
2066
1741
  ...(previousContentDimensions ? {
2067
- '--popup-width': `${previousContentDimensions.width}px`,
2068
- '--popup-height': `${previousContentDimensions.height}px`
1742
+ [cssVars.popupWidth]: `${previousContentDimensions.width}px`,
1743
+ [cssVars.popupHeight]: `${previousContentDimensions.height}px`
2069
1744
  } : null),
2070
1745
  position: 'absolute'
2071
1746
  },
@@ -2190,6 +1865,28 @@ function usePopupContentKey(activeTriggerId, payload) {
2190
1865
  return `${activeTriggerId ?? 'current'}-${contentKey}`;
2191
1866
  }
2192
1867
 
1868
+ let MenuViewportCssVars = /*#__PURE__*/function (MenuViewportCssVars) {
1869
+ /**
1870
+ * The width of the parent popup.
1871
+ * This variable is placed on the 'previous' container and stores the width of the popup when the previous content was rendered.
1872
+ * It can be used to freeze the dimensions of the popup when animating between different content.
1873
+ */
1874
+ MenuViewportCssVars["popupWidth"] = "--popup-width";
1875
+ /**
1876
+ * The height of the parent popup.
1877
+ * This variable is placed on the 'previous' container and stores the height of the popup when the previous content was rendered.
1878
+ * It can be used to freeze the dimensions of the popup when animating between different content.
1879
+ */
1880
+ MenuViewportCssVars["popupHeight"] = "--popup-height";
1881
+ return MenuViewportCssVars;
1882
+ }({});
1883
+
1884
+ const stateAttributesMapping$2 = {
1885
+ activationDirection: value => value ? {
1886
+ 'data-activation-direction': value
1887
+ } : null
1888
+ };
1889
+
2193
1890
  /**
2194
1891
  * A viewport for displaying content transitions.
2195
1892
  * This component is only required if one popup can be opened by multiple triggers, its content
@@ -2219,6 +1916,7 @@ const MenuViewport = /*#__PURE__*/React.forwardRef(function MenuViewport(compone
2219
1916
  } = usePopupViewport({
2220
1917
  store,
2221
1918
  side,
1919
+ cssVars: MenuViewportCssVars,
2222
1920
  children
2223
1921
  });
2224
1922
  const state = {
@@ -2232,50 +1930,47 @@ const MenuViewport = /*#__PURE__*/React.forwardRef(function MenuViewport(compone
2232
1930
  props: [elementProps, {
2233
1931
  children: childrenToRender
2234
1932
  }],
2235
- stateAttributesMapping: popupViewportStateMapping
1933
+ stateAttributesMapping: stateAttributesMapping$2
2236
1934
  });
2237
1935
  });
2238
1936
  if (process.env.NODE_ENV !== "production") MenuViewport.displayName = "MenuViewport";
2239
1937
 
2240
- /**
2241
- * Controls a Menu imperatively and associates detached `Menu.Trigger` components with a `Menu.Root`.
2242
- * Create one with `Menu.createHandle()` and pass it to the `handle` prop of the root and of any
2243
- * triggers rendered outside of it.
2244
- *
2245
- * The imperative methods take effect only while a root using this handle is mounted; calls made
2246
- * before a root attaches (or after it unmounts) are ignored.
2247
- */
2248
- class MenuHandle extends BasePopupHandle {
1938
+ class MenuHandle {
1939
+ /**
1940
+ * Internal store holding the menu's state.
1941
+ * @internal
1942
+ */
1943
+
2249
1944
  constructor() {
2250
- super(createNullMenuStore(), 'Menu');
1945
+ this.store = new MenuStore();
2251
1946
  }
2252
1947
 
2253
1948
  /**
2254
1949
  * Opens the menu and associates it with the trigger with the given id.
1950
+ * The trigger must be a Menu.Trigger component with this handle passed as a prop.
2255
1951
  *
2256
- * This method should only be called in an event handler or an effect (not during rendering).
2257
- *
2258
- * @param triggerId ID of the trigger to associate with the menu. The trigger must be a matching
2259
- * `Menu.Trigger` with this handle passed as a prop.
1952
+ * @param triggerId ID of the trigger to associate with the menu.
2260
1953
  */
2261
1954
  open(triggerId) {
2262
- this.openByTrigger(triggerId);
1955
+ const triggerElement = triggerId ? this.store.context.triggerElements.getById(triggerId) : undefined;
1956
+ if (triggerId && !triggerElement) {
1957
+ throw new Error(process.env.NODE_ENV !== "production" ? `Base UI: MenuHandle.open: No trigger found with id "${triggerId}".` : formatErrorMessage(83, triggerId));
1958
+ }
1959
+ this.store.setOpen(true, createChangeEventDetails('imperative-action', undefined, triggerElement));
2263
1960
  }
2264
1961
 
2265
1962
  /**
2266
1963
  * Closes the menu.
2267
- *
2268
- * This method should only be called in an event handler or an effect (not during rendering).
2269
1964
  */
2270
1965
  close() {
2271
- this.closePopup();
1966
+ this.store.setOpen(false, createChangeEventDetails('imperative-action', undefined, undefined));
2272
1967
  }
2273
1968
 
2274
1969
  /**
2275
- * Whether the menu is currently open. Returns `false` while no root is attached to the handle.
1970
+ * Indicates whether the menu is currently open.
2276
1971
  */
2277
1972
  get isOpen() {
2278
- return this.attachedStore?.select('open') ?? false;
1973
+ return this.store.select('open');
2279
1974
  }
2280
1975
  }
2281
1976
 
@@ -2322,6 +2017,20 @@ function useScrollAreaScrollbarContext() {
2322
2017
  return context;
2323
2018
  }
2324
2019
 
2020
+ let ScrollAreaScrollbarCssVars = /*#__PURE__*/function (ScrollAreaScrollbarCssVars) {
2021
+ /**
2022
+ * The scroll area thumb's height.
2023
+ * @type {number}
2024
+ */
2025
+ ScrollAreaScrollbarCssVars["scrollAreaThumbHeight"] = "--scroll-area-thumb-height";
2026
+ /**
2027
+ * The scroll area thumb's width.
2028
+ * @type {number}
2029
+ */
2030
+ ScrollAreaScrollbarCssVars["scrollAreaThumbWidth"] = "--scroll-area-thumb-width";
2031
+ return ScrollAreaScrollbarCssVars;
2032
+ }({});
2033
+
2325
2034
  /**
2326
2035
  * A vertical or horizontal scrollbar for the scroll area.
2327
2036
  * Renders a `<div>` element.
@@ -2342,6 +2051,7 @@ const ScrollAreaScrollbar = /*#__PURE__*/React.forwardRef(function ScrollAreaScr
2342
2051
  scrollingX,
2343
2052
  scrollingY,
2344
2053
  hiddenState,
2054
+ overflowEdges,
2345
2055
  scrollbarYRef,
2346
2056
  scrollbarXRef,
2347
2057
  viewportRef,
@@ -2350,37 +2060,43 @@ const ScrollAreaScrollbar = /*#__PURE__*/React.forwardRef(function ScrollAreaScr
2350
2060
  handlePointerDown,
2351
2061
  handlePointerUp,
2352
2062
  handleScroll,
2353
- disableViewportSnap,
2354
2063
  rootId,
2355
2064
  thumbSize,
2356
- hasMeasuredScrollbar,
2357
- viewportState
2065
+ hasMeasuredScrollbar
2358
2066
  } = useScrollAreaRootContext();
2359
- const vertical = orientation === 'vertical';
2360
2067
  const state = {
2361
- ...viewportState,
2362
2068
  hovering,
2363
- scrolling: vertical ? scrollingY : scrollingX,
2364
- orientation
2069
+ scrolling: {
2070
+ horizontal: scrollingX,
2071
+ vertical: scrollingY
2072
+ }[orientation],
2073
+ orientation,
2074
+ hasOverflowX: !hiddenState.x,
2075
+ hasOverflowY: !hiddenState.y,
2076
+ overflowXStart: overflowEdges.xStart,
2077
+ overflowXEnd: overflowEdges.xEnd,
2078
+ overflowYStart: overflowEdges.yStart,
2079
+ overflowYEnd: overflowEdges.yEnd,
2080
+ cornerHidden: hiddenState.corner
2365
2081
  };
2366
2082
  const direction = useDirection();
2367
2083
  const hideTrackUntilMeasured = !hasMeasuredScrollbar && !keepMounted;
2368
- const isHidden = vertical ? hiddenState.y : hiddenState.x;
2084
+ const isHidden = orientation === 'vertical' ? hiddenState.y : hiddenState.x;
2369
2085
  const shouldRender = keepMounted || !isHidden;
2370
2086
  React.useEffect(() => {
2371
2087
  if (!shouldRender) {
2372
2088
  return undefined;
2373
2089
  }
2374
2090
  const viewportEl = viewportRef.current;
2375
- const scrollbarEl = vertical ? scrollbarYRef.current : scrollbarXRef.current;
2091
+ const scrollbarEl = orientation === 'vertical' ? scrollbarYRef.current : scrollbarXRef.current;
2376
2092
  if (!scrollbarEl) {
2377
2093
  return undefined;
2378
2094
  }
2379
2095
  function handleWheel(event) {
2380
- if (!viewportEl || event.ctrlKey) {
2096
+ if (!viewportEl || !scrollbarEl || event.ctrlKey) {
2381
2097
  return;
2382
2098
  }
2383
- const horizontal = !vertical;
2099
+ const horizontal = orientation === 'horizontal';
2384
2100
  const scrollProperty = horizontal ? 'scrollLeft' : 'scrollTop';
2385
2101
  const delta = horizontal ? event.deltaX : event.deltaY;
2386
2102
  if (delta === 0) {
@@ -2407,7 +2123,7 @@ const ScrollAreaScrollbar = /*#__PURE__*/React.forwardRef(function ScrollAreaScr
2407
2123
  return addEventListener(scrollbarEl, 'wheel', handleWheel, {
2408
2124
  passive: false
2409
2125
  });
2410
- }, [direction, handleScroll, vertical, scrollbarXRef, scrollbarYRef, shouldRender, viewportRef]);
2126
+ }, [direction, handleScroll, orientation, scrollbarXRef, scrollbarYRef, shouldRender, viewportRef]);
2411
2127
  const props = {
2412
2128
  ...(rootId && {
2413
2129
  'data-id': `${rootId}-scrollbar`
@@ -2417,55 +2133,58 @@ const ScrollAreaScrollbar = /*#__PURE__*/React.forwardRef(function ScrollAreaScr
2417
2133
  return;
2418
2134
  }
2419
2135
  const target = getTarget(event.nativeEvent);
2420
- const thumbEl = vertical ? thumbYRef.current : thumbXRef.current;
2136
+ const thumb = orientation === 'vertical' ? thumbYRef.current : thumbXRef.current;
2421
2137
 
2422
2138
  // Ignore clicks on thumb, including cases where React retargets the
2423
2139
  // synthetic event to the track host across a shadow boundary.
2424
- if (thumbEl && contains(thumbEl, target)) {
2425
- return;
2426
- }
2427
- const viewportEl = viewportRef.current;
2428
- if (!viewportEl) {
2429
- return;
2430
- }
2431
- const scrollbarEl = vertical ? scrollbarYRef.current : scrollbarXRef.current;
2432
- if (!thumbEl || !scrollbarEl) {
2140
+ if (thumb && contains(thumb, target)) {
2433
2141
  return;
2434
2142
  }
2435
- const axis = vertical ? 'y' : 'x';
2436
- const thumbOffset = getOffset(thumbEl, 'margin', axis);
2437
- const scrollbarOffset = getOffset(scrollbarEl, 'padding', axis);
2438
- const thumbSizePx = vertical ? thumbEl.offsetHeight : thumbEl.offsetWidth;
2439
- const trackRect = scrollbarEl.getBoundingClientRect();
2440
- const clickPosition = vertical ? event.clientY - trackRect.top - thumbSizePx / 2 - scrollbarOffset + thumbOffset / 2 : event.clientX - trackRect.left - thumbSizePx / 2 - scrollbarOffset + thumbOffset / 2;
2441
- const scrollableSize = vertical ? viewportEl.scrollHeight : viewportEl.scrollWidth;
2442
- const viewportSize = vertical ? viewportEl.clientHeight : viewportEl.clientWidth;
2443
- const trackSize = vertical ? scrollbarEl.offsetHeight : scrollbarEl.offsetWidth;
2444
- const maxThumbOffset = trackSize - thumbSizePx - scrollbarOffset - thumbOffset;
2445
- // A short or heavily padded track can drive `maxThumbOffset` to zero or
2446
- // negative once the thumb hits its `MIN_THUMB_SIZE` floor. Dividing by it
2447
- // would yield a non-finite (`Infinity`/`NaN`) or inverted scroll position.
2448
- if (maxThumbOffset <= 0) {
2143
+ if (!viewportRef.current) {
2449
2144
  return;
2450
2145
  }
2451
- const scrollRatio = clickPosition / maxThumbOffset;
2452
- const maxScrollDistance = scrollableSize - viewportSize;
2453
-
2454
- // Disable snapping before the jump-to-click assignment, or the
2455
- // assigned position quantizes to the nearest snap point and the thumb
2456
- // stays offset from the pointer for the whole drag. `handlePointerDown`
2457
- // below re-runs this as a guarded no-op for the thumb-drag path.
2458
- disableViewportSnap();
2459
- if (vertical) {
2460
- viewportEl.scrollTop = scrollRatio * maxScrollDistance;
2461
- } else if (direction === 'rtl') {
2462
- viewportEl.scrollLeft = -(1 - scrollRatio) * maxScrollDistance;
2463
- } else {
2464
- viewportEl.scrollLeft = scrollRatio * maxScrollDistance;
2146
+
2147
+ // Handle Y-axis (vertical) scroll
2148
+ if (thumbYRef.current && scrollbarYRef.current && orientation === 'vertical') {
2149
+ const thumbYOffset = getOffset(thumbYRef.current, 'margin', 'y');
2150
+ const scrollbarYOffset = getOffset(scrollbarYRef.current, 'padding', 'y');
2151
+ const thumbHeight = thumbYRef.current.offsetHeight;
2152
+ const trackRectY = scrollbarYRef.current.getBoundingClientRect();
2153
+ const clickY = event.clientY - trackRectY.top - thumbHeight / 2 - scrollbarYOffset + thumbYOffset / 2;
2154
+ const scrollableContentHeight = viewportRef.current.scrollHeight;
2155
+ const viewportHeight = viewportRef.current.clientHeight;
2156
+ const maxThumbOffsetY = scrollbarYRef.current.offsetHeight - thumbHeight - scrollbarYOffset - thumbYOffset;
2157
+ const scrollRatioY = clickY / maxThumbOffsetY;
2158
+ const newScrollTop = scrollRatioY * (scrollableContentHeight - viewportHeight);
2159
+ viewportRef.current.scrollTop = newScrollTop;
2160
+ }
2161
+ if (thumbXRef.current && scrollbarXRef.current && orientation === 'horizontal') {
2162
+ const thumbXOffset = getOffset(thumbXRef.current, 'margin', 'x');
2163
+ const scrollbarXOffset = getOffset(scrollbarXRef.current, 'padding', 'x');
2164
+ const thumbWidth = thumbXRef.current.offsetWidth;
2165
+ const trackRectX = scrollbarXRef.current.getBoundingClientRect();
2166
+ const clickX = event.clientX - trackRectX.left - thumbWidth / 2 - scrollbarXOffset + thumbXOffset / 2;
2167
+ const scrollableContentWidth = viewportRef.current.scrollWidth;
2168
+ const viewportWidth = viewportRef.current.clientWidth;
2169
+ const maxThumbOffsetX = scrollbarXRef.current.offsetWidth - thumbWidth - scrollbarXOffset - thumbXOffset;
2170
+ const scrollRatioX = clickX / maxThumbOffsetX;
2171
+ let newScrollLeft;
2172
+ if (direction === 'rtl') {
2173
+ // In RTL, invert the scroll direction
2174
+ newScrollLeft = (1 - scrollRatioX) * (scrollableContentWidth - viewportWidth);
2175
+
2176
+ // Adjust for browsers that use negative scrollLeft in RTL
2177
+ if (viewportRef.current.scrollLeft <= 0) {
2178
+ newScrollLeft = -newScrollLeft;
2179
+ }
2180
+ } else {
2181
+ newScrollLeft = scrollRatioX * (scrollableContentWidth - viewportWidth);
2182
+ }
2183
+ viewportRef.current.scrollLeft = newScrollLeft;
2465
2184
  }
2466
2185
  handleScroll({
2467
- x: viewportEl.scrollLeft,
2468
- y: viewportEl.scrollTop
2186
+ x: viewportRef.current.scrollLeft,
2187
+ y: viewportRef.current.scrollTop
2469
2188
  });
2470
2189
  handlePointerDown(event);
2471
2190
  },
@@ -2479,30 +2198,34 @@ const ScrollAreaScrollbar = /*#__PURE__*/React.forwardRef(function ScrollAreaScr
2479
2198
  WebkitUserSelect: 'none',
2480
2199
  userSelect: 'none',
2481
2200
  visibility: hideTrackUntilMeasured ? 'hidden' : undefined,
2482
- ...(vertical ? {
2201
+ ...(orientation === 'vertical' && {
2483
2202
  top: 0,
2484
- bottom: 'var(--scroll-area-corner-height)',
2203
+ bottom: `var(${ScrollAreaRootCssVars.scrollAreaCornerHeight})`,
2485
2204
  insetInlineEnd: 0,
2486
- ['--scroll-area-thumb-height']: `${thumbSize.height}px`
2487
- } : {
2205
+ [ScrollAreaScrollbarCssVars.scrollAreaThumbHeight]: `${thumbSize.height}px`
2206
+ }),
2207
+ ...(orientation === 'horizontal' && {
2488
2208
  insetInlineStart: 0,
2489
- insetInlineEnd: 'var(--scroll-area-corner-width)',
2209
+ insetInlineEnd: `var(${ScrollAreaRootCssVars.scrollAreaCornerWidth})`,
2490
2210
  bottom: 0,
2491
- ['--scroll-area-thumb-width']: `${thumbSize.width}px`
2211
+ [ScrollAreaScrollbarCssVars.scrollAreaThumbWidth]: `${thumbSize.width}px`
2492
2212
  })
2493
2213
  }
2494
2214
  };
2495
2215
  const element = useRenderElement('div', componentProps, {
2496
- ref: [forwardedRef, vertical ? scrollbarYRef : scrollbarXRef],
2216
+ ref: [forwardedRef, orientation === 'vertical' ? scrollbarYRef : scrollbarXRef],
2497
2217
  state,
2498
2218
  props: [props, elementProps],
2499
2219
  stateAttributesMapping: scrollAreaStateAttributesMapping
2500
2220
  });
2221
+ const contextValue = React.useMemo(() => ({
2222
+ orientation
2223
+ }), [orientation]);
2501
2224
  if (!shouldRender) {
2502
2225
  return null;
2503
2226
  }
2504
2227
  return /*#__PURE__*/jsx(ScrollAreaScrollbarContext.Provider, {
2505
- value: orientation,
2228
+ value: contextValue,
2506
2229
  children: element
2507
2230
  });
2508
2231
  });
@@ -2590,30 +2313,43 @@ const ScrollAreaThumb = /*#__PURE__*/React.forwardRef(function ScrollAreaThumb(c
2590
2313
  handlePointerDown,
2591
2314
  handlePointerMove,
2592
2315
  handlePointerUp,
2316
+ setScrollingX,
2317
+ setScrollingY,
2593
2318
  scrollingX,
2594
2319
  scrollingY,
2595
2320
  hasMeasuredScrollbar
2596
2321
  } = useScrollAreaRootContext();
2597
- const orientation = useScrollAreaScrollbarContext();
2598
- const vertical = orientation === 'vertical';
2322
+ const {
2323
+ orientation
2324
+ } = useScrollAreaScrollbarContext();
2599
2325
  const state = {
2600
- scrolling: vertical ? scrollingY : scrollingX,
2326
+ scrolling: orientation === 'horizontal' ? scrollingX : scrollingY,
2601
2327
  orientation
2602
2328
  };
2329
+ function endDrag(event) {
2330
+ if (orientation === 'vertical') {
2331
+ setScrollingY(false);
2332
+ }
2333
+ if (orientation === 'horizontal') {
2334
+ setScrollingX(false);
2335
+ }
2336
+ handlePointerUp(event);
2337
+ }
2603
2338
  const element = useRenderElement('div', componentProps, {
2604
- ref: [forwardedRef, vertical ? thumbYRef : thumbXRef],
2339
+ ref: [forwardedRef, orientation === 'vertical' ? thumbYRef : thumbXRef],
2605
2340
  state,
2606
2341
  props: [{
2607
2342
  onPointerDown: handlePointerDown,
2608
2343
  onPointerMove: handlePointerMove,
2609
- onPointerUp: handlePointerUp,
2610
- onPointerCancel: handlePointerUp,
2344
+ onPointerUp: endDrag,
2345
+ onPointerCancel: endDrag,
2611
2346
  style: {
2612
2347
  visibility: hasMeasuredScrollbar ? undefined : 'hidden',
2613
- ...(vertical ? {
2614
- height: 'var(--scroll-area-thumb-height)'
2615
- } : {
2616
- width: 'var(--scroll-area-thumb-width)'
2348
+ ...(orientation === 'vertical' && {
2349
+ height: `var(${ScrollAreaScrollbarCssVars.scrollAreaThumbHeight})`
2350
+ }),
2351
+ ...(orientation === 'horizontal' && {
2352
+ width: `var(${ScrollAreaScrollbarCssVars.scrollAreaThumbWidth})`
2617
2353
  })
2618
2354
  }
2619
2355
  }, elementProps]
@@ -2693,7 +2429,7 @@ var index_parts$2 = /*#__PURE__*/Object.freeze({
2693
2429
  Positioner: ComboboxPositioner,
2694
2430
  Root: ComboboxRoot,
2695
2431
  Row: ComboboxRow,
2696
- Separator: ComboboxSeparator,
2432
+ Separator: Separator,
2697
2433
  Status: ComboboxStatus,
2698
2434
  Trigger: ComboboxTrigger,
2699
2435
  Value: ComboboxValue,
@@ -2740,6 +2476,22 @@ function getViewportRect(teleportDistance, scrubAreaEl) {
2740
2476
  };
2741
2477
  }
2742
2478
 
2479
+ // This lets us invert the scale of the cursor to match the OS scale, in which the cursor doesn't
2480
+ // scale with the content on pinch-zoom.
2481
+ function subscribeToVisualViewportResize(element, visualScaleRef) {
2482
+ const vV = getWindow(element).visualViewport;
2483
+ if (!vV) {
2484
+ return () => {};
2485
+ }
2486
+ function handleVisualResize() {
2487
+ if (vV) {
2488
+ visualScaleRef.current = vV.scale;
2489
+ }
2490
+ }
2491
+ handleVisualResize();
2492
+ return addEventListener(vV, 'resize', handleVisualResize);
2493
+ }
2494
+
2743
2495
  const SCRUB_AREA_STYLE = {
2744
2496
  touchAction: 'none',
2745
2497
  WebkitUserSelect: 'none',
@@ -2765,6 +2517,8 @@ const NumberFieldScrubArea = /*#__PURE__*/React.forwardRef(function NumberFieldS
2765
2517
  const {
2766
2518
  state,
2767
2519
  setIsScrubbing: setRootScrubbing,
2520
+ disabled,
2521
+ readOnly,
2768
2522
  inputRef,
2769
2523
  incrementValue,
2770
2524
  allowInputSyncRef,
@@ -2773,10 +2527,6 @@ const NumberFieldScrubArea = /*#__PURE__*/React.forwardRef(function NumberFieldS
2773
2527
  lastChangedValueRef,
2774
2528
  valueRef
2775
2529
  } = useNumberFieldRootContext();
2776
- const {
2777
- disabled,
2778
- readOnly
2779
- } = state;
2780
2530
  const scrubAreaRef = React.useRef(null);
2781
2531
  const isScrubbingRef = React.useRef(false);
2782
2532
  const didMoveRef = React.useRef(false);
@@ -2786,15 +2536,21 @@ const NumberFieldScrubArea = /*#__PURE__*/React.forwardRef(function NumberFieldS
2786
2536
  x: 0,
2787
2537
  y: 0
2788
2538
  });
2539
+ const visualScaleRef = React.useRef(1);
2789
2540
  const exitPointerLockTimeout = useTimeout();
2790
2541
  const [isTouchInput, setIsTouchInput] = React.useState(false);
2791
2542
  const [isPointerLockDenied, setIsPointerLockDenied] = React.useState(false);
2792
2543
  const [isScrubbing, setIsScrubbing] = React.useState(false);
2793
- function updateCursorTransform(virtualCursor, x, y) {
2794
- // Invert the visual viewport scale so the cursor matches the OS cursor, which doesn't
2795
- // scale with the content on pinch-zoom.
2796
- const scale = getWindow(virtualCursor).visualViewport?.scale ?? 1;
2797
- virtualCursor.style.transform = `translate3d(${x}px,${y}px,0) scale(${1 / scale})`;
2544
+ React.useEffect(() => {
2545
+ if (!isScrubbing || !scrubAreaCursorRef.current) {
2546
+ return undefined;
2547
+ }
2548
+ return subscribeToVisualViewportResize(scrubAreaCursorRef.current, visualScaleRef);
2549
+ }, [isScrubbing]);
2550
+ function updateCursorTransform(x, y) {
2551
+ if (scrubAreaCursorRef.current) {
2552
+ scrubAreaCursorRef.current.style.transform = `translate3d(${x}px,${y}px,0) scale(${1 / visualScaleRef.current})`;
2553
+ }
2798
2554
  }
2799
2555
  const onScrub = useStableCallback(({
2800
2556
  movementX,
@@ -2807,23 +2563,24 @@ const NumberFieldScrubArea = /*#__PURE__*/React.forwardRef(function NumberFieldS
2807
2563
  }
2808
2564
  const rect = getViewportRect(teleportDistance, scrubAreaEl);
2809
2565
  const coords = virtualCursorCoords.current;
2810
-
2811
- // Wrap the cursor to the opposite edge when its center crosses a viewport bound.
2812
- const wrap = (coord, halfSize, low, high) => {
2813
- if (coord + halfSize < low) {
2814
- return high - halfSize;
2815
- }
2816
- if (coord + halfSize > high) {
2817
- return low - halfSize;
2818
- }
2819
- return coord;
2820
- };
2821
2566
  const newCoords = {
2822
- x: wrap(Math.round(coords.x + movementX), virtualCursor.offsetWidth / 2, rect.left, rect.right),
2823
- y: wrap(Math.round(coords.y + movementY), virtualCursor.offsetHeight / 2, rect.top, rect.bottom)
2567
+ x: Math.round(coords.x + movementX),
2568
+ y: Math.round(coords.y + movementY)
2824
2569
  };
2570
+ const cursorWidth = virtualCursor.offsetWidth;
2571
+ const cursorHeight = virtualCursor.offsetHeight;
2572
+ if (newCoords.x + cursorWidth / 2 < rect.left) {
2573
+ newCoords.x = rect.right - cursorWidth / 2;
2574
+ } else if (newCoords.x + cursorWidth / 2 > rect.right) {
2575
+ newCoords.x = rect.left - cursorWidth / 2;
2576
+ }
2577
+ if (newCoords.y + cursorHeight / 2 < rect.top) {
2578
+ newCoords.y = rect.bottom - cursorHeight / 2;
2579
+ } else if (newCoords.y + cursorHeight / 2 > rect.bottom) {
2580
+ newCoords.y = rect.top - cursorHeight / 2;
2581
+ }
2825
2582
  virtualCursorCoords.current = newCoords;
2826
- updateCursorTransform(virtualCursor, newCoords.x, newCoords.y);
2583
+ updateCursorTransform(newCoords.x, newCoords.y);
2827
2584
  });
2828
2585
  const onScrubbingChange = useStableCallback((scrubbingValue, {
2829
2586
  clientX,
@@ -2842,7 +2599,7 @@ const NumberFieldScrubArea = /*#__PURE__*/React.forwardRef(function NumberFieldS
2842
2599
  y: clientY - virtualCursor.offsetHeight / 2
2843
2600
  };
2844
2601
  virtualCursorCoords.current = initialCoords;
2845
- updateCursorTransform(virtualCursor, initialCoords.x, initialCoords.y);
2602
+ updateCursorTransform(initialCoords.x, initialCoords.y);
2846
2603
  });
2847
2604
  React.useEffect(function registerGlobalScrubbingEventListeners() {
2848
2605
  // Only listen while actively scrubbing; avoids unrelated pointerup events committing.
@@ -2884,9 +2641,6 @@ const NumberFieldScrubArea = /*#__PURE__*/React.forwardRef(function NumberFieldS
2884
2641
  }
2885
2642
  }
2886
2643
  function handleScrubPointerMove(event) {
2887
- // The effects below can tear down and re-run without unmounting (`<Activity>`), which
2888
- // clears the ref while `isScrubbing` stays `true` and re-attaches this listener. The ref
2889
- // is the source of truth for whether a pointer is actually down.
2890
2644
  if (!isScrubbingRef.current) {
2891
2645
  return;
2892
2646
  }
@@ -2954,7 +2708,8 @@ const NumberFieldScrubArea = /*#__PURE__*/React.forwardRef(function NumberFieldS
2954
2708
  role: 'presentation',
2955
2709
  style: SCRUB_AREA_STYLE,
2956
2710
  async onPointerDown(event) {
2957
- if (event.defaultPrevented || readOnly || event.button || disabled) {
2711
+ const isMainButton = !event.button || event.button === 0;
2712
+ if (event.defaultPrevented || readOnly || !isMainButton || disabled) {
2958
2713
  return;
2959
2714
  }
2960
2715
  const isTouch = event.pointerType === 'touch';
@@ -2993,7 +2748,7 @@ const NumberFieldScrubArea = /*#__PURE__*/React.forwardRef(function NumberFieldS
2993
2748
  ref: [forwardedRef, scrubAreaRef],
2994
2749
  state,
2995
2750
  props: [defaultProps, elementProps],
2996
- stateAttributesMapping: stateAttributesMapping$4
2751
+ stateAttributesMapping: stateAttributesMapping$6
2997
2752
  });
2998
2753
  const contextValue = React.useMemo(() => ({
2999
2754
  isScrubbing,
@@ -3050,7 +2805,7 @@ const NumberFieldScrubAreaCursor = /*#__PURE__*/React.forwardRef(function Number
3050
2805
  role: 'presentation',
3051
2806
  style: CURSOR_STYLE
3052
2807
  }, elementProps],
3053
- stateAttributesMapping: stateAttributesMapping$4
2808
+ stateAttributesMapping: stateAttributesMapping$6
3054
2809
  });
3055
2810
  return element && /*#__PURE__*/ReactDOM.createPortal(element, ownerDocument(domElement).body);
3056
2811
  });
@@ -3094,8 +2849,7 @@ const SelectLabel = /*#__PURE__*/React.forwardRef(function SelectLabel(component
3094
2849
  id: defaultLabelId,
3095
2850
  fallbackControlId: triggerElement?.id ?? rootId,
3096
2851
  setLabelId(nextLabelId) {
3097
- const resolvedLabelId = typeof nextLabelId === 'function' ? nextLabelId(store.state.labelId) : nextLabelId;
3098
- store.set('labelId', resolvedLabelId);
2852
+ store.set('labelId', nextLabelId);
3099
2853
  }
3100
2854
  });
3101
2855
  return useRenderElement('div', componentProps, {
@@ -3140,7 +2894,7 @@ const SelectIcon = /*#__PURE__*/React.forwardRef(function SelectIcon(componentPr
3140
2894
  });
3141
2895
  if (process.env.NODE_ENV !== "production") SelectIcon.displayName = "SelectIcon";
3142
2896
 
3143
- const stateAttributesMapping = {
2897
+ const stateAttributesMapping$1 = {
3144
2898
  ...popupStateMapping,
3145
2899
  ...transitionStatusMapping
3146
2900
  };
@@ -3179,12 +2933,17 @@ const SelectBackdrop = /*#__PURE__*/React.forwardRef(function SelectBackdrop(com
3179
2933
  WebkitUserSelect: 'none'
3180
2934
  }
3181
2935
  }, elementProps],
3182
- stateAttributesMapping
2936
+ stateAttributesMapping: stateAttributesMapping$1
3183
2937
  });
3184
2938
  return element;
3185
2939
  });
3186
2940
  if (process.env.NODE_ENV !== "production") SelectBackdrop.displayName = "SelectBackdrop";
3187
2941
 
2942
+ const stateAttributesMapping = {
2943
+ ...popupStateMapping,
2944
+ ...transitionStatusMapping
2945
+ };
2946
+
3188
2947
  /**
3189
2948
  * Displays an element positioned against the select popup anchor.
3190
2949
  * Renders a `<div>` element.
@@ -3223,7 +2982,7 @@ const SelectArrow = /*#__PURE__*/React.forwardRef(function SelectArrow(component
3223
2982
  style: arrowStyles,
3224
2983
  'aria-hidden': true
3225
2984
  }, elementProps],
3226
- stateAttributesMapping: popupTransitionStateMapping
2985
+ stateAttributesMapping
3227
2986
  });
3228
2987
  if (alignItemWithTriggerActive) {
3229
2988
  return null;
@@ -3241,7 +3000,7 @@ const SelectScrollArrow = /*#__PURE__*/React.forwardRef(function SelectScrollArr
3241
3000
  className,
3242
3001
  style,
3243
3002
  direction,
3244
- keepMounted,
3003
+ keepMounted = false,
3245
3004
  ...elementProps
3246
3005
  } = componentProps;
3247
3006
  const isUp = direction === 'up';
@@ -3272,10 +3031,12 @@ const SelectScrollArrow = /*#__PURE__*/React.forwardRef(function SelectScrollArr
3272
3031
  } = useTransitionStatus(visible);
3273
3032
  useIsoLayoutEffect(() => {
3274
3033
  scrollArrowsMountedCountRef.current += 1;
3275
- store.set('hasScrollArrows', true);
3034
+ if (!store.state.hasScrollArrows) {
3035
+ store.set('hasScrollArrows', true);
3036
+ }
3276
3037
  return () => {
3277
3038
  scrollArrowsMountedCountRef.current = Math.max(0, scrollArrowsMountedCountRef.current - 1);
3278
- if (scrollArrowsMountedCountRef.current === 0) {
3039
+ if (scrollArrowsMountedCountRef.current === 0 && store.state.hasScrollArrows) {
3279
3040
  store.set('hasScrollArrows', false);
3280
3041
  }
3281
3042
  };
@@ -3312,7 +3073,7 @@ const SelectScrollArrow = /*#__PURE__*/React.forwardRef(function SelectScrollArr
3312
3073
  return;
3313
3074
  }
3314
3075
  store.set('activeIndex', null);
3315
- handleScrollArrowVisibility(scroller);
3076
+ handleScrollArrowVisibility();
3316
3077
  const maxScrollTop = getMaxScrollOffset(scroller.scrollHeight, scroller.clientHeight);
3317
3078
  const scrollTop = normalizeScrollOffset(scroller.scrollTop, maxScrollTop);
3318
3079
  const isScrolledToEdge = scrollTop === (isUp ? 0 : maxScrollTop);
@@ -3320,6 +3081,11 @@ const SelectScrollArrow = /*#__PURE__*/React.forwardRef(function SelectScrollArr
3320
3081
  if (scrollTop !== scroller.scrollTop) {
3321
3082
  scroller.scrollTop = scrollTop;
3322
3083
  }
3084
+
3085
+ // Fallback when there are no items registered yet.
3086
+ if (items.length === 0) {
3087
+ store.set(isUp ? 'scrollUpArrowVisible' : 'scrollDownArrowVisible', !isScrolledToEdge);
3088
+ }
3323
3089
  if (isScrolledToEdge) {
3324
3090
  timeout.clear();
3325
3091
  return;
@@ -3408,14 +3174,6 @@ const SelectScrollUpArrow = /*#__PURE__*/React.forwardRef(function SelectScrollU
3408
3174
  });
3409
3175
  if (process.env.NODE_ENV !== "production") SelectScrollUpArrow.displayName = "SelectScrollUpArrow";
3410
3176
 
3411
- /**
3412
- * A visual separator between items or groups.
3413
- * Renders a `<div>` element.
3414
- *
3415
- * Documentation: [Base UI Select](https://base-ui.com/react/components/select)
3416
- */
3417
- const SelectSeparator = ListboxSeparator;
3418
-
3419
3177
  var index_parts = /*#__PURE__*/Object.freeze({
3420
3178
  __proto__: null,
3421
3179
  Arrow: SelectArrow,
@@ -3434,7 +3192,7 @@ var index_parts = /*#__PURE__*/Object.freeze({
3434
3192
  Root: SelectRoot,
3435
3193
  ScrollDownArrow: SelectScrollDownArrow,
3436
3194
  ScrollUpArrow: SelectScrollUpArrow,
3437
- Separator: SelectSeparator,
3195
+ Separator: Separator,
3438
3196
  Trigger: SelectTrigger,
3439
3197
  Value: SelectValue
3440
3198
  });