From 9fc5f4459f674b121cc177f8ae99efa9fdb442c8 Mon Sep 17 00:00:00 2001 From: Steve Ruiz Date: Mon, 19 Feb 2024 14:52:43 +0000 Subject: [PATCH] Roundup fixes (#2862) This one is a roundup of superficial changes, apologies for having them in a single PR. This PR: - does some chair re-arranging for one of our hotter paths related to updating shapes - changes our type exports for editor components - adds shape indicator to editor components - moves canvas to be an editor component - fixes a CSS bug with hinted buttons - fixes CSS bugs with the menus - fixes bad imports in examples ### Change Type - [x] `major` --- .../CustomStylePanelExample.tsx | 5 +- .../custom-toolbar/CustomToolbarExample.tsx | 3 +- .../src/examples/exploded/ExplodedExample.tsx | 3 +- apps/examples/src/index.tsx | 2 +- packages/editor/api-report.md | 144 +- packages/editor/api/api.json | 1428 +++++++++++------ packages/editor/src/index.ts | 50 +- packages/editor/src/lib/TldrawEditor.tsx | 7 +- .../src/lib/components/LiveCollaborators.tsx | 2 +- .../default-components/DefaultBackground.tsx | 5 - .../default-components/DefaultBrush.tsx | 8 +- .../DefaultCanvas.tsx} | 53 +- .../DefaultCollaboratorHint.tsx | 10 +- .../default-components/DefaultCursor.tsx | 21 +- .../DefaultErrorFallback.tsx | 8 +- .../default-components/DefaultGrid.tsx | 7 +- .../default-components/DefaultHandle.tsx | 7 +- .../default-components/DefaultHandles.tsx | 9 +- .../DefaultHoveredShapeIndicator.tsx | 13 +- .../DefaultInFrontOfTheCanvas.tsx | 4 - .../DefaultLoadingScreen.tsx | 6 +- .../default-components/DefaultOnTheCanvas.tsx | 4 - .../default-components/DefaultScribble.tsx | 13 +- .../DefaultSelectionBackground.tsx | 9 +- .../DefaultSelectionForeground.tsx | 11 +- .../DefaultShapeIndicator.tsx} | 37 +- .../DefaultSnapIndictor.tsx | 6 +- .../default-components/DefaultSpinner.tsx | 7 +- .../default-components/DefaultSvgDefs.tsx | 3 - packages/editor/src/lib/editor/Editor.ts | 202 +-- .../src/lib/hooks/useEditorComponents.tsx | 96 +- packages/tldraw/api-report.md | 57 +- packages/tldraw/api/api.json | 576 ++++--- packages/tldraw/src/index.ts | 2 +- packages/tldraw/src/lib/Tldraw.test.tsx | 8 +- packages/tldraw/src/lib/Tldraw.tsx | 21 +- .../src/lib/canvas/TldrawCropHandles.tsx | 2 - .../tldraw/src/lib/canvas/TldrawHandles.tsx | 4 +- .../canvas/TldrawHoveredShapeIndicator.tsx | 10 +- .../tldraw/src/lib/canvas/TldrawScribble.tsx | 10 +- .../lib/canvas/TldrawSelectionBackground.tsx | 4 +- .../lib/canvas/TldrawSelectionForeground.tsx | 805 +++++----- packages/tldraw/src/lib/ui.css | 34 +- packages/tldraw/src/lib/ui/TldrawUi.tsx | 11 +- .../ContextMenu/DefaultContextMenu.tsx | 8 +- .../lib/ui/components/MobileStylePanel.tsx | 14 +- .../StylePanel/DefaultStylePanel.tsx | 14 +- .../StylePanel/DefaultStylePanelContent.tsx | 134 +- .../src/lib/ui/components/menu-items.tsx | 2 +- .../primitives/TldrawUiDropdownMenu.tsx | 11 +- .../primitives/menus/TldrawUiMenuGroup.tsx | 9 +- .../primitives/menus/TldrawUiMenuSubmenu.tsx | 6 +- .../src/lib/ui/hooks/useRevelantStyles.ts | 18 +- .../tldraw/src/test/TldrawEditor.test.tsx | 53 +- .../src/test/commands/lockShapes.test.ts | 10 +- .../test/testutils/renderTldrawComponent.tsx | 4 +- .../tldraw/src/test/ui/ContextMenu.test.tsx | 6 +- 57 files changed, 2191 insertions(+), 1825 deletions(-) rename packages/editor/src/lib/components/{Canvas.tsx => default-components/DefaultCanvas.tsx} (90%) delete mode 100644 packages/editor/src/lib/components/default-components/DefaultInFrontOfTheCanvas.tsx delete mode 100644 packages/editor/src/lib/components/default-components/DefaultOnTheCanvas.tsx rename packages/editor/src/lib/components/{ShapeIndicator.tsx => default-components/DefaultShapeIndicator.tsx} (74%) diff --git a/apps/examples/src/examples/custom-style-panel/CustomStylePanelExample.tsx b/apps/examples/src/examples/custom-style-panel/CustomStylePanelExample.tsx index 728f276b1..97ce4915c 100644 --- a/apps/examples/src/examples/custom-style-panel/CustomStylePanelExample.tsx +++ b/apps/examples/src/examples/custom-style-panel/CustomStylePanelExample.tsx @@ -8,6 +8,7 @@ import { TldrawUiButton, TldrawUiButtonLabel, useEditor, + useRelevantStyles, } from '@tldraw/tldraw' import '@tldraw/tldraw/tldraw.css' @@ -16,6 +17,8 @@ function CustomStylePanel(props: TLUiStylePanelProps) { // Styles are complex, sorry. Check our DefaultStylePanel for an example. + const styles = useRelevantStyles() + return ( Green - + ) } diff --git a/apps/examples/src/examples/custom-toolbar/CustomToolbarExample.tsx b/apps/examples/src/examples/custom-toolbar/CustomToolbarExample.tsx index 8f33e0f13..b495c0dab 100644 --- a/apps/examples/src/examples/custom-toolbar/CustomToolbarExample.tsx +++ b/apps/examples/src/examples/custom-toolbar/CustomToolbarExample.tsx @@ -1,5 +1,4 @@ -import { TLComponents, Tldraw } from '@tldraw/tldraw' -import { DefaultToolbar } from '@tldraw/tldraw/src/lib/ui/components/Toolbar/DefaultToolbar' +import { DefaultToolbar, TLComponents, Tldraw } from '@tldraw/tldraw' import '@tldraw/tldraw/tldraw.css' function CustomToolbar() { diff --git a/apps/examples/src/examples/exploded/ExplodedExample.tsx b/apps/examples/src/examples/exploded/ExplodedExample.tsx index e2359f3d1..9f08ed06e 100644 --- a/apps/examples/src/examples/exploded/ExplodedExample.tsx +++ b/apps/examples/src/examples/exploded/ExplodedExample.tsx @@ -1,5 +1,4 @@ import { - Canvas, ContextMenu, DefaultContextMenuContent, TldrawEditor, @@ -39,7 +38,7 @@ export default function ExplodedExample() { persistenceKey="exploded-example" > - }> + diff --git a/apps/examples/src/index.tsx b/apps/examples/src/index.tsx index df4acaa9c..89cb1cc2d 100644 --- a/apps/examples/src/index.tsx +++ b/apps/examples/src/index.tsx @@ -21,7 +21,7 @@ setDefaultEditorAssetUrls(assetUrls) setDefaultUiAssetUrls(assetUrls) const gettingStartedExamples = examples.find((e) => e.id === 'Getting Started') if (!gettingStartedExamples) throw new Error('Could not find getting started exmaples') -const basicExample = gettingStartedExamples.value.find((e) => e.priority === 1) +const basicExample = gettingStartedExamples.value.find((e) => e.title === 'Persistence key') if (!basicExample) throw new Error('Could not find initial example') const router = createBrowserRouter([ diff --git a/packages/editor/api-report.md b/packages/editor/api-report.md index 1f18d2067..158853bf6 100644 --- a/packages/editor/api-report.md +++ b/packages/editor/api-report.md @@ -306,11 +306,6 @@ export const CAMERA_SLIDE_FRICTION = 0.09; // @public (undocumented) export function canonicalizeRotation(a: number): number; -// @public (undocumented) -export function Canvas({ className }: { - className?: string; -}): JSX_2.Element; - // @public (undocumented) export class Circle2d extends Geometry2d { constructor(config: Omit & { @@ -449,50 +444,49 @@ export const DEFAULT_ANIMATION_OPTIONS: { export function DefaultBackground(): JSX_2.Element; // @public (undocumented) -export const DefaultBrush: TLBrushComponent; +export const DefaultBrush: ({ brush, color, opacity, className }: TLBrushProps) => JSX_2.Element; // @public (undocumented) -export const DefaultCollaboratorHint: TLCollaboratorHintComponent; +export function DefaultCanvas({ className }: TLCanvasComponentProps): JSX_2.Element; // @public (undocumented) -export const DefaultCursor: NamedExoticComponent< { -className?: string | undefined; -point: null | VecModel; -zoom: number; -color?: string | undefined; -name: null | string; -chatMessage: string; -}>; +export function DefaultCollaboratorHint({ className, zoom, point, color, viewport, opacity, }: TLCollaboratorHintProps): JSX_2.Element; + +// @public (undocumented) +export const DefaultCursor: NamedExoticComponent; // @public (undocumented) export const DefaultErrorFallback: TLErrorFallbackComponent; // @public (undocumented) -export const DefaultGrid: TLGridComponent; +export function DefaultGrid({ x, y, z, size }: TLGridProps): JSX_2.Element; // @public (undocumented) -export const DefaultHandle: TLHandleComponent; +export function DefaultHandle({ handle, isCoarse, className, zoom }: TLHandleProps): JSX_2.Element; // @public (undocumented) -export const DefaultHandles: TLHandlesComponent; +export const DefaultHandles: ({ children }: TLHandlesProps) => JSX_2.Element; // @public (undocumented) -export const DefaultHoveredShapeIndicator: TLHoveredShapeIndicatorComponent; +export function DefaultHoveredShapeIndicator({ shapeId }: TLHoveredShapeIndicatorProps): JSX_2.Element | null; // @public (undocumented) -export const DefaultScribble: TLScribbleComponent; +export function DefaultScribble({ scribble, zoom, color, opacity, className }: TLScribbleProps): JSX_2.Element | null; // @public (undocumented) -export const DefaultSelectionBackground: TLSelectionBackgroundComponent; +export function DefaultSelectionBackground({ bounds, rotation }: TLSelectionBackgroundProps): JSX_2.Element; // @public (undocumented) -export const DefaultSelectionForeground: TLSelectionForegroundComponent; +export function DefaultSelectionForeground({ bounds, rotation }: TLSelectionForegroundProps): JSX_2.Element; // @public (undocumented) -export const DefaultSnapIndicator: TLSnapIndicatorComponent; +export const DefaultShapeIndicator: NamedExoticComponent; // @public (undocumented) -export const DefaultSpinner: TLSpinnerComponent; +export function DefaultSnapIndicator({ className, line, zoom }: TLSnapIndicatorProps): JSX_2.Element; + +// @public (undocumented) +export function DefaultSpinner(): JSX_2.Element; // @public (undocumented) export const DefaultSvgDefs: () => null; @@ -1587,14 +1581,6 @@ export function setRuntimeOverrides(input: Partial): void; // @public (undocumented) export function setUserPreferences(user: TLUserPreferences): void; -// @public (undocumented) -export const ShapeIndicator: React_3.NamedExoticComponent<{ - id: TLShapeId; - color?: string | undefined; - opacity?: number | undefined; - className?: string | undefined; -}>; - // @public (undocumented) export abstract class ShapeUtil { constructor(editor: Editor); @@ -1898,9 +1884,6 @@ export type TLArrowPoint = { arrowhead: TLArrowShapeArrowheadStyle; }; -// @public (undocumented) -export type TLBackgroundComponent = ComponentType; - // @public (undocumented) export type TLBaseBoxShape = TLBaseShape = (record: R, source: 'rem export type TLBeforeDeleteHandler = (record: R, source: 'remote' | 'user') => false | void; // @public (undocumented) -export type TLBrushComponent = ComponentType<{ +export type TLBrushProps = { brush: BoxModel; color?: string; opacity?: number; className?: string; -}>; +}; // @public (undocumented) export type TLCancelEvent = (info: TLCancelEventInfo) => void; @@ -1965,14 +1948,14 @@ export type TLClickEventInfo = TLBaseEventInfo & { export type TLCLickEventName = 'double_click' | 'quadruple_click' | 'triple_click'; // @public (undocumented) -export type TLCollaboratorHintComponent = ComponentType<{ +export type TLCollaboratorHintProps = { className?: string; point: VecModel; viewport: Box; zoom: number; opacity?: number; color: string; -}>; +}; // @public (undocumented) export type TLCommand = { @@ -2020,14 +2003,14 @@ export interface TLContent { } // @public (undocumented) -export type TLCursorComponent = ComponentType<{ +export type TLCursorProps = { className?: string; point: null | VecModel; zoom: number; color?: string; name: null | string; chatMessage: string; -}>; +}; // @public (undocumented) export const TldrawEditor: React_2.NamedExoticComponent; @@ -2224,27 +2207,26 @@ export type TLExternalContentSource = { }; // @public (undocumented) -export type TLGridComponent = ComponentType<{ +export type TLGridProps = { x: number; y: number; z: number; size: number; -}>; +}; // @public (undocumented) -export type TLHandleComponent = ComponentType<{ +export type TLHandleProps = { shapeId: TLShapeId; handle: TLHandle; zoom: number; isCoarse: boolean; className?: string; -}>; +}; // @public (undocumented) -export type TLHandlesComponent = ComponentType<{ - className?: string; +export type TLHandlesProps = { children: any; -}>; +}; // @public (undocumented) export type TLHistoryEntry = TLCommand | TLHistoryMark; @@ -2258,12 +2240,9 @@ export type TLHistoryMark = { }; // @public (undocumented) -export type TLHoveredShapeIndicatorComponent = ComponentType<{ +export type TLHoveredShapeIndicatorProps = { shapeId: TLShapeId; -}>; - -// @public (undocumented) -export type TLInFrontOfTheCanvas = ComponentType; +}; // @public (undocumented) export type TLInterruptEvent = (info: TLInterruptEventInfo) => void; @@ -2343,9 +2322,6 @@ export type TLOnRotateHandler = TLEventChangeHandler; // @public (undocumented) export type TLOnRotateStartHandler = TLEventStartHandler; -// @public (undocumented) -export type TLOnTheCanvas = ComponentType; - // @public (undocumented) export type TLOnTranslateEndHandler = TLEventChangeHandler; @@ -2442,25 +2418,25 @@ export type TLRotationSnapshot = { }; // @public (undocumented) -export type TLScribbleComponent = ComponentType<{ +export type TLScribbleProps = { scribble: TLScribble; zoom: number; color?: string; opacity?: number; className?: string; -}>; +}; // @public (undocumented) -export type TLSelectionBackgroundComponent = React_3.ComponentType<{ +export type TLSelectionBackgroundProps = { bounds: Box; rotation: number; -}>; +}; // @public (undocumented) -export type TLSelectionForegroundComponent = ComponentType<{ +export type TLSelectionForegroundProps = { bounds: Box; rotation: number; -}>; +}; // @public (undocumented) export type TLSelectionHandle = RotateCorner | SelectionCorner | SelectionEdge; @@ -2495,12 +2471,12 @@ export interface TLSessionStateSnapshot { } // @public (undocumented) -export type TLShapeIndicatorComponent = React_3.ComponentType<{ - id: TLShapeId; +export type TLShapeIndicatorProps = { + shapeId: TLShapeId; color?: string | undefined; opacity?: number; className?: string; -}>; +}; // @public (undocumented) export interface TLShapeUtilCanvasSvgDef { @@ -2526,14 +2502,11 @@ export interface TLShapeUtilConstructor = (shape: T) => boolean; // @public (undocumented) -export type TLSnapIndicatorComponent = React_3.ComponentType<{ +export type TLSnapIndicatorProps = { className?: string; line: SnapIndicator; zoom: number; -}>; - -// @public (undocumented) -export type TLSpinnerComponent = ComponentType; +}; // @public (undocumented) export interface TLStateNodeConstructor { @@ -2584,9 +2557,6 @@ export type TLStoreWithStatus = { readonly error?: undefined; }; -// @public (undocumented) -export type TLSvgDefsComponent = React.ComponentType; - // @public (undocumented) export type TLSvgOptions = { bounds: Box; @@ -2672,6 +2642,34 @@ export function useContainer(): HTMLDivElement; // @public (undocumented) export function useEditor(): Editor; +// @public (undocumented) +export function useEditorComponents(): Partial<{ + Background: ComponentType | null; + SvgDefs: ComponentType | null; + Brush: ComponentType | null; + ZoomBrush: ComponentType | null; + ShapeIndicator: ComponentType | null; + Cursor: ComponentType | null; + Canvas: ComponentType | null; + CollaboratorBrush: ComponentType | null; + CollaboratorCursor: ComponentType | null; + CollaboratorHint: ComponentType | null; + CollaboratorShapeIndicator: ComponentType | null; + Grid: ComponentType | null; + Scribble: ComponentType | null; + CollaboratorScribble: ComponentType | null; + SnapIndicator: ComponentType | null; + Handles: ComponentType | null; + Handle: ComponentType | null; + Spinner: ComponentType | null; + SelectionForeground: ComponentType | null; + SelectionBackground: ComponentType | null; + HoveredShapeIndicator: ComponentType | null; + OnTheCanvas: ComponentType | null; + InFrontOfTheCanvas: ComponentType | null; + LoadingScreen: ComponentType | null; +} & ErrorComponents> & ErrorComponents; + // @public (undocumented) export function useIsCropping(shapeId: TLShapeId): boolean; diff --git a/packages/editor/api/api.json b/packages/editor/api/api.json index a30d1d4af..7843a8c12 100644 --- a/packages/editor/api/api.json +++ b/packages/editor/api/api.json @@ -4199,56 +4199,6 @@ ], "name": "canonicalizeRotation" }, - { - "kind": "Function", - "canonicalReference": "@tldraw/editor!Canvas:function(1)", - "docComment": "/**\n * @public\n */\n", - "excerptTokens": [ - { - "kind": "Content", - "text": "export declare function Canvas({ className }: " - }, - { - "kind": "Content", - "text": "{\n className?: string;\n}" - }, - { - "kind": "Content", - "text": "): " - }, - { - "kind": "Content", - "text": "import(\"react/jsx-runtime\")." - }, - { - "kind": "Reference", - "text": "JSX.Element", - "canonicalReference": "@types/react!JSX.Element:interface" - }, - { - "kind": "Content", - "text": ";" - } - ], - "fileUrlPath": "packages/editor/src/lib/components/Canvas.tsx", - "returnTypeTokenRange": { - "startIndex": 3, - "endIndex": 5 - }, - "releaseTag": "Public", - "overloadIndex": 1, - "parameters": [ - { - "parameterName": "{ className }", - "parameterTypeTokenRange": { - "startIndex": 1, - "endIndex": 2 - }, - "isOptional": false - } - ], - "name": "Canvas" - }, { "kind": "Class", "canonicalReference": "@tldraw/editor!Circle2d:class", @@ -6145,10 +6095,23 @@ "kind": "Content", "text": "DefaultBrush: " }, + { + "kind": "Content", + "text": "({ brush, color, opacity, className }: " + }, { "kind": "Reference", - "text": "TLBrushComponent", - "canonicalReference": "@tldraw/editor!TLBrushComponent:type" + "text": "TLBrushProps", + "canonicalReference": "@tldraw/editor!TLBrushProps:type" + }, + { + "kind": "Content", + "text": ") => import(\"react/jsx-runtime\")." + }, + { + "kind": "Reference", + "text": "JSX.Element", + "canonicalReference": "@types/react!JSX.Element:interface" } ], "fileUrlPath": "packages/editor/src/lib/components/default-components/DefaultBrush.tsx", @@ -6157,32 +6120,110 @@ "name": "DefaultBrush", "variableTypeTokenRange": { "startIndex": 1, - "endIndex": 2 + "endIndex": 5 } }, { - "kind": "Variable", - "canonicalReference": "@tldraw/editor!DefaultCollaboratorHint:var", + "kind": "Function", + "canonicalReference": "@tldraw/editor!DefaultCanvas:function(1)", "docComment": "/**\n * @public\n */\n", "excerptTokens": [ { "kind": "Content", - "text": "DefaultCollaboratorHint: " + "text": "export declare function DefaultCanvas({ className }: " }, { "kind": "Reference", - "text": "TLCollaboratorHintComponent", - "canonicalReference": "@tldraw/editor!TLCollaboratorHintComponent:type" + "text": "TLCanvasComponentProps", + "canonicalReference": "@tldraw/editor!~TLCanvasComponentProps:type" + }, + { + "kind": "Content", + "text": "): " + }, + { + "kind": "Content", + "text": "import(\"react/jsx-runtime\")." + }, + { + "kind": "Reference", + "text": "JSX.Element", + "canonicalReference": "@types/react!JSX.Element:interface" + }, + { + "kind": "Content", + "text": ";" + } + ], + "fileUrlPath": "packages/editor/src/lib/components/default-components/DefaultCanvas.tsx", + "returnTypeTokenRange": { + "startIndex": 3, + "endIndex": 5 + }, + "releaseTag": "Public", + "overloadIndex": 1, + "parameters": [ + { + "parameterName": "{ className }", + "parameterTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + }, + "isOptional": false + } + ], + "name": "DefaultCanvas" + }, + { + "kind": "Function", + "canonicalReference": "@tldraw/editor!DefaultCollaboratorHint:function(1)", + "docComment": "/**\n * @public\n */\n", + "excerptTokens": [ + { + "kind": "Content", + "text": "export declare function DefaultCollaboratorHint({ className, zoom, point, color, viewport, opacity, }: " + }, + { + "kind": "Reference", + "text": "TLCollaboratorHintProps", + "canonicalReference": "@tldraw/editor!TLCollaboratorHintProps:type" + }, + { + "kind": "Content", + "text": "): " + }, + { + "kind": "Content", + "text": "import(\"react/jsx-runtime\")." + }, + { + "kind": "Reference", + "text": "JSX.Element", + "canonicalReference": "@types/react!JSX.Element:interface" + }, + { + "kind": "Content", + "text": ";" } ], "fileUrlPath": "packages/editor/src/lib/components/default-components/DefaultCollaboratorHint.tsx", - "isReadonly": true, + "returnTypeTokenRange": { + "startIndex": 3, + "endIndex": 5 + }, "releaseTag": "Public", - "name": "DefaultCollaboratorHint", - "variableTypeTokenRange": { - "startIndex": 1, - "endIndex": 2 - } + "overloadIndex": 1, + "parameters": [ + { + "parameterName": "{ className, zoom, point, color, viewport, opacity, }", + "parameterTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + }, + "isOptional": false + } + ], + "name": "DefaultCollaboratorHint" }, { "kind": "Variable", @@ -6204,16 +6245,16 @@ }, { "kind": "Content", - "text": "<{\n className?: string | undefined;\n point: null | " + "text": "<" }, { "kind": "Reference", - "text": "VecModel", - "canonicalReference": "@tldraw/tlschema!VecModel:interface" + "text": "TLCursorProps", + "canonicalReference": "@tldraw/editor!TLCursorProps:type" }, { "kind": "Content", - "text": ";\n zoom: number;\n color?: string | undefined;\n name: null | string;\n chatMessage: string;\n}>" + "text": ">" } ], "fileUrlPath": "packages/editor/src/lib/components/default-components/DefaultCursor.tsx", @@ -6250,52 +6291,106 @@ } }, { - "kind": "Variable", - "canonicalReference": "@tldraw/editor!DefaultGrid:var", + "kind": "Function", + "canonicalReference": "@tldraw/editor!DefaultGrid:function(1)", "docComment": "/**\n * @public\n */\n", "excerptTokens": [ { "kind": "Content", - "text": "DefaultGrid: " + "text": "export declare function DefaultGrid({ x, y, z, size }: " }, { "kind": "Reference", - "text": "TLGridComponent", - "canonicalReference": "@tldraw/editor!TLGridComponent:type" + "text": "TLGridProps", + "canonicalReference": "@tldraw/editor!TLGridProps:type" + }, + { + "kind": "Content", + "text": "): " + }, + { + "kind": "Content", + "text": "import(\"react/jsx-runtime\")." + }, + { + "kind": "Reference", + "text": "JSX.Element", + "canonicalReference": "@types/react!JSX.Element:interface" + }, + { + "kind": "Content", + "text": ";" } ], "fileUrlPath": "packages/editor/src/lib/components/default-components/DefaultGrid.tsx", - "isReadonly": true, + "returnTypeTokenRange": { + "startIndex": 3, + "endIndex": 5 + }, "releaseTag": "Public", - "name": "DefaultGrid", - "variableTypeTokenRange": { - "startIndex": 1, - "endIndex": 2 - } + "overloadIndex": 1, + "parameters": [ + { + "parameterName": "{ x, y, z, size }", + "parameterTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + }, + "isOptional": false + } + ], + "name": "DefaultGrid" }, { - "kind": "Variable", - "canonicalReference": "@tldraw/editor!DefaultHandle:var", + "kind": "Function", + "canonicalReference": "@tldraw/editor!DefaultHandle:function(1)", "docComment": "/**\n * @public\n */\n", "excerptTokens": [ { "kind": "Content", - "text": "DefaultHandle: " + "text": "export declare function DefaultHandle({ handle, isCoarse, className, zoom }: " }, { "kind": "Reference", - "text": "TLHandleComponent", - "canonicalReference": "@tldraw/editor!TLHandleComponent:type" + "text": "TLHandleProps", + "canonicalReference": "@tldraw/editor!TLHandleProps:type" + }, + { + "kind": "Content", + "text": "): " + }, + { + "kind": "Content", + "text": "import(\"react/jsx-runtime\")." + }, + { + "kind": "Reference", + "text": "JSX.Element", + "canonicalReference": "@types/react!JSX.Element:interface" + }, + { + "kind": "Content", + "text": ";" } ], "fileUrlPath": "packages/editor/src/lib/components/default-components/DefaultHandle.tsx", - "isReadonly": true, + "returnTypeTokenRange": { + "startIndex": 3, + "endIndex": 5 + }, "releaseTag": "Public", - "name": "DefaultHandle", - "variableTypeTokenRange": { - "startIndex": 1, - "endIndex": 2 - } + "overloadIndex": 1, + "parameters": [ + { + "parameterName": "{ handle, isCoarse, className, zoom }", + "parameterTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + }, + "isOptional": false + } + ], + "name": "DefaultHandle" }, { "kind": "Variable", @@ -6306,10 +6401,23 @@ "kind": "Content", "text": "DefaultHandles: " }, + { + "kind": "Content", + "text": "({ children }: " + }, { "kind": "Reference", - "text": "TLHandlesComponent", - "canonicalReference": "@tldraw/editor!TLHandlesComponent:type" + "text": "TLHandlesProps", + "canonicalReference": "@tldraw/editor!TLHandlesProps:type" + }, + { + "kind": "Content", + "text": ") => import(\"react/jsx-runtime\")." + }, + { + "kind": "Reference", + "text": "JSX.Element", + "canonicalReference": "@types/react!JSX.Element:interface" } ], "fileUrlPath": "packages/editor/src/lib/components/default-components/DefaultHandles.tsx", @@ -6318,152 +6426,345 @@ "name": "DefaultHandles", "variableTypeTokenRange": { "startIndex": 1, - "endIndex": 2 + "endIndex": 5 } }, { - "kind": "Variable", - "canonicalReference": "@tldraw/editor!DefaultHoveredShapeIndicator:var", + "kind": "Function", + "canonicalReference": "@tldraw/editor!DefaultHoveredShapeIndicator:function(1)", "docComment": "/**\n * @public\n */\n", "excerptTokens": [ { "kind": "Content", - "text": "DefaultHoveredShapeIndicator: " + "text": "export declare function DefaultHoveredShapeIndicator({ shapeId }: " }, { "kind": "Reference", - "text": "TLHoveredShapeIndicatorComponent", - "canonicalReference": "@tldraw/editor!TLHoveredShapeIndicatorComponent:type" + "text": "TLHoveredShapeIndicatorProps", + "canonicalReference": "@tldraw/editor!TLHoveredShapeIndicatorProps:type" + }, + { + "kind": "Content", + "text": "): " + }, + { + "kind": "Content", + "text": "import(\"react/jsx-runtime\")." + }, + { + "kind": "Reference", + "text": "JSX.Element", + "canonicalReference": "@types/react!JSX.Element:interface" + }, + { + "kind": "Content", + "text": " | null" + }, + { + "kind": "Content", + "text": ";" } ], "fileUrlPath": "packages/editor/src/lib/components/default-components/DefaultHoveredShapeIndicator.tsx", - "isReadonly": true, + "returnTypeTokenRange": { + "startIndex": 3, + "endIndex": 6 + }, "releaseTag": "Public", - "name": "DefaultHoveredShapeIndicator", - "variableTypeTokenRange": { - "startIndex": 1, - "endIndex": 2 - } + "overloadIndex": 1, + "parameters": [ + { + "parameterName": "{ shapeId }", + "parameterTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + }, + "isOptional": false + } + ], + "name": "DefaultHoveredShapeIndicator" }, { - "kind": "Variable", - "canonicalReference": "@tldraw/editor!DefaultScribble:var", + "kind": "Function", + "canonicalReference": "@tldraw/editor!DefaultScribble:function(1)", "docComment": "/**\n * @public\n */\n", "excerptTokens": [ { "kind": "Content", - "text": "DefaultScribble: " + "text": "export declare function DefaultScribble({ scribble, zoom, color, opacity, className }: " }, { "kind": "Reference", - "text": "TLScribbleComponent", - "canonicalReference": "@tldraw/editor!TLScribbleComponent:type" + "text": "TLScribbleProps", + "canonicalReference": "@tldraw/editor!TLScribbleProps:type" + }, + { + "kind": "Content", + "text": "): " + }, + { + "kind": "Content", + "text": "import(\"react/jsx-runtime\")." + }, + { + "kind": "Reference", + "text": "JSX.Element", + "canonicalReference": "@types/react!JSX.Element:interface" + }, + { + "kind": "Content", + "text": " | null" + }, + { + "kind": "Content", + "text": ";" } ], "fileUrlPath": "packages/editor/src/lib/components/default-components/DefaultScribble.tsx", - "isReadonly": true, + "returnTypeTokenRange": { + "startIndex": 3, + "endIndex": 6 + }, "releaseTag": "Public", - "name": "DefaultScribble", - "variableTypeTokenRange": { - "startIndex": 1, - "endIndex": 2 - } + "overloadIndex": 1, + "parameters": [ + { + "parameterName": "{ scribble, zoom, color, opacity, className }", + "parameterTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + }, + "isOptional": false + } + ], + "name": "DefaultScribble" }, { - "kind": "Variable", - "canonicalReference": "@tldraw/editor!DefaultSelectionBackground:var", + "kind": "Function", + "canonicalReference": "@tldraw/editor!DefaultSelectionBackground:function(1)", "docComment": "/**\n * @public\n */\n", "excerptTokens": [ { "kind": "Content", - "text": "DefaultSelectionBackground: " + "text": "export declare function DefaultSelectionBackground({ bounds, rotation }: " }, { "kind": "Reference", - "text": "TLSelectionBackgroundComponent", - "canonicalReference": "@tldraw/editor!TLSelectionBackgroundComponent:type" + "text": "TLSelectionBackgroundProps", + "canonicalReference": "@tldraw/editor!TLSelectionBackgroundProps:type" + }, + { + "kind": "Content", + "text": "): " + }, + { + "kind": "Content", + "text": "import(\"react/jsx-runtime\")." + }, + { + "kind": "Reference", + "text": "JSX.Element", + "canonicalReference": "@types/react!JSX.Element:interface" + }, + { + "kind": "Content", + "text": ";" } ], "fileUrlPath": "packages/editor/src/lib/components/default-components/DefaultSelectionBackground.tsx", - "isReadonly": true, + "returnTypeTokenRange": { + "startIndex": 3, + "endIndex": 5 + }, "releaseTag": "Public", - "name": "DefaultSelectionBackground", - "variableTypeTokenRange": { - "startIndex": 1, - "endIndex": 2 - } + "overloadIndex": 1, + "parameters": [ + { + "parameterName": "{ bounds, rotation }", + "parameterTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + }, + "isOptional": false + } + ], + "name": "DefaultSelectionBackground" }, { - "kind": "Variable", - "canonicalReference": "@tldraw/editor!DefaultSelectionForeground:var", + "kind": "Function", + "canonicalReference": "@tldraw/editor!DefaultSelectionForeground:function(1)", "docComment": "/**\n * @public\n */\n", "excerptTokens": [ { "kind": "Content", - "text": "DefaultSelectionForeground: " + "text": "export declare function DefaultSelectionForeground({ bounds, rotation }: " }, { "kind": "Reference", - "text": "TLSelectionForegroundComponent", - "canonicalReference": "@tldraw/editor!TLSelectionForegroundComponent:type" + "text": "TLSelectionForegroundProps", + "canonicalReference": "@tldraw/editor!TLSelectionForegroundProps:type" + }, + { + "kind": "Content", + "text": "): " + }, + { + "kind": "Content", + "text": "import(\"react/jsx-runtime\")." + }, + { + "kind": "Reference", + "text": "JSX.Element", + "canonicalReference": "@types/react!JSX.Element:interface" + }, + { + "kind": "Content", + "text": ";" } ], "fileUrlPath": "packages/editor/src/lib/components/default-components/DefaultSelectionForeground.tsx", - "isReadonly": true, + "returnTypeTokenRange": { + "startIndex": 3, + "endIndex": 5 + }, "releaseTag": "Public", - "name": "DefaultSelectionForeground", - "variableTypeTokenRange": { - "startIndex": 1, - "endIndex": 2 - } + "overloadIndex": 1, + "parameters": [ + { + "parameterName": "{ bounds, rotation }", + "parameterTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + }, + "isOptional": false + } + ], + "name": "DefaultSelectionForeground" }, { "kind": "Variable", - "canonicalReference": "@tldraw/editor!DefaultSnapIndicator:var", + "canonicalReference": "@tldraw/editor!DefaultShapeIndicator:var", "docComment": "/**\n * @public\n */\n", "excerptTokens": [ { "kind": "Content", - "text": "DefaultSnapIndicator: " + "text": "DefaultShapeIndicator: " + }, + { + "kind": "Content", + "text": "import(\"react\")." }, { "kind": "Reference", - "text": "TLSnapIndicatorComponent", - "canonicalReference": "@tldraw/editor!TLSnapIndicatorComponent:type" + "text": "NamedExoticComponent", + "canonicalReference": "@types/react!React.NamedExoticComponent:interface" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "TLShapeIndicatorProps", + "canonicalReference": "@tldraw/editor!TLShapeIndicatorProps:type" + }, + { + "kind": "Content", + "text": ">" + } + ], + "fileUrlPath": "packages/editor/src/lib/components/default-components/DefaultShapeIndicator.tsx", + "isReadonly": true, + "releaseTag": "Public", + "name": "DefaultShapeIndicator", + "variableTypeTokenRange": { + "startIndex": 1, + "endIndex": 6 + } + }, + { + "kind": "Function", + "canonicalReference": "@tldraw/editor!DefaultSnapIndicator:function(1)", + "docComment": "/**\n * @public\n */\n", + "excerptTokens": [ + { + "kind": "Content", + "text": "export declare function DefaultSnapIndicator({ className, line, zoom }: " + }, + { + "kind": "Reference", + "text": "TLSnapIndicatorProps", + "canonicalReference": "@tldraw/editor!TLSnapIndicatorProps:type" + }, + { + "kind": "Content", + "text": "): " + }, + { + "kind": "Content", + "text": "import(\"react/jsx-runtime\")." + }, + { + "kind": "Reference", + "text": "JSX.Element", + "canonicalReference": "@types/react!JSX.Element:interface" + }, + { + "kind": "Content", + "text": ";" } ], "fileUrlPath": "packages/editor/src/lib/components/default-components/DefaultSnapIndictor.tsx", - "isReadonly": true, + "returnTypeTokenRange": { + "startIndex": 3, + "endIndex": 5 + }, "releaseTag": "Public", - "name": "DefaultSnapIndicator", - "variableTypeTokenRange": { - "startIndex": 1, - "endIndex": 2 - } + "overloadIndex": 1, + "parameters": [ + { + "parameterName": "{ className, line, zoom }", + "parameterTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + }, + "isOptional": false + } + ], + "name": "DefaultSnapIndicator" }, { - "kind": "Variable", - "canonicalReference": "@tldraw/editor!DefaultSpinner:var", + "kind": "Function", + "canonicalReference": "@tldraw/editor!DefaultSpinner:function(1)", "docComment": "/**\n * @public\n */\n", "excerptTokens": [ { "kind": "Content", - "text": "DefaultSpinner: " + "text": "export declare function DefaultSpinner(): " + }, + { + "kind": "Content", + "text": "import(\"react/jsx-runtime\")." }, { "kind": "Reference", - "text": "TLSpinnerComponent", - "canonicalReference": "@tldraw/editor!TLSpinnerComponent:type" + "text": "JSX.Element", + "canonicalReference": "@types/react!JSX.Element:interface" + }, + { + "kind": "Content", + "text": ";" } ], "fileUrlPath": "packages/editor/src/lib/components/default-components/DefaultSpinner.tsx", - "isReadonly": true, - "releaseTag": "Public", - "name": "DefaultSpinner", - "variableTypeTokenRange": { + "returnTypeTokenRange": { "startIndex": 1, - "endIndex": 2 - } + "endIndex": 3 + }, + "releaseTag": "Public", + "overloadIndex": 1, + "parameters": [], + "name": "DefaultSpinner" }, { "kind": "Variable", @@ -29638,43 +29939,6 @@ ], "name": "setUserPreferences" }, - { - "kind": "Variable", - "canonicalReference": "@tldraw/editor!ShapeIndicator:var", - "docComment": "/**\n * @public\n */\n", - "excerptTokens": [ - { - "kind": "Content", - "text": "ShapeIndicator: " - }, - { - "kind": "Reference", - "text": "React.NamedExoticComponent", - "canonicalReference": "@types/react!React.NamedExoticComponent:interface" - }, - { - "kind": "Content", - "text": "<{\n id: " - }, - { - "kind": "Reference", - "text": "TLShapeId", - "canonicalReference": "@tldraw/tlschema!TLShapeId:type" - }, - { - "kind": "Content", - "text": ";\n color?: string | undefined;\n opacity?: number | undefined;\n className?: string | undefined;\n}>" - } - ], - "fileUrlPath": "packages/editor/src/lib/components/ShapeIndicator.tsx", - "isReadonly": true, - "releaseTag": "Public", - "name": "ShapeIndicator", - "variableTypeTokenRange": { - "startIndex": 1, - "endIndex": 5 - } - }, { "kind": "Class", "canonicalReference": "@tldraw/editor!ShapeUtil:class", @@ -34877,33 +35141,6 @@ "endIndex": 8 } }, - { - "kind": "TypeAlias", - "canonicalReference": "@tldraw/editor!TLBackgroundComponent:type", - "docComment": "/**\n * @public\n */\n", - "excerptTokens": [ - { - "kind": "Content", - "text": "export type TLBackgroundComponent = " - }, - { - "kind": "Reference", - "text": "ComponentType", - "canonicalReference": "@types/react!React.ComponentType:type" - }, - { - "kind": "Content", - "text": ";" - } - ], - "fileUrlPath": "packages/editor/src/lib/components/default-components/DefaultBackground.tsx", - "releaseTag": "Public", - "name": "TLBackgroundComponent", - "typeTokenRange": { - "startIndex": 1, - "endIndex": 2 - } - }, { "kind": "TypeAlias", "canonicalReference": "@tldraw/editor!TLBaseBoxShape:type", @@ -35234,21 +35471,16 @@ }, { "kind": "TypeAlias", - "canonicalReference": "@tldraw/editor!TLBrushComponent:type", + "canonicalReference": "@tldraw/editor!TLBrushProps:type", "docComment": "/**\n * @public\n */\n", "excerptTokens": [ { "kind": "Content", - "text": "export type TLBrushComponent = " - }, - { - "kind": "Reference", - "text": "ComponentType", - "canonicalReference": "@types/react!React.ComponentType:type" + "text": "export type TLBrushProps = " }, { "kind": "Content", - "text": "<{\n brush: " + "text": "{\n brush: " }, { "kind": "Reference", @@ -35257,7 +35489,7 @@ }, { "kind": "Content", - "text": ";\n color?: string;\n opacity?: number;\n className?: string;\n}>" + "text": ";\n color?: string;\n opacity?: number;\n className?: string;\n}" }, { "kind": "Content", @@ -35266,10 +35498,10 @@ ], "fileUrlPath": "packages/editor/src/lib/components/default-components/DefaultBrush.tsx", "releaseTag": "Public", - "name": "TLBrushComponent", + "name": "TLBrushProps", "typeTokenRange": { "startIndex": 1, - "endIndex": 5 + "endIndex": 4 } }, { @@ -35450,21 +35682,16 @@ }, { "kind": "TypeAlias", - "canonicalReference": "@tldraw/editor!TLCollaboratorHintComponent:type", + "canonicalReference": "@tldraw/editor!TLCollaboratorHintProps:type", "docComment": "/**\n * @public\n */\n", "excerptTokens": [ { "kind": "Content", - "text": "export type TLCollaboratorHintComponent = " - }, - { - "kind": "Reference", - "text": "ComponentType", - "canonicalReference": "@types/react!React.ComponentType:type" + "text": "export type TLCollaboratorHintProps = " }, { "kind": "Content", - "text": "<{\n className?: string;\n point: " + "text": "{\n className?: string;\n point: " }, { "kind": "Reference", @@ -35482,7 +35709,7 @@ }, { "kind": "Content", - "text": ";\n zoom: number;\n opacity?: number;\n color: string;\n}>" + "text": ";\n zoom: number;\n opacity?: number;\n color: string;\n}" }, { "kind": "Content", @@ -35491,10 +35718,10 @@ ], "fileUrlPath": "packages/editor/src/lib/components/default-components/DefaultCollaboratorHint.tsx", "releaseTag": "Public", - "name": "TLCollaboratorHintComponent", + "name": "TLCollaboratorHintProps", "typeTokenRange": { "startIndex": 1, - "endIndex": 7 + "endIndex": 6 } }, { @@ -35846,21 +36073,16 @@ }, { "kind": "TypeAlias", - "canonicalReference": "@tldraw/editor!TLCursorComponent:type", + "canonicalReference": "@tldraw/editor!TLCursorProps:type", "docComment": "/**\n * @public\n */\n", "excerptTokens": [ { "kind": "Content", - "text": "export type TLCursorComponent = " - }, - { - "kind": "Reference", - "text": "ComponentType", - "canonicalReference": "@types/react!React.ComponentType:type" + "text": "export type TLCursorProps = " }, { "kind": "Content", - "text": "<{\n className?: string;\n point: null | " + "text": "{\n className?: string;\n point: null | " }, { "kind": "Reference", @@ -35869,7 +36091,7 @@ }, { "kind": "Content", - "text": ";\n zoom: number;\n color?: string;\n name: null | string;\n chatMessage: string;\n}>" + "text": ";\n zoom: number;\n color?: string;\n name: null | string;\n chatMessage: string;\n}" }, { "kind": "Content", @@ -35878,10 +36100,10 @@ ], "fileUrlPath": "packages/editor/src/lib/components/default-components/DefaultCursor.tsx", "releaseTag": "Public", - "name": "TLCursorComponent", + "name": "TLCursorProps", "typeTokenRange": { "startIndex": 1, - "endIndex": 5 + "endIndex": 4 } }, { @@ -37926,21 +38148,16 @@ }, { "kind": "TypeAlias", - "canonicalReference": "@tldraw/editor!TLGridComponent:type", + "canonicalReference": "@tldraw/editor!TLGridProps:type", "docComment": "/**\n * @public\n */\n", "excerptTokens": [ { "kind": "Content", - "text": "export type TLGridComponent = " - }, - { - "kind": "Reference", - "text": "ComponentType", - "canonicalReference": "@types/react!React.ComponentType:type" + "text": "export type TLGridProps = " }, { "kind": "Content", - "text": "<{\n x: number;\n y: number;\n z: number;\n size: number;\n}>" + "text": "{\n x: number;\n y: number;\n z: number;\n size: number;\n}" }, { "kind": "Content", @@ -37949,29 +38166,24 @@ ], "fileUrlPath": "packages/editor/src/lib/components/default-components/DefaultGrid.tsx", "releaseTag": "Public", - "name": "TLGridComponent", + "name": "TLGridProps", "typeTokenRange": { "startIndex": 1, - "endIndex": 3 + "endIndex": 2 } }, { "kind": "TypeAlias", - "canonicalReference": "@tldraw/editor!TLHandleComponent:type", + "canonicalReference": "@tldraw/editor!TLHandleProps:type", "docComment": "/**\n * @public\n */\n", "excerptTokens": [ { "kind": "Content", - "text": "export type TLHandleComponent = " - }, - { - "kind": "Reference", - "text": "ComponentType", - "canonicalReference": "@types/react!React.ComponentType:type" + "text": "export type TLHandleProps = " }, { "kind": "Content", - "text": "<{\n shapeId: " + "text": "{\n shapeId: " }, { "kind": "Reference", @@ -37989,7 +38201,7 @@ }, { "kind": "Content", - "text": ";\n zoom: number;\n isCoarse: boolean;\n className?: string;\n}>" + "text": ";\n zoom: number;\n isCoarse: boolean;\n className?: string;\n}" }, { "kind": "Content", @@ -37998,29 +38210,24 @@ ], "fileUrlPath": "packages/editor/src/lib/components/default-components/DefaultHandle.tsx", "releaseTag": "Public", - "name": "TLHandleComponent", + "name": "TLHandleProps", "typeTokenRange": { "startIndex": 1, - "endIndex": 7 + "endIndex": 6 } }, { "kind": "TypeAlias", - "canonicalReference": "@tldraw/editor!TLHandlesComponent:type", + "canonicalReference": "@tldraw/editor!TLHandlesProps:type", "docComment": "/**\n * @public\n */\n", "excerptTokens": [ { "kind": "Content", - "text": "export type TLHandlesComponent = " - }, - { - "kind": "Reference", - "text": "ComponentType", - "canonicalReference": "@types/react!React.ComponentType:type" + "text": "export type TLHandlesProps = " }, { "kind": "Content", - "text": "<{\n className?: string;\n children: any;\n}>" + "text": "{\n children: any;\n}" }, { "kind": "Content", @@ -38029,10 +38236,10 @@ ], "fileUrlPath": "packages/editor/src/lib/components/default-components/DefaultHandles.tsx", "releaseTag": "Public", - "name": "TLHandlesComponent", + "name": "TLHandlesProps", "typeTokenRange": { "startIndex": 1, - "endIndex": 3 + "endIndex": 2 } }, { @@ -38099,21 +38306,16 @@ }, { "kind": "TypeAlias", - "canonicalReference": "@tldraw/editor!TLHoveredShapeIndicatorComponent:type", + "canonicalReference": "@tldraw/editor!TLHoveredShapeIndicatorProps:type", "docComment": "/**\n * @public\n */\n", "excerptTokens": [ { "kind": "Content", - "text": "export type TLHoveredShapeIndicatorComponent = " - }, - { - "kind": "Reference", - "text": "ComponentType", - "canonicalReference": "@types/react!React.ComponentType:type" + "text": "export type TLHoveredShapeIndicatorProps = " }, { "kind": "Content", - "text": "<{\n shapeId: " + "text": "{\n shapeId: " }, { "kind": "Reference", @@ -38122,7 +38324,7 @@ }, { "kind": "Content", - "text": ";\n}>" + "text": ";\n}" }, { "kind": "Content", @@ -38131,41 +38333,10 @@ ], "fileUrlPath": "packages/editor/src/lib/components/default-components/DefaultHoveredShapeIndicator.tsx", "releaseTag": "Public", - "name": "TLHoveredShapeIndicatorComponent", + "name": "TLHoveredShapeIndicatorProps", "typeTokenRange": { "startIndex": 1, - "endIndex": 5 - } - }, - { - "kind": "TypeAlias", - "canonicalReference": "@tldraw/editor!TLInFrontOfTheCanvas:type", - "docComment": "/**\n * @public\n */\n", - "excerptTokens": [ - { - "kind": "Content", - "text": "export type TLInFrontOfTheCanvas = " - }, - { - "kind": "Reference", - "text": "ComponentType", - "canonicalReference": "@types/react!React.ComponentType:type" - }, - { - "kind": "Content", - "text": "" - }, - { - "kind": "Content", - "text": ";" - } - ], - "fileUrlPath": "packages/editor/src/lib/components/default-components/DefaultInFrontOfTheCanvas.tsx", - "releaseTag": "Public", - "name": "TLInFrontOfTheCanvas", - "typeTokenRange": { - "startIndex": 1, - "endIndex": 3 + "endIndex": 4 } }, { @@ -39228,37 +39399,6 @@ "endIndex": 5 } }, - { - "kind": "TypeAlias", - "canonicalReference": "@tldraw/editor!TLOnTheCanvas:type", - "docComment": "/**\n * @public\n */\n", - "excerptTokens": [ - { - "kind": "Content", - "text": "export type TLOnTheCanvas = " - }, - { - "kind": "Reference", - "text": "ComponentType", - "canonicalReference": "@types/react!React.ComponentType:type" - }, - { - "kind": "Content", - "text": "" - }, - { - "kind": "Content", - "text": ";" - } - ], - "fileUrlPath": "packages/editor/src/lib/components/default-components/DefaultOnTheCanvas.tsx", - "releaseTag": "Public", - "name": "TLOnTheCanvas", - "typeTokenRange": { - "startIndex": 1, - "endIndex": 3 - } - }, { "kind": "TypeAlias", "canonicalReference": "@tldraw/editor!TLOnTranslateEndHandler:type", @@ -40000,21 +40140,16 @@ }, { "kind": "TypeAlias", - "canonicalReference": "@tldraw/editor!TLScribbleComponent:type", + "canonicalReference": "@tldraw/editor!TLScribbleProps:type", "docComment": "/**\n * @public\n */\n", "excerptTokens": [ { "kind": "Content", - "text": "export type TLScribbleComponent = " - }, - { - "kind": "Reference", - "text": "ComponentType", - "canonicalReference": "@types/react!React.ComponentType:type" + "text": "export type TLScribbleProps = " }, { "kind": "Content", - "text": "<{\n scribble: " + "text": "{\n scribble: " }, { "kind": "Reference", @@ -40023,7 +40158,7 @@ }, { "kind": "Content", - "text": ";\n zoom: number;\n color?: string;\n opacity?: number;\n className?: string;\n}>" + "text": ";\n zoom: number;\n color?: string;\n opacity?: number;\n className?: string;\n}" }, { "kind": "Content", @@ -40032,29 +40167,24 @@ ], "fileUrlPath": "packages/editor/src/lib/components/default-components/DefaultScribble.tsx", "releaseTag": "Public", - "name": "TLScribbleComponent", + "name": "TLScribbleProps", "typeTokenRange": { "startIndex": 1, - "endIndex": 5 + "endIndex": 4 } }, { "kind": "TypeAlias", - "canonicalReference": "@tldraw/editor!TLSelectionBackgroundComponent:type", + "canonicalReference": "@tldraw/editor!TLSelectionBackgroundProps:type", "docComment": "/**\n * @public\n */\n", "excerptTokens": [ { "kind": "Content", - "text": "export type TLSelectionBackgroundComponent = " - }, - { - "kind": "Reference", - "text": "React.ComponentType", - "canonicalReference": "@types/react!React.ComponentType:type" + "text": "export type TLSelectionBackgroundProps = " }, { "kind": "Content", - "text": "<{\n bounds: " + "text": "{\n bounds: " }, { "kind": "Reference", @@ -40063,7 +40193,7 @@ }, { "kind": "Content", - "text": ";\n rotation: number;\n}>" + "text": ";\n rotation: number;\n}" }, { "kind": "Content", @@ -40072,29 +40202,24 @@ ], "fileUrlPath": "packages/editor/src/lib/components/default-components/DefaultSelectionBackground.tsx", "releaseTag": "Public", - "name": "TLSelectionBackgroundComponent", + "name": "TLSelectionBackgroundProps", "typeTokenRange": { "startIndex": 1, - "endIndex": 5 + "endIndex": 4 } }, { "kind": "TypeAlias", - "canonicalReference": "@tldraw/editor!TLSelectionForegroundComponent:type", + "canonicalReference": "@tldraw/editor!TLSelectionForegroundProps:type", "docComment": "/**\n * @public\n */\n", "excerptTokens": [ { "kind": "Content", - "text": "export type TLSelectionForegroundComponent = " - }, - { - "kind": "Reference", - "text": "ComponentType", - "canonicalReference": "@types/react!React.ComponentType:type" + "text": "export type TLSelectionForegroundProps = " }, { "kind": "Content", - "text": "<{\n bounds: " + "text": "{\n bounds: " }, { "kind": "Reference", @@ -40103,7 +40228,7 @@ }, { "kind": "Content", - "text": ";\n rotation: number;\n}>" + "text": ";\n rotation: number;\n}" }, { "kind": "Content", @@ -40112,10 +40237,10 @@ ], "fileUrlPath": "packages/editor/src/lib/components/default-components/DefaultSelectionForeground.tsx", "releaseTag": "Public", - "name": "TLSelectionForegroundComponent", + "name": "TLSelectionForegroundProps", "typeTokenRange": { "startIndex": 1, - "endIndex": 5 + "endIndex": 4 } }, { @@ -40432,21 +40557,16 @@ }, { "kind": "TypeAlias", - "canonicalReference": "@tldraw/editor!TLShapeIndicatorComponent:type", + "canonicalReference": "@tldraw/editor!TLShapeIndicatorProps:type", "docComment": "/**\n * @public\n */\n", "excerptTokens": [ { "kind": "Content", - "text": "export type TLShapeIndicatorComponent = " - }, - { - "kind": "Reference", - "text": "React.ComponentType", - "canonicalReference": "@types/react!React.ComponentType:type" + "text": "export type TLShapeIndicatorProps = " }, { "kind": "Content", - "text": "<{\n id: " + "text": "{\n shapeId: " }, { "kind": "Reference", @@ -40455,19 +40575,19 @@ }, { "kind": "Content", - "text": ";\n color?: string | undefined;\n opacity?: number;\n className?: string;\n}>" + "text": ";\n color?: string | undefined;\n opacity?: number;\n className?: string;\n}" }, { "kind": "Content", "text": ";" } ], - "fileUrlPath": "packages/editor/src/lib/components/ShapeIndicator.tsx", + "fileUrlPath": "packages/editor/src/lib/components/default-components/DefaultShapeIndicator.tsx", "releaseTag": "Public", - "name": "TLShapeIndicatorComponent", + "name": "TLShapeIndicatorProps", "typeTokenRange": { "startIndex": 1, - "endIndex": 5 + "endIndex": 4 } }, { @@ -40792,21 +40912,16 @@ }, { "kind": "TypeAlias", - "canonicalReference": "@tldraw/editor!TLSnapIndicatorComponent:type", + "canonicalReference": "@tldraw/editor!TLSnapIndicatorProps:type", "docComment": "/**\n * @public\n */\n", "excerptTokens": [ { "kind": "Content", - "text": "export type TLSnapIndicatorComponent = " - }, - { - "kind": "Reference", - "text": "React.ComponentType", - "canonicalReference": "@types/react!React.ComponentType:type" + "text": "export type TLSnapIndicatorProps = " }, { "kind": "Content", - "text": "<{\n className?: string;\n line: " + "text": "{\n className?: string;\n line: " }, { "kind": "Reference", @@ -40815,7 +40930,7 @@ }, { "kind": "Content", - "text": ";\n zoom: number;\n}>" + "text": ";\n zoom: number;\n}" }, { "kind": "Content", @@ -40824,41 +40939,10 @@ ], "fileUrlPath": "packages/editor/src/lib/components/default-components/DefaultSnapIndictor.tsx", "releaseTag": "Public", - "name": "TLSnapIndicatorComponent", + "name": "TLSnapIndicatorProps", "typeTokenRange": { "startIndex": 1, - "endIndex": 5 - } - }, - { - "kind": "TypeAlias", - "canonicalReference": "@tldraw/editor!TLSpinnerComponent:type", - "docComment": "/**\n * @public\n */\n", - "excerptTokens": [ - { - "kind": "Content", - "text": "export type TLSpinnerComponent = " - }, - { - "kind": "Reference", - "text": "ComponentType", - "canonicalReference": "@types/react!React.ComponentType:type" - }, - { - "kind": "Content", - "text": "" - }, - { - "kind": "Content", - "text": ";" - } - ], - "fileUrlPath": "packages/editor/src/lib/components/default-components/DefaultSpinner.tsx", - "releaseTag": "Public", - "name": "TLSpinnerComponent", - "typeTokenRange": { - "startIndex": 1, - "endIndex": 3 + "endIndex": 4 } }, { @@ -41213,33 +41297,6 @@ "endIndex": 10 } }, - { - "kind": "TypeAlias", - "canonicalReference": "@tldraw/editor!TLSvgDefsComponent:type", - "docComment": "/**\n * @public\n */\n", - "excerptTokens": [ - { - "kind": "Content", - "text": "export type TLSvgDefsComponent = " - }, - { - "kind": "Reference", - "text": "React.ComponentType", - "canonicalReference": "@types/react!React.ComponentType:type" - }, - { - "kind": "Content", - "text": ";" - } - ], - "fileUrlPath": "packages/editor/.tsbuild-api/lib/components/default-components/DefaultSvgDefs.d.ts", - "releaseTag": "Public", - "name": "TLSvgDefsComponent", - "typeTokenRange": { - "startIndex": 1, - "endIndex": 2 - } - }, { "kind": "TypeAlias", "canonicalReference": "@tldraw/editor!TLSvgOptions:type", @@ -42056,6 +42113,431 @@ "parameters": [], "name": "useEditor" }, + { + "kind": "Function", + "canonicalReference": "@tldraw/editor!useEditorComponents:function(1)", + "docComment": "/**\n * @public\n */\n", + "excerptTokens": [ + { + "kind": "Content", + "text": "export declare function useEditorComponents(): " + }, + { + "kind": "Reference", + "text": "Partial", + "canonicalReference": "!Partial:type" + }, + { + "kind": "Content", + "text": "<{\n Background: " + }, + { + "kind": "Reference", + "text": "ComponentType", + "canonicalReference": "@types/react!React.ComponentType:type" + }, + { + "kind": "Content", + "text": " | null;\n SvgDefs: " + }, + { + "kind": "Reference", + "text": "ComponentType", + "canonicalReference": "@types/react!React.ComponentType:type" + }, + { + "kind": "Content", + "text": " | null;\n Brush: " + }, + { + "kind": "Reference", + "text": "ComponentType", + "canonicalReference": "@types/react!React.ComponentType:type" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "TLBrushProps", + "canonicalReference": "@tldraw/editor!TLBrushProps:type" + }, + { + "kind": "Content", + "text": "> | null;\n ZoomBrush: " + }, + { + "kind": "Reference", + "text": "ComponentType", + "canonicalReference": "@types/react!React.ComponentType:type" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "TLBrushProps", + "canonicalReference": "@tldraw/editor!TLBrushProps:type" + }, + { + "kind": "Content", + "text": "> | null;\n ShapeIndicator: " + }, + { + "kind": "Reference", + "text": "ComponentType", + "canonicalReference": "@types/react!React.ComponentType:type" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "TLShapeIndicatorProps", + "canonicalReference": "@tldraw/editor!TLShapeIndicatorProps:type" + }, + { + "kind": "Content", + "text": "> | null;\n Cursor: " + }, + { + "kind": "Reference", + "text": "ComponentType", + "canonicalReference": "@types/react!React.ComponentType:type" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "TLCursorProps", + "canonicalReference": "@tldraw/editor!TLCursorProps:type" + }, + { + "kind": "Content", + "text": "> | null;\n Canvas: " + }, + { + "kind": "Reference", + "text": "ComponentType", + "canonicalReference": "@types/react!React.ComponentType:type" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "TLCanvasComponentProps", + "canonicalReference": "@tldraw/editor!~TLCanvasComponentProps:type" + }, + { + "kind": "Content", + "text": "> | null;\n CollaboratorBrush: " + }, + { + "kind": "Reference", + "text": "ComponentType", + "canonicalReference": "@types/react!React.ComponentType:type" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "TLBrushProps", + "canonicalReference": "@tldraw/editor!TLBrushProps:type" + }, + { + "kind": "Content", + "text": "> | null;\n CollaboratorCursor: " + }, + { + "kind": "Reference", + "text": "ComponentType", + "canonicalReference": "@types/react!React.ComponentType:type" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "TLCursorProps", + "canonicalReference": "@tldraw/editor!TLCursorProps:type" + }, + { + "kind": "Content", + "text": "> | null;\n CollaboratorHint: " + }, + { + "kind": "Reference", + "text": "ComponentType", + "canonicalReference": "@types/react!React.ComponentType:type" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "TLCollaboratorHintProps", + "canonicalReference": "@tldraw/editor!TLCollaboratorHintProps:type" + }, + { + "kind": "Content", + "text": "> | null;\n CollaboratorShapeIndicator: " + }, + { + "kind": "Reference", + "text": "ComponentType", + "canonicalReference": "@types/react!React.ComponentType:type" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "TLShapeIndicatorProps", + "canonicalReference": "@tldraw/editor!TLShapeIndicatorProps:type" + }, + { + "kind": "Content", + "text": "> | null;\n Grid: " + }, + { + "kind": "Reference", + "text": "ComponentType", + "canonicalReference": "@types/react!React.ComponentType:type" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "TLGridProps", + "canonicalReference": "@tldraw/editor!TLGridProps:type" + }, + { + "kind": "Content", + "text": "> | null;\n Scribble: " + }, + { + "kind": "Reference", + "text": "ComponentType", + "canonicalReference": "@types/react!React.ComponentType:type" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "TLScribbleProps", + "canonicalReference": "@tldraw/editor!TLScribbleProps:type" + }, + { + "kind": "Content", + "text": "> | null;\n CollaboratorScribble: " + }, + { + "kind": "Reference", + "text": "ComponentType", + "canonicalReference": "@types/react!React.ComponentType:type" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "TLScribbleProps", + "canonicalReference": "@tldraw/editor!TLScribbleProps:type" + }, + { + "kind": "Content", + "text": "> | null;\n SnapIndicator: " + }, + { + "kind": "Reference", + "text": "ComponentType", + "canonicalReference": "@types/react!React.ComponentType:type" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "TLSnapIndicatorProps", + "canonicalReference": "@tldraw/editor!TLSnapIndicatorProps:type" + }, + { + "kind": "Content", + "text": "> | null;\n Handles: " + }, + { + "kind": "Reference", + "text": "ComponentType", + "canonicalReference": "@types/react!React.ComponentType:type" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "TLHandlesProps", + "canonicalReference": "@tldraw/editor!TLHandlesProps:type" + }, + { + "kind": "Content", + "text": "> | null;\n Handle: " + }, + { + "kind": "Reference", + "text": "ComponentType", + "canonicalReference": "@types/react!React.ComponentType:type" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "TLHandleProps", + "canonicalReference": "@tldraw/editor!TLHandleProps:type" + }, + { + "kind": "Content", + "text": "> | null;\n Spinner: " + }, + { + "kind": "Reference", + "text": "ComponentType", + "canonicalReference": "@types/react!React.ComponentType:type" + }, + { + "kind": "Content", + "text": " | null;\n SelectionForeground: " + }, + { + "kind": "Reference", + "text": "ComponentType", + "canonicalReference": "@types/react!React.ComponentType:type" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "TLSelectionForegroundProps", + "canonicalReference": "@tldraw/editor!TLSelectionForegroundProps:type" + }, + { + "kind": "Content", + "text": "> | null;\n SelectionBackground: " + }, + { + "kind": "Reference", + "text": "ComponentType", + "canonicalReference": "@types/react!React.ComponentType:type" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "TLSelectionBackgroundProps", + "canonicalReference": "@tldraw/editor!TLSelectionBackgroundProps:type" + }, + { + "kind": "Content", + "text": "> | null;\n HoveredShapeIndicator: " + }, + { + "kind": "Reference", + "text": "ComponentType", + "canonicalReference": "@types/react!React.ComponentType:type" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "TLHoveredShapeIndicatorProps", + "canonicalReference": "@tldraw/editor!TLHoveredShapeIndicatorProps:type" + }, + { + "kind": "Content", + "text": "> | null;\n OnTheCanvas: " + }, + { + "kind": "Reference", + "text": "ComponentType", + "canonicalReference": "@types/react!React.ComponentType:type" + }, + { + "kind": "Content", + "text": " | null;\n InFrontOfTheCanvas: " + }, + { + "kind": "Reference", + "text": "ComponentType", + "canonicalReference": "@types/react!React.ComponentType:type" + }, + { + "kind": "Content", + "text": " | null;\n LoadingScreen: " + }, + { + "kind": "Reference", + "text": "ComponentType", + "canonicalReference": "@types/react!React.ComponentType:type" + }, + { + "kind": "Content", + "text": " | null;\n} & " + }, + { + "kind": "Reference", + "text": "ErrorComponents", + "canonicalReference": "@tldraw/editor!~ErrorComponents:type" + }, + { + "kind": "Content", + "text": "> & " + }, + { + "kind": "Reference", + "text": "ErrorComponents", + "canonicalReference": "@tldraw/editor!~ErrorComponents:type" + }, + { + "kind": "Content", + "text": ";" + } + ], + "fileUrlPath": "packages/editor/src/lib/hooks/useEditorComponents.tsx", + "returnTypeTokenRange": { + "startIndex": 1, + "endIndex": 90 + }, + "releaseTag": "Public", + "overloadIndex": 1, + "parameters": [], + "name": "useEditorComponents" + }, { "kind": "Function", "canonicalReference": "@tldraw/editor!useIsCropping:function(1)", diff --git a/packages/editor/src/index.ts b/packages/editor/src/index.ts index 0f66a4ad7..341f412b3 100644 --- a/packages/editor/src/index.ts +++ b/packages/editor/src/index.ts @@ -34,7 +34,6 @@ export { type TldrawEditorBaseProps, type TldrawEditorProps, } from './lib/TldrawEditor' -export { Canvas } from './lib/components/Canvas' export { ErrorBoundary, OptionalErrorBoundary, @@ -42,63 +41,53 @@ export { } from './lib/components/ErrorBoundary' export { HTMLContainer, type HTMLContainerProps } from './lib/components/HTMLContainer' export { SVGContainer, type SVGContainerProps } from './lib/components/SVGContainer' -export { ShapeIndicator, type TLShapeIndicatorComponent } from './lib/components/ShapeIndicator' -export { - DefaultBackground, - type TLBackgroundComponent, -} from './lib/components/default-components/DefaultBackground' -export { - DefaultBrush, - type TLBrushComponent, -} from './lib/components/default-components/DefaultBrush' +export { DefaultBackground } from './lib/components/default-components/DefaultBackground' +export { DefaultBrush, type TLBrushProps } from './lib/components/default-components/DefaultBrush' +export { DefaultCanvas } from './lib/components/default-components/DefaultCanvas' export { DefaultCollaboratorHint, - type TLCollaboratorHintComponent, + type TLCollaboratorHintProps, } from './lib/components/default-components/DefaultCollaboratorHint' export { DefaultCursor, - type TLCursorComponent, + type TLCursorProps, } from './lib/components/default-components/DefaultCursor' export { DefaultErrorFallback } from './lib/components/default-components/DefaultErrorFallback' -export { DefaultGrid, type TLGridComponent } from './lib/components/default-components/DefaultGrid' +export { DefaultGrid, type TLGridProps } from './lib/components/default-components/DefaultGrid' export { DefaultHandle, - type TLHandleComponent, + type TLHandleProps, } from './lib/components/default-components/DefaultHandle' export { DefaultHandles, - type TLHandlesComponent, + type TLHandlesProps, } from './lib/components/default-components/DefaultHandles' export { DefaultHoveredShapeIndicator, - type TLHoveredShapeIndicatorComponent, + type TLHoveredShapeIndicatorProps, } from './lib/components/default-components/DefaultHoveredShapeIndicator' -export { type TLInFrontOfTheCanvas } from './lib/components/default-components/DefaultInFrontOfTheCanvas' -export { type TLOnTheCanvas } from './lib/components/default-components/DefaultOnTheCanvas' export { DefaultScribble, - type TLScribbleComponent, + type TLScribbleProps, } from './lib/components/default-components/DefaultScribble' export { DefaultSelectionBackground, - type TLSelectionBackgroundComponent, + type TLSelectionBackgroundProps, } from './lib/components/default-components/DefaultSelectionBackground' export { DefaultSelectionForeground, - type TLSelectionForegroundComponent, + type TLSelectionForegroundProps, } from './lib/components/default-components/DefaultSelectionForeground' +export { + DefaultShapeIndicator, + type TLShapeIndicatorProps, +} from './lib/components/default-components/DefaultShapeIndicator' export { DefaultSnapIndicator, - type TLSnapIndicatorComponent, + type TLSnapIndicatorProps, } from './lib/components/default-components/DefaultSnapIndictor' -export { - DefaultSpinner, - type TLSpinnerComponent, -} from './lib/components/default-components/DefaultSpinner' -export { - DefaultSvgDefs, - type TLSvgDefsComponent, -} from './lib/components/default-components/DefaultSvgDefs' +export { DefaultSpinner } from './lib/components/default-components/DefaultSpinner' +export { DefaultSvgDefs } from './lib/components/default-components/DefaultSvgDefs' export { TAB_ID, createSessionStateSnapshotSignal, @@ -256,6 +245,7 @@ export { type TLResizeHandle, type TLSelectionHandle } from './lib/editor/types/ export { ContainerProvider, useContainer } from './lib/hooks/useContainer' export { getCursor } from './lib/hooks/useCursor' export { EditorContext, useEditor } from './lib/hooks/useEditor' +export { useEditorComponents } from './lib/hooks/useEditorComponents' export type { TLEditorComponents } from './lib/hooks/useEditorComponents' export { useShallowArrayIdentity, useShallowObjectIdentity } from './lib/hooks/useIdentity' export { useIsCropping } from './lib/hooks/useIsCropping' diff --git a/packages/editor/src/lib/TldrawEditor.tsx b/packages/editor/src/lib/TldrawEditor.tsx index e174a6700..fff13cf47 100644 --- a/packages/editor/src/lib/TldrawEditor.tsx +++ b/packages/editor/src/lib/TldrawEditor.tsx @@ -11,7 +11,6 @@ import React, { } from 'react' import classNames from 'classnames' -import { Canvas } from './components/Canvas' import { OptionalErrorBoundary } from './components/ErrorBoundary' import { DefaultErrorFallback } from './components/default-components/DefaultErrorFallback' import { DefaultLoadingScreen } from './components/default-components/DefaultLoadingScreen' @@ -309,6 +308,8 @@ function TldrawEditorWithReadyStore({ () => editor?.getCrashingError() ?? null ) + const { Canvas } = useEditorComponents() + if (!editor) { return null } @@ -331,7 +332,7 @@ function TldrawEditorWithReadyStore({ ) : ( - {children} + {children ?? (Canvas ? : null)} )} @@ -356,7 +357,7 @@ function Layout({ useFocusEvents(autoFocus) useOnMount(onMount) - return children ?? + return <>{children} } function Crash({ crashingError }: { crashingError: unknown }): null { diff --git a/packages/editor/src/lib/components/LiveCollaborators.tsx b/packages/editor/src/lib/components/LiveCollaborators.tsx index 58ce4bf0b..097f99de8 100644 --- a/packages/editor/src/lib/components/LiveCollaborators.tsx +++ b/packages/editor/src/lib/components/LiveCollaborators.tsx @@ -144,7 +144,7 @@ const Collaborator = track(function Collaborator({ diff --git a/packages/editor/src/lib/components/default-components/DefaultBackground.tsx b/packages/editor/src/lib/components/default-components/DefaultBackground.tsx index eb4566e52..03ef8cb83 100644 --- a/packages/editor/src/lib/components/default-components/DefaultBackground.tsx +++ b/packages/editor/src/lib/components/default-components/DefaultBackground.tsx @@ -1,8 +1,3 @@ -import { ComponentType } from 'react' - -/** @public */ -export type TLBackgroundComponent = ComponentType - /** @public */ export function DefaultBackground() { return
diff --git a/packages/editor/src/lib/components/default-components/DefaultBrush.tsx b/packages/editor/src/lib/components/default-components/DefaultBrush.tsx index 99d434ef1..0ceba2d60 100644 --- a/packages/editor/src/lib/components/default-components/DefaultBrush.tsx +++ b/packages/editor/src/lib/components/default-components/DefaultBrush.tsx @@ -1,18 +1,18 @@ import { BoxModel } from '@tldraw/tlschema' -import { ComponentType, useRef } from 'react' +import { useRef } from 'react' import { useTransform } from '../../hooks/useTransform' import { toDomPrecision } from '../../primitives/utils' /** @public */ -export type TLBrushComponent = ComponentType<{ +export type TLBrushProps = { brush: BoxModel color?: string opacity?: number className?: string -}> +} /** @public */ -export const DefaultBrush: TLBrushComponent = ({ brush, color, opacity, className }) => { +export const DefaultBrush = ({ brush, color, opacity, className }: TLBrushProps) => { const rSvg = useRef(null) useTransform(rSvg, brush.x, brush.y) diff --git a/packages/editor/src/lib/components/Canvas.tsx b/packages/editor/src/lib/components/default-components/DefaultCanvas.tsx similarity index 90% rename from packages/editor/src/lib/components/Canvas.tsx rename to packages/editor/src/lib/components/default-components/DefaultCanvas.tsx index 193be090b..8646a366b 100644 --- a/packages/editor/src/lib/components/Canvas.tsx +++ b/packages/editor/src/lib/components/default-components/DefaultCanvas.tsx @@ -3,27 +3,29 @@ import { TLHandle, TLShapeId } from '@tldraw/tlschema' import { dedupe, modulate, objectMapValues } from '@tldraw/utils' import classNames from 'classnames' import React from 'react' -import { COARSE_HANDLE_RADIUS, HANDLE_RADIUS } from '../constants' -import { useCanvasEvents } from '../hooks/useCanvasEvents' -import { useCoarsePointer } from '../hooks/useCoarsePointer' -import { useDocumentEvents } from '../hooks/useDocumentEvents' -import { useEditor } from '../hooks/useEditor' -import { useEditorComponents } from '../hooks/useEditorComponents' -import { useFixSafariDoubleTapZoomPencilEvents } from '../hooks/useFixSafariDoubleTapZoomPencilEvents' -import { useGestureEvents } from '../hooks/useGestureEvents' -import { useHandleEvents } from '../hooks/useHandleEvents' -import { useScreenBounds } from '../hooks/useScreenBounds' -import { Mat } from '../primitives/Mat' -import { Vec } from '../primitives/Vec' -import { toDomPrecision } from '../primitives/utils' -import { debugFlags } from '../utils/debug-flags' -import { GeometryDebuggingView } from './GeometryDebuggingView' -import { LiveCollaborators } from './LiveCollaborators' -import { Shape } from './Shape' -import { ShapeIndicator } from './ShapeIndicator' +import { COARSE_HANDLE_RADIUS, HANDLE_RADIUS } from '../../constants' +import { useCanvasEvents } from '../../hooks/useCanvasEvents' +import { useCoarsePointer } from '../../hooks/useCoarsePointer' +import { useDocumentEvents } from '../../hooks/useDocumentEvents' +import { useEditor } from '../../hooks/useEditor' +import { useEditorComponents } from '../../hooks/useEditorComponents' +import { useFixSafariDoubleTapZoomPencilEvents } from '../../hooks/useFixSafariDoubleTapZoomPencilEvents' +import { useGestureEvents } from '../../hooks/useGestureEvents' +import { useHandleEvents } from '../../hooks/useHandleEvents' +import { useScreenBounds } from '../../hooks/useScreenBounds' +import { Mat } from '../../primitives/Mat' +import { Vec } from '../../primitives/Vec' +import { toDomPrecision } from '../../primitives/utils' +import { debugFlags } from '../../utils/debug-flags' +import { GeometryDebuggingView } from '../GeometryDebuggingView' +import { LiveCollaborators } from '../LiveCollaborators' +import { Shape } from '../Shape' /** @public */ -export function Canvas({ className }: { className?: string }) { +export type TLCanvasComponentProps = { className?: string } + +/** @public */ +export function DefaultCanvas({ className }: TLCanvasComponentProps) { const editor = useEditor() const { Background, SvgDefs } = useEditorComponents() @@ -378,12 +380,19 @@ function SelectedIdIndicators() { [editor] ) + const { ShapeIndicator } = useEditorComponents() + + if (!ShapeIndicator) return null if (!shouldDisplay) return null return ( <> {selectedShapeIds.map((id) => ( - + ))} ) @@ -413,15 +422,17 @@ const HoveredShapeIndicator = function HoveredShapeIndicator() { const HintedShapeIndicator = track(function HintedShapeIndicator() { const editor = useEditor() + const { ShapeIndicator } = useEditorComponents() const ids = dedupe(editor.getHintingShapeIds()) if (!ids.length) return null + if (!ShapeIndicator) return null return ( <> {ids.map((id) => ( - + ))} ) diff --git a/packages/editor/src/lib/components/default-components/DefaultCollaboratorHint.tsx b/packages/editor/src/lib/components/default-components/DefaultCollaboratorHint.tsx index 30256b132..025e9964b 100644 --- a/packages/editor/src/lib/components/default-components/DefaultCollaboratorHint.tsx +++ b/packages/editor/src/lib/components/default-components/DefaultCollaboratorHint.tsx @@ -1,30 +1,30 @@ import { VecModel } from '@tldraw/tlschema' import classNames from 'classnames' -import { ComponentType, useRef } from 'react' +import { useRef } from 'react' import { useTransform } from '../../hooks/useTransform' import { Box } from '../../primitives/Box' import { Vec } from '../../primitives/Vec' import { clamp } from '../../primitives/utils' /** @public */ -export type TLCollaboratorHintComponent = ComponentType<{ +export type TLCollaboratorHintProps = { className?: string point: VecModel viewport: Box zoom: number opacity?: number color: string -}> +} /** @public */ -export const DefaultCollaboratorHint: TLCollaboratorHintComponent = ({ +export function DefaultCollaboratorHint({ className, zoom, point, color, viewport, opacity = 1, -}) => { +}: TLCollaboratorHintProps) { const rSvg = useRef(null) useTransform( diff --git a/packages/editor/src/lib/components/default-components/DefaultCursor.tsx b/packages/editor/src/lib/components/default-components/DefaultCursor.tsx index d55f4f9ce..348e9984d 100644 --- a/packages/editor/src/lib/components/default-components/DefaultCursor.tsx +++ b/packages/editor/src/lib/components/default-components/DefaultCursor.tsx @@ -1,19 +1,27 @@ import { VecModel } from '@tldraw/tlschema' import classNames from 'classnames' -import { ComponentType, memo, useRef } from 'react' +import { memo, useRef } from 'react' import { useTransform } from '../../hooks/useTransform' /** @public */ -export type TLCursorComponent = ComponentType<{ +export type TLCursorProps = { className?: string point: VecModel | null zoom: number color?: string name: string | null chatMessage: string -}> +} -const _Cursor: TLCursorComponent = ({ className, zoom, point, color, name, chatMessage }) => { +/** @public */ +export const DefaultCursor = memo(function DefaultCursor({ + className, + zoom, + point, + color, + name, + chatMessage, +}: TLCursorProps) { const rCursor = useRef(null) useTransform(rCursor, point?.x, point?.y, 1 / zoom) @@ -44,7 +52,4 @@ const _Cursor: TLCursorComponent = ({ className, zoom, point, color, name, chatM )}
) -} - -/** @public */ -export const DefaultCursor = memo(_Cursor) +}) diff --git a/packages/editor/src/lib/components/default-components/DefaultErrorFallback.tsx b/packages/editor/src/lib/components/default-components/DefaultErrorFallback.tsx index 626220827..cad9f3a5d 100644 --- a/packages/editor/src/lib/components/default-components/DefaultErrorFallback.tsx +++ b/packages/editor/src/lib/components/default-components/DefaultErrorFallback.tsx @@ -3,9 +3,9 @@ import classNames from 'classnames' import { ComponentType, useEffect, useLayoutEffect, useRef, useState } from 'react' import { Editor } from '../../editor/Editor' import { EditorContext } from '../../hooks/useEditor' +import { useEditorComponents } from '../../hooks/useEditorComponents' import { hardResetEditor } from '../../utils/hardResetEditor' import { refreshPage } from '../../utils/refreshPage' -import { Canvas } from '../Canvas' import { ErrorBoundary } from '../ErrorBoundary' const BASE_ERROR_URL = 'https://github.com/tldraw/tldraw/issues/new' @@ -23,6 +23,8 @@ export const DefaultErrorFallback: TLErrorFallbackComponent = ({ error, editor } const [didCopy, setDidCopy] = useState(false) const [shouldShowResetConfirmation, setShouldShowResetConfirmation] = useState(false) + const { Canvas } = useEditorComponents() + const errorMessage = error instanceof Error ? error.message : String(error) const errorStack = error instanceof Error ? error.stack : null @@ -135,9 +137,7 @@ My browser: ${navigator.userAgent}` // a plain grey background. null}> -
- -
+
{Canvas ? : null}
)} diff --git a/packages/editor/src/lib/components/default-components/DefaultGrid.tsx b/packages/editor/src/lib/components/default-components/DefaultGrid.tsx index 7075e9456..55dcee21e 100644 --- a/packages/editor/src/lib/components/default-components/DefaultGrid.tsx +++ b/packages/editor/src/lib/components/default-components/DefaultGrid.tsx @@ -1,17 +1,16 @@ import { modulate } from '@tldraw/utils' -import { ComponentType } from 'react' import { GRID_STEPS } from '../../constants' /** @public */ -export type TLGridComponent = ComponentType<{ +export type TLGridProps = { x: number y: number z: number size: number -}> +} /** @public */ -export const DefaultGrid: TLGridComponent = ({ x, y, z, size }) => { +export function DefaultGrid({ x, y, z, size }: TLGridProps) { return ( diff --git a/packages/editor/src/lib/components/default-components/DefaultHandle.tsx b/packages/editor/src/lib/components/default-components/DefaultHandle.tsx index d24500dd2..a5f924024 100644 --- a/packages/editor/src/lib/components/default-components/DefaultHandle.tsx +++ b/packages/editor/src/lib/components/default-components/DefaultHandle.tsx @@ -1,19 +1,18 @@ import { TLHandle, TLShapeId } from '@tldraw/tlschema' import classNames from 'classnames' -import { ComponentType } from 'react' import { COARSE_HANDLE_RADIUS, HANDLE_RADIUS } from '../../constants' /** @public */ -export type TLHandleComponent = ComponentType<{ +export type TLHandleProps = { shapeId: TLShapeId handle: TLHandle zoom: number isCoarse: boolean className?: string -}> +} /** @public */ -export const DefaultHandle: TLHandleComponent = ({ handle, isCoarse, className, zoom }) => { +export function DefaultHandle({ handle, isCoarse, className, zoom }: TLHandleProps) { const bgRadius = (isCoarse ? COARSE_HANDLE_RADIUS : HANDLE_RADIUS) / zoom const fgRadius = (handle.type === 'create' && isCoarse ? 3 : 4) / zoom diff --git a/packages/editor/src/lib/components/default-components/DefaultHandles.tsx b/packages/editor/src/lib/components/default-components/DefaultHandles.tsx index 494c15051..fe92b286f 100644 --- a/packages/editor/src/lib/components/default-components/DefaultHandles.tsx +++ b/packages/editor/src/lib/components/default-components/DefaultHandles.tsx @@ -1,12 +1,9 @@ -import { ComponentType } from 'react' - /** @public */ -export type TLHandlesComponent = ComponentType<{ - className?: string +export type TLHandlesProps = { children: any -}> +} /** @public */ -export const DefaultHandles: TLHandlesComponent = ({ children }) => { +export const DefaultHandles = ({ children }: TLHandlesProps) => { return {children} } diff --git a/packages/editor/src/lib/components/default-components/DefaultHoveredShapeIndicator.tsx b/packages/editor/src/lib/components/default-components/DefaultHoveredShapeIndicator.tsx index 0717fbff7..c30359965 100644 --- a/packages/editor/src/lib/components/default-components/DefaultHoveredShapeIndicator.tsx +++ b/packages/editor/src/lib/components/default-components/DefaultHoveredShapeIndicator.tsx @@ -1,13 +1,14 @@ import { TLShapeId } from '@tldraw/tlschema' -import { ComponentType } from 'react' -import { ShapeIndicator } from '../ShapeIndicator' +import { useEditorComponents } from '../../hooks/useEditorComponents' /** @public */ -export type TLHoveredShapeIndicatorComponent = ComponentType<{ +export type TLHoveredShapeIndicatorProps = { shapeId: TLShapeId -}> +} /** @public */ -export const DefaultHoveredShapeIndicator: TLHoveredShapeIndicatorComponent = ({ shapeId }) => { - return +export function DefaultHoveredShapeIndicator({ shapeId }: TLHoveredShapeIndicatorProps) { + const { ShapeIndicator } = useEditorComponents() + if (!ShapeIndicator) return null + return } diff --git a/packages/editor/src/lib/components/default-components/DefaultInFrontOfTheCanvas.tsx b/packages/editor/src/lib/components/default-components/DefaultInFrontOfTheCanvas.tsx deleted file mode 100644 index 0ce033ddd..000000000 --- a/packages/editor/src/lib/components/default-components/DefaultInFrontOfTheCanvas.tsx +++ /dev/null @@ -1,4 +0,0 @@ -import { ComponentType } from 'react' - -/** @public */ -export type TLInFrontOfTheCanvas = ComponentType diff --git a/packages/editor/src/lib/components/default-components/DefaultLoadingScreen.tsx b/packages/editor/src/lib/components/default-components/DefaultLoadingScreen.tsx index 141a67ee9..6e4ffb8ef 100644 --- a/packages/editor/src/lib/components/default-components/DefaultLoadingScreen.tsx +++ b/packages/editor/src/lib/components/default-components/DefaultLoadingScreen.tsx @@ -1,10 +1,6 @@ -import { ComponentType } from 'react' import { LoadingScreen } from '../../TldrawEditor' /** @public */ -export type TLLoadingScreenComponent = ComponentType - -/** @public */ -export const DefaultLoadingScreen: TLLoadingScreenComponent = () => { +export const DefaultLoadingScreen = () => { return Connecting... } diff --git a/packages/editor/src/lib/components/default-components/DefaultOnTheCanvas.tsx b/packages/editor/src/lib/components/default-components/DefaultOnTheCanvas.tsx deleted file mode 100644 index f6ad07e14..000000000 --- a/packages/editor/src/lib/components/default-components/DefaultOnTheCanvas.tsx +++ /dev/null @@ -1,4 +0,0 @@ -import { ComponentType } from 'react' - -/** @public */ -export type TLOnTheCanvas = ComponentType diff --git a/packages/editor/src/lib/components/default-components/DefaultScribble.tsx b/packages/editor/src/lib/components/default-components/DefaultScribble.tsx index 67c1c70a5..a34d0af4c 100644 --- a/packages/editor/src/lib/components/default-components/DefaultScribble.tsx +++ b/packages/editor/src/lib/components/default-components/DefaultScribble.tsx @@ -1,25 +1,18 @@ import { TLScribble } from '@tldraw/tlschema' import classNames from 'classnames' -import { ComponentType } from 'react' import { getSvgPathFromPoints } from '../../utils/getSvgPathFromPoints' /** @public */ -export type TLScribbleComponent = ComponentType<{ +export type TLScribbleProps = { scribble: TLScribble zoom: number color?: string opacity?: number className?: string -}> +} /** @public */ -export const DefaultScribble: TLScribbleComponent = ({ - scribble, - zoom, - color, - opacity, - className, -}) => { +export function DefaultScribble({ scribble, zoom, color, opacity, className }: TLScribbleProps) { if (!scribble.points.length) return null return ( diff --git a/packages/editor/src/lib/components/default-components/DefaultSelectionBackground.tsx b/packages/editor/src/lib/components/default-components/DefaultSelectionBackground.tsx index f3a20de9e..8a1185616 100644 --- a/packages/editor/src/lib/components/default-components/DefaultSelectionBackground.tsx +++ b/packages/editor/src/lib/components/default-components/DefaultSelectionBackground.tsx @@ -4,16 +4,13 @@ import { Box } from '../../primitives/Box' import { toDomPrecision } from '../../primitives/utils' /** @public */ -export type TLSelectionBackgroundComponent = React.ComponentType<{ +export type TLSelectionBackgroundProps = { bounds: Box rotation: number -}> +} /** @public */ -export const DefaultSelectionBackground: TLSelectionBackgroundComponent = ({ - bounds, - rotation, -}) => { +export function DefaultSelectionBackground({ bounds, rotation }: TLSelectionBackgroundProps) { const rDiv = React.useRef(null) useTransform(rDiv, bounds.x, bounds.y, 1, rotation) diff --git a/packages/editor/src/lib/components/default-components/DefaultSelectionForeground.tsx b/packages/editor/src/lib/components/default-components/DefaultSelectionForeground.tsx index 059476f29..00fe565fd 100644 --- a/packages/editor/src/lib/components/default-components/DefaultSelectionForeground.tsx +++ b/packages/editor/src/lib/components/default-components/DefaultSelectionForeground.tsx @@ -1,22 +1,19 @@ import { useValue } from '@tldraw/state' import classNames from 'classnames' -import { ComponentType, useRef } from 'react' +import { useRef } from 'react' import { useEditor } from '../../hooks/useEditor' import { useTransform } from '../../hooks/useTransform' import { Box } from '../../primitives/Box' import { toDomPrecision } from '../../primitives/utils' /** @public */ -export type TLSelectionForegroundComponent = ComponentType<{ +export type TLSelectionForegroundProps = { bounds: Box rotation: number -}> +} /** @public */ -export const DefaultSelectionForeground: TLSelectionForegroundComponent = ({ - bounds, - rotation, -}) => { +export function DefaultSelectionForeground({ bounds, rotation }: TLSelectionForegroundProps) { const editor = useEditor() const rSvg = useRef(null) diff --git a/packages/editor/src/lib/components/ShapeIndicator.tsx b/packages/editor/src/lib/components/default-components/DefaultShapeIndicator.tsx similarity index 74% rename from packages/editor/src/lib/components/ShapeIndicator.tsx rename to packages/editor/src/lib/components/default-components/DefaultShapeIndicator.tsx index 195b2c88d..b59560aa2 100644 --- a/packages/editor/src/lib/components/ShapeIndicator.tsx +++ b/packages/editor/src/lib/components/default-components/DefaultShapeIndicator.tsx @@ -1,12 +1,12 @@ import { useStateTracking, useValue } from '@tldraw/state' import { TLShape, TLShapeId } from '@tldraw/tlschema' import classNames from 'classnames' -import * as React from 'react' -import type { Editor } from '../editor/Editor' -import { ShapeUtil } from '../editor/shapes/ShapeUtil' -import { useEditor } from '../hooks/useEditor' -import { useEditorComponents } from '../hooks/useEditorComponents' -import { OptionalErrorBoundary } from './ErrorBoundary' +import { memo } from 'react' +import type { Editor } from '../../editor/Editor' +import { ShapeUtil } from '../../editor/shapes/ShapeUtil' +import { useEditor } from '../../hooks/useEditor' +import { useEditorComponents } from '../../hooks/useEditorComponents' +import { OptionalErrorBoundary } from '../ErrorBoundary' class ShapeWithPropsEquality { constructor(public shape: TLShape | undefined) {} @@ -51,24 +51,30 @@ const InnerIndicator = ({ editor, id }: { editor: Editor; id: TLShapeId }) => { } /** @public */ -export type TLShapeIndicatorComponent = React.ComponentType<{ - id: TLShapeId +export type TLShapeIndicatorProps = { + shapeId: TLShapeId color?: string | undefined opacity?: number className?: string -}> +} -const _ShapeIndicator: TLShapeIndicatorComponent = ({ id, className, color, opacity }) => { +/** @public */ +export const DefaultShapeIndicator = memo(function DefaultShapeIndicator({ + shapeId, + className, + color, + opacity, +}: TLShapeIndicatorProps) { const editor = useEditor() const transform = useValue( 'transform', () => { - const pageTransform = editor.getShapePageTransform(id) + const pageTransform = editor.getShapePageTransform(shapeId) if (!pageTransform) return '' return pageTransform.toCssString() }, - [editor, id] + [editor, shapeId] ) return ( @@ -79,11 +85,8 @@ const _ShapeIndicator: TLShapeIndicatorComponent = ({ id, className, color, opac stroke={color ?? 'var(--color-selected)'} opacity={opacity} > - + ) -} - -/** @public */ -export const ShapeIndicator = React.memo(_ShapeIndicator) +}) diff --git a/packages/editor/src/lib/components/default-components/DefaultSnapIndictor.tsx b/packages/editor/src/lib/components/default-components/DefaultSnapIndictor.tsx index e9f647920..c5940a2c0 100644 --- a/packages/editor/src/lib/components/default-components/DefaultSnapIndictor.tsx +++ b/packages/editor/src/lib/components/default-components/DefaultSnapIndictor.tsx @@ -154,14 +154,14 @@ function GapsSnapIndicator({ gaps, direction, zoom }: { zoom: number } & GapsSna } /** @public */ -export type TLSnapIndicatorComponent = React.ComponentType<{ +export type TLSnapIndicatorProps = { className?: string line: SnapIndicator zoom: number -}> +} /** @public */ -export const DefaultSnapIndicator: TLSnapIndicatorComponent = ({ className, line, zoom }) => { +export function DefaultSnapIndicator({ className, line, zoom }: TLSnapIndicatorProps) { return ( {line.type === 'points' ? ( diff --git a/packages/editor/src/lib/components/default-components/DefaultSpinner.tsx b/packages/editor/src/lib/components/default-components/DefaultSpinner.tsx index 56f4c581c..3d769f18e 100644 --- a/packages/editor/src/lib/components/default-components/DefaultSpinner.tsx +++ b/packages/editor/src/lib/components/default-components/DefaultSpinner.tsx @@ -1,10 +1,5 @@ -import { ComponentType } from 'react' - /** @public */ -export type TLSpinnerComponent = ComponentType - -/** @public */ -export const DefaultSpinner: TLSpinnerComponent = () => { +export function DefaultSpinner() { return ( diff --git a/packages/editor/src/lib/components/default-components/DefaultSvgDefs.tsx b/packages/editor/src/lib/components/default-components/DefaultSvgDefs.tsx index 8cf7ed6eb..a22aad760 100644 --- a/packages/editor/src/lib/components/default-components/DefaultSvgDefs.tsx +++ b/packages/editor/src/lib/components/default-components/DefaultSvgDefs.tsx @@ -1,6 +1,3 @@ -/** @public */ -export type TLSvgDefsComponent = React.ComponentType - /** @public */ export const DefaultSvgDefs = () => { return null diff --git a/packages/editor/src/lib/editor/Editor.ts b/packages/editor/src/lib/editor/Editor.ts index 15ad67f13..0681fd59c 100644 --- a/packages/editor/src/lib/editor/Editor.ts +++ b/packages/editor/src/lib/editor/Editor.ts @@ -53,6 +53,7 @@ import { getIndicesBetween, getOwnProperty, hasOwnProperty, + objectMapValues, sortById, sortByIndex, structuredClone, @@ -6723,23 +6724,27 @@ export class Editor extends EventEmitter { let remaining = duration let t: number - type FromTo = { prop: string; from: number; to: number } - type ShapeAnimation = { partial: TLShapePartial; values: FromTo[] } + type ShapeAnimation = { + partial: TLShapePartial + values: { prop: string; from: number; to: number }[] + } const animations: ShapeAnimation[] = [] - partials.forEach((partial) => { - if (!partial) return + let partial: TLShapePartial | null | undefined, result: ShapeAnimation + for (let i = 0, n = partials.length; i < n; i++) { + partial = partials[i] + if (!partial) continue - const result: ShapeAnimation = { + result = { partial, values: [], } const shape = this.getShape(partial.id)! + if (!shape) continue - if (!shape) return - + // We only support animations for certain props for (const key of ['x', 'y', 'rotation'] as const) { if (partial[key] !== undefined && shape[key] !== partial[key]) { result.values.push({ prop: key, from: shape[key], to: partial[key] as number }) @@ -6748,7 +6753,7 @@ export class Editor extends EventEmitter { animations.push(result) this.animatingShapes.set(shape.id, animationId) - }) + } let value: ShapeAnimation @@ -6773,28 +6778,27 @@ export class Editor extends EventEmitter { const { animatingShapes } = this - try { - const tPartials: TLShapePartial[] = [] + const updates: TLShapePartial[] = [] - for (let i = 0; i < animations.length; i++) { - value = animations[i] + let animationIdForShape: string | undefined + for (let i = 0, n = animations.length; i < n; i++) { + value = animations[i] + // Is the animation for this shape still active? + animationIdForShape = animatingShapes.get(value.partial.id) + if (animationIdForShape !== animationId) continue - if (animatingShapes.get(value.partial.id) === animationId) { - tPartials.push({ - id: value.partial.id, - type: value.partial.type, - ...value.values.reduce((acc, { prop, from, to }) => { - acc[prop] = from + (to - from) * t - return acc - }, {} as any), - }) - } - } - - this._updateShapes(tPartials, { squashing: true }) - } catch (e) { - // noop + // Create the update + updates.push({ + id: value.partial.id, + type: value.partial.type, + ...value.values.reduce((acc, { prop, from, to }) => { + acc[prop] = from + (to - from) * t + return acc + }, {} as any), + }) } + + this._updateShapes(updates, { squashing: true }) } this.addListener('tick', handleTick) @@ -6968,20 +6972,24 @@ export class Editor extends EventEmitter { partials: (TLShapePartial | null | undefined)[], historyOptions?: TLCommandHistoryOptions ) { - let compactedPartials = compact(partials) - if (this.animatingShapes.size > 0) { - compactedPartials.forEach((p) => this.animatingShapes.delete(p.id)) + const compactedPartials: TLShapePartial[] = Array(partials.length) + + for (let i = 0, n = partials.length; i < n; i++) { + const partial = partials[i] + if (!partial) continue + // Get the current shape referenced by the partial + const shape = this.getShape(partial.id) + if (!shape) continue + + // If the shape is locked and we're not setting isLocked to true, continue + if (this.isShapeOrAncestorLocked(shape) && !Object.hasOwn(partial, 'isLocked')) continue + + // Remove any animating shapes from the list of partials + this.animatingShapes.delete(partial.id) + + compactedPartials.push(partial) } - compactedPartials = compactedPartials.filter((p) => { - const shape = this.getShape(p.id) - if (!shape) return false - - // Only allow changes to unlocked shapes or changes to the isLocked property (otherwise we cannot unlock a shape) - if (this.isShapeOrAncestorLocked(shape) && !Object.hasOwn(p, 'isLocked')) return false - return true - }) - this._updateShapes(compactedPartials, historyOptions) return this } @@ -6995,45 +7003,49 @@ export class Editor extends EventEmitter { ) => { if (this.getInstanceState().isReadonly) return null - const partials = compact(_partials) + const snapshots: Record = {} + const updates: Record = {} - const snapshots = Object.fromEntries( - compact(partials.map(({ id }) => this.getShape(id))).map((shape) => { - return [shape.id, shape] - }) - ) + let shape: TLShape | undefined + let updated: TLShape - if (partials.length <= 0) return null + for (let i = 0, n = _partials.length; i < n; i++) { + const partial = _partials[i] + // Skip nullish partials (sometimes created by map fns returning undefined) + if (!partial) continue - const updated = compact( - partials.map((partial) => { - const prev = snapshots[partial.id] - if (!prev) return null - return applyPartialToShape(prev, partial) - }) - ) + // Get the current shape referenced by the partial + // If there is no current shape, we'll skip this update + shape = this.getShape(partial.id) + if (!shape) continue - const updates = Object.fromEntries(updated.map((shape) => [shape.id, shape])) + // Get the updated version of the shape + // If the update had no effect, we'll skip this update + updated = applyPartialToShape(shape, partial) + if (updated === shape) continue + + snapshots[shape.id] = shape + updates[shape.id] = updated + } return { data: { snapshots, updates }, ...historyOptions } }, { do: ({ updates }) => { - // Iterate through array; if any shape has an onUpdate handler, call it + // Iterate through array; if any shape has an onBeforeUpdate handler, call it // and, if the handler returns a new shape, replace the old shape with // the new one. This is used for example when repositioning a text shape // based on its new text content. - const result = Object.values(updates) - for (let i = 0; i < result.length; i++) { - const shape = result[i] - const current = this.store.get(shape.id) - if (!current) continue - const next = this.getShapeUtil(shape).onBeforeUpdate?.(current, shape) - if (next) { - result[i] = next - } - } - this.store.put(result) + this.store.put( + objectMapValues(updates).map((shape) => { + const current = this.store.get(shape.id) + if (current) { + const next = this.getShapeUtil(shape).onBeforeUpdate?.(current, shape) + if (next) return next + } + return shape + }) + ) }, undo: ({ snapshots }) => { this.store.put(Object.values(snapshots)) @@ -8954,44 +8966,34 @@ function alertMaxShapes(editor: Editor, pageId = editor.getCurrentPageId()) { function applyPartialToShape(prev: T, partial?: TLShapePartial): T { if (!partial) return prev let next = null as null | T - for (const [k, v] of Object.entries(partial)) { + const entries = Object.entries(partial) + for (let i = 0, n = entries.length; i < n; i++) { + const [k, v] = entries[i] if (v === undefined) continue - switch (k) { - case 'id': - case 'type': - continue - default: { - if (v !== (prev as any)[k]) { - if (!next) { - next = { ...prev } - } - if (k === 'props') { - // props property - const nextProps = { ...prev.props } as JsonObject - for (const [propKey, propValue] of Object.entries(v as object)) { - if (propValue !== undefined) { - nextProps[propKey] = propValue - } - } - next!.props = nextProps - } else if (k === 'meta') { - // meta property - const nextMeta = { ...prev.meta } as JsonObject - for (const [metaKey, metaValue] of Object.entries(v as object)) { - if (metaValue !== undefined) { - nextMeta[metaKey] = metaValue - } - } - next!.meta = nextMeta - } else { - // base property - ;(next as any)[k] = v - } + // Is the key a special key? We don't update those + if (k === 'id' || k === 'type' || k === 'typeName') continue + + // Is the value the same as it was before? + if (v === (prev as any)[k]) continue + + // There's a new value, so create the new shape if we haven't already (should we be cloning this?) + if (!next) next = { ...prev } + + // for props / meta properties, we support updates with partials of this object + if (k === 'props' || k === 'meta') { + next[k] = { ...prev[k] } as JsonObject + for (const [nextKey, nextValue] of Object.entries(v as object)) { + if (nextValue !== undefined) { + ;(next[k] as JsonObject)[nextKey] = nextValue } } + continue } - } - return next ?? prev + // base property + ;(next as any)[k] = v + } + if (!next) return prev + return next } diff --git a/packages/editor/src/lib/hooks/useEditorComponents.tsx b/packages/editor/src/lib/hooks/useEditorComponents.tsx index b15e18724..57ff72110 100644 --- a/packages/editor/src/lib/hooks/useEditorComponents.tsx +++ b/packages/editor/src/lib/hooks/useEditorComponents.tsx @@ -1,80 +1,80 @@ -import { createContext, useContext, useMemo } from 'react' -import { ShapeIndicator, TLShapeIndicatorComponent } from '../components/ShapeIndicator' +import { ComponentType, createContext, useContext, useMemo } from 'react' +import { DefaultBackground } from '../components/default-components/DefaultBackground' +import { DefaultBrush, TLBrushProps } from '../components/default-components/DefaultBrush' import { - DefaultBackground, - TLBackgroundComponent, -} from '../components/default-components/DefaultBackground' -import { DefaultBrush, TLBrushComponent } from '../components/default-components/DefaultBrush' + DefaultCanvas, + TLCanvasComponentProps, +} from '../components/default-components/DefaultCanvas' import { DefaultCollaboratorHint, - TLCollaboratorHintComponent, + TLCollaboratorHintProps, } from '../components/default-components/DefaultCollaboratorHint' -import { DefaultCursor, TLCursorComponent } from '../components/default-components/DefaultCursor' +import { DefaultCursor, TLCursorProps } from '../components/default-components/DefaultCursor' import { DefaultErrorFallback, TLErrorFallbackComponent, } from '../components/default-components/DefaultErrorFallback' -import { DefaultGrid, TLGridComponent } from '../components/default-components/DefaultGrid' -import { DefaultHandle, TLHandleComponent } from '../components/default-components/DefaultHandle' -import { DefaultHandles, TLHandlesComponent } from '../components/default-components/DefaultHandles' +import { DefaultGrid, TLGridProps } from '../components/default-components/DefaultGrid' +import { DefaultHandle, TLHandleProps } from '../components/default-components/DefaultHandle' +import { DefaultHandles, TLHandlesProps } from '../components/default-components/DefaultHandles' import { DefaultHoveredShapeIndicator, - TLHoveredShapeIndicatorComponent, + TLHoveredShapeIndicatorProps, } from '../components/default-components/DefaultHoveredShapeIndicator' -import { TLInFrontOfTheCanvas } from '../components/default-components/DefaultInFrontOfTheCanvas' -import { TLLoadingScreenComponent } from '../components/default-components/DefaultLoadingScreen' -import { TLOnTheCanvas } from '../components/default-components/DefaultOnTheCanvas' -import { - DefaultScribble, - TLScribbleComponent, -} from '../components/default-components/DefaultScribble' +import { DefaultScribble, TLScribbleProps } from '../components/default-components/DefaultScribble' import { DefaultSelectionBackground, - TLSelectionBackgroundComponent, + TLSelectionBackgroundProps, } from '../components/default-components/DefaultSelectionBackground' import { DefaultSelectionForeground, - TLSelectionForegroundComponent, + TLSelectionForegroundProps, } from '../components/default-components/DefaultSelectionForeground' import { DefaultShapeErrorFallback, TLShapeErrorFallbackComponent, } from '../components/default-components/DefaultShapeErrorFallback' +import { + DefaultShapeIndicator, + TLShapeIndicatorProps, +} from '../components/default-components/DefaultShapeIndicator' import { DefaultShapeIndicatorErrorFallback, TLShapeIndicatorErrorFallbackComponent, } from '../components/default-components/DefaultShapeIndicatorErrorFallback' import { DefaultSnapIndicator, - TLSnapIndicatorComponent, + TLSnapIndicatorProps, } from '../components/default-components/DefaultSnapIndictor' -import { DefaultSpinner, TLSpinnerComponent } from '../components/default-components/DefaultSpinner' -import { DefaultSvgDefs, TLSvgDefsComponent } from '../components/default-components/DefaultSvgDefs' +import { DefaultSpinner } from '../components/default-components/DefaultSpinner' +import { DefaultSvgDefs } from '../components/default-components/DefaultSvgDefs' import { useShallowObjectIdentity } from './useIdentity' export interface BaseEditorComponents { - Background: TLBackgroundComponent - SvgDefs: TLSvgDefsComponent - Brush: TLBrushComponent - ZoomBrush: TLBrushComponent - Cursor: TLCursorComponent - CollaboratorBrush: TLBrushComponent - CollaboratorCursor: TLCursorComponent - CollaboratorHint: TLCollaboratorHintComponent - CollaboratorShapeIndicator: TLShapeIndicatorComponent - Grid: TLGridComponent - Scribble: TLScribbleComponent - CollaboratorScribble: TLScribbleComponent - SnapIndicator: TLSnapIndicatorComponent - Handles: TLHandlesComponent - Handle: TLHandleComponent - Spinner: TLSpinnerComponent - SelectionForeground: TLSelectionForegroundComponent - SelectionBackground: TLSelectionBackgroundComponent - HoveredShapeIndicator: TLHoveredShapeIndicatorComponent - OnTheCanvas: TLOnTheCanvas - InFrontOfTheCanvas: TLInFrontOfTheCanvas - LoadingScreen: TLLoadingScreenComponent + Background: ComponentType + SvgDefs: ComponentType + Brush: ComponentType + ZoomBrush: ComponentType + ShapeIndicator: ComponentType + Cursor: ComponentType + Canvas: ComponentType + CollaboratorBrush: ComponentType + CollaboratorCursor: ComponentType + CollaboratorHint: ComponentType + CollaboratorShapeIndicator: ComponentType + Grid: ComponentType + Scribble: ComponentType + CollaboratorScribble: ComponentType + SnapIndicator: ComponentType + Handles: ComponentType + Handle: ComponentType + Spinner: ComponentType + SelectionForeground: ComponentType + SelectionBackground: ComponentType + HoveredShapeIndicator: ComponentType + OnTheCanvas: ComponentType + InFrontOfTheCanvas: ComponentType + LoadingScreen: ComponentType } // These will always have defaults @@ -116,7 +116,7 @@ export function EditorComponentsProvider({ Cursor: DefaultCursor, CollaboratorCursor: DefaultCursor, CollaboratorHint: DefaultCollaboratorHint, - CollaboratorShapeIndicator: ShapeIndicator, + CollaboratorShapeIndicator: DefaultShapeIndicator, Grid: DefaultGrid, Scribble: DefaultScribble, SnapIndicator: DefaultSnapIndicator, @@ -130,8 +130,10 @@ export function EditorComponentsProvider({ SelectionBackground: DefaultSelectionBackground, SelectionForeground: DefaultSelectionForeground, HoveredShapeIndicator: DefaultHoveredShapeIndicator, + ShapeIndicator: DefaultShapeIndicator, OnTheCanvas: null, InFrontOfTheCanvas: null, + Canvas: DefaultCanvas, ..._overrides, }), [_overrides] diff --git a/packages/tldraw/api-report.md b/packages/tldraw/api-report.md index 88ca5eefd..447f8783a 100644 --- a/packages/tldraw/api-report.md +++ b/packages/tldraw/api-report.md @@ -74,9 +74,9 @@ import { TLExitEventHandler } from '@tldraw/editor'; import { TLFrameShape } from '@tldraw/editor'; import { TLGeoShape } from '@tldraw/editor'; import { TLHandle } from '@tldraw/editor'; -import { TLHandlesComponent } from '@tldraw/editor'; +import { TLHandlesProps } from '@tldraw/editor'; import { TLHighlightShape } from '@tldraw/editor'; -import { TLHoveredShapeIndicatorComponent } from '@tldraw/editor'; +import { TLHoveredShapeIndicatorProps } from '@tldraw/editor'; import { TLImageShape } from '@tldraw/editor'; import { TLInterruptEvent } from '@tldraw/editor'; import { TLKeyboardEvent } from '@tldraw/editor'; @@ -100,9 +100,9 @@ import { TLPointerEventName } from '@tldraw/editor'; import { TLRecord } from '@tldraw/editor'; import { TLRotationSnapshot } from '@tldraw/editor'; import { TLSchema } from '@tldraw/editor'; -import { TLScribbleComponent } from '@tldraw/editor'; -import { TLSelectionBackgroundComponent } from '@tldraw/editor'; -import { TLSelectionForegroundComponent } from '@tldraw/editor'; +import { TLScribbleProps } from '@tldraw/editor'; +import { TLSelectionBackgroundProps } from '@tldraw/editor'; +import { TLSelectionForegroundProps } from '@tldraw/editor'; import { TLSelectionHandle } from '@tldraw/editor'; import { TLShape } from '@tldraw/editor'; import { TLShapeId } from '@tldraw/editor'; @@ -347,7 +347,7 @@ export const defaultShapeUtils: TLAnyShapeUtilConstructor[]; export const DefaultStylePanel: NamedExoticComponent; // @public (undocumented) -export function DefaultStylePanelContent({ relevantStyles }: TLUiStylePanelContentProps): JSX_2.Element | null; +export function DefaultStylePanelContent({ styles }: TLUiStylePanelContentProps): JSX_2.Element | null; // @public (undocumented) export const DefaultToolbar: React_2.NamedExoticComponent; @@ -1173,21 +1173,6 @@ export function Tldraw(props: TldrawProps): JSX_2.Element; // @public (undocumented) export const TLDRAW_FILE_EXTENSION: ".tldr"; -// @public (undocumented) -export function TldrawCropHandles({ size, width, height, hideAlternateHandles, }: TldrawCropHandlesProps): JSX_2.Element; - -// @public (undocumented) -export interface TldrawCropHandlesProps { - // (undocumented) - height: number; - // (undocumented) - hideAlternateHandles: boolean; - // (undocumented) - size: number; - // (undocumented) - width: number; -} - // @public (undocumented) export interface TldrawFile { // (undocumented) @@ -1199,10 +1184,10 @@ export interface TldrawFile { } // @public (undocumented) -export const TldrawHandles: TLHandlesComponent; +export function TldrawHandles({ children }: TLHandlesProps): JSX_2.Element | null; // @public (undocumented) -export const TldrawHoveredShapeIndicator: TLHoveredShapeIndicatorComponent; +export function TldrawHoveredShapeIndicator({ shapeId }: TLHoveredShapeIndicatorProps): JSX_2.Element | null; // @public export const TldrawImage: NamedExoticComponent< { @@ -1240,13 +1225,13 @@ export type TldrawProps = (Omit & Omit JSX_2.Element | null; // @public (undocumented) -export const TldrawSelectionForeground: TLSelectionForegroundComponent; +export const TldrawSelectionForeground: MemoExoticComponent<({ bounds, rotation, }: TLSelectionForegroundProps) => JSX_2.Element | null>; // @public (undocumented) export const TldrawUi: React_2.NamedExoticComponent; @@ -1313,7 +1298,7 @@ export function TldrawUiDropdownMenuCheckboxItem({ children, onSelect, ...rest } export function TldrawUiDropdownMenuContent({ side, align, sideOffset, alignOffset, children, }: TLUiDropdownMenuContentProps): JSX_2.Element; // @public (undocumented) -export function TldrawUiDropdownMenuGroup({ children, size, }: TLUiDropdownMenuGroupProps): JSX_2.Element; +export function TldrawUiDropdownMenuGroup({ children }: TLUiDropdownMenuGroupProps): JSX_2.Element; // @public (undocumented) export function TldrawUiDropdownMenuIndicator(): JSX_2.Element; @@ -1349,7 +1334,7 @@ export function TldrawUiMenuCheckboxItem({ disabled, spinner, readonlyOk, id, kbd, label, icon, onSelect, noClose, }: TLUiMenuItemProps): JSX_2.Element | null; @@ -1459,8 +1444,6 @@ export type TLUiComponentsProviderProps = { // @public (undocumented) export interface TLUiContextMenuProps { - // (undocumented) - canvas: any; // (undocumented) children?: any; } @@ -1549,7 +1532,6 @@ export type TLUiDropdownMenuContentProps = { // @public (undocumented) export type TLUiDropdownMenuGroupProps = { children: any; - size?: 'medium' | 'small' | 'tiny' | 'wide'; }; // @public (undocumented) @@ -1866,7 +1848,6 @@ export type TLUiMenuGroupProps = { label?: { [key: string]: TranslationKey; } | TranslationKey; - small?: boolean; children?: any; }; @@ -1894,7 +1875,7 @@ export type TLUiMenuSubmenuProps = { } | Translation; disabled?: boolean; children: any; - size?: 'large' | 'medium' | 'small' | 'tiny'; + size?: 'medium' | 'small' | 'tiny' | 'wide'; }; // @public (undocumented) @@ -1951,7 +1932,7 @@ export interface TLUiSliderProps { // @public (undocumented) export type TLUiStylePanelContentProps = { - relevantStyles: ReturnType; + styles: ReturnType; }; // @public (undocumented) @@ -1960,11 +1941,6 @@ export interface TLUiStylePanelProps { children?: any; // (undocumented) isMobile?: boolean; - // (undocumented) - relevantStyles: { - styles: ReadonlySharedStyleMap; - opacity: SharedStyle; - } | null; } // @public (undocumented) @@ -2136,6 +2112,9 @@ export function useNativeClipboardEvents(): void; // @public (undocumented) export function useReadonly(): boolean; +// @public (undocumented) +export function useRelevantStyles(stylesToCheck?: readonly (EnumStyleProp<"black" | "blue" | "green" | "grey" | "light-blue" | "light-green" | "light-red" | "light-violet" | "orange" | "red" | "violet" | "yellow"> | EnumStyleProp<"dashed" | "dotted" | "draw" | "solid"> | EnumStyleProp<"l" | "m" | "s" | "xl"> | EnumStyleProp<"none" | "pattern" | "semi" | "solid">)[]): null | ReadonlySharedStyleMap; + // @public (undocumented) export function useTldrawUiComponents(): Partial<{ ContextMenu: ComponentType | null; diff --git a/packages/tldraw/api/api.json b/packages/tldraw/api/api.json index 9b85ae519..c72832809 100644 --- a/packages/tldraw/api/api.json +++ b/packages/tldraw/api/api.json @@ -3185,7 +3185,7 @@ "excerptTokens": [ { "kind": "Content", - "text": "export declare function DefaultStylePanelContent({ relevantStyles }: " + "text": "export declare function DefaultStylePanelContent({ styles }: " }, { "kind": "Reference", @@ -3223,7 +3223,7 @@ "overloadIndex": 1, "parameters": [ { - "parameterName": "{ relevantStyles }", + "parameterName": "{ styles }", "parameterTypeTokenRange": { "startIndex": 1, "endIndex": 2 @@ -13722,183 +13722,6 @@ ], "name": "Tldraw" }, - { - "kind": "Function", - "canonicalReference": "@tldraw/tldraw!TldrawCropHandles:function(1)", - "docComment": "/**\n * @public\n */\n", - "excerptTokens": [ - { - "kind": "Content", - "text": "export declare function TldrawCropHandles({ size, width, height, hideAlternateHandles, }: " - }, - { - "kind": "Reference", - "text": "TldrawCropHandlesProps", - "canonicalReference": "@tldraw/tldraw!TldrawCropHandlesProps:interface" - }, - { - "kind": "Content", - "text": "): " - }, - { - "kind": "Content", - "text": "import(\"react/jsx-runtime\")." - }, - { - "kind": "Reference", - "text": "JSX.Element", - "canonicalReference": "@types/react!JSX.Element:interface" - }, - { - "kind": "Content", - "text": ";" - } - ], - "fileUrlPath": "packages/tldraw/src/lib/canvas/TldrawCropHandles.tsx", - "returnTypeTokenRange": { - "startIndex": 3, - "endIndex": 5 - }, - "releaseTag": "Public", - "overloadIndex": 1, - "parameters": [ - { - "parameterName": "{ size, width, height, hideAlternateHandles, }", - "parameterTypeTokenRange": { - "startIndex": 1, - "endIndex": 2 - }, - "isOptional": false - } - ], - "name": "TldrawCropHandles" - }, - { - "kind": "Interface", - "canonicalReference": "@tldraw/tldraw!TldrawCropHandlesProps:interface", - "docComment": "/**\n * @public\n */\n", - "excerptTokens": [ - { - "kind": "Content", - "text": "export interface TldrawCropHandlesProps " - } - ], - "fileUrlPath": "packages/tldraw/src/lib/canvas/TldrawCropHandles.tsx", - "releaseTag": "Public", - "name": "TldrawCropHandlesProps", - "preserveMemberOrder": false, - "members": [ - { - "kind": "PropertySignature", - "canonicalReference": "@tldraw/tldraw!TldrawCropHandlesProps#height:member", - "docComment": "", - "excerptTokens": [ - { - "kind": "Content", - "text": "height: " - }, - { - "kind": "Content", - "text": "number" - }, - { - "kind": "Content", - "text": ";" - } - ], - "isReadonly": false, - "isOptional": false, - "releaseTag": "Public", - "name": "height", - "propertyTypeTokenRange": { - "startIndex": 1, - "endIndex": 2 - } - }, - { - "kind": "PropertySignature", - "canonicalReference": "@tldraw/tldraw!TldrawCropHandlesProps#hideAlternateHandles:member", - "docComment": "", - "excerptTokens": [ - { - "kind": "Content", - "text": "hideAlternateHandles: " - }, - { - "kind": "Content", - "text": "boolean" - }, - { - "kind": "Content", - "text": ";" - } - ], - "isReadonly": false, - "isOptional": false, - "releaseTag": "Public", - "name": "hideAlternateHandles", - "propertyTypeTokenRange": { - "startIndex": 1, - "endIndex": 2 - } - }, - { - "kind": "PropertySignature", - "canonicalReference": "@tldraw/tldraw!TldrawCropHandlesProps#size:member", - "docComment": "", - "excerptTokens": [ - { - "kind": "Content", - "text": "size: " - }, - { - "kind": "Content", - "text": "number" - }, - { - "kind": "Content", - "text": ";" - } - ], - "isReadonly": false, - "isOptional": false, - "releaseTag": "Public", - "name": "size", - "propertyTypeTokenRange": { - "startIndex": 1, - "endIndex": 2 - } - }, - { - "kind": "PropertySignature", - "canonicalReference": "@tldraw/tldraw!TldrawCropHandlesProps#width:member", - "docComment": "", - "excerptTokens": [ - { - "kind": "Content", - "text": "width: " - }, - { - "kind": "Content", - "text": "number" - }, - { - "kind": "Content", - "text": ";" - } - ], - "isReadonly": false, - "isOptional": false, - "releaseTag": "Public", - "name": "width", - "propertyTypeTokenRange": { - "startIndex": 1, - "endIndex": 2 - } - } - ], - "extendsTokenRanges": [] - }, { "kind": "Interface", "canonicalReference": "@tldraw/tldraw!TldrawFile:interface", @@ -14005,52 +13828,114 @@ "extendsTokenRanges": [] }, { - "kind": "Variable", - "canonicalReference": "@tldraw/tldraw!TldrawHandles:var", + "kind": "Function", + "canonicalReference": "@tldraw/tldraw!TldrawHandles:function(1)", "docComment": "/**\n * @public\n */\n", "excerptTokens": [ { "kind": "Content", - "text": "TldrawHandles: " + "text": "export declare function TldrawHandles({ children }: " }, { "kind": "Reference", - "text": "TLHandlesComponent", - "canonicalReference": "@tldraw/editor!TLHandlesComponent:type" + "text": "TLHandlesProps", + "canonicalReference": "@tldraw/editor!TLHandlesProps:type" + }, + { + "kind": "Content", + "text": "): " + }, + { + "kind": "Content", + "text": "import(\"react/jsx-runtime\")." + }, + { + "kind": "Reference", + "text": "JSX.Element", + "canonicalReference": "@types/react!JSX.Element:interface" + }, + { + "kind": "Content", + "text": " | null" + }, + { + "kind": "Content", + "text": ";" } ], "fileUrlPath": "packages/tldraw/src/lib/canvas/TldrawHandles.tsx", - "isReadonly": true, + "returnTypeTokenRange": { + "startIndex": 3, + "endIndex": 6 + }, "releaseTag": "Public", - "name": "TldrawHandles", - "variableTypeTokenRange": { - "startIndex": 1, - "endIndex": 2 - } + "overloadIndex": 1, + "parameters": [ + { + "parameterName": "{ children }", + "parameterTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + }, + "isOptional": false + } + ], + "name": "TldrawHandles" }, { - "kind": "Variable", - "canonicalReference": "@tldraw/tldraw!TldrawHoveredShapeIndicator:var", + "kind": "Function", + "canonicalReference": "@tldraw/tldraw!TldrawHoveredShapeIndicator:function(1)", "docComment": "/**\n * @public\n */\n", "excerptTokens": [ { "kind": "Content", - "text": "TldrawHoveredShapeIndicator: " + "text": "export declare function TldrawHoveredShapeIndicator({ shapeId }: " }, { "kind": "Reference", - "text": "TLHoveredShapeIndicatorComponent", - "canonicalReference": "@tldraw/editor!TLHoveredShapeIndicatorComponent:type" + "text": "TLHoveredShapeIndicatorProps", + "canonicalReference": "@tldraw/editor!TLHoveredShapeIndicatorProps:type" + }, + { + "kind": "Content", + "text": "): " + }, + { + "kind": "Content", + "text": "import(\"react/jsx-runtime\")." + }, + { + "kind": "Reference", + "text": "JSX.Element", + "canonicalReference": "@types/react!JSX.Element:interface" + }, + { + "kind": "Content", + "text": " | null" + }, + { + "kind": "Content", + "text": ";" } ], "fileUrlPath": "packages/tldraw/src/lib/canvas/TldrawHoveredShapeIndicator.tsx", - "isReadonly": true, + "returnTypeTokenRange": { + "startIndex": 3, + "endIndex": 6 + }, "releaseTag": "Public", - "name": "TldrawHoveredShapeIndicator", - "variableTypeTokenRange": { - "startIndex": 1, - "endIndex": 2 - } + "overloadIndex": 1, + "parameters": [ + { + "parameterName": "{ shapeId }", + "parameterTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + }, + "isOptional": false + } + ], + "name": "TldrawHoveredShapeIndicator" }, { "kind": "Variable", @@ -14340,28 +14225,59 @@ } }, { - "kind": "Variable", - "canonicalReference": "@tldraw/tldraw!TldrawScribble:var", + "kind": "Function", + "canonicalReference": "@tldraw/tldraw!TldrawScribble:function(1)", "docComment": "/**\n * @public\n */\n", "excerptTokens": [ { "kind": "Content", - "text": "TldrawScribble: " + "text": "export declare function TldrawScribble({ scribble, zoom, color, opacity, className }: " }, { "kind": "Reference", - "text": "TLScribbleComponent", - "canonicalReference": "@tldraw/editor!TLScribbleComponent:type" + "text": "TLScribbleProps", + "canonicalReference": "@tldraw/editor!TLScribbleProps:type" + }, + { + "kind": "Content", + "text": "): " + }, + { + "kind": "Content", + "text": "import(\"react/jsx-runtime\")." + }, + { + "kind": "Reference", + "text": "JSX.Element", + "canonicalReference": "@types/react!JSX.Element:interface" + }, + { + "kind": "Content", + "text": " | null" + }, + { + "kind": "Content", + "text": ";" } ], "fileUrlPath": "packages/tldraw/src/lib/canvas/TldrawScribble.tsx", - "isReadonly": true, + "returnTypeTokenRange": { + "startIndex": 3, + "endIndex": 6 + }, "releaseTag": "Public", - "name": "TldrawScribble", - "variableTypeTokenRange": { - "startIndex": 1, - "endIndex": 2 - } + "overloadIndex": 1, + "parameters": [ + { + "parameterName": "{ scribble, zoom, color, opacity, className }", + "parameterTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + }, + "isOptional": false + } + ], + "name": "TldrawScribble" }, { "kind": "Variable", @@ -14372,10 +14288,27 @@ "kind": "Content", "text": "TldrawSelectionBackground: " }, + { + "kind": "Content", + "text": "({ bounds, rotation }: " + }, { "kind": "Reference", - "text": "TLSelectionBackgroundComponent", - "canonicalReference": "@tldraw/editor!TLSelectionBackgroundComponent:type" + "text": "TLSelectionBackgroundProps", + "canonicalReference": "@tldraw/editor!TLSelectionBackgroundProps:type" + }, + { + "kind": "Content", + "text": ") => import(\"react/jsx-runtime\")." + }, + { + "kind": "Reference", + "text": "JSX.Element", + "canonicalReference": "@types/react!JSX.Element:interface" + }, + { + "kind": "Content", + "text": " | null" } ], "fileUrlPath": "packages/tldraw/src/lib/canvas/TldrawSelectionBackground.tsx", @@ -14384,7 +14317,7 @@ "name": "TldrawSelectionBackground", "variableTypeTokenRange": { "startIndex": 1, - "endIndex": 2 + "endIndex": 6 } }, { @@ -14396,10 +14329,36 @@ "kind": "Content", "text": "TldrawSelectionForeground: " }, + { + "kind": "Content", + "text": "import(\"react\")." + }, { "kind": "Reference", - "text": "TLSelectionForegroundComponent", - "canonicalReference": "@tldraw/editor!TLSelectionForegroundComponent:type" + "text": "MemoExoticComponent", + "canonicalReference": "@types/react!React.MemoExoticComponent:type" + }, + { + "kind": "Content", + "text": "<({ bounds, rotation, }: " + }, + { + "kind": "Reference", + "text": "TLSelectionForegroundProps", + "canonicalReference": "@tldraw/editor!TLSelectionForegroundProps:type" + }, + { + "kind": "Content", + "text": ") => import(\"react/jsx-runtime\")." + }, + { + "kind": "Reference", + "text": "JSX.Element", + "canonicalReference": "@types/react!JSX.Element:interface" + }, + { + "kind": "Content", + "text": " | null>" } ], "fileUrlPath": "packages/tldraw/src/lib/canvas/TldrawSelectionForeground.tsx", @@ -14408,7 +14367,7 @@ "name": "TldrawSelectionForeground", "variableTypeTokenRange": { "startIndex": 1, - "endIndex": 2 + "endIndex": 8 } }, { @@ -15525,7 +15484,7 @@ "excerptTokens": [ { "kind": "Content", - "text": "export declare function TldrawUiDropdownMenuGroup({ children, size, }: " + "text": "export declare function TldrawUiDropdownMenuGroup({ children }: " }, { "kind": "Reference", @@ -15559,7 +15518,7 @@ "overloadIndex": 1, "parameters": [ { - "parameterName": "{ children, size, }", + "parameterName": "{ children }", "parameterTypeTokenRange": { "startIndex": 1, "endIndex": 2 @@ -16181,7 +16140,7 @@ "excerptTokens": [ { "kind": "Content", - "text": "export declare function TldrawUiMenuGroup({ id, label, small, children }: " + "text": "export declare function TldrawUiMenuGroup({ id, label, children }: " }, { "kind": "Reference", @@ -16210,7 +16169,7 @@ "overloadIndex": 1, "parameters": [ { - "parameterName": "{ id, label, small, children }", + "parameterName": "{ id, label, children }", "parameterTypeTokenRange": { "startIndex": 1, "endIndex": 2 @@ -17518,34 +17477,6 @@ "name": "TLUiContextMenuProps", "preserveMemberOrder": false, "members": [ - { - "kind": "PropertySignature", - "canonicalReference": "@tldraw/tldraw!TLUiContextMenuProps#canvas:member", - "docComment": "", - "excerptTokens": [ - { - "kind": "Content", - "text": "canvas: " - }, - { - "kind": "Content", - "text": "any" - }, - { - "kind": "Content", - "text": ";" - } - ], - "fileUrlPath": "packages/tldraw/src/lib/ui/components/ContextMenu/DefaultContextMenu.tsx", - "isReadonly": false, - "isOptional": false, - "releaseTag": "Public", - "name": "canvas", - "propertyTypeTokenRange": { - "startIndex": 1, - "endIndex": 2 - } - }, { "kind": "PropertySignature", "canonicalReference": "@tldraw/tldraw!TLUiContextMenuProps#children:member", @@ -18144,7 +18075,7 @@ }, { "kind": "Content", - "text": "{\n children: any;\n size?: 'medium' | 'small' | 'tiny' | 'wide';\n}" + "text": "{\n children: any;\n}" }, { "kind": "Content", @@ -21351,7 +21282,7 @@ }, { "kind": "Content", - "text": "{\n id: string;\n label?: {\n [key: string]: TranslationKey;\n } | TranslationKey;\n small?: boolean;\n children?: any;\n}" + "text": "{\n id: string;\n label?: {\n [key: string]: TranslationKey;\n } | TranslationKey;\n children?: any;\n}" }, { "kind": "Content", @@ -21506,7 +21437,7 @@ }, { "kind": "Content", - "text": "{\n id: string;\n label?: {\n [key: string]: Translation;\n } | Translation;\n disabled?: boolean;\n children: any;\n size?: 'large' | 'medium' | 'small' | 'tiny';\n}" + "text": "{\n id: string;\n label?: {\n [key: string]: Translation;\n } | Translation;\n disabled?: boolean;\n children: any;\n size?: 'medium' | 'small' | 'tiny' | 'wide';\n}" }, { "kind": "Content", @@ -21808,7 +21739,7 @@ }, { "kind": "Content", - "text": "{\n relevantStyles: " + "text": "{\n styles: " }, { "kind": "Reference", @@ -21822,7 +21753,7 @@ { "kind": "Reference", "text": "useRelevantStyles", - "canonicalReference": "@tldraw/tldraw!~useRelevantStyles:function" + "canonicalReference": "@tldraw/tldraw!useRelevantStyles:function" }, { "kind": "Content", @@ -21851,7 +21782,7 @@ "text": "export interface TLUiStylePanelProps " } ], - "fileUrlPath": "packages/tldraw/src/lib/ui/components/StylePanel/DefaultStylePanel.tsx", + "fileUrlPath": "packages/tldraw/.tsbuild-api/lib/ui/components/StylePanel/DefaultStylePanel.d.ts", "releaseTag": "Public", "name": "TLUiStylePanelProps", "preserveMemberOrder": false, @@ -21874,6 +21805,7 @@ "text": ";" } ], + "fileUrlPath": "packages/tldraw/src/lib/ui/components/StylePanel/DefaultStylePanel.tsx", "isReadonly": false, "isOptional": true, "releaseTag": "Public", @@ -21901,6 +21833,7 @@ "text": ";" } ], + "fileUrlPath": "packages/tldraw/src/lib/ui/components/StylePanel/DefaultStylePanel.tsx", "isReadonly": false, "isOptional": true, "releaseTag": "Public", @@ -21909,51 +21842,6 @@ "startIndex": 1, "endIndex": 2 } - }, - { - "kind": "PropertySignature", - "canonicalReference": "@tldraw/tldraw!TLUiStylePanelProps#relevantStyles:member", - "docComment": "", - "excerptTokens": [ - { - "kind": "Content", - "text": "relevantStyles: " - }, - { - "kind": "Content", - "text": "{\n styles: " - }, - { - "kind": "Reference", - "text": "ReadonlySharedStyleMap", - "canonicalReference": "@tldraw/editor!ReadonlySharedStyleMap:class" - }, - { - "kind": "Content", - "text": ";\n opacity: " - }, - { - "kind": "Reference", - "text": "SharedStyle", - "canonicalReference": "@tldraw/editor!SharedStyle:type" - }, - { - "kind": "Content", - "text": ";\n } | null" - }, - { - "kind": "Content", - "text": ";" - } - ], - "isReadonly": false, - "isOptional": false, - "releaseTag": "Public", - "name": "relevantStyles", - "propertyTypeTokenRange": { - "startIndex": 1, - "endIndex": 6 - } } ], "extendsTokenRanges": [] @@ -23678,6 +23566,92 @@ "parameters": [], "name": "useReadonly" }, + { + "kind": "Function", + "canonicalReference": "@tldraw/tldraw!useRelevantStyles:function(1)", + "docComment": "/**\n * @public\n */\n", + "excerptTokens": [ + { + "kind": "Content", + "text": "export declare function useRelevantStyles(stylesToCheck?: " + }, + { + "kind": "Content", + "text": "readonly (import(\"@tldraw/editor\")." + }, + { + "kind": "Reference", + "text": "EnumStyleProp", + "canonicalReference": "@tldraw/tlschema!EnumStyleProp:class" + }, + { + "kind": "Content", + "text": "<\"black\" | \"blue\" | \"green\" | \"grey\" | \"light-blue\" | \"light-green\" | \"light-red\" | \"light-violet\" | \"orange\" | \"red\" | \"violet\" | \"yellow\"> | import(\"@tldraw/editor\")." + }, + { + "kind": "Reference", + "text": "EnumStyleProp", + "canonicalReference": "@tldraw/tlschema!EnumStyleProp:class" + }, + { + "kind": "Content", + "text": "<\"dashed\" | \"dotted\" | \"draw\" | \"solid\"> | import(\"@tldraw/editor\")." + }, + { + "kind": "Reference", + "text": "EnumStyleProp", + "canonicalReference": "@tldraw/tlschema!EnumStyleProp:class" + }, + { + "kind": "Content", + "text": "<\"l\" | \"m\" | \"s\" | \"xl\"> | import(\"@tldraw/editor\")." + }, + { + "kind": "Reference", + "text": "EnumStyleProp", + "canonicalReference": "@tldraw/tlschema!EnumStyleProp:class" + }, + { + "kind": "Content", + "text": "<\"none\" | \"pattern\" | \"semi\" | \"solid\">)[]" + }, + { + "kind": "Content", + "text": "): " + }, + { + "kind": "Content", + "text": "null | " + }, + { + "kind": "Reference", + "text": "ReadonlySharedStyleMap", + "canonicalReference": "@tldraw/editor!ReadonlySharedStyleMap:class" + }, + { + "kind": "Content", + "text": ";" + } + ], + "fileUrlPath": "packages/tldraw/src/lib/ui/hooks/useRevelantStyles.ts", + "returnTypeTokenRange": { + "startIndex": 11, + "endIndex": 13 + }, + "releaseTag": "Public", + "overloadIndex": 1, + "parameters": [ + { + "parameterName": "stylesToCheck", + "parameterTypeTokenRange": { + "startIndex": 1, + "endIndex": 10 + }, + "isOptional": true + } + ], + "name": "useRelevantStyles" + }, { "kind": "Function", "canonicalReference": "@tldraw/tldraw!useTldrawUiComponents:function(1)", diff --git a/packages/tldraw/src/index.ts b/packages/tldraw/src/index.ts index 9fd8a1b36..9f6ed3d75 100644 --- a/packages/tldraw/src/index.ts +++ b/packages/tldraw/src/index.ts @@ -4,7 +4,6 @@ export * from '@tldraw/editor' export { Tldraw, type TldrawProps } from './lib/Tldraw' export { TldrawImage, type TldrawImageProps } from './lib/TldrawImage' -export { TldrawCropHandles, type TldrawCropHandlesProps } from './lib/canvas/TldrawCropHandles' export { TldrawHandles } from './lib/canvas/TldrawHandles' export { TldrawHoveredShapeIndicator } from './lib/canvas/TldrawHoveredShapeIndicator' export { TldrawScribble } from './lib/canvas/TldrawScribble' @@ -82,6 +81,7 @@ export { useKeyboardShortcuts } from './lib/ui/hooks/useKeyboardShortcuts' export { useLocalStorageState } from './lib/ui/hooks/useLocalStorageState' export { useMenuIsOpen } from './lib/ui/hooks/useMenuIsOpen' export { useReadonly } from './lib/ui/hooks/useReadonly' +export { useRelevantStyles } from './lib/ui/hooks/useRevelantStyles' export { toolbarItem, useToolbarSchema, diff --git a/packages/tldraw/src/lib/Tldraw.test.tsx b/packages/tldraw/src/lib/Tldraw.test.tsx index b1cf43cd2..367b37de2 100644 --- a/packages/tldraw/src/lib/Tldraw.test.tsx +++ b/packages/tldraw/src/lib/Tldraw.test.tsx @@ -9,7 +9,8 @@ describe('', () => { await renderTldrawComponent(
- + , + { waitForPatterns: false } ) await screen.findByTestId('canvas-1') @@ -26,7 +27,7 @@ describe('', () => { ) } - await renderTldrawComponent() + await renderTldrawComponent(, { waitForPatterns: false }) await screen.findByTestId('canvas-1') }) @@ -59,7 +60,8 @@ describe('', () => { const rendered = await renderTldrawComponent(
- + , + { waitForPatterns: false } ) await screen.findByTestId('canvas-1') diff --git a/packages/tldraw/src/lib/Tldraw.tsx b/packages/tldraw/src/lib/Tldraw.tsx index 090fc3c37..752b93f4b 100644 --- a/packages/tldraw/src/lib/Tldraw.tsx +++ b/packages/tldraw/src/lib/Tldraw.tsx @@ -1,5 +1,4 @@ import { - Canvas, Editor, ErrorScreen, LoadingScreen, @@ -13,6 +12,7 @@ import { TldrawEditorBaseProps, assert, useEditor, + useEditorComponents, useShallowArrayIdentity, useShallowObjectIdentity, } from '@tldraw/editor' @@ -125,7 +125,7 @@ export function Tldraw(props: TldrawProps) { tools={toolsWithDefaults} > - - return } /> + if (ContextMenu) { + // should wrap canvas + return + } + + if (Canvas) { + return + } + + return null } // duped from tldraw editor diff --git a/packages/tldraw/src/lib/canvas/TldrawCropHandles.tsx b/packages/tldraw/src/lib/canvas/TldrawCropHandles.tsx index a3df1e9db..9654c467b 100644 --- a/packages/tldraw/src/lib/canvas/TldrawCropHandles.tsx +++ b/packages/tldraw/src/lib/canvas/TldrawCropHandles.tsx @@ -1,7 +1,6 @@ import { toDomPrecision } from '@tldraw/editor' import classNames from 'classnames' -/** @public */ export interface TldrawCropHandlesProps { size: number width: number @@ -9,7 +8,6 @@ export interface TldrawCropHandlesProps { hideAlternateHandles: boolean } -/** @public */ export function TldrawCropHandles({ size, width, diff --git a/packages/tldraw/src/lib/canvas/TldrawHandles.tsx b/packages/tldraw/src/lib/canvas/TldrawHandles.tsx index a26c298f6..5f6932b56 100644 --- a/packages/tldraw/src/lib/canvas/TldrawHandles.tsx +++ b/packages/tldraw/src/lib/canvas/TldrawHandles.tsx @@ -1,7 +1,7 @@ -import { TLHandlesComponent, useEditor, useValue } from '@tldraw/editor' +import { TLHandlesProps, useEditor, useValue } from '@tldraw/editor' /** @public */ -export const TldrawHandles: TLHandlesComponent = ({ children }) => { +export function TldrawHandles({ children }: TLHandlesProps) { const editor = useEditor() const shouldDisplayHandles = useValue( 'shouldDisplayHandles', diff --git a/packages/tldraw/src/lib/canvas/TldrawHoveredShapeIndicator.tsx b/packages/tldraw/src/lib/canvas/TldrawHoveredShapeIndicator.tsx index 5ae75cc33..6327ae970 100644 --- a/packages/tldraw/src/lib/canvas/TldrawHoveredShapeIndicator.tsx +++ b/packages/tldraw/src/lib/canvas/TldrawHoveredShapeIndicator.tsx @@ -1,13 +1,14 @@ import { - ShapeIndicator, - TLHoveredShapeIndicatorComponent, + TLHoveredShapeIndicatorProps, useEditor, + useEditorComponents, useValue, } from '@tldraw/editor' /** @public */ -export const TldrawHoveredShapeIndicator: TLHoveredShapeIndicatorComponent = ({ shapeId }) => { +export function TldrawHoveredShapeIndicator({ shapeId }: TLHoveredShapeIndicatorProps) { const editor = useEditor() + const { ShapeIndicator } = useEditorComponents() const showHoveredShapeIndicator = useValue( 'show hovered', () => { @@ -23,8 +24,9 @@ export const TldrawHoveredShapeIndicator: TLHoveredShapeIndicatorComponent = ({ }, [editor] ) + if (!ShapeIndicator) return null if (!showHoveredShapeIndicator) return null - return + return } // diff --git a/packages/tldraw/src/lib/canvas/TldrawScribble.tsx b/packages/tldraw/src/lib/canvas/TldrawScribble.tsx index 1aa380d87..3823ecb18 100644 --- a/packages/tldraw/src/lib/canvas/TldrawScribble.tsx +++ b/packages/tldraw/src/lib/canvas/TldrawScribble.tsx @@ -1,15 +1,9 @@ -import { EASINGS, TLScribbleComponent, getSvgPathFromPoints } from '@tldraw/editor' +import { EASINGS, TLScribbleProps, getSvgPathFromPoints } from '@tldraw/editor' import classNames from 'classnames' import { getStroke } from '../shapes/shared/freehand/getStroke' /** @public */ -export const TldrawScribble: TLScribbleComponent = ({ - scribble, - zoom, - color, - opacity, - className, -}) => { +export function TldrawScribble({ scribble, zoom, color, opacity, className }: TLScribbleProps) { if (!scribble.points.length) return null const stroke = getStroke(scribble.points, { diff --git a/packages/tldraw/src/lib/canvas/TldrawSelectionBackground.tsx b/packages/tldraw/src/lib/canvas/TldrawSelectionBackground.tsx index 6e63b6603..c77e7ba2a 100644 --- a/packages/tldraw/src/lib/canvas/TldrawSelectionBackground.tsx +++ b/packages/tldraw/src/lib/canvas/TldrawSelectionBackground.tsx @@ -1,12 +1,12 @@ import { DefaultSelectionBackground, - TLSelectionBackgroundComponent, + TLSelectionBackgroundProps, useEditor, useValue, } from '@tldraw/editor' /** @public */ -export const TldrawSelectionBackground: TLSelectionBackgroundComponent = ({ bounds, rotation }) => { +export const TldrawSelectionBackground = ({ bounds, rotation }: TLSelectionBackgroundProps) => { const editor = useEditor() const shouldDisplay = useValue( diff --git a/packages/tldraw/src/lib/canvas/TldrawSelectionForeground.tsx b/packages/tldraw/src/lib/canvas/TldrawSelectionForeground.tsx index 244ff5692..295b4f8cb 100644 --- a/packages/tldraw/src/lib/canvas/TldrawSelectionForeground.tsx +++ b/packages/tldraw/src/lib/canvas/TldrawSelectionForeground.tsx @@ -1,8 +1,7 @@ import { - Box, RotateCorner, TLEmbedShape, - TLSelectionForegroundComponent, + TLSelectionForegroundProps, TLTextShape, getCursor, toDomPrecision, @@ -18,428 +17,428 @@ import { useReadonly } from '../ui/hooks/useReadonly' import { TldrawCropHandles } from './TldrawCropHandles' /** @public */ -export const TldrawSelectionForeground: TLSelectionForegroundComponent = track( - function TldrawSelectionForeground({ bounds, rotation }: { bounds: Box; rotation: number }) { - const editor = useEditor() - const rSvg = useRef(null) +export const TldrawSelectionForeground = track(function TldrawSelectionForeground({ + bounds, + rotation, +}: TLSelectionForegroundProps) { + const editor = useEditor() + const rSvg = useRef(null) - const isReadonlyMode = useReadonly() - const topEvents = useSelectionEvents('top') - const rightEvents = useSelectionEvents('right') - const bottomEvents = useSelectionEvents('bottom') - const leftEvents = useSelectionEvents('left') - const topLeftEvents = useSelectionEvents('top_left') - const topRightEvents = useSelectionEvents('top_right') - const bottomRightEvents = useSelectionEvents('bottom_right') - const bottomLeftEvents = useSelectionEvents('bottom_left') + const isReadonlyMode = useReadonly() + const topEvents = useSelectionEvents('top') + const rightEvents = useSelectionEvents('right') + const bottomEvents = useSelectionEvents('bottom') + const leftEvents = useSelectionEvents('left') + const topLeftEvents = useSelectionEvents('top_left') + const topRightEvents = useSelectionEvents('top_right') + const bottomRightEvents = useSelectionEvents('bottom_right') + const bottomLeftEvents = useSelectionEvents('bottom_left') - const isDefaultCursor = - !editor.getIsMenuOpen() && editor.getInstanceState().cursor.type === 'default' - const isCoarsePointer = editor.getInstanceState().isCoarsePointer + const isDefaultCursor = + !editor.getIsMenuOpen() && editor.getInstanceState().cursor.type === 'default' + const isCoarsePointer = editor.getInstanceState().isCoarsePointer - const onlyShape = editor.getOnlySelectedShape() - const isLockedShape = onlyShape && editor.isShapeOrAncestorLocked(onlyShape) + const onlyShape = editor.getOnlySelectedShape() + const isLockedShape = onlyShape && editor.isShapeOrAncestorLocked(onlyShape) - // if all shapes have an expandBy for the selection outline, we can expand by the l - const expandOutlineBy = onlyShape - ? editor.getShapeUtil(onlyShape).expandSelectionOutlinePx(onlyShape) - : 0 + // if all shapes have an expandBy for the selection outline, we can expand by the l + const expandOutlineBy = onlyShape + ? editor.getShapeUtil(onlyShape).expandSelectionOutlinePx(onlyShape) + : 0 - useTransform(rSvg, bounds?.x, bounds?.y, 1, editor.getSelectionRotation(), { - x: -expandOutlineBy, - y: -expandOutlineBy, - }) + useTransform(rSvg, bounds?.x, bounds?.y, 1, editor.getSelectionRotation(), { + x: -expandOutlineBy, + y: -expandOutlineBy, + }) - if (!bounds) return null - bounds = bounds.clone().expandBy(expandOutlineBy).zeroFix() + if (!bounds) return null + bounds = bounds.clone().expandBy(expandOutlineBy).zeroFix() - const zoom = editor.getZoomLevel() - const isChangingStyle = editor.getInstanceState().isChangingStyle + const zoom = editor.getZoomLevel() + const isChangingStyle = editor.getInstanceState().isChangingStyle - const width = bounds.width - const height = bounds.height + const width = bounds.width + const height = bounds.height - const size = 8 / zoom - const isTinyX = width < size * 2 - const isTinyY = height < size * 2 + const size = 8 / zoom + const isTinyX = width < size * 2 + const isTinyY = height < size * 2 - const isSmallX = width < size * 4 - const isSmallY = height < size * 4 - const isSmallCropX = width < size * 5 - const isSmallCropY = height < size * 5 + const isSmallX = width < size * 4 + const isSmallY = height < size * 4 + const isSmallCropX = width < size * 5 + const isSmallCropY = height < size * 5 - const mobileHandleMultiplier = isCoarsePointer ? 1.75 : 1 - const targetSize = (6 / zoom) * mobileHandleMultiplier + const mobileHandleMultiplier = isCoarsePointer ? 1.75 : 1 + const targetSize = (6 / zoom) * mobileHandleMultiplier - const targetSizeX = (isSmallX ? targetSize / 2 : targetSize) * (mobileHandleMultiplier * 0.75) - const targetSizeY = (isSmallY ? targetSize / 2 : targetSize) * (mobileHandleMultiplier * 0.75) + const targetSizeX = (isSmallX ? targetSize / 2 : targetSize) * (mobileHandleMultiplier * 0.75) + const targetSizeY = (isSmallY ? targetSize / 2 : targetSize) * (mobileHandleMultiplier * 0.75) - const showSelectionBounds = - (onlyShape ? !editor.getShapeUtil(onlyShape).hideSelectionBoundsFg(onlyShape) : true) && - !isChangingStyle + const showSelectionBounds = + (onlyShape ? !editor.getShapeUtil(onlyShape).hideSelectionBoundsFg(onlyShape) : true) && + !isChangingStyle - let shouldDisplayBox = - (showSelectionBounds && - editor.isInAny( - 'select.idle', - 'select.brushing', - 'select.scribble_brushing', - 'select.pointing_canvas', - 'select.pointing_selection', - 'select.pointing_shape', - 'select.crop.idle', - 'select.crop.pointing_crop', - 'select.pointing_resize_handle', - 'select.pointing_crop_handle' - )) || - (showSelectionBounds && - editor.isIn('select.resizing') && - onlyShape && - editor.isShapeOfType(onlyShape, 'text')) - - if (onlyShape && shouldDisplayBox) { - if (editor.environment.isFirefox && editor.isShapeOfType(onlyShape, 'embed')) { - shouldDisplayBox = false - } - } - - const showCropHandles = - editor.isInAny( - 'select.pointing_crop_handle', - 'select.crop.idle', - 'select.crop.pointing_crop' - ) && - !isChangingStyle && - !isReadonlyMode - - const shouldDisplayControls = + let shouldDisplayBox = + (showSelectionBounds && editor.isInAny( 'select.idle', + 'select.brushing', + 'select.scribble_brushing', + 'select.pointing_canvas', 'select.pointing_selection', 'select.pointing_shape', - 'select.crop.idle' - ) && - !isChangingStyle && - !isReadonlyMode - - const showCornerRotateHandles = - !isCoarsePointer && - !(isTinyX || isTinyY) && - (shouldDisplayControls || showCropHandles) && - (onlyShape ? !editor.getShapeUtil(onlyShape).hideRotateHandle(onlyShape) : true) && - !isLockedShape - - const showMobileRotateHandle = - isCoarsePointer && - (!isSmallX || !isSmallY) && - (shouldDisplayControls || showCropHandles) && - (onlyShape ? !editor.getShapeUtil(onlyShape).hideRotateHandle(onlyShape) : true) && - !isLockedShape - - const showResizeHandles = - shouldDisplayControls && - (onlyShape - ? editor.getShapeUtil(onlyShape).canResize(onlyShape) && - !editor.getShapeUtil(onlyShape).hideResizeHandles(onlyShape) - : true) && - !showCropHandles && - !isLockedShape - - const hideAlternateCornerHandles = isTinyX || isTinyY - const showOnlyOneHandle = isTinyX && isTinyY - const hideAlternateCropHandles = isSmallCropX || isSmallCropY - - const showHandles = showResizeHandles || showCropHandles - const hideRotateCornerHandles = !showCornerRotateHandles - const hideMobileRotateHandle = !shouldDisplayControls || !showMobileRotateHandle - const hideTopLeftCorner = !shouldDisplayControls || !showHandles - const hideTopRightCorner = !shouldDisplayControls || !showHandles || hideAlternateCornerHandles - const hideBottomLeftCorner = - !shouldDisplayControls || !showHandles || hideAlternateCornerHandles - const hideBottomRightCorner = - !shouldDisplayControls || !showHandles || (showOnlyOneHandle && !showCropHandles) - - // If we're showing crop handles, then show the edges too. - // If we're showing resize handles, then show the edges only - // if we're not hiding them for some other reason. - let hideVerticalEdgeTargets = true - // The same logic above applies here, except another nuance is that - // we enable resizing for text on mobile (coarse). - let hideHorizontalEdgeTargets = true - - if (showCropHandles) { - hideVerticalEdgeTargets = hideAlternateCropHandles - hideHorizontalEdgeTargets = hideAlternateCropHandles - } else if (showResizeHandles) { - hideVerticalEdgeTargets = hideAlternateCornerHandles || showOnlyOneHandle || isCoarsePointer - const isMobileAndTextShape = isCoarsePointer && onlyShape && onlyShape.type === 'text' - hideHorizontalEdgeTargets = hideVerticalEdgeTargets && !isMobileAndTextShape - } - - const textHandleHeight = Math.min(24 / zoom, height - targetSizeY * 3) - const showTextResizeHandles = - shouldDisplayControls && - isCoarsePointer && + 'select.crop.idle', + 'select.crop.pointing_crop', + 'select.pointing_resize_handle', + 'select.pointing_crop_handle' + )) || + (showSelectionBounds && + editor.isIn('select.resizing') && onlyShape && - editor.isShapeOfType(onlyShape, 'text') && - textHandleHeight * zoom >= 4 + editor.isShapeOfType(onlyShape, 'text')) - return ( - - - {shouldDisplayBox && ( - - )} - - - - - - {/* Targets */} - - - - - {/* Corner Targets */} - - - - - {/* Resize Handles */} - {showResizeHandles && ( - <> - - - - - - )} - {showTextResizeHandles && ( - <> - - - - )} - {/* Crop Handles */} - {showCropHandles && ( - - )} - - - ) + if (onlyShape && shouldDisplayBox) { + if (editor.environment.isFirefox && editor.isShapeOfType(onlyShape, 'embed')) { + shouldDisplayBox = false + } } -) + + const showCropHandles = + editor.isInAny( + 'select.pointing_crop_handle', + 'select.crop.idle', + 'select.crop.pointing_crop' + ) && + !isChangingStyle && + !isReadonlyMode + + const shouldDisplayControls = + editor.isInAny( + 'select.idle', + 'select.pointing_selection', + 'select.pointing_shape', + 'select.crop.idle' + ) && + !isChangingStyle && + !isReadonlyMode + + const showCornerRotateHandles = + !isCoarsePointer && + !(isTinyX || isTinyY) && + (shouldDisplayControls || showCropHandles) && + (onlyShape ? !editor.getShapeUtil(onlyShape).hideRotateHandle(onlyShape) : true) && + !isLockedShape + + const showMobileRotateHandle = + isCoarsePointer && + (!isSmallX || !isSmallY) && + (shouldDisplayControls || showCropHandles) && + (onlyShape ? !editor.getShapeUtil(onlyShape).hideRotateHandle(onlyShape) : true) && + !isLockedShape + + const showResizeHandles = + shouldDisplayControls && + (onlyShape + ? editor.getShapeUtil(onlyShape).canResize(onlyShape) && + !editor.getShapeUtil(onlyShape).hideResizeHandles(onlyShape) + : true) && + !showCropHandles && + !isLockedShape + + const hideAlternateCornerHandles = isTinyX || isTinyY + const showOnlyOneHandle = isTinyX && isTinyY + const hideAlternateCropHandles = isSmallCropX || isSmallCropY + + const showHandles = showResizeHandles || showCropHandles + const hideRotateCornerHandles = !showCornerRotateHandles + const hideMobileRotateHandle = !shouldDisplayControls || !showMobileRotateHandle + const hideTopLeftCorner = !shouldDisplayControls || !showHandles + const hideTopRightCorner = !shouldDisplayControls || !showHandles || hideAlternateCornerHandles + const hideBottomLeftCorner = !shouldDisplayControls || !showHandles || hideAlternateCornerHandles + const hideBottomRightCorner = + !shouldDisplayControls || !showHandles || (showOnlyOneHandle && !showCropHandles) + + // If we're showing crop handles, then show the edges too. + // If we're showing resize handles, then show the edges only + // if we're not hiding them for some other reason. + let hideVerticalEdgeTargets = true + // The same logic above applies here, except another nuance is that + // we enable resizing for text on mobile (coarse). + let hideHorizontalEdgeTargets = true + + if (showCropHandles) { + hideVerticalEdgeTargets = hideAlternateCropHandles + hideHorizontalEdgeTargets = hideAlternateCropHandles + } else if (showResizeHandles) { + hideVerticalEdgeTargets = hideAlternateCornerHandles || showOnlyOneHandle || isCoarsePointer + const isMobileAndTextShape = isCoarsePointer && onlyShape && onlyShape.type === 'text' + hideHorizontalEdgeTargets = hideVerticalEdgeTargets && !isMobileAndTextShape + } + + const textHandleHeight = Math.min(24 / zoom, height - targetSizeY * 3) + const showTextResizeHandles = + shouldDisplayControls && + isCoarsePointer && + onlyShape && + editor.isShapeOfType(onlyShape, 'text') && + textHandleHeight * zoom >= 4 + + return ( + + + {shouldDisplayBox && ( + + )} + + + + + + {/* Targets */} + + + + + {/* Corner Targets */} + + + + + {/* Resize Handles */} + {showResizeHandles && ( + <> + + + + + + )} + {showTextResizeHandles && ( + <> + + + + )} + {/* Crop Handles */} + {showCropHandles && ( + + )} + + + ) +}) export const RotateCornerHandle = function RotateCornerHandle({ cx, diff --git a/packages/tldraw/src/lib/ui.css b/packages/tldraw/src/lib/ui.css index 089d0b787..beb4ec98c 100644 --- a/packages/tldraw/src/lib/ui.css +++ b/packages/tldraw/src/lib/ui.css @@ -79,6 +79,16 @@ margin-left: var(--space-2); } +.tlui-button[data-state='hinted']::after { + background-color: var(--color-hint); + opacity: 1; +} + +.tlui-button[data-state='hinted']:not(:disabled, :focus-visible):active:after { + background: var(--color-hint); + opacity: 1; +} + @media (hover: hover) { .tlui-button::after { background-color: var(--color-muted-2); @@ -136,7 +146,6 @@ .tlui-button__menu { height: 40px; min-height: 40px; - min-width: 128px; width: 100%; gap: 8px; margin: -4px 0px; @@ -929,6 +938,10 @@ stroke-width: 1px; } +.tlui-menu__group { + width: 100%; +} + .tlui-menu__group:empty { display: none; } @@ -952,25 +965,22 @@ /* Menu Sizes */ -.tlui-menu[data-size='large'] > .tlui-menu__group, -.tlui-menu__submenu__content[data-size='large'] > .tlui-menu__group { +.tlui-menu[data-size='large'] > .tlui-menu__group { min-width: initial; } -.tlui-menu[data-size='medium'] > .tlui-menu__group, -.tlui-menu__submenu__content[data-size='medium'] > .tlui-menu__group { +.tlui-menu[data-size='medium'] > .tlui-menu__group { min-width: 144px; } -.tlui-menu[data-size='small'] > .tlui-menu__group, -.tlui-menu__submenu__content[data-size='small'] > .tlui-menu__group { - min-width: 96px; -} - -.tlui-menu[data-size='tiny'] > .tlui-menu__group, -.tlui-menu__submenu__content[data-size='tiny'] > .tlui-menu__group { +.tlui-menu[data-size='small'] > .tlui-menu__group { min-width: 0px; } + +.tlui-menu[data-size='tiny'] > .tlui-menu__group { + min-width: 0px; +} + /* ------------------ Actions Menu ------------------ */ .tlui-actions-menu { diff --git a/packages/tldraw/src/lib/ui/TldrawUi.tsx b/packages/tldraw/src/lib/ui/TldrawUi.tsx index 3901bee98..41c2f70b7 100644 --- a/packages/tldraw/src/lib/ui/TldrawUi.tsx +++ b/packages/tldraw/src/lib/ui/TldrawUi.tsx @@ -21,7 +21,6 @@ import { useNativeClipboardEvents } from './hooks/useClipboardEvents' import { useEditorEvents } from './hooks/useEditorEvents' import { useKeyboardShortcuts } from './hooks/useKeyboardShortcuts' import { useReadonly } from './hooks/useReadonly' -import { useRelevantStyles } from './hooks/useRevelantStyles' import { useTranslation } from './hooks/useTranslation/useTranslation' /** @@ -159,7 +158,7 @@ const TldrawUiContent = React.memo(function TldrawUI() {
{SharePanel && } {StylePanel && breakpoint >= PORTRAIT_BREAKPOINT.TABLET_SM && !isReadonlyMode && ( - <_StylePanel /> + )}
@@ -181,11 +180,3 @@ const TldrawUiContent = React.memo(function TldrawUI() { ) }) - -function _StylePanel() { - const { StylePanel } = useTldrawUiComponents() - const relevantStyles = useRelevantStyles() - - if (!StylePanel) return null - return -} diff --git a/packages/tldraw/src/lib/ui/components/ContextMenu/DefaultContextMenu.tsx b/packages/tldraw/src/lib/ui/components/ContextMenu/DefaultContextMenu.tsx index ac5abb240..63c40e8e2 100644 --- a/packages/tldraw/src/lib/ui/components/ContextMenu/DefaultContextMenu.tsx +++ b/packages/tldraw/src/lib/ui/components/ContextMenu/DefaultContextMenu.tsx @@ -1,5 +1,5 @@ import * as _ContextMenu from '@radix-ui/react-context-menu' -import { preventDefault, useContainer, useEditor } from '@tldraw/editor' +import { preventDefault, useContainer, useEditor, useEditorComponents } from '@tldraw/editor' import { memo, useCallback } from 'react' import { useMenuIsOpen } from '../../hooks/useMenuIsOpen' import { TldrawUiMenuContextProvider } from '../primitives/menus/TldrawUiMenuContext' @@ -7,17 +7,17 @@ import { DefaultContextMenuContent } from './DefaultContextMenuContent' /** @public */ export interface TLUiContextMenuProps { - canvas: any children?: any } /** @public */ export const DefaultContextMenu = memo(function DefaultContextMenu({ - canvas, children, }: TLUiContextMenuProps) { const editor = useEditor() + const { Canvas } = useEditorComponents() + const cb = useCallback( (isOpen: boolean) => { if (!isOpen) { @@ -68,7 +68,7 @@ export const DefaultContextMenu = memo(function DefaultContextMenu({ return ( <_ContextMenu.Root dir="ltr" onOpenChange={handleOpenChange} modal={false}> <_ContextMenu.Trigger onContextMenu={undefined} dir="ltr"> - {canvas} + {Canvas ? : null} {isOpen && ( <_ContextMenu.Portal container={container}> diff --git a/packages/tldraw/src/lib/ui/components/MobileStylePanel.tsx b/packages/tldraw/src/lib/ui/components/MobileStylePanel.tsx index 28feb384d..68deae236 100644 --- a/packages/tldraw/src/lib/ui/components/MobileStylePanel.tsx +++ b/packages/tldraw/src/lib/ui/components/MobileStylePanel.tsx @@ -22,14 +22,14 @@ export function MobileStylePanel() { const msg = useTranslation() const relevantStyles = useRelevantStyles() - const color = relevantStyles?.styles.get(DefaultColorStyle) + const color = relevantStyles?.get(DefaultColorStyle) const theme = getDefaultColorTheme({ isDarkMode: editor.user.getIsDarkMode() }) const currentColor = ( color?.type === 'shared' ? theme[color.value as TLDefaultColorStyle] : theme.black ).solid const disableStylePanel = useValue( - 'isHandOrEraserToolActive', + 'disable style panel', () => editor.isInAny('hand', 'zoom', 'eraser', 'laser'), [editor] ) @@ -64,16 +64,8 @@ export function MobileStylePanel() { - <_StylePanel /> + {StylePanel && } ) } - -function _StylePanel() { - const { StylePanel } = useTldrawUiComponents() - const relevantStyles = useRelevantStyles() - - if (!StylePanel) return null - return -} diff --git a/packages/tldraw/src/lib/ui/components/StylePanel/DefaultStylePanel.tsx b/packages/tldraw/src/lib/ui/components/StylePanel/DefaultStylePanel.tsx index a200d2cbb..6b9e2c49a 100644 --- a/packages/tldraw/src/lib/ui/components/StylePanel/DefaultStylePanel.tsx +++ b/packages/tldraw/src/lib/ui/components/StylePanel/DefaultStylePanel.tsx @@ -1,35 +1,31 @@ -import { ReadonlySharedStyleMap, SharedStyle, useEditor } from '@tldraw/editor' +import { useEditor } from '@tldraw/editor' import classNames from 'classnames' import { memo, useCallback } from 'react' +import { useRelevantStyles } from '../../hooks/useRevelantStyles' import { DefaultStylePanelContent } from './DefaultStylePanelContent' /** @public */ export interface TLUiStylePanelProps { isMobile?: boolean children?: any - relevantStyles: { - styles: ReadonlySharedStyleMap - opacity: SharedStyle - } | null } /** @public */ export const DefaultStylePanel = memo(function DefaultStylePanel({ isMobile, children, - relevantStyles, }: TLUiStylePanelProps) { const editor = useEditor() + const styles = useRelevantStyles() + const handlePointerOut = useCallback(() => { if (!isMobile) { editor.updateInstanceState({ isChangingStyle: false }) } }, [editor, isMobile]) - if (!relevantStyles) return null - - const content = children ?? + const content = children ?? return (
+ styles: ReturnType } /** @public */ -export function DefaultStylePanelContent({ relevantStyles }: TLUiStylePanelContentProps) { - if (!relevantStyles) return null +export function DefaultStylePanelContent({ styles }: TLUiStylePanelContentProps) { + if (!styles) return null - const { styles, opacity } = relevantStyles const geo = styles.get(GeoShapeGeoStyle) const arrowheadEnd = styles.get(ArrowShapeArrowheadEndStyle) const arrowheadStart = styles.get(ArrowShapeArrowheadStartStyle) @@ -51,7 +50,7 @@ export function DefaultStylePanelContent({ relevantStyles }: TLUiStylePanelConte return ( <> - + {!hideText && } {!(hideGeo && hideArrowHeads && hideSpline) && (
@@ -68,52 +67,28 @@ function useStyleChangeCallback() { const editor = useEditor() const trackEvent = useUiEvents() - return React.useMemo(() => { - return function handleStyleChange(style: StyleProp, value: T, squashing: boolean) { - editor.batch(() => { - if (editor.isIn('select')) { - editor.setStyleForSelectedShapes(style, value, { squashing }) - } - editor.setStyleForNextShapes(style, value, { squashing }) - editor.updateInstanceState({ isChangingStyle: true }) - }) + return React.useMemo( + () => + function handleStyleChange(style: StyleProp, value: T, squashing: boolean) { + editor.batch(() => { + if (editor.isIn('select')) { + editor.setStyleForSelectedShapes(style, value, { squashing }) + } + editor.setStyleForNextShapes(style, value, { squashing }) + editor.updateInstanceState({ isChangingStyle: true }) + }) - trackEvent('set-style', { source: 'style-panel', id: style.id, value: value as string }) - } - }, [editor, trackEvent]) + trackEvent('set-style', { source: 'style-panel', id: style.id, value: value as string }) + }, + [editor, trackEvent] + ) } -const tldrawSupportedOpacities = [0.1, 0.25, 0.5, 0.75, 1] as const - -function CommonStylePickerSet({ - styles, - opacity, -}: { - styles: ReadonlySharedStyleMap - opacity: SharedStyle -}) { - const editor = useEditor() - const trackEvent = useUiEvents() +function CommonStylePickerSet({ styles }: { styles: ReadonlySharedStyleMap }) { const msg = useTranslation() const handleValueChange = useStyleChangeCallback() - const handleOpacityValueChange = React.useCallback( - (value: number, ephemeral: boolean) => { - const item = tldrawSupportedOpacities[value] - editor.batch(() => { - if (editor.isIn('select')) { - editor.setOpacityForSelectedShapes(item, { ephemeral }) - } - editor.setOpacityForNextShapes(item, { ephemeral }) - editor.updateInstanceState({ isChangingStyle: true }) - }) - - trackEvent('set-style', { source: 'style-panel', id: 'opacity', value }) - }, - [editor, trackEvent] - ) - const color = styles.get(DefaultColorStyle) const fill = styles.get(DefaultFillStyle) const dash = styles.get(DefaultDashStyle) @@ -121,15 +96,6 @@ function CommonStylePickerSet({ const showPickers = fill !== undefined || dash !== undefined || size !== undefined - const opacityIndex = - opacity.type === 'mixed' - ? -1 - : tldrawSupportedOpacities.indexOf( - minBy(tldrawSupportedOpacities, (supportedOpacity) => - Math.abs(supportedOpacity - opacity.value) - )! - ) - return ( <>
)} - {opacity === undefined ? null : ( - = 0 ? opacityIndex : tldrawSupportedOpacities.length - 1} - label={ - opacity.type === 'mixed' ? 'style-panel.mixed' : `opacity-style.${opacity.value}` - } - onValueChange={handleOpacityValueChange} - steps={tldrawSupportedOpacities.length - 1} - title={msg('style-panel.opacity')} - /> - )} +
{showPickers && (
@@ -331,3 +286,50 @@ function ArrowheadStylePickerSet({ styles }: { styles: ReadonlySharedStyleMap }) /> ) } + +const tldrawSupportedOpacities = [0.1, 0.25, 0.5, 0.75, 1] as const + +function OpacitySlider() { + const editor = useEditor() + const opacity = useValue('opacity', () => editor.getSharedOpacity(), [editor]) + const trackEvent = useUiEvents() + const msg = useTranslation() + + const handleOpacityValueChange = React.useCallback( + (value: number, ephemeral: boolean) => { + const item = tldrawSupportedOpacities[value] + editor.batch(() => { + if (editor.isIn('select')) { + editor.setOpacityForSelectedShapes(item, { ephemeral }) + } + editor.setOpacityForNextShapes(item, { ephemeral }) + editor.updateInstanceState({ isChangingStyle: true }) + }) + + trackEvent('set-style', { source: 'style-panel', id: 'opacity', value }) + }, + [editor, trackEvent] + ) + + if (opacity === undefined) return null + + const opacityIndex = + opacity.type === 'mixed' + ? -1 + : tldrawSupportedOpacities.indexOf( + minBy(tldrawSupportedOpacities, (supportedOpacity) => + Math.abs(supportedOpacity - opacity.value) + )! + ) + + return ( + = 0 ? opacityIndex : tldrawSupportedOpacities.length - 1} + label={opacity.type === 'mixed' ? 'style-panel.mixed' : `opacity-style.${opacity.value}`} + onValueChange={handleOpacityValueChange} + steps={tldrawSupportedOpacities.length - 1} + title={msg('style-panel.opacity')} + /> + ) +} diff --git a/packages/tldraw/src/lib/ui/components/menu-items.tsx b/packages/tldraw/src/lib/ui/components/menu-items.tsx index b7fcd8bf7..246ffd3a0 100644 --- a/packages/tldraw/src/lib/ui/components/menu-items.tsx +++ b/packages/tldraw/src/lib/ui/components/menu-items.tsx @@ -282,7 +282,7 @@ export function ArrangeMenuSubmenu() { if (!(twoSelected || onlyFlippableShapeSelected)) return null return ( - + {twoSelected && ( diff --git a/packages/tldraw/src/lib/ui/components/primitives/TldrawUiDropdownMenu.tsx b/packages/tldraw/src/lib/ui/components/primitives/TldrawUiDropdownMenu.tsx index 61694ca2e..93472c498 100644 --- a/packages/tldraw/src/lib/ui/components/primitives/TldrawUiDropdownMenu.tsx +++ b/packages/tldraw/src/lib/ui/components/primitives/TldrawUiDropdownMenu.tsx @@ -139,6 +139,7 @@ export type TLUiDropdownMenuSubContentProps = { id?: string alignOffset?: number sideOffset?: number + size?: 'tiny' | 'small' | 'medium' | 'wide' children: any } @@ -146,6 +147,7 @@ export type TLUiDropdownMenuSubContentProps = { export function TldrawUiDropdownMenuSubContent({ alignOffset = -1, sideOffset = -4, + size = 'small', children, }: TLUiDropdownMenuSubContentProps) { const container = useContainer() @@ -156,6 +158,7 @@ export function TldrawUiDropdownMenuSubContent({ alignOffset={alignOffset} sideOffset={sideOffset} collisionPadding={4} + data-size={size} > {children} @@ -166,16 +169,12 @@ export function TldrawUiDropdownMenuSubContent({ /** @public */ export type TLUiDropdownMenuGroupProps = { children: any - size?: 'tiny' | 'small' | 'medium' | 'wide' } /** @public */ -export function TldrawUiDropdownMenuGroup({ - children, - size = 'medium', -}: TLUiDropdownMenuGroupProps) { +export function TldrawUiDropdownMenuGroup({ children }: TLUiDropdownMenuGroupProps) { return ( - <_DropdownMenu.Group dir="ltr" className="tlui-menu__group" data-size={size}> + <_DropdownMenu.Group dir="ltr" className="tlui-menu__group"> {children} ) diff --git a/packages/tldraw/src/lib/ui/components/primitives/menus/TldrawUiMenuGroup.tsx b/packages/tldraw/src/lib/ui/components/primitives/menus/TldrawUiMenuGroup.tsx index 1b9533959..56e9db524 100644 --- a/packages/tldraw/src/lib/ui/components/primitives/menus/TldrawUiMenuGroup.tsx +++ b/packages/tldraw/src/lib/ui/components/primitives/menus/TldrawUiMenuGroup.tsx @@ -12,12 +12,11 @@ export type TLUiMenuGroupProps = { * The label to display on the item. If it's a string, it will be translated. If it's an object, the keys will be used as the language keys and the values will be translated. */ label?: TranslationKey | { [key: string]: TranslationKey } - small?: boolean children?: any } /** @public */ -export function TldrawUiMenuGroup({ id, label, small = false, children }: TLUiMenuGroupProps) { +export function TldrawUiMenuGroup({ id, label, children }: TLUiMenuGroupProps) { const { type: menuType, sourceId } = useTldrawUiMenuContext() const msg = useTranslation() const labelToUse = unwrapLabel(label, menuType) @@ -33,10 +32,7 @@ export function TldrawUiMenuGroup({ id, label, small = false, children }: TLUiMe } case 'menu': { return ( - + {children} ) @@ -46,7 +42,6 @@ export function TldrawUiMenuGroup({ id, label, small = false, children }: TLUiMe {children} diff --git a/packages/tldraw/src/lib/ui/components/primitives/menus/TldrawUiMenuSubmenu.tsx b/packages/tldraw/src/lib/ui/components/primitives/menus/TldrawUiMenuSubmenu.tsx index 7d8ea635e..5a677b8c8 100644 --- a/packages/tldraw/src/lib/ui/components/primitives/menus/TldrawUiMenuSubmenu.tsx +++ b/packages/tldraw/src/lib/ui/components/primitives/menus/TldrawUiMenuSubmenu.tsx @@ -24,7 +24,7 @@ export type TLUiMenuSubmenuProps = { label?: Translation | { [key: string]: Translation } disabled?: boolean children: any - size?: 'tiny' | 'small' | 'medium' | 'large' + size?: 'tiny' | 'small' | 'medium' | 'wide' } /** @public */ @@ -32,7 +32,7 @@ export function TldrawUiMenuSubmenu({ id, disabled = false, label, - size, + size = 'small', children, }: TLUiMenuSubmenuProps) { const { type: menuType, sourceId } = useTldrawUiMenuContext() @@ -55,7 +55,7 @@ export function TldrawUiMenuSubmenu({ label={labelStr!} title={labelStr!} /> - + {children} diff --git a/packages/tldraw/src/lib/ui/hooks/useRevelantStyles.ts b/packages/tldraw/src/lib/ui/hooks/useRevelantStyles.ts index 4e5a8116b..cac7a0211 100644 --- a/packages/tldraw/src/lib/ui/hooks/useRevelantStyles.ts +++ b/packages/tldraw/src/lib/ui/hooks/useRevelantStyles.ts @@ -4,18 +4,20 @@ import { DefaultFillStyle, DefaultSizeStyle, ReadonlySharedStyleMap, - SharedStyle, SharedStyleMap, useEditor, useValue, } from '@tldraw/editor' -const selectToolStyles = [DefaultColorStyle, DefaultDashStyle, DefaultFillStyle, DefaultSizeStyle] +const selectToolStyles = Object.freeze([ + DefaultColorStyle, + DefaultDashStyle, + DefaultFillStyle, + DefaultSizeStyle, +]) -export function useRelevantStyles(): { - styles: ReadonlySharedStyleMap - opacity: SharedStyle -} | null { +/** @public */ +export function useRelevantStyles(stylesToCheck = selectToolStyles): ReadonlySharedStyleMap | null { const editor = useEditor() return useValue( 'getRelevantStyles', @@ -25,13 +27,13 @@ export function useRelevantStyles(): { editor.getSelectedShapeIds().length > 0 || !!editor.root.getCurrent()?.shapeType if (styles.size === 0 && editor.isIn('select') && editor.getSelectedShapeIds().length === 0) { - for (const style of selectToolStyles) { + for (const style of stylesToCheck) { styles.applyValue(style, editor.getStyleForNextShape(style)) } } if (styles.size === 0 && !hasShape) return null - return { styles, opacity: editor.getSharedOpacity() } + return styles }, [editor] ) diff --git a/packages/tldraw/src/test/TldrawEditor.test.tsx b/packages/tldraw/src/test/TldrawEditor.test.tsx index a6a550285..2e8d1aca9 100644 --- a/packages/tldraw/src/test/TldrawEditor.test.tsx +++ b/packages/tldraw/src/test/TldrawEditor.test.tsx @@ -2,7 +2,6 @@ import { act, render, screen } from '@testing-library/react' import { BaseBoxShapeTool, BaseBoxShapeUtil, - Canvas, Editor, HTMLContainer, TLBaseShape, @@ -26,13 +25,10 @@ function checkAllShapes(editor: Editor, shapes: string[]) { describe('', () => { it('Renders without crashing', async () => { await renderTldrawComponent( - -
- - , + , { waitForPatterns: false } ) - await screen.findByTestId('canvas-1') + await screen.findByTestId('canvas') }) it('Creates its own store with core shapes', async () => { @@ -45,12 +41,9 @@ describe('', () => { initialState="select" tools={defaultTools} autoFocus - > -
- , + />, { waitForPatterns: false } ) - await screen.findByTestId('canvas-1') checkAllShapes(editor!, ['group']) }) @@ -65,13 +58,9 @@ describe('', () => { editor = e }} autoFocus - > -
- - , + />, { waitForPatterns: false } ) - await screen.findByTestId('canvas-1') expect(editor!).toBeTruthy() checkAllShapes(editor!, ['group']) @@ -88,13 +77,9 @@ describe('', () => { expect(editor.store).toBe(store) }} autoFocus - > -
- - , + />, { waitForPatterns: false } ) - await screen.findByTestId('canvas-1') }) it('throws if the store has different shapes to the ones passed in', async () => { @@ -148,11 +133,8 @@ describe('', () => { store={initialStore} onMount={onMount} autoFocus - > -
- + /> ) - await screen.findByTestId('canvas-1') const initialEditor = onMount.mock.lastCall[0] jest.spyOn(initialEditor, 'dispose') expect(initialEditor.store).toBe(initialStore) @@ -164,11 +146,8 @@ describe('', () => { store={initialStore} onMount={onMount} autoFocus - > -
- + /> ) - await screen.findByTestId('canvas-2') // not called again: expect(onMount).toHaveBeenCalledTimes(1) // re-render with a new store: @@ -180,11 +159,8 @@ describe('', () => { store={newStore} onMount={onMount} autoFocus - > -
- + /> ) - await screen.findByTestId('canvas-3') expect(initialEditor.dispose).toHaveBeenCalledTimes(1) expect(onMount).toHaveBeenCalledTimes(2) expect(onMount.mock.lastCall[0].store).toBe(newStore) @@ -201,12 +177,9 @@ describe('', () => { onMount={(editorApp) => { editor = editorApp }} - > - -
- + />, + { waitForPatterns: false } ) - await screen.findByTestId('canvas-1') expect(editor).toBeTruthy() await act(async () => { @@ -325,13 +298,9 @@ describe('Custom shapes', () => { onMount={(editorApp) => { editor = editorApp }} - > - -
- , + />, { waitForPatterns: false } ) - await screen.findByTestId('canvas-1') expect(editor).toBeTruthy() await act(async () => { diff --git a/packages/tldraw/src/test/commands/lockShapes.test.ts b/packages/tldraw/src/test/commands/lockShapes.test.ts index 9bc7c655c..c285de573 100644 --- a/packages/tldraw/src/test/commands/lockShapes.test.ts +++ b/packages/tldraw/src/test/commands/lockShapes.test.ts @@ -165,12 +165,10 @@ describe('Locked shapes', () => { describe('Unlocking', () => { it('Can unlock shapes', () => { editor.setSelectedShapes([ids.lockedShapeA, ids.lockedShapeB]) - let lockedStatus = [ids.lockedShapeA, ids.lockedShapeB].map( - (id) => editor.getShape(id)!.isLocked - ) - expect(lockedStatus).toStrictEqual([true, true]) + const getLockedStatus = () => + [ids.lockedShapeA, ids.lockedShapeB].map((id) => editor.getShape(id)!.isLocked) + expect(getLockedStatus()).toStrictEqual([true, true]) editor.toggleLock(editor.getSelectedShapeIds()) - lockedStatus = [ids.lockedShapeA, ids.lockedShapeB].map((id) => editor.getShape(id)!.isLocked) - expect(lockedStatus).toStrictEqual([false, false]) + expect(getLockedStatus()).toStrictEqual([false, false]) }) }) diff --git a/packages/tldraw/src/test/testutils/renderTldrawComponent.tsx b/packages/tldraw/src/test/testutils/renderTldrawComponent.tsx index 3a8fb060b..5cf9ccc69 100644 --- a/packages/tldraw/src/test/testutils/renderTldrawComponent.tsx +++ b/packages/tldraw/src/test/testutils/renderTldrawComponent.tsx @@ -15,7 +15,7 @@ import { ReactElement } from 'react' */ export async function renderTldrawComponent( element: ReactElement, - { waitForPatterns = true } = {} + { waitForPatterns }: { waitForPatterns: boolean } ) { const result = render(element) if (waitForPatterns) await result.findByTestId('ready-pattern-fill-defs') @@ -24,7 +24,7 @@ export async function renderTldrawComponent( export async function renderTldrawComponentWithEditor( cb: (onMount: (editor: Editor) => void) => ReactElement, - opts?: { waitForPatterns?: boolean } + opts: { waitForPatterns: boolean } ) { const editorPromise = promiseWithResolve() const element = cb((editor) => { diff --git a/packages/tldraw/src/test/ui/ContextMenu.test.tsx b/packages/tldraw/src/test/ui/ContextMenu.test.tsx index 9c790367c..6ef49e17f 100644 --- a/packages/tldraw/src/test/ui/ContextMenu.test.tsx +++ b/packages/tldraw/src/test/ui/ContextMenu.test.tsx @@ -10,7 +10,8 @@ it('opens on right-click', async () => { onMount={(editor) => { editor.createShape({ id: createShapeId(), type: 'geo' }) }} - /> + />, + { waitForPatterns: false } ) const canvas = await screen.findByTestId('canvas') @@ -38,7 +39,8 @@ it('tunnels context menu', async () => { editor.createShape({ id: createShapeId(), type: 'geo' }) }} components={components} - /> + />, + { waitForPatterns: false } ) const canvas = await screen.findByTestId('canvas')