ShapeUtil

See source code
Table of contents
abstract class ShapeUtil<Shape extends TLShape = TLShape> {}

Constructor

Constructs a new instance of the ShapeUtil class

Parameters

NameDescription

editor

Editor;

Properties

migrations

staticoptional

Migrations allow you to make changes to a shape's props over time. Read the shape prop migrations guide for more information.


props

staticoptional

Props allow you to define the shape's properties in a way that the editor can understand. This has two main uses:

  1. Validation. Shapes will be validated using these props to stop bad data from being saved. 2. Styles. Each StyleProp in the props can be set on many shapes at once, and will be remembered from one shape to the next.
static props?: RecordProps<TLUnknownShape>;

Example

import {
  T,
  TLBaseShape,
  TLDefaultColorStyle,
  DefaultColorStyle,
  ShapeUtil,
} from "tldraw";

type MyShape = TLBaseShape<
  "mine",
  {
    color: TLDefaultColorStyle;
    text: string;
  }
>;

class MyShapeUtil extends ShapeUtil<MyShape> {
  static props = {
    // we use tldraw's built-in color style:
    color: DefaultColorStyle,
    // validate that the text prop is a string:
    text: T.string,
  };
}

type

static

The type of the shape util, which should match the shape's type.

static type: string;

editor

editor: Editor;

options

Options for this shape util. If you're implementing a custom shape util, you can override this to provide customization options for your shape. If using an existing shape util, you can customizing this by calling ShapeUtil.configure.

options: {};

Methods

configure( )

static

Configure this shape utils options.

static configure<T extends TLShapeUtilConstructor<any, any>>(
  this: T,
  options: T extends new (...args: any[]) => {
    options: infer Options;
  }
    ? Partial<Options>
    : never,
): T;

Parameters

NameDescription

this

T;

options

T extends new (...args: any[]) => {
  options: infer Options;
}
  ? Partial<Options>
  : never;

Returns

T;

canBeLaidOut( )

Whether the shape can participate in layout functions such as alignment or distribution.

canBeLaidOut(shape: Shape, info: TLShapeUtilCanBeLaidOutOpts): boolean;

Parameters

NameDescription

shape

Shape;

The shape.

info

Additional context information: the type of action causing the layout and the

Returns

boolean;

canBind( )

Whether the shape can be bound to. See TLShapeUtilCanBindOpts for details.

canBind(_opts: TLShapeUtilCanBindOpts): boolean;

Parameters

NameDescription

_opts

Returns

boolean;

canCrop( )

Whether the shape can be cropped.

canCrop(shape: Shape): boolean;

Parameters

NameDescription

shape

Shape;

Returns

boolean;

canCull( )

Whether this shape can be culled. By default, shapes are culled for performance reasons when they are outside of the viewport. Culled shapes are still rendered to the DOM, but have their display property set to none.

canCull(shape: Shape): boolean;

Parameters

NameDescription

shape

Shape;

The shape.

Returns

boolean;

canEdit( )

Whether the shape can be double clicked to edit.

canEdit(shape: Shape, info: TLEditStartInfo): boolean;

Parameters

NameDescription

shape

Shape;

info

Returns

boolean;

canEditInReadonly( )

Whether the shape can be edited in read-only mode.

canEditInReadonly(shape: Shape): boolean;

Parameters

NameDescription

shape

Shape;

Returns

boolean;

canEditWhileLocked( )

Whether the shape can be edited while locked or while an ancestor is locked.

canEditWhileLocked(shape: Shape): boolean;

Parameters

NameDescription

shape

Shape;

Returns

boolean;

canReceiveNewChildrenOfType( )

Get whether the shape can receive children of a given type.

canReceiveNewChildrenOfType(shape: Shape, _type: TLShape["type"]): boolean;

Parameters

NameDescription

shape

Shape;

The shape.

_type

TLShape["type"];

Returns

boolean;

canResize( )

Whether the shape can be resized.

canResize(shape: Shape): boolean;

Parameters

NameDescription

shape

Shape;

Returns

boolean;

canResizeChildren( )

When the shape is resized, whether the shape's children should also be resized.

canResizeChildren(shape: Shape): boolean;

Parameters

NameDescription

shape

Shape;

Returns

boolean;

canScroll( )

Whether the shape can be scrolled while editing.

canScroll(shape: Shape): boolean;

Parameters

NameDescription

shape

Shape;

Returns

boolean;

canSnap( )

Whether the shape can be snapped to by another shape.

canSnap(shape: Shape): boolean;

Parameters

NameDescription

shape

Shape;

The shape.

Returns

boolean;

canTabTo( )

Whether the shape can be tabbed to.

canTabTo(shape: Shape): boolean;

Parameters

NameDescription

shape

Shape;

The shape.

Returns

boolean;

component( )

Get a JSX element for the shape (as an HTML element).

abstract component(shape: Shape): any;

Parameters

NameDescription

shape

Shape;

The shape.

Returns

any;

getAriaDescriptor( )

getAriaDescriptor(shape: Shape): string | undefined;

Parameters

NameDescription

shape

Shape;

Returns

string | undefined;

getBoundsSnapGeometry( )

Get the geometry to use when snapping to this this shape in translate/resize operations. See BoundsSnapGeometry for details.

getBoundsSnapGeometry(shape: Shape): BoundsSnapGeometry;

Parameters

NameDescription

shape

Shape;

Returns


getCanvasSvgDefs( )

Return elements to be added to the <defs> section of the canvases SVG context. This can be used to define SVG content (e.g. patterns & masks) that can be referred to by ID from svg elements returned by component.

Each def should have a unique key. If multiple defs from different shapes all have the same key, only one will be used.

getCanvasSvgDefs(): TLShapeUtilCanvasSvgDef[];

getClipPath( )

optional

Get the clip path to apply to this shape's children.

The returned points should define the inner clip boundary - the area where children will be visible. If your shape has a stroke, you should inset the clip path by half the stroke width so children are clipped to the inner edge of the stroke rather than its center line.

getClipPath?(shape: Shape): undefined | Vec[];

Example

override getClipPath(shape: MyShape): Vec[] | undefined {
  const strokeWidth = 2
  const inset = strokeWidth / 2
  // Return points inset by half the stroke width
  return [
    new Vec(inset, inset),
    new Vec(shape.props.w - inset, inset),
    new Vec(shape.props.w - inset, shape.props.h - inset),
    new Vec(inset, shape.props.h - inset),
  ]
}

Parameters

NameDescription

shape

Shape;

The shape to get the clip path for

Returns

undefined | Vec[];

Array of points defining the clipping polygon in local coordinates, or undefined if no clipping


getDefaultProps( )

Get the default props for a shape.

abstract getDefaultProps(): Shape["props"];

getFontFaces( )

Get the font faces that should be rendered in the document in order for this shape to render correctly.

getFontFaces(shape: Shape): TLFontFace[];

Parameters

NameDescription

shape

Shape;

The shape.

Returns

TLFontFace[];

getGeometry( )

Get the shape's geometry.

abstract getGeometry(shape: Shape, opts?: TLGeometryOpts): Geometry2d;

Parameters

NameDescription

shape

Shape;

The shape.

opts

Additional options for the request.

Returns


getHandles( )

optional

Get an array of handle models for the shape. This is an optional method.

getHandles?(shape: Shape): TLHandle[];

Example

util.getHandles?.(myShape);

Parameters

NameDescription

shape

Shape;

The shape.

Returns

TLHandle[];

getHandleSnapGeometry( )

Get the geometry to use when snapping handles to this shape. See HandleSnapGeometry for details.

getHandleSnapGeometry(shape: Shape): HandleSnapGeometry;

Parameters

NameDescription

shape

Shape;

Returns


getIndicatorPath( )

Get a Path2D for rendering the shape's indicator on the canvas.

When implemented, this is used instead of ShapeUtil.indicator for more efficient canvas-based indicator rendering. Shapes that return undefined will fall back to SVG-based rendering via ShapeUtil.indicator.

For complex indicators that need clipping (e.g., arrows with labels), return an object with path, clipPath, and additionalPaths properties.

getIndicatorPath(shape: Shape): TLIndicatorPath | undefined;

Parameters

NameDescription

shape

Shape;

The shape.

Returns

TLIndicatorPath | undefined;

A Path2D to stroke, or an object with clipping info, or undefined to use SVG fallback.


getInterpolatedProps( )

optional

Get the interpolated props for an animating shape. This is an optional method.

getInterpolatedProps?(
  startShape: Shape,
  endShape: Shape,
  progress: number,
): Shape["props"];

Example

util.getInterpolatedProps?.(startShape, endShape, t);

Parameters

NameDescription

startShape

Shape;

The initial shape.

endShape

Shape;

The initial shape.

progress

number;

The normalized progress between zero (start) and 1 (end).

Returns

Shape["props"];

getReferencedUserIds( )

Return user IDs referenced in shape-specific props. Used when copying shapes to include referenced users on the clipboard. Override this if your shape stores user IDs in custom props.

getReferencedUserIds(shape: Shape): string[];

Parameters

NameDescription

shape

Shape;

Returns

string[];

getText( )

getText(shape: Shape): string | undefined;

Parameters

NameDescription

shape

Shape;

Returns

string | undefined;

hideInMinimap( )

optional

Whether a specific shape should hide in the minimap.

If not defined, the default behavior is to show all shapes in the minimap.

hideInMinimap?(shape: Shape): boolean;

Parameters

NameDescription

shape

Shape;

Returns

boolean;

boolean indicating if this shape should hide in the minimap


hideResizeHandles( )

Whether the shape should hide its resize handles when selected.

hideResizeHandles(shape: Shape): boolean;

Parameters

NameDescription

shape

Shape;

Returns

boolean;

hideRotateHandle( )

Whether the shape should hide its rotation handles when selected.

hideRotateHandle(shape: Shape): boolean;

Parameters

NameDescription

shape

Shape;

Returns

boolean;

hideSelectionBoundsBg( )

Whether the shape should hide its selection bounds background when selected.

hideSelectionBoundsBg(shape: Shape): boolean;

Parameters

NameDescription

shape

Shape;

Returns

boolean;

hideSelectionBoundsFg( )

Whether the shape should hide its selection bounds foreground when selected.

hideSelectionBoundsFg(shape: Shape): boolean;

Parameters

NameDescription

shape

Shape;

Returns

boolean;

indicator( )

Get JSX describing the shape's indicator (as an SVG element).

abstract indicator(shape: Shape): any;

Parameters

NameDescription

shape

Shape;

The shape.

Returns

any;

isAspectRatioLocked( )

Whether the shape's aspect ratio is locked.

isAspectRatioLocked(shape: Shape): boolean;

Parameters

NameDescription

shape

Shape;

Returns

boolean;

isExportBoundsContainer( )

By default, the bounds of an image export are the bounds of all the shapes it contains, plus some padding. If an export includes a shape where isExportBoundsContainer is true, then the padding is skipped if the bounds of that shape contains all the other shapes. This is useful in cases like annotating on top of an image, where you usually want to avoid extra padding around the image if you don't need it.

isExportBoundsContainer(shape: Shape): boolean;

Parameters

NameDescription

shape

Shape;

The shape to check

Returns

boolean;

True if this shape should be treated as an export bounds container


onBeforeCreate( )

optional

A callback called just before a shape is created. This method provides a last chance to modify the created shape.

onBeforeCreate?(next: Shape): Shape | void;

Example

onBeforeCreate = (next) => {
  return { ...next, x: next.x + 1 };
};

Parameters

NameDescription

next

Shape;

The next shape.

Returns

Shape | void;

The next shape or void.


onBeforeUpdate( )

optional

A callback called just before a shape is updated. This method provides a last chance to modify the updated shape.

onBeforeUpdate?(prev: Shape, next: Shape): Shape | void;

Example

onBeforeUpdate = (prev, next) => {
  if (prev.x === next.x) {
    return { ...next, x: next.x + 1 };
  }
};

Parameters

NameDescription

prev

Shape;

The previous shape.

next

Shape;

The next shape.

Returns

Shape | void;

The next shape or void.


onChildrenChange( )

optional

A callback called when a shape's children change.

onChildrenChange?(shape: Shape): TLShapePartial[] | void;

Parameters

NameDescription

shape

Shape;

The shape.

Returns

TLShapePartial[] | void;

An array of shape updates, or void.


onClick( )

optional

A callback called when a shape is clicked.

onClick?(shape: Shape): TLShapePartial<Shape> | void;

Parameters

NameDescription

shape

Shape;

The shape.

Returns

TLShapePartial<Shape> | void;

A change to apply to the shape, or void.


onCrop( )

optional

A callback called when a shape changes from a crop.

onCrop?(
  shape: Shape,
  info: TLCropInfo<Shape>,
): Omit<TLShapePartial<Shape>, "id" | "type"> | undefined | void;

Parameters

NameDescription

shape

Shape;

The shape at the start of the crop.

info

TLCropInfo<Shape>;

Info about the crop.

Returns

Omit<TLShapePartial<Shape>, "id" | "type"> | undefined | void;

A change to apply to the shape, or void.


onDoubleClick( )

optional

A callback called when a shape is double clicked.

onDoubleClick?(shape: Shape): TLShapePartial<Shape> | void;

Parameters

NameDescription

shape

Shape;

The shape.

Returns

TLShapePartial<Shape> | void;

A change to apply to the shape, or void.


onDoubleClickCorner( )

optional

A callback called when a shape's corner is double clicked.

onDoubleClickCorner?(
  shape: Shape,
  info: TLClickEventInfo,
): TLShapePartial<Shape> | void;

Parameters

NameDescription

shape

Shape;

The shape.

info

Info about the corner.

Returns

TLShapePartial<Shape> | void;

A change to apply to the shape, or void.


onDoubleClickEdge( )

optional

A callback called when a shape's edge is double clicked.

onDoubleClickEdge?(
  shape: Shape,
  info: TLClickEventInfo,
): TLShapePartial<Shape> | void;

Parameters

NameDescription

shape

Shape;

The shape.

info

Info about the edge.

Returns

TLShapePartial<Shape> | void;

A change to apply to the shape, or void.


onDoubleClickHandle( )

optional

A callback called when a shape's handle is double clicked.

onDoubleClickHandle?(
  shape: Shape,
  handle: TLHandle,
): TLShapePartial<Shape> | void;

Parameters

NameDescription

shape

Shape;

The shape.

handle

The handle that is double-clicked.

Returns

TLShapePartial<Shape> | void;

A change to apply to the shape, or void.


onDragShapesIn( )

optional

A callback called when some other shapes are dragged into this one. This fires when the shapes are dragged over the shape for the first time.

onDragShapesIn?(
  shape: Shape,
  shapes: TLShape[],
  info: TLDragShapesInInfo,
): void;

Parameters

NameDescription

shape

Shape;

The shape.

shapes

TLShape[];

The shapes that are being dragged in.

info

Returns

void;

onDragShapesOut( )

optional

A callback called when some other shapes are dragged out of this one.

onDragShapesOut?(
  shape: Shape,
  shapes: TLShape[],
  info: TLDragShapesOutInfo,
): void;

Parameters

NameDescription

shape

Shape;

The shape.

shapes

TLShape[];

The shapes that are being dragged out.

info

Returns

void;

onDragShapesOver( )

optional

A callback called when some other shapes are dragged over this one. This fires when the shapes are dragged over the shape for the first time (after the onDragShapesIn callback), and again on every update while the shapes are being dragged.

onDragShapesOver?(
  shape: Shape,
  shapes: TLShape[],
  info: TLDragShapesOverInfo,
): void;

Example

onDragShapesOver = (shape, shapes) => {
  this.editor.reparentShapes(shapes, shape.id);
};

Parameters

NameDescription

shape

Shape;

The shape.

shapes

TLShape[];

The shapes that are being dragged over this one.

info

Returns

void;

onDropShapesOver( )

optional

A callback called when some other shapes are dropped over this one.

onDropShapesOver?(
  shape: Shape,
  shapes: TLShape[],
  info: TLDropShapesOverInfo,
): void;

Parameters

NameDescription

shape

Shape;

The shape.

shapes

TLShape[];

The shapes that are being dropped over this one.

info

Returns

void;

onEditEnd( )

optional

A callback called when a shape finishes being edited.

onEditEnd?(shape: Shape): void;

Parameters

NameDescription

shape

Shape;

The shape.

Returns

void;

onEditStart( )

optional

A callback called when a shape starts being edited.

onEditStart?(shape: Shape): void;

Parameters

NameDescription

shape

Shape;

The shape.

Returns

void;

onHandleDrag( )

optional

A callback called when a shape's handle changes.

onHandleDrag?(
  shape: Shape,
  info: TLHandleDragInfo<Shape>,
): TLShapePartial<Shape> | void;

Parameters

NameDescription

shape

Shape;

The current shape.

info

TLHandleDragInfo<Shape>;

An object containing the handle and whether the handle is 'precise' or not.

Returns

TLShapePartial<Shape> | void;

A change to apply to the shape, or void.


onHandleDragCancel( )

optional

A callback called when a shape's handle drag is cancelled.

onHandleDragCancel?(current: Shape, info: TLHandleDragInfo<Shape>): void;

Parameters

NameDescription

current

Shape;

The current shape.

info

TLHandleDragInfo<Shape>;

An object containing the handle and whether the handle is 'precise' or not.

Returns

void;

onHandleDragEnd( )

optional

A callback called when a shape's handle finishes being dragged.

onHandleDragEnd?(
  current: Shape,
  info: TLHandleDragInfo<Shape>,
): TLShapePartial<Shape> | void;

Parameters

NameDescription

current

Shape;

The current shape.

info

TLHandleDragInfo<Shape>;

An object containing the handle and whether the handle is 'precise' or not.

Returns

TLShapePartial<Shape> | void;

A change to apply to the shape, or void.


onHandleDragStart( )

optional

A callback called when a shape's handle starts being dragged.

onHandleDragStart?(
  shape: Shape,
  info: TLHandleDragInfo<Shape>,
): TLShapePartial<Shape> | void;

Parameters

NameDescription

shape

Shape;

The shape.

info

TLHandleDragInfo<Shape>;

An object containing the handle and whether the handle is 'precise' or not.

Returns

TLShapePartial<Shape> | void;

A change to apply to the shape, or void.


onResize( )

optional

A callback called when a shape changes from a resize.

onResize?(
  shape: Shape,
  info: TLResizeInfo<Shape>,
): Omit<TLShapePartial<Shape>, "id" | "type"> | undefined | void;

Parameters

NameDescription

shape

Shape;

The shape at the start of the resize.

info

TLResizeInfo<Shape>;

Info about the resize.

Returns

Omit<TLShapePartial<Shape>, "id" | "type"> | undefined | void;

A change to apply to the shape, or void.


onResizeCancel( )

optional

A callback called when a shape resize is cancelled.

onResizeCancel?(initial: Shape, current: Shape): void;

Parameters

NameDescription

initial

Shape;

The shape at the start of the resize.

current

Shape;

The current shape.

Returns

void;

onResizeEnd( )

optional

A callback called when a shape finishes resizing.

onResizeEnd?(initial: Shape, current: Shape): TLShapePartial<Shape> | void;

Parameters

NameDescription

initial

Shape;

The shape at the start of the resize.

current

Shape;

The current shape.

Returns

TLShapePartial<Shape> | void;

A change to apply to the shape, or void.


onResizeStart( )

optional

A callback called when a shape starts being resized.

onResizeStart?(shape: Shape): TLShapePartial<Shape> | void;

Parameters

NameDescription

shape

Shape;

The shape.

Returns

TLShapePartial<Shape> | void;

A change to apply to the shape, or void.


onRotate( )

optional

A callback called when a shape changes from a rotation.

onRotate?(initial: Shape, current: Shape): TLShapePartial<Shape> | void;

Parameters

NameDescription

initial

Shape;

The shape at the start of the rotation.

current

Shape;

The current shape.

Returns

TLShapePartial<Shape> | void;

A change to apply to the shape, or void.


onRotateCancel( )

optional

A callback called when a shape rotation is cancelled.

onRotateCancel?(initial: Shape, current: Shape): void;

Parameters

NameDescription

initial

Shape;

The shape at the start of the rotation.

current

Shape;

The current shape.

Returns

void;

onRotateEnd( )

optional

A callback called when a shape finishes rotating.

onRotateEnd?(initial: Shape, current: Shape): TLShapePartial<Shape> | void;

Parameters

NameDescription

initial

Shape;

The shape at the start of the rotation.

current

Shape;

The current shape.

Returns

TLShapePartial<Shape> | void;

A change to apply to the shape, or void.


onRotateStart( )

optional

A callback called when a shape starts being rotated.

onRotateStart?(shape: Shape): TLShapePartial<Shape> | void;

Parameters

NameDescription

shape

Shape;

The shape.

Returns

TLShapePartial<Shape> | void;

A change to apply to the shape, or void.


onTranslate( )

optional

A callback called when a shape changes from a translation.

onTranslate?(initial: Shape, current: Shape): TLShapePartial<Shape> | void;

Parameters

NameDescription

initial

Shape;

The shape at the start of the translation.

current

Shape;

The current shape.

Returns

TLShapePartial<Shape> | void;

A change to apply to the shape, or void.


onTranslateCancel( )

optional

A callback called when a shape translation is cancelled.

onTranslateCancel?(initial: Shape, current: Shape): void;

Parameters

NameDescription

initial

Shape;

The shape at the start of the translation.

current

Shape;

The current shape.

Returns

void;

onTranslateEnd( )

optional

A callback called when a shape finishes translating.

onTranslateEnd?(initial: Shape, current: Shape): TLShapePartial<Shape> | void;

Parameters

NameDescription

initial

Shape;

The shape at the start of the translation.

current

Shape;

The current shape.

Returns

TLShapePartial<Shape> | void;

A change to apply to the shape, or void.


onTranslateStart( )

optional

A callback called when a shape starts being translated.

onTranslateStart?(shape: Shape): TLShapePartial<Shape> | void;

Parameters

NameDescription

shape

Shape;

The shape.

Returns

TLShapePartial<Shape> | void;

A change to apply to the shape, or void.


shouldClipChild( )

optional

Whether a specific child shape should be clipped by this shape. Only called if getClipPath returns a valid polygon.

If not defined, the default behavior is to clip all children.

shouldClipChild?(child: TLShape): boolean;

Parameters

NameDescription

child

TLShape;

The child shape to check

Returns

boolean;

boolean indicating if this child should be clipped


toBackgroundSvg( )

optional

Get the shape's background layer as an SVG object.

toBackgroundSvg?(
  shape: Shape,
  ctx: SvgExportContext,
): null | Promise<null | ReactElement> | ReactElement;

Parameters

NameDescription

shape

Shape;

The shape.

ctx

ctx - The export context for the SVG - used for adding e.g. <def>s

Returns

null | Promise<null | ReactElement> | ReactElement;

An SVG element.


toSvg( )

optional

Get the shape as an SVG object.

toSvg?(
  shape: Shape,
  ctx: SvgExportContext,
): null | Promise<null | ReactElement> | ReactElement;

Parameters

NameDescription

shape

Shape;

The shape.

ctx

The export context for the SVG - used for adding e.g. <def>s

Returns

null | Promise<null | ReactElement> | ReactElement;

An SVG element.


useLegacyIndicator( )

Whether to use the legacy React-based indicator rendering.

Override this to return false if your shape implements ShapeUtil.getIndicatorPath for canvas-based indicator rendering.

useLegacyIndicator(): boolean;

Prev
ScribbleManager
Next
SnapManager