@ai-matrx/canvas 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -0
- package/README.md +66 -1
- package/dist/index.cjs +203 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -3
- package/dist/index.d.ts +7 -3
- package/dist/index.js +203 -21
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +972 -286
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +100 -3
- package/dist/react.d.ts +100 -3
- package/dist/react.js +980 -291
- package/dist/react.js.map +1 -1
- package/dist/styles.css +238 -26
- package/dist/{toggleKind-A9v45oSb.d.cts → toggleKind-BD78LnMB.d.cts} +105 -1
- package/dist/{toggleKind-A9v45oSb.d.ts → toggleKind-BD78LnMB.d.ts} +105 -1
- package/dist/tokens.css +3 -0
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/types.ts","../src/core/ids.ts","../src/core/layout.ts","../src/core/reducer.ts","../src/core/store.ts","../src/core/remote.ts","../src/core/persistence.ts","../src/core/rules.ts","../src/core/commands.ts","../src/core/controller.ts","../src/core/selectors.ts","../src/core/toggleKind.ts"],"sourcesContent":["/**\n * @ai-matrx/canvas — core types.\n *\n * The canvas is ONE docked column on the right edge of an application. It holds\n * panes; panes hold tabs; every tab is one CanvasItem. A CanvasItem is\n * identified by `kind` + `key`, so opening the same thing twice always lands on\n * the existing tab instead of creating a duplicate.\n *\n * Everything in CanvasState is plain JSON: it lives in the host's Redux store\n * (or the package's own standalone store), it is persisted between sessions,\n * and it can be inspected. No functions, no class instances, no React nodes.\n */\n\n/** Any value that survives JSON.stringify → JSON.parse unchanged. */\nexport type CanvasJson =\n | string\n | number\n | boolean\n | null\n | readonly CanvasJson[]\n | { readonly [key: string]: CanvasJson | undefined };\n\ndeclare const itemIdBrand: unique symbol;\ndeclare const paneIdBrand: unique symbol;\ndeclare const splitIdBrand: unique symbol;\ndeclare const windowIdBrand: unique symbol;\n\n/** `${kind}::${key}` — the identity of one thing on the canvas. */\nexport type CanvasItemId = string & { readonly [itemIdBrand]: true };\nexport type CanvasPaneId = string & { readonly [paneIdBrand]: true };\nexport type CanvasSplitId = string & { readonly [splitIdBrand]: true };\n/**\n * One application window that renders a canvas. Single-window hosts only ever\n * see `CANVAS_MAIN_WINDOW`; a desktop host with one store in its main process\n * gives every other window (a second app window, a popped-out tab) its own id.\n */\nexport type CanvasWindowId = string & { readonly [windowIdBrand]: true };\n\nexport const CANVAS_MAIN_WINDOW = \"main\" as CanvasWindowId;\n\nexport interface CanvasItem {\n readonly id: CanvasItemId;\n /** Registered kind id (see `registerCanvasKind`). */\n readonly kind: string;\n /** Stable key inside the kind — an artifact id, a conversation id, \"default\". */\n readonly key: string;\n /** Explicit tab title. `null` ⇒ the kind's `title(data)` or its label. */\n readonly title: string | null;\n readonly data: CanvasJson;\n readonly openedAt: number;\n readonly updatedAt: number;\n}\n\nexport interface CanvasPane {\n readonly id: CanvasPaneId;\n readonly itemIds: readonly CanvasItemId[];\n readonly activeItemId: CanvasItemId | null;\n}\n\n/** \"horizontal\" = children side by side; \"vertical\" = children stacked. */\nexport type CanvasOrientation = \"horizontal\" | \"vertical\";\n\nexport type CanvasLayoutNode =\n | { readonly type: \"pane\"; readonly paneId: CanvasPaneId }\n | {\n readonly type: \"split\";\n readonly id: CanvasSplitId;\n readonly orientation: CanvasOrientation;\n readonly children: readonly CanvasLayoutNode[];\n /** Fractions, one per child, summing to 1. */\n readonly sizes: readonly number[];\n };\n\n/**\n * What one window shows: its column's visibility, full screen, width and its\n * own tree of panes. Panes and items are shared across windows (ids are\n * global), so moving a tab between windows is an ordinary move.\n */\nexport interface CanvasWindowFrame {\n readonly isOpen: boolean;\n /**\n * \"Expanded\": the column fills everything the HOST gives it (the web: the\n * whole window; the desktop: everything right of the sidebar). One flag —\n * the host's placement decides what \"everything\" is.\n */\n readonly isFullscreen: boolean;\n /** Column width in CSS pixels; null until the person drags it — the host's layout rule decides. */\n readonly width: number | null;\n readonly layout: CanvasLayoutNode;\n readonly focusedPaneId: CanvasPaneId;\n}\n\n/** A window other than the main one. */\nexport interface CanvasExtraWindow extends CanvasWindowFrame {\n readonly id: CanvasWindowId;\n /**\n * \"window\": another app window with its own column.\n * \"pop-out\": a window holding tabs popped out of `home`; \"Dock back\" returns them there.\n */\n readonly role: \"window\" | \"pop-out\";\n /** Where this window's tabs go when it closes or a tab docks back. */\n readonly home: CanvasWindowId;\n}\n\n/**\n * The whole canvas. The top-level frame fields ARE the main window's frame, so\n * a single-window host reads `state.isOpen`, `state.layout`… exactly as before;\n * every other window lives in `windows`.\n */\nexport interface CanvasState extends CanvasWindowFrame {\n readonly version: 1;\n /** Windows other than the main one. Empty for single-window hosts. Never restored after a reload. */\n readonly windows: { readonly [windowId: string]: CanvasExtraWindow };\n readonly panes: { readonly [paneId: string]: CanvasPane };\n readonly items: { readonly [itemId: string]: CanvasItem };\n /** Monotonic counter for minting pane/split ids — keeps the reducer pure. */\n readonly seq: number;\n /** True once a persisted snapshot was applied (or there was none). */\n readonly hydrated: boolean;\n}\n\n/** Where a newly opened item goes. Existing items never move on open. */\nexport type CanvasOpenTarget =\n | \"focused\"\n | \"split-right\"\n | \"split-down\"\n | { readonly paneId: CanvasPaneId };\n\nexport interface CanvasOpenInput {\n readonly kind: string;\n /** Which window a NEW item opens in. Default: the controller's window (main). An existing item stays where it is. */\n readonly windowId?: CanvasWindowId | undefined;\n readonly key: string;\n readonly title?: string | null | undefined;\n readonly data?: CanvasJson | undefined;\n readonly target?: CanvasOpenTarget | undefined;\n /** Reveal the canvas when it is put away. Default true. */\n readonly reveal?: boolean | undefined;\n /** Make the item the pane's active tab. Default true. */\n readonly activate?: boolean | undefined;\n}\n\nexport const CANVAS_MIN_WIDTH = 360;\nexport const CANVAS_DEFAULT_WIDTH = 640;\nexport const CANVAS_MIN_SPLIT_FRACTION = 0.12;\n\n/** A rectangle in window CSS pixels (getBoundingClientRect coordinates). */\nexport interface CanvasRect {\n readonly x: number;\n readonly y: number;\n readonly width: number;\n readonly height: number;\n}\n","import type { CanvasItemId, CanvasJson, CanvasPaneId, CanvasSplitId, CanvasWindowId } from \"./types\";\n\nconst SEP = \"::\";\n\nexport function canvasItemId(kind: string, key: string): CanvasItemId {\n return `${kind}${SEP}${key}` as CanvasItemId;\n}\n\nexport function parseCanvasItemId(id: CanvasItemId): { kind: string; key: string } {\n const at = id.indexOf(SEP);\n return at < 0 ? { kind: id, key: \"\" } : { kind: id.slice(0, at), key: id.slice(at + SEP.length) };\n}\n\nexport function paneIdFromSeq(seq: number): CanvasPaneId {\n return `pane-${seq}` as CanvasPaneId;\n}\n\nexport function splitIdFromSeq(seq: number): CanvasSplitId {\n return `split-${seq}` as CanvasSplitId;\n}\n\n/**\n * Returns the path of the first value that is NOT plain JSON, or null when the\n * whole value is JSON. Functions, class instances, Dates, Maps, NaN and\n * Infinity all fail — they would silently vanish or change on persist.\n */\nexport function findNonJson(value: unknown, path = \"data\"): string | null {\n if (value === null) return null;\n switch (typeof value) {\n case \"string\":\n case \"boolean\":\n return null;\n case \"number\":\n return Number.isFinite(value) ? null : path;\n case \"object\": {\n if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i++) {\n const bad = findNonJson(value[i], `${path}[${i}]`);\n if (bad) return bad;\n }\n return null;\n }\n const proto = Object.getPrototypeOf(value) as unknown;\n if (proto !== Object.prototype && proto !== null) return path;\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n if (v === undefined) continue;\n const bad = findNonJson(v, `${path}.${k}`);\n if (bad) return bad;\n }\n return null;\n }\n default:\n return path;\n }\n}\n\nexport function isCanvasJson(value: unknown): value is CanvasJson {\n return findNonJson(value) === null;\n}\n\n/** Brands a host's window id. `CANVAS_MAIN_WINDOW` is the default window. */\nexport function canvasWindowId(id: string): CanvasWindowId {\n return id as CanvasWindowId;\n}\n","/**\n * Pure helpers over the canvas layout tree. Every function returns a new tree\n * and never mutates its input.\n */\n\nimport {\n CANVAS_MIN_SPLIT_FRACTION,\n type CanvasLayoutNode,\n type CanvasOrientation,\n type CanvasPaneId,\n type CanvasSplitId,\n} from \"./types\";\n\nexport function listPaneIds(node: CanvasLayoutNode): CanvasPaneId[] {\n if (node.type === \"pane\") return [node.paneId];\n return node.children.flatMap(listPaneIds);\n}\n\nexport function containsPane(node: CanvasLayoutNode, paneId: CanvasPaneId): boolean {\n if (node.type === \"pane\") return node.paneId === paneId;\n return node.children.some((child) => containsPane(child, paneId));\n}\n\nfunction evenSizes(count: number): number[] {\n return Array.from({ length: count }, () => 1 / count);\n}\n\n/** Renormalizes to sum 1; falls back to even sizes for garbage input. */\nexport function normalizeSizes(sizes: readonly number[], count: number): number[] {\n if (sizes.length !== count || sizes.some((s) => !Number.isFinite(s) || s <= 0)) {\n return evenSizes(count);\n }\n const total = sizes.reduce((sum, s) => sum + s, 0);\n return sizes.map((s) => s / total);\n}\n\n/**\n * Places `newPaneId` beside `paneId`. When the pane's parent already splits in\n * the same orientation the new pane becomes a sibling (sharing the pane's\n * space); otherwise the pane is replaced by a new two-way split.\n */\nexport function splitPane(\n node: CanvasLayoutNode,\n paneId: CanvasPaneId,\n newPaneId: CanvasPaneId,\n orientation: CanvasOrientation,\n newSplitId: CanvasSplitId,\n /** The existing pane's share of the space it gives up (0.7 = the 70/30 divider). */\n firstShare = 0.5,\n): CanvasLayoutNode {\n const first = Number.isFinite(firstShare) ? Math.min(1 - CANVAS_MIN_SPLIT_FRACTION, Math.max(CANVAS_MIN_SPLIT_FRACTION, firstShare)) : 0.5;\n if (node.type === \"pane\") {\n if (node.paneId !== paneId) return node;\n return {\n type: \"split\",\n id: newSplitId,\n orientation,\n children: [node, { type: \"pane\", paneId: newPaneId }],\n sizes: [first, 1 - first],\n };\n }\n const index = node.children.findIndex(\n (child) => child.type === \"pane\" && child.paneId === paneId,\n );\n if (index >= 0 && node.orientation === orientation) {\n const share = node.sizes[index] ?? 1 / node.children.length;\n const children = [...node.children];\n children.splice(index + 1, 0, { type: \"pane\", paneId: newPaneId });\n const sizes = [...node.sizes];\n sizes.splice(index, 1, share * first, share * (1 - first));\n return { ...node, children, sizes: normalizeSizes(sizes, children.length) };\n }\n return {\n ...node,\n children: node.children.map((child) =>\n splitPane(child, paneId, newPaneId, orientation, newSplitId, first),\n ),\n };\n}\n\n/**\n * Removes a pane. A split left with one child collapses into that child, and\n * the removed pane's space goes to its siblings proportionally. Returns null\n * when the tree held only that pane.\n */\nexport function removePane(\n node: CanvasLayoutNode,\n paneId: CanvasPaneId,\n): CanvasLayoutNode | null {\n if (node.type === \"pane\") return node.paneId === paneId ? null : node;\n const children: CanvasLayoutNode[] = [];\n const sizes: number[] = [];\n node.children.forEach((child, i) => {\n const next = removePane(child, paneId);\n if (next) {\n children.push(next);\n sizes.push(node.sizes[i] ?? 1 / node.children.length);\n }\n });\n if (children.length === 0) return null;\n if (children.length === 1) return children[0] ?? null;\n return { ...node, children, sizes: normalizeSizes(sizes, children.length) };\n}\n\nexport function containsSplit(node: CanvasLayoutNode, splitId: CanvasSplitId): boolean {\n if (node.type === \"pane\") return false;\n return node.id === splitId || node.children.some((child) => containsSplit(child, splitId));\n}\n\nexport function resizeSplit(\n node: CanvasLayoutNode,\n splitId: CanvasSplitId,\n sizes: readonly number[],\n): CanvasLayoutNode {\n if (node.type === \"pane\") return node;\n if (node.id === splitId) {\n const clamped = sizes.map((s) => Math.max(CANVAS_MIN_SPLIT_FRACTION, s));\n return { ...node, sizes: normalizeSizes(clamped, node.children.length) };\n }\n return {\n ...node,\n children: node.children.map((child) => resizeSplit(child, splitId, sizes)),\n };\n}\n\n/** True when the tree is well formed against the set of known panes. */\nexport function isValidLayout(\n node: unknown,\n knownPanes: ReadonlySet<string>,\n seen: Set<string> = new Set(),\n): node is CanvasLayoutNode {\n if (!node || typeof node !== \"object\") return false;\n const n = node as Record<string, unknown>;\n if (n.type === \"pane\") {\n const id = n.paneId;\n if (typeof id !== \"string\" || !knownPanes.has(id) || seen.has(id)) return false;\n seen.add(id);\n return true;\n }\n if (n.type !== \"split\") return false;\n if (typeof n.id !== \"string\") return false;\n if (n.orientation !== \"horizontal\" && n.orientation !== \"vertical\") return false;\n if (!Array.isArray(n.children) || n.children.length < 2) return false;\n if (!Array.isArray(n.sizes) || n.sizes.length !== n.children.length) return false;\n return n.children.every((child) => isValidLayout(child, knownPanes, seen));\n}\n","/**\n * THE canvas reducer. Plain Redux-compatible reducer + action creators with no\n * Redux Toolkit dependency, so it mounts in a host's RTK store\n * (`canvasHost: canvasReducer`), runs inside the package's own standalone\n * store, or runs in a desktop main process behind IPC — identical behaviour.\n *\n * Identity law: an item is `kind::key`. Opening an item that is already on the\n * canvas never duplicates it — it refreshes its data/title, activates its tab\n * and focuses its pane, wherever that pane is (in whichever window).\n *\n * Windows: the top-level frame fields are the MAIN window's; every other window\n * (a second app window, a popped-out tab) lives in `state.windows`. Panes and\n * items are global, so a tab moves between windows like between panes.\n */\n\nimport { canvasItemId, paneIdFromSeq, splitIdFromSeq } from \"./ids\";\nimport { containsPane, containsSplit, isValidLayout, listPaneIds, normalizeSizes, removePane, resizeSplit, splitPane } from \"./layout\";\nimport {\n CANVAS_MAIN_WINDOW,\n CANVAS_MIN_WIDTH,\n type CanvasExtraWindow,\n type CanvasItem,\n type CanvasItemId,\n type CanvasJson,\n type CanvasLayoutNode,\n type CanvasOpenInput,\n type CanvasOrientation,\n type CanvasPane,\n type CanvasPaneId,\n type CanvasSplitId,\n type CanvasState,\n type CanvasWindowFrame,\n type CanvasWindowId,\n} from \"./types\";\n\nconst P = \"matrxCanvas/\";\n\n/** What happens to a closing window's tabs: back to its home window, or closed with it. */\nexport type CanvasWindowCloseMode = \"dock\" | \"close\";\n\nexport type CanvasAction =\n | { type: `${typeof P}open`; payload: CanvasOpenInput & { now: number; splitShare?: number | undefined } }\n | { type: `${typeof P}update`; payload: { itemId: CanvasItemId; data?: CanvasJson | undefined; title?: string | null | undefined; now: number } }\n | { type: `${typeof P}rekey`; payload: { itemId: CanvasItemId; key: string } }\n | { type: `${typeof P}closeItem`; payload: { itemId: CanvasItemId } }\n | { type: `${typeof P}closeOthers`; payload: { itemId: CanvasItemId } }\n | { type: `${typeof P}activate`; payload: { itemId: CanvasItemId } }\n | { type: `${typeof P}focusPane`; payload: { paneId: CanvasPaneId } }\n | { type: `${typeof P}moveItem`; payload: { itemId: CanvasItemId; toPaneId: CanvasPaneId; index?: number | undefined } }\n | { type: `${typeof P}splitPane`; payload: { paneId: CanvasPaneId; orientation: CanvasOrientation; moveItemId?: CanvasItemId | undefined; share?: number | undefined } }\n | { type: `${typeof P}closePane`; payload: { paneId: CanvasPaneId } }\n | { type: `${typeof P}resizeSplit`; payload: { splitId: CanvasSplitId; sizes: readonly number[] } }\n | { type: `${typeof P}setOpen`; payload: { open: boolean; windowId?: CanvasWindowId | undefined } }\n | { type: `${typeof P}toggle`; payload?: { windowId?: CanvasWindowId | undefined } | undefined }\n | { type: `${typeof P}setFullscreen`; payload: { fullscreen: boolean; windowId?: CanvasWindowId | undefined } }\n | { type: `${typeof P}setWidth`; payload: { width: number; windowId?: CanvasWindowId | undefined } }\n | { type: `${typeof P}popOut`; payload: { itemId: CanvasItemId; windowId: CanvasWindowId } }\n | { type: `${typeof P}dockBack`; payload: { itemId: CanvasItemId } }\n | { type: `${typeof P}closeWindow`; payload: { windowId: CanvasWindowId; mode: CanvasWindowCloseMode } }\n | { type: `${typeof P}hydrate`; payload: { snapshot: CanvasState | null } }\n | { type: `${typeof P}reset` };\n\nconst win = (windowId: CanvasWindowId | undefined) => (windowId && windowId !== CANVAS_MAIN_WINDOW ? { windowId } : {});\n\nexport const canvasActions = {\n open: (input: CanvasOpenInput, options?: { splitShare?: number | undefined }): CanvasAction => ({\n type: `${P}open`,\n payload: { ...input, now: Date.now(), ...(options?.splitShare !== undefined ? { splitShare: options.splitShare } : {}) },\n }),\n update: (itemId: CanvasItemId, patch: { data?: CanvasJson | undefined; title?: string | null | undefined }): CanvasAction => ({\n type: `${P}update`,\n payload: { itemId, ...patch, now: Date.now() },\n }),\n /** Gives an item a new identity in place (e.g. a draft that was just saved and now has an id). */\n rekey: (itemId: CanvasItemId, key: string): CanvasAction => ({ type: `${P}rekey`, payload: { itemId, key } }),\n closeItem: (itemId: CanvasItemId): CanvasAction => ({ type: `${P}closeItem`, payload: { itemId } }),\n closeOthers: (itemId: CanvasItemId): CanvasAction => ({ type: `${P}closeOthers`, payload: { itemId } }),\n activate: (itemId: CanvasItemId): CanvasAction => ({ type: `${P}activate`, payload: { itemId } }),\n focusPane: (paneId: CanvasPaneId): CanvasAction => ({ type: `${P}focusPane`, payload: { paneId } }),\n moveItem: (itemId: CanvasItemId, toPaneId: CanvasPaneId, index?: number): CanvasAction => ({\n type: `${P}moveItem`,\n payload: { itemId, toPaneId, index },\n }),\n /** `share` = the existing pane's fraction of the space (layout rules' stackSplit / sideSplit). */\n splitPane: (paneId: CanvasPaneId, orientation: CanvasOrientation, moveItemId?: CanvasItemId, share?: number): CanvasAction => ({\n type: `${P}splitPane`,\n payload: { paneId, orientation, moveItemId, ...(share !== undefined ? { share } : {}) },\n }),\n closePane: (paneId: CanvasPaneId): CanvasAction => ({ type: `${P}closePane`, payload: { paneId } }),\n resizeSplit: (splitId: CanvasSplitId, sizes: readonly number[]): CanvasAction => ({\n type: `${P}resizeSplit`,\n payload: { splitId, sizes },\n }),\n setOpen: (open: boolean, windowId?: CanvasWindowId): CanvasAction => ({ type: `${P}setOpen`, payload: { open, ...win(windowId) } }),\n toggle: (windowId?: CanvasWindowId): CanvasAction =>\n windowId && windowId !== CANVAS_MAIN_WINDOW ? { type: `${P}toggle`, payload: { windowId } } : { type: `${P}toggle` },\n setFullscreen: (fullscreen: boolean, windowId?: CanvasWindowId): CanvasAction => ({\n type: `${P}setFullscreen`,\n payload: { fullscreen, ...win(windowId) },\n }),\n setWidth: (width: number, windowId?: CanvasWindowId): CanvasAction => ({ type: `${P}setWidth`, payload: { width, ...win(windowId) } }),\n /** Moves a tab into its own pop-out window `windowId` (made by the host's popOut port). */\n popOut: (itemId: CanvasItemId, windowId: CanvasWindowId): CanvasAction => ({ type: `${P}popOut`, payload: { itemId, windowId } }),\n /** Returns a popped-out tab to the window it came from. */\n dockBack: (itemId: CanvasItemId): CanvasAction => ({ type: `${P}dockBack`, payload: { itemId } }),\n /** A host window closed: its tabs dock home (default) or close with it. The main window never closes. */\n closeWindow: (windowId: CanvasWindowId, mode: CanvasWindowCloseMode = \"dock\"): CanvasAction => ({\n type: `${P}closeWindow`,\n payload: { windowId, mode },\n }),\n hydrate: (snapshot: CanvasState | null): CanvasAction => ({ type: `${P}hydrate`, payload: { snapshot } }),\n reset: (): CanvasAction => ({ type: `${P}reset` }),\n} as const;\n\nexport function isCanvasAction(action: unknown): action is CanvasAction {\n return (\n !!action &&\n typeof action === \"object\" &&\n typeof (action as { type?: unknown }).type === \"string\" &&\n (action as { type: string }).type.startsWith(P)\n );\n}\n\nexport function createInitialCanvasState(): CanvasState {\n const paneId = paneIdFromSeq(1);\n return {\n version: 1,\n isOpen: false,\n isFullscreen: false,\n width: null,\n layout: { type: \"pane\", paneId },\n focusedPaneId: paneId,\n windows: {},\n panes: { [paneId]: { id: paneId, itemIds: [], activeItemId: null } },\n items: {},\n seq: 1,\n hydrated: false,\n };\n}\n\n// ── window helpers ─────────────────────────────────────────────────────────\n\n/** Every window id, main first. */\nexport function listCanvasWindowIds(state: CanvasState): CanvasWindowId[] {\n return [CANVAS_MAIN_WINDOW, ...(Object.keys(state.windows ?? {}) as CanvasWindowId[])];\n}\n\n/** A window's frame, or null when that window does not exist. */\nexport function canvasWindowFrame(state: CanvasState, windowId: CanvasWindowId = CANVAS_MAIN_WINDOW): CanvasWindowFrame | null {\n return windowId === CANVAS_MAIN_WINDOW ? state : (state.windows?.[windowId] ?? null);\n}\n\n/** The window whose layout holds this pane. */\nexport function canvasWindowOfPane(state: CanvasState, paneId: CanvasPaneId): CanvasWindowId | null {\n for (const id of listCanvasWindowIds(state)) {\n const frame = canvasWindowFrame(state, id);\n if (frame && containsPane(frame.layout, paneId)) return id;\n }\n return null;\n}\n\n/** The window an item is in right now (null when it is not on the canvas). */\nexport function canvasWindowOfItem(state: CanvasState, itemId: CanvasItemId): CanvasWindowId | null {\n const pane = paneOf(state, itemId);\n return pane ? canvasWindowOfPane(state, pane.id) : null;\n}\n\ntype FramePatch = { -readonly [K in keyof CanvasWindowFrame]?: CanvasWindowFrame[K] };\n\nfunction withFrame(state: CanvasState, windowId: CanvasWindowId, patch: FramePatch): CanvasState {\n if (windowId === CANVAS_MAIN_WINDOW) return { ...state, ...patch };\n const current = state.windows[windowId];\n if (!current) return state;\n return { ...state, windows: { ...state.windows, [windowId]: { ...current, ...patch } } };\n}\n\n/** A non-main window comes into being the first time something targets it. */\nfunction ensureWindow(state: CanvasState, windowId: CanvasWindowId, role: CanvasExtraWindow[\"role\"] = \"window\", home: CanvasWindowId = CANVAS_MAIN_WINDOW): CanvasState {\n if (windowId === CANVAS_MAIN_WINDOW || state.windows[windowId]) return state;\n const seq = state.seq + 1;\n const paneId = paneIdFromSeq(seq);\n const frame: CanvasExtraWindow = {\n id: windowId,\n role,\n home,\n isOpen: false,\n isFullscreen: false,\n width: null,\n layout: { type: \"pane\", paneId },\n focusedPaneId: paneId,\n };\n return {\n ...state,\n seq,\n panes: { ...state.panes, [paneId]: { id: paneId, itemIds: [], activeItemId: null } },\n windows: { ...state.windows, [windowId]: frame },\n };\n}\n\nfunction removeWindow(state: CanvasState, windowId: CanvasWindowId): CanvasState {\n const frame = state.windows[windowId];\n if (!frame) return state;\n const panes = { ...state.panes };\n for (const paneId of listPaneIds(frame.layout)) delete panes[paneId];\n const windows = { ...state.windows };\n delete windows[windowId];\n return { ...state, panes, windows };\n}\n\nfunction windowItemIds(state: CanvasState, windowId: CanvasWindowId): CanvasItemId[] {\n const frame = canvasWindowFrame(state, windowId);\n if (!frame) return [];\n return listPaneIds(frame.layout).flatMap((paneId) => state.panes[paneId]?.itemIds ?? []);\n}\n\n/** A pop-out window left with no tabs has nothing to show and goes away. */\nfunction dropEmptyPopOut(state: CanvasState, windowId: CanvasWindowId | null): CanvasState {\n if (!windowId || windowId === CANVAS_MAIN_WINDOW) return state;\n const frame = state.windows[windowId];\n if (!frame || frame.role !== \"pop-out\" || windowItemIds(state, windowId).length > 0) return state;\n return removeWindow(state, windowId);\n}\n\n// ── pane helpers ───────────────────────────────────────────────────────────\n\nfunction paneOf(state: CanvasState, itemId: CanvasItemId): CanvasPane | null {\n for (const pane of Object.values(state.panes)) {\n if (pane.itemIds.includes(itemId)) return pane;\n }\n return null;\n}\n\nfunction withPane(state: CanvasState, pane: CanvasPane): CanvasState {\n return { ...state, panes: { ...state.panes, [pane.id]: pane } };\n}\n\nfunction focus(state: CanvasState, paneId: CanvasPaneId): CanvasState {\n const windowId = canvasWindowOfPane(state, paneId);\n return windowId ? withFrame(state, windowId, { focusedPaneId: paneId }) : state;\n}\n\n/** After removing `itemId` from a tab list, the neighbour that takes focus. */\nfunction nextActive(itemIds: readonly CanvasItemId[], removed: CanvasItemId, current: CanvasItemId | null): CanvasItemId | null {\n if (current !== removed) return current;\n const index = itemIds.indexOf(removed);\n const rest = itemIds.filter((id) => id !== removed);\n return rest[Math.min(index, rest.length - 1)] ?? null;\n}\n\nfunction detachItem(state: CanvasState, itemId: CanvasItemId): CanvasState {\n const pane = paneOf(state, itemId);\n if (!pane) return state;\n return withPane(state, {\n ...pane,\n itemIds: pane.itemIds.filter((id) => id !== itemId),\n activeItemId: nextActive(pane.itemIds, itemId, pane.activeItemId),\n });\n}\n\nfunction dropPane(state: CanvasState, paneId: CanvasPaneId): CanvasState {\n const windowId = canvasWindowOfPane(state, paneId);\n const frame = windowId ? canvasWindowFrame(state, windowId) : null;\n if (!windowId || !frame) return state;\n const layout = removePane(frame.layout, paneId);\n if (!layout) return state; // never remove a window's last pane\n const panes = { ...state.panes };\n delete panes[paneId];\n const focusedPaneId = frame.focusedPaneId === paneId ? (listPaneIds(layout)[0] ?? frame.focusedPaneId) : frame.focusedPaneId;\n return withFrame({ ...state, panes }, windowId, { layout, focusedPaneId });\n}\n\nfunction addSplit(\n state: CanvasState,\n paneId: CanvasPaneId,\n orientation: CanvasOrientation,\n share: number | undefined,\n): { state: CanvasState; newPaneId: CanvasPaneId } | null {\n const windowId = canvasWindowOfPane(state, paneId);\n const frame = windowId ? canvasWindowFrame(state, windowId) : null;\n if (!windowId || !frame) return null;\n const seq = state.seq + 1;\n const newPaneId = paneIdFromSeq(seq);\n const layout = splitPane(frame.layout, paneId, newPaneId, orientation, splitIdFromSeq(seq), share ?? 0.5);\n const next = withFrame(\n { ...state, seq, panes: { ...state.panes, [newPaneId]: { id: newPaneId, itemIds: [], activeItemId: null } } },\n windowId,\n { layout, focusedPaneId: newPaneId },\n );\n return { newPaneId, state: next };\n}\n\nfunction insertInto(state: CanvasState, paneId: CanvasPaneId, itemId: CanvasItemId, activate: boolean, index?: number): CanvasState {\n const pane = state.panes[paneId];\n if (!pane) return state;\n const itemIds = [...pane.itemIds.filter((id) => id !== itemId)];\n const at = index === undefined ? afterActive(itemIds, pane.activeItemId) : Math.max(0, Math.min(index, itemIds.length));\n itemIds.splice(at, 0, itemId);\n return withPane(state, {\n ...pane,\n itemIds,\n activeItemId: activate || pane.activeItemId === null ? itemId : pane.activeItemId,\n });\n}\n\n/** New tabs open right after the active tab, the way browsers do it. */\nfunction afterActive(itemIds: readonly CanvasItemId[], active: CanvasItemId | null): number {\n const index = active ? itemIds.indexOf(active) : -1;\n return index < 0 ? itemIds.length : index + 1;\n}\n\n/** Moves one item into another window's focused pane (docking, folding). */\nfunction sendHome(state: CanvasState, itemId: CanvasItemId, home: CanvasWindowId, activate: boolean): CanvasState {\n const homeFrame = canvasWindowFrame(state, home) ?? state;\n const target = canvasWindowFrame(state, home) ? home : CANVAS_MAIN_WINDOW;\n let next = detachItem(state, itemId);\n next = insertInto(next, homeFrame.focusedPaneId, itemId, activate);\n return activate ? withFrame(next, target, { focusedPaneId: homeFrame.focusedPaneId }) : next;\n}\n\nfunction clampWidth(width: number): number | null {\n return Number.isFinite(width) ? Math.max(CANVAS_MIN_WIDTH, Math.round(width)) : null;\n}\n\n// ── memory ─────────────────────────────────────────────────────────────────\n\n/**\n * Every window but the main one is a session thing: its tabs come home to the\n * main window's focused pane (nothing is lost) and the window goes away. Used\n * for what is saved and for what is restored.\n */\nexport function foldCanvasWindows(state: CanvasState): CanvasState {\n const extra = Object.keys(state.windows ?? {}) as CanvasWindowId[];\n if (extra.length === 0) return state.windows ? state : { ...state, windows: {} };\n let next = state;\n for (const windowId of extra) {\n for (const itemId of windowItemIds(next, windowId)) next = sendHome(next, itemId, CANVAS_MAIN_WINDOW, false);\n next = removeWindow(next, windowId);\n }\n return next;\n}\n\n/**\n * Validates a persisted snapshot. Anything malformed is dropped back to the\n * initial state rather than half-applied — a corrupt layout must never crash\n * the shell. Extra windows are folded home; full screen never comes back.\n */\nexport function sanitizeCanvasSnapshot(raw: unknown): CanvasState | null {\n if (!raw || typeof raw !== \"object\") return null;\n const s = raw as Partial<CanvasState> & { windows?: unknown };\n if (s.version !== 1 || !s.panes || typeof s.panes !== \"object\" || !s.items || typeof s.items !== \"object\" || !s.layout) return null;\n const paneIds = new Set(Object.keys(s.panes));\n const seen = new Set<string>();\n if (!isValidLayout(s.layout, paneIds, seen)) return null;\n\n // Extra windows: each must be a well-formed frame over panes nobody else uses.\n const windows: Record<string, CanvasExtraWindow> = {};\n if (s.windows && typeof s.windows === \"object\") {\n for (const [id, value] of Object.entries(s.windows as Record<string, unknown>)) {\n if (!value || typeof value !== \"object\" || id === CANVAS_MAIN_WINDOW) continue;\n const w = value as Partial<CanvasExtraWindow>;\n const claimed = new Set(seen);\n if (!isValidLayout(w.layout, paneIds, claimed)) continue;\n for (const pane of claimed) seen.add(pane);\n const layoutPanes = listPaneIds(w.layout);\n const focused = w.focusedPaneId && layoutPanes.includes(w.focusedPaneId) ? w.focusedPaneId : layoutPanes[0];\n if (!focused) continue;\n windows[id] = {\n id: id as CanvasWindowId,\n role: w.role === \"pop-out\" ? \"pop-out\" : \"window\",\n home: typeof w.home === \"string\" ? (w.home as CanvasWindowId) : CANVAS_MAIN_WINDOW,\n isOpen: w.isOpen === true,\n isFullscreen: false,\n width: typeof w.width === \"number\" ? clampWidth(w.width) : null,\n layout: normalizeLayout(w.layout),\n focusedPaneId: focused,\n };\n }\n }\n // Every pane must belong to exactly one window's layout.\n if (seen.size !== paneIds.size) return null;\n\n const items: Record<string, CanvasItem> = {};\n for (const [id, item] of Object.entries(s.items)) {\n if (item && typeof item.kind === \"string\" && typeof item.key === \"string\" && canvasItemId(item.kind, item.key) === id) {\n items[id] = item;\n }\n }\n const placed = new Set<string>();\n const panes: Record<string, CanvasPane> = {};\n for (const [id, pane] of Object.entries(s.panes)) {\n const itemIds = (Array.isArray(pane.itemIds) ? pane.itemIds : []).filter((itemId) => itemId in items && !placed.has(itemId));\n for (const itemId of itemIds) placed.add(itemId);\n const activeItemId = pane.activeItemId && itemIds.includes(pane.activeItemId) ? pane.activeItemId : (itemIds[0] ?? null);\n panes[id] = { id: id as CanvasPaneId, itemIds, activeItemId };\n }\n const mainPanes = listPaneIds(s.layout);\n const focused = s.focusedPaneId && mainPanes.includes(s.focusedPaneId) ? s.focusedPaneId : mainPanes[0];\n if (!focused) return null;\n const layout = normalizeLayout(s.layout);\n // seq must stay ahead of every id already minted, or the next split collides.\n const highest = Math.max(highestIdNumber(layout), ...Object.values(windows).map((w) => highestIdNumber(w.layout)));\n const seq = Math.max(typeof s.seq === \"number\" && Number.isFinite(s.seq) ? s.seq : 0, highest);\n let state: CanvasState = {\n version: 1,\n isOpen: s.isOpen === true,\n // Full screen is a moment, not a preference: a reload never starts there.\n isFullscreen: false,\n width: typeof s.width === \"number\" ? clampWidth(s.width) : null,\n layout,\n focusedPaneId: focused,\n windows,\n panes,\n items,\n seq,\n hydrated: true,\n };\n state = foldCanvasWindows(state);\n // An item that lost its pane is put back where it can be seen, never kept invisible.\n for (const id of Object.keys(items) as CanvasItemId[]) {\n if (!placed.has(id)) state = insertInto(state, state.focusedPaneId, id, false);\n }\n return state;\n}\n\nfunction normalizeLayout(node: CanvasLayoutNode): CanvasLayoutNode {\n if (node.type === \"pane\") return node;\n return { ...node, sizes: normalizeSizes(node.sizes, node.children.length), children: node.children.map(normalizeLayout) };\n}\n\nfunction highestIdNumber(node: CanvasLayoutNode): number {\n const own = Number((node.type === \"pane\" ? node.paneId : node.id).split(\"-\").pop());\n const mine = Number.isFinite(own) ? own : 0;\n return node.type === \"pane\" ? mine : Math.max(mine, ...node.children.map(highestIdNumber));\n}\n\n// ── reducer ────────────────────────────────────────────────────────────────\n\nexport function canvasReducer(state: CanvasState = createInitialCanvasState(), action: { type: string }): CanvasState {\n if (!isCanvasAction(action)) return state;\n // A state saved before windows existed carries no `windows` map.\n if (!state.windows) state = { ...state, windows: {} };\n switch (action.type) {\n case `${P}open`: {\n const { kind, key, title, data, target = \"focused\", reveal = true, activate = true, now, splitShare } = action.payload;\n const itemId = canvasItemId(kind, key);\n const existing = state.items[itemId];\n let next = state;\n let revealIn: CanvasWindowId = action.payload.windowId ?? CANVAS_MAIN_WINDOW;\n if (existing) {\n const item: CanvasItem = {\n ...existing,\n ...(data !== undefined ? { data } : {}),\n ...(title !== undefined ? { title } : {}),\n updatedAt: now,\n };\n next = { ...next, items: { ...next.items, [itemId]: item } };\n const pane = paneOf(next, itemId);\n if (pane) {\n revealIn = canvasWindowOfPane(next, pane.id) ?? CANVAS_MAIN_WINDOW;\n if (activate) next = focus(withPane(next, { ...pane, activeItemId: itemId }), pane.id);\n } else {\n next = ensureWindow(next, revealIn);\n const frame = canvasWindowFrame(next, revealIn) ?? next;\n next = insertInto(next, frame.focusedPaneId, itemId, true);\n }\n } else {\n const item: CanvasItem = { id: itemId, kind, key, title: title ?? null, data: data ?? null, openedAt: now, updatedAt: now };\n next = ensureWindow({ ...next, items: { ...next.items, [itemId]: item } }, revealIn);\n const frame = canvasWindowFrame(next, revealIn) ?? next;\n let paneId: CanvasPaneId = frame.focusedPaneId;\n if (typeof target === \"object\" && next.panes[target.paneId]) {\n paneId = target.paneId;\n revealIn = canvasWindowOfPane(next, paneId) ?? revealIn;\n } else if (target === \"split-right\" || target === \"split-down\") {\n const split = addSplit(next, frame.focusedPaneId, target === \"split-right\" ? \"horizontal\" : \"vertical\", splitShare);\n if (split) {\n next = split.state;\n paneId = split.newPaneId;\n }\n }\n next = insertInto(next, paneId, itemId, activate);\n if (activate) next = focus(next, paneId);\n }\n return reveal ? withFrame(next, revealIn, { isOpen: true }) : next;\n }\n case `${P}update`: {\n const { itemId, data, title, now } = action.payload;\n const item = state.items[itemId];\n if (!item) return state;\n return {\n ...state,\n items: {\n ...state.items,\n [itemId]: { ...item, ...(data !== undefined ? { data } : {}), ...(title !== undefined ? { title } : {}), updatedAt: now },\n },\n };\n }\n case `${P}rekey`: {\n const { itemId, key } = action.payload;\n const item = state.items[itemId];\n if (!item || item.key === key) return state;\n const nextId = canvasItemId(item.kind, key);\n // The new identity is already open elsewhere: keep that one, drop this.\n if (state.items[nextId]) return canvasReducer(canvasReducer(state, canvasActions.closeItem(itemId)), canvasActions.activate(nextId));\n const items = { ...state.items, [nextId]: { ...item, id: nextId, key } };\n delete items[itemId];\n const panes: Record<string, CanvasPane> = {};\n for (const pane of Object.values(state.panes)) {\n panes[pane.id] = pane.itemIds.includes(itemId)\n ? {\n ...pane,\n itemIds: pane.itemIds.map((id) => (id === itemId ? nextId : id)),\n activeItemId: pane.activeItemId === itemId ? nextId : pane.activeItemId,\n }\n : pane;\n }\n return { ...state, items, panes };\n }\n case `${P}closeItem`: {\n const { itemId } = action.payload;\n if (!state.items[itemId]) return state;\n const pane = paneOf(state, itemId);\n const windowId = pane ? canvasWindowOfPane(state, pane.id) : null;\n let next = detachItem(state, itemId);\n const items = { ...next.items };\n delete items[itemId];\n next = { ...next, items };\n // A pane emptied by closing its last tab goes away, unless it is its window's only one.\n if (pane && next.panes[pane.id]?.itemIds.length === 0) next = dropPane(next, pane.id);\n return dropEmptyPopOut(next, windowId);\n }\n case `${P}closeOthers`: {\n const { itemId } = action.payload;\n const pane = paneOf(state, itemId);\n if (!pane) return state;\n const items = { ...state.items };\n for (const id of pane.itemIds) if (id !== itemId) delete items[id];\n return { ...withPane(state, { ...pane, itemIds: [itemId], activeItemId: itemId }), items };\n }\n case `${P}activate`: {\n const pane = paneOf(state, action.payload.itemId);\n if (!pane) return state;\n return focus(withPane(state, { ...pane, activeItemId: action.payload.itemId }), pane.id);\n }\n case `${P}focusPane`: {\n const windowId = canvasWindowOfPane(state, action.payload.paneId);\n const frame = windowId ? canvasWindowFrame(state, windowId) : null;\n if (!windowId || !frame || frame.focusedPaneId === action.payload.paneId) return state;\n return withFrame(state, windowId, { focusedPaneId: action.payload.paneId });\n }\n case `${P}moveItem`: {\n const { itemId, toPaneId, index } = action.payload;\n const from = paneOf(state, itemId);\n if (!from || !state.panes[toPaneId]) return state;\n // Dropped back onto its own pane with no position: nothing moved.\n if (from.id === toPaneId && index === undefined) return canvasReducer(state, canvasActions.focusPane(toPaneId));\n const fromWindow = canvasWindowOfPane(state, from.id);\n let next = from.id === toPaneId ? state : detachItem(state, itemId);\n next = focus(insertInto(next, toPaneId, itemId, true, index), toPaneId);\n if (from.id !== toPaneId && next.panes[from.id]?.itemIds.length === 0) next = dropPane(next, from.id);\n return dropEmptyPopOut(next, fromWindow);\n }\n case `${P}splitPane`: {\n const { paneId, orientation, moveItemId, share } = action.payload;\n const pane = state.panes[paneId];\n if (!pane) return state;\n const split = addSplit(state, paneId, orientation, share);\n if (!split) return state;\n let next = split.state;\n // The new pane takes the requested tab when its old pane keeps something;\n // otherwise it starts empty and shows the launcher.\n if (moveItemId && pane.itemIds.includes(moveItemId) && pane.itemIds.length > 1) {\n next = detachItem(next, moveItemId);\n next = insertInto(next, split.newPaneId, moveItemId, true);\n }\n return next;\n }\n case `${P}closePane`: {\n const pane = state.panes[action.payload.paneId];\n const windowId = pane ? canvasWindowOfPane(state, pane.id) : null;\n const frame = windowId ? canvasWindowFrame(state, windowId) : null;\n if (!pane || !windowId || !frame) return state;\n const onlyPane = listPaneIds(frame.layout).length === 1;\n if (onlyPane) {\n // A pop-out's last pane closing closes the window; its tabs go home.\n if (windowId !== CANVAS_MAIN_WINDOW && state.windows[windowId]?.role === \"pop-out\") {\n return canvasReducer(state, canvasActions.closeWindow(windowId, \"dock\"));\n }\n // Closing the last pane puts the canvas away and KEEPS its tabs — the\n // toggle brings everything back exactly as it was.\n return withFrame(state, windowId, { isOpen: false, isFullscreen: false });\n }\n const items = { ...state.items };\n for (const id of pane.itemIds) delete items[id];\n return dropPane({ ...state, items }, pane.id);\n }\n case `${P}resizeSplit`: {\n const { splitId, sizes } = action.payload;\n for (const windowId of listCanvasWindowIds(state)) {\n const frame = canvasWindowFrame(state, windowId);\n if (frame && containsSplit(frame.layout, splitId)) {\n return withFrame(state, windowId, { layout: resizeSplit(frame.layout, splitId, sizes) });\n }\n }\n return state;\n }\n case `${P}setOpen`: {\n const { open, windowId = CANVAS_MAIN_WINDOW } = action.payload;\n const next = open ? ensureWindow(state, windowId) : state;\n const frame = canvasWindowFrame(next, windowId);\n if (!frame || frame.isOpen === open) return next;\n return withFrame(next, windowId, { isOpen: open, isFullscreen: open ? frame.isFullscreen : false });\n }\n case `${P}toggle`: {\n const windowId = action.payload?.windowId ?? CANVAS_MAIN_WINDOW;\n const next = ensureWindow(state, windowId);\n const frame = canvasWindowFrame(next, windowId);\n if (!frame) return state;\n return withFrame(next, windowId, { isOpen: !frame.isOpen, isFullscreen: frame.isOpen ? false : frame.isFullscreen });\n }\n case `${P}setFullscreen`: {\n const { fullscreen, windowId = CANVAS_MAIN_WINDOW } = action.payload;\n const next = fullscreen ? ensureWindow(state, windowId) : state;\n const frame = canvasWindowFrame(next, windowId);\n if (!frame) return state;\n return withFrame(next, windowId, { isFullscreen: fullscreen, isOpen: fullscreen ? true : frame.isOpen });\n }\n case `${P}setWidth`: {\n const { width, windowId = CANVAS_MAIN_WINDOW } = action.payload;\n const next = ensureWindow(state, windowId);\n return withFrame(next, windowId, { width: clampWidth(width) });\n }\n case `${P}popOut`: {\n const { itemId, windowId } = action.payload;\n const from = paneOf(state, itemId);\n if (!from || windowId === CANVAS_MAIN_WINDOW) return state;\n const fromWindow = canvasWindowOfPane(state, from.id) ?? CANVAS_MAIN_WINDOW;\n if (fromWindow === windowId) return state;\n let next = ensureWindow(state, windowId, \"pop-out\", fromWindow);\n const target = canvasWindowFrame(next, windowId);\n if (!target) return state;\n next = detachItem(next, itemId);\n next = insertInto(next, target.focusedPaneId, itemId, true);\n next = withFrame(next, windowId, { isOpen: true, focusedPaneId: target.focusedPaneId });\n if (next.panes[from.id]?.itemIds.length === 0) next = dropPane(next, from.id);\n next = dropEmptyPopOut(next, fromWindow);\n // The window it left has nothing left to show: put its column away.\n if (canvasWindowFrame(next, fromWindow) && windowItemIds(next, fromWindow).length === 0) {\n next = withFrame(next, fromWindow, { isOpen: false, isFullscreen: false });\n }\n return next;\n }\n case `${P}dockBack`: {\n const { itemId } = action.payload;\n const windowId = canvasWindowOfItem(state, itemId);\n if (!windowId || windowId === CANVAS_MAIN_WINDOW) return state;\n const frame = state.windows[windowId];\n if (!frame) return state;\n const home = canvasWindowFrame(state, frame.home) ? frame.home : CANVAS_MAIN_WINDOW;\n let next = sendHome(state, itemId, home, true);\n next = withFrame(next, home, { isOpen: true });\n const left = paneOf(state, itemId);\n if (left && next.panes[left.id]?.itemIds.length === 0) next = dropPane(next, left.id);\n return dropEmptyPopOut(next, windowId);\n }\n case `${P}closeWindow`: {\n const { windowId, mode } = action.payload;\n const frame = state.windows[windowId];\n if (!frame) return state;\n const itemIds = windowItemIds(state, windowId);\n let next = state;\n if (mode === \"close\") {\n const items = { ...next.items };\n for (const id of itemIds) delete items[id];\n next = { ...next, items };\n } else if (itemIds.length > 0) {\n const home = canvasWindowFrame(state, frame.home) ? frame.home : CANVAS_MAIN_WINDOW;\n const active = state.panes[frame.focusedPaneId]?.activeItemId ?? null;\n for (const id of itemIds) next = sendHome(next, id, home, id === active);\n next = withFrame(next, home, { isOpen: true });\n }\n return removeWindow(next, windowId);\n }\n case `${P}hydrate`: {\n const snapshot = action.payload.snapshot ? sanitizeCanvasSnapshot(action.payload.snapshot) : null;\n if (!snapshot) return { ...state, hydrated: true };\n // Anything opened before hydration finished wins over the snapshot.\n let next: CanvasState = snapshot;\n for (const item of Object.values(state.items)) {\n const pane = paneOf(state, item.id);\n next = { ...next, items: { ...next.items, [item.id]: item } };\n if (!paneOf(next, item.id)) next = insertInto(next, next.focusedPaneId, item.id, pane?.activeItemId === item.id);\n }\n return { ...next, isOpen: next.isOpen || state.isOpen, hydrated: true };\n }\n case `${P}reset`:\n return { ...createInitialCanvasState(), hydrated: true };\n default:\n return state;\n }\n}\n","/**\n * The store seam. The canvas never owns a second copy of its state: it reads\n * and writes through a CanvasStoreBinding.\n *\n * - A host WITH Redux mounts `canvasReducer` in its root reducer and binds it:\n * bindCanvasToReduxStore(store, (root) => root.canvasHost)\n * - A host WITHOUT Redux (a Vite tool, an Electron window) calls\n * createCanvasStore()\n * which runs the very same reducer in a tiny standalone store.\n */\n\nimport { canvasReducer, createInitialCanvasState, type CanvasAction } from \"./reducer\";\nimport type { CanvasState } from \"./types\";\n\nexport interface CanvasStoreBinding {\n getState(): CanvasState;\n dispatch(action: CanvasAction): void;\n subscribe(listener: () => void): () => void;\n /**\n * \"remote\": the state lives in another process (createRemoteCanvasStore) —\n * that process hydrates and saves it, so a controller over this binding\n * never does. Absent means \"local\".\n */\n readonly authority?: \"local\" | \"remote\";\n}\n\nexport function createCanvasStore(initial?: CanvasState): CanvasStoreBinding {\n let state = initial ?? createInitialCanvasState();\n const listeners = new Set<() => void>();\n return {\n getState: () => state,\n dispatch(action) {\n const next = canvasReducer(state, action);\n if (next === state) return;\n state = next;\n for (const listener of [...listeners]) listener();\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n };\n}\n\n/** The minimum of a Redux store the canvas needs. */\nexport interface ReduxStoreLike<TRoot> {\n getState(): TRoot;\n dispatch(action: CanvasAction): unknown;\n subscribe(listener: () => void): () => void;\n}\n\nexport function bindCanvasToReduxStore<TRoot>(\n store: ReduxStoreLike<TRoot>,\n select: (root: TRoot) => CanvasState,\n): CanvasStoreBinding {\n return {\n getState: () => select(store.getState()),\n dispatch: (action) => {\n store.dispatch(action);\n },\n subscribe: (listener) => store.subscribe(listener),\n };\n}\n","/**\n * A canvas store that lives in ANOTHER process — an Electron renderer bound to\n * the one store in the main process over IPC.\n *\n * - dispatch is async and fire-and-forget: the action goes to the owner, and\n * the state changes when the owner's next snapshot arrives (no optimistic\n * copy that could disagree with the owner);\n * - every update is a WHOLE snapshot with no shared object identity, so each\n * one is merged into the previous state structurally: anything unchanged\n * keeps its old reference, an identical snapshot changes nothing and wakes\n * nobody — selector results stay stable and useSyncExternalStore never loops;\n * - the binding is marked `authority: \"remote\"`: the owner hydrates and saves,\n * so a controller over it never does.\n *\n * The owner side (main process) is the ordinary `createCanvasStore()` +\n * `createCanvasController({ persistence })`; see the README.\n */\n\nimport { isCanvasAction, type CanvasAction } from \"./reducer\";\nimport type { CanvasStoreBinding } from \"./store\";\nimport type { CanvasState } from \"./types\";\n\nexport interface RemoteCanvasStoreOptions {\n /** The owner's state at connect time (e.g. from an `invoke(\"canvas:get\")`). */\n readonly initialSnapshot: CanvasState;\n /** Sends one action to the owner. A rejection is reported, never swallowed. */\n readonly dispatch: (action: CanvasAction) => Promise<void> | void;\n /** Delivers every new owner snapshot; returns the unsubscribe. */\n readonly subscribe: (onSnapshot: (snapshot: CanvasState) => void) => () => void;\n /** Where a failed dispatch is reported. Default: console.error. */\n readonly onError?: ((error: unknown, action: CanvasAction) => void) | undefined;\n}\n\nexport interface RemoteCanvasStore extends CanvasStoreBinding {\n /** Stops listening to the owner. */\n dispose(): void;\n}\n\nexport function createRemoteCanvasStore(options: RemoteCanvasStoreOptions): RemoteCanvasStore {\n let state: CanvasState = options.initialSnapshot;\n const listeners = new Set<() => void>();\n const report =\n options.onError ??\n ((error: unknown, action: CanvasAction) => console.error(`[@ai-matrx/canvas] remote dispatch of ${action.type} failed`, error));\n\n const stop = options.subscribe((snapshot) => {\n const next = shareStructure(state, snapshot);\n if (next === state) return;\n state = next;\n for (const listener of [...listeners]) listener();\n });\n\n return {\n authority: \"remote\",\n getState: () => state,\n dispatch(action) {\n if (!isCanvasAction(action)) return;\n try {\n void Promise.resolve(options.dispatch(action)).catch((error: unknown) => report(error, action));\n } catch (error) {\n report(error, action);\n }\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n dispose() {\n stop();\n listeners.clear();\n },\n };\n}\n\n/**\n * Returns `next`, but with every subtree that is deep-equal to the same subtree\n * of `prev` replaced by `prev`'s object. When nothing changed it returns `prev`\n * itself. Plain JSON only (what crosses a process boundary).\n */\nexport function shareStructure<T>(prev: T, next: T): T {\n if (Object.is(prev, next)) return prev;\n if (typeof prev !== \"object\" || typeof next !== \"object\" || prev === null || next === null) return next;\n if (Array.isArray(prev) !== Array.isArray(next)) return next;\n if (Array.isArray(prev) && Array.isArray(next)) {\n let same = prev.length === next.length;\n const out = next.map((value: unknown, i: number) => {\n const shared = i < prev.length ? shareStructure(prev[i] as unknown, value) : value;\n if (shared !== prev[i]) same = false;\n return shared;\n });\n return (same ? prev : out) as T;\n }\n const a = prev as Record<string, unknown>;\n const b = next as Record<string, unknown>;\n const keys = Object.keys(b);\n let same = keys.length === Object.keys(a).length;\n const out: Record<string, unknown> = {};\n for (const key of keys) {\n const shared = key in a ? shareStructure(a[key], b[key]) : b[key];\n if (shared !== a[key] || !(key in a)) same = false;\n out[key] = shared;\n }\n return (same ? prev : out) as T;\n}\n","/**\n * Remembering the canvas between sessions — a table stake, never optional.\n *\n * The default port writes to localStorage under a versioned key. Items whose\n * kind opts out (`restore: false`, e.g. a live session that cannot come back)\n * are dropped from the snapshot, and panes they leave empty are dropped too.\n */\n\nimport { removePane } from \"./layout\";\nimport { foldCanvasWindows } from \"./reducer\";\nimport type { CanvasItemId, CanvasState } from \"./types\";\n\nexport interface CanvasPersistencePort {\n load(): CanvasState | null | Promise<CanvasState | null>;\n save(snapshot: CanvasState): void | Promise<void>;\n}\n\nexport const CANVAS_STORAGE_KEY = \"ai-matrx.canvas.v1\";\n\nexport function createLocalStorageCanvasPersistence(\n key: string = CANVAS_STORAGE_KEY,\n storage: Pick<Storage, \"getItem\" | \"setItem\"> | null = typeof window === \"undefined\" ? null : safeLocalStorage(),\n): CanvasPersistencePort {\n return {\n load() {\n if (!storage) throw new Error(\"Canvas storage is unavailable; allow browser storage or provide a persistence port.\");\n const raw = storage.getItem(key);\n if (!raw) return null;\n return JSON.parse(raw) as CanvasState;\n },\n save(snapshot) {\n if (!storage) throw new Error(\"Canvas storage is unavailable; allow browser storage or provide a persistence port.\");\n storage.setItem(key, JSON.stringify(snapshot));\n },\n };\n}\n\n/**\n * Memory over any key-value store — an Electron main process's `state/kv`,\n * electron-store, IndexedDB behind a promise, a test map. Values are written\n * as plain JSON objects (not strings) so a structured store keeps them\n * inspectable; a string-only store can wrap this with JSON.stringify.\n */\nexport interface CanvasKeyValueStore {\n get(key: string): unknown;\n set(key: string, value: unknown): void | Promise<void>;\n}\n\nexport function createKeyValueCanvasPersistence(kv: CanvasKeyValueStore, key: string = CANVAS_STORAGE_KEY): CanvasPersistencePort {\n return {\n async load() {\n const raw = await kv.get(key);\n if (raw === undefined || raw === null) return null;\n return (typeof raw === \"string\" ? JSON.parse(raw) : raw) as CanvasState;\n },\n save: (snapshot) => kv.set(key, JSON.parse(JSON.stringify(snapshot)) as unknown),\n };\n}\n\nfunction safeLocalStorage(): Storage | null {\n try {\n const probe = \"__mxc_probe__\";\n window.localStorage.setItem(probe, \"1\");\n window.localStorage.removeItem(probe);\n return window.localStorage;\n } catch {\n return null; // load/save report through the controller's existing error sink.\n }\n}\n\n/**\n * Builds the snapshot that is actually written: only restorable items, and\n * every window but the main one folded home (other windows never come back).\n */\nexport function toPersistableSnapshot(\n state: CanvasState,\n isRestorable: (kind: string) => boolean,\n): CanvasState {\n state = foldCanvasWindows(state);\n const keep = new Set<CanvasItemId>(\n Object.values(state.items).filter((item) => isRestorable(item.kind)).map((item) => item.id),\n );\n if (keep.size === Object.keys(state.items).length) return state;\n const items = Object.fromEntries(Object.entries(state.items).filter(([id]) => keep.has(id as CanvasItemId)));\n let layout = state.layout;\n const panes: Record<string, CanvasState[\"panes\"][string]> = {};\n for (const pane of Object.values(state.panes)) {\n const itemIds = pane.itemIds.filter((id) => keep.has(id));\n if (itemIds.length === 0 && pane.itemIds.length > 0) {\n const pruned = removePane(layout, pane.id);\n if (pruned) {\n layout = pruned;\n continue;\n }\n }\n panes[pane.id] = {\n ...pane,\n itemIds,\n activeItemId: pane.activeItemId && keep.has(pane.activeItemId) ? pane.activeItemId : (itemIds[0] ?? null),\n };\n }\n const focusedPaneId = panes[state.focusedPaneId] ? state.focusedPaneId : (Object.values(panes)[0]?.id ?? state.focusedPaneId);\n return { ...state, items, panes, layout, focusedPaneId };\n}\n","/**\n * Layout rules — the host-tunable numbers behind the column's width and how its\n * panes share space. Pure functions, so a desktop main process can place native\n * views with exactly the numbers the renderer draws with.\n *\n * The canvas always shrinks FIRST: while the window narrows, the centre keeps\n * `centreMinWidth` and the canvas gives way down to `minWidth`; only then does\n * the centre squeeze. Side-by-side panes narrower than `paneMinWidth` stack\n * instead of squeezing.\n */\n\nimport { CANVAS_DEFAULT_WIDTH, CANVAS_MIN_WIDTH } from \"./types\";\n\nexport interface CanvasLayoutRules {\n /** Width before the person drags the edge: CSS px, or a fraction of the region the canvas shares. */\n readonly defaultWidth: number | { readonly fraction: number };\n /** The narrowest the canvas column gets on a desktop-sized window. */\n readonly minWidth: number;\n /** Room the content beside the canvas always keeps (the canvas shrinks first). */\n readonly centreMinWidth: number;\n /** The FIRST pane's share when a pane splits down (stacked). 0.7 = the 70/30 divider. */\n readonly stackSplit: number;\n /** The first pane's share when a pane splits right (side by side). */\n readonly sideSplit: number;\n /** Side-by-side panes that would be narrower than this render stacked. 0 = never. */\n readonly paneMinWidth: number;\n}\n\n/** The web app's numbers (the defaults). */\nexport const CANVAS_WEB_LAYOUT_RULES: CanvasLayoutRules = {\n defaultWidth: CANVAS_DEFAULT_WIDTH,\n minWidth: CANVAS_MIN_WIDTH,\n centreMinWidth: 420,\n stackSplit: 0.5,\n sideSplit: 0.5,\n paneMinWidth: 0,\n};\n\n/** The desktop app's numbers (Claude desktop's proportions). */\nexport const CANVAS_DESKTOP_LAYOUT_RULES: CanvasLayoutRules = {\n defaultWidth: { fraction: 0.36 },\n minWidth: CANVAS_MIN_WIDTH,\n centreMinWidth: 520,\n stackSplit: 0.7,\n sideSplit: 0.5,\n paneMinWidth: 360,\n};\n\nconst clampFraction = (value: number, fallback: number) =>\n Number.isFinite(value) ? Math.min(0.88, Math.max(0.12, value)) : fallback;\n\n/** Fills missing fields from the web defaults and repairs nonsense values. */\nexport function resolveCanvasLayoutRules(rules?: Partial<CanvasLayoutRules> | null): CanvasLayoutRules {\n const merged = { ...CANVAS_WEB_LAYOUT_RULES, ...(rules ?? {}) };\n const positive = (value: number, fallback: number) => (Number.isFinite(value) && value >= 0 ? value : fallback);\n return {\n defaultWidth:\n typeof merged.defaultWidth === \"number\"\n ? positive(merged.defaultWidth, CANVAS_DEFAULT_WIDTH)\n : { fraction: Math.min(1, Math.max(0.05, Number.isFinite(merged.defaultWidth.fraction) ? merged.defaultWidth.fraction : 0.36)) },\n minWidth: positive(merged.minWidth, CANVAS_MIN_WIDTH),\n centreMinWidth: positive(merged.centreMinWidth, CANVAS_WEB_LAYOUT_RULES.centreMinWidth),\n stackSplit: clampFraction(merged.stackSplit, 0.5),\n sideSplit: clampFraction(merged.sideSplit, 0.5),\n paneMinWidth: positive(merged.paneMinWidth, 0),\n };\n}\n\n/** The width before the person chose one. `region` is the space the canvas shares (0 = unknown). */\nexport function defaultCanvasWidth(rules: CanvasLayoutRules, region: number): number {\n if (typeof rules.defaultWidth === \"number\") return rules.defaultWidth;\n return region > 0 ? Math.round(region * rules.defaultWidth.fraction) : CANVAS_DEFAULT_WIDTH;\n}\n\n/**\n * The column's width right now: the stored width (or the rule's default),\n * fitted so the centre keeps `centreMinWidth` and the canvas never goes under\n * `minWidth`. A width remembered on a wide monitor never crushes a laptop.\n */\nexport function fitCanvasWidth(stored: number | null, region: number, rules: CanvasLayoutRules): number {\n const wanted = stored ?? defaultCanvasWidth(rules, region);\n if (region <= 0) return Math.max(rules.minWidth, wanted);\n return Math.max(rules.minWidth, Math.min(wanted, region - rules.centreMinWidth));\n}\n\n/** Clamp for a dragged width: the same bounds as fitting. */\nexport function clampDraggedCanvasWidth(next: number, region: number, rules: CanvasLayoutRules): number {\n const max = Math.max(rules.minWidth, region - rules.centreMinWidth);\n return Math.min(max, Math.max(rules.minWidth, Math.round(next)));\n}\n\n/** Whether a side-by-side split this wide (px) with this many children renders stacked. */\nexport function shouldStackSplit(width: number, children: number, rules: CanvasLayoutRules): boolean {\n return rules.paneMinWidth > 0 && width > 0 && width < rules.paneMinWidth * children;\n}\n","/**\n * The canvas's keyboard shortcuts, as DATA. A web host gets them bound in the\n * DOM by `CanvasProvider`; a desktop host binds the same table in its main\n * process (menu accelerators / `before-input-event`), because keys pressed\n * inside a native web view never reach the renderer's DOM. Every shortcut runs\n * through `runCanvasCommand`, so both paths do exactly the same thing.\n */\n\nimport type { CanvasController } from \"./controller\";\nimport { canvasWindowFrame } from \"./reducer\";\nimport type { CanvasWindowId } from \"./types\";\n\nexport type CanvasCommandId =\n | \"canvas.toggle\"\n | \"canvas.toggleFullscreen\"\n | \"canvas.exitFullscreen\"\n | \"canvas.closeTab\"\n | \"canvas.nextTab\"\n | \"canvas.previousTab\"\n | \"canvas.splitRight\"\n | \"canvas.splitDown\";\n\n/**\n * When a shortcut applies:\n * - \"presented\": a canvas column is on screen in this window;\n * - \"fullscreen\": the canvas is expanded (and Escape is not owned by a menu or dialog);\n * - \"canvas-focus\": keyboard focus is inside the canvas (a tab, a pane, a native body).\n */\nexport type CanvasShortcutWhen = \"presented\" | \"fullscreen\" | \"canvas-focus\";\n\nexport interface CanvasShortcut {\n readonly id: CanvasCommandId;\n /** Electron accelerator syntax: \"CmdOrCtrl+\\\\\", \"Escape\", \"Ctrl+Shift+Tab\". */\n readonly accelerator: string;\n readonly when: CanvasShortcutWhen;\n readonly label: string;\n /** False when browsers reserve the keys (⌘W, Ctrl+Tab): only a desktop host can bind it. */\n readonly web: boolean;\n}\n\nexport const CANVAS_SHORTCUTS: readonly CanvasShortcut[] = [\n { id: \"canvas.toggle\", accelerator: \"CmdOrCtrl+\\\\\", when: \"presented\", label: \"Show or hide canvas\", web: true },\n { id: \"canvas.exitFullscreen\", accelerator: \"Escape\", when: \"fullscreen\", label: \"Restore canvas\", web: true },\n { id: \"canvas.toggleFullscreen\", accelerator: \"CmdOrCtrl+Shift+Enter\", when: \"canvas-focus\", label: \"Expand canvas\", web: true },\n { id: \"canvas.splitRight\", accelerator: \"CmdOrCtrl+Alt+\\\\\", when: \"canvas-focus\", label: \"Split right\", web: true },\n { id: \"canvas.splitDown\", accelerator: \"CmdOrCtrl+Alt+Shift+\\\\\", when: \"canvas-focus\", label: \"Split down\", web: true },\n { id: \"canvas.closeTab\", accelerator: \"CmdOrCtrl+W\", when: \"canvas-focus\", label: \"Close tab\", web: false },\n { id: \"canvas.nextTab\", accelerator: \"Ctrl+Tab\", when: \"canvas-focus\", label: \"Next tab\", web: false },\n { id: \"canvas.previousTab\", accelerator: \"Ctrl+Shift+Tab\", when: \"canvas-focus\", label: \"Previous tab\", web: false },\n];\n\n/** The tooltip hint for a command, e.g. \"⌘\\\\\" on a Mac. */\nexport function canvasShortcutHint(id: CanvasCommandId, isMac: boolean): string | null {\n const shortcut = CANVAS_SHORTCUTS.find((entry) => entry.id === id);\n if (!shortcut) return null;\n return shortcut.accelerator\n .split(\"+\")\n .map((part) => {\n if (part === \"CmdOrCtrl\") return isMac ? \"⌘\" : \"Ctrl+\";\n if (part === \"Ctrl\") return isMac ? \"⌃\" : \"Ctrl+\";\n if (part === \"Alt\") return isMac ? \"⌥\" : \"Alt+\";\n if (part === \"Shift\") return isMac ? \"⇧\" : \"Shift+\";\n if (part === \"Escape\") return \"Esc\";\n return part;\n })\n .join(\"\");\n}\n\n/**\n * Runs one command against a window's canvas. Returns true when it did\n * something (so a binding knows whether to swallow the key).\n */\nexport function runCanvasCommand(controller: CanvasController, id: CanvasCommandId, windowId: CanvasWindowId = controller.windowId): boolean {\n const state = controller.getState();\n const frame = canvasWindowFrame(state, windowId);\n const pane = frame ? state.panes[frame.focusedPaneId] : undefined;\n switch (id) {\n case \"canvas.toggle\":\n controller.toggle(windowId);\n return true;\n case \"canvas.toggleFullscreen\":\n controller.setFullscreen(!(frame?.isFullscreen ?? false), windowId);\n return true;\n case \"canvas.exitFullscreen\":\n if (!frame?.isFullscreen) return false;\n controller.setFullscreen(false, windowId);\n return true;\n case \"canvas.closeTab\":\n if (!frame?.isOpen || !pane?.activeItemId) return false;\n controller.close(pane.activeItemId);\n return true;\n case \"canvas.nextTab\":\n case \"canvas.previousTab\": {\n if (!frame?.isOpen || !pane?.activeItemId || pane.itemIds.length < 2) return false;\n const at = pane.itemIds.indexOf(pane.activeItemId);\n const step = id === \"canvas.nextTab\" ? 1 : -1;\n const next = pane.itemIds[(at + step + pane.itemIds.length) % pane.itemIds.length];\n if (next) controller.activate(next);\n return true;\n }\n case \"canvas.splitRight\":\n case \"canvas.splitDown\":\n if (!frame?.isOpen || !pane) return false;\n controller.splitPane(pane.id, id === \"canvas.splitRight\" ? \"horizontal\" : \"vertical\", pane.itemIds.length > 1 ? (pane.activeItemId ?? undefined) : undefined);\n return true;\n default:\n return false;\n }\n}\n\n/** The subset of a KeyboardEvent an accelerator is matched against. */\nexport interface CanvasKeyInput {\n readonly key: string;\n readonly code?: string;\n readonly metaKey: boolean;\n readonly ctrlKey: boolean;\n readonly altKey: boolean;\n readonly shiftKey: boolean;\n}\n\nconst CODE_FOR: Record<string, string> = { \"\\\\\": \"Backslash\", Tab: \"Tab\", Escape: \"Escape\", Enter: \"Enter\" };\n\n/**\n * Whether a key event is this accelerator. \"CmdOrCtrl\" is ⌘ on a Mac and Ctrl\n * elsewhere; symbol keys match by physical key (⌥\\ types « on a Mac).\n */\nexport function matchesCanvasAccelerator(input: CanvasKeyInput, accelerator: string, isMac: boolean): boolean {\n const parts = accelerator.split(\"+\");\n // \"CmdOrCtrl+\\\\\" splits into [..., \"\\\\\"]; a trailing \"+\" key would split empty.\n const key = parts.pop() ?? \"\";\n const want = { meta: false, ctrl: false, alt: false, shift: false };\n for (const part of parts) {\n if (part === \"CmdOrCtrl\") want[isMac ? \"meta\" : \"ctrl\"] = true;\n else if (part === \"Cmd\" || part === \"Meta\") want.meta = true;\n else if (part === \"Ctrl\") want.ctrl = true;\n else if (part === \"Alt\") want.alt = true;\n else if (part === \"Shift\") want.shift = true;\n }\n if (input.metaKey !== want.meta || input.ctrlKey !== want.ctrl || input.altKey !== want.alt || input.shiftKey !== want.shift) return false;\n const code = CODE_FOR[key] ?? (/^[A-Z]$/i.test(key) ? `Key${key.toUpperCase()}` : undefined);\n if (code && input.code === code) return true;\n return input.key.toLowerCase() === key.toLowerCase();\n}\n","/**\n * The canvas controller: the ONE imperative API every caller uses. It wraps a\n * store binding, validates what callers hand it (so the reducer stays pure and\n * trusting), and owns hydration, autosave, pop-outs and session lifecycles.\n *\n * A controller acts for ONE window by default (`controller.windowId`, main\n * unless the host says otherwise); `forWindow(id)` gives the same canvas seen\n * from another window. Nothing fails silently: a refused open, a pop-out the\n * host cannot do, a throwing session hook — each is reported through the\n * error sink.\n */\n\nimport { canvasActions, canvasWindowOfItem, canvasWindowFrame, listCanvasWindowIds, sanitizeCanvasSnapshot, type CanvasAction, type CanvasWindowCloseMode } from \"./reducer\";\nimport { canvasItemId, canvasWindowId, findNonJson } from \"./ids\";\nimport { listPaneIds } from \"./layout\";\nimport { toPersistableSnapshot, type CanvasPersistencePort } from \"./persistence\";\nimport { resolveCanvasLayoutRules, type CanvasLayoutRules } from \"./rules\";\nimport type { CanvasStoreBinding } from \"./store\";\nimport {\n CANVAS_MAIN_WINDOW,\n type CanvasItem,\n type CanvasItemId,\n type CanvasJson,\n type CanvasOpenInput,\n type CanvasOrientation,\n type CanvasPaneId,\n type CanvasSplitId,\n type CanvasState,\n type CanvasWindowId,\n} from \"./types\";\n\nexport interface CanvasErrorReport {\n readonly code:\n | \"non-json-data\"\n | \"unknown-kind\"\n | \"persistence-load\"\n | \"persistence-save\"\n | \"pop-out-unavailable\"\n | \"pop-out-refused\"\n | \"pop-out-failed\"\n | \"session-hook\";\n readonly message: string;\n readonly detail?: unknown;\n}\n\nexport type CanvasErrorSink = (report: CanvasErrorReport) => void;\n\nexport const consoleCanvasErrorSink: CanvasErrorSink = (report) => {\n console.error(`[@ai-matrx/canvas] ${report.code}: ${report.message}`, report.detail ?? \"\");\n};\n\n/**\n * The host's window abilities. Without `popOut` a pop-out is refused aloud and\n * no \"Pop out\" entry is shown.\n */\nexport interface CanvasWindowPorts {\n /**\n * Opens a window (web: a floating panel; desktop: a BrowserWindow) that will\n * render the canvas for the returned window id, then the package moves the\n * item there. Resolve null to refuse.\n */\n readonly popOut?: ((item: CanvasItem) => Promise<{ readonly windowId: string } | null>) | undefined;\n /** Called after a tab docked back out of `fromWindowId` (close that window when the state no longer lists it). */\n readonly dockBack?: ((itemId: CanvasItemId, fromWindowId: CanvasWindowId) => void) | undefined;\n}\n\n/** Why a session-backed item attached or detached. */\nexport type CanvasSessionAttachReason = \"open\" | \"restore\" | \"arrive\";\nexport type CanvasSessionDetachReason = \"close\" | \"leave\" | \"unmount\";\n\nexport interface CanvasSessionEvent<R extends string> {\n readonly item: CanvasItem;\n readonly sessionKey: string;\n /** The window the item is in (attach) or was in (detach). */\n readonly windowId: CanvasWindowId;\n readonly reason: R;\n}\n\n/**\n * A kind with `restore: \"session\"`: its tab is a view onto a process the host\n * keeps (a terminal). Closing the tab DETACHES (the process lives on); a\n * restore or a move REATTACHES. The package only calls these; the host owns the\n * process side.\n */\nexport interface CanvasSessionHooks {\n readonly sessionKey: (item: CanvasItem) => string | null;\n readonly onAttach?: ((event: CanvasSessionEvent<CanvasSessionAttachReason>) => void) | undefined;\n readonly onDetach?: ((event: CanvasSessionEvent<CanvasSessionDetachReason>) => void) | undefined;\n}\n\nexport interface CanvasControllerOptions {\n readonly store: CanvasStoreBinding;\n readonly persistence?: CanvasPersistencePort | null | undefined;\n /** Kinds that may not come back after a reload. Default: every kind restores. */\n readonly isRestorable?: ((kind: string) => boolean) | undefined;\n /** When given, opens of an unregistered kind are refused and reported. */\n readonly isKnownKind?: ((kind: string) => boolean) | undefined;\n readonly onError?: CanvasErrorSink | undefined;\n readonly saveDelayMs?: number | undefined;\n /**\n * Whether a remembered \"open\" may be restored right now. A host returns\n * false where an open canvas would take the whole screen (a phone).\n */\n readonly mayRestoreOpen?: (() => boolean) | undefined;\n /** The window this controller acts for by default. Default: the main window. */\n readonly windowId?: string | undefined;\n /** Width and split numbers (see CANVAS_WEB_LAYOUT_RULES / CANVAS_DESKTOP_LAYOUT_RULES). */\n readonly layoutRules?: Partial<CanvasLayoutRules> | undefined;\n /** Read on every use, so a provider can hand in its latest ports. */\n readonly windowPorts?: (() => CanvasWindowPorts) | undefined;\n /** Session hooks for a kind, or undefined when the kind is not session-backed. */\n readonly sessions?: ((kind: string) => CanvasSessionHooks | undefined) | undefined;\n}\n\nexport interface CanvasController {\n readonly store: CanvasStoreBinding;\n /** The window this controller acts for by default. */\n readonly windowId: CanvasWindowId;\n readonly rules: CanvasLayoutRules;\n /** The same canvas, acting for another window. */\n forWindow(windowId: string): CanvasController;\n getState(): CanvasState;\n open(input: CanvasOpenInput): CanvasItemId | null;\n update(itemId: CanvasItemId, patch: { data?: CanvasJson | undefined; title?: string | null | undefined }): boolean;\n /** Gives an item a new identity in place (a draft that was saved and now has a durable id). */\n rekey(itemId: CanvasItemId, key: string): CanvasItemId | null;\n close(itemId: CanvasItemId): void;\n closeOthers(itemId: CanvasItemId): void;\n activate(itemId: CanvasItemId): void;\n focusPane(paneId: CanvasPaneId): void;\n moveItem(itemId: CanvasItemId, toPaneId: CanvasPaneId, index?: number): void;\n /** Splits with the layout rules' share (stackSplit for \"vertical\", sideSplit for \"horizontal\"). */\n splitPane(paneId: CanvasPaneId, orientation: CanvasOrientation, moveItemId?: CanvasItemId): void;\n closePane(paneId: CanvasPaneId): void;\n resizeSplit(splitId: CanvasSplitId, sizes: readonly number[]): void;\n show(windowId?: CanvasWindowId): void;\n hide(windowId?: CanvasWindowId): void;\n toggle(windowId?: CanvasWindowId): void;\n setFullscreen(fullscreen: boolean, windowId?: CanvasWindowId): void;\n setWidth(width: number, windowId?: CanvasWindowId): void;\n /** Moves a tab into its own window through the host's popOut port. Refused aloud without one. */\n popOut(itemId: CanvasItemId): Promise<CanvasWindowId | null>;\n /** Returns a popped-out tab to the window it came from. False when it is not popped out. */\n dockBack(itemId: CanvasItemId): boolean;\n /** A host window closed: its tabs dock home (default) or close with it. */\n closeWindow(windowId: CanvasWindowId, mode?: CanvasWindowCloseMode): void;\n /** Is this exact thing on the canvas right now (in any window)? */\n has(kind: string, key: string): boolean;\n /**\n * Is a canvas column on screen (in this window, or in `windowId`)? A store\n * can exist in a layout that shows no column (a kiosk, a meeting stage);\n * opening there must be refused aloud.\n */\n isPresented(windowId?: CanvasWindowId): boolean;\n /** Called by a column on mount; returns the unmount callback. */\n registerPresentation(windowId?: CanvasWindowId): () => void;\n subscribePresentation(listener: () => void): () => void;\n /** Loads the persisted snapshot, starts autosave and session tracking. Returns a disposer. */\n start(): () => void;\n}\n\ninterface Shared {\n readonly options: CanvasControllerOptions;\n readonly onError: CanvasErrorSink;\n readonly rules: CanvasLayoutRules;\n readonly presentations: Map<CanvasWindowId, number>;\n readonly presentationListeners: Set<() => void>;\n readonly views: Map<CanvasWindowId, CanvasController>;\n /** Windows whose controllers are started (session tracking scope for a remote store). */\n readonly started: Map<CanvasWindowId, number>;\n sessionStop: (() => void) | null;\n}\n\nexport function createCanvasController(options: CanvasControllerOptions): CanvasController {\n const shared: Shared = {\n options,\n onError: options.onError ?? consoleCanvasErrorSink,\n rules: resolveCanvasLayoutRules(options.layoutRules),\n presentations: new Map(),\n presentationListeners: new Set(),\n views: new Map(),\n started: new Map(),\n sessionStop: null,\n };\n return view(shared, canvasWindowId(options.windowId ?? CANVAS_MAIN_WINDOW));\n}\n\nfunction view(shared: Shared, windowId: CanvasWindowId): CanvasController {\n const cached = shared.views.get(windowId);\n if (cached) return cached;\n const { options, onError, rules } = shared;\n const { store, persistence = null } = options;\n const isRestorable = options.isRestorable ?? (() => true);\n const dispatch = (action: CanvasAction) => store.dispatch(action);\n const notifyPresentation = () => {\n for (const listener of [...shared.presentationListeners]) listener();\n };\n const shareFor = (orientation: CanvasOrientation) => (orientation === \"vertical\" ? rules.stackSplit : rules.sideSplit);\n\n const controller: CanvasController = {\n store,\n windowId,\n rules,\n forWindow: (id) => view(shared, canvasWindowId(id)),\n getState: () => store.getState(),\n open(input) {\n if (options.isKnownKind && !options.isKnownKind(input.kind)) {\n onError({ code: \"unknown-kind\", message: `No canvas kind \"${input.kind}\" is registered.`, detail: input });\n return null;\n }\n if (input.data !== undefined) {\n const bad = findNonJson(input.data);\n if (bad) {\n onError({\n code: \"non-json-data\",\n message: `Canvas data for \"${input.kind}\" must be plain JSON; ${bad} is not.`,\n detail: { kind: input.kind, key: input.key },\n });\n return null;\n }\n }\n const target = input.target ?? \"focused\";\n const splitShare = target === \"split-down\" ? rules.stackSplit : target === \"split-right\" ? rules.sideSplit : undefined;\n const resolved: CanvasOpenInput = input.windowId || windowId === CANVAS_MAIN_WINDOW ? input : { ...input, windowId };\n dispatch(canvasActions.open(resolved, splitShare === undefined ? undefined : { splitShare }));\n return canvasItemId(input.kind, input.key);\n },\n update(itemId, patch) {\n if (patch.data !== undefined) {\n const bad = findNonJson(patch.data);\n if (bad) {\n onError({ code: \"non-json-data\", message: `Canvas update for ${itemId} must be plain JSON; ${bad} is not.` });\n return false;\n }\n }\n if (!store.getState().items[itemId]) return false;\n dispatch(canvasActions.update(itemId, patch));\n return true;\n },\n rekey(itemId, key) {\n const item = store.getState().items[itemId];\n if (!item) return null;\n dispatch(canvasActions.rekey(itemId, key));\n return canvasItemId(item.kind, key);\n },\n close: (itemId) => dispatch(canvasActions.closeItem(itemId)),\n closeOthers: (itemId) => dispatch(canvasActions.closeOthers(itemId)),\n activate: (itemId) => dispatch(canvasActions.activate(itemId)),\n focusPane: (paneId) => dispatch(canvasActions.focusPane(paneId)),\n moveItem: (itemId, toPaneId, index) => dispatch(canvasActions.moveItem(itemId, toPaneId, index)),\n splitPane: (paneId, orientation, moveItemId) => dispatch(canvasActions.splitPane(paneId, orientation, moveItemId, shareFor(orientation))),\n closePane: (paneId) => dispatch(canvasActions.closePane(paneId)),\n resizeSplit: (splitId, sizes) => dispatch(canvasActions.resizeSplit(splitId, sizes)),\n show: (w = windowId) => dispatch(canvasActions.setOpen(true, w)),\n hide: (w = windowId) => dispatch(canvasActions.setOpen(false, w)),\n toggle: (w = windowId) => dispatch(canvasActions.toggle(w)),\n setFullscreen: (fullscreen, w = windowId) => dispatch(canvasActions.setFullscreen(fullscreen, w)),\n setWidth: (width, w = windowId) => dispatch(canvasActions.setWidth(width, w)),\n async popOut(itemId) {\n const item = store.getState().items[itemId];\n if (!item) return null;\n const port = options.windowPorts?.().popOut;\n if (!port) {\n onError({ code: \"pop-out-unavailable\", message: \"This app cannot pop canvas tabs out into their own window.\", detail: { itemId } });\n return null;\n }\n let result: { readonly windowId: string } | null;\n try {\n result = await port(item);\n } catch (error) {\n onError({ code: \"pop-out-failed\", message: \"The window for this tab could not be opened.\", detail: error });\n return null;\n }\n if (!result) {\n onError({ code: \"pop-out-refused\", message: \"The app declined to pop this tab out.\", detail: { itemId } });\n return null;\n }\n const target = canvasWindowId(result.windowId);\n dispatch(canvasActions.popOut(itemId, target));\n return target;\n },\n dockBack(itemId) {\n const state = store.getState();\n const from = canvasWindowOfItem(state, itemId);\n if (!from || from === CANVAS_MAIN_WINDOW || state.windows[from]?.role !== \"pop-out\") return false;\n dispatch(canvasActions.dockBack(itemId));\n options.windowPorts?.().dockBack?.(itemId, from);\n return true;\n },\n closeWindow: (w, mode = \"dock\") => dispatch(canvasActions.closeWindow(w, mode)),\n has: (kind, key) => canvasItemId(kind, key) in store.getState().items,\n isPresented: (w = windowId) => (shared.presentations.get(w) ?? 0) > 0,\n registerPresentation(w = windowId) {\n shared.presentations.set(w, (shared.presentations.get(w) ?? 0) + 1);\n notifyPresentation();\n let done = false;\n return () => {\n if (done) return;\n done = true;\n shared.presentations.set(w, Math.max(0, (shared.presentations.get(w) ?? 1) - 1));\n notifyPresentation();\n };\n },\n subscribePresentation(listener) {\n shared.presentationListeners.add(listener);\n return () => shared.presentationListeners.delete(listener);\n },\n start() {\n let disposed = false;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let lastSaved: CanvasState | null = null;\n // Another process owns a remote store: it hydrates and saves; this side only renders.\n const owns = store.authority !== \"remote\";\n const memory = owns ? persistence : null;\n\n const save = () => {\n timer = null;\n const state = store.getState();\n if (!memory || !state.hydrated || state === lastSaved) return;\n lastSaved = state;\n try {\n void Promise.resolve(memory.save(toPersistableSnapshot(state, isRestorable))).catch((error: unknown) =>\n onError({ code: \"persistence-save\", message: \"Saving the canvas layout failed.\", detail: error }),\n );\n } catch (error) {\n onError({ code: \"persistence-save\", message: \"Saving the canvas layout failed.\", detail: error });\n }\n };\n\n // A host store dispatches constantly (streaming, typing). Only a change\n // to the CANVAS state reschedules the save, or a busy app starves it.\n let seen = store.getState();\n const unsubscribe = store.subscribe(() => {\n if (!memory || disposed) return;\n const current = store.getState();\n if (current === seen) return;\n seen = current;\n if (timer) clearTimeout(timer);\n timer = setTimeout(save, options.saveDelayMs ?? 250);\n });\n\n if (!owns || store.getState().hydrated) {\n // Already hydrated (a second provider over the same store), or owned elsewhere.\n } else if (!memory) {\n dispatch(canvasActions.hydrate(null));\n } else {\n Promise.resolve()\n .then(() => memory.load())\n .then(\n (snapshot) => {\n if (disposed) return;\n const openedThisSession = store.getState().isOpen;\n const validSnapshot = snapshot === null ? null : sanitizeCanvasSnapshot(snapshot);\n if (snapshot !== null && validSnapshot === null) {\n onError({ code: \"persistence-load\", message: \"The saved canvas layout is invalid. Clear the saved layout or repair the persistence port.\" });\n }\n dispatch(canvasActions.hydrate(validSnapshot));\n if (!openedThisSession && options.mayRestoreOpen && !options.mayRestoreOpen() && store.getState().isOpen) {\n dispatch(canvasActions.setOpen(false));\n }\n },\n (error: unknown) => {\n onError({ code: \"persistence-load\", message: \"The saved canvas layout could not be read.\", detail: error });\n if (!disposed) dispatch(canvasActions.hydrate(null));\n },\n );\n }\n\n const stopSessions = startSessions(shared, windowId);\n\n return () => {\n disposed = true;\n unsubscribe();\n stopSessions();\n if (timer) {\n clearTimeout(timer);\n save();\n }\n };\n },\n };\n shared.views.set(windowId, controller);\n return controller;\n}\n\n/**\n * Session lifecycle tracking, once per controller family. A local store is\n * one process showing every window, so it tracks them all; a remote store is\n * one window's renderer, so it tracks only the windows started here — a tab\n * moving to another process's window LEAVES and ARRIVES there.\n */\nfunction startSessions(shared: Shared, windowId: CanvasWindowId): () => void {\n const { options, onError } = shared;\n const sessions = options.sessions;\n if (!sessions) return () => undefined;\n shared.started.set(windowId, (shared.started.get(windowId) ?? 0) + 1);\n let stopped = false;\n if (!shared.sessionStop) {\n const store = options.store;\n const local = store.authority !== \"remote\";\n let tracked: Map<CanvasItemId, { item: CanvasItem; key: string; windowId: CanvasWindowId }> | null = null;\n\n const call = (fn: () => void) => {\n try {\n fn();\n } catch (error) {\n onError({ code: \"session-hook\", message: \"A canvas session hook threw.\", detail: error });\n }\n };\n\n const read = (fn: () => string | null): string | null => {\n try {\n return fn();\n } catch (error) {\n onError({ code: \"session-hook\", message: \"A canvas kind's sessionKey threw.\", detail: error });\n return null;\n }\n };\n\n let prevItems = new Set<CanvasItemId>();\n const snapshot = (state: CanvasState) => {\n const out = new Map<CanvasItemId, { item: CanvasItem; key: string; windowId: CanvasWindowId }>();\n for (const w of listCanvasWindowIds(state)) {\n if (!local && !shared.started.has(w)) continue;\n const frame = canvasWindowFrame(state, w);\n if (!frame) continue;\n for (const paneId of listPaneIds(frame.layout)) {\n for (const itemId of state.panes[paneId]?.itemIds ?? []) {\n const item = state.items[itemId];\n const hooks = item ? sessions(item.kind) : undefined;\n if (!item || !hooks) continue;\n const key = read(() => hooks.sessionKey(item));\n if (key) out.set(itemId, { item, key, windowId: w });\n }\n }\n }\n return out;\n };\n\n const sync = () => {\n const state = options.store.getState();\n if (!state.hydrated) return;\n const next = snapshot(state);\n const first = tracked === null;\n const prev = tracked ?? new Map();\n for (const [id, entry] of prev) {\n const now = next.get(id);\n if (now && now.key === entry.key) continue;\n const hooks = sessions(entry.item.kind);\n const reason: CanvasSessionDetachReason = state.items[id] && !now ? \"leave\" : \"close\";\n call(() => hooks?.onDetach?.({ item: entry.item, sessionKey: entry.key, windowId: entry.windowId, reason }));\n }\n for (const [id, entry] of next) {\n const before = prev.get(id);\n if (before && before.key === entry.key) continue;\n const hooks = sessions(entry.item.kind);\n const reason: CanvasSessionAttachReason = first ? \"restore\" : prevItems.has(id) ? \"arrive\" : \"open\";\n call(() => hooks?.onAttach?.({ item: entry.item, sessionKey: entry.key, windowId: entry.windowId, reason }));\n }\n tracked = next;\n prevItems = new Set(Object.keys(state.items) as CanvasItemId[]);\n };\n let lastState: CanvasState | null = null;\n const unsubscribe = store.subscribe(() => {\n const state = store.getState();\n if (state === lastState) return;\n lastState = state;\n sync();\n });\n sync();\n shared.sessionStop = () => {\n unsubscribe();\n for (const entry of tracked?.values() ?? []) {\n const hooks = sessions(entry.item.kind);\n call(() => hooks?.onDetach?.({ item: entry.item, sessionKey: entry.key, windowId: entry.windowId, reason: \"unmount\" }));\n }\n tracked = null;\n };\n }\n return () => {\n if (stopped) return;\n stopped = true;\n const left = (shared.started.get(windowId) ?? 1) - 1;\n if (left > 0) shared.started.set(windowId, left);\n else shared.started.delete(windowId);\n if (shared.started.size === 0 && shared.sessionStop) {\n const stop = shared.sessionStop;\n shared.sessionStop = null;\n stop();\n }\n };\n}\n","/**\n * Selectors over CanvasState. Each returns a value that is referentially\n * stable for an unchanged state, so they are safe in useSyncExternalStore and\n * in a host's useSelector. Window-scoped selectors default to the main window;\n * an unknown window reads as closed and empty.\n */\n\nimport { listPaneIds } from \"./layout\";\nimport { canvasWindowFrame, canvasWindowOfItem } from \"./reducer\";\nimport {\n CANVAS_MAIN_WINDOW,\n type CanvasExtraWindow,\n type CanvasItem,\n type CanvasItemId,\n type CanvasLayoutNode,\n type CanvasPane,\n type CanvasPaneId,\n type CanvasState,\n type CanvasWindowId,\n} from \"./types\";\n\nconst frame = (s: CanvasState, w: CanvasWindowId | undefined) => canvasWindowFrame(s, w ?? CANVAS_MAIN_WINDOW);\n\nexport const selectCanvasIsOpen = (s: CanvasState, windowId?: CanvasWindowId): boolean => frame(s, windowId)?.isOpen ?? false;\nexport const selectCanvasIsFullscreen = (s: CanvasState, windowId?: CanvasWindowId): boolean => frame(s, windowId)?.isFullscreen ?? false;\n/** The width the person chose, or null while the host's layout rule decides. */\nexport const selectCanvasWidth = (s: CanvasState, windowId?: CanvasWindowId): number | null => frame(s, windowId)?.width ?? null;\nexport const selectCanvasLayout = (s: CanvasState, windowId?: CanvasWindowId): CanvasLayoutNode | null => frame(s, windowId)?.layout ?? null;\nexport const selectCanvasFocusedPaneId = (s: CanvasState, windowId?: CanvasWindowId): CanvasPaneId | null =>\n frame(s, windowId)?.focusedPaneId ?? null;\nexport const selectCanvasIsHydrated = (s: CanvasState): boolean => s.hydrated;\n/** Every item on the canvas, in every window. */\nexport const selectCanvasItemCount = (s: CanvasState): number => Object.keys(s.items).length;\n\nexport const selectCanvasPane = (s: CanvasState, paneId: CanvasPaneId): CanvasPane | undefined => s.panes[paneId];\nexport const selectCanvasItem = (s: CanvasState, itemId: CanvasItemId): CanvasItem | undefined => s.items[itemId];\n\nexport function selectCanvasPaneCount(s: CanvasState, windowId?: CanvasWindowId): number {\n const layout = frame(s, windowId)?.layout;\n return layout ? listPaneIds(layout).length : 0;\n}\n\n/** Items shown in one window. */\nexport function selectCanvasWindowItemCount(s: CanvasState, windowId?: CanvasWindowId): number {\n const layout = frame(s, windowId)?.layout;\n if (!layout) return 0;\n return listPaneIds(layout).reduce((sum, paneId) => sum + (s.panes[paneId]?.itemIds.length ?? 0), 0);\n}\n\n/** The item the person is looking at in a window's focused pane. */\nexport function selectCanvasActiveItem(s: CanvasState, windowId?: CanvasWindowId): CanvasItem | null {\n const f = frame(s, windowId);\n const pane = f ? s.panes[f.focusedPaneId] : undefined;\n return pane?.activeItemId ? (s.items[pane.activeItemId] ?? null) : null;\n}\n\nconst NO_WINDOWS: CanvasState[\"windows\"] = Object.freeze({});\n\n/** Windows other than main (second app windows and pop-outs), by id. Stable per state. */\nexport function selectCanvasWindows(s: CanvasState): CanvasState[\"windows\"] {\n return s.windows ?? NO_WINDOWS;\n}\n\n/** One extra window, or undefined (main is never in this map). */\nexport const selectCanvasExtraWindow = (s: CanvasState, windowId: CanvasWindowId): CanvasExtraWindow | undefined => s.windows?.[windowId];\n\n/** The window an item is in, or null when it is not on the canvas. */\nexport const selectCanvasWindowOfItem = canvasWindowOfItem;\n","/**\n * \"Toggle or focus this kind\" — what a toolbar icon does (the desktop's\n * Terminal/Review/Browser icons, the web's quick-tool launchers):\n *\n * absent → open it (and reveal the canvas)\n * background → bring it forward: activate its tab, focus its pane, reveal\n * visible → close it (default) or put the canvas away (`whenVisible: \"hide\"`)\n *\n * \"Visible\" means: on the canvas, the active tab of its pane, and its window's\n * canvas is open. The same item in a popped-out window counts in that window.\n */\n\nimport { canvasItemId } from \"./ids\";\nimport { canvasWindowFrame, canvasWindowOfItem } from \"./reducer\";\nimport type { CanvasController } from \"./controller\";\nimport type { CanvasJson, CanvasState } from \"./types\";\n\nexport type CanvasKindVisibility = \"absent\" | \"background\" | \"visible\";\n\nexport const CANVAS_DEFAULT_KEY = \"default\";\n\n/** Stable primitive result — safe in useSyncExternalStore and useSelector. */\nexport function selectCanvasKindVisibility(state: CanvasState, kind: string, key: string = CANVAS_DEFAULT_KEY): CanvasKindVisibility {\n const itemId = canvasItemId(kind, key);\n if (!state.items[itemId]) return \"absent\";\n const windowId = canvasWindowOfItem(state, itemId);\n if (!windowId) return \"background\";\n const isOpen = canvasWindowFrame(state, windowId)?.isOpen ?? false;\n const pane = Object.values(state.panes).find((p) => p.itemIds.includes(itemId));\n return isOpen && pane?.activeItemId === itemId ? \"visible\" : \"background\";\n}\n\nexport interface ToggleKindInput {\n readonly kind: string;\n /** Default \"default\" — one instance of the kind (a toolbar tool). */\n readonly key?: string | undefined;\n /** Data for a NEW item; an existing item keeps its data. */\n readonly data?: CanvasJson | undefined;\n readonly title?: string | null | undefined;\n /** What a click does when the item is already in front. Default \"close\". */\n readonly whenVisible?: \"close\" | \"hide\" | undefined;\n}\n\n/** Returns what the item is after the click. */\nexport function toggleKind(controller: CanvasController, input: ToggleKindInput): CanvasKindVisibility {\n const key = input.key ?? CANVAS_DEFAULT_KEY;\n const itemId = canvasItemId(input.kind, key);\n const before = selectCanvasKindVisibility(controller.getState(), input.kind, key);\n\n if (before === \"visible\") {\n if ((input.whenVisible ?? \"close\") === \"close\") {\n controller.close(itemId);\n } else {\n controller.hide(canvasWindowOfItem(controller.getState(), itemId) ?? undefined);\n }\n return selectCanvasKindVisibility(controller.getState(), input.kind, key);\n }\n\n if (before === \"background\") {\n // An existing item is never re-fed data: open() activates, focuses its pane and reveals.\n controller.open({ kind: input.kind, key });\n const windowId = canvasWindowOfItem(controller.getState(), itemId);\n if (windowId) controller.show(windowId);\n return selectCanvasKindVisibility(controller.getState(), input.kind, key);\n }\n\n const opened = controller.open({\n kind: input.kind,\n key,\n ...(input.data !== undefined ? { data: input.data } : {}),\n ...(input.title !== undefined ? { title: input.title } : {}),\n });\n return opened ? selectCanvasKindVisibility(controller.getState(), input.kind, key) : \"absent\";\n}\n"],"mappings":"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","names":["frame","focused","same","out","frame","frame"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/types.ts","../src/core/ids.ts","../src/core/layout.ts","../src/core/reducer.ts","../src/core/store.ts","../src/core/remote.ts","../src/core/persistence.ts","../src/core/rules.ts","../src/core/commands.ts","../src/core/controller.ts","../src/core/selectors.ts","../src/core/presentation.ts","../src/core/toggleKind.ts"],"sourcesContent":["/**\n * @ai-matrx/canvas — core types.\n *\n * The canvas is ONE docked column on the right edge of an application. It holds\n * panes; panes hold tabs; every tab is one CanvasItem. A CanvasItem is\n * identified by `kind` + `key`, so opening the same thing twice always lands on\n * the existing tab instead of creating a duplicate.\n *\n * Everything in CanvasState is plain JSON: it lives in the host's Redux store\n * (or the package's own standalone store), it is persisted between sessions,\n * and it can be inspected. No functions, no class instances, no React nodes.\n */\n\n/** Any value that survives JSON.stringify → JSON.parse unchanged. */\nexport type CanvasJson =\n | string\n | number\n | boolean\n | null\n | readonly CanvasJson[]\n | { readonly [key: string]: CanvasJson | undefined };\n\ndeclare const itemIdBrand: unique symbol;\ndeclare const paneIdBrand: unique symbol;\ndeclare const splitIdBrand: unique symbol;\ndeclare const windowIdBrand: unique symbol;\n\n/** `${kind}::${key}` — the identity of one thing on the canvas. */\nexport type CanvasItemId = string & { readonly [itemIdBrand]: true };\nexport type CanvasPaneId = string & { readonly [paneIdBrand]: true };\nexport type CanvasSplitId = string & { readonly [splitIdBrand]: true };\n/**\n * One application window that renders a canvas. Single-window hosts only ever\n * see `CANVAS_MAIN_WINDOW`; a desktop host with one store in its main process\n * gives every other window (a second app window, a popped-out tab) its own id.\n */\nexport type CanvasWindowId = string & { readonly [windowIdBrand]: true };\n\nexport const CANVAS_MAIN_WINDOW = \"main\" as CanvasWindowId;\n\n/**\n * Where a tab was before it navigated in place (`controller.navigate`). Plain\n * JSON, so history persists with the layout; Back reopens the last entry.\n */\nexport interface CanvasHistoryEntry {\n readonly kind: string;\n readonly key: string;\n readonly title: string | null;\n readonly data: CanvasJson;\n}\n\n/** The built-in \"New tab\" item: the launcher, shown as a tab. Never registered as a kind. */\nexport const CANVAS_LAUNCHER_KIND = \"canvas.launcher\";\n\n/** How many steps Back can go in one tab. Older entries fall off. */\nexport const CANVAS_HISTORY_LIMIT = 50;\n\nexport interface CanvasItem {\n readonly id: CanvasItemId;\n /** Registered kind id (see `registerCanvasKind`). */\n readonly kind: string;\n /** Stable key inside the kind — an artifact id, a conversation id, \"default\". */\n readonly key: string;\n /** Explicit tab title. `null` ⇒ the kind's `title(data)` or its label. */\n readonly title: string | null;\n readonly data: CanvasJson;\n readonly openedAt: number;\n readonly updatedAt: number;\n /** Earlier contents of this tab, oldest first (navigate in place). Absent = no Back. */\n readonly history?: readonly CanvasHistoryEntry[] | undefined;\n /**\n * The mounted body's identity. Minted when the item is created and kept by\n * `rekey`, so a draft that receives its durable id keeps its live body.\n * Absent on items saved before 0.5.0 (the item id stands in).\n */\n readonly instance?: string | undefined;\n}\n\nexport interface CanvasPane {\n readonly id: CanvasPaneId;\n readonly itemIds: readonly CanvasItemId[];\n readonly activeItemId: CanvasItemId | null;\n}\n\n/** \"horizontal\" = children side by side; \"vertical\" = children stacked. */\nexport type CanvasOrientation = \"horizontal\" | \"vertical\";\n\nexport type CanvasLayoutNode =\n | { readonly type: \"pane\"; readonly paneId: CanvasPaneId }\n | {\n readonly type: \"split\";\n readonly id: CanvasSplitId;\n readonly orientation: CanvasOrientation;\n readonly children: readonly CanvasLayoutNode[];\n /** Fractions, one per child, summing to 1. */\n readonly sizes: readonly number[];\n };\n\n/**\n * What one window shows: its column's visibility, full screen, width and its\n * own tree of panes. Panes and items are shared across windows (ids are\n * global), so moving a tab between windows is an ordinary move.\n */\nexport interface CanvasWindowFrame {\n readonly isOpen: boolean;\n /**\n * \"Expanded\": the column fills everything the HOST gives it (the web: the\n * whole window; the desktop: everything right of the sidebar). One flag —\n * the host's placement decides what \"everything\" is.\n */\n readonly isFullscreen: boolean;\n /** Column width in CSS pixels; null until the person drags it — the host's layout rule decides. */\n readonly width: number | null;\n readonly layout: CanvasLayoutNode;\n readonly focusedPaneId: CanvasPaneId;\n}\n\n/** A window other than the main one. */\nexport interface CanvasExtraWindow extends CanvasWindowFrame {\n readonly id: CanvasWindowId;\n /**\n * \"window\": another app window with its own column.\n * \"pop-out\": a window holding tabs popped out of `home`; \"Dock back\" returns them there.\n */\n readonly role: \"window\" | \"pop-out\";\n /** Where this window's tabs go when it closes or a tab docks back. */\n readonly home: CanvasWindowId;\n}\n\n/**\n * The whole canvas. The top-level frame fields ARE the main window's frame, so\n * a single-window host reads `state.isOpen`, `state.layout`… exactly as before;\n * every other window lives in `windows`.\n */\nexport interface CanvasState extends CanvasWindowFrame {\n readonly version: 1;\n /** Windows other than the main one. Empty for single-window hosts. Never restored after a reload. */\n readonly windows: { readonly [windowId: string]: CanvasExtraWindow };\n readonly panes: { readonly [paneId: string]: CanvasPane };\n readonly items: { readonly [itemId: string]: CanvasItem };\n /** Monotonic counter for minting pane/split ids — keeps the reducer pure. */\n readonly seq: number;\n /** True once a persisted snapshot was applied (or there was none). */\n readonly hydrated: boolean;\n}\n\n/** Where a newly opened item goes. Existing items never move on open. */\nexport type CanvasOpenTarget =\n | \"focused\"\n | \"split-right\"\n | \"split-down\"\n | { readonly paneId: CanvasPaneId };\n\n/** Where a NEW item of a kind prefers to open while the canvas already shows something. */\nexport type CanvasPreferredTarget = \"focused\" | \"split-right\" | \"split-down\";\n\n/** What a tab navigates to in place. */\nexport interface CanvasNavigateInput {\n readonly kind: string;\n readonly key: string;\n readonly title?: string | null | undefined;\n readonly data?: CanvasJson | undefined;\n}\n\nexport interface CanvasOpenInput {\n readonly kind: string;\n /** Which window a NEW item opens in. Default: the controller's window (main). An existing item stays where it is. */\n readonly windowId?: CanvasWindowId | undefined;\n readonly key: string;\n readonly title?: string | null | undefined;\n readonly data?: CanvasJson | undefined;\n readonly target?: CanvasOpenTarget | undefined;\n /** Reveal the canvas when it is put away. Default true. */\n readonly reveal?: boolean | undefined;\n /** Make the item the pane's active tab. Default true. */\n readonly activate?: boolean | undefined;\n}\n\nexport const CANVAS_MIN_WIDTH = 360;\nexport const CANVAS_DEFAULT_WIDTH = 640;\nexport const CANVAS_MIN_SPLIT_FRACTION = 0.12;\n\n/** A rectangle in window CSS pixels (getBoundingClientRect coordinates). */\nexport interface CanvasRect {\n readonly x: number;\n readonly y: number;\n readonly width: number;\n readonly height: number;\n}\n","import type { CanvasItemId, CanvasJson, CanvasPaneId, CanvasSplitId, CanvasWindowId } from \"./types\";\n\nconst SEP = \"::\";\n\nexport function canvasItemId(kind: string, key: string): CanvasItemId {\n return `${kind}${SEP}${key}` as CanvasItemId;\n}\n\nexport function parseCanvasItemId(id: CanvasItemId): { kind: string; key: string } {\n const at = id.indexOf(SEP);\n return at < 0 ? { kind: id, key: \"\" } : { kind: id.slice(0, at), key: id.slice(at + SEP.length) };\n}\n\nexport function paneIdFromSeq(seq: number): CanvasPaneId {\n return `pane-${seq}` as CanvasPaneId;\n}\n\nexport function splitIdFromSeq(seq: number): CanvasSplitId {\n return `split-${seq}` as CanvasSplitId;\n}\n\n/**\n * Returns the path of the first value that is NOT plain JSON, or null when the\n * whole value is JSON. Functions, class instances, Dates, Maps, NaN and\n * Infinity all fail — they would silently vanish or change on persist.\n */\nexport function findNonJson(value: unknown, path = \"data\"): string | null {\n if (value === null) return null;\n switch (typeof value) {\n case \"string\":\n case \"boolean\":\n return null;\n case \"number\":\n return Number.isFinite(value) ? null : path;\n case \"object\": {\n if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i++) {\n const bad = findNonJson(value[i], `${path}[${i}]`);\n if (bad) return bad;\n }\n return null;\n }\n const proto = Object.getPrototypeOf(value) as unknown;\n if (proto !== Object.prototype && proto !== null) return path;\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n if (v === undefined) continue;\n const bad = findNonJson(v, `${path}.${k}`);\n if (bad) return bad;\n }\n return null;\n }\n default:\n return path;\n }\n}\n\nexport function isCanvasJson(value: unknown): value is CanvasJson {\n return findNonJson(value) === null;\n}\n\n/** Brands a host's window id. `CANVAS_MAIN_WINDOW` is the default window. */\nexport function canvasWindowId(id: string): CanvasWindowId {\n return id as CanvasWindowId;\n}\n","/**\n * Pure helpers over the canvas layout tree. Every function returns a new tree\n * and never mutates its input.\n */\n\nimport {\n CANVAS_MIN_SPLIT_FRACTION,\n type CanvasLayoutNode,\n type CanvasOrientation,\n type CanvasPaneId,\n type CanvasSplitId,\n} from \"./types\";\n\nexport function listPaneIds(node: CanvasLayoutNode): CanvasPaneId[] {\n if (node.type === \"pane\") return [node.paneId];\n return node.children.flatMap(listPaneIds);\n}\n\nexport function containsPane(node: CanvasLayoutNode, paneId: CanvasPaneId): boolean {\n if (node.type === \"pane\") return node.paneId === paneId;\n return node.children.some((child) => containsPane(child, paneId));\n}\n\nfunction evenSizes(count: number): number[] {\n return Array.from({ length: count }, () => 1 / count);\n}\n\n/** Renormalizes to sum 1; falls back to even sizes for garbage input. */\nexport function normalizeSizes(sizes: readonly number[], count: number): number[] {\n if (sizes.length !== count || sizes.some((s) => !Number.isFinite(s) || s <= 0)) {\n return evenSizes(count);\n }\n const total = sizes.reduce((sum, s) => sum + s, 0);\n return sizes.map((s) => s / total);\n}\n\n/**\n * Places `newPaneId` beside `paneId`. When the pane's parent already splits in\n * the same orientation the new pane becomes a sibling (sharing the pane's\n * space); otherwise the pane is replaced by a new two-way split.\n */\nexport function splitPane(\n node: CanvasLayoutNode,\n paneId: CanvasPaneId,\n newPaneId: CanvasPaneId,\n orientation: CanvasOrientation,\n newSplitId: CanvasSplitId,\n /** The existing pane's share of the space it gives up (0.7 = the 70/30 divider). */\n firstShare = 0.5,\n): CanvasLayoutNode {\n const first = Number.isFinite(firstShare) ? Math.min(1 - CANVAS_MIN_SPLIT_FRACTION, Math.max(CANVAS_MIN_SPLIT_FRACTION, firstShare)) : 0.5;\n if (node.type === \"pane\") {\n if (node.paneId !== paneId) return node;\n return {\n type: \"split\",\n id: newSplitId,\n orientation,\n children: [node, { type: \"pane\", paneId: newPaneId }],\n sizes: [first, 1 - first],\n };\n }\n const index = node.children.findIndex(\n (child) => child.type === \"pane\" && child.paneId === paneId,\n );\n if (index >= 0 && node.orientation === orientation) {\n const share = node.sizes[index] ?? 1 / node.children.length;\n const children = [...node.children];\n children.splice(index + 1, 0, { type: \"pane\", paneId: newPaneId });\n const sizes = [...node.sizes];\n sizes.splice(index, 1, share * first, share * (1 - first));\n return { ...node, children, sizes: normalizeSizes(sizes, children.length) };\n }\n return {\n ...node,\n children: node.children.map((child) =>\n splitPane(child, paneId, newPaneId, orientation, newSplitId, first),\n ),\n };\n}\n\n/**\n * Removes a pane. A split left with one child collapses into that child, and\n * the removed pane's space goes to its siblings proportionally. Returns null\n * when the tree held only that pane.\n */\nexport function removePane(\n node: CanvasLayoutNode,\n paneId: CanvasPaneId,\n): CanvasLayoutNode | null {\n if (node.type === \"pane\") return node.paneId === paneId ? null : node;\n const children: CanvasLayoutNode[] = [];\n const sizes: number[] = [];\n node.children.forEach((child, i) => {\n const next = removePane(child, paneId);\n if (next) {\n children.push(next);\n sizes.push(node.sizes[i] ?? 1 / node.children.length);\n }\n });\n if (children.length === 0) return null;\n if (children.length === 1) return children[0] ?? null;\n return { ...node, children, sizes: normalizeSizes(sizes, children.length) };\n}\n\nexport function containsSplit(node: CanvasLayoutNode, splitId: CanvasSplitId): boolean {\n if (node.type === \"pane\") return false;\n return node.id === splitId || node.children.some((child) => containsSplit(child, splitId));\n}\n\nexport function resizeSplit(\n node: CanvasLayoutNode,\n splitId: CanvasSplitId,\n sizes: readonly number[],\n): CanvasLayoutNode {\n if (node.type === \"pane\") return node;\n if (node.id === splitId) {\n const clamped = sizes.map((s) => Math.max(CANVAS_MIN_SPLIT_FRACTION, s));\n return { ...node, sizes: normalizeSizes(clamped, node.children.length) };\n }\n return {\n ...node,\n children: node.children.map((child) => resizeSplit(child, splitId, sizes)),\n };\n}\n\n/** True when the tree is well formed against the set of known panes. */\nexport function isValidLayout(\n node: unknown,\n knownPanes: ReadonlySet<string>,\n seen: Set<string> = new Set(),\n): node is CanvasLayoutNode {\n if (!node || typeof node !== \"object\") return false;\n const n = node as Record<string, unknown>;\n if (n.type === \"pane\") {\n const id = n.paneId;\n if (typeof id !== \"string\" || !knownPanes.has(id) || seen.has(id)) return false;\n seen.add(id);\n return true;\n }\n if (n.type !== \"split\") return false;\n if (typeof n.id !== \"string\") return false;\n if (n.orientation !== \"horizontal\" && n.orientation !== \"vertical\") return false;\n if (!Array.isArray(n.children) || n.children.length < 2) return false;\n if (!Array.isArray(n.sizes) || n.sizes.length !== n.children.length) return false;\n return n.children.every((child) => isValidLayout(child, knownPanes, seen));\n}\n","/**\n * THE canvas reducer. Plain Redux-compatible reducer + action creators with no\n * Redux Toolkit dependency, so it mounts in a host's RTK store\n * (`canvasHost: canvasReducer`), runs inside the package's own standalone\n * store, or runs in a desktop main process behind IPC — identical behaviour.\n *\n * Identity law: an item is `kind::key`. Opening an item that is already on the\n * canvas never duplicates it — it refreshes its data/title, activates its tab\n * and focuses its pane, wherever that pane is (in whichever window).\n *\n * Windows: the top-level frame fields are the MAIN window's; every other window\n * (a second app window, a popped-out tab) lives in `state.windows`. Panes and\n * items are global, so a tab moves between windows like between panes.\n */\n\nimport { canvasItemId, paneIdFromSeq, splitIdFromSeq } from \"./ids\";\nimport { containsPane, containsSplit, isValidLayout, listPaneIds, normalizeSizes, removePane, resizeSplit, splitPane } from \"./layout\";\nimport {\n CANVAS_HISTORY_LIMIT,\n CANVAS_LAUNCHER_KIND,\n CANVAS_MAIN_WINDOW,\n CANVAS_MIN_WIDTH,\n type CanvasExtraWindow,\n type CanvasHistoryEntry,\n type CanvasItem,\n type CanvasItemId,\n type CanvasJson,\n type CanvasLayoutNode,\n type CanvasNavigateInput,\n type CanvasOpenInput,\n type CanvasOrientation,\n type CanvasPane,\n type CanvasPaneId,\n type CanvasSplitId,\n type CanvasState,\n type CanvasWindowFrame,\n type CanvasWindowId,\n} from \"./types\";\n\nconst P = \"matrxCanvas/\";\n\n/** What happens to a closing window's tabs: back to its home window, or closed with it. */\nexport type CanvasWindowCloseMode = \"dock\" | \"close\";\n\nexport type CanvasAction =\n | { type: `${typeof P}open`; payload: CanvasOpenInput & { now: number; splitShare?: number | undefined } }\n | { type: `${typeof P}update`; payload: { itemId: CanvasItemId; data?: CanvasJson | undefined; title?: string | null | undefined; now: number } }\n | { type: `${typeof P}rekey`; payload: { itemId: CanvasItemId; key: string } }\n | { type: `${typeof P}navigate`; payload: { itemId: CanvasItemId; to: CanvasNavigateInput; now: number } }\n | { type: `${typeof P}back`; payload: { itemId: CanvasItemId; now: number } }\n | { type: `${typeof P}closeItem`; payload: { itemId: CanvasItemId } }\n | { type: `${typeof P}closeOthers`; payload: { itemId: CanvasItemId } }\n | { type: `${typeof P}activate`; payload: { itemId: CanvasItemId } }\n | { type: `${typeof P}focusPane`; payload: { paneId: CanvasPaneId } }\n | { type: `${typeof P}moveItem`; payload: { itemId: CanvasItemId; toPaneId: CanvasPaneId; index?: number | undefined } }\n | { type: `${typeof P}splitPane`; payload: { paneId: CanvasPaneId; orientation: CanvasOrientation; moveItemId?: CanvasItemId | undefined; share?: number | undefined } }\n | { type: `${typeof P}closePane`; payload: { paneId: CanvasPaneId } }\n | { type: `${typeof P}resizeSplit`; payload: { splitId: CanvasSplitId; sizes: readonly number[] } }\n | { type: `${typeof P}setOpen`; payload: { open: boolean; windowId?: CanvasWindowId | undefined } }\n | { type: `${typeof P}toggle`; payload?: { windowId?: CanvasWindowId | undefined } | undefined }\n | { type: `${typeof P}setFullscreen`; payload: { fullscreen: boolean; windowId?: CanvasWindowId | undefined } }\n | { type: `${typeof P}setWidth`; payload: { width: number; windowId?: CanvasWindowId | undefined } }\n | { type: `${typeof P}popOut`; payload: { itemId: CanvasItemId; windowId: CanvasWindowId } }\n | { type: `${typeof P}dockBack`; payload: { itemId: CanvasItemId } }\n | { type: `${typeof P}closeWindow`; payload: { windowId: CanvasWindowId; mode: CanvasWindowCloseMode } }\n | { type: `${typeof P}hydrate`; payload: { snapshot: CanvasState | null } }\n | { type: `${typeof P}reset` };\n\nconst win = (windowId: CanvasWindowId | undefined) => (windowId && windowId !== CANVAS_MAIN_WINDOW ? { windowId } : {});\n\nexport const canvasActions = {\n open: (input: CanvasOpenInput, options?: { splitShare?: number | undefined }): CanvasAction => ({\n type: `${P}open`,\n payload: { ...input, now: Date.now(), ...(options?.splitShare !== undefined ? { splitShare: options.splitShare } : {}) },\n }),\n update: (itemId: CanvasItemId, patch: { data?: CanvasJson | undefined; title?: string | null | undefined }): CanvasAction => ({\n type: `${P}update`,\n payload: { itemId, ...patch, now: Date.now() },\n }),\n /** Gives an item a new identity in place (e.g. a draft that was just saved and now has an id). */\n rekey: (itemId: CanvasItemId, key: string): CanvasAction => ({ type: `${P}rekey`, payload: { itemId, key } }),\n /** Replaces a tab's content with another item in place, remembering what it showed (Back returns). */\n navigate: (itemId: CanvasItemId, to: CanvasNavigateInput): CanvasAction => ({ type: `${P}navigate`, payload: { itemId, to, now: Date.now() } }),\n /** Returns a tab to what it showed before its last navigate. */\n back: (itemId: CanvasItemId): CanvasAction => ({ type: `${P}back`, payload: { itemId, now: Date.now() } }),\n closeItem: (itemId: CanvasItemId): CanvasAction => ({ type: `${P}closeItem`, payload: { itemId } }),\n closeOthers: (itemId: CanvasItemId): CanvasAction => ({ type: `${P}closeOthers`, payload: { itemId } }),\n activate: (itemId: CanvasItemId): CanvasAction => ({ type: `${P}activate`, payload: { itemId } }),\n focusPane: (paneId: CanvasPaneId): CanvasAction => ({ type: `${P}focusPane`, payload: { paneId } }),\n moveItem: (itemId: CanvasItemId, toPaneId: CanvasPaneId, index?: number): CanvasAction => ({\n type: `${P}moveItem`,\n payload: { itemId, toPaneId, index },\n }),\n /** `share` = the existing pane's fraction of the space (layout rules' stackSplit / sideSplit). */\n splitPane: (paneId: CanvasPaneId, orientation: CanvasOrientation, moveItemId?: CanvasItemId, share?: number): CanvasAction => ({\n type: `${P}splitPane`,\n payload: { paneId, orientation, moveItemId, ...(share !== undefined ? { share } : {}) },\n }),\n closePane: (paneId: CanvasPaneId): CanvasAction => ({ type: `${P}closePane`, payload: { paneId } }),\n resizeSplit: (splitId: CanvasSplitId, sizes: readonly number[]): CanvasAction => ({\n type: `${P}resizeSplit`,\n payload: { splitId, sizes },\n }),\n setOpen: (open: boolean, windowId?: CanvasWindowId): CanvasAction => ({ type: `${P}setOpen`, payload: { open, ...win(windowId) } }),\n toggle: (windowId?: CanvasWindowId): CanvasAction =>\n windowId && windowId !== CANVAS_MAIN_WINDOW ? { type: `${P}toggle`, payload: { windowId } } : { type: `${P}toggle` },\n setFullscreen: (fullscreen: boolean, windowId?: CanvasWindowId): CanvasAction => ({\n type: `${P}setFullscreen`,\n payload: { fullscreen, ...win(windowId) },\n }),\n setWidth: (width: number, windowId?: CanvasWindowId): CanvasAction => ({ type: `${P}setWidth`, payload: { width, ...win(windowId) } }),\n /** Moves a tab into its own pop-out window `windowId` (made by the host's popOut port). */\n popOut: (itemId: CanvasItemId, windowId: CanvasWindowId): CanvasAction => ({ type: `${P}popOut`, payload: { itemId, windowId } }),\n /** Returns a popped-out tab to the window it came from. */\n dockBack: (itemId: CanvasItemId): CanvasAction => ({ type: `${P}dockBack`, payload: { itemId } }),\n /** A host window closed: its tabs dock home (default) or close with it. The main window never closes. */\n closeWindow: (windowId: CanvasWindowId, mode: CanvasWindowCloseMode = \"dock\"): CanvasAction => ({\n type: `${P}closeWindow`,\n payload: { windowId, mode },\n }),\n hydrate: (snapshot: CanvasState | null): CanvasAction => ({ type: `${P}hydrate`, payload: { snapshot } }),\n reset: (): CanvasAction => ({ type: `${P}reset` }),\n} as const;\n\nexport function isCanvasAction(action: unknown): action is CanvasAction {\n return (\n !!action &&\n typeof action === \"object\" &&\n typeof (action as { type?: unknown }).type === \"string\" &&\n (action as { type: string }).type.startsWith(P)\n );\n}\n\nexport function createInitialCanvasState(): CanvasState {\n const paneId = paneIdFromSeq(1);\n return {\n version: 1,\n isOpen: false,\n isFullscreen: false,\n width: null,\n layout: { type: \"pane\", paneId },\n focusedPaneId: paneId,\n windows: {},\n panes: { [paneId]: { id: paneId, itemIds: [], activeItemId: null } },\n items: {},\n seq: 1,\n hydrated: false,\n };\n}\n\n// ── window helpers ─────────────────────────────────────────────────────────\n\n/** Every window id, main first. */\nexport function listCanvasWindowIds(state: CanvasState): CanvasWindowId[] {\n return [CANVAS_MAIN_WINDOW, ...(Object.keys(state.windows ?? {}) as CanvasWindowId[])];\n}\n\n/** A window's frame, or null when that window does not exist. */\nexport function canvasWindowFrame(state: CanvasState, windowId: CanvasWindowId = CANVAS_MAIN_WINDOW): CanvasWindowFrame | null {\n return windowId === CANVAS_MAIN_WINDOW ? state : (state.windows?.[windowId] ?? null);\n}\n\n/** The window whose layout holds this pane. */\nexport function canvasWindowOfPane(state: CanvasState, paneId: CanvasPaneId): CanvasWindowId | null {\n for (const id of listCanvasWindowIds(state)) {\n const frame = canvasWindowFrame(state, id);\n if (frame && containsPane(frame.layout, paneId)) return id;\n }\n return null;\n}\n\n/** The window an item is in right now (null when it is not on the canvas). */\nexport function canvasWindowOfItem(state: CanvasState, itemId: CanvasItemId): CanvasWindowId | null {\n const pane = paneOf(state, itemId);\n return pane ? canvasWindowOfPane(state, pane.id) : null;\n}\n\ntype FramePatch = { -readonly [K in keyof CanvasWindowFrame]?: CanvasWindowFrame[K] };\n\nfunction withFrame(state: CanvasState, windowId: CanvasWindowId, patch: FramePatch): CanvasState {\n if (windowId === CANVAS_MAIN_WINDOW) return { ...state, ...patch };\n const current = state.windows[windowId];\n if (!current) return state;\n return { ...state, windows: { ...state.windows, [windowId]: { ...current, ...patch } } };\n}\n\n/** A non-main window comes into being the first time something targets it. */\nfunction ensureWindow(state: CanvasState, windowId: CanvasWindowId, role: CanvasExtraWindow[\"role\"] = \"window\", home: CanvasWindowId = CANVAS_MAIN_WINDOW): CanvasState {\n if (windowId === CANVAS_MAIN_WINDOW || state.windows[windowId]) return state;\n const seq = state.seq + 1;\n const paneId = paneIdFromSeq(seq);\n const frame: CanvasExtraWindow = {\n id: windowId,\n role,\n home,\n isOpen: false,\n isFullscreen: false,\n width: null,\n layout: { type: \"pane\", paneId },\n focusedPaneId: paneId,\n };\n return {\n ...state,\n seq,\n panes: { ...state.panes, [paneId]: { id: paneId, itemIds: [], activeItemId: null } },\n windows: { ...state.windows, [windowId]: frame },\n };\n}\n\nfunction removeWindow(state: CanvasState, windowId: CanvasWindowId): CanvasState {\n const frame = state.windows[windowId];\n if (!frame) return state;\n const panes = { ...state.panes };\n for (const paneId of listPaneIds(frame.layout)) delete panes[paneId];\n const windows = { ...state.windows };\n delete windows[windowId];\n return { ...state, panes, windows };\n}\n\nfunction windowItemIds(state: CanvasState, windowId: CanvasWindowId): CanvasItemId[] {\n const frame = canvasWindowFrame(state, windowId);\n if (!frame) return [];\n return listPaneIds(frame.layout).flatMap((paneId) => state.panes[paneId]?.itemIds ?? []);\n}\n\n/** A pop-out window left with no tabs has nothing to show and goes away. */\nfunction dropEmptyPopOut(state: CanvasState, windowId: CanvasWindowId | null): CanvasState {\n if (!windowId || windowId === CANVAS_MAIN_WINDOW) return state;\n const frame = state.windows[windowId];\n if (!frame || frame.role !== \"pop-out\" || windowItemIds(state, windowId).length > 0) return state;\n return removeWindow(state, windowId);\n}\n\n// ── pane helpers ───────────────────────────────────────────────────────────\n\nfunction paneOf(state: CanvasState, itemId: CanvasItemId): CanvasPane | null {\n for (const pane of Object.values(state.panes)) {\n if (pane.itemIds.includes(itemId)) return pane;\n }\n return null;\n}\n\nfunction withPane(state: CanvasState, pane: CanvasPane): CanvasState {\n return { ...state, panes: { ...state.panes, [pane.id]: pane } };\n}\n\nfunction focus(state: CanvasState, paneId: CanvasPaneId): CanvasState {\n const windowId = canvasWindowOfPane(state, paneId);\n return windowId ? withFrame(state, windowId, { focusedPaneId: paneId }) : state;\n}\n\n/** After removing `itemId` from a tab list, the neighbour that takes focus. */\nfunction nextActive(itemIds: readonly CanvasItemId[], removed: CanvasItemId, current: CanvasItemId | null): CanvasItemId | null {\n if (current !== removed) return current;\n const index = itemIds.indexOf(removed);\n const rest = itemIds.filter((id) => id !== removed);\n return rest[Math.min(index, rest.length - 1)] ?? null;\n}\n\nfunction detachItem(state: CanvasState, itemId: CanvasItemId): CanvasState {\n const pane = paneOf(state, itemId);\n if (!pane) return state;\n return withPane(state, {\n ...pane,\n itemIds: pane.itemIds.filter((id) => id !== itemId),\n activeItemId: nextActive(pane.itemIds, itemId, pane.activeItemId),\n });\n}\n\nfunction dropPane(state: CanvasState, paneId: CanvasPaneId): CanvasState {\n const windowId = canvasWindowOfPane(state, paneId);\n const frame = windowId ? canvasWindowFrame(state, windowId) : null;\n if (!windowId || !frame) return state;\n const layout = removePane(frame.layout, paneId);\n if (!layout) return state; // never remove a window's last pane\n const panes = { ...state.panes };\n delete panes[paneId];\n const focusedPaneId = frame.focusedPaneId === paneId ? (listPaneIds(layout)[0] ?? frame.focusedPaneId) : frame.focusedPaneId;\n return withFrame({ ...state, panes }, windowId, { layout, focusedPaneId });\n}\n\nfunction addSplit(\n state: CanvasState,\n paneId: CanvasPaneId,\n orientation: CanvasOrientation,\n share: number | undefined,\n): { state: CanvasState; newPaneId: CanvasPaneId } | null {\n const windowId = canvasWindowOfPane(state, paneId);\n const frame = windowId ? canvasWindowFrame(state, windowId) : null;\n if (!windowId || !frame) return null;\n const seq = state.seq + 1;\n const newPaneId = paneIdFromSeq(seq);\n const layout = splitPane(frame.layout, paneId, newPaneId, orientation, splitIdFromSeq(seq), share ?? 0.5);\n const next = withFrame(\n { ...state, seq, panes: { ...state.panes, [newPaneId]: { id: newPaneId, itemIds: [], activeItemId: null } } },\n windowId,\n { layout, focusedPaneId: newPaneId },\n );\n return { newPaneId, state: next };\n}\n\nfunction insertInto(state: CanvasState, paneId: CanvasPaneId, itemId: CanvasItemId, activate: boolean, index?: number): CanvasState {\n const pane = state.panes[paneId];\n if (!pane) return state;\n const itemIds = [...pane.itemIds.filter((id) => id !== itemId)];\n const at = index === undefined ? afterActive(itemIds, pane.activeItemId) : Math.max(0, Math.min(index, itemIds.length));\n itemIds.splice(at, 0, itemId);\n return withPane(state, {\n ...pane,\n itemIds,\n activeItemId: activate || pane.activeItemId === null ? itemId : pane.activeItemId,\n });\n}\n\n/** New tabs open right after the active tab, the way browsers do it. */\nfunction afterActive(itemIds: readonly CanvasItemId[], active: CanvasItemId | null): number {\n const index = active ? itemIds.indexOf(active) : -1;\n return index < 0 ? itemIds.length : index + 1;\n}\n\n/** Moves one item into another window's focused pane (docking, folding). */\nfunction sendHome(state: CanvasState, itemId: CanvasItemId, home: CanvasWindowId, activate: boolean): CanvasState {\n const homeFrame = canvasWindowFrame(state, home) ?? state;\n const target = canvasWindowFrame(state, home) ? home : CANVAS_MAIN_WINDOW;\n let next = detachItem(state, itemId);\n next = insertInto(next, homeFrame.focusedPaneId, itemId, activate);\n return activate ? withFrame(next, target, { focusedPaneId: homeFrame.focusedPaneId }) : next;\n}\n\n/** A new item. `instance` names its mounted body for as long as the item lives (rekey keeps it). */\nfunction newItem(kind: string, key: string, title: string | null, data: CanvasJson, now: number, history?: readonly CanvasHistoryEntry[]): CanvasItem {\n const id = canvasItemId(kind, key);\n return {\n id,\n kind,\n key,\n title,\n data,\n openedAt: now,\n updatedAt: now,\n instance: `${now.toString(36)}:${id}`,\n ...(history && history.length > 0 ? { history: history.slice(-CANVAS_HISTORY_LIMIT) } : {}),\n };\n}\n\nfunction historyEntry(item: CanvasItem): CanvasHistoryEntry {\n return { kind: item.kind, key: item.key, title: item.title, data: item.data };\n}\n\n/**\n * Puts `next` where `current` is (same pane, same position, same active state)\n * and drops `current`. Both identities must differ and `next` must be absent.\n */\nfunction replaceInPlace(state: CanvasState, current: CanvasItem, next: CanvasItem): CanvasState {\n const pane = paneOf(state, current.id);\n if (!pane) return state;\n const items = { ...state.items, [next.id]: next };\n delete items[current.id];\n const withItems: CanvasState = { ...state, items };\n const replaced = withPane(withItems, {\n ...pane,\n itemIds: pane.itemIds.map((id) => (id === current.id ? next.id : id)),\n activeItemId: pane.activeItemId === current.id ? next.id : pane.activeItemId,\n });\n return focus(replaced, pane.id);\n}\n\n/** Focuses an existing item wherever it is and reveals its window. */\nfunction focusExisting(state: CanvasState, itemId: CanvasItemId): CanvasState {\n const pane = paneOf(state, itemId);\n if (!pane) return state;\n const next = focus(withPane(state, { ...pane, activeItemId: itemId }), pane.id);\n const windowId = canvasWindowOfPane(next, pane.id);\n return windowId ? withFrame(next, windowId, { isOpen: true }) : next;\n}\n\nfunction sanitizeHistory(raw: unknown): CanvasHistoryEntry[] {\n if (!Array.isArray(raw)) return [];\n const out: CanvasHistoryEntry[] = [];\n for (const entry of raw as unknown[]) {\n if (!entry || typeof entry !== \"object\") continue;\n const e = entry as Partial<CanvasHistoryEntry>;\n if (typeof e.kind !== \"string\" || typeof e.key !== \"string\") continue;\n out.push({ kind: e.kind, key: e.key, title: typeof e.title === \"string\" ? e.title : null, data: e.data ?? null });\n }\n return out.slice(-CANVAS_HISTORY_LIMIT);\n}\n\n/** A saved item with only the fields this version understands, history validated. */\nfunction sanitizeItem(item: CanvasItem): CanvasItem {\n const history = sanitizeHistory((item as { history?: unknown }).history);\n const { history: _history, instance, ...rest } = item;\n return {\n ...rest,\n ...(typeof instance === \"string\" && instance ? { instance } : {}),\n ...(history.length > 0 ? { history } : {}),\n };\n}\n\nfunction clampWidth(width: number): number | null {\n return Number.isFinite(width) ? Math.max(CANVAS_MIN_WIDTH, Math.round(width)) : null;\n}\n\n// ── memory ─────────────────────────────────────────────────────────────────\n\n/**\n * Every window but the main one is a session thing: its tabs come home to the\n * main window's focused pane (nothing is lost) and the window goes away. Used\n * for what is saved and for what is restored.\n */\nexport function foldCanvasWindows(state: CanvasState): CanvasState {\n const extra = Object.keys(state.windows ?? {}) as CanvasWindowId[];\n if (extra.length === 0) return state.windows ? state : { ...state, windows: {} };\n let next = state;\n for (const windowId of extra) {\n for (const itemId of windowItemIds(next, windowId)) next = sendHome(next, itemId, CANVAS_MAIN_WINDOW, false);\n next = removeWindow(next, windowId);\n }\n return next;\n}\n\n/**\n * Validates a persisted snapshot. Anything malformed is dropped back to the\n * initial state rather than half-applied — a corrupt layout must never crash\n * the shell. Extra windows are folded home; full screen never comes back.\n */\nexport function sanitizeCanvasSnapshot(raw: unknown): CanvasState | null {\n if (!raw || typeof raw !== \"object\") return null;\n const s = raw as Partial<CanvasState> & { windows?: unknown };\n if (s.version !== 1 || !s.panes || typeof s.panes !== \"object\" || !s.items || typeof s.items !== \"object\" || !s.layout) return null;\n const paneIds = new Set(Object.keys(s.panes));\n const seen = new Set<string>();\n if (!isValidLayout(s.layout, paneIds, seen)) return null;\n\n // Extra windows: each must be a well-formed frame over panes nobody else uses.\n const windows: Record<string, CanvasExtraWindow> = {};\n if (s.windows && typeof s.windows === \"object\") {\n for (const [id, value] of Object.entries(s.windows as Record<string, unknown>)) {\n if (!value || typeof value !== \"object\" || id === CANVAS_MAIN_WINDOW) continue;\n const w = value as Partial<CanvasExtraWindow>;\n const claimed = new Set(seen);\n if (!isValidLayout(w.layout, paneIds, claimed)) continue;\n for (const pane of claimed) seen.add(pane);\n const layoutPanes = listPaneIds(w.layout);\n const focused = w.focusedPaneId && layoutPanes.includes(w.focusedPaneId) ? w.focusedPaneId : layoutPanes[0];\n if (!focused) continue;\n windows[id] = {\n id: id as CanvasWindowId,\n role: w.role === \"pop-out\" ? \"pop-out\" : \"window\",\n home: typeof w.home === \"string\" ? (w.home as CanvasWindowId) : CANVAS_MAIN_WINDOW,\n isOpen: w.isOpen === true,\n isFullscreen: false,\n width: typeof w.width === \"number\" ? clampWidth(w.width) : null,\n layout: normalizeLayout(w.layout),\n focusedPaneId: focused,\n };\n }\n }\n // Every pane must belong to exactly one window's layout.\n if (seen.size !== paneIds.size) return null;\n\n const items: Record<string, CanvasItem> = {};\n for (const [id, item] of Object.entries(s.items)) {\n if (item && typeof item.kind === \"string\" && typeof item.key === \"string\" && canvasItemId(item.kind, item.key) === id) {\n items[id] = sanitizeItem(item);\n }\n }\n const placed = new Set<string>();\n const panes: Record<string, CanvasPane> = {};\n for (const [id, pane] of Object.entries(s.panes)) {\n const itemIds = (Array.isArray(pane.itemIds) ? pane.itemIds : []).filter((itemId) => itemId in items && !placed.has(itemId));\n for (const itemId of itemIds) placed.add(itemId);\n const activeItemId = pane.activeItemId && itemIds.includes(pane.activeItemId) ? pane.activeItemId : (itemIds[0] ?? null);\n panes[id] = { id: id as CanvasPaneId, itemIds, activeItemId };\n }\n const mainPanes = listPaneIds(s.layout);\n const focused = s.focusedPaneId && mainPanes.includes(s.focusedPaneId) ? s.focusedPaneId : mainPanes[0];\n if (!focused) return null;\n const layout = normalizeLayout(s.layout);\n // seq must stay ahead of every id already minted, or the next split collides.\n const highest = Math.max(highestIdNumber(layout), ...Object.values(windows).map((w) => highestIdNumber(w.layout)));\n const seq = Math.max(typeof s.seq === \"number\" && Number.isFinite(s.seq) ? s.seq : 0, highest);\n let state: CanvasState = {\n version: 1,\n isOpen: s.isOpen === true,\n // Full screen is a moment, not a preference: a reload never starts there.\n isFullscreen: false,\n width: typeof s.width === \"number\" ? clampWidth(s.width) : null,\n layout,\n focusedPaneId: focused,\n windows,\n panes,\n items,\n seq,\n hydrated: true,\n };\n state = foldCanvasWindows(state);\n // An item that lost its pane is put back where it can be seen, never kept invisible.\n for (const id of Object.keys(items) as CanvasItemId[]) {\n if (!placed.has(id)) state = insertInto(state, state.focusedPaneId, id, false);\n }\n return state;\n}\n\nfunction normalizeLayout(node: CanvasLayoutNode): CanvasLayoutNode {\n if (node.type === \"pane\") return node;\n return { ...node, sizes: normalizeSizes(node.sizes, node.children.length), children: node.children.map(normalizeLayout) };\n}\n\nfunction highestIdNumber(node: CanvasLayoutNode): number {\n const own = Number((node.type === \"pane\" ? node.paneId : node.id).split(\"-\").pop());\n const mine = Number.isFinite(own) ? own : 0;\n return node.type === \"pane\" ? mine : Math.max(mine, ...node.children.map(highestIdNumber));\n}\n\n// ── reducer ────────────────────────────────────────────────────────────────\n\nexport function canvasReducer(state: CanvasState = createInitialCanvasState(), action: { type: string }): CanvasState {\n if (!isCanvasAction(action)) return state;\n // A state saved before windows existed carries no `windows` map.\n if (!state.windows) state = { ...state, windows: {} };\n switch (action.type) {\n case `${P}open`: {\n const { kind, key, title, data, target = \"focused\", reveal = true, activate = true, now, splitShare } = action.payload;\n const itemId = canvasItemId(kind, key);\n const existing = state.items[itemId];\n let next = state;\n let revealIn: CanvasWindowId = action.payload.windowId ?? CANVAS_MAIN_WINDOW;\n if (existing) {\n const item: CanvasItem = {\n ...existing,\n ...(data !== undefined ? { data } : {}),\n ...(title !== undefined ? { title } : {}),\n updatedAt: now,\n };\n next = { ...next, items: { ...next.items, [itemId]: item } };\n const pane = paneOf(next, itemId);\n if (pane) {\n revealIn = canvasWindowOfPane(next, pane.id) ?? CANVAS_MAIN_WINDOW;\n if (activate) next = focus(withPane(next, { ...pane, activeItemId: itemId }), pane.id);\n } else {\n next = ensureWindow(next, revealIn);\n const frame = canvasWindowFrame(next, revealIn) ?? next;\n next = insertInto(next, frame.focusedPaneId, itemId, true);\n }\n } else {\n const item = newItem(kind, key, title ?? null, data ?? null, now);\n next = ensureWindow({ ...next, items: { ...next.items, [itemId]: item } }, revealIn);\n const frame = canvasWindowFrame(next, revealIn) ?? next;\n let paneId: CanvasPaneId = frame.focusedPaneId;\n if (typeof target === \"object\" && next.panes[target.paneId]) {\n paneId = target.paneId;\n revealIn = canvasWindowOfPane(next, paneId) ?? revealIn;\n } else if (target === \"split-right\" || target === \"split-down\") {\n const split = addSplit(next, frame.focusedPaneId, target === \"split-right\" ? \"horizontal\" : \"vertical\", splitShare);\n if (split) {\n next = split.state;\n paneId = split.newPaneId;\n }\n }\n next = insertInto(next, paneId, itemId, activate);\n if (activate) next = focus(next, paneId);\n }\n return reveal ? withFrame(next, revealIn, { isOpen: true }) : next;\n }\n case `${P}update`: {\n const { itemId, data, title, now } = action.payload;\n const item = state.items[itemId];\n if (!item) return state;\n return {\n ...state,\n items: {\n ...state.items,\n [itemId]: { ...item, ...(data !== undefined ? { data } : {}), ...(title !== undefined ? { title } : {}), updatedAt: now },\n },\n };\n }\n case `${P}rekey`: {\n const { itemId, key } = action.payload;\n const item = state.items[itemId];\n if (!item || item.key === key) return state;\n const nextId = canvasItemId(item.kind, key);\n // The new identity is already open elsewhere: keep that one, drop this.\n if (state.items[nextId]) return canvasReducer(canvasReducer(state, canvasActions.closeItem(itemId)), canvasActions.activate(nextId));\n const items = { ...state.items, [nextId]: { ...item, id: nextId, key } };\n delete items[itemId];\n const panes: Record<string, CanvasPane> = {};\n for (const pane of Object.values(state.panes)) {\n panes[pane.id] = pane.itemIds.includes(itemId)\n ? {\n ...pane,\n itemIds: pane.itemIds.map((id) => (id === itemId ? nextId : id)),\n activeItemId: pane.activeItemId === itemId ? nextId : pane.activeItemId,\n }\n : pane;\n }\n return { ...state, items, panes };\n }\n case `${P}navigate`: {\n const { itemId, to, now } = action.payload;\n const current = state.items[itemId];\n if (!current || !paneOf(state, itemId)) return state;\n const targetId = canvasItemId(to.kind, to.key);\n if (targetId === itemId) {\n // Navigating to itself is a refresh, never a history step.\n const refresh: CanvasAction = { type: `${P}update`, payload: { itemId, data: to.data, title: to.title, now } };\n return canvasReducer(state, refresh);\n }\n if (state.items[targetId]) {\n // Identity law: the thing is already open — focus it there, never a second copy.\n // A launcher tab has done its job and closes; any other tab keeps what it shows.\n const focused = focusExisting(state, targetId);\n return current.kind === CANVAS_LAUNCHER_KIND ? canvasReducer(focused, canvasActions.closeItem(itemId)) : focused;\n }\n const history = [...(current.history ?? []), historyEntry(current)];\n return replaceInPlace(state, current, newItem(to.kind, to.key, to.title ?? null, to.data ?? null, now, history));\n }\n case `${P}back`: {\n const { itemId, now } = action.payload;\n const current = state.items[itemId];\n const history = current?.history ?? [];\n const entry = history[history.length - 1];\n if (!current || !entry || !paneOf(state, itemId)) return state;\n const targetId = canvasItemId(entry.kind, entry.key);\n if (targetId === itemId) return state;\n if (state.items[targetId]) {\n // What Back would return to was opened elsewhere since: go there; this step is done.\n return focusExisting(canvasReducer(state, canvasActions.closeItem(itemId)), targetId);\n }\n return replaceInPlace(state, current, newItem(entry.kind, entry.key, entry.title, entry.data, now, history.slice(0, -1)));\n }\n case `${P}closeItem`: {\n const { itemId } = action.payload;\n if (!state.items[itemId]) return state;\n const pane = paneOf(state, itemId);\n const windowId = pane ? canvasWindowOfPane(state, pane.id) : null;\n let next = detachItem(state, itemId);\n const items = { ...next.items };\n delete items[itemId];\n next = { ...next, items };\n // A pane emptied by closing its last tab goes away, unless it is its window's only one.\n if (pane && next.panes[pane.id]?.itemIds.length === 0) next = dropPane(next, pane.id);\n return dropEmptyPopOut(next, windowId);\n }\n case `${P}closeOthers`: {\n const { itemId } = action.payload;\n const pane = paneOf(state, itemId);\n if (!pane) return state;\n const items = { ...state.items };\n for (const id of pane.itemIds) if (id !== itemId) delete items[id];\n return { ...withPane(state, { ...pane, itemIds: [itemId], activeItemId: itemId }), items };\n }\n case `${P}activate`: {\n const pane = paneOf(state, action.payload.itemId);\n if (!pane) return state;\n return focus(withPane(state, { ...pane, activeItemId: action.payload.itemId }), pane.id);\n }\n case `${P}focusPane`: {\n const windowId = canvasWindowOfPane(state, action.payload.paneId);\n const frame = windowId ? canvasWindowFrame(state, windowId) : null;\n if (!windowId || !frame || frame.focusedPaneId === action.payload.paneId) return state;\n return withFrame(state, windowId, { focusedPaneId: action.payload.paneId });\n }\n case `${P}moveItem`: {\n const { itemId, toPaneId, index } = action.payload;\n const from = paneOf(state, itemId);\n if (!from || !state.panes[toPaneId]) return state;\n // Dropped back onto its own pane with no position: nothing moved.\n if (from.id === toPaneId && index === undefined) return canvasReducer(state, canvasActions.focusPane(toPaneId));\n const fromWindow = canvasWindowOfPane(state, from.id);\n let next = from.id === toPaneId ? state : detachItem(state, itemId);\n next = focus(insertInto(next, toPaneId, itemId, true, index), toPaneId);\n if (from.id !== toPaneId && next.panes[from.id]?.itemIds.length === 0) next = dropPane(next, from.id);\n return dropEmptyPopOut(next, fromWindow);\n }\n case `${P}splitPane`: {\n const { paneId, orientation, moveItemId, share } = action.payload;\n const pane = state.panes[paneId];\n if (!pane) return state;\n const split = addSplit(state, paneId, orientation, share);\n if (!split) return state;\n let next = split.state;\n // The new pane takes the requested tab when its old pane keeps something;\n // otherwise it starts empty and shows the launcher.\n if (moveItemId && pane.itemIds.includes(moveItemId) && pane.itemIds.length > 1) {\n next = detachItem(next, moveItemId);\n next = insertInto(next, split.newPaneId, moveItemId, true);\n }\n return next;\n }\n case `${P}closePane`: {\n const pane = state.panes[action.payload.paneId];\n const windowId = pane ? canvasWindowOfPane(state, pane.id) : null;\n const frame = windowId ? canvasWindowFrame(state, windowId) : null;\n if (!pane || !windowId || !frame) return state;\n const onlyPane = listPaneIds(frame.layout).length === 1;\n if (onlyPane) {\n // A pop-out's last pane closing closes the window; its tabs go home.\n if (windowId !== CANVAS_MAIN_WINDOW && state.windows[windowId]?.role === \"pop-out\") {\n return canvasReducer(state, canvasActions.closeWindow(windowId, \"dock\"));\n }\n // Closing the last pane puts the canvas away and KEEPS its tabs — the\n // toggle brings everything back exactly as it was.\n return withFrame(state, windowId, { isOpen: false, isFullscreen: false });\n }\n const items = { ...state.items };\n for (const id of pane.itemIds) delete items[id];\n return dropPane({ ...state, items }, pane.id);\n }\n case `${P}resizeSplit`: {\n const { splitId, sizes } = action.payload;\n for (const windowId of listCanvasWindowIds(state)) {\n const frame = canvasWindowFrame(state, windowId);\n if (frame && containsSplit(frame.layout, splitId)) {\n return withFrame(state, windowId, { layout: resizeSplit(frame.layout, splitId, sizes) });\n }\n }\n return state;\n }\n case `${P}setOpen`: {\n const { open, windowId = CANVAS_MAIN_WINDOW } = action.payload;\n const next = open ? ensureWindow(state, windowId) : state;\n const frame = canvasWindowFrame(next, windowId);\n if (!frame || frame.isOpen === open) return next;\n return withFrame(next, windowId, { isOpen: open, isFullscreen: open ? frame.isFullscreen : false });\n }\n case `${P}toggle`: {\n const windowId = action.payload?.windowId ?? CANVAS_MAIN_WINDOW;\n const next = ensureWindow(state, windowId);\n const frame = canvasWindowFrame(next, windowId);\n if (!frame) return state;\n return withFrame(next, windowId, { isOpen: !frame.isOpen, isFullscreen: frame.isOpen ? false : frame.isFullscreen });\n }\n case `${P}setFullscreen`: {\n const { fullscreen, windowId = CANVAS_MAIN_WINDOW } = action.payload;\n const next = fullscreen ? ensureWindow(state, windowId) : state;\n const frame = canvasWindowFrame(next, windowId);\n if (!frame) return state;\n return withFrame(next, windowId, { isFullscreen: fullscreen, isOpen: fullscreen ? true : frame.isOpen });\n }\n case `${P}setWidth`: {\n const { width, windowId = CANVAS_MAIN_WINDOW } = action.payload;\n const next = ensureWindow(state, windowId);\n return withFrame(next, windowId, { width: clampWidth(width) });\n }\n case `${P}popOut`: {\n const { itemId, windowId } = action.payload;\n const from = paneOf(state, itemId);\n if (!from || windowId === CANVAS_MAIN_WINDOW) return state;\n const fromWindow = canvasWindowOfPane(state, from.id) ?? CANVAS_MAIN_WINDOW;\n if (fromWindow === windowId) return state;\n let next = ensureWindow(state, windowId, \"pop-out\", fromWindow);\n const target = canvasWindowFrame(next, windowId);\n if (!target) return state;\n next = detachItem(next, itemId);\n next = insertInto(next, target.focusedPaneId, itemId, true);\n next = withFrame(next, windowId, { isOpen: true, focusedPaneId: target.focusedPaneId });\n if (next.panes[from.id]?.itemIds.length === 0) next = dropPane(next, from.id);\n next = dropEmptyPopOut(next, fromWindow);\n // The window it left has nothing left to show: put its column away.\n if (canvasWindowFrame(next, fromWindow) && windowItemIds(next, fromWindow).length === 0) {\n next = withFrame(next, fromWindow, { isOpen: false, isFullscreen: false });\n }\n return next;\n }\n case `${P}dockBack`: {\n const { itemId } = action.payload;\n const windowId = canvasWindowOfItem(state, itemId);\n if (!windowId || windowId === CANVAS_MAIN_WINDOW) return state;\n const frame = state.windows[windowId];\n if (!frame) return state;\n const home = canvasWindowFrame(state, frame.home) ? frame.home : CANVAS_MAIN_WINDOW;\n let next = sendHome(state, itemId, home, true);\n next = withFrame(next, home, { isOpen: true });\n const left = paneOf(state, itemId);\n if (left && next.panes[left.id]?.itemIds.length === 0) next = dropPane(next, left.id);\n return dropEmptyPopOut(next, windowId);\n }\n case `${P}closeWindow`: {\n const { windowId, mode } = action.payload;\n const frame = state.windows[windowId];\n if (!frame) return state;\n const itemIds = windowItemIds(state, windowId);\n let next = state;\n if (mode === \"close\") {\n const items = { ...next.items };\n for (const id of itemIds) delete items[id];\n next = { ...next, items };\n } else if (itemIds.length > 0) {\n const home = canvasWindowFrame(state, frame.home) ? frame.home : CANVAS_MAIN_WINDOW;\n const active = state.panes[frame.focusedPaneId]?.activeItemId ?? null;\n for (const id of itemIds) next = sendHome(next, id, home, id === active);\n next = withFrame(next, home, { isOpen: true });\n }\n return removeWindow(next, windowId);\n }\n case `${P}hydrate`: {\n const snapshot = action.payload.snapshot ? sanitizeCanvasSnapshot(action.payload.snapshot) : null;\n if (!snapshot) return { ...state, hydrated: true };\n // Anything opened before hydration finished wins over the snapshot.\n let next: CanvasState = snapshot;\n for (const item of Object.values(state.items)) {\n const pane = paneOf(state, item.id);\n next = { ...next, items: { ...next.items, [item.id]: item } };\n if (!paneOf(next, item.id)) next = insertInto(next, next.focusedPaneId, item.id, pane?.activeItemId === item.id);\n }\n return { ...next, isOpen: next.isOpen || state.isOpen, hydrated: true };\n }\n case `${P}reset`:\n return { ...createInitialCanvasState(), hydrated: true };\n default:\n return state;\n }\n}\n","/**\n * The store seam. The canvas never owns a second copy of its state: it reads\n * and writes through a CanvasStoreBinding.\n *\n * - A host WITH Redux mounts `canvasReducer` in its root reducer and binds it:\n * bindCanvasToReduxStore(store, (root) => root.canvasHost)\n * - A host WITHOUT Redux (a Vite tool, an Electron window) calls\n * createCanvasStore()\n * which runs the very same reducer in a tiny standalone store.\n */\n\nimport { canvasReducer, createInitialCanvasState, type CanvasAction } from \"./reducer\";\nimport type { CanvasState } from \"./types\";\n\nexport interface CanvasStoreBinding {\n getState(): CanvasState;\n dispatch(action: CanvasAction): void;\n subscribe(listener: () => void): () => void;\n /**\n * \"remote\": the state lives in another process (createRemoteCanvasStore) —\n * that process hydrates and saves it, so a controller over this binding\n * never does. Absent means \"local\".\n */\n readonly authority?: \"local\" | \"remote\";\n}\n\nexport function createCanvasStore(initial?: CanvasState): CanvasStoreBinding {\n let state = initial ?? createInitialCanvasState();\n const listeners = new Set<() => void>();\n return {\n getState: () => state,\n dispatch(action) {\n const next = canvasReducer(state, action);\n if (next === state) return;\n state = next;\n for (const listener of [...listeners]) listener();\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n };\n}\n\n/** The minimum of a Redux store the canvas needs. */\nexport interface ReduxStoreLike<TRoot> {\n getState(): TRoot;\n dispatch(action: CanvasAction): unknown;\n subscribe(listener: () => void): () => void;\n}\n\nexport function bindCanvasToReduxStore<TRoot>(\n store: ReduxStoreLike<TRoot>,\n select: (root: TRoot) => CanvasState,\n): CanvasStoreBinding {\n return {\n getState: () => select(store.getState()),\n dispatch: (action) => {\n store.dispatch(action);\n },\n subscribe: (listener) => store.subscribe(listener),\n };\n}\n","/**\n * A canvas store that lives in ANOTHER process — an Electron renderer bound to\n * the one store in the main process over IPC.\n *\n * - dispatch is async and fire-and-forget: the action goes to the owner, and\n * the state changes when the owner's next snapshot arrives (no optimistic\n * copy that could disagree with the owner);\n * - every update is a WHOLE snapshot with no shared object identity, so each\n * one is merged into the previous state structurally: anything unchanged\n * keeps its old reference, an identical snapshot changes nothing and wakes\n * nobody — selector results stay stable and useSyncExternalStore never loops;\n * - the binding is marked `authority: \"remote\"`: the owner hydrates and saves,\n * so a controller over it never does.\n *\n * The owner side (main process) is the ordinary `createCanvasStore()` +\n * `createCanvasController({ persistence })`; see the README.\n */\n\nimport { isCanvasAction, type CanvasAction } from \"./reducer\";\nimport type { CanvasStoreBinding } from \"./store\";\nimport type { CanvasState } from \"./types\";\n\nexport interface RemoteCanvasStoreOptions {\n /** The owner's state at connect time (e.g. from an `invoke(\"canvas:get\")`). */\n readonly initialSnapshot: CanvasState;\n /** Sends one action to the owner. A rejection is reported, never swallowed. */\n readonly dispatch: (action: CanvasAction) => Promise<void> | void;\n /** Delivers every new owner snapshot; returns the unsubscribe. */\n readonly subscribe: (onSnapshot: (snapshot: CanvasState) => void) => () => void;\n /** Where a failed dispatch is reported. Default: console.error. */\n readonly onError?: ((error: unknown, action: CanvasAction) => void) | undefined;\n}\n\nexport interface RemoteCanvasStore extends CanvasStoreBinding {\n /** Stops listening to the owner. */\n dispose(): void;\n}\n\nexport function createRemoteCanvasStore(options: RemoteCanvasStoreOptions): RemoteCanvasStore {\n let state: CanvasState = options.initialSnapshot;\n const listeners = new Set<() => void>();\n const report =\n options.onError ??\n ((error: unknown, action: CanvasAction) => console.error(`[@ai-matrx/canvas] remote dispatch of ${action.type} failed`, error));\n\n const stop = options.subscribe((snapshot) => {\n const next = shareStructure(state, snapshot);\n if (next === state) return;\n state = next;\n for (const listener of [...listeners]) listener();\n });\n\n return {\n authority: \"remote\",\n getState: () => state,\n dispatch(action) {\n if (!isCanvasAction(action)) return;\n try {\n void Promise.resolve(options.dispatch(action)).catch((error: unknown) => report(error, action));\n } catch (error) {\n report(error, action);\n }\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n dispose() {\n stop();\n listeners.clear();\n },\n };\n}\n\n/**\n * Returns `next`, but with every subtree that is deep-equal to the same subtree\n * of `prev` replaced by `prev`'s object. When nothing changed it returns `prev`\n * itself. Plain JSON only (what crosses a process boundary).\n */\nexport function shareStructure<T>(prev: T, next: T): T {\n if (Object.is(prev, next)) return prev;\n if (typeof prev !== \"object\" || typeof next !== \"object\" || prev === null || next === null) return next;\n if (Array.isArray(prev) !== Array.isArray(next)) return next;\n if (Array.isArray(prev) && Array.isArray(next)) {\n let same = prev.length === next.length;\n const out = next.map((value: unknown, i: number) => {\n const shared = i < prev.length ? shareStructure(prev[i] as unknown, value) : value;\n if (shared !== prev[i]) same = false;\n return shared;\n });\n return (same ? prev : out) as T;\n }\n const a = prev as Record<string, unknown>;\n const b = next as Record<string, unknown>;\n const keys = Object.keys(b);\n let same = keys.length === Object.keys(a).length;\n const out: Record<string, unknown> = {};\n for (const key of keys) {\n const shared = key in a ? shareStructure(a[key], b[key]) : b[key];\n if (shared !== a[key] || !(key in a)) same = false;\n out[key] = shared;\n }\n return (same ? prev : out) as T;\n}\n","/**\n * Remembering the canvas between sessions — a table stake, never optional.\n *\n * The default port writes to localStorage under a versioned key. Items whose\n * kind opts out (`restore: false`, e.g. a live session that cannot come back)\n * are dropped from the snapshot, and panes they leave empty are dropped too.\n */\n\nimport { removePane } from \"./layout\";\nimport { foldCanvasWindows } from \"./reducer\";\nimport type { CanvasItemId, CanvasState } from \"./types\";\n\nexport interface CanvasPersistencePort {\n load(): CanvasState | null | Promise<CanvasState | null>;\n save(snapshot: CanvasState): void | Promise<void>;\n}\n\nexport const CANVAS_STORAGE_KEY = \"ai-matrx.canvas.v1\";\n\nexport function createLocalStorageCanvasPersistence(\n key: string = CANVAS_STORAGE_KEY,\n storage: Pick<Storage, \"getItem\" | \"setItem\"> | null = typeof window === \"undefined\" ? null : safeLocalStorage(),\n): CanvasPersistencePort {\n return {\n load() {\n if (!storage) throw new Error(\"Canvas storage is unavailable; allow browser storage or provide a persistence port.\");\n const raw = storage.getItem(key);\n if (!raw) return null;\n return JSON.parse(raw) as CanvasState;\n },\n save(snapshot) {\n if (!storage) throw new Error(\"Canvas storage is unavailable; allow browser storage or provide a persistence port.\");\n storage.setItem(key, JSON.stringify(snapshot));\n },\n };\n}\n\n/**\n * Memory over any key-value store — an Electron main process's `state/kv`,\n * electron-store, IndexedDB behind a promise, a test map. Values are written\n * as plain JSON objects (not strings) so a structured store keeps them\n * inspectable; a string-only store can wrap this with JSON.stringify.\n */\nexport interface CanvasKeyValueStore {\n get(key: string): unknown;\n set(key: string, value: unknown): void | Promise<void>;\n}\n\nexport function createKeyValueCanvasPersistence(kv: CanvasKeyValueStore, key: string = CANVAS_STORAGE_KEY): CanvasPersistencePort {\n return {\n async load() {\n const raw = await kv.get(key);\n if (raw === undefined || raw === null) return null;\n return (typeof raw === \"string\" ? JSON.parse(raw) : raw) as CanvasState;\n },\n save: (snapshot) => kv.set(key, JSON.parse(JSON.stringify(snapshot)) as unknown),\n };\n}\n\nfunction safeLocalStorage(): Storage | null {\n try {\n const probe = \"__mxc_probe__\";\n window.localStorage.setItem(probe, \"1\");\n window.localStorage.removeItem(probe);\n return window.localStorage;\n } catch {\n return null; // load/save report through the controller's existing error sink.\n }\n}\n\n/**\n * Builds the snapshot that is actually written: only restorable items, and\n * every window but the main one folded home (other windows never come back).\n */\nexport function toPersistableSnapshot(\n state: CanvasState,\n isRestorable: (kind: string) => boolean,\n): CanvasState {\n state = foldCanvasWindows(state);\n const keep = new Set<CanvasItemId>(\n Object.values(state.items).filter((item) => isRestorable(item.kind)).map((item) => item.id),\n );\n if (keep.size === Object.keys(state.items).length) return state;\n const items = Object.fromEntries(Object.entries(state.items).filter(([id]) => keep.has(id as CanvasItemId)));\n let layout = state.layout;\n const panes: Record<string, CanvasState[\"panes\"][string]> = {};\n for (const pane of Object.values(state.panes)) {\n const itemIds = pane.itemIds.filter((id) => keep.has(id));\n if (itemIds.length === 0 && pane.itemIds.length > 0) {\n const pruned = removePane(layout, pane.id);\n if (pruned) {\n layout = pruned;\n continue;\n }\n }\n panes[pane.id] = {\n ...pane,\n itemIds,\n activeItemId: pane.activeItemId && keep.has(pane.activeItemId) ? pane.activeItemId : (itemIds[0] ?? null),\n };\n }\n const focusedPaneId = panes[state.focusedPaneId] ? state.focusedPaneId : (Object.values(panes)[0]?.id ?? state.focusedPaneId);\n return { ...state, items, panes, layout, focusedPaneId };\n}\n","/**\n * Layout rules — the host-tunable numbers behind the column's width and how its\n * panes share space. Pure functions, so a desktop main process can place native\n * views with exactly the numbers the renderer draws with.\n *\n * The canvas always shrinks FIRST: while the window narrows, the centre keeps\n * `centreMinWidth` and the canvas gives way down to `minWidth`; only then does\n * the centre squeeze. Side-by-side panes narrower than `paneMinWidth` stack\n * instead of squeezing.\n */\n\nimport { CANVAS_DEFAULT_WIDTH, CANVAS_MIN_WIDTH } from \"./types\";\n\nexport interface CanvasLayoutRules {\n /** Width before the person drags the edge: CSS px, or a fraction of the region the canvas shares. */\n readonly defaultWidth: number | { readonly fraction: number };\n /** The narrowest the canvas column gets on a desktop-sized window. */\n readonly minWidth: number;\n /** Room the content beside the canvas always keeps (the canvas shrinks first). */\n readonly centreMinWidth: number;\n /** The FIRST pane's share when a pane splits down (stacked). 0.7 = the 70/30 divider. */\n readonly stackSplit: number;\n /** The first pane's share when a pane splits right (side by side). */\n readonly sideSplit: number;\n /** Side-by-side panes that would be narrower than this render stacked. 0 = never. */\n readonly paneMinWidth: number;\n}\n\n/** The web app's numbers (the defaults). */\nexport const CANVAS_WEB_LAYOUT_RULES: CanvasLayoutRules = {\n defaultWidth: CANVAS_DEFAULT_WIDTH,\n minWidth: CANVAS_MIN_WIDTH,\n centreMinWidth: 420,\n // Split down 70/30 like the desktop: what opens below (notifications, a feed) is the smaller pane.\n stackSplit: 0.7,\n sideSplit: 0.5,\n paneMinWidth: 0,\n};\n\n/** The desktop app's numbers (Claude desktop's proportions). */\nexport const CANVAS_DESKTOP_LAYOUT_RULES: CanvasLayoutRules = {\n defaultWidth: { fraction: 0.36 },\n minWidth: CANVAS_MIN_WIDTH,\n centreMinWidth: 520,\n stackSplit: 0.7,\n sideSplit: 0.5,\n paneMinWidth: 360,\n};\n\nconst clampFraction = (value: number, fallback: number) =>\n Number.isFinite(value) ? Math.min(0.88, Math.max(0.12, value)) : fallback;\n\n/** Fills missing fields from the web defaults and repairs nonsense values. */\nexport function resolveCanvasLayoutRules(rules?: Partial<CanvasLayoutRules> | null): CanvasLayoutRules {\n const merged = { ...CANVAS_WEB_LAYOUT_RULES, ...(rules ?? {}) };\n const positive = (value: number, fallback: number) => (Number.isFinite(value) && value >= 0 ? value : fallback);\n return {\n defaultWidth:\n typeof merged.defaultWidth === \"number\"\n ? positive(merged.defaultWidth, CANVAS_DEFAULT_WIDTH)\n : { fraction: Math.min(1, Math.max(0.05, Number.isFinite(merged.defaultWidth.fraction) ? merged.defaultWidth.fraction : 0.36)) },\n minWidth: positive(merged.minWidth, CANVAS_MIN_WIDTH),\n centreMinWidth: positive(merged.centreMinWidth, CANVAS_WEB_LAYOUT_RULES.centreMinWidth),\n stackSplit: clampFraction(merged.stackSplit, 0.5),\n sideSplit: clampFraction(merged.sideSplit, 0.5),\n paneMinWidth: positive(merged.paneMinWidth, 0),\n };\n}\n\n/** The width before the person chose one. `region` is the space the canvas shares (0 = unknown). */\nexport function defaultCanvasWidth(rules: CanvasLayoutRules, region: number): number {\n if (typeof rules.defaultWidth === \"number\") return rules.defaultWidth;\n return region > 0 ? Math.round(region * rules.defaultWidth.fraction) : CANVAS_DEFAULT_WIDTH;\n}\n\n/**\n * The column's width right now: the stored width (or the rule's default),\n * fitted so the centre keeps `centreMinWidth` and the canvas never goes under\n * `minWidth`. A width remembered on a wide monitor never crushes a laptop.\n */\nexport function fitCanvasWidth(stored: number | null, region: number, rules: CanvasLayoutRules): number {\n const wanted = stored ?? defaultCanvasWidth(rules, region);\n if (region <= 0) return Math.max(rules.minWidth, wanted);\n return Math.max(rules.minWidth, Math.min(wanted, region - rules.centreMinWidth));\n}\n\n/** Clamp for a dragged width: the same bounds as fitting. */\nexport function clampDraggedCanvasWidth(next: number, region: number, rules: CanvasLayoutRules): number {\n const max = Math.max(rules.minWidth, region - rules.centreMinWidth);\n return Math.min(max, Math.max(rules.minWidth, Math.round(next)));\n}\n\n/** Whether a side-by-side split this wide (px) with this many children renders stacked. */\nexport function shouldStackSplit(width: number, children: number, rules: CanvasLayoutRules): boolean {\n return rules.paneMinWidth > 0 && width > 0 && width < rules.paneMinWidth * children;\n}\n","/**\n * The canvas's keyboard shortcuts, as DATA. A web host gets them bound in the\n * DOM by `CanvasProvider`; a desktop host binds the same table in its main\n * process (menu accelerators / `before-input-event`), because keys pressed\n * inside a native web view never reach the renderer's DOM. Every shortcut runs\n * through `runCanvasCommand`, so both paths do exactly the same thing.\n */\n\nimport type { CanvasController } from \"./controller\";\nimport { canvasWindowFrame } from \"./reducer\";\nimport type { CanvasWindowId } from \"./types\";\n\nexport type CanvasCommandId =\n | \"canvas.toggle\"\n | \"canvas.toggleFullscreen\"\n | \"canvas.exitFullscreen\"\n | \"canvas.closeTab\"\n | \"canvas.nextTab\"\n | \"canvas.previousTab\"\n | \"canvas.splitRight\"\n | \"canvas.splitDown\";\n\n/**\n * When a shortcut applies:\n * - \"presented\": a canvas column is on screen in this window;\n * - \"fullscreen\": the canvas is expanded (and Escape is not owned by a menu or dialog);\n * - \"canvas-focus\": keyboard focus is inside the canvas (a tab, a pane, a native body).\n */\nexport type CanvasShortcutWhen = \"presented\" | \"fullscreen\" | \"canvas-focus\";\n\nexport interface CanvasShortcut {\n readonly id: CanvasCommandId;\n /** Electron accelerator syntax: \"CmdOrCtrl+\\\\\", \"Escape\", \"Ctrl+Shift+Tab\". */\n readonly accelerator: string;\n readonly when: CanvasShortcutWhen;\n readonly label: string;\n /** False when browsers reserve the keys (⌘W, Ctrl+Tab): only a desktop host can bind it. */\n readonly web: boolean;\n}\n\nexport const CANVAS_SHORTCUTS: readonly CanvasShortcut[] = [\n { id: \"canvas.toggle\", accelerator: \"CmdOrCtrl+\\\\\", when: \"presented\", label: \"Show or hide canvas\", web: true },\n { id: \"canvas.exitFullscreen\", accelerator: \"Escape\", when: \"fullscreen\", label: \"Restore canvas\", web: true },\n { id: \"canvas.toggleFullscreen\", accelerator: \"CmdOrCtrl+Shift+Enter\", when: \"canvas-focus\", label: \"Expand canvas\", web: true },\n { id: \"canvas.splitRight\", accelerator: \"CmdOrCtrl+Alt+\\\\\", when: \"canvas-focus\", label: \"Split right\", web: true },\n { id: \"canvas.splitDown\", accelerator: \"CmdOrCtrl+Alt+Shift+\\\\\", when: \"canvas-focus\", label: \"Split down\", web: true },\n { id: \"canvas.closeTab\", accelerator: \"CmdOrCtrl+W\", when: \"canvas-focus\", label: \"Close tab\", web: false },\n { id: \"canvas.nextTab\", accelerator: \"Ctrl+Tab\", when: \"canvas-focus\", label: \"Next tab\", web: false },\n { id: \"canvas.previousTab\", accelerator: \"Ctrl+Shift+Tab\", when: \"canvas-focus\", label: \"Previous tab\", web: false },\n];\n\n/** The tooltip hint for a command, e.g. \"⌘\\\\\" on a Mac. */\nexport function canvasShortcutHint(id: CanvasCommandId, isMac: boolean): string | null {\n const shortcut = CANVAS_SHORTCUTS.find((entry) => entry.id === id);\n if (!shortcut) return null;\n return shortcut.accelerator\n .split(\"+\")\n .map((part) => {\n if (part === \"CmdOrCtrl\") return isMac ? \"⌘\" : \"Ctrl+\";\n if (part === \"Ctrl\") return isMac ? \"⌃\" : \"Ctrl+\";\n if (part === \"Alt\") return isMac ? \"⌥\" : \"Alt+\";\n if (part === \"Shift\") return isMac ? \"⇧\" : \"Shift+\";\n if (part === \"Escape\") return \"Esc\";\n return part;\n })\n .join(\"\");\n}\n\n/**\n * Runs one command against a window's canvas. Returns true when it did\n * something (so a binding knows whether to swallow the key).\n */\nexport function runCanvasCommand(controller: CanvasController, id: CanvasCommandId, windowId: CanvasWindowId = controller.windowId): boolean {\n const state = controller.getState();\n const frame = canvasWindowFrame(state, windowId);\n const pane = frame ? state.panes[frame.focusedPaneId] : undefined;\n switch (id) {\n case \"canvas.toggle\":\n controller.toggle(windowId);\n return true;\n case \"canvas.toggleFullscreen\":\n controller.setFullscreen(!(frame?.isFullscreen ?? false), windowId);\n return true;\n case \"canvas.exitFullscreen\":\n if (!frame?.isFullscreen) return false;\n controller.setFullscreen(false, windowId);\n return true;\n case \"canvas.closeTab\":\n if (!frame?.isOpen || !pane?.activeItemId) return false;\n controller.close(pane.activeItemId);\n return true;\n case \"canvas.nextTab\":\n case \"canvas.previousTab\": {\n if (!frame?.isOpen || !pane?.activeItemId || pane.itemIds.length < 2) return false;\n const at = pane.itemIds.indexOf(pane.activeItemId);\n const step = id === \"canvas.nextTab\" ? 1 : -1;\n const next = pane.itemIds[(at + step + pane.itemIds.length) % pane.itemIds.length];\n if (next) controller.activate(next);\n return true;\n }\n case \"canvas.splitRight\":\n case \"canvas.splitDown\":\n if (!frame?.isOpen || !pane) return false;\n controller.splitPane(pane.id, id === \"canvas.splitRight\" ? \"horizontal\" : \"vertical\", pane.itemIds.length > 1 ? (pane.activeItemId ?? undefined) : undefined);\n return true;\n default:\n return false;\n }\n}\n\n/** The subset of a KeyboardEvent an accelerator is matched against. */\nexport interface CanvasKeyInput {\n readonly key: string;\n readonly code?: string;\n readonly metaKey: boolean;\n readonly ctrlKey: boolean;\n readonly altKey: boolean;\n readonly shiftKey: boolean;\n}\n\nconst CODE_FOR: Record<string, string> = { \"\\\\\": \"Backslash\", Tab: \"Tab\", Escape: \"Escape\", Enter: \"Enter\" };\n\n/**\n * Whether a key event is this accelerator. \"CmdOrCtrl\" is ⌘ on a Mac and Ctrl\n * elsewhere; symbol keys match by physical key (⌥\\ types « on a Mac).\n */\nexport function matchesCanvasAccelerator(input: CanvasKeyInput, accelerator: string, isMac: boolean): boolean {\n const parts = accelerator.split(\"+\");\n // \"CmdOrCtrl+\\\\\" splits into [..., \"\\\\\"]; a trailing \"+\" key would split empty.\n const key = parts.pop() ?? \"\";\n const want = { meta: false, ctrl: false, alt: false, shift: false };\n for (const part of parts) {\n if (part === \"CmdOrCtrl\") want[isMac ? \"meta\" : \"ctrl\"] = true;\n else if (part === \"Cmd\" || part === \"Meta\") want.meta = true;\n else if (part === \"Ctrl\") want.ctrl = true;\n else if (part === \"Alt\") want.alt = true;\n else if (part === \"Shift\") want.shift = true;\n }\n if (input.metaKey !== want.meta || input.ctrlKey !== want.ctrl || input.altKey !== want.alt || input.shiftKey !== want.shift) return false;\n const code = CODE_FOR[key] ?? (/^[A-Z]$/i.test(key) ? `Key${key.toUpperCase()}` : undefined);\n if (code && input.code === code) return true;\n return input.key.toLowerCase() === key.toLowerCase();\n}\n","/**\n * The canvas controller: the ONE imperative API every caller uses. It wraps a\n * store binding, validates what callers hand it (so the reducer stays pure and\n * trusting), and owns hydration, autosave, pop-outs and session lifecycles.\n *\n * A controller acts for ONE window by default (`controller.windowId`, main\n * unless the host says otherwise); `forWindow(id)` gives the same canvas seen\n * from another window. Nothing fails silently: a refused open, a pop-out the\n * host cannot do, a throwing session hook — each is reported through the\n * error sink.\n */\n\nimport { canvasActions, canvasWindowOfItem, canvasWindowFrame, listCanvasWindowIds, sanitizeCanvasSnapshot, type CanvasAction, type CanvasWindowCloseMode } from \"./reducer\";\nimport { canvasItemId, canvasWindowId, findNonJson } from \"./ids\";\nimport { listPaneIds } from \"./layout\";\nimport { toPersistableSnapshot, type CanvasPersistencePort } from \"./persistence\";\nimport { resolveCanvasLayoutRules, type CanvasLayoutRules } from \"./rules\";\nimport type { CanvasStoreBinding } from \"./store\";\nimport {\n CANVAS_LAUNCHER_KIND,\n CANVAS_MAIN_WINDOW,\n type CanvasItem,\n type CanvasItemId,\n type CanvasJson,\n type CanvasNavigateInput,\n type CanvasOpenInput,\n type CanvasOpenTarget,\n type CanvasOrientation,\n type CanvasPaneId,\n type CanvasPreferredTarget,\n type CanvasSplitId,\n type CanvasState,\n type CanvasWindowId,\n} from \"./types\";\n\nexport interface CanvasErrorReport {\n readonly code:\n | \"non-json-data\"\n | \"unknown-kind\"\n | \"persistence-load\"\n | \"persistence-save\"\n | \"pop-out-unavailable\"\n | \"pop-out-refused\"\n | \"pop-out-failed\"\n | \"session-hook\";\n readonly message: string;\n readonly detail?: unknown;\n}\n\nexport type CanvasErrorSink = (report: CanvasErrorReport) => void;\n\nexport const consoleCanvasErrorSink: CanvasErrorSink = (report) => {\n console.error(`[@ai-matrx/canvas] ${report.code}: ${report.message}`, report.detail ?? \"\");\n};\n\n/**\n * The host's window abilities. Without `popOut` a pop-out is refused aloud and\n * no \"Pop out\" entry is shown.\n */\nexport interface CanvasWindowPorts {\n /**\n * Opens a window (web: a floating panel; desktop: a BrowserWindow) that will\n * render the canvas for the returned window id, then the package moves the\n * item there. Resolve null to refuse.\n */\n readonly popOut?: ((item: CanvasItem) => Promise<{ readonly windowId: string } | null>) | undefined;\n /** Called after a tab docked back out of `fromWindowId` (close that window when the state no longer lists it). */\n readonly dockBack?: ((itemId: CanvasItemId, fromWindowId: CanvasWindowId) => void) | undefined;\n}\n\n/** Why a session-backed item attached or detached. */\nexport type CanvasSessionAttachReason = \"open\" | \"restore\" | \"arrive\";\nexport type CanvasSessionDetachReason = \"close\" | \"leave\" | \"unmount\";\n\nexport interface CanvasSessionEvent<R extends string> {\n readonly item: CanvasItem;\n readonly sessionKey: string;\n /** The window the item is in (attach) or was in (detach). */\n readonly windowId: CanvasWindowId;\n readonly reason: R;\n}\n\n/**\n * A kind with `restore: \"session\"`: its tab is a view onto a process the host\n * keeps (a terminal). Closing the tab DETACHES (the process lives on); a\n * restore or a move REATTACHES. The package only calls these; the host owns the\n * process side.\n */\nexport interface CanvasSessionHooks {\n readonly sessionKey: (item: CanvasItem) => string | null;\n readonly onAttach?: ((event: CanvasSessionEvent<CanvasSessionAttachReason>) => void) | undefined;\n readonly onDetach?: ((event: CanvasSessionEvent<CanvasSessionDetachReason>) => void) | undefined;\n}\n\nexport interface CanvasControllerOptions {\n readonly store: CanvasStoreBinding;\n readonly persistence?: CanvasPersistencePort | null | undefined;\n /** Kinds that may not come back after a reload. Default: every kind restores. */\n readonly isRestorable?: ((kind: string) => boolean) | undefined;\n /** When given, opens of an unregistered kind are refused and reported. */\n readonly isKnownKind?: ((kind: string) => boolean) | undefined;\n readonly onError?: CanvasErrorSink | undefined;\n readonly saveDelayMs?: number | undefined;\n /**\n * Whether a remembered \"open\" may be restored right now. A host returns\n * false where an open canvas would take the whole screen (a phone).\n */\n readonly mayRestoreOpen?: (() => boolean) | undefined;\n /** The window this controller acts for by default. Default: the main window. */\n readonly windowId?: string | undefined;\n /** Width and split numbers (see CANVAS_WEB_LAYOUT_RULES / CANVAS_DESKTOP_LAYOUT_RULES). */\n readonly layoutRules?: Partial<CanvasLayoutRules> | undefined;\n /** Read on every use, so a provider can hand in its latest ports. */\n readonly windowPorts?: (() => CanvasWindowPorts) | undefined;\n /** Session hooks for a kind, or undefined when the kind is not session-backed. */\n readonly sessions?: ((kind: string) => CanvasSessionHooks | undefined) | undefined;\n /**\n * Where a NEW item of a kind opens while the canvas already shows something\n * (a kind's `preferredTarget`). An explicit `target` always wins.\n */\n readonly preferredTarget?: ((kind: string) => CanvasPreferredTarget | undefined) | undefined;\n}\n\nexport interface CanvasController {\n readonly store: CanvasStoreBinding;\n /** The window this controller acts for by default. */\n readonly windowId: CanvasWindowId;\n readonly rules: CanvasLayoutRules;\n /** The same canvas, acting for another window. */\n forWindow(windowId: string): CanvasController;\n getState(): CanvasState;\n open(input: CanvasOpenInput): CanvasItemId | null;\n update(itemId: CanvasItemId, patch: { data?: CanvasJson | undefined; title?: string | null | undefined }): boolean;\n /** Gives an item a new identity in place (a draft that was saved and now has a durable id). */\n rekey(itemId: CanvasItemId, key: string): CanvasItemId | null;\n /**\n * Replaces a tab's content with another item IN PLACE and records history,\n * so the pane header offers Back. Identity still holds: when the target is\n * already open, it is focused where it is (a launcher tab then closes; any\n * other tab keeps what it shows). Returns the item now shown, or null.\n */\n navigate(itemId: CanvasItemId, to: CanvasNavigateInput): CanvasItemId | null;\n /** Returns a tab to what it showed before (see navigate). Null when it has no history. */\n back(itemId: CanvasItemId): CanvasItemId | null;\n /** Opens the launcher as a new tab in a pane (default: this window's focused pane), or focuses the one already there. */\n newTab(paneId?: CanvasPaneId): CanvasItemId;\n close(itemId: CanvasItemId): void;\n closeOthers(itemId: CanvasItemId): void;\n activate(itemId: CanvasItemId): void;\n focusPane(paneId: CanvasPaneId): void;\n moveItem(itemId: CanvasItemId, toPaneId: CanvasPaneId, index?: number): void;\n /** Splits with the layout rules' share (stackSplit for \"vertical\", sideSplit for \"horizontal\"). */\n splitPane(paneId: CanvasPaneId, orientation: CanvasOrientation, moveItemId?: CanvasItemId): void;\n closePane(paneId: CanvasPaneId): void;\n resizeSplit(splitId: CanvasSplitId, sizes: readonly number[]): void;\n show(windowId?: CanvasWindowId): void;\n hide(windowId?: CanvasWindowId): void;\n toggle(windowId?: CanvasWindowId): void;\n setFullscreen(fullscreen: boolean, windowId?: CanvasWindowId): void;\n setWidth(width: number, windowId?: CanvasWindowId): void;\n /** Moves a tab into its own window through the host's popOut port. Refused aloud without one. */\n popOut(itemId: CanvasItemId): Promise<CanvasWindowId | null>;\n /** Returns a popped-out tab to the window it came from. False when it is not popped out. */\n dockBack(itemId: CanvasItemId): boolean;\n /** A host window closed: its tabs dock home (default) or close with it. */\n closeWindow(windowId: CanvasWindowId, mode?: CanvasWindowCloseMode): void;\n /** Is this exact thing on the canvas right now (in any window)? */\n has(kind: string, key: string): boolean;\n /**\n * Is a canvas column on screen (in this window, or in `windowId`)? A store\n * can exist in a layout that shows no column (a kiosk, a meeting stage);\n * opening there must be refused aloud.\n */\n isPresented(windowId?: CanvasWindowId): boolean;\n /** Called by a column on mount; returns the unmount callback. */\n registerPresentation(windowId?: CanvasWindowId): () => void;\n subscribePresentation(listener: () => void): () => void;\n /** Loads the persisted snapshot, starts autosave and session tracking. Returns a disposer. */\n start(): () => void;\n}\n\ninterface Shared {\n readonly options: CanvasControllerOptions;\n readonly onError: CanvasErrorSink;\n readonly rules: CanvasLayoutRules;\n readonly presentations: Map<CanvasWindowId, number>;\n readonly presentationListeners: Set<() => void>;\n readonly views: Map<CanvasWindowId, CanvasController>;\n /** Windows whose controllers are started (session tracking scope for a remote store). */\n readonly started: Map<CanvasWindowId, number>;\n sessionStop: (() => void) | null;\n /** Mints \"New tab\" keys (unique per controller family). */\n launcherSeq: number;\n}\n\nexport function createCanvasController(options: CanvasControllerOptions): CanvasController {\n const shared: Shared = {\n options,\n onError: options.onError ?? consoleCanvasErrorSink,\n rules: resolveCanvasLayoutRules(options.layoutRules),\n presentations: new Map(),\n presentationListeners: new Set(),\n views: new Map(),\n started: new Map(),\n sessionStop: null,\n launcherSeq: 0,\n };\n return view(shared, canvasWindowId(options.windowId ?? CANVAS_MAIN_WINDOW));\n}\n\nfunction view(shared: Shared, windowId: CanvasWindowId): CanvasController {\n const cached = shared.views.get(windowId);\n if (cached) return cached;\n const { options, onError, rules } = shared;\n const { store, persistence = null } = options;\n const isRestorable = options.isRestorable ?? (() => true);\n const dispatch = (action: CanvasAction) => store.dispatch(action);\n const notifyPresentation = () => {\n for (const listener of [...shared.presentationListeners]) listener();\n };\n const shareFor = (orientation: CanvasOrientation) => (orientation === \"vertical\" ? rules.stackSplit : rules.sideSplit);\n\n /** Refuses aloud what may not be opened: an unknown kind, data that is not plain JSON. */\n const acceptable = (input: { readonly kind: string; readonly key: string; readonly data?: CanvasJson | undefined }): boolean => {\n if (input.kind !== CANVAS_LAUNCHER_KIND && options.isKnownKind && !options.isKnownKind(input.kind)) {\n onError({ code: \"unknown-kind\", message: `No canvas kind \"${input.kind}\" is registered.`, detail: input });\n return false;\n }\n if (input.data !== undefined) {\n const bad = findNonJson(input.data);\n if (bad) {\n onError({\n code: \"non-json-data\",\n message: `Canvas data for \"${input.kind}\" must be plain JSON; ${bad} is not.`,\n detail: { kind: input.kind, key: input.key },\n });\n return false;\n }\n }\n return true;\n };\n\n /**\n * A kind's preferred place for a NEW item, applied only while the canvas\n * already shows something in this window: a pane already holding that kind\n * takes it (one notifications pane, not a new split per press); otherwise\n * the preferred split of the focused pane. A put-away or empty canvas, or an\n * item that already exists, just opens where it would anyway.\n */\n const preferredTargetFor = (input: CanvasOpenInput): CanvasOpenTarget => {\n const preferred = options.preferredTarget?.(input.kind);\n if (!preferred || preferred === \"focused\") return \"focused\";\n const state = store.getState();\n if (canvasItemId(input.kind, input.key) in state.items) return \"focused\";\n const frame = canvasWindowFrame(state, input.windowId ?? windowId);\n if (!frame?.isOpen) return \"focused\";\n const panes = listPaneIds(frame.layout);\n const holding = panes.find((paneId) => state.panes[paneId]?.itemIds.some((id) => state.items[id]?.kind === input.kind));\n if (holding) return { paneId: holding };\n return state.panes[frame.focusedPaneId]?.activeItemId ? preferred : \"focused\";\n };\n\n const controller: CanvasController = {\n store,\n windowId,\n rules,\n forWindow: (id) => view(shared, canvasWindowId(id)),\n getState: () => store.getState(),\n open(input) {\n if (!acceptable(input)) return null;\n const target = input.target ?? preferredTargetFor(input);\n const splitShare = target === \"split-down\" ? rules.stackSplit : target === \"split-right\" ? rules.sideSplit : undefined;\n const withTarget: CanvasOpenInput = input.target === target ? input : { ...input, target };\n const resolved: CanvasOpenInput = withTarget.windowId || windowId === CANVAS_MAIN_WINDOW ? withTarget : { ...withTarget, windowId };\n dispatch(canvasActions.open(resolved, splitShare === undefined ? undefined : { splitShare }));\n return canvasItemId(input.kind, input.key);\n },\n update(itemId, patch) {\n if (patch.data !== undefined) {\n const bad = findNonJson(patch.data);\n if (bad) {\n onError({ code: \"non-json-data\", message: `Canvas update for ${itemId} must be plain JSON; ${bad} is not.` });\n return false;\n }\n }\n if (!store.getState().items[itemId]) return false;\n dispatch(canvasActions.update(itemId, patch));\n return true;\n },\n navigate(itemId, to) {\n if (!store.getState().items[itemId] || !acceptable(to)) return null;\n dispatch(canvasActions.navigate(itemId, to));\n const shown = canvasItemId(to.kind, to.key);\n return shown in store.getState().items ? shown : null;\n },\n back(itemId) {\n const history = store.getState().items[itemId]?.history ?? [];\n const entry = history[history.length - 1];\n if (!entry) return null;\n dispatch(canvasActions.back(itemId));\n return canvasItemId(entry.kind, entry.key);\n },\n newTab(paneId) {\n const state = store.getState();\n const frame = canvasWindowFrame(state, windowId);\n const target = paneId && state.panes[paneId] ? paneId : (frame?.focusedPaneId ?? state.focusedPaneId);\n const existing = state.panes[target]?.itemIds.find((id) => state.items[id]?.kind === CANVAS_LAUNCHER_KIND);\n if (existing) {\n dispatch(canvasActions.activate(existing));\n dispatch(canvasActions.setOpen(true, canvasWindowOfItem(store.getState(), existing) ?? windowId));\n return existing;\n }\n // Minted here, not in the reducer, so a remote store can name it before the main process answers.\n shared.launcherSeq += 1;\n const key = `${Date.now().toString(36)}-${shared.launcherSeq}`;\n dispatch(canvasActions.open({ kind: CANVAS_LAUNCHER_KIND, key, target: { paneId: target }, ...(windowId === CANVAS_MAIN_WINDOW ? {} : { windowId }) }));\n return canvasItemId(CANVAS_LAUNCHER_KIND, key);\n },\n rekey(itemId, key) {\n const item = store.getState().items[itemId];\n if (!item) return null;\n dispatch(canvasActions.rekey(itemId, key));\n return canvasItemId(item.kind, key);\n },\n close: (itemId) => dispatch(canvasActions.closeItem(itemId)),\n closeOthers: (itemId) => dispatch(canvasActions.closeOthers(itemId)),\n activate: (itemId) => dispatch(canvasActions.activate(itemId)),\n focusPane: (paneId) => dispatch(canvasActions.focusPane(paneId)),\n moveItem: (itemId, toPaneId, index) => dispatch(canvasActions.moveItem(itemId, toPaneId, index)),\n splitPane: (paneId, orientation, moveItemId) => dispatch(canvasActions.splitPane(paneId, orientation, moveItemId, shareFor(orientation))),\n closePane: (paneId) => dispatch(canvasActions.closePane(paneId)),\n resizeSplit: (splitId, sizes) => dispatch(canvasActions.resizeSplit(splitId, sizes)),\n show: (w = windowId) => dispatch(canvasActions.setOpen(true, w)),\n hide: (w = windowId) => dispatch(canvasActions.setOpen(false, w)),\n toggle: (w = windowId) => dispatch(canvasActions.toggle(w)),\n setFullscreen: (fullscreen, w = windowId) => dispatch(canvasActions.setFullscreen(fullscreen, w)),\n setWidth: (width, w = windowId) => dispatch(canvasActions.setWidth(width, w)),\n async popOut(itemId) {\n const item = store.getState().items[itemId];\n if (!item) return null;\n const port = options.windowPorts?.().popOut;\n if (!port) {\n onError({ code: \"pop-out-unavailable\", message: \"This app cannot pop canvas tabs out into their own window.\", detail: { itemId } });\n return null;\n }\n let result: { readonly windowId: string } | null;\n try {\n result = await port(item);\n } catch (error) {\n onError({ code: \"pop-out-failed\", message: \"The window for this tab could not be opened.\", detail: error });\n return null;\n }\n if (!result) {\n onError({ code: \"pop-out-refused\", message: \"The app declined to pop this tab out.\", detail: { itemId } });\n return null;\n }\n const target = canvasWindowId(result.windowId);\n dispatch(canvasActions.popOut(itemId, target));\n return target;\n },\n dockBack(itemId) {\n const state = store.getState();\n const from = canvasWindowOfItem(state, itemId);\n if (!from || from === CANVAS_MAIN_WINDOW || state.windows[from]?.role !== \"pop-out\") return false;\n dispatch(canvasActions.dockBack(itemId));\n options.windowPorts?.().dockBack?.(itemId, from);\n return true;\n },\n closeWindow: (w, mode = \"dock\") => dispatch(canvasActions.closeWindow(w, mode)),\n has: (kind, key) => canvasItemId(kind, key) in store.getState().items,\n isPresented: (w = windowId) => (shared.presentations.get(w) ?? 0) > 0,\n registerPresentation(w = windowId) {\n shared.presentations.set(w, (shared.presentations.get(w) ?? 0) + 1);\n notifyPresentation();\n let done = false;\n return () => {\n if (done) return;\n done = true;\n shared.presentations.set(w, Math.max(0, (shared.presentations.get(w) ?? 1) - 1));\n notifyPresentation();\n };\n },\n subscribePresentation(listener) {\n shared.presentationListeners.add(listener);\n return () => shared.presentationListeners.delete(listener);\n },\n start() {\n let disposed = false;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let lastSaved: CanvasState | null = null;\n // Another process owns a remote store: it hydrates and saves; this side only renders.\n const owns = store.authority !== \"remote\";\n const memory = owns ? persistence : null;\n\n const save = () => {\n timer = null;\n const state = store.getState();\n if (!memory || !state.hydrated || state === lastSaved) return;\n lastSaved = state;\n try {\n void Promise.resolve(memory.save(toPersistableSnapshot(state, isRestorable))).catch((error: unknown) =>\n onError({ code: \"persistence-save\", message: \"Saving the canvas layout failed.\", detail: error }),\n );\n } catch (error) {\n onError({ code: \"persistence-save\", message: \"Saving the canvas layout failed.\", detail: error });\n }\n };\n\n // A host store dispatches constantly (streaming, typing). Only a change\n // to the CANVAS state reschedules the save, or a busy app starves it.\n let seen = store.getState();\n const unsubscribe = store.subscribe(() => {\n if (!memory || disposed) return;\n const current = store.getState();\n if (current === seen) return;\n seen = current;\n if (timer) clearTimeout(timer);\n timer = setTimeout(save, options.saveDelayMs ?? 250);\n });\n\n if (!owns || store.getState().hydrated) {\n // Already hydrated (a second provider over the same store), or owned elsewhere.\n } else if (!memory) {\n dispatch(canvasActions.hydrate(null));\n } else {\n Promise.resolve()\n .then(() => memory.load())\n .then(\n (snapshot) => {\n if (disposed) return;\n const openedThisSession = store.getState().isOpen;\n const validSnapshot = snapshot === null ? null : sanitizeCanvasSnapshot(snapshot);\n if (snapshot !== null && validSnapshot === null) {\n onError({ code: \"persistence-load\", message: \"The saved canvas layout is invalid. Clear the saved layout or repair the persistence port.\" });\n }\n dispatch(canvasActions.hydrate(validSnapshot));\n if (!openedThisSession && options.mayRestoreOpen && !options.mayRestoreOpen() && store.getState().isOpen) {\n dispatch(canvasActions.setOpen(false));\n }\n },\n (error: unknown) => {\n onError({ code: \"persistence-load\", message: \"The saved canvas layout could not be read.\", detail: error });\n if (!disposed) dispatch(canvasActions.hydrate(null));\n },\n );\n }\n\n const stopSessions = startSessions(shared, windowId);\n\n return () => {\n disposed = true;\n unsubscribe();\n stopSessions();\n if (timer) {\n clearTimeout(timer);\n save();\n }\n };\n },\n };\n shared.views.set(windowId, controller);\n return controller;\n}\n\n/**\n * Session lifecycle tracking, once per controller family. A local store is\n * one process showing every window, so it tracks them all; a remote store is\n * one window's renderer, so it tracks only the windows started here — a tab\n * moving to another process's window LEAVES and ARRIVES there.\n */\nfunction startSessions(shared: Shared, windowId: CanvasWindowId): () => void {\n const { options, onError } = shared;\n const sessions = options.sessions;\n if (!sessions) return () => undefined;\n shared.started.set(windowId, (shared.started.get(windowId) ?? 0) + 1);\n let stopped = false;\n if (!shared.sessionStop) {\n const store = options.store;\n const local = store.authority !== \"remote\";\n let tracked: Map<CanvasItemId, { item: CanvasItem; key: string; windowId: CanvasWindowId }> | null = null;\n\n const call = (fn: () => void) => {\n try {\n fn();\n } catch (error) {\n onError({ code: \"session-hook\", message: \"A canvas session hook threw.\", detail: error });\n }\n };\n\n const read = (fn: () => string | null): string | null => {\n try {\n return fn();\n } catch (error) {\n onError({ code: \"session-hook\", message: \"A canvas kind's sessionKey threw.\", detail: error });\n return null;\n }\n };\n\n let prevItems = new Set<CanvasItemId>();\n const snapshot = (state: CanvasState) => {\n const out = new Map<CanvasItemId, { item: CanvasItem; key: string; windowId: CanvasWindowId }>();\n for (const w of listCanvasWindowIds(state)) {\n if (!local && !shared.started.has(w)) continue;\n const frame = canvasWindowFrame(state, w);\n if (!frame) continue;\n for (const paneId of listPaneIds(frame.layout)) {\n for (const itemId of state.panes[paneId]?.itemIds ?? []) {\n const item = state.items[itemId];\n const hooks = item ? sessions(item.kind) : undefined;\n if (!item || !hooks) continue;\n const key = read(() => hooks.sessionKey(item));\n if (key) out.set(itemId, { item, key, windowId: w });\n }\n }\n }\n return out;\n };\n\n const sync = () => {\n const state = options.store.getState();\n if (!state.hydrated) return;\n const next = snapshot(state);\n const first = tracked === null;\n const prev = tracked ?? new Map();\n for (const [id, entry] of prev) {\n const now = next.get(id);\n if (now && now.key === entry.key) continue;\n const hooks = sessions(entry.item.kind);\n const reason: CanvasSessionDetachReason = state.items[id] && !now ? \"leave\" : \"close\";\n call(() => hooks?.onDetach?.({ item: entry.item, sessionKey: entry.key, windowId: entry.windowId, reason }));\n }\n for (const [id, entry] of next) {\n const before = prev.get(id);\n if (before && before.key === entry.key) continue;\n const hooks = sessions(entry.item.kind);\n const reason: CanvasSessionAttachReason = first ? \"restore\" : prevItems.has(id) ? \"arrive\" : \"open\";\n call(() => hooks?.onAttach?.({ item: entry.item, sessionKey: entry.key, windowId: entry.windowId, reason }));\n }\n tracked = next;\n prevItems = new Set(Object.keys(state.items) as CanvasItemId[]);\n };\n let lastState: CanvasState | null = null;\n const unsubscribe = store.subscribe(() => {\n const state = store.getState();\n if (state === lastState) return;\n lastState = state;\n sync();\n });\n sync();\n shared.sessionStop = () => {\n unsubscribe();\n for (const entry of tracked?.values() ?? []) {\n const hooks = sessions(entry.item.kind);\n call(() => hooks?.onDetach?.({ item: entry.item, sessionKey: entry.key, windowId: entry.windowId, reason: \"unmount\" }));\n }\n tracked = null;\n };\n }\n return () => {\n if (stopped) return;\n stopped = true;\n const left = (shared.started.get(windowId) ?? 1) - 1;\n if (left > 0) shared.started.set(windowId, left);\n else shared.started.delete(windowId);\n if (shared.started.size === 0 && shared.sessionStop) {\n const stop = shared.sessionStop;\n shared.sessionStop = null;\n stop();\n }\n };\n}\n","/**\n * Selectors over CanvasState. Each returns a value that is referentially\n * stable for an unchanged state, so they are safe in useSyncExternalStore and\n * in a host's useSelector. Window-scoped selectors default to the main window;\n * an unknown window reads as closed and empty.\n */\n\nimport { listPaneIds } from \"./layout\";\nimport { canvasWindowFrame, canvasWindowOfItem } from \"./reducer\";\nimport {\n CANVAS_MAIN_WINDOW,\n type CanvasExtraWindow,\n type CanvasHistoryEntry,\n type CanvasItem,\n type CanvasItemId,\n type CanvasLayoutNode,\n type CanvasPane,\n type CanvasPaneId,\n type CanvasState,\n type CanvasWindowId,\n} from \"./types\";\n\nconst frame = (s: CanvasState, w: CanvasWindowId | undefined) => canvasWindowFrame(s, w ?? CANVAS_MAIN_WINDOW);\n\nexport const selectCanvasIsOpen = (s: CanvasState, windowId?: CanvasWindowId): boolean => frame(s, windowId)?.isOpen ?? false;\nexport const selectCanvasIsFullscreen = (s: CanvasState, windowId?: CanvasWindowId): boolean => frame(s, windowId)?.isFullscreen ?? false;\n/** The width the person chose, or null while the host's layout rule decides. */\nexport const selectCanvasWidth = (s: CanvasState, windowId?: CanvasWindowId): number | null => frame(s, windowId)?.width ?? null;\nexport const selectCanvasLayout = (s: CanvasState, windowId?: CanvasWindowId): CanvasLayoutNode | null => frame(s, windowId)?.layout ?? null;\nexport const selectCanvasFocusedPaneId = (s: CanvasState, windowId?: CanvasWindowId): CanvasPaneId | null =>\n frame(s, windowId)?.focusedPaneId ?? null;\nexport const selectCanvasIsHydrated = (s: CanvasState): boolean => s.hydrated;\n/** Every item on the canvas, in every window. */\nexport const selectCanvasItemCount = (s: CanvasState): number => Object.keys(s.items).length;\n\nexport const selectCanvasPane = (s: CanvasState, paneId: CanvasPaneId): CanvasPane | undefined => s.panes[paneId];\nexport const selectCanvasItem = (s: CanvasState, itemId: CanvasItemId): CanvasItem | undefined => s.items[itemId];\n\nexport function selectCanvasPaneCount(s: CanvasState, windowId?: CanvasWindowId): number {\n const layout = frame(s, windowId)?.layout;\n return layout ? listPaneIds(layout).length : 0;\n}\n\n/** Items shown in one window. */\nexport function selectCanvasWindowItemCount(s: CanvasState, windowId?: CanvasWindowId): number {\n const layout = frame(s, windowId)?.layout;\n if (!layout) return 0;\n return listPaneIds(layout).reduce((sum, paneId) => sum + (s.panes[paneId]?.itemIds.length ?? 0), 0);\n}\n\n/** The item the person is looking at in a window's focused pane. */\nexport function selectCanvasActiveItem(s: CanvasState, windowId?: CanvasWindowId): CanvasItem | null {\n const f = frame(s, windowId);\n const pane = f ? s.panes[f.focusedPaneId] : undefined;\n return pane?.activeItemId ? (s.items[pane.activeItemId] ?? null) : null;\n}\n\nconst NO_WINDOWS: CanvasState[\"windows\"] = Object.freeze({});\n\n/** Windows other than main (second app windows and pop-outs), by id. Stable per state. */\nexport function selectCanvasWindows(s: CanvasState): CanvasState[\"windows\"] {\n return s.windows ?? NO_WINDOWS;\n}\n\n/** One extra window, or undefined (main is never in this map). */\nexport const selectCanvasExtraWindow = (s: CanvasState, windowId: CanvasWindowId): CanvasExtraWindow | undefined => s.windows?.[windowId];\n\n/** The window an item is in, or null when it is not on the canvas. */\nexport const selectCanvasWindowOfItem = canvasWindowOfItem;\n\nconst NO_HISTORY: readonly CanvasHistoryEntry[] = Object.freeze([]);\n\n/** What a tab showed before, oldest first. Stable per state. */\nexport function selectCanvasItemHistory(s: CanvasState, itemId: CanvasItemId): readonly CanvasHistoryEntry[] {\n return s.items[itemId]?.history ?? NO_HISTORY;\n}\n\n/** Whether a tab offers Back (it navigated in place). */\nexport const selectCanvasCanGoBack = (s: CanvasState, itemId: CanvasItemId): boolean => (s.items[itemId]?.history?.length ?? 0) > 0;\n","/**\n * Presentation — what a body knows about the space the canvas gives it.\n *\n * A body rendered in the canvas is told so, and told its live shape: a tall\n * narrow pane is not a wide page. Content that lays itself out in a direction\n * (a graph, a timeline, a row of cards) reads `orientation` and flows down a\n * portrait pane instead of across it. Pure data and pure functions, so a\n * desktop main process can compute the same answer for a native view.\n */\n\nexport type CanvasPresentationOrientation = \"portrait\" | \"landscape\" | \"square\";\n\nexport interface CanvasPresentation {\n /** Always \"canvas\" — a body rendered anywhere else gets no presentation at all. */\n readonly host: \"canvas\";\n /** The body's size in CSS pixels, live. */\n readonly width: number;\n readonly height: number;\n readonly orientation: CanvasPresentationOrientation;\n /** Narrower than `CANVAS_NARROW_WIDTH`: one column of content at most. */\n readonly isNarrow: boolean;\n /** The canvas is expanded to fill the space its host gives it. */\n readonly isFullscreen: boolean;\n /** How many panes the window's canvas shows right now. */\n readonly paneCount: number;\n}\n\n/** Under this width (px) a body is narrow. */\nexport const CANVAS_NARROW_WIDTH = 480;\n\n/** Width ÷ height past which a body is landscape (and under whose inverse, portrait). */\nconst SQUARE_BAND = 1.2;\n\nexport function canvasOrientation(width: number, height: number): CanvasPresentationOrientation {\n if (!(width > 0) || !(height > 0)) return \"square\";\n const ratio = width / height;\n if (ratio >= SQUARE_BAND) return \"landscape\";\n if (ratio <= 1 / SQUARE_BAND) return \"portrait\";\n return \"square\";\n}\n\nexport function canvasPresentation(input: {\n readonly width: number;\n readonly height: number;\n readonly isFullscreen: boolean;\n readonly paneCount: number;\n}): CanvasPresentation {\n const width = Math.max(0, Math.round(input.width));\n const height = Math.max(0, Math.round(input.height));\n return {\n host: \"canvas\",\n width,\n height,\n orientation: canvasOrientation(width, height),\n isNarrow: width > 0 && width < CANVAS_NARROW_WIDTH,\n isFullscreen: input.isFullscreen,\n paneCount: Math.max(1, input.paneCount),\n };\n}\n\n/**\n * Which way content with a layout direction should flow: \"vertical\" (top to\n * bottom) in a portrait or narrow body, \"horizontal\" (left to right) otherwise\n * and outside the canvas.\n */\nexport function preferredFlowDirection(presentation: CanvasPresentation | null | undefined): \"vertical\" | \"horizontal\" {\n if (!presentation) return \"horizontal\";\n if (presentation.orientation === \"portrait\") return \"vertical\";\n if (presentation.orientation === \"landscape\") return \"horizontal\";\n return presentation.isNarrow ? \"vertical\" : \"horizontal\";\n}\n","/**\n * \"Toggle or focus this kind\" — what a toolbar icon does (the desktop's\n * Terminal/Review/Browser icons, the web's quick-tool launchers):\n *\n * absent → open it (and reveal the canvas)\n * background → bring it forward: activate its tab, focus its pane, reveal\n * visible → close it (default) or put the canvas away (`whenVisible: \"hide\"`)\n *\n * \"Visible\" means: on the canvas, the active tab of its pane, and its window's\n * canvas is open. The same item in a popped-out window counts in that window.\n */\n\nimport { canvasItemId } from \"./ids\";\nimport { canvasWindowFrame, canvasWindowOfItem } from \"./reducer\";\nimport type { CanvasController } from \"./controller\";\nimport type { CanvasJson, CanvasState } from \"./types\";\n\nexport type CanvasKindVisibility = \"absent\" | \"background\" | \"visible\";\n\nexport const CANVAS_DEFAULT_KEY = \"default\";\n\n/** Stable primitive result — safe in useSyncExternalStore and useSelector. */\nexport function selectCanvasKindVisibility(state: CanvasState, kind: string, key: string = CANVAS_DEFAULT_KEY): CanvasKindVisibility {\n const itemId = canvasItemId(kind, key);\n if (!state.items[itemId]) return \"absent\";\n const windowId = canvasWindowOfItem(state, itemId);\n if (!windowId) return \"background\";\n const isOpen = canvasWindowFrame(state, windowId)?.isOpen ?? false;\n const pane = Object.values(state.panes).find((p) => p.itemIds.includes(itemId));\n return isOpen && pane?.activeItemId === itemId ? \"visible\" : \"background\";\n}\n\nexport interface ToggleKindInput {\n readonly kind: string;\n /** Default \"default\" — one instance of the kind (a toolbar tool). */\n readonly key?: string | undefined;\n /** Data for a NEW item; an existing item keeps its data. */\n readonly data?: CanvasJson | undefined;\n readonly title?: string | null | undefined;\n /** What a click does when the item is already in front. Default \"close\". */\n readonly whenVisible?: \"close\" | \"hide\" | undefined;\n}\n\n/** Returns what the item is after the click. */\nexport function toggleKind(controller: CanvasController, input: ToggleKindInput): CanvasKindVisibility {\n const key = input.key ?? CANVAS_DEFAULT_KEY;\n const itemId = canvasItemId(input.kind, key);\n const before = selectCanvasKindVisibility(controller.getState(), input.kind, key);\n\n if (before === \"visible\") {\n if ((input.whenVisible ?? \"close\") === \"close\") {\n controller.close(itemId);\n } else {\n controller.hide(canvasWindowOfItem(controller.getState(), itemId) ?? undefined);\n }\n return selectCanvasKindVisibility(controller.getState(), input.kind, key);\n }\n\n if (before === \"background\") {\n // An existing item is never re-fed data: open() activates, focuses its pane and reveals.\n controller.open({ kind: input.kind, key });\n const windowId = canvasWindowOfItem(controller.getState(), itemId);\n if (windowId) controller.show(windowId);\n return selectCanvasKindVisibility(controller.getState(), input.kind, key);\n }\n\n const opened = controller.open({\n kind: input.kind,\n key,\n ...(input.data !== undefined ? { data: input.data } : {}),\n ...(input.title !== undefined ? { title: input.title } : {}),\n });\n return opened ? selectCanvasKindVisibility(controller.getState(), input.kind, key) : \"absent\";\n}\n"],"mappings":"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","names":["frame","focused","same","out","frame","frame"]}
|