Editable custom shape
A custom shape that becomes interactive when you double-click it.
import { Tldraw } from 'tldraw'
import 'tldraw/tldraw.css'
import { EditableShapeUtil } from './EditableShapeUtil'
const customShapeUtils = [EditableShapeUtil]
export default function EditableShapeExample() {
return (
<div className="tldraw__editor">
<Tldraw
// Pass in the array of custom shape classes
shapeUtils={customShapeUtils}
// Create a shape when the editor mounts
onMount={(editor) => {
editor.createShape({ type: 'my-editable-shape', x: 100, y: 100 })
}}
/>
</div>
)
}
/*
Introduction:
In tldraw, shapes can exist in an editing state. When shapes are in the editing state
they are focused and can't be dragged, resized or rotated. Shapes enter this state
when they are double-clicked. In our default shapes we mostly use this for editing text.
In this example we'll create a shape that renders an emoji and allows the user to change
the emoji when the shape is in the editing state.
Most of the relevant code for this is in the EditableShapeUtil.tsx file. If you want a more
in-depth explanation of the shape util, check out the custom shape example.
*/
The editor has at most one editing shape at a time. While a shape is being edited it can't be dragged, resized, or rotated, and pointer events reach its content. Only shapes whose util returns true from canEdit can enter this state; the user gets there by double-clicking the shape or selecting it and pressing Enter, and leaves it with Escape or by clicking the canvas.
The default shapes mostly use editing for text, but it's a general mechanism. This example's shape shows an emoji, and while editing it shows a button that cycles to the next emoji with editor.updateShape. The component reads editor.getEditingShapeId() to decide what to render, turns on pointerEvents only while editing, and marks pointer-down events as handled so clicking the button doesn't start a drag. onEditEnd spins the shape when editing finishes.
Try double-clicking the shape, clicking Next a few times, then pressing Escape. The relevant code is in EditableShapeUtil.tsx; for a walkthrough of the shape util basics, see the custom shape example.