useCanvasEvents.ts 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. import * as React from 'react'
  2. import { TLTargetType } from '@tldraw/core'
  3. import { useApp } from './useApp'
  4. import { DOUBLE_CLICK_DURATION } from '../constants'
  5. import type { TLReactCustomEvents } from '../types'
  6. import { useRendererContext } from './useRendererContext'
  7. export function useCanvasEvents() {
  8. const app = useApp()
  9. const { callbacks } = useRendererContext()
  10. const rDoubleClickTimer = React.useRef<number>(-1)
  11. const events = React.useMemo(() => {
  12. const onPointerMove: TLReactCustomEvents['pointer'] = e => {
  13. const { order = 0 } = e
  14. callbacks.onPointerMove?.({ type: TLTargetType.Canvas, order }, e)
  15. }
  16. const onPointerDown: TLReactCustomEvents['pointer'] = e => {
  17. const { order = 0 } = e
  18. if (!order) e.currentTarget?.setPointerCapture(e.pointerId)
  19. callbacks.onPointerDown?.({ type: TLTargetType.Canvas, order }, e)
  20. const now = Date.now()
  21. const elapsed = now - rDoubleClickTimer.current
  22. if (elapsed > DOUBLE_CLICK_DURATION) {
  23. rDoubleClickTimer.current = now
  24. } else {
  25. if (elapsed <= DOUBLE_CLICK_DURATION) {
  26. callbacks.onDoubleClick?.({ type: TLTargetType.Canvas, order }, e)
  27. rDoubleClickTimer.current = -1
  28. }
  29. }
  30. }
  31. const onPointerUp: TLReactCustomEvents['pointer'] = e => {
  32. const { order = 0 } = e
  33. if (!order) e.currentTarget?.releasePointerCapture(e.pointerId)
  34. callbacks.onPointerUp?.({ type: TLTargetType.Canvas, order }, e)
  35. }
  36. const onPointerEnter: TLReactCustomEvents['pointer'] = e => {
  37. const { order = 0 } = e
  38. callbacks.onPointerEnter?.({ type: TLTargetType.Canvas, order }, e)
  39. }
  40. const onPointerLeave: TLReactCustomEvents['pointer'] = e => {
  41. const { order = 0 } = e
  42. callbacks.onPointerLeave?.({ type: TLTargetType.Canvas, order }, e)
  43. }
  44. const onDrop = async (e: React.DragEvent<Element>) => {
  45. e.preventDefault()
  46. const point = [e.clientX, e.clientY]
  47. app.drop(e.dataTransfer, point)
  48. }
  49. const onDragOver = (e: React.DragEvent<Element>) => {
  50. e.preventDefault()
  51. }
  52. return {
  53. onPointerDown,
  54. onPointerMove,
  55. onPointerUp,
  56. onPointerEnter,
  57. onPointerLeave,
  58. onDrop,
  59. onDragOver,
  60. }
  61. }, [callbacks])
  62. return events
  63. }