@sqlrooms/canvas 0.29.0-rc.1 → 0.29.0-rc.2
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/dist/CanvasAssistantDrawer.d.ts +3 -0
- package/dist/CanvasAssistantDrawer.d.ts.map +1 -0
- package/dist/CanvasAssistantDrawer.js +14 -0
- package/dist/CanvasAssistantDrawer.js.map +1 -0
- package/dist/CanvasSlice.js +1 -1
- package/dist/CanvasSlice.js.map +1 -1
- package/dist/dag.d.ts +53 -0
- package/dist/dag.d.ts.map +1 -0
- package/dist/dag.js +126 -0
- package/dist/dag.js.map +1 -0
- package/dist/nodes/AddNodePopover.d.ts.map +1 -1
- package/dist/nodes/AddNodePopover.js +2 -6
- package/dist/nodes/AddNodePopover.js.map +1 -1
- package/dist/nodes/CanvasNodeContainer.js +1 -1
- package/dist/nodes/CanvasNodeContainer.js.map +1 -1
- package/dist/nodes/SqlNode.d.ts +11 -0
- package/dist/nodes/SqlNode.d.ts.map +1 -0
- package/dist/nodes/SqlNode.js +52 -0
- package/dist/nodes/SqlNode.js.map +1 -0
- package/dist/nodes/VegaNode.d.ts +11 -0
- package/dist/nodes/VegaNode.d.ts.map +1 -0
- package/dist/nodes/VegaNode.js +12 -0
- package/dist/nodes/VegaNode.js.map +1 -0
- package/package.json +9 -9
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CanvasAssistantDrawer.d.ts","sourceRoot":"","sources":["../src/CanvasAssistantDrawer.tsx"],"names":[],"mappings":"AAYA,OAAO,EAAC,EAAE,EAAC,MAAM,OAAO,CAAC;AAGzB,eAAO,MAAM,qBAAqB,EAAE,EAiDnC,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Chat } from '@sqlrooms/ai';
|
|
3
|
+
import { Button, Drawer, DrawerClose, DrawerContent, DrawerFooter, DrawerHeader, DrawerTitle, DrawerTrigger, } from '@sqlrooms/ui';
|
|
4
|
+
import { SparklesIcon, XIcon } from 'lucide-react';
|
|
5
|
+
import { useStoreWithCanvas } from './CanvasSlice';
|
|
6
|
+
export const CanvasAssistantDrawer = () => {
|
|
7
|
+
const isAssistantOpen = useStoreWithCanvas((state) => state.canvas.isAssistantOpen);
|
|
8
|
+
const setAssistantOpen = useStoreWithCanvas((state) => state.canvas.setAssistantOpen);
|
|
9
|
+
return (_jsxs(Drawer, { direction: "right", open: isAssistantOpen, onOpenChange: setAssistantOpen, children: [_jsx(DrawerTrigger, { asChild: true, children: _jsx(Button, { variant: "default", className: "absolute right-4 top-4 z-10 h-8 w-8 rounded-full", children: _jsx(SparklesIcon, { className: "h-4 w-4" }) }) }), _jsx(DrawerContent, { className: "border-none bg-transparent p-4 outline-none", style: {
|
|
10
|
+
width: 500,
|
|
11
|
+
maxWidth: '50%',
|
|
12
|
+
}, "data-vaul-drawer-direction": "right", overlayClassName: "bg-transparent", children: _jsx("div", { className: "border-border bg-background relative mx-auto flex h-full w-full flex-col gap-0 overflow-hidden rounded-md border", children: _jsxs(Chat, { children: [_jsxs(DrawerHeader, { children: [_jsx(DrawerTitle, { children: "Assistant" }), _jsx(DrawerClose, { asChild: true, className: "absolute right-2 top-2", children: _jsx(Button, { variant: "ghost", size: "xs", children: _jsx(XIcon, { className: "h-4 w-4" }) }) })] }), _jsx(Chat.Messages, { className: "flex-grow overflow-auto px-4" }), _jsx(DrawerFooter, { children: _jsx(Chat.Composer, { placeholder: "What would you like to do?" }) })] }) }) })] }));
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=CanvasAssistantDrawer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CanvasAssistantDrawer.js","sourceRoot":"","sources":["../src/CanvasAssistantDrawer.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,cAAc,CAAC;AAClC,OAAO,EACL,MAAM,EACN,MAAM,EACN,WAAW,EACX,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,aAAa,GACd,MAAM,cAAc,CAAC;AACtB,OAAO,EAAC,YAAY,EAAE,KAAK,EAAC,MAAM,cAAc,CAAC;AAEjD,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAEjD,MAAM,CAAC,MAAM,qBAAqB,GAAO,GAAG,EAAE;IAC5C,MAAM,eAAe,GAAG,kBAAkB,CACxC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,eAAe,CACxC,CAAC;IACF,MAAM,gBAAgB,GAAG,kBAAkB,CACzC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,gBAAgB,CACzC,CAAC;IACF,OAAO,CACL,MAAC,MAAM,IACL,SAAS,EAAC,OAAO,EACjB,IAAI,EAAE,eAAe,EACrB,YAAY,EAAE,gBAAgB,aAE9B,KAAC,aAAa,IAAC,OAAO,kBACpB,KAAC,MAAM,IACL,OAAO,EAAC,SAAS,EACjB,SAAS,EAAC,kDAAkD,YAE5D,KAAC,YAAY,IAAC,SAAS,EAAC,SAAS,GAAG,GAC7B,GACK,EAChB,KAAC,aAAa,IACZ,SAAS,EAAC,6CAA6C,EACvD,KAAK,EAAE;oBACL,KAAK,EAAE,GAAG;oBACV,QAAQ,EAAE,KAAK;iBAChB,gCAC0B,OAAO,EAClC,gBAAgB,EAAC,gBAAgB,YAEjC,cAAK,SAAS,EAAC,kHAAkH,YAC/H,MAAC,IAAI,eACH,MAAC,YAAY,eACX,KAAC,WAAW,4BAAwB,EACpC,KAAC,WAAW,IAAC,OAAO,QAAC,SAAS,EAAC,wBAAwB,YACrD,KAAC,MAAM,IAAC,OAAO,EAAC,OAAO,EAAC,IAAI,EAAC,IAAI,YAC/B,KAAC,KAAK,IAAC,SAAS,EAAC,SAAS,GAAG,GACtB,GACG,IACD,EACf,KAAC,IAAI,CAAC,QAAQ,IAAC,SAAS,EAAC,8BAA8B,GAAG,EAC1D,KAAC,YAAY,cACX,KAAC,IAAI,CAAC,QAAQ,IAAC,WAAW,EAAC,4BAA4B,GAAG,GAC7C,IACV,GACH,GACQ,IACT,CACV,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import {Chat} from '@sqlrooms/ai';\nimport {\n Button,\n Drawer,\n DrawerClose,\n DrawerContent,\n DrawerFooter,\n DrawerHeader,\n DrawerTitle,\n DrawerTrigger,\n} from '@sqlrooms/ui';\nimport {SparklesIcon, XIcon} from 'lucide-react';\nimport {FC} from 'react';\nimport {useStoreWithCanvas} from './CanvasSlice';\n\nexport const CanvasAssistantDrawer: FC = () => {\n const isAssistantOpen = useStoreWithCanvas(\n (state) => state.canvas.isAssistantOpen,\n );\n const setAssistantOpen = useStoreWithCanvas(\n (state) => state.canvas.setAssistantOpen,\n );\n return (\n <Drawer\n direction=\"right\"\n open={isAssistantOpen}\n onOpenChange={setAssistantOpen}\n >\n <DrawerTrigger asChild>\n <Button\n variant=\"default\"\n className=\"absolute right-4 top-4 z-10 h-8 w-8 rounded-full\"\n >\n <SparklesIcon className=\"h-4 w-4\" />\n </Button>\n </DrawerTrigger>\n <DrawerContent\n className=\"border-none bg-transparent p-4 outline-none\"\n style={{\n width: 500,\n maxWidth: '50%',\n }}\n data-vaul-drawer-direction=\"right\"\n overlayClassName=\"bg-transparent\"\n >\n <div className=\"border-border bg-background relative mx-auto flex h-full w-full flex-col gap-0 overflow-hidden rounded-md border\">\n <Chat>\n <DrawerHeader>\n <DrawerTitle>Assistant</DrawerTitle>\n <DrawerClose asChild className=\"absolute right-2 top-2\">\n <Button variant=\"ghost\" size=\"xs\">\n <XIcon className=\"h-4 w-4\" />\n </Button>\n </DrawerClose>\n </DrawerHeader>\n <Chat.Messages className=\"flex-grow overflow-auto px-4\" />\n <DrawerFooter>\n <Chat.Composer placeholder=\"What would you like to do?\" />\n </DrawerFooter>\n </Chat>\n </div>\n </DrawerContent>\n </Drawer>\n );\n};\n"]}
|
package/dist/CanvasSlice.js
CHANGED
|
@@ -90,7 +90,7 @@ export function createCanvasSlice(props = {}) {
|
|
|
90
90
|
if (!reg)
|
|
91
91
|
return newId;
|
|
92
92
|
// 1. Create the cell in CellsSlice
|
|
93
|
-
const cell = reg.createCell(newId);
|
|
93
|
+
const cell = reg.createCell({ id: newId, get, set });
|
|
94
94
|
const existingTitles = Object.values(get().cells.config.data).map((c) => {
|
|
95
95
|
const title = c.data.title;
|
|
96
96
|
return typeof title === 'string' ? title : '';
|
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, getSheetsByType} from '@sqlrooms/cells';\nimport {DuckDbSliceState} from '@sqlrooms/duckdb';\nimport {\n BaseRoomStoreState,\n createSlice,\n useBaseRoomStore,\n} from '@sqlrooms/room-store';\nimport {generateUniqueName} from '@sqlrooms/utils';\nimport type {Viewport, XYPosition} from '@xyflow/react';\nimport {\n applyNodeChanges,\n Connection,\n type EdgeChange,\n type NodeChange,\n} from '@xyflow/react';\nimport {produce} from 'immer';\nimport {z} from 'zod';\n\nconst DEFAULT_NODE_WIDTH = 800;\nconst DEFAULT_NODE_HEIGHT = 600;\nconst CANVAS_SCHEMA_NAME = 'canvas';\nconst VIEWPORT_EPSILON = 0.1;\n\n/** View metadata for a single node on the canvas */\nexport const CanvasNodeMeta = z.object({\n id: z.string(),\n position: z.object({x: z.number(), y: z.number()}),\n width: z.number().default(DEFAULT_NODE_WIDTH),\n height: z.number().default(DEFAULT_NODE_HEIGHT),\n data: z.record(z.string(), z.any()).default({}), // Required by ReactFlow NodeBase\n});\nexport type CanvasNodeMeta = z.infer<typeof CanvasNodeMeta>;\n\n/** View metadata for a sheet (canvas view) */\nexport const CanvasSheetMeta = z.object({\n viewport: z.object({\n x: z.number(),\n y: z.number(),\n zoom: z.number(),\n }),\n nodeOrder: z.array(z.string()).default([]),\n});\nexport type CanvasSheetMeta = z.infer<typeof CanvasSheetMeta>;\n\nexport const CanvasSliceConfig = z.object({\n sheets: z\n .record(\n z.string(),\n z.object({\n id: z.string(),\n nodes: z.record(z.string(), CanvasNodeMeta).default({}),\n meta: CanvasSheetMeta,\n }),\n )\n .default({}),\n});\nexport type CanvasSliceConfig = z.infer<typeof CanvasSliceConfig>;\n\nexport type CanvasSliceState = {\n canvas: {\n config: CanvasSliceConfig;\n initialize: () => Promise<void>;\n setConfig: (config: CanvasSliceConfig) => void;\n setViewport: (viewport: Viewport) => void;\n getCanvasSheets: () => Record<string, import('@sqlrooms/cells').Sheet>;\n\n addNode: (params: {\n sheetId: string;\n nodeType?: string;\n initialPosition?: XYPosition;\n parentId?: string;\n }) => Promise<string>;\n\n renameNode: (nodeId: string, newTitle: string) => Promise<void>;\n updateNode: (\n nodeId: string,\n updater: (cell: Cell) => Cell,\n ) => Promise<void>;\n deleteNode: (nodeId: string) => void;\n\n applyNodeChanges: (changes: NodeChange<CanvasNodeMeta>[]) => void;\n applyEdgeChanges: (changes: EdgeChange<any>[]) => void;\n addEdge: (edge: Connection) => void;\n\n executeSqlNodeQuery: (\n nodeId: string,\n opts?: {cascade?: boolean},\n ) => Promise<void>;\n };\n};\n\nfunction getSheet(config: CanvasSliceConfig, sheetId: string) {\n return config.sheets[sheetId];\n}\n\nfunction ensureCanvasSheetMeta(\n config: CanvasSliceConfig,\n sheetId: string,\n viewport: Viewport = {x: 0, y: 0, zoom: 1},\n) {\n let sheet = config.sheets[sheetId];\n if (!sheet) {\n sheet = {\n id: sheetId,\n nodes: {},\n meta: {\n viewport,\n nodeOrder: [],\n },\n };\n config.sheets[sheetId] = sheet;\n }\n return sheet;\n}\n\nfunction isSameViewport(a: Viewport, b: Viewport) {\n return (\n Math.abs(a.x - b.x) < VIEWPORT_EPSILON &&\n Math.abs(a.y - b.y) < VIEWPORT_EPSILON &&\n Math.abs(a.zoom - b.zoom) < VIEWPORT_EPSILON\n );\n}\n\nexport function createDefaultCanvasConfig(\n props?: Partial<CanvasSliceConfig>,\n): CanvasSliceConfig {\n const base: CanvasSliceConfig = {\n sheets: {},\n };\n\n return {...base, ...props};\n}\n\nexport function createCanvasSlice(\n props: {config?: Partial<CanvasSliceConfig>} = {},\n) {\n type CanvasRootState = BaseRoomStoreState &\n DuckDbSliceState &\n CanvasSliceState &\n CellsRootState;\n\n return createSlice<CanvasSliceState, CanvasRootState>((set, get, store) => {\n return {\n canvas: {\n config: createDefaultCanvasConfig(props.config),\n setConfig: (config: CanvasSliceConfig) => {\n set((state: CanvasRootState) =>\n produce(state, (draft: CanvasRootState) => {\n draft.canvas.config = config;\n }),\n );\n },\n\n getCanvasSheets: () => getSheetsByType(get(), 'canvas'),\n\n async initialize() {\n const sheetId =\n get().cells.config.currentSheetId ||\n get().cells.config.sheetOrder[0];\n if (!sheetId) return;\n // don't await this - it will block the UI\n get().cells.runAllCellsCascade(sheetId);\n },\n\n addNode: async ({\n sheetId,\n nodeType = 'sql',\n initialPosition,\n parentId,\n }: {\n sheetId: string;\n nodeType?: string;\n initialPosition?: XYPosition;\n parentId?: string;\n }) => {\n const newId = createId();\n const registry = get().cells.cellRegistry;\n const reg = registry[nodeType];\n if (!reg) return newId;\n\n // 1. Create the cell in CellsSlice\n const cell = reg.createCell({id: newId, get, set}) as Cell;\n\n const existingTitles = Object.values(get().cells.config.data).map(\n (c) => {\n const title = (c.data as Record<string, unknown>).title;\n return typeof title === 'string' ? title : '';\n },\n );\n (cell.data as Record<string, unknown>).title = generateUniqueName(\n `${reg.title} 1`,\n existingTitles,\n ' ',\n );\n\n await get().cells.addCell(sheetId, cell);\n\n // 2. If parent exists, add an edge in CellsSlice\n if (parentId) {\n get().cells.addEdge(sheetId, {source: parentId, target: newId});\n }\n\n // 3. Update view-specific metadata\n set((state: CanvasRootState) =>\n produce(state, (draft: CanvasRootState) => {\n let sheet = getSheet(draft.canvas.config, sheetId);\n sheet = ensureCanvasSheetMeta(draft.canvas.config, sheetId);\n\n const parentNode = parentId ? sheet.nodes[parentId] : undefined;\n const position: XYPosition = initialPosition\n ? initialPosition\n : parentNode\n ? {\n x: parentNode.position.x + parentNode.width + 100,\n y: parentNode.position.y,\n }\n : {\n x: sheet.meta.viewport.x + 100,\n y: sheet.meta.viewport.y + 100,\n };\n\n sheet.nodes[newId] = {\n id: newId,\n position,\n width: DEFAULT_NODE_WIDTH,\n height: DEFAULT_NODE_HEIGHT,\n data: {},\n };\n sheet.meta.nodeOrder.push(newId);\n }),\n );\n return newId;\n },\n\n renameNode: async (nodeId: string, newTitle: string) => {\n await get().cells.updateCell(nodeId, (c) =>\n produce(c, (draft) => {\n (draft.data as Record<string, unknown>).title = newTitle;\n }),\n );\n },\n\n updateNode: async (nodeId: string, updater: (cell: Cell) => Cell) => {\n await get().cells.updateCell(nodeId, updater);\n },\n\n deleteNode: (nodeId: string) => {\n get().cells.removeCell(nodeId);\n set((state: CanvasRootState) =>\n produce(state, (draft: CanvasRootState) => {\n for (const sheet of Object.values(draft.canvas.config.sheets)) {\n delete sheet.nodes[nodeId];\n sheet.meta.nodeOrder = sheet.meta.nodeOrder.filter(\n (id) => id !== nodeId,\n );\n }\n }),\n );\n },\n\n applyNodeChanges: (changes: NodeChange<CanvasNodeMeta>[]) => {\n set((state: CanvasRootState) =>\n produce(state, (draft: CanvasRootState) => {\n const sheetId = draft.cells.config.currentSheetId;\n if (!sheetId) return;\n const sheet = ensureCanvasSheetMeta(draft.canvas.config, sheetId);\n\n // Ensure all cells from CellsSlice have a node entry in CanvasSlice\n const cellsSheet = draft.cells.config.sheets[sheetId];\n if (cellsSheet) {\n for (const cellId of cellsSheet.cellIds) {\n if (!sheet.nodes[cellId]) {\n sheet.nodes[cellId] = {\n id: cellId,\n position: {x: 100, y: 100},\n width: DEFAULT_NODE_WIDTH,\n height: DEFAULT_NODE_HEIGHT,\n data: {},\n };\n sheet.meta.nodeOrder.push(cellId);\n }\n }\n }\n\n const nodesArray = sheet.meta.nodeOrder\n .map((id) => sheet.nodes[id])\n .filter(Boolean) as CanvasNodeMeta[];\n const updated = applyNodeChanges(changes, nodesArray);\n sheet.nodes = updated.reduce<Record<string, CanvasNodeMeta>>(\n (acc, node) => {\n acc[node.id] = node;\n return acc;\n },\n {},\n );\n sheet.meta.nodeOrder = updated.map((n) => n.id);\n }),\n );\n },\n\n applyEdgeChanges: (changes: EdgeChange<any>[]) => {\n // Canvas edge editing is intentionally disabled for now.\n // Compatibility no-op: keep API stable until edge kinds are introduced.\n void changes;\n },\n\n addEdge: (connection: Connection) => {\n // Canvas edge editing is intentionally disabled for now.\n // Compatibility no-op: dependency edges are derived from graph cache.\n void connection;\n },\n\n setViewport: (viewport: Viewport) => {\n const sheetId = get().cells.config.currentSheetId;\n if (!sheetId) return;\n const existing = get().canvas.config.sheets[sheetId];\n if (existing && isSameViewport(existing.meta.viewport, viewport)) {\n return;\n }\n set((state: CanvasRootState) =>\n produce(state, (draft: CanvasRootState) => {\n let sheet = getSheet(draft.canvas.config, sheetId);\n sheet = ensureCanvasSheetMeta(\n draft.canvas.config,\n sheetId,\n viewport,\n );\n sheet.meta.viewport = viewport;\n }),\n );\n },\n\n executeSqlNodeQuery: async (\n nodeId: string,\n opts?: {cascade?: boolean},\n ) => {\n await get().cells.runCell(nodeId, {\n ...opts,\n schemaName: CANVAS_SCHEMA_NAME,\n });\n },\n },\n };\n });\n}\n\nexport type DuckDbSliceStateWithCanvas = DuckDbSliceState &\n CanvasSliceState &\n CellsRootState;\n\nexport function useStoreWithCanvas<T>(\n selector: (state: DuckDbSliceStateWithCanvas) => T,\n): T {\n return useBaseRoomStore<BaseRoomStoreState, T>((state) =>\n selector(state as unknown as DuckDbSliceStateWithCanvas),\n );\n}\n"]}
|
package/dist/dag.d.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/** A minimal graph node with an `id`. */
|
|
2
|
+
export type DagNode = {
|
|
3
|
+
id: string;
|
|
4
|
+
};
|
|
5
|
+
/** A directed edge from `source` to `target`. */
|
|
6
|
+
export type DagEdge = {
|
|
7
|
+
source: string;
|
|
8
|
+
target: string;
|
|
9
|
+
};
|
|
10
|
+
/** Forward adjacency list mapping node id to its child node ids. */
|
|
11
|
+
export type Adjacency = Record<string, string[]>;
|
|
12
|
+
/**
|
|
13
|
+
* Build a forward adjacency list for a directed graph.
|
|
14
|
+
* Ensures that every node id exists in the adjacency map, even if it has no outgoing edges.
|
|
15
|
+
*
|
|
16
|
+
* @param nodes - The set of nodes to include in the graph.
|
|
17
|
+
* @param edges - Directed edges where `source` points to `target`.
|
|
18
|
+
* @returns A mapping from node id to an array of child node ids.
|
|
19
|
+
*/
|
|
20
|
+
export declare function buildAdjacency(nodes: DagNode[], edges: DagEdge[]): Adjacency;
|
|
21
|
+
/**
|
|
22
|
+
* Find a node by id in a list of nodes.
|
|
23
|
+
*
|
|
24
|
+
* @param nodes - Array of nodes with an `id` field.
|
|
25
|
+
* @param id - The node id to find.
|
|
26
|
+
* @returns The node if found, otherwise undefined.
|
|
27
|
+
*/
|
|
28
|
+
export declare function findNodeById<T extends {
|
|
29
|
+
id: string;
|
|
30
|
+
}>(nodes: T[], id: string): T | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Topologically sort all nodes in the graph using Kahn's algorithm.
|
|
33
|
+
* If a cycle is detected, the remaining nodes are appended in arbitrary order,
|
|
34
|
+
* and a warning is logged.
|
|
35
|
+
*
|
|
36
|
+
* @param nodes - The set of nodes to sort.
|
|
37
|
+
* @param edges - Directed edges defining dependencies.
|
|
38
|
+
* @returns An array of node ids in dependency order (parents before children).
|
|
39
|
+
*/
|
|
40
|
+
export declare function topoSortAll(nodes: DagNode[], edges: DagEdge[]): string[];
|
|
41
|
+
/**
|
|
42
|
+
* Get a topological order for the downstream subgraph reachable from `startId`.
|
|
43
|
+
* Only nodes reachable from the start are included (the starting node is excluded).
|
|
44
|
+
* If a cycle exists within the reachable subgraph, the remaining nodes are appended
|
|
45
|
+
* at the end in arbitrary order and a warning is logged.
|
|
46
|
+
*
|
|
47
|
+
* @param startId - The node id to start traversal from.
|
|
48
|
+
* @param nodes - The set of nodes in the full graph.
|
|
49
|
+
* @param edges - Directed edges defining the full graph dependencies.
|
|
50
|
+
* @returns Node ids reachable from `startId`, in dependency order.
|
|
51
|
+
*/
|
|
52
|
+
export declare function topoSortDownstream(startId: string, nodes: DagNode[], edges: DagEdge[]): string[];
|
|
53
|
+
//# sourceMappingURL=dag.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dag.d.ts","sourceRoot":"","sources":["../src/dag.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,MAAM,MAAM,OAAO,GAAG;IAAC,EAAE,EAAE,MAAM,CAAA;CAAC,CAAC;AACnC,iDAAiD;AACjD,MAAM,MAAM,OAAO,GAAG;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAC,CAAC;AACvD,oEAAoE;AACpE,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;AAEjD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,SAAS,CAQ5E;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS;IAAC,EAAE,EAAE,MAAM,CAAA;CAAC,EACjD,KAAK,EAAE,CAAC,EAAE,EACV,EAAE,EAAE,MAAM,GACT,CAAC,GAAG,SAAS,CAEf;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM,EAAE,CAkCxE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,OAAO,EAAE,EAChB,KAAK,EAAE,OAAO,EAAE,GACf,MAAM,EAAE,CA8CV"}
|
package/dist/dag.js
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build a forward adjacency list for a directed graph.
|
|
3
|
+
* Ensures that every node id exists in the adjacency map, even if it has no outgoing edges.
|
|
4
|
+
*
|
|
5
|
+
* @param nodes - The set of nodes to include in the graph.
|
|
6
|
+
* @param edges - Directed edges where `source` points to `target`.
|
|
7
|
+
* @returns A mapping from node id to an array of child node ids.
|
|
8
|
+
*/
|
|
9
|
+
export function buildAdjacency(nodes, edges) {
|
|
10
|
+
const adjacency = {};
|
|
11
|
+
for (const n of nodes)
|
|
12
|
+
adjacency[n.id] = [];
|
|
13
|
+
for (const e of edges) {
|
|
14
|
+
const list = adjacency[e.source] || (adjacency[e.source] = []);
|
|
15
|
+
list.push(e.target);
|
|
16
|
+
}
|
|
17
|
+
return adjacency;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Find a node by id in a list of nodes.
|
|
21
|
+
*
|
|
22
|
+
* @param nodes - Array of nodes with an `id` field.
|
|
23
|
+
* @param id - The node id to find.
|
|
24
|
+
* @returns The node if found, otherwise undefined.
|
|
25
|
+
*/
|
|
26
|
+
export function findNodeById(nodes, id) {
|
|
27
|
+
return nodes.find((n) => n.id === id);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Topologically sort all nodes in the graph using Kahn's algorithm.
|
|
31
|
+
* If a cycle is detected, the remaining nodes are appended in arbitrary order,
|
|
32
|
+
* and a warning is logged.
|
|
33
|
+
*
|
|
34
|
+
* @param nodes - The set of nodes to sort.
|
|
35
|
+
* @param edges - Directed edges defining dependencies.
|
|
36
|
+
* @returns An array of node ids in dependency order (parents before children).
|
|
37
|
+
*/
|
|
38
|
+
export function topoSortAll(nodes, edges) {
|
|
39
|
+
const adjacency = buildAdjacency(nodes, edges);
|
|
40
|
+
const inDegree = {};
|
|
41
|
+
for (const n of nodes)
|
|
42
|
+
inDegree[n.id] = 0;
|
|
43
|
+
for (const e of edges) {
|
|
44
|
+
inDegree[e.target] = (inDegree[e.target] ?? 0) + 1;
|
|
45
|
+
}
|
|
46
|
+
const queue = Object.keys(inDegree).filter((id) => (inDegree[id] ?? 0) === 0);
|
|
47
|
+
const order = [];
|
|
48
|
+
while (queue.length) {
|
|
49
|
+
const cur = queue.shift();
|
|
50
|
+
order.push(cur);
|
|
51
|
+
const neighbors = adjacency[cur] || [];
|
|
52
|
+
for (const nb of neighbors) {
|
|
53
|
+
inDegree[nb] = (inDegree[nb] ?? 0) - 1;
|
|
54
|
+
if (inDegree[nb] === 0)
|
|
55
|
+
queue.push(nb);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (order.length < nodes.length) {
|
|
59
|
+
const remaining = nodes
|
|
60
|
+
.map((n) => n.id)
|
|
61
|
+
.filter((id) => !order.includes(id));
|
|
62
|
+
// eslint-disable-next-line no-console
|
|
63
|
+
console.warn('[dag.topoSortAll] Cycle detected; appending remaining nodes arbitrarily:', remaining);
|
|
64
|
+
order.push(...remaining);
|
|
65
|
+
}
|
|
66
|
+
return order;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get a topological order for the downstream subgraph reachable from `startId`.
|
|
70
|
+
* Only nodes reachable from the start are included (the starting node is excluded).
|
|
71
|
+
* If a cycle exists within the reachable subgraph, the remaining nodes are appended
|
|
72
|
+
* at the end in arbitrary order and a warning is logged.
|
|
73
|
+
*
|
|
74
|
+
* @param startId - The node id to start traversal from.
|
|
75
|
+
* @param nodes - The set of nodes in the full graph.
|
|
76
|
+
* @param edges - Directed edges defining the full graph dependencies.
|
|
77
|
+
* @returns Node ids reachable from `startId`, in dependency order.
|
|
78
|
+
*/
|
|
79
|
+
export function topoSortDownstream(startId, nodes, edges) {
|
|
80
|
+
const adjacency = buildAdjacency(nodes, edges);
|
|
81
|
+
// Collect reachable nodes from startId (excluding start)
|
|
82
|
+
const reachable = new Set();
|
|
83
|
+
const queue = [...(adjacency[startId] || [])];
|
|
84
|
+
while (queue.length) {
|
|
85
|
+
const cur = queue.shift();
|
|
86
|
+
if (reachable.has(cur))
|
|
87
|
+
continue;
|
|
88
|
+
reachable.add(cur);
|
|
89
|
+
const neighbors = adjacency[cur] || [];
|
|
90
|
+
for (const nb of neighbors)
|
|
91
|
+
queue.push(nb);
|
|
92
|
+
}
|
|
93
|
+
if (reachable.size === 0)
|
|
94
|
+
return [];
|
|
95
|
+
// Kahn's algorithm for topological sort within subgraph
|
|
96
|
+
const inDegree = {};
|
|
97
|
+
for (const id of reachable)
|
|
98
|
+
inDegree[id] = 0;
|
|
99
|
+
for (const e of edges) {
|
|
100
|
+
if (reachable.has(e.source) && reachable.has(e.target)) {
|
|
101
|
+
inDegree[e.target] = (inDegree[e.target] ?? 0) + 1;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
const queue2 = Array.from(reachable).filter((id) => (inDegree[id] ?? 0) === 0);
|
|
105
|
+
const order = [];
|
|
106
|
+
while (queue2.length) {
|
|
107
|
+
const cur = queue2.shift();
|
|
108
|
+
order.push(cur);
|
|
109
|
+
const neighbors = adjacency[cur] || [];
|
|
110
|
+
for (const nb of neighbors) {
|
|
111
|
+
if (!reachable.has(nb))
|
|
112
|
+
continue;
|
|
113
|
+
inDegree[nb] = (inDegree[nb] ?? 0) - 1;
|
|
114
|
+
if (inDegree[nb] === 0)
|
|
115
|
+
queue2.push(nb);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (order.length < reachable.size) {
|
|
119
|
+
const remaining = Array.from(reachable).filter((id) => !order.includes(id));
|
|
120
|
+
// eslint-disable-next-line no-console
|
|
121
|
+
console.warn('[dag.topoSortDownstream] Cycle detected in downstream graph:', remaining);
|
|
122
|
+
order.push(...remaining);
|
|
123
|
+
}
|
|
124
|
+
return order;
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=dag.js.map
|
package/dist/dag.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dag.js","sourceRoot":"","sources":["../src/dag.ts"],"names":[],"mappings":"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","sourcesContent":["/** A minimal graph node with an `id`. */\nexport type DagNode = {id: string};\n/** A directed edge from `source` to `target`. */\nexport type DagEdge = {source: string; target: string};\n/** Forward adjacency list mapping node id to its child node ids. */\nexport type Adjacency = Record<string, string[]>;\n\n/**\n * Build a forward adjacency list for a directed graph.\n * Ensures that every node id exists in the adjacency map, even if it has no outgoing edges.\n *\n * @param nodes - The set of nodes to include in the graph.\n * @param edges - Directed edges where `source` points to `target`.\n * @returns A mapping from node id to an array of child node ids.\n */\nexport function buildAdjacency(nodes: DagNode[], edges: DagEdge[]): Adjacency {\n const adjacency: Adjacency = {};\n for (const n of nodes) adjacency[n.id] = [];\n for (const e of edges) {\n const list = adjacency[e.source] || (adjacency[e.source] = []);\n list.push(e.target);\n }\n return adjacency;\n}\n\n/**\n * Find a node by id in a list of nodes.\n *\n * @param nodes - Array of nodes with an `id` field.\n * @param id - The node id to find.\n * @returns The node if found, otherwise undefined.\n */\nexport function findNodeById<T extends {id: string}>(\n nodes: T[],\n id: string,\n): T | undefined {\n return nodes.find((n) => n.id === id);\n}\n\n/**\n * Topologically sort all nodes in the graph using Kahn's algorithm.\n * If a cycle is detected, the remaining nodes are appended in arbitrary order,\n * and a warning is logged.\n *\n * @param nodes - The set of nodes to sort.\n * @param edges - Directed edges defining dependencies.\n * @returns An array of node ids in dependency order (parents before children).\n */\nexport function topoSortAll(nodes: DagNode[], edges: DagEdge[]): string[] {\n const adjacency = buildAdjacency(nodes, edges);\n const inDegree: Record<string, number> = {};\n for (const n of nodes) inDegree[n.id] = 0;\n for (const e of edges) {\n inDegree[e.target] = (inDegree[e.target] ?? 0) + 1;\n }\n\n const queue: string[] = Object.keys(inDegree).filter(\n (id) => (inDegree[id] ?? 0) === 0,\n );\n const order: string[] = [];\n while (queue.length) {\n const cur = queue.shift() as string;\n order.push(cur);\n const neighbors = adjacency[cur] || [];\n for (const nb of neighbors) {\n inDegree[nb] = (inDegree[nb] ?? 0) - 1;\n if (inDegree[nb] === 0) queue.push(nb);\n }\n }\n\n if (order.length < nodes.length) {\n const remaining = nodes\n .map((n) => n.id)\n .filter((id) => !order.includes(id));\n // eslint-disable-next-line no-console\n console.warn(\n '[dag.topoSortAll] Cycle detected; appending remaining nodes arbitrarily:',\n remaining,\n );\n order.push(...remaining);\n }\n return order;\n}\n\n/**\n * Get a topological order for the downstream subgraph reachable from `startId`.\n * Only nodes reachable from the start are included (the starting node is excluded).\n * If a cycle exists within the reachable subgraph, the remaining nodes are appended\n * at the end in arbitrary order and a warning is logged.\n *\n * @param startId - The node id to start traversal from.\n * @param nodes - The set of nodes in the full graph.\n * @param edges - Directed edges defining the full graph dependencies.\n * @returns Node ids reachable from `startId`, in dependency order.\n */\nexport function topoSortDownstream(\n startId: string,\n nodes: DagNode[],\n edges: DagEdge[],\n): string[] {\n const adjacency = buildAdjacency(nodes, edges);\n // Collect reachable nodes from startId (excluding start)\n const reachable = new Set<string>();\n const queue: string[] = [...(adjacency[startId] || [])];\n while (queue.length) {\n const cur = queue.shift() as string;\n if (reachable.has(cur)) continue;\n reachable.add(cur);\n const neighbors = adjacency[cur] || [];\n for (const nb of neighbors) queue.push(nb);\n }\n if (reachable.size === 0) return [];\n\n // Kahn's algorithm for topological sort within subgraph\n const inDegree: Record<string, number> = {};\n for (const id of reachable) inDegree[id] = 0;\n for (const e of edges) {\n if (reachable.has(e.source) && reachable.has(e.target)) {\n inDegree[e.target] = (inDegree[e.target] ?? 0) + 1;\n }\n }\n const queue2: string[] = Array.from(reachable).filter(\n (id) => (inDegree[id] ?? 0) === 0,\n );\n const order: string[] = [];\n while (queue2.length) {\n const cur = queue2.shift() as string;\n order.push(cur);\n const neighbors = adjacency[cur] || [];\n for (const nb of neighbors) {\n if (!reachable.has(nb)) continue;\n inDegree[nb] = (inDegree[nb] ?? 0) - 1;\n if (inDegree[nb] === 0) queue2.push(nb);\n }\n }\n if (order.length < reachable.size) {\n const remaining = Array.from(reachable).filter((id) => !order.includes(id));\n // eslint-disable-next-line no-console\n console.warn(\n '[dag.topoSortDownstream] Cycle detected in downstream graph:',\n remaining,\n );\n order.push(...remaining);\n }\n return order;\n}\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,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC,CAkCH,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
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
5
|
export const AddNodePopover = ({ className, parentId, children }) => {
|
|
@@ -7,17 +7,13 @@ export const AddNodePopover = ({ className, parentId, children }) => {
|
|
|
7
7
|
const addNode = useStoreWithCanvas((s) => s.canvas.addNode);
|
|
8
8
|
const sheetId = useStoreWithCanvas((s) => s.cells.config.currentSheetId);
|
|
9
9
|
const registry = useStoreWithCanvas((s) => s.cells.cellRegistry);
|
|
10
|
-
const { toast } = useToast();
|
|
11
10
|
const onAdd = (type) => {
|
|
12
11
|
if (sheetId) {
|
|
13
12
|
addNode({ sheetId, parentId, nodeType: type });
|
|
14
13
|
setOpen(false);
|
|
15
14
|
}
|
|
16
15
|
else {
|
|
17
|
-
toast(
|
|
18
|
-
variant: 'destructive',
|
|
19
|
-
description: 'No sheet selected',
|
|
20
|
-
});
|
|
16
|
+
toast.error('No sheet selected');
|
|
21
17
|
}
|
|
22
18
|
};
|
|
23
19
|
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,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;IAEjE,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,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACnC,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 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\n const onAdd = (type: string) => {\n if (sheetId) {\n addNode({sheetId, parentId, nodeType: type});\n setOpen(false);\n } else {\n toast.error('No sheet 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"]}
|
|
@@ -22,6 +22,6 @@ export const CanvasNodeContainer = ({ id, className, headerRight, children }) =>
|
|
|
22
22
|
const onTitleChange = useCallback(async (v) => {
|
|
23
23
|
await renameNode(id, v);
|
|
24
24
|
}, [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
|
|
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 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
26
|
};
|
|
27
27
|
//# 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
|
|
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 top-1/2 -right-10\" 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"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import { CanvasNodeData } from '../CanvasSlice';
|
|
3
|
+
type SqlData = Extract<CanvasNodeData, {
|
|
4
|
+
type: 'sql';
|
|
5
|
+
}>;
|
|
6
|
+
export declare const SqlNode: FC<{
|
|
7
|
+
id: string;
|
|
8
|
+
data: SqlData;
|
|
9
|
+
}>;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=SqlNode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SqlNode.d.ts","sourceRoot":"","sources":["../../src/nodes/SqlNode.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAC,EAAE,EAAoB,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAC,cAAc,EAAqB,MAAM,gBAAgB,CAAC;AAelE,KAAK,OAAO,GAAG,OAAO,CAAC,cAAc,EAAE;IAAC,IAAI,EAAE,KAAK,CAAA;CAAC,CAAC,CAAC;AAEtD,eAAO,MAAM,OAAO,EAAE,EAAE,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAC,CAgGnD,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { QueryDataTable } from '@sqlrooms/data-table';
|
|
3
|
+
import { SqlMonacoEditor } from '@sqlrooms/sql-editor';
|
|
4
|
+
import { Button, useToast } from '@sqlrooms/ui';
|
|
5
|
+
import { useMemo, useState } from 'react';
|
|
6
|
+
import { useStoreWithCanvas } from '../CanvasSlice';
|
|
7
|
+
import { CanvasNodeContainer } from './CanvasNodeContainer';
|
|
8
|
+
// import type * as Monaco from 'monaco-editor';
|
|
9
|
+
// type EditorInstance = Monaco.editor.IStandaloneCodeEditor;
|
|
10
|
+
// type MonacoInstance = typeof Monaco;
|
|
11
|
+
const EDITOR_OPTIONS = {
|
|
12
|
+
minimap: { enabled: false },
|
|
13
|
+
lineNumbers: 'off',
|
|
14
|
+
scrollbar: {
|
|
15
|
+
handleMouseWheel: false,
|
|
16
|
+
},
|
|
17
|
+
fixedOverflowWidgets: false,
|
|
18
|
+
};
|
|
19
|
+
export const SqlNode = ({ id, data }) => {
|
|
20
|
+
const sql = data.sql || '';
|
|
21
|
+
const updateNode = useStoreWithCanvas((s) => s.canvas.updateNode);
|
|
22
|
+
const tables = useStoreWithCanvas((s) => s.db.tables);
|
|
23
|
+
const execute = useStoreWithCanvas((s) => s.canvas.executeSqlNodeQuery);
|
|
24
|
+
const result = useStoreWithCanvas((s) => s.canvas.sqlResults[id]);
|
|
25
|
+
const { toast } = useToast();
|
|
26
|
+
// const handleEditorMount = useCallback(
|
|
27
|
+
// (editor: EditorInstance, monaco: MonacoInstance) => {
|
|
28
|
+
// editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, () => {
|
|
29
|
+
// if (editor.hasTextFocus()) {
|
|
30
|
+
// execute(id);
|
|
31
|
+
// }
|
|
32
|
+
// });
|
|
33
|
+
// },
|
|
34
|
+
// [execute],
|
|
35
|
+
// );
|
|
36
|
+
// const reactFlowContainerRef = useRef<HTMLDivElement>(null);
|
|
37
|
+
// useEffect(() => {
|
|
38
|
+
// reactFlowContainerRef.current = document.querySelector<HTMLDivElement>(
|
|
39
|
+
// '.react-flow__renderer',
|
|
40
|
+
// );
|
|
41
|
+
// }, []);
|
|
42
|
+
const [overflowWidgetsDomNode, setOverflowWidgetsDomNode] = useState(null);
|
|
43
|
+
const editorOptions = useMemo(() => overflowWidgetsDomNode
|
|
44
|
+
? {
|
|
45
|
+
...EDITOR_OPTIONS,
|
|
46
|
+
overflowWidgetsDomNode: overflowWidgetsDomNode ?? undefined,
|
|
47
|
+
fixedOverflowWidgets: false,
|
|
48
|
+
}
|
|
49
|
+
: EDITOR_OPTIONS, [overflowWidgetsDomNode]);
|
|
50
|
+
return (_jsx(CanvasNodeContainer, { id: id, headerRight: _jsxs(_Fragment, { children: [_jsx(Button, { size: "sm", variant: "secondary", onClick: () => execute(id), children: "Run" }), _jsx("span", { className: "text-[10px] uppercase text-gray-500", children: "SQL" })] }), children: _jsxs("div", { className: "flex h-full w-full flex-col", children: [_jsx("div", { className: "relative flex-1", children: _jsx(SqlMonacoEditor, { className: "absolute inset-0 p-1", value: sql, options: editorOptions, onChange: (v) => updateNode(id, (d) => ({ ...d, sql: v || '' })), tableSchemas: tables }) }), result?.status === 'error' && (_jsx("div", { className: "flex-1 overflow-auto whitespace-pre-wrap border-t p-4 font-mono text-xs text-red-600", children: result.error })), result?.status === 'success' && (_jsx("div", { className: "flex-[2] overflow-hidden border-t", children: _jsx(QueryDataTable, { query: `SELECT * FROM ${result.tableName}`, fontSize: "text-xs" }) }))] }) }));
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=SqlNode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SqlNode.js","sourceRoot":"","sources":["../../src/nodes/SqlNode.tsx"],"names":[],"mappings":"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","sourcesContent":["import {QueryDataTable} from '@sqlrooms/data-table';\nimport {SqlMonacoEditor} from '@sqlrooms/sql-editor';\nimport {Button, useToast} from '@sqlrooms/ui';\nimport {FC, useMemo, useState} from 'react';\nimport {CanvasNodeData, useStoreWithCanvas} from '../CanvasSlice';\nimport {CanvasNodeContainer} from './CanvasNodeContainer';\n// import type * as Monaco from 'monaco-editor';\n// type EditorInstance = Monaco.editor.IStandaloneCodeEditor;\n// type MonacoInstance = typeof Monaco;\n\nconst EDITOR_OPTIONS: Parameters<typeof SqlMonacoEditor>[0]['options'] = {\n minimap: {enabled: false},\n lineNumbers: 'off',\n scrollbar: {\n handleMouseWheel: false,\n },\n fixedOverflowWidgets: false,\n};\n\ntype SqlData = Extract<CanvasNodeData, {type: 'sql'}>;\n\nexport const SqlNode: FC<{id: string; data: SqlData}> = ({id, data}) => {\n const sql = data.sql || '';\n const updateNode = useStoreWithCanvas((s) => s.canvas.updateNode);\n const tables = useStoreWithCanvas((s) => s.db.tables);\n const execute = useStoreWithCanvas((s) => s.canvas.executeSqlNodeQuery);\n const result = useStoreWithCanvas((s) => s.canvas.sqlResults[id]);\n const {toast} = useToast();\n\n // const handleEditorMount = useCallback(\n // (editor: EditorInstance, monaco: MonacoInstance) => {\n // editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, () => {\n // if (editor.hasTextFocus()) {\n // execute(id);\n // }\n // });\n // },\n // [execute],\n // );\n\n // const reactFlowContainerRef = useRef<HTMLDivElement>(null);\n // useEffect(() => {\n // reactFlowContainerRef.current = document.querySelector<HTMLDivElement>(\n // '.react-flow__renderer',\n // );\n // }, []);\n const [overflowWidgetsDomNode, setOverflowWidgetsDomNode] =\n useState<HTMLDivElement | null>(null);\n\n const editorOptions = useMemo(\n (): typeof EDITOR_OPTIONS =>\n overflowWidgetsDomNode\n ? {\n ...EDITOR_OPTIONS,\n overflowWidgetsDomNode: overflowWidgetsDomNode ?? undefined,\n fixedOverflowWidgets: false,\n }\n : EDITOR_OPTIONS,\n [overflowWidgetsDomNode],\n );\n\n return (\n <CanvasNodeContainer\n id={id}\n headerRight={\n <>\n <Button size=\"sm\" variant=\"secondary\" onClick={() => execute(id)}>\n Run\n </Button>\n <span className=\"text-[10px] uppercase text-gray-500\">SQL</span>\n </>\n }\n >\n <div className=\"flex h-full w-full flex-col\">\n <div className=\"relative flex-1\">\n <SqlMonacoEditor\n className=\"absolute inset-0 p-1\"\n value={sql}\n options={editorOptions}\n onChange={(v) =>\n updateNode(id, (d) => ({...(d as SqlData), sql: v || ''}))\n }\n tableSchemas={tables}\n // onMount={handleEditorMount}\n />\n </div>\n {result?.status === 'error' && (\n <div className=\"flex-1 overflow-auto whitespace-pre-wrap border-t p-4 font-mono text-xs text-red-600\">\n {result.error}\n </div>\n )}\n {result?.status === 'success' && (\n <div className=\"flex-[2] overflow-hidden border-t\">\n <QueryDataTable\n query={`SELECT * FROM ${result.tableName}`}\n fontSize=\"text-xs\"\n />\n </div>\n )}\n </div>\n {/* {reactFlowContainerRef.current &&\n createPortal(\n <div\n ref={(node) => {\n if (node && !overflowWidgetsDomNode) {\n setOverflowWidgetsDomNode(node);\n }\n }}\n // CRITICAL: You must re-apply the monaco class here!\n className=\"monaco-editor\"\n // CRITICAL: Styles to ensure overlays position correctly relative to window\n style={{position: 'absolute', top: 0, left: 0}}\n />,\n reactFlowContainerRef.current,\n )} */}\n </CanvasNodeContainer>\n );\n};\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import { CanvasNodeData } from '../CanvasSlice';
|
|
3
|
+
type VegaData = Extract<CanvasNodeData, {
|
|
4
|
+
type: 'vega';
|
|
5
|
+
}>;
|
|
6
|
+
export declare const VegaNode: FC<{
|
|
7
|
+
id: string;
|
|
8
|
+
data: VegaData;
|
|
9
|
+
}>;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=VegaNode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VegaNode.d.ts","sourceRoot":"","sources":["../../src/nodes/VegaNode.tsx"],"names":[],"mappings":"AACA,OAAO,EAAC,EAAE,EAAC,MAAM,OAAO,CAAC;AACzB,OAAO,EAAC,cAAc,EAAC,MAAM,gBAAgB,CAAC;AAG9C,KAAK,QAAQ,GAAG,OAAO,CAAC,cAAc,EAAE;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC,CAAC,CAAC;AAExD,eAAO,MAAM,QAAQ,EAAE,EAAE,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAC,CA2BrD,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { VegaLiteChart } from '@sqlrooms/vega';
|
|
3
|
+
import { CanvasNodeContainer } from './CanvasNodeContainer';
|
|
4
|
+
export const VegaNode = ({ id, data }) => {
|
|
5
|
+
const spec = (data.vegaSpec || {
|
|
6
|
+
mark: 'point',
|
|
7
|
+
data: { values: [] },
|
|
8
|
+
});
|
|
9
|
+
const { vegaSpec, sql } = data;
|
|
10
|
+
return (_jsx(CanvasNodeContainer, { id: id, headerRight: _jsx("span", { className: "text-[10px] uppercase text-gray-500", children: "Vega" }), children: _jsx("div", { className: "h-full flex-1 overflow-hidden p-2", children: sql && vegaSpec ? (_jsx(VegaLiteChart, { spec: vegaSpec, sqlQuery: sql, aspectRatio: 16 / 9, className: "h-full" })) : null }) }));
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=VegaNode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VegaNode.js","sourceRoot":"","sources":["../../src/nodes/VegaNode.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,aAAa,EAAyB,MAAM,gBAAgB,CAAC;AAGrE,OAAO,EAAC,mBAAmB,EAAC,MAAM,uBAAuB,CAAC;AAI1D,MAAM,CAAC,MAAM,QAAQ,GAAqC,CAAC,EAAC,EAAE,EAAE,IAAI,EAAC,EAAE,EAAE;IACvE,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI;QAC7B,IAAI,EAAE,OAAO;QACb,IAAI,EAAE,EAAC,MAAM,EAAE,EAAE,EAAC;KACnB,CAAsB,CAAC;IAExB,MAAM,EAAC,QAAQ,EAAE,GAAG,EAAC,GAAG,IAAI,CAAC;IAE7B,OAAO,CACL,KAAC,mBAAmB,IAClB,EAAE,EAAE,EAAE,EACN,WAAW,EACT,eAAM,SAAS,EAAC,qCAAqC,qBAAY,YAGnE,cAAK,SAAS,EAAC,mCAAmC,YAC/C,GAAG,IAAI,QAAQ,CAAC,CAAC,CAAC,CACjB,KAAC,aAAa,IACZ,IAAI,EAAE,QAAQ,EACd,QAAQ,EAAE,GAAG,EACb,WAAW,EAAE,EAAE,GAAG,CAAC,EACnB,SAAS,EAAC,QAAQ,GAClB,CACH,CAAC,CAAC,CAAC,IAAI,GACJ,GACc,CACvB,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import {VegaLiteChart, type VisualizationSpec} from '@sqlrooms/vega';\nimport {FC} from 'react';\nimport {CanvasNodeData} from '../CanvasSlice';\nimport {CanvasNodeContainer} from './CanvasNodeContainer';\n\ntype VegaData = Extract<CanvasNodeData, {type: 'vega'}>;\n\nexport const VegaNode: FC<{id: string; data: VegaData}> = ({id, data}) => {\n const spec = (data.vegaSpec || {\n mark: 'point',\n data: {values: []},\n }) as VisualizationSpec;\n\n const {vegaSpec, sql} = data;\n\n return (\n <CanvasNodeContainer\n id={id}\n headerRight={\n <span className=\"text-[10px] uppercase text-gray-500\">Vega</span>\n }\n >\n <div className=\"h-full flex-1 overflow-hidden p-2\">\n {sql && vegaSpec ? (\n <VegaLiteChart\n spec={vegaSpec}\n sqlQuery={sql}\n aspectRatio={16 / 9}\n className=\"h-full\"\n />\n ) : null}\n </div>\n </CanvasNodeContainer>\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.2",
|
|
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.2",
|
|
36
|
+
"@sqlrooms/crdt": "0.29.0-rc.2",
|
|
37
|
+
"@sqlrooms/duckdb": "0.29.0-rc.2",
|
|
38
|
+
"@sqlrooms/room-store": "0.29.0-rc.2",
|
|
39
|
+
"@sqlrooms/ui": "0.29.0-rc.2",
|
|
40
|
+
"@sqlrooms/utils": "0.29.0-rc.2",
|
|
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": "5d511631992c1af8852ea79ced488867aad4a555"
|
|
59
59
|
}
|