New headless components:
- CanvasRoot — provides canvas context, initializes surface + render loop
- CanvasSurface — bare <canvas> element, receives ref from CanvasRoot
SkiaRenderer.renderFromEditorState() — single method replaces 30-line
state sync in use-canvas.ts. Takes EditorState + graph + textEditor
directly, sets all renderer properties and calls render().
Example app updated to use CanvasRoot/CanvasSurface, ToolbarRoot/
ToolbarItem, PageListRoot instead of old monolithic components.
Renderless components (Reka UI-style) exposing editor logic via slots:
- OpenPencilProvider — injects editor via Vue provide/inject
- OpenPencilCanvas — CanvasKit/Skia surface with render loop
- PageList, LayerTree, ToolSelector, NodeProperties — slot-based
Composables:
- useEditor() — access editor from any descendant
- useCanvas() — low-level surface lifecycle (moved from app)
The app's use-canvas.ts is now a 2-line re-export from the SDK.
Includes example app in packages/vue/example/.