kopia lustrzana https://github.com/Tldraw/Tldraw
80 wiersze
2.3 KiB
TypeScript
80 wiersze
2.3 KiB
TypeScript
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
import * as React from 'react'
|
|
import Utils from '../utils'
|
|
import type { TLBounds, TLComponentProps, TLForwardedRef, TLShape, TLUser } from '../types'
|
|
import { intersectPolylineBounds } from '@tldraw/intersect'
|
|
|
|
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>
|
|
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>())
|
|
}
|
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
return this.refMap.get(shape.id)!
|
|
}
|
|
|
|
hitTestBounds = (shape: T, bounds: TLBounds) => {
|
|
const shapeBounds = this.getBounds(shape)
|
|
|
|
if (!shape.rotation) {
|
|
return (
|
|
Utils.boundsContain(bounds, shapeBounds) ||
|
|
Utils.boundsContain(shapeBounds, bounds) ||
|
|
Utils.boundsCollide(shapeBounds, bounds)
|
|
)
|
|
}
|
|
|
|
const corners = Utils.getRotatedCorners(shapeBounds, shape.rotation)
|
|
|
|
return (
|
|
corners.every((point) => Utils.pointInBounds(point, bounds)) ||
|
|
intersectPolylineBounds(corners, bounds).length > 0
|
|
)
|
|
}
|
|
|
|
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>(
|
|
component: (props: TLComponentProps<T, E, M>, ref: TLForwardedRef<E>) => JSX.Element
|
|
) => {
|
|
return React.forwardRef(component)
|
|
}
|
|
|
|
static Indicator = <T extends TLShape, M = any>(
|
|
component: (props: {
|
|
shape: T
|
|
meta: M
|
|
isHovered: boolean
|
|
isSelected: boolean
|
|
}) => JSX.Element
|
|
) => component
|
|
}
|