@layera-labs/orbit-model
v1.0.0-beta.4
Published
Headless reactive document model for the Orbit canvas editor SDK
Maintainers
Readme
@layera-labs/orbit-model
The document model for the Orbit canvas editor: a reactive store holding pages, elements, selection, viewport and history. Headless — no React, no canvas, no DOM.
This is v2, the current line. @layera-labs/orbit-model, @layera-labs/orbit-render,
@layera-labs/orbit-providers and @layera-labs/orbit-editor are one stack. The older
@layera-labs/orbit-core / @layera-labs/orbit-react packages are v1 legacy; see the note at the
bottom before you pick.
npm i @layera-labs/orbit-model@betaBeta.
1.0.0-beta.3under thebetatag; the API moves without notice. The package itself has no React dependency, but the stack it belongs to is React 18 only — see@layera-labs/orbit-renderfor why.
The store
createStore() returns an OrbitStore whose state is a Valtio
proxy. Mutations are ordinary property writes; the renderer and the UI re-read from a
snapshot. Every public method records an undo step.
import { createStore, snapshot } from '@layera-labs/orbit-model';
const store = createStore({ width: 1080, height: 1080 });
const id = store.addElement({
type: 'text',
text: 'Orbit',
x: 80,
y: 120,
fontSize: 64,
});
store.updateElement(id, { fill: '#c25b3a' });
store.select([id]);
store.undo(); // back to the black text
store.canRedo; // true
const doc = store.toJSON(); // a plain Document. A template IS this shape
store.loadJSON(doc); // replaces the document, resets history and selectionTransactions are how you avoid a hundred undo steps
A drag that fires sixty pointer moves should be one entry in the history, not sixty.
transaction coalesces everything inside it into a single undo step:
store.transaction(() => {
for (const id of ids) store.updateElement(id, { x: nextX(id), y: nextY(id) });
});Two ways to observe
const off = store.subscribe(() => draw(snapshot(store.state))); // any change
const offSel = store.on('selectionChange', (s) => inspect(s.selection));subscribe is the low-level Valtio hook and fires on everything. on is the
imperative event API for SDK consumers and names what changed. In React, bind with
Valtio's useSnapshot(store.state) rather than either.
What else it does
Pages (addPage, duplicatePage, reorderPages, renamePage, resizePage,
setBackground), z-order (bringToFront, sendBackward, moveElement), grouping
(group, ungroup — getElement searches into groups), alignment and distribution
(alignToPage, alignSelection, distribute), and applyAction, which applies one
or more declarative CanvasActions atomically. applyAction is the seam an AI layer
writes through, so an agent's edit is one undoable step like any other.
fromPolotnoJSON imports a Polotno document.
migrateSceneGraphToDocument converts a v1 SceneGraph from @layera-labs/orbit-shared.
What it does not do
It does not render. It does not know what a Konva node is, or what a font file is, or
how to search for a photo. Those are @layera-labs/orbit-render and
@layera-labs/orbit-providers. It also has nothing to do with video — the video timeline is
a different document kind entirely, in
@layera-labs/orbit-video,
and merging the two was considered and rejected.
Links
- Repository
- docs/architecture-v2.md — the v2 spec
MIT.
