Member Junction
    Preparing search index...

    The whiteboard engine: items + ordered render list, single selection, snapshot-based undo/redo (one entry per user gesture or per agent tool call via RunBatch), change journal + coalesced scene deltas, JSON persistence, and the cancelable BEFORE / AFTER mutation event surface.

    Every targeted mutation raises a cancelable BEFORE event and, when it applies, a matching AFTER event:

    Mutation Before (cancelable) After
    AddItem (incl. Highlight, DuplicateItem) ItemAdding$ ItemAdded$
    UpdateItem / MoveItem / BringToFront / SendToBack ItemUpdating$ ItemUpdated$
    UpdateItem touching content fields (Text / Label / Sub / Markdown / Html / Title) ContentChanging$ (after ItemUpdating$) ContentChanged$
    RemoveItem ItemRemoving$ ItemRemoved$
    AddPage PageAdding$ PageAdded$
    SwitchPage PageSwitching$ PageSwitched$
    RenamePage PageRenaming$ PageRenamed$
    RemovePage PageRemoving$ PageRemoved$
    Select (and implicit clears) SelectionChanged$
    Clear BoardCleared$
    LoadFromJSON BoardLoaded$

    Handlers run synchronously during the emit; setting Cancel = true on the event args aborts the mutation (the caller sees null / false) with no undo snapshot, journal entry or Changed$ emission. These events layer ALONGSIDE the existing Changed$ / journal / perception machinery — they never replace it. Undo / redo whole-scene replacements are NOT item mutations and only surface through Changed$ as 'replace' ops.

    Index

    Constructors

    Properties

    BoardCleared$: Observable<WhiteboardBoardClearedEventArgs> = ...

    AFTER event: Clear removed everything from the board (one undo step).

    BoardLoaded$: Observable<WhiteboardBoardLoadedEventArgs> = ...

    AFTER event: LoadFromJSON rehydrated a persisted board into this instance.

    Changed$: Observable<WhiteboardChange> = ...

    Fires after every mutation (including undo/redo 'replace' events).

    ContentChanged$: Observable<WhiteboardContentChangedEventArgs> = ...

    AFTER event: an item's content fields changed (markdown / html / text edits).

    ContentChanging$: Observable<WhiteboardContentChangingEventArgs> = ...

    Cancelable BEFORE event raised — in addition to ItemUpdating$ — when an UpdateItem patch touches CONTENT fields (Text / Label / Sub / Markdown / Html / Title). The dedicated hook for content governance: set Cancel = true synchronously to veto the whole update.

    ItemAdded$: Observable<WhiteboardItemAddedEventArgs> = ...

    AFTER event: an item was added (fires once per applied AddItem).

    ItemAdding$: Observable<WhiteboardItemAddingEventArgs> = ...

    Cancelable BEFORE event of AddItem (and Highlight / DuplicateItem, which add through it). Set Cancel = true synchronously to veto the add — AddItem then returns null and nothing changes.

    ItemRemoved$: Observable<WhiteboardItemRemovedEventArgs> = ...

    AFTER event: an item was removed from the board.

    ItemRemoving$: Observable<WhiteboardItemRemovingEventArgs> = ...

    Cancelable BEFORE event of RemoveItem. Set Cancel = true synchronously to keep the item — RemoveItem then returns false and nothing changes.

    ItemUpdated$: Observable<WhiteboardItemUpdatedEventArgs> = ...

    AFTER event: an item changed (patch applied / moved / z-reordered).

    ItemUpdating$: Observable<WhiteboardItemUpdatingEventArgs> = ...

    Cancelable BEFORE event of UpdateItem (Operation: 'update'), MoveItem ('move') and BringToFront / SendToBack ('reorder'). Set Cancel = true synchronously to veto — the mutator returns false.

    PageAdded$: Observable<WhiteboardPageAddedEventArgs> = ...

    AFTER event: a page was added (and became the active page).

    PageAdding$: Observable<WhiteboardPageAddingEventArgs> = ...

    Cancelable BEFORE event of AddPage. Set Cancel = true synchronously to veto — AddPage then returns null and nothing changes.

    PageRemoved$: Observable<WhiteboardPageRemovedEventArgs> = ...

    AFTER event: a page (and all of its items) was removed from the board.

    PageRemoving$: Observable<WhiteboardPageRemovingEventArgs> = ...

    Cancelable BEFORE event of RemovePage (never raised for the guarded last-page case). Set Cancel = true synchronously to keep the page.

    PageRenamed$: Observable<WhiteboardPageRenamedEventArgs> = ...

    AFTER event: a page was renamed.

    PageRenaming$: Observable<WhiteboardPageRenamingEventArgs> = ...

    Cancelable BEFORE event of RenamePage. Handlers may rewrite NewName; set Cancel = true synchronously to veto — RenamePage then returns false.

    PageSwitched$: Observable<WhiteboardPageSwitchedEventArgs> = ...

    AFTER event: the active page changed via SwitchPage.

    PageSwitching$: Observable<WhiteboardPageSwitchingEventArgs> = ...

    Cancelable BEFORE event of SwitchPage. Set Cancel = true synchronously to stay on the current page — SwitchPage then returns false.

    SelectionChanged$: Observable<WhiteboardSelectionChangedEventArgs> = ...

    AFTER event: the single selection changed — via Select or implicitly (the selected item was removed / dropped by a restore). Selection is transient UI state, so this is a notification only (never cancelable, never journaled).

    Accessors

    • get ActivePageID(): string

      ID of the active page (every item operation targets this page).

      Returns string

    • get ElementCount(): number

      ACTIVE-page "elements" as the status footer reports them (transient highlights excluded).

      Returns number

    • get SelectedID(): string

      The PRIMARY selected item's ID (the most recently selected member of the multi-selection), or null when nothing is selected. Selection is UI state — not persisted. For the full multi-selection see SelectedIDs.

      Returns string

    • get SelectedIDs(): string[]

      All selected item IDs in selection order (last = primary). Returns a copy.

      Returns string[]

    Methods

    • Add a new page and SWITCH to it. name is trimmed; when omitted (or blank) the page auto-names itself "Page N" from the monotonic page counter, so auto-names never repeat even after removals.

      Raises the cancelable PageAdding$ BEFORE event (handlers may rewrite the name) — returns null when vetoed; fires PageAdded$ after. One undoable step; journals a 'replace' op (the agent's visible scene swaps to the new, empty page), so perception consumers re-read the scene.

      Parameters

      Returns WhiteboardPageInfo

    • Pre-mutation bookkeeping shared by every committed mutation: pushes the undo snapshot (unless inside a RunBatch, which snapshotted at batch start) and invalidates the redo branch. Subclasses extending the mutation paths should call this exactly once per logical change, AFTER any cancelable before-event survived.

      Returns void

    • Raise an item above everything else. Follows the engine's existing Z handling: ++zCounter is by construction greater than every assigned Z (max + 1), exactly how AddItem stamps new items. Journals as an 'update'.

      Raises the cancelable ItemUpdating$ BEFORE event (Operation: 'reorder') — returns false when vetoed or the ID is unknown; fires ItemUpdated$ after.

      Parameters

      Returns boolean

    • Build the coalesced scene delta of everything that changed AFTER sinceToken (a previously observed CurrentSeq; defaults to 0 = everything).

      Coalescing: per item, the NET effect wins — N moves → one moved entry at the current position; add+move → one added entry (current state); add+remove → nothing; update+move → one updated entry. When the window contains a 'replace' (undo/redo/load) or the journal no longer reaches the token, the delta carries reset: true plus the full compact items array — replace-current-state semantics, never an append-only log.

      Parameters

      • sinceToken: number = 0

      Returns WhiteboardSceneDelta

    • Apply a SINGLE-or-clear selection change (legacy internal path).

      Parameters

      • next: string

      Returns void

    • Remove EVERYTHING from the ACTIVE page as ONE undoable operation (other pages are untouched). Journals a single 'replace' op (perception consumers re-read the now-empty scene) and fires BoardCleared$. Clears the selection (firing SelectionChanged$ when one existed). Returns false when the active page was already empty.

      Parameters

      Returns boolean

    • The page-aware scene sentence shared by every delta / summary tail line.

      Returns string

    • Compose the human-readable tail line of deltas / summaries ("2 added, 1 moved. …"), including which page is active and the full page list — so the model always knows pages exist and which one its item entries describe.

      Parameters

      • parts: {
            added?: number;
            moved?: number;
            removed?: number;
            reset?: boolean;
            updated?: number;
        }

      Returns string

    • Duplicate an item: a DEEP clone (ink points included) with a fresh engine-stamped identity, offset +16/+16 from the source so the copy is visibly distinct. Connectors (which reference other items) and transient highlights cannot be duplicated — returns null without mutating. The clone lands through AddItem, so it journals as a normal 'add', is one undo step, and raises the ItemAdding$ / ItemAdded$ pair (a canceled add also returns null).

      Parameters

      Returns WhiteboardItem

    • Whether an item is part of the current (single or multi) selection.

      Parameters

      • id: string

      Returns boolean

    • All ACTIVE-page items whose axis-aligned bounds intersect the given rectangle — the marquee (rubber-band) hit test, in render order. Transient highlight regions are excluded: they are "pointing" chrome dismissed by click, never selected. Edge-touching items (zero overlap area) do NOT count as intersecting.

      Parameters

      Returns WhiteboardItem[]

    • Rehydrate THIS instance in place from ToJSON output — used by the channel's RestoreState hook so existing subscriptions (perception feed, save pipeline) and any bound surface keep pointing at the same engine. TOLERANT: malformed input returns false and leaves the current state untouched (never throws).

      On success the undo/redo stacks and journal are cleared (restored state is the new baseline), stale delta tokens force reset semantics, one 'replace' change is emitted so consumers re-read the full scene, and BoardLoaded$ fires.

      Parameters

      • json: string

      Returns boolean

    • Move an item to an absolute board position. Positioned kinds move their origin; ink strokes translate every point; connectors translate their floating endpoints.

      Raises the cancelable ItemUpdating$ BEFORE event (Operation: 'move', Position = the requested top-left) — returns false when vetoed or the ID is unknown; fires ItemUpdated$ after an applied move.

      Parameters

      Returns boolean

    • Move EVERY selected item by the same delta as ONE undo step (the multi-select group drag). Internally one RunBatch of per-item MoveItem calls, so each member still raises its own cancelable 'move' BEFORE event (a veto skips just that member) and journals normally — but a single Undo reverts the whole group move. Returns how many items actually moved (0 when nothing is selected or the delta is 0).

      Parameters

      Returns number

    • Push the current scene onto the undo stack (bounded) and drop the redo branch.

      Returns void

    • Re-apply the most recently undone snapshot. Emits a 'replace' change.

      Returns boolean

    • Remove an item. Connectors that referenced it survive: their endpoint freezes to the removed item's last center (the floating-endpoint fallback).

      Raises the cancelable ItemRemoving$ BEFORE event — returns false when vetoed or the ID is unknown; fires ItemRemoved$ after an applied removal.

      Parameters

      Returns boolean

    • Remove a page AND all of its items (tolerant lookup, same as SwitchPage). The LAST remaining page can never be removed (false, no events). Removing the ACTIVE page activates a neighbor — the next page when one exists, otherwise the previous one.

      Raises the cancelable PageRemoving$ BEFORE event — returns false when vetoed or the page is unknown; fires PageRemoved$ after (with the activated neighbor when the active page was removed). One undoable step; journals a 'replace' op.

      Parameters

      Returns boolean

    • Remove EVERY selected item as ONE undo step (the multi-select Delete key). One RunBatch of per-item RemoveItem calls — each member still raises its cancelable ItemRemoving$ BEFORE event (a veto keeps just that member), and a single Undo restores the whole group. The selection empties as items are removed. Returns how many items were actually removed.

      Parameters

      Returns number

    • Rename a page (tolerant lookup, same as SwitchPage). The new name is trimmed; an empty result returns false. Renaming to the current name is a successful no-op (no events, no journal entry).

      Raises the cancelable PageRenaming$ BEFORE event (handlers may rewrite NewName) — returns false when vetoed; fires PageRenamed$ after. One undoable step; journals a 'replace' op so the agent's page list stays current.

      Parameters

      Returns boolean

    • Swap the whole board to a snapshot's pages/counters (drops a now-missing selection; an unknown active-page id falls back to the first page; an empty page list gains a fresh "Page 1" so the engine never runs page-less).

      Parameters

      • snap: WhiteboardStateJSON

      Returns void

    • Run several mutations as ONE undo step (one snapshot). Used per agent tool call and for compound user gestures, so the toast's "Undo" reverts the whole tool effect at once.

      Type Parameters

      • T

      Parameters

      • fn: () => T

      Returns T

    • Set (or clear) the selection to a SINGLE item. Unknown IDs clear the selection. Fires SelectionChanged$ when the effective selection actually changes.

      Parameters

      • id: string

      Returns void

    • Replace the selection with a set of items (the marquee result). Unknown IDs are dropped and duplicates collapse to their first occurrence; order is preserved (the last surviving entry becomes the primary selection). An empty / fully-unknown list clears the selection.

      Parameters

      • ids: string[]

      Returns void

    • Deep-copied serializable snapshot of the WHOLE board — every page's items plus the page structure and counters (undo entries / ToJSON). Page items serialize in render order (ascending Z).

      Returns WhiteboardStateJSON

    • Make another page the active page. Tolerant lookup: exact ID first, then case-insensitive name (see FindPage). Switching to the already-active page is a successful no-op (no events, no journal entry).

      Raises the cancelable PageSwitching$ BEFORE event — returns false when vetoed or the page is unknown; fires PageSwitched$ after. Journals a 'replace' op (the visible scene swaps wholesale) but deliberately pushes NO undo snapshot — switching is navigation, not a content mutation.

      Parameters

      Returns boolean

    • Toggle one item's membership in the multi-selection WITHOUT clearing the rest — the shift-click semantics. A newly added item becomes the primary selection (SelectedID); unknown IDs are a no-op.

      Parameters

      • id: string

      Returns void

    • Serialize the board (state of record — persisted as the session-channel artifact). Emits the VERSION 2 paged shape (see WhiteboardStateJSON); the legacy flat shape is still accepted on load and rehydrates as a single page "Page 1".

      Returns string

    • Restore the previous snapshot. Emits a 'replace' change.

      Returns boolean

    • Rehydrate a board from ToJSON output — BOTH shapes accepted: the current paged shape (version 2) and the legacy flat shape (version 1, items at the root), which migrates to one page named "Page 1". Throws on malformed input (use LoadFromJSON or ParseBoardStateJson for the tolerant variants).

      Parameters

      • json: string

      Returns WhiteboardState