Tldraw/packages/core/src/components/renderer/renderer.tsx

195 wiersze
4.9 KiB
TypeScript

/* eslint-disable @typescript-eslint/no-explicit-any */
import * as React from 'react'
import type {
TLShape,
TLPage,
TLPageState,
TLCallbacks,
TLTheme,
TLBounds,
TLBinding,
TLSnapLine,
TLUsers,
} from '../../types'
import { Canvas } from '../canvas'
import { Inputs } from '../../inputs'
import { useTLTheme, TLContext, TLContextType } from '../../hooks'
import type { TLShapeUtilsMap } from '../../TLShapeUtil'
export interface RendererProps<T extends TLShape, M = any> extends Partial<TLCallbacks<T>> {
/**
* An object containing instances of your shape classes.
*/
shapeUtils: TLShapeUtilsMap<T>
/**
* The current page, containing shapes and bindings.
*/
page: TLPage<T, TLBinding>
/**
* The current page state.
*/
pageState: TLPageState
/**
* (optional) A unique id to be applied to the renderer element, used to scope styles.
*/
id?: string
/**
* (optional) A ref for the renderer's container element, used for scoping event handlers.
*/
containerRef?: React.RefObject<HTMLElement>
/**
* (optional) An object of custom options that should be passed to rendered shapes.
*/
meta?: M
/**
* (optional) The current users to render.
*/
users?: TLUsers<T>
/**
* (optional) The current snap lines to render.
*/
snapLines?: TLSnapLine[]
/**
* (optional) The current user's id, used to identify the user.
*/
userId?: string
/**
* (optional) An object of custom theme colors.
*/
theme?: Partial<TLTheme>
/**
* (optional) When true, the renderer will not show the bounds for selected objects.
*/
hideBounds?: boolean
/**
* (optional) When true, the renderer will not show the handles of shapes with handles.
*/
hideHandles?: boolean
/**
* (optional) When true, the renderer will not show resize handles for selected objects.
*/
hideResizeHandles?: boolean
/**
* (optional) When true, the renderer will not show rotate handles for selected objects.
*/
hideRotateHandles?: boolean
/**
* (optional) When true, the renderer will not show buttons for cloning shapes.
*/
hideCloneHandles?: boolean
/**
* (optional) When true, the renderer will not show binding controls.
*/
hideBindingHandles?: boolean
/**
* (optional) When true, the renderer will not show indicators for selected or
* hovered objects,
*/
hideIndicators?: boolean
/**
* (optional) When true, the renderer will not show the grid.
*/
hideGrid?: boolean
/**
* (optional) The size of the grid step.
*/
grid?: number
/**
* (optional) A callback that receives the renderer's inputs manager.
*/
onMount?: (inputs: Inputs) => void
/**
* (optional) A callback that is fired when the editor's client bounding box changes.
*/
onBoundsChange?: (bounds: TLBounds) => void
}
/**
* The Renderer component is the main component of the library. It
* accepts the current `page`, the `shapeUtils` needed to interpret
* and render the shapes and bindings on the `page`, and the current
* `pageState`.
* @param props
* @returns
*/
export function Renderer<T extends TLShape, M extends Record<string, unknown>>({
id = 'tl',
shapeUtils,
page,
pageState,
users,
userId,
theme,
meta,
snapLines,
grid,
containerRef,
hideHandles = false,
hideIndicators = false,
hideCloneHandles = false,
hideBindingHandles = false,
hideResizeHandles = false,
hideRotateHandles = false,
hideBounds = false,
hideGrid = true,
...rest
}: RendererProps<T, M>): JSX.Element {
useTLTheme(theme, '#' + id)
const rSelectionBounds = React.useRef<TLBounds>(null)
const rPageState = React.useRef<TLPageState>(pageState)
React.useEffect(() => {
rPageState.current = pageState
}, [pageState])
const [context, setContext] = React.useState<TLContextType<T>>(() => ({
callbacks: rest,
shapeUtils,
rSelectionBounds,
rPageState,
bounds: {
minX: 0,
minY: 0,
maxX: Infinity,
maxY: Infinity,
width: Infinity,
height: Infinity,
},
inputs: new Inputs(),
}))
const onBoundsChange = React.useCallback((bounds: TLBounds) => {
setContext((context) => ({
...context,
bounds,
}))
}, [])
return (
<TLContext.Provider value={context as unknown as TLContextType<TLShape>}>
<Canvas
id={id}
page={page}
pageState={pageState}
snapLines={snapLines}
grid={grid}
users={users}
userId={userId}
externalContainerRef={containerRef}
hideBounds={hideBounds}
hideIndicators={hideIndicators}
hideHandles={hideHandles}
hideCloneHandles={hideCloneHandles}
hideBindingHandles={hideBindingHandles}
hideRotateHandle={hideRotateHandles}
hideResizeHandles={hideResizeHandles}
hideGrid={hideGrid}
onBoundsChange={onBoundsChange}
meta={meta}
/>
</TLContext.Provider>
)
}