@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 +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 +65 -64
- 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 +5 -10
- 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 +9 -9
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,38 +72,47 @@ 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];
|
|
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
|
-
|
|
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(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
|
-
|
|
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"}
|
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
|
-
|
|
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
|
-
}), (
|
|
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
|
-
|
|
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
|
-
|
|
44
|
-
id:
|
|
45
|
-
nodes: Object.values(
|
|
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:
|
|
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
|
|
57
|
-
for (const
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
id:
|
|
61
|
-
nodes: (
|
|
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
|
-
...
|
|
66
|
+
...artifactValue.meta,
|
|
67
67
|
// Keep local viewport or use default
|
|
68
|
-
viewport:
|
|
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
|
-
|
|
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,
|
|
1
|
+
{"version":3,"file":"crdt.js","sourceRoot":"","sources":["../src/crdt.ts"],"names":[],"mappings":"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","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"]}
|
package/dist/edgeUtils.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { type Edge, type
|
|
2
|
-
export declare function getRenderableEdges(
|
|
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
|
package/dist/edgeUtils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"edgeUtils.d.ts","sourceRoot":"","sources":["../src/edgeUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,IAAI,EACT,KAAK,
|
|
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(
|
|
3
|
-
if (!
|
|
2
|
+
export function getRenderableEdges(artifact) {
|
|
3
|
+
if (!artifact)
|
|
4
4
|
return [];
|
|
5
|
-
return getRenderableDependencyEdges(
|
|
5
|
+
return getRenderableDependencyEdges(artifact);
|
|
6
6
|
}
|
|
7
7
|
//# sourceMappingURL=edgeUtils.js.map
|
package/dist/edgeUtils.js.map
CHANGED
|
@@ -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,
|
|
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,
|
|
7
|
+
export { CanvasSliceConfig, CanvasNodeMeta, CanvasArtifactMeta, } from './CanvasSlice';
|
|
8
8
|
export { Canvas } from './Canvas';
|
|
9
9
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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,
|
|
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,
|
|
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,
|
|
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 +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,
|
|
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,
|
|
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 (
|
|
13
|
-
addNode({
|
|
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,
|
|
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,
|
|
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
|
|
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;
|
|
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.
|
|
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.
|
|
36
|
-
"@sqlrooms/crdt": "0.29.0-rc.
|
|
37
|
-
"@sqlrooms/duckdb": "0.29.0-rc.
|
|
38
|
-
"@sqlrooms/room-store": "0.29.0-rc.
|
|
39
|
-
"@sqlrooms/ui": "0.29.0-rc.
|
|
40
|
-
"@sqlrooms/utils": "0.29.0-rc.
|
|
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": "
|
|
58
|
+
"gitHead": "4ffaf6c31d41c27f96bd3e4f5e83d431968721c3"
|
|
59
59
|
}
|