feat: implement Story 2.1 — canvas workspace with @xyflow/react and unified graph model

Replace the placeholder diagram editor with a professional Studio layout featuring
an interactive @xyflow/react canvas, unified graph data model with bidirectional
converters, Zustand state management, and oklch design tokens. Includes 25 unit
tests for converters and store, with all code review fixes applied.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Alejandro Gutiérrez
2026-02-24 02:07:59 +00:00
parent 098f4968be
commit 5033109656
17 changed files with 1922 additions and 96 deletions

View File

@@ -0,0 +1,59 @@
"use client";
import {
ReactFlow,
ReactFlowProvider,
Background,
Controls,
MiniMap,
BackgroundVariant,
} from "@xyflow/react";
import { useGraphStore } from "../../stores/useGraphStore";
const nodeTypes = {};
function CanvasInner() {
const nodes = useGraphStore((s) => s.nodes);
const edges = useGraphStore((s) => s.edges);
const onNodesChange = useGraphStore((s) => s.onNodesChange);
const onEdgesChange = useGraphStore((s) => s.onEdgesChange);
const onViewportChange = useGraphStore((s) => s.onViewportChange);
return (
<div className="w-full h-full">
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onViewportChange={onViewportChange}
nodeTypes={nodeTypes}
fitView
colorMode="system"
proOptions={{ hideAttribution: true }}
>
<Background
variant={BackgroundVariant.Dots}
gap={20}
size={1}
color="var(--canvas-grid)"
/>
<Controls showInteractive={false} />
<MiniMap
pannable
zoomable
style={{ width: 120, height: 80 }}
/>
</ReactFlow>
</div>
);
}
export function DiagramCanvas() {
return (
<ReactFlowProvider>
<CanvasInner />
</ReactFlowProvider>
);
}