You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

useShapeEvents.ts 2.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /* eslint-disable @typescript-eslint/explicit-module-boundary-types */
  2. import React, { MutableRefObject, useCallback } from 'react'
  3. import state from 'state'
  4. import inputs from 'state/inputs'
  5. import Vec from 'utils/vec'
  6. export default function useShapeEvents(
  7. id: string,
  8. isCurrentParent: boolean,
  9. rGroup: MutableRefObject<SVGElement>
  10. ) {
  11. const handlePointerDown = useCallback(
  12. (e: React.PointerEvent) => {
  13. if (isCurrentParent) return
  14. if (!inputs.canAccept(e.pointerId)) return
  15. e.stopPropagation()
  16. rGroup.current.setPointerCapture(e.pointerId)
  17. const info = inputs.pointerDown(e, id)
  18. if (e.button === 0) {
  19. if (inputs.isDoubleClick() && !(info.altKey || info.metaKey)) {
  20. state.send('DOUBLE_POINTED_SHAPE', info)
  21. }
  22. state.send('POINTED_SHAPE', info)
  23. } else {
  24. state.send('RIGHT_POINTED', info)
  25. }
  26. },
  27. [id, isCurrentParent]
  28. )
  29. const handlePointerUp = useCallback(
  30. (e: React.PointerEvent) => {
  31. if (isCurrentParent) return
  32. if (!inputs.canAccept(e.pointerId)) return
  33. e.stopPropagation()
  34. rGroup.current.releasePointerCapture(e.pointerId)
  35. state.send('STOPPED_POINTING', inputs.pointerUp(e, id))
  36. },
  37. [id, isCurrentParent]
  38. )
  39. const handlePointerEnter = useCallback(
  40. (e: React.PointerEvent) => {
  41. if (isCurrentParent) return
  42. if (!inputs.canAccept(e.pointerId)) return
  43. e.stopPropagation()
  44. state.send('HOVERED_SHAPE', inputs.pointerEnter(e, id))
  45. },
  46. [id, isCurrentParent]
  47. )
  48. const handlePointerMove = useCallback(
  49. (e: React.PointerEvent) => {
  50. if (!inputs.canAccept(e.pointerId)) return
  51. const prev = inputs.pointer?.point
  52. const info = inputs.pointerMove(e)
  53. if (prev && state.isIn('selecting') && inputs.keys[' ']) {
  54. if (!e.currentTarget.hasPointerCapture(e.pointerId)) {
  55. e.currentTarget.setPointerCapture(e.pointerId)
  56. }
  57. state.send('KEYBOARD_PANNED_CAMERA', {
  58. delta: Vec.sub(prev, info.point),
  59. })
  60. return
  61. }
  62. if (isCurrentParent) return
  63. state.send('MOVED_OVER_SHAPE', inputs.pointerEnter(e, id))
  64. },
  65. [id, isCurrentParent]
  66. )
  67. const handlePointerLeave = useCallback(
  68. (e: React.PointerEvent) => {
  69. if (isCurrentParent) return
  70. if (!inputs.canAccept(e.pointerId)) return
  71. e.stopPropagation()
  72. state.send('UNHOVERED_SHAPE', { target: id })
  73. },
  74. [id, isCurrentParent]
  75. )
  76. const handleTouchStart = useCallback((e: React.TouchEvent) => {
  77. e.preventDefault()
  78. }, [])
  79. const handleTouchEnd = useCallback((e: React.TouchEvent) => {
  80. e.preventDefault()
  81. }, [])
  82. return {
  83. onPointerDown: handlePointerDown,
  84. onPointerUp: handlePointerUp,
  85. onPointerEnter: handlePointerEnter,
  86. onPointerMove: handlePointerMove,
  87. onPointerLeave: handlePointerLeave,
  88. onTouchStart: handleTouchStart,
  89. onTouchEnd: handleTouchEnd,
  90. }
  91. }