@sqlrooms/canvas 0.29.0-rc.1 → 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 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`, `CanvasSheetMeta`
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
@@ -1,4 +1,6 @@
1
1
  import '@xyflow/react/dist/style.css';
2
2
  import React from 'react';
3
- export declare const Canvas: React.FC;
3
+ export declare const Canvas: React.FC<{
4
+ artifactId: string;
5
+ }>;
4
6
  //# sourceMappingURL=Canvas.d.ts.map
@@ -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,EAuH1B,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
- const sheetId = currentSheetId ?? s.cells.config.sheetOrder[0];
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
- const sheetId = currentSheetId ?? s.cells.config.sheetOrder[0];
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
@@ -1 +1 @@
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 = () => {\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 currentSheetId = useStoreWithCanvas(\n (s) => s.cells.config.currentSheetId,\n );\n const addSheet = useStoreWithCanvas((s) => s.cells.addSheet);\n\n const canvasSheet = useStoreWithCanvas((s) => {\n const sheetId = currentSheetId ?? s.cells.config.sheetOrder[0];\n return sheetId ? s.canvas.config.sheets[sheetId] : undefined;\n });\n\n const cellsSheet = useStoreWithCanvas((s) => {\n const sheetId = currentSheetId ?? s.cells.config.sheetOrder[0];\n return sheetId ? s.cells.config.sheets[sheetId] : undefined;\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(viewport);\n }, 150);\n },\n [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>\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={applyNodeChanges}\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"]}
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"]}
@@ -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 sheet (canvas view) */
19
- export declare const CanvasSheetMeta: z.ZodObject<{
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 CanvasSheetMeta = z.infer<typeof CanvasSheetMeta>;
27
+ export type CanvasArtifactMeta = z.infer<typeof CanvasArtifactMeta>;
28
28
  export declare const CanvasSliceConfig: z.ZodObject<{
29
- sheets: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
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
- setViewport: (viewport: Viewport) => void;
58
- getCanvasSheets: () => Record<string, import('@sqlrooms/cells').Sheet>;
57
+ ensureArtifact: (artifactId: string) => void;
58
+ removeArtifact: (artifactId: string) => void;
59
+ setViewport: (artifactId: string, viewport: Viewport) => void;
59
60
  addNode: (params: {
60
- sheetId: string;
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":"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"}
1
+ {"version":3,"file":"CanvasSlice.d.ts","sourceRoot":"","sources":["../src/CanvasSlice.ts"],"names":[],"mappings":"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"}
@@ -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 sheet (canvas view) */
21
- export const CanvasSheetMeta = z.object({
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
- sheets: z
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 getSheet(config, sheetId) {
39
- return config.sheets[sheetId];
36
+ function getArtifact(config, artifactId) {
37
+ return config.artifacts[artifactId];
40
38
  }
41
- function ensureCanvasSheetMeta(config, sheetId, viewport = { x: 0, y: 0, zoom: 1 }) {
42
- let sheet = config.sheets[sheetId];
43
- if (!sheet) {
44
- sheet = {
45
- id: sheetId,
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.sheets[sheetId] = sheet;
50
+ config.artifacts[artifactId] = artifact;
53
51
  }
54
- return sheet;
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
- sheets: {},
61
+ artifacts: {},
64
62
  };
65
63
  return { ...base, ...props };
66
64
  }
@@ -74,38 +72,47 @@ export function createCanvasSlice(props = {}) {
74
72
  draft.canvas.config = config;
75
73
  }));
76
74
  },
77
- getCanvasSheets: () => getSheetsByType(get(), 'canvas'),
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
- const sheetId = get().cells.config.currentSheetId ||
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 ({ sheetId, nodeType = 'sql', initialPosition, parentId, }) => {
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];
90
94
  if (!reg)
91
95
  return newId;
92
96
  // 1. Create the cell in CellsSlice
93
- const cell = reg.createCell(newId);
97
+ const cell = reg.createCell({ id: newId, get, set });
94
98
  const existingTitles = Object.values(get().cells.config.data).map((c) => {
95
99
  const title = c.data.title;
96
100
  return typeof title === 'string' ? title : '';
97
101
  });
98
102
  cell.data.title = generateUniqueName(`${reg.title} 1`, existingTitles, ' ');
99
- await get().cells.addCell(sheetId, cell);
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(sheetId, { source: parentId, target: newId });
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 sheet = getSheet(draft.canvas.config, sheetId);
107
- sheet = ensureCanvasSheetMeta(draft.canvas.config, sheetId);
108
- const parentNode = parentId ? sheet.nodes[parentId] : undefined;
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: sheet.meta.viewport.x + 100,
118
- y: sheet.meta.viewport.y + 100,
124
+ x: artifact.meta.viewport.x + 100,
125
+ y: artifact.meta.viewport.y + 100,
119
126
  };
120
- sheet.nodes[newId] = {
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
- sheet.meta.nodeOrder.push(newId);
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 sheet of Object.values(draft.canvas.config.sheets)) {
143
- delete sheet.nodes[nodeId];
144
- sheet.meta.nodeOrder = sheet.meta.nodeOrder.filter((id) => id !== nodeId);
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 sheetId = draft.cells.config.currentSheetId;
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 cellsSheet = draft.cells.config.sheets[sheetId];
156
- if (cellsSheet) {
157
- for (const cellId of cellsSheet.cellIds) {
158
- if (!sheet.nodes[cellId]) {
159
- sheet.nodes[cellId] = {
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
- sheet.meta.nodeOrder.push(cellId);
170
+ artifact.meta.nodeOrder.push(cellId);
167
171
  }
168
172
  }
169
173
  }
170
- const nodesArray = sheet.meta.nodeOrder
171
- .map((id) => sheet.nodes[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
- sheet.nodes = updated.reduce((acc, node) => {
178
+ artifact.nodes = updated.reduce((acc, node) => {
175
179
  acc[node.id] = node;
176
180
  return acc;
177
181
  }, {});
178
- sheet.meta.nodeOrder = updated.map((n) => n.id);
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 sheetId = get().cells.config.currentSheetId;
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 sheet = getSheet(draft.canvas.config, sheetId);
201
- sheet = ensureCanvasSheetMeta(draft.canvas.config, sheetId, viewport);
202
- sheet.meta.viewport = viewport;
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) => {
@@ -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(newId) 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":"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","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
- sheets: /*elided*/ any;
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
- sheets: /*elided*/ any;
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
- sheets: /*elided*/ any;
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
- sheets: /*elided*/ any;
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
- sheets: never[];
37
+ artifacts: never[];
38
38
  };
39
39
  };
40
40
  /**
@@ -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,CAmD5C;AAED;;GAEG;AACH,eAAO,MAAM,sBAAsB,+BAAyB,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"}
package/dist/crdt.js CHANGED
@@ -5,7 +5,7 @@ import { CanvasSliceConfig } from './CanvasSlice';
5
5
  */
6
6
  export const canvasMirrorSchema = schema.LoroMap({
7
7
  config: schema.LoroMap({
8
- sheets: schema.LoroList(schema.LoroMap({
8
+ artifacts: schema.LoroList(schema.LoroMap({
9
9
  id: schema.String(),
10
10
  nodes: schema.LoroList(schema.LoroMap({
11
11
  id: schema.String(),
@@ -20,7 +20,7 @@ export const canvasMirrorSchema = schema.LoroMap({
20
20
  nodeOrder: schema.LoroList(schema.String()),
21
21
  // viewport is kept local (unsynced)
22
22
  }),
23
- }), (sheet) => sheet.id),
23
+ }), (artifact) => artifact.id),
24
24
  }),
25
25
  });
26
26
  /**
@@ -28,7 +28,7 @@ export const canvasMirrorSchema = schema.LoroMap({
28
28
  */
29
29
  export const canvasMirrorInitialState = {
30
30
  config: {
31
- sheets: [],
31
+ artifacts: [],
32
32
  },
33
33
  };
34
34
  /**
@@ -40,11 +40,11 @@ export function createCanvasCrdtMirror() {
40
40
  initialState: canvasMirrorInitialState,
41
41
  select: (state) => ({
42
42
  config: {
43
- sheets: Object.values(state.canvas.config.sheets).map((sheet) => ({
44
- id: sheet.id,
45
- nodes: Object.values(sheet.nodes),
43
+ artifacts: Object.values(state.canvas.config.artifacts).map((artifact) => ({
44
+ id: artifact.id,
45
+ nodes: Object.values(artifact.nodes),
46
46
  meta: {
47
- nodeOrder: sheet.meta.nodeOrder,
47
+ nodeOrder: artifact.meta.nodeOrder,
48
48
  },
49
49
  })),
50
50
  },
@@ -53,19 +53,19 @@ export function createCanvasCrdtMirror() {
53
53
  if (!value?.config)
54
54
  return;
55
55
  const currentConfig = get().canvas.config;
56
- const newSheets = {};
57
- for (const sheetValue of value.config.sheets || []) {
58
- const localSheet = currentConfig.sheets[sheetValue.id];
59
- newSheets[sheetValue.id] = {
60
- id: sheetValue.id,
61
- nodes: (sheetValue.nodes || []).reduce((acc, node) => {
56
+ const newArtifacts = {};
57
+ for (const artifactValue of value.config.artifacts || []) {
58
+ const localArtifact = currentConfig.artifacts[artifactValue.id];
59
+ newArtifacts[artifactValue.id] = {
60
+ id: artifactValue.id,
61
+ nodes: (artifactValue.nodes || []).reduce((acc, node) => {
62
62
  acc[node.id] = node;
63
63
  return acc;
64
64
  }, {}),
65
65
  meta: {
66
- ...sheetValue.meta,
66
+ ...artifactValue.meta,
67
67
  // Keep local viewport or use default
68
- viewport: localSheet?.meta.viewport ?? { x: 0, y: 0, zoom: 1 },
68
+ viewport: localArtifact?.meta.viewport ?? { x: 0, y: 0, zoom: 1 },
69
69
  },
70
70
  };
71
71
  }
@@ -75,7 +75,7 @@ export function createCanvasCrdtMirror() {
75
75
  ...state.canvas,
76
76
  config: CanvasSliceConfig.parse({
77
77
  ...currentConfig,
78
- sheets: newSheets,
78
+ artifacts: newArtifacts,
79
79
  }),
80
80
  },
81
81
  }));
package/dist/crdt.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"crdt.js","sourceRoot":"","sources":["../src/crdt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AAEnC,OAAO,EAAC,iBAAiB,EAAwB,MAAM,eAAe,CAAC;AAEvE;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC,OAAO,CAAC;IAC/C,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC;QACrB,MAAM,EAAE,MAAM,CAAC,QAAQ,CACrB,MAAM,CAAC,OAAO,CAAC;YACb,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE;YACnB,KAAK,EAAE,MAAM,CAAC,QAAQ,CACpB,MAAM,CAAC,OAAO,CAAC;gBACb,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE;gBACnB,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC;oBACvB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;oBAClB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;iBACnB,CAAC;gBACF,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE;gBACtB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;aACxB,CAAC,EACF,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAClB;YACD,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC;gBACnB,SAAS,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;gBAC3C,oCAAoC;aACrC,CAAC;SACH,CAAC,EACF,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CACpB;KACF,CAAC;CACH,CAAC,CAAC;AAIH;;GAEG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,MAAM,EAAE;QACN,MAAM,EAAE,EAAE;KACX;CACF,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,sBAAsB;IAGpC,OAAO;QACL,MAAM,EAAE,kBAAkB;QAC1B,YAAY,EAAE,wBAAwB;QACtC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAClB,MAAM,EAAE;gBACN,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;oBAChE,EAAE,EAAE,KAAK,CAAC,EAAE;oBACZ,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC;oBACjC,IAAI,EAAE;wBACJ,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,SAAS;qBAChC;iBACF,CAAC,CAAC;aACJ;SACF,CAAC;QACF,KAAK,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;YACzB,IAAI,CAAC,KAAK,EAAE,MAAM;gBAAE,OAAO;YAC3B,MAAM,aAAa,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC;YAE1C,MAAM,SAAS,GAAwB,EAAE,CAAC;YAC1C,KAAK,MAAM,UAAU,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;gBACnD,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;gBACvD,SAAS,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG;oBACzB,EAAE,EAAE,UAAU,CAAC,EAAE;oBACjB,KAAK,EAAE,CAAC,UAAU,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,CACpC,CAAC,GAAwB,EAAE,IAAS,EAAE,EAAE;wBACtC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC;wBACpB,OAAO,GAAG,CAAC;oBACb,CAAC,EACD,EAAE,CACH;oBACD,IAAI,EAAE;wBACJ,GAAG,UAAU,CAAC,IAAI;wBAClB,qCAAqC;wBACrC,QAAQ,EAAE,UAAU,EAAE,IAAI,CAAC,QAAQ,IAAI,EAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAC;qBAC7D;iBACF,CAAC;YACJ,CAAC;YAED,GAAG,CAAC,CAAC,KAAQ,EAAE,EAAE,CAAC,CAAC;gBACjB,GAAG,KAAK;gBACR,MAAM,EAAE;oBACN,GAAG,KAAK,CAAC,MAAM;oBACf,MAAM,EAAE,iBAAiB,CAAC,KAAK,CAAC;wBAC9B,GAAG,aAAa;wBAChB,MAAM,EAAE,SAAS;qBAClB,CAAC;iBACH;aACF,CAAC,CAAC,CAAC;QACN,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,sBAAsB,CAAC","sourcesContent":["import {schema} from 'loro-mirror';\nimport type {CrdtMirror} from '@sqlrooms/crdt';\nimport {CanvasSliceConfig, type CanvasSliceState} from './CanvasSlice';\n\n/**\n * Mirror schema for syncing the `@sqlrooms/canvas` slice via `@sqlrooms/crdt`.\n */\nexport const canvasMirrorSchema = schema.LoroMap({\n config: schema.LoroMap({\n sheets: schema.LoroList(\n schema.LoroMap({\n id: schema.String(),\n nodes: schema.LoroList(\n schema.LoroMap({\n id: schema.String(),\n position: schema.LoroMap({\n x: schema.Number(),\n y: schema.Number(),\n }),\n width: schema.Number(),\n height: schema.Number(),\n }),\n (node) => node.id,\n ),\n meta: schema.LoroMap({\n nodeOrder: schema.LoroList(schema.String()),\n // viewport is kept local (unsynced)\n }),\n }),\n (sheet) => sheet.id,\n ),\n }),\n});\n\nexport type CanvasMirrorSchema = typeof canvasMirrorSchema;\n\n/**\n * Default initial mirror state for the canvas CRDT schema.\n */\nexport const canvasMirrorInitialState = {\n config: {\n sheets: [],\n },\n};\n\n/**\n * Creates a CRDT mirror bundle for the canvas slice.\n */\nexport function createCanvasCrdtMirror<\n S extends CanvasSliceState = CanvasSliceState,\n>(): CrdtMirror<S, typeof canvasMirrorSchema> {\n return {\n schema: canvasMirrorSchema,\n initialState: canvasMirrorInitialState,\n select: (state) => ({\n config: {\n sheets: Object.values(state.canvas.config.sheets).map((sheet) => ({\n id: sheet.id,\n nodes: Object.values(sheet.nodes),\n meta: {\n nodeOrder: sheet.meta.nodeOrder,\n },\n })),\n },\n }),\n apply: (value, set, get) => {\n if (!value?.config) return;\n const currentConfig = get().canvas.config;\n\n const newSheets: Record<string, any> = {};\n for (const sheetValue of value.config.sheets || []) {\n const localSheet = currentConfig.sheets[sheetValue.id];\n newSheets[sheetValue.id] = {\n id: sheetValue.id,\n nodes: (sheetValue.nodes || []).reduce(\n (acc: Record<string, any>, node: any) => {\n acc[node.id] = node;\n return acc;\n },\n {},\n ),\n meta: {\n ...sheetValue.meta,\n // Keep local viewport or use default\n viewport: localSheet?.meta.viewport ?? {x: 0, y: 0, zoom: 1},\n },\n };\n }\n\n set((state: S) => ({\n ...state,\n canvas: {\n ...state.canvas,\n config: CanvasSliceConfig.parse({\n ...currentConfig,\n sheets: newSheets,\n }),\n },\n }));\n },\n };\n}\n\n/**\n * @deprecated Use `createCanvasCrdtMirror` instead.\n */\nexport const createCanvasCrdtModule = createCanvasCrdtMirror;\n"]}
1
+ {"version":3,"file":"crdt.js","sourceRoot":"","sources":["../src/crdt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AAEnC,OAAO,EAAC,iBAAiB,EAAwB,MAAM,eAAe,CAAC;AAEvE;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC,OAAO,CAAC;IAC/C,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC;QACrB,SAAS,EAAE,MAAM,CAAC,QAAQ,CACxB,MAAM,CAAC,OAAO,CAAC;YACb,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE;YACnB,KAAK,EAAE,MAAM,CAAC,QAAQ,CACpB,MAAM,CAAC,OAAO,CAAC;gBACb,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE;gBACnB,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC;oBACvB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;oBAClB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;iBACnB,CAAC;gBACF,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE;gBACtB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;aACxB,CAAC,EACF,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAClB;YACD,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC;gBACnB,SAAS,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;gBAC3C,oCAAoC;aACrC,CAAC;SACH,CAAC,EACF,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,EAAE,CAC1B;KACF,CAAC;CACH,CAAC,CAAC;AAIH;;GAEG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,MAAM,EAAE;QACN,SAAS,EAAE,EAAE;KACd;CACF,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,sBAAsB;IAGpC,OAAO;QACL,MAAM,EAAE,kBAAkB;QAC1B,YAAY,EAAE,wBAAwB;QACtC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAClB,MAAM,EAAE;gBACN,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,CACzD,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;oBACb,EAAE,EAAE,QAAQ,CAAC,EAAE;oBACf,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;oBACpC,IAAI,EAAE;wBACJ,SAAS,EAAE,QAAQ,CAAC,IAAI,CAAC,SAAS;qBACnC;iBACF,CAAC,CACH;aACF;SACF,CAAC;QACF,KAAK,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;YACzB,IAAI,CAAC,KAAK,EAAE,MAAM;gBAAE,OAAO;YAC3B,MAAM,aAAa,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC;YAE1C,MAAM,YAAY,GAAwB,EAAE,CAAC;YAC7C,KAAK,MAAM,aAAa,IAAI,KAAK,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,EAAE,CAAC;gBACzD,MAAM,aAAa,GAAG,aAAa,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;gBAChE,YAAY,CAAC,aAAa,CAAC,EAAE,CAAC,GAAG;oBAC/B,EAAE,EAAE,aAAa,CAAC,EAAE;oBACpB,KAAK,EAAE,CAAC,aAAa,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,CACvC,CAAC,GAAwB,EAAE,IAAS,EAAE,EAAE;wBACtC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC;wBACpB,OAAO,GAAG,CAAC;oBACb,CAAC,EACD,EAAE,CACH;oBACD,IAAI,EAAE;wBACJ,GAAG,aAAa,CAAC,IAAI;wBACrB,qCAAqC;wBACrC,QAAQ,EAAE,aAAa,EAAE,IAAI,CAAC,QAAQ,IAAI,EAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAC;qBAChE;iBACF,CAAC;YACJ,CAAC;YAED,GAAG,CAAC,CAAC,KAAQ,EAAE,EAAE,CAAC,CAAC;gBACjB,GAAG,KAAK;gBACR,MAAM,EAAE;oBACN,GAAG,KAAK,CAAC,MAAM;oBACf,MAAM,EAAE,iBAAiB,CAAC,KAAK,CAAC;wBAC9B,GAAG,aAAa;wBAChB,SAAS,EAAE,YAAY;qBACxB,CAAC;iBACH;aACF,CAAC,CAAC,CAAC;QACN,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,sBAAsB,CAAC","sourcesContent":["import {schema} from 'loro-mirror';\nimport type {CrdtMirror} from '@sqlrooms/crdt';\nimport {CanvasSliceConfig, type CanvasSliceState} from './CanvasSlice';\n\n/**\n * Mirror schema for syncing the `@sqlrooms/canvas` slice via `@sqlrooms/crdt`.\n */\nexport const canvasMirrorSchema = schema.LoroMap({\n config: schema.LoroMap({\n artifacts: schema.LoroList(\n schema.LoroMap({\n id: schema.String(),\n nodes: schema.LoroList(\n schema.LoroMap({\n id: schema.String(),\n position: schema.LoroMap({\n x: schema.Number(),\n y: schema.Number(),\n }),\n width: schema.Number(),\n height: schema.Number(),\n }),\n (node) => node.id,\n ),\n meta: schema.LoroMap({\n nodeOrder: schema.LoroList(schema.String()),\n // viewport is kept local (unsynced)\n }),\n }),\n (artifact) => artifact.id,\n ),\n }),\n});\n\nexport type CanvasMirrorSchema = typeof canvasMirrorSchema;\n\n/**\n * Default initial mirror state for the canvas CRDT schema.\n */\nexport const canvasMirrorInitialState = {\n config: {\n artifacts: [],\n },\n};\n\n/**\n * Creates a CRDT mirror bundle for the canvas slice.\n */\nexport function createCanvasCrdtMirror<\n S extends CanvasSliceState = CanvasSliceState,\n>(): CrdtMirror<S, typeof canvasMirrorSchema> {\n return {\n schema: canvasMirrorSchema,\n initialState: canvasMirrorInitialState,\n select: (state) => ({\n config: {\n artifacts: Object.values(state.canvas.config.artifacts).map(\n (artifact) => ({\n id: artifact.id,\n nodes: Object.values(artifact.nodes),\n meta: {\n nodeOrder: artifact.meta.nodeOrder,\n },\n }),\n ),\n },\n }),\n apply: (value, set, get) => {\n if (!value?.config) return;\n const currentConfig = get().canvas.config;\n\n const newArtifacts: Record<string, any> = {};\n for (const artifactValue of value.config.artifacts || []) {\n const localArtifact = currentConfig.artifacts[artifactValue.id];\n newArtifacts[artifactValue.id] = {\n id: artifactValue.id,\n nodes: (artifactValue.nodes || []).reduce(\n (acc: Record<string, any>, node: any) => {\n acc[node.id] = node;\n return acc;\n },\n {},\n ),\n meta: {\n ...artifactValue.meta,\n // Keep local viewport or use default\n viewport: localArtifact?.meta.viewport ?? {x: 0, y: 0, zoom: 1},\n },\n };\n }\n\n set((state: S) => ({\n ...state,\n canvas: {\n ...state.canvas,\n config: CanvasSliceConfig.parse({\n ...currentConfig,\n artifacts: newArtifacts,\n }),\n },\n }));\n },\n };\n}\n\n/**\n * @deprecated Use `createCanvasCrdtMirror` instead.\n */\nexport const createCanvasCrdtModule = createCanvasCrdtMirror;\n"]}
@@ -1,3 +1,3 @@
1
- import { type Edge, type Sheet } from '@sqlrooms/cells';
2
- export declare function getRenderableEdges(sheet: Sheet | undefined): Edge[];
1
+ import { type Edge, type CellArtifactRuntime } from '@sqlrooms/cells';
2
+ export declare function getRenderableEdges(artifact: CellArtifactRuntime | undefined): Edge[];
3
3
  //# sourceMappingURL=edgeUtils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"edgeUtils.d.ts","sourceRoot":"","sources":["../src/edgeUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,IAAI,EACT,KAAK,KAAK,EACX,MAAM,iBAAiB,CAAC;AAEzB,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG,SAAS,GAAG,IAAI,EAAE,CAGnE"}
1
+ {"version":3,"file":"edgeUtils.d.ts","sourceRoot":"","sources":["../src/edgeUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,IAAI,EACT,KAAK,mBAAmB,EACzB,MAAM,iBAAiB,CAAC;AAEzB,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,mBAAmB,GAAG,SAAS,GACxC,IAAI,EAAE,CAGR"}
package/dist/edgeUtils.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { getRenderableDependencyEdges, } from '@sqlrooms/cells';
2
- export function getRenderableEdges(sheet) {
3
- if (!sheet)
2
+ export function getRenderableEdges(artifact) {
3
+ if (!artifact)
4
4
  return [];
5
- return getRenderableDependencyEdges(sheet);
5
+ return getRenderableDependencyEdges(artifact);
6
6
  }
7
7
  //# sourceMappingURL=edgeUtils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"edgeUtils.js","sourceRoot":"","sources":["../src/edgeUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,GAG7B,MAAM,iBAAiB,CAAC;AAEzB,MAAM,UAAU,kBAAkB,CAAC,KAAwB;IACzD,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,OAAO,4BAA4B,CAAC,KAAK,CAAC,CAAC;AAC7C,CAAC","sourcesContent":["import {\n getRenderableDependencyEdges,\n type Edge,\n type Sheet,\n} from '@sqlrooms/cells';\n\nexport function getRenderableEdges(sheet: Sheet | undefined): Edge[] {\n if (!sheet) return [];\n return getRenderableDependencyEdges(sheet);\n}\n"]}
1
+ {"version":3,"file":"edgeUtils.js","sourceRoot":"","sources":["../src/edgeUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,GAG7B,MAAM,iBAAiB,CAAC;AAEzB,MAAM,UAAU,kBAAkB,CAChC,QAAyC;IAEzC,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,CAAC;IACzB,OAAO,4BAA4B,CAAC,QAAQ,CAAC,CAAC;AAChD,CAAC","sourcesContent":["import {\n getRenderableDependencyEdges,\n type Edge,\n type CellArtifactRuntime,\n} from '@sqlrooms/cells';\n\nexport function getRenderableEdges(\n artifact: CellArtifactRuntime | undefined,\n): Edge[] {\n if (!artifact) return [];\n return getRenderableDependencyEdges(artifact);\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -4,6 +4,6 @@
4
4
  */
5
5
  export { createCanvasSlice, createDefaultCanvasConfig } from './CanvasSlice';
6
6
  export type { CanvasSliceState } from './CanvasSlice';
7
- export { CanvasSliceConfig, CanvasNodeMeta, CanvasSheetMeta, } from './CanvasSlice';
7
+ export { CanvasSliceConfig, CanvasNodeMeta, CanvasArtifactMeta, } from './CanvasSlice';
8
8
  export { Canvas } from './Canvas';
9
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAC,iBAAiB,EAAE,yBAAyB,EAAC,MAAM,eAAe,CAAC;AAC3E,YAAY,EAAC,gBAAgB,EAAC,MAAM,eAAe,CAAC;AACpD,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,eAAe,GAChB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAC,iBAAiB,EAAE,yBAAyB,EAAC,MAAM,eAAe,CAAC;AAC3E,YAAY,EAAC,gBAAgB,EAAC,MAAM,eAAe,CAAC;AACpD,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,kBAAkB,GACnB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAC"}
package/dist/index.js CHANGED
@@ -3,6 +3,6 @@
3
3
  * @packageDocumentation
4
4
  */
5
5
  export { createCanvasSlice, createDefaultCanvasConfig } from './CanvasSlice';
6
- export { CanvasSliceConfig, CanvasNodeMeta, CanvasSheetMeta, } from './CanvasSlice';
6
+ export { CanvasSliceConfig, CanvasNodeMeta, CanvasArtifactMeta, } from './CanvasSlice';
7
7
  export { Canvas } from './Canvas';
8
8
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAC,iBAAiB,EAAE,yBAAyB,EAAC,MAAM,eAAe,CAAC;AAE3E,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,eAAe,GAChB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAC","sourcesContent":["/**\n * {@include ../README.md}\n * @packageDocumentation\n */\n\nexport {createCanvasSlice, createDefaultCanvasConfig} from './CanvasSlice';\nexport type {CanvasSliceState} from './CanvasSlice';\nexport {\n CanvasSliceConfig,\n CanvasNodeMeta,\n CanvasSheetMeta,\n} from './CanvasSlice';\nexport {Canvas} from './Canvas';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAC,iBAAiB,EAAE,yBAAyB,EAAC,MAAM,eAAe,CAAC;AAE3E,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,kBAAkB,GACnB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAC","sourcesContent":["/**\n * {@include ../README.md}\n * @packageDocumentation\n */\n\nexport {createCanvasSlice, createDefaultCanvasConfig} from './CanvasSlice';\nexport type {CanvasSliceState} from './CanvasSlice';\nexport {\n CanvasSliceConfig,\n CanvasNodeMeta,\n CanvasArtifactMeta,\n} from './CanvasSlice';\nexport {Canvas} from './Canvas';\n"]}
@@ -1,5 +1,6 @@
1
1
  import { FC, PropsWithChildren } from 'react';
2
2
  export declare const AddNodePopover: FC<PropsWithChildren<{
3
+ artifactId: string;
3
4
  className?: string;
4
5
  parentId?: string;
5
6
  }>>;
@@ -1 +1 @@
1
- {"version":3,"file":"AddNodePopover.d.ts","sourceRoot":"","sources":["../../src/nodes/AddNodePopover.tsx"],"names":[],"mappings":"AAQA,OAAO,EAAC,EAAE,EAAE,iBAAiB,EAAW,MAAM,OAAO,CAAC;AAGtD,eAAO,MAAM,cAAc,EAAE,EAAE,CAC7B,iBAAiB,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC,CAqCH,CAAC"}
1
+ {"version":3,"file":"AddNodePopover.d.ts","sourceRoot":"","sources":["../../src/nodes/AddNodePopover.tsx"],"names":[],"mappings":"AAQA,OAAO,EAAC,EAAE,EAAE,iBAAiB,EAAW,MAAM,OAAO,CAAC;AAGtD,eAAO,MAAM,cAAc,EAAE,EAAE,CAC7B,iBAAiB,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC,CAiCH,CAAC"}
@@ -1,23 +1,18 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Button, cn, Popover, PopoverContent, PopoverTrigger, useToast, } from '@sqlrooms/ui';
2
+ import { Button, cn, Popover, PopoverContent, PopoverTrigger, toast, } from '@sqlrooms/ui';
3
3
  import { useState } from 'react';
4
4
  import { useStoreWithCanvas } from '../CanvasSlice';
5
- export const AddNodePopover = ({ className, parentId, children }) => {
5
+ export const AddNodePopover = ({ artifactId, className, parentId, children }) => {
6
6
  const [open, setOpen] = useState(false);
7
7
  const addNode = useStoreWithCanvas((s) => s.canvas.addNode);
8
- const sheetId = useStoreWithCanvas((s) => s.cells.config.currentSheetId);
9
8
  const registry = useStoreWithCanvas((s) => s.cells.cellRegistry);
10
- const { toast } = useToast();
11
9
  const onAdd = (type) => {
12
- if (sheetId) {
13
- addNode({ sheetId, parentId, nodeType: type });
10
+ if (artifactId) {
11
+ addNode({ artifactId, parentId, nodeType: type });
14
12
  setOpen(false);
15
13
  }
16
14
  else {
17
- toast({
18
- variant: 'destructive',
19
- description: 'No sheet selected',
20
- });
15
+ toast.error('No artifact selected');
21
16
  }
22
17
  };
23
18
  return (_jsx("div", { className: cn(className), children: _jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: children }), _jsx(PopoverContent, { side: "right", align: "center", className: "flex w-auto flex-col gap-2 p-2", children: Object.entries(registry).map(([type, reg]) => (_jsx(Button, { size: "xs", onClick: () => onAdd(type), children: reg.title }, type))) })] }) }));
@@ -1 +1 @@
1
- {"version":3,"file":"AddNodePopover.js","sourceRoot":"","sources":["../../src/nodes/AddNodePopover.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,MAAM,EACN,EAAE,EACF,OAAO,EACP,cAAc,EACd,cAAc,EACd,QAAQ,GACT,MAAM,cAAc,CAAC;AACtB,OAAO,EAAwB,QAAQ,EAAC,MAAM,OAAO,CAAC;AACtD,OAAO,EAAC,kBAAkB,EAAC,MAAM,gBAAgB,CAAC;AAElD,MAAM,CAAC,MAAM,cAAc,GAKvB,CAAC,EAAC,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAC,EAAE,EAAE;IACtC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,OAAO,GAAG,kBAAkB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC5D,MAAM,OAAO,GAAG,kBAAkB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;IACzE,MAAM,QAAQ,GAAG,kBAAkB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACjE,MAAM,EAAC,KAAK,EAAC,GAAG,QAAQ,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,CAAC,IAAY,EAAE,EAAE;QAC7B,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,EAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAC,CAAC,CAAC;YAC7C,OAAO,CAAC,KAAK,CAAC,CAAC;QACjB,CAAC;aAAM,CAAC;YACN,KAAK,CAAC;gBACJ,OAAO,EAAE,aAAa;gBACtB,WAAW,EAAE,mBAAmB;aACjC,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,CACL,cAAK,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,YAC3B,MAAC,OAAO,IAAC,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,aACxC,KAAC,cAAc,IAAC,OAAO,kBAAE,QAAQ,GAAkB,EACnD,KAAC,cAAc,IACb,IAAI,EAAC,OAAO,EACZ,KAAK,EAAC,QAAQ,EACd,SAAS,EAAC,gCAAgC,YAEzC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAC7C,KAAC,MAAM,IAAY,IAAI,EAAC,IAAI,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,YACpD,GAAG,CAAC,KAAK,IADC,IAAI,CAER,CACV,CAAC,GACa,IACT,GACN,CACP,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import {\n Button,\n cn,\n Popover,\n PopoverContent,\n PopoverTrigger,\n useToast,\n} from '@sqlrooms/ui';\nimport {FC, PropsWithChildren, useState} from 'react';\nimport {useStoreWithCanvas} from '../CanvasSlice';\n\nexport const AddNodePopover: FC<\n PropsWithChildren<{\n className?: string;\n parentId?: string;\n }>\n> = ({className, parentId, children}) => {\n const [open, setOpen] = useState(false);\n const addNode = useStoreWithCanvas((s) => s.canvas.addNode);\n const sheetId = useStoreWithCanvas((s) => s.cells.config.currentSheetId);\n const registry = useStoreWithCanvas((s) => s.cells.cellRegistry);\n const {toast} = useToast();\n const onAdd = (type: string) => {\n if (sheetId) {\n addNode({sheetId, parentId, nodeType: type});\n setOpen(false);\n } else {\n toast({\n variant: 'destructive',\n description: 'No sheet selected',\n });\n }\n };\n\n return (\n <div className={cn(className)}>\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>{children}</PopoverTrigger>\n <PopoverContent\n side=\"right\"\n align=\"center\"\n className=\"flex w-auto flex-col gap-2 p-2\"\n >\n {Object.entries(registry).map(([type, reg]) => (\n <Button key={type} size=\"xs\" onClick={() => onAdd(type)}>\n {reg.title}\n </Button>\n ))}\n </PopoverContent>\n </Popover>\n </div>\n );\n};\n"]}
1
+ {"version":3,"file":"AddNodePopover.js","sourceRoot":"","sources":["../../src/nodes/AddNodePopover.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,MAAM,EACN,EAAE,EACF,OAAO,EACP,cAAc,EACd,cAAc,EACd,KAAK,GACN,MAAM,cAAc,CAAC;AACtB,OAAO,EAAwB,QAAQ,EAAC,MAAM,OAAO,CAAC;AACtD,OAAO,EAAC,kBAAkB,EAAC,MAAM,gBAAgB,CAAC;AAElD,MAAM,CAAC,MAAM,cAAc,GAMvB,CAAC,EAAC,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAC,EAAE,EAAE;IAClD,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,OAAO,GAAG,kBAAkB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC5D,MAAM,QAAQ,GAAG,kBAAkB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IAEjE,MAAM,KAAK,GAAG,CAAC,IAAY,EAAE,EAAE;QAC7B,IAAI,UAAU,EAAE,CAAC;YACf,OAAO,CAAC,EAAC,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAC,CAAC,CAAC;YAChD,OAAO,CAAC,KAAK,CAAC,CAAC;QACjB,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;QACtC,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,CACL,cAAK,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,YAC3B,MAAC,OAAO,IAAC,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,aACxC,KAAC,cAAc,IAAC,OAAO,kBAAE,QAAQ,GAAkB,EACnD,KAAC,cAAc,IACb,IAAI,EAAC,OAAO,EACZ,KAAK,EAAC,QAAQ,EACd,SAAS,EAAC,gCAAgC,YAEzC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAC7C,KAAC,MAAM,IAAY,IAAI,EAAC,IAAI,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,YACpD,GAAG,CAAC,KAAK,IADC,IAAI,CAER,CACV,CAAC,GACa,IACT,GACN,CACP,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import {\n Button,\n cn,\n Popover,\n PopoverContent,\n PopoverTrigger,\n toast,\n} from '@sqlrooms/ui';\nimport {FC, PropsWithChildren, useState} from 'react';\nimport {useStoreWithCanvas} from '../CanvasSlice';\n\nexport const AddNodePopover: FC<\n PropsWithChildren<{\n artifactId: string;\n className?: string;\n parentId?: string;\n }>\n> = ({artifactId, className, parentId, children}) => {\n const [open, setOpen] = useState(false);\n const addNode = useStoreWithCanvas((s) => s.canvas.addNode);\n const registry = useStoreWithCanvas((s) => s.cells.cellRegistry);\n\n const onAdd = (type: string) => {\n if (artifactId) {\n addNode({artifactId, parentId, nodeType: type});\n setOpen(false);\n } else {\n toast.error('No artifact selected');\n }\n };\n\n return (\n <div className={cn(className)}>\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>{children}</PopoverTrigger>\n <PopoverContent\n side=\"right\"\n align=\"center\"\n className=\"flex w-auto flex-col gap-2 p-2\"\n >\n {Object.entries(registry).map(([type, reg]) => (\n <Button key={type} size=\"xs\" onClick={() => onAdd(type)}>\n {reg.title}\n </Button>\n ))}\n </PopoverContent>\n </Popover>\n </div>\n );\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"CanvasNodeContainer.d.ts","sourceRoot":"","sources":["../../src/nodes/CanvasNodeContainer.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAC,EAAE,EAAE,iBAAiB,EAAE,SAAS,EAAc,MAAM,OAAO,CAAC;AAUpE;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,EAAE,CAClC,iBAAiB,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wDAAwD;IACxD,WAAW,CAAC,EAAE,SAAS,CAAC;CACzB,CAAC,CAoEH,CAAC"}
1
+ {"version":3,"file":"CanvasNodeContainer.d.ts","sourceRoot":"","sources":["../../src/nodes/CanvasNodeContainer.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAC,EAAE,EAAE,iBAAiB,EAAE,SAAS,EAAc,MAAM,OAAO,CAAC;AAUpE;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,EAAE,CAClC,iBAAiB,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wDAAwD;IACxD,WAAW,CAAC,EAAE,SAAS,CAAC;CACzB,CAAC,CA2EH,CAAC"}
@@ -18,10 +18,11 @@ const PROMPT_PLACEHOLDER = {
18
18
  export const CanvasNodeContainer = ({ id, className, headerRight, children }) => {
19
19
  const renameNode = useStoreWithCanvas((s) => s.canvas.renameNode);
20
20
  const cell = useStoreWithCanvas((s) => s.cells.config.data[id]);
21
+ const artifactId = useStoreWithCanvas((s) => s.cells.getArtifactIdForCell(id));
21
22
  const title = cell?.data?.title;
22
23
  const onTitleChange = useCallback(async (v) => {
23
24
  await renameNode(id, v);
24
25
  }, [id, renameNode]);
25
- return (_jsxs("div", { className: cn(`bg-background relative flex h-full w-full rounded-md border shadow-sm`, className), children: [_jsx(NodeResizer, { minWidth: 200, minHeight: 200 }), _jsxs("div", { className: "flex h-full min-h-0 w-full flex-col items-center", children: [(title !== undefined || headerRight) && (_jsxs("div", { className: "flex w-full items-center justify-between gap-2 border-b px-3 py-2", children: [_jsx(EditableText, { className: "text-sm font-medium", value: title ?? '', onChange: (v) => onTitleChange?.(v) }), _jsx("div", { className: "flex items-center gap-2", children: headerRight })] })), _jsx("div", { className: "w-full flex-1 overflow-auto", children: children })] }), _jsx(AddNodePopover, { className: "absolute -right-10 top-1/2", parentId: id, children: _jsx(Button, { variant: "default", className: "h-8 w-8 -translate-y-1/2 rounded-full", title: "Add child node", children: _jsx(PlusIcon, { className: "h-4 w-4" }) }) }), _jsx(Handle, { type: "source", position: Position.Right }), _jsx(Handle, { type: "target", position: Position.Left })] }));
26
+ return (_jsxs("div", { className: cn(`bg-background relative flex h-full w-full rounded-md border shadow-sm`, className), children: [_jsx(NodeResizer, { minWidth: 200, minHeight: 200 }), _jsxs("div", { className: "flex h-full min-h-0 w-full flex-col items-center", children: [(title !== undefined || headerRight) && (_jsxs("div", { className: "flex w-full items-center justify-between gap-2 border-b px-3 py-2", children: [_jsx(EditableText, { className: "text-sm font-medium", value: title ?? '', onChange: (v) => onTitleChange?.(v) }), _jsx("div", { className: "flex items-center gap-2", children: headerRight })] })), _jsx("div", { className: "w-full flex-1 overflow-auto", children: children })] }), _jsx(AddNodePopover, { artifactId: artifactId ?? '', className: "absolute top-1/2 -right-10", parentId: id, children: _jsx(Button, { variant: "default", className: "h-8 w-8 -translate-y-1/2 rounded-full", title: "Add child node", children: _jsx(PlusIcon, { className: "h-4 w-4" }) }) }), _jsx(Handle, { type: "source", position: Position.Right }), _jsx(Handle, { type: "target", position: Position.Left })] }));
26
27
  };
27
28
  //# sourceMappingURL=CanvasNodeContainer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CanvasNodeContainer.js","sourceRoot":"","sources":["../../src/nodes/CanvasNodeContainer.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,MAAM,EAAE,YAAY,EAAE,EAAE,EAAC,MAAM,cAAc,CAAC;AACtD,OAAO,EAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAC,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAC,QAAQ,EAAC,MAAM,cAAc,CAAC;AACtC,OAAO,EAAmC,WAAW,EAAC,MAAM,OAAO,CAAC;AACpE,OAAO,EAAC,kBAAkB,EAAC,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAEhD,MAAM,kBAAkB,GAAG;IACzB,GAAG,EAAE,8CAA8C;IACnD,IAAI,EAAE,2CAA2C;IACjD,OAAO,EAAE,4BAA4B;CACtC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAO5B,CAAC,EAAC,EAAE,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAC,EAAE,EAAE;IAC7C,MAAM,UAAU,GAAG,kBAAkB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAClE,MAAM,IAAI,GAAG,kBAAkB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAEhE,MAAM,KAAK,GAAI,IAAI,EAAE,IAAY,EAAE,KAAK,CAAC;IACzC,MAAM,aAAa,GAAG,WAAW,CAC/B,KAAK,EAAE,CAAS,EAAE,EAAE;QAClB,MAAM,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAC1B,CAAC,EACD,CAAC,EAAE,EAAE,UAAU,CAAC,CACjB,CAAC;IACF,OAAO,CACL,eACE,SAAS,EAAE,EAAE,CACX,uEAAuE,EACvE,SAAS,CACV,aAED,KAAC,WAAW,IAAC,QAAQ,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,GAAI,EAC9C,eAAK,SAAS,EAAC,kDAAkD,aAC9D,CAAC,KAAK,KAAK,SAAS,IAAI,WAAW,CAAC,IAAI,CACvC,eAAK,SAAS,EAAC,mEAAmE,aAChF,KAAC,YAAY,IACX,SAAS,EAAC,qBAAqB,EAC/B,KAAK,EAAE,KAAK,IAAI,EAAE,EAClB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,GACnC,EACF,cAAK,SAAS,EAAC,yBAAyB,YAAE,WAAW,GAAO,IACxD,CACP,EAuBD,cAAK,SAAS,EAAC,6BAA6B,YAAE,QAAQ,GAAO,IACzD,EACN,KAAC,cAAc,IAAC,SAAS,EAAC,4BAA4B,EAAC,QAAQ,EAAE,EAAE,YACjE,KAAC,MAAM,IACL,OAAO,EAAC,SAAS,EACjB,SAAS,EAAC,uCAAuC,EACjD,KAAK,EAAC,gBAAgB,YAEtB,KAAC,QAAQ,IAAC,SAAS,EAAC,SAAS,GAAG,GACzB,GACM,EACjB,KAAC,MAAM,IAAC,IAAI,EAAC,QAAQ,EAAC,QAAQ,EAAE,QAAQ,CAAC,KAAK,GAAI,EAClD,KAAC,MAAM,IAAC,IAAI,EAAC,QAAQ,EAAC,QAAQ,EAAE,QAAQ,CAAC,IAAI,GAAI,IAC7C,CACP,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import {Button, EditableText, cn} from '@sqlrooms/ui';\nimport {Handle, NodeResizer, Position} from '@xyflow/react';\nimport {PlusIcon} from 'lucide-react';\nimport {FC, PropsWithChildren, ReactNode, useCallback} from 'react';\nimport {useStoreWithCanvas} from '../CanvasSlice';\nimport {AddNodePopover} from './AddNodePopover';\n\nconst PROMPT_PLACEHOLDER = {\n sql: 'What would you like to learn about the data?',\n vega: 'How would you like to visualize the data?',\n default: 'What would you like to do?',\n};\n\n/**\n * Container applied to every canvas node. Provides resizing, connection handles,\n * and a standard \"add child\" affordance that creates downstream nodes.\n * Also renders an optional shared header with editable title and customizable right-side content.\n */\nexport const CanvasNodeContainer: FC<\n PropsWithChildren<{\n id: string;\n className?: string;\n /** Right-side header content (e.g. buttons, badges). */\n headerRight?: ReactNode;\n }>\n> = ({id, className, headerRight, children}) => {\n const renameNode = useStoreWithCanvas((s) => s.canvas.renameNode);\n const cell = useStoreWithCanvas((s) => s.cells.config.data[id]);\n\n const title = (cell?.data as any)?.title;\n const onTitleChange = useCallback(\n async (v: string) => {\n await renameNode(id, v);\n },\n [id, renameNode],\n );\n return (\n <div\n className={cn(\n `bg-background relative flex h-full w-full rounded-md border shadow-sm`,\n className,\n )}\n >\n <NodeResizer minWidth={200} minHeight={200} />\n <div className=\"flex h-full min-h-0 w-full flex-col items-center\">\n {(title !== undefined || headerRight) && (\n <div className=\"flex w-full items-center justify-between gap-2 border-b px-3 py-2\">\n <EditableText\n className=\"text-sm font-medium\"\n value={title ?? ''}\n onChange={(v) => onTitleChange?.(v)}\n />\n <div className=\"flex items-center gap-2\">{headerRight}</div>\n </div>\n )}\n {/* <Popover>\n <PopoverTrigger asChild>\n <Button\n variant=\"default\"\n className=\"h-8 w-8 -translate-y-1/2 rounded-full\"\n >\n <SparklesIcon className=\"h-4 w-4\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"max-h-[50vh] w-[400px] overflow-auto\">\n <QueryControls\n placeholder={`✨ ${\n PROMPT_PLACEHOLDER[\n (cell?.type ?? 'default') as keyof typeof PROMPT_PLACEHOLDER\n ]\n }`}\n onRun={() => {\n setAssistantOpen?.(true);\n }}\n />\n </PopoverContent>\n </Popover> */}\n <div className=\"w-full flex-1 overflow-auto\">{children}</div>\n </div>\n <AddNodePopover className=\"absolute -right-10 top-1/2\" parentId={id}>\n <Button\n variant=\"default\"\n className=\"h-8 w-8 -translate-y-1/2 rounded-full\"\n title=\"Add child node\"\n >\n <PlusIcon className=\"h-4 w-4\" />\n </Button>\n </AddNodePopover>\n <Handle type=\"source\" position={Position.Right} />\n <Handle type=\"target\" position={Position.Left} />\n </div>\n );\n};\n"]}
1
+ {"version":3,"file":"CanvasNodeContainer.js","sourceRoot":"","sources":["../../src/nodes/CanvasNodeContainer.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,MAAM,EAAE,YAAY,EAAE,EAAE,EAAC,MAAM,cAAc,CAAC;AACtD,OAAO,EAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAC,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAC,QAAQ,EAAC,MAAM,cAAc,CAAC;AACtC,OAAO,EAAmC,WAAW,EAAC,MAAM,OAAO,CAAC;AACpE,OAAO,EAAC,kBAAkB,EAAC,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAEhD,MAAM,kBAAkB,GAAG;IACzB,GAAG,EAAE,8CAA8C;IACnD,IAAI,EAAE,2CAA2C;IACjD,OAAO,EAAE,4BAA4B;CACtC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAO5B,CAAC,EAAC,EAAE,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAC,EAAE,EAAE;IAC7C,MAAM,UAAU,GAAG,kBAAkB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAClE,MAAM,IAAI,GAAG,kBAAkB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAChE,MAAM,UAAU,GAAG,kBAAkB,CAAC,CAAC,CAAC,EAAE,EAAE,CAC1C,CAAC,CAAC,KAAK,CAAC,oBAAoB,CAAC,EAAE,CAAC,CACjC,CAAC;IAEF,MAAM,KAAK,GAAI,IAAI,EAAE,IAAY,EAAE,KAAK,CAAC;IACzC,MAAM,aAAa,GAAG,WAAW,CAC/B,KAAK,EAAE,CAAS,EAAE,EAAE;QAClB,MAAM,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAC1B,CAAC,EACD,CAAC,EAAE,EAAE,UAAU,CAAC,CACjB,CAAC;IACF,OAAO,CACL,eACE,SAAS,EAAE,EAAE,CACX,uEAAuE,EACvE,SAAS,CACV,aAED,KAAC,WAAW,IAAC,QAAQ,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,GAAI,EAC9C,eAAK,SAAS,EAAC,kDAAkD,aAC9D,CAAC,KAAK,KAAK,SAAS,IAAI,WAAW,CAAC,IAAI,CACvC,eAAK,SAAS,EAAC,mEAAmE,aAChF,KAAC,YAAY,IACX,SAAS,EAAC,qBAAqB,EAC/B,KAAK,EAAE,KAAK,IAAI,EAAE,EAClB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,GACnC,EACF,cAAK,SAAS,EAAC,yBAAyB,YAAE,WAAW,GAAO,IACxD,CACP,EAuBD,cAAK,SAAS,EAAC,6BAA6B,YAAE,QAAQ,GAAO,IACzD,EACN,KAAC,cAAc,IACb,UAAU,EAAE,UAAU,IAAI,EAAE,EAC5B,SAAS,EAAC,4BAA4B,EACtC,QAAQ,EAAE,EAAE,YAEZ,KAAC,MAAM,IACL,OAAO,EAAC,SAAS,EACjB,SAAS,EAAC,uCAAuC,EACjD,KAAK,EAAC,gBAAgB,YAEtB,KAAC,QAAQ,IAAC,SAAS,EAAC,SAAS,GAAG,GACzB,GACM,EACjB,KAAC,MAAM,IAAC,IAAI,EAAC,QAAQ,EAAC,QAAQ,EAAE,QAAQ,CAAC,KAAK,GAAI,EAClD,KAAC,MAAM,IAAC,IAAI,EAAC,QAAQ,EAAC,QAAQ,EAAE,QAAQ,CAAC,IAAI,GAAI,IAC7C,CACP,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import {Button, EditableText, cn} from '@sqlrooms/ui';\nimport {Handle, NodeResizer, Position} from '@xyflow/react';\nimport {PlusIcon} from 'lucide-react';\nimport {FC, PropsWithChildren, ReactNode, useCallback} from 'react';\nimport {useStoreWithCanvas} from '../CanvasSlice';\nimport {AddNodePopover} from './AddNodePopover';\n\nconst PROMPT_PLACEHOLDER = {\n sql: 'What would you like to learn about the data?',\n vega: 'How would you like to visualize the data?',\n default: 'What would you like to do?',\n};\n\n/**\n * Container applied to every canvas node. Provides resizing, connection handles,\n * and a standard \"add child\" affordance that creates downstream nodes.\n * Also renders an optional shared header with editable title and customizable right-side content.\n */\nexport const CanvasNodeContainer: FC<\n PropsWithChildren<{\n id: string;\n className?: string;\n /** Right-side header content (e.g. buttons, badges). */\n headerRight?: ReactNode;\n }>\n> = ({id, className, headerRight, children}) => {\n const renameNode = useStoreWithCanvas((s) => s.canvas.renameNode);\n const cell = useStoreWithCanvas((s) => s.cells.config.data[id]);\n const artifactId = useStoreWithCanvas((s) =>\n s.cells.getArtifactIdForCell(id),\n );\n\n const title = (cell?.data as any)?.title;\n const onTitleChange = useCallback(\n async (v: string) => {\n await renameNode(id, v);\n },\n [id, renameNode],\n );\n return (\n <div\n className={cn(\n `bg-background relative flex h-full w-full rounded-md border shadow-sm`,\n className,\n )}\n >\n <NodeResizer minWidth={200} minHeight={200} />\n <div className=\"flex h-full min-h-0 w-full flex-col items-center\">\n {(title !== undefined || headerRight) && (\n <div className=\"flex w-full items-center justify-between gap-2 border-b px-3 py-2\">\n <EditableText\n className=\"text-sm font-medium\"\n value={title ?? ''}\n onChange={(v) => onTitleChange?.(v)}\n />\n <div className=\"flex items-center gap-2\">{headerRight}</div>\n </div>\n )}\n {/* <Popover>\n <PopoverTrigger asChild>\n <Button\n variant=\"default\"\n className=\"h-8 w-8 -translate-y-1/2 rounded-full\"\n >\n <SparklesIcon className=\"h-4 w-4\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"max-h-[50vh] w-[400px] overflow-auto\">\n <QueryControls\n placeholder={`✨ ${\n PROMPT_PLACEHOLDER[\n (cell?.type ?? 'default') as keyof typeof PROMPT_PLACEHOLDER\n ]\n }`}\n onRun={() => {\n setAssistantOpen?.(true);\n }}\n />\n </PopoverContent>\n </Popover> */}\n <div className=\"w-full flex-1 overflow-auto\">{children}</div>\n </div>\n <AddNodePopover\n artifactId={artifactId ?? ''}\n className=\"absolute top-1/2 -right-10\"\n parentId={id}\n >\n <Button\n variant=\"default\"\n className=\"h-8 w-8 -translate-y-1/2 rounded-full\"\n title=\"Add child node\"\n >\n <PlusIcon className=\"h-4 w-4\" />\n </Button>\n </AddNodePopover>\n <Handle type=\"source\" position={Position.Right} />\n <Handle type=\"target\" position={Position.Left} />\n </div>\n );\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sqlrooms/canvas",
3
- "version": "0.29.0-rc.1",
3
+ "version": "0.29.0-rc.3",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "module": "dist/index.js",
@@ -22,7 +22,7 @@
22
22
  "license": "MIT",
23
23
  "repository": {
24
24
  "type": "git",
25
- "url": "https://github.com/sqlrooms/sqlrooms.git"
25
+ "url": "git+https://github.com/sqlrooms/sqlrooms.git"
26
26
  },
27
27
  "files": [
28
28
  "dist"
@@ -32,12 +32,12 @@
32
32
  },
33
33
  "dependencies": {
34
34
  "@paralleldrive/cuid2": "^3.0.0",
35
- "@sqlrooms/cells": "0.29.0-rc.1",
36
- "@sqlrooms/crdt": "0.29.0-rc.1",
37
- "@sqlrooms/duckdb": "0.29.0-rc.1",
38
- "@sqlrooms/room-store": "0.29.0-rc.1",
39
- "@sqlrooms/ui": "0.29.0-rc.1",
40
- "@sqlrooms/utils": "0.29.0-rc.1",
35
+ "@sqlrooms/cells": "0.29.0-rc.3",
36
+ "@sqlrooms/crdt": "0.29.0-rc.3",
37
+ "@sqlrooms/duckdb": "0.29.0-rc.3",
38
+ "@sqlrooms/room-store": "0.29.0-rc.3",
39
+ "@sqlrooms/ui": "0.29.0-rc.3",
40
+ "@sqlrooms/utils": "0.29.0-rc.3",
41
41
  "@xyflow/react": "^12.8.5",
42
42
  "immer": "^11.0.1",
43
43
  "loro-mirror": "^1.1.2",
@@ -55,5 +55,5 @@
55
55
  "typecheck": "tsc --noEmit",
56
56
  "typedoc": "typedoc"
57
57
  },
58
- "gitHead": "69f127fd34bd7f2ce3d75d6098dbf8c1f5ab50f3"
58
+ "gitHead": "4ffaf6c31d41c27f96bd3e4f5e83d431968721c3"
59
59
  }