Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/tldraw/tldraw/llms.txt

Use this file to discover all available pages before exploring further.

BindingUtil is an abstract base class for creating custom binding types in tldraw. Bindings represent relationships between shapes (like an arrow pointing to a shape) and define how those relationships behave throughout their lifecycle.

Constructor

constructor(editor: Editor)
editor
Editor
required
The editor instance that this binding util is associated with.

Static properties

type
string
required
The type identifier for this binding util. Must match the binding’s type.
props
RecordProps<TLUnknownBinding>
Validations for this binding’s props.
migrations
TLPropsMigrations
Migrations for this binding’s props, used when upgrading binding data between schema versions.

Instance properties

editor
Editor
required
The editor instance passed to the constructor.

Abstract methods

getDefaultProps()

abstract getDefaultProps(): Partial<Binding['props']>
Returns the default props for a binding of this type. Returns: Partial<Binding['props']> - Default properties for the binding.

Lifecycle methods

onBeforeCreate()

onBeforeCreate?(options: BindingOnCreateOptions<Binding>): Binding | void
Called when a binding is about to be created. Optionally return a new binding to replace the one being created (e.g., to set different initial props).
options
BindingOnCreateOptions<Binding>
required
binding
Binding
The binding being created.
Returns: Binding | void - Optionally return a modified binding.

onAfterCreate()

onAfterCreate?(options: BindingOnCreateOptions<Binding>): void
Called after a binding has been created.
options
BindingOnCreateOptions<Binding>
required
binding
Binding
The binding that was created.

onBeforeChange()

onBeforeChange?(options: BindingOnChangeOptions<Binding>): Binding | void
Called when a binding is about to be changed. Note that this only fires when the binding record itself is changing, not when the associated shapes change (use onAfterChangeFromShape and onAfterChangeToShape for that). Optionally return a new binding to replace the one being changed (e.g., to enforce constraints on the binding’s props).
options
BindingOnChangeOptions<Binding>
required
bindingBefore
Binding
The binding record before the change.
bindingAfter
Binding
The binding record after the change.
Returns: Binding | void - Optionally return a modified binding.

onAfterChange()

onAfterChange?(options: BindingOnChangeOptions<Binding>): void
Called after a binding has been changed. Note that this only fires when the binding record itself is changing, not when the associated shapes change.
options
BindingOnChangeOptions<Binding>
required
bindingBefore
Binding
The binding record before the change.
bindingAfter
Binding
The binding record after the change.

onBeforeDelete()

onBeforeDelete?(options: BindingOnDeleteOptions<Binding>): void
Called when a binding is about to be deleted.
options
BindingOnDeleteOptions<Binding>
required
binding
Binding
The binding being deleted.

onAfterDelete()

onAfterDelete?(options: BindingOnDeleteOptions<Binding>): void
Called after a binding has been deleted.
options
BindingOnDeleteOptions<Binding>
required
binding
Binding
The binding that was deleted.

Shape change methods

onAfterChangeFromShape()

onAfterChangeFromShape?(options: BindingOnShapeChangeOptions<Binding>): void
Called after the shape referenced in a binding’s fromId is changed. Use this to propagate changes to the binding itself or the other shape as needed.
options
BindingOnShapeChangeOptions<Binding>
required
binding
Binding
The binding record linking these two shapes.
shapeBefore
TLShape
The shape record before the change.
shapeAfter
TLShape
The shape record after the change.
reason
'self' | 'ancestry'
Why did this shape change? 'self' means the shape itself changed, 'ancestry' means the shape’s ancestry changed but the shape itself may not have.

onAfterChangeToShape()

onAfterChangeToShape?(options: BindingOnShapeChangeOptions<Binding>): void
Called after the shape referenced in a binding’s toId is changed. Use this to propagate changes to the binding itself or the other shape as needed.
options
BindingOnShapeChangeOptions<Binding>
required
binding
Binding
The binding record linking these two shapes.
shapeBefore
TLShape
The shape record before the change.
shapeAfter
TLShape
The shape record after the change.
reason
'self' | 'ancestry'
Why did this shape change? 'self' means the shape itself changed, 'ancestry' means the shape’s ancestry changed but the shape itself may not have.

Shape deletion methods

onBeforeDeleteFromShape()

onBeforeDeleteFromShape?(options: BindingOnShapeDeleteOptions<Binding>): void
Called before the shape referenced in a binding’s fromId is about to be deleted. Use with care - you may want to use onBeforeIsolateFromShape instead.
options
BindingOnShapeDeleteOptions<Binding>
required
binding
Binding
The binding record that refers to the shape.
shape
TLShape
The shape that is about to be deleted.

onBeforeDeleteToShape()

onBeforeDeleteToShape?(options: BindingOnShapeDeleteOptions<Binding>): void
Called before the shape referenced in a binding’s toId is about to be deleted. Use with care - you may want to use onBeforeIsolateToShape instead.
options
BindingOnShapeDeleteOptions<Binding>
required
binding
Binding
The binding record that refers to the shape.
shape
TLShape
The shape that is about to be deleted.

Shape isolation methods

onBeforeIsolateFromShape()

onBeforeIsolateFromShape?(options: BindingOnShapeIsolateOptions<Binding>): void
Called before the shape referenced in a binding’s fromId is about to be isolated from the shape referenced in toId. Isolation happens whenever two bound shapes are separated:
  • One is deleted, but the other is not
  • One is copied, but the other is not
  • One is duplicated, but the other is not
If the remaining shape depends on the binding for its rendering, it may now be in an inconsistent state. For example, an arrow shape depends on the binding to know where the end of the arrow is. If the binding is removed, the arrow would suddenly point to the wrong location. Use isolation callbacks to update the shape based on the binding that’s about to be removed.
options
BindingOnShapeIsolateOptions<Binding>
required
binding
Binding
The binding record that refers to the shape.
removedShape
TLShape
The shape being removed. For deletion, this is the deleted shape. For copy/duplicate, this is the shape that isn’t being copied/duplicated and is getting left behind.

onBeforeIsolateToShape()

onBeforeIsolateToShape?(options: BindingOnShapeIsolateOptions<Binding>): void
Called before the shape referenced in a binding’s toId is about to be isolated from the shape referenced in fromId. See onBeforeIsolateFromShape for details about isolation.
options
BindingOnShapeIsolateOptions<Binding>
required
binding
Binding
The binding record that refers to the shape.
removedShape
TLShape
The shape being removed. For deletion, this is the deleted shape. For copy/duplicate, this is the shape that isn’t being copied/duplicated and is getting left behind.

Other methods

onOperationComplete()

onOperationComplete?(): void
Called whenever a store operation involving this binding type has completed. This is useful for working with networks of related bindings that may need to update together.

Example

import { BindingUtil, TLBinding } from '@tldraw/editor'

// Define a custom binding type
interface StickerBinding extends TLBinding {
  type: 'sticker'
  props: {
    position: { x: number; y: number }
  }
}

// Create a binding util for the sticker binding
class StickerBindingUtil extends BindingUtil<StickerBinding> {
  static override type = 'sticker'
  
  override getDefaultProps() {
    return {
      position: { x: 0.5, y: 0.5 }
    }
  }
  
  override onAfterChangeToShape({ binding, shapeAfter }) {
    // Update the sticker position when the bound shape moves
    const sticker = this.editor.getShape(binding.fromId)
    if (!sticker) return
    
    // Custom logic to reposition the sticker
    // ...
  }
  
  override onBeforeDeleteToShape({ binding }) {
    // Remove the sticker when the bound shape is deleted
    this.editor.deleteShapes([binding.fromId])
  }
}