@hakuna-matata-ui/hooks
Version:
React hooks for Chakra components
70 lines (60 loc) • 1.56 kB
text/typescript
import {
AnyPointerEvent,
noop,
PanEventHandler,
PanSession,
PanSessionHandlers,
} from "@hakuna-matata-ui/utils"
import React, { useEffect, useRef } from "react"
import { usePointerEvent } from "./use-pointer-event"
import { useUnmountEffect } from "./use-unmount-effect"
export interface UsePanGestureProps {
onPan?: PanEventHandler
onPanStart?: PanEventHandler
onPanEnd?: PanEventHandler
onPanSessionStart?: PanEventHandler
onPanSessionEnd?: PanEventHandler
threshold?: number
}
export function usePanGesture(
ref: React.RefObject<HTMLElement>,
props: UsePanGestureProps,
) {
const {
onPan,
onPanStart,
onPanEnd,
onPanSessionStart,
onPanSessionEnd,
threshold,
} = props
const hasPanEvents = Boolean(
onPan || onPanStart || onPanEnd || onPanSessionStart || onPanSessionEnd,
)
const panSession = useRef<PanSession | null>(null)
const handlers: Partial<PanSessionHandlers> = {
onSessionStart: onPanSessionStart,
onSessionEnd: onPanSessionEnd,
onStart: onPanStart,
onMove: onPan,
onEnd(event, info) {
panSession.current = null
onPanEnd?.(event, info)
},
}
useEffect(() => {
panSession.current?.updateHandlers(handlers)
})
function onPointerDown(event: AnyPointerEvent) {
panSession.current = new PanSession(event, handlers, threshold)
}
usePointerEvent(
() => ref.current,
"pointerdown",
hasPanEvents ? onPointerDown : noop,
)
useUnmountEffect(() => {
panSession.current?.end()
panSession.current = null
})
}