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

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