2021-05-28 14:37:23 +00:00
|
|
|
import * as React from 'react'
|
2021-06-03 12:06:39 +00:00
|
|
|
import { Edge, Corner } from 'types'
|
2021-05-28 14:37:23 +00:00
|
|
|
import { useSelector } from 'state'
|
2021-05-31 19:13:43 +00:00
|
|
|
import {
|
|
|
|
deepCompareArrays,
|
2021-06-03 12:06:39 +00:00
|
|
|
getCurrentCamera,
|
2021-05-31 19:13:43 +00:00
|
|
|
getPage,
|
|
|
|
getSelectedShapes,
|
|
|
|
isMobile,
|
|
|
|
} from 'utils/utils'
|
2021-05-22 15:45:24 +00:00
|
|
|
|
2021-05-28 14:37:23 +00:00
|
|
|
import CenterHandle from './center-handle'
|
|
|
|
import CornerHandle from './corner-handle'
|
|
|
|
import EdgeHandle from './edge-handle'
|
|
|
|
import RotateHandle from './rotate-handle'
|
2021-05-31 19:13:43 +00:00
|
|
|
import Handles from './handles'
|
2021-05-22 15:45:24 +00:00
|
|
|
|
|
|
|
export default function Bounds() {
|
2021-05-28 14:37:23 +00:00
|
|
|
const isBrushing = useSelector((s) => s.isIn('brushSelecting'))
|
|
|
|
const isSelecting = useSelector((s) => s.isIn('selecting'))
|
2021-06-03 12:06:39 +00:00
|
|
|
const zoom = useSelector((s) => getCurrentCamera(s.data).zoom)
|
2021-05-22 15:45:24 +00:00
|
|
|
const bounds = useSelector((s) => s.values.selectedBounds)
|
2021-05-29 12:40:41 +00:00
|
|
|
|
2021-05-31 19:13:43 +00:00
|
|
|
const selectedIds = useSelector(
|
|
|
|
(s) => Array.from(s.values.selectedIds.values()),
|
|
|
|
deepCompareArrays
|
|
|
|
)
|
|
|
|
|
2021-05-22 15:45:24 +00:00
|
|
|
const rotation = useSelector(({ data }) =>
|
|
|
|
data.selectedIds.size === 1 ? getSelectedShapes(data)[0].rotation : 0
|
|
|
|
)
|
|
|
|
|
2021-05-29 12:40:41 +00:00
|
|
|
const isAllLocked = useSelector((s) => {
|
|
|
|
const page = getPage(s.data)
|
2021-05-31 19:13:43 +00:00
|
|
|
return selectedIds.every((id) => page.shapes[id]?.isLocked)
|
|
|
|
})
|
|
|
|
|
2021-05-31 20:44:21 +00:00
|
|
|
const isSingleHandles = useSelector((s) => {
|
2021-05-31 19:13:43 +00:00
|
|
|
const page = getPage(s.data)
|
2021-05-31 20:44:21 +00:00
|
|
|
return (
|
|
|
|
selectedIds.length === 1 &&
|
|
|
|
page.shapes[selectedIds[0]]?.handles !== undefined
|
|
|
|
)
|
2021-05-29 12:40:41 +00:00
|
|
|
})
|
|
|
|
|
2021-05-22 15:45:24 +00:00
|
|
|
if (!bounds) return null
|
2021-05-31 19:13:43 +00:00
|
|
|
|
2021-05-22 15:45:24 +00:00
|
|
|
if (!isSelecting) return null
|
|
|
|
|
2021-05-31 20:44:21 +00:00
|
|
|
if (isSingleHandles) return null
|
2021-05-31 19:13:43 +00:00
|
|
|
|
2021-05-30 13:39:53 +00:00
|
|
|
const size = (isMobile().any ? 10 : 8) / zoom // Touch target size
|
2021-05-22 15:45:24 +00:00
|
|
|
|
|
|
|
return (
|
|
|
|
<g
|
2021-05-28 14:37:23 +00:00
|
|
|
pointerEvents={isBrushing ? 'none' : 'all'}
|
2021-05-22 15:45:24 +00:00
|
|
|
transform={`
|
|
|
|
rotate(${rotation * (180 / Math.PI)},
|
|
|
|
${(bounds.minX + bounds.maxX) / 2},
|
|
|
|
${(bounds.minY + bounds.maxY) / 2})
|
|
|
|
translate(${bounds.minX},${bounds.minY})`}
|
|
|
|
>
|
2021-05-29 12:40:41 +00:00
|
|
|
<CenterHandle bounds={bounds} isLocked={isAllLocked} />
|
|
|
|
{!isAllLocked && (
|
|
|
|
<>
|
|
|
|
<EdgeHandle size={size} bounds={bounds} edge={Edge.Top} />
|
|
|
|
<EdgeHandle size={size} bounds={bounds} edge={Edge.Right} />
|
|
|
|
<EdgeHandle size={size} bounds={bounds} edge={Edge.Bottom} />
|
|
|
|
<EdgeHandle size={size} bounds={bounds} edge={Edge.Left} />
|
|
|
|
<CornerHandle size={size} bounds={bounds} corner={Corner.TopLeft} />
|
|
|
|
<CornerHandle size={size} bounds={bounds} corner={Corner.TopRight} />
|
|
|
|
<CornerHandle
|
|
|
|
size={size}
|
|
|
|
bounds={bounds}
|
|
|
|
corner={Corner.BottomRight}
|
|
|
|
/>
|
|
|
|
<CornerHandle
|
|
|
|
size={size}
|
|
|
|
bounds={bounds}
|
|
|
|
corner={Corner.BottomLeft}
|
|
|
|
/>
|
|
|
|
<RotateHandle size={size} bounds={bounds} />
|
|
|
|
</>
|
|
|
|
)}
|
2021-05-22 15:45:24 +00:00
|
|
|
</g>
|
|
|
|
)
|
|
|
|
}
|