@memberjunction/ng-whiteboard 0.0.1 → 5.42.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +302 -28
  2. package/dist/lib/whiteboard-agent-sees-popover.component.d.ts +31 -0
  3. package/dist/lib/whiteboard-agent-sees-popover.component.d.ts.map +1 -0
  4. package/dist/lib/whiteboard-agent-sees-popover.component.js +132 -0
  5. package/dist/lib/whiteboard-agent-sees-popover.component.js.map +1 -0
  6. package/dist/lib/whiteboard-board.component.d.ts +458 -0
  7. package/dist/lib/whiteboard-board.component.d.ts.map +1 -0
  8. package/dist/lib/whiteboard-board.component.js +2357 -0
  9. package/dist/lib/whiteboard-board.component.js.map +1 -0
  10. package/dist/lib/whiteboard-context-menu.d.ts +57 -0
  11. package/dist/lib/whiteboard-context-menu.d.ts.map +1 -0
  12. package/dist/lib/whiteboard-context-menu.js +69 -0
  13. package/dist/lib/whiteboard-context-menu.js.map +1 -0
  14. package/dist/lib/whiteboard-export.d.ts +94 -0
  15. package/dist/lib/whiteboard-export.d.ts.map +1 -0
  16. package/dist/lib/whiteboard-export.js +592 -0
  17. package/dist/lib/whiteboard-export.js.map +1 -0
  18. package/dist/lib/whiteboard-host.component.d.ts +174 -0
  19. package/dist/lib/whiteboard-host.component.d.ts.map +1 -0
  20. package/dist/lib/whiteboard-host.component.js +758 -0
  21. package/dist/lib/whiteboard-host.component.js.map +1 -0
  22. package/dist/lib/whiteboard-pages.component.d.ts +83 -0
  23. package/dist/lib/whiteboard-pages.component.d.ts.map +1 -0
  24. package/dist/lib/whiteboard-pages.component.js +211 -0
  25. package/dist/lib/whiteboard-pages.component.js.map +1 -0
  26. package/dist/lib/whiteboard-snapshot.component.d.ts +30 -0
  27. package/dist/lib/whiteboard-snapshot.component.d.ts.map +1 -0
  28. package/dist/lib/whiteboard-snapshot.component.js +91 -0
  29. package/dist/lib/whiteboard-snapshot.component.js.map +1 -0
  30. package/dist/lib/whiteboard-srcdoc.pipe.d.ts +60 -0
  31. package/dist/lib/whiteboard-srcdoc.pipe.d.ts.map +1 -0
  32. package/dist/lib/whiteboard-srcdoc.pipe.js +75 -0
  33. package/dist/lib/whiteboard-srcdoc.pipe.js.map +1 -0
  34. package/dist/lib/whiteboard-state.d.ts +1113 -0
  35. package/dist/lib/whiteboard-state.d.ts.map +1 -0
  36. package/dist/lib/whiteboard-state.js +1396 -0
  37. package/dist/lib/whiteboard-state.js.map +1 -0
  38. package/dist/lib/whiteboard-toolbar.component.d.ts +95 -0
  39. package/dist/lib/whiteboard-toolbar.component.d.ts.map +1 -0
  40. package/dist/lib/whiteboard-toolbar.component.js +344 -0
  41. package/dist/lib/whiteboard-toolbar.component.js.map +1 -0
  42. package/dist/lib/whiteboard-tools.d.ts +103 -0
  43. package/dist/lib/whiteboard-tools.d.ts.map +1 -0
  44. package/dist/lib/whiteboard-tools.js +748 -0
  45. package/dist/lib/whiteboard-tools.js.map +1 -0
  46. package/dist/lib/whiteboard-widget-bridge.d.ts +217 -0
  47. package/dist/lib/whiteboard-widget-bridge.d.ts.map +1 -0
  48. package/dist/lib/whiteboard-widget-bridge.js +254 -0
  49. package/dist/lib/whiteboard-widget-bridge.js.map +1 -0
  50. package/dist/lib/whiteboard-zoom.component.d.ts +55 -0
  51. package/dist/lib/whiteboard-zoom.component.d.ts.map +1 -0
  52. package/dist/lib/whiteboard-zoom.component.js +139 -0
  53. package/dist/lib/whiteboard-zoom.component.js.map +1 -0
  54. package/dist/lib/whiteboard.module.d.ts +29 -0
  55. package/dist/lib/whiteboard.module.d.ts.map +1 -0
  56. package/dist/lib/whiteboard.module.js +78 -0
  57. package/dist/lib/whiteboard.module.js.map +1 -0
  58. package/dist/public-api.d.ts +49 -0
  59. package/dist/public-api.d.ts.map +1 -0
  60. package/dist/public-api.js +59 -0
  61. package/dist/public-api.js.map +1 -0
  62. package/package.json +43 -6
@@ -0,0 +1,1113 @@
1
+ import { Observable } from 'rxjs';
2
+ /**
3
+ * WHITEBOARD — typed board model + state engine.
4
+ *
5
+ * This file is intentionally Angular-free: it is the single mutation API used by BOTH the
6
+ * user-facing board tools (pen, stickies, shapes, …) and any programmatic co-author —
7
+ * typically an AI agent driving the `Whiteboard_*` tool set (`Whiteboard_AddNote`,
8
+ * `Whiteboard_DrawConnector`, …, see `whiteboard-tools.ts`).
9
+ *
10
+ * Pages (OneNote-style): a board is an ordered list of named PAGES, each with its own
11
+ * items collection; exactly one page is ACTIVE at a time and every item operation
12
+ * (add / update / move / remove / connectors / clear / perception) targets the active
13
+ * page. See {@link WhiteboardState.AddPage} / {@link WhiteboardState.SwitchPage} /
14
+ * {@link WhiteboardState.RenamePage} / {@link WhiteboardState.RemovePage}. A fresh
15
+ * board starts with one page named "Page 1"; legacy (pre-pages, flat) persisted JSON
16
+ * rehydrates as that single page.
17
+ *
18
+ * Perception model (how a programmatic co-author "sees" the board):
19
+ * - every mutation appends to a compact change journal and emits on {@link WhiteboardState.Changed$};
20
+ * - {@link WhiteboardState.BuildSceneDelta} coalesces the journal since a token into ONE delta
21
+ * (multiple moves of one item → one `moved` entry) with replace-current-state semantics;
22
+ * - {@link WhiteboardState.BuildSceneSummary} produces the full compact scene the
23
+ * "What the agent sees" popover renders;
24
+ * - {@link WhiteboardState.ToJSON} / {@link WhiteboardState.FromJSON} persist the board's
25
+ * state of record (e.g. a session-channel artifact in MJ realtime sessions).
26
+ *
27
+ * Extensibility: every targeted mutation also raises a cancelable BEFORE event and a
28
+ * matching AFTER event (`ItemAdding$` / `ItemAdded$`, `ItemUpdating$` / `ItemUpdated$`,
29
+ * `ItemRemoving$` / `ItemRemoved$`) — see the {@link WhiteboardState} class docs.
30
+ */
31
+ /** Who authored a board item / mutation. The violet treatment is RESERVED for `'agent'`. */
32
+ export type WhiteboardAuthor = 'user' | 'agent';
33
+ /** The discriminant for the {@link WhiteboardItem} union. */
34
+ export type WhiteboardItemKind = 'sticky' | 'shape' | 'ink' | 'text' | 'image' | 'connector' | 'highlight' | 'markdown' | 'html';
35
+ /** Shape geometry of a {@link WhiteboardShapeItem}. */
36
+ export type WhiteboardShapeKind = 'rect' | 'ellipse' | 'diamond';
37
+ /** Visual tint of a USER sticky (agent stickies always render violet, regardless of tint). */
38
+ export type WhiteboardStickyTint = 'amber' | 'amber-light';
39
+ /**
40
+ * Curated font-size steps for text labels and sticky notes. The toolbar's text-style flyout
41
+ * and the agent's `fontSize` tool params both restrict to these values.
42
+ */
43
+ export declare const WHITEBOARD_FONT_SIZES: readonly number[];
44
+ /**
45
+ * Font family choices for text labels / stickies. The keys are mapped to token-friendly
46
+ * font stacks in the board CSS (`wb-font-serif`, `wb-font-mono`; sans is the default).
47
+ */
48
+ export type WhiteboardFontFamily = 'sans' | 'serif' | 'mono';
49
+ /** Font weights for text labels / stickies (regular or bold). */
50
+ export type WhiteboardFontWeight = 400 | 700;
51
+ /** A point in board (content) coordinates. */
52
+ export interface WhiteboardPoint {
53
+ X: number;
54
+ Y: number;
55
+ }
56
+ /** Fields shared by every board item. */
57
+ export interface WhiteboardItemBase {
58
+ /** Stable item id (e.g. `sticky-3`) — referenced by connectors, deltas and agent tools. */
59
+ ID: string;
60
+ /** Who placed the item. Drives the ownership chrome (chips / violet vs slate-amber). */
61
+ Author: WhiteboardAuthor;
62
+ /** Render order (higher renders on top). Assigned by the engine. */
63
+ Z: number;
64
+ }
65
+ /** A sticky note. */
66
+ export interface WhiteboardStickyItem extends WhiteboardItemBase {
67
+ Kind: 'sticky';
68
+ X: number;
69
+ Y: number;
70
+ /** Width in px; defaults to {@link WHITEBOARD_DEFAULTS.StickyW} when omitted. */
71
+ W?: number;
72
+ Text: string;
73
+ /** User-palette tint; ignored for agent stickies (always violet). */
74
+ Tint?: WhiteboardStickyTint;
75
+ /** Slight playful tilt, in degrees. */
76
+ Rotation?: number;
77
+ /** Curated font size (see {@link WHITEBOARD_FONT_SIZES}); omitted = the CSS default. */
78
+ FontSize?: number;
79
+ /** Font family key (mapped to token-friendly stacks in CSS); omitted = sans. */
80
+ FontFamily?: WhiteboardFontFamily;
81
+ /** Font weight; omitted = the kind's CSS default. */
82
+ FontWeight?: WhiteboardFontWeight;
83
+ }
84
+ /** A drawn shape box (rect / ellipse / diamond) with an optional label + sub-label. */
85
+ export interface WhiteboardShapeItem extends WhiteboardItemBase {
86
+ Kind: 'shape';
87
+ Shape: WhiteboardShapeKind;
88
+ X: number;
89
+ Y: number;
90
+ W: number;
91
+ H: number;
92
+ Label: string;
93
+ Sub?: string;
94
+ }
95
+ /** A free-floating text label. */
96
+ export interface WhiteboardTextItem extends WhiteboardItemBase {
97
+ Kind: 'text';
98
+ X: number;
99
+ Y: number;
100
+ Text: string;
101
+ /** Wrap width in px — text wraps at this width. Omitted = wrap at the default max width. */
102
+ W?: number;
103
+ /** Curated font size (see {@link WHITEBOARD_FONT_SIZES}); omitted = the CSS default. */
104
+ FontSize?: number;
105
+ /** Font family key (mapped to token-friendly stacks in CSS); omitted = sans. */
106
+ FontFamily?: WhiteboardFontFamily;
107
+ /** Font weight; omitted = the kind's CSS default. */
108
+ FontWeight?: WhiteboardFontWeight;
109
+ /**
110
+ * Text color from the USER pen palette. Violet is reserved for the agent's ownership
111
+ * styling (enforced in the user UI — the palette never offers violet); agent text gets
112
+ * its violet from the Author treatment, never from this field.
113
+ */
114
+ Color?: string;
115
+ }
116
+ /** A pasted / inserted image card. `Url` is a runtime object URL (not persisted as pixels). */
117
+ export interface WhiteboardImageItem extends WhiteboardItemBase {
118
+ Kind: 'image';
119
+ X: number;
120
+ Y: number;
121
+ /** Width in px; defaults to {@link WHITEBOARD_DEFAULTS.ImageW}. */
122
+ W?: number;
123
+ Name: string;
124
+ Url?: string | null;
125
+ }
126
+ /** A freehand ink stroke (polyline in board coordinates, smoothed at render time). */
127
+ export interface WhiteboardInkItem extends WhiteboardItemBase {
128
+ Kind: 'ink';
129
+ Points: WhiteboardPoint[];
130
+ /** Stroke color. The user palette NEVER includes violet — violet ink is the agent's. */
131
+ Color: string;
132
+ StrokeWidth: number;
133
+ }
134
+ /**
135
+ * A connector between two endpoints. Each endpoint references an item by ID when attached;
136
+ * when the referenced item is removed (or was never set) the endpoint falls back to the
137
+ * absolute `…Point` coordinate.
138
+ */
139
+ export interface WhiteboardConnectorItem extends WhiteboardItemBase {
140
+ Kind: 'connector';
141
+ FromItemID?: string | null;
142
+ ToItemID?: string | null;
143
+ FromPoint?: WhiteboardPoint | null;
144
+ ToPoint?: WhiteboardPoint | null;
145
+ }
146
+ /** A pulsing highlight region ("pointing without touching") — dismissed by clicking it. */
147
+ export interface WhiteboardHighlightItem extends WhiteboardItemBase {
148
+ Kind: 'highlight';
149
+ X: number;
150
+ Y: number;
151
+ W: number;
152
+ H: number;
153
+ Label?: string;
154
+ }
155
+ /**
156
+ * A rendered MARKDOWN panel — a rich, formatted card (headings, lists, code, links) for
157
+ * illustrative content that outgrows a sticky note. Width is explicit (the panel's column
158
+ * width); height is content-driven, optionally capped by `H` (overflow clips).
159
+ */
160
+ export interface WhiteboardMarkdownItem extends WhiteboardItemBase {
161
+ Kind: 'markdown';
162
+ X: number;
163
+ Y: number;
164
+ /** Panel width in px (required — markdown always renders in an explicit column). */
165
+ W: number;
166
+ /** Optional max height in px; content beyond it is clipped. Omitted = content-driven. */
167
+ H?: number;
168
+ /** The markdown source. Rendered SAFELY (sanitized — never raw HTML passthrough). */
169
+ Markdown: string;
170
+ }
171
+ /**
172
+ * An interactive HTML widget — arbitrary HTML (scripts included) rendered inside a
173
+ * STRICTLY SANDBOXED iframe (`sandbox="allow-scripts"` only, opaque origin — see the
174
+ * board component for the full security rationale). Dragged/selected by its card chrome —
175
+ * header bar, border ring and lazy placeholder — while pointer events inside the sandboxed
176
+ * frame stay with the widget, so iframe interactivity and board interactions coexist.
177
+ */
178
+ export interface WhiteboardHtmlItem extends WhiteboardItemBase {
179
+ Kind: 'html';
180
+ X: number;
181
+ Y: number;
182
+ W: number;
183
+ H: number;
184
+ /** The widget's full HTML source (becomes the sandboxed iframe's `srcdoc`). */
185
+ Html: string;
186
+ /** Optional title shown on the widget's header bar. */
187
+ Title?: string;
188
+ }
189
+ /** Discriminated union of everything that can live on the board. */
190
+ export type WhiteboardItem = WhiteboardStickyItem | WhiteboardShapeItem | WhiteboardTextItem | WhiteboardImageItem | WhiteboardInkItem | WhiteboardConnectorItem | WhiteboardHighlightItem | WhiteboardMarkdownItem | WhiteboardHtmlItem;
191
+ /** Distributive Omit that preserves the discriminated union. */
192
+ type DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;
193
+ /** What callers pass to {@link WhiteboardState.AddItem} — the engine stamps ID / Z / Author. */
194
+ export type WhiteboardItemInput = DistributiveOmit<WhiteboardItem, 'ID' | 'Z' | 'Author'>;
195
+ /** Patchable fields for {@link WhiteboardState.UpdateItem} (kind/identity fields excluded). */
196
+ export interface WhiteboardItemPatch {
197
+ X?: number;
198
+ Y?: number;
199
+ W?: number;
200
+ H?: number;
201
+ Text?: string;
202
+ Label?: string;
203
+ Sub?: string;
204
+ Name?: string;
205
+ Url?: string | null;
206
+ Color?: string;
207
+ StrokeWidth?: number;
208
+ Points?: WhiteboardPoint[];
209
+ Tint?: WhiteboardStickyTint;
210
+ Rotation?: number;
211
+ FontSize?: number;
212
+ FontFamily?: WhiteboardFontFamily;
213
+ FontWeight?: WhiteboardFontWeight;
214
+ Shape?: WhiteboardShapeKind;
215
+ Markdown?: string;
216
+ Html?: string;
217
+ Title?: string;
218
+ FromItemID?: string | null;
219
+ ToItemID?: string | null;
220
+ FromPoint?: WhiteboardPoint | null;
221
+ ToPoint?: WhiteboardPoint | null;
222
+ }
223
+ /** Mutation kinds carried on {@link WhiteboardChange} and in the journal. */
224
+ export type WhiteboardChangeOp = 'add' | 'update' | 'move' | 'remove' | 'replace';
225
+ /**
226
+ * Base shape of every cancelable BEFORE event raised by {@link WhiteboardState} (and by
227
+ * the components layered on top of it). Handlers run SYNCHRONOUSLY during the emit; any
228
+ * handler may set {@link Cancel} to `true` and the operation is aborted before it touches
229
+ * the board (no undo snapshot, no journal entry, no {@link WhiteboardState.Changed$}
230
+ * emission). The matching AFTER event then never fires.
231
+ */
232
+ export interface WhiteboardCancelableEventArgs {
233
+ /** Set to `true` (in a synchronous handler) to veto the operation. */
234
+ Cancel: boolean;
235
+ }
236
+ /**
237
+ * BEFORE-event args for {@link WhiteboardState.ItemAdding$}. Raised by
238
+ * {@link WhiteboardState.AddItem} (and therefore also by {@link WhiteboardState.Highlight}
239
+ * and {@link WhiteboardState.DuplicateItem}, which add through it) before anything is
240
+ * stamped or stored. Handlers may mutate {@link Input} (e.g. clamp coordinates, rewrite
241
+ * text) — the engine adds whatever the args carry after the emit — or set `Cancel` to
242
+ * veto the add entirely (the caller receives `null`).
243
+ */
244
+ export interface WhiteboardItemAddingEventArgs extends WhiteboardCancelableEventArgs {
245
+ /** The item about to be added (no ID / Z / Author yet — the engine stamps those). */
246
+ Input: WhiteboardItemInput;
247
+ /** Who is adding the item. */
248
+ Author: WhiteboardAuthor;
249
+ }
250
+ /** AFTER-event args for {@link WhiteboardState.ItemAdded$} — the item is on the board. */
251
+ export interface WhiteboardItemAddedEventArgs {
252
+ /** The added item, with its engine-stamped ID / Z / Author. */
253
+ Item: WhiteboardItem;
254
+ /** Who added the item. */
255
+ Author: WhiteboardAuthor;
256
+ }
257
+ /**
258
+ * Which mutation family an updating/updated event describes:
259
+ * - `'update'` — a field patch via {@link WhiteboardState.UpdateItem};
260
+ * - `'move'` — a reposition via {@link WhiteboardState.MoveItem};
261
+ * - `'reorder'` — a z-order change via {@link WhiteboardState.BringToFront} /
262
+ * {@link WhiteboardState.SendToBack}.
263
+ */
264
+ export type WhiteboardUpdateOperation = 'update' | 'move' | 'reorder';
265
+ /**
266
+ * BEFORE-event args for {@link WhiteboardState.ItemUpdating$}. {@link Item} is the LIVE,
267
+ * pre-mutation item (do not mutate it directly — cancel and apply your own patch
268
+ * instead). For `'update'` operations handlers may adjust {@link Patch}; for `'move'`
269
+ * operations {@link Position} carries the requested top-left target.
270
+ */
271
+ export interface WhiteboardItemUpdatingEventArgs extends WhiteboardCancelableEventArgs {
272
+ /** The item about to change (current, pre-mutation state). */
273
+ Item: WhiteboardItem;
274
+ /** Which mutation family is about to run. */
275
+ Operation: WhiteboardUpdateOperation;
276
+ /** The field patch (`'update'` operations only). Handlers may adjust it. */
277
+ Patch?: WhiteboardItemPatch;
278
+ /** The requested top-left position (`'move'` operations only). */
279
+ Position?: WhiteboardPoint;
280
+ /** Who is changing the item. */
281
+ Author: WhiteboardAuthor;
282
+ }
283
+ /** AFTER-event args for {@link WhiteboardState.ItemUpdated$} — the change has applied. */
284
+ export interface WhiteboardItemUpdatedEventArgs {
285
+ /** The item in its post-mutation state. */
286
+ Item: WhiteboardItem;
287
+ /** Which mutation family ran. */
288
+ Operation: WhiteboardUpdateOperation;
289
+ /** Who changed the item. */
290
+ Author: WhiteboardAuthor;
291
+ }
292
+ /**
293
+ * BEFORE-event args for {@link WhiteboardState.ItemRemoving$} — raised before the item
294
+ * leaves the board (and before any connector endpoints anchored to it are frozen).
295
+ * Cancel to keep the item.
296
+ */
297
+ export interface WhiteboardItemRemovingEventArgs extends WhiteboardCancelableEventArgs {
298
+ /** The item about to be removed. */
299
+ Item: WhiteboardItem;
300
+ /** Who is removing the item. */
301
+ Author: WhiteboardAuthor;
302
+ }
303
+ /** AFTER-event args for {@link WhiteboardState.ItemRemoved$} — the item is gone. */
304
+ export interface WhiteboardItemRemovedEventArgs {
305
+ /** The removed item (its last state — no longer on the board). */
306
+ Item: WhiteboardItem;
307
+ /** Who removed the item. */
308
+ Author: WhiteboardAuthor;
309
+ }
310
+ /**
311
+ * BEFORE-event args for {@link WhiteboardState.ContentChanging$} — raised (in addition to
312
+ * {@link WhiteboardState.ItemUpdating$}) when an {@link WhiteboardState.UpdateItem} patch
313
+ * touches an item's CONTENT fields: `Text`, `Label`, `Sub`, `Markdown`, `Html` or `Title`.
314
+ * This is the hook for content governance (length limits, redaction, moderation) without
315
+ * having to inspect every geometry patch. Cancel to veto the whole update.
316
+ */
317
+ export interface WhiteboardContentChangingEventArgs extends WhiteboardCancelableEventArgs {
318
+ /** The item whose content is about to change (current, pre-mutation state). */
319
+ Item: WhiteboardItem;
320
+ /** The full patch being applied (content fields included). Handlers may adjust it. */
321
+ Patch: WhiteboardItemPatch;
322
+ /** Who is changing the content. */
323
+ Author: WhiteboardAuthor;
324
+ }
325
+ /** AFTER-event args for {@link WhiteboardState.ContentChanged$} — the content has applied. */
326
+ export interface WhiteboardContentChangedEventArgs {
327
+ /** The item in its post-mutation state. */
328
+ Item: WhiteboardItem;
329
+ /** The patch that was applied. */
330
+ Patch: WhiteboardItemPatch;
331
+ /** Who changed the content. */
332
+ Author: WhiteboardAuthor;
333
+ }
334
+ /**
335
+ * AFTER-event args for {@link WhiteboardState.SelectionChanged$} — the selection changed
336
+ * (single OR multi). Selection is UI state: it is not journaled, not undoable and not
337
+ * persisted, so this event is a notification only (not cancelable). Fires for explicit
338
+ * {@link WhiteboardState.Select} / {@link WhiteboardState.ToggleSelect} /
339
+ * {@link WhiteboardState.SelectMany} calls AND for implicit clears (a selected item was
340
+ * removed, the page switched, or a restore dropped it).
341
+ */
342
+ export interface WhiteboardSelectionChangedEventArgs {
343
+ /** The PRIMARY selected item's ID (last added to the selection), or null when cleared. */
344
+ SelectedID: string | null;
345
+ /** The previously primary item's ID, or null when nothing was selected. */
346
+ PreviousID: string | null;
347
+ /** The full multi-selection (selection order, last = primary). Empty when cleared. */
348
+ SelectedIDs: string[];
349
+ }
350
+ /**
351
+ * AFTER-event args for {@link WhiteboardState.BoardCleared$} — every item was removed in
352
+ * one operation via {@link WhiteboardState.Clear}. The clear is a single undo step; one
353
+ * `'replace'` op lands in the journal so perception consumers re-read the (now empty)
354
+ * scene.
355
+ */
356
+ export interface WhiteboardBoardClearedEventArgs {
357
+ /** Who cleared the board. */
358
+ Author: WhiteboardAuthor;
359
+ /** How many items were removed (highlights included). */
360
+ ItemCount: number;
361
+ }
362
+ /**
363
+ * AFTER-event args for {@link WhiteboardState.BoardLoaded$} — a persisted board was
364
+ * rehydrated IN PLACE via {@link WhiteboardState.LoadFromJSON}. Undo/redo stacks and the
365
+ * journal were reset (the restored state is the new baseline) and one `'replace'` op was
366
+ * journaled, so perception consumers re-read the full scene.
367
+ */
368
+ export interface WhiteboardBoardLoadedEventArgs {
369
+ /** How many items the restored board contains (summed across ALL pages). */
370
+ ItemCount: number;
371
+ }
372
+ /**
373
+ * Public, read-only descriptor of one board page — what {@link WhiteboardState.Pages}
374
+ * returns and what every page before/after event carries. A snapshot, not a live view:
375
+ * re-read {@link WhiteboardState.Pages} after mutations.
376
+ */
377
+ export interface WhiteboardPageInfo {
378
+ /** Stable page id (e.g. `page-2`) — accepted anywhere a page name is accepted. */
379
+ ID: string;
380
+ /** Display name (e.g. "Page 1"). Not guaranteed unique; IDs are. */
381
+ Name: string;
382
+ /** How many items live on the page (highlights included). */
383
+ ItemCount: number;
384
+ /** Whether this is the board's active page. */
385
+ Active: boolean;
386
+ /**
387
+ * Who CREATED the page. Drives the page strip's delegated-violet garnish for
388
+ * agent-created pages (mirroring the item-level agent treatment). Persisted in the
389
+ * v2 JSON as an additive `author` field; payloads without it rehydrate as `'user'`.
390
+ */
391
+ Author: WhiteboardAuthor;
392
+ }
393
+ /**
394
+ * BEFORE-event args for {@link WhiteboardState.PageAdding$} — raised by
395
+ * {@link WhiteboardState.AddPage} before the page exists. Handlers may rewrite
396
+ * {@link Name} (the engine trims it; an emptied name falls back to the auto-name) or set
397
+ * `Cancel` to veto the add (the caller receives `null`).
398
+ */
399
+ export interface WhiteboardPageAddingEventArgs extends WhiteboardCancelableEventArgs {
400
+ /** The name the page will get (auto-named "Page N" when the caller omitted one). */
401
+ Name: string;
402
+ /** Who is adding the page. */
403
+ Author: WhiteboardAuthor;
404
+ }
405
+ /** AFTER-event args for {@link WhiteboardState.PageAdded$} — the page exists and is active. */
406
+ export interface WhiteboardPageAddedEventArgs {
407
+ /** The added page (now the active page). */
408
+ Page: WhiteboardPageInfo;
409
+ /** Who added the page. */
410
+ Author: WhiteboardAuthor;
411
+ }
412
+ /**
413
+ * BEFORE-event args for {@link WhiteboardState.PageSwitching$} — raised by
414
+ * {@link WhiteboardState.SwitchPage} before the active page changes. Cancel to stay on
415
+ * the current page.
416
+ */
417
+ export interface WhiteboardPageSwitchingEventArgs extends WhiteboardCancelableEventArgs {
418
+ /** The page that is currently active. */
419
+ FromPage: WhiteboardPageInfo;
420
+ /** The page about to become active. */
421
+ ToPage: WhiteboardPageInfo;
422
+ /** Who is switching. */
423
+ Author: WhiteboardAuthor;
424
+ }
425
+ /** AFTER-event args for {@link WhiteboardState.PageSwitched$} — the active page changed. */
426
+ export interface WhiteboardPageSwitchedEventArgs {
427
+ /** The previously active page. */
428
+ FromPage: WhiteboardPageInfo;
429
+ /** The newly active page. */
430
+ ToPage: WhiteboardPageInfo;
431
+ /** Who switched. */
432
+ Author: WhiteboardAuthor;
433
+ }
434
+ /**
435
+ * BEFORE-event args for {@link WhiteboardState.PageRenaming$} — raised by
436
+ * {@link WhiteboardState.RenamePage}. Handlers may rewrite {@link NewName} (trimmed by
437
+ * the engine; an emptied rewrite aborts the rename) or set `Cancel` to veto.
438
+ */
439
+ export interface WhiteboardPageRenamingEventArgs extends WhiteboardCancelableEventArgs {
440
+ /** The page about to be renamed (pre-rename snapshot). */
441
+ Page: WhiteboardPageInfo;
442
+ /** The requested new name. Handlers may adjust it. */
443
+ NewName: string;
444
+ /** Who is renaming. */
445
+ Author: WhiteboardAuthor;
446
+ }
447
+ /** AFTER-event args for {@link WhiteboardState.PageRenamed$} — the rename applied. */
448
+ export interface WhiteboardPageRenamedEventArgs {
449
+ /** The page in its post-rename state. */
450
+ Page: WhiteboardPageInfo;
451
+ /** The name the page had before. */
452
+ OldName: string;
453
+ /** Who renamed it. */
454
+ Author: WhiteboardAuthor;
455
+ }
456
+ /**
457
+ * BEFORE-event args for {@link WhiteboardState.PageRemoving$} — raised by
458
+ * {@link WhiteboardState.RemovePage} (never for the last remaining page — that is
459
+ * guarded before the event). Cancel to keep the page.
460
+ */
461
+ export interface WhiteboardPageRemovingEventArgs extends WhiteboardCancelableEventArgs {
462
+ /** The page about to be removed (with all of its items). */
463
+ Page: WhiteboardPageInfo;
464
+ /** Who is removing it. */
465
+ Author: WhiteboardAuthor;
466
+ }
467
+ /** AFTER-event args for {@link WhiteboardState.PageRemoved$} — the page is gone. */
468
+ export interface WhiteboardPageRemovedEventArgs {
469
+ /** The removed page (its last state). */
470
+ Page: WhiteboardPageInfo;
471
+ /** When the REMOVED page was active: the neighbor page that became active. Else null. */
472
+ ActivatedPage: WhiteboardPageInfo | null;
473
+ /** Who removed it. */
474
+ Author: WhiteboardAuthor;
475
+ }
476
+ /** Compact page descriptor carried on scene deltas / summaries (model-facing). */
477
+ export interface WhiteboardScenePage {
478
+ id: string;
479
+ name: string;
480
+ active: boolean;
481
+ items: number;
482
+ }
483
+ /**
484
+ * One coalesce-able change notification, emitted on {@link WhiteboardState.Changed$}
485
+ * after every mutation. `'replace'` means "the whole scene was swapped" (undo / redo /
486
+ * FromJSON) — consumers should re-read the full state.
487
+ */
488
+ export interface WhiteboardChange {
489
+ Op: WhiteboardChangeOp;
490
+ /** Empty string for `'replace'` ops. */
491
+ ItemID: string;
492
+ Author: WhiteboardAuthor;
493
+ /** Human fragment for toasts / activity ("added a sticky note"). */
494
+ SummaryFragment: string;
495
+ /** Monotonic sequence number — also the delta token currency. */
496
+ Seq: number;
497
+ }
498
+ /** Compact, model-facing representation of one item inside deltas / summaries. */
499
+ export interface WhiteboardCompactItem {
500
+ id: string;
501
+ type: WhiteboardItemKind;
502
+ author: WhiteboardAuthor;
503
+ x?: number;
504
+ y?: number;
505
+ w?: number;
506
+ h?: number;
507
+ /** Clipped text content (sticky/text/shape labels; markdown/html: clipped SOURCE). */
508
+ text?: string;
509
+ shape?: WhiteboardShapeKind;
510
+ /** Image file name, or the html widget's Title. */
511
+ name?: string;
512
+ from?: string | WhiteboardPoint | null;
513
+ to?: string | WhiteboardPoint | null;
514
+ points?: number;
515
+ fontSize?: number;
516
+ fontFamily?: WhiteboardFontFamily;
517
+ bold?: boolean;
518
+ color?: string;
519
+ }
520
+ /**
521
+ * The coalesced scene delta fed into the live agent context ("What the agent sees").
522
+ * Replace-current-state semantics: each entry is the item's CURRENT state, not an edit log.
523
+ * When `reset` is true the `items` array replaces the agent's entire view of the board
524
+ * (emitted after undo/redo/load, or when the journal no longer reaches the caller's token).
525
+ */
526
+ export interface WhiteboardSceneDelta {
527
+ op: 'scene-delta';
528
+ seq: number;
529
+ added: WhiteboardCompactItem[];
530
+ moved: {
531
+ id: string;
532
+ x: number;
533
+ y: number;
534
+ }[];
535
+ updated: WhiteboardCompactItem[];
536
+ removed: string[];
537
+ reset?: boolean;
538
+ items?: WhiteboardCompactItem[];
539
+ /** The board's page list — `active: true` marks the page the item entries describe. */
540
+ pages: WhiteboardScenePage[];
541
+ summary: string;
542
+ }
543
+ /** Full compact scene snapshot (popover stats + delta-reset payloads). ACTIVE page only. */
544
+ export interface WhiteboardSceneSummary {
545
+ op: 'scene-summary';
546
+ seq: number;
547
+ counts: {
548
+ total: number;
549
+ user: number;
550
+ agent: number;
551
+ byKind: Partial<Record<WhiteboardItemKind, number>>;
552
+ };
553
+ items: WhiteboardCompactItem[];
554
+ /** The board's page list — `active: true` marks the page the item entries describe. */
555
+ pages: WhiteboardScenePage[];
556
+ summary: string;
557
+ }
558
+ /** Axis-aligned bounds of an item, in board coordinates. */
559
+ export interface WhiteboardBounds {
560
+ X: number;
561
+ Y: number;
562
+ W: number;
563
+ H: number;
564
+ }
565
+ /** Render-time default dimensions for items whose size is content-driven. */
566
+ export declare const WHITEBOARD_DEFAULTS: {
567
+ readonly StickyW: 172;
568
+ readonly StickyH: 96;
569
+ readonly ImageW: 198;
570
+ readonly ImageH: 134;
571
+ readonly TextW: 132;
572
+ readonly TextH: 18;
573
+ readonly ShapeMinH: 56;
574
+ readonly MarkdownW: 280;
575
+ readonly MarkdownMinH: 96;
576
+ readonly HtmlW: 360;
577
+ readonly HtmlH: 240;
578
+ };
579
+ /**
580
+ * Whether an item kind is BOX-RESIZABLE by the user — i.e. the selection chrome shows the
581
+ * 8 resize handles for it. Everything with a box model resizes: stickies, shapes, text
582
+ * labels, images, markdown panels, HTML widgets and highlight regions. Ink strokes and
583
+ * connectors are path-based and are not box-resizable.
584
+ */
585
+ export declare function IsResizableKind(kind: WhiteboardItemKind): boolean;
586
+ /**
587
+ * The patch a COMMITTED resize gesture applies for an item kind, given the gesture's
588
+ * final bounds:
589
+ * - full-box kinds (`shape`, `highlight`, `html`) commit X / Y / W / H;
590
+ * - content-driven-height kinds (`sticky`, `text`, `image`, `markdown`) commit
591
+ * X / Y / W only — their rendered height stays content-driven (markdown's optional
592
+ * `H` max-height cap is set by tools/agents, never by the drag gesture);
593
+ * - non-resizable kinds (`ink`, `connector`) return `null` (nothing to commit).
594
+ */
595
+ export declare function BuildResizeCommitPatch(kind: WhiteboardItemKind, bounds: WhiteboardBounds): WhiteboardItemPatch | null;
596
+ /** Serialized shape of one page inside {@link WhiteboardStateJSON} (version 2+). */
597
+ interface WhiteboardPageJSON {
598
+ id: string;
599
+ name: string;
600
+ items: WhiteboardItem[];
601
+ /**
602
+ * Who created the page (additive, v2-tolerant: absent in pre-authorship payloads and
603
+ * treated as `'user'` on load). Drives the agent-page chip garnish.
604
+ */
605
+ author?: WhiteboardAuthor;
606
+ }
607
+ /**
608
+ * Serialized shape produced by {@link WhiteboardState.ToJSON} — VERSION 2 (paged).
609
+ * Version 1 (the legacy flat shape: `{ version: 1, seq, idCounter, zCounter, items }`)
610
+ * is still accepted by {@link WhiteboardState.FromJSON} / {@link WhiteboardState.LoadFromJSON}
611
+ * and rehydrates as a single page named "Page 1".
612
+ */
613
+ interface WhiteboardStateJSON {
614
+ version: 2;
615
+ seq: number;
616
+ idCounter: number;
617
+ zCounter: number;
618
+ /** Monotonic page-id/auto-name counter (never decremented, so names don't collide). */
619
+ pageCounter: number;
620
+ /** ID of the active page (always one of `pages`). */
621
+ activePageId: string;
622
+ /** The ordered page list (always at least one page). */
623
+ pages: WhiteboardPageJSON[];
624
+ }
625
+ /** Internal live record of one page (the active page's map backs `this.items`). */
626
+ interface PageRecord {
627
+ ID: string;
628
+ Name: string;
629
+ /** Who created the page (drives the agent-page garnish; persisted). */
630
+ Author: WhiteboardAuthor;
631
+ Items: Map<string, WhiteboardItem>;
632
+ }
633
+ /**
634
+ * The whiteboard engine: items + ordered render list, single selection, snapshot-based
635
+ * undo/redo (one entry per user gesture or per agent tool call via {@link RunBatch}),
636
+ * change journal + coalesced scene deltas, JSON persistence, and the cancelable
637
+ * BEFORE / AFTER mutation event surface.
638
+ *
639
+ * ## Before / after events
640
+ *
641
+ * Every targeted mutation raises a cancelable BEFORE event and, when it applies, a
642
+ * matching AFTER event:
643
+ *
644
+ * | Mutation | Before (cancelable) | After |
645
+ * |---|---|---|
646
+ * | {@link AddItem} (incl. {@link Highlight}, {@link DuplicateItem}) | {@link ItemAdding$} | {@link ItemAdded$} |
647
+ * | {@link UpdateItem} / {@link MoveItem} / {@link BringToFront} / {@link SendToBack} | {@link ItemUpdating$} | {@link ItemUpdated$} |
648
+ * | {@link UpdateItem} touching content fields (Text / Label / Sub / Markdown / Html / Title) | {@link ContentChanging$} (after ItemUpdating$) | {@link ContentChanged$} |
649
+ * | {@link RemoveItem} | {@link ItemRemoving$} | {@link ItemRemoved$} |
650
+ * | {@link AddPage} | {@link PageAdding$} | {@link PageAdded$} |
651
+ * | {@link SwitchPage} | {@link PageSwitching$} | {@link PageSwitched$} |
652
+ * | {@link RenamePage} | {@link PageRenaming$} | {@link PageRenamed$} |
653
+ * | {@link RemovePage} | {@link PageRemoving$} | {@link PageRemoved$} |
654
+ * | {@link Select} (and implicit clears) | — | {@link SelectionChanged$} |
655
+ * | {@link Clear} | — | {@link BoardCleared$} |
656
+ * | {@link LoadFromJSON} | — | {@link BoardLoaded$} |
657
+ *
658
+ * Handlers run synchronously during the emit; setting `Cancel = true` on the event args
659
+ * aborts the mutation (the caller sees `null` / `false`) with no undo snapshot, journal
660
+ * entry or {@link Changed$} emission. These events layer ALONGSIDE the existing
661
+ * {@link Changed$} / journal / perception machinery — they never replace it. Undo / redo
662
+ * whole-scene replacements are NOT item mutations and only surface through
663
+ * {@link Changed$} as `'replace'` ops.
664
+ */
665
+ export declare class WhiteboardState {
666
+ private static readonly UndoMax;
667
+ private static readonly JournalMax;
668
+ /**
669
+ * The ordered page list. A fresh board has one page named "Page 1". Every item
670
+ * operation reads/writes the ACTIVE page's map through the `items` accessor below, so
671
+ * the entire pre-pages mutation surface is page-scoped without per-call changes.
672
+ */
673
+ private pages;
674
+ /** ID of the active page (always present in {@link pages}). */
675
+ private activePageId;
676
+ /** Monotonic page counter — mints page IDs and the "Page N" auto-names. */
677
+ private pageCounter;
678
+ /** The ACTIVE page's item map (accessor keeps all item mutations page-scoped). */
679
+ private get items();
680
+ private set items(value);
681
+ /** The active page record (defensive fallback to the first page — never undefined). */
682
+ private get activePage();
683
+ private idCounter;
684
+ private zCounter;
685
+ private seq;
686
+ private undoStack;
687
+ private redoStack;
688
+ private batchDepth;
689
+ private journal;
690
+ /** Per-item snapshot of "did this item exist at journal-trim time" is not needed because
691
+ * trimming forces reset semantics for tokens older than the journal window. */
692
+ private journalTrimmedBeforeSeq;
693
+ private changed;
694
+ /** Fires after every mutation (including undo/redo `'replace'` events). */
695
+ readonly Changed$: Observable<WhiteboardChange>;
696
+ private itemAdding;
697
+ /**
698
+ * Cancelable BEFORE event of {@link AddItem} (and {@link Highlight} /
699
+ * {@link DuplicateItem}, which add through it). Set `Cancel = true` synchronously to
700
+ * veto the add — {@link AddItem} then returns `null` and nothing changes.
701
+ */
702
+ readonly ItemAdding$: Observable<WhiteboardItemAddingEventArgs>;
703
+ private itemAdded;
704
+ /** AFTER event: an item was added (fires once per applied {@link AddItem}). */
705
+ readonly ItemAdded$: Observable<WhiteboardItemAddedEventArgs>;
706
+ private itemUpdating;
707
+ /**
708
+ * Cancelable BEFORE event of {@link UpdateItem} (`Operation: 'update'`),
709
+ * {@link MoveItem} (`'move'`) and {@link BringToFront} / {@link SendToBack}
710
+ * (`'reorder'`). Set `Cancel = true` synchronously to veto — the mutator returns `false`.
711
+ */
712
+ readonly ItemUpdating$: Observable<WhiteboardItemUpdatingEventArgs>;
713
+ private itemUpdated;
714
+ /** AFTER event: an item changed (patch applied / moved / z-reordered). */
715
+ readonly ItemUpdated$: Observable<WhiteboardItemUpdatedEventArgs>;
716
+ private itemRemoving;
717
+ /**
718
+ * Cancelable BEFORE event of {@link RemoveItem}. Set `Cancel = true` synchronously to
719
+ * keep the item — {@link RemoveItem} then returns `false` and nothing changes.
720
+ */
721
+ readonly ItemRemoving$: Observable<WhiteboardItemRemovingEventArgs>;
722
+ private itemRemoved;
723
+ /** AFTER event: an item was removed from the board. */
724
+ readonly ItemRemoved$: Observable<WhiteboardItemRemovedEventArgs>;
725
+ private contentChanging;
726
+ /**
727
+ * Cancelable BEFORE event raised — in addition to {@link ItemUpdating$} — when an
728
+ * {@link UpdateItem} patch touches CONTENT fields (Text / Label / Sub / Markdown /
729
+ * Html / Title). The dedicated hook for content governance: set `Cancel = true`
730
+ * synchronously to veto the whole update.
731
+ */
732
+ readonly ContentChanging$: Observable<WhiteboardContentChangingEventArgs>;
733
+ private contentChanged;
734
+ /** AFTER event: an item's content fields changed (markdown / html / text edits). */
735
+ readonly ContentChanged$: Observable<WhiteboardContentChangedEventArgs>;
736
+ private selectionChanged;
737
+ /**
738
+ * AFTER event: the single selection changed — via {@link Select} or implicitly (the
739
+ * selected item was removed / dropped by a restore). Selection is transient UI state,
740
+ * so this is a notification only (never cancelable, never journaled).
741
+ */
742
+ readonly SelectionChanged$: Observable<WhiteboardSelectionChangedEventArgs>;
743
+ private boardCleared;
744
+ /** AFTER event: {@link Clear} removed everything from the board (one undo step). */
745
+ readonly BoardCleared$: Observable<WhiteboardBoardClearedEventArgs>;
746
+ private boardLoaded;
747
+ /** AFTER event: {@link LoadFromJSON} rehydrated a persisted board into this instance. */
748
+ readonly BoardLoaded$: Observable<WhiteboardBoardLoadedEventArgs>;
749
+ private pageAdding;
750
+ /**
751
+ * Cancelable BEFORE event of {@link AddPage}. Set `Cancel = true` synchronously to
752
+ * veto — {@link AddPage} then returns `null` and nothing changes.
753
+ */
754
+ readonly PageAdding$: Observable<WhiteboardPageAddingEventArgs>;
755
+ private pageAdded;
756
+ /** AFTER event: a page was added (and became the active page). */
757
+ readonly PageAdded$: Observable<WhiteboardPageAddedEventArgs>;
758
+ private pageSwitching;
759
+ /**
760
+ * Cancelable BEFORE event of {@link SwitchPage}. Set `Cancel = true` synchronously to
761
+ * stay on the current page — {@link SwitchPage} then returns `false`.
762
+ */
763
+ readonly PageSwitching$: Observable<WhiteboardPageSwitchingEventArgs>;
764
+ private pageSwitched;
765
+ /** AFTER event: the active page changed via {@link SwitchPage}. */
766
+ readonly PageSwitched$: Observable<WhiteboardPageSwitchedEventArgs>;
767
+ private pageRenaming;
768
+ /**
769
+ * Cancelable BEFORE event of {@link RenamePage}. Handlers may rewrite `NewName`; set
770
+ * `Cancel = true` synchronously to veto — {@link RenamePage} then returns `false`.
771
+ */
772
+ readonly PageRenaming$: Observable<WhiteboardPageRenamingEventArgs>;
773
+ private pageRenamed;
774
+ /** AFTER event: a page was renamed. */
775
+ readonly PageRenamed$: Observable<WhiteboardPageRenamedEventArgs>;
776
+ private pageRemoving;
777
+ /**
778
+ * Cancelable BEFORE event of {@link RemovePage} (never raised for the guarded
779
+ * last-page case). Set `Cancel = true` synchronously to keep the page.
780
+ */
781
+ readonly PageRemoving$: Observable<WhiteboardPageRemovingEventArgs>;
782
+ private pageRemoved;
783
+ /** AFTER event: a page (and all of its items) was removed from the board. */
784
+ readonly PageRemoved$: Observable<WhiteboardPageRemovedEventArgs>;
785
+ /**
786
+ * The MULTI-selection, in selection order (last entry is the primary selection).
787
+ * Selection is volatile UI state — never journaled, never undoable, never persisted,
788
+ * and cleared on page switches and whole-scene restores.
789
+ */
790
+ private selectedIds;
791
+ /**
792
+ * The PRIMARY selected item's ID (the most recently selected member of the
793
+ * multi-selection), or null when nothing is selected. Selection is UI state — not
794
+ * persisted. For the full multi-selection see {@link SelectedIDs}.
795
+ */
796
+ get SelectedID(): string | null;
797
+ /** All selected item IDs in selection order (last = primary). Returns a copy. */
798
+ get SelectedIDs(): string[];
799
+ /** All items on the ACTIVE page in render order (ascending Z). */
800
+ get Items(): WhiteboardItem[];
801
+ /** The ordered page list (read-only snapshots — see {@link WhiteboardPageInfo}). */
802
+ get Pages(): WhiteboardPageInfo[];
803
+ /** ID of the active page (every item operation targets this page). */
804
+ get ActivePageID(): string;
805
+ /** Display name of the active page. */
806
+ get ActivePageName(): string;
807
+ /** Total item count summed across ALL pages (the active-page count is {@link ElementCount}). */
808
+ get TotalItemCount(): number;
809
+ /**
810
+ * Tolerant page lookup: by exact ID first, then by case-insensitive, trimmed name
811
+ * (first match wins on duplicate names). Returns `undefined` when nothing matches.
812
+ */
813
+ FindPage(idOrName: string): WhiteboardPageInfo | undefined;
814
+ /** Current sequence number — use as the `sinceToken` for the next {@link BuildSceneDelta}. */
815
+ get CurrentSeq(): number;
816
+ /** Look up one ACTIVE-page item by ID (items on other pages are not visible here). */
817
+ GetItem(id: string): WhiteboardItem | undefined;
818
+ /** ACTIVE-page "elements" as the status footer reports them (transient highlights excluded). */
819
+ get ElementCount(): number;
820
+ /** Active-page elements by author (highlights excluded, same basis as {@link ElementCount}). */
821
+ CountByAuthor(author: WhiteboardAuthor): number;
822
+ get CanUndo(): boolean;
823
+ get CanRedo(): boolean;
824
+ /** Axis-aligned bounds for any item (estimates for content-sized kinds). */
825
+ ItemBounds(item: WhiteboardItem): WhiteboardBounds;
826
+ /** Rough rendered height of a markdown panel (line count · line height + card padding). */
827
+ private static markdownHeightEstimate;
828
+ private static pointsBounds;
829
+ /** Bounding box of all items (null when the board is empty). Powers fit-to-content + minimap. */
830
+ ContentBounds(): WhiteboardBounds | null;
831
+ /**
832
+ * Resolve one connector endpoint: anchored to the referenced item's bounds-center when the
833
+ * item still exists, otherwise the absolute fallback point (floating endpoint).
834
+ */
835
+ ResolveEndpoint(conn: WhiteboardConnectorItem, end: 'from' | 'to'): WhiteboardPoint;
836
+ /**
837
+ * Set (or clear) the selection to a SINGLE item. Unknown IDs clear the selection.
838
+ * Fires {@link SelectionChanged$} when the effective selection actually changes.
839
+ */
840
+ Select(id: string | null): void;
841
+ /**
842
+ * Toggle one item's membership in the multi-selection WITHOUT clearing the rest —
843
+ * the shift-click semantics. A newly added item becomes the primary selection
844
+ * ({@link SelectedID}); unknown IDs are a no-op.
845
+ */
846
+ ToggleSelect(id: string): void;
847
+ /**
848
+ * Replace the selection with a set of items (the marquee result). Unknown IDs are
849
+ * dropped and duplicates collapse to their first occurrence; order is preserved
850
+ * (the last surviving entry becomes the primary selection). An empty / fully-unknown
851
+ * list clears the selection.
852
+ */
853
+ SelectMany(ids: string[]): void;
854
+ /** Whether an item is part of the current (single or multi) selection. */
855
+ IsItemSelected(id: string): boolean;
856
+ /**
857
+ * All ACTIVE-page items whose axis-aligned bounds intersect the given rectangle —
858
+ * the marquee (rubber-band) hit test, in render order. Transient highlight regions
859
+ * are excluded: they are "pointing" chrome dismissed by click, never selected.
860
+ * Edge-touching items (zero overlap area) do NOT count as intersecting.
861
+ */
862
+ ItemsIntersecting(rect: WhiteboardBounds): WhiteboardItem[];
863
+ /** Apply a SINGLE-or-clear selection change (legacy internal path). */
864
+ protected changeSelection(next: string | null): void;
865
+ /** Swap the multi-selection and fire {@link SelectionChanged$} when it differs. */
866
+ protected applySelection(next: string[]): void;
867
+ /**
868
+ * Add an item; the engine stamps ID, Z and Author and emits one change.
869
+ *
870
+ * Raises the cancelable {@link ItemAdding$} BEFORE event first — when a handler
871
+ * cancels, nothing changes and `null` is returned. On success the stamped item is
872
+ * returned and {@link ItemAdded$} fires after the journal/{@link Changed$} emission.
873
+ */
874
+ AddItem(input: WhiteboardItemInput, author: WhiteboardAuthor): WhiteboardItem | null;
875
+ /**
876
+ * Patch an item's mutable fields. Returns false when the ID is unknown — or when a
877
+ * handler of the cancelable {@link ItemUpdating$} BEFORE event (or, for patches that
878
+ * touch content fields, the cancelable {@link ContentChanging$} event) vetoed the
879
+ * change. On success {@link ItemUpdated$} — and {@link ContentChanged$} for content
880
+ * patches — fires after the journal/{@link Changed$} emission.
881
+ */
882
+ UpdateItem(id: string, patch: WhiteboardItemPatch, author: WhiteboardAuthor): boolean;
883
+ /** Whether a patch touches CONTENT fields (drives the ContentChanging/Changed pair). */
884
+ protected static isContentPatch(patch: WhiteboardItemPatch): boolean;
885
+ /**
886
+ * Move an item to an absolute board position. Positioned kinds move their origin; ink
887
+ * strokes translate every point; connectors translate their floating endpoints.
888
+ *
889
+ * Raises the cancelable {@link ItemUpdating$} BEFORE event (`Operation: 'move'`,
890
+ * `Position` = the requested top-left) — returns false when vetoed or the ID is
891
+ * unknown; fires {@link ItemUpdated$} after an applied move.
892
+ */
893
+ MoveItem(id: string, x: number, y: number, author: WhiteboardAuthor): boolean;
894
+ /**
895
+ * Remove an item. Connectors that referenced it survive: their endpoint freezes to the
896
+ * removed item's last center (the floating-endpoint fallback).
897
+ *
898
+ * Raises the cancelable {@link ItemRemoving$} BEFORE event — returns false when vetoed
899
+ * or the ID is unknown; fires {@link ItemRemoved$} after an applied removal.
900
+ */
901
+ RemoveItem(id: string, author: WhiteboardAuthor): boolean;
902
+ /**
903
+ * Duplicate an item: a DEEP clone (ink points included) with a fresh engine-stamped
904
+ * identity, offset +16/+16 from the source so the copy is visibly distinct. Connectors
905
+ * (which reference other items) and transient highlights cannot be duplicated — returns
906
+ * `null` without mutating. The clone lands through {@link AddItem}, so it journals as a
907
+ * normal `'add'`, is one undo step, and raises the {@link ItemAdding$} /
908
+ * {@link ItemAdded$} pair (a canceled add also returns `null`).
909
+ */
910
+ DuplicateItem(id: string, author: WhiteboardAuthor): WhiteboardItem | null;
911
+ /**
912
+ * Raise an item above everything else. Follows the engine's existing Z handling:
913
+ * `++zCounter` is by construction greater than every assigned Z (max + 1), exactly how
914
+ * {@link AddItem} stamps new items. Journals as an `'update'`.
915
+ *
916
+ * Raises the cancelable {@link ItemUpdating$} BEFORE event (`Operation: 'reorder'`) —
917
+ * returns false when vetoed or the ID is unknown; fires {@link ItemUpdated$} after.
918
+ */
919
+ BringToFront(id: string, author: WhiteboardAuthor): boolean;
920
+ /**
921
+ * Drop an item below everything else (current min Z − 1). Journals as an `'update'`.
922
+ *
923
+ * Raises the cancelable {@link ItemUpdating$} BEFORE event (`Operation: 'reorder'`) —
924
+ * returns false when vetoed or the ID is unknown; fires {@link ItemUpdated$} after.
925
+ */
926
+ SendToBack(id: string, author: WhiteboardAuthor): boolean;
927
+ /** Raise the cancelable `'reorder'` BEFORE event; returns false when a handler vetoed. */
928
+ protected raiseReorder(item: WhiteboardItem, author: WhiteboardAuthor): boolean;
929
+ /**
930
+ * Convenience: add a pulsing highlight region (agent "pointing without touching").
931
+ * Adds through {@link AddItem}, so the {@link ItemAdding$} / {@link ItemAdded$} pair
932
+ * fires — returns `null` when a handler canceled the add.
933
+ */
934
+ Highlight(x: number, y: number, w: number, h: number, label: string | undefined, author: WhiteboardAuthor): WhiteboardHighlightItem | null;
935
+ /**
936
+ * Remove EVERYTHING from the ACTIVE page as ONE undoable operation (other pages are
937
+ * untouched). Journals a single `'replace'` op (perception consumers re-read the
938
+ * now-empty scene) and fires {@link BoardCleared$}. Clears the selection (firing
939
+ * {@link SelectionChanged$} when one existed). Returns false when the active page was
940
+ * already empty.
941
+ */
942
+ Clear(author?: WhiteboardAuthor): boolean;
943
+ /**
944
+ * Move EVERY selected item by the same delta as ONE undo step (the multi-select group
945
+ * drag). Internally one {@link RunBatch} of per-item {@link MoveItem} calls, so each
946
+ * member still raises its own cancelable `'move'` BEFORE event (a veto skips just that
947
+ * member) and journals normally — but a single Undo reverts the whole group move.
948
+ * Returns how many items actually moved (0 when nothing is selected or the delta is 0).
949
+ */
950
+ MoveSelectedBy(dx: number, dy: number, author: WhiteboardAuthor): number;
951
+ /**
952
+ * Remove EVERY selected item as ONE undo step (the multi-select Delete key). One
953
+ * {@link RunBatch} of per-item {@link RemoveItem} calls — each member still raises its
954
+ * cancelable {@link ItemRemoving$} BEFORE event (a veto keeps just that member), and a
955
+ * single Undo restores the whole group. The selection empties as items are removed.
956
+ * Returns how many items were actually removed.
957
+ */
958
+ RemoveSelected(author: WhiteboardAuthor): number;
959
+ /** Project a live page record to its public read-only descriptor. */
960
+ protected pageInfo(page: PageRecord): WhiteboardPageInfo;
961
+ /** Resolve a page by exact ID first, then case-insensitive trimmed name. */
962
+ private resolvePage;
963
+ /**
964
+ * Add a new page and SWITCH to it. `name` is trimmed; when omitted (or blank) the page
965
+ * auto-names itself "Page N" from the monotonic page counter, so auto-names never
966
+ * repeat even after removals.
967
+ *
968
+ * Raises the cancelable {@link PageAdding$} BEFORE event (handlers may rewrite the
969
+ * name) — returns `null` when vetoed; fires {@link PageAdded$} after. One undoable
970
+ * step; journals a `'replace'` op (the agent's visible scene swaps to the new, empty
971
+ * page), so perception consumers re-read the scene.
972
+ */
973
+ AddPage(name?: string, author?: WhiteboardAuthor): WhiteboardPageInfo | null;
974
+ /**
975
+ * Make another page the active page. Tolerant lookup: exact ID first, then
976
+ * case-insensitive name (see {@link FindPage}). Switching to the already-active page
977
+ * is a successful no-op (no events, no journal entry).
978
+ *
979
+ * Raises the cancelable {@link PageSwitching$} BEFORE event — returns `false` when
980
+ * vetoed or the page is unknown; fires {@link PageSwitched$} after. Journals a
981
+ * `'replace'` op (the visible scene swaps wholesale) but deliberately pushes NO undo
982
+ * snapshot — switching is navigation, not a content mutation.
983
+ */
984
+ SwitchPage(idOrName: string, author?: WhiteboardAuthor): boolean;
985
+ /**
986
+ * Rename a page (tolerant lookup, same as {@link SwitchPage}). The new name is
987
+ * trimmed; an empty result returns `false`. Renaming to the current name is a
988
+ * successful no-op (no events, no journal entry).
989
+ *
990
+ * Raises the cancelable {@link PageRenaming$} BEFORE event (handlers may rewrite
991
+ * `NewName`) — returns `false` when vetoed; fires {@link PageRenamed$} after. One
992
+ * undoable step; journals a `'replace'` op so the agent's page list stays current.
993
+ */
994
+ RenamePage(idOrName: string, newName: string, author?: WhiteboardAuthor): boolean;
995
+ /**
996
+ * Remove a page AND all of its items (tolerant lookup, same as {@link SwitchPage}).
997
+ * The LAST remaining page can never be removed (`false`, no events). Removing the
998
+ * ACTIVE page activates a neighbor — the next page when one exists, otherwise the
999
+ * previous one.
1000
+ *
1001
+ * Raises the cancelable {@link PageRemoving$} BEFORE event — returns `false` when
1002
+ * vetoed or the page is unknown; fires {@link PageRemoved$} after (with the activated
1003
+ * neighbor when the active page was removed). One undoable step; journals a
1004
+ * `'replace'` op.
1005
+ */
1006
+ RemovePage(idOrName: string, author?: WhiteboardAuthor): boolean;
1007
+ /**
1008
+ * Run several mutations as ONE undo step (one snapshot). Used per agent tool call and for
1009
+ * compound user gestures, so the toast's "Undo" reverts the whole tool effect at once.
1010
+ */
1011
+ RunBatch<T>(fn: () => T): T;
1012
+ /** Restore the previous snapshot. Emits a `'replace'` change. */
1013
+ Undo(): boolean;
1014
+ /** Re-apply the most recently undone snapshot. Emits a `'replace'` change. */
1015
+ Redo(): boolean;
1016
+ /**
1017
+ * Build the coalesced scene delta of everything that changed AFTER `sinceToken`
1018
+ * (a previously observed {@link CurrentSeq}; defaults to 0 = everything).
1019
+ *
1020
+ * Coalescing: per item, the NET effect wins — N moves → one `moved` entry at the current
1021
+ * position; add+move → one `added` entry (current state); add+remove → nothing;
1022
+ * update+move → one `updated` entry. When the window contains a `'replace'` (undo/redo/load)
1023
+ * or the journal no longer reaches the token, the delta carries `reset: true` plus the full
1024
+ * compact `items` array — replace-current-state semantics, never an append-only log.
1025
+ */
1026
+ BuildSceneDelta(sinceToken?: number): WhiteboardSceneDelta;
1027
+ /** Full compact scene + counts — the popover's stats and the delta-reset payload. */
1028
+ BuildSceneSummary(): WhiteboardSceneSummary;
1029
+ /** Compact page list for deltas / summaries (model-facing). */
1030
+ protected scenePages(): WhiteboardScenePage[];
1031
+ /**
1032
+ * Serialize the board (state of record — persisted as the session-channel artifact).
1033
+ * Emits the VERSION 2 paged shape (see {@link WhiteboardStateJSON}); the legacy flat
1034
+ * shape is still accepted on load and rehydrates as a single page "Page 1".
1035
+ */
1036
+ ToJSON(): string;
1037
+ /**
1038
+ * Rehydrate a board from {@link ToJSON} output — BOTH shapes accepted: the current
1039
+ * paged shape (version 2) and the legacy flat shape (version 1, `items` at the root),
1040
+ * which migrates to one page named "Page 1". Throws on malformed input (use
1041
+ * {@link LoadFromJSON} or `ParseBoardStateJson` for the tolerant variants).
1042
+ */
1043
+ static FromJSON(json: string): WhiteboardState;
1044
+ /**
1045
+ * Normalize a parsed persisted payload — EITHER shape — into the current
1046
+ * {@link WhiteboardStateJSON}. Returns `null` for anything unrecognizable (the
1047
+ * callers decide whether that throws or fails soft). Defensive throughout: page
1048
+ * entries missing ids/names/item arrays are repaired, an empty page list gains one
1049
+ * "Page 1", and an unknown `activePageId` falls back to the first page.
1050
+ */
1051
+ private static normalizePersisted;
1052
+ /**
1053
+ * Rehydrate THIS instance in place from {@link ToJSON} output — used by the channel's
1054
+ * `RestoreState` hook so existing subscriptions (perception feed, save pipeline) and any
1055
+ * bound surface keep pointing at the same engine. TOLERANT: malformed input returns
1056
+ * `false` and leaves the current state untouched (never throws).
1057
+ *
1058
+ * On success the undo/redo stacks and journal are cleared (restored state is the new
1059
+ * baseline), stale delta tokens force reset semantics, one `'replace'` change is
1060
+ * emitted so consumers re-read the full scene, and {@link BoardLoaded$} fires.
1061
+ */
1062
+ LoadFromJSON(json: string): boolean;
1063
+ /** Mint the next stable item ID for a kind (`sticky-3`, `shape-7`, …). */
1064
+ protected nextId(kind: WhiteboardItemKind): string;
1065
+ /**
1066
+ * Pre-mutation bookkeeping shared by every committed mutation: pushes the undo
1067
+ * snapshot (unless inside a {@link RunBatch}, which snapshotted at batch start) and
1068
+ * invalidates the redo branch. Subclasses extending the mutation paths should call
1069
+ * this exactly once per logical change, AFTER any cancelable before-event survived.
1070
+ */
1071
+ protected beforeMutate(): void;
1072
+ /** Push the current scene onto the undo stack (bounded) and drop the redo branch. */
1073
+ protected pushUndo(): void;
1074
+ /**
1075
+ * Deep-copied serializable snapshot of the WHOLE board — every page's items plus the
1076
+ * page structure and counters (undo entries / ToJSON). Page items serialize in render
1077
+ * order (ascending Z).
1078
+ */
1079
+ protected snapshot(): WhiteboardStateJSON;
1080
+ /**
1081
+ * Swap the whole board to a snapshot's pages/counters (drops a now-missing selection;
1082
+ * an unknown active-page id falls back to the first page; an empty page list gains a
1083
+ * fresh "Page 1" so the engine never runs page-less).
1084
+ */
1085
+ protected restore(snap: WhiteboardStateJSON): void;
1086
+ /**
1087
+ * Post-mutation bookkeeping shared by every committed mutation: bumps the sequence,
1088
+ * appends the journal entry (bounded — trimming forces reset deltas for stale tokens)
1089
+ * and emits the {@link Changed$} notification.
1090
+ */
1091
+ protected record(op: WhiteboardChangeOp, itemId: string, author: WhiteboardAuthor, summaryFragment: string): void;
1092
+ /** Project one item to its compact, model-facing representation (deltas / summaries). */
1093
+ protected compact(item: WhiteboardItem): WhiteboardCompactItem;
1094
+ /** Project the optional text-style fields onto a compact item (sticky / text kinds). */
1095
+ private static compactTextStyle;
1096
+ /**
1097
+ * Compose the human-readable tail line of deltas / summaries ("2 added, 1 moved. …"),
1098
+ * including which page is active and the full page list — so the model always knows
1099
+ * pages exist and which one its item entries describe.
1100
+ */
1101
+ protected composeSummaryText(parts: {
1102
+ added?: number;
1103
+ moved?: number;
1104
+ updated?: number;
1105
+ removed?: number;
1106
+ reset?: boolean;
1107
+ }): string;
1108
+ /** The page-aware scene sentence shared by every delta / summary tail line. */
1109
+ protected composePagesText(): string;
1110
+ private static describe;
1111
+ }
1112
+ export {};
1113
+ //# sourceMappingURL=whiteboard-state.d.ts.map