Add support for custom cursor components (#994)
* Add support for custom cursor components * Add tests for the custom cursor props * Make the main tldraw app take the components prop * feat: add the ability to hide cursors * Update cursor props * Update imports Co-authored-by: Judicael <46365844+judicaelandria@users.noreply.github.com> Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
This commit is contained in:
parent
b7c968e2aa
commit
d721ae6a2f
16 changed files with 157 additions and 40 deletions
|
@ -1,4 +1,4 @@
|
||||||
import { Tldraw, useFileSystem } from '@tldraw/tldraw'
|
import { Tldraw, TldrawProps, useFileSystem } from '@tldraw/tldraw'
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import { useMultiplayerAssets } from '~hooks/useMultiplayerAssets'
|
import { useMultiplayerAssets } from '~hooks/useMultiplayerAssets'
|
||||||
import { useMultiplayerState } from '~hooks/useMultiplayerState'
|
import { useMultiplayerState } from '~hooks/useMultiplayerState'
|
||||||
|
|
|
@ -19,7 +19,7 @@ export abstract class TLShapeUtil<T extends TLShape, E extends Element = any, M
|
||||||
abstract Indicator: (props: {
|
abstract Indicator: (props: {
|
||||||
shape: T
|
shape: T
|
||||||
meta: M
|
meta: M
|
||||||
user?: TLUser<T>
|
user?: TLUser
|
||||||
bounds: TLBounds
|
bounds: TLBounds
|
||||||
isHovered: boolean
|
isHovered: boolean
|
||||||
isSelected: boolean
|
isSelected: boolean
|
||||||
|
|
|
@ -2,6 +2,10 @@ import * as React from 'react'
|
||||||
import { mockDocument, renderWithContext } from '~test'
|
import { mockDocument, renderWithContext } from '~test'
|
||||||
import { Canvas } from './Canvas'
|
import { Canvas } from './Canvas'
|
||||||
|
|
||||||
|
function TestCustomCursor() {
|
||||||
|
return <div>Custom cursor</div>
|
||||||
|
}
|
||||||
|
|
||||||
describe('page', () => {
|
describe('page', () => {
|
||||||
test('mounts component without crashing', () => {
|
test('mounts component without crashing', () => {
|
||||||
expect(() =>
|
expect(() =>
|
||||||
|
@ -26,4 +30,29 @@ describe('page', () => {
|
||||||
)
|
)
|
||||||
).not.toThrowError()
|
).not.toThrowError()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('mounts component with custom cursors without crashing', () => {
|
||||||
|
expect(() =>
|
||||||
|
renderWithContext(
|
||||||
|
<Canvas
|
||||||
|
page={mockDocument.page}
|
||||||
|
pageState={mockDocument.pageState}
|
||||||
|
hideBounds={false}
|
||||||
|
hideGrid={false}
|
||||||
|
hideIndicators={false}
|
||||||
|
hideHandles={false}
|
||||||
|
hideBindingHandles={false}
|
||||||
|
hideResizeHandles={false}
|
||||||
|
hideCloneHandles={false}
|
||||||
|
hideRotateHandle={false}
|
||||||
|
showDashedBrush={false}
|
||||||
|
onBoundsChange={() => {
|
||||||
|
// noop
|
||||||
|
}}
|
||||||
|
assets={{}}
|
||||||
|
components={{ Cursor: TestCustomCursor }}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
).not.toThrowError()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import { Brush } from '~components/Brush'
|
import { Brush } from '~components/Brush'
|
||||||
|
import { Cursor, CursorComponent } from '~components/Cursor'
|
||||||
import { EraseLine } from '~components/EraseLine'
|
import { EraseLine } from '~components/EraseLine'
|
||||||
import { Grid } from '~components/Grid'
|
import { Grid } from '~components/Grid'
|
||||||
import { Overlay } from '~components/Overlay'
|
import { Overlay } from '~components/Overlay'
|
||||||
|
@ -36,7 +37,7 @@ export interface CanvasProps<T extends TLShape, M extends Record<string, unknown
|
||||||
snapLines?: TLSnapLine[]
|
snapLines?: TLSnapLine[]
|
||||||
eraseLine?: number[][]
|
eraseLine?: number[][]
|
||||||
grid?: number
|
grid?: number
|
||||||
users?: TLUsers<T>
|
users?: TLUsers
|
||||||
userId?: string
|
userId?: string
|
||||||
hideBounds: boolean
|
hideBounds: boolean
|
||||||
hideHandles: boolean
|
hideHandles: boolean
|
||||||
|
@ -49,9 +50,13 @@ export interface CanvasProps<T extends TLShape, M extends Record<string, unknown
|
||||||
showDashedBrush: boolean
|
showDashedBrush: boolean
|
||||||
externalContainerRef?: React.RefObject<HTMLElement>
|
externalContainerRef?: React.RefObject<HTMLElement>
|
||||||
performanceMode?: TLPerformanceMode
|
performanceMode?: TLPerformanceMode
|
||||||
|
components?: {
|
||||||
|
Cursor?: CursorComponent
|
||||||
|
}
|
||||||
meta?: M
|
meta?: M
|
||||||
id?: string
|
id?: string
|
||||||
onBoundsChange: (bounds: TLBounds) => void
|
onBoundsChange: (bounds: TLBounds) => void
|
||||||
|
hideCursors?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
function _Canvas<T extends TLShape, M extends Record<string, unknown>>({
|
function _Canvas<T extends TLShape, M extends Record<string, unknown>>({
|
||||||
|
@ -64,9 +69,9 @@ function _Canvas<T extends TLShape, M extends Record<string, unknown>>({
|
||||||
grid,
|
grid,
|
||||||
users,
|
users,
|
||||||
userId,
|
userId,
|
||||||
|
components = {},
|
||||||
meta,
|
meta,
|
||||||
performanceMode,
|
performanceMode,
|
||||||
externalContainerRef,
|
|
||||||
showDashedBrush,
|
showDashedBrush,
|
||||||
hideHandles,
|
hideHandles,
|
||||||
hideBounds,
|
hideBounds,
|
||||||
|
@ -77,6 +82,7 @@ function _Canvas<T extends TLShape, M extends Record<string, unknown>>({
|
||||||
hideRotateHandle,
|
hideRotateHandle,
|
||||||
hideGrid,
|
hideGrid,
|
||||||
onBoundsChange,
|
onBoundsChange,
|
||||||
|
hideCursors,
|
||||||
}: CanvasProps<T, M>) {
|
}: CanvasProps<T, M>) {
|
||||||
const rCanvas = React.useRef<HTMLDivElement>(null)
|
const rCanvas = React.useRef<HTMLDivElement>(null)
|
||||||
|
|
||||||
|
@ -128,7 +134,9 @@ function _Canvas<T extends TLShape, M extends Record<string, unknown>>({
|
||||||
{pageState.brush && (
|
{pageState.brush && (
|
||||||
<Brush brush={pageState.brush} dashed={showDashedBrush} zoom={pageState.camera.zoom} />
|
<Brush brush={pageState.brush} dashed={showDashedBrush} zoom={pageState.camera.zoom} />
|
||||||
)}
|
)}
|
||||||
{users && <Users userId={userId} users={users} />}
|
{users && !hideCursors && (
|
||||||
|
<Users userId={userId} users={users} Cursor={components?.Cursor ?? Cursor} />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<Overlay camera={pageState.camera}>
|
<Overlay camera={pageState.camera}>
|
||||||
{eraseLine && <EraseLine points={eraseLine} zoom={pageState.camera.zoom} />}
|
{eraseLine && <EraseLine points={eraseLine} zoom={pageState.camera.zoom} />}
|
||||||
|
|
27
packages/core/src/components/Cursor/Cursor.tsx
Normal file
27
packages/core/src/components/Cursor/Cursor.tsx
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import * as React from 'react'
|
||||||
|
|
||||||
|
interface CursorProps {
|
||||||
|
id: string
|
||||||
|
color: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CursorComponent = (props: CursorProps) => any
|
||||||
|
|
||||||
|
export const Cursor: CursorComponent = React.memo(({ color }) => {
|
||||||
|
return (
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 35 35" fill="none" fillRule="evenodd">
|
||||||
|
<g fill="rgba(0,0,0,.2)" transform="translate(1,1)">
|
||||||
|
<path d="m12 24.4219v-16.015l11.591 11.619h-6.781l-.411.124z" />
|
||||||
|
<path d="m21.0845 25.0962-3.605 1.535-4.682-11.089 3.686-1.553z" />
|
||||||
|
</g>
|
||||||
|
<g fill="white">
|
||||||
|
<path d="m12 24.4219v-16.015l11.591 11.619h-6.781l-.411.124z" />
|
||||||
|
<path d="m21.0845 25.0962-3.605 1.535-4.682-11.089 3.686-1.553z" />
|
||||||
|
</g>
|
||||||
|
<g fill={color}>
|
||||||
|
<path d="m19.751 24.4155-1.844.774-3.1-7.374 1.841-.775z" />
|
||||||
|
<path d="m13 10.814v11.188l2.969-2.866.428-.139h4.768z" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
})
|
1
packages/core/src/components/Cursor/index.ts
Normal file
1
packages/core/src/components/Cursor/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export * from './Cursor'
|
|
@ -7,6 +7,10 @@ import type { TLBounds, TLPage, TLPageState } from '~types'
|
||||||
import Utils from '~utils'
|
import Utils from '~utils'
|
||||||
import { Renderer } from './Renderer'
|
import { Renderer } from './Renderer'
|
||||||
|
|
||||||
|
function TestCustomCursor() {
|
||||||
|
return <div>Custom cursor</div>
|
||||||
|
}
|
||||||
|
|
||||||
describe('renderer', () => {
|
describe('renderer', () => {
|
||||||
test('mounts component without crashing', () => {
|
test('mounts component without crashing', () => {
|
||||||
expect(() =>
|
expect(() =>
|
||||||
|
@ -19,6 +23,19 @@ describe('renderer', () => {
|
||||||
)
|
)
|
||||||
).not.toThrowError()
|
).not.toThrowError()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('mounts component with custom cursors without crashing', () => {
|
||||||
|
expect(() =>
|
||||||
|
render(
|
||||||
|
<Renderer
|
||||||
|
shapeUtils={mockUtils as any}
|
||||||
|
page={mockDocument.page}
|
||||||
|
pageState={mockDocument.pageState}
|
||||||
|
components={{ Cursor: TestCustomCursor }}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
).not.toThrowError()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// describe('When passing observables', () => {
|
// describe('When passing observables', () => {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import { Canvas } from '~/components/Canvas'
|
import { Canvas } from '~/components/Canvas'
|
||||||
import type { TLShapeUtilsMap } from '~TLShapeUtil'
|
import { CursorComponent } from '~components/Cursor'
|
||||||
import { TLContext, TLContextType, useTLTheme } from '~hooks'
|
import { TLContext, TLContextType, useTLTheme } from '~hooks'
|
||||||
import { Inputs } from '~inputs'
|
import { Inputs } from '~inputs'
|
||||||
import type {
|
import type {
|
||||||
|
@ -17,7 +17,7 @@ import type {
|
||||||
TLUsers,
|
TLUsers,
|
||||||
} from '~types'
|
} from '~types'
|
||||||
|
|
||||||
const EMPTY_OBJECT = {} as TLAssets
|
const EMPTY_OBJECT = Object.freeze({}) as TLAssets
|
||||||
|
|
||||||
export type RendererProps<T extends TLShape, M = any> = Partial<TLCallbacks<T>> & {
|
export type RendererProps<T extends TLShape, M = any> = Partial<TLCallbacks<T>> & {
|
||||||
/**
|
/**
|
||||||
|
@ -46,6 +46,20 @@ export type RendererProps<T extends TLShape, M = any> = Partial<TLCallbacks<T>>
|
||||||
* (optional) A ref for the renderer's container element, used for scoping event handlers.
|
* (optional) A ref for the renderer's container element, used for scoping event handlers.
|
||||||
*/
|
*/
|
||||||
containerRef?: React.RefObject<HTMLElement>
|
containerRef?: React.RefObject<HTMLElement>
|
||||||
|
/**
|
||||||
|
* (optional) Custom components to override parts of the default UI.
|
||||||
|
*/
|
||||||
|
components?: {
|
||||||
|
/**
|
||||||
|
* The component to render for multiplayer cursors.
|
||||||
|
*/
|
||||||
|
Cursor?: CursorComponent
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (optional) To hide cursors
|
||||||
|
*/
|
||||||
|
hideCursors?: boolean
|
||||||
/**
|
/**
|
||||||
* (optional) An object of custom options that should be passed to rendered shapes.
|
* (optional) An object of custom options that should be passed to rendered shapes.
|
||||||
*/
|
*/
|
||||||
|
@ -53,7 +67,7 @@ export type RendererProps<T extends TLShape, M = any> = Partial<TLCallbacks<T>>
|
||||||
/**
|
/**
|
||||||
* (optional) The current users to render.
|
* (optional) The current users to render.
|
||||||
*/
|
*/
|
||||||
users?: TLUsers<T>
|
users?: TLUsers
|
||||||
/**
|
/**
|
||||||
* (optional) The current snap lines to render.
|
* (optional) The current snap lines to render.
|
||||||
*/
|
*/
|
||||||
|
@ -148,6 +162,7 @@ function _Renderer<T extends TLShape, M extends Record<string, unknown>>({
|
||||||
grid,
|
grid,
|
||||||
containerRef,
|
containerRef,
|
||||||
performanceMode,
|
performanceMode,
|
||||||
|
components,
|
||||||
hideHandles = false,
|
hideHandles = false,
|
||||||
hideIndicators = false,
|
hideIndicators = false,
|
||||||
hideCloneHandles = false,
|
hideCloneHandles = false,
|
||||||
|
@ -157,6 +172,7 @@ function _Renderer<T extends TLShape, M extends Record<string, unknown>>({
|
||||||
hideBounds = false,
|
hideBounds = false,
|
||||||
hideGrid = true,
|
hideGrid = true,
|
||||||
showDashedBrush = false,
|
showDashedBrush = false,
|
||||||
|
hideCursors,
|
||||||
...rest
|
...rest
|
||||||
}: RendererProps<T, M>) {
|
}: RendererProps<T, M>) {
|
||||||
useTLTheme(theme, '#' + id)
|
useTLTheme(theme, '#' + id)
|
||||||
|
@ -216,7 +232,9 @@ function _Renderer<T extends TLShape, M extends Record<string, unknown>>({
|
||||||
showDashedBrush={showDashedBrush}
|
showDashedBrush={showDashedBrush}
|
||||||
onBoundsChange={onBoundsChange}
|
onBoundsChange={onBoundsChange}
|
||||||
performanceMode={performanceMode}
|
performanceMode={performanceMode}
|
||||||
|
components={components}
|
||||||
meta={meta}
|
meta={meta}
|
||||||
|
hideCursors={hideCursors}
|
||||||
/>
|
/>
|
||||||
</TLContext.Provider>
|
</TLContext.Provider>
|
||||||
)
|
)
|
||||||
|
|
|
@ -8,7 +8,7 @@ export interface IndicatorProps<T extends TLShape, M = unknown> {
|
||||||
isSelected?: boolean
|
isSelected?: boolean
|
||||||
isHovered?: boolean
|
isHovered?: boolean
|
||||||
isEditing?: boolean
|
isEditing?: boolean
|
||||||
user?: TLUser<T>
|
user?: TLUser
|
||||||
}
|
}
|
||||||
|
|
||||||
function _ShapeIndicator<T extends TLShape, M>({
|
function _ShapeIndicator<T extends TLShape, M>({
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import type { TLShape, TLUser } from '~types'
|
import { CursorComponent } from '~components/Cursor'
|
||||||
|
import type { TLUser } from '~types'
|
||||||
|
|
||||||
interface UserProps {
|
interface UserProps {
|
||||||
user: TLUser<TLShape>
|
user: TLUser
|
||||||
|
Cursor: CursorComponent
|
||||||
}
|
}
|
||||||
|
|
||||||
export function User({ user }: UserProps) {
|
export function User({ user, Cursor }: UserProps) {
|
||||||
const rCursor = React.useRef<SVGSVGElement>(null)
|
const rCursor = React.useRef<HTMLDivElement>(null)
|
||||||
|
|
||||||
React.useLayoutEffect(() => {
|
React.useLayoutEffect(() => {
|
||||||
if (rCursor.current) {
|
if (rCursor.current) {
|
||||||
|
@ -15,26 +17,11 @@ export function User({ user }: UserProps) {
|
||||||
}, [user.point])
|
}, [user.point])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg
|
<div
|
||||||
ref={rCursor}
|
ref={rCursor}
|
||||||
className={`tl-absolute tl-user tl-counter-scaled ${user.session ? '' : 'tl-animated'}`}
|
className={`tl-absolute tl-user tl-counter-scaled ${user.session ? '' : 'tl-animated'}`}
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
viewBox="0 0 35 35"
|
|
||||||
fill="none"
|
|
||||||
fillRule="evenodd"
|
|
||||||
>
|
>
|
||||||
<g fill="rgba(0,0,0,.2)" transform="translate(1,1)">
|
<Cursor id={user.id} color={user.color} />
|
||||||
<path d="m12 24.4219v-16.015l11.591 11.619h-6.781l-.411.124z" />
|
</div>
|
||||||
<path d="m21.0845 25.0962-3.605 1.535-4.682-11.089 3.686-1.553z" />
|
|
||||||
</g>
|
|
||||||
<g fill="white">
|
|
||||||
<path d="m12 24.4219v-16.015l11.591 11.619h-6.781l-.411.124z" />
|
|
||||||
<path d="m21.0845 25.0962-3.605 1.535-4.682-11.089 3.686-1.553z" />
|
|
||||||
</g>
|
|
||||||
<g fill={user.color}>
|
|
||||||
<path d="m19.751 24.4155-1.844.774-3.1-7.374 1.841-.775z" />
|
|
||||||
<path d="m13 10.814v11.188l2.969-2.866.428-.139h4.768z" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,21 @@
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
|
import { CursorComponent } from '~components/Cursor'
|
||||||
import { User } from '~components/User/User'
|
import { User } from '~components/User/User'
|
||||||
import type { TLShape, TLUsers } from '~types'
|
import type { TLUsers } from '~types'
|
||||||
|
|
||||||
export interface UserProps {
|
export interface UserProps {
|
||||||
userId?: string
|
userId?: string
|
||||||
users: TLUsers<TLShape>
|
users: TLUsers
|
||||||
|
Cursor: CursorComponent
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Users({ userId, users }: UserProps) {
|
export function Users({ userId, users, Cursor }: UserProps) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{Object.values(users)
|
{Object.values(users)
|
||||||
.filter((user) => user && user.id !== userId)
|
.filter((user) => user && user.id !== userId)
|
||||||
.map((user) => (
|
.map((user) => (
|
||||||
<User key={user.id} user={user} />
|
<User key={user.id} user={user} Cursor={Cursor} />
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
|
@ -7,7 +7,7 @@ import Utils from '~utils'
|
||||||
interface UserIndicatorProps<T extends TLShape> {
|
interface UserIndicatorProps<T extends TLShape> {
|
||||||
page: TLPage<any, any>
|
page: TLPage<any, any>
|
||||||
userId: string
|
userId: string
|
||||||
users: TLUsers<T>
|
users: TLUsers
|
||||||
meta: any
|
meta: any
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
export * from './Renderer'
|
export * from './Renderer'
|
||||||
export * from './SVGContainer'
|
export * from './SVGContainer'
|
||||||
export * from './HTMLContainer'
|
export * from './HTMLContainer'
|
||||||
|
export * from './Cursor'
|
||||||
|
|
|
@ -44,7 +44,7 @@ export interface TLPageState {
|
||||||
bindingId?: string | null
|
bindingId?: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TLUser<T extends TLShape> {
|
export interface TLUser {
|
||||||
id: string
|
id: string
|
||||||
color: string
|
color: string
|
||||||
point: number[]
|
point: number[]
|
||||||
|
@ -52,7 +52,7 @@ export interface TLUser<T extends TLShape> {
|
||||||
session?: boolean
|
session?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TLUsers<T extends TLShape, U extends TLUser<T> = TLUser<T>> = Record<string, U>
|
export type TLUsers = Record<string, TLUser>
|
||||||
|
|
||||||
export type TLSnapLine = number[][]
|
export type TLSnapLine = number[][]
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Renderer } from '@tldraw/core'
|
import { CursorComponent, Renderer } from '@tldraw/core'
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import { ErrorBoundary as _Errorboundary } from 'react-error-boundary'
|
import { ErrorBoundary as _Errorboundary } from 'react-error-boundary'
|
||||||
import { IntlProvider } from 'react-intl'
|
import { IntlProvider } from 'react-intl'
|
||||||
|
@ -102,6 +102,21 @@ export interface TldrawProps extends TDCallbacks {
|
||||||
* bucket based solution will cause massive base64 string to be written to the liveblocks room.
|
* bucket based solution will cause massive base64 string to be written to the liveblocks room.
|
||||||
*/
|
*/
|
||||||
disableAssets?: boolean
|
disableAssets?: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (optional) Custom components to override parts of the default UI.
|
||||||
|
*/
|
||||||
|
components?: {
|
||||||
|
/**
|
||||||
|
* The component to render for multiplayer cursors.
|
||||||
|
*/
|
||||||
|
Cursor?: CursorComponent
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (optional) To hide cursors
|
||||||
|
*/
|
||||||
|
hideCursors?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const isSystemDarkMode = window.matchMedia
|
const isSystemDarkMode = window.matchMedia
|
||||||
|
@ -123,6 +138,7 @@ export function Tldraw({
|
||||||
readOnly = false,
|
readOnly = false,
|
||||||
disableAssets = false,
|
disableAssets = false,
|
||||||
darkMode = isSystemDarkMode,
|
darkMode = isSystemDarkMode,
|
||||||
|
components,
|
||||||
onMount,
|
onMount,
|
||||||
onChange,
|
onChange,
|
||||||
onChangePresence,
|
onChangePresence,
|
||||||
|
@ -143,6 +159,7 @@ export function Tldraw({
|
||||||
onSessionStart,
|
onSessionStart,
|
||||||
onSessionEnd,
|
onSessionEnd,
|
||||||
onExport,
|
onExport,
|
||||||
|
hideCursors,
|
||||||
}: TldrawProps) {
|
}: TldrawProps) {
|
||||||
const [sId, setSId] = React.useState(id)
|
const [sId, setSId] = React.useState(id)
|
||||||
|
|
||||||
|
@ -336,6 +353,8 @@ export function Tldraw({
|
||||||
showTools={showTools}
|
showTools={showTools}
|
||||||
showUI={showUI}
|
showUI={showUI}
|
||||||
readOnly={readOnly}
|
readOnly={readOnly}
|
||||||
|
components={components}
|
||||||
|
hideCursors={hideCursors}
|
||||||
/>
|
/>
|
||||||
</AlertDialogContext.Provider>
|
</AlertDialogContext.Provider>
|
||||||
</TldrawContext.Provider>
|
</TldrawContext.Provider>
|
||||||
|
@ -353,6 +372,10 @@ interface InnerTldrawProps {
|
||||||
showStyles: boolean
|
showStyles: boolean
|
||||||
showUI: boolean
|
showUI: boolean
|
||||||
showTools: boolean
|
showTools: boolean
|
||||||
|
components?: {
|
||||||
|
Cursor?: CursorComponent
|
||||||
|
}
|
||||||
|
hideCursors?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const InnerTldraw = React.memo(function InnerTldraw({
|
const InnerTldraw = React.memo(function InnerTldraw({
|
||||||
|
@ -366,6 +389,8 @@ const InnerTldraw = React.memo(function InnerTldraw({
|
||||||
showTools,
|
showTools,
|
||||||
readOnly,
|
readOnly,
|
||||||
showUI,
|
showUI,
|
||||||
|
components,
|
||||||
|
hideCursors,
|
||||||
}: InnerTldrawProps) {
|
}: InnerTldrawProps) {
|
||||||
const app = useTldrawApp()
|
const app = useTldrawApp()
|
||||||
const [dialogContainer, setDialogContainer] = React.useState<any>(null)
|
const [dialogContainer, setDialogContainer] = React.useState<any>(null)
|
||||||
|
@ -489,6 +514,8 @@ const InnerTldraw = React.memo(function InnerTldraw({
|
||||||
userId={room?.userId}
|
userId={room?.userId}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
meta={meta}
|
meta={meta}
|
||||||
|
components={components}
|
||||||
|
hideCursors={hideCursors}
|
||||||
hideBounds={hideBounds}
|
hideBounds={hideBounds}
|
||||||
hideHandles={hideHandles}
|
hideHandles={hideHandles}
|
||||||
hideResizeHandles={isHideResizeHandlesShape}
|
hideResizeHandles={isHideResizeHandlesShape}
|
||||||
|
|
|
@ -176,7 +176,7 @@ export enum TDUserStatus {
|
||||||
}
|
}
|
||||||
|
|
||||||
// A TDUser, for multiplayer rooms
|
// A TDUser, for multiplayer rooms
|
||||||
export interface TDUser extends TLUser<TDShape> {
|
export interface TDUser extends TLUser {
|
||||||
activeShapes: TDShape[]
|
activeShapes: TDShape[]
|
||||||
status: TDUserStatus
|
status: TDUserStatus
|
||||||
session?: boolean
|
session?: boolean
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue