@jobber/components 8.23.0 → 8.23.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/dist/Autocomplete/index.cjs +1 -1
  2. package/dist/Autocomplete/index.mjs +1 -1
  3. package/dist/Card/index.cjs +4 -4
  4. package/dist/Card/index.mjs +4 -4
  5. package/dist/Chip/index.cjs +1 -1
  6. package/dist/Chip/index.mjs +1 -1
  7. package/dist/Chips/InternalChipDismissible/hooks/index.cjs +1 -1
  8. package/dist/Chips/InternalChipDismissible/hooks/index.mjs +1 -1
  9. package/dist/Chips/InternalChipDismissible/index.cjs +1 -1
  10. package/dist/Chips/InternalChipDismissible/index.mjs +1 -1
  11. package/dist/Chips/index.cjs +1 -1
  12. package/dist/Chips/index.mjs +1 -1
  13. package/dist/ComboboxChipRemove-cjs.js +668 -379
  14. package/dist/ComboboxChipRemove-es.js +508 -219
  15. package/dist/ConfirmationModal/index.cjs +1 -1
  16. package/dist/ConfirmationModal/index.mjs +1 -1
  17. package/dist/DataDump/index.cjs +4 -4
  18. package/dist/DataDump/index.mjs +4 -4
  19. package/dist/DataList/components/DataListActions/index.cjs +1 -1
  20. package/dist/DataList/components/DataListActions/index.mjs +1 -1
  21. package/dist/DataList/components/DataListBulkActions/index.cjs +1 -1
  22. package/dist/DataList/components/DataListBulkActions/index.mjs +1 -1
  23. package/dist/DataList/components/DataListFilters/components/DataListSort/index.cjs +1 -1
  24. package/dist/DataList/components/DataListFilters/components/DataListSort/index.mjs +1 -1
  25. package/dist/DataList/components/DataListFilters/index.cjs +1 -1
  26. package/dist/DataList/components/DataListFilters/index.mjs +1 -1
  27. package/dist/DataList/components/DataListHeader/index.cjs +1 -1
  28. package/dist/DataList/components/DataListHeader/index.mjs +1 -1
  29. package/dist/DataList/components/DataListItem/index.cjs +1 -1
  30. package/dist/DataList/components/DataListItem/index.mjs +1 -1
  31. package/dist/DataList/components/DataListItemActions/index.cjs +1 -1
  32. package/dist/DataList/components/DataListItemActions/index.mjs +1 -1
  33. package/dist/DataList/components/DataListItemActionsOverflow/index.cjs +1 -1
  34. package/dist/DataList/components/DataListItemActionsOverflow/index.mjs +1 -1
  35. package/dist/DataList/components/DataListItems/index.cjs +1 -1
  36. package/dist/DataList/components/DataListItems/index.mjs +1 -1
  37. package/dist/DataList/components/DataListLayout/index.cjs +1 -1
  38. package/dist/DataList/components/DataListLayout/index.mjs +1 -1
  39. package/dist/DataList/components/DataListLayoutActions/index.cjs +1 -1
  40. package/dist/DataList/components/DataListLayoutActions/index.mjs +1 -1
  41. package/dist/DataList/index.cjs +1 -1
  42. package/dist/DataList/index.mjs +1 -1
  43. package/dist/DatePicker/index.cjs +1 -1
  44. package/dist/DatePicker/index.mjs +1 -1
  45. package/dist/Dialog/index.cjs +3 -3
  46. package/dist/Dialog/index.mjs +3 -3
  47. package/dist/DrawerDescription-cjs.js +32 -33
  48. package/dist/DrawerDescription-es.js +19 -20
  49. package/dist/DrawerTitle-cjs.js +7 -5
  50. package/dist/DrawerTitle-es.js +7 -5
  51. package/dist/FilterPicker/components/FilterPickerActivator/index.cjs +1 -1
  52. package/dist/FilterPicker/components/FilterPickerActivator/index.mjs +1 -1
  53. package/dist/FilterPicker/components/FilterPickerContent/index.cjs +1 -1
  54. package/dist/FilterPicker/components/FilterPickerContent/index.mjs +1 -1
  55. package/dist/FilterPicker/components/FilterPickerTrigger/index.cjs +1 -1
  56. package/dist/FilterPicker/components/FilterPickerTrigger/index.mjs +1 -1
  57. package/dist/FilterPicker/index.cjs +1 -1
  58. package/dist/FilterPicker/index.mjs +1 -1
  59. package/dist/FormFieldWrapper-cjs.js +2 -2
  60. package/dist/FormFieldWrapper-es.js +2 -2
  61. package/dist/FormatFile/index.cjs +1 -1
  62. package/dist/FormatFile/index.mjs +1 -1
  63. package/dist/Gallery/index.cjs +1 -1
  64. package/dist/Gallery/index.mjs +1 -1
  65. package/dist/InputDate/index.cjs +1 -1
  66. package/dist/InputDate/index.mjs +1 -1
  67. package/dist/InputNumberExperimental-cjs.js +319 -102
  68. package/dist/InputNumberExperimental-es.js +321 -104
  69. package/dist/LightBox/index.cjs +1 -1
  70. package/dist/LightBox/index.mjs +1 -1
  71. package/dist/Menu/index.cjs +4 -4
  72. package/dist/Menu/index.mjs +4 -4
  73. package/dist/MenuSubmenuTrigger-cjs.js +545 -498
  74. package/dist/MenuSubmenuTrigger-es.js +490 -443
  75. package/dist/Modal/index.cjs +1 -1
  76. package/dist/Modal/index.mjs +1 -1
  77. package/dist/NumberFieldInput-cjs.js +609 -496
  78. package/dist/NumberFieldInput-es.js +612 -498
  79. package/dist/Page/index.cjs +4 -4
  80. package/dist/Page/index.mjs +4 -4
  81. package/dist/Popover/index.cjs +1 -1
  82. package/dist/Popover/index.mjs +1 -1
  83. package/dist/ScrollAreaViewport-cjs.js +326 -601
  84. package/dist/ScrollAreaViewport-es.js +278 -548
  85. package/dist/SelectGroupLabel-cjs.js +494 -528
  86. package/dist/SelectGroupLabel-es.js +411 -445
  87. package/dist/Separator-cjs.js +1 -0
  88. package/dist/Separator-es.js +1 -0
  89. package/dist/Tooltip/index.cjs +1 -1
  90. package/dist/Tooltip/index.mjs +1 -1
  91. package/dist/docs/InputTime/InputTime.md +8 -0
  92. package/dist/docs/SelectPrimitive/SelectPrimitive.md +38 -25
  93. package/dist/floating-ui.react-cjs.js +586 -10
  94. package/dist/floating-ui.react-dom-cjs.js +92 -92
  95. package/dist/floating-ui.react-dom-es.js +1 -1
  96. package/dist/floating-ui.react-es.js +580 -4
  97. package/dist/floating-ui.utils-cjs.js +159 -0
  98. package/dist/floating-ui.utils-es.js +136 -0
  99. package/dist/index.cjs +4 -4
  100. package/dist/index.mjs +4 -4
  101. package/dist/{ToolbarRootContext-cjs.js → isElementDisabled-cjs.js} +5 -0
  102. package/dist/{ToolbarRootContext-es.js → isElementDisabled-es.js} +5 -1
  103. package/dist/primitives/BottomSheet/index.cjs +3 -3
  104. package/dist/primitives/BottomSheet/index.mjs +3 -3
  105. package/dist/primitives/ComboboxPrimitive/index.cjs +2 -2
  106. package/dist/primitives/ComboboxPrimitive/index.mjs +2 -2
  107. package/dist/primitives/InputNumberExperimental/index.cjs +1 -1
  108. package/dist/primitives/InputNumberExperimental/index.mjs +1 -1
  109. package/dist/primitives/SelectPrimitive/index.cjs +5 -5
  110. package/dist/primitives/SelectPrimitive/index.mjs +5 -5
  111. package/dist/primitives/index.cjs +4 -4
  112. package/dist/primitives/index.mjs +4 -4
  113. package/dist/resolveAriaLabelledBy-cjs.js +5 -0
  114. package/dist/resolveAriaLabelledBy-es.js +5 -1
  115. package/dist/{CSPContext-cjs.js → scrollEdges-cjs.js} +30 -2
  116. package/dist/{CSPContext-es.js → scrollEdges-es.js} +28 -3
  117. package/dist/styles.css +9 -3
  118. package/dist/unstyledPrimitives/index.cjs +1217 -639
  119. package/dist/unstyledPrimitives/index.mjs +1163 -585
  120. package/dist/useButton-cjs.js +283 -317
  121. package/dist/useButton-es.js +277 -298
  122. package/dist/useCompositeListItem-cjs.js +328 -279
  123. package/dist/useCompositeListItem-es.js +293 -246
  124. package/dist/useLabel-cjs.js +11 -1
  125. package/dist/useLabel-es.js +11 -2
  126. package/dist/useLabelableId-cjs.js +37 -91
  127. package/dist/useLabelableId-es.js +37 -90
  128. package/dist/useRenderElement-cjs.js +81 -26
  129. package/dist/useRenderElement-es.js +81 -27
  130. package/dist/{InternalBackdrop-cjs.js → useScrollLock-cjs.js} +1286 -1220
  131. package/dist/{InternalBackdrop-es.js → useScrollLock-es.js} +1250 -1207
  132. package/package.json +3 -3
  133. package/dist/index.esm-cjs.js +0 -738
  134. package/dist/index.esm-es.js +0 -712
@@ -1,15 +1,104 @@
1
1
  import * as React from 'react';
2
2
  import { a as useRefWithInit, E as EMPTY_OBJECT, f as formatErrorMessage, m as mergeProps, d as makeEventPreventable } from './useRenderElement-es.js';
3
- import { i as isShadowRoot, b as isElement, a as isHTMLElement } from './floating-ui.utils.dom-es.js';
3
+ import { i as isShadowRoot, a as isHTMLElement } from './floating-ui.utils.dom-es.js';
4
4
  import * as ReactDOM from 'react-dom';
5
5
 
6
- // https://github.com/mui/material-ui/issues/41190#issuecomment-2040873379
7
- const useInsertionEffect = React[`useInsertionEffect${Math.random().toFixed(1)}`.slice(0, -3)];
6
+ let set;
7
+ if (process.env.NODE_ENV !== 'production') {
8
+ set = new Set();
9
+ }
10
+ function error(...messages) {
11
+ if (process.env.NODE_ENV !== 'production') {
12
+ const messageKey = messages.join(' ');
13
+ if (!set.has(messageKey)) {
14
+ set.add(messageKey);
15
+ console.error(`Base UI: ${messageKey}`);
16
+ }
17
+ }
18
+ }
19
+
20
+ function useControlled({
21
+ controlled,
22
+ default: defaultProp,
23
+ name,
24
+ state = 'value'
25
+ }) {
26
+ // isControlled is ignored in the hook dependency lists as it should never change.
27
+ const {
28
+ current: isControlled
29
+ } = React.useRef(controlled !== undefined);
30
+ const [valueState, setValue] = React.useState(defaultProp);
31
+ const value = isControlled ? controlled : valueState;
32
+ if (process.env.NODE_ENV !== 'production') {
33
+ React.useEffect(() => {
34
+ if (isControlled !== (controlled !== undefined)) {
35
+ 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'));
36
+ }
37
+ }, [state, name, controlled]);
38
+ const {
39
+ current: defaultValue
40
+ } = React.useRef(defaultProp);
41
+ React.useEffect(() => {
42
+ if (!isControlled && serializeToDevModeString(defaultValue) !== serializeToDevModeString(defaultProp)) {
43
+ 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'));
44
+ }
45
+ }, [defaultProp]);
46
+ }
47
+ const setValueIfUncontrolled = React.useCallback(newValue => {
48
+ if (!isControlled) {
49
+ setValue(newValue);
50
+ }
51
+ }, []);
52
+ return [value, setValueIfUncontrolled];
53
+ }
54
+ function serializeToDevModeString(input) {
55
+ let nextId = 0;
56
+ const seen = new WeakMap();
57
+ try {
58
+ const result = JSON.stringify(input, function replacer(key, value) {
59
+ if (key === '_owner' && this != null && typeof this === 'object' && '$$typeof' in this) {
60
+ return undefined;
61
+ }
62
+ if (typeof value === 'bigint') {
63
+ return `__bigint__:${value}`;
64
+ }
65
+ if (value !== null && typeof value === 'object') {
66
+ const id = seen.get(value);
67
+ if (id !== undefined) {
68
+ return `__object__:${id}`;
69
+ }
70
+ seen.set(value, nextId);
71
+ nextId += 1;
72
+ }
73
+ return value;
74
+ });
75
+ return result ?? `__top__:${typeof input}`;
76
+ } catch {
77
+ return '__unserializable__';
78
+ }
79
+ }
80
+
81
+ const noop = () => {};
82
+ const useIsoLayoutEffect = typeof document !== 'undefined' ? React.useLayoutEffect : noop;
83
+
84
+ /**
85
+ * A clone of the React namespace for reading APIs that may be missing in older
86
+ * supported React versions. Bundlers can rewrite direct `React.someNewApi`
87
+ * reads into named imports, which breaks React 17. Reading from this cloned
88
+ * object keeps those lookups optional.
89
+ *
90
+ * @see https://github.com/mui/material-ui/issues/41190#issuecomment-2040873379
91
+ */
92
+ const SafeReact = {
93
+ ...React
94
+ };
95
+
96
+ const useInsertionEffect = SafeReact.useInsertionEffect;
8
97
  const useSafeInsertionEffect =
9
98
  // React 17 doesn't have useInsertionEffect.
10
99
  useInsertionEffect &&
11
100
  // Preact replaces useInsertionEffect with useLayoutEffect and fires too late.
12
- useInsertionEffect !== React.useLayoutEffect ? useInsertionEffect : fn => fn();
101
+ useInsertionEffect !== SafeReact.useLayoutEffect ? useInsertionEffect : fn => fn();
13
102
  /**
14
103
  * Stabilizes the function passed so it's always the same between renders.
15
104
  *
@@ -39,49 +128,36 @@ function createStableCallback() {
39
128
  }
40
129
  function assertNotCalled() {
41
130
  if (process.env.NODE_ENV !== 'production') {
131
+ // TODO: fix mui/no-guarded-throw
132
+ // eslint-disable-next-line mui/no-guarded-throw
42
133
  throw /* minify-error-disabled */new Error('Base UI: Cannot call an event handler while rendering.');
43
134
  }
44
135
  }
45
136
 
46
- function useControlled({
47
- controlled,
48
- default: defaultProp,
49
- name,
50
- state = 'value'
51
- }) {
52
- // isControlled is ignored in the hook dependency lists as it should never change.
53
- const {
54
- current: isControlled
55
- } = React.useRef(controlled !== undefined);
56
- const [valueState, setValue] = React.useState(defaultProp);
57
- const value = isControlled ? controlled : valueState;
58
- if (process.env.NODE_ENV !== 'production') {
59
- React.useEffect(() => {
60
- if (isControlled !== (controlled !== undefined)) {
61
- 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'));
62
- }
63
- }, [state, name, controlled]);
64
- const {
65
- current: defaultValue
66
- } = React.useRef(defaultProp);
67
- React.useEffect(() => {
68
- // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is for more details.
69
- if (!isControlled && JSON.stringify(defaultValue) !== JSON.stringify(defaultProp)) {
70
- 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'));
71
- }
72
- }, [JSON.stringify(defaultProp)]);
73
- }
74
- const setValueIfUncontrolled = React.useCallback(newValue => {
75
- if (!isControlled) {
76
- setValue(newValue);
137
+ /**
138
+ * Untracks the provided value by turning it into a ref to remove its reactivity.
139
+ *
140
+ * Used to access the passed value inside `React.useEffect` without causing the effect to re-run when the value changes.
141
+ */
142
+ function useValueAsRef(value) {
143
+ const latest = useRefWithInit(createLatestRef, value).current;
144
+ latest.next = value;
145
+
146
+ // eslint-disable-next-line react-hooks/exhaustive-deps
147
+ useIsoLayoutEffect(latest.effect);
148
+ return latest;
149
+ }
150
+ function createLatestRef(value) {
151
+ const latest = {
152
+ current: value,
153
+ next: value,
154
+ effect: () => {
155
+ latest.current = latest.next;
77
156
  }
78
- }, []);
79
- return [value, setValueIfUncontrolled];
157
+ };
158
+ return latest;
80
159
  }
81
160
 
82
- const noop = () => {};
83
- const useIsoLayoutEffect = typeof document !== 'undefined' ? React.useLayoutEffect : noop;
84
-
85
161
  const visuallyHiddenBase = {
86
162
  clipPath: 'inset(50%)',
87
163
  overflow: 'hidden',
@@ -103,6 +179,21 @@ const visuallyHiddenInput = {
103
179
  position: 'absolute'
104
180
  };
105
181
 
182
+ function ownerDocument(node) {
183
+ return node?.ownerDocument || document;
184
+ }
185
+
186
+ /**
187
+ * Adds an event listener and returns a cleanup function to remove it.
188
+ */
189
+
190
+ function addEventListener(target, type, listener, options) {
191
+ target.addEventListener(type, listener, options);
192
+ return () => {
193
+ target.removeEventListener(type, listener, options);
194
+ };
195
+ }
196
+
106
197
  const EMPTY$2 = [];
107
198
 
108
199
  /**
@@ -259,198 +350,71 @@ function useTimeout() {
259
350
  }
260
351
 
261
352
  /**
262
- * Untracks the provided value by turning it into a ref to remove its reactivity.
353
+ * Reads `navigator.userAgent` / `navigator.platform` (legacy but universally
354
+ * supported) into a normalized shape. In development, prefers the modern
355
+ * `navigator.userAgentData` API on Chromium to avoid DevTools warnings about
356
+ * the deprecated reads; that branch is dead-code-eliminated in production
357
+ * builds to keep the bundle small.
263
358
  *
264
- * Used to access the passed value inside `React.useEffect` without causing the effect to re-run when the value changes.
359
+ * Returns empty/zero values when `navigator` is undefined (SSR), so every
360
+ * derived flag safely evaluates to `false`.
265
361
  */
266
- function useValueAsRef(value) {
267
- const latest = useRefWithInit(createLatestRef, value).current;
268
- latest.next = value;
269
-
270
- // eslint-disable-next-line react-hooks/exhaustive-deps
271
- useIsoLayoutEffect(latest.effect);
272
- return latest;
273
- }
274
- function createLatestRef(value) {
275
- const latest = {
276
- current: value,
277
- next: value,
278
- effect: () => {
279
- latest.current = latest.next;
280
- }
281
- };
282
- return latest;
283
- }
284
-
285
- const hasNavigator = typeof navigator !== 'undefined';
286
- const nav = getNavigatorData();
287
- const platform = getPlatform();
288
- const userAgent = getUserAgent();
289
- const isWebKit = typeof CSS === 'undefined' || !CSS.supports ? false : CSS.supports('-webkit-backdrop-filter:none');
290
- const isIOS =
291
- // iPads can claim to be MacIntel
292
- nav.platform === 'MacIntel' && nav.maxTouchPoints > 1 ? true : /iP(hone|ad|od)|iOS/.test(nav.platform);
293
- const isFirefox = hasNavigator && /firefox/i.test(userAgent);
294
- const isSafari = hasNavigator && /apple/i.test(navigator.vendor);
295
- const isAndroid = hasNavigator && /android/i.test(platform) || /android/i.test(userAgent);
296
- const isMac = hasNavigator && platform.toLowerCase().startsWith('mac') && !navigator.maxTouchPoints;
297
- const isJSDOM = userAgent.includes('jsdom/');
298
-
299
- // Avoid Chrome DevTools blue warning.
300
- function getNavigatorData() {
301
- if (!hasNavigator) {
362
+ function readRawData() {
363
+ if (typeof navigator === 'undefined') {
302
364
  return {
365
+ userAgent: '',
303
366
  platform: '',
304
- maxTouchPoints: -1
367
+ maxTouchPoints: 0
305
368
  };
306
369
  }
307
- const uaData = navigator.userAgentData;
308
- if (uaData?.platform) {
309
- return {
310
- platform: uaData.platform,
311
- maxTouchPoints: navigator.maxTouchPoints
312
- };
370
+ if (process.env.NODE_ENV !== 'production') {
371
+ const uaData = navigator.userAgentData;
372
+ if (uaData && Array.isArray(uaData.brands)) {
373
+ return {
374
+ userAgent: uaData.brands.map(({
375
+ brand,
376
+ version
377
+ }) => `${brand}/${version}`).join(' '),
378
+ platform: uaData.platform ?? navigator.platform ?? '',
379
+ maxTouchPoints: navigator.maxTouchPoints ?? 0
380
+ };
381
+ }
313
382
  }
314
383
  return {
384
+ userAgent: navigator.userAgent,
315
385
  platform: navigator.platform ?? '',
316
- maxTouchPoints: navigator.maxTouchPoints ?? -1
386
+ maxTouchPoints: navigator.maxTouchPoints ?? 0
317
387
  };
318
388
  }
319
- function getUserAgent() {
320
- if (!hasNavigator) {
321
- return '';
322
- }
323
- const uaData = navigator.userAgentData;
324
- if (uaData && Array.isArray(uaData.brands)) {
325
- return uaData.brands.map(({
326
- brand,
327
- version
328
- }) => `${brand}/${version}`).join(' ');
329
- }
330
- return navigator.userAgent;
331
- }
332
- function getPlatform() {
333
- if (!hasNavigator) {
334
- return '';
335
- }
336
- const uaData = navigator.userAgentData;
337
- if (uaData?.platform) {
338
- return uaData.platform;
339
- }
340
- return navigator.platform ?? '';
341
- }
389
+ const {
390
+ userAgent,
391
+ platform,
392
+ maxTouchPoints
393
+ } = readRawData();
394
+ const lowerUserAgent = userAgent.toLowerCase();
395
+ const lowerPlatform = platform.toLowerCase();
342
396
 
343
- const FOCUSABLE_ATTRIBUTE = 'data-base-ui-focusable';
344
- const ACTIVE_KEY = 'active';
345
- const SELECTED_KEY = 'selected';
346
- const TYPEABLE_SELECTOR = "input:not([type='hidden']):not([disabled])," + "[contenteditable]:not([contenteditable='false']),textarea:not([disabled])";
347
- const ARROW_LEFT = 'ArrowLeft';
348
- const ARROW_RIGHT = 'ArrowRight';
349
- const ARROW_UP = 'ArrowUp';
350
- const ARROW_DOWN = 'ArrowDown';
397
+ // iPadOS 13+ reports `MacIntel` for `navigator.platform`; disambiguated via
398
+ // `maxTouchPoints` so iPad is classified as iOS, not macOS.
399
+ // https://github.com/mui/base-ui/issues/1309
400
+ /** iPhone, iPad (including iPadOS 13+ reporting as macOS), iPod. */
401
+ const ios = /^i(os$|p)/.test(lowerPlatform) || lowerPlatform === 'macintel' && maxTouchPoints > 1;
351
402
 
352
- function activeElement(doc) {
353
- let element = doc.activeElement;
354
- while (element?.shadowRoot?.activeElement != null) {
355
- element = element.shadowRoot.activeElement;
356
- }
357
- return element;
358
- }
359
- function contains(parent, child) {
360
- if (!parent || !child) {
361
- return false;
362
- }
363
- const rootNode = child.getRootNode?.();
403
+ /** Android phones, tablets, and embedded Android browsers. */
404
+ const ANDROID_STRING = 'android';
405
+ const android = lowerPlatform === ANDROID_STRING || lowerUserAgent.includes(ANDROID_STRING);
364
406
 
365
- // First, attempt with faster native method
366
- if (parent.contains(child)) {
367
- return true;
368
- }
407
+ /** macOS desktop. Excludes iPadOS, which reports as `MacIntel`. */
408
+ const mac = !ios && lowerPlatform.startsWith('mac');
369
409
 
370
- // then fallback to custom implementation with Shadow DOM support
371
- if (rootNode && isShadowRoot(rootNode)) {
372
- let next = child;
373
- while (next) {
374
- if (parent === next) {
375
- return true;
376
- }
377
- next = next.parentNode || next.host;
378
- }
379
- }
410
+ /** Windows desktop. */
411
+ lowerPlatform.startsWith('win');
380
412
 
381
- // Give up, the result is false
382
- return false;
383
- }
384
- function isTargetInsideEnabledTrigger(target, triggerElements) {
385
- if (!isElement(target)) {
386
- return false;
387
- }
388
- const targetElement = target;
389
- if (triggerElements.hasElement(targetElement)) {
390
- return !targetElement.hasAttribute('data-trigger-disabled');
391
- }
392
- for (const [, trigger] of triggerElements.entries()) {
393
- if (contains(trigger, targetElement)) {
394
- return !trigger.hasAttribute('data-trigger-disabled');
395
- }
396
- }
397
- return false;
398
- }
399
- function getTarget(event) {
400
- if ('composedPath' in event) {
401
- return event.composedPath()[0];
402
- }
403
-
404
- // TS thinks `event` is of type never as it assumes all browsers support
405
- // `composedPath()`, but browsers without shadow DOM don't.
406
- return event.target;
407
- }
408
- function isEventTargetWithin(event, node) {
409
- if (node == null) {
410
- return false;
411
- }
412
- if ('composedPath' in event) {
413
- return event.composedPath().includes(node);
414
- }
413
+ /** Any Apple OS (`mac || ios`). */
414
+ const apple = mac || ios;
415
415
 
416
- // TS thinks `event` is of type never as it assumes all browsers support composedPath, but browsers without shadow dom don't
417
- const eventAgain = event;
418
- return eventAgain.target != null && node.contains(eventAgain.target);
419
- }
420
- function isRootElement(element) {
421
- return element.matches('html,body');
422
- }
423
- function isTypeableElement(element) {
424
- return isHTMLElement(element) && element.matches(TYPEABLE_SELECTOR);
425
- }
426
- function isTypeableCombobox(element) {
427
- if (!element) {
428
- return false;
429
- }
430
- return element.getAttribute('role') === 'combobox' && isTypeableElement(element);
431
- }
432
- function matchesFocusVisible(element) {
433
- // We don't want to block focus from working with `visibleOnly`
434
- // (JSDOM doesn't match `:focus-visible` when the element has `:focus`)
435
- if (!element || isJSDOM) {
436
- return true;
437
- }
438
- try {
439
- return element.matches(':focus-visible');
440
- } catch (_e) {
441
- return true;
442
- }
443
- }
444
- function getFloatingFocusElement(floatingElement) {
445
- if (!floatingElement) {
446
- return null;
447
- }
448
- // Try to find the element that has `{...getFloatingProps()}` spread on it.
449
- // This indicates the floating element is acting as a positioning wrapper, and
450
- // so focus should be managed on the child element with the event handlers and
451
- // aria props.
452
- return floatingElement.hasAttribute(FOCUSABLE_ATTRIBUTE) ? floatingElement : floatingElement.querySelector(`[${FOCUSABLE_ATTRIBUTE}]`) || floatingElement;
453
- }
416
+ /** Running in jsdom or HappyDOM (used by unit tests). */
417
+ const jsdom = /jsdom|happydom/.test(lowerUserAgent);
454
418
 
455
419
  function stopEvent(event) {
456
420
  event.preventDefault();
@@ -465,16 +429,16 @@ function isVirtualClick(event) {
465
429
  if (event.pointerType === '' && event.isTrusted) {
466
430
  return true;
467
431
  }
468
- if (isAndroid && event.pointerType) {
432
+ if (android && event.pointerType) {
469
433
  return event.type === 'click' && event.buttons === 1;
470
434
  }
471
435
  return event.detail === 0 && !event.pointerType;
472
436
  }
473
437
  function isVirtualPointerEvent(event) {
474
- if (isJSDOM) {
438
+ if (jsdom) {
475
439
  return false;
476
440
  }
477
- return !isAndroid && event.width === 0 && event.height === 0 || isAndroid && event.width === 1 && event.height === 1 && event.pressure === 0 && event.detail === 0 && event.pointerType === 'mouse' ||
441
+ return !android && event.width === 0 && event.height === 0 || android && event.width === 1 && event.height === 1 && event.pressure === 0 && event.detail === 0 && event.pointerType === 'mouse' ||
478
442
  // iOS VoiceOver returns 0.333• for width/height.
479
443
  event.width < 1 && event.height < 1 && event.pressure === 0 && event.detail === 0 && event.pointerType === 'touch';
480
444
  }
@@ -492,8 +456,44 @@ function isClickLikeEvent(event) {
492
456
  return type === 'click' || type === 'mousedown' || type === 'keydown' || type === 'keyup';
493
457
  }
494
458
 
495
- function ownerDocument(node) {
496
- return node?.ownerDocument || document;
459
+ function activeElement(doc) {
460
+ let element = doc.activeElement;
461
+ while (element?.shadowRoot?.activeElement != null) {
462
+ element = element.shadowRoot.activeElement;
463
+ }
464
+ return element;
465
+ }
466
+ function contains(parent, child) {
467
+ if (!parent || !child) {
468
+ return false;
469
+ }
470
+ const rootNode = child.getRootNode?.();
471
+
472
+ // First, attempt with the faster native method.
473
+ if (parent.contains(child)) {
474
+ return true;
475
+ }
476
+
477
+ // Then fall back to traversing out of shadow roots when needed.
478
+ if (rootNode && isShadowRoot(rootNode)) {
479
+ let next = child;
480
+ while (next) {
481
+ if (parent === next) {
482
+ return true;
483
+ }
484
+ next = next.parentNode || next.host;
485
+ }
486
+ }
487
+ return false;
488
+ }
489
+ function getTarget(event) {
490
+ if ('composedPath' in event) {
491
+ return event.composedPath()[0];
492
+ }
493
+
494
+ // TS assumes `composedPath()` always exists, but older browsers without
495
+ // shadow DOM support still fall back to `target`.
496
+ return event.target;
497
497
  }
498
498
 
499
499
  const none = 'none';
@@ -518,6 +518,7 @@ const closeWatcher = 'close-watcher';
518
518
  const listNavigation = 'list-navigation';
519
519
  const keyboard = 'keyboard';
520
520
  const pointer = 'pointer';
521
+ const wheel = 'wheel';
521
522
  const scrub = 'scrub';
522
523
  const cancelOpen = 'cancel-open';
523
524
  const siblingOpen = 'sibling-open';
@@ -575,11 +576,6 @@ function createGenericEventDetails(reason, event, customProperties) {
575
576
  return details;
576
577
  }
577
578
 
578
- // https://github.com/mui/material-ui/issues/41190#issuecomment-2040873379
579
- const SafeReact = {
580
- ...React
581
- };
582
-
583
579
  let globalId = 0;
584
580
 
585
581
  // TODO React 17: Remove `useGlobalId` once React 17 support is removed
@@ -684,12 +680,12 @@ function useTransitionStatus(open, enableIdleState = false, deferEndingState = f
684
680
  return () => {
685
681
  AnimationFrame.cancel(frame);
686
682
  };
687
- }, [enableIdleState, open, mounted, setTransitionStatus, transitionStatus]);
688
- return React.useMemo(() => ({
683
+ }, [enableIdleState, open, mounted, transitionStatus]);
684
+ return {
689
685
  mounted,
690
686
  setMounted,
691
687
  transitionStatus
692
- }), [mounted, transitionStatus]);
688
+ };
693
689
  }
694
690
 
695
691
  let TransitionStatusDataAttributes = /*#__PURE__*/function (TransitionStatusDataAttributes) {
@@ -739,70 +735,67 @@ function useAnimationsFinished(elementOrRef, waitForStartingStyleRemoved = false
739
735
  */
740
736
  signal = null) => {
741
737
  frame.cancel();
742
- function done() {
743
- // Synchronously flush the unmounting of the component so that the browser doesn't
744
- // paint: https://github.com/mui/base-ui/issues/979
745
- ReactDOM.flushSync(fnToExecute);
746
- }
747
738
  const element = resolveRef(elementOrRef);
748
739
  if (element == null) {
749
740
  return;
750
741
  }
751
742
  const resolvedElement = element;
743
+ const done = () => {
744
+ // Synchronously flush the unmounting of the component so that the browser doesn't
745
+ // paint: https://github.com/mui/base-ui/issues/979
746
+ ReactDOM.flushSync(fnToExecute);
747
+ };
752
748
  if (typeof resolvedElement.getAnimations !== 'function' || globalThis.BASE_UI_ANIMATIONS_DISABLED) {
753
749
  fnToExecute();
754
- } else {
755
- function execWaitForStartingStyleRemoved() {
756
- const startingStyleAttribute = TransitionStatusDataAttributes.startingStyle;
757
-
758
- // If `[data-starting-style]` isn't present, fall back to waiting one more frame
759
- // to give "open" animations a chance to be registered.
760
- if (!resolvedElement.hasAttribute(startingStyleAttribute)) {
761
- frame.request(exec);
762
- return;
763
- }
764
-
765
- // Wait for `[data-starting-style]` to have been removed.
766
- const attributeObserver = new MutationObserver(() => {
767
- if (!resolvedElement.hasAttribute(startingStyleAttribute)) {
768
- attributeObserver.disconnect();
769
- exec();
770
- }
771
- });
772
- attributeObserver.observe(resolvedElement, {
773
- attributes: true,
774
- attributeFilter: [startingStyleAttribute]
775
- });
776
- signal?.addEventListener('abort', () => attributeObserver.disconnect(), {
777
- once: true
778
- });
779
- }
780
- function exec() {
781
- Promise.all(resolvedElement.getAnimations().map(anim => anim.finished)).then(() => {
782
- if (signal?.aborted) {
783
- return;
784
- }
750
+ return;
751
+ }
752
+ function exec() {
753
+ Promise.all(resolvedElement.getAnimations().map(animation => animation.finished)).then(() => {
754
+ if (!signal?.aborted) {
785
755
  done();
786
- }).catch(() => {
787
- const currentAnimations = resolvedElement.getAnimations();
788
- if (treatAbortedAsFinished) {
789
- if (signal?.aborted) {
790
- return;
791
- }
756
+ }
757
+ }).catch(() => {
758
+ if (treatAbortedAsFinished) {
759
+ if (!signal?.aborted) {
792
760
  done();
793
- } else if (currentAnimations.length > 0 && currentAnimations.some(anim => anim.pending || anim.playState !== 'finished')) {
794
- // Sometimes animations can be aborted because a property they depend on changes while the animation plays.
795
- // In such cases, we need to re-check if any new animations have started.
796
- exec();
797
761
  }
798
- });
799
- }
800
- if (waitForStartingStyleRemoved) {
801
- execWaitForStartingStyleRemoved();
762
+ return;
763
+ }
764
+ const currentAnimations = resolvedElement.getAnimations();
765
+ if (!signal?.aborted && currentAnimations.length > 0 && currentAnimations.some(animation => animation.pending || animation.playState !== 'finished')) {
766
+ // Sometimes animations can be aborted because a property they depend on changes while the animation plays.
767
+ // In such cases, we need to re-check if any new animations have started.
768
+ exec();
769
+ }
770
+ });
771
+ }
772
+ if (waitForStartingStyleRemoved) {
773
+ const startingStyleAttribute = TransitionStatusDataAttributes.startingStyle;
774
+
775
+ // If `[data-starting-style]` isn't present, fall back to waiting one more frame
776
+ // to give "open" animations a chance to be registered.
777
+ if (!resolvedElement.hasAttribute(startingStyleAttribute)) {
778
+ frame.request(exec);
802
779
  return;
803
780
  }
804
- frame.request(exec);
781
+
782
+ // Wait for `[data-starting-style]` to have been removed.
783
+ const attributeObserver = new MutationObserver(() => {
784
+ if (!resolvedElement.hasAttribute(startingStyleAttribute)) {
785
+ attributeObserver.disconnect();
786
+ exec();
787
+ }
788
+ });
789
+ attributeObserver.observe(resolvedElement, {
790
+ attributes: true,
791
+ attributeFilter: [startingStyleAttribute]
792
+ });
793
+ signal?.addEventListener('abort', () => attributeObserver.disconnect(), {
794
+ once: true
795
+ });
796
+ return;
805
797
  }
798
+ frame.request(exec);
806
799
  });
807
800
  }
808
801
 
@@ -853,20 +846,6 @@ function useValueChanged(value, onChange) {
853
846
  }, [value]);
854
847
  }
855
848
 
856
- let set;
857
- if (process.env.NODE_ENV !== 'production') {
858
- set = new Set();
859
- }
860
- function error(...messages) {
861
- if (process.env.NODE_ENV !== 'production') {
862
- const messageKey = messages.join(' ');
863
- if (!set.has(messageKey)) {
864
- set.add(messageKey);
865
- console.error(`Base UI: ${messageKey}`);
866
- }
867
- }
868
- }
869
-
870
849
  const CompositeRootContext = /*#__PURE__*/React.createContext(undefined);
871
850
  if (process.env.NODE_ENV !== "production") CompositeRootContext.displayName = "CompositeRootContext";
872
851
  function useCompositeRootContext(optional = false) {
@@ -982,9 +961,7 @@ function useButton(parameters = {}) {
982
961
  onPointerDown: externalOnPointerDown,
983
962
  ...otherExternalProps
984
963
  } = externalProps;
985
- const type = isNativeButton ? 'button' : undefined;
986
964
  return mergeProps({
987
- type,
988
965
  onClick(event) {
989
966
  if (disabled) {
990
967
  event.preventDefault();
@@ -1069,9 +1046,11 @@ function useButton(parameters = {}) {
1069
1046
  }
1070
1047
  externalOnPointerDown?.(event);
1071
1048
  }
1072
- }, !isNativeButton ? {
1049
+ }, isNativeButton ? {
1050
+ type: 'button'
1051
+ } : {
1073
1052
  role: 'button'
1074
- } : undefined, focusableWhenDisabledProps, otherExternalProps);
1053
+ }, focusableWhenDisabledProps, otherExternalProps);
1075
1054
  }, [disabled, focusableWhenDisabledProps, isCompositeItem, isNativeButton]);
1076
1055
  const buttonRef = useStableCallback(element => {
1077
1056
  elementRef.current = element;
@@ -1089,4 +1068,4 @@ function isValidLinkElement(elem) {
1089
1068
  return Boolean(elem?.tagName === 'A' && elem?.href);
1090
1069
  }
1091
1070
 
1092
- export { closeWatcher as $, ARROW_DOWN as A, isVirtualPointerEvent as B, ARROW_UP as C, useOnMount as D, useControlled as E, isIOS as F, none as G, visuallyHiddenInput as H, visuallyHidden as I, inputChange as J, inputClear as K, inputBlur as L, inputPaste as M, createGenericEventDetails as N, incrementPress as O, decrementPress as P, useValueChanged as Q, keyboard as R, SafeReact as S, Timeout as T, outsidePress as U, cancelOpen as V, useAnimationFrame as W, isWebKit as X, windowResize as Y, itemPress as Z, isAndroid as _, useIsoLayoutEffect as a, isMouseLikePointerType as a0, isTypeableElement as a1, matchesFocusVisible as a2, isTargetInsideEnabledTrigger as a3, triggerFocus as a4, isMac as a5, isSafari as a6, triggerPress as a7, escapeKey as a8, TYPEABLE_SELECTOR as a9, triggerHover as aa, useAnimationsFinished as ab, siblingOpen as ac, useCompositeRootContext as ad, inputPress as ae, isFirefox as af, clearPress as ag, chipRemovePress as ah, resolveRef as ai, isClickLikeEvent as aj, isReactEvent as ak, isEventTargetWithin as al, isRootElement as am, FOCUSABLE_ATTRIBUTE as an, ACTIVE_KEY as ao, SELECTED_KEY as ap, TransitionStatusDataAttributes as aq, AnimationFrame as ar, pointer as as, swipe as at, scrub as au, useStableCallback as b, useButton as c, createChangeEventDetails as d, closePress as e, useOpenChangeComplete as f, getTarget as g, useTimeout as h, imperativeAction as i, error as j, useTransitionStatus as k, useId as l, getFloatingFocusElement as m, useValueAsRef as n, ownerDocument as o, isTypeableCombobox as p, activeElement as q, contains as r, stopEvent as s, transitionStatusMapping as t, useBaseUiId as u, listNavigation as v, ARROW_LEFT as w, ARROW_RIGHT as x, focusOut as y, isVirtualClick as z };
1071
+ export { triggerPress as $, ios as A, addEventListener as B, none as C, visuallyHiddenInput as D, visuallyHidden as E, inputChange as F, inputClear as G, inputBlur as H, inputPaste as I, createGenericEventDetails as J, wheel as K, useOnMount as L, incrementPress as M, decrementPress as N, useValueChanged as O, keyboard as P, outsidePress as Q, cancelOpen as R, SafeReact as S, Timeout as T, windowResize as U, itemPress as V, android as W, closeWatcher as X, isMouseLikePointerType as Y, triggerFocus as Z, mac as _, useIsoLayoutEffect as a, escapeKey as a0, triggerHover as a1, useAnimationsFinished as a2, siblingOpen as a3, useCompositeRootContext as a4, inputPress as a5, clearPress as a6, chipRemovePress as a7, lowerUserAgent as a8, apple as a9, resolveRef as aa, isReactEvent as ab, isClickLikeEvent as ac, TransitionStatusDataAttributes as ad, AnimationFrame as ae, pointer as af, swipe as ag, scrub as ah, useStableCallback as b, useButton as c, createChangeEventDetails as d, closePress as e, useOpenChangeComplete as f, getTarget as g, useTimeout as h, imperativeAction as i, error as j, useTransitionStatus as k, useId as l, useValueAsRef as m, useAnimationFrame as n, ownerDocument as o, activeElement as p, contains as q, listNavigation as r, stopEvent as s, transitionStatusMapping as t, useBaseUiId as u, focusOut as v, isVirtualClick as w, isVirtualPointerEvent as x, jsdom as y, useControlled as z };