@memberjunction/ng-whiteboard 6.1.4 → 6.2.0-edge.1
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.
- package/dist/lib/whiteboard-board.component.d.ts +1 -1
- package/dist/lib/whiteboard-board.component.js +2 -2
- package/dist/lib/whiteboard-board.component.js.map +1 -1
- package/dist/lib/whiteboard-host.component.d.ts +12 -2
- package/dist/lib/whiteboard-host.component.d.ts.map +1 -1
- package/dist/lib/whiteboard-host.component.js +17 -7
- package/dist/lib/whiteboard-host.component.js.map +1 -1
- package/dist/lib/whiteboard-state.d.ts +2 -2
- package/dist/lib/whiteboard-state.js +5 -5
- package/dist/lib/whiteboard-state.js.map +1 -1
- package/dist/lib/whiteboard-zoom.component.d.ts +3 -3
- package/dist/lib/whiteboard-zoom.component.js +7 -7
- package/dist/lib/whiteboard-zoom.component.js.map +1 -1
- package/package.json +6 -6
|
@@ -198,10 +198,20 @@ export declare class RealtimeWhiteboardHostComponent implements OnInit, OnDestro
|
|
|
198
198
|
*/
|
|
199
199
|
ApplyAgentTool(toolName: string, argsJson: string): string;
|
|
200
200
|
ToggleSees(event: Event): void;
|
|
201
|
-
|
|
201
|
+
private closeSees;
|
|
202
202
|
ToggleFocus(): void;
|
|
203
203
|
ToggleExport(event: Event): void;
|
|
204
|
-
|
|
204
|
+
private closeExport;
|
|
205
|
+
/**
|
|
206
|
+
* The component's ONLY `document:click` listener — dismisses every open popover.
|
|
207
|
+
*
|
|
208
|
+
* ⚠️ Do NOT add a second `@HostListener('document:click')` here. Angular keys host
|
|
209
|
+
* listeners by event name, so a second declaration for the same event silently
|
|
210
|
+
* replaces the first (no build error, no warning). That had already happened:
|
|
211
|
+
* `closeSees` and `closeExport` each declared one, so only the latter registered
|
|
212
|
+
* and the Sees dropdown never closed on an outside click.
|
|
213
|
+
*/
|
|
214
|
+
CloseOpenPopovers(): void;
|
|
205
215
|
/** Download the board as one self-contained HTML document. */
|
|
206
216
|
/** Request a first-class artifact snapshot of the board (handled by the channel plugin). */
|
|
207
217
|
ExportSaveToArtifacts(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"whiteboard-host.component.d.ts","sourceRoot":"","sources":["../../src/lib/whiteboard-host.component.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"whiteboard-host.component.d.ts","sourceRoot":"","sources":["../../src/lib/whiteboard-host.component.ts"],"names":[],"mappings":"AAAA,OAAO,EACqC,YAAY,EACtD,SAAS,EAAE,MAAM,EAClB,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,oBAAoB,EAAE,4BAA4B,EAAE,6BAA6B,EACjF,8BAA8B,EAAE,+BAA+B,EAC/D,8BAA8B,EAAE,+BAA+B,EAAE,eAAe,EACjF,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAgD,MAAM,0BAA0B,CAAC;AAM9H,OAAO,EACL,gCAAgC,EAAE,uBAAuB,EACzD,iCAAiC,EAAE,kCAAkC,EACtE,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,gCAAgC,EAAE,2BAA2B,EAAE,mCAAmC,EACnG,MAAM,4BAA4B,CAAC;;AAYpC;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAaa,+BAAgC,YAAW,MAAM,EAAE,SAAS;IACvE,iEAAiE;IACtC,KAAK,EAAG,eAAe,CAAC;IACnD,2EAA2E;IAClE,SAAS,SAAW;IAC7B,uCAAuC;IAC9B,UAAU,SAAgB;IACnC,6DAA6D;IACpD,UAAU,SAAsB;IACzC;;;;;;;;;;;;;;;OAeG;IACM,qBAAqB,UAAS;IAEvC;;;;;;;;;;;;;;;;;OAiBG;IACH,IACI,UAAU,CAAC,KAAK,EAAE,oBAAoB,EAkBzC;IACD,IAAI,UAAU,IAAI,oBAAoB,CAErC;IACD,OAAO,CAAC,WAAW,CAA8B;IAEjD;;;;;;;;;;;;;;;OAeG;IACM,QAAQ,UAAS;IAE1B,iFAAiF;IACvE,UAAU,uBAA8B;IAClD,yFAAyF;IAC/E,SAAS,qBAA4B;IAC/C,+EAA+E;IACrE,eAAe,wBAA+B;IACxD,0GAA0G;IAChG,wBAAwB,qBAA4B;IAC9D;;;;OAIG;IACO,gBAAgB,oDAA2D;IACrF;;;;OAIG;IACO,eAAe,4CAAmD;IAC5E;;;;;;OAMG;IACO,iBAAiB,iDAAwD;IACnF;;;OAGG;IACO,eAAe,mDAA0D;IACnF,wEAAwE;IAC9D,cAAc,kDAAyD;IAQjF,uEAAuE;IAC7D,UAAU,8CAAqD;IACzE,0DAA0D;IAChD,SAAS,6CAAoD;IACvE,mGAAmG;IACzF,YAAY,gDAAuD;IAC7E,4DAA4D;IAClD,WAAW,+CAAsD;IAC3E,yEAAyE;IAC/D,YAAY,gDAAuD;IAC7E,4DAA4D;IAClD,WAAW,+CAAsD;IAEvB,KAAK,CAAC,EAAE,gCAAgC,CAAC;IAG7F;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,IAAW,IAAI,IAAI,cAAc,CAEhC;IACD,IAAW,IAAI,CAAC,KAAK,EAAE,cAAc,EAIpC;IACD,OAAO,CAAC,KAAK,CAA4B;IAClC,QAAQ,EAAE,MAAM,CAA4B;IAC5C,QAAQ,SAAK;IACb,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAAU;IACnD,QAAQ,SAAM;IACd,UAAU,EAAE,oBAAoB,CAAU;IAC1C,QAAQ,UAAQ;IAChB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAQ;IAGhC,QAAQ,UAAS;IACjB,SAAS,UAAS;IAClB,UAAU,UAAS;IAGnB,aAAa,EAAE,uBAAuB,GAAG,IAAI,CAAQ;IACrD,SAAS,EAAE,MAAM,GAAG,IAAI,CAAQ;IACvC,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,UAAU,CAA8C;IAChE,OAAO,CAAC,aAAa,CAA8C;IAG5D,aAAa,SAAM;IAC1B,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,UAAU,CAA8C;IAGzD,OAAO,SAAc;IAC5B,OAAO,CAAC,MAAM,CAA+C;IAE7D,OAAO,CAAC,UAAU,CAAC,CAAe;IAClC,OAAO,CAAC,UAAU,CAAsB;IACxC,OAAO,CAAC,GAAG,CAA6B;IAExC,QAAQ,IAAI,IAAI;IAyBhB,WAAW,IAAI,IAAI;IAsBnB;;;;;OAKG;IACI,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM;IAmB1D,UAAU,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAKrC,OAAO,CAAC,SAAS;IAMV,WAAW,IAAI,IAAI;IAOnB,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAKvC,OAAO,CAAC,WAAW;IAMnB;;;;;;;;OAQG;IAEI,iBAAiB,IAAI,IAAI;IAKhC,8DAA8D;IAC9D,4FAA4F;IACrF,qBAAqB,IAAI,IAAI;IAK7B,kBAAkB,IAAI,IAAI;IAKjC,yFAAyF;IAClF,0BAA0B,IAAI,IAAI;IAMzC,6DAA6D;IACtD,iBAAiB,IAAI,IAAI;IAKhC;;;;OAIG;IACI,yBAAyB,IAAI,IAAI;IASxC,uFAAuF;IACvF,IAAW,gBAAgB,IAAI,OAAO,CAErC;IAED;;;;OAIG;IACI,WAAW,IAAI,IAAI;IAc1B,OAAO,CAAC,eAAe;IAIvB,6EAA6E;IAC7E,OAAO,CAAC,aAAa;IAQrB,+FAA+F;IAC/F,OAAO,CAAC,MAAM,CAAC,YAAY;IAI3B,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,MAAM,CAAC,eAAe;IAMvB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAUtC;;;;;OAKG;IAC2B,QAAQ,CAAC,YAAY,QAAQ;IAE3D,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA+C;IAEpE;;;;;;OAMG;IAEI,iBAAiB,IAAI,IAAI;IAMhC,wEAAwE;IACxE,OAAO,CAAC,cAAc;IAOf,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAmE5C,IAAW,YAAY,IAAI,MAAM,CAEhC;IAED,IAAW,SAAS,IAAI,MAAM,CAE7B;IAED,IAAW,UAAU,IAAI,MAAM,CAE9B;IAED,IAAW,UAAU,IAAI,MAAM,CAE9B;IAED,iFAAiF;IACjF,IAAW,cAAc,IAAI,MAAM,CASlC;IAED,IAAW,oBAAoB,IAAI,MAAM,CAExC;IAID,OAAO,CAAC,kBAAkB;IAU1B,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,iBAAiB;IAmBzB,OAAO,CAAC,eAAe;IAiBvB,OAAO,CAAC,SAAS;IAUjB,OAAO,CAAC,MAAM,CAAC,UAAU;IAoBzB,OAAO,CAAC,MAAM,CAAC,UAAU;yCA3oBd,+BAA+B;2CAA/B,+BAA+B;CA2pB3C"}
|
|
@@ -391,7 +391,7 @@ export class RealtimeWhiteboardHostComponent {
|
|
|
391
391
|
event.stopPropagation();
|
|
392
392
|
this.SeesOpen = !this.SeesOpen;
|
|
393
393
|
}
|
|
394
|
-
|
|
394
|
+
closeSees() {
|
|
395
395
|
if (this.SeesOpen) {
|
|
396
396
|
this.SeesOpen = false;
|
|
397
397
|
}
|
|
@@ -405,11 +405,24 @@ export class RealtimeWhiteboardHostComponent {
|
|
|
405
405
|
event.stopPropagation();
|
|
406
406
|
this.ExportOpen = !this.ExportOpen;
|
|
407
407
|
}
|
|
408
|
-
|
|
408
|
+
closeExport() {
|
|
409
409
|
if (this.ExportOpen) {
|
|
410
410
|
this.ExportOpen = false;
|
|
411
411
|
}
|
|
412
412
|
}
|
|
413
|
+
/**
|
|
414
|
+
* The component's ONLY `document:click` listener — dismisses every open popover.
|
|
415
|
+
*
|
|
416
|
+
* ⚠️ Do NOT add a second `@HostListener('document:click')` here. Angular keys host
|
|
417
|
+
* listeners by event name, so a second declaration for the same event silently
|
|
418
|
+
* replaces the first (no build error, no warning). That had already happened:
|
|
419
|
+
* `closeSees` and `closeExport` each declared one, so only the latter registered
|
|
420
|
+
* and the Sees dropdown never closed on an outside click.
|
|
421
|
+
*/
|
|
422
|
+
CloseOpenPopovers() {
|
|
423
|
+
this.closeSees();
|
|
424
|
+
this.closeExport();
|
|
425
|
+
}
|
|
413
426
|
/** Download the board as one self-contained HTML document. */
|
|
414
427
|
/** Request a first-class artifact snapshot of the board (handled by the channel plugin). */
|
|
415
428
|
ExportSaveToArtifacts() {
|
|
@@ -712,7 +725,7 @@ export class RealtimeWhiteboardHostComponent {
|
|
|
712
725
|
let _t;
|
|
713
726
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.Board = _t.first);
|
|
714
727
|
} }, hostVars: 1, hostBindings: function RealtimeWhiteboardHostComponent_HostBindings(rf, ctx) { if (rf & 1) {
|
|
715
|
-
i0.ɵɵlistener("click", function RealtimeWhiteboardHostComponent_click_HostBindingHandler() { return ctx.
|
|
728
|
+
i0.ɵɵlistener("click", function RealtimeWhiteboardHostComponent_click_HostBindingHandler() { return ctx.CloseOpenPopovers(); }, i0.ɵɵresolveDocument)("pointerdown", function RealtimeWhiteboardHostComponent_pointerdown_HostBindingHandler() { return ctx.OnHostPointerDown(); })("keydown", function RealtimeWhiteboardHostComponent_keydown_HostBindingHandler($event) { return ctx.OnKeydown($event); }, i0.ɵɵresolveDocument);
|
|
716
729
|
} if (rf & 2) {
|
|
717
730
|
i0.ɵɵattribute("tabindex", ctx.HostTabIndex);
|
|
718
731
|
} }, inputs: { State: "State", AgentName: "AgentName", BoardTitle: "BoardTitle", SavedLabel: "SavedLabel", EnableGlobalShortcuts: "EnableGlobalShortcuts", ToolRoster: "ToolRoster", ReadOnly: "ReadOnly" }, outputs: { SceneDelta: "SceneDelta", AgentUndo: "AgentUndo", FocusModeChange: "FocusModeChange", SaveToArtifactsRequested: "SaveToArtifactsRequested", WidgetSubmitting: "WidgetSubmitting", WidgetSubmitted: "WidgetSubmitted", WidgetInteraction: "WidgetInteraction", ContentApplying: "ContentApplying", ContentApplied: "ContentApplied", ItemAdding: "ItemAdding", ItemAdded: "ItemAdded", ItemUpdating: "ItemUpdating", ItemUpdated: "ItemUpdated", ItemRemoving: "ItemRemoving", ItemRemoved: "ItemRemoved" }, decls: 70, vars: 40, consts: [["board", ""], [1, "board-head"], [1, "bt"], [1, "fa-solid", "fa-chalkboard"], [1, "board-save"], [1, "fa-solid", "fa-circle-check"], [1, "board-legend"], [1, "sw", "sw--you"], [1, "sw", "sw--sage"], [1, "fa-solid", "fa-feather", "legend-feather"], [1, "head-end"], ["type", "button", 1, "head-btn", "head-btn--sees", 3, "click"], [1, "eye-pulse"], [1, "fa-regular", "fa-eye"], [3, "AgentName", "DeltaJson", "DebounceMs", "ElementCount", "LastDeltaLabel"], [1, "export-wrap"], ["type", "button", 1, "head-btn", 3, "click"], [1, "fa-solid", "fa-file-export"], [1, "export-menu"], ["type", "button", "title", "More", 1, "head-btn", "head-btn--more"], [1, "fa-solid", "fa-ellipsis"], [1, "board-wrap"], [3, "ToolChangeRequest", "WidgetSubmitting", "WidgetSubmitted", "WidgetInteraction", "ContentApplying", "ContentApplied", "State", "AgentName", "Tool", "ToolRoster", "ReadOnly", "PenColor", "PenWidth", "ShapeKind", "TextSize", "TextFamily", "TextBold", "TextColor", "AgentPresence"], [3, "ActiveTool", "ToolRoster", "PenColor", "PenWidth", "ShapeKind", "TextSize", "TextFamily", "TextBold", "TextColor", "CanUndo", "CanRedo", "AgentName"], [3, "ZoomOut", "ZoomIn", "ZoomBy", "Fit", "ToggleMinimap", "ZoomPercent", "MinimapOpen"], [1, "board-toast"], [1, "board-status"], [1, "stat"], [1, "seg-r"], [1, "stat", "ctx-live", 3, "title"], [1, "d"], [1, "ctx-live__text"], ["title", "Persists as a session artifact when the call ends", 1, "stat", "persist"], ["aria-hidden", "true", 1, "fa-solid", "fa-box-archive"], [1, "persist__long"], [1, "persist__short"], ["type", "button", 1, "export-item", 3, "click"], [1, "fa-solid", "fa-file-code"], ["type", "button", 1, "export-item"], [1, "fa-solid", "fa-bezier-curve"], ["type", "button", "title", "One SVG file per page", 1, "export-item"], [1, "fa-solid", "fa-print"], [1, "fa-solid", "fa-box-archive"], ["type", "button", "title", "One SVG file per page", 1, "export-item", 3, "click"], [3, "ToolChange", "PenColorChange", "PenWidthChange", "ShapeKindChange", "TextSizeChange", "TextFamilyChange", "TextBoldChange", "TextColorChange", "StyleSelection", "Undo", "Redo", "ActiveTool", "ToolRoster", "PenColor", "PenWidth", "ShapeKind", "TextSize", "TextFamily", "TextBold", "TextColor", "CanUndo", "CanRedo", "AgentName"], [1, "fa-solid", "fa-feather"], [1, "board-toast__text"], [1, "undo"], [1, "undo", 3, "click"], [1, "fa-solid", "fa-rotate-left"]], template: function RealtimeWhiteboardHostComponent_Template(rf, ctx) { if (rf & 1) {
|
|
@@ -915,10 +928,7 @@ export class RealtimeWhiteboardHostComponent {
|
|
|
915
928
|
}], Board: [{
|
|
916
929
|
type: ViewChild,
|
|
917
930
|
args: [RealtimeWhiteboardBoardComponent]
|
|
918
|
-
}],
|
|
919
|
-
type: HostListener,
|
|
920
|
-
args: ['document:click']
|
|
921
|
-
}], CloseExport: [{
|
|
931
|
+
}], CloseOpenPopovers: [{
|
|
922
932
|
type: HostListener,
|
|
923
933
|
args: ['document:click']
|
|
924
934
|
}], HostTabIndex: [{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"whiteboard-host.component.js","sourceRoot":"","sources":["../../src/lib/whiteboard-host.component.ts","../../src/lib/whiteboard-host.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n ChangeDetectorRef, Component, ElementRef, EventEmitter, HostBinding, HostListener, Input,\n OnDestroy, OnInit, Output, ViewChild, inject\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { Subscription } from 'rxjs';\nimport {\n WhiteboardFontFamily, WhiteboardItemAddedEventArgs, WhiteboardItemAddingEventArgs,\n WhiteboardItemRemovedEventArgs, WhiteboardItemRemovingEventArgs,\n WhiteboardItemUpdatedEventArgs, WhiteboardItemUpdatingEventArgs, WhiteboardState\n} from './whiteboard-state';\nimport { WhiteboardTool, WhiteboardToolRoster, ClampToolToRoster, IsToolAllowed, SameRoster } from './whiteboard-tool-roster';\nimport {\n BuildWhiteboardExportHtml, BuildWhiteboardExportHtmlAllPages, BuildWhiteboardExportSvg,\n BuildWhiteboardExportSvgPages\n} from './whiteboard-export';\nimport { ApplyWhiteboardAgentTool, WHITEBOARD_TOOL_NAMES, WhiteboardToolResult } from './whiteboard-tools';\nimport {\n RealtimeWhiteboardBoardComponent, WhiteboardAgentPresence,\n WhiteboardContentAppliedEventArgs, WhiteboardContentApplyingEventArgs\n} from './whiteboard-board.component';\nimport {\n WhiteboardWidgetInteractionEvent, WhiteboardWidgetSubmitEvent, WhiteboardWidgetSubmittingEventArgs\n} from './whiteboard-widget-bridge';\nimport { RealtimeWhiteboardToolbarComponent, WHITEBOARD_PEN_COLORS } from './whiteboard-toolbar.component';\nimport { RealtimeWhiteboardZoomComponent } from './whiteboard-zoom.component';\nimport { RealtimeWhiteboardAgentSeesPopoverComponent } from './whiteboard-agent-sees-popover.component';\n\n/** Debounce window for the perception feed (the popover's \"debounce 750 ms\" stat). */\nconst SCENE_DELTA_DEBOUNCE_MS = 750;\n/** How long the agent-action toast stays up (coalescing further actions while visible). */\nconst TOAST_MS = 6000;\n/** How long the presence cursor lingers after the agent's last board action. */\nconst PRESENCE_MS = 4200;\n\n/**\n * LIVE WHITEBOARD host (`mj-realtime-whiteboard-host`): board header (title / saved chip /\n * ownership legend / \"What [Agent] sees\" popover / Focus toggle), the board surface with its\n * floating toolbar + zoom cluster, the agent action toast with Undo, and the status footer —\n * everything EXCEPT the overlay/tab chrome, which the session shell owns.\n *\n * Integration contract:\n * - `State` is created by the integration layer (channel state of record) and passed in;\n * - `SceneDelta` emits the debounced (750 ms), coalesced scene-delta JSON on user changes —\n * the perception feed the integration pipes into the live agent context;\n * - `ApplyAgentTool(toolName, argsJson)` executes one agent channel tool\n * (`Whiteboard_AddNote` … see `WHITEBOARD_TOOL_DEFINITIONS`) with the violet pop-in,\n * toast and presence-cursor garnish, returning the result JSON for the tool round-trip;\n * - `AgentUndo` fires when the user clicks Undo on the agent-action toast;\n * - `FocusModeChange` asks the shell to collapse/restore the call rail (\"Focus board\").\n *\n * Extensibility (before/after events): the host mirrors the engine's cancelable\n * BEFORE / AFTER mutation pairs as outputs (`ItemAdding`/`ItemAdded`,\n * `ItemUpdating`/`ItemUpdated`, `ItemRemoving`/`ItemRemoved`) and forwards the board's\n * editor + widget pairs (`ContentApplying`/`ContentApplied`,\n * `WidgetSubmitting`/`WidgetSubmitted`). All BEFORE events honor `Cancel = true` set\n * synchronously by a handler.\n */\n@Component({\n standalone: true,\n selector: 'mj-realtime-whiteboard-host',\n imports: [\n CommonModule,\n RealtimeWhiteboardBoardComponent,\n RealtimeWhiteboardToolbarComponent,\n RealtimeWhiteboardZoomComponent,\n RealtimeWhiteboardAgentSeesPopoverComponent\n ],\n templateUrl: './whiteboard-host.component.html',\n styleUrl: './whiteboard-host.component.css'\n})\nexport class RealtimeWhiteboardHostComponent implements OnInit, OnDestroy {\n /** Shared board state engine, owned by the integration layer. */\n @Input({ required: true }) State!: WhiteboardState;\n /** Display name of the session's agent (legend, chips, popover, toast). */\n @Input() AgentName = 'Agent';\n /** Board title shown in the header. */\n @Input() BoardTitle = 'Whiteboard';\n /** Persistence chip text (e.g. \"Saved to session · v14\"). */\n @Input() SavedLabel = 'Saved to session';\n /**\n * Opt back in to DOCUMENT-WIDE keyboard shortcuts.\n *\n * The host binds eleven bare single-character tool shortcuts (v h p r s t m w i c e). While\n * those listened on `document` unconditionally they fired wherever the user was on the page,\n * which fails WCAG 2.1.4 (Character Key Shortcuts): a speech-input user saying an ordinary\n * word, or anyone typing in a non-input control elsewhere, silently switched the board tool.\n * They are now scoped to focus being inside this host, which satisfies the criterion's\n * \"active only on focus\" branch.\n *\n * Scoping covers the host's ENTIRE keydown handler, not only the letters: undo/redo\n * (Cmd/Ctrl+Z, +Y), Escape and Delete/Backspace are focus-gated as well.\n *\n * Set `true` only for a surface where the whiteboard is the entire page AND the 2.1.4\n * exposure has been accepted — it is an accessibility regression, not a convenience flag.\n */\n @Input() EnableGlobalShortcuts = false;\n\n /**\n * Which tools this surface offers. `null` (default) is all eleven: today's rendering.\n *\n * The roster governs which tools are AVAILABLE, closing every door to a tool it leaves out:\n * the toolbar button, the single-letter shortcut, and the canvas \"add … here\" action. It is\n * deliberately not a content policy — it does not restrict what already exists on the board,\n * what the agent places, or authoring on existing items (Duplicate, z-order, Delete, paste).\n * The one exception is Restyle…, which is hidden when the roster omits `text`, because it\n * opens the TEXT tool's style flyout and would otherwise be a menu entry that does nothing.\n *\n * An empty roster (or one naming no real tool) narrows the palette to nothing and clamps the\n * active tool to `select`. It does NOT make the board read-only — that is {@link ReadOnly}.\n *\n * A setter rather than `ngOnChanges` (packages/Angular/CLAUDE.md): a realtime channel's\n * `BindSurface` assigns this property directly on a dynamically-created component, and\n * Angular fires no `ngOnChanges` for a plain assignment, so a clamp implemented there would\n * silently never run on the path real consumers use.\n */\n @Input()\n set ToolRoster(value: WhiteboardToolRoster) {\n // Anything that is not an array reads as NO roster. The type does not protect us here: a\n // STATIC template attribute (`ToolRoster=\"select,pan\"` — a plausible typo for the binding)\n // hands us a string, and a string reaching the helpers' `.includes` / `.filter` would throw\n // during render. A consumer's punctuation slip must not take the board down.\n //\n // The kept value is a frozen COPY, so the roster the host enforces cannot be edited behind\n // its back — a consumer splicing its own array afterwards changes their array, not ours,\n // and is picked up as a genuine change the next time they bind it.\n const next = Array.isArray(value) ? Object.freeze([...value]) : null;\n // Compare by CONTENT, not identity (see SameRoster): identity re-clamped on every change\n // detection for a bound array literal, and never re-clamped for an array mutated in place.\n if (SameRoster(next, this._toolRoster)) {\n return;\n }\n this._toolRoster = next;\n // Re-validate the CURRENT tool through the same chokepoint every other write uses.\n this.Tool = this._tool;\n }\n get ToolRoster(): WhiteboardToolRoster {\n return this._toolRoster;\n }\n private _toolRoster: WhiteboardToolRoster = null;\n\n /**\n * Render the board read-only: nothing on it can be created, edited, moved or deleted.\n *\n * This is the OTHER axis from {@link ToolRoster}, and the two do not substitute for each\n * other. The roster answers \"which tools does this surface offer\" — it narrows a palette the\n * user still authors with. `ReadOnly` answers \"may anything change at all\" — it is about\n * mutation, not about choice, so an empty roster is not a read-only board and a full roster\n * on a read-only board still mutates nothing.\n *\n * The board component already guards every mutation entry point and hides the page strip's\n * add / rename / delete affordances; the host adds the chrome that only it owns — the floating\n * toolbar is not rendered (matching `WhiteboardSnapshotComponent`, which draws a read-only\n * board with no toolbar), the agent toast's Undo is hidden because Undo applies a mutation,\n * and the keyboard handler returns before any key can act. Pan and zoom stay live: reading a\n * board you cannot change still means moving around it.\n */\n @Input() ReadOnly = false;\n\n /** Debounced (750 ms), coalesced scene-delta JSON — the live perception feed. */\n @Output() SceneDelta = new EventEmitter<string>();\n /** The user clicked Undo on the agent-action toast (the undo itself already applied). */\n @Output() AgentUndo = new EventEmitter<void>();\n /** Focus-board toggle — the session shell collapses/restores the call rail. */\n @Output() FocusModeChange = new EventEmitter<boolean>();\n /** Emitted when the user picks \"Save to artifacts\" — the channel plugin persists via its host context. */\n @Output() SaveToArtifactsRequested = new EventEmitter<void>();\n /**\n * Cancelable BEFORE event (forwarded from the board): a sandboxed HTML widget submitted\n * input via `MJWhiteboard.submit` and it passed validation. Set `Cancel = true`\n * synchronously to drop it before {@link WidgetSubmitted} fires.\n */\n @Output() WidgetSubmitting = new EventEmitter<WhiteboardWidgetSubmittingEventArgs>();\n /**\n * AFTER event: a sandboxed HTML widget submitted user input via `MJWhiteboard.submit`\n * (validated + size-capped by the board, not canceled). Integration layers forward it\n * to their agent runtime — e.g. MJ's channel plugin sends a `[whiteboard]` context note.\n */\n @Output() WidgetSubmitted = new EventEmitter<WhiteboardWidgetSubmitEvent>();\n /**\n * AMBIENT widget telemetry (forwarded from the board): the injected recorder observed\n * passive form activity (clicks / changes / typing / focus) inside a sandboxed HTML\n * widget, validated + pre-summarized. Integration layers forward it to their agent\n * runtime as throttled, low-priority background context — e.g. MJ's channel plugin sends\n * an \"ambient activity\" `[whiteboard]` note at most once per widget per few seconds.\n */\n @Output() WidgetInteraction = new EventEmitter<WhiteboardWidgetInteractionEvent>();\n /**\n * Cancelable BEFORE event (forwarded from the board): an in-board editor commit is\n * about to write to the state engine. Set `Cancel = true` synchronously to discard it.\n */\n @Output() ContentApplying = new EventEmitter<WhiteboardContentApplyingEventArgs>();\n /** AFTER event (forwarded from the board): an editor commit applied. */\n @Output() ContentApplied = new EventEmitter<WhiteboardContentAppliedEventArgs>();\n\n // Engine mutation mirrors — the same before/after events {@link WhiteboardState} raises,\n // re-emitted as component outputs so template-driven consumers can bind them without\n // subscribing to the engine directly. Emission is synchronous, so cancelable BEFORE\n // mirrors (`ItemAdding` / `ItemUpdating` / `ItemRemoving`) honor `Cancel = true` set by\n // a template handler exactly like a direct engine subscription would.\n\n /** Cancelable BEFORE mirror of {@link WhiteboardState.ItemAdding$}. */\n @Output() ItemAdding = new EventEmitter<WhiteboardItemAddingEventArgs>();\n /** AFTER mirror of {@link WhiteboardState.ItemAdded$}. */\n @Output() ItemAdded = new EventEmitter<WhiteboardItemAddedEventArgs>();\n /** Cancelable BEFORE mirror of {@link WhiteboardState.ItemUpdating$} (update / move / reorder). */\n @Output() ItemUpdating = new EventEmitter<WhiteboardItemUpdatingEventArgs>();\n /** AFTER mirror of {@link WhiteboardState.ItemUpdated$}. */\n @Output() ItemUpdated = new EventEmitter<WhiteboardItemUpdatedEventArgs>();\n /** Cancelable BEFORE mirror of {@link WhiteboardState.ItemRemoving$}. */\n @Output() ItemRemoving = new EventEmitter<WhiteboardItemRemovingEventArgs>();\n /** AFTER mirror of {@link WhiteboardState.ItemRemoved$}. */\n @Output() ItemRemoved = new EventEmitter<WhiteboardItemRemovedEventArgs>();\n\n @ViewChild(RealtimeWhiteboardBoardComponent) public Board?: RealtimeWhiteboardBoardComponent;\n\n // tool state (host-owned; toolbar + keyboard drive it, board consumes it)\n /**\n * The active tool, and the ONE place the roster invariant is enforced on a write.\n *\n * \"The active tool is always one the roster allows\" is a property of every write, not of the\n * handful of call sites that exist today (the roster setter, Escape, the key map, and the two\n * template `Tool = $event` bindings). Guarding each of those would leave the next writer —\n * a new shortcut, a gesture, a host API — to remember the rule. Guarding here closes them all\n * by construction, and makes assignment order irrelevant: setting `ToolRoster` and `Tool` in\n * either order still lands on an allowed tool.\n *\n * A DISALLOWED request is ignored rather than clamped: pressing Escape under `['pen','eraser']`\n * should leave you on pen, not bounce you to the roster's fallback. The clamp is only for the\n * case where the tool you are already holding stopped being allowed.\n *\n * ONE EXCEPTION to \"always one the roster allows\": a roster that allows nothing at all — empty,\n * or naming no real tool. The board must hold some tool, so {@link ClampToolToRoster} floors it\n * at `select`, which is then held even though the roster does not list it. That is deliberate\n * and is the safe answer precisely because `select` can create nothing; the alternative —\n * keeping the tool the roster just revoked — left a creating tool live with no toolbar to see\n * it and no key to change it. See {@link ClampToolToRoster} for why the floor is `select`\n * rather than the roster's first entry.\n */\n public get Tool(): WhiteboardTool {\n return this._tool;\n }\n public set Tool(value: WhiteboardTool) {\n this._tool = IsToolAllowed(this._toolRoster, value)\n ? value\n : ClampToolToRoster(this._tool, this._toolRoster);\n }\n private _tool: WhiteboardTool = 'select';\n public PenColor: string = WHITEBOARD_PEN_COLORS[0];\n public PenWidth = 4;\n public ShapeKind: 'rect' | 'ellipse' | 'diamond' = 'rect';\n public TextSize = 12;\n public TextFamily: WhiteboardFontFamily = 'sans';\n public TextBold = true;\n public TextColor: string | null = null;\n\n // header state\n public SeesOpen = false;\n public FocusMode = false;\n public ExportOpen = false;\n\n // agent garnish state\n public AgentPresence: WhiteboardAgentPresence | null = null;\n public ToastText: string | null = null;\n private toastPhrases: string[] = [];\n private toastTimer: ReturnType<typeof setTimeout> | null = null;\n private presenceTimer: ReturnType<typeof setTimeout> | null = null;\n\n // perception feed state\n public LastDeltaJson = '';\n private lastDeltaToken = 0;\n private lastDeltaAt: number | null = null;\n private deltaTimer: ReturnType<typeof setTimeout> | null = null;\n\n // \"synced n s ago\" ticker\n public NowTick = Date.now();\n private ticker: ReturnType<typeof setInterval> | null = null;\n\n private changedSub?: Subscription;\n private mirrorSubs: Subscription[] = [];\n private cdr = inject(ChangeDetectorRef);\n\n ngOnInit(): void {\n this.changedSub = this.State.Changed$.subscribe((change) => {\n // perception feed: user edits (and scene replacements like undo) schedule a delta\n if (change.Author === 'user' || change.Op === 'replace') {\n this.scheduleSceneDelta();\n }\n this.cdr.markForCheck();\n });\n // Mirror the engine's before/after mutation events as component outputs. The re-emit\n // runs synchronously inside the engine's emit, so Cancel set by an output handler\n // still vetoes the mutation.\n this.mirrorSubs.push(\n this.State.ItemAdding$.subscribe((e) => this.ItemAdding.emit(e)),\n this.State.ItemAdded$.subscribe((e) => this.ItemAdded.emit(e)),\n this.State.ItemUpdating$.subscribe((e) => this.ItemUpdating.emit(e)),\n this.State.ItemUpdated$.subscribe((e) => this.ItemUpdated.emit(e)),\n this.State.ItemRemoving$.subscribe((e) => this.ItemRemoving.emit(e)),\n this.State.ItemRemoved$.subscribe((e) => this.ItemRemoved.emit(e))\n );\n this.ticker = setInterval(() => {\n this.NowTick = Date.now();\n this.cdr.markForCheck();\n }, 1000);\n }\n\n ngOnDestroy(): void {\n this.changedSub?.unsubscribe();\n for (const sub of this.mirrorSubs) {\n sub.unsubscribe();\n }\n this.mirrorSubs = [];\n if (this.deltaTimer) {\n clearTimeout(this.deltaTimer);\n }\n if (this.toastTimer) {\n clearTimeout(this.toastTimer);\n }\n if (this.presenceTimer) {\n clearTimeout(this.presenceTimer);\n }\n if (this.ticker) {\n clearInterval(this.ticker);\n }\n }\n\n // ────────────────────────────────────────────── AGENT tool entry point\n\n /**\n * Execute one agent whiteboard tool (author `'agent'`, one undo batch), with the UI\n * garnish: presence cursor glides to the mutation point, the new item pops in violet,\n * and the action toast (with Undo) appears. Returns the result JSON string that the\n * integration layer feeds back to the realtime model as the `tool_response`.\n */\n public ApplyAgentTool(toolName: string, argsJson: string): string {\n const resultJson = ApplyWhiteboardAgentTool(this.State, toolName, argsJson);\n let result: WhiteboardToolResult | null = null;\n try {\n result = JSON.parse(resultJson) as WhiteboardToolResult;\n }\n catch {\n result = null;\n }\n if (result?.success) {\n this.showAgentPresence(result.itemId);\n this.pushToastPhrase(RealtimeWhiteboardHostComponent.toolPhrase(toolName));\n }\n this.cdr.markForCheck();\n return resultJson;\n }\n\n // ────────────────────────────────────────────── header actions\n\n public ToggleSees(event: Event): void {\n event.stopPropagation();\n this.SeesOpen = !this.SeesOpen;\n }\n\n @HostListener('document:click')\n public CloseSees(): void {\n if (this.SeesOpen) {\n this.SeesOpen = false;\n }\n }\n\n public ToggleFocus(): void {\n this.FocusMode = !this.FocusMode;\n this.FocusModeChange.emit(this.FocusMode);\n }\n\n // ────────────────────────────────────────────── export menu\n\n public ToggleExport(event: Event): void {\n event.stopPropagation();\n this.ExportOpen = !this.ExportOpen;\n }\n\n @HostListener('document:click')\n public CloseExport(): void {\n if (this.ExportOpen) {\n this.ExportOpen = false;\n }\n }\n\n /** Download the board as one self-contained HTML document. */\n /** Request a first-class artifact snapshot of the board (handled by the channel plugin). */\n public ExportSaveToArtifacts(): void {\n this.ExportOpen = false;\n this.SaveToArtifactsRequested.emit();\n }\n\n public ExportDownloadHtml(): void {\n this.downloadBlob(this.buildExportHtml(), 'text/html', `whiteboard-${RealtimeWhiteboardHostComponent.exportDateStamp()}.html`);\n this.ExportOpen = false;\n }\n\n /** Download ONE self-contained HTML document containing EVERY page (titled sections). */\n public ExportDownloadHtmlAllPages(): void {\n const html = BuildWhiteboardExportHtmlAllPages(this.State, this.exportOptions());\n this.downloadBlob(html, 'text/html', `whiteboard-all-pages-${RealtimeWhiteboardHostComponent.exportDateStamp()}.html`);\n this.ExportOpen = false;\n }\n\n /** Download the ACTIVE page as a standalone SVG document. */\n public ExportDownloadSvg(): void {\n this.downloadBlob(BuildWhiteboardExportSvg(this.State), 'image/svg+xml', `whiteboard-${RealtimeWhiteboardHostComponent.exportDateStamp()}.svg`);\n this.ExportOpen = false;\n }\n\n /**\n * Download EVERY page as its own standalone SVG document (SVG is single-image, so\n * \"all pages\" is one file per page, downloaded sequentially with the page name\n * slug-suffixed into each filename).\n */\n public ExportDownloadSvgAllPages(): void {\n const stamp = RealtimeWhiteboardHostComponent.exportDateStamp();\n for (const page of BuildWhiteboardExportSvgPages(this.State)) {\n const slug = RealtimeWhiteboardHostComponent.fileNameSlug(page.PageName) || page.PageID;\n this.downloadBlob(page.Content, 'image/svg+xml', `whiteboard-${stamp}-${slug}.svg`);\n }\n this.ExportOpen = false;\n }\n\n /** Whether the board has more than one page (gates the \"all pages\" export entries). */\n public get HasMultiplePages(): boolean {\n return this.State.Pages.length > 1;\n }\n\n /**\n * Print the board: open a blank window, write the self-contained export document and\n * invoke the print dialog (same precedent as the artifact viewer's print path). When the\n * popup is blocked this is a logged no-op — nothing breaks, the user can retry.\n */\n public ExportPrint(): void {\n this.ExportOpen = false;\n const printWindow = window.open('about:blank', '_blank');\n if (!printWindow) {\n console.warn('Whiteboard print: popup was blocked — allow popups for this site and retry.');\n return;\n }\n printWindow.document.write(this.buildExportHtml());\n printWindow.document.close();\n printWindow.focus();\n // let the document lay out before invoking the dialog (artifact-viewer precedent)\n setTimeout(() => printWindow.print(), 250);\n }\n\n private buildExportHtml(): string {\n return BuildWhiteboardExportHtml(this.State, this.exportOptions());\n }\n\n /** Shared options for the HTML export builders (single page + all pages). */\n private exportOptions(): { Title: string; AgentName: string; GeneratedAt: string } {\n return {\n Title: this.BoardTitle,\n AgentName: this.AgentName,\n GeneratedAt: new Date().toLocaleString()\n };\n }\n\n /** Safe filename fragment from a page name (lowercased, non-alphanumerics collapse to '-'). */\n private static fileNameSlug(name: string): string {\n return (name ?? '').toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 40);\n }\n\n private downloadBlob(content: string, mimeType: string, fileName: string): void {\n const url = URL.createObjectURL(new Blob([content], { type: mimeType }));\n const anchor = document.createElement('a');\n anchor.href = url;\n anchor.download = fileName;\n anchor.click();\n URL.revokeObjectURL(url);\n }\n\n private static exportDateStamp(): string {\n return new Date().toISOString().slice(0, 10);\n }\n\n // ────────────────────────────────────────────── toast\n\n public OnToastUndo(event: Event): void {\n event.stopPropagation();\n // The agent's tool call ran as ONE undo batch, so a single Undo reverts it whole.\n this.State.Undo();\n this.hideToast();\n this.AgentUndo.emit();\n }\n\n // ────────────────────────────────────────────── keyboard shortcuts\n\n /**\n * The board is made focusable so its shortcuts have a focus scope to be bound to. `-1`, not\n * `0`: the canvas has no keyboard interaction model yet (see the whiteboard keyboard-\n * operability work), so adding a real Tab stop would put a stop in the page that a keyboard\n * user can reach and do nothing with. Click focuses it; that is the whole contract today.\n */\n @HostBinding('attr.tabindex') readonly HostTabIndex = '-1';\n\n private readonly host: ElementRef<HTMLElement> = inject(ElementRef);\n\n /**\n * Clicking the board takes focus, so the shortcuts below apply. The browser would usually do\n * this on its own by focusing the nearest focusable ancestor, but the board's pointer\n * pipeline is elaborate enough (drag, marquee, handles, transient shapes) that relying on\n * that default is fragile — one `preventDefault()` added later would silently kill every\n * shortcut. This makes it explicit.\n */\n @HostListener('pointerdown')\n public OnHostPointerDown(): void {\n if (!this.hasFocusWithin()) {\n this.host.nativeElement.focus({ preventScroll: true });\n }\n }\n\n /** Whether focus currently sits on, or inside, this whiteboard host. */\n private hasFocusWithin(): boolean {\n const el = this.host.nativeElement;\n const active = document.activeElement;\n return !!active && (active === el || el.contains(active));\n }\n\n @HostListener('document:keydown', ['$event'])\n public OnKeydown(event: KeyboardEvent): void {\n // WCAG 2.1.4: only live while focus is on the board. NOTE this gates the WHOLE handler,\n // not just the single-character tool keys that 2.1.4 is about — undo/redo (Cmd/Ctrl+Z,\n // +Y), Escape and Delete/Backspace are scoped too. That is deliberate: a board that\n // swallows the document's Cmd+Z from anywhere on the page is its own bug, and \"the board\n // responds to keys when you are on the board\" is the only model that stays predictable.\n // See {@link EnableGlobalShortcuts} for the (discouraged) opt-out.\n if (!this.EnableGlobalShortcuts && !this.hasFocusWithin()) {\n return;\n }\n // Read-only boards answer to NO key, Escape included. Every branch below either mutates\n // (undo/redo, Delete) or picks a tool that could, and Escape's selection-clear is not worth\n // an exception: \"the keyboard does nothing here\" is one rule a user can hold, where \"the\n // keyboard does nothing except Escape\" is a rule they have to be told.\n if (this.ReadOnly) {\n return;\n }\n const target = event.target as HTMLElement | null;\n if (target && (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable)) {\n return;\n }\n if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === 'z') {\n event.preventDefault();\n if (event.shiftKey) {\n this.State.Redo();\n }\n else {\n this.State.Undo();\n }\n return;\n }\n if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === 'y') {\n event.preventDefault();\n this.State.Redo();\n return;\n }\n if (event.metaKey || event.ctrlKey || event.altKey) {\n return;\n }\n switch (event.key) {\n case 'Escape':\n this.Tool = 'select';\n this.Board?.CancelTransient();\n this.State.Select(null);\n break;\n case 'Delete':\n case 'Backspace':\n if (this.State.SelectedIDs.length > 0) {\n event.preventDefault();\n // removes the WHOLE (single or multi) selection as one undo step\n this.State.RemoveSelected('user');\n }\n break;\n default: {\n const tool = RealtimeWhiteboardHostComponent.toolForKey(event.key);\n // No roster check here: the Tool setter ignores a disallowed write, so a key for a\n // hidden tool is a no-op by construction rather than by a remembered guard.\n if (tool) {\n this.Tool = tool;\n }\n break;\n }\n }\n }\n\n // ────────────────────────────────────────────── status footer / popover bindings\n\n public get ElementCount(): number {\n return this.State.ElementCount;\n }\n\n public get UserCount(): number {\n return this.State.CountByAuthor('user');\n }\n\n public get AgentCount(): number {\n return this.State.CountByAuthor('agent');\n }\n\n public get CurrentSeq(): number {\n return this.State.CurrentSeq;\n }\n\n /** \"2 s ago\" style age of the last emitted delta (the ticker keeps it fresh). */\n public get LastDeltaLabel(): string {\n if (this.lastDeltaAt == null) {\n return '—';\n }\n const seconds = Math.max(0, Math.round((this.NowTick - this.lastDeltaAt) / 1000));\n if (seconds < 60) {\n return `${seconds} s ago`;\n }\n return `${Math.floor(seconds / 60)} min ago`;\n }\n\n public get SceneDeltaDebounceMs(): number {\n return SCENE_DELTA_DEBOUNCE_MS;\n }\n\n // ────────────────────────────────────────────── internals\n\n private scheduleSceneDelta(): void {\n if (this.deltaTimer) {\n clearTimeout(this.deltaTimer);\n }\n this.deltaTimer = setTimeout(() => {\n this.deltaTimer = null;\n this.emitSceneDelta();\n }, SCENE_DELTA_DEBOUNCE_MS);\n }\n\n private emitSceneDelta(): void {\n const delta = this.State.BuildSceneDelta(this.lastDeltaToken);\n this.lastDeltaToken = this.State.CurrentSeq;\n this.lastDeltaAt = Date.now();\n this.LastDeltaJson = JSON.stringify(delta, null, 2);\n this.SceneDelta.emit(JSON.stringify(delta));\n this.cdr.markForCheck();\n }\n\n private showAgentPresence(itemId: string | undefined): void {\n let x = 480;\n let y = 220;\n const item = itemId ? this.State.GetItem(itemId) : undefined;\n if (item) {\n const b = this.State.ItemBounds(item);\n x = b.X + b.W + 14;\n y = b.Y + b.H / 2 - 13;\n }\n this.AgentPresence = { Active: true, X: x, Y: y, Label: `${this.AgentName} is drawing…` };\n if (this.presenceTimer) {\n clearTimeout(this.presenceTimer);\n }\n this.presenceTimer = setTimeout(() => {\n this.AgentPresence = null;\n this.cdr.markForCheck();\n }, PRESENCE_MS);\n }\n\n private pushToastPhrase(phrase: string): void {\n if (!this.ToastText) {\n this.toastPhrases = [];\n }\n if (!this.toastPhrases.includes(phrase)) {\n this.toastPhrases.push(phrase);\n }\n const joined = this.toastPhrases.length > 1\n ? `${this.toastPhrases.slice(0, -1).join(', ')} & ${this.toastPhrases[this.toastPhrases.length - 1]}`\n : this.toastPhrases[0];\n this.ToastText = `${this.AgentName} ${joined} · just now`;\n if (this.toastTimer) {\n clearTimeout(this.toastTimer);\n }\n this.toastTimer = setTimeout(() => this.hideToast(), TOAST_MS);\n }\n\n private hideToast(): void {\n this.ToastText = null;\n this.toastPhrases = [];\n if (this.toastTimer) {\n clearTimeout(this.toastTimer);\n this.toastTimer = null;\n }\n this.cdr.markForCheck();\n }\n\n private static toolPhrase(toolName: string): string {\n switch (toolName) {\n case WHITEBOARD_TOOL_NAMES.AddNote: return 'added a note';\n case WHITEBOARD_TOOL_NAMES.AddShape: return 'added a shape';\n case WHITEBOARD_TOOL_NAMES.AddText: return 'added a label';\n case WHITEBOARD_TOOL_NAMES.AddMarkdown: return 'added a markdown panel';\n case WHITEBOARD_TOOL_NAMES.AddHtml: return 'added an HTML widget';\n case WHITEBOARD_TOOL_NAMES.UpdateContent: return 'edited an item';\n case WHITEBOARD_TOOL_NAMES.DrawConnector: return 'added a connector';\n case WHITEBOARD_TOOL_NAMES.Highlight: return 'highlighted a region';\n case WHITEBOARD_TOOL_NAMES.MoveItem: return 'moved an item';\n case WHITEBOARD_TOOL_NAMES.RemoveItem: return 'removed an item';\n case WHITEBOARD_TOOL_NAMES.StyleItem: return 'restyled an item';\n case WHITEBOARD_TOOL_NAMES.AddPage: return 'created a page';\n case WHITEBOARD_TOOL_NAMES.SwitchPage: return 'switched pages';\n case WHITEBOARD_TOOL_NAMES.RenamePage: return 'renamed a page';\n default: return 'updated the board';\n }\n }\n\n private static toolForKey(key: string): WhiteboardTool | null {\n switch (key.toLowerCase()) {\n case 'v': return 'select';\n case 'h': return 'pan';\n case 'p': return 'pen';\n case 'r': return 'shape';\n case 's': return 'sticky';\n case 't': return 'text';\n case 'm': return 'markdown';\n case 'w': return 'html';\n case 'i': return 'image';\n case 'c': return 'connector';\n case 'e': return 'eraser';\n default: return null;\n }\n }\n}\n","<!-- board header -->\n<div class=\"board-head\">\n <span class=\"bt\"><i class=\"fa-solid fa-chalkboard\"></i> {{ BoardTitle }}</span>\n <span class=\"board-save\"><i class=\"fa-solid fa-circle-check\"></i> {{ SavedLabel }}</span>\n <span class=\"board-legend\">\n <span><span class=\"sw sw--you\"></span>You</span>\n <span><span class=\"sw sw--sage\"></span>{{ AgentName }} <i class=\"fa-solid fa-feather legend-feather\"></i></span>\n </span>\n <div class=\"head-end\">\n <button type=\"button\" class=\"head-btn head-btn--sees\" [class.on]=\"SeesOpen\" (click)=\"ToggleSees($event)\">\n <span class=\"eye-pulse\"></span><i class=\"fa-regular fa-eye\"></i> What {{ AgentName }} sees\n @if (SeesOpen) {\n <mj-realtime-whiteboard-agent-sees-popover\n [AgentName]=\"AgentName\"\n [DeltaJson]=\"LastDeltaJson\"\n [DebounceMs]=\"SceneDeltaDebounceMs\"\n [ElementCount]=\"ElementCount\"\n [LastDeltaLabel]=\"LastDeltaLabel\"/>\n }\n </button>\n <span class=\"export-wrap\">\n <button type=\"button\" class=\"head-btn\" [class.on]=\"ExportOpen\" (click)=\"ToggleExport($event)\">\n <i class=\"fa-solid fa-file-export\"></i> Export\n </button>\n @if (ExportOpen) {\n <div class=\"export-menu\">\n <button type=\"button\" class=\"export-item\" (click)=\"ExportDownloadHtml()\">\n <i class=\"fa-solid fa-file-code\"></i> Download HTML\n </button>\n @if (HasMultiplePages) {\n <button type=\"button\" class=\"export-item\" (click)=\"ExportDownloadHtmlAllPages()\">\n <i class=\"fa-solid fa-file-code\"></i> Download HTML — all pages\n </button>\n }\n <button type=\"button\" class=\"export-item\" (click)=\"ExportDownloadSvg()\">\n <i class=\"fa-solid fa-bezier-curve\"></i> Download SVG\n </button>\n @if (HasMultiplePages) {\n <button type=\"button\" class=\"export-item\" title=\"One SVG file per page\"\n (click)=\"ExportDownloadSvgAllPages()\">\n <i class=\"fa-solid fa-bezier-curve\"></i> Download SVG — all pages\n </button>\n }\n <button type=\"button\" class=\"export-item\" (click)=\"ExportPrint()\">\n <i class=\"fa-solid fa-print\"></i> Print\n </button>\n <button type=\"button\" class=\"export-item\" (click)=\"ExportSaveToArtifacts()\">\n <i class=\"fa-solid fa-box-archive\"></i> Save to artifacts\n </button>\n </div>\n }\n </span>\n <button type=\"button\" class=\"head-btn\" [class.on]=\"FocusMode\" (click)=\"ToggleFocus()\">\n <i [class]=\"FocusMode ? 'fa-solid fa-compress' : 'fa-solid fa-expand'\"></i>\n {{ FocusMode ? 'Show thread' : 'Focus board' }}\n </button>\n <button type=\"button\" class=\"head-btn head-btn--more\" title=\"More\"><i class=\"fa-solid fa-ellipsis\"></i></button>\n </div>\n</div>\n\n<!-- the board -->\n<div class=\"board-wrap\">\n <mj-realtime-whiteboard #board\n [State]=\"State\"\n [AgentName]=\"AgentName\"\n [Tool]=\"Tool\"\n [ToolRoster]=\"ToolRoster\"\n [ReadOnly]=\"ReadOnly\"\n [PenColor]=\"PenColor\"\n [PenWidth]=\"PenWidth\"\n [ShapeKind]=\"ShapeKind\"\n [TextSize]=\"TextSize\"\n [TextFamily]=\"TextFamily\"\n [TextBold]=\"TextBold\"\n [TextColor]=\"TextColor\"\n [AgentPresence]=\"AgentPresence\"\n (ToolChangeRequest)=\"Tool = $event\"\n (WidgetSubmitting)=\"WidgetSubmitting.emit($event)\"\n (WidgetSubmitted)=\"WidgetSubmitted.emit($event)\"\n (WidgetInteraction)=\"WidgetInteraction.emit($event)\"\n (ContentApplying)=\"ContentApplying.emit($event)\"\n (ContentApplied)=\"ContentApplied.emit($event)\"/>\n\n <!-- the toolbar is authoring chrome: a read-only board renders none, matching\n WhiteboardSnapshotComponent. Zoom stays — navigation is not mutation. -->\n @if (!ReadOnly) {\n <mj-realtime-whiteboard-toolbar\n [ActiveTool]=\"Tool\"\n [ToolRoster]=\"ToolRoster\"\n [PenColor]=\"PenColor\"\n [PenWidth]=\"PenWidth\"\n [ShapeKind]=\"ShapeKind\"\n [TextSize]=\"TextSize\"\n [TextFamily]=\"TextFamily\"\n [TextBold]=\"TextBold\"\n [TextColor]=\"TextColor\"\n [CanUndo]=\"State.CanUndo\"\n [CanRedo]=\"State.CanRedo\"\n [AgentName]=\"AgentName\"\n (ToolChange)=\"Tool = $event\"\n (PenColorChange)=\"PenColor = $event\"\n (PenWidthChange)=\"PenWidth = $event\"\n (ShapeKindChange)=\"ShapeKind = $event\"\n (TextSizeChange)=\"TextSize = $event\"\n (TextFamilyChange)=\"TextFamily = $event\"\n (TextBoldChange)=\"TextBold = $event\"\n (TextColorChange)=\"TextColor = $event\"\n (StyleSelection)=\"board.ApplyTextStyleToSelection($event)\"\n (Undo)=\"State.Undo()\"\n (Redo)=\"State.Redo()\"/>\n }\n\n <mj-realtime-whiteboard-zoom\n [ZoomPercent]=\"board.ZoomPercent\"\n [MinimapOpen]=\"board.MinimapOpen\"\n (ZoomOut)=\"board.ZoomOut()\"\n (ZoomIn)=\"board.ZoomIn()\"\n (ZoomBy)=\"board.ZoomByFactor($event)\"\n (Fit)=\"board.FitToContent()\"\n (ToggleMinimap)=\"board.ToggleMinimap()\"/>\n\n <!-- agent action toast -->\n @if (ToastText) {\n <div class=\"board-toast\">\n <i class=\"fa-solid fa-feather\"></i>\n <span class=\"board-toast__text\">{{ ToastText }}</span>\n @if (!ReadOnly) {\n <span class=\"undo\" (click)=\"OnToastUndo($event)\"><i class=\"fa-solid fa-rotate-left\"></i> Undo</span>\n }\n </div>\n }\n</div>\n\n<!-- board status footer: ONE row, never wraps — items ellipsize, and the long\n persistence prose collapses to an icon chip (full text on its tooltip) when\n the host is narrow (container query on the host width). -->\n<div class=\"board-status\">\n <span class=\"stat\"><b>{{ ElementCount }}</b> elements</span>\n <span class=\"stat\">you <b>{{ UserCount }}</b> · {{ AgentName }} <b>{{ AgentCount }}</b></span>\n <span class=\"stat\">synced <b>{{ LastDeltaLabel }}</b> · seq <b>{{ CurrentSeq }}</b></span>\n <span class=\"seg-r\">\n <span class=\"stat ctx-live\" [title]=\"AgentName + '’s live context: current'\">\n <span class=\"d\"></span><span class=\"ctx-live__text\"> {{ AgentName }}'s live context: current</span>\n </span>\n <span class=\"stat persist\" title=\"Persists as a session artifact when the call ends\">\n <i class=\"fa-solid fa-box-archive\" aria-hidden=\"true\"></i>\n <span class=\"persist__long\">persists as <b>session artifact</b> when the call ends</span>\n <span class=\"persist__short\">session artifact</span>\n </span>\n </span>\n</div>\n"]}
|
|
1
|
+
{"version":3,"file":"whiteboard-host.component.js","sourceRoot":"","sources":["../../src/lib/whiteboard-host.component.ts","../../src/lib/whiteboard-host.component.html"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,KAAK,EACrE,MAAM,EAAE,SAAS,EAAE,MAAM,EAC7C,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,EAG4D,eAAe,EACjF,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAwC,iBAAiB,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC9H,OAAO,EACL,yBAAyB,EAAE,iCAAiC,EAAE,wBAAwB,EACtF,6BAA6B,EAC9B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,wBAAwB,EAAE,qBAAqB,EAAwB,MAAM,oBAAoB,CAAC;AAC3G,OAAO,EACL,gCAAgC,EAEjC,MAAM,8BAA8B,CAAC;AAItC,OAAO,EAAE,kCAAkC,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAC3G,OAAO,EAAE,+BAA+B,EAAE,MAAM,6BAA6B,CAAC;AAC9E,OAAO,EAAE,2CAA2C,EAAE,MAAM,2CAA2C,CAAC;;;ICdhG,gEAKqC;;;IAAnC,AADA,AADA,AADA,AADA,4CAAuB,mCACI,2CACQ,qCACN,yCACI;;;;IAa/B,kCAAiF;IAAvC,mNAAS,mCAA4B,KAAC;IAC9E,wBAAqC;IAAC,gDACxC;IAAA,iBAAS;;;;IAMT,kCAC8C;IAAtC,mNAAS,kCAA2B,KAAC;IAC3C,wBAAwC;IAAC,+CAC3C;IAAA,iBAAS;;;;IAfX,AADF,+BAAyB,iBACkD;IAA/B,oMAAS,2BAAoB,KAAC;IACtE,wBAAqC;IAAC,+BACxC;IAAA,iBAAS;IACT,oHAAwB;IAKxB,kCAAwE;IAA9B,oMAAS,0BAAmB,KAAC;IACrE,wBAAwC;IAAC,8BAC3C;IAAA,iBAAS;IACT,oHAAwB;IAMxB,kCAAkE;IAAxB,oMAAS,oBAAa,KAAC;IAC/D,yBAAiC;IAAC,wBACpC;IAAA,iBAAS;IACT,mCAA4E;IAAlC,qMAAS,8BAAuB,KAAC;IACzE,yBAAuC;IAAC,oCAC1C;IACF,AADE,iBAAS,EACL;;;IApBJ,eAIC;IAJD,kDAIC;IAID,eAKC;IALD,kDAKC;;;;IA4CT,0DAuByB;IAAvB,AADA,AADA,AADA,AADA,AADA,AADA,AADA,AADA,AADA,AADA,qQAA4B,oQACQ,oQACA,uQACE,oQACF,0QACI,oQACJ,uQACE,6PACpB,0CAAuC,KAAC,6MAClD,mBAAY,KAAC,6MACb,mBAAY,KAAC;IAvBvB,iBAuByB;;;IAXvB,AADA,AADA,AADA,AADA,AADA,AADA,AADA,AADA,AADA,AADA,AADA,wCAAmB,iCACM,6BACJ,6BACA,+BACE,6BACF,iCACI,6BACJ,+BACE,iCACE,iCACA,+BACF;;;;IA6BnB,gCAAiD;IAA9B,uNAAS,0BAAmB,KAAC;IAAC,wBAAuC;IAAC,qBAAI;IAAA,iBAAO;;;IAJxG,+BAAyB;IACvB,wBAAmC;IACnC,gCAAgC;IAAA,YAAe;IAAA,iBAAO;IACtD,kHAAiB;IAGnB,iBAAM;;;IAJ4B,eAAe;IAAf,sCAAe;IAC/C,cAEC;IAFD,2CAEC;;ADpGP,sFAAsF;AACtF,MAAM,uBAAuB,GAAG,GAAG,CAAC;AACpC,2FAA2F;AAC3F,MAAM,QAAQ,GAAG,IAAI,CAAC;AACtB,gFAAgF;AAChF,MAAM,WAAW,GAAG,IAAI,CAAC;AAEzB;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAcH,MAAM,OAAO,+BAA+B;IAb5C;QAgBE,2EAA2E;QAClE,cAAS,GAAG,OAAO,CAAC;QAC7B,uCAAuC;QAC9B,eAAU,GAAG,YAAY,CAAC;QACnC,6DAA6D;QACpD,eAAU,GAAG,kBAAkB,CAAC;QACzC;;;;;;;;;;;;;;;WAeG;QACM,0BAAqB,GAAG,KAAK,CAAC;QA2C/B,gBAAW,GAAyB,IAAI,CAAC;QAEjD;;;;;;;;;;;;;;;WAeG;QACM,aAAQ,GAAG,KAAK,CAAC;QAE1B,iFAAiF;QACvE,eAAU,GAAG,IAAI,YAAY,EAAU,CAAC;QAClD,yFAAyF;QAC/E,cAAS,GAAG,IAAI,YAAY,EAAQ,CAAC;QAC/C,+EAA+E;QACrE,oBAAe,GAAG,IAAI,YAAY,EAAW,CAAC;QACxD,0GAA0G;QAChG,6BAAwB,GAAG,IAAI,YAAY,EAAQ,CAAC;QAC9D;;;;WAIG;QACO,qBAAgB,GAAG,IAAI,YAAY,EAAuC,CAAC;QACrF;;;;WAIG;QACO,oBAAe,GAAG,IAAI,YAAY,EAA+B,CAAC;QAC5E;;;;;;WAMG;QACO,sBAAiB,GAAG,IAAI,YAAY,EAAoC,CAAC;QACnF;;;WAGG;QACO,oBAAe,GAAG,IAAI,YAAY,EAAsC,CAAC;QACnF,wEAAwE;QAC9D,mBAAc,GAAG,IAAI,YAAY,EAAqC,CAAC;QAEjF,yFAAyF;QACzF,qFAAqF;QACrF,oFAAoF;QACpF,wFAAwF;QACxF,sEAAsE;QAEtE,uEAAuE;QAC7D,eAAU,GAAG,IAAI,YAAY,EAAiC,CAAC;QACzE,0DAA0D;QAChD,cAAS,GAAG,IAAI,YAAY,EAAgC,CAAC;QACvE,mGAAmG;QACzF,iBAAY,GAAG,IAAI,YAAY,EAAmC,CAAC;QAC7E,4DAA4D;QAClD,gBAAW,GAAG,IAAI,YAAY,EAAkC,CAAC;QAC3E,yEAAyE;QAC/D,iBAAY,GAAG,IAAI,YAAY,EAAmC,CAAC;QAC7E,4DAA4D;QAClD,gBAAW,GAAG,IAAI,YAAY,EAAkC,CAAC;QAmCnE,UAAK,GAAmB,QAAQ,CAAC;QAClC,aAAQ,GAAW,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAC5C,aAAQ,GAAG,CAAC,CAAC;QACb,cAAS,GAAmC,MAAM,CAAC;QACnD,aAAQ,GAAG,EAAE,CAAC;QACd,eAAU,GAAyB,MAAM,CAAC;QAC1C,aAAQ,GAAG,IAAI,CAAC;QAChB,cAAS,GAAkB,IAAI,CAAC;QAEvC,eAAe;QACR,aAAQ,GAAG,KAAK,CAAC;QACjB,cAAS,GAAG,KAAK,CAAC;QAClB,eAAU,GAAG,KAAK,CAAC;QAE1B,sBAAsB;QACf,kBAAa,GAAmC,IAAI,CAAC;QACrD,cAAS,GAAkB,IAAI,CAAC;QAC/B,iBAAY,GAAa,EAAE,CAAC;QAC5B,eAAU,GAAyC,IAAI,CAAC;QACxD,kBAAa,GAAyC,IAAI,CAAC;QAEnE,wBAAwB;QACjB,kBAAa,GAAG,EAAE,CAAC;QAClB,mBAAc,GAAG,CAAC,CAAC;QACnB,gBAAW,GAAkB,IAAI,CAAC;QAClC,eAAU,GAAyC,IAAI,CAAC;QAEhE,0BAA0B;QACnB,YAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACpB,WAAM,GAA0C,IAAI,CAAC;QAGrD,eAAU,GAAmB,EAAE,CAAC;QAChC,QAAG,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC;QA8NxC,oEAAoE;QAEpE;;;;;WAKG;QACoC,iBAAY,GAAG,IAAI,CAAC;QAE1C,SAAI,GAA4B,MAAM,CAAC,UAAU,CAAC,CAAC;KAkOrE;IAhoBC;;;;;;;;;;;;;;;;;OAiBG;IACH,IACI,UAAU,CAAC,KAA2B;QACxC,yFAAyF;QACzF,2FAA2F;QAC3F,4FAA4F;QAC5F,6EAA6E;QAC7E,EAAE;QACF,2FAA2F;QAC3F,yFAAyF;QACzF,mEAAmE;QACnE,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACrE,yFAAyF;QACzF,2FAA2F;QAC3F,IAAI,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;YACvC,OAAO;QACT,CAAC;QACD,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,mFAAmF;QACnF,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC;IACzB,CAAC;IACD,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IA8ED,0EAA0E;IAC1E;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,IAAW,IAAI;QACb,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IACD,IAAW,IAAI,CAAC,KAAqB;QACnC,IAAI,CAAC,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC;YACjD,CAAC,CAAC,KAAK;YACP,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IACtD,CAAC;IAoCD,QAAQ;QACN,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,EAAE;YACzD,kFAAkF;YAClF,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,IAAI,MAAM,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;gBACxD,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC5B,CAAC;YACD,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QAC1B,CAAC,CAAC,CAAC;QACH,qFAAqF;QACrF,kFAAkF;QAClF,6BAA6B;QAC7B,IAAI,CAAC,UAAU,CAAC,IAAI,CAClB,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAChE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAC9D,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EACpE,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAClE,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EACpE,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CACnE,CAAC;QACF,IAAI,CAAC,MAAM,GAAG,WAAW,CAAC,GAAG,EAAE;YAC7B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAC1B,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QAC1B,CAAC,EAAE,IAAI,CAAC,CAAC;IACX,CAAC;IAED,WAAW;QACT,IAAI,CAAC,UAAU,EAAE,WAAW,EAAE,CAAC;QAC/B,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YAClC,GAAG,CAAC,WAAW,EAAE,CAAC;QACpB,CAAC;QACD,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;QACrB,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAChC,CAAC;QACD,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAChC,CAAC;QACD,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACnC,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,wEAAwE;IAExE;;;;;OAKG;IACI,cAAc,CAAC,QAAgB,EAAE,QAAgB;QACtD,MAAM,UAAU,GAAG,wBAAwB,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC5E,IAAI,MAAM,GAAgC,IAAI,CAAC;QAC/C,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAyB,CAAC;QAC1D,CAAC;QACD,MAAM,CAAC;YACL,MAAM,GAAG,IAAI,CAAC;QAChB,CAAC;QACD,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;YACpB,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACtC,IAAI,CAAC,eAAe,CAAC,+BAA+B,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC7E,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QACxB,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,gEAAgE;IAEzD,UAAU,CAAC,KAAY;QAC5B,KAAK,CAAC,eAAe,EAAE,CAAC;QACxB,IAAI,CAAC,QAAQ,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC;IACjC,CAAC;IAEO,SAAS;QACf,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACxB,CAAC;IACH,CAAC;IAEM,WAAW;QAChB,IAAI,CAAC,SAAS,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;QACjC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC5C,CAAC;IAED,6DAA6D;IAEtD,YAAY,CAAC,KAAY;QAC9B,KAAK,CAAC,eAAe,EAAE,CAAC;QACxB,IAAI,CAAC,UAAU,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC;IACrC,CAAC;IAEO,WAAW;QACjB,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QAC1B,CAAC;IACH,CAAC;IAED;;;;;;;;OAQG;IAEI,iBAAiB;QACtB,IAAI,CAAC,SAAS,EAAE,CAAC;QACjB,IAAI,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;IAED,8DAA8D;IAC9D,4FAA4F;IACrF,qBAAqB;QAC1B,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QACxB,IAAI,CAAC,wBAAwB,CAAC,IAAI,EAAE,CAAC;IACvC,CAAC;IAEM,kBAAkB;QACvB,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE,WAAW,EAAE,cAAc,+BAA+B,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;QAC/H,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;IAC1B,CAAC;IAED,yFAAyF;IAClF,0BAA0B;QAC/B,MAAM,IAAI,GAAG,iCAAiC,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;QACjF,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,WAAW,EAAE,wBAAwB,+BAA+B,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;QACvH,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;IAC1B,CAAC;IAED,6DAA6D;IACtD,iBAAiB;QACtB,IAAI,CAAC,YAAY,CAAC,wBAAwB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,eAAe,EAAE,cAAc,+BAA+B,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;QAChJ,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;IAC1B,CAAC;IAED;;;;OAIG;IACI,yBAAyB;QAC9B,MAAM,KAAK,GAAG,+BAA+B,CAAC,eAAe,EAAE,CAAC;QAChE,KAAK,MAAM,IAAI,IAAI,6BAA6B,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAC7D,MAAM,IAAI,GAAG,+BAA+B,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC;YACxF,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,EAAE,cAAc,KAAK,IAAI,IAAI,MAAM,CAAC,CAAC;QACtF,CAAC;QACD,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;IAC1B,CAAC;IAED,uFAAuF;IACvF,IAAW,gBAAgB;QACzB,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;IACrC,CAAC;IAED;;;;OAIG;IACI,WAAW;QAChB,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QACxB,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;QACzD,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO,CAAC,IAAI,CAAC,6EAA6E,CAAC,CAAC;YAC5F,OAAO;QACT,CAAC;QACD,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC;QACnD,WAAW,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QAC7B,WAAW,CAAC,KAAK,EAAE,CAAC;QACpB,kFAAkF;QAClF,UAAU,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,GAAG,CAAC,CAAC;IAC7C,CAAC;IAEO,eAAe;QACrB,OAAO,yBAAyB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,6EAA6E;IACrE,aAAa;QACnB,OAAO;YACL,KAAK,EAAE,IAAI,CAAC,UAAU;YACtB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,cAAc,EAAE;SACzC,CAAC;IACJ,CAAC;IAED,+FAA+F;IACvF,MAAM,CAAC,YAAY,CAAC,IAAY;QACtC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACrG,CAAC;IAEO,YAAY,CAAC,OAAe,EAAE,QAAgB,EAAE,QAAgB;QACtE,MAAM,GAAG,GAAG,GAAG,CAAC,eAAe,CAAC,IAAI,IAAI,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;QACzE,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;QAC3C,MAAM,CAAC,IAAI,GAAG,GAAG,CAAC;QAClB,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAC3B,MAAM,CAAC,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAEO,MAAM,CAAC,eAAe;QAC5B,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED,uDAAuD;IAEhD,WAAW,CAAC,KAAY;QAC7B,KAAK,CAAC,eAAe,EAAE,CAAC;QACxB,kFAAkF;QAClF,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAClB,IAAI,CAAC,SAAS,EAAE,CAAC;QACjB,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;IACxB,CAAC;IAcD;;;;;;OAMG;IAEI,iBAAiB;QACtB,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;YAC3B,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IAED,wEAAwE;IAChE,cAAc;QACpB,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC;QACnC,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC;QACtC,OAAO,CAAC,CAAC,MAAM,IAAI,CAAC,MAAM,KAAK,EAAE,IAAI,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IAC5D,CAAC;IAGM,SAAS,CAAC,KAAoB;QACnC,wFAAwF;QACxF,uFAAuF;QACvF,oFAAoF;QACpF,yFAAyF;QACzF,wFAAwF;QACxF,mEAAmE;QACnE,IAAI,CAAC,IAAI,CAAC,qBAAqB,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;YAC1D,OAAO;QACT,CAAC;QACD,wFAAwF;QACxF,4FAA4F;QAC5F,yFAAyF;QACzF,uEAAuE;QACvE,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,OAAO;QACT,CAAC;QACD,MAAM,MAAM,GAAG,KAAK,CAAC,MAA4B,CAAC;QAClD,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,KAAK,OAAO,IAAI,MAAM,CAAC,OAAO,KAAK,UAAU,IAAI,MAAM,CAAC,iBAAiB,CAAC,EAAE,CAAC;YACxG,OAAO;QACT,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,GAAG,EAAE,CAAC;YACxE,KAAK,CAAC,cAAc,EAAE,CAAC;YACvB,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACnB,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YACpB,CAAC;iBACI,CAAC;gBACJ,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YACpB,CAAC;YACD,OAAO;QACT,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,GAAG,EAAE,CAAC;YACxE,KAAK,CAAC,cAAc,EAAE,CAAC;YACvB,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YAClB,OAAO;QACT,CAAC;QACD,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YACnD,OAAO;QACT,CAAC;QACD,QAAQ,KAAK,CAAC,GAAG,EAAE,CAAC;YAClB,KAAK,QAAQ;gBACX,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC;gBACrB,IAAI,CAAC,KAAK,EAAE,eAAe,EAAE,CAAC;gBAC9B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBACxB,MAAM;YACR,KAAK,QAAQ,CAAC;YACd,KAAK,WAAW;gBACd,IAAI,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACtC,KAAK,CAAC,cAAc,EAAE,CAAC;oBACvB,iEAAiE;oBACjE,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;gBACpC,CAAC;gBACD,MAAM;YACR,OAAO,CAAC,CAAC,CAAC;gBACR,MAAM,IAAI,GAAG,+BAA+B,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBACnE,mFAAmF;gBACnF,4EAA4E;gBAC5E,IAAI,IAAI,EAAE,CAAC;oBACT,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;gBACnB,CAAC;gBACD,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IAED,kFAAkF;IAElF,IAAW,YAAY;QACrB,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC;IACjC,CAAC;IAED,IAAW,SAAS;QAClB,OAAO,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IAC1C,CAAC;IAED,IAAW,UAAU;QACnB,OAAO,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IAC3C,CAAC;IAED,IAAW,UAAU;QACnB,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC;IAC/B,CAAC;IAED,iFAAiF;IACjF,IAAW,cAAc;QACvB,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,EAAE,CAAC;YAC7B,OAAO,GAAG,CAAC;QACb,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;QAClF,IAAI,OAAO,GAAG,EAAE,EAAE,CAAC;YACjB,OAAO,GAAG,OAAO,QAAQ,CAAC;QAC5B,CAAC;QACD,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,UAAU,CAAC;IAC/C,CAAC;IAED,IAAW,oBAAoB;QAC7B,OAAO,uBAAuB,CAAC;IACjC,CAAC;IAED,2DAA2D;IAEnD,kBAAkB;QACxB,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAChC,CAAC;QACD,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC,GAAG,EAAE;YAChC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;YACvB,IAAI,CAAC,cAAc,EAAE,CAAC;QACxB,CAAC,EAAE,uBAAuB,CAAC,CAAC;IAC9B,CAAC;IAEO,cAAc;QACpB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC9D,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC;QAC5C,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC9B,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACpD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QAC5C,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;IAC1B,CAAC;IAEO,iBAAiB,CAAC,MAA0B;QAClD,IAAI,CAAC,GAAG,GAAG,CAAC;QACZ,IAAI,CAAC,GAAG,GAAG,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC7D,IAAI,IAAI,EAAE,CAAC;YACT,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YACtC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;YACnB,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;QACzB,CAAC;QACD,IAAI,CAAC,aAAa,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,SAAS,cAAc,EAAE,CAAC;QAC1F,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACnC,CAAC;QACD,IAAI,CAAC,aAAa,GAAG,UAAU,CAAC,GAAG,EAAE;YACnC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;YAC1B,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QAC1B,CAAC,EAAE,WAAW,CAAC,CAAC;IAClB,CAAC;IAEO,eAAe,CAAC,MAAc;QACpC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;QACzB,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACxC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC;YACzC,CAAC,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE;YACrG,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACzB,IAAI,CAAC,SAAS,GAAG,GAAG,IAAI,CAAC,SAAS,IAAI,MAAM,aAAa,CAAC;QAC1D,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAChC,CAAC;QACD,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,QAAQ,CAAC,CAAC;IACjE,CAAC;IAEO,SAAS;QACf,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;QACvB,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC9B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACzB,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;IAC1B,CAAC;IAEO,MAAM,CAAC,UAAU,CAAC,QAAgB;QACxC,QAAQ,QAAQ,EAAE,CAAC;YACjB,KAAK,qBAAqB,CAAC,OAAO,CAAC,CAAC,OAAO,cAAc,CAAC;YAC1D,KAAK,qBAAqB,CAAC,QAAQ,CAAC,CAAC,OAAO,eAAe,CAAC;YAC5D,KAAK,qBAAqB,CAAC,OAAO,CAAC,CAAC,OAAO,eAAe,CAAC;YAC3D,KAAK,qBAAqB,CAAC,WAAW,CAAC,CAAC,OAAO,wBAAwB,CAAC;YACxE,KAAK,qBAAqB,CAAC,OAAO,CAAC,CAAC,OAAO,sBAAsB,CAAC;YAClE,KAAK,qBAAqB,CAAC,aAAa,CAAC,CAAC,OAAO,gBAAgB,CAAC;YAClE,KAAK,qBAAqB,CAAC,aAAa,CAAC,CAAC,OAAO,mBAAmB,CAAC;YACrE,KAAK,qBAAqB,CAAC,SAAS,CAAC,CAAC,OAAO,sBAAsB,CAAC;YACpE,KAAK,qBAAqB,CAAC,QAAQ,CAAC,CAAC,OAAO,eAAe,CAAC;YAC5D,KAAK,qBAAqB,CAAC,UAAU,CAAC,CAAC,OAAO,iBAAiB,CAAC;YAChE,KAAK,qBAAqB,CAAC,SAAS,CAAC,CAAC,OAAO,kBAAkB,CAAC;YAChE,KAAK,qBAAqB,CAAC,OAAO,CAAC,CAAC,OAAO,gBAAgB,CAAC;YAC5D,KAAK,qBAAqB,CAAC,UAAU,CAAC,CAAC,OAAO,gBAAgB,CAAC;YAC/D,KAAK,qBAAqB,CAAC,UAAU,CAAC,CAAC,OAAO,gBAAgB,CAAC;YAC/D,OAAO,CAAC,CAAC,OAAO,mBAAmB,CAAC;QACtC,CAAC;IACH,CAAC;IAEO,MAAM,CAAC,UAAU,CAAC,GAAW;QACnC,QAAQ,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC;YAC1B,KAAK,GAAG,CAAC,CAAC,OAAO,QAAQ,CAAC;YAC1B,KAAK,GAAG,CAAC,CAAC,OAAO,KAAK,CAAC;YACvB,KAAK,GAAG,CAAC,CAAC,OAAO,KAAK,CAAC;YACvB,KAAK,GAAG,CAAC,CAAC,OAAO,OAAO,CAAC;YACzB,KAAK,GAAG,CAAC,CAAC,OAAO,QAAQ,CAAC;YAC1B,KAAK,GAAG,CAAC,CAAC,OAAO,MAAM,CAAC;YACxB,KAAK,GAAG,CAAC,CAAC,OAAO,UAAU,CAAC;YAC5B,KAAK,GAAG,CAAC,CAAC,OAAO,MAAM,CAAC;YACxB,KAAK,GAAG,CAAC,CAAC,OAAO,OAAO,CAAC;YACzB,KAAK,GAAG,CAAC,CAAC,OAAO,WAAW,CAAC;YAC7B,KAAK,GAAG,CAAC,CAAC,OAAO,QAAQ,CAAC;YAC1B,OAAO,CAAC,CAAC,OAAO,IAAI,CAAC;QACvB,CAAC;IACH,CAAC;gIA1pBU,+BAA+B;oEAA/B,+BAA+B;2BA+I/B,gCAAgC;;;;;YA/IhC,oGAAA,uBAAmB,0BAAY,mGAA/B,uBAAmB,IAAY,iGAA/B,qBAAiB,0BAAc;;;;;YCrE1C,AADF,8BAAwB,cACL;YAAA,uBAAsC;YAAC,YAAgB;YAAA,iBAAO;YAC/E,+BAAyB;YAAA,uBAAwC;YAAC,YAAgB;YAAA,iBAAO;YAEvF,AADF,+BAA2B,WACnB;YAAA,0BAAgC;YAAA,oBAAG;YAAA,iBAAO;YAChD,6BAAM;YAAA,2BAAiC;YAAA,aAAgB;YAAA,wBAAkD;YAC3G,AAD2G,iBAAO,EAC3G;YAEL,AADF,gCAAsB,kBACqF;YAA7B,mHAAS,sBAAkB,IAAC;YACvE,AAA/B,4BAA+B,aAAiC;YAAC,aACjE;YAAA,0IAAgB;YAQlB,iBAAS;YAEP,AADF,iCAA0B,kBACsE;YAA/B,mHAAS,wBAAoB,IAAC;YAC3F,yBAAuC;YAAC,yBAC1C;YAAA,iBAAS;YACT,qGAAkB;YA2BpB,iBAAO;YACP,mCAAsF;YAAxB,6GAAS,iBAAa,IAAC;YACnF,qBAA2E;YAC3E,aACF;YAAA,iBAAS;YACT,mCAAmE;YAAA,yBAAoC;YAE3G,AADE,AADyG,iBAAS,EAC5G,EACF;YAIJ,AADF,gCAAwB,qCAoB4B;YAAhD,AADA,AADA,AADA,AADA,AADA,gLAAmC,4IACf,iCAA6B,IAAC,0IAC/B,gCAA4B,IAAC,8IAC3B,kCAA8B,IAAC,0IACjC,gCAA4B,IAAC,wIAC9B,+BAA2B,IAAC;YAnBhD,iBAmBkD;YAIlD,gIAAiB;YA2BjB,wDAO2C;YAAzC,AADA,AADA,AADA,AADA,iNAAW,kBAAe,KAAC,kMACjB,iBAAc,KAAC,wMACf,6BAA0B,KAAC,4LAC9B,uBAAoB,KAAC,gNACX,wBAAqB,KAAC;YAPzC,iBAO2C;YAG3C,oGAAiB;YASnB,iBAAM;YAMe,AAAnB,AADF,gCAA0B,gBACL,SAAG;YAAA,aAAkB;YAAA,iBAAI;YAAC,0BAAQ;YAAA,iBAAO;YAC5D,iCAAmB;YAAA,qBAAI;YAAA,0BAAG;YAAA,aAAe;YAAA,iBAAI;YAAC,aAAkB;YAAA,0BAAG;YAAA,aAAgB;YAAI,AAAJ,iBAAI,EAAO;YAC9F,iCAAmB;YAAA,wBAAO;YAAA,0BAAG;YAAA,aAAoB;YAAA,iBAAI;YAAC,6BAAM;YAAA,0BAAG;YAAA,aAAgB;YAAI,AAAJ,iBAAI,EAAO;YAExF,AADF,iCAAoB,gBAC2D;YAC3E,4BAAuB;YAAA,iCAA6B;YAAC,aAAuC;YAC9F,AAD8F,iBAAO,EAC9F;YACP,iCAAqF;YACnF,yBAA0D;YAC1D,iCAA4B;YAAA,6BAAY;YAAA,0BAAG;YAAA,iCAAgB;YAAA,iBAAI;YAAC,oCAAkB;YAAA,iBAAO;YACzF,iCAA6B;YAAA,iCAAgB;YAGnD,AADE,AADE,AAD+C,iBAAO,EAC/C,EACF,EACH;;;YApJoD,eAAgB;YAAhB,0CAAgB;YACN,eAAgB;YAAhB,0CAAgB;YAGzC,eAAgB;YAAhB,6CAAgB;YAGD,eAAqB;YAArB,kCAAqB;YACR,eACjE;YADiE,wDACjE;YAAA,cAOC;YAPD,wCAOC;YAGsC,eAAuB;YAAvB,oCAAuB;YAG9D,eA0BC;YA1BD,0CA0BC;YAEoC,cAAsB;YAAtB,mCAAsB;YACxD,cAAmE;YAAnE,4EAAmE;YACtE,cACF;YADE,8EACF;YAQA,eAAe;YAYf,AADA,AADA,AADA,AADA,AADA,AADA,AADA,AADA,AADA,AADA,AADA,AADA,iCAAe,4BACQ,kBACV,8BACY,0BACJ,0BACA,0BACA,4BACE,0BACF,8BACI,0BACJ,4BACE,oCACQ;YAUjC,eAyBC;YAzBD,yCAyBC;YAGC,cAAiC;YACjC,AADA,kDAAiC,qCACA;YAQnC,cAQC;YARD,yCAQC;YAOqB,eAAkB;YAAlB,sCAAkB;YACd,eAAe;YAAf,mCAAe;YAAK,cAAkB;YAAlB,qDAAkB;YAAG,eAAgB;YAAhB,oCAAgB;YACtD,eAAoB;YAApB,wCAAoB;YAAc,eAAgB;YAAhB,oCAAgB;YAEjD,eAAgD;YAAhD,uEAAgD;YACrB,eAAuC;YAAvC,qEAAuC;4BDhF9F,YAAY;YACZ,gCAAgC;YAChC,kCAAkC;YAClC,+BAA+B;YAC/B,2CAA2C;;iFAKlC,+BAA+B;cAb3C,SAAS;6BACI,IAAI,YACN,6BAA6B,WAC9B;oBACP,YAAY;oBACZ,gCAAgC;oBAChC,kCAAkC;oBAClC,+BAA+B;oBAC/B,2CAA2C;iBAC5C;;kBAMA,KAAK;mBAAC,EAAE,QAAQ,EAAE,IAAI,EAAE;;kBAExB,KAAK;;kBAEL,KAAK;;kBAEL,KAAK;;kBAiBL,KAAK;;kBAoBL,KAAK;;kBAyCL,KAAK;;kBAGL,MAAM;;kBAEN,MAAM;;kBAEN,MAAM;;kBAEN,MAAM;;kBAMN,MAAM;;kBAMN,MAAM;;kBAQN,MAAM;;kBAKN,MAAM;;kBAEN,MAAM;;kBASN,MAAM;;kBAEN,MAAM;;kBAEN,MAAM;;kBAEN,MAAM;;kBAEN,MAAM;;kBAEN,MAAM;;kBAEN,SAAS;mBAAC,gCAAgC;;kBAkL1C,YAAY;mBAAC,gBAAgB;;kBAsH7B,WAAW;mBAAC,eAAe;;kBAW3B,YAAY;mBAAC,aAAa;;kBAc1B,YAAY;mBAAC,kBAAkB,EAAE,CAAC,QAAQ,CAAC;;kFAhdjC,+BAA+B","sourcesContent":["import {\n ChangeDetectorRef, Component, ElementRef, EventEmitter, HostBinding, HostListener, Input,\n OnDestroy, OnInit, Output, ViewChild, inject\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { Subscription } from 'rxjs';\nimport {\n WhiteboardFontFamily, WhiteboardItemAddedEventArgs, WhiteboardItemAddingEventArgs,\n WhiteboardItemRemovedEventArgs, WhiteboardItemRemovingEventArgs,\n WhiteboardItemUpdatedEventArgs, WhiteboardItemUpdatingEventArgs, WhiteboardState\n} from './whiteboard-state';\nimport { WhiteboardTool, WhiteboardToolRoster, ClampToolToRoster, IsToolAllowed, SameRoster } from './whiteboard-tool-roster';\nimport {\n BuildWhiteboardExportHtml, BuildWhiteboardExportHtmlAllPages, BuildWhiteboardExportSvg,\n BuildWhiteboardExportSvgPages\n} from './whiteboard-export';\nimport { ApplyWhiteboardAgentTool, WHITEBOARD_TOOL_NAMES, WhiteboardToolResult } from './whiteboard-tools';\nimport {\n RealtimeWhiteboardBoardComponent, WhiteboardAgentPresence,\n WhiteboardContentAppliedEventArgs, WhiteboardContentApplyingEventArgs\n} from './whiteboard-board.component';\nimport {\n WhiteboardWidgetInteractionEvent, WhiteboardWidgetSubmitEvent, WhiteboardWidgetSubmittingEventArgs\n} from './whiteboard-widget-bridge';\nimport { RealtimeWhiteboardToolbarComponent, WHITEBOARD_PEN_COLORS } from './whiteboard-toolbar.component';\nimport { RealtimeWhiteboardZoomComponent } from './whiteboard-zoom.component';\nimport { RealtimeWhiteboardAgentSeesPopoverComponent } from './whiteboard-agent-sees-popover.component';\n\n/** Debounce window for the perception feed (the popover's \"debounce 750 ms\" stat). */\nconst SCENE_DELTA_DEBOUNCE_MS = 750;\n/** How long the agent-action toast stays up (coalescing further actions while visible). */\nconst TOAST_MS = 6000;\n/** How long the presence cursor lingers after the agent's last board action. */\nconst PRESENCE_MS = 4200;\n\n/**\n * LIVE WHITEBOARD host (`mj-realtime-whiteboard-host`): board header (title / saved chip /\n * ownership legend / \"What [Agent] sees\" popover / Focus toggle), the board surface with its\n * floating toolbar + zoom cluster, the agent action toast with Undo, and the status footer —\n * everything EXCEPT the overlay/tab chrome, which the session shell owns.\n *\n * Integration contract:\n * - `State` is created by the integration layer (channel state of record) and passed in;\n * - `SceneDelta` emits the debounced (750 ms), coalesced scene-delta JSON on user changes —\n * the perception feed the integration pipes into the live agent context;\n * - `ApplyAgentTool(toolName, argsJson)` executes one agent channel tool\n * (`Whiteboard_AddNote` … see `WHITEBOARD_TOOL_DEFINITIONS`) with the violet pop-in,\n * toast and presence-cursor garnish, returning the result JSON for the tool round-trip;\n * - `AgentUndo` fires when the user clicks Undo on the agent-action toast;\n * - `FocusModeChange` asks the shell to collapse/restore the call rail (\"Focus board\").\n *\n * Extensibility (before/after events): the host mirrors the engine's cancelable\n * BEFORE / AFTER mutation pairs as outputs (`ItemAdding`/`ItemAdded`,\n * `ItemUpdating`/`ItemUpdated`, `ItemRemoving`/`ItemRemoved`) and forwards the board's\n * editor + widget pairs (`ContentApplying`/`ContentApplied`,\n * `WidgetSubmitting`/`WidgetSubmitted`). All BEFORE events honor `Cancel = true` set\n * synchronously by a handler.\n */\n@Component({\n standalone: true,\n selector: 'mj-realtime-whiteboard-host',\n imports: [\n CommonModule,\n RealtimeWhiteboardBoardComponent,\n RealtimeWhiteboardToolbarComponent,\n RealtimeWhiteboardZoomComponent,\n RealtimeWhiteboardAgentSeesPopoverComponent\n ],\n templateUrl: './whiteboard-host.component.html',\n styleUrl: './whiteboard-host.component.css'\n})\nexport class RealtimeWhiteboardHostComponent implements OnInit, OnDestroy {\n /** Shared board state engine, owned by the integration layer. */\n @Input({ required: true }) State!: WhiteboardState;\n /** Display name of the session's agent (legend, chips, popover, toast). */\n @Input() AgentName = 'Agent';\n /** Board title shown in the header. */\n @Input() BoardTitle = 'Whiteboard';\n /** Persistence chip text (e.g. \"Saved to session · v14\"). */\n @Input() SavedLabel = 'Saved to session';\n /**\n * Opt back in to DOCUMENT-WIDE keyboard shortcuts.\n *\n * The host binds eleven bare single-character tool shortcuts (v h p r s t m w i c e). While\n * those listened on `document` unconditionally they fired wherever the user was on the page,\n * which fails WCAG 2.1.4 (Character Key Shortcuts): a speech-input user saying an ordinary\n * word, or anyone typing in a non-input control elsewhere, silently switched the board tool.\n * They are now scoped to focus being inside this host, which satisfies the criterion's\n * \"active only on focus\" branch.\n *\n * Scoping covers the host's ENTIRE keydown handler, not only the letters: undo/redo\n * (Cmd/Ctrl+Z, +Y), Escape and Delete/Backspace are focus-gated as well.\n *\n * Set `true` only for a surface where the whiteboard is the entire page AND the 2.1.4\n * exposure has been accepted — it is an accessibility regression, not a convenience flag.\n */\n @Input() EnableGlobalShortcuts = false;\n\n /**\n * Which tools this surface offers. `null` (default) is all eleven: today's rendering.\n *\n * The roster governs which tools are AVAILABLE, closing every door to a tool it leaves out:\n * the toolbar button, the single-letter shortcut, and the canvas \"add … here\" action. It is\n * deliberately not a content policy — it does not restrict what already exists on the board,\n * what the agent places, or authoring on existing items (Duplicate, z-order, Delete, paste).\n * The one exception is Restyle…, which is hidden when the roster omits `text`, because it\n * opens the TEXT tool's style flyout and would otherwise be a menu entry that does nothing.\n *\n * An empty roster (or one naming no real tool) narrows the palette to nothing and clamps the\n * active tool to `select`. It does NOT make the board read-only — that is {@link ReadOnly}.\n *\n * A setter rather than `ngOnChanges` (packages/Angular/CLAUDE.md): a realtime channel's\n * `BindSurface` assigns this property directly on a dynamically-created component, and\n * Angular fires no `ngOnChanges` for a plain assignment, so a clamp implemented there would\n * silently never run on the path real consumers use.\n */\n @Input()\n set ToolRoster(value: WhiteboardToolRoster) {\n // Anything that is not an array reads as NO roster. The type does not protect us here: a\n // STATIC template attribute (`ToolRoster=\"select,pan\"` — a plausible typo for the binding)\n // hands us a string, and a string reaching the helpers' `.includes` / `.filter` would throw\n // during render. A consumer's punctuation slip must not take the board down.\n //\n // The kept value is a frozen COPY, so the roster the host enforces cannot be edited behind\n // its back — a consumer splicing its own array afterwards changes their array, not ours,\n // and is picked up as a genuine change the next time they bind it.\n const next = Array.isArray(value) ? Object.freeze([...value]) : null;\n // Compare by CONTENT, not identity (see SameRoster): identity re-clamped on every change\n // detection for a bound array literal, and never re-clamped for an array mutated in place.\n if (SameRoster(next, this._toolRoster)) {\n return;\n }\n this._toolRoster = next;\n // Re-validate the CURRENT tool through the same chokepoint every other write uses.\n this.Tool = this._tool;\n }\n get ToolRoster(): WhiteboardToolRoster {\n return this._toolRoster;\n }\n private _toolRoster: WhiteboardToolRoster = null;\n\n /**\n * Render the board read-only: nothing on it can be created, edited, moved or deleted.\n *\n * This is the OTHER axis from {@link ToolRoster}, and the two do not substitute for each\n * other. The roster answers \"which tools does this surface offer\" — it narrows a palette the\n * user still authors with. `ReadOnly` answers \"may anything change at all\" — it is about\n * mutation, not about choice, so an empty roster is not a read-only board and a full roster\n * on a read-only board still mutates nothing.\n *\n * The board component already guards every mutation entry point and hides the page strip's\n * add / rename / delete affordances; the host adds the chrome that only it owns — the floating\n * toolbar is not rendered (matching `WhiteboardSnapshotComponent`, which draws a read-only\n * board with no toolbar), the agent toast's Undo is hidden because Undo applies a mutation,\n * and the keyboard handler returns before any key can act. Pan and zoom stay live: reading a\n * board you cannot change still means moving around it.\n */\n @Input() ReadOnly = false;\n\n /** Debounced (750 ms), coalesced scene-delta JSON — the live perception feed. */\n @Output() SceneDelta = new EventEmitter<string>();\n /** The user clicked Undo on the agent-action toast (the undo itself already applied). */\n @Output() AgentUndo = new EventEmitter<void>();\n /** Focus-board toggle — the session shell collapses/restores the call rail. */\n @Output() FocusModeChange = new EventEmitter<boolean>();\n /** Emitted when the user picks \"Save to artifacts\" — the channel plugin persists via its host context. */\n @Output() SaveToArtifactsRequested = new EventEmitter<void>();\n /**\n * Cancelable BEFORE event (forwarded from the board): a sandboxed HTML widget submitted\n * input via `MJWhiteboard.submit` and it passed validation. Set `Cancel = true`\n * synchronously to drop it before {@link WidgetSubmitted} fires.\n */\n @Output() WidgetSubmitting = new EventEmitter<WhiteboardWidgetSubmittingEventArgs>();\n /**\n * AFTER event: a sandboxed HTML widget submitted user input via `MJWhiteboard.submit`\n * (validated + size-capped by the board, not canceled). Integration layers forward it\n * to their agent runtime — e.g. MJ's channel plugin sends a `[whiteboard]` context note.\n */\n @Output() WidgetSubmitted = new EventEmitter<WhiteboardWidgetSubmitEvent>();\n /**\n * AMBIENT widget telemetry (forwarded from the board): the injected recorder observed\n * passive form activity (clicks / changes / typing / focus) inside a sandboxed HTML\n * widget, validated + pre-summarized. Integration layers forward it to their agent\n * runtime as throttled, low-priority background context — e.g. MJ's channel plugin sends\n * an \"ambient activity\" `[whiteboard]` note at most once per widget per few seconds.\n */\n @Output() WidgetInteraction = new EventEmitter<WhiteboardWidgetInteractionEvent>();\n /**\n * Cancelable BEFORE event (forwarded from the board): an in-board editor commit is\n * about to write to the state engine. Set `Cancel = true` synchronously to discard it.\n */\n @Output() ContentApplying = new EventEmitter<WhiteboardContentApplyingEventArgs>();\n /** AFTER event (forwarded from the board): an editor commit applied. */\n @Output() ContentApplied = new EventEmitter<WhiteboardContentAppliedEventArgs>();\n\n // Engine mutation mirrors — the same before/after events {@link WhiteboardState} raises,\n // re-emitted as component outputs so template-driven consumers can bind them without\n // subscribing to the engine directly. Emission is synchronous, so cancelable BEFORE\n // mirrors (`ItemAdding` / `ItemUpdating` / `ItemRemoving`) honor `Cancel = true` set by\n // a template handler exactly like a direct engine subscription would.\n\n /** Cancelable BEFORE mirror of {@link WhiteboardState.ItemAdding$}. */\n @Output() ItemAdding = new EventEmitter<WhiteboardItemAddingEventArgs>();\n /** AFTER mirror of {@link WhiteboardState.ItemAdded$}. */\n @Output() ItemAdded = new EventEmitter<WhiteboardItemAddedEventArgs>();\n /** Cancelable BEFORE mirror of {@link WhiteboardState.ItemUpdating$} (update / move / reorder). */\n @Output() ItemUpdating = new EventEmitter<WhiteboardItemUpdatingEventArgs>();\n /** AFTER mirror of {@link WhiteboardState.ItemUpdated$}. */\n @Output() ItemUpdated = new EventEmitter<WhiteboardItemUpdatedEventArgs>();\n /** Cancelable BEFORE mirror of {@link WhiteboardState.ItemRemoving$}. */\n @Output() ItemRemoving = new EventEmitter<WhiteboardItemRemovingEventArgs>();\n /** AFTER mirror of {@link WhiteboardState.ItemRemoved$}. */\n @Output() ItemRemoved = new EventEmitter<WhiteboardItemRemovedEventArgs>();\n\n @ViewChild(RealtimeWhiteboardBoardComponent) public Board?: RealtimeWhiteboardBoardComponent;\n\n // tool state (host-owned; toolbar + keyboard drive it, board consumes it)\n /**\n * The active tool, and the ONE place the roster invariant is enforced on a write.\n *\n * \"The active tool is always one the roster allows\" is a property of every write, not of the\n * handful of call sites that exist today (the roster setter, Escape, the key map, and the two\n * template `Tool = $event` bindings). Guarding each of those would leave the next writer —\n * a new shortcut, a gesture, a host API — to remember the rule. Guarding here closes them all\n * by construction, and makes assignment order irrelevant: setting `ToolRoster` and `Tool` in\n * either order still lands on an allowed tool.\n *\n * A DISALLOWED request is ignored rather than clamped: pressing Escape under `['pen','eraser']`\n * should leave you on pen, not bounce you to the roster's fallback. The clamp is only for the\n * case where the tool you are already holding stopped being allowed.\n *\n * ONE EXCEPTION to \"always one the roster allows\": a roster that allows nothing at all — empty,\n * or naming no real tool. The board must hold some tool, so {@link ClampToolToRoster} floors it\n * at `select`, which is then held even though the roster does not list it. That is deliberate\n * and is the safe answer precisely because `select` can create nothing; the alternative —\n * keeping the tool the roster just revoked — left a creating tool live with no toolbar to see\n * it and no key to change it. See {@link ClampToolToRoster} for why the floor is `select`\n * rather than the roster's first entry.\n */\n public get Tool(): WhiteboardTool {\n return this._tool;\n }\n public set Tool(value: WhiteboardTool) {\n this._tool = IsToolAllowed(this._toolRoster, value)\n ? value\n : ClampToolToRoster(this._tool, this._toolRoster);\n }\n private _tool: WhiteboardTool = 'select';\n public PenColor: string = WHITEBOARD_PEN_COLORS[0];\n public PenWidth = 4;\n public ShapeKind: 'rect' | 'ellipse' | 'diamond' = 'rect';\n public TextSize = 12;\n public TextFamily: WhiteboardFontFamily = 'sans';\n public TextBold = true;\n public TextColor: string | null = null;\n\n // header state\n public SeesOpen = false;\n public FocusMode = false;\n public ExportOpen = false;\n\n // agent garnish state\n public AgentPresence: WhiteboardAgentPresence | null = null;\n public ToastText: string | null = null;\n private toastPhrases: string[] = [];\n private toastTimer: ReturnType<typeof setTimeout> | null = null;\n private presenceTimer: ReturnType<typeof setTimeout> | null = null;\n\n // perception feed state\n public LastDeltaJson = '';\n private lastDeltaToken = 0;\n private lastDeltaAt: number | null = null;\n private deltaTimer: ReturnType<typeof setTimeout> | null = null;\n\n // \"synced n s ago\" ticker\n public NowTick = Date.now();\n private ticker: ReturnType<typeof setInterval> | null = null;\n\n private changedSub?: Subscription;\n private mirrorSubs: Subscription[] = [];\n private cdr = inject(ChangeDetectorRef);\n\n ngOnInit(): void {\n this.changedSub = this.State.Changed$.subscribe((change) => {\n // perception feed: user edits (and scene replacements like undo) schedule a delta\n if (change.Author === 'user' || change.Op === 'replace') {\n this.scheduleSceneDelta();\n }\n this.cdr.markForCheck();\n });\n // Mirror the engine's before/after mutation events as component outputs. The re-emit\n // runs synchronously inside the engine's emit, so Cancel set by an output handler\n // still vetoes the mutation.\n this.mirrorSubs.push(\n this.State.ItemAdding$.subscribe((e) => this.ItemAdding.emit(e)),\n this.State.ItemAdded$.subscribe((e) => this.ItemAdded.emit(e)),\n this.State.ItemUpdating$.subscribe((e) => this.ItemUpdating.emit(e)),\n this.State.ItemUpdated$.subscribe((e) => this.ItemUpdated.emit(e)),\n this.State.ItemRemoving$.subscribe((e) => this.ItemRemoving.emit(e)),\n this.State.ItemRemoved$.subscribe((e) => this.ItemRemoved.emit(e))\n );\n this.ticker = setInterval(() => {\n this.NowTick = Date.now();\n this.cdr.markForCheck();\n }, 1000);\n }\n\n ngOnDestroy(): void {\n this.changedSub?.unsubscribe();\n for (const sub of this.mirrorSubs) {\n sub.unsubscribe();\n }\n this.mirrorSubs = [];\n if (this.deltaTimer) {\n clearTimeout(this.deltaTimer);\n }\n if (this.toastTimer) {\n clearTimeout(this.toastTimer);\n }\n if (this.presenceTimer) {\n clearTimeout(this.presenceTimer);\n }\n if (this.ticker) {\n clearInterval(this.ticker);\n }\n }\n\n // ────────────────────────────────────────────── AGENT tool entry point\n\n /**\n * Execute one agent whiteboard tool (author `'agent'`, one undo batch), with the UI\n * garnish: presence cursor glides to the mutation point, the new item pops in violet,\n * and the action toast (with Undo) appears. Returns the result JSON string that the\n * integration layer feeds back to the realtime model as the `tool_response`.\n */\n public ApplyAgentTool(toolName: string, argsJson: string): string {\n const resultJson = ApplyWhiteboardAgentTool(this.State, toolName, argsJson);\n let result: WhiteboardToolResult | null = null;\n try {\n result = JSON.parse(resultJson) as WhiteboardToolResult;\n }\n catch {\n result = null;\n }\n if (result?.success) {\n this.showAgentPresence(result.itemId);\n this.pushToastPhrase(RealtimeWhiteboardHostComponent.toolPhrase(toolName));\n }\n this.cdr.markForCheck();\n return resultJson;\n }\n\n // ────────────────────────────────────────────── header actions\n\n public ToggleSees(event: Event): void {\n event.stopPropagation();\n this.SeesOpen = !this.SeesOpen;\n }\n\n private closeSees(): void {\n if (this.SeesOpen) {\n this.SeesOpen = false;\n }\n }\n\n public ToggleFocus(): void {\n this.FocusMode = !this.FocusMode;\n this.FocusModeChange.emit(this.FocusMode);\n }\n\n // ────────────────────────────────────────────── export menu\n\n public ToggleExport(event: Event): void {\n event.stopPropagation();\n this.ExportOpen = !this.ExportOpen;\n }\n\n private closeExport(): void {\n if (this.ExportOpen) {\n this.ExportOpen = false;\n }\n }\n\n /**\n * The component's ONLY `document:click` listener — dismisses every open popover.\n *\n * ⚠️ Do NOT add a second `@HostListener('document:click')` here. Angular keys host\n * listeners by event name, so a second declaration for the same event silently\n * replaces the first (no build error, no warning). That had already happened:\n * `closeSees` and `closeExport` each declared one, so only the latter registered\n * and the Sees dropdown never closed on an outside click.\n */\n @HostListener('document:click')\n public CloseOpenPopovers(): void {\n this.closeSees();\n this.closeExport();\n }\n\n /** Download the board as one self-contained HTML document. */\n /** Request a first-class artifact snapshot of the board (handled by the channel plugin). */\n public ExportSaveToArtifacts(): void {\n this.ExportOpen = false;\n this.SaveToArtifactsRequested.emit();\n }\n\n public ExportDownloadHtml(): void {\n this.downloadBlob(this.buildExportHtml(), 'text/html', `whiteboard-${RealtimeWhiteboardHostComponent.exportDateStamp()}.html`);\n this.ExportOpen = false;\n }\n\n /** Download ONE self-contained HTML document containing EVERY page (titled sections). */\n public ExportDownloadHtmlAllPages(): void {\n const html = BuildWhiteboardExportHtmlAllPages(this.State, this.exportOptions());\n this.downloadBlob(html, 'text/html', `whiteboard-all-pages-${RealtimeWhiteboardHostComponent.exportDateStamp()}.html`);\n this.ExportOpen = false;\n }\n\n /** Download the ACTIVE page as a standalone SVG document. */\n public ExportDownloadSvg(): void {\n this.downloadBlob(BuildWhiteboardExportSvg(this.State), 'image/svg+xml', `whiteboard-${RealtimeWhiteboardHostComponent.exportDateStamp()}.svg`);\n this.ExportOpen = false;\n }\n\n /**\n * Download EVERY page as its own standalone SVG document (SVG is single-image, so\n * \"all pages\" is one file per page, downloaded sequentially with the page name\n * slug-suffixed into each filename).\n */\n public ExportDownloadSvgAllPages(): void {\n const stamp = RealtimeWhiteboardHostComponent.exportDateStamp();\n for (const page of BuildWhiteboardExportSvgPages(this.State)) {\n const slug = RealtimeWhiteboardHostComponent.fileNameSlug(page.PageName) || page.PageID;\n this.downloadBlob(page.Content, 'image/svg+xml', `whiteboard-${stamp}-${slug}.svg`);\n }\n this.ExportOpen = false;\n }\n\n /** Whether the board has more than one page (gates the \"all pages\" export entries). */\n public get HasMultiplePages(): boolean {\n return this.State.Pages.length > 1;\n }\n\n /**\n * Print the board: open a blank window, write the self-contained export document and\n * invoke the print dialog (same precedent as the artifact viewer's print path). When the\n * popup is blocked this is a logged no-op — nothing breaks, the user can retry.\n */\n public ExportPrint(): void {\n this.ExportOpen = false;\n const printWindow = window.open('about:blank', '_blank');\n if (!printWindow) {\n console.warn('Whiteboard print: popup was blocked — allow popups for this site and retry.');\n return;\n }\n printWindow.document.write(this.buildExportHtml());\n printWindow.document.close();\n printWindow.focus();\n // let the document lay out before invoking the dialog (artifact-viewer precedent)\n setTimeout(() => printWindow.print(), 250);\n }\n\n private buildExportHtml(): string {\n return BuildWhiteboardExportHtml(this.State, this.exportOptions());\n }\n\n /** Shared options for the HTML export builders (single page + all pages). */\n private exportOptions(): { Title: string; AgentName: string; GeneratedAt: string } {\n return {\n Title: this.BoardTitle,\n AgentName: this.AgentName,\n GeneratedAt: new Date().toLocaleString()\n };\n }\n\n /** Safe filename fragment from a page name (lowercased, non-alphanumerics collapse to '-'). */\n private static fileNameSlug(name: string): string {\n return (name ?? '').toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 40);\n }\n\n private downloadBlob(content: string, mimeType: string, fileName: string): void {\n const url = URL.createObjectURL(new Blob([content], { type: mimeType }));\n const anchor = document.createElement('a');\n anchor.href = url;\n anchor.download = fileName;\n anchor.click();\n URL.revokeObjectURL(url);\n }\n\n private static exportDateStamp(): string {\n return new Date().toISOString().slice(0, 10);\n }\n\n // ────────────────────────────────────────────── toast\n\n public OnToastUndo(event: Event): void {\n event.stopPropagation();\n // The agent's tool call ran as ONE undo batch, so a single Undo reverts it whole.\n this.State.Undo();\n this.hideToast();\n this.AgentUndo.emit();\n }\n\n // ────────────────────────────────────────────── keyboard shortcuts\n\n /**\n * The board is made focusable so its shortcuts have a focus scope to be bound to. `-1`, not\n * `0`: the canvas has no keyboard interaction model yet (see the whiteboard keyboard-\n * operability work), so adding a real Tab stop would put a stop in the page that a keyboard\n * user can reach and do nothing with. Click focuses it; that is the whole contract today.\n */\n @HostBinding('attr.tabindex') readonly HostTabIndex = '-1';\n\n private readonly host: ElementRef<HTMLElement> = inject(ElementRef);\n\n /**\n * Clicking the board takes focus, so the shortcuts below apply. The browser would usually do\n * this on its own by focusing the nearest focusable ancestor, but the board's pointer\n * pipeline is elaborate enough (drag, marquee, handles, transient shapes) that relying on\n * that default is fragile — one `preventDefault()` added later would silently kill every\n * shortcut. This makes it explicit.\n */\n @HostListener('pointerdown')\n public OnHostPointerDown(): void {\n if (!this.hasFocusWithin()) {\n this.host.nativeElement.focus({ preventScroll: true });\n }\n }\n\n /** Whether focus currently sits on, or inside, this whiteboard host. */\n private hasFocusWithin(): boolean {\n const el = this.host.nativeElement;\n const active = document.activeElement;\n return !!active && (active === el || el.contains(active));\n }\n\n @HostListener('document:keydown', ['$event'])\n public OnKeydown(event: KeyboardEvent): void {\n // WCAG 2.1.4: only live while focus is on the board. NOTE this gates the WHOLE handler,\n // not just the single-character tool keys that 2.1.4 is about — undo/redo (Cmd/Ctrl+Z,\n // +Y), Escape and Delete/Backspace are scoped too. That is deliberate: a board that\n // swallows the document's Cmd+Z from anywhere on the page is its own bug, and \"the board\n // responds to keys when you are on the board\" is the only model that stays predictable.\n // See {@link EnableGlobalShortcuts} for the (discouraged) opt-out.\n if (!this.EnableGlobalShortcuts && !this.hasFocusWithin()) {\n return;\n }\n // Read-only boards answer to NO key, Escape included. Every branch below either mutates\n // (undo/redo, Delete) or picks a tool that could, and Escape's selection-clear is not worth\n // an exception: \"the keyboard does nothing here\" is one rule a user can hold, where \"the\n // keyboard does nothing except Escape\" is a rule they have to be told.\n if (this.ReadOnly) {\n return;\n }\n const target = event.target as HTMLElement | null;\n if (target && (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable)) {\n return;\n }\n if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === 'z') {\n event.preventDefault();\n if (event.shiftKey) {\n this.State.Redo();\n }\n else {\n this.State.Undo();\n }\n return;\n }\n if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === 'y') {\n event.preventDefault();\n this.State.Redo();\n return;\n }\n if (event.metaKey || event.ctrlKey || event.altKey) {\n return;\n }\n switch (event.key) {\n case 'Escape':\n this.Tool = 'select';\n this.Board?.CancelTransient();\n this.State.Select(null);\n break;\n case 'Delete':\n case 'Backspace':\n if (this.State.SelectedIDs.length > 0) {\n event.preventDefault();\n // removes the WHOLE (single or multi) selection as one undo step\n this.State.RemoveSelected('user');\n }\n break;\n default: {\n const tool = RealtimeWhiteboardHostComponent.toolForKey(event.key);\n // No roster check here: the Tool setter ignores a disallowed write, so a key for a\n // hidden tool is a no-op by construction rather than by a remembered guard.\n if (tool) {\n this.Tool = tool;\n }\n break;\n }\n }\n }\n\n // ────────────────────────────────────────────── status footer / popover bindings\n\n public get ElementCount(): number {\n return this.State.ElementCount;\n }\n\n public get UserCount(): number {\n return this.State.CountByAuthor('user');\n }\n\n public get AgentCount(): number {\n return this.State.CountByAuthor('agent');\n }\n\n public get CurrentSeq(): number {\n return this.State.CurrentSeq;\n }\n\n /** \"2 s ago\" style age of the last emitted delta (the ticker keeps it fresh). */\n public get LastDeltaLabel(): string {\n if (this.lastDeltaAt == null) {\n return '—';\n }\n const seconds = Math.max(0, Math.round((this.NowTick - this.lastDeltaAt) / 1000));\n if (seconds < 60) {\n return `${seconds} s ago`;\n }\n return `${Math.floor(seconds / 60)} min ago`;\n }\n\n public get SceneDeltaDebounceMs(): number {\n return SCENE_DELTA_DEBOUNCE_MS;\n }\n\n // ────────────────────────────────────────────── internals\n\n private scheduleSceneDelta(): void {\n if (this.deltaTimer) {\n clearTimeout(this.deltaTimer);\n }\n this.deltaTimer = setTimeout(() => {\n this.deltaTimer = null;\n this.emitSceneDelta();\n }, SCENE_DELTA_DEBOUNCE_MS);\n }\n\n private emitSceneDelta(): void {\n const delta = this.State.BuildSceneDelta(this.lastDeltaToken);\n this.lastDeltaToken = this.State.CurrentSeq;\n this.lastDeltaAt = Date.now();\n this.LastDeltaJson = JSON.stringify(delta, null, 2);\n this.SceneDelta.emit(JSON.stringify(delta));\n this.cdr.markForCheck();\n }\n\n private showAgentPresence(itemId: string | undefined): void {\n let x = 480;\n let y = 220;\n const item = itemId ? this.State.GetItem(itemId) : undefined;\n if (item) {\n const b = this.State.ItemBounds(item);\n x = b.X + b.W + 14;\n y = b.Y + b.H / 2 - 13;\n }\n this.AgentPresence = { Active: true, X: x, Y: y, Label: `${this.AgentName} is drawing…` };\n if (this.presenceTimer) {\n clearTimeout(this.presenceTimer);\n }\n this.presenceTimer = setTimeout(() => {\n this.AgentPresence = null;\n this.cdr.markForCheck();\n }, PRESENCE_MS);\n }\n\n private pushToastPhrase(phrase: string): void {\n if (!this.ToastText) {\n this.toastPhrases = [];\n }\n if (!this.toastPhrases.includes(phrase)) {\n this.toastPhrases.push(phrase);\n }\n const joined = this.toastPhrases.length > 1\n ? `${this.toastPhrases.slice(0, -1).join(', ')} & ${this.toastPhrases[this.toastPhrases.length - 1]}`\n : this.toastPhrases[0];\n this.ToastText = `${this.AgentName} ${joined} · just now`;\n if (this.toastTimer) {\n clearTimeout(this.toastTimer);\n }\n this.toastTimer = setTimeout(() => this.hideToast(), TOAST_MS);\n }\n\n private hideToast(): void {\n this.ToastText = null;\n this.toastPhrases = [];\n if (this.toastTimer) {\n clearTimeout(this.toastTimer);\n this.toastTimer = null;\n }\n this.cdr.markForCheck();\n }\n\n private static toolPhrase(toolName: string): string {\n switch (toolName) {\n case WHITEBOARD_TOOL_NAMES.AddNote: return 'added a note';\n case WHITEBOARD_TOOL_NAMES.AddShape: return 'added a shape';\n case WHITEBOARD_TOOL_NAMES.AddText: return 'added a label';\n case WHITEBOARD_TOOL_NAMES.AddMarkdown: return 'added a markdown panel';\n case WHITEBOARD_TOOL_NAMES.AddHtml: return 'added an HTML widget';\n case WHITEBOARD_TOOL_NAMES.UpdateContent: return 'edited an item';\n case WHITEBOARD_TOOL_NAMES.DrawConnector: return 'added a connector';\n case WHITEBOARD_TOOL_NAMES.Highlight: return 'highlighted a region';\n case WHITEBOARD_TOOL_NAMES.MoveItem: return 'moved an item';\n case WHITEBOARD_TOOL_NAMES.RemoveItem: return 'removed an item';\n case WHITEBOARD_TOOL_NAMES.StyleItem: return 'restyled an item';\n case WHITEBOARD_TOOL_NAMES.AddPage: return 'created a page';\n case WHITEBOARD_TOOL_NAMES.SwitchPage: return 'switched pages';\n case WHITEBOARD_TOOL_NAMES.RenamePage: return 'renamed a page';\n default: return 'updated the board';\n }\n }\n\n private static toolForKey(key: string): WhiteboardTool | null {\n switch (key.toLowerCase()) {\n case 'v': return 'select';\n case 'h': return 'pan';\n case 'p': return 'pen';\n case 'r': return 'shape';\n case 's': return 'sticky';\n case 't': return 'text';\n case 'm': return 'markdown';\n case 'w': return 'html';\n case 'i': return 'image';\n case 'c': return 'connector';\n case 'e': return 'eraser';\n default: return null;\n }\n }\n}\n","<!-- board header -->\n<div class=\"board-head\">\n <span class=\"bt\"><i class=\"fa-solid fa-chalkboard\"></i> {{ BoardTitle }}</span>\n <span class=\"board-save\"><i class=\"fa-solid fa-circle-check\"></i> {{ SavedLabel }}</span>\n <span class=\"board-legend\">\n <span><span class=\"sw sw--you\"></span>You</span>\n <span><span class=\"sw sw--sage\"></span>{{ AgentName }} <i class=\"fa-solid fa-feather legend-feather\"></i></span>\n </span>\n <div class=\"head-end\">\n <button type=\"button\" class=\"head-btn head-btn--sees\" [class.on]=\"SeesOpen\" (click)=\"ToggleSees($event)\">\n <span class=\"eye-pulse\"></span><i class=\"fa-regular fa-eye\"></i> What {{ AgentName }} sees\n @if (SeesOpen) {\n <mj-realtime-whiteboard-agent-sees-popover\n [AgentName]=\"AgentName\"\n [DeltaJson]=\"LastDeltaJson\"\n [DebounceMs]=\"SceneDeltaDebounceMs\"\n [ElementCount]=\"ElementCount\"\n [LastDeltaLabel]=\"LastDeltaLabel\"/>\n }\n </button>\n <span class=\"export-wrap\">\n <button type=\"button\" class=\"head-btn\" [class.on]=\"ExportOpen\" (click)=\"ToggleExport($event)\">\n <i class=\"fa-solid fa-file-export\"></i> Export\n </button>\n @if (ExportOpen) {\n <div class=\"export-menu\">\n <button type=\"button\" class=\"export-item\" (click)=\"ExportDownloadHtml()\">\n <i class=\"fa-solid fa-file-code\"></i> Download HTML\n </button>\n @if (HasMultiplePages) {\n <button type=\"button\" class=\"export-item\" (click)=\"ExportDownloadHtmlAllPages()\">\n <i class=\"fa-solid fa-file-code\"></i> Download HTML — all pages\n </button>\n }\n <button type=\"button\" class=\"export-item\" (click)=\"ExportDownloadSvg()\">\n <i class=\"fa-solid fa-bezier-curve\"></i> Download SVG\n </button>\n @if (HasMultiplePages) {\n <button type=\"button\" class=\"export-item\" title=\"One SVG file per page\"\n (click)=\"ExportDownloadSvgAllPages()\">\n <i class=\"fa-solid fa-bezier-curve\"></i> Download SVG — all pages\n </button>\n }\n <button type=\"button\" class=\"export-item\" (click)=\"ExportPrint()\">\n <i class=\"fa-solid fa-print\"></i> Print\n </button>\n <button type=\"button\" class=\"export-item\" (click)=\"ExportSaveToArtifacts()\">\n <i class=\"fa-solid fa-box-archive\"></i> Save to artifacts\n </button>\n </div>\n }\n </span>\n <button type=\"button\" class=\"head-btn\" [class.on]=\"FocusMode\" (click)=\"ToggleFocus()\">\n <i [class]=\"FocusMode ? 'fa-solid fa-compress' : 'fa-solid fa-expand'\"></i>\n {{ FocusMode ? 'Show thread' : 'Focus board' }}\n </button>\n <button type=\"button\" class=\"head-btn head-btn--more\" title=\"More\"><i class=\"fa-solid fa-ellipsis\"></i></button>\n </div>\n</div>\n\n<!-- the board -->\n<div class=\"board-wrap\">\n <mj-realtime-whiteboard #board\n [State]=\"State\"\n [AgentName]=\"AgentName\"\n [Tool]=\"Tool\"\n [ToolRoster]=\"ToolRoster\"\n [ReadOnly]=\"ReadOnly\"\n [PenColor]=\"PenColor\"\n [PenWidth]=\"PenWidth\"\n [ShapeKind]=\"ShapeKind\"\n [TextSize]=\"TextSize\"\n [TextFamily]=\"TextFamily\"\n [TextBold]=\"TextBold\"\n [TextColor]=\"TextColor\"\n [AgentPresence]=\"AgentPresence\"\n (ToolChangeRequest)=\"Tool = $event\"\n (WidgetSubmitting)=\"WidgetSubmitting.emit($event)\"\n (WidgetSubmitted)=\"WidgetSubmitted.emit($event)\"\n (WidgetInteraction)=\"WidgetInteraction.emit($event)\"\n (ContentApplying)=\"ContentApplying.emit($event)\"\n (ContentApplied)=\"ContentApplied.emit($event)\"/>\n\n <!-- the toolbar is authoring chrome: a read-only board renders none, matching\n WhiteboardSnapshotComponent. Zoom stays — navigation is not mutation. -->\n @if (!ReadOnly) {\n <mj-realtime-whiteboard-toolbar\n [ActiveTool]=\"Tool\"\n [ToolRoster]=\"ToolRoster\"\n [PenColor]=\"PenColor\"\n [PenWidth]=\"PenWidth\"\n [ShapeKind]=\"ShapeKind\"\n [TextSize]=\"TextSize\"\n [TextFamily]=\"TextFamily\"\n [TextBold]=\"TextBold\"\n [TextColor]=\"TextColor\"\n [CanUndo]=\"State.CanUndo\"\n [CanRedo]=\"State.CanRedo\"\n [AgentName]=\"AgentName\"\n (ToolChange)=\"Tool = $event\"\n (PenColorChange)=\"PenColor = $event\"\n (PenWidthChange)=\"PenWidth = $event\"\n (ShapeKindChange)=\"ShapeKind = $event\"\n (TextSizeChange)=\"TextSize = $event\"\n (TextFamilyChange)=\"TextFamily = $event\"\n (TextBoldChange)=\"TextBold = $event\"\n (TextColorChange)=\"TextColor = $event\"\n (StyleSelection)=\"board.ApplyTextStyleToSelection($event)\"\n (Undo)=\"State.Undo()\"\n (Redo)=\"State.Redo()\"/>\n }\n\n <mj-realtime-whiteboard-zoom\n [ZoomPercent]=\"board.ZoomPercent\"\n [MinimapOpen]=\"board.MinimapOpen\"\n (ZoomOut)=\"board.ZoomOut()\"\n (ZoomIn)=\"board.ZoomIn()\"\n (ZoomBy)=\"board.ZoomByFactor($event)\"\n (Fit)=\"board.FitToContent()\"\n (ToggleMinimap)=\"board.ToggleMinimap()\"/>\n\n <!-- agent action toast -->\n @if (ToastText) {\n <div class=\"board-toast\">\n <i class=\"fa-solid fa-feather\"></i>\n <span class=\"board-toast__text\">{{ ToastText }}</span>\n @if (!ReadOnly) {\n <span class=\"undo\" (click)=\"OnToastUndo($event)\"><i class=\"fa-solid fa-rotate-left\"></i> Undo</span>\n }\n </div>\n }\n</div>\n\n<!-- board status footer: ONE row, never wraps — items ellipsize, and the long\n persistence prose collapses to an icon chip (full text on its tooltip) when\n the host is narrow (container query on the host width). -->\n<div class=\"board-status\">\n <span class=\"stat\"><b>{{ ElementCount }}</b> elements</span>\n <span class=\"stat\">you <b>{{ UserCount }}</b> · {{ AgentName }} <b>{{ AgentCount }}</b></span>\n <span class=\"stat\">synced <b>{{ LastDeltaLabel }}</b> · seq <b>{{ CurrentSeq }}</b></span>\n <span class=\"seg-r\">\n <span class=\"stat ctx-live\" [title]=\"AgentName + '’s live context: current'\">\n <span class=\"d\"></span><span class=\"ctx-live__text\"> {{ AgentName }}'s live context: current</span>\n </span>\n <span class=\"stat persist\" title=\"Persists as a session artifact when the call ends\">\n <i class=\"fa-solid fa-box-archive\" aria-hidden=\"true\"></i>\n <span class=\"persist__long\">persists as <b>session artifact</b> when the call ends</span>\n <span class=\"persist__short\">session artifact</span>\n </span>\n </span>\n</div>\n"]}
|
|
@@ -663,8 +663,8 @@ interface PageRecord {
|
|
|
663
663
|
* {@link Changed$} as `'replace'` ops.
|
|
664
664
|
*/
|
|
665
665
|
export declare class WhiteboardState {
|
|
666
|
-
private static readonly
|
|
667
|
-
private static readonly
|
|
666
|
+
private static readonly undoMax;
|
|
667
|
+
private static readonly journalMax;
|
|
668
668
|
/**
|
|
669
669
|
* The ordered page list. A fresh board has one page named "Page 1". Every item
|
|
670
670
|
* operation reads/writes the ACTIVE page's map through the `items` accessor below, so
|
|
@@ -205,8 +205,8 @@ export class WhiteboardState {
|
|
|
205
205
|
*/
|
|
206
206
|
this.selectedIds = [];
|
|
207
207
|
}
|
|
208
|
-
static { this.
|
|
209
|
-
static { this.
|
|
208
|
+
static { this.undoMax = 100; }
|
|
209
|
+
static { this.journalMax = 1000; }
|
|
210
210
|
/** The ACTIVE page's item map (accessor keeps all item mutations page-scoped). */
|
|
211
211
|
get items() {
|
|
212
212
|
return this.activePage.Items;
|
|
@@ -1177,7 +1177,7 @@ export class WhiteboardState {
|
|
|
1177
1177
|
/** Push the current scene onto the undo stack (bounded) and drop the redo branch. */
|
|
1178
1178
|
pushUndo() {
|
|
1179
1179
|
this.undoStack.push(this.snapshot());
|
|
1180
|
-
if (this.undoStack.length > WhiteboardState.
|
|
1180
|
+
if (this.undoStack.length > WhiteboardState.undoMax) {
|
|
1181
1181
|
this.undoStack.shift();
|
|
1182
1182
|
}
|
|
1183
1183
|
this.redoStack = [];
|
|
@@ -1238,8 +1238,8 @@ export class WhiteboardState {
|
|
|
1238
1238
|
record(op, itemId, author, summaryFragment) {
|
|
1239
1239
|
this.seq++;
|
|
1240
1240
|
this.journal.push({ Seq: this.seq, Op: op, ItemID: itemId });
|
|
1241
|
-
if (this.journal.length > WhiteboardState.
|
|
1242
|
-
const dropped = this.journal.splice(0, this.journal.length - WhiteboardState.
|
|
1241
|
+
if (this.journal.length > WhiteboardState.journalMax) {
|
|
1242
|
+
const dropped = this.journal.splice(0, this.journal.length - WhiteboardState.journalMax);
|
|
1243
1243
|
this.journalTrimmedBeforeSeq = dropped[dropped.length - 1].Seq;
|
|
1244
1244
|
}
|
|
1245
1245
|
this.changed.next({ Op: op, ItemID: itemId, Author: author, SummaryFragment: summaryFragment, Seq: this.seq });
|