From 91d6aac2a44d1baf5aae6c56edc0fb8825b2307e Mon Sep 17 00:00:00 2001 From: shrimbly Date: Fri, 16 Jan 2026 22:29:36 +1300 Subject: [PATCH] feat(26-01): create WorkflowPreview component - Add WorkflowPreview component with non-interactive React Flow - Simple colored rectangles represent different node types - Supports fitView for automatic scaling within container - Uses ReactFlowProvider for standalone usage --- src/components/quickstart/WorkflowPreview.tsx | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 src/components/quickstart/WorkflowPreview.tsx diff --git a/src/components/quickstart/WorkflowPreview.tsx b/src/components/quickstart/WorkflowPreview.tsx new file mode 100644 index 00000000..b2c4d8eb --- /dev/null +++ b/src/components/quickstart/WorkflowPreview.tsx @@ -0,0 +1,120 @@ +"use client"; + +import { useMemo } from "react"; +import { + ReactFlow, + ReactFlowProvider, + Node, + Edge, +} from "@xyflow/react"; +import "@xyflow/react/dist/style.css"; + +// Node type to color mapping - using minimap colors from WorkflowCanvas +const NODE_COLORS: Record = { + imageInput: "#22c55e", // green-500 + annotation: "#eab308", // yellow-500 + prompt: "#3b82f6", // blue-500 + nanoBanana: "#f97316", // orange-500 + generateVideo: "#a855f7", // purple-500 + llmGenerate: "#06b6d4", // cyan-500 + splitGrid: "#ec4899", // pink-500 + output: "#6b7280", // gray-500 +}; + +// Simple preview node component - just a colored rectangle +function PreviewNode({ data }: { data: { nodeType: string } }) { + const color = NODE_COLORS[data.nodeType] || "#6b7280"; + + return ( +
+ ); +} + +const previewNodeTypes = { + preview: PreviewNode, +}; + +interface WorkflowPreviewProps { + workflow: { + nodes: Node[]; + edges: Edge[]; + }; + className?: string; +} + +function WorkflowPreviewInner({ workflow, className = "" }: WorkflowPreviewProps) { + // Transform workflow nodes to preview nodes + const previewNodes = useMemo(() => { + return workflow.nodes.map((node) => ({ + id: node.id, + type: "preview", + position: node.position, + data: { nodeType: node.type || "unknown" }, + // Scale down the node sizes for preview + style: { + width: ((node.style?.width as number) || 300) * 0.15, + height: ((node.style?.height as number) || 280) * 0.15, + }, + })); + }, [workflow.nodes]); + + // Use the workflow edges as-is (simplified rendering) + const previewEdges = useMemo(() => { + return workflow.edges.map((edge) => ({ + id: edge.id, + source: edge.source, + target: edge.target, + // Simple edge style + style: { stroke: "#525252", strokeWidth: 1 }, + type: "default", + })); + }, [workflow.edges]); + + return ( +
+ +
+ ); +} + +// Wrap with ReactFlowProvider for standalone usage +export function WorkflowPreview(props: WorkflowPreviewProps) { + return ( + + + + ); +}