@sanity/ui 2.6.4-canary.2 → 2.6.5

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 +164 -97
  4. package/dist/index.esm.js.map +1 -1
  5. package/dist/index.js +162 -95
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.mjs +164 -97
  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 +29 -31
  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, useLayoutEffect, 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;
598
+ }
599
+ function subscribe$2(onStoreChange) {
600
+ const matchMedia = getMatchMedia$1();
601
+ return matchMedia.addEventListener("change", onStoreChange), () => matchMedia.removeEventListener("change", onStoreChange);
602
+ }
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);
591
628
  }
592
- function usePrefersDark(getServerSnapshot2 = () => !1) {
593
- return useMatchMedia("(prefers-color-scheme: dark)", getServerSnapshot2);
629
+ function useForwardedRef(ref) {
630
+ const innerRef = useRef(null);
631
+ return useImperativeHandle(ref, () => innerRef.current), innerRef;
594
632
  }
595
- function usePrefersReducedMotion(getServerSnapshot2 = () => !1) {
596
- return useMatchMedia("(prefers-reduced-motion: reduce)", getServerSnapshot2);
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,
@@ -4311,23 +4362,11 @@ const Root$a = styled(Layer)`
4311
4362
  zOffset = layer.tooltip.zOffset,
4312
4363
  delay,
4313
4364
  ...restProps
4314
- } = props, animate = usePrefersReducedMotion() ? !1 : _animate, fallbackPlacements = useArrayProp(fallbackPlacementsProp), ref = useRef(null), [referenceElement, setReferenceElement] = useState(null), arrowRef = useRef(null), rootBoundary = "viewport";
4365
+ } = props, animate = usePrefersReducedMotion() ? !1 : _animate, fallbackPlacements = useArrayProp(fallbackPlacementsProp), ref = useRef(null), [referenceElement, setReferenceElement] = useState(null), arrowRef = useRef(null), rootBoundary = "viewport", [tooltipMaxWidth, setTooltipMaxWidth] = useState(0);
4315
4366
  useImperativeHandle(forwardedRef, () => ref.current);
4316
4367
  const portal = usePortal(), portalElement = typeof portalProp == "string" ? ((_c = portal.elements) == null ? void 0 : _c[portalProp]) || null : portal.element, middleware = useMemo(() => {
4317
4368
  const ret = [];
4318
4369
  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
4370
  flip({
4332
4371
  boundary: boundaryElement || void 0,
4333
4372
  fallbackPlacements,
@@ -4341,7 +4380,7 @@ const Root$a = styled(Layer)`
4341
4380
  padding: DEFAULT_TOOLTIP_PADDING
4342
4381
  })
4343
4382
  ), 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({
4383
+ }, [animate, arrowProp, boundaryElement, fallbackPlacements]), { floatingStyles, placement, middlewareData, refs, update } = useFloating({
4345
4384
  middleware,
4346
4385
  placement: placementProp,
4347
4386
  whileElementsMounted: autoUpdate
@@ -4408,7 +4447,13 @@ const Root$a = styled(Layer)`
4408
4447
  return window.addEventListener("keydown", handleWindowKeyDown), () => {
4409
4448
  window.removeEventListener("keydown", handleWindowKeyDown);
4410
4449
  };
4411
- }, [handleIsOpenChange, showTooltip]), useCloseOnMouseLeave({ handleIsOpenChange, referenceElement, showTooltip });
4450
+ }, [handleIsOpenChange, showTooltip]), useCloseOnMouseLeave({ handleIsOpenChange, referenceElement, showTooltip }), useLayoutEffect(() => {
4451
+ const availableWidths = [
4452
+ ...boundaryElement ? [boundaryElement.offsetWidth] : [],
4453
+ (portalElement == null ? void 0 : portalElement.offsetWidth) || document.body.offsetWidth
4454
+ ];
4455
+ setTooltipMaxWidth(Math.min(...availableWidths) - DEFAULT_TOOLTIP_PADDING * 2);
4456
+ }, [boundaryElement, portalElement]);
4412
4457
  const setArrow = useCallback(
4413
4458
  (arrowEl) => {
4414
4459
  arrowRef.current = arrowEl, update();
@@ -4449,7 +4494,10 @@ const Root$a = styled(Layer)`
4449
4494
  "data-ui": "Tooltip",
4450
4495
  ...restProps,
4451
4496
  ref: setFloating,
4452
- style: floatingStyles,
4497
+ style: {
4498
+ ...floatingStyles,
4499
+ maxWidth: tooltipMaxWidth > 0 ? `${tooltipMaxWidth}px` : void 0
4500
+ },
4453
4501
  zOffset,
4454
4502
  children: /* @__PURE__ */ jsx(
4455
4503
  TooltipCard,
@@ -4497,13 +4545,16 @@ function useCloseOnMouseLeave({
4497
4545
  referenceElement,
4498
4546
  showTooltip
4499
4547
  }) {
4500
- const handleWindowMouseMove = useEffectEvent((event) => {
4501
- referenceElement && (referenceElement === event.target || event.target instanceof Node && referenceElement.contains(event.target) || handleIsOpenChange(!1));
4548
+ const onMouseMove = useEffectEvent((target) => {
4549
+ referenceElement && (referenceElement === target || target instanceof Node && referenceElement.contains(target) || handleIsOpenChange(!1));
4502
4550
  });
4503
4551
  useEffect(() => {
4504
- if (showTooltip)
4505
- return window.addEventListener("mousemove", handleWindowMouseMove), () => window.removeEventListener("mousemove", handleWindowMouseMove);
4506
- }, [handleWindowMouseMove, showTooltip]);
4552
+ if (!showTooltip) return;
4553
+ const handleMouseMove = (event) => {
4554
+ onMouseMove(event.target);
4555
+ };
4556
+ return window.addEventListener("mousemove", handleMouseMove), () => window.removeEventListener("mousemove", handleMouseMove);
4557
+ }, [onMouseMove, showTooltip]);
4507
4558
  }
4508
4559
  const Root$9 = styled.div`
4509
4560
  line-height: 0;
@@ -4916,8 +4967,8 @@ const AUTOCOMPLETE_LISTBOX_IGNORE_KEYS = [
4916
4967
  appearance: none;
4917
4968
  margin: -4px;
4918
4969
  `, 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]);
4970
+ 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), []);
4971
+ useClickOutside(collapse, [expandElement, popoverElement]);
4921
4972
  const rawItems = useMemo(() => Children.toArray(children).filter(isValidElement), [children]), items = useMemo(() => {
4922
4973
  const len = rawItems.length;
4923
4974
  if (maxLength && len > maxLength) {
@@ -4932,7 +4983,7 @@ const AUTOCOMPLETE_LISTBOX_IGNORE_KEYS = [
4932
4983
  open,
4933
4984
  placement: "top",
4934
4985
  portal: !0,
4935
- ref: popoverElementRef,
4986
+ ref: setPopoverElement,
4936
4987
  children: /* @__PURE__ */ jsx(
4937
4988
  ExpandButton,
4938
4989
  {
@@ -4940,7 +4991,7 @@ const AUTOCOMPLETE_LISTBOX_IGNORE_KEYS = [
4940
4991
  mode: "bleed",
4941
4992
  onClick: open ? collapse : expand,
4942
4993
  padding: 1,
4943
- ref: expandElementRef,
4994
+ ref: setExpandElement,
4944
4995
  selected: open,
4945
4996
  text: "\u2026"
4946
4997
  }
@@ -5065,8 +5116,8 @@ const Root$7 = styled(Layer)(responsivePaddingStyle, dialogStyle, responsiveDial
5065
5116
  scheme,
5066
5117
  shadow: shadowProp,
5067
5118
  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(
5119
+ } = 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;
5120
+ useImperativeHandle(forwardedRef, () => ref.current), useImperativeHandle(
5070
5121
  forwardedContentRef,
5071
5122
  () => contentRef.current
5072
5123
  ), useEffect(() => {
@@ -5081,13 +5132,20 @@ const Root$7 = styled(Layer)(responsivePaddingStyle, dialogStyle, responsiveDial
5081
5132
  [boundaryElement, isTopLayer, onClose, portalElement]
5082
5133
  )
5083
5134
  ), 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: [
5135
+ useCallback(
5136
+ (event) => {
5137
+ if (!isTopLayer || !onClickOutside) return;
5138
+ const target = event.target;
5139
+ target && !isTargetWithinScope(boundaryElement, portalElement, target) || onClickOutside();
5140
+ },
5141
+ [boundaryElement, isTopLayer, onClickOutside, portalElement]
5142
+ ),
5143
+ [rootElement]
5144
+ );
5145
+ const setRef = useCallback((el) => {
5146
+ setRootElement(el), ref.current = el;
5147
+ }, []);
5148
+ 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
5149
  showHeader && /* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsxs(Flex, { align: "center", padding: 3, children: [
5092
5150
  /* @__PURE__ */ jsx(Box, { flex: 1, padding: 2, children: header && /* @__PURE__ */ jsx(Text, { id: labelId, size: 1, weight: "semibold", children: header }) }),
5093
5151
  showCloseButton && /* @__PURE__ */ jsx(Box, { flex: "none", children: /* @__PURE__ */ jsx(
@@ -5265,13 +5323,13 @@ function _sortElements(rootElement, elements) {
5265
5323
  elements.sort(_sort);
5266
5324
  }
5267
5325
  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) => {
5326
+ 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
5327
  _setActiveIndex(nextActiveIndex), activeIndexRef.current = nextActiveIndex;
5270
5328
  }, []), mount = useCallback(
5271
5329
  (element, selected) => {
5272
5330
  if (!element) return () => {
5273
5331
  };
5274
- if (elementsRef.current.indexOf(element) === -1 && (elementsRef.current.push(element), _sortElements(rootElementRef.current, elementsRef.current)), selected) {
5332
+ if (elementsRef.current.indexOf(element) === -1 && (elementsRef.current.push(element), _sortElements(rootElement, elementsRef.current)), selected) {
5275
5333
  const selectedIndex = elementsRef.current.indexOf(element);
5276
5334
  setActiveIndex(selectedIndex);
5277
5335
  }
@@ -5280,7 +5338,7 @@ function useMenuController(props) {
5280
5338
  idx > -1 && elementsRef.current.splice(idx, 1);
5281
5339
  };
5282
5340
  },
5283
- [rootElementRef, setActiveIndex]
5341
+ [rootElement, setActiveIndex]
5284
5342
  ), handleKeyDown = useCallback(
5285
5343
  (event) => {
5286
5344
  if (event.key === "Tab") {
@@ -5335,13 +5393,13 @@ function useMenuController(props) {
5335
5393
  },
5336
5394
  [setActiveIndex]
5337
5395
  ), handleItemMouseLeave = useCallback(() => {
5338
- var _a;
5339
- setActiveIndex(-2), (_a = rootElementRef.current) == null || _a.focus();
5340
- }, [rootElementRef, setActiveIndex]);
5396
+ setActiveIndex(-2), rootElement == null || rootElement.focus();
5397
+ }, [setActiveIndex, rootElement]);
5341
5398
  return useEffect(() => {
5342
5399
  if (!mounted) return;
5343
5400
  const rafId = window.requestAnimationFrame(() => {
5344
- if (activeIndex === -1) {
5401
+ const _activeIndex = activeIndexRef.current;
5402
+ if (_activeIndex === -1) {
5345
5403
  if (shouldFocus === "first") {
5346
5404
  const el = _getFocusableElements(elementsRef.current)[0];
5347
5405
  if (el) {
@@ -5358,7 +5416,7 @@ function useMenuController(props) {
5358
5416
  }
5359
5417
  return;
5360
5418
  }
5361
- const element = elementsRef.current[activeIndex] || null;
5419
+ const element = elementsRef.current[_activeIndex] || null;
5362
5420
  element == null || element.focus();
5363
5421
  });
5364
5422
  return () => {
@@ -5370,7 +5428,9 @@ function useMenuController(props) {
5370
5428
  handleItemMouseEnter,
5371
5429
  handleItemMouseLeave,
5372
5430
  handleKeyDown,
5373
- mount
5431
+ mount,
5432
+ rootElement,
5433
+ setRootElement
5374
5434
  };
5375
5435
  }
5376
5436
  const Root$5 = styled(Box)`
@@ -5402,18 +5462,23 @@ const Root$5 = styled(Box)`
5402
5462
  handleItemMouseEnter,
5403
5463
  handleItemMouseLeave,
5404
5464
  handleKeyDown,
5405
- mount
5406
- } = useMenuController({ onKeyDown, originElement, shouldFocus, rootElementRef: ref }), handleRefChange = useCallback(
5465
+ mount,
5466
+ rootElement,
5467
+ setRootElement
5468
+ } = useMenuController({ onKeyDown, originElement, shouldFocus }), handleRefChange = useCallback(
5407
5469
  (el) => {
5408
- ref.current = el, ref.current && registerElement && registerElement(ref.current);
5470
+ setRootElement(el), ref.current = el;
5409
5471
  },
5410
- [registerElement]
5472
+ [setRootElement]
5411
5473
  );
5412
5474
  useEffect(() => {
5413
5475
  onItemSelect && onItemSelect(activeIndex);
5414
5476
  }, [activeIndex, onItemSelect]), useClickOutside(
5415
- (event) => isTopLayer && onClickOutside && onClickOutside(event),
5416
- () => [ref.current]
5477
+ useCallback(
5478
+ (event) => isTopLayer && onClickOutside && onClickOutside(event),
5479
+ [isTopLayer, onClickOutside]
5480
+ ),
5481
+ [rootElement]
5417
5482
  ), useGlobalKeyDown(
5418
5483
  useCallback(
5419
5484
  (event) => {
@@ -5421,7 +5486,10 @@ const Root$5 = styled(Box)`
5421
5486
  },
5422
5487
  [isTopLayer, onEscape]
5423
5488
  )
5424
- );
5489
+ ), useEffect(() => {
5490
+ if (!(!rootElement || !registerElement))
5491
+ return registerElement(rootElement);
5492
+ }, [registerElement, rootElement]);
5425
5493
  const value = useMemo(
5426
5494
  () => ({
5427
5495
  version: 0,
@@ -6097,7 +6165,7 @@ const CustomInline = styled(Inline)`
6097
6165
  }
6098
6166
  100% {
6099
6167
  width: 100%;
6100
- }
6168
+ }
6101
6169
  `, LOADING_BAR_HEIGHT = 2;
6102
6170
  function rootStyles(props) {
6103
6171
  const { color } = getTheme_v2$1(props.theme), loadingBarColor = color.button.default[props.tone].enabled.bg;
@@ -6795,7 +6863,6 @@ export {
6795
6863
  useForwardedRef,
6796
6864
  useGlobalKeyDown,
6797
6865
  useLayer,
6798
- useMatchMedia,
6799
6866
  useMediaIndex,
6800
6867
  usePortal,
6801
6868
  usePrefersDark,