Canvas
A freehand drawing surface — pen, two eraser modes, resizable text, and six shape tools, each with independent color and fill pickers. A pure widget block like Embed or Divider: contentIds is always empty, and everything lives in props.
Toolbar
| Tool | What it does |
|---|---|
| Pen | Freehand strokes, pressure-aware where the input device reports pressure. |
| Eraser | Two modes, in a popover: Object (removes a whole stroke/shape on contact) and Precise (erases only the part of a stroke actually under the cursor). |
| Select | Move, resize, and rotate existing strokes/shapes/text; also exposes Bring to front / Send to back for overlapping shapes. |
| Text | Drop resizable text anywhere on the canvas, with its own font-size control. |
| Shape | Rectangle, Ellipse, Arrow, Diamond, Triangle, Star — one popover, remembers the last shape you used. |
| Color / Fill | Swatch pickers plus a custom-color swatch for stroke and fill independently; shapes support "no fill" (outline only). |
| Stroke size | Line/shape-outline thickness. |
| Zoom | Zoom in / reset to 100% / zoom out, for working on a larger drawing than the block's own rendered size. |
| Export as PNG | Rasterizes the current drawing to a downloadable PNG, independent of the document's own SVG export (see Export below). |
JSON shape
{
"id": "c1",
"type": "canvas",
"contentIds": [],
"props": {
"strokes": [
{ "id": "s1", "color": "#6c5ce7", "size": 4, "points": [[100, 100, 0.6], [140, 160, 0.7]] }
],
"shapes": [
{ "id": "sh1", "type": "rect", "x": 300, "y": 60, "width": 160, "height": 100, "color": "#1971c2", "strokeWidth": 2 }
],
"width": 480,
"height": 320
}
}| Prop | Type | Notes |
|---|---|---|
strokes | { id, points, color, size }[] | Freehand pen strokes. points is an array of [x, y, pressure] triples. |
shapes | { id, type, ... }[] | type is one of rectangle, ellipse, diamond, triangle, star, or arrow. Every type except arrow shares { type, x, y, width, height, color, strokeWidth, fillColor? }; arrow instead uses { type: 'arrow', x1, y1, x2, y2, color, strokeWidth }. The arrowhead itself is derived at render/export time, not stored. fillColor is omitted (renders as outline-only) when the "no fill" option was chosen. |
width / height | number | The block's own rendered pixel size, default 480 × 320. Resizable by dragging, like Embed. |
width/height — resizing the canvas changes how big that fixed space is drawn, it never touches or rescales the stroke/shape data itself.Using it in your editor
useEditor() registers every built-in block by default, canvas included — most apps need nothing extra here. Canvas is a single block type — no companion group like Table's TABLE_BLOCKS — so register it on its own if opting in manually:
import { useEditor, NoteloomEditor, registerBlocks, paragraphBlockType, canvasBlockType } from 'noteloom';
function Editor() {
const editor = useEditor({
registerBlocks: (registry) => registerBlocks(registry, { paragraph: paragraphBlockType, canvas: canvasBlockType }),
});
return <NoteloomEditor editor={editor} />;
}See Picking only the blocks you want for combining this with other types.
canvasBlockType requires a noteloom version where it's exported from the package root — if it imports as undefined, update noteloom, or use registerBuiltInBlocks in the meantime (it already wires canvas in internally, opt-in or not).Export
A canvas bakes down to a self-contained inline <svg> as part of the document's normal HTML export (toHTML / exportDocumentHTML / clipboard copy) — no canvas-to-image conversion step, and no extra asset to host. An empty canvas (no strokes or shapes yet) exports as an empty <p></p>, the same convention Embed uses for "nothing meaningful here yet."
Known limitations (v1)
- No plain-text representation —
toPlainTextreturns an empty string, the same as a divider's decorative"---". There is no OCR or auto-generated description of what was drawn. - A canvas can only be created via its own slash command. Pasting foreign SVG markup back in doesn't reverse-parse into editable stroke/shape data (reconstructing normalized points from arbitrary path
ddata is out of scope) — it falls through to whatever the paste pipeline does for an unrecognized node.
Slash command
Canvas — keywords: canvas, draw, drawing, sketch, freehand.
Styling
.be-canvas-toolbar and its .be-canvas-toolbar-btn/.be-canvas-picker family style the pen/eraser/text/shape/color controls — all covered by the default theme (Theming & styling) like every other block.