2021-12-28 11:23:17 +00:00
|
|
|
import { intersectPolygonBounds } from '@tldraw/intersect'
|
2022-08-02 13:56:12 +00:00
|
|
|
import * as React from 'react'
|
|
|
|
import type { TLBounds, TLComponentProps, TLForwardedRef, TLShape, TLUser } from '~types'
|
|
|
|
import Utils from '~utils'
|
2021-11-18 13:09:18 +00:00
|
|
|
|
|
|
|
export abstract class TLShapeUtil<T extends TLShape, E extends Element = any, M = any> {
|
|
|
|
refMap = new Map<string, React.RefObject<E>>()
|
|
|
|
|
|
|
|
boundsCache = new WeakMap<TLShape, TLBounds>()
|
|
|
|
|
|
|
|
showCloneHandles = false
|
|
|
|
|
|
|
|
hideBounds = false
|
|
|
|
|
|
|
|
isStateful = false
|
|
|
|
|
|
|
|
abstract Component: React.ForwardRefExoticComponent<TLComponentProps<T, E, M>>
|
|
|
|
|
|
|
|
abstract Indicator: (props: {
|
|
|
|
shape: T
|
|
|
|
meta: M
|
|
|
|
user?: TLUser<T>
|
2021-12-28 11:23:17 +00:00
|
|
|
bounds: TLBounds
|
2021-11-18 13:09:18 +00:00
|
|
|
isHovered: boolean
|
|
|
|
isSelected: boolean
|
|
|
|
}) => React.ReactElement | null
|
|
|
|
|
|
|
|
abstract getBounds: (shape: T) => TLBounds
|
|
|
|
|
|
|
|
shouldRender = (prev: T, next: T): boolean => true
|
|
|
|
|
|
|
|
getRef = (shape: T): React.RefObject<E> => {
|
|
|
|
if (!this.refMap.has(shape.id)) {
|
|
|
|
this.refMap.set(shape.id, React.createRef<E>())
|
|
|
|
}
|
|
|
|
return this.refMap.get(shape.id)!
|
|
|
|
}
|
|
|
|
|
|
|
|
hitTestBounds = (shape: T, bounds: TLBounds) => {
|
|
|
|
const shapeBounds = this.getBounds(shape)
|
|
|
|
const corners = Utils.getRotatedCorners(shapeBounds, shape.rotation)
|
|
|
|
return (
|
|
|
|
corners.every((point) => Utils.pointInBounds(point, bounds)) ||
|
2021-12-17 16:29:08 +00:00
|
|
|
intersectPolygonBounds(corners, bounds).length > 0
|
2021-11-18 13:09:18 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
getRotatedBounds: (shape: T) => TLBounds = (shape) => {
|
|
|
|
return Utils.getBoundsFromPoints(Utils.getRotatedCorners(this.getBounds(shape), shape.rotation))
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------- Static --------------------- */
|
|
|
|
|
|
|
|
static Component = <T extends TLShape, E extends Element = any, M = any>(
|
2022-05-14 13:15:55 +00:00
|
|
|
component: (props: TLComponentProps<T, E, M>, ref: TLForwardedRef<E>) => React.ReactElement
|
2021-11-18 13:09:18 +00:00
|
|
|
) => {
|
|
|
|
return React.forwardRef(component)
|
|
|
|
}
|
|
|
|
|
|
|
|
static Indicator = <T extends TLShape, M = any>(
|
|
|
|
component: (props: {
|
|
|
|
shape: T
|
|
|
|
meta: M
|
|
|
|
isHovered: boolean
|
|
|
|
isSelected: boolean
|
2021-12-28 11:23:17 +00:00
|
|
|
bounds: TLBounds
|
2022-05-14 13:15:55 +00:00
|
|
|
}) => React.ReactElement
|
2021-11-18 13:09:18 +00:00
|
|
|
) => component
|
|
|
|
}
|