2021-05-31 19:13:43 +00:00
|
|
|
import useHandleEvents from 'hooks/useHandleEvents'
|
2021-06-21 21:35:28 +00:00
|
|
|
import { getShapeUtils } from 'state/shape-utils'
|
2021-05-31 19:13:43 +00:00
|
|
|
import { useRef } from 'react'
|
|
|
|
import { useSelector } from 'state'
|
|
|
|
import styled from 'styles'
|
2021-06-29 12:00:59 +00:00
|
|
|
import tld from 'utils/tld'
|
2021-06-16 12:09:45 +00:00
|
|
|
import vec from 'utils/vec'
|
2021-05-31 19:13:43 +00:00
|
|
|
|
2021-06-21 21:35:28 +00:00
|
|
|
export default function Handles(): JSX.Element {
|
2021-05-31 19:13:43 +00:00
|
|
|
const shape = useSelector(
|
2021-06-28 12:13:34 +00:00
|
|
|
(s) =>
|
|
|
|
s.values.selectedIds.length === 1 &&
|
2021-06-29 12:00:59 +00:00
|
|
|
tld.getPage(s.data).shapes[s.values.selectedIds[0]]
|
2021-05-31 19:13:43 +00:00
|
|
|
)
|
|
|
|
|
2021-06-05 06:36:39 +00:00
|
|
|
const isSelecting = useSelector((s) =>
|
|
|
|
s.isInAny('notPointing', 'pinching', 'translatingHandles')
|
|
|
|
)
|
2021-05-31 19:13:43 +00:00
|
|
|
|
2021-06-10 09:49:16 +00:00
|
|
|
if (!shape || !shape.handles || !isSelecting) return null
|
2021-05-31 19:13:43 +00:00
|
|
|
|
2021-06-05 07:42:17 +00:00
|
|
|
const center = getShapeUtils(shape).getCenter(shape)
|
|
|
|
|
2021-05-31 19:13:43 +00:00
|
|
|
return (
|
2021-06-05 07:42:17 +00:00
|
|
|
<g transform={`rotate(${shape.rotation * (180 / Math.PI)},${center})`}>
|
2021-05-31 19:13:43 +00:00
|
|
|
{Object.values(shape.handles).map((handle) => (
|
|
|
|
<Handle
|
|
|
|
key={handle.id}
|
|
|
|
id={handle.id}
|
|
|
|
point={vec.add(handle.point, shape.point)}
|
|
|
|
/>
|
|
|
|
))}
|
|
|
|
</g>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2021-06-05 14:29:49 +00:00
|
|
|
function Handle({ id, point }: { id: string; point: number[] }) {
|
2021-05-31 19:13:43 +00:00
|
|
|
const rGroup = useRef<SVGGElement>(null)
|
|
|
|
const events = useHandleEvents(id, rGroup)
|
|
|
|
|
|
|
|
return (
|
2021-06-05 06:36:39 +00:00
|
|
|
<StyledGroup
|
2021-05-31 19:13:43 +00:00
|
|
|
key={id}
|
2021-06-05 06:36:39 +00:00
|
|
|
className="handles"
|
2021-05-31 19:13:43 +00:00
|
|
|
ref={rGroup}
|
|
|
|
{...events}
|
|
|
|
pointerEvents="all"
|
|
|
|
transform={`translate(${point})`}
|
|
|
|
>
|
2021-06-01 21:49:32 +00:00
|
|
|
<HandleCircleOuter r={12} />
|
2021-06-05 06:36:39 +00:00
|
|
|
<use href="#handle" pointerEvents="none" />
|
|
|
|
</StyledGroup>
|
2021-05-31 19:13:43 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2021-06-05 06:36:39 +00:00
|
|
|
const StyledGroup = styled('g', {
|
|
|
|
'&:hover': {
|
|
|
|
cursor: 'pointer',
|
|
|
|
},
|
|
|
|
'&:active': {
|
|
|
|
cursor: 'none',
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
2021-05-31 19:13:43 +00:00
|
|
|
const HandleCircleOuter = styled('circle', {
|
|
|
|
fill: 'transparent',
|
2021-06-05 06:36:39 +00:00
|
|
|
stroke: 'none',
|
|
|
|
opacity: 0.2,
|
2021-05-31 19:13:43 +00:00
|
|
|
pointerEvents: 'all',
|
|
|
|
cursor: 'pointer',
|
2021-06-05 06:36:39 +00:00
|
|
|
transform: 'scale(var(--scale))',
|
|
|
|
'&:hover': {
|
|
|
|
fill: '$selected',
|
|
|
|
'& > *': {
|
|
|
|
stroke: '$selected',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
'&:active': {
|
|
|
|
fill: '$selected',
|
|
|
|
},
|
2021-05-31 19:13:43 +00:00
|
|
|
})
|