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.

handles.tsx 1.6KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. import useHandleEvents from 'hooks/useHandleEvents'
  2. import { getShapeUtils } from 'lib/shape-utils'
  3. import { useRef } from 'react'
  4. import { useSelector } from 'state'
  5. import styled from 'styles'
  6. import { deepCompareArrays, getPage } from 'utils/utils'
  7. import * as vec from 'utils/vec'
  8. export default function Handles() {
  9. const selectedIds = useSelector(
  10. (s) => Array.from(s.values.selectedIds.values()),
  11. deepCompareArrays
  12. )
  13. const shape = useSelector(
  14. ({ data }) =>
  15. selectedIds.length === 1 && getPage(data).shapes[selectedIds[0]]
  16. )
  17. const isTranslatingHandles = useSelector((s) => s.isIn('translatingHandles'))
  18. if (!shape.handles || isTranslatingHandles) return null
  19. return (
  20. <g>
  21. {Object.values(shape.handles).map((handle) => (
  22. <Handle
  23. key={handle.id}
  24. shapeId={shape.id}
  25. id={handle.id}
  26. point={vec.add(handle.point, shape.point)}
  27. />
  28. ))}
  29. </g>
  30. )
  31. }
  32. function Handle({
  33. shapeId,
  34. id,
  35. point,
  36. }: {
  37. shapeId: string
  38. id: string
  39. point: number[]
  40. }) {
  41. const rGroup = useRef<SVGGElement>(null)
  42. const events = useHandleEvents(id, rGroup)
  43. const transform = `
  44. translate(${point})
  45. `
  46. return (
  47. <g
  48. key={id}
  49. ref={rGroup}
  50. {...events}
  51. pointerEvents="all"
  52. transform={`translate(${point})`}
  53. >
  54. <HandleCircleOuter r={8} />
  55. <HandleCircle r={4} />
  56. </g>
  57. )
  58. }
  59. const HandleCircleOuter = styled('circle', {
  60. fill: 'transparent',
  61. pointerEvents: 'all',
  62. cursor: 'pointer',
  63. })
  64. const HandleCircle = styled('circle', {
  65. zStrokeWidth: 2,
  66. stroke: '$text',
  67. fill: '$panel',
  68. pointerEvents: 'none',
  69. })