@sanity/ui 2.8.0 → 2.8.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 +25 -53
- package/dist/index.d.ts +25 -53
- package/dist/index.esm.js +61 -12
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +60 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +61 -12
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/core/components/dialog/dialog.tsx +12 -9
- package/src/core/components/menu/menu.tsx +7 -1
- package/src/core/hooks/index.ts +1 -0
- package/src/core/hooks/useClickOutside.test.tsx +0 -109
- package/src/core/hooks/useClickOutside.ts +70 -103
- package/src/core/hooks/useClickOutsideEvent.test.tsx +116 -0
- package/src/core/hooks/useClickOutsideEvent.ts +72 -0
- package/src/core/primitives/popover/__workshop__/AlignedStory.tsx +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -630,6 +630,16 @@ export declare interface CheckboxProps {
|
|
|
630
630
|
*/
|
|
631
631
|
export declare type ClickOutsideElements = (HTMLElement | null | (HTMLElement | null)[])[]
|
|
632
632
|
|
|
633
|
+
/**
|
|
634
|
+
* @public
|
|
635
|
+
*/
|
|
636
|
+
export declare type ClickOutsideEventElements = (HTMLElement | null | (HTMLElement | null)[])[]
|
|
637
|
+
|
|
638
|
+
/**
|
|
639
|
+
* @public
|
|
640
|
+
*/
|
|
641
|
+
export declare type ClickOutsideEventListener = (event: MouseEvent) => void
|
|
642
|
+
|
|
633
643
|
/**
|
|
634
644
|
* @public
|
|
635
645
|
*/
|
|
@@ -2655,71 +2665,33 @@ export declare function useBoundaryElement(): BoundaryElementContextValue
|
|
|
2655
2665
|
|
|
2656
2666
|
/**
|
|
2657
2667
|
* @public
|
|
2658
|
-
|
|
2659
|
-
export declare function useClickOutside(
|
|
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:
|
|
2668
|
+
* @deprecated replaced by the new `useClickOutsideEvent` hook, instead of:
|
|
2689
2669
|
* ```tsx
|
|
2690
|
-
* const
|
|
2691
|
-
*
|
|
2692
|
-
* return
|
|
2693
|
-
* <>
|
|
2694
|
-
* <button ref={buttonRef} />
|
|
2695
|
-
* {open && <div ref={setElement} />}
|
|
2696
|
-
* </>
|
|
2697
|
-
* )
|
|
2670
|
+
* const [button, setButtonElement] = useState(null)
|
|
2671
|
+
* useClickOutside((event) => {}, [button])
|
|
2672
|
+
* return <button ref={setButtonElement} />
|
|
2698
2673
|
* ```
|
|
2699
|
-
*
|
|
2674
|
+
* do:
|
|
2700
2675
|
* ```tsx
|
|
2701
2676
|
* const buttonRef = useRef()
|
|
2702
|
-
*
|
|
2703
|
-
*
|
|
2704
|
-
* return (
|
|
2705
|
-
* <>
|
|
2706
|
-
* <button ref={buttonRef} />
|
|
2707
|
-
* {open && <div ref={setElement} />}
|
|
2708
|
-
* </>
|
|
2709
|
-
* )
|
|
2677
|
+
* useClickOutsideEvent((event) => {}, () => [buttonRef.current])
|
|
2678
|
+
* return <button ref={buttonRef} />
|
|
2710
2679
|
* ```
|
|
2711
2680
|
*/
|
|
2712
2681
|
export declare function useClickOutside(
|
|
2713
|
-
listener: ClickOutsideListener
|
|
2714
|
-
elementsArg
|
|
2682
|
+
listener: ClickOutsideListener,
|
|
2683
|
+
elementsArg?: ClickOutsideElements,
|
|
2715
2684
|
boundaryElement?: HTMLElement | null,
|
|
2716
|
-
):
|
|
2685
|
+
): (el: HTMLElement | null) => void
|
|
2717
2686
|
|
|
2718
2687
|
/**
|
|
2719
2688
|
* @public
|
|
2720
|
-
* @deprecated - use your own `const [element, setElement] = useState(null)` logic instead
|
|
2721
2689
|
*/
|
|
2722
|
-
export declare
|
|
2690
|
+
export declare function useClickOutsideEvent(
|
|
2691
|
+
listener: ClickOutsideEventListener | false | undefined,
|
|
2692
|
+
elementsArg?: () => ClickOutsideEventElements,
|
|
2693
|
+
boundaryElement?: () => HTMLElement | null,
|
|
2694
|
+
): void
|
|
2723
2695
|
|
|
2724
2696
|
/**
|
|
2725
2697
|
* @beta
|
package/dist/index.d.ts
CHANGED
|
@@ -630,6 +630,16 @@ export declare interface CheckboxProps {
|
|
|
630
630
|
*/
|
|
631
631
|
export declare type ClickOutsideElements = (HTMLElement | null | (HTMLElement | null)[])[]
|
|
632
632
|
|
|
633
|
+
/**
|
|
634
|
+
* @public
|
|
635
|
+
*/
|
|
636
|
+
export declare type ClickOutsideEventElements = (HTMLElement | null | (HTMLElement | null)[])[]
|
|
637
|
+
|
|
638
|
+
/**
|
|
639
|
+
* @public
|
|
640
|
+
*/
|
|
641
|
+
export declare type ClickOutsideEventListener = (event: MouseEvent) => void
|
|
642
|
+
|
|
633
643
|
/**
|
|
634
644
|
* @public
|
|
635
645
|
*/
|
|
@@ -2655,71 +2665,33 @@ export declare function useBoundaryElement(): BoundaryElementContextValue
|
|
|
2655
2665
|
|
|
2656
2666
|
/**
|
|
2657
2667
|
* @public
|
|
2658
|
-
|
|
2659
|
-
export declare function useClickOutside(
|
|
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:
|
|
2668
|
+
* @deprecated replaced by the new `useClickOutsideEvent` hook, instead of:
|
|
2689
2669
|
* ```tsx
|
|
2690
|
-
* const
|
|
2691
|
-
*
|
|
2692
|
-
* return
|
|
2693
|
-
* <>
|
|
2694
|
-
* <button ref={buttonRef} />
|
|
2695
|
-
* {open && <div ref={setElement} />}
|
|
2696
|
-
* </>
|
|
2697
|
-
* )
|
|
2670
|
+
* const [button, setButtonElement] = useState(null)
|
|
2671
|
+
* useClickOutside((event) => {}, [button])
|
|
2672
|
+
* return <button ref={setButtonElement} />
|
|
2698
2673
|
* ```
|
|
2699
|
-
*
|
|
2674
|
+
* do:
|
|
2700
2675
|
* ```tsx
|
|
2701
2676
|
* const buttonRef = useRef()
|
|
2702
|
-
*
|
|
2703
|
-
*
|
|
2704
|
-
* return (
|
|
2705
|
-
* <>
|
|
2706
|
-
* <button ref={buttonRef} />
|
|
2707
|
-
* {open && <div ref={setElement} />}
|
|
2708
|
-
* </>
|
|
2709
|
-
* )
|
|
2677
|
+
* useClickOutsideEvent((event) => {}, () => [buttonRef.current])
|
|
2678
|
+
* return <button ref={buttonRef} />
|
|
2710
2679
|
* ```
|
|
2711
2680
|
*/
|
|
2712
2681
|
export declare function useClickOutside(
|
|
2713
|
-
listener: ClickOutsideListener
|
|
2714
|
-
elementsArg
|
|
2682
|
+
listener: ClickOutsideListener,
|
|
2683
|
+
elementsArg?: ClickOutsideElements,
|
|
2715
2684
|
boundaryElement?: HTMLElement | null,
|
|
2716
|
-
):
|
|
2685
|
+
): (el: HTMLElement | null) => void
|
|
2717
2686
|
|
|
2718
2687
|
/**
|
|
2719
2688
|
* @public
|
|
2720
|
-
* @deprecated - use your own `const [element, setElement] = useState(null)` logic instead
|
|
2721
2689
|
*/
|
|
2722
|
-
export declare
|
|
2690
|
+
export declare function useClickOutsideEvent(
|
|
2691
|
+
listener: ClickOutsideEventListener | false | undefined,
|
|
2692
|
+
elementsArg?: () => ClickOutsideEventElements,
|
|
2693
|
+
boundaryElement?: () => HTMLElement | null,
|
|
2694
|
+
): void
|
|
2723
2695
|
|
|
2724
2696
|
/**
|
|
2725
2697
|
* @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, useRef, useEffect, 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,8 +131,48 @@ 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 [
|
|
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;
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
for (const el of prevElements)
|
|
149
|
+
if (!nextElements.includes(el)) {
|
|
150
|
+
setElements(nextElements), elementsRef.current = nextElements;
|
|
151
|
+
return;
|
|
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;
|
|
173
|
+
}
|
|
174
|
+
function useClickOutsideEvent(listener, elementsArg = () => EMPTY_ARRAY, boundaryElement) {
|
|
175
|
+
const onEvent = useEffectEvent((evt) => {
|
|
136
176
|
if (!listener)
|
|
137
177
|
return;
|
|
138
178
|
const target = evt.target;
|
|
@@ -141,20 +181,19 @@ function useClickOutside(listener, elementsArg = EMPTY_ARRAY, boundaryElement) {
|
|
|
141
181
|
const resolvedBoundaryElement = typeof boundaryElement == "function" ? boundaryElement() : boundaryElement;
|
|
142
182
|
if (resolvedBoundaryElement && !resolvedBoundaryElement.contains(target))
|
|
143
183
|
return;
|
|
144
|
-
const elements = (Array.isArray(elementsArg) ?
|
|
184
|
+
const elements = (Array.isArray(elementsArg) ? elementsArg : elementsArg()).flat();
|
|
145
185
|
for (const el of elements)
|
|
146
186
|
if (el && (target === el || el.contains(target)))
|
|
147
187
|
return;
|
|
148
188
|
listener(evt);
|
|
149
189
|
}), hasListener = !!listener;
|
|
150
|
-
|
|
190
|
+
useEffect(() => {
|
|
151
191
|
if (!hasListener) return;
|
|
152
192
|
const handleEvent = (evt) => onEvent(evt);
|
|
153
193
|
return document.addEventListener("mousedown", handleEvent), () => {
|
|
154
194
|
document.removeEventListener("mousedown", handleEvent);
|
|
155
195
|
};
|
|
156
|
-
}, [hasListener, onEvent])
|
|
157
|
-
return setLegacyElement;
|
|
196
|
+
}, [hasListener, onEvent]);
|
|
158
197
|
}
|
|
159
198
|
function useCustomValidity(ref, customValidity) {
|
|
160
199
|
useEffect(() => {
|
|
@@ -5109,11 +5148,14 @@ const Root$7 = styled(Layer)(responsivePaddingStyle, dialogStyle, responsiveDial
|
|
|
5109
5148
|
[boundaryElement, isTopLayer, onClose, portalElement]
|
|
5110
5149
|
)
|
|
5111
5150
|
), useClickOutside(
|
|
5112
|
-
(
|
|
5113
|
-
|
|
5114
|
-
|
|
5115
|
-
|
|
5116
|
-
|
|
5151
|
+
useCallback(
|
|
5152
|
+
(event) => {
|
|
5153
|
+
if (!isTopLayer || !onClickOutside) return;
|
|
5154
|
+
const target = event.target;
|
|
5155
|
+
target && !isTargetWithinScope(boundaryElement, portalElement, target) || onClickOutside();
|
|
5156
|
+
},
|
|
5157
|
+
[boundaryElement, isTopLayer, onClickOutside, portalElement]
|
|
5158
|
+
),
|
|
5117
5159
|
[rootElement]
|
|
5118
5160
|
);
|
|
5119
5161
|
const setRef = useCallback((el) => {
|
|
@@ -5450,7 +5492,13 @@ const Root$5 = styled(Box)`
|
|
|
5450
5492
|
);
|
|
5451
5493
|
useEffect(() => {
|
|
5452
5494
|
onItemSelect && onItemSelect(activeIndex);
|
|
5453
|
-
}, [activeIndex, onItemSelect]), useClickOutside(
|
|
5495
|
+
}, [activeIndex, onItemSelect]), useClickOutside(
|
|
5496
|
+
useCallback(
|
|
5497
|
+
(event) => isTopLayer && onClickOutside && onClickOutside(event),
|
|
5498
|
+
[isTopLayer, onClickOutside]
|
|
5499
|
+
),
|
|
5500
|
+
[rootElement]
|
|
5501
|
+
), useGlobalKeyDown(
|
|
5454
5502
|
useCallback(
|
|
5455
5503
|
(event) => {
|
|
5456
5504
|
isTopLayer && event.key === "Escape" && (event.stopPropagation(), onEscape && onEscape());
|
|
@@ -6841,6 +6889,7 @@ export {
|
|
|
6841
6889
|
useArrayProp,
|
|
6842
6890
|
useBoundaryElement,
|
|
6843
6891
|
useClickOutside,
|
|
6892
|
+
useClickOutsideEvent,
|
|
6844
6893
|
useCustomValidity,
|
|
6845
6894
|
useDialog,
|
|
6846
6895
|
useElementRect,
|