Tldraw/packages/tldraw/src/shape-utils/group/group.tsx

126 wiersze
3.4 KiB
TypeScript

import * as React from 'react'
import { Utils, SVGContainer } from '@tldraw/core'
import { defaultStyle } from '../shape-styles'
import { TLDrawShapeType, GroupShape, ColorStyle, TLDrawMeta } from '~types'
import { getBoundsRectangle } from '../shared'
import { BINDING_DISTANCE } from '~constants'
import { TLDrawShapeUtil } from '../TLDrawShapeUtil'
import css from '~styles'
type T = GroupShape
type E = SVGSVGElement
export class GroupUtil extends TLDrawShapeUtil<T, E> {
type = TLDrawShapeType.Group as const
canBind = true
getShape = (props: Partial<T>): T => {
return Utils.deepMerge<T>(
{
id: 'id',
type: TLDrawShapeType.Group,
name: 'Group',
parentId: 'page',
childIndex: 1,
point: [0, 0],
size: [100, 100],
rotation: 0,
children: [],
style: defaultStyle,
},
props
)
}
Component = TLDrawShapeUtil.Component<T, E, TLDrawMeta>(
({ shape, isBinding, isHovered, isSelected, events }, ref) => {
const { id, size } = shape
const sw = 2
const w = Math.max(0, size[0] - sw / 2)
const h = Math.max(0, size[1] - sw / 2)
const strokes: [number[], number[], number][] = [
[[sw / 2, sw / 2], [w, sw / 2], w - sw / 2],
[[w, sw / 2], [w, h], h - sw / 2],
[[w, h], [sw / 2, h], w - sw / 2],
[[sw / 2, h], [sw / 2, sw / 2], h - sw / 2],
]
const paths = strokes.map(([start, end], i) => {
return <line key={id + '_' + i} x1={start[0]} y1={start[1]} x2={end[0]} y2={end[1]} />
})
return (
<SVGContainer ref={ref} {...events}>
{isBinding && (
<rect
className="tl-binding-indicator"
x={-BINDING_DISTANCE}
y={-BINDING_DISTANCE}
width={size[0] + BINDING_DISTANCE * 2}
height={size[1] + BINDING_DISTANCE * 2}
/>
)}
<rect
x={0}
y={0}
width={size[0]}
height={size[1]}
fill="transparent"
pointerEvents="all"
/>
<g
className={scaledLines()}
stroke={ColorStyle.Black}
opacity={isHovered || isSelected ? 1 : 0}
strokeLinecap="round"
pointerEvents="stroke"
>
{paths}
</g>
</SVGContainer>
)
}
)
Indicator = TLDrawShapeUtil.Indicator<T>(({ shape }) => {
const { id, size } = shape
const sw = 2
const w = Math.max(0, size[0] - sw / 2)
const h = Math.max(0, size[1] - sw / 2)
const strokes: [number[], number[], number][] = [
[[sw / 2, sw / 2], [w, sw / 2], w - sw / 2],
[[w, sw / 2], [w, h], h - sw / 2],
[[w, h], [sw / 2, h], w - sw / 2],
[[sw / 2, h], [sw / 2, sw / 2], h - sw / 2],
]
const paths = strokes.map(([start, end], i) => {
return <line key={id + '_' + i} x1={start[0]} y1={start[1]} x2={end[0]} y2={end[1]} />
})
return (
<g className={scaledLines()} strokeLinecap="round" pointerEvents="stroke">
{paths}
</g>
)
})
getBounds = (shape: T) => {
return getBoundsRectangle(shape, this.boundsCache)
}
shouldRender = (prev: T, next: T) => {
return next.size !== prev.size || next.style !== prev.style
}
}
const scaledLines = css({
strokeWidth: 'calc(1.5px * var(--tl-scale))',
strokeDasharray: `calc(1px * var(--tl-scale)), calc(3px * var(--tl-scale))`,
})