@sqlrooms/canvas 0.29.0-rc.2 → 0.29.0-rc.3
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/README.md +7 -2
- package/dist/Canvas.d.ts +3 -1
- package/dist/Canvas.d.ts.map +1 -1
- package/dist/Canvas.js +6 -10
- package/dist/Canvas.js.map +1 -1
- package/dist/CanvasSlice.d.ts +9 -8
- package/dist/CanvasSlice.d.ts.map +1 -1
- package/dist/CanvasSlice.js +64 -63
- package/dist/CanvasSlice.js.map +1 -1
- package/dist/crdt.d.ts +5 -5
- package/dist/crdt.d.ts.map +1 -1
- package/dist/crdt.js +16 -16
- package/dist/crdt.js.map +1 -1
- package/dist/edgeUtils.d.ts +2 -2
- package/dist/edgeUtils.d.ts.map +1 -1
- package/dist/edgeUtils.js +3 -3
- package/dist/edgeUtils.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/nodes/AddNodePopover.d.ts +1 -0
- package/dist/nodes/AddNodePopover.d.ts.map +1 -1
- package/dist/nodes/AddNodePopover.js +4 -5
- package/dist/nodes/AddNodePopover.js.map +1 -1
- package/dist/nodes/CanvasNodeContainer.d.ts.map +1 -1
- package/dist/nodes/CanvasNodeContainer.js +2 -1
- package/dist/nodes/CanvasNodeContainer.js.map +1 -1
- package/package.json +8 -8
- package/dist/CanvasAssistantDrawer.d.ts +0 -3
- package/dist/CanvasAssistantDrawer.d.ts.map +0 -1
- package/dist/CanvasAssistantDrawer.js +0 -14
- package/dist/CanvasAssistantDrawer.js.map +0 -1
- package/dist/dag.d.ts +0 -53
- package/dist/dag.d.ts.map +0 -1
- package/dist/dag.js +0 -126
- package/dist/dag.js.map +0 -1
- package/dist/nodes/SqlNode.d.ts +0 -11
- package/dist/nodes/SqlNode.d.ts.map +0 -1
- package/dist/nodes/SqlNode.js +0 -52
- package/dist/nodes/SqlNode.js.map +0 -1
- package/dist/nodes/VegaNode.d.ts +0 -11
- package/dist/nodes/VegaNode.d.ts.map +0 -1
- package/dist/nodes/VegaNode.js +0 -12
- package/dist/nodes/VegaNode.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
React Flow-based canvas for building SQL + Vega node DAGs in SQLRooms apps.
|
|
1
|
+
React Flow-based artifact-scoped canvas for building SQL + Vega node DAGs in SQLRooms apps.
|
|
2
2
|
|
|
3
3
|
This package includes:
|
|
4
4
|
|
|
5
|
+
- `createCanvasSlice` for artifact-scoped canvas runtime state
|
|
6
|
+
- `createDefaultCanvasConfig` for persisted config defaults
|
|
7
|
+
- `Canvas` React component, which requires an explicit `artifactId`
|
|
8
|
+
- `CanvasSliceConfig`, `CanvasNodeMeta`, and `CanvasArtifactMeta` schemas/types
|
|
9
|
+
|
|
5
10
|
Refer to the [Canvas example](https://github.com/sqlrooms/examples/tree/main/canvas).
|
|
6
11
|
|
|
7
12
|
## Stable vs internal imports
|
|
8
13
|
|
|
9
14
|
Use root imports from `@sqlrooms/canvas` as the stable API surface.
|
|
10
15
|
|
|
11
|
-
- stable: `createCanvasSlice`, `createDefaultCanvasConfig`, `Canvas`, `CanvasSliceConfig`, `CanvasNodeMeta`, `
|
|
16
|
+
- stable: `createCanvasSlice`, `createDefaultCanvasConfig`, `Canvas`, `CanvasSliceConfig`, `CanvasNodeMeta`, `CanvasArtifactMeta`
|
|
12
17
|
- internal: direct imports from implementation files under `src/` are not semver-stable and may change without notice
|
package/dist/Canvas.d.ts
CHANGED
package/dist/Canvas.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Canvas.d.ts","sourceRoot":"","sources":["../src/Canvas.tsx"],"names":[],"mappings":"AAWA,OAAO,8BAA8B,CAAC;AAEtC,OAAO,KAA+C,MAAM,OAAO,CAAC;AAiCpE,eAAO,MAAM,MAAM,EAAE,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"Canvas.d.ts","sourceRoot":"","sources":["../src/Canvas.tsx"],"names":[],"mappings":"AAWA,OAAO,8BAA8B,CAAC;AAEtC,OAAO,KAA+C,MAAM,OAAO,CAAC;AAiCpE,eAAO,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAC,CAkHjD,CAAC"}
|
package/dist/Canvas.js
CHANGED
|
@@ -18,7 +18,7 @@ const RegistryNodeRenderer = ({ id, renderCell }) => {
|
|
|
18
18
|
renderContainer: ({ header, content, footer }) => (_jsxs(CanvasNodeContainer, { id: id, headerRight: header, children: [content, footer] })),
|
|
19
19
|
});
|
|
20
20
|
};
|
|
21
|
-
export const Canvas = () => {
|
|
21
|
+
export const Canvas = ({ artifactId }) => {
|
|
22
22
|
const registry = useStoreWithCanvas((s) => s.cells.cellRegistry);
|
|
23
23
|
const nodeTypes = useMemo(() => {
|
|
24
24
|
return Object.fromEntries(Object.entries(registry).map(([type, reg]) => [
|
|
@@ -26,15 +26,11 @@ export const Canvas = () => {
|
|
|
26
26
|
({ id }) => (_jsx(RegistryNodeRenderer, { id: id, renderCell: reg.renderCell })),
|
|
27
27
|
]));
|
|
28
28
|
}, [registry]);
|
|
29
|
-
const currentSheetId = useStoreWithCanvas((s) => s.cells.config.currentSheetId);
|
|
30
|
-
const addSheet = useStoreWithCanvas((s) => s.cells.addSheet);
|
|
31
29
|
const canvasSheet = useStoreWithCanvas((s) => {
|
|
32
|
-
|
|
33
|
-
return sheetId ? s.canvas.config.sheets[sheetId] : undefined;
|
|
30
|
+
return s.canvas.config.artifacts[artifactId];
|
|
34
31
|
});
|
|
35
32
|
const cellsSheet = useStoreWithCanvas((s) => {
|
|
36
|
-
|
|
37
|
-
return sheetId ? s.cells.config.sheets[sheetId] : undefined;
|
|
33
|
+
return s.cells.config.artifacts[artifactId];
|
|
38
34
|
});
|
|
39
35
|
const cellsData = useStoreWithCanvas((s) => s.cells.config.data);
|
|
40
36
|
const nodes = useMemo(() => {
|
|
@@ -73,14 +69,14 @@ export const Canvas = () => {
|
|
|
73
69
|
clearTimeout(viewportTimeoutRef.current);
|
|
74
70
|
}
|
|
75
71
|
viewportTimeoutRef.current = setTimeout(() => {
|
|
76
|
-
setViewport(viewport);
|
|
72
|
+
setViewport(artifactId, viewport);
|
|
77
73
|
}, 150);
|
|
78
|
-
}, [setViewport]);
|
|
74
|
+
}, [artifactId, setViewport]);
|
|
79
75
|
const empty = nodes.length === 0;
|
|
80
76
|
const { theme: colorMode } = useTheme();
|
|
81
77
|
// if (!cellsSheet || cellsSheet.type !== 'canvas') {
|
|
82
78
|
// return null;
|
|
83
79
|
// }
|
|
84
|
-
return (_jsx("div", { className: "flex h-full w-full flex-col", children: _jsxs("div", { className: "relative flex-1 overflow-hidden", children: [empty && (_jsx("div", { className: "absolute inset-0 z-10 flex items-center justify-center", children: _jsx(AddNodePopover, { children: _jsxs(Button, { size: "xs", children: [_jsx(PlusIcon, { className: "h-4 w-4" }), "Add node"] }) }) })), _jsxs(ReactFlow, { minZoom: 0.1, colorMode: colorMode, nodes: nodes, edges: edges, nodeTypes: nodeTypes, onNodesChange: applyNodeChanges, viewport: internalViewport, onViewportChange: debouncedSetViewport, nodesConnectable: false, edgesReconnectable: false, connectOnClick: false, children: [_jsx(MiniMap, {}), _jsx(Controls, { position: "top-left" }), _jsx(Background, { variant: BackgroundVariant.Dots, gap: 16, size: 1 })] })] }) }));
|
|
80
|
+
return (_jsx("div", { className: "flex h-full w-full flex-col", children: _jsxs("div", { className: "relative flex-1 overflow-hidden", children: [empty && (_jsx("div", { className: "absolute inset-0 z-10 flex items-center justify-center", children: _jsx(AddNodePopover, { artifactId: artifactId, children: _jsxs(Button, { size: "xs", children: [_jsx(PlusIcon, { className: "h-4 w-4" }), "Add node"] }) }) })), _jsxs(ReactFlow, { minZoom: 0.1, colorMode: colorMode, nodes: nodes, edges: edges, nodeTypes: nodeTypes, onNodesChange: (changes) => applyNodeChanges(artifactId, changes), viewport: internalViewport, onViewportChange: debouncedSetViewport, nodesConnectable: false, edgesReconnectable: false, connectOnClick: false, children: [_jsx(MiniMap, {}), _jsx(Controls, { position: "top-left" }), _jsx(Background, { variant: BackgroundVariant.Dots, gap: 16, size: 1 })] })] }) }));
|
|
85
81
|
};
|
|
86
82
|
//# sourceMappingURL=Canvas.js.map
|
package/dist/Canvas.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Canvas.js","sourceRoot":"","sources":["../src/Canvas.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,MAAM,EAAE,QAAQ,EAAC,MAAM,cAAc,CAAC;AAC9C,OAAO,EACL,UAAU,EACV,iBAAiB,EACjB,QAAQ,EAER,OAAO,EAEP,SAAS,GAEV,MAAM,eAAe,CAAC;AACvB,OAAO,8BAA8B,CAAC;AACtC,OAAO,EAAC,QAAQ,EAAC,MAAM,cAAc,CAAC;AACtC,OAAc,EAAC,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAC,MAAM,OAAO,CAAC;AACpE,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AACjD,OAAO,EAAC,kBAAkB,EAAC,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAC,cAAc,EAAC,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAC,mBAAmB,EAAC,MAAM,6BAA6B,CAAC;AAEhE,MAAM,oBAAoB,GAWrB,CAAC,EAAC,EAAE,EAAE,UAAU,EAAC,EAAE,EAAE;IACxB,MAAM,IAAI,GAAG,kBAAkB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAChE,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAEvB,OAAO,UAAU,CAAC;QAChB,EAAE;QACF,IAAI;QACJ,eAAe,EAAE,CAAC,EAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAC,EAAE,EAAE,CAAC,CAC9C,MAAC,mBAAmB,IAAC,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE,MAAM,aAC7C,OAAO,EACP,MAAM,IACa,CACvB;KACF,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,MAAM,
|
|
1
|
+
{"version":3,"file":"Canvas.js","sourceRoot":"","sources":["../src/Canvas.tsx"],"names":[],"mappings":"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","sourcesContent":["import {Button, useTheme} from '@sqlrooms/ui';\nimport {\n Background,\n BackgroundVariant,\n Controls,\n Edge,\n MiniMap,\n Node,\n ReactFlow,\n Viewport,\n} from '@xyflow/react';\nimport '@xyflow/react/dist/style.css';\nimport {PlusIcon} from 'lucide-react';\nimport React, {useCallback, useMemo, useRef, useState} from 'react';\nimport {useStoreWithCanvas} from './CanvasSlice';\nimport {getRenderableEdges} from './edgeUtils';\nimport {AddNodePopover} from './nodes/AddNodePopover';\nimport {CanvasNodeContainer} from './nodes/CanvasNodeContainer';\n\nconst RegistryNodeRenderer: React.FC<{\n id: string;\n renderCell: (args: {\n id: string;\n cell: import('@sqlrooms/cells').Cell;\n renderContainer: (props: {\n header?: React.ReactNode;\n content: React.ReactNode;\n footer?: React.ReactNode;\n }) => React.ReactElement;\n }) => React.ReactElement;\n}> = ({id, renderCell}) => {\n const cell = useStoreWithCanvas((s) => s.cells.config.data[id]);\n if (!cell) return null;\n\n return renderCell({\n id,\n cell,\n renderContainer: ({header, content, footer}) => (\n <CanvasNodeContainer id={id} headerRight={header}>\n {content}\n {footer}\n </CanvasNodeContainer>\n ),\n });\n};\n\nexport const Canvas: React.FC<{artifactId: string}> = ({artifactId}) => {\n const registry = useStoreWithCanvas((s) => s.cells.cellRegistry);\n const nodeTypes = useMemo(() => {\n return Object.fromEntries(\n Object.entries(registry).map(([type, reg]) => [\n type,\n ({id}: {id: string}) => (\n <RegistryNodeRenderer id={id} renderCell={reg.renderCell} />\n ),\n ]),\n );\n }, [registry]);\n\n const canvasSheet = useStoreWithCanvas((s) => {\n return s.canvas.config.artifacts[artifactId];\n });\n\n const cellsSheet = useStoreWithCanvas((s) => {\n return s.cells.config.artifacts[artifactId];\n });\n\n const cellsData = useStoreWithCanvas((s) => s.cells.config.data);\n\n const nodes = useMemo(() => {\n if (!cellsSheet) return [] as Node[];\n\n // Use all cells from the canonical sheet\n const list = cellsSheet.cellIds\n .map((id: string) => {\n // Get view-specific metadata if it exists\n const canvasNode = canvasSheet?.nodes[id];\n const cell = cellsData[id];\n if (!cell) return null;\n\n return {\n id,\n position: canvasNode?.position ?? {x: 100, y: 100},\n width: canvasNode?.width ?? 800,\n height: canvasNode?.height ?? 600,\n type: cell.type,\n data: cell.data,\n };\n })\n .filter(Boolean);\n return list as unknown as Node[];\n }, [canvasSheet, cellsSheet, cellsData]);\n\n const edges = useMemo(\n () => getRenderableEdges(cellsSheet) as Edge[],\n [cellsSheet],\n );\n const viewport = canvasSheet?.meta.viewport ?? {x: 0, y: 0, zoom: 1};\n const applyNodeChanges = useStoreWithCanvas((s) => s.canvas.applyNodeChanges);\n const setViewport = useStoreWithCanvas((s) => s.canvas.setViewport);\n const [internalViewport, setInternalViewport] = useState<Viewport>(viewport);\n\n // Debounce viewport updates to prevent rapid state saves from React Flow\n const viewportTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const debouncedSetViewport = useCallback(\n (viewport: Viewport) => {\n setInternalViewport(viewport);\n if (viewportTimeoutRef.current) {\n clearTimeout(viewportTimeoutRef.current);\n }\n viewportTimeoutRef.current = setTimeout(() => {\n setViewport(artifactId, viewport);\n }, 150);\n },\n [artifactId, setViewport],\n );\n\n const empty = nodes.length === 0;\n const {theme: colorMode} = useTheme();\n\n // if (!cellsSheet || cellsSheet.type !== 'canvas') {\n // return null;\n // }\n\n return (\n <div className=\"flex h-full w-full flex-col\">\n <div className=\"relative flex-1 overflow-hidden\">\n {empty && (\n <div className=\"absolute inset-0 z-10 flex items-center justify-center\">\n <AddNodePopover artifactId={artifactId}>\n <Button size=\"xs\">\n <PlusIcon className=\"h-4 w-4\" />\n Add node\n </Button>\n </AddNodePopover>\n </div>\n )}\n <ReactFlow\n minZoom={0.1}\n colorMode={colorMode}\n nodes={nodes as any}\n edges={edges}\n nodeTypes={nodeTypes}\n onNodesChange={(changes) =>\n applyNodeChanges(artifactId, changes as any)\n }\n viewport={internalViewport}\n onViewportChange={debouncedSetViewport}\n nodesConnectable={false}\n edgesReconnectable={false}\n connectOnClick={false}\n // fitView\n >\n <MiniMap />\n <Controls position=\"top-left\" />\n <Background variant={BackgroundVariant.Dots} gap={16} size={1} />\n </ReactFlow>\n </div>\n </div>\n );\n};\n"]}
|
package/dist/CanvasSlice.d.ts
CHANGED
|
@@ -15,8 +15,8 @@ export declare const CanvasNodeMeta: z.ZodObject<{
|
|
|
15
15
|
data: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
16
16
|
}, z.core.$strip>;
|
|
17
17
|
export type CanvasNodeMeta = z.infer<typeof CanvasNodeMeta>;
|
|
18
|
-
/** View metadata for a
|
|
19
|
-
export declare const
|
|
18
|
+
/** View metadata for a canvas artifact. */
|
|
19
|
+
export declare const CanvasArtifactMeta: z.ZodObject<{
|
|
20
20
|
viewport: z.ZodObject<{
|
|
21
21
|
x: z.ZodNumber;
|
|
22
22
|
y: z.ZodNumber;
|
|
@@ -24,9 +24,9 @@ export declare const CanvasSheetMeta: z.ZodObject<{
|
|
|
24
24
|
}, z.core.$strip>;
|
|
25
25
|
nodeOrder: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
26
26
|
}, z.core.$strip>;
|
|
27
|
-
export type
|
|
27
|
+
export type CanvasArtifactMeta = z.infer<typeof CanvasArtifactMeta>;
|
|
28
28
|
export declare const CanvasSliceConfig: z.ZodObject<{
|
|
29
|
-
|
|
29
|
+
artifacts: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
30
30
|
id: z.ZodString;
|
|
31
31
|
nodes: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
32
32
|
id: z.ZodString;
|
|
@@ -54,10 +54,11 @@ export type CanvasSliceState = {
|
|
|
54
54
|
config: CanvasSliceConfig;
|
|
55
55
|
initialize: () => Promise<void>;
|
|
56
56
|
setConfig: (config: CanvasSliceConfig) => void;
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
ensureArtifact: (artifactId: string) => void;
|
|
58
|
+
removeArtifact: (artifactId: string) => void;
|
|
59
|
+
setViewport: (artifactId: string, viewport: Viewport) => void;
|
|
59
60
|
addNode: (params: {
|
|
60
|
-
|
|
61
|
+
artifactId: string;
|
|
61
62
|
nodeType?: string;
|
|
62
63
|
initialPosition?: XYPosition;
|
|
63
64
|
parentId?: string;
|
|
@@ -65,7 +66,7 @@ export type CanvasSliceState = {
|
|
|
65
66
|
renameNode: (nodeId: string, newTitle: string) => Promise<void>;
|
|
66
67
|
updateNode: (nodeId: string, updater: (cell: Cell) => Cell) => Promise<void>;
|
|
67
68
|
deleteNode: (nodeId: string) => void;
|
|
68
|
-
applyNodeChanges: (changes: NodeChange<CanvasNodeMeta>[]) => void;
|
|
69
|
+
applyNodeChanges: (artifactId: string, changes: NodeChange<CanvasNodeMeta>[]) => void;
|
|
69
70
|
applyEdgeChanges: (changes: EdgeChange<any>[]) => void;
|
|
70
71
|
addEdge: (edge: Connection) => void;
|
|
71
72
|
executeSqlNodeQuery: (nodeId: string, opts?: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CanvasSlice.d.ts","sourceRoot":"","sources":["../src/CanvasSlice.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,KAAK,IAAI,EAAE,KAAK,cAAc,
|
|
1
|
+
{"version":3,"file":"CanvasSlice.d.ts","sourceRoot":"","sources":["../src/CanvasSlice.ts"],"names":[],"mappings":"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"}
|
package/dist/CanvasSlice.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { createId } from '@paralleldrive/cuid2';
|
|
2
|
-
import { getSheetsByType } from '@sqlrooms/cells';
|
|
3
2
|
import { createSlice, useBaseRoomStore, } from '@sqlrooms/room-store';
|
|
4
3
|
import { generateUniqueName } from '@sqlrooms/utils';
|
|
5
4
|
import { applyNodeChanges, } from '@xyflow/react';
|
|
@@ -17,8 +16,8 @@ export const CanvasNodeMeta = z.object({
|
|
|
17
16
|
height: z.number().default(DEFAULT_NODE_HEIGHT),
|
|
18
17
|
data: z.record(z.string(), z.any()).default({}), // Required by ReactFlow NodeBase
|
|
19
18
|
});
|
|
20
|
-
/** View metadata for a
|
|
21
|
-
export const
|
|
19
|
+
/** View metadata for a canvas artifact. */
|
|
20
|
+
export const CanvasArtifactMeta = z.object({
|
|
22
21
|
viewport: z.object({
|
|
23
22
|
x: z.number(),
|
|
24
23
|
y: z.number(),
|
|
@@ -26,32 +25,31 @@ export const CanvasSheetMeta = z.object({
|
|
|
26
25
|
}),
|
|
27
26
|
nodeOrder: z.array(z.string()).default([]),
|
|
28
27
|
});
|
|
28
|
+
const CanvasArtifactRuntime = z.object({
|
|
29
|
+
id: z.string(),
|
|
30
|
+
nodes: z.record(z.string(), CanvasNodeMeta).default({}),
|
|
31
|
+
meta: CanvasArtifactMeta,
|
|
32
|
+
});
|
|
29
33
|
export const CanvasSliceConfig = z.object({
|
|
30
|
-
|
|
31
|
-
.record(z.string(), z.object({
|
|
32
|
-
id: z.string(),
|
|
33
|
-
nodes: z.record(z.string(), CanvasNodeMeta).default({}),
|
|
34
|
-
meta: CanvasSheetMeta,
|
|
35
|
-
}))
|
|
36
|
-
.default({}),
|
|
34
|
+
artifacts: z.record(z.string(), CanvasArtifactRuntime).default({}),
|
|
37
35
|
});
|
|
38
|
-
function
|
|
39
|
-
return config.
|
|
36
|
+
function getArtifact(config, artifactId) {
|
|
37
|
+
return config.artifacts[artifactId];
|
|
40
38
|
}
|
|
41
|
-
function
|
|
42
|
-
let
|
|
43
|
-
if (!
|
|
44
|
-
|
|
45
|
-
id:
|
|
39
|
+
function ensureCanvasArtifactMeta(config, artifactId, viewport = { x: 0, y: 0, zoom: 1 }) {
|
|
40
|
+
let artifact = config.artifacts[artifactId];
|
|
41
|
+
if (!artifact) {
|
|
42
|
+
artifact = {
|
|
43
|
+
id: artifactId,
|
|
46
44
|
nodes: {},
|
|
47
45
|
meta: {
|
|
48
46
|
viewport,
|
|
49
47
|
nodeOrder: [],
|
|
50
48
|
},
|
|
51
49
|
};
|
|
52
|
-
config.
|
|
50
|
+
config.artifacts[artifactId] = artifact;
|
|
53
51
|
}
|
|
54
|
-
return
|
|
52
|
+
return artifact;
|
|
55
53
|
}
|
|
56
54
|
function isSameViewport(a, b) {
|
|
57
55
|
return (Math.abs(a.x - b.x) < VIEWPORT_EPSILON &&
|
|
@@ -60,7 +58,7 @@ function isSameViewport(a, b) {
|
|
|
60
58
|
}
|
|
61
59
|
export function createDefaultCanvasConfig(props) {
|
|
62
60
|
const base = {
|
|
63
|
-
|
|
61
|
+
artifacts: {},
|
|
64
62
|
};
|
|
65
63
|
return { ...base, ...props };
|
|
66
64
|
}
|
|
@@ -74,16 +72,22 @@ export function createCanvasSlice(props = {}) {
|
|
|
74
72
|
draft.canvas.config = config;
|
|
75
73
|
}));
|
|
76
74
|
},
|
|
77
|
-
|
|
75
|
+
ensureArtifact: (artifactId) => {
|
|
76
|
+
get().cells.ensureArtifact(artifactId);
|
|
77
|
+
set((state) => produce(state, (draft) => {
|
|
78
|
+
ensureCanvasArtifactMeta(draft.canvas.config, artifactId);
|
|
79
|
+
}));
|
|
80
|
+
},
|
|
81
|
+
removeArtifact: (artifactId) => {
|
|
82
|
+
get().cells.removeArtifact(artifactId);
|
|
83
|
+
set((state) => produce(state, (draft) => {
|
|
84
|
+
delete draft.canvas.config.artifacts[artifactId];
|
|
85
|
+
}));
|
|
86
|
+
},
|
|
78
87
|
async initialize() {
|
|
79
|
-
|
|
80
|
-
get().cells.config.sheetOrder[0];
|
|
81
|
-
if (!sheetId)
|
|
82
|
-
return;
|
|
83
|
-
// don't await this - it will block the UI
|
|
84
|
-
get().cells.runAllCellsCascade(sheetId);
|
|
88
|
+
// no-op: host apps should call artifact-scoped runtime explicitly
|
|
85
89
|
},
|
|
86
|
-
addNode: async ({
|
|
90
|
+
addNode: async ({ artifactId, nodeType = 'sql', initialPosition, parentId, }) => {
|
|
87
91
|
const newId = createId();
|
|
88
92
|
const registry = get().cells.cellRegistry;
|
|
89
93
|
const reg = registry[nodeType];
|
|
@@ -96,16 +100,19 @@ export function createCanvasSlice(props = {}) {
|
|
|
96
100
|
return typeof title === 'string' ? title : '';
|
|
97
101
|
});
|
|
98
102
|
cell.data.title = generateUniqueName(`${reg.title} 1`, existingTitles, ' ');
|
|
99
|
-
|
|
103
|
+
get().cells.ensureArtifact(artifactId);
|
|
104
|
+
await get().cells.addCell(artifactId, cell);
|
|
100
105
|
// 2. If parent exists, add an edge in CellsSlice
|
|
101
106
|
if (parentId) {
|
|
102
|
-
get().cells.addEdge(
|
|
107
|
+
get().cells.addEdge(artifactId, { source: parentId, target: newId });
|
|
103
108
|
}
|
|
104
109
|
// 3. Update view-specific metadata
|
|
105
110
|
set((state) => produce(state, (draft) => {
|
|
106
|
-
let
|
|
107
|
-
|
|
108
|
-
const parentNode = parentId
|
|
111
|
+
let artifact = getArtifact(draft.canvas.config, artifactId);
|
|
112
|
+
artifact = ensureCanvasArtifactMeta(draft.canvas.config, artifactId);
|
|
113
|
+
const parentNode = parentId
|
|
114
|
+
? artifact.nodes[parentId]
|
|
115
|
+
: undefined;
|
|
109
116
|
const position = initialPosition
|
|
110
117
|
? initialPosition
|
|
111
118
|
: parentNode
|
|
@@ -114,17 +121,17 @@ export function createCanvasSlice(props = {}) {
|
|
|
114
121
|
y: parentNode.position.y,
|
|
115
122
|
}
|
|
116
123
|
: {
|
|
117
|
-
x:
|
|
118
|
-
y:
|
|
124
|
+
x: artifact.meta.viewport.x + 100,
|
|
125
|
+
y: artifact.meta.viewport.y + 100,
|
|
119
126
|
};
|
|
120
|
-
|
|
127
|
+
artifact.nodes[newId] = {
|
|
121
128
|
id: newId,
|
|
122
129
|
position,
|
|
123
130
|
width: DEFAULT_NODE_WIDTH,
|
|
124
131
|
height: DEFAULT_NODE_HEIGHT,
|
|
125
132
|
data: {},
|
|
126
133
|
};
|
|
127
|
-
|
|
134
|
+
artifact.meta.nodeOrder.push(newId);
|
|
128
135
|
}));
|
|
129
136
|
return newId;
|
|
130
137
|
},
|
|
@@ -139,43 +146,40 @@ export function createCanvasSlice(props = {}) {
|
|
|
139
146
|
deleteNode: (nodeId) => {
|
|
140
147
|
get().cells.removeCell(nodeId);
|
|
141
148
|
set((state) => produce(state, (draft) => {
|
|
142
|
-
for (const
|
|
143
|
-
delete
|
|
144
|
-
|
|
149
|
+
for (const artifact of Object.values(draft.canvas.config.artifacts)) {
|
|
150
|
+
delete artifact.nodes[nodeId];
|
|
151
|
+
artifact.meta.nodeOrder = artifact.meta.nodeOrder.filter((id) => id !== nodeId);
|
|
145
152
|
}
|
|
146
153
|
}));
|
|
147
154
|
},
|
|
148
|
-
applyNodeChanges: (changes) => {
|
|
155
|
+
applyNodeChanges: (artifactId, changes) => {
|
|
149
156
|
set((state) => produce(state, (draft) => {
|
|
150
|
-
const
|
|
151
|
-
if (!sheetId)
|
|
152
|
-
return;
|
|
153
|
-
const sheet = ensureCanvasSheetMeta(draft.canvas.config, sheetId);
|
|
157
|
+
const artifact = ensureCanvasArtifactMeta(draft.canvas.config, artifactId);
|
|
154
158
|
// Ensure all cells from CellsSlice have a node entry in CanvasSlice
|
|
155
|
-
const
|
|
156
|
-
if (
|
|
157
|
-
for (const cellId of
|
|
158
|
-
if (!
|
|
159
|
-
|
|
159
|
+
const cellsArtifact = draft.cells.config.artifacts[artifactId];
|
|
160
|
+
if (cellsArtifact) {
|
|
161
|
+
for (const cellId of cellsArtifact.cellIds) {
|
|
162
|
+
if (!artifact.nodes[cellId]) {
|
|
163
|
+
artifact.nodes[cellId] = {
|
|
160
164
|
id: cellId,
|
|
161
165
|
position: { x: 100, y: 100 },
|
|
162
166
|
width: DEFAULT_NODE_WIDTH,
|
|
163
167
|
height: DEFAULT_NODE_HEIGHT,
|
|
164
168
|
data: {},
|
|
165
169
|
};
|
|
166
|
-
|
|
170
|
+
artifact.meta.nodeOrder.push(cellId);
|
|
167
171
|
}
|
|
168
172
|
}
|
|
169
173
|
}
|
|
170
|
-
const nodesArray =
|
|
171
|
-
.map((id) =>
|
|
174
|
+
const nodesArray = artifact.meta.nodeOrder
|
|
175
|
+
.map((id) => artifact.nodes[id])
|
|
172
176
|
.filter(Boolean);
|
|
173
177
|
const updated = applyNodeChanges(changes, nodesArray);
|
|
174
|
-
|
|
178
|
+
artifact.nodes = updated.reduce((acc, node) => {
|
|
175
179
|
acc[node.id] = node;
|
|
176
180
|
return acc;
|
|
177
181
|
}, {});
|
|
178
|
-
|
|
182
|
+
artifact.meta.nodeOrder = updated.map((n) => n.id);
|
|
179
183
|
}));
|
|
180
184
|
},
|
|
181
185
|
applyEdgeChanges: (changes) => {
|
|
@@ -188,18 +192,15 @@ export function createCanvasSlice(props = {}) {
|
|
|
188
192
|
// Compatibility no-op: dependency edges are derived from graph cache.
|
|
189
193
|
void connection;
|
|
190
194
|
},
|
|
191
|
-
setViewport: (viewport) => {
|
|
192
|
-
const
|
|
193
|
-
if (!sheetId)
|
|
194
|
-
return;
|
|
195
|
-
const existing = get().canvas.config.sheets[sheetId];
|
|
195
|
+
setViewport: (artifactId, viewport) => {
|
|
196
|
+
const existing = get().canvas.config.artifacts[artifactId];
|
|
196
197
|
if (existing && isSameViewport(existing.meta.viewport, viewport)) {
|
|
197
198
|
return;
|
|
198
199
|
}
|
|
199
200
|
set((state) => produce(state, (draft) => {
|
|
200
|
-
let
|
|
201
|
-
|
|
202
|
-
|
|
201
|
+
let artifact = getArtifact(draft.canvas.config, artifactId);
|
|
202
|
+
artifact = ensureCanvasArtifactMeta(draft.canvas.config, artifactId, viewport);
|
|
203
|
+
artifact.meta.viewport = viewport;
|
|
203
204
|
}));
|
|
204
205
|
},
|
|
205
206
|
executeSqlNodeQuery: async (nodeId, opts) => {
|
package/dist/CanvasSlice.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CanvasSlice.js","sourceRoot":"","sources":["../src/CanvasSlice.ts"],"names":[],"mappings":"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","sourcesContent":["import {createId} from '@paralleldrive/cuid2';\nimport {type Cell, type CellsRootState, getSheetsByType} from '@sqlrooms/cells';\nimport {DuckDbSliceState} from '@sqlrooms/duckdb';\nimport {\n BaseRoomStoreState,\n createSlice,\n useBaseRoomStore,\n} from '@sqlrooms/room-store';\nimport {generateUniqueName} from '@sqlrooms/utils';\nimport type {Viewport, XYPosition} from '@xyflow/react';\nimport {\n applyNodeChanges,\n Connection,\n type EdgeChange,\n type NodeChange,\n} from '@xyflow/react';\nimport {produce} from 'immer';\nimport {z} from 'zod';\n\nconst DEFAULT_NODE_WIDTH = 800;\nconst DEFAULT_NODE_HEIGHT = 600;\nconst CANVAS_SCHEMA_NAME = 'canvas';\nconst VIEWPORT_EPSILON = 0.1;\n\n/** View metadata for a single node on the canvas */\nexport const CanvasNodeMeta = z.object({\n id: z.string(),\n position: z.object({x: z.number(), y: z.number()}),\n width: z.number().default(DEFAULT_NODE_WIDTH),\n height: z.number().default(DEFAULT_NODE_HEIGHT),\n data: z.record(z.string(), z.any()).default({}), // Required by ReactFlow NodeBase\n});\nexport type CanvasNodeMeta = z.infer<typeof CanvasNodeMeta>;\n\n/** View metadata for a sheet (canvas view) */\nexport const CanvasSheetMeta = z.object({\n viewport: z.object({\n x: z.number(),\n y: z.number(),\n zoom: z.number(),\n }),\n nodeOrder: z.array(z.string()).default([]),\n});\nexport type CanvasSheetMeta = z.infer<typeof CanvasSheetMeta>;\n\nexport const CanvasSliceConfig = z.object({\n sheets: z\n .record(\n z.string(),\n z.object({\n id: z.string(),\n nodes: z.record(z.string(), CanvasNodeMeta).default({}),\n meta: CanvasSheetMeta,\n }),\n )\n .default({}),\n});\nexport type CanvasSliceConfig = z.infer<typeof CanvasSliceConfig>;\n\nexport type CanvasSliceState = {\n canvas: {\n config: CanvasSliceConfig;\n initialize: () => Promise<void>;\n setConfig: (config: CanvasSliceConfig) => void;\n setViewport: (viewport: Viewport) => void;\n getCanvasSheets: () => Record<string, import('@sqlrooms/cells').Sheet>;\n\n addNode: (params: {\n sheetId: string;\n nodeType?: string;\n initialPosition?: XYPosition;\n parentId?: string;\n }) => Promise<string>;\n\n renameNode: (nodeId: string, newTitle: string) => Promise<void>;\n updateNode: (\n nodeId: string,\n updater: (cell: Cell) => Cell,\n ) => Promise<void>;\n deleteNode: (nodeId: string) => void;\n\n applyNodeChanges: (changes: NodeChange<CanvasNodeMeta>[]) => void;\n applyEdgeChanges: (changes: EdgeChange<any>[]) => void;\n addEdge: (edge: Connection) => void;\n\n executeSqlNodeQuery: (\n nodeId: string,\n opts?: {cascade?: boolean},\n ) => Promise<void>;\n };\n};\n\nfunction getSheet(config: CanvasSliceConfig, sheetId: string) {\n return config.sheets[sheetId];\n}\n\nfunction ensureCanvasSheetMeta(\n config: CanvasSliceConfig,\n sheetId: string,\n viewport: Viewport = {x: 0, y: 0, zoom: 1},\n) {\n let sheet = config.sheets[sheetId];\n if (!sheet) {\n sheet = {\n id: sheetId,\n nodes: {},\n meta: {\n viewport,\n nodeOrder: [],\n },\n };\n config.sheets[sheetId] = sheet;\n }\n return sheet;\n}\n\nfunction isSameViewport(a: Viewport, b: Viewport) {\n return (\n Math.abs(a.x - b.x) < VIEWPORT_EPSILON &&\n Math.abs(a.y - b.y) < VIEWPORT_EPSILON &&\n Math.abs(a.zoom - b.zoom) < VIEWPORT_EPSILON\n );\n}\n\nexport function createDefaultCanvasConfig(\n props?: Partial<CanvasSliceConfig>,\n): CanvasSliceConfig {\n const base: CanvasSliceConfig = {\n sheets: {},\n };\n\n return {...base, ...props};\n}\n\nexport function createCanvasSlice(\n props: {config?: Partial<CanvasSliceConfig>} = {},\n) {\n type CanvasRootState = BaseRoomStoreState &\n DuckDbSliceState &\n CanvasSliceState &\n CellsRootState;\n\n return createSlice<CanvasSliceState, CanvasRootState>((set, get, store) => {\n return {\n canvas: {\n config: createDefaultCanvasConfig(props.config),\n setConfig: (config: CanvasSliceConfig) => {\n set((state: CanvasRootState) =>\n produce(state, (draft: CanvasRootState) => {\n draft.canvas.config = config;\n }),\n );\n },\n\n getCanvasSheets: () => getSheetsByType(get(), 'canvas'),\n\n async initialize() {\n const sheetId =\n get().cells.config.currentSheetId ||\n get().cells.config.sheetOrder[0];\n if (!sheetId) return;\n // don't await this - it will block the UI\n get().cells.runAllCellsCascade(sheetId);\n },\n\n addNode: async ({\n sheetId,\n nodeType = 'sql',\n initialPosition,\n parentId,\n }: {\n sheetId: string;\n nodeType?: string;\n initialPosition?: XYPosition;\n parentId?: string;\n }) => {\n const newId = createId();\n const registry = get().cells.cellRegistry;\n const reg = registry[nodeType];\n if (!reg) return newId;\n\n // 1. Create the cell in CellsSlice\n const cell = reg.createCell({id: newId, get, set}) as Cell;\n\n const existingTitles = Object.values(get().cells.config.data).map(\n (c) => {\n const title = (c.data as Record<string, unknown>).title;\n return typeof title === 'string' ? title : '';\n },\n );\n (cell.data as Record<string, unknown>).title = generateUniqueName(\n `${reg.title} 1`,\n existingTitles,\n ' ',\n );\n\n await get().cells.addCell(sheetId, cell);\n\n // 2. If parent exists, add an edge in CellsSlice\n if (parentId) {\n get().cells.addEdge(sheetId, {source: parentId, target: newId});\n }\n\n // 3. Update view-specific metadata\n set((state: CanvasRootState) =>\n produce(state, (draft: CanvasRootState) => {\n let sheet = getSheet(draft.canvas.config, sheetId);\n sheet = ensureCanvasSheetMeta(draft.canvas.config, sheetId);\n\n const parentNode = parentId ? sheet.nodes[parentId] : undefined;\n const position: XYPosition = initialPosition\n ? initialPosition\n : parentNode\n ? {\n x: parentNode.position.x + parentNode.width + 100,\n y: parentNode.position.y,\n }\n : {\n x: sheet.meta.viewport.x + 100,\n y: sheet.meta.viewport.y + 100,\n };\n\n sheet.nodes[newId] = {\n id: newId,\n position,\n width: DEFAULT_NODE_WIDTH,\n height: DEFAULT_NODE_HEIGHT,\n data: {},\n };\n sheet.meta.nodeOrder.push(newId);\n }),\n );\n return newId;\n },\n\n renameNode: async (nodeId: string, newTitle: string) => {\n await get().cells.updateCell(nodeId, (c) =>\n produce(c, (draft) => {\n (draft.data as Record<string, unknown>).title = newTitle;\n }),\n );\n },\n\n updateNode: async (nodeId: string, updater: (cell: Cell) => Cell) => {\n await get().cells.updateCell(nodeId, updater);\n },\n\n deleteNode: (nodeId: string) => {\n get().cells.removeCell(nodeId);\n set((state: CanvasRootState) =>\n produce(state, (draft: CanvasRootState) => {\n for (const sheet of Object.values(draft.canvas.config.sheets)) {\n delete sheet.nodes[nodeId];\n sheet.meta.nodeOrder = sheet.meta.nodeOrder.filter(\n (id) => id !== nodeId,\n );\n }\n }),\n );\n },\n\n applyNodeChanges: (changes: NodeChange<CanvasNodeMeta>[]) => {\n set((state: CanvasRootState) =>\n produce(state, (draft: CanvasRootState) => {\n const sheetId = draft.cells.config.currentSheetId;\n if (!sheetId) return;\n const sheet = ensureCanvasSheetMeta(draft.canvas.config, sheetId);\n\n // Ensure all cells from CellsSlice have a node entry in CanvasSlice\n const cellsSheet = draft.cells.config.sheets[sheetId];\n if (cellsSheet) {\n for (const cellId of cellsSheet.cellIds) {\n if (!sheet.nodes[cellId]) {\n sheet.nodes[cellId] = {\n id: cellId,\n position: {x: 100, y: 100},\n width: DEFAULT_NODE_WIDTH,\n height: DEFAULT_NODE_HEIGHT,\n data: {},\n };\n sheet.meta.nodeOrder.push(cellId);\n }\n }\n }\n\n const nodesArray = sheet.meta.nodeOrder\n .map((id) => sheet.nodes[id])\n .filter(Boolean) as CanvasNodeMeta[];\n const updated = applyNodeChanges(changes, nodesArray);\n sheet.nodes = updated.reduce<Record<string, CanvasNodeMeta>>(\n (acc, node) => {\n acc[node.id] = node;\n return acc;\n },\n {},\n );\n sheet.meta.nodeOrder = updated.map((n) => n.id);\n }),\n );\n },\n\n applyEdgeChanges: (changes: EdgeChange<any>[]) => {\n // Canvas edge editing is intentionally disabled for now.\n // Compatibility no-op: keep API stable until edge kinds are introduced.\n void changes;\n },\n\n addEdge: (connection: Connection) => {\n // Canvas edge editing is intentionally disabled for now.\n // Compatibility no-op: dependency edges are derived from graph cache.\n void connection;\n },\n\n setViewport: (viewport: Viewport) => {\n const sheetId = get().cells.config.currentSheetId;\n if (!sheetId) return;\n const existing = get().canvas.config.sheets[sheetId];\n if (existing && isSameViewport(existing.meta.viewport, viewport)) {\n return;\n }\n set((state: CanvasRootState) =>\n produce(state, (draft: CanvasRootState) => {\n let sheet = getSheet(draft.canvas.config, sheetId);\n sheet = ensureCanvasSheetMeta(\n draft.canvas.config,\n sheetId,\n viewport,\n );\n sheet.meta.viewport = viewport;\n }),\n );\n },\n\n executeSqlNodeQuery: async (\n nodeId: string,\n opts?: {cascade?: boolean},\n ) => {\n await get().cells.runCell(nodeId, {\n ...opts,\n schemaName: CANVAS_SCHEMA_NAME,\n });\n },\n },\n };\n });\n}\n\nexport type DuckDbSliceStateWithCanvas = DuckDbSliceState &\n CanvasSliceState &\n CellsRootState;\n\nexport function useStoreWithCanvas<T>(\n selector: (state: DuckDbSliceStateWithCanvas) => T,\n): T {\n return useBaseRoomStore<BaseRoomStoreState, T>((state) =>\n selector(state as unknown as DuckDbSliceStateWithCanvas),\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"CanvasSlice.js","sourceRoot":"","sources":["../src/CanvasSlice.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,sBAAsB,CAAC;AAG9C,OAAO,EAEL,WAAW,EACX,gBAAgB,GACjB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAC,kBAAkB,EAAC,MAAM,iBAAiB,CAAC;AAEnD,OAAO,EACL,gBAAgB,GAIjB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAC,OAAO,EAAC,MAAM,OAAO,CAAC;AAC9B,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAC/B,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAChC,MAAM,kBAAkB,GAAG,QAAQ,CAAC;AACpC,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAE7B,oDAAoD;AACpD,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,EAAC,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,EAAC,CAAC;IAClD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,kBAAkB,CAAC;IAC7C,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,mBAAmB,CAAC;IAC/C,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,iCAAiC;CACnF,CAAC,CAAC;AAGH,2CAA2C;AAC3C,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC;QACjB,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE;QACb,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE;QACb,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;KACjB,CAAC;IACF,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;CAC3C,CAAC,CAAC;AAGH,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,cAAc,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACvD,IAAI,EAAE,kBAAkB;CACzB,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,qBAAqB,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;CACnE,CAAC,CAAC;AAwCH,SAAS,WAAW,CAAC,MAAyB,EAAE,UAAkB;IAChE,OAAO,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;AACtC,CAAC;AAED,SAAS,wBAAwB,CAC/B,MAAyB,EACzB,UAAkB,EAClB,WAAqB,EAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAC;IAE1C,IAAI,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAC5C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,QAAQ,GAAG;YACT,EAAE,EAAE,UAAU;YACd,KAAK,EAAE,EAAE;YACT,IAAI,EAAE;gBACJ,QAAQ;gBACR,SAAS,EAAE,EAAE;aACd;SACF,CAAC;QACF,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,QAAQ,CAAC;IAC1C,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,cAAc,CAAC,CAAW,EAAE,CAAW;IAC9C,OAAO,CACL,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,gBAAgB;QACtC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,gBAAgB;QACtC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,gBAAgB,CAC7C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,KAAkC;IAElC,MAAM,IAAI,GAAsB;QAC9B,SAAS,EAAE,EAAE;KACd,CAAC;IAEF,OAAO,EAAC,GAAG,IAAI,EAAE,GAAG,KAAK,EAAC,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,QAA+C,EAAE;IAOjD,OAAO,WAAW,CAAoC,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;QACxE,OAAO;YACL,MAAM,EAAE;gBACN,MAAM,EAAE,yBAAyB,CAAC,KAAK,CAAC,MAAM,CAAC;gBAC/C,SAAS,EAAE,CAAC,MAAyB,EAAE,EAAE;oBACvC,GAAG,CAAC,CAAC,KAAsB,EAAE,EAAE,CAC7B,OAAO,CAAC,KAAK,EAAE,CAAC,KAAsB,EAAE,EAAE;wBACxC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC;oBAC/B,CAAC,CAAC,CACH,CAAC;gBACJ,CAAC;gBAED,cAAc,EAAE,CAAC,UAAU,EAAE,EAAE;oBAC7B,GAAG,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;oBACvC,GAAG,CAAC,CAAC,KAAsB,EAAE,EAAE,CAC7B,OAAO,CAAC,KAAK,EAAE,CAAC,KAAsB,EAAE,EAAE;wBACxC,wBAAwB,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;oBAC5D,CAAC,CAAC,CACH,CAAC;gBACJ,CAAC;gBAED,cAAc,EAAE,CAAC,UAAU,EAAE,EAAE;oBAC7B,GAAG,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;oBACvC,GAAG,CAAC,CAAC,KAAsB,EAAE,EAAE,CAC7B,OAAO,CAAC,KAAK,EAAE,CAAC,KAAsB,EAAE,EAAE;wBACxC,OAAO,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;oBACnD,CAAC,CAAC,CACH,CAAC;gBACJ,CAAC;gBAED,KAAK,CAAC,UAAU;oBACd,kEAAkE;gBACpE,CAAC;gBAED,OAAO,EAAE,KAAK,EAAE,EACd,UAAU,EACV,QAAQ,GAAG,KAAK,EAChB,eAAe,EACf,QAAQ,GAMT,EAAE,EAAE;oBACH,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;oBACzB,MAAM,QAAQ,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC;oBAC1C,MAAM,GAAG,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;oBAC/B,IAAI,CAAC,GAAG;wBAAE,OAAO,KAAK,CAAC;oBAEvB,mCAAmC;oBACnC,MAAM,IAAI,GAAG,GAAG,CAAC,UAAU,CAAC,EAAC,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAC,CAAS,CAAC;oBAE3D,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAC/D,CAAC,CAAC,EAAE,EAAE;wBACJ,MAAM,KAAK,GAAI,CAAC,CAAC,IAAgC,CAAC,KAAK,CAAC;wBACxD,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;oBAChD,CAAC,CACF,CAAC;oBACD,IAAI,CAAC,IAAgC,CAAC,KAAK,GAAG,kBAAkB,CAC/D,GAAG,GAAG,CAAC,KAAK,IAAI,EAChB,cAAc,EACd,GAAG,CACJ,CAAC;oBAEF,GAAG,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;oBACvC,MAAM,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;oBAE5C,iDAAiD;oBACjD,IAAI,QAAQ,EAAE,CAAC;wBACb,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,EAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAC,CAAC,CAAC;oBACrE,CAAC;oBAED,mCAAmC;oBACnC,GAAG,CAAC,CAAC,KAAsB,EAAE,EAAE,CAC7B,OAAO,CAAC,KAAK,EAAE,CAAC,KAAsB,EAAE,EAAE;wBACxC,IAAI,QAAQ,GAAG,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;wBAC5D,QAAQ,GAAG,wBAAwB,CACjC,KAAK,CAAC,MAAM,CAAC,MAAM,EACnB,UAAU,CACX,CAAC;wBAEF,MAAM,UAAU,GAAG,QAAQ;4BACzB,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC;4BAC1B,CAAC,CAAC,SAAS,CAAC;wBACd,MAAM,QAAQ,GAAe,eAAe;4BAC1C,CAAC,CAAC,eAAe;4BACjB,CAAC,CAAC,UAAU;gCACV,CAAC,CAAC;oCACE,CAAC,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,GAAG,UAAU,CAAC,KAAK,GAAG,GAAG;oCACjD,CAAC,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;iCACzB;gCACH,CAAC,CAAC;oCACE,CAAC,EAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,GAAG;oCACjC,CAAC,EAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,GAAG;iCAClC,CAAC;wBAER,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG;4BACtB,EAAE,EAAE,KAAK;4BACT,QAAQ;4BACR,KAAK,EAAE,kBAAkB;4BACzB,MAAM,EAAE,mBAAmB;4BAC3B,IAAI,EAAE,EAAE;yBACT,CAAC;wBACF,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBACtC,CAAC,CAAC,CACH,CAAC;oBACF,OAAO,KAAK,CAAC;gBACf,CAAC;gBAED,UAAU,EAAE,KAAK,EAAE,MAAc,EAAE,QAAgB,EAAE,EAAE;oBACrD,MAAM,GAAG,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CACzC,OAAO,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE;wBAClB,KAAK,CAAC,IAAgC,CAAC,KAAK,GAAG,QAAQ,CAAC;oBAC3D,CAAC,CAAC,CACH,CAAC;gBACJ,CAAC;gBAED,UAAU,EAAE,KAAK,EAAE,MAAc,EAAE,OAA6B,EAAE,EAAE;oBAClE,MAAM,GAAG,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAChD,CAAC;gBAED,UAAU,EAAE,CAAC,MAAc,EAAE,EAAE;oBAC7B,GAAG,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;oBAC/B,GAAG,CAAC,CAAC,KAAsB,EAAE,EAAE,CAC7B,OAAO,CAAC,KAAK,EAAE,CAAC,KAAsB,EAAE,EAAE;wBACxC,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,MAAM,CAClC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAC9B,EAAE,CAAC;4BACF,OAAO,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;4BAC9B,QAAQ,CAAC,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CACtD,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,KAAK,MAAM,CACtB,CAAC;wBACJ,CAAC;oBACH,CAAC,CAAC,CACH,CAAC;gBACJ,CAAC;gBAED,gBAAgB,EAAE,CAChB,UAAkB,EAClB,OAAqC,EACrC,EAAE;oBACF,GAAG,CAAC,CAAC,KAAsB,EAAE,EAAE,CAC7B,OAAO,CAAC,KAAK,EAAE,CAAC,KAAsB,EAAE,EAAE;wBACxC,MAAM,QAAQ,GAAG,wBAAwB,CACvC,KAAK,CAAC,MAAM,CAAC,MAAM,EACnB,UAAU,CACX,CAAC;wBAEF,oEAAoE;wBACpE,MAAM,aAAa,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;wBAC/D,IAAI,aAAa,EAAE,CAAC;4BAClB,KAAK,MAAM,MAAM,IAAI,aAAa,CAAC,OAAO,EAAE,CAAC;gCAC3C,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;oCAC5B,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG;wCACvB,EAAE,EAAE,MAAM;wCACV,QAAQ,EAAE,EAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAC;wCAC1B,KAAK,EAAE,kBAAkB;wCACzB,MAAM,EAAE,mBAAmB;wCAC3B,IAAI,EAAE,EAAE;qCACT,CAAC;oCACF,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gCACvC,CAAC;4BACH,CAAC;wBACH,CAAC;wBAED,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS;6BACvC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;6BAC/B,MAAM,CAAC,OAAO,CAAqB,CAAC;wBACvC,MAAM,OAAO,GAAG,gBAAgB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;wBACtD,QAAQ,CAAC,KAAK,GAAG,OAAO,CAAC,MAAM,CAC7B,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;4BACZ,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC;4BACpB,OAAO,GAAG,CAAC;wBACb,CAAC,EACD,EAAE,CACH,CAAC;wBACF,QAAQ,CAAC,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;oBACrD,CAAC,CAAC,CACH,CAAC;gBACJ,CAAC;gBAED,gBAAgB,EAAE,CAAC,OAA0B,EAAE,EAAE;oBAC/C,yDAAyD;oBACzD,wEAAwE;oBACxE,KAAK,OAAO,CAAC;gBACf,CAAC;gBAED,OAAO,EAAE,CAAC,UAAsB,EAAE,EAAE;oBAClC,yDAAyD;oBACzD,sEAAsE;oBACtE,KAAK,UAAU,CAAC;gBAClB,CAAC;gBAED,WAAW,EAAE,CAAC,UAAkB,EAAE,QAAkB,EAAE,EAAE;oBACtD,MAAM,QAAQ,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;oBAC3D,IAAI,QAAQ,IAAI,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC;wBACjE,OAAO;oBACT,CAAC;oBACD,GAAG,CAAC,CAAC,KAAsB,EAAE,EAAE,CAC7B,OAAO,CAAC,KAAK,EAAE,CAAC,KAAsB,EAAE,EAAE;wBACxC,IAAI,QAAQ,GAAG,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;wBAC5D,QAAQ,GAAG,wBAAwB,CACjC,KAAK,CAAC,MAAM,CAAC,MAAM,EACnB,UAAU,EACV,QAAQ,CACT,CAAC;wBACF,QAAQ,CAAC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;oBACpC,CAAC,CAAC,CACH,CAAC;gBACJ,CAAC;gBAED,mBAAmB,EAAE,KAAK,EACxB,MAAc,EACd,IAA0B,EAC1B,EAAE;oBACF,MAAM,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE;wBAChC,GAAG,IAAI;wBACP,UAAU,EAAE,kBAAkB;qBAC/B,CAAC,CAAC;gBACL,CAAC;aACF;SACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAMD,MAAM,UAAU,kBAAkB,CAChC,QAAkD;IAElD,OAAO,gBAAgB,CAAwB,CAAC,KAAK,EAAE,EAAE,CACvD,QAAQ,CAAC,KAA8C,CAAC,CACzD,CAAC;AACJ,CAAC","sourcesContent":["import {createId} from '@paralleldrive/cuid2';\nimport {type Cell, type CellsRootState} from '@sqlrooms/cells';\nimport {DuckDbSliceState} from '@sqlrooms/duckdb';\nimport {\n BaseRoomStoreState,\n createSlice,\n useBaseRoomStore,\n} from '@sqlrooms/room-store';\nimport {generateUniqueName} from '@sqlrooms/utils';\nimport type {Viewport, XYPosition} from '@xyflow/react';\nimport {\n applyNodeChanges,\n Connection,\n type EdgeChange,\n type NodeChange,\n} from '@xyflow/react';\nimport {produce} from 'immer';\nimport {z} from 'zod';\n\nconst DEFAULT_NODE_WIDTH = 800;\nconst DEFAULT_NODE_HEIGHT = 600;\nconst CANVAS_SCHEMA_NAME = 'canvas';\nconst VIEWPORT_EPSILON = 0.1;\n\n/** View metadata for a single node on the canvas */\nexport const CanvasNodeMeta = z.object({\n id: z.string(),\n position: z.object({x: z.number(), y: z.number()}),\n width: z.number().default(DEFAULT_NODE_WIDTH),\n height: z.number().default(DEFAULT_NODE_HEIGHT),\n data: z.record(z.string(), z.any()).default({}), // Required by ReactFlow NodeBase\n});\nexport type CanvasNodeMeta = z.infer<typeof CanvasNodeMeta>;\n\n/** View metadata for a canvas artifact. */\nexport const CanvasArtifactMeta = z.object({\n viewport: z.object({\n x: z.number(),\n y: z.number(),\n zoom: z.number(),\n }),\n nodeOrder: z.array(z.string()).default([]),\n});\nexport type CanvasArtifactMeta = z.infer<typeof CanvasArtifactMeta>;\n\nconst CanvasArtifactRuntime = z.object({\n id: z.string(),\n nodes: z.record(z.string(), CanvasNodeMeta).default({}),\n meta: CanvasArtifactMeta,\n});\n\nexport const CanvasSliceConfig = z.object({\n artifacts: z.record(z.string(), CanvasArtifactRuntime).default({}),\n});\nexport type CanvasSliceConfig = z.infer<typeof CanvasSliceConfig>;\n\nexport type CanvasSliceState = {\n canvas: {\n config: CanvasSliceConfig;\n initialize: () => Promise<void>;\n setConfig: (config: CanvasSliceConfig) => void;\n ensureArtifact: (artifactId: string) => void;\n removeArtifact: (artifactId: string) => void;\n setViewport: (artifactId: string, viewport: Viewport) => void;\n\n addNode: (params: {\n artifactId: string;\n nodeType?: string;\n initialPosition?: XYPosition;\n parentId?: string;\n }) => Promise<string>;\n\n renameNode: (nodeId: string, newTitle: string) => Promise<void>;\n updateNode: (\n nodeId: string,\n updater: (cell: Cell) => Cell,\n ) => Promise<void>;\n deleteNode: (nodeId: string) => void;\n\n applyNodeChanges: (\n artifactId: string,\n changes: NodeChange<CanvasNodeMeta>[],\n ) => void;\n applyEdgeChanges: (changes: EdgeChange<any>[]) => void;\n addEdge: (edge: Connection) => void;\n\n executeSqlNodeQuery: (\n nodeId: string,\n opts?: {cascade?: boolean},\n ) => Promise<void>;\n };\n};\n\nfunction getArtifact(config: CanvasSliceConfig, artifactId: string) {\n return config.artifacts[artifactId];\n}\n\nfunction ensureCanvasArtifactMeta(\n config: CanvasSliceConfig,\n artifactId: string,\n viewport: Viewport = {x: 0, y: 0, zoom: 1},\n) {\n let artifact = config.artifacts[artifactId];\n if (!artifact) {\n artifact = {\n id: artifactId,\n nodes: {},\n meta: {\n viewport,\n nodeOrder: [],\n },\n };\n config.artifacts[artifactId] = artifact;\n }\n return artifact;\n}\n\nfunction isSameViewport(a: Viewport, b: Viewport) {\n return (\n Math.abs(a.x - b.x) < VIEWPORT_EPSILON &&\n Math.abs(a.y - b.y) < VIEWPORT_EPSILON &&\n Math.abs(a.zoom - b.zoom) < VIEWPORT_EPSILON\n );\n}\n\nexport function createDefaultCanvasConfig(\n props?: Partial<CanvasSliceConfig>,\n): CanvasSliceConfig {\n const base: CanvasSliceConfig = {\n artifacts: {},\n };\n\n return {...base, ...props};\n}\n\nexport function createCanvasSlice(\n props: {config?: Partial<CanvasSliceConfig>} = {},\n) {\n type CanvasRootState = BaseRoomStoreState &\n DuckDbSliceState &\n CanvasSliceState &\n CellsRootState;\n\n return createSlice<CanvasSliceState, CanvasRootState>((set, get, store) => {\n return {\n canvas: {\n config: createDefaultCanvasConfig(props.config),\n setConfig: (config: CanvasSliceConfig) => {\n set((state: CanvasRootState) =>\n produce(state, (draft: CanvasRootState) => {\n draft.canvas.config = config;\n }),\n );\n },\n\n ensureArtifact: (artifactId) => {\n get().cells.ensureArtifact(artifactId);\n set((state: CanvasRootState) =>\n produce(state, (draft: CanvasRootState) => {\n ensureCanvasArtifactMeta(draft.canvas.config, artifactId);\n }),\n );\n },\n\n removeArtifact: (artifactId) => {\n get().cells.removeArtifact(artifactId);\n set((state: CanvasRootState) =>\n produce(state, (draft: CanvasRootState) => {\n delete draft.canvas.config.artifacts[artifactId];\n }),\n );\n },\n\n async initialize() {\n // no-op: host apps should call artifact-scoped runtime explicitly\n },\n\n addNode: async ({\n artifactId,\n nodeType = 'sql',\n initialPosition,\n parentId,\n }: {\n artifactId: string;\n nodeType?: string;\n initialPosition?: XYPosition;\n parentId?: string;\n }) => {\n const newId = createId();\n const registry = get().cells.cellRegistry;\n const reg = registry[nodeType];\n if (!reg) return newId;\n\n // 1. Create the cell in CellsSlice\n const cell = reg.createCell({id: newId, get, set}) as Cell;\n\n const existingTitles = Object.values(get().cells.config.data).map(\n (c) => {\n const title = (c.data as Record<string, unknown>).title;\n return typeof title === 'string' ? title : '';\n },\n );\n (cell.data as Record<string, unknown>).title = generateUniqueName(\n `${reg.title} 1`,\n existingTitles,\n ' ',\n );\n\n get().cells.ensureArtifact(artifactId);\n await get().cells.addCell(artifactId, cell);\n\n // 2. If parent exists, add an edge in CellsSlice\n if (parentId) {\n get().cells.addEdge(artifactId, {source: parentId, target: newId});\n }\n\n // 3. Update view-specific metadata\n set((state: CanvasRootState) =>\n produce(state, (draft: CanvasRootState) => {\n let artifact = getArtifact(draft.canvas.config, artifactId);\n artifact = ensureCanvasArtifactMeta(\n draft.canvas.config,\n artifactId,\n );\n\n const parentNode = parentId\n ? artifact.nodes[parentId]\n : undefined;\n const position: XYPosition = initialPosition\n ? initialPosition\n : parentNode\n ? {\n x: parentNode.position.x + parentNode.width + 100,\n y: parentNode.position.y,\n }\n : {\n x: artifact.meta.viewport.x + 100,\n y: artifact.meta.viewport.y + 100,\n };\n\n artifact.nodes[newId] = {\n id: newId,\n position,\n width: DEFAULT_NODE_WIDTH,\n height: DEFAULT_NODE_HEIGHT,\n data: {},\n };\n artifact.meta.nodeOrder.push(newId);\n }),\n );\n return newId;\n },\n\n renameNode: async (nodeId: string, newTitle: string) => {\n await get().cells.updateCell(nodeId, (c) =>\n produce(c, (draft) => {\n (draft.data as Record<string, unknown>).title = newTitle;\n }),\n );\n },\n\n updateNode: async (nodeId: string, updater: (cell: Cell) => Cell) => {\n await get().cells.updateCell(nodeId, updater);\n },\n\n deleteNode: (nodeId: string) => {\n get().cells.removeCell(nodeId);\n set((state: CanvasRootState) =>\n produce(state, (draft: CanvasRootState) => {\n for (const artifact of Object.values(\n draft.canvas.config.artifacts,\n )) {\n delete artifact.nodes[nodeId];\n artifact.meta.nodeOrder = artifact.meta.nodeOrder.filter(\n (id) => id !== nodeId,\n );\n }\n }),\n );\n },\n\n applyNodeChanges: (\n artifactId: string,\n changes: NodeChange<CanvasNodeMeta>[],\n ) => {\n set((state: CanvasRootState) =>\n produce(state, (draft: CanvasRootState) => {\n const artifact = ensureCanvasArtifactMeta(\n draft.canvas.config,\n artifactId,\n );\n\n // Ensure all cells from CellsSlice have a node entry in CanvasSlice\n const cellsArtifact = draft.cells.config.artifacts[artifactId];\n if (cellsArtifact) {\n for (const cellId of cellsArtifact.cellIds) {\n if (!artifact.nodes[cellId]) {\n artifact.nodes[cellId] = {\n id: cellId,\n position: {x: 100, y: 100},\n width: DEFAULT_NODE_WIDTH,\n height: DEFAULT_NODE_HEIGHT,\n data: {},\n };\n artifact.meta.nodeOrder.push(cellId);\n }\n }\n }\n\n const nodesArray = artifact.meta.nodeOrder\n .map((id) => artifact.nodes[id])\n .filter(Boolean) as CanvasNodeMeta[];\n const updated = applyNodeChanges(changes, nodesArray);\n artifact.nodes = updated.reduce<Record<string, CanvasNodeMeta>>(\n (acc, node) => {\n acc[node.id] = node;\n return acc;\n },\n {},\n );\n artifact.meta.nodeOrder = updated.map((n) => n.id);\n }),\n );\n },\n\n applyEdgeChanges: (changes: EdgeChange<any>[]) => {\n // Canvas edge editing is intentionally disabled for now.\n // Compatibility no-op: keep API stable until edge kinds are introduced.\n void changes;\n },\n\n addEdge: (connection: Connection) => {\n // Canvas edge editing is intentionally disabled for now.\n // Compatibility no-op: dependency edges are derived from graph cache.\n void connection;\n },\n\n setViewport: (artifactId: string, viewport: Viewport) => {\n const existing = get().canvas.config.artifacts[artifactId];\n if (existing && isSameViewport(existing.meta.viewport, viewport)) {\n return;\n }\n set((state: CanvasRootState) =>\n produce(state, (draft: CanvasRootState) => {\n let artifact = getArtifact(draft.canvas.config, artifactId);\n artifact = ensureCanvasArtifactMeta(\n draft.canvas.config,\n artifactId,\n viewport,\n );\n artifact.meta.viewport = viewport;\n }),\n );\n },\n\n executeSqlNodeQuery: async (\n nodeId: string,\n opts?: {cascade?: boolean},\n ) => {\n await get().cells.runCell(nodeId, {\n ...opts,\n schemaName: CANVAS_SCHEMA_NAME,\n });\n },\n },\n };\n });\n}\n\nexport type DuckDbSliceStateWithCanvas = DuckDbSliceState &\n CanvasSliceState &\n CellsRootState;\n\nexport function useStoreWithCanvas<T>(\n selector: (state: DuckDbSliceStateWithCanvas) => T,\n): T {\n return useBaseRoomStore<BaseRoomStoreState, T>((state) =>\n selector(state as unknown as DuckDbSliceStateWithCanvas),\n );\n}\n"]}
|
package/dist/crdt.d.ts
CHANGED
|
@@ -5,12 +5,12 @@ import { type CanvasSliceState } from './CanvasSlice';
|
|
|
5
5
|
*/
|
|
6
6
|
export declare const canvasMirrorSchema: import("loro-mirror").LoroMapSchema<{
|
|
7
7
|
config: import("loro-mirror").LoroMapSchema<{
|
|
8
|
-
|
|
8
|
+
artifacts: /*elided*/ any;
|
|
9
9
|
}> & {
|
|
10
10
|
options: {};
|
|
11
11
|
} & {
|
|
12
12
|
catchall: <C extends import("loro-mirror").SchemaType>(catchallSchema: C) => import("loro-mirror").LoroMapSchemaWithCatchall<{
|
|
13
|
-
|
|
13
|
+
artifacts: /*elided*/ any;
|
|
14
14
|
}, C>;
|
|
15
15
|
};
|
|
16
16
|
}> & {
|
|
@@ -18,12 +18,12 @@ export declare const canvasMirrorSchema: import("loro-mirror").LoroMapSchema<{
|
|
|
18
18
|
} & {
|
|
19
19
|
catchall: <C extends import("loro-mirror").SchemaType>(catchallSchema: C) => import("loro-mirror").LoroMapSchemaWithCatchall<{
|
|
20
20
|
config: import("loro-mirror").LoroMapSchema<{
|
|
21
|
-
|
|
21
|
+
artifacts: /*elided*/ any;
|
|
22
22
|
}> & {
|
|
23
23
|
options: {};
|
|
24
24
|
} & {
|
|
25
25
|
catchall: <C_1 extends import("loro-mirror").SchemaType>(catchallSchema: C_1) => import("loro-mirror").LoroMapSchemaWithCatchall<{
|
|
26
|
-
|
|
26
|
+
artifacts: /*elided*/ any;
|
|
27
27
|
}, C_1>;
|
|
28
28
|
};
|
|
29
29
|
}, C>;
|
|
@@ -34,7 +34,7 @@ export type CanvasMirrorSchema = typeof canvasMirrorSchema;
|
|
|
34
34
|
*/
|
|
35
35
|
export declare const canvasMirrorInitialState: {
|
|
36
36
|
config: {
|
|
37
|
-
|
|
37
|
+
artifacts: never[];
|
|
38
38
|
};
|
|
39
39
|
};
|
|
40
40
|
/**
|
package/dist/crdt.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crdt.d.ts","sourceRoot":"","sources":["../src/crdt.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAoB,KAAK,gBAAgB,EAAC,MAAM,eAAe,CAAC;AAEvE;;GAEG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;CAyB7B,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,OAAO,kBAAkB,CAAC;AAE3D;;GAEG;AACH,eAAO,MAAM,wBAAwB;;;;CAIpC,CAAC;AAEF;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,CAAC,SAAS,gBAAgB,GAAG,gBAAgB,KAC1C,UAAU,CAAC,CAAC,EAAE,OAAO,kBAAkB,CAAC,
|
|
1
|
+
{"version":3,"file":"crdt.d.ts","sourceRoot":"","sources":["../src/crdt.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAoB,KAAK,gBAAgB,EAAC,MAAM,eAAe,CAAC;AAEvE;;GAEG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;CAyB7B,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,OAAO,kBAAkB,CAAC;AAE3D;;GAEG;AACH,eAAO,MAAM,wBAAwB;;;;CAIpC,CAAC;AAEF;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,CAAC,SAAS,gBAAgB,GAAG,gBAAgB,KAC1C,UAAU,CAAC,CAAC,EAAE,OAAO,kBAAkB,CAAC,CAqD5C;AAED;;GAEG;AACH,eAAO,MAAM,sBAAsB,+BAAyB,CAAC"}
|