tldraw/components/canvas/bounds/bounding-box.tsx

91 lines
2.6 KiB
TypeScript
Raw Normal View History

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-04 16:08:43 +00:00
getBoundsCenter,
2021-06-03 12:06:39 +00:00
getCurrentCamera,
2021-05-31 19:13:43 +00:00
getPage,
getSelectedIds,
2021-05-31 19:13:43 +00:00
getSelectedShapes,
isMobile,
} from 'utils/utils'
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-06-21 21:35:28 +00:00
export default function Bounds(): JSX.Element {
2021-05-28 14:37:23 +00:00
const isBrushing = useSelector((s) => s.isIn('brushSelecting'))
2021-06-17 21:50:04 +00:00
2021-05-28 14:37:23 +00:00
const isSelecting = useSelector((s) => s.isIn('selecting'))
2021-06-17 21:50:04 +00:00
2021-06-03 12:06:39 +00:00
const zoom = useSelector((s) => getCurrentCamera(s.data).zoom)
2021-06-17 21:50:04 +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
)
const rotation = useSelector(({ data }) =>
getSelectedIds(data).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
})
if (!bounds) return null
2021-05-31 19:13:43 +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-06-10 09:49:16 +00:00
const size = (isMobile() ? 10 : 8) / zoom // Touch target size
2021-06-05 07:42:17 +00:00
const center = getBoundsCenter(bounds)
return (
<g
2021-05-28 14:37:23 +00:00
pointerEvents={isBrushing ? 'none' : 'all'}
transform={`
2021-06-05 07:42:17 +00:00
rotate(${rotation * (180 / Math.PI)},${center})
2021-06-04 16:08:43 +00:00
translate(${bounds.minX},${bounds.minY})
rotate(${(bounds.rotation || 0) * (180 / Math.PI)}, 0, 0)`}
>
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} />
</>
)}
</g>
)
}