SDK ReferenceWorkspace API

Workspace API

The Workspace class is the core engine orchestrating events, DOM mounting, and overlay drawing. It is the primary public entry point for consumer integrations.

Constructor

import { Workspace } from '@canvus/core'
 
const ws = new Workspace(container: HTMLElement, callbacks?: WorkspaceCallbacks, config?: WorkspaceConfig)
ParameterTypeDescription
containerHTMLElementThe host DOM element to mount the workspace into
callbacksWorkspaceCallbacksOptional event callbacks (see Configuration)
configWorkspaceConfigOptional configuration overrides (see Configuration)

Node Management

addNode(node, parentId?, index?)

Mounts a node into the Shadow DOM, updates the tree hierarchy model, measures bounds, and triggers a layout repaint.

addNode(node: Readonly<WebHTMLNode>, parentId?: string | null, index?: number): Rect

Returns: Measured canvas-space bounds of the mounted node.

const rect = ws.addNode({
  id: 'card-1',
  rawMarkup: '<div class="card">Content</div>',
  currentRect: { x: 100, y: 100, width: 300, height: 200 },
}, null, 0)  // root level, first position

removeNode(id)

Removes a node and all of its descendants from the DOM mount and the internal tree tracker.

removeNode(id: string): boolean

updateMarkup(id, markup)

Updates a node’s inner HTML, recalculates layout, and triggers a repaint.

updateMarkup(id: string, markup: string): Rect | null

Clipboard & Deletion

deleteSelectedNode()

Deletes the currently selected node (if selection size is 1) from the workspace. Automatically generates a delete-node operation and commits the parent’s new HTML.

deleteSelectedNode(): void

duplicateSelectedNode()

Duplicates the selected node right next to it as a sibling. Generates a create-node operation and commits the parent’s HTML.

duplicateSelectedNode(): void

copySelectedNode()

Copies the selected node’s markup and bounds to the internal clipboard.

copySelectedNode(): void

cutSelectedNode()

Cuts the selected node to the clipboard, removing it from the canvas.

cutSelectedNode(): void

pasteNode()

Pastes the node currently in the clipboard into the canvas. Resolves the location based on current selection: pastes inside a selected container, or as a sibling right after a selected leaf node.

pasteNode(): void

Style Manipulation

setNodeStyle(id, property, value)

Mutates a CSS property on the node content element inside the Shadow DOM, triggers layout measurements, and commits changes.

setNodeStyle(id: string, property: string, value: string | null): void

setNodeStyles(id, styles)

Batches style changes to limit reflow costs.

setNodeStyles(id: string, styles: Record<string, string | null>): void
ws.setNodeStyles('card-1', {
  'padding': '24px',
  'background-color': '#f0f0f0',
  'border-radius': '12px',
})

Class Manipulation

addClass(id, className)

Appends a CSS class name, triggers reflow checks, and generates an update-classes operation.

addClass(id: string, className: string): void

removeClass(id, className)

Removes a class name, triggers reflow, and emits an update-classes operation.

removeClass(id: string, className: string): void

toggleClass(id, className)

Toggles a CSS class name.

toggleClass(id: string, className: string): void

Tree Operations

reparentNode(nodeId, newParentId, index?)

Moves a node wrapper to a new parent in both the Shadow DOM tree and the tree model.

reparentNode(nodeId: string, newParentId: string | null, index?: number): void

reorderChild(nodeId, newIndex)

Reorders a node inside its parent, updating sibling arrangements.

reorderChild(nodeId: string, newIndex: number): void

getNodeTree()

Returns the active structural tree database container.

getNodeTree(): NodeTree

Operations

applyOperation(op)

Replays a serialized action payload back onto the workspace. Used to trigger Undo/Redo state actions.

applyOperation(op: Operation): void

See the Operations Guide for details on the operation schema and undo/redo patterns.


Selection

selectNode(id)

Sets selection to a single node.

selectNode(id: string): void

deselectAll()

Clears active selection sets.

deselectAll(): void

getSelectedIds()

Returns active node selections.

getSelectedIds(): ReadonlySet<string>

Viewport

getViewport()

Gets the current zoom scale and translation panning offsets.

getViewport(): Readonly<ViewportMatrix>

setViewport(vp)

Forces a viewport update.

setViewport(vp: ViewportMatrix): void

resetViewport()

Resets the workspace scale to 1:1 and offsets to 0,0.

resetViewport(): void

Query Methods

getNodes()

Returns a flat array of all registered nodes in topological order.

getNodes(): ReadonlyArray<Readonly<ResolvedNode>>

getWrapper(id)

Returns the wrapper element of the specified node.

getWrapper(id: string): HTMLElement | null

extractHTML(id)

Flat String Bridge. Exports clean, unpolluted HTML strings of target subtrees (stripping wrapper elements).

extractHTML(id: string): string | null

measureAll()

Forces a synchronous layout read of all elements.

measureAll(): Map<string, Rect>

getContentRoot(id)

Returns the user’s content root element (the first child inside the SDK wrapper) for a given node ID. Useful for advanced DOM inspection or custom editor mounting.

getContentRoot(id: string): HTMLElement | null

computeAggregateBounds(nodes)

Utility function (exported from tree.ts) that computes a single bounding rectangle encompassing all provided nodes. Returns null if no nodes have measured rects.

import { computeAggregateBounds } from '@canvus/core'
 
const bounds = computeAggregateBounds(ws.getNodes())
// { x, y, width, height } or null

Preview Mode

setPreviewMode(enabled)

Toggles the workspace between Edit Mode and Preview Mode. In Preview Mode, all editing overlays (selection, handles, spacing adjusters) are hidden, pointer events pass through to the Shadow DOM content, and interactive elements behave normally (links, buttons, forms).

setPreviewMode(enabled: boolean): void
// Enter preview mode — user can interact with content natively
ws.setPreviewMode(true)
 
// Return to edit mode — selection and resize handles re-appear
ws.setPreviewMode(false)

Entering Preview Mode automatically clears the current selection, hover state, and any active interaction gesture.

isPreviewMode()

Returns whether the workspace is currently in Preview Mode.

isPreviewMode(): boolean

Drawing Tools

setActiveTool(tool)

Sets the active drawing tool ("box", "text", or null to return to selection/idle mode). Selecting a drawing tool automatically deselects all nodes and changes the workspace cursor to crosshair.

setActiveTool(tool: CanvusTool): void

getActiveTool()

Returns the currently active drawing tool.

getActiveTool(): CanvusTool

setDrawingTag(tag)

Customizes the HTML tag type for box or text drawing.

setDrawingTag(tag: string): void

getDrawingTag()

Returns the active drawing tag based on the selected tool.

getDrawingTag(): string

State Forcing

forceNodeState(nodeId, state, enabled)

Forces a CSS pseudo-class state (hover, active, or focus) on the specified node element. This injects/removes a .canvus-state-hover, .canvus-state-active, or .canvus-state-focus class on the content root.

Useful in Electron environments where the SDK overlay blocks native :hover from reaching content elements.

forceNodeState(nodeId: string, state: "hover" | "active" | "focus", enabled: boolean): void
// Force hover state on a button for visual preview
ws.forceNodeState('btn-1', 'hover', true)
 
// Remove forced hover
ws.forceNodeState('btn-1', 'hover', false)

To delegate pseudo-class forcing to the host (e.g., via Chrome DevTools Protocol in Electron), use the onForcePseudoState callback. See Configuration.


JS Badge Marking

markNodeHasJS(nodeId)

Explicitly marks a node as containing JavaScript behavior. When the node is selected, the canvas overlay renders a specialized amber ⚡️ JS badge next to the layout badge.

The host application calls this based on its own analysis (static analysis, CDP, source maps) rather than the SDK auto-detecting scripts.

markNodeHasJS(nodeId: string): void

unmarkNodeHasJS(nodeId)

Removes the JavaScript badge from a node.

unmarkNodeHasJS(nodeId: string): void

hasJSMark(nodeId)

Returns whether a node is flagged as containing JavaScript behavior.

hasJSMark(nodeId: string): boolean
// Flag node as having JS after executing its scripts
ws.markNodeHasJS('interactive-widget')
 
// Check status
if (ws.hasJSMark('interactive-widget')) {
  console.log('Node has JS badge')
}
 
// Remove the flag
ws.unmarkNodeHasJS('interactive-widget')

Synthetic Interaction

dispatchInteractionEvent(nodeId, eventName)

Dispatches a synthetic pointer/mouse event (e.g., mouseenter, mouseleave, click, dblclick) to a node’s content root element inside the Shadow DOM.

Useful for programmatically triggering element behaviors without requiring actual user pointer gestures.

dispatchInteractionEvent(nodeId: string, eventName: string): void
// Simulate a click on an interactive element
ws.dispatchInteractionEvent('btn-1', 'click')
 
// Simulate hover entry/exit
ws.dispatchInteractionEvent('card-1', 'mouseenter')
ws.dispatchInteractionEvent('card-1', 'mouseleave')

Stylesheet Injection

injectCSS(css)

Injects a CSS string into the Shadow DOM as a scoped <style> block. Automatically rewrites :root, html, and body selectors to :host for proper Shadow DOM scoping.

injectCSS(css: string): HTMLStyleElement
ws.injectCSS(`
  .card { padding: 24px; border-radius: 12px; }
  .btn { background: #6366f1; color: white; }
`)

injectCSSLink(href)

Loads an external stylesheet into the Shadow DOM as a <link> element. Returns a promise that resolves when the stylesheet has loaded.

injectCSSLink(href: string): Promise<HTMLLinkElement>
await ws.injectCSSLink('https://cdn.example.com/styles.css')

Subsystem Access

getShadowMount()

Exposes the inner open Shadow Root mounting subsystem.

getShadowMount(): ShadowMount

getOverlayRenderer()

Exposes the inner 2D canvas overlay painter.

getOverlayRenderer(): OverlayRenderer

Lifecycle

dispose()

Cleans up window resize, wheel, and mouse gesture event listeners.

dispose(): void
⚠️

Always call dispose() when unmounting the workspace to prevent memory leaks from orphaned event listeners.