@ai-matrx/canvas 0.0.0-bootstrap.0 → 0.1.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 +11 -0
- package/LICENSE +21 -0
- package/README.md +20 -2
- package/dist/index.cjs +758 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +380 -0
- package/dist/index.d.ts +380 -0
- package/dist/index.js +735 -0
- package/dist/index.js.map +1 -0
- package/dist/react.cjs +1477 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +424 -0
- package/dist/react.d.ts +424 -0
- package/dist/react.js +1458 -0
- package/dist/react.js.map +1 -0
- package/dist/styles.css +451 -0
- package/dist/tokens.css +49 -0
- package/package.json +85 -6
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/core/types.ts","../src/core/ids.ts","../src/core/layout.ts","../src/core/reducer.ts","../src/core/store.ts","../src/core/persistence.ts","../src/core/controller.ts","../src/core/selectors.ts"],"sourcesContent":["/**\n * @ai-matrx/canvas — framework-free core.\n *\n * The state, reducer, identity rules, persistence and controller. No React,\n * no DOM at import time. The React layer lives at `@ai-matrx/canvas/react`.\n */\n\nexport * from \"./core/types\";\nexport { canvasItemId, parseCanvasItemId, findNonJson, isCanvasJson } from \"./core/ids\";\nexport { listPaneIds, normalizeSizes } from \"./core/layout\";\nexport {\n canvasReducer,\n canvasActions,\n createInitialCanvasState,\n isCanvasAction,\n sanitizeCanvasSnapshot,\n type CanvasAction,\n} from \"./core/reducer\";\nexport {\n createCanvasStore,\n bindCanvasToReduxStore,\n type CanvasStoreBinding,\n type ReduxStoreLike,\n} from \"./core/store\";\nexport {\n createLocalStorageCanvasPersistence,\n toPersistableSnapshot,\n CANVAS_STORAGE_KEY,\n type CanvasPersistencePort,\n} from \"./core/persistence\";\nexport {\n createCanvasController,\n consoleCanvasErrorSink,\n type CanvasController,\n type CanvasControllerOptions,\n type CanvasErrorReport,\n type CanvasErrorSink,\n} from \"./core/controller\";\nexport * from \"./core/selectors\";\n","/**\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;\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\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\nexport interface CanvasState {\n readonly version: 1;\n readonly isOpen: boolean;\n readonly isFullscreen: boolean;\n /** Column width in CSS pixels (desktop). */\n readonly width: number;\n readonly layout: CanvasLayoutNode;\n readonly panes: { readonly [paneId: string]: CanvasPane };\n readonly items: { readonly [itemId: string]: CanvasItem };\n readonly focusedPaneId: CanvasPaneId;\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 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","import type { CanvasItemId, CanvasJson, CanvasPaneId, CanvasSplitId } 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 * 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): CanvasLayoutNode {\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: [0.5, 0.5],\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 / 2, share / 2);\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),\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 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`) or runs inside the package's own standalone\n * store with 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.\n */\n\nimport { canvasItemId, paneIdFromSeq, splitIdFromSeq } from \"./ids\";\nimport { isValidLayout, listPaneIds, normalizeSizes, removePane, resizeSplit, splitPane } from \"./layout\";\nimport {\n CANVAS_DEFAULT_WIDTH,\n CANVAS_MIN_WIDTH,\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} from \"./types\";\n\nconst P = \"matrxCanvas/\";\n\nexport type CanvasAction =\n | { type: `${typeof P}open`; payload: CanvasOpenInput & { now: number } }\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 } }\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 } }\n | { type: `${typeof P}toggle` }\n | { type: `${typeof P}setFullscreen`; payload: { fullscreen: boolean } }\n | { type: `${typeof P}setWidth`; payload: { width: number } }\n | { type: `${typeof P}hydrate`; payload: { snapshot: CanvasState | null } }\n | { type: `${typeof P}reset` };\n\nexport const canvasActions = {\n open: (input: CanvasOpenInput): CanvasAction => ({ type: `${P}open`, payload: { ...input, now: Date.now() } }),\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 splitPane: (paneId: CanvasPaneId, orientation: CanvasOrientation, moveItemId?: CanvasItemId): CanvasAction => ({\n type: `${P}splitPane`,\n payload: { paneId, orientation, moveItemId },\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): CanvasAction => ({ type: `${P}setOpen`, payload: { open } }),\n toggle: (): CanvasAction => ({ type: `${P}toggle` }),\n setFullscreen: (fullscreen: boolean): CanvasAction => ({ type: `${P}setFullscreen`, payload: { fullscreen } }),\n setWidth: (width: number): CanvasAction => ({ type: `${P}setWidth`, payload: { width } }),\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: CANVAS_DEFAULT_WIDTH,\n layout: { type: \"pane\", paneId },\n panes: { [paneId]: { id: paneId, itemIds: [], activeItemId: null } },\n items: {},\n focusedPaneId: paneId,\n seq: 1,\n hydrated: false,\n };\n}\n\n// ── 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\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 layout = removePane(state.layout, paneId);\n if (!layout) return state; // never remove the last pane\n const panes = { ...state.panes };\n delete panes[paneId];\n const focusedPaneId = state.focusedPaneId === paneId ? (listPaneIds(layout)[0] ?? state.focusedPaneId) : state.focusedPaneId;\n return { ...state, layout, panes, focusedPaneId };\n}\n\nfunction addSplit(state: CanvasState, paneId: CanvasPaneId, orientation: CanvasOrientation): { state: CanvasState; newPaneId: CanvasPaneId } {\n const seq = state.seq + 1;\n const newPaneId = paneIdFromSeq(seq);\n const layout = splitPane(state.layout, paneId, newPaneId, orientation, splitIdFromSeq(seq));\n return {\n newPaneId,\n state: {\n ...state,\n seq,\n layout,\n panes: { ...state.panes, [newPaneId]: { id: newPaneId, itemIds: [], activeItemId: null } },\n focusedPaneId: newPaneId,\n },\n };\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\nfunction clampWidth(width: number): number {\n return Number.isFinite(width) ? Math.max(CANVAS_MIN_WIDTH, Math.round(width)) : CANVAS_DEFAULT_WIDTH;\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.\n */\nexport function sanitizeCanvasSnapshot(raw: unknown): CanvasState | null {\n if (!raw || typeof raw !== \"object\") return null;\n const s = raw as Partial<CanvasState>;\n if (s.version !== 1 || !s.panes || !s.items || !s.layout) return null;\n const paneIds = new Set(Object.keys(s.panes));\n if (!isValidLayout(s.layout, paneIds)) return null;\n const layoutPanes = new Set<string>(listPaneIds(s.layout));\n if (layoutPanes.size !== paneIds.size) return null;\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 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);\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 focused = s.focusedPaneId && paneIds.has(s.focusedPaneId) ? s.focusedPaneId : listPaneIds(s.layout)[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 seq = Math.max(typeof s.seq === \"number\" && Number.isFinite(s.seq) ? s.seq : 0, highestIdNumber(layout));\n return {\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: clampWidth(typeof s.width === \"number\" ? s.width : CANVAS_DEFAULT_WIDTH),\n layout,\n panes,\n items,\n focusedPaneId: focused,\n seq,\n hydrated: true,\n };\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 switch (action.type) {\n case `${P}open`: {\n const { kind, key, title, data, target = \"focused\", reveal = true, activate = true, now } = action.payload;\n const itemId = canvasItemId(kind, key);\n const existing = state.items[itemId];\n let next = state;\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 && activate) next = { ...withPane(next, { ...pane, activeItemId: itemId }), focusedPaneId: pane.id };\n if (!pane) next = insertInto(next, next.focusedPaneId, itemId, true);\n } else {\n const item: CanvasItem = { id: itemId, kind, key, title: title ?? null, data: data ?? null, openedAt: now, updatedAt: now };\n next = { ...next, items: { ...next.items, [itemId]: item } };\n let paneId: CanvasPaneId = next.focusedPaneId;\n if (typeof target === \"object\" && next.panes[target.paneId]) {\n paneId = target.paneId;\n } else if (target === \"split-right\" || target === \"split-down\") {\n const split = addSplit(next, next.focusedPaneId, target === \"split-right\" ? \"horizontal\" : \"vertical\");\n next = split.state;\n paneId = split.newPaneId;\n }\n next = insertInto(next, paneId, itemId, activate);\n if (activate) next = { ...next, focusedPaneId: paneId };\n }\n return reveal ? { ...next, 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 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 the only one.\n if (pane && next.panes[pane.id]?.itemIds.length === 0) next = dropPane(next, pane.id);\n return next;\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 { ...withPane(state, { ...pane, activeItemId: action.payload.itemId }), focusedPaneId: pane.id };\n }\n case `${P}focusPane`:\n return state.panes[action.payload.paneId] ? { ...state, focusedPaneId: action.payload.paneId } : state;\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 state.focusedPaneId === toPaneId ? state : { ...state, focusedPaneId: toPaneId };\n let next = from.id === toPaneId ? state : detachItem(state, itemId);\n next = insertInto(next, toPaneId, itemId, true, index);\n next = { ...next, focusedPaneId: toPaneId };\n if (from.id !== toPaneId && next.panes[from.id]?.itemIds.length === 0) next = dropPane(next, from.id);\n return next;\n }\n case `${P}splitPane`: {\n const { paneId, orientation, moveItemId } = action.payload;\n const pane = state.panes[paneId];\n if (!pane) return state;\n const split = addSplit(state, paneId, orientation);\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 if (!pane) return state;\n const onlyPane = listPaneIds(state.layout).length === 1;\n // Closing the last pane puts the canvas away and KEEPS its tabs — the\n // toggle brings everything back exactly as it was.\n if (onlyPane) return { ...state, isOpen: false, isFullscreen: false };\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 return { ...state, layout: resizeSplit(state.layout, action.payload.splitId, action.payload.sizes) };\n case `${P}setOpen`:\n return action.payload.open === state.isOpen\n ? state\n : { ...state, isOpen: action.payload.open, isFullscreen: action.payload.open ? state.isFullscreen : false };\n case `${P}toggle`:\n return { ...state, isOpen: !state.isOpen, isFullscreen: state.isOpen ? false : state.isFullscreen };\n case `${P}setFullscreen`:\n return { ...state, isFullscreen: action.payload.fullscreen, isOpen: action.payload.fullscreen ? true : state.isOpen };\n case `${P}setWidth`:\n return { ...state, width: clampWidth(action.payload.width) };\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\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 * 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 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\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/** Builds the snapshot that is actually written: only restorable items. */\nexport function toPersistableSnapshot(\n state: CanvasState,\n isRestorable: (kind: string) => boolean,\n): CanvasState {\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 * 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.\n *\n * Nothing fails silently: a refused open (non-JSON data, unknown kind) is\n * reported through the error sink and returns false.\n */\n\nimport { canvasActions, sanitizeCanvasSnapshot, type CanvasAction } from \"./reducer\";\nimport { canvasItemId, findNonJson } from \"./ids\";\nimport { toPersistableSnapshot, type CanvasPersistencePort } from \"./persistence\";\nimport type { CanvasStoreBinding } from \"./store\";\nimport type {\n CanvasItemId,\n CanvasJson,\n CanvasOpenInput,\n CanvasOrientation,\n CanvasPaneId,\n CanvasSplitId,\n CanvasState,\n} from \"./types\";\n\nexport interface CanvasErrorReport {\n readonly code: \"non-json-data\" | \"unknown-kind\" | \"persistence-load\" | \"persistence-save\";\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\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}\n\nexport interface CanvasController {\n readonly store: CanvasStoreBinding;\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 splitPane(paneId: CanvasPaneId, orientation: CanvasOrientation, moveItemId?: CanvasItemId): void;\n closePane(paneId: CanvasPaneId): void;\n resizeSplit(splitId: CanvasSplitId, sizes: readonly number[]): void;\n show(): void;\n hide(): void;\n toggle(): void;\n setFullscreen(fullscreen: boolean): void;\n setWidth(width: number): void;\n /** Is this exact thing on the canvas right now? */\n has(kind: string, key: string): boolean;\n /**\n * Is a canvas column on screen? A store can exist in a layout that shows no\n * column (a kiosk, a meeting stage); opening there must be refused aloud.\n */\n isPresented(): boolean;\n /** Called by a column on mount; returns the unmount callback. */\n registerPresentation(): () => void;\n subscribePresentation(listener: () => void): () => void;\n /** Loads the persisted snapshot and starts autosave. Returns a disposer. */\n start(): () => void;\n}\n\nexport function createCanvasController(options: CanvasControllerOptions): CanvasController {\n const { store, persistence = null } = options;\n const onError = options.onError ?? consoleCanvasErrorSink;\n const isRestorable = options.isRestorable ?? (() => true);\n const dispatch = (action: CanvasAction) => store.dispatch(action);\n\n let presentations = 0;\n const presentationListeners = new Set<() => void>();\n const notifyPresentation = () => {\n for (const listener of [...presentationListeners]) listener();\n };\n\n const controller: CanvasController = {\n store,\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 dispatch(canvasActions.open(input));\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)),\n closePane: (paneId) => dispatch(canvasActions.closePane(paneId)),\n resizeSplit: (splitId, sizes) => dispatch(canvasActions.resizeSplit(splitId, sizes)),\n show: () => dispatch(canvasActions.setOpen(true)),\n hide: () => dispatch(canvasActions.setOpen(false)),\n toggle: () => dispatch(canvasActions.toggle()),\n setFullscreen: (fullscreen) => dispatch(canvasActions.setFullscreen(fullscreen)),\n setWidth: (width) => dispatch(canvasActions.setWidth(width)),\n has: (kind, key) => canvasItemId(kind, key) in store.getState().items,\n isPresented: () => presentations > 0,\n registerPresentation() {\n presentations += 1;\n notifyPresentation();\n let done = false;\n return () => {\n if (done) return;\n done = true;\n presentations -= 1;\n notifyPresentation();\n };\n },\n subscribePresentation(listener) {\n presentationListeners.add(listener);\n return () => 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\n const save = () => {\n timer = null;\n const state = store.getState();\n if (!persistence || !state.hydrated || state === lastSaved) return;\n lastSaved = state;\n try {\n void Promise.resolve(persistence.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 (!persistence || 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 (store.getState().hydrated) {\n // Already hydrated (e.g. a second provider over the same store).\n } else if (!persistence) {\n dispatch(canvasActions.hydrate(null));\n } else {\n Promise.resolve()\n .then(() => persistence.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 return () => {\n disposed = true;\n unsubscribe();\n if (timer) {\n clearTimeout(timer);\n save();\n }\n };\n },\n };\n return controller;\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.\n */\n\nimport { listPaneIds } from \"./layout\";\nimport type { CanvasItem, CanvasItemId, CanvasPane, CanvasPaneId, CanvasState } from \"./types\";\n\nexport const selectCanvasIsOpen = (s: CanvasState): boolean => s.isOpen;\nexport const selectCanvasIsFullscreen = (s: CanvasState): boolean => s.isFullscreen;\nexport const selectCanvasWidth = (s: CanvasState): number => s.width;\nexport const selectCanvasLayout = (s: CanvasState) => s.layout;\nexport const selectCanvasFocusedPaneId = (s: CanvasState): CanvasPaneId => s.focusedPaneId;\nexport const selectCanvasIsHydrated = (s: CanvasState): boolean => s.hydrated;\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): number {\n return listPaneIds(s.layout).length;\n}\n\n/** The item the person is looking at in the focused pane. */\nexport function selectCanvasActiveItem(s: CanvasState): CanvasItem | null {\n const pane = s.panes[s.focusedPaneId];\n return pane?.activeItemId ? (s.items[pane.activeItemId] ?? null) : null;\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ai-matrx/canvas — core types.
|
|
3
|
+
*
|
|
4
|
+
* The canvas is ONE docked column on the right edge of an application. It holds
|
|
5
|
+
* panes; panes hold tabs; every tab is one CanvasItem. A CanvasItem is
|
|
6
|
+
* identified by `kind` + `key`, so opening the same thing twice always lands on
|
|
7
|
+
* the existing tab instead of creating a duplicate.
|
|
8
|
+
*
|
|
9
|
+
* Everything in CanvasState is plain JSON: it lives in the host's Redux store
|
|
10
|
+
* (or the package's own standalone store), it is persisted between sessions,
|
|
11
|
+
* and it can be inspected. No functions, no class instances, no React nodes.
|
|
12
|
+
*/
|
|
13
|
+
/** Any value that survives JSON.stringify → JSON.parse unchanged. */
|
|
14
|
+
type CanvasJson = string | number | boolean | null | readonly CanvasJson[] | {
|
|
15
|
+
readonly [key: string]: CanvasJson | undefined;
|
|
16
|
+
};
|
|
17
|
+
declare const itemIdBrand: unique symbol;
|
|
18
|
+
declare const paneIdBrand: unique symbol;
|
|
19
|
+
declare const splitIdBrand: unique symbol;
|
|
20
|
+
/** `${kind}::${key}` — the identity of one thing on the canvas. */
|
|
21
|
+
type CanvasItemId = string & {
|
|
22
|
+
readonly [itemIdBrand]: true;
|
|
23
|
+
};
|
|
24
|
+
type CanvasPaneId = string & {
|
|
25
|
+
readonly [paneIdBrand]: true;
|
|
26
|
+
};
|
|
27
|
+
type CanvasSplitId = string & {
|
|
28
|
+
readonly [splitIdBrand]: true;
|
|
29
|
+
};
|
|
30
|
+
interface CanvasItem {
|
|
31
|
+
readonly id: CanvasItemId;
|
|
32
|
+
/** Registered kind id (see `registerCanvasKind`). */
|
|
33
|
+
readonly kind: string;
|
|
34
|
+
/** Stable key inside the kind — an artifact id, a conversation id, "default". */
|
|
35
|
+
readonly key: string;
|
|
36
|
+
/** Explicit tab title. `null` ⇒ the kind's `title(data)` or its label. */
|
|
37
|
+
readonly title: string | null;
|
|
38
|
+
readonly data: CanvasJson;
|
|
39
|
+
readonly openedAt: number;
|
|
40
|
+
readonly updatedAt: number;
|
|
41
|
+
}
|
|
42
|
+
interface CanvasPane {
|
|
43
|
+
readonly id: CanvasPaneId;
|
|
44
|
+
readonly itemIds: readonly CanvasItemId[];
|
|
45
|
+
readonly activeItemId: CanvasItemId | null;
|
|
46
|
+
}
|
|
47
|
+
/** "horizontal" = children side by side; "vertical" = children stacked. */
|
|
48
|
+
type CanvasOrientation = "horizontal" | "vertical";
|
|
49
|
+
type CanvasLayoutNode = {
|
|
50
|
+
readonly type: "pane";
|
|
51
|
+
readonly paneId: CanvasPaneId;
|
|
52
|
+
} | {
|
|
53
|
+
readonly type: "split";
|
|
54
|
+
readonly id: CanvasSplitId;
|
|
55
|
+
readonly orientation: CanvasOrientation;
|
|
56
|
+
readonly children: readonly CanvasLayoutNode[];
|
|
57
|
+
/** Fractions, one per child, summing to 1. */
|
|
58
|
+
readonly sizes: readonly number[];
|
|
59
|
+
};
|
|
60
|
+
interface CanvasState {
|
|
61
|
+
readonly version: 1;
|
|
62
|
+
readonly isOpen: boolean;
|
|
63
|
+
readonly isFullscreen: boolean;
|
|
64
|
+
/** Column width in CSS pixels (desktop). */
|
|
65
|
+
readonly width: number;
|
|
66
|
+
readonly layout: CanvasLayoutNode;
|
|
67
|
+
readonly panes: {
|
|
68
|
+
readonly [paneId: string]: CanvasPane;
|
|
69
|
+
};
|
|
70
|
+
readonly items: {
|
|
71
|
+
readonly [itemId: string]: CanvasItem;
|
|
72
|
+
};
|
|
73
|
+
readonly focusedPaneId: CanvasPaneId;
|
|
74
|
+
/** Monotonic counter for minting pane/split ids — keeps the reducer pure. */
|
|
75
|
+
readonly seq: number;
|
|
76
|
+
/** True once a persisted snapshot was applied (or there was none). */
|
|
77
|
+
readonly hydrated: boolean;
|
|
78
|
+
}
|
|
79
|
+
/** Where a newly opened item goes. Existing items never move on open. */
|
|
80
|
+
type CanvasOpenTarget = "focused" | "split-right" | "split-down" | {
|
|
81
|
+
readonly paneId: CanvasPaneId;
|
|
82
|
+
};
|
|
83
|
+
interface CanvasOpenInput {
|
|
84
|
+
readonly kind: string;
|
|
85
|
+
readonly key: string;
|
|
86
|
+
readonly title?: string | null | undefined;
|
|
87
|
+
readonly data?: CanvasJson | undefined;
|
|
88
|
+
readonly target?: CanvasOpenTarget | undefined;
|
|
89
|
+
/** Reveal the canvas when it is put away. Default true. */
|
|
90
|
+
readonly reveal?: boolean | undefined;
|
|
91
|
+
/** Make the item the pane's active tab. Default true. */
|
|
92
|
+
readonly activate?: boolean | undefined;
|
|
93
|
+
}
|
|
94
|
+
declare const CANVAS_MIN_WIDTH = 360;
|
|
95
|
+
declare const CANVAS_DEFAULT_WIDTH = 640;
|
|
96
|
+
declare const CANVAS_MIN_SPLIT_FRACTION = 0.12;
|
|
97
|
+
|
|
98
|
+
declare function canvasItemId(kind: string, key: string): CanvasItemId;
|
|
99
|
+
declare function parseCanvasItemId(id: CanvasItemId): {
|
|
100
|
+
kind: string;
|
|
101
|
+
key: string;
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* Returns the path of the first value that is NOT plain JSON, or null when the
|
|
105
|
+
* whole value is JSON. Functions, class instances, Dates, Maps, NaN and
|
|
106
|
+
* Infinity all fail — they would silently vanish or change on persist.
|
|
107
|
+
*/
|
|
108
|
+
declare function findNonJson(value: unknown, path?: string): string | null;
|
|
109
|
+
declare function isCanvasJson(value: unknown): value is CanvasJson;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Pure helpers over the canvas layout tree. Every function returns a new tree
|
|
113
|
+
* and never mutates its input.
|
|
114
|
+
*/
|
|
115
|
+
|
|
116
|
+
declare function listPaneIds(node: CanvasLayoutNode): CanvasPaneId[];
|
|
117
|
+
/** Renormalizes to sum 1; falls back to even sizes for garbage input. */
|
|
118
|
+
declare function normalizeSizes(sizes: readonly number[], count: number): number[];
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* THE canvas reducer. Plain Redux-compatible reducer + action creators with no
|
|
122
|
+
* Redux Toolkit dependency, so it mounts in a host's RTK store
|
|
123
|
+
* (`canvasHost: canvasReducer`) or runs inside the package's own standalone
|
|
124
|
+
* store with identical behaviour.
|
|
125
|
+
*
|
|
126
|
+
* Identity law: an item is `kind::key`. Opening an item that is already on the
|
|
127
|
+
* canvas never duplicates it — it refreshes its data/title, activates its tab
|
|
128
|
+
* and focuses its pane, wherever that pane is.
|
|
129
|
+
*/
|
|
130
|
+
|
|
131
|
+
declare const P = "matrxCanvas/";
|
|
132
|
+
type CanvasAction = {
|
|
133
|
+
type: `${typeof P}open`;
|
|
134
|
+
payload: CanvasOpenInput & {
|
|
135
|
+
now: number;
|
|
136
|
+
};
|
|
137
|
+
} | {
|
|
138
|
+
type: `${typeof P}update`;
|
|
139
|
+
payload: {
|
|
140
|
+
itemId: CanvasItemId;
|
|
141
|
+
data?: CanvasJson | undefined;
|
|
142
|
+
title?: string | null | undefined;
|
|
143
|
+
now: number;
|
|
144
|
+
};
|
|
145
|
+
} | {
|
|
146
|
+
type: `${typeof P}rekey`;
|
|
147
|
+
payload: {
|
|
148
|
+
itemId: CanvasItemId;
|
|
149
|
+
key: string;
|
|
150
|
+
};
|
|
151
|
+
} | {
|
|
152
|
+
type: `${typeof P}closeItem`;
|
|
153
|
+
payload: {
|
|
154
|
+
itemId: CanvasItemId;
|
|
155
|
+
};
|
|
156
|
+
} | {
|
|
157
|
+
type: `${typeof P}closeOthers`;
|
|
158
|
+
payload: {
|
|
159
|
+
itemId: CanvasItemId;
|
|
160
|
+
};
|
|
161
|
+
} | {
|
|
162
|
+
type: `${typeof P}activate`;
|
|
163
|
+
payload: {
|
|
164
|
+
itemId: CanvasItemId;
|
|
165
|
+
};
|
|
166
|
+
} | {
|
|
167
|
+
type: `${typeof P}focusPane`;
|
|
168
|
+
payload: {
|
|
169
|
+
paneId: CanvasPaneId;
|
|
170
|
+
};
|
|
171
|
+
} | {
|
|
172
|
+
type: `${typeof P}moveItem`;
|
|
173
|
+
payload: {
|
|
174
|
+
itemId: CanvasItemId;
|
|
175
|
+
toPaneId: CanvasPaneId;
|
|
176
|
+
index?: number | undefined;
|
|
177
|
+
};
|
|
178
|
+
} | {
|
|
179
|
+
type: `${typeof P}splitPane`;
|
|
180
|
+
payload: {
|
|
181
|
+
paneId: CanvasPaneId;
|
|
182
|
+
orientation: CanvasOrientation;
|
|
183
|
+
moveItemId?: CanvasItemId | undefined;
|
|
184
|
+
};
|
|
185
|
+
} | {
|
|
186
|
+
type: `${typeof P}closePane`;
|
|
187
|
+
payload: {
|
|
188
|
+
paneId: CanvasPaneId;
|
|
189
|
+
};
|
|
190
|
+
} | {
|
|
191
|
+
type: `${typeof P}resizeSplit`;
|
|
192
|
+
payload: {
|
|
193
|
+
splitId: CanvasSplitId;
|
|
194
|
+
sizes: readonly number[];
|
|
195
|
+
};
|
|
196
|
+
} | {
|
|
197
|
+
type: `${typeof P}setOpen`;
|
|
198
|
+
payload: {
|
|
199
|
+
open: boolean;
|
|
200
|
+
};
|
|
201
|
+
} | {
|
|
202
|
+
type: `${typeof P}toggle`;
|
|
203
|
+
} | {
|
|
204
|
+
type: `${typeof P}setFullscreen`;
|
|
205
|
+
payload: {
|
|
206
|
+
fullscreen: boolean;
|
|
207
|
+
};
|
|
208
|
+
} | {
|
|
209
|
+
type: `${typeof P}setWidth`;
|
|
210
|
+
payload: {
|
|
211
|
+
width: number;
|
|
212
|
+
};
|
|
213
|
+
} | {
|
|
214
|
+
type: `${typeof P}hydrate`;
|
|
215
|
+
payload: {
|
|
216
|
+
snapshot: CanvasState | null;
|
|
217
|
+
};
|
|
218
|
+
} | {
|
|
219
|
+
type: `${typeof P}reset`;
|
|
220
|
+
};
|
|
221
|
+
declare const canvasActions: {
|
|
222
|
+
readonly open: (input: CanvasOpenInput) => CanvasAction;
|
|
223
|
+
readonly update: (itemId: CanvasItemId, patch: {
|
|
224
|
+
data?: CanvasJson | undefined;
|
|
225
|
+
title?: string | null | undefined;
|
|
226
|
+
}) => CanvasAction;
|
|
227
|
+
/** Gives an item a new identity in place (e.g. a draft that was just saved and now has an id). */
|
|
228
|
+
readonly rekey: (itemId: CanvasItemId, key: string) => CanvasAction;
|
|
229
|
+
readonly closeItem: (itemId: CanvasItemId) => CanvasAction;
|
|
230
|
+
readonly closeOthers: (itemId: CanvasItemId) => CanvasAction;
|
|
231
|
+
readonly activate: (itemId: CanvasItemId) => CanvasAction;
|
|
232
|
+
readonly focusPane: (paneId: CanvasPaneId) => CanvasAction;
|
|
233
|
+
readonly moveItem: (itemId: CanvasItemId, toPaneId: CanvasPaneId, index?: number) => CanvasAction;
|
|
234
|
+
readonly splitPane: (paneId: CanvasPaneId, orientation: CanvasOrientation, moveItemId?: CanvasItemId) => CanvasAction;
|
|
235
|
+
readonly closePane: (paneId: CanvasPaneId) => CanvasAction;
|
|
236
|
+
readonly resizeSplit: (splitId: CanvasSplitId, sizes: readonly number[]) => CanvasAction;
|
|
237
|
+
readonly setOpen: (open: boolean) => CanvasAction;
|
|
238
|
+
readonly toggle: () => CanvasAction;
|
|
239
|
+
readonly setFullscreen: (fullscreen: boolean) => CanvasAction;
|
|
240
|
+
readonly setWidth: (width: number) => CanvasAction;
|
|
241
|
+
readonly hydrate: (snapshot: CanvasState | null) => CanvasAction;
|
|
242
|
+
readonly reset: () => CanvasAction;
|
|
243
|
+
};
|
|
244
|
+
declare function isCanvasAction(action: unknown): action is CanvasAction;
|
|
245
|
+
declare function createInitialCanvasState(): CanvasState;
|
|
246
|
+
/**
|
|
247
|
+
* Validates a persisted snapshot. Anything malformed is dropped back to the
|
|
248
|
+
* initial state rather than half-applied — a corrupt layout must never crash
|
|
249
|
+
* the shell.
|
|
250
|
+
*/
|
|
251
|
+
declare function sanitizeCanvasSnapshot(raw: unknown): CanvasState | null;
|
|
252
|
+
declare function canvasReducer(state: CanvasState | undefined, action: {
|
|
253
|
+
type: string;
|
|
254
|
+
}): CanvasState;
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* The store seam. The canvas never owns a second copy of its state: it reads
|
|
258
|
+
* and writes through a CanvasStoreBinding.
|
|
259
|
+
*
|
|
260
|
+
* - A host WITH Redux mounts `canvasReducer` in its root reducer and binds it:
|
|
261
|
+
* bindCanvasToReduxStore(store, (root) => root.canvasHost)
|
|
262
|
+
* - A host WITHOUT Redux (a Vite tool, an Electron window) calls
|
|
263
|
+
* createCanvasStore()
|
|
264
|
+
* which runs the very same reducer in a tiny standalone store.
|
|
265
|
+
*/
|
|
266
|
+
|
|
267
|
+
interface CanvasStoreBinding {
|
|
268
|
+
getState(): CanvasState;
|
|
269
|
+
dispatch(action: CanvasAction): void;
|
|
270
|
+
subscribe(listener: () => void): () => void;
|
|
271
|
+
}
|
|
272
|
+
declare function createCanvasStore(initial?: CanvasState): CanvasStoreBinding;
|
|
273
|
+
/** The minimum of a Redux store the canvas needs. */
|
|
274
|
+
interface ReduxStoreLike<TRoot> {
|
|
275
|
+
getState(): TRoot;
|
|
276
|
+
dispatch(action: CanvasAction): unknown;
|
|
277
|
+
subscribe(listener: () => void): () => void;
|
|
278
|
+
}
|
|
279
|
+
declare function bindCanvasToReduxStore<TRoot>(store: ReduxStoreLike<TRoot>, select: (root: TRoot) => CanvasState): CanvasStoreBinding;
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Remembering the canvas between sessions — a table stake, never optional.
|
|
283
|
+
*
|
|
284
|
+
* The default port writes to localStorage under a versioned key. Items whose
|
|
285
|
+
* kind opts out (`restore: false`, e.g. a live session that cannot come back)
|
|
286
|
+
* are dropped from the snapshot, and panes they leave empty are dropped too.
|
|
287
|
+
*/
|
|
288
|
+
|
|
289
|
+
interface CanvasPersistencePort {
|
|
290
|
+
load(): CanvasState | null | Promise<CanvasState | null>;
|
|
291
|
+
save(snapshot: CanvasState): void | Promise<void>;
|
|
292
|
+
}
|
|
293
|
+
declare const CANVAS_STORAGE_KEY = "ai-matrx.canvas.v1";
|
|
294
|
+
declare function createLocalStorageCanvasPersistence(key?: string, storage?: Pick<Storage, "getItem" | "setItem"> | null): CanvasPersistencePort;
|
|
295
|
+
/** Builds the snapshot that is actually written: only restorable items. */
|
|
296
|
+
declare function toPersistableSnapshot(state: CanvasState, isRestorable: (kind: string) => boolean): CanvasState;
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* The canvas controller: the ONE imperative API every caller uses. It wraps a
|
|
300
|
+
* store binding, validates what callers hand it (so the reducer stays pure and
|
|
301
|
+
* trusting), and owns hydration + autosave.
|
|
302
|
+
*
|
|
303
|
+
* Nothing fails silently: a refused open (non-JSON data, unknown kind) is
|
|
304
|
+
* reported through the error sink and returns false.
|
|
305
|
+
*/
|
|
306
|
+
|
|
307
|
+
interface CanvasErrorReport {
|
|
308
|
+
readonly code: "non-json-data" | "unknown-kind" | "persistence-load" | "persistence-save";
|
|
309
|
+
readonly message: string;
|
|
310
|
+
readonly detail?: unknown;
|
|
311
|
+
}
|
|
312
|
+
type CanvasErrorSink = (report: CanvasErrorReport) => void;
|
|
313
|
+
declare const consoleCanvasErrorSink: CanvasErrorSink;
|
|
314
|
+
interface CanvasControllerOptions {
|
|
315
|
+
readonly store: CanvasStoreBinding;
|
|
316
|
+
readonly persistence?: CanvasPersistencePort | null | undefined;
|
|
317
|
+
/** Kinds that may not come back after a reload. Default: every kind restores. */
|
|
318
|
+
readonly isRestorable?: ((kind: string) => boolean) | undefined;
|
|
319
|
+
/** When given, opens of an unregistered kind are refused and reported. */
|
|
320
|
+
readonly isKnownKind?: ((kind: string) => boolean) | undefined;
|
|
321
|
+
readonly onError?: CanvasErrorSink | undefined;
|
|
322
|
+
readonly saveDelayMs?: number | undefined;
|
|
323
|
+
/**
|
|
324
|
+
* Whether a remembered "open" may be restored right now. A host returns
|
|
325
|
+
* false where an open canvas would take the whole screen (a phone).
|
|
326
|
+
*/
|
|
327
|
+
readonly mayRestoreOpen?: (() => boolean) | undefined;
|
|
328
|
+
}
|
|
329
|
+
interface CanvasController {
|
|
330
|
+
readonly store: CanvasStoreBinding;
|
|
331
|
+
getState(): CanvasState;
|
|
332
|
+
open(input: CanvasOpenInput): CanvasItemId | null;
|
|
333
|
+
update(itemId: CanvasItemId, patch: {
|
|
334
|
+
data?: CanvasJson | undefined;
|
|
335
|
+
title?: string | null | undefined;
|
|
336
|
+
}): boolean;
|
|
337
|
+
/** Gives an item a new identity in place (a draft that was saved and now has a durable id). */
|
|
338
|
+
rekey(itemId: CanvasItemId, key: string): CanvasItemId | null;
|
|
339
|
+
close(itemId: CanvasItemId): void;
|
|
340
|
+
closeOthers(itemId: CanvasItemId): void;
|
|
341
|
+
activate(itemId: CanvasItemId): void;
|
|
342
|
+
focusPane(paneId: CanvasPaneId): void;
|
|
343
|
+
moveItem(itemId: CanvasItemId, toPaneId: CanvasPaneId, index?: number): void;
|
|
344
|
+
splitPane(paneId: CanvasPaneId, orientation: CanvasOrientation, moveItemId?: CanvasItemId): void;
|
|
345
|
+
closePane(paneId: CanvasPaneId): void;
|
|
346
|
+
resizeSplit(splitId: CanvasSplitId, sizes: readonly number[]): void;
|
|
347
|
+
show(): void;
|
|
348
|
+
hide(): void;
|
|
349
|
+
toggle(): void;
|
|
350
|
+
setFullscreen(fullscreen: boolean): void;
|
|
351
|
+
setWidth(width: number): void;
|
|
352
|
+
/** Is this exact thing on the canvas right now? */
|
|
353
|
+
has(kind: string, key: string): boolean;
|
|
354
|
+
/**
|
|
355
|
+
* Is a canvas column on screen? A store can exist in a layout that shows no
|
|
356
|
+
* column (a kiosk, a meeting stage); opening there must be refused aloud.
|
|
357
|
+
*/
|
|
358
|
+
isPresented(): boolean;
|
|
359
|
+
/** Called by a column on mount; returns the unmount callback. */
|
|
360
|
+
registerPresentation(): () => void;
|
|
361
|
+
subscribePresentation(listener: () => void): () => void;
|
|
362
|
+
/** Loads the persisted snapshot and starts autosave. Returns a disposer. */
|
|
363
|
+
start(): () => void;
|
|
364
|
+
}
|
|
365
|
+
declare function createCanvasController(options: CanvasControllerOptions): CanvasController;
|
|
366
|
+
|
|
367
|
+
declare const selectCanvasIsOpen: (s: CanvasState) => boolean;
|
|
368
|
+
declare const selectCanvasIsFullscreen: (s: CanvasState) => boolean;
|
|
369
|
+
declare const selectCanvasWidth: (s: CanvasState) => number;
|
|
370
|
+
declare const selectCanvasLayout: (s: CanvasState) => CanvasLayoutNode;
|
|
371
|
+
declare const selectCanvasFocusedPaneId: (s: CanvasState) => CanvasPaneId;
|
|
372
|
+
declare const selectCanvasIsHydrated: (s: CanvasState) => boolean;
|
|
373
|
+
declare const selectCanvasItemCount: (s: CanvasState) => number;
|
|
374
|
+
declare const selectCanvasPane: (s: CanvasState, paneId: CanvasPaneId) => CanvasPane | undefined;
|
|
375
|
+
declare const selectCanvasItem: (s: CanvasState, itemId: CanvasItemId) => CanvasItem | undefined;
|
|
376
|
+
declare function selectCanvasPaneCount(s: CanvasState): number;
|
|
377
|
+
/** The item the person is looking at in the focused pane. */
|
|
378
|
+
declare function selectCanvasActiveItem(s: CanvasState): CanvasItem | null;
|
|
379
|
+
|
|
380
|
+
export { CANVAS_DEFAULT_WIDTH, CANVAS_MIN_SPLIT_FRACTION, CANVAS_MIN_WIDTH, CANVAS_STORAGE_KEY, type CanvasAction, type CanvasController, type CanvasControllerOptions, type CanvasErrorReport, type CanvasErrorSink, type CanvasItem, type CanvasItemId, type CanvasJson, type CanvasLayoutNode, type CanvasOpenInput, type CanvasOpenTarget, type CanvasOrientation, type CanvasPane, type CanvasPaneId, type CanvasPersistencePort, type CanvasSplitId, type CanvasState, type CanvasStoreBinding, type ReduxStoreLike, bindCanvasToReduxStore, canvasActions, canvasItemId, canvasReducer, consoleCanvasErrorSink, createCanvasController, createCanvasStore, createInitialCanvasState, createLocalStorageCanvasPersistence, findNonJson, isCanvasAction, isCanvasJson, listPaneIds, normalizeSizes, parseCanvasItemId, sanitizeCanvasSnapshot, selectCanvasActiveItem, selectCanvasFocusedPaneId, selectCanvasIsFullscreen, selectCanvasIsHydrated, selectCanvasIsOpen, selectCanvasItem, selectCanvasItemCount, selectCanvasLayout, selectCanvasPane, selectCanvasPaneCount, selectCanvasWidth, toPersistableSnapshot };
|