@sanity/ui 2.6.7-canary.0 → 2.6.8-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/index.d.mts +6 -42
  2. package/dist/index.d.ts +6 -42
  3. package/dist/index.esm.js +158 -87
  4. package/dist/index.esm.js.map +1 -1
  5. package/dist/index.js +157 -86
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.mjs +158 -87
  8. package/dist/index.mjs.map +1 -1
  9. package/package.json +1 -1
  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/tooltipDelayGroup/tooltipDelayGroupProvider.tsx +0 -1
  33. package/src/core/utils/layer/layerProvider.tsx +0 -1
  34. package/src/core/utils/portal/__workshop__/named.tsx +8 -10
  35. package/src/core/utils/portal/portalProvider.tsx +13 -7
  36. 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,6 +1,6 @@
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, useLayoutEffect, 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";
@@ -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);
591
611
  }
592
- function usePrefersDark(getServerSnapshot2 = () => !1) {
593
- return useMatchMedia("(prefers-color-scheme: dark)", getServerSnapshot2);
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;
594
615
  }
595
- function usePrefersReducedMotion(getServerSnapshot2 = () => !1) {
596
- return useMatchMedia("(prefers-reduced-motion: reduce)", getServerSnapshot2);
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,25 +3060,31 @@ 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
  }
3022
- function useMounted() {
3023
- return useSyncExternalStore(
3024
- subscribe,
3025
- () => !0,
3026
- () => !1
3027
- );
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]);
3028
3072
  }
3029
- const subscribe = () => () => {
3030
- };
3031
3073
  function PortalProvider(props) {
3032
- const { boundaryElement, children, element, __unstable_elements: elements } = props, mounted = useMounted(), value = useMemo(() => ({
3074
+ const { boundaryElement, children, element, __unstable_elements: elementsProp } = props, elements = useUnique(elementsProp), fallbackElement = useSyncExternalStore(
3075
+ emptySubscribe,
3076
+ () => document.body,
3077
+ () => null
3078
+ ), value = useMemo(() => ({
3033
3079
  version: 0,
3034
3080
  boundaryElement: boundaryElement || null,
3035
- element: element || mounted ? document.body : null,
3081
+ element: element || fallbackElement,
3036
3082
  elements
3037
- }), [boundaryElement, element, elements, mounted]);
3083
+ }), [boundaryElement, element, elements, fallbackElement]);
3038
3084
  return /* @__PURE__ */ jsx(PortalContext.Provider, { value, children });
3039
3085
  }
3040
- const Root$i = styled.div`
3086
+ const emptySubscribe = () => () => {
3087
+ }, Root$i = styled.div`
3041
3088
  display: block;
3042
3089
  width: 0;
3043
3090
  height: 0;
@@ -4916,8 +4963,8 @@ const AUTOCOMPLETE_LISTBOX_IGNORE_KEYS = [
4916
4963
  appearance: none;
4917
4964
  margin: -4px;
4918
4965
  `, 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]);
4966
+ 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), []);
4967
+ useClickOutside(collapse, [expandElement, popoverElement]);
4921
4968
  const rawItems = useMemo(() => Children.toArray(children).filter(isValidElement), [children]), items = useMemo(() => {
4922
4969
  const len = rawItems.length;
4923
4970
  if (maxLength && len > maxLength) {
@@ -4932,7 +4979,7 @@ const AUTOCOMPLETE_LISTBOX_IGNORE_KEYS = [
4932
4979
  open,
4933
4980
  placement: "top",
4934
4981
  portal: !0,
4935
- ref: popoverElementRef,
4982
+ ref: setPopoverElement,
4936
4983
  children: /* @__PURE__ */ jsx(
4937
4984
  ExpandButton,
4938
4985
  {
@@ -4940,7 +4987,7 @@ const AUTOCOMPLETE_LISTBOX_IGNORE_KEYS = [
4940
4987
  mode: "bleed",
4941
4988
  onClick: open ? collapse : expand,
4942
4989
  padding: 1,
4943
- ref: expandElementRef,
4990
+ ref: setExpandElement,
4944
4991
  selected: open,
4945
4992
  text: "\u2026"
4946
4993
  }
@@ -5065,8 +5112,8 @@ const Root$7 = styled(Layer)(responsivePaddingStyle, dialogStyle, responsiveDial
5065
5112
  scheme,
5066
5113
  shadow: shadowProp,
5067
5114
  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(
5115
+ } = 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;
5116
+ useImperativeHandle(forwardedRef, () => ref.current), useImperativeHandle(
5070
5117
  forwardedContentRef,
5071
5118
  () => contentRef.current
5072
5119
  ), useEffect(() => {
@@ -5081,13 +5128,20 @@ const Root$7 = styled(Layer)(responsivePaddingStyle, dialogStyle, responsiveDial
5081
5128
  [boundaryElement, isTopLayer, onClose, portalElement]
5082
5129
  )
5083
5130
  ), 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: [
5131
+ useCallback(
5132
+ (event) => {
5133
+ if (!isTopLayer || !onClickOutside) return;
5134
+ const target = event.target;
5135
+ target && !isTargetWithinScope(boundaryElement, portalElement, target) || onClickOutside();
5136
+ },
5137
+ [boundaryElement, isTopLayer, onClickOutside, portalElement]
5138
+ ),
5139
+ [rootElement]
5140
+ );
5141
+ const setRef = useCallback((el) => {
5142
+ setRootElement(el), ref.current = el;
5143
+ }, []);
5144
+ 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
5145
  showHeader && /* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsxs(Flex, { align: "center", padding: 3, children: [
5092
5146
  /* @__PURE__ */ jsx(Box, { flex: 1, padding: 2, children: header && /* @__PURE__ */ jsx(Text, { id: labelId, size: 1, weight: "semibold", children: header }) }),
5093
5147
  showCloseButton && /* @__PURE__ */ jsx(Box, { flex: "none", children: /* @__PURE__ */ jsx(
@@ -5265,13 +5319,13 @@ function _sortElements(rootElement, elements) {
5265
5319
  elements.sort(_sort);
5266
5320
  }
5267
5321
  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) => {
5322
+ 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
5323
  _setActiveIndex(nextActiveIndex), activeIndexRef.current = nextActiveIndex;
5270
5324
  }, []), mount = useCallback(
5271
5325
  (element, selected) => {
5272
5326
  if (!element) return () => {
5273
5327
  };
5274
- if (elementsRef.current.indexOf(element) === -1 && (elementsRef.current.push(element), _sortElements(rootElementRef.current, elementsRef.current)), selected) {
5328
+ if (elementsRef.current.indexOf(element) === -1 && (elementsRef.current.push(element), _sortElements(rootElement, elementsRef.current)), selected) {
5275
5329
  const selectedIndex = elementsRef.current.indexOf(element);
5276
5330
  setActiveIndex(selectedIndex);
5277
5331
  }
@@ -5280,7 +5334,7 @@ function useMenuController(props) {
5280
5334
  idx > -1 && elementsRef.current.splice(idx, 1);
5281
5335
  };
5282
5336
  },
5283
- [rootElementRef, setActiveIndex]
5337
+ [rootElement, setActiveIndex]
5284
5338
  ), handleKeyDown = useCallback(
5285
5339
  (event) => {
5286
5340
  if (event.key === "Tab") {
@@ -5335,13 +5389,13 @@ function useMenuController(props) {
5335
5389
  },
5336
5390
  [setActiveIndex]
5337
5391
  ), handleItemMouseLeave = useCallback(() => {
5338
- var _a;
5339
- setActiveIndex(-2), (_a = rootElementRef.current) == null || _a.focus();
5340
- }, [rootElementRef, setActiveIndex]);
5392
+ setActiveIndex(-2), rootElement == null || rootElement.focus();
5393
+ }, [setActiveIndex, rootElement]);
5341
5394
  return useEffect(() => {
5342
5395
  if (!mounted) return;
5343
5396
  const rafId = window.requestAnimationFrame(() => {
5344
- if (activeIndex === -1) {
5397
+ const _activeIndex = activeIndexRef.current;
5398
+ if (_activeIndex === -1) {
5345
5399
  if (shouldFocus === "first") {
5346
5400
  const el = _getFocusableElements(elementsRef.current)[0];
5347
5401
  if (el) {
@@ -5358,7 +5412,7 @@ function useMenuController(props) {
5358
5412
  }
5359
5413
  return;
5360
5414
  }
5361
- const element = elementsRef.current[activeIndex] || null;
5415
+ const element = elementsRef.current[_activeIndex] || null;
5362
5416
  element == null || element.focus();
5363
5417
  });
5364
5418
  return () => {
@@ -5370,7 +5424,9 @@ function useMenuController(props) {
5370
5424
  handleItemMouseEnter,
5371
5425
  handleItemMouseLeave,
5372
5426
  handleKeyDown,
5373
- mount
5427
+ mount,
5428
+ rootElement,
5429
+ setRootElement
5374
5430
  };
5375
5431
  }
5376
5432
  const Root$5 = styled(Box)`
@@ -5402,18 +5458,23 @@ const Root$5 = styled(Box)`
5402
5458
  handleItemMouseEnter,
5403
5459
  handleItemMouseLeave,
5404
5460
  handleKeyDown,
5405
- mount
5406
- } = useMenuController({ onKeyDown, originElement, shouldFocus, rootElementRef: ref }), handleRefChange = useCallback(
5461
+ mount,
5462
+ rootElement,
5463
+ setRootElement
5464
+ } = useMenuController({ onKeyDown, originElement, shouldFocus }), handleRefChange = useCallback(
5407
5465
  (el) => {
5408
- ref.current = el, ref.current && registerElement && registerElement(ref.current);
5466
+ setRootElement(el), ref.current = el;
5409
5467
  },
5410
- [registerElement]
5468
+ [setRootElement]
5411
5469
  );
5412
5470
  useEffect(() => {
5413
5471
  onItemSelect && onItemSelect(activeIndex);
5414
5472
  }, [activeIndex, onItemSelect]), useClickOutside(
5415
- (event) => isTopLayer && onClickOutside && onClickOutside(event),
5416
- () => [ref.current]
5473
+ useCallback(
5474
+ (event) => isTopLayer && onClickOutside && onClickOutside(event),
5475
+ [isTopLayer, onClickOutside]
5476
+ ),
5477
+ [rootElement]
5417
5478
  ), useGlobalKeyDown(
5418
5479
  useCallback(
5419
5480
  (event) => {
@@ -5421,7 +5482,10 @@ const Root$5 = styled(Box)`
5421
5482
  },
5422
5483
  [isTopLayer, onEscape]
5423
5484
  )
5424
- );
5485
+ ), useEffect(() => {
5486
+ if (!(!rootElement || !registerElement))
5487
+ return registerElement(rootElement);
5488
+ }, [registerElement, rootElement]);
5425
5489
  const value = useMemo(
5426
5490
  () => ({
5427
5491
  version: 0,
@@ -6097,7 +6161,7 @@ const CustomInline = styled(Inline)`
6097
6161
  }
6098
6162
  100% {
6099
6163
  width: 100%;
6100
- }
6164
+ }
6101
6165
  `, LOADING_BAR_HEIGHT = 2;
6102
6166
  function rootStyles(props) {
6103
6167
  const { color } = getTheme_v2$1(props.theme), loadingBarColor = color.button.default[props.tone].enabled.bg;
@@ -6183,7 +6247,15 @@ function Toast(props) {
6183
6247
  }
6184
6248
  );
6185
6249
  }
6186
- const key$1 = Symbol.for("@sanity/ui/context/toast"), ToastContext = createGlobalScopedContext(key$1, null), Root$1 = styled(Layer)`
6250
+ function useMounted() {
6251
+ return useSyncExternalStore(
6252
+ subscribe,
6253
+ () => !0,
6254
+ () => !1
6255
+ );
6256
+ }
6257
+ const subscribe = () => () => {
6258
+ }, key$1 = Symbol.for("@sanity/ui/context/toast"), ToastContext = createGlobalScopedContext(key$1, null), Root$1 = styled(Layer)`
6187
6259
  position: fixed;
6188
6260
  top: 0;
6189
6261
  left: 0;
@@ -6795,7 +6867,6 @@ export {
6795
6867
  useForwardedRef,
6796
6868
  useGlobalKeyDown,
6797
6869
  useLayer,
6798
- useMatchMedia,
6799
6870
  useMediaIndex,
6800
6871
  usePortal,
6801
6872
  usePrefersDark,