Svelte
Use CanvasFlow in Svelte 3, 4 or 5 with an action that mounts the canvas and stores that follow the editor.
Svelte components are compiled, so canvasflow/svelte does not ship one. It gives you what Svelte is best at instead: an action that mounts the canvas into any element, and stores that follow the editor. It works with Svelte 3, 4 and 5 and needs no peer, because the stores follow Svelte's store contract.
A board in a few lines#
<script>
import { createFlow } from 'canvasflow/svelte'
const flow = createFlow()
</script>
<div use:flow.action={{ persistenceKey: 'board' }} style="height: 100vh"></div>
createFlow() makes one canvas for the component. Its action mounts the canvas and the default UI into the element and removes them when the element goes away. Give the element a height, because an editor needs room.
Options#
The action takes everything createCanvasFlow accepts (persistenceKey, dir, readonly, themes, plugins, shapes, tools, storageā¦), plus:
| Option | What it does |
|---|---|
ui |
false for no default UI, or an object that configures it (see Customizing the UI). |
onMount |
Called once with (editor, app, ui). Return a function and it runs as a cleanup. |
Options are read once, when the canvas mounts. dir and readonly follow later changes, so use:flow.action={{ dir }} follows a variable.
Follow the editor#
flow.value(selector) returns a store of any value of the editor. It is undefined until the canvas has mounted, and it updates only when the result changes.
<script>
import { createFlow } from 'canvasflow/svelte'
const flow = createFlow()
const selected = flow.value((editor) => editor.getSelectedIds().length)
const shapes = flow.value((editor) => editor.getCurrentPageShapes().length)
</script>
<div use:flow.action={{ persistenceKey: 'board' }} style="height: 100vh"></div>
<p>{$selected ?? 0} selected of {$shapes ?? 0}</p>
flow.editor, flow.app and flow.ui are stores too (null until mounted). flow.on('tool', handler) listens to an event for as long as the canvas is mounted. flowStores(flow) returns ready-made stores for selectedIds, tool, camera, canUndo, canRedo, theme and direction.
Headless#
createFlowCanvas() is the same without the default UI, and never references it, so your bundle does not carry the toolbar. Build your own:
<script>
import { createFlowCanvas, flowStores } from 'canvasflow/svelte'
const flow = createFlowCanvas()
const editor = flow.editor
const { tool, canUndo } = flowStores(flow)
const tools = ['select', 'draw', 'rectangle', 'arrow', 'text']
</script>
<div role="toolbar">
{#each tools as id}
<button aria-pressed={$tool === id} on:click={() => $editor?.setTool(id)}>{id}</button>
{/each}
<button disabled={!$canUndo} on:click={() => $editor?.undo()}>Undo</button>
</div>
<div use:flow.action style="height: 100vh"></div>
See Building your own UI for the full tour.
SvelteKit and server rendering#
Actions run in the browser, so nothing renders on the server. The element is an empty box until the page runs, and importing canvasflow/svelte on a server is safe.