@sanity/ui 2.6.4-canary.2 → 2.6.4

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 (37) hide show
  1. package/dist/index.d.mts +6 -42
  2. package/dist/index.d.ts +6 -42
  3. package/dist/index.esm.js +156 -90
  4. package/dist/index.esm.js.map +1 -1
  5. package/dist/index.js +154 -88
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.mjs +156 -90
  8. package/dist/index.mjs.map +1 -1
  9. package/package.json +34 -26
  10. package/src/core/components/breadcrumbs/breadcrumbs.tsx +6 -15
  11. package/src/core/components/dialog/dialog.tsx +21 -12
  12. package/src/core/components/menu/menu.tsx +18 -11
  13. package/src/core/components/menu/menuButton.tsx +1 -1
  14. package/src/core/components/menu/menuContext.ts +1 -1
  15. package/src/core/components/menu/useMenuController.ts +17 -11
  16. package/src/core/components/toast/styles.ts +1 -2
  17. package/src/core/components/toast/useToast.ts +0 -1
  18. package/src/core/components/tree/tree.tsx +0 -1
  19. package/src/core/components/tree/treeItem.tsx +0 -1
  20. package/src/core/helpers/focus.ts +0 -1
  21. package/src/core/helpers/scroll.ts +0 -1
  22. package/src/core/hooks/_internal/index.ts +1 -0
  23. package/src/core/hooks/_internal/useUnique.ts +34 -0
  24. package/src/core/hooks/index.ts +2 -3
  25. package/src/core/hooks/useClickOutside.ts +72 -38
  26. package/src/core/hooks/useElementSize.ts +0 -1
  27. package/src/core/hooks/useMediaIndex/useMediaIndex.ts +10 -2
  28. package/src/core/hooks/usePrefersDark.ts +55 -10
  29. package/src/core/hooks/usePrefersReducedMotion.ts +56 -10
  30. package/src/core/primitives/popover/__workshop__/AlignedStory.tsx +7 -9
  31. package/src/core/primitives/tooltip/__workshop__/customPortal.tsx +6 -8
  32. package/src/core/primitives/tooltip/tooltip.tsx +21 -25
  33. package/src/core/primitives/tooltip/tooltipDelayGroup/tooltipDelayGroupProvider.tsx +0 -1
  34. package/src/core/utils/layer/layerProvider.tsx +0 -1
  35. package/src/core/utils/portal/__workshop__/named.tsx +8 -10
  36. package/src/core/utils/portal/portalProvider.tsx +3 -2
  37. package/src/core/hooks/useMatchMedia.ts +0 -46
package/dist/index.d.mts CHANGED
@@ -628,7 +628,7 @@ export declare interface CheckboxProps {
628
628
  /**
629
629
  * @public
630
630
  */
631
- export declare type ClickOutsideListener = (event: MouseEvent | TouchEvent) => void
631
+ export declare type ClickOutsideListener = (event: MouseEvent) => void
632
632
 
633
633
  /**
634
634
  * @public
@@ -1432,7 +1432,7 @@ export declare interface MenuProps extends ResponsivePaddingProps {
1432
1432
  * @deprecated Use `shouldFocus="last"` instead.
1433
1433
  */
1434
1434
  focusLast?: boolean
1435
- onClickOutside?: (event: MouseEvent | TouchEvent) => void
1435
+ onClickOutside?: (event: MouseEvent) => void
1436
1436
  onEscape?: () => void
1437
1437
  onItemClick?: () => void
1438
1438
  onItemSelect?: (index: number) => void
@@ -2649,22 +2649,13 @@ export declare function useArrayProp<T extends ArrayPropPrimitive = ArrayPropPri
2649
2649
  export declare function useBoundaryElement(): BoundaryElementContextValue
2650
2650
 
2651
2651
  /**
2652
- * Use the callback version of `elementsArg` if you're using `useRef` to handle elements:
2653
- * ```tsx
2654
- * useClickOutside(
2655
- * () => {},
2656
- * () => [ref.current],
2657
- * )
2658
- *
2659
2652
  * @public
2660
2653
  */
2661
2654
  export declare function useClickOutside(
2662
2655
  listener: ClickOutsideListener,
2663
- elementsArg?:
2664
- | Array<HTMLElement | HTMLElement[] | null>
2665
- | (() => Array<HTMLElement | HTMLElement[] | null>),
2656
+ elementsArg?: Array<HTMLElement | HTMLElement[] | null>,
2666
2657
  boundaryElement?: HTMLElement | null,
2667
- ): void
2658
+ ): (el: HTMLElement | null) => void
2668
2659
 
2669
2660
  /**
2670
2661
  * @beta
@@ -2722,18 +2713,6 @@ export declare function useGlobalKeyDown(onKeyDown: (event: KeyboardEvent) => vo
2722
2713
  */
2723
2714
  export declare function useLayer(): LayerContextValue
2724
2715
 
2725
- /**
2726
- * Efficiently subscribes to `window.matchMedia` queries
2727
- *
2728
- * @param getServerSnapshot - Only called during server-side rendering, and hydration if using hydrateRoot. Required if the hook is called during SSR (https://react.dev/reference/react/useSyncExternalStore#adding-support-for-server-rendering)
2729
- *
2730
- * @public
2731
- */
2732
- export declare function useMatchMedia(
2733
- mediaQueryString: `(${string})`,
2734
- getServerSnapshot?: () => boolean,
2735
- ): boolean
2736
-
2737
2716
  /**
2738
2717
  * This API might change. DO NOT USE IN PRODUCTION.
2739
2718
  * @beta
@@ -2746,30 +2725,15 @@ export declare function useMediaIndex(): number
2746
2725
  export declare function usePortal(): PortalContextValue
2747
2726
 
2748
2727
  /**
2749
- * Returns true if a dark color scheme is preferred, false if a light color scheme is preferred or the preference is not known.
2750
- *
2751
- * @param getServerSnapshot - Only called during server-side rendering, and hydration if using hydrateRoot. Since the server environment doesn't have access to the DOM, we can't determine the current value of the media query and we assume `(prefers-color-scheme: light)` since it's the most common scheme (https://react.dev/reference/react/useSyncExternalStore#adding-support-for-server-rendering)
2752
- *
2753
- * If you persist the detected preference in a cookie or a header then you may implement your own server snapshot to read it.
2754
- * Chrome supports reading the `prefers-color-scheme` media query from a header if the server response: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Sec-CH-Prefers-Color-Scheme
2755
- * @example https://gist.github.com/stipsan/13c0cccf8dfc34f4b44bb1b984baf7df
2756
- *
2757
2728
  * @public
2758
2729
  */
2759
- export declare function usePrefersDark(getServerSnapshot?: () => boolean): boolean
2730
+ export declare function usePrefersDark(): boolean
2760
2731
 
2761
2732
  /**
2762
2733
  * Returns true if motion should be reduced
2763
- *
2764
- * @param getServerSnapshot - Only called during server-side rendering, and hydration if using hydrateRoot. Since the server environment doesn't have access to the DOM, we can't determine the current value of the media query and we assume `(prefers-reduced-motion: no-preference)` since it's the most common scheme (https://react.dev/reference/react/useSyncExternalStore#adding-support-for-server-rendering)
2765
- *
2766
- * If you persist the detected preference in a cookie or a header then you may implement your own server snapshot to read it.
2767
- * Chrome supports reading the `prefers-reduced-motion` media query from a header if the server response: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Sec-CH-Prefers-Reduced-Motion
2768
- * @example https://gist.github.com/stipsan/0c0f839a27842249cada893e9fb7767b
2769
- *
2770
2734
  * @public
2771
2735
  */
2772
- export declare function usePrefersReducedMotion(getServerSnapshot?: () => boolean): boolean
2736
+ export declare function usePrefersReducedMotion(): boolean
2773
2737
 
2774
2738
  /**
2775
2739
  * @public
package/dist/index.d.ts CHANGED
@@ -628,7 +628,7 @@ export declare interface CheckboxProps {
628
628
  /**
629
629
  * @public
630
630
  */
631
- export declare type ClickOutsideListener = (event: MouseEvent | TouchEvent) => void
631
+ export declare type ClickOutsideListener = (event: MouseEvent) => void
632
632
 
633
633
  /**
634
634
  * @public
@@ -1432,7 +1432,7 @@ export declare interface MenuProps extends ResponsivePaddingProps {
1432
1432
  * @deprecated Use `shouldFocus="last"` instead.
1433
1433
  */
1434
1434
  focusLast?: boolean
1435
- onClickOutside?: (event: MouseEvent | TouchEvent) => void
1435
+ onClickOutside?: (event: MouseEvent) => void
1436
1436
  onEscape?: () => void
1437
1437
  onItemClick?: () => void
1438
1438
  onItemSelect?: (index: number) => void
@@ -2649,22 +2649,13 @@ export declare function useArrayProp<T extends ArrayPropPrimitive = ArrayPropPri
2649
2649
  export declare function useBoundaryElement(): BoundaryElementContextValue
2650
2650
 
2651
2651
  /**
2652
- * Use the callback version of `elementsArg` if you're using `useRef` to handle elements:
2653
- * ```tsx
2654
- * useClickOutside(
2655
- * () => {},
2656
- * () => [ref.current],
2657
- * )
2658
- *
2659
2652
  * @public
2660
2653
  */
2661
2654
  export declare function useClickOutside(
2662
2655
  listener: ClickOutsideListener,
2663
- elementsArg?:
2664
- | Array<HTMLElement | HTMLElement[] | null>
2665
- | (() => Array<HTMLElement | HTMLElement[] | null>),
2656
+ elementsArg?: Array<HTMLElement | HTMLElement[] | null>,
2666
2657
  boundaryElement?: HTMLElement | null,
2667
- ): void
2658
+ ): (el: HTMLElement | null) => void
2668
2659
 
2669
2660
  /**
2670
2661
  * @beta
@@ -2722,18 +2713,6 @@ export declare function useGlobalKeyDown(onKeyDown: (event: KeyboardEvent) => vo
2722
2713
  */
2723
2714
  export declare function useLayer(): LayerContextValue
2724
2715
 
2725
- /**
2726
- * Efficiently subscribes to `window.matchMedia` queries
2727
- *
2728
- * @param getServerSnapshot - Only called during server-side rendering, and hydration if using hydrateRoot. Required if the hook is called during SSR (https://react.dev/reference/react/useSyncExternalStore#adding-support-for-server-rendering)
2729
- *
2730
- * @public
2731
- */
2732
- export declare function useMatchMedia(
2733
- mediaQueryString: `(${string})`,
2734
- getServerSnapshot?: () => boolean,
2735
- ): boolean
2736
-
2737
2716
  /**
2738
2717
  * This API might change. DO NOT USE IN PRODUCTION.
2739
2718
  * @beta
@@ -2746,30 +2725,15 @@ export declare function useMediaIndex(): number
2746
2725
  export declare function usePortal(): PortalContextValue
2747
2726
 
2748
2727
  /**
2749
- * Returns true if a dark color scheme is preferred, false if a light color scheme is preferred or the preference is not known.
2750
- *
2751
- * @param getServerSnapshot - Only called during server-side rendering, and hydration if using hydrateRoot. Since the server environment doesn't have access to the DOM, we can't determine the current value of the media query and we assume `(prefers-color-scheme: light)` since it's the most common scheme (https://react.dev/reference/react/useSyncExternalStore#adding-support-for-server-rendering)
2752
- *
2753
- * If you persist the detected preference in a cookie or a header then you may implement your own server snapshot to read it.
2754
- * Chrome supports reading the `prefers-color-scheme` media query from a header if the server response: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Sec-CH-Prefers-Color-Scheme
2755
- * @example https://gist.github.com/stipsan/13c0cccf8dfc34f4b44bb1b984baf7df
2756
- *
2757
2728
  * @public
2758
2729
  */
2759
- export declare function usePrefersDark(getServerSnapshot?: () => boolean): boolean
2730
+ export declare function usePrefersDark(): boolean
2760
2731
 
2761
2732
  /**
2762
2733
  * Returns true if motion should be reduced
2763
- *
2764
- * @param getServerSnapshot - Only called during server-side rendering, and hydration if using hydrateRoot. Since the server environment doesn't have access to the DOM, we can't determine the current value of the media query and we assume `(prefers-reduced-motion: no-preference)` since it's the most common scheme (https://react.dev/reference/react/useSyncExternalStore#adding-support-for-server-rendering)
2765
- *
2766
- * If you persist the detected preference in a cookie or a header then you may implement your own server snapshot to read it.
2767
- * Chrome supports reading the `prefers-reduced-motion` media query from a header if the server response: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Sec-CH-Prefers-Reduced-Motion
2768
- * @example https://gist.github.com/stipsan/0c0f839a27842249cada893e9fb7767b
2769
- *
2770
2734
  * @public
2771
2735
  */
2772
- export declare function usePrefersReducedMotion(getServerSnapshot?: () => boolean): boolean
2736
+ export declare function usePrefersReducedMotion(): boolean
2773
2737
 
2774
2738
  /**
2775
2739
  * @public
package/dist/index.esm.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import { buildTheme, createColorTheme as createColorTheme$1, hexToRgb as hexToRgb$1, hslToRgb as hslToRgb$1, multiply as multiply$1, parseColor as parseColor$1, rgbToHex as rgbToHex$1, rgbToHsl as rgbToHsl$1, rgba as rgba$1, screen as screen$1, getTheme_v2, getScopedTheme } from "@sanity/ui/theme";
2
2
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
3
- import { useMemo, useEffect, useState, useRef, useImperativeHandle, useDebugValue, useSyncExternalStore, createContext, useContext, forwardRef, useId, useCallback, Children, isValidElement, cloneElement, Component, memo, useReducer, Fragment as Fragment$1, startTransition } from "react";
3
+ import { useMemo, useState, useRef, useEffect, createContext, useContext, useSyncExternalStore, useImperativeHandle, forwardRef, useId, useCallback, Children, isValidElement, cloneElement, Component, memo, useReducer, Fragment as Fragment$1, startTransition } from "react";
4
4
  import ReactIs, { isValidElementType } from "react-is";
5
5
  import { ThemeProvider as ThemeProvider$1, useTheme as useTheme$1, css, styled, keyframes } from "styled-components";
6
6
  import { SpinnerIcon, CheckmarkIcon, RemoveIcon, ChevronDownIcon, CloseIcon, ChevronRightIcon, ToggleArrowRightIcon } from "@sanity/icons";
7
7
  import Refractor from "react-refractor";
8
- import { detectOverflow, flip, offset, shift, arrow, hide, useFloating, autoUpdate, size as size$2 } from "@floating-ui/react-dom";
8
+ import { detectOverflow, flip, offset, shift, arrow, hide, useFloating, autoUpdate } from "@floating-ui/react-dom";
9
9
  import { motion, AnimatePresence } from "framer-motion";
10
10
  import { createPortal } from "react-dom";
11
11
  import { useEffectEvent } from "use-effect-event";
@@ -131,26 +131,45 @@ function useArrayProp(val, defaultVal) {
131
131
  [__perf_hash__]
132
132
  );
133
133
  }
134
+ function _getElements(element, elementsArg) {
135
+ const ret = [element];
136
+ for (const el of elementsArg)
137
+ Array.isArray(el) ? ret.push(...el) : ret.push(el);
138
+ return ret.filter(Boolean);
139
+ }
134
140
  function useClickOutside(listener, elementsArg = EMPTY_ARRAY, boundaryElement) {
135
- const eventHandler = useEffectEvent((evt) => {
136
- const target = evt.target;
137
- if (!(target instanceof Node) || boundaryElement && !boundaryElement.contains(target))
141
+ const [element, setElement] = useState(null), [elements, setElements] = useState(() => _getElements(element, elementsArg)), elementsRef = useRef(elements);
142
+ return useEffect(() => {
143
+ const prevElements = elementsRef.current, nextElements = _getElements(element, elementsArg);
144
+ if (prevElements.length !== nextElements.length) {
145
+ setElements(nextElements), elementsRef.current = nextElements;
138
146
  return;
139
- const elements = (Array.isArray(elementsArg) ? elementsArg : elementsArg()).flat();
140
- for (const el of elements)
141
- if (el && (target === el || el.contains(target)))
147
+ }
148
+ for (const el of prevElements)
149
+ if (!nextElements.includes(el)) {
150
+ setElements(nextElements), elementsRef.current = nextElements;
142
151
  return;
143
- listener(evt);
144
- });
145
- useEffect(() => (document.addEventListener("mousedown", eventHandler), document.addEventListener("touchstart", eventHandler), () => {
146
- document.removeEventListener("mousedown", eventHandler), document.removeEventListener("touchstart", eventHandler);
147
- }), [eventHandler]);
148
- }
149
- function useCustomValidity(ref, customValidity) {
150
- useEffect(() => {
151
- var _a;
152
- (_a = ref.current) == null || _a.setCustomValidity(customValidity || "");
153
- }, [customValidity, ref]);
152
+ }
153
+ for (const el of nextElements)
154
+ if (!prevElements.includes(el)) {
155
+ setElements(nextElements), elementsRef.current = nextElements;
156
+ return;
157
+ }
158
+ }, [element, elementsArg]), useEffect(() => {
159
+ if (!listener) return;
160
+ const handleWindowMouseDown = (evt) => {
161
+ const target = evt.target;
162
+ if (target instanceof Node && !(boundaryElement && !boundaryElement.contains(target))) {
163
+ for (const el of elements)
164
+ if (target === el || el.contains(target))
165
+ return;
166
+ listener(evt);
167
+ }
168
+ };
169
+ return window.addEventListener("mousedown", handleWindowMouseDown), () => {
170
+ window.removeEventListener("mousedown", handleWindowMouseDown);
171
+ };
172
+ }, [boundaryElement, listener, elements]), setElement;
154
173
  }
155
174
  var resizeObservers = [], hasActiveObservations = function() {
156
175
  return resizeObservers.some(function(ro) {
@@ -485,27 +504,9 @@ function useElementRect(element) {
485
504
  const elementSize = useElementSize(element);
486
505
  return (elementSize == null ? void 0 : elementSize._contentRect) || null;
487
506
  }
488
- function useForwardedRef(ref) {
489
- const innerRef = useRef(null);
490
- return useImperativeHandle(ref, () => innerRef.current), innerRef;
491
- }
492
507
  function useGlobalKeyDown(onKeyDown) {
493
508
  return useEffect(() => (addEventListener("keydown", onKeyDown), () => removeEventListener("keydown", onKeyDown)), [onKeyDown]);
494
509
  }
495
- function useMatchMedia(mediaQueryString, getServerSnapshot2) {
496
- const { subscribe: subscribe2, getSnapshot } = useMemo(() => {
497
- let MEDIA_QUERY_CACHE;
498
- const getMatchMedia = () => (MEDIA_QUERY_CACHE || (MEDIA_QUERY_CACHE = window.matchMedia(mediaQueryString)), MEDIA_QUERY_CACHE);
499
- return {
500
- subscribe: (onStoreChange) => {
501
- const matchMedia = getMatchMedia();
502
- return matchMedia.addEventListener("change", onStoreChange), () => matchMedia.removeEventListener("change", onStoreChange);
503
- },
504
- getSnapshot: () => getMatchMedia().matches
505
- };
506
- }, [mediaQueryString]);
507
- return useDebugValue(mediaQueryString), useSyncExternalStore(subscribe2, getSnapshot, getServerSnapshot2);
508
- }
509
510
  function getGlobalScope() {
510
511
  if (typeof globalThis < "u") return globalThis;
511
512
  if (typeof window < "u") return window;
@@ -548,6 +549,7 @@ function useTheme() {
548
549
  function useTheme_v2() {
549
550
  return getTheme_v2(useTheme$1());
550
551
  }
552
+ const MEDIA_STORE_CACHE = /* @__PURE__ */ new WeakMap();
551
553
  function _getMediaQuery(media, index) {
552
554
  return index === 0 ? `screen and (max-width: ${media[index] - 1}px)` : index === media.length ? `screen and (min-width: ${media[index - 1]}px)` : `screen and (min-width: ${media[index - 1]}px) and (max-width: ${media[index] - 1}px)`;
553
555
  }
@@ -582,18 +584,57 @@ function _createMediaStore(media) {
582
584
  };
583
585
  } };
584
586
  }
585
- function getServerSnapshot() {
587
+ function getServerSnapshot$2() {
586
588
  return 0;
587
589
  }
588
590
  function useMediaIndex() {
589
- const { media } = useTheme_v2(), store = useMemo(() => _createMediaStore(media), [media]);
590
- return useSyncExternalStore(store.subscribe, store.getSnapshot, getServerSnapshot);
591
+ const { media } = useTheme_v2();
592
+ let store = MEDIA_STORE_CACHE.get(media);
593
+ return store || (store = _createMediaStore(media), MEDIA_STORE_CACHE.set(media, store)), useSyncExternalStore(store.subscribe, store.getSnapshot, getServerSnapshot$2);
594
+ }
595
+ let MEDIA_QUERY_CACHE$1;
596
+ function getMatchMedia$1() {
597
+ return MEDIA_QUERY_CACHE$1 || (MEDIA_QUERY_CACHE$1 = window.matchMedia("(prefers-color-scheme: dark)")), MEDIA_QUERY_CACHE$1;
591
598
  }
592
- function usePrefersDark(getServerSnapshot2 = () => !1) {
593
- return useMatchMedia("(prefers-color-scheme: dark)", getServerSnapshot2);
599
+ function subscribe$2(onStoreChange) {
600
+ const matchMedia = getMatchMedia$1();
601
+ return matchMedia.addEventListener("change", onStoreChange), () => matchMedia.removeEventListener("change", onStoreChange);
594
602
  }
595
- function usePrefersReducedMotion(getServerSnapshot2 = () => !1) {
596
- return useMatchMedia("(prefers-reduced-motion: reduce)", getServerSnapshot2);
603
+ function getSnapshot$1() {
604
+ return getMatchMedia$1().matches;
605
+ }
606
+ function getServerSnapshot$1() {
607
+ return !1;
608
+ }
609
+ function usePrefersDark() {
610
+ return useSyncExternalStore(subscribe$2, getSnapshot$1, getServerSnapshot$1);
611
+ }
612
+ let MEDIA_QUERY_CACHE;
613
+ function getMatchMedia() {
614
+ return MEDIA_QUERY_CACHE || (MEDIA_QUERY_CACHE = window.matchMedia("(prefers-reduced-motion: reduce)")), MEDIA_QUERY_CACHE;
615
+ }
616
+ function subscribe$1(onStoreChange) {
617
+ const matchMedia = getMatchMedia();
618
+ return matchMedia.addEventListener("change", onStoreChange), () => matchMedia.removeEventListener("change", onStoreChange);
619
+ }
620
+ function getSnapshot() {
621
+ return getMatchMedia().matches;
622
+ }
623
+ function getServerSnapshot() {
624
+ return !1;
625
+ }
626
+ function usePrefersReducedMotion() {
627
+ return useSyncExternalStore(subscribe$1, getSnapshot, getServerSnapshot);
628
+ }
629
+ function useForwardedRef(ref) {
630
+ const innerRef = useRef(null);
631
+ return useImperativeHandle(ref, () => innerRef.current), innerRef;
632
+ }
633
+ function useCustomValidity(ref, customValidity) {
634
+ useEffect(() => {
635
+ var _a;
636
+ (_a = ref.current) == null || _a.setCustomValidity(customValidity || "");
637
+ }, [customValidity, ref]);
597
638
  }
598
639
  function responsiveBorderStyle() {
599
640
  return [border, borderTop, borderRight, borderBottom, borderLeft];
@@ -3019,6 +3060,16 @@ function Portal(props) {
3019
3060
  const { children, __unstable_name: name } = props, portal = usePortal(), portalElement = (name ? portal.elements && portal.elements[name] : portal.element) || ((_a = portal.elements) == null ? void 0 : _a.default);
3020
3061
  return portalElement ? createPortal(children, portalElement) : null;
3021
3062
  }
3063
+ function useUnique(value) {
3064
+ const valueRef = useRef(value);
3065
+ return _isEqual(valueRef.current, value) || (valueRef.current = value), valueRef.current;
3066
+ }
3067
+ function _isEqual(objA, objB) {
3068
+ if (!objA || !objB)
3069
+ return objA === objB;
3070
+ const keysA = Object.keys(objA), keysB = Object.keys(objB);
3071
+ return keysA.length !== keysB.length ? !1 : keysA.every((key2) => objA[key2] === objB[key2]);
3072
+ }
3022
3073
  function useMounted() {
3023
3074
  return useSyncExternalStore(
3024
3075
  subscribe,
@@ -3029,7 +3080,7 @@ function useMounted() {
3029
3080
  const subscribe = () => () => {
3030
3081
  };
3031
3082
  function PortalProvider(props) {
3032
- const { boundaryElement, children, element, __unstable_elements: elements } = props, mounted = useMounted(), value = useMemo(() => ({
3083
+ const { boundaryElement, children, element, __unstable_elements: elementsProp } = props, elements = useUnique(elementsProp), mounted = useMounted(), value = useMemo(() => ({
3033
3084
  version: 0,
3034
3085
  boundaryElement: boundaryElement || null,
3035
3086
  element: element || mounted ? document.body : null,
@@ -4292,6 +4343,7 @@ function TooltipDelayGroupProvider(props) {
4292
4343
  }
4293
4344
  const Root$a = styled(Layer)`
4294
4345
  pointer-events: none;
4346
+ max-width: ${({ $maxWidth }) => $maxWidth}px;
4295
4347
  `, Tooltip = forwardRef(function(props, forwardedRef) {
4296
4348
  var _a, _b, _c, _d, _e, _f, _g;
4297
4349
  const boundaryElementContext = useBoundaryElement(), { layer } = useTheme_v2(), {
@@ -4313,21 +4365,18 @@ const Root$a = styled(Layer)`
4313
4365
  ...restProps
4314
4366
  } = props, animate = usePrefersReducedMotion() ? !1 : _animate, fallbackPlacements = useArrayProp(fallbackPlacementsProp), ref = useRef(null), [referenceElement, setReferenceElement] = useState(null), arrowRef = useRef(null), rootBoundary = "viewport";
4315
4367
  useImperativeHandle(forwardedRef, () => ref.current);
4316
- const portal = usePortal(), portalElement = typeof portalProp == "string" ? ((_c = portal.elements) == null ? void 0 : _c[portalProp]) || null : portal.element, middleware = useMemo(() => {
4368
+ const portal = usePortal(), portalElement = typeof portalProp == "string" ? ((_c = portal.elements) == null ? void 0 : _c[portalProp]) || null : portal.element, mounted = useMounted(), tooltipWidth = useMemo(() => {
4369
+ const availableWidths = [
4370
+ ...boundaryElement ? [boundaryElement.offsetWidth] : [],
4371
+ portalElement != null && portalElement.offsetWidth || mounted ? document.body.offsetWidth : (
4372
+ // We don't actually know what the width of the body is during SSR, so we'll just assume it's 800px or larger
4373
+ 800
4374
+ )
4375
+ ];
4376
+ return Math.min(...availableWidths) - DEFAULT_TOOLTIP_PADDING * 2;
4377
+ }, [boundaryElement, mounted, portalElement]), middleware = useMemo(() => {
4317
4378
  const ret = [];
4318
4379
  return ret.push(
4319
- size$2({
4320
- apply({ elements }) {
4321
- const availableWidths = [
4322
- ...boundaryElement ? [boundaryElement.offsetWidth] : [],
4323
- (portalElement == null ? void 0 : portalElement.offsetWidth) || document.body.offsetWidth
4324
- ], tooltipWidth = Math.min(...availableWidths) - DEFAULT_TOOLTIP_PADDING * 2;
4325
- Object.assign(elements.floating.style, {
4326
- maxWidth: tooltipWidth > 0 ? `${tooltipWidth}px` : void 0
4327
- });
4328
- }
4329
- })
4330
- ), ret.push(
4331
4380
  flip({
4332
4381
  boundary: boundaryElement || void 0,
4333
4382
  fallbackPlacements,
@@ -4341,7 +4390,7 @@ const Root$a = styled(Layer)`
4341
4390
  padding: DEFAULT_TOOLTIP_PADDING
4342
4391
  })
4343
4392
  ), arrowProp && ret.push(arrow({ element: arrowRef, padding: DEFAULT_TOOLTIP_PADDING })), animate && ret.push(origin), ret;
4344
- }, [animate, arrowProp, boundaryElement, fallbackPlacements, portalElement]), { floatingStyles, placement, middlewareData, refs, update } = useFloating({
4393
+ }, [animate, arrowProp, boundaryElement, fallbackPlacements]), { floatingStyles, placement, middlewareData, refs, update } = useFloating({
4345
4394
  middleware,
4346
4395
  placement: placementProp,
4347
4396
  whileElementsMounted: autoUpdate
@@ -4451,6 +4500,7 @@ const Root$a = styled(Layer)`
4451
4500
  ref: setFloating,
4452
4501
  style: floatingStyles,
4453
4502
  zOffset,
4503
+ $maxWidth: tooltipWidth,
4454
4504
  children: /* @__PURE__ */ jsx(
4455
4505
  TooltipCard,
4456
4506
  {
@@ -4916,8 +4966,8 @@ const AUTOCOMPLETE_LISTBOX_IGNORE_KEYS = [
4916
4966
  appearance: none;
4917
4967
  margin: -4px;
4918
4968
  `, Breadcrumbs = forwardRef(function(props, ref) {
4919
- const { children, maxLength, separator, space: spaceRaw = 2, ...restProps } = props, space = useArrayProp(spaceRaw), [open, setOpen] = useState(!1), expandElementRef = useRef(null), popoverElementRef = useRef(null), collapse = useCallback(() => setOpen(!1), []), expand = useCallback(() => setOpen(!0), []);
4920
- useClickOutside(collapse, () => [expandElementRef.current, popoverElementRef.current]);
4969
+ const { children, maxLength, separator, space: spaceRaw = 2, ...restProps } = props, space = useArrayProp(spaceRaw), [open, setOpen] = useState(!1), [expandElement, setExpandElement] = useState(null), [popoverElement, setPopoverElement] = useState(null), collapse = useCallback(() => setOpen(!1), []), expand = useCallback(() => setOpen(!0), []);
4970
+ useClickOutside(collapse, [expandElement, popoverElement]);
4921
4971
  const rawItems = useMemo(() => Children.toArray(children).filter(isValidElement), [children]), items = useMemo(() => {
4922
4972
  const len = rawItems.length;
4923
4973
  if (maxLength && len > maxLength) {
@@ -4932,7 +4982,7 @@ const AUTOCOMPLETE_LISTBOX_IGNORE_KEYS = [
4932
4982
  open,
4933
4983
  placement: "top",
4934
4984
  portal: !0,
4935
- ref: popoverElementRef,
4985
+ ref: setPopoverElement,
4936
4986
  children: /* @__PURE__ */ jsx(
4937
4987
  ExpandButton,
4938
4988
  {
@@ -4940,7 +4990,7 @@ const AUTOCOMPLETE_LISTBOX_IGNORE_KEYS = [
4940
4990
  mode: "bleed",
4941
4991
  onClick: open ? collapse : expand,
4942
4992
  padding: 1,
4943
- ref: expandElementRef,
4993
+ ref: setExpandElement,
4944
4994
  selected: open,
4945
4995
  text: "\u2026"
4946
4996
  }
@@ -5065,8 +5115,8 @@ const Root$7 = styled(Layer)(responsivePaddingStyle, dialogStyle, responsiveDial
5065
5115
  scheme,
5066
5116
  shadow: shadowProp,
5067
5117
  width: widthProp
5068
- } = props, portal = usePortal(), portalElement = portalProp ? ((_a = portal.elements) == null ? void 0 : _a[portalProp]) || null : portal.element, boundaryElement = useBoundaryElement().element, radius = useArrayProp(radiusProp), shadow = useArrayProp(shadowProp), width = useArrayProp(widthProp), ref = useRef(null), contentRef = useRef(null), layer = useLayer(), { isTopLayer } = layer, labelId = `${id}_label`, showCloseButton = !!onClose && hideCloseButton === !1, showHeader = !!header || showCloseButton;
5069
- return useImperativeHandle(forwardedRef, () => ref.current), useImperativeHandle(
5118
+ } = props, portal = usePortal(), portalElement = portalProp ? ((_a = portal.elements) == null ? void 0 : _a[portalProp]) || null : portal.element, boundaryElement = useBoundaryElement().element, radius = useArrayProp(radiusProp), shadow = useArrayProp(shadowProp), width = useArrayProp(widthProp), ref = useRef(null), [rootElement, setRootElement] = useState(null), contentRef = useRef(null), layer = useLayer(), { isTopLayer } = layer, labelId = `${id}_label`, showCloseButton = !!onClose && hideCloseButton === !1, showHeader = !!header || showCloseButton;
5119
+ useImperativeHandle(forwardedRef, () => ref.current), useImperativeHandle(
5070
5120
  forwardedContentRef,
5071
5121
  () => contentRef.current
5072
5122
  ), useEffect(() => {
@@ -5081,13 +5131,20 @@ const Root$7 = styled(Layer)(responsivePaddingStyle, dialogStyle, responsiveDial
5081
5131
  [boundaryElement, isTopLayer, onClose, portalElement]
5082
5132
  )
5083
5133
  ), useClickOutside(
5084
- (event) => {
5085
- if (!isTopLayer || !onClickOutside) return;
5086
- const target = event.target;
5087
- target && !isTargetWithinScope(boundaryElement, portalElement, target) || onClickOutside();
5088
- },
5089
- () => [ref.current]
5090
- ), /* @__PURE__ */ jsx(DialogContainer, { "data-ui": "DialogCard", width, children: /* @__PURE__ */ jsx(DialogCardRoot, { radius, ref, scheme, shadow, children: /* @__PURE__ */ jsxs(DialogLayout, { direction: "column", children: [
5134
+ useCallback(
5135
+ (event) => {
5136
+ if (!isTopLayer || !onClickOutside) return;
5137
+ const target = event.target;
5138
+ target && !isTargetWithinScope(boundaryElement, portalElement, target) || onClickOutside();
5139
+ },
5140
+ [boundaryElement, isTopLayer, onClickOutside, portalElement]
5141
+ ),
5142
+ [rootElement]
5143
+ );
5144
+ const setRef = useCallback((el) => {
5145
+ setRootElement(el), ref.current = el;
5146
+ }, []);
5147
+ return /* @__PURE__ */ jsx(DialogContainer, { "data-ui": "DialogCard", width, children: /* @__PURE__ */ jsx(DialogCardRoot, { radius, ref: setRef, scheme, shadow, children: /* @__PURE__ */ jsxs(DialogLayout, { direction: "column", children: [
5091
5148
  showHeader && /* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsxs(Flex, { align: "center", padding: 3, children: [
5092
5149
  /* @__PURE__ */ jsx(Box, { flex: 1, padding: 2, children: header && /* @__PURE__ */ jsx(Text, { id: labelId, size: 1, weight: "semibold", children: header }) }),
5093
5150
  showCloseButton && /* @__PURE__ */ jsx(Box, { flex: "none", children: /* @__PURE__ */ jsx(
@@ -5265,13 +5322,13 @@ function _sortElements(rootElement, elements) {
5265
5322
  elements.sort(_sort);
5266
5323
  }
5267
5324
  function useMenuController(props) {
5268
- const { onKeyDown, originElement, shouldFocus, rootElementRef } = props, elementsRef = useRef([]), [activeIndex, _setActiveIndex] = useState(-1), activeIndexRef = useRef(activeIndex), activeElement = useMemo(() => elementsRef.current[activeIndex] || null, [activeIndex]), mounted = !!rootElementRef.current, setActiveIndex = useCallback((nextActiveIndex) => {
5325
+ const { onKeyDown, originElement, shouldFocus } = props, elementsRef = useRef([]), [rootElement, setRootElement] = useState(null), [activeIndex, _setActiveIndex] = useState(-1), activeIndexRef = useRef(activeIndex), activeElement = elementsRef.current[activeIndex] || null, mounted = !!rootElement, setActiveIndex = useCallback((nextActiveIndex) => {
5269
5326
  _setActiveIndex(nextActiveIndex), activeIndexRef.current = nextActiveIndex;
5270
5327
  }, []), mount = useCallback(
5271
5328
  (element, selected) => {
5272
5329
  if (!element) return () => {
5273
5330
  };
5274
- if (elementsRef.current.indexOf(element) === -1 && (elementsRef.current.push(element), _sortElements(rootElementRef.current, elementsRef.current)), selected) {
5331
+ if (elementsRef.current.indexOf(element) === -1 && (elementsRef.current.push(element), _sortElements(rootElement, elementsRef.current)), selected) {
5275
5332
  const selectedIndex = elementsRef.current.indexOf(element);
5276
5333
  setActiveIndex(selectedIndex);
5277
5334
  }
@@ -5280,7 +5337,7 @@ function useMenuController(props) {
5280
5337
  idx > -1 && elementsRef.current.splice(idx, 1);
5281
5338
  };
5282
5339
  },
5283
- [rootElementRef, setActiveIndex]
5340
+ [rootElement, setActiveIndex]
5284
5341
  ), handleKeyDown = useCallback(
5285
5342
  (event) => {
5286
5343
  if (event.key === "Tab") {
@@ -5335,13 +5392,13 @@ function useMenuController(props) {
5335
5392
  },
5336
5393
  [setActiveIndex]
5337
5394
  ), handleItemMouseLeave = useCallback(() => {
5338
- var _a;
5339
- setActiveIndex(-2), (_a = rootElementRef.current) == null || _a.focus();
5340
- }, [rootElementRef, setActiveIndex]);
5395
+ setActiveIndex(-2), rootElement == null || rootElement.focus();
5396
+ }, [setActiveIndex, rootElement]);
5341
5397
  return useEffect(() => {
5342
5398
  if (!mounted) return;
5343
5399
  const rafId = window.requestAnimationFrame(() => {
5344
- if (activeIndex === -1) {
5400
+ const _activeIndex = activeIndexRef.current;
5401
+ if (_activeIndex === -1) {
5345
5402
  if (shouldFocus === "first") {
5346
5403
  const el = _getFocusableElements(elementsRef.current)[0];
5347
5404
  if (el) {
@@ -5358,7 +5415,7 @@ function useMenuController(props) {
5358
5415
  }
5359
5416
  return;
5360
5417
  }
5361
- const element = elementsRef.current[activeIndex] || null;
5418
+ const element = elementsRef.current[_activeIndex] || null;
5362
5419
  element == null || element.focus();
5363
5420
  });
5364
5421
  return () => {
@@ -5370,7 +5427,9 @@ function useMenuController(props) {
5370
5427
  handleItemMouseEnter,
5371
5428
  handleItemMouseLeave,
5372
5429
  handleKeyDown,
5373
- mount
5430
+ mount,
5431
+ rootElement,
5432
+ setRootElement
5374
5433
  };
5375
5434
  }
5376
5435
  const Root$5 = styled(Box)`
@@ -5402,18 +5461,23 @@ const Root$5 = styled(Box)`
5402
5461
  handleItemMouseEnter,
5403
5462
  handleItemMouseLeave,
5404
5463
  handleKeyDown,
5405
- mount
5406
- } = useMenuController({ onKeyDown, originElement, shouldFocus, rootElementRef: ref }), handleRefChange = useCallback(
5464
+ mount,
5465
+ rootElement,
5466
+ setRootElement
5467
+ } = useMenuController({ onKeyDown, originElement, shouldFocus }), handleRefChange = useCallback(
5407
5468
  (el) => {
5408
- ref.current = el, ref.current && registerElement && registerElement(ref.current);
5469
+ setRootElement(el), ref.current = el;
5409
5470
  },
5410
- [registerElement]
5471
+ [setRootElement]
5411
5472
  );
5412
5473
  useEffect(() => {
5413
5474
  onItemSelect && onItemSelect(activeIndex);
5414
5475
  }, [activeIndex, onItemSelect]), useClickOutside(
5415
- (event) => isTopLayer && onClickOutside && onClickOutside(event),
5416
- () => [ref.current]
5476
+ useCallback(
5477
+ (event) => isTopLayer && onClickOutside && onClickOutside(event),
5478
+ [isTopLayer, onClickOutside]
5479
+ ),
5480
+ [rootElement]
5417
5481
  ), useGlobalKeyDown(
5418
5482
  useCallback(
5419
5483
  (event) => {
@@ -5421,7 +5485,10 @@ const Root$5 = styled(Box)`
5421
5485
  },
5422
5486
  [isTopLayer, onEscape]
5423
5487
  )
5424
- );
5488
+ ), useEffect(() => {
5489
+ if (!(!rootElement || !registerElement))
5490
+ return registerElement(rootElement);
5491
+ }, [registerElement, rootElement]);
5425
5492
  const value = useMemo(
5426
5493
  () => ({
5427
5494
  version: 0,
@@ -6097,7 +6164,7 @@ const CustomInline = styled(Inline)`
6097
6164
  }
6098
6165
  100% {
6099
6166
  width: 100%;
6100
- }
6167
+ }
6101
6168
  `, LOADING_BAR_HEIGHT = 2;
6102
6169
  function rootStyles(props) {
6103
6170
  const { color } = getTheme_v2$1(props.theme), loadingBarColor = color.button.default[props.tone].enabled.bg;
@@ -6795,7 +6862,6 @@ export {
6795
6862
  useForwardedRef,
6796
6863
  useGlobalKeyDown,
6797
6864
  useLayer,
6798
- useMatchMedia,
6799
6865
  useMediaIndex,
6800
6866
  usePortal,
6801
6867
  usePrefersDark,