({
triggerEl,
contentEl,
trigger,
open: openProp,
defaultOpen = false,
onOpenChange,
disableHoverableContent = false,
skipDelayDuration,
delayDuration: delayDurationProp,
dispatchDiscreteCustomEvent,
getChildOpens,
}: PointerOpenOptions)
| 34 | } |
| 35 | |
| 36 | export const usePointerOpen = ({ |
| 37 | triggerEl, |
| 38 | contentEl, |
| 39 | trigger, |
| 40 | open: openProp, |
| 41 | defaultOpen = false, |
| 42 | onOpenChange, |
| 43 | disableHoverableContent = false, |
| 44 | skipDelayDuration, |
| 45 | delayDuration: delayDurationProp, |
| 46 | dispatchDiscreteCustomEvent, |
| 47 | getChildOpens, |
| 48 | }: PointerOpenOptions): [boolean, (open: boolean) => void] => { |
| 49 | const isPointerDownRef = React.useRef(false) |
| 50 | const hasPointerMoveOpenedRef = React.useRef(false) |
| 51 | const handlePointerUp = React.useCallback(() => (isPointerDownRef.current = false), []) |
| 52 | const [isOpenDelayed, setIsOpenDelayed] = React.useState(true) |
| 53 | const skipDelayTimerRef = React.useRef(0) |
| 54 | const [open = false, setOpen] = useControllableState({ |
| 55 | prop: openProp, |
| 56 | defaultProp: defaultOpen, |
| 57 | onChange: open => { |
| 58 | if (open) { |
| 59 | window.clearTimeout(skipDelayTimerRef.current) |
| 60 | setIsOpenDelayed(false) |
| 61 | |
| 62 | // as `onChange` is called within a lifecycle method we |
| 63 | // avoid dispatching via `dispatchDiscreteCustomEvent`. |
| 64 | if (dispatchDiscreteCustomEvent) |
| 65 | document.dispatchEvent(new CustomEvent(dispatchDiscreteCustomEvent)) |
| 66 | } else { |
| 67 | window.clearTimeout(skipDelayTimerRef.current) |
| 68 | skipDelayTimerRef.current = window.setTimeout( |
| 69 | () => setIsOpenDelayed(true), |
| 70 | skipDelayDuration, |
| 71 | ) |
| 72 | } |
| 73 | onOpenChange?.(open) |
| 74 | }, |
| 75 | }) |
| 76 | const openTimerRef = React.useRef(0) |
| 77 | const delayDuration = delayDurationProp ?? 300 |
| 78 | const wasOpenDelayedRef = React.useRef(false) |
| 79 | const handleOpen = React.useCallback(() => { |
| 80 | window.clearTimeout(openTimerRef.current) |
| 81 | wasOpenDelayedRef.current = false |
| 82 | setOpen(true) |
| 83 | }, [setOpen]) |
| 84 | |
| 85 | const handleClose = React.useCallback(() => { |
| 86 | window.clearTimeout(openTimerRef.current) |
| 87 | setOpen(false) |
| 88 | }, [setOpen]) |
| 89 | |
| 90 | const handleDelayedOpen = React.useCallback(() => { |
| 91 | window.clearTimeout(openTimerRef.current) |
| 92 | openTimerRef.current = window.setTimeout(() => { |
| 93 | wasOpenDelayedRef.current = true |
no test coverage detected
searching dependent graphs…