@jobber/components 8.23.0 → 8.23.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/dist/Autocomplete/index.cjs +1 -1
  2. package/dist/Autocomplete/index.mjs +1 -1
  3. package/dist/Card/index.cjs +4 -4
  4. package/dist/Card/index.mjs +4 -4
  5. package/dist/Chip/index.cjs +1 -1
  6. package/dist/Chip/index.mjs +1 -1
  7. package/dist/Chips/InternalChipDismissible/hooks/index.cjs +1 -1
  8. package/dist/Chips/InternalChipDismissible/hooks/index.mjs +1 -1
  9. package/dist/Chips/InternalChipDismissible/index.cjs +1 -1
  10. package/dist/Chips/InternalChipDismissible/index.mjs +1 -1
  11. package/dist/Chips/index.cjs +1 -1
  12. package/dist/Chips/index.mjs +1 -1
  13. package/dist/ComboboxChipRemove-cjs.js +668 -379
  14. package/dist/ComboboxChipRemove-es.js +508 -219
  15. package/dist/ConfirmationModal/index.cjs +1 -1
  16. package/dist/ConfirmationModal/index.mjs +1 -1
  17. package/dist/DataDump/index.cjs +4 -4
  18. package/dist/DataDump/index.mjs +4 -4
  19. package/dist/DataList/components/DataListActions/index.cjs +1 -1
  20. package/dist/DataList/components/DataListActions/index.mjs +1 -1
  21. package/dist/DataList/components/DataListBulkActions/index.cjs +1 -1
  22. package/dist/DataList/components/DataListBulkActions/index.mjs +1 -1
  23. package/dist/DataList/components/DataListFilters/components/DataListSort/index.cjs +1 -1
  24. package/dist/DataList/components/DataListFilters/components/DataListSort/index.mjs +1 -1
  25. package/dist/DataList/components/DataListFilters/index.cjs +1 -1
  26. package/dist/DataList/components/DataListFilters/index.mjs +1 -1
  27. package/dist/DataList/components/DataListHeader/index.cjs +1 -1
  28. package/dist/DataList/components/DataListHeader/index.mjs +1 -1
  29. package/dist/DataList/components/DataListItem/index.cjs +1 -1
  30. package/dist/DataList/components/DataListItem/index.mjs +1 -1
  31. package/dist/DataList/components/DataListItemActions/index.cjs +1 -1
  32. package/dist/DataList/components/DataListItemActions/index.mjs +1 -1
  33. package/dist/DataList/components/DataListItemActionsOverflow/index.cjs +1 -1
  34. package/dist/DataList/components/DataListItemActionsOverflow/index.mjs +1 -1
  35. package/dist/DataList/components/DataListItems/index.cjs +1 -1
  36. package/dist/DataList/components/DataListItems/index.mjs +1 -1
  37. package/dist/DataList/components/DataListLayout/index.cjs +1 -1
  38. package/dist/DataList/components/DataListLayout/index.mjs +1 -1
  39. package/dist/DataList/components/DataListLayoutActions/index.cjs +1 -1
  40. package/dist/DataList/components/DataListLayoutActions/index.mjs +1 -1
  41. package/dist/DataList/index.cjs +1 -1
  42. package/dist/DataList/index.mjs +1 -1
  43. package/dist/DatePicker/index.cjs +1 -1
  44. package/dist/DatePicker/index.mjs +1 -1
  45. package/dist/Dialog/index.cjs +3 -3
  46. package/dist/Dialog/index.mjs +3 -3
  47. package/dist/DrawerDescription-cjs.js +32 -33
  48. package/dist/DrawerDescription-es.js +19 -20
  49. package/dist/DrawerTitle-cjs.js +7 -5
  50. package/dist/DrawerTitle-es.js +7 -5
  51. package/dist/FilterPicker/components/FilterPickerActivator/index.cjs +1 -1
  52. package/dist/FilterPicker/components/FilterPickerActivator/index.mjs +1 -1
  53. package/dist/FilterPicker/components/FilterPickerContent/index.cjs +1 -1
  54. package/dist/FilterPicker/components/FilterPickerContent/index.mjs +1 -1
  55. package/dist/FilterPicker/components/FilterPickerTrigger/index.cjs +1 -1
  56. package/dist/FilterPicker/components/FilterPickerTrigger/index.mjs +1 -1
  57. package/dist/FilterPicker/index.cjs +1 -1
  58. package/dist/FilterPicker/index.mjs +1 -1
  59. package/dist/FormFieldWrapper-cjs.js +2 -2
  60. package/dist/FormFieldWrapper-es.js +2 -2
  61. package/dist/FormatFile/index.cjs +1 -1
  62. package/dist/FormatFile/index.mjs +1 -1
  63. package/dist/Gallery/index.cjs +1 -1
  64. package/dist/Gallery/index.mjs +1 -1
  65. package/dist/InputDate/index.cjs +1 -1
  66. package/dist/InputDate/index.mjs +1 -1
  67. package/dist/InputNumberExperimental-cjs.js +319 -102
  68. package/dist/InputNumberExperimental-es.js +321 -104
  69. package/dist/LightBox/index.cjs +1 -1
  70. package/dist/LightBox/index.mjs +1 -1
  71. package/dist/Menu/index.cjs +4 -4
  72. package/dist/Menu/index.mjs +4 -4
  73. package/dist/MenuSubmenuTrigger-cjs.js +545 -498
  74. package/dist/MenuSubmenuTrigger-es.js +490 -443
  75. package/dist/Modal/index.cjs +1 -1
  76. package/dist/Modal/index.mjs +1 -1
  77. package/dist/NumberFieldInput-cjs.js +609 -496
  78. package/dist/NumberFieldInput-es.js +612 -498
  79. package/dist/Page/index.cjs +4 -4
  80. package/dist/Page/index.mjs +4 -4
  81. package/dist/Popover/index.cjs +1 -1
  82. package/dist/Popover/index.mjs +1 -1
  83. package/dist/ScrollAreaViewport-cjs.js +326 -601
  84. package/dist/ScrollAreaViewport-es.js +278 -548
  85. package/dist/SelectGroupLabel-cjs.js +494 -528
  86. package/dist/SelectGroupLabel-es.js +411 -445
  87. package/dist/Separator-cjs.js +1 -0
  88. package/dist/Separator-es.js +1 -0
  89. package/dist/Tooltip/index.cjs +1 -1
  90. package/dist/Tooltip/index.mjs +1 -1
  91. package/dist/docs/InputTime/InputTime.md +8 -0
  92. package/dist/docs/SelectPrimitive/SelectPrimitive.md +38 -25
  93. package/dist/floating-ui.react-cjs.js +586 -10
  94. package/dist/floating-ui.react-dom-cjs.js +92 -92
  95. package/dist/floating-ui.react-dom-es.js +1 -1
  96. package/dist/floating-ui.react-es.js +580 -4
  97. package/dist/floating-ui.utils-cjs.js +159 -0
  98. package/dist/floating-ui.utils-es.js +136 -0
  99. package/dist/index.cjs +4 -4
  100. package/dist/index.mjs +4 -4
  101. package/dist/{ToolbarRootContext-cjs.js → isElementDisabled-cjs.js} +5 -0
  102. package/dist/{ToolbarRootContext-es.js → isElementDisabled-es.js} +5 -1
  103. package/dist/primitives/BottomSheet/index.cjs +3 -3
  104. package/dist/primitives/BottomSheet/index.mjs +3 -3
  105. package/dist/primitives/ComboboxPrimitive/index.cjs +2 -2
  106. package/dist/primitives/ComboboxPrimitive/index.mjs +2 -2
  107. package/dist/primitives/InputNumberExperimental/index.cjs +1 -1
  108. package/dist/primitives/InputNumberExperimental/index.mjs +1 -1
  109. package/dist/primitives/SelectPrimitive/index.cjs +5 -5
  110. package/dist/primitives/SelectPrimitive/index.mjs +5 -5
  111. package/dist/primitives/index.cjs +4 -4
  112. package/dist/primitives/index.mjs +4 -4
  113. package/dist/resolveAriaLabelledBy-cjs.js +5 -0
  114. package/dist/resolveAriaLabelledBy-es.js +5 -1
  115. package/dist/{CSPContext-cjs.js → scrollEdges-cjs.js} +30 -2
  116. package/dist/{CSPContext-es.js → scrollEdges-es.js} +28 -3
  117. package/dist/styles.css +9 -3
  118. package/dist/unstyledPrimitives/index.cjs +1217 -639
  119. package/dist/unstyledPrimitives/index.mjs +1163 -585
  120. package/dist/useButton-cjs.js +283 -317
  121. package/dist/useButton-es.js +277 -298
  122. package/dist/useCompositeListItem-cjs.js +328 -279
  123. package/dist/useCompositeListItem-es.js +293 -246
  124. package/dist/useLabel-cjs.js +11 -1
  125. package/dist/useLabel-es.js +11 -2
  126. package/dist/useLabelableId-cjs.js +37 -91
  127. package/dist/useLabelableId-es.js +37 -90
  128. package/dist/useRenderElement-cjs.js +81 -26
  129. package/dist/useRenderElement-es.js +81 -27
  130. package/dist/{InternalBackdrop-cjs.js → useScrollLock-cjs.js} +1286 -1220
  131. package/dist/{InternalBackdrop-es.js → useScrollLock-es.js} +1250 -1207
  132. package/package.json +3 -3
  133. package/dist/index.esm-cjs.js +0 -738
  134. package/dist/index.esm-es.js +0 -712
@@ -25,13 +25,102 @@ function _interopNamespaceDefault(e) {
25
25
  var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
26
26
  var ReactDOM__namespace = /*#__PURE__*/_interopNamespaceDefault(ReactDOM);
27
27
 
28
- // https://github.com/mui/material-ui/issues/41190#issuecomment-2040873379
29
- const useInsertionEffect = React__namespace[`useInsertionEffect${Math.random().toFixed(1)}`.slice(0, -3)];
28
+ let set;
29
+ if (process.env.NODE_ENV !== 'production') {
30
+ set = new Set();
31
+ }
32
+ function error(...messages) {
33
+ if (process.env.NODE_ENV !== 'production') {
34
+ const messageKey = messages.join(' ');
35
+ if (!set.has(messageKey)) {
36
+ set.add(messageKey);
37
+ console.error(`Base UI: ${messageKey}`);
38
+ }
39
+ }
40
+ }
41
+
42
+ function useControlled({
43
+ controlled,
44
+ default: defaultProp,
45
+ name,
46
+ state = 'value'
47
+ }) {
48
+ // isControlled is ignored in the hook dependency lists as it should never change.
49
+ const {
50
+ current: isControlled
51
+ } = React__namespace.useRef(controlled !== undefined);
52
+ const [valueState, setValue] = React__namespace.useState(defaultProp);
53
+ const value = isControlled ? controlled : valueState;
54
+ if (process.env.NODE_ENV !== 'production') {
55
+ React__namespace.useEffect(() => {
56
+ if (isControlled !== (controlled !== undefined)) {
57
+ 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'));
58
+ }
59
+ }, [state, name, controlled]);
60
+ const {
61
+ current: defaultValue
62
+ } = React__namespace.useRef(defaultProp);
63
+ React__namespace.useEffect(() => {
64
+ if (!isControlled && serializeToDevModeString(defaultValue) !== serializeToDevModeString(defaultProp)) {
65
+ 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'));
66
+ }
67
+ }, [defaultProp]);
68
+ }
69
+ const setValueIfUncontrolled = React__namespace.useCallback(newValue => {
70
+ if (!isControlled) {
71
+ setValue(newValue);
72
+ }
73
+ }, []);
74
+ return [value, setValueIfUncontrolled];
75
+ }
76
+ function serializeToDevModeString(input) {
77
+ let nextId = 0;
78
+ const seen = new WeakMap();
79
+ try {
80
+ const result = JSON.stringify(input, function replacer(key, value) {
81
+ if (key === '_owner' && this != null && typeof this === 'object' && '$$typeof' in this) {
82
+ return undefined;
83
+ }
84
+ if (typeof value === 'bigint') {
85
+ return `__bigint__:${value}`;
86
+ }
87
+ if (value !== null && typeof value === 'object') {
88
+ const id = seen.get(value);
89
+ if (id !== undefined) {
90
+ return `__object__:${id}`;
91
+ }
92
+ seen.set(value, nextId);
93
+ nextId += 1;
94
+ }
95
+ return value;
96
+ });
97
+ return result ?? `__top__:${typeof input}`;
98
+ } catch {
99
+ return '__unserializable__';
100
+ }
101
+ }
102
+
103
+ const noop = () => {};
104
+ const useIsoLayoutEffect = typeof document !== 'undefined' ? React__namespace.useLayoutEffect : noop;
105
+
106
+ /**
107
+ * A clone of the React namespace for reading APIs that may be missing in older
108
+ * supported React versions. Bundlers can rewrite direct `React.someNewApi`
109
+ * reads into named imports, which breaks React 17. Reading from this cloned
110
+ * object keeps those lookups optional.
111
+ *
112
+ * @see https://github.com/mui/material-ui/issues/41190#issuecomment-2040873379
113
+ */
114
+ const SafeReact = {
115
+ ...React__namespace
116
+ };
117
+
118
+ const useInsertionEffect = SafeReact.useInsertionEffect;
30
119
  const useSafeInsertionEffect =
31
120
  // React 17 doesn't have useInsertionEffect.
32
121
  useInsertionEffect &&
33
122
  // Preact replaces useInsertionEffect with useLayoutEffect and fires too late.
34
- useInsertionEffect !== React__namespace.useLayoutEffect ? useInsertionEffect : fn => fn();
123
+ useInsertionEffect !== SafeReact.useLayoutEffect ? useInsertionEffect : fn => fn();
35
124
  /**
36
125
  * Stabilizes the function passed so it's always the same between renders.
37
126
  *
@@ -61,49 +150,36 @@ function createStableCallback() {
61
150
  }
62
151
  function assertNotCalled() {
63
152
  if (process.env.NODE_ENV !== 'production') {
153
+ // TODO: fix mui/no-guarded-throw
154
+ // eslint-disable-next-line mui/no-guarded-throw
64
155
  throw /* minify-error-disabled */new Error('Base UI: Cannot call an event handler while rendering.');
65
156
  }
66
157
  }
67
158
 
68
- function useControlled({
69
- controlled,
70
- default: defaultProp,
71
- name,
72
- state = 'value'
73
- }) {
74
- // isControlled is ignored in the hook dependency lists as it should never change.
75
- const {
76
- current: isControlled
77
- } = React__namespace.useRef(controlled !== undefined);
78
- const [valueState, setValue] = React__namespace.useState(defaultProp);
79
- const value = isControlled ? controlled : valueState;
80
- if (process.env.NODE_ENV !== 'production') {
81
- React__namespace.useEffect(() => {
82
- if (isControlled !== (controlled !== undefined)) {
83
- console.error([`Base UI: 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'));
84
- }
85
- }, [state, name, controlled]);
86
- const {
87
- current: defaultValue
88
- } = React__namespace.useRef(defaultProp);
89
- React__namespace.useEffect(() => {
90
- // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is for more details.
91
- if (!isControlled && JSON.stringify(defaultValue) !== JSON.stringify(defaultProp)) {
92
- console.error([`Base UI: 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'));
93
- }
94
- }, [JSON.stringify(defaultProp)]);
95
- }
96
- const setValueIfUncontrolled = React__namespace.useCallback(newValue => {
97
- if (!isControlled) {
98
- setValue(newValue);
159
+ /**
160
+ * Untracks the provided value by turning it into a ref to remove its reactivity.
161
+ *
162
+ * Used to access the passed value inside `React.useEffect` without causing the effect to re-run when the value changes.
163
+ */
164
+ function useValueAsRef(value) {
165
+ const latest = useRenderElement.useRefWithInit(createLatestRef, value).current;
166
+ latest.next = value;
167
+
168
+ // eslint-disable-next-line react-hooks/exhaustive-deps
169
+ useIsoLayoutEffect(latest.effect);
170
+ return latest;
171
+ }
172
+ function createLatestRef(value) {
173
+ const latest = {
174
+ current: value,
175
+ next: value,
176
+ effect: () => {
177
+ latest.current = latest.next;
99
178
  }
100
- }, []);
101
- return [value, setValueIfUncontrolled];
179
+ };
180
+ return latest;
102
181
  }
103
182
 
104
- const noop = () => {};
105
- const useIsoLayoutEffect = typeof document !== 'undefined' ? React__namespace.useLayoutEffect : noop;
106
-
107
183
  const visuallyHiddenBase = {
108
184
  clipPath: 'inset(50%)',
109
185
  overflow: 'hidden',
@@ -125,6 +201,21 @@ const visuallyHiddenInput = {
125
201
  position: 'absolute'
126
202
  };
127
203
 
204
+ function ownerDocument(node) {
205
+ return node?.ownerDocument || document;
206
+ }
207
+
208
+ /**
209
+ * Adds an event listener and returns a cleanup function to remove it.
210
+ */
211
+
212
+ function addEventListener(target, type, listener, options) {
213
+ target.addEventListener(type, listener, options);
214
+ return () => {
215
+ target.removeEventListener(type, listener, options);
216
+ };
217
+ }
218
+
128
219
  const EMPTY$2 = [];
129
220
 
130
221
  /**
@@ -281,198 +372,71 @@ function useTimeout() {
281
372
  }
282
373
 
283
374
  /**
284
- * Untracks the provided value by turning it into a ref to remove its reactivity.
375
+ * Reads `navigator.userAgent` / `navigator.platform` (legacy but universally
376
+ * supported) into a normalized shape. In development, prefers the modern
377
+ * `navigator.userAgentData` API on Chromium to avoid DevTools warnings about
378
+ * the deprecated reads; that branch is dead-code-eliminated in production
379
+ * builds to keep the bundle small.
285
380
  *
286
- * Used to access the passed value inside `React.useEffect` without causing the effect to re-run when the value changes.
381
+ * Returns empty/zero values when `navigator` is undefined (SSR), so every
382
+ * derived flag safely evaluates to `false`.
287
383
  */
288
- function useValueAsRef(value) {
289
- const latest = useRenderElement.useRefWithInit(createLatestRef, value).current;
290
- latest.next = value;
291
-
292
- // eslint-disable-next-line react-hooks/exhaustive-deps
293
- useIsoLayoutEffect(latest.effect);
294
- return latest;
295
- }
296
- function createLatestRef(value) {
297
- const latest = {
298
- current: value,
299
- next: value,
300
- effect: () => {
301
- latest.current = latest.next;
302
- }
303
- };
304
- return latest;
305
- }
306
-
307
- const hasNavigator = typeof navigator !== 'undefined';
308
- const nav = getNavigatorData();
309
- const platform = getPlatform();
310
- const userAgent = getUserAgent();
311
- const isWebKit = typeof CSS === 'undefined' || !CSS.supports ? false : CSS.supports('-webkit-backdrop-filter:none');
312
- const isIOS =
313
- // iPads can claim to be MacIntel
314
- nav.platform === 'MacIntel' && nav.maxTouchPoints > 1 ? true : /iP(hone|ad|od)|iOS/.test(nav.platform);
315
- const isFirefox = hasNavigator && /firefox/i.test(userAgent);
316
- const isSafari = hasNavigator && /apple/i.test(navigator.vendor);
317
- const isAndroid = hasNavigator && /android/i.test(platform) || /android/i.test(userAgent);
318
- const isMac = hasNavigator && platform.toLowerCase().startsWith('mac') && !navigator.maxTouchPoints;
319
- const isJSDOM = userAgent.includes('jsdom/');
320
-
321
- // Avoid Chrome DevTools blue warning.
322
- function getNavigatorData() {
323
- if (!hasNavigator) {
384
+ function readRawData() {
385
+ if (typeof navigator === 'undefined') {
324
386
  return {
387
+ userAgent: '',
325
388
  platform: '',
326
- maxTouchPoints: -1
389
+ maxTouchPoints: 0
327
390
  };
328
391
  }
329
- const uaData = navigator.userAgentData;
330
- if (uaData?.platform) {
331
- return {
332
- platform: uaData.platform,
333
- maxTouchPoints: navigator.maxTouchPoints
334
- };
392
+ if (process.env.NODE_ENV !== 'production') {
393
+ const uaData = navigator.userAgentData;
394
+ if (uaData && Array.isArray(uaData.brands)) {
395
+ return {
396
+ userAgent: uaData.brands.map(({
397
+ brand,
398
+ version
399
+ }) => `${brand}/${version}`).join(' '),
400
+ platform: uaData.platform ?? navigator.platform ?? '',
401
+ maxTouchPoints: navigator.maxTouchPoints ?? 0
402
+ };
403
+ }
335
404
  }
336
405
  return {
406
+ userAgent: navigator.userAgent,
337
407
  platform: navigator.platform ?? '',
338
- maxTouchPoints: navigator.maxTouchPoints ?? -1
408
+ maxTouchPoints: navigator.maxTouchPoints ?? 0
339
409
  };
340
410
  }
341
- function getUserAgent() {
342
- if (!hasNavigator) {
343
- return '';
344
- }
345
- const uaData = navigator.userAgentData;
346
- if (uaData && Array.isArray(uaData.brands)) {
347
- return uaData.brands.map(({
348
- brand,
349
- version
350
- }) => `${brand}/${version}`).join(' ');
351
- }
352
- return navigator.userAgent;
353
- }
354
- function getPlatform() {
355
- if (!hasNavigator) {
356
- return '';
357
- }
358
- const uaData = navigator.userAgentData;
359
- if (uaData?.platform) {
360
- return uaData.platform;
361
- }
362
- return navigator.platform ?? '';
363
- }
411
+ const {
412
+ userAgent,
413
+ platform,
414
+ maxTouchPoints
415
+ } = readRawData();
416
+ const lowerUserAgent = userAgent.toLowerCase();
417
+ const lowerPlatform = platform.toLowerCase();
364
418
 
365
- const FOCUSABLE_ATTRIBUTE = 'data-base-ui-focusable';
366
- const ACTIVE_KEY = 'active';
367
- const SELECTED_KEY = 'selected';
368
- const TYPEABLE_SELECTOR = "input:not([type='hidden']):not([disabled])," + "[contenteditable]:not([contenteditable='false']),textarea:not([disabled])";
369
- const ARROW_LEFT = 'ArrowLeft';
370
- const ARROW_RIGHT = 'ArrowRight';
371
- const ARROW_UP = 'ArrowUp';
372
- const ARROW_DOWN = 'ArrowDown';
419
+ // iPadOS 13+ reports `MacIntel` for `navigator.platform`; disambiguated via
420
+ // `maxTouchPoints` so iPad is classified as iOS, not macOS.
421
+ // https://github.com/mui/base-ui/issues/1309
422
+ /** iPhone, iPad (including iPadOS 13+ reporting as macOS), iPod. */
423
+ const ios = /^i(os$|p)/.test(lowerPlatform) || lowerPlatform === 'macintel' && maxTouchPoints > 1;
373
424
 
374
- function activeElement(doc) {
375
- let element = doc.activeElement;
376
- while (element?.shadowRoot?.activeElement != null) {
377
- element = element.shadowRoot.activeElement;
378
- }
379
- return element;
380
- }
381
- function contains(parent, child) {
382
- if (!parent || !child) {
383
- return false;
384
- }
385
- const rootNode = child.getRootNode?.();
425
+ /** Android phones, tablets, and embedded Android browsers. */
426
+ const ANDROID_STRING = 'android';
427
+ const android = lowerPlatform === ANDROID_STRING || lowerUserAgent.includes(ANDROID_STRING);
386
428
 
387
- // First, attempt with faster native method
388
- if (parent.contains(child)) {
389
- return true;
390
- }
429
+ /** macOS desktop. Excludes iPadOS, which reports as `MacIntel`. */
430
+ const mac = !ios && lowerPlatform.startsWith('mac');
391
431
 
392
- // then fallback to custom implementation with Shadow DOM support
393
- if (rootNode && floatingUi_utils_dom.isShadowRoot(rootNode)) {
394
- let next = child;
395
- while (next) {
396
- if (parent === next) {
397
- return true;
398
- }
399
- next = next.parentNode || next.host;
400
- }
401
- }
402
-
403
- // Give up, the result is false
404
- return false;
405
- }
406
- function isTargetInsideEnabledTrigger(target, triggerElements) {
407
- if (!floatingUi_utils_dom.isElement(target)) {
408
- return false;
409
- }
410
- const targetElement = target;
411
- if (triggerElements.hasElement(targetElement)) {
412
- return !targetElement.hasAttribute('data-trigger-disabled');
413
- }
414
- for (const [, trigger] of triggerElements.entries()) {
415
- if (contains(trigger, targetElement)) {
416
- return !trigger.hasAttribute('data-trigger-disabled');
417
- }
418
- }
419
- return false;
420
- }
421
- function getTarget(event) {
422
- if ('composedPath' in event) {
423
- return event.composedPath()[0];
424
- }
432
+ /** Windows desktop. */
433
+ lowerPlatform.startsWith('win');
425
434
 
426
- // TS thinks `event` is of type never as it assumes all browsers support
427
- // `composedPath()`, but browsers without shadow DOM don't.
428
- return event.target;
429
- }
430
- function isEventTargetWithin(event, node) {
431
- if (node == null) {
432
- return false;
433
- }
434
- if ('composedPath' in event) {
435
- return event.composedPath().includes(node);
436
- }
435
+ /** Any Apple OS (`mac || ios`). */
436
+ const apple = mac || ios;
437
437
 
438
- // TS thinks `event` is of type never as it assumes all browsers support composedPath, but browsers without shadow dom don't
439
- const eventAgain = event;
440
- return eventAgain.target != null && node.contains(eventAgain.target);
441
- }
442
- function isRootElement(element) {
443
- return element.matches('html,body');
444
- }
445
- function isTypeableElement(element) {
446
- return floatingUi_utils_dom.isHTMLElement(element) && element.matches(TYPEABLE_SELECTOR);
447
- }
448
- function isTypeableCombobox(element) {
449
- if (!element) {
450
- return false;
451
- }
452
- return element.getAttribute('role') === 'combobox' && isTypeableElement(element);
453
- }
454
- function matchesFocusVisible(element) {
455
- // We don't want to block focus from working with `visibleOnly`
456
- // (JSDOM doesn't match `:focus-visible` when the element has `:focus`)
457
- if (!element || isJSDOM) {
458
- return true;
459
- }
460
- try {
461
- return element.matches(':focus-visible');
462
- } catch (_e) {
463
- return true;
464
- }
465
- }
466
- function getFloatingFocusElement(floatingElement) {
467
- if (!floatingElement) {
468
- return null;
469
- }
470
- // Try to find the element that has `{...getFloatingProps()}` spread on it.
471
- // This indicates the floating element is acting as a positioning wrapper, and
472
- // so focus should be managed on the child element with the event handlers and
473
- // aria props.
474
- return floatingElement.hasAttribute(FOCUSABLE_ATTRIBUTE) ? floatingElement : floatingElement.querySelector(`[${FOCUSABLE_ATTRIBUTE}]`) || floatingElement;
475
- }
438
+ /** Running in jsdom or HappyDOM (used by unit tests). */
439
+ const jsdom = /jsdom|happydom/.test(lowerUserAgent);
476
440
 
477
441
  function stopEvent(event) {
478
442
  event.preventDefault();
@@ -487,16 +451,16 @@ function isVirtualClick(event) {
487
451
  if (event.pointerType === '' && event.isTrusted) {
488
452
  return true;
489
453
  }
490
- if (isAndroid && event.pointerType) {
454
+ if (android && event.pointerType) {
491
455
  return event.type === 'click' && event.buttons === 1;
492
456
  }
493
457
  return event.detail === 0 && !event.pointerType;
494
458
  }
495
459
  function isVirtualPointerEvent(event) {
496
- if (isJSDOM) {
460
+ if (jsdom) {
497
461
  return false;
498
462
  }
499
- return !isAndroid && event.width === 0 && event.height === 0 || isAndroid && event.width === 1 && event.height === 1 && event.pressure === 0 && event.detail === 0 && event.pointerType === 'mouse' ||
463
+ return !android && event.width === 0 && event.height === 0 || android && event.width === 1 && event.height === 1 && event.pressure === 0 && event.detail === 0 && event.pointerType === 'mouse' ||
500
464
  // iOS VoiceOver returns 0.333• for width/height.
501
465
  event.width < 1 && event.height < 1 && event.pressure === 0 && event.detail === 0 && event.pointerType === 'touch';
502
466
  }
@@ -514,8 +478,44 @@ function isClickLikeEvent(event) {
514
478
  return type === 'click' || type === 'mousedown' || type === 'keydown' || type === 'keyup';
515
479
  }
516
480
 
517
- function ownerDocument(node) {
518
- return node?.ownerDocument || document;
481
+ function activeElement(doc) {
482
+ let element = doc.activeElement;
483
+ while (element?.shadowRoot?.activeElement != null) {
484
+ element = element.shadowRoot.activeElement;
485
+ }
486
+ return element;
487
+ }
488
+ function contains(parent, child) {
489
+ if (!parent || !child) {
490
+ return false;
491
+ }
492
+ const rootNode = child.getRootNode?.();
493
+
494
+ // First, attempt with the faster native method.
495
+ if (parent.contains(child)) {
496
+ return true;
497
+ }
498
+
499
+ // Then fall back to traversing out of shadow roots when needed.
500
+ if (rootNode && floatingUi_utils_dom.isShadowRoot(rootNode)) {
501
+ let next = child;
502
+ while (next) {
503
+ if (parent === next) {
504
+ return true;
505
+ }
506
+ next = next.parentNode || next.host;
507
+ }
508
+ }
509
+ return false;
510
+ }
511
+ function getTarget(event) {
512
+ if ('composedPath' in event) {
513
+ return event.composedPath()[0];
514
+ }
515
+
516
+ // TS assumes `composedPath()` always exists, but older browsers without
517
+ // shadow DOM support still fall back to `target`.
518
+ return event.target;
519
519
  }
520
520
 
521
521
  const none = 'none';
@@ -540,6 +540,7 @@ const closeWatcher = 'close-watcher';
540
540
  const listNavigation = 'list-navigation';
541
541
  const keyboard = 'keyboard';
542
542
  const pointer = 'pointer';
543
+ const wheel = 'wheel';
543
544
  const scrub = 'scrub';
544
545
  const cancelOpen = 'cancel-open';
545
546
  const siblingOpen = 'sibling-open';
@@ -597,11 +598,6 @@ function createGenericEventDetails(reason, event, customProperties) {
597
598
  return details;
598
599
  }
599
600
 
600
- // https://github.com/mui/material-ui/issues/41190#issuecomment-2040873379
601
- const SafeReact = {
602
- ...React__namespace
603
- };
604
-
605
601
  let globalId = 0;
606
602
 
607
603
  // TODO React 17: Remove `useGlobalId` once React 17 support is removed
@@ -706,12 +702,12 @@ function useTransitionStatus(open, enableIdleState = false, deferEndingState = f
706
702
  return () => {
707
703
  AnimationFrame.cancel(frame);
708
704
  };
709
- }, [enableIdleState, open, mounted, setTransitionStatus, transitionStatus]);
710
- return React__namespace.useMemo(() => ({
705
+ }, [enableIdleState, open, mounted, transitionStatus]);
706
+ return {
711
707
  mounted,
712
708
  setMounted,
713
709
  transitionStatus
714
- }), [mounted, transitionStatus]);
710
+ };
715
711
  }
716
712
 
717
713
  let TransitionStatusDataAttributes = /*#__PURE__*/function (TransitionStatusDataAttributes) {
@@ -761,70 +757,67 @@ function useAnimationsFinished(elementOrRef, waitForStartingStyleRemoved = false
761
757
  */
762
758
  signal = null) => {
763
759
  frame.cancel();
764
- function done() {
765
- // Synchronously flush the unmounting of the component so that the browser doesn't
766
- // paint: https://github.com/mui/base-ui/issues/979
767
- ReactDOM__namespace.flushSync(fnToExecute);
768
- }
769
760
  const element = resolveRef(elementOrRef);
770
761
  if (element == null) {
771
762
  return;
772
763
  }
773
764
  const resolvedElement = element;
765
+ const done = () => {
766
+ // Synchronously flush the unmounting of the component so that the browser doesn't
767
+ // paint: https://github.com/mui/base-ui/issues/979
768
+ ReactDOM__namespace.flushSync(fnToExecute);
769
+ };
774
770
  if (typeof resolvedElement.getAnimations !== 'function' || globalThis.BASE_UI_ANIMATIONS_DISABLED) {
775
771
  fnToExecute();
776
- } else {
777
- function execWaitForStartingStyleRemoved() {
778
- const startingStyleAttribute = TransitionStatusDataAttributes.startingStyle;
779
-
780
- // If `[data-starting-style]` isn't present, fall back to waiting one more frame
781
- // to give "open" animations a chance to be registered.
782
- if (!resolvedElement.hasAttribute(startingStyleAttribute)) {
783
- frame.request(exec);
784
- return;
785
- }
786
-
787
- // Wait for `[data-starting-style]` to have been removed.
788
- const attributeObserver = new MutationObserver(() => {
789
- if (!resolvedElement.hasAttribute(startingStyleAttribute)) {
790
- attributeObserver.disconnect();
791
- exec();
792
- }
793
- });
794
- attributeObserver.observe(resolvedElement, {
795
- attributes: true,
796
- attributeFilter: [startingStyleAttribute]
797
- });
798
- signal?.addEventListener('abort', () => attributeObserver.disconnect(), {
799
- once: true
800
- });
801
- }
802
- function exec() {
803
- Promise.all(resolvedElement.getAnimations().map(anim => anim.finished)).then(() => {
804
- if (signal?.aborted) {
805
- return;
806
- }
772
+ return;
773
+ }
774
+ function exec() {
775
+ Promise.all(resolvedElement.getAnimations().map(animation => animation.finished)).then(() => {
776
+ if (!signal?.aborted) {
807
777
  done();
808
- }).catch(() => {
809
- const currentAnimations = resolvedElement.getAnimations();
810
- if (treatAbortedAsFinished) {
811
- if (signal?.aborted) {
812
- return;
813
- }
778
+ }
779
+ }).catch(() => {
780
+ if (treatAbortedAsFinished) {
781
+ if (!signal?.aborted) {
814
782
  done();
815
- } else if (currentAnimations.length > 0 && currentAnimations.some(anim => anim.pending || anim.playState !== 'finished')) {
816
- // Sometimes animations can be aborted because a property they depend on changes while the animation plays.
817
- // In such cases, we need to re-check if any new animations have started.
818
- exec();
819
783
  }
820
- });
821
- }
822
- if (waitForStartingStyleRemoved) {
823
- execWaitForStartingStyleRemoved();
784
+ return;
785
+ }
786
+ const currentAnimations = resolvedElement.getAnimations();
787
+ if (!signal?.aborted && currentAnimations.length > 0 && currentAnimations.some(animation => animation.pending || animation.playState !== 'finished')) {
788
+ // Sometimes animations can be aborted because a property they depend on changes while the animation plays.
789
+ // In such cases, we need to re-check if any new animations have started.
790
+ exec();
791
+ }
792
+ });
793
+ }
794
+ if (waitForStartingStyleRemoved) {
795
+ const startingStyleAttribute = TransitionStatusDataAttributes.startingStyle;
796
+
797
+ // If `[data-starting-style]` isn't present, fall back to waiting one more frame
798
+ // to give "open" animations a chance to be registered.
799
+ if (!resolvedElement.hasAttribute(startingStyleAttribute)) {
800
+ frame.request(exec);
824
801
  return;
825
802
  }
826
- frame.request(exec);
803
+
804
+ // Wait for `[data-starting-style]` to have been removed.
805
+ const attributeObserver = new MutationObserver(() => {
806
+ if (!resolvedElement.hasAttribute(startingStyleAttribute)) {
807
+ attributeObserver.disconnect();
808
+ exec();
809
+ }
810
+ });
811
+ attributeObserver.observe(resolvedElement, {
812
+ attributes: true,
813
+ attributeFilter: [startingStyleAttribute]
814
+ });
815
+ signal?.addEventListener('abort', () => attributeObserver.disconnect(), {
816
+ once: true
817
+ });
818
+ return;
827
819
  }
820
+ frame.request(exec);
828
821
  });
829
822
  }
830
823
 
@@ -875,20 +868,6 @@ function useValueChanged(value, onChange) {
875
868
  }, [value]);
876
869
  }
877
870
 
878
- let set;
879
- if (process.env.NODE_ENV !== 'production') {
880
- set = new Set();
881
- }
882
- function error(...messages) {
883
- if (process.env.NODE_ENV !== 'production') {
884
- const messageKey = messages.join(' ');
885
- if (!set.has(messageKey)) {
886
- set.add(messageKey);
887
- console.error(`Base UI: ${messageKey}`);
888
- }
889
- }
890
- }
891
-
892
871
  const CompositeRootContext = /*#__PURE__*/React__namespace.createContext(undefined);
893
872
  if (process.env.NODE_ENV !== "production") CompositeRootContext.displayName = "CompositeRootContext";
894
873
  function useCompositeRootContext(optional = false) {
@@ -1004,9 +983,7 @@ function useButton(parameters = {}) {
1004
983
  onPointerDown: externalOnPointerDown,
1005
984
  ...otherExternalProps
1006
985
  } = externalProps;
1007
- const type = isNativeButton ? 'button' : undefined;
1008
986
  return useRenderElement.mergeProps({
1009
- type,
1010
987
  onClick(event) {
1011
988
  if (disabled) {
1012
989
  event.preventDefault();
@@ -1091,9 +1068,11 @@ function useButton(parameters = {}) {
1091
1068
  }
1092
1069
  externalOnPointerDown?.(event);
1093
1070
  }
1094
- }, !isNativeButton ? {
1071
+ }, isNativeButton ? {
1072
+ type: 'button'
1073
+ } : {
1095
1074
  role: 'button'
1096
- } : undefined, focusableWhenDisabledProps, otherExternalProps);
1075
+ }, focusableWhenDisabledProps, otherExternalProps);
1097
1076
  }, [disabled, focusableWhenDisabledProps, isCompositeItem, isNativeButton]);
1098
1077
  const buttonRef = useStableCallback(element => {
1099
1078
  elementRef.current = element;
@@ -1111,19 +1090,14 @@ function isValidLinkElement(elem) {
1111
1090
  return Boolean(elem?.tagName === 'A' && elem?.href);
1112
1091
  }
1113
1092
 
1114
- exports.ACTIVE_KEY = ACTIVE_KEY;
1115
- exports.ARROW_DOWN = ARROW_DOWN;
1116
- exports.ARROW_LEFT = ARROW_LEFT;
1117
- exports.ARROW_RIGHT = ARROW_RIGHT;
1118
- exports.ARROW_UP = ARROW_UP;
1119
1093
  exports.AnimationFrame = AnimationFrame;
1120
- exports.FOCUSABLE_ATTRIBUTE = FOCUSABLE_ATTRIBUTE;
1121
- exports.SELECTED_KEY = SELECTED_KEY;
1122
1094
  exports.SafeReact = SafeReact;
1123
- exports.TYPEABLE_SELECTOR = TYPEABLE_SELECTOR;
1124
1095
  exports.Timeout = Timeout;
1125
1096
  exports.TransitionStatusDataAttributes = TransitionStatusDataAttributes;
1126
1097
  exports.activeElement = activeElement;
1098
+ exports.addEventListener = addEventListener;
1099
+ exports.android = android;
1100
+ exports.apple = apple;
1127
1101
  exports.cancelOpen = cancelOpen;
1128
1102
  exports.chipRemovePress = chipRemovePress;
1129
1103
  exports.clearPress = clearPress;
@@ -1136,7 +1110,6 @@ exports.decrementPress = decrementPress;
1136
1110
  exports.error = error;
1137
1111
  exports.escapeKey = escapeKey;
1138
1112
  exports.focusOut = focusOut;
1139
- exports.getFloatingFocusElement = getFloatingFocusElement;
1140
1113
  exports.getTarget = getTarget;
1141
1114
  exports.imperativeAction = imperativeAction;
1142
1115
  exports.incrementPress = incrementPress;
@@ -1145,26 +1118,18 @@ exports.inputChange = inputChange;
1145
1118
  exports.inputClear = inputClear;
1146
1119
  exports.inputPaste = inputPaste;
1147
1120
  exports.inputPress = inputPress;
1148
- exports.isAndroid = isAndroid;
1121
+ exports.ios = ios;
1149
1122
  exports.isClickLikeEvent = isClickLikeEvent;
1150
- exports.isEventTargetWithin = isEventTargetWithin;
1151
- exports.isFirefox = isFirefox;
1152
- exports.isIOS = isIOS;
1153
- exports.isMac = isMac;
1154
1123
  exports.isMouseLikePointerType = isMouseLikePointerType;
1155
1124
  exports.isReactEvent = isReactEvent;
1156
- exports.isRootElement = isRootElement;
1157
- exports.isSafari = isSafari;
1158
- exports.isTargetInsideEnabledTrigger = isTargetInsideEnabledTrigger;
1159
- exports.isTypeableCombobox = isTypeableCombobox;
1160
- exports.isTypeableElement = isTypeableElement;
1161
1125
  exports.isVirtualClick = isVirtualClick;
1162
1126
  exports.isVirtualPointerEvent = isVirtualPointerEvent;
1163
- exports.isWebKit = isWebKit;
1164
1127
  exports.itemPress = itemPress;
1128
+ exports.jsdom = jsdom;
1165
1129
  exports.keyboard = keyboard;
1166
1130
  exports.listNavigation = listNavigation;
1167
- exports.matchesFocusVisible = matchesFocusVisible;
1131
+ exports.lowerUserAgent = lowerUserAgent;
1132
+ exports.mac = mac;
1168
1133
  exports.none = none;
1169
1134
  exports.outsidePress = outsidePress;
1170
1135
  exports.ownerDocument = ownerDocument;
@@ -1195,4 +1160,5 @@ exports.useValueAsRef = useValueAsRef;
1195
1160
  exports.useValueChanged = useValueChanged;
1196
1161
  exports.visuallyHidden = visuallyHidden;
1197
1162
  exports.visuallyHiddenInput = visuallyHiddenInput;
1163
+ exports.wheel = wheel;
1198
1164
  exports.windowResize = windowResize;