Selection and interaction
Selection modes, box selection, and the interaction state machine.
Selection and interaction are how users communicate with the board. Select nodes to act on them, drag to move, resize from handles, and box-select on empty canvas.
Current interaction
Selection
Nothing selected yet.
Selecting nodes
engine.select(nodeId) // replace selection
engine.select([nodeA, nodeB]) // replace with multiple
engine.select(nodeId, 'append') // add to selection
engine.select(nodeId, 'toggle') // flip in/out
engine.selectAll() // all visible nodes
engine.clearSelection() // deselect everything
const selected = engine.getSelection() // NodeId[]| Mode | Behavior |
|---|---|
'replace' | Clears existing selection, selects the given IDs (default). |
'append' | Adds IDs to the existing selection. |
'toggle' | Flips each ID in/out of the selection. |
Keyboard shortcuts: ⌘ + A to select all, Escape to deselect.
In Vue, use the useBoardSelection() composable for reactive access:
<script setup lang="ts">
const selection = useBoardSelection()
// selection.value is readonly NodeId[]
</script>Interaction state machine
The engine tracks pointer interactions through six modes. Only one mode is active at a time.
n, ne, e, se, s, sw, w, nw). Hold Shift for aspect-ratio locking.
The default Vue handles are also keyboard-operable: focus a handle and use the
arrow keys to move its active edge by one grid step, or hold Shift for a
major-grid step.createBoardEngine({ boxSelect: { behavior: 'contain' | 'intersect' } }).Enter with one text node selected, or choosing Edit in the selection toolbar. The built-in BoardNode shows a <textarea> overlay. File, link, and group renderers own any custom editing UI they provide.Pointer event flow
When a pointer event hits BoardRoot:
- Middle mouse / Space starts panning.
- Resize handle selects the node, then starts resizing after the drag threshold.
- Node selects the node, then starts dragging after the drag threshold.
- Empty canvas clears selection, then starts a box-selection session after the drag threshold.
Pointer movement is throttled through requestAnimationFrame and translated by BoardRoot; the low-level start, update, commit, and cancellation methods are absent from the normal engine API and available only through the unsupported first-party framework ABI. Pointer up commits the session, while pointer cancellation or Escape restores its starting geometry.
BoardRoot handles two-finger pinch gestures on touch devices automatically.Implementation detail
Text editing commands
BoardRoot exclusively owns pointer sessions. Applications can still control
the meaningful text-edit boundary directly:
engine.beginTextEdit(nodeId)
engine.commitTextEdit(nodeId, 'New text')
engine.cancelTextEdit()Implementation detail
Interaction events
engine.on('interaction:start', (state) => console.log('Started:', state.mode))
engine.on('interaction:update', (state) => {
/* high-frequency during drag */
})
engine.on('interaction:end', (state) => console.log('Ended:', state.mode))