@sanity/ui 2.7.1-canary.0 → 2.7.1-canary.2
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.
- package/dist/index.d.mts +67 -3
- package/dist/index.d.ts +67 -3
- package/dist/index.esm.js +29 -61
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +28 -60
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +29 -61
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
- package/src/core/components/dialog/dialog.tsx +9 -12
- package/src/core/components/menu/menu.tsx +1 -7
- package/src/core/hooks/useClickOutside.test.tsx +592 -0
- package/src/core/hooks/useClickOutside.ts +112 -63
- package/src/core/hooks/useMatchMedia.ts +3 -9
- package/src/core/primitives/popover/__workshop__/AlignedStory.tsx +9 -7
package/dist/index.d.mts
CHANGED
|
@@ -625,6 +625,11 @@ export declare interface CheckboxProps {
|
|
|
625
625
|
customValidity?: string
|
|
626
626
|
}
|
|
627
627
|
|
|
628
|
+
/**
|
|
629
|
+
* @public
|
|
630
|
+
*/
|
|
631
|
+
export declare type ClickOutsideElements = (HTMLElement | null | (HTMLElement | null)[])[]
|
|
632
|
+
|
|
628
633
|
/**
|
|
629
634
|
* @public
|
|
630
635
|
*/
|
|
@@ -2652,10 +2657,69 @@ export declare function useBoundaryElement(): BoundaryElementContextValue
|
|
|
2652
2657
|
* @public
|
|
2653
2658
|
*/
|
|
2654
2659
|
export declare function useClickOutside(
|
|
2655
|
-
listener: ClickOutsideListener,
|
|
2656
|
-
elementsArg
|
|
2660
|
+
listener: ClickOutsideListener | false | undefined,
|
|
2661
|
+
elementsArg: () => ClickOutsideElements,
|
|
2662
|
+
boundaryElement?: () => HTMLElement | null,
|
|
2663
|
+
): void
|
|
2664
|
+
|
|
2665
|
+
/**
|
|
2666
|
+
* @public
|
|
2667
|
+
* @deprecated - change `useClickOutside(handler, () => [...], boundary)` to `useClickOutside(handler, () => [...], () => boundary)`
|
|
2668
|
+
*/
|
|
2669
|
+
export declare function useClickOutside(
|
|
2670
|
+
listener: ClickOutsideListener | false | undefined,
|
|
2671
|
+
elementsArg: () => ClickOutsideElements,
|
|
2672
|
+
boundaryElement: HTMLElement | null,
|
|
2673
|
+
): void
|
|
2674
|
+
|
|
2675
|
+
/**
|
|
2676
|
+
* @public
|
|
2677
|
+
* @deprecated - change `useClickOutside(handler, [...], () => boundary)` to `useClickOutside(handler, () => [...], () => boundary)`
|
|
2678
|
+
*/
|
|
2679
|
+
export declare function useClickOutside(
|
|
2680
|
+
listener: ClickOutsideListener | false | undefined,
|
|
2681
|
+
elementsArg: ClickOutsideElements,
|
|
2682
|
+
boundaryElement: () => HTMLElement | null,
|
|
2683
|
+
): UseClickOutsideSetElement
|
|
2684
|
+
|
|
2685
|
+
/**
|
|
2686
|
+
* @public
|
|
2687
|
+
* @deprecated
|
|
2688
|
+
* Instead of:
|
|
2689
|
+
* ```tsx
|
|
2690
|
+
* const buttonRef = useRef(null)
|
|
2691
|
+
* const setElement = useClickOutside(() => {}, [buttonRef.current])
|
|
2692
|
+
* return (
|
|
2693
|
+
* <>
|
|
2694
|
+
* <button ref={buttonRef} />
|
|
2695
|
+
* {open && <div ref={setElement} />}
|
|
2696
|
+
* </>
|
|
2697
|
+
* )
|
|
2698
|
+
* ```
|
|
2699
|
+
* Use:
|
|
2700
|
+
* ```tsx
|
|
2701
|
+
* const buttonRef = useRef()
|
|
2702
|
+
* const [element, setElement] = useState(null)
|
|
2703
|
+
* useClickOutside(() => {}, () => [buttonRef.current, element])
|
|
2704
|
+
* return (
|
|
2705
|
+
* <>
|
|
2706
|
+
* <button ref={buttonRef} />
|
|
2707
|
+
* {open && <div ref={setElement} />}
|
|
2708
|
+
* </>
|
|
2709
|
+
* )
|
|
2710
|
+
* ```
|
|
2711
|
+
*/
|
|
2712
|
+
export declare function useClickOutside(
|
|
2713
|
+
listener: ClickOutsideListener | false | undefined,
|
|
2714
|
+
elementsArg: ClickOutsideElements,
|
|
2657
2715
|
boundaryElement?: HTMLElement | null,
|
|
2658
|
-
):
|
|
2716
|
+
): UseClickOutsideSetElement
|
|
2717
|
+
|
|
2718
|
+
/**
|
|
2719
|
+
* @public
|
|
2720
|
+
* @deprecated - use your own `const [element, setElement] = useState(null)` logic instead
|
|
2721
|
+
*/
|
|
2722
|
+
export declare type UseClickOutsideSetElement = (el: HTMLElement | null) => void
|
|
2659
2723
|
|
|
2660
2724
|
/**
|
|
2661
2725
|
* @beta
|
package/dist/index.d.ts
CHANGED
|
@@ -625,6 +625,11 @@ export declare interface CheckboxProps {
|
|
|
625
625
|
customValidity?: string
|
|
626
626
|
}
|
|
627
627
|
|
|
628
|
+
/**
|
|
629
|
+
* @public
|
|
630
|
+
*/
|
|
631
|
+
export declare type ClickOutsideElements = (HTMLElement | null | (HTMLElement | null)[])[]
|
|
632
|
+
|
|
628
633
|
/**
|
|
629
634
|
* @public
|
|
630
635
|
*/
|
|
@@ -2652,10 +2657,69 @@ export declare function useBoundaryElement(): BoundaryElementContextValue
|
|
|
2652
2657
|
* @public
|
|
2653
2658
|
*/
|
|
2654
2659
|
export declare function useClickOutside(
|
|
2655
|
-
listener: ClickOutsideListener,
|
|
2656
|
-
elementsArg
|
|
2660
|
+
listener: ClickOutsideListener | false | undefined,
|
|
2661
|
+
elementsArg: () => ClickOutsideElements,
|
|
2662
|
+
boundaryElement?: () => HTMLElement | null,
|
|
2663
|
+
): void
|
|
2664
|
+
|
|
2665
|
+
/**
|
|
2666
|
+
* @public
|
|
2667
|
+
* @deprecated - change `useClickOutside(handler, () => [...], boundary)` to `useClickOutside(handler, () => [...], () => boundary)`
|
|
2668
|
+
*/
|
|
2669
|
+
export declare function useClickOutside(
|
|
2670
|
+
listener: ClickOutsideListener | false | undefined,
|
|
2671
|
+
elementsArg: () => ClickOutsideElements,
|
|
2672
|
+
boundaryElement: HTMLElement | null,
|
|
2673
|
+
): void
|
|
2674
|
+
|
|
2675
|
+
/**
|
|
2676
|
+
* @public
|
|
2677
|
+
* @deprecated - change `useClickOutside(handler, [...], () => boundary)` to `useClickOutside(handler, () => [...], () => boundary)`
|
|
2678
|
+
*/
|
|
2679
|
+
export declare function useClickOutside(
|
|
2680
|
+
listener: ClickOutsideListener | false | undefined,
|
|
2681
|
+
elementsArg: ClickOutsideElements,
|
|
2682
|
+
boundaryElement: () => HTMLElement | null,
|
|
2683
|
+
): UseClickOutsideSetElement
|
|
2684
|
+
|
|
2685
|
+
/**
|
|
2686
|
+
* @public
|
|
2687
|
+
* @deprecated
|
|
2688
|
+
* Instead of:
|
|
2689
|
+
* ```tsx
|
|
2690
|
+
* const buttonRef = useRef(null)
|
|
2691
|
+
* const setElement = useClickOutside(() => {}, [buttonRef.current])
|
|
2692
|
+
* return (
|
|
2693
|
+
* <>
|
|
2694
|
+
* <button ref={buttonRef} />
|
|
2695
|
+
* {open && <div ref={setElement} />}
|
|
2696
|
+
* </>
|
|
2697
|
+
* )
|
|
2698
|
+
* ```
|
|
2699
|
+
* Use:
|
|
2700
|
+
* ```tsx
|
|
2701
|
+
* const buttonRef = useRef()
|
|
2702
|
+
* const [element, setElement] = useState(null)
|
|
2703
|
+
* useClickOutside(() => {}, () => [buttonRef.current, element])
|
|
2704
|
+
* return (
|
|
2705
|
+
* <>
|
|
2706
|
+
* <button ref={buttonRef} />
|
|
2707
|
+
* {open && <div ref={setElement} />}
|
|
2708
|
+
* </>
|
|
2709
|
+
* )
|
|
2710
|
+
* ```
|
|
2711
|
+
*/
|
|
2712
|
+
export declare function useClickOutside(
|
|
2713
|
+
listener: ClickOutsideListener | false | undefined,
|
|
2714
|
+
elementsArg: ClickOutsideElements,
|
|
2657
2715
|
boundaryElement?: HTMLElement | null,
|
|
2658
|
-
):
|
|
2716
|
+
): UseClickOutsideSetElement
|
|
2717
|
+
|
|
2718
|
+
/**
|
|
2719
|
+
* @public
|
|
2720
|
+
* @deprecated - use your own `const [element, setElement] = useState(null)` logic instead
|
|
2721
|
+
*/
|
|
2722
|
+
export declare type UseClickOutsideSetElement = (el: HTMLElement | null) => void
|
|
2659
2723
|
|
|
2660
2724
|
/**
|
|
2661
2725
|
* @beta
|
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, useState,
|
|
3
|
+
import { useMemo, useState, useEffect, useRef, useImperativeHandle, useDebugValue, useSyncExternalStore, createContext, useContext, 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,45 +131,30 @@ 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
|
-
}
|
|
140
134
|
function useClickOutside(listener, elementsArg = EMPTY_ARRAY, boundaryElement) {
|
|
141
|
-
const [
|
|
142
|
-
|
|
143
|
-
const prevElements = elementsRef.current, nextElements = _getElements(element, elementsArg);
|
|
144
|
-
if (prevElements.length !== nextElements.length) {
|
|
145
|
-
setElements(nextElements), elementsRef.current = nextElements;
|
|
135
|
+
const [legacyElement, setLegacyElement] = useState(null), onEvent = useEffectEvent((evt) => {
|
|
136
|
+
if (!listener)
|
|
146
137
|
return;
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
138
|
+
const target = evt.target;
|
|
139
|
+
if (!(target instanceof Node))
|
|
140
|
+
return;
|
|
141
|
+
const resolvedBoundaryElement = typeof boundaryElement == "function" ? boundaryElement() : boundaryElement;
|
|
142
|
+
if (resolvedBoundaryElement && !resolvedBoundaryElement.contains(target))
|
|
143
|
+
return;
|
|
144
|
+
const elements = (Array.isArray(elementsArg) ? [legacyElement, ...elementsArg] : elementsArg()).flat();
|
|
145
|
+
for (const el of elements)
|
|
146
|
+
if (el && (target === el || el.contains(target)))
|
|
156
147
|
return;
|
|
157
|
-
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
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);
|
|
148
|
+
listener(evt);
|
|
149
|
+
}), hasListener = !!listener;
|
|
150
|
+
if (useEffect(() => {
|
|
151
|
+
if (!hasListener) return;
|
|
152
|
+
const handleEvent = (evt) => onEvent(evt);
|
|
153
|
+
return document.addEventListener("mousedown", handleEvent), () => {
|
|
154
|
+
document.removeEventListener("mousedown", handleEvent);
|
|
171
155
|
};
|
|
172
|
-
}, [
|
|
156
|
+
}, [hasListener, onEvent]), Array.isArray(elementsArg))
|
|
157
|
+
return setLegacyElement;
|
|
173
158
|
}
|
|
174
159
|
function useCustomValidity(ref, customValidity) {
|
|
175
160
|
useEffect(() => {
|
|
@@ -520,21 +505,13 @@ function useGlobalKeyDown(onKeyDown) {
|
|
|
520
505
|
function useMatchMedia(mediaQueryString, getServerSnapshot2) {
|
|
521
506
|
const { subscribe: subscribe2, getSnapshot } = useMemo(() => {
|
|
522
507
|
let MEDIA_QUERY_CACHE;
|
|
523
|
-
|
|
524
|
-
return MEDIA_QUERY_CACHE === void 0 && (MEDIA_QUERY_CACHE = window.matchMedia(mediaQueryString)), MEDIA_QUERY_CACHE;
|
|
525
|
-
}
|
|
508
|
+
const getMatchMedia = () => (MEDIA_QUERY_CACHE || (MEDIA_QUERY_CACHE = window.matchMedia(mediaQueryString)), MEDIA_QUERY_CACHE);
|
|
526
509
|
return {
|
|
527
510
|
subscribe: (onStoreChange) => {
|
|
528
511
|
const matchMedia = getMatchMedia();
|
|
529
512
|
return matchMedia.addEventListener("change", onStoreChange), () => matchMedia.removeEventListener("change", onStoreChange);
|
|
530
513
|
},
|
|
531
|
-
getSnapshot: () =>
|
|
532
|
-
try {
|
|
533
|
-
return getMatchMedia().matches;
|
|
534
|
-
} catch (err) {
|
|
535
|
-
throw new Error(`Failed to match media query: ${mediaQueryString}`, { cause: err });
|
|
536
|
-
}
|
|
537
|
-
}
|
|
514
|
+
getSnapshot: () => getMatchMedia().matches
|
|
538
515
|
};
|
|
539
516
|
}, [mediaQueryString]);
|
|
540
517
|
return useDebugValue(mediaQueryString), useSyncExternalStore(subscribe2, getSnapshot, getServerSnapshot2);
|
|
@@ -5132,14 +5109,11 @@ const Root$7 = styled(Layer)(responsivePaddingStyle, dialogStyle, responsiveDial
|
|
|
5132
5109
|
[boundaryElement, isTopLayer, onClose, portalElement]
|
|
5133
5110
|
)
|
|
5134
5111
|
), useClickOutside(
|
|
5135
|
-
|
|
5136
|
-
(
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
},
|
|
5141
|
-
[boundaryElement, isTopLayer, onClickOutside, portalElement]
|
|
5142
|
-
),
|
|
5112
|
+
(event) => {
|
|
5113
|
+
if (!isTopLayer || !onClickOutside) return;
|
|
5114
|
+
const target = event.target;
|
|
5115
|
+
target && !isTargetWithinScope(boundaryElement, portalElement, target) || onClickOutside();
|
|
5116
|
+
},
|
|
5143
5117
|
[rootElement]
|
|
5144
5118
|
);
|
|
5145
5119
|
const setRef = useCallback((el) => {
|
|
@@ -5476,13 +5450,7 @@ const Root$5 = styled(Box)`
|
|
|
5476
5450
|
);
|
|
5477
5451
|
useEffect(() => {
|
|
5478
5452
|
onItemSelect && onItemSelect(activeIndex);
|
|
5479
|
-
}, [activeIndex, onItemSelect]), useClickOutside(
|
|
5480
|
-
useCallback(
|
|
5481
|
-
(event) => isTopLayer && onClickOutside && onClickOutside(event),
|
|
5482
|
-
[isTopLayer, onClickOutside]
|
|
5483
|
-
),
|
|
5484
|
-
[rootElement]
|
|
5485
|
-
), useGlobalKeyDown(
|
|
5453
|
+
}, [activeIndex, onItemSelect]), useClickOutside((event) => isTopLayer && onClickOutside && onClickOutside(event), [rootElement]), useGlobalKeyDown(
|
|
5486
5454
|
useCallback(
|
|
5487
5455
|
(event) => {
|
|
5488
5456
|
isTopLayer && event.key === "Escape" && (event.stopPropagation(), onEscape && onEscape());
|