@jobber/components 9.4.0 → 9.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/dist/Autocomplete/index.cjs +0 -1
  2. package/dist/Autocomplete/index.mjs +0 -1
  3. package/dist/Card/index.cjs +7 -7
  4. package/dist/Card/index.mjs +7 -7
  5. package/dist/Chip/index.cjs +0 -1
  6. package/dist/Chip/index.mjs +0 -1
  7. package/dist/Chips/InternalChipDismissible/hooks/index.cjs +0 -1
  8. package/dist/Chips/InternalChipDismissible/hooks/index.mjs +0 -1
  9. package/dist/Chips/InternalChipDismissible/index.cjs +0 -1
  10. package/dist/Chips/InternalChipDismissible/index.mjs +0 -1
  11. package/dist/Chips/index.cjs +0 -1
  12. package/dist/Chips/index.mjs +0 -1
  13. package/dist/ComboboxChipRemove-cjs.js +181 -184
  14. package/dist/ComboboxChipRemove-es.js +4 -7
  15. package/dist/ConfirmationModal/index.cjs +0 -1
  16. package/dist/ConfirmationModal/index.mjs +0 -1
  17. package/dist/DataDump/index.cjs +7 -7
  18. package/dist/DataDump/index.mjs +7 -7
  19. package/dist/DataList/components/DataListActions/index.cjs +0 -1
  20. package/dist/DataList/components/DataListActions/index.mjs +0 -1
  21. package/dist/DataList/components/DataListBulkActions/index.cjs +0 -1
  22. package/dist/DataList/components/DataListBulkActions/index.mjs +0 -1
  23. package/dist/DataList/components/DataListFilters/components/DataListSort/index.cjs +0 -1
  24. package/dist/DataList/components/DataListFilters/components/DataListSort/index.mjs +0 -1
  25. package/dist/DataList/components/DataListFilters/index.cjs +0 -1
  26. package/dist/DataList/components/DataListFilters/index.mjs +0 -1
  27. package/dist/DataList/components/DataListHeader/index.cjs +0 -1
  28. package/dist/DataList/components/DataListHeader/index.mjs +0 -1
  29. package/dist/DataList/components/DataListItem/index.cjs +0 -1
  30. package/dist/DataList/components/DataListItem/index.mjs +0 -1
  31. package/dist/DataList/components/DataListItemActions/index.cjs +0 -1
  32. package/dist/DataList/components/DataListItemActions/index.mjs +0 -1
  33. package/dist/DataList/components/DataListItemActionsOverflow/index.cjs +0 -1
  34. package/dist/DataList/components/DataListItemActionsOverflow/index.mjs +0 -1
  35. package/dist/DataList/components/DataListItems/index.cjs +0 -1
  36. package/dist/DataList/components/DataListItems/index.mjs +0 -1
  37. package/dist/DataList/components/DataListLayout/index.cjs +0 -1
  38. package/dist/DataList/components/DataListLayout/index.mjs +0 -1
  39. package/dist/DataList/components/DataListLayoutActions/index.cjs +0 -1
  40. package/dist/DataList/components/DataListLayoutActions/index.mjs +0 -1
  41. package/dist/DataList/index.cjs +0 -1
  42. package/dist/DataList/index.mjs +0 -1
  43. package/dist/DatePicker/index.cjs +0 -2
  44. package/dist/DatePicker/index.mjs +0 -2
  45. package/dist/DatePicker-cjs.js +19 -18
  46. package/dist/DatePicker-es.js +2 -1
  47. package/dist/Dialog/index.cjs +11 -6
  48. package/dist/Dialog/index.mjs +11 -6
  49. package/dist/DrawerDescription-cjs.js +7 -8
  50. package/dist/DrawerDescription-es.js +1 -2
  51. package/dist/DrawerTitle-cjs.js +4 -4
  52. package/dist/DrawerTitle-es.js +1 -1
  53. package/dist/FieldDescription-cjs.js +49 -49
  54. package/dist/FieldDescription-es.js +2 -2
  55. package/dist/FilterPicker/components/FilterPickerActivator/index.cjs +0 -1
  56. package/dist/FilterPicker/components/FilterPickerActivator/index.mjs +0 -1
  57. package/dist/FilterPicker/components/FilterPickerContent/index.cjs +0 -1
  58. package/dist/FilterPicker/components/FilterPickerContent/index.mjs +0 -1
  59. package/dist/FilterPicker/components/FilterPickerTrigger/index.cjs +0 -1
  60. package/dist/FilterPicker/components/FilterPickerTrigger/index.mjs +0 -1
  61. package/dist/FilterPicker/index.cjs +0 -1
  62. package/dist/FilterPicker/index.mjs +0 -1
  63. package/dist/FormatFile/index.cjs +0 -1
  64. package/dist/FormatFile/index.mjs +0 -1
  65. package/dist/Gallery/index.cjs +0 -1
  66. package/dist/Gallery/index.mjs +0 -1
  67. package/dist/HelperText-cjs.js +3 -2
  68. package/dist/HelperText-es.js +3 -2
  69. package/dist/InputDate/index.cjs +0 -2
  70. package/dist/InputDate/index.mjs +0 -2
  71. package/dist/InputNumber/InputNumber.d.ts +75 -5
  72. package/dist/InputNumber/index.cjs +27 -3
  73. package/dist/InputNumber/index.d.ts +2 -2
  74. package/dist/InputNumber/index.mjs +27 -3
  75. package/dist/{primitives/InputNumberExperimental → InputNumber}/types.d.ts +48 -35
  76. package/dist/InputNumber-cjs.js +267 -4986
  77. package/dist/InputNumber-es.js +268 -4987
  78. package/dist/LightBox/index.cjs +0 -1
  79. package/dist/LightBox/index.mjs +0 -1
  80. package/dist/Menu/index.cjs +7 -7
  81. package/dist/Menu/index.mjs +7 -7
  82. package/dist/Menu-cjs.js +4 -1
  83. package/dist/Menu-es.js +4 -1
  84. package/dist/MenuSubmenuTrigger-cjs.js +142 -143
  85. package/dist/MenuSubmenuTrigger-es.js +5 -6
  86. package/dist/Modal/index.cjs +0 -1
  87. package/dist/Modal/index.mjs +0 -1
  88. package/dist/NumberFieldInput-cjs.js +63 -63
  89. package/dist/NumberFieldInput-es.js +5 -5
  90. package/dist/Page/index.cjs +7 -8
  91. package/dist/Page/index.mjs +7 -8
  92. package/dist/Popover/index.cjs +0 -1
  93. package/dist/Popover/index.mjs +0 -1
  94. package/dist/ScrollAreaViewport-cjs.js +119 -121
  95. package/dist/ScrollAreaViewport-es.js +3 -5
  96. package/dist/Select/index.cjs +3 -9
  97. package/dist/Select/index.mjs +3 -9
  98. package/dist/SelectGroupLabel-cjs.js +117 -107
  99. package/dist/SelectGroupLabel-es.js +20 -12
  100. package/dist/Tooltip/index.cjs +0 -1
  101. package/dist/Tooltip/index.mjs +0 -1
  102. package/dist/dialogReturnFocus-cjs.js +4 -1
  103. package/dist/dialogReturnFocus-es.js +4 -1
  104. package/dist/docs/InputNumber/InputNumber.md +564 -56
  105. package/dist/docs/index.md +0 -1
  106. package/dist/floating-ui.react-cjs.js +34 -35
  107. package/dist/floating-ui.react-dom-cjs.js +64 -65
  108. package/dist/floating-ui.react-dom-es.js +1 -2
  109. package/dist/floating-ui.react-es.js +1 -2
  110. package/dist/floating-ui.utils-cjs.js +183 -0
  111. package/dist/floating-ui.utils-es.js +165 -1
  112. package/dist/index.cjs +10 -15
  113. package/dist/index.mjs +10 -15
  114. package/dist/primitives/BottomSheet/index.cjs +2 -5
  115. package/dist/primitives/BottomSheet/index.mjs +2 -5
  116. package/dist/primitives/ComboboxPrimitive/index.cjs +3 -7
  117. package/dist/primitives/ComboboxPrimitive/index.mjs +3 -7
  118. package/dist/primitives/HelperText/HelperText.d.ts +4 -1
  119. package/dist/primitives/HelperText/index.cjs +1 -1
  120. package/dist/primitives/HelperText/index.mjs +1 -1
  121. package/dist/primitives/SelectPrimitive/index.cjs +3 -9
  122. package/dist/primitives/SelectPrimitive/index.mjs +3 -9
  123. package/dist/primitives/index.cjs +2 -16
  124. package/dist/primitives/index.d.ts +0 -2
  125. package/dist/primitives/index.mjs +2 -15
  126. package/dist/scrollEdges-cjs.js +6 -2
  127. package/dist/scrollEdges-es.js +5 -2
  128. package/dist/styles.css +573 -902
  129. package/dist/unstyledPrimitives/index.cjs +105 -111
  130. package/dist/unstyledPrimitives/index.mjs +5 -11
  131. package/dist/useCompositeListItem-cjs.js +516 -90
  132. package/dist/useCompositeListItem-es.js +407 -6
  133. package/dist/useLabel-cjs.js +10 -10
  134. package/dist/useLabel-es.js +3 -3
  135. package/dist/useRenderElement-es.js +1 -1
  136. package/dist/useScrollLock-cjs.js +1332 -203
  137. package/dist/useScrollLock-es.js +1068 -5
  138. package/dist/utils/meta/meta.json +12 -0
  139. package/package.json +2 -3
  140. package/dist/InputNumber/InputNumber.types.d.ts +0 -20
  141. package/dist/InputNumberExperimental-cjs.js +0 -277
  142. package/dist/InputNumberExperimental-es.js +0 -275
  143. package/dist/clamp-cjs.js +0 -7
  144. package/dist/clamp-es.js +0 -5
  145. package/dist/clsx-cjs.js +0 -5
  146. package/dist/clsx-es.js +0 -3
  147. package/dist/docs/InputNumberExperimental/InputNumberExperimental.md +0 -578
  148. package/dist/floating-ui.utils.dom-cjs.js +0 -185
  149. package/dist/floating-ui.utils.dom-es.js +0 -165
  150. package/dist/isElementDisabled-cjs.js +0 -40
  151. package/dist/isElementDisabled-es.js +0 -18
  152. package/dist/primitives/InputNumberExperimental/InputNumberExperimental.d.ts +0 -77
  153. package/dist/primitives/InputNumberExperimental/index.cjs +0 -30
  154. package/dist/primitives/InputNumberExperimental/index.d.ts +0 -2
  155. package/dist/primitives/InputNumberExperimental/index.mjs +0 -24
  156. package/dist/resolveAriaLabelledBy-cjs.js +0 -200
  157. package/dist/resolveAriaLabelledBy-es.js +0 -166
  158. package/dist/useButton-cjs.js +0 -1164
  159. package/dist/useButton-es.js +0 -1071
  160. package/dist/useLabelableId-cjs.js +0 -278
  161. package/dist/useLabelableId-es.js +0 -247
@@ -1,11 +1,9 @@
1
1
  'use strict';
2
2
 
3
3
  var React = require('react');
4
- var floatingUi_utils_dom = require('./floating-ui.utils.dom-cjs.js');
5
- var useButton = require('./useButton-cjs.js');
4
+ var floatingUi_utils = require('./floating-ui.utils-cjs.js');
6
5
  var useRenderElement = require('./useRenderElement-cjs.js');
7
6
  var jsxRuntime = require('react/jsx-runtime');
8
- var floatingUi_utils = require('./floating-ui.utils-cjs.js');
9
7
  var ReactDOM = require('react-dom');
10
8
 
11
9
  function _interopNamespaceDefault(e) {
@@ -28,6 +26,84 @@ function _interopNamespaceDefault(e) {
28
26
  var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
29
27
  var ReactDOM__namespace = /*#__PURE__*/_interopNamespaceDefault(ReactDOM);
30
28
 
29
+ let set;
30
+ if (process.env.NODE_ENV !== 'production') {
31
+ set = new Set();
32
+ }
33
+ function error(...messages) {
34
+ if (process.env.NODE_ENV !== 'production') {
35
+ const messageKey = messages.join(' ');
36
+ if (!set.has(messageKey)) {
37
+ set.add(messageKey);
38
+ console.error(`Base UI: ${messageKey}`);
39
+ }
40
+ }
41
+ }
42
+
43
+ function useControlled({
44
+ controlled,
45
+ default: defaultProp,
46
+ name,
47
+ state = 'value'
48
+ }) {
49
+ // isControlled is ignored in the hook dependency lists as it should never change.
50
+ const {
51
+ current: isControlled
52
+ } = React__namespace.useRef(controlled !== undefined);
53
+ const [valueState, setValue] = React__namespace.useState(defaultProp);
54
+ const value = isControlled ? controlled : valueState;
55
+ if (process.env.NODE_ENV !== 'production') {
56
+ React__namespace.useEffect(() => {
57
+ if (isControlled !== (controlled !== undefined)) {
58
+ error([`A component is changing the ${isControlled ? '' : 'un'}controlled ${state} state of ${name} to be ${isControlled ? 'un' : ''}controlled.`, 'Elements should not switch from uncontrolled to controlled (or vice versa).', `Decide between using a controlled or uncontrolled ${name} ` + 'element for the lifetime of the component.', "The nature of the state is determined during the first render. It's considered controlled if the value is not `undefined`.", 'More info: https://fb.me/react-controlled-components'].join('\n'));
59
+ }
60
+ }, [state, name, controlled]);
61
+ const {
62
+ current: defaultValue
63
+ } = React__namespace.useRef(defaultProp);
64
+ React__namespace.useEffect(() => {
65
+ if (!isControlled && serializeToDevModeString(defaultValue) !== serializeToDevModeString(defaultProp)) {
66
+ error([`A component is changing the default ${state} state of an uncontrolled ${name} after being initialized. ` + `To suppress this warning opt to use a controlled ${name}.`].join('\n'));
67
+ }
68
+ }, [defaultProp]);
69
+ }
70
+ const setValueIfUncontrolled = React__namespace.useCallback(newValue => {
71
+ if (!isControlled) {
72
+ setValue(newValue);
73
+ }
74
+ }, []);
75
+ return [value, setValueIfUncontrolled];
76
+ }
77
+ function serializeToDevModeString(input) {
78
+ let nextId = 0;
79
+ const seen = new WeakMap();
80
+ try {
81
+ const result = JSON.stringify(input, function replacer(key, value) {
82
+ if (key === '_owner' && this != null && typeof this === 'object' && '$$typeof' in this) {
83
+ return undefined;
84
+ }
85
+ if (typeof value === 'bigint') {
86
+ return `__bigint__:${value}`;
87
+ }
88
+ if (value !== null && typeof value === 'object') {
89
+ const id = seen.get(value);
90
+ if (id !== undefined) {
91
+ return `__object__:${id}`;
92
+ }
93
+ seen.set(value, nextId);
94
+ nextId += 1;
95
+ }
96
+ return value;
97
+ });
98
+ return result ?? `__top__:${typeof input}`;
99
+ } catch {
100
+ return '__unserializable__';
101
+ }
102
+ }
103
+
104
+ const noop = () => {};
105
+ const useIsoLayoutEffect = typeof document !== 'undefined' ? React__namespace.useLayoutEffect : noop;
106
+
31
107
  function useOnFirstRender(fn) {
32
108
  const ref = React__namespace.useRef(true);
33
109
  if (ref.current) {
@@ -36,6 +112,104 @@ function useOnFirstRender(fn) {
36
112
  }
37
113
  }
38
114
 
115
+ /**
116
+ * A clone of the React namespace for reading APIs that may be missing in older
117
+ * supported React versions. Bundlers can rewrite direct `React.someNewApi`
118
+ * reads into named imports, which breaks React 17. Reading from this cloned
119
+ * object keeps those lookups optional.
120
+ *
121
+ * @see https://github.com/mui/material-ui/issues/41190#issuecomment-2040873379
122
+ */
123
+ const SafeReact = {
124
+ ...React__namespace
125
+ };
126
+
127
+ const useInsertionEffect = SafeReact.useInsertionEffect;
128
+ const useSafeInsertionEffect =
129
+ // React 17 doesn't have useInsertionEffect.
130
+ useInsertionEffect &&
131
+ // Preact replaces useInsertionEffect with useLayoutEffect and fires too late.
132
+ useInsertionEffect !== SafeReact.useLayoutEffect ? useInsertionEffect : fn => fn();
133
+ /**
134
+ * Stabilizes the function passed so it's always the same between renders.
135
+ *
136
+ * The function becomes non-reactive to any values it captures.
137
+ * It can safely be passed as a dependency of `React.useMemo` and `React.useEffect` without re-triggering them if its captured values change.
138
+ *
139
+ * The function must only be called inside effects and event handlers, never during render (which throws an error).
140
+ *
141
+ * This hook is a more permissive version of React 19.2's `React.useEffectEvent` in that it can be passed through contexts and called in event handler props, not just effects.
142
+ */
143
+ function useStableCallback(callback) {
144
+ const stable = useRenderElement.useRefWithInit(createStableCallback).current;
145
+ stable.next = callback;
146
+ useSafeInsertionEffect(stable.effect);
147
+ return stable.trampoline;
148
+ }
149
+ function createStableCallback() {
150
+ const stable = {
151
+ next: undefined,
152
+ callback: assertNotCalled,
153
+ trampoline: (...args) => stable.callback?.(...args),
154
+ effect: () => {
155
+ stable.callback = stable.next;
156
+ }
157
+ };
158
+ return stable;
159
+ }
160
+ function assertNotCalled() {
161
+ if (process.env.NODE_ENV !== 'production') {
162
+ // TODO: fix mui/no-guarded-throw
163
+ // eslint-disable-next-line mui/no-guarded-throw
164
+ throw /* minify-error-disabled */new Error('Base UI: Cannot call an event handler while rendering.');
165
+ }
166
+ }
167
+
168
+ /**
169
+ * Untracks the provided value by turning it into a ref to remove its reactivity.
170
+ *
171
+ * Used to access the passed value inside `React.useEffect` without causing the effect to re-run when the value changes.
172
+ */
173
+ function useValueAsRef(value) {
174
+ const latest = useRenderElement.useRefWithInit(createLatestRef, value).current;
175
+ latest.next = value;
176
+
177
+ // eslint-disable-next-line react-hooks/exhaustive-deps
178
+ useIsoLayoutEffect(latest.effect);
179
+ return latest;
180
+ }
181
+ function createLatestRef(value) {
182
+ const latest = {
183
+ current: value,
184
+ next: value,
185
+ effect: () => {
186
+ latest.current = latest.next;
187
+ }
188
+ };
189
+ return latest;
190
+ }
191
+
192
+ const visuallyHiddenBase = {
193
+ clipPath: 'inset(50%)',
194
+ overflow: 'hidden',
195
+ whiteSpace: 'nowrap',
196
+ border: 0,
197
+ padding: 0,
198
+ width: 1,
199
+ height: 1,
200
+ margin: -1
201
+ };
202
+ const visuallyHidden = {
203
+ ...visuallyHiddenBase,
204
+ position: 'fixed',
205
+ top: 0,
206
+ left: 0
207
+ };
208
+ const visuallyHiddenInput = {
209
+ ...visuallyHiddenBase,
210
+ position: 'absolute'
211
+ };
212
+
39
213
  /**
40
214
  * The NoOptionalParams type is a utility type that checks if a function has optional or default parameters.
41
215
  * If the function has optional or default parameters, it returns a string literal type with an error message.
@@ -799,7 +973,7 @@ class ReactStore extends Store {
799
973
  React__namespace.useDebugValue(key);
800
974
  // eslint-disable-next-line consistent-this
801
975
  const store = this;
802
- useButton.useIsoLayoutEffect(() => {
976
+ useIsoLayoutEffect(() => {
803
977
  if (store.state[key] !== value) {
804
978
  store.set(key, value);
805
979
  }
@@ -816,7 +990,7 @@ class ReactStore extends Store {
816
990
  useSyncedValueWithCleanup(key, value) {
817
991
  // eslint-disable-next-line consistent-this
818
992
  const store = this;
819
- useButton.useIsoLayoutEffect(() => {
993
+ useIsoLayoutEffect(() => {
820
994
  if (store.state[key] !== value) {
821
995
  store.set(key, value);
822
996
  }
@@ -845,7 +1019,7 @@ class ReactStore extends Store {
845
1019
  }
846
1020
  }
847
1021
  const dependencies = Object.values(statePart);
848
- useButton.useIsoLayoutEffect(() => {
1022
+ useIsoLayoutEffect(() => {
849
1023
  store.update(statePart);
850
1024
  // eslint-disable-next-line react-hooks/exhaustive-deps
851
1025
  }, [store, ...dependencies]);
@@ -860,7 +1034,7 @@ class ReactStore extends Store {
860
1034
  // eslint-disable-next-line consistent-this
861
1035
  const store = this;
862
1036
  const isControlled = controlled !== undefined;
863
- useButton.useIsoLayoutEffect(() => {
1037
+ useIsoLayoutEffect(() => {
864
1038
  if (isControlled && !Object.is(store.state[key], controlled)) {
865
1039
  // Set the internal state to match the controlled value.
866
1040
  store.setState({
@@ -914,7 +1088,7 @@ class ReactStore extends Store {
914
1088
  */
915
1089
  useContextCallback(key, fn) {
916
1090
  React__namespace.useDebugValue(key);
917
- const stableFunction = useButton.useStableCallback(fn ?? useRenderElement.NOOP);
1091
+ const stableFunction = useStableCallback(fn ?? useRenderElement.NOOP);
918
1092
  this.context[key] = stableFunction;
919
1093
  }
920
1094
 
@@ -975,6 +1149,240 @@ function mergeCleanups(...cleanups) {
975
1149
  };
976
1150
  }
977
1151
 
1152
+ function ownerDocument(node) {
1153
+ return node?.ownerDocument || document;
1154
+ }
1155
+
1156
+ /**
1157
+ * Adds an event listener and returns a cleanup function to remove it.
1158
+ */
1159
+
1160
+ function addEventListener(target, type, listener, options) {
1161
+ target.addEventListener(type, listener, options);
1162
+ return () => {
1163
+ target.removeEventListener(type, listener, options);
1164
+ };
1165
+ }
1166
+
1167
+ const EMPTY$2 = [];
1168
+
1169
+ /**
1170
+ * A React.useEffect equivalent that runs once, when the component is mounted.
1171
+ */
1172
+ function useOnMount(fn) {
1173
+ // TODO: uncomment once we enable eslint-plugin-react-compiler // eslint-disable-next-line react-compiler/react-compiler -- no need to put `fn` in the dependency array
1174
+ /* eslint-disable react-hooks/exhaustive-deps */
1175
+ React__namespace.useEffect(fn, EMPTY$2);
1176
+ /* eslint-enable react-hooks/exhaustive-deps */
1177
+ }
1178
+
1179
+ /** Unlike `setTimeout`, rAF doesn't guarantee a positive integer return value, so we can't have
1180
+ * a monomorphic `uint` type with `0` meaning empty.
1181
+ * See warning note at:
1182
+ * https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame#return_value */
1183
+ const EMPTY$1 = null;
1184
+ let LAST_RAF = globalThis.requestAnimationFrame;
1185
+ class Scheduler {
1186
+ /* This implementation uses an array as a backing data-structure for frame callbacks.
1187
+ * It allows `O(1)` callback cancelling by inserting a `null` in the array, though it
1188
+ * never calls the native `cancelAnimationFrame` if there are no frames left. This can
1189
+ * be much more efficient if there is a call pattern that alterns as
1190
+ * "request-cancel-request-cancel-…".
1191
+ * But in the case of "request-request-…-cancel-cancel-…", it leaves the final animation
1192
+ * frame to run anyway. We turn that frame into a `O(1)` no-op via `callbacksCount`. */
1193
+
1194
+ callbacks = [];
1195
+ callbacksCount = 0;
1196
+ nextId = 1;
1197
+ startId = 1;
1198
+ isScheduled = false;
1199
+ tick = timestamp => {
1200
+ this.isScheduled = false;
1201
+ const currentCallbacks = this.callbacks;
1202
+ const currentCallbacksCount = this.callbacksCount;
1203
+
1204
+ // Update these before iterating, callbacks could call `requestAnimationFrame` again.
1205
+ this.callbacks = [];
1206
+ this.callbacksCount = 0;
1207
+ this.startId = this.nextId;
1208
+ if (currentCallbacksCount > 0) {
1209
+ for (let i = 0; i < currentCallbacks.length; i += 1) {
1210
+ currentCallbacks[i]?.(timestamp);
1211
+ }
1212
+ }
1213
+ };
1214
+ request(fn) {
1215
+ const id = this.nextId;
1216
+ this.nextId += 1;
1217
+ this.callbacks.push(fn);
1218
+ this.callbacksCount += 1;
1219
+
1220
+ /* In a test environment with fake timers, a fake `requestAnimationFrame` can be called
1221
+ * but there's no guarantee that the animation frame will actually run before the fake
1222
+ * timers are teared, which leaves `isScheduled` set, but won't run our `tick()`. */
1223
+ const didRAFChange = process.env.NODE_ENV !== 'production' && LAST_RAF !== requestAnimationFrame && (LAST_RAF = requestAnimationFrame, true);
1224
+ if (!this.isScheduled || didRAFChange) {
1225
+ requestAnimationFrame(this.tick);
1226
+ this.isScheduled = true;
1227
+ }
1228
+ return id;
1229
+ }
1230
+ cancel(id) {
1231
+ const index = id - this.startId;
1232
+ if (index < 0 || index >= this.callbacks.length) {
1233
+ return;
1234
+ }
1235
+ this.callbacks[index] = null;
1236
+ this.callbacksCount -= 1;
1237
+ }
1238
+ }
1239
+ const scheduler = new Scheduler();
1240
+ class AnimationFrame {
1241
+ static create() {
1242
+ return new AnimationFrame();
1243
+ }
1244
+ static request(fn) {
1245
+ return scheduler.request(fn);
1246
+ }
1247
+ static cancel(id) {
1248
+ return scheduler.cancel(id);
1249
+ }
1250
+ currentId = EMPTY$1;
1251
+
1252
+ /**
1253
+ * Executes `fn` after `delay`, clearing any previously scheduled call.
1254
+ */
1255
+ request(fn) {
1256
+ this.cancel();
1257
+ this.currentId = scheduler.request(() => {
1258
+ this.currentId = EMPTY$1;
1259
+ fn();
1260
+ });
1261
+ }
1262
+ cancel = () => {
1263
+ if (this.currentId !== EMPTY$1) {
1264
+ scheduler.cancel(this.currentId);
1265
+ this.currentId = EMPTY$1;
1266
+ }
1267
+ };
1268
+ disposeEffect = () => {
1269
+ return this.cancel;
1270
+ };
1271
+ }
1272
+
1273
+ /**
1274
+ * A `requestAnimationFrame` with automatic cleanup and guard.
1275
+ */
1276
+ function useAnimationFrame() {
1277
+ const timeout = useRenderElement.useRefWithInit(AnimationFrame.create).current;
1278
+ useOnMount(timeout.disposeEffect);
1279
+ return timeout;
1280
+ }
1281
+
1282
+ const EMPTY = 0;
1283
+ class Timeout {
1284
+ static create() {
1285
+ return new Timeout();
1286
+ }
1287
+ currentId = EMPTY;
1288
+
1289
+ /**
1290
+ * Executes `fn` after `delay`, clearing any previously scheduled call.
1291
+ */
1292
+ start(delay, fn) {
1293
+ this.clear();
1294
+ this.currentId = setTimeout(() => {
1295
+ this.currentId = EMPTY;
1296
+ fn();
1297
+ }, delay); /* Node.js types are enabled in development */
1298
+ }
1299
+ isStarted() {
1300
+ return this.currentId !== EMPTY;
1301
+ }
1302
+ clear = () => {
1303
+ if (this.currentId !== EMPTY) {
1304
+ clearTimeout(this.currentId);
1305
+ this.currentId = EMPTY;
1306
+ }
1307
+ };
1308
+ disposeEffect = () => {
1309
+ return this.clear;
1310
+ };
1311
+ }
1312
+
1313
+ /**
1314
+ * A `setTimeout` with automatic cleanup and guard.
1315
+ */
1316
+ function useTimeout() {
1317
+ const timeout = useRenderElement.useRefWithInit(Timeout.create).current;
1318
+ useOnMount(timeout.disposeEffect);
1319
+ return timeout;
1320
+ }
1321
+
1322
+ /**
1323
+ * Reads `navigator.userAgent` / `navigator.platform` (legacy but universally
1324
+ * supported) into a normalized shape. In development, prefers the modern
1325
+ * `navigator.userAgentData` API on Chromium to avoid DevTools warnings about
1326
+ * the deprecated reads; that branch is dead-code-eliminated in production
1327
+ * builds to keep the bundle small.
1328
+ *
1329
+ * Returns empty/zero values when `navigator` is undefined (SSR), so every
1330
+ * derived flag safely evaluates to `false`.
1331
+ */
1332
+ function readRawData() {
1333
+ if (typeof navigator === 'undefined') {
1334
+ return {
1335
+ userAgent: '',
1336
+ platform: '',
1337
+ maxTouchPoints: 0
1338
+ };
1339
+ }
1340
+ if (process.env.NODE_ENV !== 'production') {
1341
+ const uaData = navigator.userAgentData;
1342
+ if (uaData && Array.isArray(uaData.brands)) {
1343
+ return {
1344
+ userAgent: uaData.brands.map(({
1345
+ brand,
1346
+ version
1347
+ }) => `${brand}/${version}`).join(' '),
1348
+ platform: uaData.platform ?? navigator.platform ?? '',
1349
+ maxTouchPoints: navigator.maxTouchPoints ?? 0
1350
+ };
1351
+ }
1352
+ }
1353
+ return {
1354
+ userAgent: navigator.userAgent,
1355
+ platform: navigator.platform ?? '',
1356
+ maxTouchPoints: navigator.maxTouchPoints ?? 0
1357
+ };
1358
+ }
1359
+ const {
1360
+ userAgent,
1361
+ platform,
1362
+ maxTouchPoints
1363
+ } = readRawData();
1364
+ const lowerUserAgent = userAgent.toLowerCase();
1365
+ const lowerPlatform = platform.toLowerCase();
1366
+
1367
+ // iPadOS 13+ reports `MacIntel` for `navigator.platform`; disambiguated via
1368
+ // `maxTouchPoints` so iPad is classified as iOS, not macOS.
1369
+ // https://github.com/mui/base-ui/issues/1309
1370
+ /** iPhone, iPad (including iPadOS 13+ reporting as macOS), iPod. */
1371
+ const ios = /^i(os$|p)/.test(lowerPlatform) || lowerPlatform === 'macintel' && maxTouchPoints > 1;
1372
+
1373
+ /** Android phones, tablets, and embedded Android browsers. */
1374
+ const ANDROID_STRING = 'android';
1375
+ const android = lowerPlatform === ANDROID_STRING || lowerUserAgent.includes(ANDROID_STRING);
1376
+
1377
+ /** macOS desktop. Excludes iPadOS, which reports as `MacIntel`. */
1378
+ const mac = !ios && lowerPlatform.startsWith('mac');
1379
+
1380
+ /** Windows desktop. */
1381
+ lowerPlatform.startsWith('win');
1382
+
1383
+ /** Any Apple OS (`mac || ios`). */
1384
+ const apple = mac || ios;
1385
+
978
1386
  // WebKit (Safari, all iOS browsers, GNOME Web). Distinguished from Blink by
979
1387
  // the legacy `-webkit-backdrop-filter` name — Blink forked from WebKit in 2013
980
1388
  // and only ships the unprefixed `backdrop-filter`.
@@ -986,14 +1394,14 @@ const webkit = typeof CSS !== 'undefined' && !!CSS.supports?.('-webkit-backdrop-
986
1394
  // `!webkit` prefix also defends against future iOS-browser UA changes that
987
1395
  // might inject `Firefox` into a WebKit-based UA.
988
1396
  /** Gecko: Firefox. */
989
- const gecko = !webkit && useButton.lowerUserAgent.includes('firefox');
1397
+ const gecko = !webkit && lowerUserAgent.includes('firefox');
990
1398
 
991
1399
  // All Chromium-based browsers ship `Chrome/` or `Chromium/` in their UA — both
992
1400
  // share the `chrom` prefix, so a single substring check covers Chrome, Edge,
993
1401
  // Opera, Brave, etc. Chrome-on-iOS uses `CriOS/` and stays WebKit. The positive
994
1402
  // UA check also makes this SSR-safe — an empty UA matches nothing.
995
1403
  /** Blink: Chrome, Edge, Opera, Brave, and other Chromium-based browsers. */
996
- !webkit && useButton.lowerUserAgent.includes('chrom');
1404
+ !webkit && lowerUserAgent.includes('chrom');
997
1405
 
998
1406
  // Whether a screen reader is *actually* running cannot be detected. These flags
999
1407
  // identify platforms where a specific screen reader could be active. VoiceOver
@@ -1004,7 +1412,50 @@ const gecko = !webkit && useButton.lowerUserAgent.includes('firefox');
1004
1412
  * The user *may* be using VoiceOver — actual activation is not detectable.
1005
1413
  * True on any Apple platform (macOS, iOS, iPadOS).
1006
1414
  */
1007
- const voiceOver = useButton.apple;
1415
+ const voiceOver = apple;
1416
+
1417
+ /** Running in jsdom or HappyDOM (used by unit tests). */
1418
+ const jsdom = /jsdom|happydom/.test(lowerUserAgent);
1419
+
1420
+ function stopEvent(event) {
1421
+ event.preventDefault();
1422
+ event.stopPropagation();
1423
+ }
1424
+ function isReactEvent(event) {
1425
+ return 'nativeEvent' in event;
1426
+ }
1427
+
1428
+ // License: https://github.com/adobe/react-spectrum/blob/main/packages/@react-aria/utils/src/isVirtualEvent.ts
1429
+ function isVirtualClick(event) {
1430
+ if (event.pointerType === '' && event.isTrusted) {
1431
+ return true;
1432
+ }
1433
+ if (android && event.pointerType) {
1434
+ return event.type === 'click' && event.buttons === 1;
1435
+ }
1436
+ return event.detail === 0 && !event.pointerType;
1437
+ }
1438
+ function isVirtualPointerEvent(event) {
1439
+ if (jsdom) {
1440
+ return false;
1441
+ }
1442
+ return !android && event.width === 0 && event.height === 0 || android && event.width === 1 && event.height === 1 && event.pressure === 0 && event.detail === 0 && event.pointerType === 'mouse' ||
1443
+ // iOS VoiceOver returns 0.333• for width/height.
1444
+ event.width < 1 && event.height < 1 && event.pressure === 0 && event.detail === 0 && event.pointerType === 'touch';
1445
+ }
1446
+ function isMouseLikePointerType(pointerType, strict) {
1447
+ // On some Linux machines with Chromium, mouse inputs return a `pointerType`
1448
+ // of "pen": https://github.com/floating-ui/floating-ui/issues/2015
1449
+ const values = ['mouse', 'pen'];
1450
+ if (!strict) {
1451
+ values.push('', undefined);
1452
+ }
1453
+ return values.includes(pointerType);
1454
+ }
1455
+ function isClickLikeEvent(event) {
1456
+ const type = event.type;
1457
+ return type === 'click' || type === 'mousedown' || type === 'keydown' || type === 'keyup';
1458
+ }
1008
1459
 
1009
1460
  const FOCUSABLE_ATTRIBUTE = 'data-base-ui-focusable';
1010
1461
  const TYPEABLE_SELECTOR = "input:not([type='hidden']):not([disabled])," + "[contenteditable]:not([contenteditable='false']),textarea:not([disabled])";
@@ -1013,8 +1464,48 @@ const ARROW_RIGHT = 'ArrowRight';
1013
1464
  const ARROW_UP = 'ArrowUp';
1014
1465
  const ARROW_DOWN = 'ArrowDown';
1015
1466
 
1467
+ function activeElement(doc) {
1468
+ let element = doc.activeElement;
1469
+ while (element?.shadowRoot?.activeElement != null) {
1470
+ element = element.shadowRoot.activeElement;
1471
+ }
1472
+ return element;
1473
+ }
1474
+ function contains(parent, child) {
1475
+ if (!parent || !child) {
1476
+ return false;
1477
+ }
1478
+ const rootNode = child.getRootNode?.();
1479
+
1480
+ // First, attempt with the faster native method.
1481
+ if (parent.contains(child)) {
1482
+ return true;
1483
+ }
1484
+
1485
+ // Then fall back to traversing out of shadow roots when needed.
1486
+ if (rootNode && floatingUi_utils.isShadowRoot(rootNode)) {
1487
+ let next = child;
1488
+ while (next) {
1489
+ if (parent === next) {
1490
+ return true;
1491
+ }
1492
+ next = next.parentNode || next.host;
1493
+ }
1494
+ }
1495
+ return false;
1496
+ }
1497
+ function getTarget(event) {
1498
+ if ('composedPath' in event) {
1499
+ return event.composedPath()[0];
1500
+ }
1501
+
1502
+ // TS assumes `composedPath()` always exists, but older browsers without
1503
+ // shadow DOM support still fall back to `target`.
1504
+ return event.target;
1505
+ }
1506
+
1016
1507
  function isTargetInsideEnabledTrigger(target, triggerElements) {
1017
- if (!floatingUi_utils_dom.isElement(target)) {
1508
+ if (!floatingUi_utils.isElement(target)) {
1018
1509
  return false;
1019
1510
  }
1020
1511
  const targetElement = target;
@@ -1022,7 +1513,7 @@ function isTargetInsideEnabledTrigger(target, triggerElements) {
1022
1513
  return !targetElement.hasAttribute('data-trigger-disabled');
1023
1514
  }
1024
1515
  for (const [, trigger] of triggerElements.entries()) {
1025
- if (useButton.contains(trigger, targetElement)) {
1516
+ if (contains(trigger, targetElement)) {
1026
1517
  return !trigger.hasAttribute('data-trigger-disabled');
1027
1518
  }
1028
1519
  }
@@ -1044,7 +1535,7 @@ function isRootElement(element) {
1044
1535
  return element.matches('html,body');
1045
1536
  }
1046
1537
  function isTypeableElement(element) {
1047
- return floatingUi_utils_dom.isHTMLElement(element) && element.matches(TYPEABLE_SELECTOR);
1538
+ return floatingUi_utils.isHTMLElement(element) && element.matches(TYPEABLE_SELECTOR);
1048
1539
  }
1049
1540
  function isInteractiveElement(element) {
1050
1541
  return element?.closest(`button,a[href],[role="button"],select,[tabindex]:not([tabindex="-1"]),${TYPEABLE_SELECTOR}`) != null;
@@ -1058,7 +1549,7 @@ function isTypeableCombobox(element) {
1058
1549
  function matchesFocusVisible(element) {
1059
1550
  // We don't want to block focus from working with `visibleOnly`
1060
1551
  // (JSDOM doesn't match `:focus-visible` when the element has `:focus`)
1061
- if (!element || useButton.jsdom) {
1552
+ if (!element || jsdom) {
1062
1553
  return true;
1063
1554
  }
1064
1555
  try {
@@ -1078,9 +1569,89 @@ function getFloatingFocusElement(floatingElement) {
1078
1569
  return floatingElement.hasAttribute(FOCUSABLE_ATTRIBUTE) ? floatingElement : floatingElement.querySelector(`[${FOCUSABLE_ATTRIBUTE}]`) || floatingElement;
1079
1570
  }
1080
1571
 
1572
+ const none = 'none';
1573
+ const triggerPress = 'trigger-press';
1574
+ const triggerHover = 'trigger-hover';
1575
+ const triggerFocus = 'trigger-focus';
1576
+ const outsidePress = 'outside-press';
1577
+ const itemPress = 'item-press';
1578
+ const closePress = 'close-press';
1579
+ const clearPress = 'clear-press';
1580
+ const chipRemovePress = 'chip-remove-press';
1581
+ const incrementPress = 'increment-press';
1582
+ const decrementPress = 'decrement-press';
1583
+ const inputChange = 'input-change';
1584
+ const inputClear = 'input-clear';
1585
+ const inputBlur = 'input-blur';
1586
+ const inputPaste = 'input-paste';
1587
+ const inputPress = 'input-press';
1588
+ const focusOut = 'focus-out';
1589
+ const escapeKey = 'escape-key';
1590
+ const closeWatcher = 'close-watcher';
1591
+ const listNavigation = 'list-navigation';
1592
+ const keyboard = 'keyboard';
1593
+ const pointer = 'pointer';
1594
+ const wheel = 'wheel';
1595
+ const scrub = 'scrub';
1596
+ const cancelOpen = 'cancel-open';
1597
+ const siblingOpen = 'sibling-open';
1598
+ const imperativeAction = 'imperative-action';
1599
+ const swipe = 'swipe';
1600
+ const windowResize = 'window-resize';
1601
+
1602
+ /**
1603
+ * Maps a change `reason` string to the corresponding native event type.
1604
+ */
1605
+
1606
+ /**
1607
+ * Details of custom change events emitted by Base UI components.
1608
+ */
1609
+
1610
+ /**
1611
+ * Details of custom generic events emitted by Base UI components.
1612
+ */
1613
+
1614
+ /**
1615
+ * Creates a Base UI event details object with the given reason and utilities
1616
+ * for preventing Base UI's internal event handling.
1617
+ */
1618
+ function createChangeEventDetails(reason, event, trigger, customProperties) {
1619
+ let canceled = false;
1620
+ let allowPropagation = false;
1621
+ const custom = customProperties ?? useRenderElement.EMPTY_OBJECT;
1622
+ const details = {
1623
+ reason,
1624
+ event: event ?? new Event('base-ui'),
1625
+ cancel() {
1626
+ canceled = true;
1627
+ },
1628
+ allowPropagation() {
1629
+ allowPropagation = true;
1630
+ },
1631
+ get isCanceled() {
1632
+ return canceled;
1633
+ },
1634
+ get isPropagationAllowed() {
1635
+ return allowPropagation;
1636
+ },
1637
+ trigger,
1638
+ ...custom
1639
+ };
1640
+ return details;
1641
+ }
1642
+ function createGenericEventDetails(reason, event, customProperties) {
1643
+ const custom = customProperties ?? useRenderElement.EMPTY_OBJECT;
1644
+ const details = {
1645
+ reason,
1646
+ event: event ?? new Event('base-ui'),
1647
+ ...custom
1648
+ };
1649
+ return details;
1650
+ }
1651
+
1081
1652
  const FocusGuard = /*#__PURE__*/React__namespace.forwardRef(function FocusGuard(props, ref) {
1082
1653
  const [role, setRole] = React__namespace.useState();
1083
- useButton.useIsoLayoutEffect(() => {
1654
+ useIsoLayoutEffect(() => {
1084
1655
  // Unlike NVDA and JAWS, VoiceOver's virtual cursor triggers `onFocus` as
1085
1656
  // it moves — but only on focusable/role-button elements through WebKit's
1086
1657
  // NSAccessibility path. Setting `role="button"` lets the focus trap catch
@@ -1097,7 +1668,7 @@ const FocusGuard = /*#__PURE__*/React__namespace.forwardRef(function FocusGuard(
1097
1668
  return /*#__PURE__*/jsxRuntime.jsx("span", {
1098
1669
  ...props,
1099
1670
  ref: ref,
1100
- style: useButton.visuallyHidden,
1671
+ style: visuallyHidden,
1101
1672
  "aria-hidden": role ? undefined : true,
1102
1673
  ...restProps,
1103
1674
  "data-base-ui-focus-guard": ""
@@ -1258,7 +1829,7 @@ function getGridNavigatedIndex(list, {
1258
1829
  return undefined;
1259
1830
  };
1260
1831
  if (stop) {
1261
- useButton.stopEvent(event);
1832
+ stopEvent(event);
1262
1833
  }
1263
1834
  const verticalCandidate = navigateVertically(verticalDirection) ?? navigateVerticallyWithInferredRows(verticalDirection);
1264
1835
  if (verticalCandidate !== undefined) {
@@ -1308,7 +1879,7 @@ function getGridNavigatedIndex(list, {
1308
1879
  const prevRow = floatingUi_utils.floor(prevIndex / cols);
1309
1880
  if (event.key === (rtl ? ARROW_LEFT : ARROW_RIGHT)) {
1310
1881
  if (stop) {
1311
- useButton.stopEvent(event);
1882
+ stopEvent(event);
1312
1883
  }
1313
1884
  if (prevIndex % cols !== cols - 1) {
1314
1885
  nextIndex = findNonDisabledListIndex(list, {
@@ -1339,7 +1910,7 @@ function getGridNavigatedIndex(list, {
1339
1910
  }
1340
1911
  if (event.key === (rtl ? ARROW_RIGHT : ARROW_LEFT)) {
1341
1912
  if (stop) {
1342
- useButton.stopEvent(event);
1913
+ stopEvent(event);
1343
1914
  }
1344
1915
  if (prevIndex % cols !== 0) {
1345
1916
  nextIndex = findNonDisabledListIndex(list, {
@@ -1405,7 +1976,7 @@ function isListIndexDisabled(list, index, disabledIndices) {
1405
1976
  function isHiddenByStyles(styles) {
1406
1977
  return styles.visibility === 'hidden' || styles.visibility === 'collapse';
1407
1978
  }
1408
- function isElementVisible(element, styles = element ? floatingUi_utils_dom.getComputedStyle(element) : null) {
1979
+ function isElementVisible(element, styles = element ? floatingUi_utils.getComputedStyle(element) : null) {
1409
1980
  if (!element || !element.isConnected || !styles || isHiddenByStyles(styles)) {
1410
1981
  return false;
1411
1982
  }
@@ -1425,11 +1996,11 @@ function getParentElement(element) {
1425
1996
  return element.parentElement;
1426
1997
  }
1427
1998
  const rootNode = element.getRootNode();
1428
- return floatingUi_utils_dom.isShadowRoot(rootNode) ? rootNode.host : null;
1999
+ return floatingUi_utils.isShadowRoot(rootNode) ? rootNode.host : null;
1429
2000
  }
1430
2001
  function getDetailsSummary(details) {
1431
2002
  for (const child of Array.from(details.children)) {
1432
- if (floatingUi_utils_dom.getNodeName(child) === 'summary') {
2003
+ if (floatingUi_utils.getNodeName(child) === 'summary') {
1433
2004
  return child;
1434
2005
  }
1435
2006
  }
@@ -1437,11 +2008,11 @@ function getDetailsSummary(details) {
1437
2008
  }
1438
2009
  function isWithinOpenDetailsSummary(element, details) {
1439
2010
  const summary = getDetailsSummary(details);
1440
- return !!summary && (element === summary || useButton.contains(summary, element));
2011
+ return !!summary && (element === summary || contains(summary, element));
1441
2012
  }
1442
2013
  function isFocusableCandidate(element) {
1443
- const nodeName = element ? floatingUi_utils_dom.getNodeName(element) : '';
1444
- return element != null && element.matches(CANDIDATE_SELECTOR) && (nodeName !== 'summary' || element.parentElement != null && floatingUi_utils_dom.getNodeName(element.parentElement) === 'details' && getDetailsSummary(element.parentElement) === element) && (nodeName !== 'details' || getDetailsSummary(element) == null) && (nodeName !== 'input' || element.type !== 'hidden');
2014
+ const nodeName = element ? floatingUi_utils.getNodeName(element) : '';
2015
+ return element != null && element.matches(CANDIDATE_SELECTOR) && (nodeName !== 'summary' || element.parentElement != null && floatingUi_utils.getNodeName(element.parentElement) === 'details' && getDetailsSummary(element.parentElement) === element) && (nodeName !== 'details' || getDetailsSummary(element) == null) && (nodeName !== 'input' || element.type !== 'hidden');
1445
2016
  }
1446
2017
  function isFocusableElement(element) {
1447
2018
  if (!isFocusableCandidate(element) || !element.isConnected || element.matches(':disabled')) {
@@ -1449,18 +2020,18 @@ function isFocusableElement(element) {
1449
2020
  }
1450
2021
  for (let current = element; current; current = getParentElement(current)) {
1451
2022
  const isAncestor = current !== element;
1452
- const isSlot = floatingUi_utils_dom.getNodeName(current) === 'slot';
2023
+ const isSlot = floatingUi_utils.getNodeName(current) === 'slot';
1453
2024
  if (current.hasAttribute('inert')) {
1454
2025
  return false;
1455
2026
  }
1456
- if (isAncestor && floatingUi_utils_dom.getNodeName(current) === 'details' && !current.open && !isWithinOpenDetailsSummary(element, current) || current.hasAttribute('hidden') || !isSlot && !isVisibleInTabbableTree(current, isAncestor)) {
2027
+ if (isAncestor && floatingUi_utils.getNodeName(current) === 'details' && !current.open && !isWithinOpenDetailsSummary(element, current) || current.hasAttribute('hidden') || !isSlot && !isVisibleInTabbableTree(current, isAncestor)) {
1457
2028
  return false;
1458
2029
  }
1459
2030
  }
1460
2031
  return true;
1461
2032
  }
1462
2033
  function isVisibleInTabbableTree(element, isAncestor) {
1463
- const styles = floatingUi_utils_dom.getComputedStyle(element);
2034
+ const styles = floatingUi_utils.getComputedStyle(element);
1464
2035
  if (!isAncestor) {
1465
2036
  return isElementVisible(element, styles);
1466
2037
  }
@@ -1469,15 +2040,15 @@ function isVisibleInTabbableTree(element, isAncestor) {
1469
2040
  function getTabIndex(element) {
1470
2041
  const tabIndex = element.tabIndex;
1471
2042
  if (tabIndex < 0) {
1472
- const nodeName = floatingUi_utils_dom.getNodeName(element);
1473
- if (nodeName === 'details' || nodeName === 'audio' || nodeName === 'video' || floatingUi_utils_dom.isHTMLElement(element) && element.isContentEditable) {
2043
+ const nodeName = floatingUi_utils.getNodeName(element);
2044
+ if (nodeName === 'details' || nodeName === 'audio' || nodeName === 'video' || floatingUi_utils.isHTMLElement(element) && element.isContentEditable) {
1474
2045
  return 0;
1475
2046
  }
1476
2047
  }
1477
2048
  return tabIndex;
1478
2049
  }
1479
2050
  function getNamedRadioInput(element) {
1480
- if (floatingUi_utils_dom.getNodeName(element) !== 'input') {
2051
+ if (floatingUi_utils.getNodeName(element) !== 'input') {
1481
2052
  return null;
1482
2053
  }
1483
2054
  const input = element;
@@ -1501,7 +2072,7 @@ function isTabbableRadio(element, candidates) {
1501
2072
  }) === input;
1502
2073
  }
1503
2074
  function getComposedChildren(container) {
1504
- if (floatingUi_utils_dom.isHTMLElement(container) && floatingUi_utils_dom.getNodeName(container) === 'slot') {
2075
+ if (floatingUi_utils.isHTMLElement(container) && floatingUi_utils.getNodeName(container) === 'slot') {
1505
2076
  const assignedElements = container.assignedElements({
1506
2077
  flatten: true
1507
2078
  });
@@ -1509,7 +2080,7 @@ function getComposedChildren(container) {
1509
2080
  return assignedElements;
1510
2081
  }
1511
2082
  }
1512
- if (floatingUi_utils_dom.isHTMLElement(container) && container.shadowRoot) {
2083
+ if (floatingUi_utils.isHTMLElement(container) && container.shadowRoot) {
1513
2084
  return Array.from(container.shadowRoot.children);
1514
2085
  }
1515
2086
  return Array.from(container.children);
@@ -1524,7 +2095,7 @@ function appendCandidates(container, list) {
1524
2095
  }
1525
2096
  function appendMatchingElements(container, selector, list) {
1526
2097
  getComposedChildren(container).forEach(child => {
1527
- if (floatingUi_utils_dom.isHTMLElement(child) && child.matches(selector)) {
2098
+ if (floatingUi_utils.isHTMLElement(child) && child.matches(selector)) {
1528
2099
  list.push(child);
1529
2100
  }
1530
2101
  appendMatchingElements(child, selector, list);
@@ -1548,23 +2119,23 @@ function getTabbableIn(container, dir) {
1548
2119
  if (len === 0) {
1549
2120
  return undefined;
1550
2121
  }
1551
- const active = useButton.activeElement(useButton.ownerDocument(container));
2122
+ const active = activeElement(ownerDocument(container));
1552
2123
  const index = list.indexOf(active);
1553
2124
  // eslint-disable-next-line no-nested-ternary
1554
2125
  const nextIndex = index === -1 ? dir === 1 ? 0 : len - 1 : index + dir;
1555
2126
  return list[nextIndex];
1556
2127
  }
1557
2128
  function getNextTabbable(referenceElement) {
1558
- return getTabbableIn(useButton.ownerDocument(referenceElement).body, 1) || referenceElement;
2129
+ return getTabbableIn(ownerDocument(referenceElement).body, 1) || referenceElement;
1559
2130
  }
1560
2131
  function getPreviousTabbable(referenceElement) {
1561
- return getTabbableIn(useButton.ownerDocument(referenceElement).body, -1) || referenceElement;
2132
+ return getTabbableIn(ownerDocument(referenceElement).body, -1) || referenceElement;
1562
2133
  }
1563
2134
  function getTabbableNearElement(referenceElement, dir) {
1564
2135
  if (!referenceElement) {
1565
2136
  return null;
1566
2137
  }
1567
- const list = tabbable(useButton.ownerDocument(referenceElement).body);
2138
+ const list = tabbable(ownerDocument(referenceElement).body);
1568
2139
  const elementCount = list.length;
1569
2140
  if (elementCount === 0) {
1570
2141
  return null;
@@ -1585,7 +2156,7 @@ function getTabbableBeforeElement(referenceElement) {
1585
2156
  function isOutsideEvent(event, container) {
1586
2157
  const containerElement = container || event.currentTarget;
1587
2158
  const relatedTarget = event.relatedTarget;
1588
- return !relatedTarget || !useButton.contains(containerElement, relatedTarget);
2159
+ return !relatedTarget || !contains(containerElement, relatedTarget);
1589
2160
  }
1590
2161
  function disableFocusInside(container) {
1591
2162
  const tabbableElements = tabbable(container);
@@ -1681,7 +2252,7 @@ function unwrapHost(node) {
1681
2252
  if (!node) {
1682
2253
  return null;
1683
2254
  }
1684
- return floatingUi_utils_dom.isShadowRoot(node) ? node.host : unwrapHost(node.parentNode);
2255
+ return floatingUi_utils.isShadowRoot(node) ? node.host : unwrapHost(node.parentNode);
1685
2256
  }
1686
2257
  const correctElements = (parent, targets) => targets.map(target => {
1687
2258
  if (parent.contains(target)) {
@@ -1711,7 +2282,7 @@ const collectOutsideElements = (root, keepElements, stopElements) => {
1711
2282
  return;
1712
2283
  }
1713
2284
  Array.from(parent.children).forEach(node => {
1714
- if (floatingUi_utils_dom.getNodeName(node) === 'script') {
2285
+ if (floatingUi_utils.getNodeName(node) === 'script') {
1715
2286
  return;
1716
2287
  }
1717
2288
  if (keepElements.has(node)) {
@@ -1811,12 +2382,50 @@ function markOthers(avoidElements, options = {}) {
1811
2382
  inert = false,
1812
2383
  mark = true
1813
2384
  } = options;
1814
- const body = useButton.ownerDocument(avoidElements[0]).body;
2385
+ const body = ownerDocument(avoidElements[0]).body;
1815
2386
  return applyAttributeToOthers(avoidElements, body, ariaHidden, inert, {
1816
2387
  mark
1817
2388
  });
1818
2389
  }
1819
2390
 
2391
+ let globalId = 0;
2392
+
2393
+ // TODO React 17: Remove `useGlobalId` once React 17 support is removed
2394
+ function useGlobalId(idOverride, prefix = 'mui') {
2395
+ const [defaultId, setDefaultId] = React__namespace.useState(idOverride);
2396
+ const id = idOverride || defaultId;
2397
+ React__namespace.useEffect(() => {
2398
+ if (defaultId == null) {
2399
+ // Fallback to this default id when possible.
2400
+ // Use the incrementing value for client-side rendering only.
2401
+ // We can't use it server-side.
2402
+ // If you want to use random values please consider the Birthday Problem: https://en.wikipedia.org/wiki/Birthday_problem
2403
+ globalId += 1;
2404
+ setDefaultId(`${prefix}-${globalId}`);
2405
+ }
2406
+ }, [defaultId, prefix]);
2407
+ return id;
2408
+ }
2409
+ const maybeReactUseId = SafeReact.useId;
2410
+
2411
+ /**
2412
+ *
2413
+ * @example <div id={useId()} />
2414
+ * @param idOverride
2415
+ * @returns {string}
2416
+ */
2417
+ function useId(idOverride, prefix) {
2418
+ // React.useId() is only available from React 17.0.0.
2419
+ if (maybeReactUseId !== undefined) {
2420
+ const reactId = maybeReactUseId();
2421
+ return idOverride ?? (prefix ? `${prefix}-${reactId}` : reactId);
2422
+ }
2423
+
2424
+ // TODO: uncomment once we enable eslint-plugin-react-compiler // eslint-disable-next-line react-compiler/react-compiler
2425
+ // eslint-disable-next-line react-hooks/rules-of-hooks -- `React.useId` is invariant at runtime.
2426
+ return useGlobalId(idOverride, prefix);
2427
+ }
2428
+
1820
2429
  const TYPEAHEAD_RESET_MS = 500;
1821
2430
  const PATIENT_CLICK_THRESHOLD = 500;
1822
2431
  const DISABLED_TRANSITIONS_STYLE = {
@@ -1868,12 +2477,12 @@ function useFloatingPortalNode(props = {}) {
1868
2477
  componentProps = useRenderElement.EMPTY_OBJECT,
1869
2478
  elementProps
1870
2479
  } = props;
1871
- const uniqueId = useButton.useId();
2480
+ const uniqueId = useId();
1872
2481
  const portalContext = usePortalContext();
1873
2482
  const parentPortalNode = portalContext?.portalNode;
1874
2483
  const [containerElement, setContainerElement] = React__namespace.useState(null);
1875
2484
  const [portalNode, setPortalNode] = React__namespace.useState(null);
1876
- const setPortalNodeRef = useButton.useStableCallback(node => {
2485
+ const setPortalNodeRef = useStableCallback(node => {
1877
2486
  if (node !== null) {
1878
2487
  // the useIsoLayoutEffect below watching containerProp / parentPortalNode
1879
2488
  // sets setPortalNode(null) when the container becomes null or changes.
@@ -1882,7 +2491,7 @@ function useFloatingPortalNode(props = {}) {
1882
2491
  }
1883
2492
  });
1884
2493
  const containerRef = React__namespace.useRef(null);
1885
- useButton.useIsoLayoutEffect(() => {
2494
+ useIsoLayoutEffect(() => {
1886
2495
  // Wait for the container to be resolved if explicitly `null`.
1887
2496
  if (containerProp === null) {
1888
2497
  if (containerRef.current) {
@@ -1897,7 +2506,7 @@ function useFloatingPortalNode(props = {}) {
1897
2506
  if (uniqueId == null) {
1898
2507
  return;
1899
2508
  }
1900
- const resolvedContainer = (containerProp && (floatingUi_utils_dom.isNode(containerProp) ? containerProp : containerProp.current)) ?? parentPortalNode ?? document.body;
2509
+ const resolvedContainer = (containerProp && (floatingUi_utils.isNode(containerProp) ? containerProp : containerProp.current)) ?? parentPortalNode ?? document.body;
1901
2510
  if (resolvedContainer == null) {
1902
2511
  if (containerRef.current) {
1903
2512
  containerRef.current = null;
@@ -1992,9 +2601,9 @@ const FloatingPortal = /*#__PURE__*/React__namespace.forwardRef(function Floatin
1992
2601
 
1993
2602
  // Listen to the event on the capture phase so they run before the focus
1994
2603
  // trap elements onFocus prop is called.
1995
- return mergeCleanups(useButton.addEventListener(portalNode, 'focusin', onFocus, true), useButton.addEventListener(portalNode, 'focusout', onFocus, true));
2604
+ return mergeCleanups(addEventListener(portalNode, 'focusin', onFocus, true), addEventListener(portalNode, 'focusout', onFocus, true));
1996
2605
  }, [portalNode, modal]);
1997
- useButton.useIsoLayoutEffect(() => {
2606
+ useIsoLayoutEffect(() => {
1998
2607
  if (!portalNode || open !== true || !focusInsideDisabledRef.current) {
1999
2608
  return;
2000
2609
  }
@@ -2040,7 +2649,7 @@ const FloatingPortal = /*#__PURE__*/React__namespace.forwardRef(function Floatin
2040
2649
  const nextTabbable = getNextTabbable(domReference);
2041
2650
  nextTabbable?.focus();
2042
2651
  if (focusManagerState?.closeOnFocusOut) {
2043
- focusManagerState?.onOpenChange(false, useButton.createChangeEventDetails(useButton.focusOut, event.nativeEvent));
2652
+ focusManagerState?.onOpenChange(false, createChangeEventDetails(focusOut, event.nativeEvent));
2044
2653
  }
2045
2654
  }
2046
2655
  }
@@ -2112,10 +2721,10 @@ const useFloatingTree = externalTree => {
2112
2721
  * @see https://floating-ui.com/docs/FloatingTree
2113
2722
  */
2114
2723
  function useFloatingNodeId(externalTree) {
2115
- const id = useButton.useId();
2724
+ const id = useId();
2116
2725
  const tree = useFloatingTree(externalTree);
2117
2726
  const parentId = useFloatingParentNodeId();
2118
- useButton.useIsoLayoutEffect(() => {
2727
+ useIsoLayoutEffect(() => {
2119
2728
  if (!id) {
2120
2729
  return undefined;
2121
2730
  }
@@ -2172,8 +2781,19 @@ function FloatingTree(props) {
2172
2781
  });
2173
2782
  }
2174
2783
 
2784
+ /**
2785
+ * If the provided argument is a ref object, returns its `current` value.
2786
+ * Otherwise, returns the argument itself.
2787
+ */
2788
+ function resolveRef(maybeRef) {
2789
+ if (maybeRef == null) {
2790
+ return maybeRef;
2791
+ }
2792
+ return 'current' in maybeRef ? maybeRef.current : maybeRef;
2793
+ }
2794
+
2175
2795
  function getEventType(event, lastInteractionType) {
2176
- const win = floatingUi_utils_dom.getWindow(useButton.getTarget(event));
2796
+ const win = floatingUi_utils.getWindow(getTarget(event));
2177
2797
  if (event instanceof win.KeyboardEvent) {
2178
2798
  return 'keyboard';
2179
2799
  }
@@ -2203,7 +2823,7 @@ function clearDisconnectedPreviouslyFocusedElements() {
2203
2823
  }
2204
2824
  function addPreviouslyFocusedElement(element) {
2205
2825
  clearDisconnectedPreviouslyFocusedElements();
2206
- if (element && floatingUi_utils_dom.getNodeName(element) !== 'body') {
2826
+ if (element && floatingUi_utils.getNodeName(element) !== 'body') {
2207
2827
  previouslyFocusedElements.push(new WeakRef(element));
2208
2828
  if (previouslyFocusedElements.length > LIST_LIMIT) {
2209
2829
  previouslyFocusedElements = previouslyFocusedElements.slice(-LIST_LIMIT);
@@ -2278,7 +2898,7 @@ function FloatingFocusManager(props) {
2278
2898
  events,
2279
2899
  dataRef
2280
2900
  } = store.context;
2281
- const getNodeId = useButton.useStableCallback(() => dataRef.current.floatingContext?.nodeId);
2901
+ const getNodeId = useStableCallback(() => dataRef.current.floatingContext?.nodeId);
2282
2902
  const ignoreInitialFocus = initialFocus === false;
2283
2903
  // If the reference is a combobox and is typeable (e.g. input/textarea),
2284
2904
  // there are different focus semantics. The guards should not be rendered, but
@@ -2286,10 +2906,10 @@ function FloatingFocusManager(props) {
2286
2906
  // hidden dismiss button should only appear at the end of the list, not the
2287
2907
  // start.
2288
2908
  const isUntrappedTypeableCombobox = isTypeableCombobox(domReference) && ignoreInitialFocus;
2289
- const initialFocusRef = useButton.useValueAsRef(initialFocus);
2290
- const returnFocusRef = useButton.useValueAsRef(returnFocus);
2291
- const openInteractionTypeRef = useButton.useValueAsRef(openInteractionType);
2292
- const openRef = useButton.useValueAsRef(open);
2909
+ const initialFocusRef = useValueAsRef(initialFocus);
2910
+ const returnFocusRef = useValueAsRef(returnFocus);
2911
+ const openInteractionTypeRef = useValueAsRef(openInteractionType);
2912
+ const openRef = useValueAsRef(open);
2293
2913
  const tree = useFloatingTree(externalTree);
2294
2914
  const portalContext = usePortalContext();
2295
2915
  const preventReturnFocusRef = React__namespace.useRef(false);
@@ -2302,15 +2922,15 @@ function FloatingFocusManager(props) {
2302
2922
  const afterGuardRef = React__namespace.useRef(null);
2303
2923
  const mergedBeforeGuardRef = useRenderElement.useMergedRefs(beforeGuardRef, beforeContentFocusGuardRef, portalContext?.beforeInsideRef);
2304
2924
  const mergedAfterGuardRef = useRenderElement.useMergedRefs(afterGuardRef, portalContext?.afterInsideRef);
2305
- const blurTimeout = useButton.useTimeout();
2306
- const pointerDownTimeout = useButton.useTimeout();
2307
- const restoreFocusFrame = useButton.useAnimationFrame();
2925
+ const blurTimeout = useTimeout();
2926
+ const pointerDownTimeout = useTimeout();
2927
+ const restoreFocusFrame = useAnimationFrame();
2308
2928
  const isInsidePortal = portalContext != null;
2309
2929
  const floatingFocusElement = getFloatingFocusElement(floating);
2310
- const getTabbableContent = useButton.useStableCallback((container = floatingFocusElement) => {
2930
+ const getTabbableContent = useStableCallback((container = floatingFocusElement) => {
2311
2931
  return container ? tabbable(container) : [];
2312
2932
  });
2313
- const getResolvedInsideElements = useButton.useStableCallback(() => getInsideElements?.().filter(element => element != null) ?? []);
2933
+ const getResolvedInsideElements = useStableCallback(() => getInsideElements?.().filter(element => element != null) ?? []);
2314
2934
 
2315
2935
  // Prevent Tab from escaping the modal when there are no tabbable elements.
2316
2936
  React__namespace.useEffect(() => {
@@ -2320,13 +2940,13 @@ function FloatingFocusManager(props) {
2320
2940
  function onKeyDown(event) {
2321
2941
  if (event.key === 'Tab') {
2322
2942
  // The focus guards have nothing to focus, so we need to stop the event.
2323
- if (useButton.contains(floatingFocusElement, useButton.activeElement(useButton.ownerDocument(floatingFocusElement))) && getTabbableContent().length === 0 && !isUntrappedTypeableCombobox) {
2324
- useButton.stopEvent(event);
2943
+ if (contains(floatingFocusElement, activeElement(ownerDocument(floatingFocusElement))) && getTabbableContent().length === 0 && !isUntrappedTypeableCombobox) {
2944
+ stopEvent(event);
2325
2945
  }
2326
2946
  }
2327
2947
  }
2328
- const doc = useButton.ownerDocument(floatingFocusElement);
2329
- return useButton.addEventListener(doc, 'keydown', onKeyDown);
2948
+ const doc = ownerDocument(floatingFocusElement);
2949
+ return addEventListener(doc, 'keydown', onKeyDown);
2330
2950
  }, [disabled, floatingFocusElement, modal, isUntrappedTypeableCombobox, getTabbableContent]);
2331
2951
 
2332
2952
  // Track pointer/keyboard interactions to disambiguate focus and outside presses.
@@ -2334,14 +2954,14 @@ function FloatingFocusManager(props) {
2334
2954
  if (disabled || !open) {
2335
2955
  return undefined;
2336
2956
  }
2337
- const doc = useButton.ownerDocument(floatingFocusElement);
2957
+ const doc = ownerDocument(floatingFocusElement);
2338
2958
  function clearPointerDownOutside() {
2339
2959
  pointerDownOutsideRef.current = false;
2340
2960
  }
2341
2961
  function onPointerDown(event) {
2342
- const target = useButton.getTarget(event);
2962
+ const target = getTarget(event);
2343
2963
  const insideElements = getResolvedInsideElements();
2344
- const pointerTargetInside = useButton.contains(floating, target) || useButton.contains(domReference, target) || useButton.contains(portalContext?.portalNode, target) || insideElements.some(element => element === target || useButton.contains(element, target));
2964
+ const pointerTargetInside = contains(floating, target) || contains(domReference, target) || contains(portalContext?.portalNode, target) || insideElements.some(element => element === target || contains(element, target));
2345
2965
  pointerDownOutsideRef.current = !pointerTargetInside;
2346
2966
  lastInteractionTypeRef.current = event.pointerType || 'keyboard';
2347
2967
  if (target?.closest(`[${CLICK_TRIGGER_IDENTIFIER}]`)) {
@@ -2356,7 +2976,7 @@ function FloatingFocusManager(props) {
2356
2976
  function onKeyDown() {
2357
2977
  lastInteractionTypeRef.current = 'keyboard';
2358
2978
  }
2359
- return mergeCleanups(useButton.addEventListener(doc, 'pointerdown', onPointerDown, true), useButton.addEventListener(doc, 'pointerup', clearPointerDownOutside, true), useButton.addEventListener(doc, 'pointercancel', clearPointerDownOutside, true), useButton.addEventListener(doc, 'keydown', onKeyDown, true),
2979
+ return mergeCleanups(addEventListener(doc, 'pointerdown', onPointerDown, true), addEventListener(doc, 'pointerup', clearPointerDownOutside, true), addEventListener(doc, 'pointercancel', clearPointerDownOutside, true), addEventListener(doc, 'keydown', onKeyDown, true),
2360
2980
  // Avoid a stale `true` leaking into the next open (e.g. keep-mounted popups)
2361
2981
  // if the popup dismissed between pointerdown and pointerup.
2362
2982
  clearPointerDownOutside);
@@ -2367,7 +2987,7 @@ function FloatingFocusManager(props) {
2367
2987
  if (disabled || !closeOnFocusOut) {
2368
2988
  return undefined;
2369
2989
  }
2370
- const doc = useButton.ownerDocument(floatingFocusElement);
2990
+ const doc = ownerDocument(floatingFocusElement);
2371
2991
 
2372
2992
  // In Safari, buttons lose focus when pressing them.
2373
2993
  function handlePointerDown() {
@@ -2377,7 +2997,7 @@ function FloatingFocusManager(props) {
2377
2997
  });
2378
2998
  }
2379
2999
  function handleFocusIn(event) {
2380
- const target = useButton.getTarget(event);
3000
+ const target = getTarget(event);
2381
3001
  if (isTabbable(target)) {
2382
3002
  lastFocusedTabbableRef.current = target;
2383
3003
  }
@@ -2385,30 +3005,30 @@ function FloatingFocusManager(props) {
2385
3005
  function handleFocusOutside(event) {
2386
3006
  const relatedTarget = event.relatedTarget;
2387
3007
  const currentTarget = event.currentTarget;
2388
- const target = useButton.getTarget(event);
3008
+ const target = getTarget(event);
2389
3009
 
2390
3010
  // When focus is lost to the body (e.g. on a backdrop press), record the element that
2391
3011
  // had focus so a confirmation dialog opened while the body is focused can return focus
2392
3012
  // to it. Scoped to `modal` to avoid non-modal popups polluting the shared stack.
2393
- if (modal && relatedTarget == null && target != null && useButton.contains(floating, target)) {
3013
+ if (modal && relatedTarget == null && target != null && contains(floating, target)) {
2394
3014
  addPreviouslyFocusedElement(target);
2395
3015
  }
2396
3016
  queueMicrotask(() => {
2397
3017
  const nodeId = getNodeId();
2398
3018
  const triggers = store.context.triggerElements;
2399
3019
  const insideElements = getResolvedInsideElements();
2400
- const isRelatedFocusGuard = relatedTarget?.hasAttribute(createAttribute('focus-guard')) && [beforeGuardRef.current, afterGuardRef.current, portalContext?.beforeInsideRef.current, portalContext?.afterInsideRef.current, portalContext?.beforeOutsideRef.current, portalContext?.afterOutsideRef.current, useButton.resolveRef(previousFocusableElement), useButton.resolveRef(nextFocusableElement)].includes(relatedTarget);
2401
- const movedToUnrelatedNode = !(useButton.contains(domReference, relatedTarget) || useButton.contains(floating, relatedTarget) || useButton.contains(relatedTarget, floating) || useButton.contains(portalContext?.portalNode, relatedTarget) || insideElements.some(element => element === relatedTarget || useButton.contains(element, relatedTarget)) || relatedTarget != null && triggers.hasElement(relatedTarget) || triggers.hasMatchingElement(trigger => useButton.contains(trigger, relatedTarget)) || isRelatedFocusGuard || tree && (getNodeChildren(tree.nodesRef.current, nodeId).find(node => useButton.contains(node.context?.elements.floating, relatedTarget) || useButton.contains(node.context?.elements.domReference, relatedTarget)) || getNodeAncestors(tree.nodesRef.current, nodeId).find(node => [node.context?.elements.floating, getFloatingFocusElement(node.context?.elements.floating)].includes(relatedTarget) || node.context?.elements.domReference === relatedTarget)));
3020
+ const isRelatedFocusGuard = relatedTarget?.hasAttribute(createAttribute('focus-guard')) && [beforeGuardRef.current, afterGuardRef.current, portalContext?.beforeInsideRef.current, portalContext?.afterInsideRef.current, portalContext?.beforeOutsideRef.current, portalContext?.afterOutsideRef.current, resolveRef(previousFocusableElement), resolveRef(nextFocusableElement)].includes(relatedTarget);
3021
+ const movedToUnrelatedNode = !(contains(domReference, relatedTarget) || contains(floating, relatedTarget) || contains(relatedTarget, floating) || contains(portalContext?.portalNode, relatedTarget) || insideElements.some(element => element === relatedTarget || contains(element, relatedTarget)) || relatedTarget != null && triggers.hasElement(relatedTarget) || triggers.hasMatchingElement(trigger => contains(trigger, relatedTarget)) || isRelatedFocusGuard || tree && (getNodeChildren(tree.nodesRef.current, nodeId).find(node => contains(node.context?.elements.floating, relatedTarget) || contains(node.context?.elements.domReference, relatedTarget)) || getNodeAncestors(tree.nodesRef.current, nodeId).find(node => [node.context?.elements.floating, getFloatingFocusElement(node.context?.elements.floating)].includes(relatedTarget) || node.context?.elements.domReference === relatedTarget)));
2402
3022
  if (currentTarget === domReference && floatingFocusElement) {
2403
3023
  handleTabIndex(floatingFocusElement);
2404
3024
  }
2405
3025
 
2406
3026
  // Restore focus to the previous tabbable element index to prevent
2407
3027
  // focus from being lost outside the floating tree.
2408
- if (restoreFocus && currentTarget !== domReference && !isElementVisible(target) && useButton.activeElement(doc) === doc.body) {
3028
+ if (restoreFocus && currentTarget !== domReference && !isElementVisible(target) && activeElement(doc) === doc.body) {
2409
3029
  // Let `FloatingPortal` effect knows that focus is still inside the
2410
3030
  // floating tree.
2411
- if (floatingUi_utils_dom.isHTMLElement(floatingFocusElement)) {
3031
+ if (floatingUi_utils.isHTMLElement(floatingFocusElement)) {
2412
3032
  floatingFocusElement.focus();
2413
3033
  // If explicitly requested to restore focus to the popup container, do not search
2414
3034
  // for the next/previous tabbable element.
@@ -2426,7 +3046,7 @@ function FloatingFocusManager(props) {
2426
3046
  const tabbableContent = getTabbableContent();
2427
3047
  const prevTabbable = lastFocusedTabbableRef.current;
2428
3048
  const nodeToFocus = (prevTabbable && tabbableContent.includes(prevTabbable) ? prevTabbable : null) || tabbableContent[tabbableContent.length - 1] || floatingFocusElement;
2429
- if (floatingUi_utils_dom.isHTMLElement(nodeToFocus)) {
3049
+ if (floatingUi_utils.isHTMLElement(nodeToFocus)) {
2430
3050
  nodeToFocus.focus();
2431
3051
  }
2432
3052
  }
@@ -2449,7 +3069,7 @@ function FloatingFocusManager(props) {
2449
3069
  // Allow closing when `isUntrappedTypeableCombobox` regardless of the previously focused element.
2450
3070
  isUntrappedTypeableCombobox || relatedTarget !== getPreviouslyFocusedElement())) {
2451
3071
  preventReturnFocusRef.current = true;
2452
- store.setOpen(false, useButton.createChangeEventDetails(useButton.focusOut, event));
3072
+ store.setOpen(false, createChangeEventDetails(focusOut, event));
2453
3073
  }
2454
3074
  });
2455
3075
  }
@@ -2462,11 +3082,11 @@ function FloatingFocusManager(props) {
2462
3082
  dataRef.current.insideReactTree = false;
2463
3083
  });
2464
3084
  }
2465
- const domReferenceElement = floatingUi_utils_dom.isHTMLElement(domReference) ? domReference : null;
3085
+ const domReferenceElement = floatingUi_utils.isHTMLElement(domReference) ? domReference : null;
2466
3086
  if (!floating && !domReferenceElement) {
2467
3087
  return undefined;
2468
3088
  }
2469
- return mergeCleanups(domReferenceElement && useButton.addEventListener(domReferenceElement, 'focusout', handleFocusOutside), domReferenceElement && useButton.addEventListener(domReferenceElement, 'pointerdown', handlePointerDown), floating && useButton.addEventListener(floating, 'focusin', handleFocusIn), floating && useButton.addEventListener(floating, 'focusout', handleFocusOutside), floating && portalContext && useButton.addEventListener(floating, 'focusout', markInsideReactTree, true));
3089
+ return mergeCleanups(domReferenceElement && addEventListener(domReferenceElement, 'focusout', handleFocusOutside), domReferenceElement && addEventListener(domReferenceElement, 'pointerdown', handlePointerDown), floating && addEventListener(floating, 'focusin', handleFocusIn), floating && addEventListener(floating, 'focusout', handleFocusOutside), floating && portalContext && addEventListener(floating, 'focusout', markInsideReactTree, true));
2470
3090
  }, [disabled, domReference, floating, floatingFocusElement, modal, tree, portalContext, store, closeOnFocusOut, restoreFocus, getTabbableContent, isUntrappedTypeableCombobox, getNodeId, dataRef, blurTimeout, pointerDownTimeout, restoreFocusFrame, nextFocusableElement, previousFocusableElement, getResolvedInsideElements]);
2471
3091
 
2472
3092
  // Hide everything outside the floating tree from assistive tech while open.
@@ -2480,7 +3100,7 @@ function FloatingFocusManager(props) {
2480
3100
  const ancestors = tree ? getNodeAncestors(tree.nodesRef.current, getNodeId()) : [];
2481
3101
  const rootAncestorComboboxDomReference = ancestors.find(node => isTypeableCombobox(node.context?.elements.domReference || null))?.context?.elements.domReference;
2482
3102
  const controlInsideElements = [floating, ...portalNodes, beforeGuardRef.current, afterGuardRef.current, portalContext?.beforeOutsideRef.current, portalContext?.afterOutsideRef.current, ...getResolvedInsideElements()];
2483
- const insideElements = [...controlInsideElements, rootAncestorComboboxDomReference, useButton.resolveRef(previousFocusableElement), useButton.resolveRef(nextFocusableElement), isUntrappedTypeableCombobox ? domReference : null].filter(x => x != null);
3103
+ const insideElements = [...controlInsideElements, rootAncestorComboboxDomReference, resolveRef(previousFocusableElement), resolveRef(nextFocusableElement), isUntrappedTypeableCombobox ? domReference : null].filter(x => x != null);
2484
3104
  const ariaHiddenCleanup = markOthers(insideElements, {
2485
3105
  ariaHidden: modal || isUntrappedTypeableCombobox,
2486
3106
  mark: false
@@ -2494,12 +3114,12 @@ function FloatingFocusManager(props) {
2494
3114
  }, [open, disabled, domReference, floating, modal, portalContext, isUntrappedTypeableCombobox, tree, getNodeId, nextFocusableElement, previousFocusableElement, getResolvedInsideElements]);
2495
3115
 
2496
3116
  // Focus the initial element when the floating element opens.
2497
- useButton.useIsoLayoutEffect(() => {
2498
- if (!open || disabled || !floatingUi_utils_dom.isHTMLElement(floatingFocusElement)) {
3117
+ useIsoLayoutEffect(() => {
3118
+ if (!open || disabled || !floatingUi_utils.isHTMLElement(floatingFocusElement)) {
2499
3119
  return;
2500
3120
  }
2501
- const doc = useButton.ownerDocument(floatingFocusElement);
2502
- const previouslyFocusedElement = useButton.activeElement(doc);
3121
+ const doc = ownerDocument(floatingFocusElement);
3122
+ const previouslyFocusedElement = activeElement(doc);
2503
3123
 
2504
3124
  // Wait for any layout effect state setters to execute to set `tabIndex`.
2505
3125
  queueMicrotask(() => {
@@ -2510,7 +3130,7 @@ function FloatingFocusManager(props) {
2510
3130
  if (resolvedInitialFocus === undefined || resolvedInitialFocus === false) {
2511
3131
  return;
2512
3132
  }
2513
- const focusAlreadyInsideFloatingEl = useButton.contains(floatingFocusElement, previouslyFocusedElement);
3133
+ const focusAlreadyInsideFloatingEl = contains(floatingFocusElement, previouslyFocusedElement);
2514
3134
  if (focusAlreadyInsideFloatingEl) {
2515
3135
  return;
2516
3136
  }
@@ -2525,10 +3145,10 @@ function FloatingFocusManager(props) {
2525
3145
  if (resolvedInitialFocus === true || resolvedInitialFocus === null) {
2526
3146
  elToFocus = getDefaultFocusElement();
2527
3147
  } else {
2528
- elToFocus = useButton.resolveRef(resolvedInitialFocus);
3148
+ elToFocus = resolveRef(resolvedInitialFocus);
2529
3149
  }
2530
3150
  elToFocus = elToFocus || getDefaultFocusElement();
2531
- const hadFocusInside = useButton.contains(floatingFocusElement, useButton.activeElement(doc));
3151
+ const hadFocusInside = contains(floatingFocusElement, activeElement(doc));
2532
3152
  enqueueFocus(elToFocus, {
2533
3153
  preventScroll: elToFocus === floatingFocusElement,
2534
3154
  shouldFocus() {
@@ -2541,8 +3161,8 @@ function FloatingFocusManager(props) {
2541
3161
  if (hadFocusInside) {
2542
3162
  return true;
2543
3163
  }
2544
- const currentActiveElement = useButton.activeElement(doc);
2545
- const focusMovedInside = currentActiveElement !== elToFocus && useButton.contains(floatingFocusElement, currentActiveElement);
3164
+ const currentActiveElement = activeElement(doc);
3165
+ const focusMovedInside = currentActiveElement !== elToFocus && contains(floatingFocusElement, currentActiveElement);
2546
3166
  return !focusMovedInside;
2547
3167
  }
2548
3168
  });
@@ -2550,12 +3170,12 @@ function FloatingFocusManager(props) {
2550
3170
  }, [disabled, open, floatingFocusElement, getTabbableContent, initialFocusRef, openInteractionTypeRef, openRef]);
2551
3171
 
2552
3172
  // Track return focus targets and restore focus on unmount/close.
2553
- useButton.useIsoLayoutEffect(() => {
3173
+ useIsoLayoutEffect(() => {
2554
3174
  if (disabled || !floatingFocusElement) {
2555
3175
  return undefined;
2556
3176
  }
2557
- const doc = useButton.ownerDocument(floatingFocusElement);
2558
- const elementFocusedBeforeOpen = useButton.activeElement(doc);
3177
+ const doc = ownerDocument(floatingFocusElement);
3178
+ const elementFocusedBeforeOpen = activeElement(doc);
2559
3179
  // Only nullish interaction types represent programmatic opens. The empty
2560
3180
  // string default is intentionally not treated as programmatic.
2561
3181
  const preferPreviousFocus = openInteractionTypeRef.current == null;
@@ -2567,19 +3187,19 @@ function FloatingFocusManager(props) {
2567
3187
  if (!details.open) {
2568
3188
  closeTypeRef.current = getEventType(details.nativeEvent, lastInteractionTypeRef.current);
2569
3189
  }
2570
- if (details.reason === useButton.triggerHover && details.nativeEvent.type === 'mouseleave') {
3190
+ if (details.reason === triggerHover && details.nativeEvent.type === 'mouseleave') {
2571
3191
  preventReturnFocusRef.current = true;
2572
3192
  }
2573
- if (details.reason !== useButton.outsidePress) {
3193
+ if (details.reason !== outsidePress) {
2574
3194
  return;
2575
3195
  }
2576
3196
  if (details.nested) {
2577
3197
  preventReturnFocusRef.current = false;
2578
- } else if (useButton.isVirtualClick(details.nativeEvent) || useButton.isVirtualPointerEvent(details.nativeEvent)) {
3198
+ } else if (isVirtualClick(details.nativeEvent) || isVirtualPointerEvent(details.nativeEvent)) {
2579
3199
  preventReturnFocusRef.current = false;
2580
3200
  } else {
2581
3201
  let isPreventScrollSupported = false;
2582
- useButton.ownerDocument(floatingFocusElement).createElement('div').focus({
3202
+ ownerDocument(floatingFocusElement).createElement('div').focus({
2583
3203
  get preventScroll() {
2584
3204
  isPreventScrollSupported = true;
2585
3205
  return false;
@@ -2605,7 +3225,7 @@ function FloatingFocusManager(props) {
2605
3225
  resolvedReturnFocusValue = true;
2606
3226
  }
2607
3227
  const referenceReturnElement = domReference?.isConnected ? domReference : null;
2608
- const previousReturnElement = elementFocusedBeforeOpen?.isConnected && floatingUi_utils_dom.getNodeName(elementFocusedBeforeOpen) !== 'body' ? elementFocusedBeforeOpen : null;
3228
+ const previousReturnElement = elementFocusedBeforeOpen?.isConnected && floatingUi_utils.getNodeName(elementFocusedBeforeOpen) !== 'body' ? elementFocusedBeforeOpen : null;
2609
3229
  let defaultReturnElement = preferPreviousFocus ? previousReturnElement || referenceReturnElement : referenceReturnElement || previousReturnElement;
2610
3230
  if (!defaultReturnElement) {
2611
3231
  defaultReturnElement = getPreviouslyFocusedElement() || null;
@@ -2613,13 +3233,13 @@ function FloatingFocusManager(props) {
2613
3233
  if (typeof resolvedReturnFocusValue === 'boolean') {
2614
3234
  return defaultReturnElement;
2615
3235
  }
2616
- return useButton.resolveRef(resolvedReturnFocusValue) || defaultReturnElement || null;
3236
+ return resolveRef(resolvedReturnFocusValue) || defaultReturnElement || null;
2617
3237
  }
2618
3238
  return () => {
2619
3239
  events.off('openchange', onOpenChangeLocal);
2620
- const activeEl = useButton.activeElement(doc);
3240
+ const activeEl = activeElement(doc);
2621
3241
  const insideElements = getResolvedInsideElements();
2622
- const isFocusInsideFloatingTree = useButton.contains(floating, activeEl) || insideElements.some(element => element === activeEl || useButton.contains(element, activeEl)) || tree && getNodeChildren(tree.nodesRef.current, getNodeId(), false).some(node => useButton.contains(node.context?.elements.floating, activeEl));
3242
+ const isFocusInsideFloatingTree = contains(floating, activeEl) || insideElements.some(element => element === activeEl || contains(element, activeEl)) || tree && getNodeChildren(tree.nodesRef.current, getNodeId(), false).some(node => contains(node.context?.elements.floating, activeEl));
2623
3243
 
2624
3244
  // eslint-disable-next-line react-hooks/exhaustive-deps
2625
3245
  const returnFocusValueOrFn = returnFocusRef.current;
@@ -2628,7 +3248,7 @@ function FloatingFocusManager(props) {
2628
3248
  // This is `returnElement`, if it's tabbable, or its first tabbable child.
2629
3249
  const tabbableReturnElement = getFirstTabbableElement(returnElement);
2630
3250
  const hasExplicitReturnFocus = typeof returnFocusValueOrFn !== 'boolean';
2631
- if (returnFocusValueOrFn && !preventReturnFocusRef.current && floatingUi_utils_dom.isHTMLElement(tabbableReturnElement) && (
3251
+ if (returnFocusValueOrFn && !preventReturnFocusRef.current && floatingUi_utils.isHTMLElement(tabbableReturnElement) && (
2632
3252
  // If the focus moved somewhere else after mount, avoid returning focus
2633
3253
  // since it likely entered a different element which should be
2634
3254
  // respected: https://github.com/floating-ui/floating-ui/issues/2607
@@ -2645,22 +3265,22 @@ function FloatingFocusManager(props) {
2645
3265
  // Safari may randomly scroll to the bottom of the page if an input inside a popup has focus
2646
3266
  // when the popup unmounts from the DOM.
2647
3267
  // By blurring it before the popup unmounts, we can prevent this behavior.
2648
- useButton.useIsoLayoutEffect(() => {
3268
+ useIsoLayoutEffect(() => {
2649
3269
  if (!webkit || open || !floating) {
2650
3270
  return;
2651
3271
  }
2652
- const activeEl = useButton.activeElement(useButton.ownerDocument(floating));
2653
- if (!floatingUi_utils_dom.isHTMLElement(activeEl) || !isTypeableElement(activeEl)) {
3272
+ const activeEl = activeElement(ownerDocument(floating));
3273
+ if (!floatingUi_utils.isHTMLElement(activeEl) || !isTypeableElement(activeEl)) {
2654
3274
  return;
2655
3275
  }
2656
- if (useButton.contains(floating, activeEl)) {
3276
+ if (contains(floating, activeEl)) {
2657
3277
  activeEl.blur();
2658
3278
  }
2659
3279
  }, [open, floating]);
2660
3280
 
2661
3281
  // Synchronize the `context` & `modal` value to the FloatingPortal context.
2662
3282
  // It will decide whether or not it needs to render its own guards.
2663
- useButton.useIsoLayoutEffect(() => {
3283
+ useIsoLayoutEffect(() => {
2664
3284
  if (disabled || !portalContext) {
2665
3285
  return undefined;
2666
3286
  }
@@ -2677,7 +3297,7 @@ function FloatingFocusManager(props) {
2677
3297
  }, [disabled, portalContext, modal, open, store, closeOnFocusOut, domReference]);
2678
3298
 
2679
3299
  // Keep the floating element tabIndex in sync and clear stale focus records.
2680
- useButton.useIsoLayoutEffect(() => {
3300
+ useIsoLayoutEffect(() => {
2681
3301
  if (disabled || !floatingFocusElement) {
2682
3302
  return undefined;
2683
3303
  }
@@ -2701,7 +3321,7 @@ function FloatingFocusManager(props) {
2701
3321
  const nextTabbable = getNextTabbable(domReference);
2702
3322
  nextTabbable?.focus();
2703
3323
  } else {
2704
- useButton.resolveRef(previousFocusableElement ?? portalContext.beforeOutsideRef)?.focus();
3324
+ resolveRef(previousFocusableElement ?? portalContext.beforeOutsideRef)?.focus();
2705
3325
  }
2706
3326
  }
2707
3327
  }
@@ -2719,7 +3339,7 @@ function FloatingFocusManager(props) {
2719
3339
  const prevTabbable = getPreviousTabbable(domReference);
2720
3340
  prevTabbable?.focus();
2721
3341
  } else {
2722
- useButton.resolveRef(nextFocusableElement ?? portalContext.afterOutsideRef)?.focus();
3342
+ resolveRef(nextFocusableElement ?? portalContext.afterOutsideRef)?.focus();
2723
3343
  }
2724
3344
  }
2725
3345
  }
@@ -2739,16 +3359,16 @@ function useClick(context, props = {}) {
2739
3359
  ignoreMouse = false,
2740
3360
  stickIfOpen = true,
2741
3361
  touchOpenDelay = 0,
2742
- reason = useButton.triggerPress
3362
+ reason = triggerPress
2743
3363
  } = props;
2744
3364
  const store = 'rootStore' in context ? context.rootStore : context;
2745
3365
  const dataRef = store.context.dataRef;
2746
3366
  const pointerTypeRef = React__namespace.useRef(undefined);
2747
- const frame = useButton.useAnimationFrame();
2748
- const touchOpenTimeout = useButton.useTimeout();
3367
+ const frame = useAnimationFrame();
3368
+ const touchOpenTimeout = useTimeout();
2749
3369
  const reference = React__namespace.useMemo(() => {
2750
3370
  function setOpenWithTouchDelay(nextOpen, nativeEvent, target, pointerType) {
2751
- const details = useButton.createChangeEventDetails(reason, nativeEvent, target);
3371
+ const details = createChangeEventDetails(reason, nativeEvent, target);
2752
3372
  if (nextOpen && pointerType === 'touch' && touchOpenDelay > 0) {
2753
3373
  touchOpenTimeout.start(touchOpenDelay, () => {
2754
3374
  store.setOpen(true, details);
@@ -2791,14 +3411,14 @@ function useClick(context, props = {}) {
2791
3411
 
2792
3412
  // Ignore all buttons except for the "main" button.
2793
3413
  // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button
2794
- if (event.button !== 0 || eventOption === 'click' || useButton.isMouseLikePointerType(pointerType, true) && ignoreMouse) {
3414
+ if (event.button !== 0 || eventOption === 'click' || isMouseLikePointerType(pointerType, true) && ignoreMouse) {
2795
3415
  return;
2796
3416
  }
2797
3417
  const nextOpen = getNextOpen(open, event.currentTarget, openEventType => openEventType === 'click' || openEventType === 'mousedown');
2798
3418
 
2799
3419
  // Animations sometimes won't run on a typeable element if using a rAF.
2800
3420
  // Focus is always set on these elements. For touch, we may delay opening.
2801
- const target = useButton.getTarget(nativeEvent);
3421
+ const target = getTarget(nativeEvent);
2802
3422
  if (isTypeableElement(target)) {
2803
3423
  setOpenWithTouchDelay(nextOpen, nativeEvent, target, pointerType);
2804
3424
  return;
@@ -2823,7 +3443,7 @@ function useClick(context, props = {}) {
2823
3443
  pointerTypeRef.current = undefined;
2824
3444
  return;
2825
3445
  }
2826
- if (useButton.isMouseLikePointerType(pointerType, true) && ignoreMouse) {
3446
+ if (isMouseLikePointerType(pointerType, true) && ignoreMouse) {
2827
3447
  return;
2828
3448
  }
2829
3449
  const open = store.select('open');
@@ -2857,7 +3477,7 @@ function normalizeProp(normalizable) {
2857
3477
  function useDismiss(context, props = {}) {
2858
3478
  const {
2859
3479
  enabled = true,
2860
- escapeKey = true,
3480
+ escapeKey: escapeKey$1 = true,
2861
3481
  outsidePress: outsidePressProp = true,
2862
3482
  outsidePressEvent = 'sloppy',
2863
3483
  referencePress = alwaysFalse,
@@ -2871,10 +3491,10 @@ function useDismiss(context, props = {}) {
2871
3491
  dataRef
2872
3492
  } = store.context;
2873
3493
  const tree = useFloatingTree(externalTree);
2874
- const outsidePressFn = useButton.useStableCallback(typeof outsidePressProp === 'function' ? outsidePressProp : () => false);
2875
- const outsidePress = typeof outsidePressProp === 'function' ? outsidePressFn : outsidePressProp;
2876
- const outsidePressEnabled = outsidePress !== false;
2877
- const getOutsidePressEventProp = useButton.useStableCallback(() => outsidePressEvent);
3494
+ const outsidePressFn = useStableCallback(typeof outsidePressProp === 'function' ? outsidePressProp : () => false);
3495
+ const outsidePress$1 = typeof outsidePressProp === 'function' ? outsidePressFn : outsidePressProp;
3496
+ const outsidePressEnabled = outsidePress$1 !== false;
3497
+ const getOutsidePressEventProp = useStableCallback(() => outsidePressEvent);
2878
3498
  const {
2879
3499
  escapeKey: escapeKeyBubbles,
2880
3500
  outsidePress: outsidePressBubbles
@@ -2886,28 +3506,28 @@ function useDismiss(context, props = {}) {
2886
3506
  const isComposingRef = React__namespace.useRef(false);
2887
3507
  const currentPointerTypeRef = React__namespace.useRef('');
2888
3508
  const touchStateRef = React__namespace.useRef(null);
2889
- const cancelDismissOnEndTimeout = useButton.useTimeout();
2890
- const clearInsideReactTreeTimeout = useButton.useTimeout();
2891
- const clearInsideReactTree = useButton.useStableCallback(() => {
3509
+ const cancelDismissOnEndTimeout = useTimeout();
3510
+ const clearInsideReactTreeTimeout = useTimeout();
3511
+ const clearInsideReactTree = useStableCallback(() => {
2892
3512
  clearInsideReactTreeTimeout.clear();
2893
3513
  dataRef.current.insideReactTree = false;
2894
3514
  });
2895
- const hasBlockingChild = useButton.useStableCallback(bubbleKey => {
3515
+ const hasBlockingChild = useStableCallback(bubbleKey => {
2896
3516
  const nodeId = dataRef.current.floatingContext?.nodeId;
2897
3517
  const children = tree ? getNodeChildren(tree.nodesRef.current, nodeId) : [];
2898
3518
  return children.some(child => child.context?.open && !child.context.dataRef.current[bubbleKey]);
2899
3519
  });
2900
- const isEventWithinOwnElements = useButton.useStableCallback(event => {
3520
+ const isEventWithinOwnElements = useStableCallback(event => {
2901
3521
  return isEventTargetWithin(event, store.select('floatingElement')) || isEventTargetWithin(event, store.select('domReferenceElement'));
2902
3522
  });
2903
- const closeOnReferencePress = useButton.useStableCallback(event => {
3523
+ const closeOnReferencePress = useStableCallback(event => {
2904
3524
  if (!referencePress()) {
2905
3525
  return;
2906
3526
  }
2907
- store.setOpen(false, useButton.createChangeEventDetails(useButton.triggerPress, event.nativeEvent));
3527
+ store.setOpen(false, createChangeEventDetails(triggerPress, event.nativeEvent));
2908
3528
  });
2909
- const closeOnEscapeKeyDown = useButton.useStableCallback(event => {
2910
- if (!open || !enabled || !escapeKey || event.key !== 'Escape') {
3529
+ const closeOnEscapeKeyDown = useStableCallback(event => {
3530
+ if (!open || !enabled || !escapeKey$1 || event.key !== 'Escape') {
2911
3531
  return;
2912
3532
  }
2913
3533
 
@@ -2919,8 +3539,8 @@ function useDismiss(context, props = {}) {
2919
3539
  if (!escapeKeyBubbles && hasBlockingChild('__escapeKeyBubbles')) {
2920
3540
  return;
2921
3541
  }
2922
- const native = useButton.isReactEvent(event) ? event.nativeEvent : event;
2923
- const eventDetails = useButton.createChangeEventDetails(useButton.escapeKey, native);
3542
+ const native = isReactEvent(event) ? event.nativeEvent : event;
3543
+ const eventDetails = createChangeEventDetails(escapeKey, native);
2924
3544
  store.setOpen(false, eventDetails);
2925
3545
  if (!eventDetails.isCanceled) {
2926
3546
  event.preventDefault();
@@ -2929,19 +3549,19 @@ function useDismiss(context, props = {}) {
2929
3549
  event.stopPropagation();
2930
3550
  }
2931
3551
  });
2932
- const markInsideReactTree = useButton.useStableCallback(() => {
3552
+ const markInsideReactTree = useStableCallback(() => {
2933
3553
  dataRef.current.insideReactTree = true;
2934
3554
  clearInsideReactTreeTimeout.start(0, clearInsideReactTree);
2935
3555
  });
2936
- const markPressStartedInsideReactTree = useButton.useStableCallback(event => {
3556
+ const markPressStartedInsideReactTree = useStableCallback(event => {
2937
3557
  if (!open || !enabled || event.button !== 0) {
2938
3558
  return;
2939
3559
  }
2940
- const target = useButton.getTarget(event.nativeEvent);
3560
+ const target = getTarget(event.nativeEvent);
2941
3561
 
2942
3562
  // Only treat presses that start within the floating DOM subtree as inside.
2943
3563
  // This avoids suppressing parent dismissal when interacting with nested portals.
2944
- if (!useButton.contains(store.select('floatingElement'), target)) {
3564
+ if (!contains(store.select('floatingElement'), target)) {
2945
3565
  return;
2946
3566
  }
2947
3567
  if (!pressStartedInsideRef.current) {
@@ -2949,7 +3569,7 @@ function useDismiss(context, props = {}) {
2949
3569
  pressStartPreventedRef.current = false;
2950
3570
  }
2951
3571
  });
2952
- const markInsidePressStartPrevented = useButton.useStableCallback(event => {
3572
+ const markInsidePressStartPrevented = useStableCallback(event => {
2953
3573
  if (!open || !enabled) {
2954
3574
  return;
2955
3575
  }
@@ -2966,8 +3586,8 @@ function useDismiss(context, props = {}) {
2966
3586
  }
2967
3587
  dataRef.current.__escapeKeyBubbles = escapeKeyBubbles;
2968
3588
  dataRef.current.__outsidePressBubbles = outsidePressBubbles;
2969
- const compositionTimeout = new useButton.Timeout();
2970
- const preventedPressSuppressionTimeout = new useButton.Timeout();
3589
+ const compositionTimeout = new Timeout();
3590
+ const preventedPressSuppressionTimeout = new Timeout();
2971
3591
  function handleCompositionStart() {
2972
3592
  compositionTimeout.clear();
2973
3593
  isComposingRef.current = true;
@@ -3029,20 +3649,20 @@ function useDismiss(context, props = {}) {
3029
3649
  clearInsideReactTree();
3030
3650
  return;
3031
3651
  }
3032
- const target = useButton.getTarget(event);
3652
+ const target = getTarget(event);
3033
3653
  const inertSelector = `[${createAttribute('inert')}]`;
3034
- const targetRoot = floatingUi_utils_dom.isElement(target) ? target.getRootNode() : null;
3035
- const markers = Array.from((floatingUi_utils_dom.isShadowRoot(targetRoot) ? targetRoot : useButton.ownerDocument(store.select('floatingElement'))).querySelectorAll(inertSelector));
3654
+ const targetRoot = floatingUi_utils.isElement(target) ? target.getRootNode() : null;
3655
+ const markers = Array.from((floatingUi_utils.isShadowRoot(targetRoot) ? targetRoot : ownerDocument(store.select('floatingElement'))).querySelectorAll(inertSelector));
3036
3656
  const triggers = store.context.triggerElements;
3037
3657
 
3038
3658
  // If another trigger is clicked, don't close the floating element.
3039
- if (target && (triggers.hasElement(target) || triggers.hasMatchingElement(trigger => useButton.contains(trigger, target)))) {
3659
+ if (target && (triggers.hasElement(target) || triggers.hasMatchingElement(trigger => contains(trigger, target)))) {
3040
3660
  return;
3041
3661
  }
3042
- let targetRootAncestor = floatingUi_utils_dom.isElement(target) ? target : null;
3043
- while (targetRootAncestor && !floatingUi_utils_dom.isLastTraversableNode(targetRootAncestor)) {
3044
- const nextParent = floatingUi_utils_dom.getParentNode(targetRootAncestor);
3045
- if (floatingUi_utils_dom.isLastTraversableNode(nextParent) || !floatingUi_utils_dom.isElement(nextParent)) {
3662
+ let targetRootAncestor = floatingUi_utils.isElement(target) ? target : null;
3663
+ while (targetRootAncestor && !floatingUi_utils.isLastTraversableNode(targetRootAncestor)) {
3664
+ const nextParent = floatingUi_utils.getParentNode(targetRootAncestor);
3665
+ if (floatingUi_utils.isLastTraversableNode(nextParent) || !floatingUi_utils.isElement(nextParent)) {
3046
3666
  break;
3047
3667
  }
3048
3668
  targetRootAncestor = nextParent;
@@ -3050,20 +3670,20 @@ function useDismiss(context, props = {}) {
3050
3670
 
3051
3671
  // Check if the click occurred on a third-party element injected after the
3052
3672
  // floating element rendered.
3053
- if (markers.length && floatingUi_utils_dom.isElement(target) && !isRootElement(target) &&
3673
+ if (markers.length && floatingUi_utils.isElement(target) && !isRootElement(target) &&
3054
3674
  // Clicked on a direct ancestor (e.g. FloatingOverlay).
3055
- !useButton.contains(target, store.select('floatingElement')) &&
3675
+ !contains(target, store.select('floatingElement')) &&
3056
3676
  // If the target root element contains none of the markers, then the
3057
3677
  // element was injected after the floating element rendered.
3058
- markers.every(marker => !useButton.contains(targetRootAncestor, marker))) {
3678
+ markers.every(marker => !contains(targetRootAncestor, marker))) {
3059
3679
  return;
3060
3680
  }
3061
3681
 
3062
3682
  // Check if the click occurred on the scrollbar
3063
3683
  // Skip for touch events: scrollbars don't receive touch events on most platforms
3064
- if (floatingUi_utils_dom.isHTMLElement(target) && !('touches' in event)) {
3065
- const lastTraversableNode = floatingUi_utils_dom.isLastTraversableNode(target);
3066
- const style = floatingUi_utils_dom.getComputedStyle(target);
3684
+ if (floatingUi_utils.isHTMLElement(target) && !('touches' in event)) {
3685
+ const lastTraversableNode = floatingUi_utils.isLastTraversableNode(target);
3686
+ const style = floatingUi_utils.getComputedStyle(target);
3067
3687
  const scrollRe = /auto|scroll/;
3068
3688
  const isScrollableX = lastTraversableNode || scrollRe.test(style.overflowX);
3069
3689
  const isScrollableY = lastTraversableNode || scrollRe.test(style.overflowY);
@@ -3094,13 +3714,13 @@ function useDismiss(context, props = {}) {
3094
3714
  suppressNextOutsideClickRef.current = false;
3095
3715
  return;
3096
3716
  }
3097
- if (typeof outsidePress === 'function' && !outsidePress(event)) {
3717
+ if (typeof outsidePress$1 === 'function' && !outsidePress$1(event)) {
3098
3718
  return;
3099
3719
  }
3100
3720
  if (hasBlockingChild('__outsidePressBubbles')) {
3101
3721
  return;
3102
3722
  }
3103
- store.setOpen(false, useButton.createChangeEventDetails(useButton.outsidePress, event));
3723
+ store.setOpen(false, createChangeEventDetails(outsidePress, event));
3104
3724
  clearInsideReactTree();
3105
3725
  }
3106
3726
  function handlePointerDown(event) {
@@ -3131,11 +3751,11 @@ function useDismiss(context, props = {}) {
3131
3751
  }
3132
3752
  }
3133
3753
  function addTargetEventListenerOnce(event, listener) {
3134
- const target = useButton.getTarget(event);
3754
+ const target = getTarget(event);
3135
3755
  if (!target) {
3136
3756
  return;
3137
3757
  }
3138
- const unsubscribe = useButton.addEventListener(target, event.type, () => {
3758
+ const unsubscribe = addEventListener(target, event.type, () => {
3139
3759
  listener(event);
3140
3760
  unsubscribe();
3141
3761
  });
@@ -3189,7 +3809,7 @@ function useDismiss(context, props = {}) {
3189
3809
  }
3190
3810
 
3191
3811
  // Avoid suppressing when outsidePress explicitly ignores this target.
3192
- if (typeof outsidePress === 'function' && !outsidePress(event)) {
3812
+ if (typeof outsidePress$1 === 'function' && !outsidePress$1(event)) {
3193
3813
  return;
3194
3814
  }
3195
3815
  preventedPressSuppressionTimeout.clear();
@@ -3232,8 +3852,8 @@ function useDismiss(context, props = {}) {
3232
3852
  function handleTouchEndCapture(event) {
3233
3853
  addTargetEventListenerOnce(event, handleTouchEnd);
3234
3854
  }
3235
- const doc = useButton.ownerDocument(floatingElement);
3236
- const unsubscribe = mergeCleanups(escapeKey && mergeCleanups(useButton.addEventListener(doc, 'keydown', closeOnEscapeKeyDown), useButton.addEventListener(doc, 'compositionstart', handleCompositionStart), useButton.addEventListener(doc, 'compositionend', handleCompositionEnd)), outsidePressEnabled && mergeCleanups(useButton.addEventListener(doc, 'click', closeOnPressOutsideCapture, true), useButton.addEventListener(doc, 'pointerdown', closeOnPressOutsideCapture, true), useButton.addEventListener(doc, 'pointerup', handlePressEndCapture, true), useButton.addEventListener(doc, 'pointercancel', handlePressEndCapture, true), useButton.addEventListener(doc, 'mousedown', closeOnPressOutsideCapture, true), useButton.addEventListener(doc, 'mouseup', handlePressEndCapture, true), useButton.addEventListener(doc, 'touchstart', handleTouchStartCapture, true), useButton.addEventListener(doc, 'touchmove', handleTouchMoveCapture, true), useButton.addEventListener(doc, 'touchend', handleTouchEndCapture, true)));
3855
+ const doc = ownerDocument(floatingElement);
3856
+ const unsubscribe = mergeCleanups(escapeKey$1 && mergeCleanups(addEventListener(doc, 'keydown', closeOnEscapeKeyDown), addEventListener(doc, 'compositionstart', handleCompositionStart), addEventListener(doc, 'compositionend', handleCompositionEnd)), outsidePressEnabled && mergeCleanups(addEventListener(doc, 'click', closeOnPressOutsideCapture, true), addEventListener(doc, 'pointerdown', closeOnPressOutsideCapture, true), addEventListener(doc, 'pointerup', handlePressEndCapture, true), addEventListener(doc, 'pointercancel', handlePressEndCapture, true), addEventListener(doc, 'mousedown', closeOnPressOutsideCapture, true), addEventListener(doc, 'mouseup', handlePressEndCapture, true), addEventListener(doc, 'touchstart', handleTouchStartCapture, true), addEventListener(doc, 'touchmove', handleTouchMoveCapture, true), addEventListener(doc, 'touchend', handleTouchEndCapture, true)));
3237
3857
  return () => {
3238
3858
  unsubscribe();
3239
3859
  compositionTimeout.clear();
@@ -3241,8 +3861,8 @@ function useDismiss(context, props = {}) {
3241
3861
  resetPressStartState();
3242
3862
  suppressNextOutsideClickRef.current = false;
3243
3863
  };
3244
- }, [dataRef, floatingElement, escapeKey, outsidePressEnabled, outsidePress, open, enabled, escapeKeyBubbles, outsidePressBubbles, closeOnEscapeKeyDown, clearInsideReactTree, getOutsidePressEventProp, hasBlockingChild, isEventWithinOwnElements, tree, store, cancelDismissOnEndTimeout]);
3245
- React__namespace.useEffect(clearInsideReactTree, [outsidePress, clearInsideReactTree]);
3864
+ }, [dataRef, floatingElement, escapeKey$1, outsidePressEnabled, outsidePress$1, open, enabled, escapeKeyBubbles, outsidePressBubbles, closeOnEscapeKeyDown, clearInsideReactTree, getOutsidePressEventProp, hasBlockingChild, isEventWithinOwnElements, tree, store, cancelDismissOnEndTimeout]);
3865
+ React__namespace.useEffect(clearInsideReactTree, [outsidePress$1, clearInsideReactTree]);
3246
3866
  const reference = React__namespace.useMemo(() => ({
3247
3867
  onKeyDown: closeOnEscapeKeyDown,
3248
3868
  onPointerDown: closeOnReferencePress,
@@ -3315,7 +3935,7 @@ class FloatingRootStore extends ReactStore {
3315
3935
  if (!newOpen || !this.state.open ||
3316
3936
  // Prevent a pending hover-open from overwriting a click-open event, while allowing
3317
3937
  // click events to upgrade a hover-open.
3318
- event != null && useButton.isClickLikeEvent(event)) {
3938
+ event != null && isClickLikeEvent(event)) {
3319
3939
  this.context.dataRef.current.openEvent = newOpen ? event : undefined;
3320
3940
  }
3321
3941
  };
@@ -3385,14 +4005,14 @@ function useSyncedFloatingRootContext(options) {
3385
4005
  }
3386
4006
  const store = floatingRootContextProp ?? internalStoreRef.current;
3387
4007
  popupStore.useSyncedValue('floatingId', floatingId);
3388
- useButton.useIsoLayoutEffect(() => {
4008
+ useIsoLayoutEffect(() => {
3389
4009
  const valuesToSync = {
3390
4010
  open,
3391
4011
  floatingId,
3392
4012
  referenceElement,
3393
4013
  floatingElement
3394
4014
  };
3395
- if (floatingUi_utils_dom.isElement(referenceElement)) {
4015
+ if (floatingUi_utils.isElement(referenceElement)) {
3396
4016
  valuesToSync.domReferenceElement = referenceElement;
3397
4017
  }
3398
4018
  if (store.state.positionReference === store.state.referenceElement) {
@@ -3407,6 +4027,204 @@ function useSyncedFloatingRootContext(options) {
3407
4027
  return store;
3408
4028
  }
3409
4029
 
4030
+ /**
4031
+ * Provides a status string for CSS animations.
4032
+ * @param open - a boolean that determines if the element is open.
4033
+ * @param enableIdleState - a boolean that enables the `'idle'` state between `'starting'` and `'ending'`
4034
+ */
4035
+ function useTransitionStatus(open, enableIdleState = false, deferEndingState = false) {
4036
+ const [transitionStatus, setTransitionStatus] = React__namespace.useState(open && enableIdleState ? 'idle' : undefined);
4037
+ const [mounted, setMounted] = React__namespace.useState(open);
4038
+ if (open && !mounted) {
4039
+ setMounted(true);
4040
+ setTransitionStatus('starting');
4041
+ }
4042
+ if (!open && mounted && transitionStatus !== 'ending' && !deferEndingState) {
4043
+ setTransitionStatus('ending');
4044
+ }
4045
+ if (!open && !mounted && transitionStatus === 'ending') {
4046
+ setTransitionStatus(undefined);
4047
+ }
4048
+ useIsoLayoutEffect(() => {
4049
+ if (!open && mounted && transitionStatus !== 'ending' && deferEndingState) {
4050
+ const frame = AnimationFrame.request(() => {
4051
+ setTransitionStatus('ending');
4052
+ });
4053
+ return () => {
4054
+ AnimationFrame.cancel(frame);
4055
+ };
4056
+ }
4057
+ return undefined;
4058
+ }, [open, mounted, transitionStatus, deferEndingState]);
4059
+ useIsoLayoutEffect(() => {
4060
+ if (!open || enableIdleState) {
4061
+ return undefined;
4062
+ }
4063
+ const frame = AnimationFrame.request(() => {
4064
+ // Avoid `flushSync` here due to Firefox.
4065
+ // See https://github.com/mui/base-ui/pull/3424
4066
+ setTransitionStatus(undefined);
4067
+ });
4068
+ return () => {
4069
+ AnimationFrame.cancel(frame);
4070
+ };
4071
+ }, [enableIdleState, open]);
4072
+ useIsoLayoutEffect(() => {
4073
+ if (!open || !enableIdleState) {
4074
+ return undefined;
4075
+ }
4076
+ if (open && mounted && transitionStatus !== 'idle') {
4077
+ setTransitionStatus('starting');
4078
+ }
4079
+ const frame = AnimationFrame.request(() => {
4080
+ setTransitionStatus('idle');
4081
+ });
4082
+ return () => {
4083
+ AnimationFrame.cancel(frame);
4084
+ };
4085
+ }, [enableIdleState, open, mounted, transitionStatus]);
4086
+ return {
4087
+ mounted,
4088
+ setMounted,
4089
+ transitionStatus
4090
+ };
4091
+ }
4092
+
4093
+ let TransitionStatusDataAttributes = /*#__PURE__*/function (TransitionStatusDataAttributes) {
4094
+ /**
4095
+ * Present when the component is animating in.
4096
+ */
4097
+ TransitionStatusDataAttributes["startingStyle"] = "data-starting-style";
4098
+ /**
4099
+ * Present when the component is animating out.
4100
+ */
4101
+ TransitionStatusDataAttributes["endingStyle"] = "data-ending-style";
4102
+ return TransitionStatusDataAttributes;
4103
+ }({});
4104
+ const STARTING_HOOK = {
4105
+ [TransitionStatusDataAttributes.startingStyle]: ''
4106
+ };
4107
+ const ENDING_HOOK = {
4108
+ [TransitionStatusDataAttributes.endingStyle]: ''
4109
+ };
4110
+ const transitionStatusMapping = {
4111
+ transitionStatus(value) {
4112
+ if (value === 'starting') {
4113
+ return STARTING_HOOK;
4114
+ }
4115
+ if (value === 'ending') {
4116
+ return ENDING_HOOK;
4117
+ }
4118
+ return null;
4119
+ }
4120
+ };
4121
+
4122
+ /**
4123
+ * Executes a function once all animations have finished on the provided element.
4124
+ * @param elementOrRef - The element to watch for animations.
4125
+ * @param waitForStartingStyleRemoved - Whether to wait for [data-starting-style] to be removed before checking for animations.
4126
+ * @param treatAbortedAsFinished - Whether to treat aborted animations as finished. If `false`, and there are aborted animations,
4127
+ * the function will check again if any new animations have started and wait for them to finish.
4128
+ * @returns A function that takes a callback to execute once all animations have finished, and an optional AbortSignal to abort the callback
4129
+ */
4130
+ function useAnimationsFinished(elementOrRef, waitForStartingStyleRemoved = false, treatAbortedAsFinished = true) {
4131
+ const frame = useAnimationFrame();
4132
+ return useStableCallback((fnToExecute,
4133
+ /**
4134
+ * An optional [AbortSignal](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) that
4135
+ * can be used to abort `fnToExecute` before all the animations have finished.
4136
+ * @default null
4137
+ */
4138
+ signal = null) => {
4139
+ frame.cancel();
4140
+ const element = resolveRef(elementOrRef);
4141
+ if (element == null) {
4142
+ return;
4143
+ }
4144
+ const resolvedElement = element;
4145
+ const done = () => {
4146
+ // Synchronously flush the unmounting of the component so that the browser doesn't
4147
+ // paint: https://github.com/mui/base-ui/issues/979
4148
+ ReactDOM__namespace.flushSync(fnToExecute);
4149
+ };
4150
+ if (typeof resolvedElement.getAnimations !== 'function' || globalThis.BASE_UI_ANIMATIONS_DISABLED) {
4151
+ fnToExecute();
4152
+ return;
4153
+ }
4154
+ function exec() {
4155
+ Promise.all(resolvedElement.getAnimations().map(animation => animation.finished)).then(() => {
4156
+ if (!signal?.aborted) {
4157
+ done();
4158
+ }
4159
+ }).catch(() => {
4160
+ if (treatAbortedAsFinished) {
4161
+ if (!signal?.aborted) {
4162
+ done();
4163
+ }
4164
+ return;
4165
+ }
4166
+ const currentAnimations = resolvedElement.getAnimations();
4167
+ if (!signal?.aborted && currentAnimations.length > 0 && currentAnimations.some(animation => animation.pending || animation.playState !== 'finished')) {
4168
+ // Sometimes animations can be aborted because a property they depend on changes while the animation plays.
4169
+ // In such cases, we need to re-check if any new animations have started.
4170
+ exec();
4171
+ }
4172
+ });
4173
+ }
4174
+ if (waitForStartingStyleRemoved) {
4175
+ const startingStyleAttribute = TransitionStatusDataAttributes.startingStyle;
4176
+
4177
+ // If `[data-starting-style]` isn't present, fall back to waiting one more frame
4178
+ // to give "open" animations a chance to be registered.
4179
+ if (!resolvedElement.hasAttribute(startingStyleAttribute)) {
4180
+ frame.request(exec);
4181
+ return;
4182
+ }
4183
+
4184
+ // Wait for `[data-starting-style]` to have been removed.
4185
+ const attributeObserver = new MutationObserver(() => {
4186
+ if (!resolvedElement.hasAttribute(startingStyleAttribute)) {
4187
+ attributeObserver.disconnect();
4188
+ exec();
4189
+ }
4190
+ });
4191
+ attributeObserver.observe(resolvedElement, {
4192
+ attributes: true,
4193
+ attributeFilter: [startingStyleAttribute]
4194
+ });
4195
+ signal?.addEventListener('abort', () => attributeObserver.disconnect(), {
4196
+ once: true
4197
+ });
4198
+ return;
4199
+ }
4200
+ frame.request(exec);
4201
+ });
4202
+ }
4203
+
4204
+ /**
4205
+ * Calls the provided function when the CSS open/close animation or transition completes.
4206
+ */
4207
+ function useOpenChangeComplete(parameters) {
4208
+ const {
4209
+ enabled = true,
4210
+ open,
4211
+ ref,
4212
+ onComplete: onCompleteParam
4213
+ } = parameters;
4214
+ const onComplete = useStableCallback(onCompleteParam);
4215
+ const runOnceAnimationsFinish = useAnimationsFinished(ref, open, false);
4216
+ React__namespace.useEffect(() => {
4217
+ if (!enabled) {
4218
+ return undefined;
4219
+ }
4220
+ const abortController = new AbortController();
4221
+ runOnceAnimationsFinish(onComplete, abortController.signal);
4222
+ return () => {
4223
+ abortController.abort();
4224
+ };
4225
+ }, [enabled, open, onComplete, runOnceAnimationsFinish]);
4226
+ }
4227
+
3410
4228
  const FOCUSABLE_POPUP_PROPS = {
3411
4229
  tabIndex: -1,
3412
4230
  [FOCUSABLE_ATTRIBUTE]: ''
@@ -3421,7 +4239,7 @@ function createDefaultInitialFocus(popupRef) {
3421
4239
  return interactionType => interactionType === 'touch' ? popupRef.current : true;
3422
4240
  }
3423
4241
  function usePopupStore(externalStore, createStore, treatPopupAsFloatingElement = false) {
3424
- const floatingId = useButton.useId();
4242
+ const floatingId = useId();
3425
4243
  const nested = useFloatingParentNodeId() != null;
3426
4244
  const internalStoreRef = React__namespace.useRef(null);
3427
4245
  if (externalStore === undefined && internalStoreRef.current === null) {
@@ -3529,7 +4347,7 @@ function useInitialOpenSync(store, openProp, defaultOpen, defaultTriggerId) {
3529
4347
  function useTriggerDataForwarding(triggerId, triggerElementRef, store, stateUpdates) {
3530
4348
  const isMountedByThisTrigger = store.useState('isMountedByTrigger', triggerId);
3531
4349
  const baseRegisterTrigger = useTriggerRegistration(triggerId, store);
3532
- const registerTrigger = useButton.useStableCallback(element => {
4350
+ const registerTrigger = useStableCallback(element => {
3533
4351
  baseRegisterTrigger(element);
3534
4352
  if (!element) {
3535
4353
  return;
@@ -3554,7 +4372,7 @@ function useTriggerDataForwarding(triggerId, triggerElementRef, store, stateUpda
3554
4372
  });
3555
4373
  }
3556
4374
  });
3557
- useButton.useIsoLayoutEffect(() => {
4375
+ useIsoLayoutEffect(() => {
3558
4376
  if (isMountedByThisTrigger) {
3559
4377
  store.update({
3560
4378
  activeTriggerElement: triggerElementRef.current,
@@ -3591,7 +4409,7 @@ function useImplicitActiveTrigger(store, options = {}) {
3591
4409
  } = options;
3592
4410
  const open = store.useState('open');
3593
4411
  const reactiveTriggerCount = store.useState('triggerCount');
3594
- useButton.useIsoLayoutEffect(() => {
4412
+ useIsoLayoutEffect(() => {
3595
4413
  if (!open) {
3596
4414
  if (store.state.triggerCount !== 0) {
3597
4415
  store.set('triggerCount', 0);
@@ -3629,7 +4447,7 @@ function useImplicitActiveTrigger(store, options = {}) {
3629
4447
  // Defer so a same-tick replacement trigger with the same id can register first.
3630
4448
  queueMicrotask(() => {
3631
4449
  if (store.select('open') && store.select('activeTriggerId') === lostActiveTriggerId && !store.context.triggerElements.getById(lostActiveTriggerId)) {
3632
- const eventDetails = useButton.createChangeEventDetails(useButton.none);
4450
+ const eventDetails = createChangeEventDetails(none);
3633
4451
  store.setOpen(false, eventDetails);
3634
4452
  // If closing is canceled, keep the previous active trigger ownership for the
3635
4453
  // still-open popup instead of claiming another trigger implicitly.
@@ -3662,7 +4480,7 @@ function useOpenStateTransitions(open, store, onUnmount) {
3662
4480
  mounted,
3663
4481
  setMounted,
3664
4482
  transitionStatus
3665
- } = useButton.useTransitionStatus(open);
4483
+ } = useTransitionStatus(open);
3666
4484
  const preventUnmountingOnClose = store.useState('preventUnmountingOnClose');
3667
4485
  // Opening starts a new close cycle. Clear during render so the close-completion hook below
3668
4486
  // reads the synchronized value on the same pass.
@@ -3672,7 +4490,7 @@ function useOpenStateTransitions(open, store, onUnmount) {
3672
4490
  transitionStatus,
3673
4491
  preventUnmountingOnClose: syncedPreventUnmountingOnClose
3674
4492
  });
3675
- const forceUnmount = useButton.useStableCallback(() => {
4493
+ const forceUnmount = useStableCallback(() => {
3676
4494
  setMounted(false);
3677
4495
  store.update({
3678
4496
  activeTriggerId: null,
@@ -3683,7 +4501,7 @@ function useOpenStateTransitions(open, store, onUnmount) {
3683
4501
  onUnmount?.();
3684
4502
  store.context.onOpenChangeComplete?.(false);
3685
4503
  });
3686
- useButton.useOpenChangeComplete({
4504
+ useOpenChangeComplete({
3687
4505
  enabled: mounted && !open && !syncedPreventUnmountingOnClose,
3688
4506
  open,
3689
4507
  ref: store.context.popupRef,
@@ -3700,7 +4518,7 @@ function useOpenStateTransitions(open, store, onUnmount) {
3700
4518
  }
3701
4519
  function usePopupInteractionProps(store, statePart) {
3702
4520
  store.useSyncedValues(statePart);
3703
- useButton.useIsoLayoutEffect(() => () => {
4521
+ useIsoLayoutEffect(() => () => {
3704
4522
  store.update({
3705
4523
  activeTriggerProps: useRenderElement.EMPTY_OBJECT,
3706
4524
  inactiveTriggerProps: useRenderElement.EMPTY_OBJECT,
@@ -3709,12 +4527,12 @@ function usePopupInteractionProps(store, statePart) {
3709
4527
  }, [store]);
3710
4528
  }
3711
4529
  function usePopupRootSync(store, open) {
3712
- useButton.useIsoLayoutEffect(() => {
4530
+ useIsoLayoutEffect(() => {
3713
4531
  if (!open && store.state.openMethod !== null) {
3714
4532
  store.set('openMethod', null);
3715
4533
  }
3716
4534
  }, [open, store]);
3717
- useButton.useIsoLayoutEffect(() => () => {
4535
+ useIsoLayoutEffect(() => () => {
3718
4536
  if (store.state.openMethod !== null) {
3719
4537
  store.set('openMethod', null);
3720
4538
  }
@@ -3816,6 +4634,15 @@ class PopupTriggerMap {
3816
4634
  }
3817
4635
  }
3818
4636
 
4637
+ /**
4638
+ * Wraps `useId` and prefixes generated `id`s with `base-ui-`
4639
+ * @param {string | undefined} idOverride overrides the generated id when provided
4640
+ * @returns {string | undefined}
4641
+ */
4642
+ function useBaseUiId(idOverride) {
4643
+ return useId(idOverride, 'base-ui');
4644
+ }
4645
+
3819
4646
  /**
3820
4647
  * Provides a cross-browser way to determine the type of the pointer used to click.
3821
4648
  * Safari and Firefox do not provide the PointerEvent to the click handler (they use MouseEvent) yet.
@@ -3852,15 +4679,29 @@ function useEnhancedClickHandler(handler) {
3852
4679
  };
3853
4680
  }
3854
4681
 
4682
+ function useValueChanged(value, onChange) {
4683
+ const valueRef = React__namespace.useRef(value);
4684
+ const onChangeCallback = useStableCallback(onChange);
4685
+ useIsoLayoutEffect(() => {
4686
+ if (valueRef.current === value) {
4687
+ return;
4688
+ }
4689
+ onChangeCallback(valueRef.current);
4690
+ }, [value, onChangeCallback]);
4691
+ useIsoLayoutEffect(() => {
4692
+ valueRef.current = value;
4693
+ }, [value]);
4694
+ }
4695
+
3855
4696
  function useOpenMethodTriggerProps(open, setOpenMethod) {
3856
- const handleTriggerClick = useButton.useStableCallback((_, interactionType) => {
4697
+ const handleTriggerClick = useStableCallback((_, interactionType) => {
3857
4698
  const isOpen = typeof open === 'function' ? open() : open;
3858
4699
  if (!isOpen) {
3859
4700
  setOpenMethod(interactionType || (
3860
4701
  // On iOS Safari, the hitslop around touch targets means tapping outside an element's
3861
4702
  // bounds does not fire `pointerdown` but does fire `mousedown`. The `interactionType`
3862
4703
  // will be "" in that case.
3863
- useButton.ios ? 'touch' : ''));
4704
+ ios ? 'touch' : ''));
3864
4705
  }
3865
4706
  });
3866
4707
  const {
@@ -3881,7 +4722,7 @@ function useOpenMethodTriggerProps(open, setOpenMethod) {
3881
4722
  function useOpenInteractionType(open) {
3882
4723
  const [openMethod, setOpenMethod] = React__namespace.useState(null);
3883
4724
  const triggerProps = useOpenMethodTriggerProps(open, setOpenMethod);
3884
- useButton.useValueChanged(open, previousOpen => {
4725
+ useValueChanged(open, previousOpen => {
3885
4726
  if (previousOpen && !open) {
3886
4727
  setOpenMethod(null);
3887
4728
  }
@@ -3902,6 +4743,228 @@ function useDirection() {
3902
4743
  return context?.direction ?? 'ltr';
3903
4744
  }
3904
4745
 
4746
+ const CompositeRootContext = /*#__PURE__*/React__namespace.createContext(undefined);
4747
+ if (process.env.NODE_ENV !== "production") CompositeRootContext.displayName = "CompositeRootContext";
4748
+ function useCompositeRootContext(optional = false) {
4749
+ const context = React__namespace.useContext(CompositeRootContext);
4750
+ if (context === undefined && !optional) {
4751
+ throw new Error(process.env.NODE_ENV !== "production" ? 'Base UI: CompositeRootContext is missing. Composite parts must be placed within <Composite.Root>.' : useRenderElement.formatErrorMessage(16));
4752
+ }
4753
+ return context;
4754
+ }
4755
+
4756
+ function useFocusableWhenDisabled(parameters) {
4757
+ const {
4758
+ focusableWhenDisabled,
4759
+ disabled,
4760
+ composite = false,
4761
+ tabIndex: tabIndexProp = 0,
4762
+ isNativeButton
4763
+ } = parameters;
4764
+ const isFocusableComposite = composite && focusableWhenDisabled !== false;
4765
+ const isNonFocusableComposite = composite && focusableWhenDisabled === false;
4766
+
4767
+ // we can't explicitly assign `undefined` to any of these props because it
4768
+ // would otherwise prevent subsequently merged props from setting them
4769
+ const props = React__namespace.useMemo(() => {
4770
+ const additionalProps = {
4771
+ // allow Tabbing away from focusableWhenDisabled elements
4772
+ onKeyDown(event) {
4773
+ if (disabled && focusableWhenDisabled && event.key !== 'Tab') {
4774
+ event.preventDefault();
4775
+ }
4776
+ }
4777
+ };
4778
+ if (!composite) {
4779
+ additionalProps.tabIndex = tabIndexProp;
4780
+ if (!isNativeButton && disabled) {
4781
+ additionalProps.tabIndex = focusableWhenDisabled ? tabIndexProp : -1;
4782
+ }
4783
+ }
4784
+ if (isNativeButton && (focusableWhenDisabled || isFocusableComposite) || !isNativeButton && disabled) {
4785
+ additionalProps['aria-disabled'] = disabled;
4786
+ }
4787
+ if (isNativeButton && (!focusableWhenDisabled || isNonFocusableComposite)) {
4788
+ additionalProps.disabled = disabled;
4789
+ }
4790
+ return additionalProps;
4791
+ }, [composite, disabled, focusableWhenDisabled, isFocusableComposite, isNonFocusableComposite, isNativeButton, tabIndexProp]);
4792
+ return {
4793
+ props
4794
+ };
4795
+ }
4796
+
4797
+ function useButton(parameters = {}) {
4798
+ const {
4799
+ disabled = false,
4800
+ focusableWhenDisabled,
4801
+ tabIndex = 0,
4802
+ native: isNativeButton = true,
4803
+ composite: compositeProp
4804
+ } = parameters;
4805
+ const elementRef = React__namespace.useRef(null);
4806
+ const compositeRootContext = useCompositeRootContext(true);
4807
+ const isCompositeItem = compositeProp ?? compositeRootContext !== undefined;
4808
+ const {
4809
+ props: focusableWhenDisabledProps
4810
+ } = useFocusableWhenDisabled({
4811
+ focusableWhenDisabled,
4812
+ disabled,
4813
+ composite: isCompositeItem,
4814
+ tabIndex,
4815
+ isNativeButton
4816
+ });
4817
+ if (process.env.NODE_ENV !== 'production') {
4818
+ // eslint-disable-next-line react-hooks/rules-of-hooks
4819
+ React__namespace.useEffect(() => {
4820
+ if (!elementRef.current) {
4821
+ return;
4822
+ }
4823
+ const isButtonTag = isButtonElement(elementRef.current);
4824
+ if (isNativeButton) {
4825
+ if (!isButtonTag) {
4826
+ const ownerStackMessage = SafeReact.captureOwnerStack?.() || '';
4827
+ const message = 'A component that acts as a button expected a native <button> because the ' + '`nativeButton` prop is true. Rendering a non-<button> removes native button ' + 'semantics, which can impact forms and accessibility. Use a real <button> in the ' + '`render` prop, or set `nativeButton` to `false`.';
4828
+ error(`${message}${ownerStackMessage}`);
4829
+ }
4830
+ } else if (isButtonTag) {
4831
+ const ownerStackMessage = SafeReact.captureOwnerStack?.() || '';
4832
+ const message = 'A component that acts as a button expected a non-<button> because the `nativeButton` ' + 'prop is false. Rendering a <button> keeps native behavior while Base UI applies ' + 'non-native attributes and handlers, which can add unintended extra attributes (such ' + 'as `role` or `aria-disabled`). Use a non-<button> in the `render` prop, or set ' + '`nativeButton` to `true`.';
4833
+ error(`${message}${ownerStackMessage}`);
4834
+ }
4835
+ }, [isNativeButton]);
4836
+ }
4837
+
4838
+ // handles a disabled composite button rendering another button, e.g.
4839
+ // <Toolbar.Button disabled render={<Menu.Trigger />} />
4840
+ // the `disabled` prop needs to pass through 2 `useButton`s then finally
4841
+ // delete the `disabled` attribute from DOM
4842
+ const updateDisabled = React__namespace.useCallback(() => {
4843
+ const element = elementRef.current;
4844
+ if (!isButtonElement(element)) {
4845
+ return;
4846
+ }
4847
+ if (isCompositeItem && disabled && focusableWhenDisabledProps.disabled === undefined && element.disabled) {
4848
+ element.disabled = false;
4849
+ }
4850
+ }, [disabled, focusableWhenDisabledProps.disabled, isCompositeItem]);
4851
+ useIsoLayoutEffect(updateDisabled, [updateDisabled]);
4852
+ const getButtonProps = React__namespace.useCallback((externalProps = {}) => {
4853
+ const {
4854
+ onClick: externalOnClick,
4855
+ onMouseDown: externalOnMouseDown,
4856
+ onKeyUp: externalOnKeyUp,
4857
+ onKeyDown: externalOnKeyDown,
4858
+ onPointerDown: externalOnPointerDown,
4859
+ ...otherExternalProps
4860
+ } = externalProps;
4861
+ return useRenderElement.mergeProps({
4862
+ onClick(event) {
4863
+ if (disabled) {
4864
+ event.preventDefault();
4865
+ return;
4866
+ }
4867
+ externalOnClick?.(event);
4868
+ },
4869
+ onMouseDown(event) {
4870
+ if (!disabled) {
4871
+ externalOnMouseDown?.(event);
4872
+ }
4873
+ },
4874
+ onKeyDown(event) {
4875
+ if (disabled) {
4876
+ return;
4877
+ }
4878
+ useRenderElement.makeEventPreventable(event);
4879
+ externalOnKeyDown?.(event);
4880
+ if (event.baseUIHandlerPrevented) {
4881
+ return;
4882
+ }
4883
+ const isCurrentTarget = event.target === event.currentTarget;
4884
+ const currentTarget = event.currentTarget;
4885
+ const isButton = isButtonElement(currentTarget);
4886
+ const isLink = !isNativeButton && isValidLinkElement(currentTarget);
4887
+ const shouldClick = isCurrentTarget && (isNativeButton ? isButton : !isLink);
4888
+ const isEnterKey = event.key === 'Enter';
4889
+ const isSpaceKey = event.key === ' ';
4890
+ const role = currentTarget.getAttribute('role');
4891
+ const isTextNavigationRole = role?.startsWith('menuitem') || role === 'option' || role === 'gridcell';
4892
+ if (isCurrentTarget && isCompositeItem && isSpaceKey) {
4893
+ if (event.defaultPrevented && isTextNavigationRole) {
4894
+ return;
4895
+ }
4896
+ event.preventDefault();
4897
+ if (isLink || isNativeButton && isButton) {
4898
+ currentTarget.click();
4899
+ event.preventBaseUIHandler();
4900
+ } else if (shouldClick) {
4901
+ externalOnClick?.(event);
4902
+ event.preventBaseUIHandler();
4903
+ }
4904
+ return;
4905
+ }
4906
+
4907
+ // Keyboard accessibility for native and non-native elements.
4908
+ if (shouldClick) {
4909
+ if (!isNativeButton && (isSpaceKey || isEnterKey)) {
4910
+ event.preventDefault();
4911
+ }
4912
+ if (!isNativeButton && isEnterKey) {
4913
+ externalOnClick?.(event);
4914
+ }
4915
+ }
4916
+ },
4917
+ onKeyUp(event) {
4918
+ if (disabled) {
4919
+ return;
4920
+ }
4921
+
4922
+ // calling preventDefault in keyUp on a <button> will not dispatch a click event if Space is pressed
4923
+ // https://codesandbox.io/p/sandbox/button-keyup-preventdefault-dn7f0
4924
+ useRenderElement.makeEventPreventable(event);
4925
+ externalOnKeyUp?.(event);
4926
+ if (event.target === event.currentTarget && isNativeButton && isCompositeItem && isButtonElement(event.currentTarget) && event.key === ' ') {
4927
+ event.preventDefault();
4928
+ return;
4929
+ }
4930
+ if (event.baseUIHandlerPrevented) {
4931
+ return;
4932
+ }
4933
+
4934
+ // Keyboard accessibility for non interactive elements
4935
+ if (event.target === event.currentTarget && !isNativeButton && !isCompositeItem && event.key === ' ') {
4936
+ externalOnClick?.(event);
4937
+ }
4938
+ },
4939
+ onPointerDown(event) {
4940
+ if (disabled) {
4941
+ event.preventDefault();
4942
+ return;
4943
+ }
4944
+ externalOnPointerDown?.(event);
4945
+ }
4946
+ }, isNativeButton ? {
4947
+ type: 'button'
4948
+ } : {
4949
+ role: 'button'
4950
+ }, focusableWhenDisabledProps, otherExternalProps);
4951
+ }, [disabled, focusableWhenDisabledProps, isCompositeItem, isNativeButton]);
4952
+ const buttonRef = useStableCallback(element => {
4953
+ elementRef.current = element;
4954
+ updateDisabled();
4955
+ });
4956
+ return {
4957
+ getButtonProps,
4958
+ buttonRef
4959
+ };
4960
+ }
4961
+ function isButtonElement(elem) {
4962
+ return floatingUi_utils.isHTMLElement(elem) && elem.tagName === 'BUTTON';
4963
+ }
4964
+ function isValidLinkElement(elem) {
4965
+ return Boolean(elem?.tagName === 'A' && elem?.href);
4966
+ }
4967
+
3905
4968
  let CommonPopupDataAttributes = function (CommonPopupDataAttributes) {
3906
4969
  /**
3907
4970
  * Present when the popup is open.
@@ -3914,11 +4977,11 @@ let CommonPopupDataAttributes = function (CommonPopupDataAttributes) {
3914
4977
  /**
3915
4978
  * Present when the popup is animating in.
3916
4979
  */
3917
- CommonPopupDataAttributes[CommonPopupDataAttributes["startingStyle"] = useButton.TransitionStatusDataAttributes.startingStyle] = "startingStyle";
4980
+ CommonPopupDataAttributes[CommonPopupDataAttributes["startingStyle"] = TransitionStatusDataAttributes.startingStyle] = "startingStyle";
3918
4981
  /**
3919
4982
  * Present when the popup is animating out.
3920
4983
  */
3921
- CommonPopupDataAttributes[CommonPopupDataAttributes["endingStyle"] = useButton.TransitionStatusDataAttributes.endingStyle] = "endingStyle";
4984
+ CommonPopupDataAttributes[CommonPopupDataAttributes["endingStyle"] = TransitionStatusDataAttributes.endingStyle] = "endingStyle";
3922
4985
  /**
3923
4986
  * Present when the anchor is hidden.
3924
4987
  */
@@ -4037,8 +5100,8 @@ function hasInsetScrollbars(referenceElement) {
4037
5100
  if (typeof document === 'undefined') {
4038
5101
  return false;
4039
5102
  }
4040
- const doc = useButton.ownerDocument(referenceElement);
4041
- const win = floatingUi_utils_dom.getWindow(doc);
5103
+ const doc = ownerDocument(referenceElement);
5104
+ const win = floatingUi_utils.getWindow(doc);
4042
5105
  return win.innerWidth - doc.documentElement.clientWidth > 0;
4043
5106
  }
4044
5107
  function supportsStableScrollbarGutter(referenceElement) {
@@ -4046,10 +5109,10 @@ function supportsStableScrollbarGutter(referenceElement) {
4046
5109
  if (!supported || typeof document === 'undefined') {
4047
5110
  return false;
4048
5111
  }
4049
- const doc = useButton.ownerDocument(referenceElement);
5112
+ const doc = ownerDocument(referenceElement);
4050
5113
  const html = doc.documentElement;
4051
5114
  const body = doc.body;
4052
- const scrollContainer = floatingUi_utils_dom.isOverflowElement(html) ? html : body;
5115
+ const scrollContainer = floatingUi_utils.isOverflowElement(html) ? html : body;
4053
5116
  const originalScrollContainerOverflowY = scrollContainer.style.overflowY;
4054
5117
  const originalHtmlStyleGutter = html.style.scrollbarGutter;
4055
5118
  html.style.scrollbarGutter = 'stable';
@@ -4062,7 +5125,7 @@ function supportsStableScrollbarGutter(referenceElement) {
4062
5125
  return before === after;
4063
5126
  }
4064
5127
  function preventScrollOverlayScrollbars(referenceElement) {
4065
- const doc = useButton.ownerDocument(referenceElement);
5128
+ const doc = ownerDocument(referenceElement);
4066
5129
  const html = doc.documentElement;
4067
5130
  const body = doc.body;
4068
5131
 
@@ -4070,7 +5133,7 @@ function preventScrollOverlayScrollbars(referenceElement) {
4070
5133
  // won't have any effect.
4071
5134
  // But if <body> has an `overflow` style (like `overflow-x: hidden`), we need to lock it
4072
5135
  // instead, as sticky elements shift otherwise.
4073
- const elementToLock = floatingUi_utils_dom.isOverflowElement(html) ? html : body;
5136
+ const elementToLock = floatingUi_utils.isOverflowElement(html) ? html : body;
4074
5137
  const originalElementToLockStyles = {
4075
5138
  overflowY: elementToLock.style.overflowY,
4076
5139
  overflowX: elementToLock.style.overflowX
@@ -4084,14 +5147,14 @@ function preventScrollOverlayScrollbars(referenceElement) {
4084
5147
  };
4085
5148
  }
4086
5149
  function preventScrollInsetScrollbars(referenceElement) {
4087
- const doc = useButton.ownerDocument(referenceElement);
5150
+ const doc = ownerDocument(referenceElement);
4088
5151
  const html = doc.documentElement;
4089
5152
  const body = doc.body;
4090
- const win = floatingUi_utils_dom.getWindow(html);
5153
+ const win = floatingUi_utils.getWindow(html);
4091
5154
  let scrollTop = 0;
4092
5155
  let scrollLeft = 0;
4093
5156
  let updateGutterOnly = false;
4094
- const resizeFrame = useButton.AnimationFrame.create();
5157
+ const resizeFrame = AnimationFrame.create();
4095
5158
 
4096
5159
  // Pinch-zoom in Safari causes a shift. Just don't lock scroll if there's any pinch-zoom.
4097
5160
  if (webkit && (win.visualViewport?.scale ?? 1) !== 1) {
@@ -4135,7 +5198,7 @@ function preventScrollInsetScrollbars(referenceElement) {
4135
5198
  // with whitespace. Warn if <body> has margins?
4136
5199
  const marginY = parseFloat(bodyStyles.marginTop) + parseFloat(bodyStyles.marginBottom);
4137
5200
  const marginX = parseFloat(bodyStyles.marginLeft) + parseFloat(bodyStyles.marginRight);
4138
- const elementToLock = floatingUi_utils_dom.isOverflowElement(html) ? html : body;
5201
+ const elementToLock = floatingUi_utils.isOverflowElement(html) ? html : body;
4139
5202
  updateGutterOnly = supportsStableScrollbarGutter(referenceElement);
4140
5203
 
4141
5204
  /*
@@ -4188,7 +5251,7 @@ function preventScrollInsetScrollbars(referenceElement) {
4188
5251
  resizeFrame.request(lockScroll);
4189
5252
  }
4190
5253
  lockScroll();
4191
- const unsubscribeResize = useButton.addEventListener(win, 'resize', handleResize);
5254
+ const unsubscribeResize = addEventListener(win, 'resize', handleResize);
4192
5255
  return () => {
4193
5256
  resizeFrame.cancel();
4194
5257
  cleanup();
@@ -4203,8 +5266,8 @@ function preventScrollInsetScrollbars(referenceElement) {
4203
5266
  class ScrollLocker {
4204
5267
  lockCount = 0;
4205
5268
  restore = null;
4206
- timeoutLock = useButton.Timeout.create();
4207
- timeoutUnlock = useButton.Timeout.create();
5269
+ timeoutLock = Timeout.create();
5270
+ timeoutUnlock = Timeout.create();
4208
5271
  acquire(referenceElement) {
4209
5272
  this.lockCount += 1;
4210
5273
  if (this.lockCount === 1 && this.restore === null) {
@@ -4228,16 +5291,16 @@ class ScrollLocker {
4228
5291
  if (this.lockCount === 0 || this.restore !== null) {
4229
5292
  return;
4230
5293
  }
4231
- const doc = useButton.ownerDocument(referenceElement);
5294
+ const doc = ownerDocument(referenceElement);
4232
5295
  const html = doc.documentElement;
4233
- const htmlOverflowY = floatingUi_utils_dom.getWindow(html).getComputedStyle(html).overflowY;
5296
+ const htmlOverflowY = floatingUi_utils.getWindow(html).getComputedStyle(html).overflowY;
4234
5297
 
4235
5298
  // If the site author already hid overflow on <html>, respect it and bail out.
4236
5299
  if (htmlOverflowY === 'hidden' || htmlOverflowY === 'clip') {
4237
5300
  this.restore = useRenderElement.NOOP;
4238
5301
  return;
4239
5302
  }
4240
- const hasOverlayScrollbars = useButton.ios || !hasInsetScrollbars(referenceElement);
5303
+ const hasOverlayScrollbars = ios || !hasInsetScrollbars(referenceElement);
4241
5304
 
4242
5305
  // On iOS, scroll locking does not work if the navbar is collapsed. Due to numerous
4243
5306
  // side effects and bugs that arise on iOS, it must be researched extensively before
@@ -4257,7 +5320,7 @@ const SCROLL_LOCKER = new ScrollLocker();
4257
5320
  * @param referenceElement - Element to use as a reference for lock calculations.
4258
5321
  */
4259
5322
  function useScrollLock(enabled = true, referenceElement = null) {
4260
- useButton.useIsoLayoutEffect(() => {
5323
+ useIsoLayoutEffect(() => {
4261
5324
  if (!enabled) {
4262
5325
  return undefined;
4263
5326
  }
@@ -4287,16 +5350,34 @@ exports.PATIENT_CLICK_THRESHOLD = PATIENT_CLICK_THRESHOLD;
4287
5350
  exports.POPUP_COLLISION_AVOIDANCE = POPUP_COLLISION_AVOIDANCE;
4288
5351
  exports.PopupTriggerMap = PopupTriggerMap;
4289
5352
  exports.ReactStore = ReactStore;
5353
+ exports.SafeReact = SafeReact;
4290
5354
  exports.Store = Store;
4291
5355
  exports.TYPEAHEAD_RESET_MS = TYPEAHEAD_RESET_MS;
5356
+ exports.Timeout = Timeout;
5357
+ exports.TransitionStatusDataAttributes = TransitionStatusDataAttributes;
5358
+ exports.activeElement = activeElement;
5359
+ exports.addEventListener = addEventListener;
5360
+ exports.android = android;
4292
5361
  exports.attachPreventUnmountOnClose = attachPreventUnmountOnClose;
5362
+ exports.cancelOpen = cancelOpen;
5363
+ exports.chipRemovePress = chipRemovePress;
5364
+ exports.clearPress = clearPress;
5365
+ exports.closePress = closePress;
5366
+ exports.closeWatcher = closeWatcher;
5367
+ exports.contains = contains;
4293
5368
  exports.createAttribute = createAttribute;
5369
+ exports.createChangeEventDetails = createChangeEventDetails;
4294
5370
  exports.createDefaultInitialFocus = createDefaultInitialFocus;
5371
+ exports.createGenericEventDetails = createGenericEventDetails;
4295
5372
  exports.createSelector = createSelector;
5373
+ exports.decrementPress = decrementPress;
4296
5374
  exports.enqueueFocus = enqueueFocus;
5375
+ exports.error = error;
5376
+ exports.escapeKey = escapeKey;
4297
5377
  exports.fastComponent = fastComponent;
4298
5378
  exports.fastComponentRef = fastComponentRef;
4299
5379
  exports.findNonDisabledListIndex = findNonDisabledListIndex;
5380
+ exports.focusOut = focusOut;
4300
5381
  exports.gecko = gecko;
4301
5382
  exports.getFloatingFocusElement = getFloatingFocusElement;
4302
5383
  exports.getGridNavigatedIndex = getGridNavigatedIndex;
@@ -4306,30 +5387,69 @@ exports.getNextTabbable = getNextTabbable;
4306
5387
  exports.getNodeChildren = getNodeChildren;
4307
5388
  exports.getTabbableAfterElement = getTabbableAfterElement;
4308
5389
  exports.getTabbableBeforeElement = getTabbableBeforeElement;
5390
+ exports.getTarget = getTarget;
5391
+ exports.imperativeAction = imperativeAction;
5392
+ exports.incrementPress = incrementPress;
4309
5393
  exports.inertValue = inertValue;
5394
+ exports.inputBlur = inputBlur;
5395
+ exports.inputChange = inputChange;
5396
+ exports.inputClear = inputClear;
5397
+ exports.inputPaste = inputPaste;
5398
+ exports.inputPress = inputPress;
5399
+ exports.ios = ios;
4310
5400
  exports.isElementVisible = isElementVisible;
4311
5401
  exports.isIndexOutOfListBounds = isIndexOutOfListBounds;
4312
5402
  exports.isInteractiveElement = isInteractiveElement;
4313
5403
  exports.isListIndexDisabled = isListIndexDisabled;
5404
+ exports.isMouseLikePointerType = isMouseLikePointerType;
4314
5405
  exports.isOutsideEvent = isOutsideEvent;
4315
5406
  exports.isTargetInsideEnabledTrigger = isTargetInsideEnabledTrigger;
4316
5407
  exports.isTypeableCombobox = isTypeableCombobox;
4317
5408
  exports.isTypeableElement = isTypeableElement;
5409
+ exports.isVirtualClick = isVirtualClick;
5410
+ exports.isVirtualPointerEvent = isVirtualPointerEvent;
5411
+ exports.itemPress = itemPress;
5412
+ exports.jsdom = jsdom;
5413
+ exports.keyboard = keyboard;
5414
+ exports.listNavigation = listNavigation;
5415
+ exports.mac = mac;
4318
5416
  exports.matchesFocusVisible = matchesFocusVisible;
4319
5417
  exports.mergeCleanups = mergeCleanups;
5418
+ exports.none = none;
5419
+ exports.outsidePress = outsidePress;
5420
+ exports.ownerDocument = ownerDocument;
5421
+ exports.pointer = pointer;
4320
5422
  exports.popupStateMapping = popupStateMapping;
4321
5423
  exports.pressableTriggerOpenStateMapping = pressableTriggerOpenStateMapping;
5424
+ exports.scrub = scrub;
4322
5425
  exports.setPopupOpenState = setPopupOpenState;
5426
+ exports.siblingOpen = siblingOpen;
5427
+ exports.stopEvent = stopEvent;
5428
+ exports.swipe = swipe;
5429
+ exports.transitionStatusMapping = transitionStatusMapping;
5430
+ exports.triggerFocus = triggerFocus;
5431
+ exports.triggerHover = triggerHover;
4323
5432
  exports.triggerOpenStateMapping = triggerOpenStateMapping;
5433
+ exports.triggerPress = triggerPress;
5434
+ exports.useAnimationFrame = useAnimationFrame;
5435
+ exports.useAnimationsFinished = useAnimationsFinished;
5436
+ exports.useBaseUiId = useBaseUiId;
5437
+ exports.useButton = useButton;
4324
5438
  exports.useClick = useClick;
5439
+ exports.useCompositeRootContext = useCompositeRootContext;
5440
+ exports.useControlled = useControlled;
4325
5441
  exports.useDirection = useDirection;
4326
5442
  exports.useDismiss = useDismiss;
4327
5443
  exports.useFloatingNodeId = useFloatingNodeId;
4328
5444
  exports.useFloatingParentNodeId = useFloatingParentNodeId;
4329
5445
  exports.useFloatingTree = useFloatingTree;
5446
+ exports.useId = useId;
4330
5447
  exports.useImplicitActiveTrigger = useImplicitActiveTrigger;
4331
5448
  exports.useInitialOpenSync = useInitialOpenSync;
5449
+ exports.useIsoLayoutEffect = useIsoLayoutEffect;
4332
5450
  exports.useOnFirstRender = useOnFirstRender;
5451
+ exports.useOnMount = useOnMount;
5452
+ exports.useOpenChangeComplete = useOpenChangeComplete;
4333
5453
  exports.useOpenInteractionType = useOpenInteractionType;
4334
5454
  exports.useOpenMethodTriggerProps = useOpenMethodTriggerProps;
4335
5455
  exports.useOpenStateTransitions = useOpenStateTransitions;
@@ -4337,8 +5457,17 @@ exports.usePopupInteractionProps = usePopupInteractionProps;
4337
5457
  exports.usePopupRootSync = usePopupRootSync;
4338
5458
  exports.usePopupStore = usePopupStore;
4339
5459
  exports.useScrollLock = useScrollLock;
5460
+ exports.useStableCallback = useStableCallback;
4340
5461
  exports.useStore = useStore;
4341
5462
  exports.useSyncedFloatingRootContext = useSyncedFloatingRootContext;
5463
+ exports.useTimeout = useTimeout;
5464
+ exports.useTransitionStatus = useTransitionStatus;
4342
5465
  exports.useTriggerDataForwarding = useTriggerDataForwarding;
4343
5466
  exports.useTriggerRegistration = useTriggerRegistration;
5467
+ exports.useValueAsRef = useValueAsRef;
5468
+ exports.useValueChanged = useValueChanged;
5469
+ exports.visuallyHidden = visuallyHidden;
5470
+ exports.visuallyHiddenInput = visuallyHiddenInput;
4344
5471
  exports.webkit = webkit;
5472
+ exports.wheel = wheel;
5473
+ exports.windowResize = windowResize;