Tldraw/packages/editor/src/lib/hooks/useSelectionEvents.ts

103 wiersze
2.3 KiB
TypeScript

import { useMemo } from 'react'
import { RIGHT_MOUSE_BUTTON } from '../constants'
import { TLSelectionHandle } from '../editor/types/selection-types'
import {
loopToHtmlElement,
releasePointerCapture,
setPointerCapture,
stopEventPropagation,
} from '../utils/dom'
import { getPointerInfo } from '../utils/getPointerInfo'
import { useEditor } from './useEditor'
/** @public */
export function useSelectionEvents(handle: TLSelectionHandle) {
const editor = useEditor()
const events = useMemo(
function selectionEvents() {
const onPointerDown: React.PointerEventHandler = (e) => {
if ((e as any).isKilled) return
if (e.button === RIGHT_MOUSE_BUTTON) {
editor.dispatch({
type: 'pointer',
target: 'selection',
handle,
name: 'right_click',
...getPointerInfo(e),
})
return
}
if (e.button !== 0) return
// Because the events are probably set on SVG elements,
// we need to instead place pointer capture on the first HTML
// element above the event's target; and set a listener to
// remove pointer capture when the pointer is released.
const elm = loopToHtmlElement(e.currentTarget)
function releaseCapture() {
elm.removeEventListener('pointerup', releaseCapture)
releasePointerCapture(elm, e)
}
setPointerCapture(elm, e)
elm.addEventListener('pointerup', releaseCapture)
editor.dispatch({
name: 'pointer_down',
type: 'pointer',
target: 'selection',
handle,
...getPointerInfo(e),
})
stopEventPropagation(e)
}
// Track the last screen point
let lastX: number, lastY: number
function onPointerMove(e: React.PointerEvent) {
if ((e as any).isKilled) return
if (e.button !== 0) return
if (e.clientX === lastX && e.clientY === lastY) return
lastX = e.clientX
lastY = e.clientY
editor.dispatch({
name: 'pointer_move',
type: 'pointer',
target: 'selection',
handle,
...getPointerInfo(e),
})
}
const onPointerUp: React.PointerEventHandler = (e) => {
if ((e as any).isKilled) return
if (e.button !== 0) return
editor.dispatch({
name: 'pointer_up',
type: 'pointer',
target: 'selection',
handle,
...getPointerInfo(e),
})
}
return {
onPointerDown,
onPointerMove,
onPointerUp,
}
},
[editor, handle]
)
return events
}