Prevent shape changes

Reject changes to a shape's position, rotation, and size while still allowing style and text edits.

import { Tldraw, toRichText } from 'tldraw'
import 'tldraw/tldraw.css'

export default function PreventShapeChangeExample() {
	return (
		<div className="tldraw__editor">
			<Tldraw
				onMount={(editor) => {
					editor.createShape({
						type: 'geo',
						x: 100,
						y: 100,
						props: {
							w: 300,
							h: 300,
							richText: toRichText("style me but don't transform me"),
						},
					})

					// Unlike locking the shape, rejecting transforms here leaves it selectable and editable.
					editor.sideEffects.registerBeforeChangeHandler('shape', (prev, next) => {
						if (
							editor.isShapeOfType(prev, 'geo') &&
							editor.isShapeOfType(next, 'geo') &&
							next.props.geo === 'rectangle'
						) {
							if (
								next.x !== prev.x ||
								next.y !== prev.y ||
								next.rotation !== prev.rotation ||
								next.props.w !== prev.props.w ||
								next.props.h !== prev.props.h
							) {
								return prev
							}
						}
						return next
					})
				}}
			/>
		</div>
	)
}

editor.sideEffects.registerBeforeChangeHandler sees every proposed shape change and returns the record that will be written. This example compares prev and next for geo rectangles and returns prev (cancelling the change) if x, y, rotation, props.w, or props.h would differ. Other changes pass through untouched.

Try dragging, rotating, or resizing the rectangle: nothing happens. Now change its color or edit its label: that works. This is a finer-grained alternative to isLocked, which would also stop the shape being selected. A rejected change is silent, so consider giving the user some feedback if this is a real permission rule.

Is this page helpful?
Prev
Prevent instance changes
Next
Prevent multi-shape selection