tldraw/apps/examples/src/17-shape-meta/ShapeMetaExample.tsx
Steve Ruiz fd29006538
[feature] add meta property to records (#1627)
This PR adds a `meta` property to shapes and other records.

It adds it to:
- asset
- camera
- document
- instance
- instancePageState
- instancePresence
- page
- pointer
- rootShape

## Setting meta

This data can generally be added wherever you would normally update the
corresponding record.

An exception exists for shapes, which can be updated using a partial of
the `meta` in the same way that we update shapes with a partial of
`props`.

```ts
this.updateShapes([{
    id: myShape.id,
    type: "geo",
    meta: { 
      nemesis: "steve",
      special: true
    }
])
```

## `Editor.getInitialMetaForShape`

The `Editor.getInitialMetaForShape` method is kind of a hack to set the
initial meta property for newly created shapes. You can set it
externally. Escape hatch!

### Change Type

- [x] `minor` — New feature

### Test Plan

todo

- [ ] Unit Tests (todo)

### Release Notes

- todo
2023-06-28 14:24:05 +00:00

49 lines
1.3 KiB
TypeScript

import { TLShape, Tldraw, track, useEditor } from '@tldraw/tldraw'
import '@tldraw/tldraw/tldraw.css'
export default function ShapeMetaExample() {
return (
<div className="tldraw__editor">
<Tldraw
persistenceKey="shape_meta_example"
autoFocus
onMount={(editor) => {
editor.getInitialMetaForShape = (shape) => {
return { label: `My ${shape.type} shape` }
}
}}
>
<ShapeLabelUiWithHelper />
</Tldraw>
</div>
)
}
// By default, the TLShape type's meta property is { [key: string]: any }, but we can type it
// by unioning the type with a new type that has a meta property of our choosing.
type ShapeWithMyMeta = TLShape & { meta: { label: string } }
export const ShapeLabelUiWithHelper = track(function ShapeLabelUiWithHelper() {
const editor = useEditor()
const onlySelectedShape = editor.onlySelectedShape as ShapeWithMyMeta | null
if (!onlySelectedShape) {
return null
}
function onChange(e: React.ChangeEvent<HTMLInputElement>) {
if (onlySelectedShape) {
const { id, type, meta } = onlySelectedShape
editor.updateShapes<ShapeWithMyMeta>([
{ id, type, meta: { ...meta, label: e.currentTarget.value } },
])
}
}
return (
<div style={{ position: 'absolute', zIndex: 300, top: 64, left: 12 }}>
shape label: <input value={onlySelectedShape.meta.label} onChange={onChange} />
</div>
)
})