@pyreon/flow 0.11.5 → 0.11.7
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 +10 -10
- package/lib/index.js.map +1 -1
- package/lib/types/index.d.ts +13 -13
- package/package.json +16 -16
- package/src/components/background.tsx +8 -8
- package/src/components/controls.tsx +9 -9
- package/src/components/flow-component.tsx +46 -46
- package/src/components/handle.tsx +8 -8
- package/src/components/minimap.tsx +5 -5
- package/src/components/node-resizer.tsx +25 -25
- package/src/components/node-toolbar.tsx +12 -12
- package/src/components/panel.tsx +9 -9
- package/src/edges.ts +6 -6
- package/src/flow.ts +11 -11
- package/src/index.ts +17 -17
- package/src/layout.ts +23 -23
- package/src/tests/flow-advanced.test.ts +190 -190
- package/src/tests/flow.test.ts +417 -417
- package/src/types.ts +24 -24
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["positionStyles","positionStyles"],"sources":["../../../core/core/lib/jsx-runtime.js","../src/components/background.tsx","../src/components/controls.tsx","../src/types.ts","../src/edges.ts","../src/components/flow-component.tsx","../src/components/handle.tsx","../src/components/minimap.tsx","../src/components/node-resizer.tsx","../src/components/node-toolbar.tsx","../src/components/panel.tsx","../src/layout.ts","../src/flow.ts","../src/styles.ts"],"sourcesContent":["//#region src/h.ts\n/** Marker for fragment nodes — renders children without a wrapper element */\nconst Fragment = Symbol(\"Pyreon.Fragment\");\n/**\n* Hyperscript function — the compiled output of JSX.\n* `<div class=\"x\">hello</div>` → `h(\"div\", { class: \"x\" }, \"hello\")`\n*\n* Generic on P so TypeScript validates props match the component's signature\n* at the call site, then stores the result in the loosely-typed VNode.\n*/\n/** Shared empty props sentinel — identity-checked in mountElement to skip applyProps. */\nconst EMPTY_PROPS = {};\nfunction h(type, props, ...children) {\n\treturn {\n\t\ttype,\n\t\tprops: props ?? EMPTY_PROPS,\n\t\tchildren: normalizeChildren(children),\n\t\tkey: props?.key ?? null\n\t};\n}\nfunction normalizeChildren(children) {\n\tfor (let i = 0; i < children.length; i++) if (Array.isArray(children[i])) return flattenChildren(children);\n\treturn children;\n}\nfunction flattenChildren(children) {\n\tconst result = [];\n\tfor (const child of children) if (Array.isArray(child)) result.push(...flattenChildren(child));\n\telse result.push(child);\n\treturn result;\n}\n\n//#endregion\n//#region src/jsx-runtime.ts\n/**\n* JSX automatic runtime.\n*\n* When tsconfig has `\"jsxImportSource\": \"@pyreon/core\"`, the TS/bundler compiler\n* rewrites JSX to imports from this file automatically:\n* <div class=\"x\" /> → jsx(\"div\", { class: \"x\" })\n*/\nfunction jsx(type, props, key) {\n\tconst { children, ...rest } = props;\n\tconst propsWithKey = key != null ? {\n\t\t...rest,\n\t\tkey\n\t} : rest;\n\tif (typeof type === \"function\") return h(type, children !== void 0 ? {\n\t\t...propsWithKey,\n\t\tchildren\n\t} : propsWithKey);\n\treturn h(type, propsWithKey, ...children === void 0 ? [] : Array.isArray(children) ? children : [children]);\n}\nconst jsxs = jsx;\n\n//#endregion\nexport { Fragment, jsx, jsxs };\n//# sourceMappingURL=jsx-runtime.js.map","import type { VNodeChild } from \"@pyreon/core\"\nimport type { BackgroundProps } from \"../types\"\n\n/**\n * Background pattern for the flow canvas.\n * Renders dots, lines, or cross patterns that move with the viewport.\n *\n * @example\n * ```tsx\n * <Flow instance={flow}>\n * <Background variant=\"dots\" gap={20} />\n * </Flow>\n * ```\n */\nexport function Background(props: BackgroundProps): VNodeChild {\n const { variant = \"dots\", gap = 20, size = 1, color = \"#ddd\" } = props\n\n const patternId = `flow-bg-${variant}`\n\n if (variant === \"dots\") {\n return (\n <svg\n role=\"img\"\n aria-label=\"background pattern\"\n class=\"pyreon-flow-background\"\n style=\"position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none;\"\n >\n <defs>\n <pattern\n id={patternId}\n x=\"0\"\n y=\"0\"\n width={String(gap)}\n height={String(gap)}\n {...{ patternUnits: \"userSpaceOnUse\" }}\n >\n <circle cx={String(size)} cy={String(size)} r={String(size)} fill={color} />\n </pattern>\n </defs>\n <rect width=\"100%\" height=\"100%\" fill={`url(#${patternId})`} />\n </svg>\n )\n }\n\n if (variant === \"lines\") {\n return (\n <svg\n role=\"img\"\n aria-label=\"background pattern\"\n class=\"pyreon-flow-background\"\n style=\"position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none;\"\n >\n <defs>\n <pattern\n id={patternId}\n x=\"0\"\n y=\"0\"\n width={String(gap)}\n height={String(gap)}\n {...{ patternUnits: \"userSpaceOnUse\" }}\n >\n <line\n x1=\"0\"\n y1={String(gap)}\n x2={String(gap)}\n y2={String(gap)}\n stroke={color}\n stroke-width={String(size)}\n />\n <line\n x1={String(gap)}\n y1=\"0\"\n x2={String(gap)}\n y2={String(gap)}\n stroke={color}\n stroke-width={String(size)}\n />\n </pattern>\n </defs>\n <rect width=\"100%\" height=\"100%\" fill={`url(#${patternId})`} />\n </svg>\n )\n }\n\n // cross\n return (\n <svg\n role=\"img\"\n aria-label=\"background pattern\"\n class=\"pyreon-flow-background\"\n style=\"position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none;\"\n >\n <defs>\n <pattern\n id={patternId}\n x=\"0\"\n y=\"0\"\n width={String(gap)}\n height={String(gap)}\n {...{ patternUnits: \"userSpaceOnUse\" }}\n >\n <line\n x1={String(gap / 2 - size * 2)}\n y1={String(gap / 2)}\n x2={String(gap / 2 + size * 2)}\n y2={String(gap / 2)}\n stroke={color}\n stroke-width={String(size)}\n />\n <line\n x1={String(gap / 2)}\n y1={String(gap / 2 - size * 2)}\n x2={String(gap / 2)}\n y2={String(gap / 2 + size * 2)}\n stroke={color}\n stroke-width={String(size)}\n />\n </pattern>\n </defs>\n <rect width=\"100%\" height=\"100%\" fill={`url(#${patternId})`} />\n </svg>\n )\n}\n","import type { VNodeChild } from \"@pyreon/core\"\nimport type { ControlsProps, FlowInstance } from \"../types\"\n\nconst positionStyles: Record<string, string> = {\n \"top-left\": \"top: 10px; left: 10px;\",\n \"top-right\": \"top: 10px; right: 10px;\",\n \"bottom-left\": \"bottom: 10px; left: 10px;\",\n \"bottom-right\": \"bottom: 10px; right: 10px;\",\n}\n\n// Simple SVG icons\nconst ZoomInIcon = () => (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n >\n <circle cx=\"7\" cy=\"7\" r=\"5\" />\n <line x1=\"7\" y1=\"5\" x2=\"7\" y2=\"9\" />\n <line x1=\"5\" y1=\"7\" x2=\"9\" y2=\"7\" />\n <line x1=\"11\" y1=\"11\" x2=\"14\" y2=\"14\" />\n </svg>\n)\n\nconst ZoomOutIcon = () => (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n >\n <circle cx=\"7\" cy=\"7\" r=\"5\" />\n <line x1=\"5\" y1=\"7\" x2=\"9\" y2=\"7\" />\n <line x1=\"11\" y1=\"11\" x2=\"14\" y2=\"14\" />\n </svg>\n)\n\nconst FitViewIcon = () => (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n >\n <rect x=\"2\" y=\"2\" width=\"12\" height=\"12\" rx=\"2\" />\n <line x1=\"2\" y1=\"6\" x2=\"14\" y2=\"6\" />\n <line x1=\"6\" y1=\"2\" x2=\"6\" y2=\"14\" />\n </svg>\n)\n\nconst LockIcon = () => (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n >\n <rect x=\"3\" y=\"7\" width=\"10\" height=\"7\" rx=\"1\" />\n <path d=\"M5 7V5a3 3 0 0 1 6 0v2\" />\n </svg>\n)\n\n/**\n * Zoom and viewport controls for the flow canvas.\n * Shows zoom in, zoom out, fit view, and optional lock button.\n *\n * @example\n * ```tsx\n * <Flow instance={flow}>\n * <Controls />\n * </Flow>\n * ```\n */\nexport function Controls(props: ControlsProps & { instance?: FlowInstance }): VNodeChild {\n const {\n showZoomIn = true,\n showZoomOut = true,\n showFitView = true,\n showLock = false,\n position = \"bottom-left\",\n instance,\n } = props\n\n if (!instance) return null\n\n const baseStyle = `position: absolute; ${positionStyles[position] ?? positionStyles[\"bottom-left\"]} display: flex; flex-direction: column; gap: 2px; z-index: 5; background: white; border: 1px solid #ddd; border-radius: 6px; padding: 2px; box-shadow: 0 1px 4px rgba(0,0,0,0.08);`\n const btnStyle =\n \"width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; border: none; background: transparent; border-radius: 4px; cursor: pointer; color: #555; padding: 0;\"\n\n return () => {\n const zoomPercent = Math.round(instance.zoom() * 100)\n\n return (\n <div class=\"pyreon-flow-controls\" style={baseStyle}>\n {showZoomIn && (\n <button type=\"button\" style={btnStyle} title=\"Zoom in\" onClick={() => instance.zoomIn()}>\n <ZoomInIcon />\n </button>\n )}\n {showZoomOut && (\n <button\n type=\"button\"\n style={btnStyle}\n title=\"Zoom out\"\n onClick={() => instance.zoomOut()}\n >\n <ZoomOutIcon />\n </button>\n )}\n {showFitView && (\n <button\n type=\"button\"\n style={btnStyle}\n title=\"Fit view\"\n onClick={() => instance.fitView()}\n >\n <FitViewIcon />\n </button>\n )}\n {showLock && (\n <button\n type=\"button\"\n style={btnStyle}\n title=\"Lock/unlock\"\n onClick={() => {\n // Toggle pan/zoom by updating config\n // This is a simple toggle — could be improved with state\n }}\n >\n <LockIcon />\n </button>\n )}\n <div\n style=\"font-size: 10px; text-align: center; color: #999; padding: 2px 0; user-select: none;\"\n title=\"Current zoom level\"\n >\n {zoomPercent}%\n </div>\n </div>\n )\n }\n}\n","import type { VNodeChild } from \"@pyreon/core\"\nimport type { Computed, Signal } from \"@pyreon/reactivity\"\n\n// ─── Position & Geometry ─────────────────────────────────────────────────────\n\nexport interface XYPosition {\n x: number\n y: number\n}\n\nexport interface Dimensions {\n width: number\n height: number\n}\n\nexport interface Rect extends XYPosition, Dimensions {}\n\n// ─── Viewport ────────────────────────────────────────────────────────────────\n\nexport interface Viewport {\n x: number\n y: number\n zoom: number\n}\n\n// ─── Handle ──────────────────────────────────────────────────────────────────\n\nexport type HandleType = \"source\" | \"target\"\n\nexport enum Position {\n Top = \"top\",\n Right = \"right\",\n Bottom = \"bottom\",\n Left = \"left\",\n}\n\nexport interface HandleConfig {\n id?: string\n type: HandleType\n position: Position\n}\n\n// ─── Node ────────────────────────────────────────────────────────────────────\n\nexport interface FlowNode<TData = Record<string, unknown>> {\n id: string\n type?: string\n position: XYPosition\n data: TData\n width?: number\n height?: number\n /** Whether the node can be dragged */\n draggable?: boolean\n /** Whether the node can be selected */\n selectable?: boolean\n /** Whether the node can be connected to */\n connectable?: boolean\n /** Custom class name */\n class?: string\n /** Custom style */\n style?: string\n /** Source handles */\n sourceHandles?: HandleConfig[]\n /** Target handles */\n targetHandles?: HandleConfig[]\n /** Parent node id for grouping */\n parentId?: string\n /** Whether this node is a group */\n group?: boolean\n}\n\n// ─── Edge ────────────────────────────────────────────────────────────────────\n\nexport type EdgeType = \"bezier\" | \"smoothstep\" | \"straight\" | \"step\"\n\nexport interface FlowEdge {\n id?: string\n source: string\n target: string\n sourceHandle?: string\n targetHandle?: string\n type?: EdgeType\n label?: string\n animated?: boolean\n class?: string\n style?: string\n /** Custom data attached to the edge */\n data?: Record<string, unknown>\n /** Waypoints — intermediate points the edge passes through */\n waypoints?: XYPosition[]\n}\n\n// ─── Connection ──────────────────────────────────────────────────────────────\n\nexport interface Connection {\n source: string\n target: string\n sourceHandle?: string\n targetHandle?: string\n}\n\nexport type ConnectionRule = Record<string, { outputs: string[] }>\n\n// ─── Node Change Events ──────────────────────────────────────────────────────\n\nexport type NodeChange =\n | { type: \"position\"; id: string; position: XYPosition }\n | { type: \"dimensions\"; id: string; dimensions: Dimensions }\n | { type: \"select\"; id: string; selected: boolean }\n | { type: \"remove\"; id: string }\n\n// ─── Edge path result ────────────────────────────────────────────────────────\n\nexport interface EdgePathResult {\n path: string\n labelX: number\n labelY: number\n}\n\n// ─── Flow config ─────────────────────────────────────────────────────────────\n\nexport interface FlowConfig {\n nodes?: FlowNode[]\n edges?: FlowEdge[]\n /** Default edge type */\n defaultEdgeType?: EdgeType\n /** Min zoom level — default: 0.1 */\n minZoom?: number\n /** Max zoom level — default: 4 */\n maxZoom?: number\n /** Snap to grid */\n snapToGrid?: boolean\n /** Grid size for snapping — default: 15 */\n snapGrid?: number\n /** Connection rules — which node types can connect */\n connectionRules?: ConnectionRule\n /** Whether nodes are draggable by default — default: true */\n nodesDraggable?: boolean\n /** Whether nodes are connectable by default — default: true */\n nodesConnectable?: boolean\n /** Whether nodes are selectable by default — default: true */\n nodesSelectable?: boolean\n /** Whether to allow multi-selection — default: true */\n multiSelect?: boolean\n /** Drag boundaries for nodes — [[minX, minY], [maxX, maxY]] */\n nodeExtent?: [[number, number], [number, number]]\n /** Whether panning is enabled — default: true */\n pannable?: boolean\n /** Whether zooming is enabled — default: true */\n zoomable?: boolean\n /** Fit view on initial render — default: false */\n fitView?: boolean\n /** Padding for fitView — default: 0.1 */\n fitViewPadding?: number\n}\n\n// ─── Flow instance ───────────────────────────────────────────────────────────\n\nexport interface FlowInstance {\n // ── State (signals) ──────────────────────────────────────────────────────\n\n /** All nodes — reactive */\n nodes: Signal<FlowNode[]>\n /** All edges — reactive */\n edges: Signal<FlowEdge[]>\n /** Viewport state — reactive */\n viewport: Signal<Viewport>\n /** Current zoom level — computed */\n zoom: Computed<number>\n /** Selected node ids — computed */\n selectedNodes: Computed<string[]>\n /** Selected edge ids — computed */\n selectedEdges: Computed<string[]>\n /** Container dimensions — updated by the Flow component via ResizeObserver */\n containerSize: Signal<{ width: number; height: number }>\n\n // ── Node operations ──────────────────────────────────────────────────────\n\n /** Get a single node by id */\n getNode: (id: string) => FlowNode | undefined\n /** Add a node */\n addNode: (node: FlowNode) => void\n /** Remove a node and its connected edges */\n removeNode: (id: string) => void\n /** Update a node's properties */\n updateNode: (id: string, update: Partial<FlowNode>) => void\n /** Update a node's position */\n updateNodePosition: (id: string, position: XYPosition) => void\n\n // ── Edge operations ──────────────────────────────────────────────────────\n\n /** Get a single edge by id */\n getEdge: (id: string) => FlowEdge | undefined\n /** Add an edge */\n addEdge: (edge: FlowEdge) => void\n /** Remove an edge */\n removeEdge: (id: string) => void\n /** Check if a connection is valid (based on rules) */\n isValidConnection: (connection: Connection) => boolean\n\n // ── Selection ────────────────────────────────────────────────────────────\n\n /** Select a node */\n selectNode: (id: string, additive?: boolean) => void\n /** Deselect a node */\n deselectNode: (id: string) => void\n /** Select an edge */\n selectEdge: (id: string, additive?: boolean) => void\n /** Clear all selection */\n clearSelection: () => void\n /** Select all nodes */\n selectAll: () => void\n /** Delete selected nodes/edges */\n deleteSelected: () => void\n\n // ── Viewport ─────────────────────────────────────────────────────────────\n\n /** Fit view to show all nodes */\n fitView: (nodeIds?: string[], padding?: number) => void\n /** Set zoom level */\n zoomTo: (zoom: number) => void\n /** Zoom in */\n zoomIn: () => void\n /** Zoom out */\n zoomOut: () => void\n /** Pan to position */\n panTo: (position: XYPosition) => void\n /** Check if a node is visible in the current viewport */\n isNodeVisible: (id: string) => boolean\n\n // ── Layout ───────────────────────────────────────────────────────────────\n\n /** Apply auto-layout using elkjs */\n layout: (algorithm?: LayoutAlgorithm, options?: LayoutOptions) => Promise<void>\n\n // ── Batch ────────────────────────────────────────────────────────────────\n\n /** Batch multiple operations */\n batch: (fn: () => void) => void\n\n // ── Graph queries ────────────────────────────────────────────────────────\n\n /** Get edges connected to a node */\n getConnectedEdges: (nodeId: string) => FlowEdge[]\n /** Get incoming edges for a node */\n getIncomers: (nodeId: string) => FlowNode[]\n /** Get outgoing edges from a node */\n getOutgoers: (nodeId: string) => FlowNode[]\n\n // ── Listeners ────────────────────────────────────────────────────────────\n\n /** Called when a connection is made */\n onConnect: (callback: (connection: Connection) => void) => () => void\n /** Called when nodes change */\n onNodesChange: (callback: (changes: NodeChange[]) => void) => () => void\n /** Called when a node is clicked */\n onNodeClick: (callback: (node: FlowNode) => void) => () => void\n /** Called when an edge is clicked */\n onEdgeClick: (callback: (edge: FlowEdge) => void) => () => void\n /** Called when a node starts being dragged */\n onNodeDragStart: (callback: (node: FlowNode) => void) => () => void\n /** Called when a node stops being dragged */\n onNodeDragEnd: (callback: (node: FlowNode) => void) => () => void\n /** Called when a node is double-clicked */\n onNodeDoubleClick: (callback: (node: FlowNode) => void) => () => void\n\n // ── Copy / Paste ─────────────────────────────────────────────────────────\n\n /** Copy selected nodes and their edges to clipboard */\n copySelected: () => void\n /** Paste clipboard contents with offset */\n paste: (offset?: XYPosition) => void\n\n // ── Undo / Redo ─────────────────────────────────────────────────────────\n\n /** Save current state to undo history */\n pushHistory: () => void\n /** Undo last change */\n undo: () => void\n /** Redo last undone change */\n redo: () => void\n\n // ── Multi-node drag ─────────────────────────────────────────────────────\n\n /** Move all selected nodes by dx/dy */\n moveSelectedNodes: (dx: number, dy: number) => void\n\n // ── Helper lines ────────────────────────────────────────────────────────\n\n /** Get snap guide lines for a dragged node */\n getSnapLines: (\n dragNodeId: string,\n position: XYPosition,\n threshold?: number,\n ) => { x: number | null; y: number | null; snappedPosition: XYPosition }\n\n // ── Sub-flows / Groups ───────────────────────────────────────────────────\n\n /** Get child nodes of a group node */\n getChildNodes: (parentId: string) => FlowNode[]\n /** Get absolute position of a node (accounting for parent offsets) */\n getAbsolutePosition: (nodeId: string) => XYPosition\n\n // ── Edge reconnecting ──────────────────────────────────────────────────\n\n // ── Edge waypoints ──────────────────────────────────────────────────────\n\n /** Add a waypoint (bend point) to an edge */\n addEdgeWaypoint: (edgeId: string, point: XYPosition, index?: number) => void\n /** Remove a waypoint from an edge */\n removeEdgeWaypoint: (edgeId: string, index: number) => void\n /** Update a waypoint position */\n updateEdgeWaypoint: (edgeId: string, index: number, point: XYPosition) => void\n\n // ── Edge reconnecting ──────────────────────────────────────────────────\n\n /** Reconnect an edge to a new source/target */\n reconnectEdge: (\n edgeId: string,\n newConnection: {\n source?: string\n target?: string\n sourceHandle?: string\n targetHandle?: string\n },\n ) => void\n\n // ── Proximity connect ────────────────────────────────────────────────────\n\n /** Find the nearest unconnected node within threshold distance */\n getProximityConnection: (nodeId: string, threshold?: number) => Connection | null\n\n // ── Collision detection ─────────────────────────────────────────────────\n\n /** Get nodes that overlap with the given node */\n getOverlappingNodes: (nodeId: string) => FlowNode[]\n /** Push overlapping nodes apart */\n resolveCollisions: (nodeId: string, spacing?: number) => void\n\n // ── Node extent ─────────────────────────────────────────────────────────\n\n /** Set drag boundaries for all nodes — [[minX, minY], [maxX, maxY]] or null to remove */\n setNodeExtent: (extent: [[number, number], [number, number]] | null) => void\n /** Clamp a position to the current node extent */\n clampToExtent: (position: XYPosition, nodeWidth?: number, nodeHeight?: number) => XYPosition\n\n // ── Search / Filter ─────────────────────────────────────────────────────\n\n /** Find nodes matching a predicate */\n findNodes: (predicate: (node: FlowNode) => boolean) => FlowNode[]\n /** Find nodes by label text (case-insensitive) */\n searchNodes: (query: string) => FlowNode[]\n /** Focus viewport on a specific node (pan + optional zoom) */\n focusNode: (nodeId: string, zoom?: number) => void\n\n // ── Export ─────────────────────────────────────────────────────────────\n\n /** Export the flow as a JSON-serializable object */\n toJSON: () => { nodes: FlowNode[]; edges: FlowEdge[]; viewport: Viewport }\n /** Import flow state from a JSON object */\n fromJSON: (data: { nodes: FlowNode[]; edges: FlowEdge[]; viewport?: Viewport }) => void\n\n // ── Viewport animation ─────────────────────────────────────────────────\n\n /** Animate viewport to a new position/zoom */\n animateViewport: (target: Partial<Viewport>, duration?: number) => void\n\n // ── Internal emitters (used by Flow component) ──────────────────────────\n\n /** @internal */\n _emit: {\n nodeDragStart: (node: FlowNode) => void\n nodeDragEnd: (node: FlowNode) => void\n nodeDoubleClick: (node: FlowNode) => void\n nodeClick: (node: FlowNode) => void\n edgeClick: (edge: FlowEdge) => void\n }\n\n // ── Config ───────────────────────────────────────────────────────────────\n\n /** The flow configuration */\n config: FlowConfig\n\n // ── Cleanup ──────────────────────────────────────────────────────────────\n\n /** Dispose all listeners and clean up */\n dispose: () => void\n}\n\n// ─── Layout ──────────────────────────────────────────────────────────────────\n\nexport type LayoutAlgorithm =\n | \"layered\"\n | \"force\"\n | \"stress\"\n | \"tree\"\n | \"radial\"\n | \"box\"\n | \"rectpacking\"\n\nexport interface LayoutOptions {\n /** Layout direction — default: 'DOWN' */\n direction?: \"UP\" | \"DOWN\" | \"LEFT\" | \"RIGHT\"\n /** Spacing between nodes — default: 50 */\n nodeSpacing?: number\n /** Spacing between layers — default: 80 */\n layerSpacing?: number\n /** Edge routing — default: 'orthogonal' */\n edgeRouting?: \"orthogonal\" | \"splines\" | \"polyline\"\n /** Whether to animate the layout transition — default: true */\n animate?: boolean\n /** Animation duration in ms — default: 300 */\n animationDuration?: number\n}\n\n// ─── Component props ─────────────────────────────────────────────────────────\n\nexport interface FlowProps {\n instance: FlowInstance\n style?: string\n class?: string\n children?: VNodeChild\n}\n\nexport interface BackgroundProps {\n variant?: \"dots\" | \"lines\" | \"cross\"\n gap?: number\n size?: number\n color?: string\n}\n\nexport interface MiniMapProps {\n style?: string\n class?: string\n nodeColor?: string | ((node: FlowNode) => string)\n maskColor?: string\n width?: number\n height?: number\n}\n\nexport interface ControlsProps {\n showZoomIn?: boolean\n showZoomOut?: boolean\n showFitView?: boolean\n showLock?: boolean\n position?: \"top-left\" | \"top-right\" | \"bottom-left\" | \"bottom-right\"\n}\n\nexport interface PanelProps {\n position?: \"top-left\" | \"top-right\" | \"bottom-left\" | \"bottom-right\"\n style?: string\n class?: string\n children?: VNodeChild\n}\n\nexport interface HandleProps {\n type: HandleType\n position: Position\n id?: string\n style?: string\n class?: string\n}\n\nexport type NodeComponentProps<TData = Record<string, unknown>> = {\n id: string\n data: TData\n selected: boolean\n dragging: boolean\n}\n","import type { EdgePathResult, FlowNode, XYPosition } from \"./types\"\nimport { Position } from \"./types\"\n\n/**\n * Auto-detect the best handle position based on relative node positions.\n * If the node has configured handles, uses those. Otherwise picks the\n * closest edge (top/right/bottom/left) based on direction to the other node.\n */\nexport function getSmartHandlePositions(\n sourceNode: FlowNode,\n targetNode: FlowNode,\n): { sourcePosition: Position; targetPosition: Position } {\n const sw = sourceNode.width ?? 150\n const sh = sourceNode.height ?? 40\n const tw = targetNode.width ?? 150\n const th = targetNode.height ?? 40\n\n const dx = targetNode.position.x + tw / 2 - (sourceNode.position.x + sw / 2)\n const dy = targetNode.position.y + th / 2 - (sourceNode.position.y + sh / 2)\n\n const sourceHandle = sourceNode.sourceHandles?.[0]\n const targetHandle = targetNode.targetHandles?.[0]\n\n const sourcePosition = sourceHandle\n ? sourceHandle.position\n : Math.abs(dx) > Math.abs(dy)\n ? dx > 0\n ? Position.Right\n : Position.Left\n : dy > 0\n ? Position.Bottom\n : Position.Top\n\n const targetPosition = targetHandle\n ? targetHandle.position\n : Math.abs(dx) > Math.abs(dy)\n ? dx > 0\n ? Position.Left\n : Position.Right\n : dy > 0\n ? Position.Top\n : Position.Bottom\n\n return { sourcePosition, targetPosition }\n}\n\n/**\n * Get the center point between source and target positions.\n */\nfunction getCenter(source: XYPosition, target: XYPosition): XYPosition {\n return {\n x: (source.x + target.x) / 2,\n y: (source.y + target.y) / 2,\n }\n}\n\n/**\n * Get the handle position offset for a given position (top/right/bottom/left).\n */\nexport function getHandlePosition(\n position: Position,\n nodeX: number,\n nodeY: number,\n nodeWidth: number,\n nodeHeight: number,\n _handleId?: string,\n): XYPosition {\n switch (position) {\n case Position.Top:\n return { x: nodeX + nodeWidth / 2, y: nodeY }\n case Position.Right:\n return { x: nodeX + nodeWidth, y: nodeY + nodeHeight / 2 }\n case Position.Bottom:\n return { x: nodeX + nodeWidth / 2, y: nodeY + nodeHeight }\n case Position.Left:\n return { x: nodeX, y: nodeY + nodeHeight / 2 }\n }\n}\n\n/**\n * Calculate a cubic bezier edge path between two points.\n *\n * @example\n * ```ts\n * const { path, labelX, labelY } = getBezierPath({\n * sourceX: 0, sourceY: 0, sourcePosition: Position.Right,\n * targetX: 200, targetY: 100, targetPosition: Position.Left,\n * })\n * // path = \"M0,0 C100,0 100,100 200,100\"\n * ```\n */\nexport function getBezierPath(params: {\n sourceX: number\n sourceY: number\n sourcePosition?: Position\n targetX: number\n targetY: number\n targetPosition?: Position\n curvature?: number\n}): EdgePathResult {\n const {\n sourceX,\n sourceY,\n sourcePosition = Position.Bottom,\n targetX,\n targetY,\n targetPosition = Position.Top,\n curvature = 0.25,\n } = params\n\n const distX = Math.abs(targetX - sourceX)\n const distY = Math.abs(targetY - sourceY)\n const dist = Math.sqrt(distX * distX + distY * distY)\n const offset = dist * curvature\n\n let sourceControlX = sourceX\n let sourceControlY = sourceY\n let targetControlX = targetX\n let targetControlY = targetY\n\n switch (sourcePosition) {\n case Position.Top:\n sourceControlY = sourceY - offset\n break\n case Position.Bottom:\n sourceControlY = sourceY + offset\n break\n case Position.Left:\n sourceControlX = sourceX - offset\n break\n case Position.Right:\n sourceControlX = sourceX + offset\n break\n }\n\n switch (targetPosition) {\n case Position.Top:\n targetControlY = targetY - offset\n break\n case Position.Bottom:\n targetControlY = targetY + offset\n break\n case Position.Left:\n targetControlX = targetX - offset\n break\n case Position.Right:\n targetControlX = targetX + offset\n break\n }\n\n const center = getCenter({ x: sourceX, y: sourceY }, { x: targetX, y: targetY })\n\n return {\n path: `M${sourceX},${sourceY} C${sourceControlX},${sourceControlY} ${targetControlX},${targetControlY} ${targetX},${targetY}`,\n labelX: center.x,\n labelY: center.y,\n }\n}\n\n/**\n * Calculate a smoothstep edge path — horizontal/vertical segments with rounded corners.\n */\nexport function getSmoothStepPath(params: {\n sourceX: number\n sourceY: number\n sourcePosition?: Position\n targetX: number\n targetY: number\n targetPosition?: Position\n borderRadius?: number\n offset?: number\n}): EdgePathResult {\n const {\n sourceX,\n sourceY,\n sourcePosition = Position.Bottom,\n targetX,\n targetY,\n targetPosition = Position.Top,\n borderRadius = 5,\n offset = 20,\n } = params\n\n const isHorizontalSource = sourcePosition === Position.Left || sourcePosition === Position.Right\n const isHorizontalTarget = targetPosition === Position.Left || targetPosition === Position.Right\n\n // Calculate offset points\n const sourceOffsetX =\n sourcePosition === Position.Right ? offset : sourcePosition === Position.Left ? -offset : 0\n const sourceOffsetY =\n sourcePosition === Position.Bottom ? offset : sourcePosition === Position.Top ? -offset : 0\n const targetOffsetX =\n targetPosition === Position.Right ? offset : targetPosition === Position.Left ? -offset : 0\n const targetOffsetY =\n targetPosition === Position.Bottom ? offset : targetPosition === Position.Top ? -offset : 0\n\n const sX = sourceX + sourceOffsetX\n const sY = sourceY + sourceOffsetY\n const tX = targetX + targetOffsetX\n const tY = targetY + targetOffsetY\n\n const center = getCenter({ x: sourceX, y: sourceY }, { x: targetX, y: targetY })\n\n // Simple smoothstep: source → midpoint → target with rounded corners\n const midX = (sX + tX) / 2\n const midY = (sY + tY) / 2\n const r = borderRadius\n\n let path: string\n\n if (isHorizontalSource && !isHorizontalTarget) {\n // Horizontal source → vertical target\n const cornerY = tY\n path = `M${sourceX},${sourceY} L${sX},${sY} L${sX},${cornerY > sY ? cornerY - r : cornerY + r} Q${sX},${cornerY} ${sX + (tX > sX ? r : -r)},${cornerY} L${tX},${cornerY} L${targetX},${targetY}`\n } else if (!isHorizontalSource && isHorizontalTarget) {\n // Vertical source → horizontal target\n const cornerX = tX\n path = `M${sourceX},${sourceY} L${sX},${sY} L${cornerX > sX ? cornerX - r : cornerX + r},${sY} Q${cornerX},${sY} ${cornerX},${sY + (tY > sY ? r : -r)} L${cornerX},${tY} L${targetX},${targetY}`\n } else if (isHorizontalSource && isHorizontalTarget) {\n // Both horizontal — go through middle Y\n path = `M${sourceX},${sourceY} L${sX},${sourceY} L${midX},${sourceY} Q${midX},${sourceY} ${midX},${midY} L${midX},${targetY} L${tX},${targetY} L${targetX},${targetY}`\n } else {\n // Both vertical — go through middle X\n path = `M${sourceX},${sourceY} L${sourceX},${sY} L${sourceX},${midY} Q${sourceX},${midY} ${midX},${midY} L${targetX},${midY} L${targetX},${tY} L${targetX},${targetY}`\n }\n\n return { path, labelX: center.x, labelY: center.y }\n}\n\n/**\n * Calculate a straight edge path — direct line between two points.\n */\nexport function getStraightPath(params: {\n sourceX: number\n sourceY: number\n targetX: number\n targetY: number\n}): EdgePathResult {\n const { sourceX, sourceY, targetX, targetY } = params\n const center = getCenter({ x: sourceX, y: sourceY }, { x: targetX, y: targetY })\n\n return {\n path: `M${sourceX},${sourceY} L${targetX},${targetY}`,\n labelX: center.x,\n labelY: center.y,\n }\n}\n\n/**\n * Calculate a step edge path — right-angle segments with no rounding.\n */\nexport function getStepPath(params: {\n sourceX: number\n sourceY: number\n sourcePosition?: Position\n targetX: number\n targetY: number\n targetPosition?: Position\n}): EdgePathResult {\n return getSmoothStepPath({ ...params, borderRadius: 0 })\n}\n\n/**\n * Calculate an edge path that passes through waypoints.\n * Uses line segments with optional smoothing.\n */\nexport function getWaypointPath(params: {\n sourceX: number\n sourceY: number\n targetX: number\n targetY: number\n waypoints: XYPosition[]\n}): EdgePathResult {\n const { sourceX, sourceY, targetX, targetY, waypoints } = params\n\n if (waypoints.length === 0) {\n return getStraightPath({ sourceX, sourceY, targetX, targetY })\n }\n\n const allPoints = [{ x: sourceX, y: sourceY }, ...waypoints, { x: targetX, y: targetY }]\n\n const segments = allPoints.map((p) => `${p.x},${p.y}`)\n const path = `M${segments.join(\" L\")}`\n\n // Label at the middle waypoint\n const midIdx = Math.floor(waypoints.length / 2)\n const midPoint = waypoints[midIdx] ?? {\n x: (sourceX + targetX) / 2,\n y: (sourceY + targetY) / 2,\n }\n\n return { path, labelX: midPoint.x, labelY: midPoint.y }\n}\n\n/**\n * Get the edge path for a given edge type.\n */\nexport function getEdgePath(\n type: string,\n sourceX: number,\n sourceY: number,\n sourcePosition: Position,\n targetX: number,\n targetY: number,\n targetPosition: Position,\n): EdgePathResult {\n switch (type) {\n case \"smoothstep\":\n return getSmoothStepPath({\n sourceX,\n sourceY,\n sourcePosition,\n targetX,\n targetY,\n targetPosition,\n })\n case \"straight\":\n return getStraightPath({ sourceX, sourceY, targetX, targetY })\n case \"step\":\n return getStepPath({\n sourceX,\n sourceY,\n sourcePosition,\n targetX,\n targetY,\n targetPosition,\n })\n default:\n return getBezierPath({\n sourceX,\n sourceY,\n sourcePosition,\n targetX,\n targetY,\n targetPosition,\n })\n }\n}\n","import type { VNodeChild } from \"@pyreon/core\"\nimport { signal } from \"@pyreon/reactivity\"\nimport { getEdgePath, getHandlePosition, getSmartHandlePositions, getWaypointPath } from \"../edges\"\nimport type { Connection, FlowInstance, FlowNode, NodeComponentProps } from \"../types\"\nimport { Position } from \"../types\"\n\n// ─── Node type registry ──────────────────────────────────────────────────────\n\ntype NodeTypeMap = Record<string, (props: NodeComponentProps<any>) => VNodeChild>\n\n/**\n * Default node renderer — simple labeled box.\n */\nfunction DefaultNode(props: NodeComponentProps) {\n const borderColor = props.selected ? \"#3b82f6\" : \"#ddd\"\n const cursor = props.dragging ? \"grabbing\" : \"grab\"\n return (\n <div\n style={`padding: 8px 16px; background: white; border: 2px solid ${borderColor}; border-radius: 6px; font-size: 13px; min-width: 80px; text-align: center; cursor: ${cursor}; user-select: none;`}\n >\n {(props.data?.label as string) ?? props.id}\n </div>\n )\n}\n\n// ─── Connection line state ───────────────────────────────────────────────────\n\ninterface ConnectionState {\n active: boolean\n sourceNodeId: string\n sourceHandleId: string\n sourcePosition: Position\n sourceX: number\n sourceY: number\n currentX: number\n currentY: number\n}\n\nconst emptyConnection: ConnectionState = {\n active: false,\n sourceNodeId: \"\",\n sourceHandleId: \"\",\n sourcePosition: Position.Right,\n sourceX: 0,\n sourceY: 0,\n currentX: 0,\n currentY: 0,\n}\n\n// ─── Selection box state ─────────────────────────────────────────────────────\n\ninterface SelectionBoxState {\n active: boolean\n startX: number\n startY: number\n currentX: number\n currentY: number\n}\n\nconst emptySelectionBox: SelectionBoxState = {\n active: false,\n startX: 0,\n startY: 0,\n currentX: 0,\n currentY: 0,\n}\n\n// ─── Drag state ──────────────────────────────────────────────────────────────\n\ninterface DragState {\n active: boolean\n nodeId: string\n startX: number\n startY: number\n /** Starting positions of all nodes being dragged (for multi-drag) */\n startPositions: Map<string, { x: number; y: number }>\n}\n\nconst emptyDrag: DragState = {\n active: false,\n nodeId: \"\",\n startX: 0,\n startY: 0,\n startPositions: new Map(),\n}\n\n// ─── Edge Layer ──────────────────────────────────────────────────────────────\n\nfunction EdgeLayer(props: {\n instance: FlowInstance\n connectionState: () => ConnectionState\n edgeTypes?: EdgeTypeMap\n}): VNodeChild {\n const { instance, connectionState, edgeTypes } = props\n\n return () => {\n const nodes = instance.nodes()\n const edges = instance.edges()\n const nodeMap = new Map(nodes.map((n) => [n.id, n]))\n const conn = connectionState()\n\n return (\n <svg\n role=\"img\"\n aria-label=\"flow edges\"\n class=\"pyreon-flow-edges\"\n style=\"position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; overflow: visible;\"\n >\n <defs>\n <marker\n id=\"flow-arrowhead\"\n {...{\n markerWidth: \"10\",\n markerHeight: \"7\",\n refX: \"10\",\n refY: \"3.5\",\n orient: \"auto\",\n }}\n >\n <polygon points=\"0 0, 10 3.5, 0 7\" fill=\"#999\" />\n </marker>\n </defs>\n {edges.map((edge) => {\n const sourceNode = nodeMap.get(edge.source)\n const targetNode = nodeMap.get(edge.target)\n if (!sourceNode || !targetNode) return <g key={edge.id} />\n\n const sourceW = sourceNode.width ?? 150\n const sourceH = sourceNode.height ?? 40\n const targetW = targetNode.width ?? 150\n const targetH = targetNode.height ?? 40\n\n const { sourcePosition, targetPosition } = getSmartHandlePositions(sourceNode, targetNode)\n\n const sourcePos = getHandlePosition(\n sourcePosition,\n sourceNode.position.x,\n sourceNode.position.y,\n sourceW,\n sourceH,\n )\n const targetPos = getHandlePosition(\n targetPosition,\n targetNode.position.x,\n targetNode.position.y,\n targetW,\n targetH,\n )\n\n const { path, labelX, labelY } = edge.waypoints?.length\n ? getWaypointPath({\n sourceX: sourcePos.x,\n sourceY: sourcePos.y,\n targetX: targetPos.x,\n targetY: targetPos.y,\n waypoints: edge.waypoints,\n })\n : getEdgePath(\n edge.type ?? \"bezier\",\n sourcePos.x,\n sourcePos.y,\n sourcePosition,\n targetPos.x,\n targetPos.y,\n targetPosition,\n )\n\n const selectedEdges = instance.selectedEdges()\n const isSelected = edge.id ? selectedEdges.includes(edge.id) : false\n\n // Custom edge renderer\n const CustomEdge = edge.type && edgeTypes?.[edge.type]\n if (CustomEdge) {\n return (\n <g key={edge.id} onClick={() => edge.id && instance.selectEdge(edge.id)}>\n <CustomEdge\n edge={edge}\n sourceX={sourcePos.x}\n sourceY={sourcePos.y}\n targetX={targetPos.x}\n targetY={targetPos.y}\n selected={isSelected}\n />\n </g>\n )\n }\n\n return (\n <g key={edge.id}>\n <path\n d={path}\n fill=\"none\"\n stroke={isSelected ? \"#3b82f6\" : \"#999\"}\n stroke-width={isSelected ? \"2\" : \"1.5\"}\n marker-end=\"url(#flow-arrowhead)\"\n class={edge.animated ? \"pyreon-flow-edge-animated\" : \"\"}\n style={`pointer-events: stroke; cursor: pointer; ${edge.style ?? \"\"}`}\n onClick={() => {\n if (edge.id) instance.selectEdge(edge.id)\n instance._emit.edgeClick(edge)\n }}\n />\n {edge.label && (\n <text\n x={String(labelX)}\n y={String(labelY)}\n text-anchor=\"middle\"\n dominant-baseline=\"central\"\n style=\"font-size: 11px; fill: #666; pointer-events: none;\"\n >\n {edge.label}\n </text>\n )}\n </g>\n )\n })}\n {conn.active && (\n <path\n d={\n getEdgePath(\n \"bezier\",\n conn.sourceX,\n conn.sourceY,\n conn.sourcePosition,\n conn.currentX,\n conn.currentY,\n Position.Left,\n ).path\n }\n fill=\"none\"\n stroke=\"#3b82f6\"\n stroke-width=\"2\"\n stroke-dasharray=\"5,5\"\n />\n )}\n </svg>\n )\n }\n}\n\n// ─── Node Layer ──────────────────────────────────────────────────────────────\n\nfunction NodeLayer(props: {\n instance: FlowInstance\n nodeTypes: NodeTypeMap\n draggingNodeId: () => string\n onNodePointerDown: (e: PointerEvent, node: FlowNode) => void\n onHandlePointerDown: (\n e: PointerEvent,\n nodeId: string,\n handleType: string,\n handleId: string,\n position: Position,\n ) => void\n}): VNodeChild {\n const { instance, nodeTypes, draggingNodeId, onNodePointerDown, onHandlePointerDown } = props\n\n return () => {\n const nodes = instance.nodes()\n const selectedIds = instance.selectedNodes()\n const dragId = draggingNodeId()\n\n return (\n <>\n {nodes.map((node) => {\n const isSelected = selectedIds.includes(node.id)\n const isDragging = dragId === node.id\n const NodeComponent = (node.type && nodeTypes[node.type]) || nodeTypes.default!\n\n return (\n <div\n key={node.id}\n class={`pyreon-flow-node ${node.class ?? \"\"} ${isSelected ? \"selected\" : \"\"} ${isDragging ? \"dragging\" : \"\"}`}\n style={`position: absolute; transform: translate(${node.position.x}px, ${node.position.y}px); z-index: ${isDragging ? 1000 : isSelected ? 100 : 0}; ${node.style ?? \"\"}`}\n data-nodeid={node.id}\n onClick={(e: MouseEvent) => {\n e.stopPropagation()\n instance.selectNode(node.id, e.shiftKey)\n instance._emit.nodeClick(node)\n }}\n onDblClick={(e: MouseEvent) => {\n e.stopPropagation()\n instance._emit.nodeDoubleClick(node)\n }}\n onPointerDown={(e: PointerEvent) => {\n // Check if clicking a handle\n const target = e.target as HTMLElement\n const handle = target.closest(\".pyreon-flow-handle\")\n if (handle) {\n const hType = handle.getAttribute(\"data-handletype\") ?? \"source\"\n const hId = handle.getAttribute(\"data-handleid\") ?? \"source\"\n const hPos =\n (handle.getAttribute(\"data-handleposition\") as Position) ?? Position.Right\n onHandlePointerDown(e, node.id, hType, hId, hPos)\n return\n }\n // Otherwise start dragging node\n if (node.draggable !== false && instance.config.nodesDraggable !== false) {\n onNodePointerDown(e, node)\n }\n }}\n >\n <NodeComponent\n id={node.id}\n data={node.data}\n selected={isSelected}\n dragging={isDragging}\n />\n </div>\n )\n })}\n </>\n )\n }\n}\n\n// ─── Flow Component ──────────────────────────────────────────────────────────\n\ntype EdgeTypeMap = Record<\n string,\n (props: {\n edge: import(\"../types\").FlowEdge\n sourceX: number\n sourceY: number\n targetX: number\n targetY: number\n selected: boolean\n }) => VNodeChild\n>\n\nexport interface FlowComponentProps {\n instance: FlowInstance\n /** Custom node type renderers */\n nodeTypes?: NodeTypeMap\n /** Custom edge type renderers */\n edgeTypes?: EdgeTypeMap\n style?: string\n class?: string\n children?: VNodeChild\n}\n\n/**\n * The main Flow component — renders the interactive flow diagram.\n *\n * Supports node dragging, connection drawing, custom node types,\n * pan/zoom, and all standard flow interactions.\n *\n * @example\n * ```tsx\n * const flow = createFlow({\n * nodes: [...],\n * edges: [...],\n * })\n *\n * <Flow instance={flow} nodeTypes={{ custom: CustomNode }}>\n * <Background />\n * <MiniMap />\n * <Controls />\n * </Flow>\n * ```\n */\nexport function Flow(props: FlowComponentProps): VNodeChild {\n const { instance, children, edgeTypes } = props\n const nodeTypes: NodeTypeMap = {\n default: DefaultNode,\n input: DefaultNode,\n output: DefaultNode,\n ...props.nodeTypes,\n }\n\n // ── Drag state ─────────────────────────────────────────────────────────\n\n const dragState = signal<DragState>({ ...emptyDrag })\n const connectionState = signal<ConnectionState>({ ...emptyConnection })\n const selectionBox = signal<SelectionBoxState>({ ...emptySelectionBox })\n const helperLines = signal<{ x: number | null; y: number | null }>({\n x: null,\n y: null,\n })\n\n const draggingNodeId = () => (dragState().active ? dragState().nodeId : \"\")\n\n // ── Node dragging ──────────────────────────────────────────────────────\n\n const handleNodePointerDown = (e: PointerEvent, node: FlowNode) => {\n e.stopPropagation()\n\n // Capture starting positions of all selected nodes (for multi-drag)\n const selected = instance.selectedNodes()\n const startPositions = new Map<string, { x: number; y: number }>()\n\n // Always include the dragged node\n startPositions.set(node.id, { ...node.position })\n\n // Include other selected nodes if this node is part of selection\n if (selected.includes(node.id)) {\n for (const nid of selected) {\n if (nid === node.id) continue\n const n = instance.getNode(nid)\n if (n) startPositions.set(nid, { ...n.position })\n }\n }\n\n // Save undo state before drag\n instance.pushHistory()\n\n dragState.set({\n active: true,\n nodeId: node.id,\n startX: e.clientX,\n startY: e.clientY,\n startPositions,\n })\n\n instance.selectNode(node.id, e.shiftKey)\n\n instance._emit.nodeDragStart(node)\n\n const container = (e.currentTarget as HTMLElement).closest(\".pyreon-flow\") as HTMLElement\n if (container) container.setPointerCapture(e.pointerId)\n }\n\n // ── Connection drawing ─────────────────────────────────────────────────\n\n const handleHandlePointerDown = (\n e: PointerEvent,\n nodeId: string,\n _handleType: string,\n handleId: string,\n position: Position,\n ) => {\n e.stopPropagation()\n e.preventDefault()\n\n const node = instance.getNode(nodeId)\n if (!node) return\n\n const w = node.width ?? 150\n const h = node.height ?? 40\n const handlePos = getHandlePosition(position, node.position.x, node.position.y, w, h)\n\n connectionState.set({\n active: true,\n sourceNodeId: nodeId,\n sourceHandleId: handleId,\n sourcePosition: position,\n sourceX: handlePos.x,\n sourceY: handlePos.y,\n currentX: handlePos.x,\n currentY: handlePos.y,\n })\n\n const container = (e.target as HTMLElement).closest(\".pyreon-flow\") as HTMLElement\n if (container) container.setPointerCapture(e.pointerId)\n }\n\n // ── Zoom ───────────────────────────────────────────────────────────────\n\n const handleWheel = (e: WheelEvent) => {\n if (instance.config.zoomable === false) return\n e.preventDefault()\n\n const delta = -e.deltaY * 0.001\n const newZoom = Math.min(\n Math.max(instance.viewport.peek().zoom * (1 + delta), instance.config.minZoom ?? 0.1),\n instance.config.maxZoom ?? 4,\n )\n\n const rect = (e.currentTarget as HTMLElement).getBoundingClientRect()\n const mouseX = e.clientX - rect.left\n const mouseY = e.clientY - rect.top\n const vp = instance.viewport.peek()\n const scale = newZoom / vp.zoom\n\n instance.viewport.set({\n x: mouseX - (mouseX - vp.x) * scale,\n y: mouseY - (mouseY - vp.y) * scale,\n zoom: newZoom,\n })\n }\n\n // ── Pan ────────────────────────────────────────────────────────────────\n\n let isPanning = false\n let panStartX = 0\n let panStartY = 0\n let panStartVpX = 0\n let panStartVpY = 0\n\n const handlePointerDown = (e: PointerEvent) => {\n if (instance.config.pannable === false) return\n\n const target = e.target as HTMLElement\n if (target.closest(\".pyreon-flow-node\")) return\n if (target.closest(\".pyreon-flow-handle\")) return\n\n // Shift+drag on empty space → selection box\n if (e.shiftKey && instance.config.multiSelect !== false) {\n const container = e.currentTarget as HTMLElement\n const rect = container.getBoundingClientRect()\n const vp = instance.viewport.peek()\n const flowX = (e.clientX - rect.left - vp.x) / vp.zoom\n const flowY = (e.clientY - rect.top - vp.y) / vp.zoom\n\n selectionBox.set({\n active: true,\n startX: flowX,\n startY: flowY,\n currentX: flowX,\n currentY: flowY,\n })\n container.setPointerCapture(e.pointerId)\n return\n }\n\n isPanning = true\n panStartX = e.clientX\n panStartY = e.clientY\n const vp = instance.viewport.peek()\n panStartVpX = vp.x\n panStartVpY = vp.y\n ;(e.currentTarget as HTMLElement).setPointerCapture(e.pointerId)\n\n instance.clearSelection()\n }\n\n // ── Unified pointer move/up ────────────────────────────────────────────\n\n const handlePointerMove = (e: PointerEvent) => {\n const drag = dragState.peek()\n const conn = connectionState.peek()\n const sel = selectionBox.peek()\n\n if (sel.active) {\n const container = e.currentTarget as HTMLElement\n const rect = container.getBoundingClientRect()\n const vp = instance.viewport.peek()\n const flowX = (e.clientX - rect.left - vp.x) / vp.zoom\n const flowY = (e.clientY - rect.top - vp.y) / vp.zoom\n selectionBox.set({ ...sel, currentX: flowX, currentY: flowY })\n return\n }\n\n if (drag.active) {\n // Node dragging with snap guides\n const vp = instance.viewport.peek()\n const dx = (e.clientX - drag.startX) / vp.zoom\n const dy = (e.clientY - drag.startY) / vp.zoom\n\n const primaryStart = drag.startPositions.get(drag.nodeId)\n if (!primaryStart) return\n\n const rawPos = { x: primaryStart.x + dx, y: primaryStart.y + dy }\n const snap = instance.getSnapLines(drag.nodeId, rawPos)\n helperLines.set({ x: snap.x, y: snap.y })\n\n // Calculate actual delta (including snap adjustment)\n const actualDx = snap.snappedPosition.x - primaryStart.x\n const actualDy = snap.snappedPosition.y - primaryStart.y\n\n // Update all dragged nodes from their starting positions\n instance.nodes.update((nds) =>\n nds.map((n) => {\n const start = drag.startPositions.get(n.id)\n if (!start) return n\n return {\n ...n,\n position: { x: start.x + actualDx, y: start.y + actualDy },\n }\n }),\n )\n return\n }\n\n if (conn.active) {\n // Connection drawing — convert screen to flow coordinates\n const container = e.currentTarget as HTMLElement\n const rect = container.getBoundingClientRect()\n const vp = instance.viewport.peek()\n const flowX = (e.clientX - rect.left - vp.x) / vp.zoom\n const flowY = (e.clientY - rect.top - vp.y) / vp.zoom\n\n connectionState.set({\n ...conn,\n currentX: flowX,\n currentY: flowY,\n })\n return\n }\n\n if (isPanning) {\n const dx = e.clientX - panStartX\n const dy = e.clientY - panStartY\n instance.viewport.set({\n ...instance.viewport.peek(),\n x: panStartVpX + dx,\n y: panStartVpY + dy,\n })\n }\n }\n\n const handlePointerUp = (e: PointerEvent) => {\n const drag = dragState.peek()\n const conn = connectionState.peek()\n const sel = selectionBox.peek()\n\n if (sel.active) {\n // Select all nodes within the selection rectangle\n const minX = Math.min(sel.startX, sel.currentX)\n const minY = Math.min(sel.startY, sel.currentY)\n const maxX = Math.max(sel.startX, sel.currentX)\n const maxY = Math.max(sel.startY, sel.currentY)\n\n instance.clearSelection()\n for (const node of instance.nodes.peek()) {\n const w = node.width ?? 150\n const h = node.height ?? 40\n const nx = node.position.x\n const ny = node.position.y\n // Node is within box if any part overlaps\n if (nx + w > minX && nx < maxX && ny + h > minY && ny < maxY) {\n instance.selectNode(node.id, true)\n }\n }\n\n selectionBox.set({ ...emptySelectionBox })\n return\n }\n\n if (drag.active) {\n const node = instance.getNode(drag.nodeId)\n if (node) instance._emit.nodeDragEnd(node)\n dragState.set({ ...emptyDrag })\n helperLines.set({ x: null, y: null })\n }\n\n if (conn.active) {\n // Check if we released over a handle target\n const target = e.target as HTMLElement\n const handle = target.closest(\".pyreon-flow-handle\")\n if (handle) {\n const targetNodeId = handle.closest(\".pyreon-flow-node\")?.getAttribute(\"data-nodeid\") ?? \"\"\n const targetHandleId = handle.getAttribute(\"data-handleid\") ?? \"target\"\n\n if (targetNodeId && targetNodeId !== conn.sourceNodeId) {\n const connection: Connection = {\n source: conn.sourceNodeId,\n target: targetNodeId,\n sourceHandle: conn.sourceHandleId,\n targetHandle: targetHandleId,\n }\n\n if (instance.isValidConnection(connection)) {\n instance.addEdge({\n source: connection.source,\n target: connection.target,\n ...(connection.sourceHandle != null ? { sourceHandle: connection.sourceHandle } : {}),\n ...(connection.targetHandle != null ? { targetHandle: connection.targetHandle } : {}),\n })\n }\n }\n }\n\n connectionState.set({ ...emptyConnection })\n }\n\n isPanning = false\n }\n\n // ── Keyboard ───────────────────────────────────────────────────────────\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"Delete\" || e.key === \"Backspace\") {\n const target = e.target as HTMLElement\n if (target.tagName === \"INPUT\" || target.tagName === \"TEXTAREA\") return\n instance.pushHistory()\n instance.deleteSelected()\n }\n if (e.key === \"Escape\") {\n instance.clearSelection()\n connectionState.set({ ...emptyConnection })\n }\n if (e.key === \"a\" && (e.metaKey || e.ctrlKey)) {\n e.preventDefault()\n instance.selectAll()\n }\n if (e.key === \"c\" && (e.metaKey || e.ctrlKey)) {\n instance.copySelected()\n }\n if (e.key === \"v\" && (e.metaKey || e.ctrlKey)) {\n instance.paste()\n }\n if (e.key === \"z\" && (e.metaKey || e.ctrlKey) && !e.shiftKey) {\n e.preventDefault()\n instance.undo()\n }\n if (e.key === \"z\" && (e.metaKey || e.ctrlKey) && e.shiftKey) {\n e.preventDefault()\n instance.redo()\n }\n }\n\n // ── Touch support (pinch zoom) ──────────────────────────────────────────\n\n let lastTouchDist = 0\n let lastTouchCenter = { x: 0, y: 0 }\n\n const handleTouchStart = (e: TouchEvent) => {\n if (e.touches.length === 2) {\n e.preventDefault()\n const t1 = e.touches[0]!\n const t2 = e.touches[1]!\n lastTouchDist = Math.hypot(t2.clientX - t1.clientX, t2.clientY - t1.clientY)\n lastTouchCenter = {\n x: (t1.clientX + t2.clientX) / 2,\n y: (t1.clientY + t2.clientY) / 2,\n }\n }\n }\n\n const handleTouchMove = (e: TouchEvent) => {\n if (e.touches.length === 2 && instance.config.zoomable !== false) {\n e.preventDefault()\n const t1 = e.touches[0]!\n const t2 = e.touches[1]!\n const dist = Math.hypot(t2.clientX - t1.clientX, t2.clientY - t1.clientY)\n const center = {\n x: (t1.clientX + t2.clientX) / 2,\n y: (t1.clientY + t2.clientY) / 2,\n }\n\n const vp = instance.viewport.peek()\n const scaleFactor = dist / lastTouchDist\n const newZoom = Math.min(\n Math.max(vp.zoom * scaleFactor, instance.config.minZoom ?? 0.1),\n instance.config.maxZoom ?? 4,\n )\n\n const rect = (e.currentTarget as HTMLElement).getBoundingClientRect()\n const mouseX = center.x - rect.left\n const mouseY = center.y - rect.top\n const scale = newZoom / vp.zoom\n\n // Pan with touch center movement\n const panDx = center.x - lastTouchCenter.x\n const panDy = center.y - lastTouchCenter.y\n\n instance.viewport.set({\n x: mouseX - (mouseX - vp.x) * scale + panDx,\n y: mouseY - (mouseY - vp.y) * scale + panDy,\n zoom: newZoom,\n })\n\n lastTouchDist = dist\n lastTouchCenter = center\n }\n }\n\n // ── Container size tracking ─────────────────────────────────────────────\n\n let resizeObserver: ResizeObserver | null = null\n\n const containerRef = (el: Element | null) => {\n if (resizeObserver) {\n resizeObserver.disconnect()\n resizeObserver = null\n }\n if (!el) return\n\n const updateSize = () => {\n const rect = el.getBoundingClientRect()\n instance.containerSize.set({\n width: rect.width,\n height: rect.height,\n })\n }\n\n updateSize()\n resizeObserver = new ResizeObserver(updateSize)\n resizeObserver.observe(el)\n }\n\n const containerStyle = `position: relative; width: 100%; height: 100%; overflow: hidden; outline: none; touch-action: none; ${props.style ?? \"\"}`\n\n return (\n <div\n ref={containerRef}\n class={`pyreon-flow ${props.class ?? \"\"}`}\n style={containerStyle}\n tabIndex={0}\n onWheel={handleWheel}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onTouchStart={handleTouchStart}\n onTouchMove={handleTouchMove}\n onKeyDown={handleKeyDown}\n >\n {children}\n {() => {\n const vp = instance.viewport()\n return (\n <div\n class=\"pyreon-flow-viewport\"\n style={`position: absolute; transform-origin: 0 0; transform: translate(${vp.x}px, ${vp.y}px) scale(${vp.zoom});`}\n >\n <EdgeLayer\n instance={instance}\n connectionState={() => connectionState()}\n {...(edgeTypes != null ? { edgeTypes } : {})}\n />\n {() => {\n const sel = selectionBox()\n if (!sel.active) return null\n const x = Math.min(sel.startX, sel.currentX)\n const y = Math.min(sel.startY, sel.currentY)\n const w = Math.abs(sel.currentX - sel.startX)\n const h = Math.abs(sel.currentY - sel.startY)\n return (\n <div\n class=\"pyreon-flow-selection-box\"\n style={`position: absolute; left: ${x}px; top: ${y}px; width: ${w}px; height: ${h}px; border: 1px dashed #3b82f6; background: rgba(59, 130, 246, 0.08); pointer-events: none; z-index: 10;`}\n />\n )\n }}\n {() => {\n const lines = helperLines()\n if (!lines.x && !lines.y) return null\n return (\n <svg\n role=\"img\"\n aria-label=\"helper lines\"\n style=\"position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; overflow: visible; z-index: 5;\"\n >\n {lines.x !== null && (\n <line\n x1={String(lines.x)}\n y1=\"-10000\"\n x2={String(lines.x)}\n y2=\"10000\"\n stroke=\"#3b82f6\"\n stroke-width=\"0.5\"\n stroke-dasharray=\"4,4\"\n />\n )}\n {lines.y !== null && (\n <line\n x1=\"-10000\"\n y1={String(lines.y)}\n x2=\"10000\"\n y2={String(lines.y)}\n stroke=\"#3b82f6\"\n stroke-width=\"0.5\"\n stroke-dasharray=\"4,4\"\n />\n )}\n </svg>\n )\n }}\n <NodeLayer\n instance={instance}\n nodeTypes={nodeTypes}\n draggingNodeId={draggingNodeId}\n onNodePointerDown={handleNodePointerDown}\n onHandlePointerDown={handleHandlePointerDown}\n />\n </div>\n )\n }}\n </div>\n )\n}\n","import type { VNodeChild } from \"@pyreon/core\"\nimport type { HandleProps } from \"../types\"\n\nconst positionOffset: Record<string, string> = {\n top: \"top: -4px; left: 50%; transform: translateX(-50%);\",\n right: \"right: -4px; top: 50%; transform: translateY(-50%);\",\n bottom: \"bottom: -4px; left: 50%; transform: translateX(-50%);\",\n left: \"left: -4px; top: 50%; transform: translateY(-50%);\",\n}\n\n/**\n * Connection handle — attachment point on a node where edges connect.\n * Place inside custom node components.\n *\n * @example\n * ```tsx\n * function CustomNode({ data }: NodeComponentProps) {\n * return (\n * <div class=\"custom-node\">\n * <Handle type=\"target\" position={Position.Left} />\n * <span>{data.label}</span>\n * <Handle type=\"source\" position={Position.Right} />\n * </div>\n * )\n * }\n * ```\n */\nexport function Handle(props: HandleProps): VNodeChild {\n const { type, position, id, style = \"\" } = props\n const posStyle = positionOffset[position] ?? positionOffset.bottom\n const baseStyle = `position: absolute; ${posStyle} width: 8px; height: 8px; background: #555; border: 2px solid white; border-radius: 50%; cursor: crosshair; z-index: 1; ${style}`\n\n return (\n <div\n class={`pyreon-flow-handle pyreon-flow-handle-${type} ${props.class ?? \"\"}`}\n style={baseStyle}\n data-handletype={type}\n data-handleid={id ?? type}\n data-handleposition={position}\n />\n )\n}\n","import type { VNodeChild } from \"@pyreon/core\"\nimport type { FlowInstance, MiniMapProps } from \"../types\"\n\n/**\n * Miniature overview of the flow diagram showing all nodes\n * and the current viewport position. Click to navigate.\n *\n * @example\n * ```tsx\n * <Flow instance={flow}>\n * <MiniMap nodeColor={(n) => n.type === 'error' ? 'red' : '#ddd'} />\n * </Flow>\n * ```\n */\nexport function MiniMap(props: MiniMapProps & { instance?: FlowInstance }): VNodeChild {\n const {\n width = 200,\n height = 150,\n nodeColor = \"#e2e8f0\",\n maskColor = \"rgba(0, 0, 0, 0.08)\",\n instance,\n } = props\n\n if (!instance) return null\n\n const containerStyle = `position: absolute; bottom: 10px; right: 10px; width: ${width}px; height: ${height}px; border: 1px solid #ddd; background: white; border-radius: 4px; overflow: hidden; z-index: 5; cursor: pointer;`\n\n return () => {\n const nodes = instance.nodes()\n if (nodes.length === 0) return <div class=\"pyreon-flow-minimap\" style={containerStyle} />\n\n // Calculate graph bounds\n let minX = Number.POSITIVE_INFINITY\n let minY = Number.POSITIVE_INFINITY\n let maxX = Number.NEGATIVE_INFINITY\n let maxY = Number.NEGATIVE_INFINITY\n\n for (const node of nodes) {\n const w = node.width ?? 150\n const h = node.height ?? 40\n minX = Math.min(minX, node.position.x)\n minY = Math.min(minY, node.position.y)\n maxX = Math.max(maxX, node.position.x + w)\n maxY = Math.max(maxY, node.position.y + h)\n }\n\n const padding = 40\n const graphW = maxX - minX + padding * 2\n const graphH = maxY - minY + padding * 2\n const scale = Math.min(width / graphW, height / graphH)\n\n // Viewport rectangle in minimap coordinates\n const vp = instance.viewport()\n const cs = instance.containerSize()\n const vpLeft = (-vp.x / vp.zoom - minX + padding) * scale\n const vpTop = (-vp.y / vp.zoom - minY + padding) * scale\n const vpWidth = (cs.width / vp.zoom) * scale\n const vpHeight = (cs.height / vp.zoom) * scale\n\n const handleClick = (e: MouseEvent) => {\n const rect = (e.currentTarget as HTMLElement).getBoundingClientRect()\n const clickX = e.clientX - rect.left\n const clickY = e.clientY - rect.top\n\n // Convert minimap click to flow coordinates\n const flowX = clickX / scale + minX - padding\n const flowY = clickY / scale + minY - padding\n\n // Center viewport on clicked point\n instance.viewport.set({\n ...vp,\n x: -(flowX * vp.zoom) + cs.width / 2,\n y: -(flowY * vp.zoom) + cs.height / 2,\n })\n }\n\n return (\n <div class=\"pyreon-flow-minimap\" style={containerStyle} onClick={handleClick}>\n <svg role=\"img\" aria-label=\"minimap\" width={String(width)} height={String(height)}>\n {/* Mask outside viewport */}\n <rect width={String(width)} height={String(height)} fill={maskColor} />\n\n {/* Nodes */}\n {nodes.map((node) => {\n const w = (node.width ?? 150) * scale\n const h = (node.height ?? 40) * scale\n const x = (node.position.x - minX + padding) * scale\n const y = (node.position.y - minY + padding) * scale\n const color = typeof nodeColor === \"function\" ? nodeColor(node) : nodeColor\n\n return (\n <rect\n key={node.id}\n x={String(x)}\n y={String(y)}\n width={String(w)}\n height={String(h)}\n fill={color}\n rx=\"2\"\n />\n )\n })}\n\n {/* Viewport indicator */}\n <rect\n x={String(Math.max(0, vpLeft))}\n y={String(Math.max(0, vpTop))}\n width={String(Math.min(vpWidth, width))}\n height={String(Math.min(vpHeight, height))}\n fill=\"none\"\n stroke=\"#3b82f6\"\n stroke-width=\"1.5\"\n rx=\"2\"\n />\n </svg>\n </div>\n )\n }\n}\n","import type { VNodeChild } from \"@pyreon/core\"\nimport type { FlowInstance } from \"../types\"\n\nexport interface NodeResizerProps {\n nodeId: string\n instance: FlowInstance\n /** Minimum width — default: 50 */\n minWidth?: number\n /** Minimum height — default: 30 */\n minHeight?: number\n /** Handle size in px — default: 8 */\n handleSize?: number\n /** Also show edge (non-corner) resize handles — default: false */\n showEdgeHandles?: boolean\n}\n\ntype ResizeDirection = \"nw\" | \"ne\" | \"sw\" | \"se\" | \"n\" | \"s\" | \"e\" | \"w\"\n\nconst directionCursors: Record<ResizeDirection, string> = {\n nw: \"nw-resize\",\n ne: \"ne-resize\",\n sw: \"sw-resize\",\n se: \"se-resize\",\n n: \"n-resize\",\n s: \"s-resize\",\n e: \"e-resize\",\n w: \"w-resize\",\n}\n\nconst directionPositions: Record<ResizeDirection, string> = {\n nw: \"top: -4px; left: -4px;\",\n ne: \"top: -4px; right: -4px;\",\n sw: \"bottom: -4px; left: -4px;\",\n se: \"bottom: -4px; right: -4px;\",\n n: \"top: -4px; left: 50%; transform: translateX(-50%);\",\n s: \"bottom: -4px; left: 50%; transform: translateX(-50%);\",\n e: \"right: -4px; top: 50%; transform: translateY(-50%);\",\n w: \"left: -4px; top: 50%; transform: translateY(-50%);\",\n}\n\n/**\n * Node resize handles. Place inside a custom node component\n * to allow users to resize the node by dragging corners or edges.\n *\n * Uses pointer capture for clean event handling — no document listener leaks.\n *\n * @example\n * ```tsx\n * function ResizableNode({ id, data, selected }: NodeComponentProps) {\n * return (\n * <div style=\"min-width: 100px; min-height: 50px; position: relative;\">\n * {data.label}\n * <NodeResizer nodeId={id} instance={flow} />\n * </div>\n * )\n * }\n * ```\n */\nexport function NodeResizer(props: NodeResizerProps): VNodeChild {\n const {\n nodeId,\n instance,\n minWidth = 50,\n minHeight = 30,\n handleSize = 8,\n showEdgeHandles = false,\n } = props\n\n const directions: ResizeDirection[] = showEdgeHandles\n ? [\"nw\", \"ne\", \"sw\", \"se\", \"n\", \"s\", \"e\", \"w\"]\n : [\"nw\", \"ne\", \"sw\", \"se\"]\n\n const createHandler = (dir: ResizeDirection) => {\n let startX = 0\n let startY = 0\n let startWidth = 0\n let startHeight = 0\n let startNodeX = 0\n let startNodeY = 0\n let zoomAtStart = 1\n\n const onPointerDown = (e: PointerEvent) => {\n e.stopPropagation()\n e.preventDefault()\n\n const node = instance.getNode(nodeId)\n if (!node) return\n\n startX = e.clientX\n startY = e.clientY\n startWidth = node.width ?? 150\n startHeight = node.height ?? 40\n startNodeX = node.position.x\n startNodeY = node.position.y\n zoomAtStart = instance.viewport.peek().zoom\n\n // Use pointer capture — clean, no leaks\n const el = e.currentTarget as HTMLElement\n el.setPointerCapture(e.pointerId)\n }\n\n const onPointerMove = (e: PointerEvent) => {\n const el = e.currentTarget as HTMLElement\n if (!el.hasPointerCapture(e.pointerId)) return\n\n const dx = (e.clientX - startX) / zoomAtStart\n const dy = (e.clientY - startY) / zoomAtStart\n\n let newW = startWidth\n let newH = startHeight\n let newX = startNodeX\n let newY = startNodeY\n\n // Horizontal\n if (dir === \"e\" || dir === \"se\" || dir === \"ne\") {\n newW = Math.max(minWidth, startWidth + dx)\n }\n if (dir === \"w\" || dir === \"sw\" || dir === \"nw\") {\n newW = Math.max(minWidth, startWidth - dx)\n newX = startNodeX + startWidth - newW\n }\n\n // Vertical\n if (dir === \"s\" || dir === \"se\" || dir === \"sw\") {\n newH = Math.max(minHeight, startHeight + dy)\n }\n if (dir === \"n\" || dir === \"ne\" || dir === \"nw\") {\n newH = Math.max(minHeight, startHeight - dy)\n newY = startNodeY + startHeight - newH\n }\n\n instance.updateNode(nodeId, {\n width: newW,\n height: newH,\n position: { x: newX, y: newY },\n })\n }\n\n const onPointerUp = (e: PointerEvent) => {\n const el = e.currentTarget as HTMLElement\n if (el.hasPointerCapture(e.pointerId)) {\n el.releasePointerCapture(e.pointerId)\n }\n }\n\n return { onPointerDown, onPointerMove, onPointerUp }\n }\n\n const size = `${handleSize}px`\n const baseStyle = `position: absolute; width: ${size}; height: ${size}; background: white; border: 1.5px solid #3b82f6; border-radius: 2px; z-index: 2;`\n\n return (\n <>\n {directions.map((dir) => {\n const handler = createHandler(dir)\n return (\n <div\n key={dir}\n class={`pyreon-flow-resizer pyreon-flow-resizer-${dir}`}\n style={`${baseStyle} ${directionPositions[dir]} cursor: ${directionCursors[dir]};`}\n onPointerDown={handler.onPointerDown}\n onPointerMove={handler.onPointerMove}\n onPointerUp={handler.onPointerUp}\n />\n )\n })}\n </>\n )\n}\n","import type { VNodeChild } from \"@pyreon/core\"\n\nexport interface NodeToolbarProps {\n /** Position relative to node — default: 'top' */\n position?: \"top\" | \"bottom\" | \"left\" | \"right\"\n /** Offset from node in px — default: 8 */\n offset?: number\n /** Only show when node is selected — default: true */\n showOnSelect?: boolean\n /** Whether the node is currently selected */\n selected?: boolean\n style?: string\n class?: string\n children?: VNodeChild\n}\n\nconst positionStyles: Record<string, string> = {\n top: \"bottom: 100%; left: 50%; transform: translateX(-50%);\",\n bottom: \"top: 100%; left: 50%; transform: translateX(-50%);\",\n left: \"right: 100%; top: 50%; transform: translateY(-50%);\",\n right: \"left: 100%; top: 50%; transform: translateY(-50%);\",\n}\n\n/**\n * Floating toolbar that appears near a node, typically when selected.\n * Place inside a custom node component.\n *\n * @example\n * ```tsx\n * function EditableNode({ id, data, selected }: NodeComponentProps) {\n * return (\n * <div class=\"node\">\n * {data.label}\n * <NodeToolbar selected={selected}>\n * <button onClick={() => duplicate(id)}>Duplicate</button>\n * <button onClick={() => remove(id)}>Delete</button>\n * </NodeToolbar>\n * </div>\n * )\n * }\n * ```\n */\nexport function NodeToolbar(props: NodeToolbarProps): VNodeChild {\n const { position = \"top\", offset = 8, showOnSelect = true, selected = false, children } = props\n\n if (showOnSelect && !selected) return null\n\n const posStyle = positionStyles[position] ?? positionStyles.top\n const marginProp =\n position === \"top\"\n ? `margin-bottom: ${offset}px;`\n : position === \"bottom\"\n ? `margin-top: ${offset}px;`\n : position === \"left\"\n ? `margin-right: ${offset}px;`\n : `margin-left: ${offset}px;`\n\n const baseStyle = `position: absolute; ${posStyle} ${marginProp} z-index: 10; display: flex; gap: 4px; background: white; border: 1px solid #ddd; border-radius: 6px; padding: 4px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); ${props.style ?? \"\"}`\n\n return (\n <div class={`pyreon-flow-node-toolbar ${props.class ?? \"\"}`} style={baseStyle}>\n {children}\n </div>\n )\n}\n","import type { VNodeChild } from \"@pyreon/core\"\nimport type { PanelProps } from \"../types\"\n\nconst positionStyles: Record<string, string> = {\n \"top-left\": \"top: 10px; left: 10px;\",\n \"top-right\": \"top: 10px; right: 10px;\",\n \"bottom-left\": \"bottom: 10px; left: 10px;\",\n \"bottom-right\": \"bottom: 10px; right: 10px;\",\n}\n\n/**\n * Positioned overlay panel for custom content inside the flow canvas.\n *\n * @example\n * ```tsx\n * <Flow instance={flow}>\n * <Panel position=\"top-right\">\n * <SearchBar />\n * </Panel>\n * </Flow>\n * ```\n */\nexport function Panel(props: PanelProps): VNodeChild {\n const { position = \"top-left\", style = \"\", children } = props\n const posStyle = positionStyles[position] ?? positionStyles[\"top-left\"]\n const baseStyle = `position: absolute; ${posStyle} z-index: 5; ${style}`\n\n return (\n <div class={`pyreon-flow-panel ${props.class ?? \"\"}`} style={baseStyle}>\n {children}\n </div>\n )\n}\n","import type { FlowEdge, FlowNode, LayoutAlgorithm, LayoutOptions } from \"./types\"\n\n// ─── ELK algorithm mapping ───────────────────────────────────────────────────\n\nconst ELK_ALGORITHMS: Record<LayoutAlgorithm, string> = {\n layered: \"org.eclipse.elk.layered\",\n force: \"org.eclipse.elk.force\",\n stress: \"org.eclipse.elk.stress\",\n tree: \"org.eclipse.elk.mrtree\",\n radial: \"org.eclipse.elk.radial\",\n box: \"org.eclipse.elk.box\",\n rectpacking: \"org.eclipse.elk.rectpacking\",\n}\n\nconst ELK_DIRECTIONS: Record<string, string> = {\n UP: \"UP\",\n DOWN: \"DOWN\",\n LEFT: \"LEFT\",\n RIGHT: \"RIGHT\",\n}\n\n// ─── Lazy-loaded ELK instance ────────────────────────────────────────────────\n\nlet elkInstance: any = null\nlet elkPromise: Promise<any> | null = null\n\nasync function getELK(): Promise<any> {\n if (elkInstance) return elkInstance\n if (elkPromise) return elkPromise\n\n elkPromise = import(\"elkjs/lib/elk.bundled.js\").then((mod) => {\n const ELK = mod.default || mod\n elkInstance = new ELK()\n return elkInstance\n })\n\n return elkPromise\n}\n\n// ─── Convert flow graph to ELK format ────────────────────────────────────────\n\ninterface ElkNode {\n id: string\n width: number\n height: number\n}\n\ninterface ElkEdge {\n id: string\n sources: string[]\n targets: string[]\n}\n\ninterface ElkGraph {\n id: string\n layoutOptions: Record<string, string>\n children: ElkNode[]\n edges: ElkEdge[]\n}\n\ninterface ElkResult {\n children: Array<{ id: string; x: number; y: number }>\n}\n\nfunction toElkGraph(\n nodes: FlowNode[],\n edges: FlowEdge[],\n algorithm: LayoutAlgorithm,\n options: LayoutOptions,\n): ElkGraph {\n const layoutOptions: Record<string, string> = {\n \"elk.algorithm\": ELK_ALGORITHMS[algorithm] ?? ELK_ALGORITHMS.layered,\n }\n\n if (options.direction) {\n layoutOptions[\"elk.direction\"] = ELK_DIRECTIONS[options.direction] ?? \"DOWN\"\n }\n\n if (options.nodeSpacing !== undefined) {\n layoutOptions[\"elk.spacing.nodeNode\"] = String(options.nodeSpacing)\n }\n\n if (options.layerSpacing !== undefined) {\n layoutOptions[\"elk.layered.spacing.nodeNodeBetweenLayers\"] = String(options.layerSpacing)\n }\n\n if (options.edgeRouting) {\n const routingMap: Record<string, string> = {\n orthogonal: \"ORTHOGONAL\",\n splines: \"SPLINES\",\n polyline: \"POLYLINE\",\n }\n layoutOptions[\"elk.edgeRouting\"] = routingMap[options.edgeRouting] ?? \"ORTHOGONAL\"\n }\n\n return {\n id: \"root\",\n layoutOptions,\n children: nodes.map((node) => ({\n id: node.id,\n width: node.width ?? 150,\n height: node.height ?? 40,\n })),\n edges: edges.map((edge, i) => ({\n id: edge.id ?? `e-${i}`,\n sources: [edge.source],\n targets: [edge.target],\n })),\n }\n}\n\n// ─── Public API ──────────────────────────────────────────────────────────────\n\n/**\n * Compute a layout for the given nodes and edges using elkjs.\n * Returns an array of { id, position } for each node.\n *\n * elkjs is lazy-loaded — zero bundle cost until this function is called.\n *\n * @example\n * ```ts\n * const positions = await computeLayout(nodes, edges, 'layered', {\n * direction: 'RIGHT',\n * nodeSpacing: 50,\n * layerSpacing: 100,\n * })\n * // positions: [{ id: '1', position: { x: 0, y: 0 } }, ...]\n * ```\n */\nexport async function computeLayout(\n nodes: FlowNode[],\n edges: FlowEdge[],\n algorithm: LayoutAlgorithm = \"layered\",\n options: LayoutOptions = {},\n): Promise<Array<{ id: string; position: { x: number; y: number } }>> {\n const elk = await getELK()\n const graph = toElkGraph(nodes, edges, algorithm, options)\n const result: ElkResult = await elk.layout(graph)\n\n return (result.children ?? []).map((child) => ({\n id: child.id,\n position: { x: child.x ?? 0, y: child.y ?? 0 },\n }))\n}\n","import { batch, computed, signal } from \"@pyreon/reactivity\"\nimport { computeLayout } from \"./layout\"\nimport type {\n Connection,\n FlowConfig,\n FlowEdge,\n FlowInstance,\n FlowNode,\n LayoutAlgorithm,\n LayoutOptions,\n NodeChange,\n XYPosition,\n} from \"./types\"\n\n/**\n * Generate a unique edge id from source/target.\n */\nfunction edgeId(edge: FlowEdge): string {\n if (edge.id) return edge.id\n const sh = edge.sourceHandle ? `-${edge.sourceHandle}` : \"\"\n const th = edge.targetHandle ? `-${edge.targetHandle}` : \"\"\n return `e-${edge.source}${sh}-${edge.target}${th}`\n}\n\n/**\n * Create a reactive flow instance — the core state manager for flow diagrams.\n *\n * All state is signal-based. Nodes, edges, viewport, and selection are\n * reactive and update the UI automatically when modified.\n *\n * @param config - Initial configuration with nodes, edges, and options\n * @returns A FlowInstance with signals and methods for managing the diagram\n *\n * @example\n * ```tsx\n * const flow = createFlow({\n * nodes: [\n * { id: '1', position: { x: 0, y: 0 }, data: { label: 'Start' } },\n * { id: '2', position: { x: 200, y: 100 }, data: { label: 'End' } },\n * ],\n * edges: [{ source: '1', target: '2' }],\n * })\n *\n * flow.nodes() // reactive node list\n * flow.viewport() // { x: 0, y: 0, zoom: 1 }\n * flow.addNode({ id: '3', position: { x: 400, y: 0 }, data: { label: 'New' } })\n * flow.layout('layered', { direction: 'RIGHT' })\n * ```\n */\nexport function createFlow(config: FlowConfig = {}): FlowInstance {\n const {\n nodes: initialNodes = [],\n edges: initialEdges = [],\n defaultEdgeType = \"bezier\",\n minZoom = 0.1,\n maxZoom = 4,\n snapToGrid = false,\n snapGrid = 15,\n connectionRules,\n } = config\n\n // Ensure all edges have ids\n const edgesWithIds = initialEdges.map((e) => ({\n ...e,\n id: edgeId(e),\n type: e.type ?? defaultEdgeType,\n }))\n\n // ── Core signals ─────────────────────────────────────────────────────────\n\n const nodes = signal<FlowNode[]>([...initialNodes])\n const edges = signal<FlowEdge[]>(edgesWithIds)\n const viewport = signal({ x: 0, y: 0, zoom: 1 })\n const containerSize = signal({ width: 800, height: 600 })\n\n // Track selected state separately for O(1) lookups\n const selectedNodeIds = signal(new Set<string>())\n const selectedEdgeIds = signal(new Set<string>())\n\n // ── Computed ─────────────────────────────────────────────────────────────\n\n const zoom = computed(() => viewport().zoom)\n\n const selectedNodes = computed(() => [...selectedNodeIds()])\n const selectedEdges = computed(() => [...selectedEdgeIds()])\n\n // ── Listeners ────────────────────────────────────────────────────────────\n\n const connectListeners = new Set<(connection: Connection) => void>()\n const nodesChangeListeners = new Set<(changes: NodeChange[]) => void>()\n const nodeClickListeners = new Set<(node: FlowNode) => void>()\n const edgeClickListeners = new Set<(edge: FlowEdge) => void>()\n const nodeDragStartListeners = new Set<(node: FlowNode) => void>()\n const nodeDragEndListeners = new Set<(node: FlowNode) => void>()\n const nodeDoubleClickListeners = new Set<(node: FlowNode) => void>()\n\n function emitNodeChanges(changes: NodeChange[]) {\n for (const cb of nodesChangeListeners) cb(changes)\n }\n\n // ── Node operations ──────────────────────────────────────────────────────\n\n function getNode(id: string): FlowNode | undefined {\n return nodes.peek().find((n) => n.id === id)\n }\n\n function addNode(node: FlowNode): void {\n nodes.update((nds) => [...nds, node])\n }\n\n function removeNode(id: string): void {\n batch(() => {\n nodes.update((nds) => nds.filter((n) => n.id !== id))\n // Remove connected edges\n edges.update((eds) => eds.filter((e) => e.source !== id && e.target !== id))\n selectedNodeIds.update((set) => {\n const next = new Set(set)\n next.delete(id)\n return next\n })\n })\n emitNodeChanges([{ type: \"remove\", id }])\n }\n\n function updateNode(id: string, update: Partial<FlowNode>): void {\n nodes.update((nds) => nds.map((n) => (n.id === id ? { ...n, ...update } : n)))\n }\n\n function updateNodePosition(id: string, position: XYPosition): void {\n let pos = snapToGrid\n ? {\n x: Math.round(position.x / snapGrid) * snapGrid,\n y: Math.round(position.y / snapGrid) * snapGrid,\n }\n : position\n\n // Apply extent clamping\n const node = getNode(id)\n pos = clampToExtent(pos, node?.width, node?.height)\n\n nodes.update((nds) => nds.map((n) => (n.id === id ? { ...n, position: pos } : n)))\n emitNodeChanges([{ type: \"position\", id, position: pos }])\n }\n\n // ── Edge operations ──────────────────────────────────────────────────────\n\n function getEdge(id: string): FlowEdge | undefined {\n return edges.peek().find((e) => e.id === id)\n }\n\n function addEdge(edge: FlowEdge): void {\n const newEdge = {\n ...edge,\n id: edgeId(edge),\n type: edge.type ?? defaultEdgeType,\n }\n\n // Don't add duplicate edges\n const existing = edges.peek()\n if (existing.some((e) => e.id === newEdge.id)) return\n\n edges.update((eds) => [...eds, newEdge])\n\n // Notify connect listeners\n const connection: Connection = {\n source: edge.source,\n target: edge.target,\n ...(edge.sourceHandle != null ? { sourceHandle: edge.sourceHandle } : {}),\n ...(edge.targetHandle != null ? { targetHandle: edge.targetHandle } : {}),\n }\n for (const cb of connectListeners) cb(connection)\n }\n\n function removeEdge(id: string): void {\n edges.update((eds) => eds.filter((e) => e.id !== id))\n selectedEdgeIds.update((set) => {\n const next = new Set(set)\n next.delete(id)\n return next\n })\n }\n\n function isValidConnection(connection: Connection): boolean {\n if (!connectionRules) return true\n\n // Find source node type\n const sourceNode = getNode(connection.source)\n if (!sourceNode) return false\n\n const sourceType = sourceNode.type ?? \"default\"\n const rule = connectionRules[sourceType]\n if (!rule) return true // no rule = allow\n\n // Find target node type\n const targetNode = getNode(connection.target)\n if (!targetNode) return false\n\n const targetType = targetNode.type ?? \"default\"\n return rule.outputs.includes(targetType)\n }\n\n // ── Selection ────────────────────────────────────────────────────────────\n\n function selectNode(id: string, additive = false): void {\n selectedNodeIds.update((set) => {\n const next = additive ? new Set(set) : new Set<string>()\n next.add(id)\n return next\n })\n if (!additive) {\n selectedEdgeIds.set(new Set())\n }\n }\n\n function deselectNode(id: string): void {\n selectedNodeIds.update((set) => {\n const next = new Set(set)\n next.delete(id)\n return next\n })\n }\n\n function selectEdge(id: string, additive = false): void {\n selectedEdgeIds.update((set) => {\n const next = additive ? new Set(set) : new Set<string>()\n next.add(id)\n return next\n })\n if (!additive) {\n selectedNodeIds.set(new Set())\n }\n }\n\n function clearSelection(): void {\n batch(() => {\n selectedNodeIds.set(new Set())\n selectedEdgeIds.set(new Set())\n })\n }\n\n function selectAll(): void {\n selectedNodeIds.set(new Set(nodes.peek().map((n) => n.id)))\n }\n\n function deleteSelected(): void {\n batch(() => {\n const nodeIdsToRemove = selectedNodeIds.peek()\n const edgeIdsToRemove = selectedEdgeIds.peek()\n\n if (nodeIdsToRemove.size > 0) {\n nodes.update((nds) => nds.filter((n) => !nodeIdsToRemove.has(n.id)))\n // Also remove edges connected to deleted nodes\n edges.update((eds) =>\n eds.filter(\n (e) =>\n !nodeIdsToRemove.has(e.source) &&\n !nodeIdsToRemove.has(e.target) &&\n !edgeIdsToRemove.has(e.id!),\n ),\n )\n } else if (edgeIdsToRemove.size > 0) {\n edges.update((eds) => eds.filter((e) => !edgeIdsToRemove.has(e.id!)))\n }\n\n selectedNodeIds.set(new Set())\n selectedEdgeIds.set(new Set())\n })\n }\n\n // ── Viewport ─────────────────────────────────────────────────────────────\n\n function fitView(nodeIds?: string[], padding = config.fitViewPadding ?? 0.1): void {\n const targetNodes = nodeIds ? nodes.peek().filter((n) => nodeIds.includes(n.id)) : nodes.peek()\n\n if (targetNodes.length === 0) return\n\n let minX = Number.POSITIVE_INFINITY\n let minY = Number.POSITIVE_INFINITY\n let maxX = Number.NEGATIVE_INFINITY\n let maxY = Number.NEGATIVE_INFINITY\n\n for (const node of targetNodes) {\n const w = node.width ?? 150\n const h = node.height ?? 40\n minX = Math.min(minX, node.position.x)\n minY = Math.min(minY, node.position.y)\n maxX = Math.max(maxX, node.position.x + w)\n maxY = Math.max(maxY, node.position.y + h)\n }\n\n const graphWidth = maxX - minX\n const graphHeight = maxY - minY\n\n const { width: containerWidth, height: containerHeight } = containerSize.peek()\n\n const zoomX = containerWidth / (graphWidth * (1 + padding * 2))\n const zoomY = containerHeight / (graphHeight * (1 + padding * 2))\n const newZoom = Math.min(Math.max(Math.min(zoomX, zoomY), minZoom), maxZoom)\n\n const centerX = (minX + maxX) / 2\n const centerY = (minY + maxY) / 2\n\n viewport.set({\n x: containerWidth / 2 - centerX * newZoom,\n y: containerHeight / 2 - centerY * newZoom,\n zoom: newZoom,\n })\n }\n\n function zoomTo(z: number): void {\n viewport.update((v) => ({\n ...v,\n zoom: Math.min(Math.max(z, minZoom), maxZoom),\n }))\n }\n\n function zoomIn(): void {\n viewport.update((v) => ({\n ...v,\n zoom: Math.min(v.zoom * 1.2, maxZoom),\n }))\n }\n\n function zoomOut(): void {\n viewport.update((v) => ({\n ...v,\n zoom: Math.max(v.zoom / 1.2, minZoom),\n }))\n }\n\n function panTo(position: XYPosition): void {\n viewport.update((v) => ({\n ...v,\n x: -position.x * v.zoom,\n y: -position.y * v.zoom,\n }))\n }\n\n function isNodeVisible(id: string): boolean {\n const node = getNode(id)\n if (!node) return false\n // Simplified check — actual implementation would use container dimensions\n const v = viewport.peek()\n const w = node.width ?? 150\n const h = node.height ?? 40\n const screenX = node.position.x * v.zoom + v.x\n const screenY = node.position.y * v.zoom + v.y\n const screenW = w * v.zoom\n const screenH = h * v.zoom\n const { width: cw, height: ch } = containerSize.peek()\n return screenX + screenW > 0 && screenX < cw && screenY + screenH > 0 && screenY < ch\n }\n\n // ── Layout ───────────────────────────────────────────────────────────────\n\n async function layout(\n algorithm: LayoutAlgorithm = \"layered\",\n options: LayoutOptions = {},\n ): Promise<void> {\n const currentNodes = nodes.peek()\n const currentEdges = edges.peek()\n\n const positions = await computeLayout(currentNodes, currentEdges, algorithm, options)\n\n const animate = options.animate !== false\n const duration = options.animationDuration ?? 300\n\n if (!animate) {\n batch(() => {\n nodes.update((nds) =>\n nds.map((node) => {\n const pos = positions.find((p) => p.id === node.id)\n return pos ? { ...node, position: pos.position } : node\n }),\n )\n })\n return\n }\n\n // Animated transition — interpolate positions over duration\n const startPositions = new Map(currentNodes.map((n) => [n.id, { ...n.position }]))\n const targetPositions = new Map(positions.map((p) => [p.id, p.position]))\n\n const startTime = performance.now()\n\n const animateFrame = () => {\n const elapsed = performance.now() - startTime\n const t = Math.min(elapsed / duration, 1)\n // Ease-out cubic\n const eased = 1 - (1 - t) ** 3\n\n batch(() => {\n nodes.update((nds) =>\n nds.map((node) => {\n const start = startPositions.get(node.id)\n const end = targetPositions.get(node.id)\n if (!start || !end) return node\n return {\n ...node,\n position: {\n x: start.x + (end.x - start.x) * eased,\n y: start.y + (end.y - start.y) * eased,\n },\n }\n }),\n )\n })\n\n if (t < 1) requestAnimationFrame(animateFrame)\n }\n\n requestAnimationFrame(animateFrame)\n }\n\n // ── Batch ────────────────────────────────────────────────────────────────\n\n function batchOp(fn: () => void): void {\n batch(fn)\n }\n\n // ── Graph queries ────────────────────────────────────────────────────────\n\n function getConnectedEdges(nodeId: string): FlowEdge[] {\n return edges.peek().filter((e) => e.source === nodeId || e.target === nodeId)\n }\n\n function getIncomers(nodeId: string): FlowNode[] {\n const incomingEdges = edges.peek().filter((e) => e.target === nodeId)\n const sourceIds = new Set(incomingEdges.map((e) => e.source))\n return nodes.peek().filter((n) => sourceIds.has(n.id))\n }\n\n function getOutgoers(nodeId: string): FlowNode[] {\n const outgoingEdges = edges.peek().filter((e) => e.source === nodeId)\n const targetIds = new Set(outgoingEdges.map((e) => e.target))\n return nodes.peek().filter((n) => targetIds.has(n.id))\n }\n\n // ── Listeners ────────────────────────────────────────────────────────────\n\n function onConnect(callback: (connection: Connection) => void): () => void {\n connectListeners.add(callback)\n return () => connectListeners.delete(callback)\n }\n\n function onNodesChange(callback: (changes: NodeChange[]) => void): () => void {\n nodesChangeListeners.add(callback)\n return () => nodesChangeListeners.delete(callback)\n }\n\n function onNodeClick(callback: (node: FlowNode) => void): () => void {\n nodeClickListeners.add(callback)\n return () => nodeClickListeners.delete(callback)\n }\n\n function onEdgeClick(callback: (edge: FlowEdge) => void): () => void {\n edgeClickListeners.add(callback)\n return () => edgeClickListeners.delete(callback)\n }\n\n function onNodeDragStart(callback: (node: FlowNode) => void): () => void {\n nodeDragStartListeners.add(callback)\n return () => nodeDragStartListeners.delete(callback)\n }\n\n function onNodeDragEnd(callback: (node: FlowNode) => void): () => void {\n nodeDragEndListeners.add(callback)\n return () => nodeDragEndListeners.delete(callback)\n }\n\n function onNodeDoubleClick(callback: (node: FlowNode) => void): () => void {\n nodeDoubleClickListeners.add(callback)\n return () => nodeDoubleClickListeners.delete(callback)\n }\n\n // ── Copy / Paste ────────────────────────────────────────────────────────\n\n let clipboard: { nodes: FlowNode[]; edges: FlowEdge[] } | null = null\n\n function copySelected(): void {\n const selectedNodeSet = selectedNodeIds.peek()\n if (selectedNodeSet.size === 0) return\n\n const copiedNodes = nodes.peek().filter((n) => selectedNodeSet.has(n.id))\n const nodeIdSet = new Set(copiedNodes.map((n) => n.id))\n const copiedEdges = edges\n .peek()\n .filter((e) => nodeIdSet.has(e.source) && nodeIdSet.has(e.target))\n\n clipboard = { nodes: copiedNodes, edges: copiedEdges }\n }\n\n function paste(offset: XYPosition = { x: 50, y: 50 }): void {\n if (!clipboard) return\n\n const idMap = new Map<string, string>()\n const newNodes: FlowNode[] = []\n\n // Create new nodes with offset positions and new ids\n for (const node of clipboard.nodes) {\n const newId = `${node.id}-copy-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`\n idMap.set(node.id, newId)\n newNodes.push({\n ...node,\n id: newId,\n position: {\n x: node.position.x + offset.x,\n y: node.position.y + offset.y,\n },\n })\n }\n\n const newEdges: FlowEdge[] = clipboard.edges.map((e) => {\n const { id: _id, ...rest } = e\n return {\n ...rest,\n source: idMap.get(e.source) ?? e.source,\n target: idMap.get(e.target) ?? e.target,\n }\n })\n\n batch(() => {\n for (const node of newNodes) addNode(node)\n for (const edge of newEdges) addEdge(edge)\n\n // Select pasted nodes\n selectedNodeIds.set(new Set(newNodes.map((n) => n.id)))\n selectedEdgeIds.set(new Set())\n })\n }\n\n // ── Undo / Redo ────────────────────────────────────────────────────────\n\n const undoStack: Array<{ nodes: FlowNode[]; edges: FlowEdge[] }> = []\n const redoStack: Array<{ nodes: FlowNode[]; edges: FlowEdge[] }> = []\n const maxHistory = 50\n\n function pushHistory(): void {\n undoStack.push({\n nodes: structuredClone(nodes.peek()),\n edges: structuredClone(edges.peek()),\n })\n if (undoStack.length > maxHistory) undoStack.shift()\n redoStack.length = 0\n }\n\n function undo(): void {\n const prev = undoStack.pop()\n if (!prev) return\n\n redoStack.push({\n nodes: structuredClone(nodes.peek()),\n edges: structuredClone(edges.peek()),\n })\n\n batch(() => {\n nodes.set(prev.nodes)\n edges.set(prev.edges)\n clearSelection()\n })\n }\n\n function redo(): void {\n const next = redoStack.pop()\n if (!next) return\n\n undoStack.push({\n nodes: structuredClone(nodes.peek()),\n edges: structuredClone(edges.peek()),\n })\n\n batch(() => {\n nodes.set(next.nodes)\n edges.set(next.edges)\n clearSelection()\n })\n }\n\n // ── Multi-node drag ────────────────────────────────────────────────────\n\n function moveSelectedNodes(dx: number, dy: number): void {\n const selected = selectedNodeIds.peek()\n if (selected.size === 0) return\n\n nodes.update((nds) =>\n nds.map((n) => {\n if (!selected.has(n.id)) return n\n return {\n ...n,\n position: {\n x: n.position.x + dx,\n y: n.position.y + dy,\n },\n }\n }),\n )\n }\n\n // ── Helper lines (snap guides) ─────────────────────────────────────────\n\n function getSnapLines(\n dragNodeId: string,\n position: XYPosition,\n threshold = 5,\n ): { x: number | null; y: number | null; snappedPosition: XYPosition } {\n const dragNode = getNode(dragNodeId)\n if (!dragNode) return { x: null, y: null, snappedPosition: position }\n\n const w = dragNode.width ?? 150\n const h = dragNode.height ?? 40\n const dragCenterX = position.x + w / 2\n const dragCenterY = position.y + h / 2\n\n let snapX: number | null = null\n let snapY: number | null = null\n let snappedX = position.x\n let snappedY = position.y\n\n for (const node of nodes.peek()) {\n if (node.id === dragNodeId) continue\n const nw = node.width ?? 150\n const nh = node.height ?? 40\n const nodeCenterX = node.position.x + nw / 2\n const nodeCenterY = node.position.y + nh / 2\n\n // Snap to center X\n if (Math.abs(dragCenterX - nodeCenterX) < threshold) {\n snapX = nodeCenterX\n snappedX = nodeCenterX - w / 2\n }\n // Snap to left edge\n if (Math.abs(position.x - node.position.x) < threshold) {\n snapX = node.position.x\n snappedX = node.position.x\n }\n // Snap to right edge\n if (Math.abs(position.x + w - (node.position.x + nw)) < threshold) {\n snapX = node.position.x + nw\n snappedX = node.position.x + nw - w\n }\n\n // Snap to center Y\n if (Math.abs(dragCenterY - nodeCenterY) < threshold) {\n snapY = nodeCenterY\n snappedY = nodeCenterY - h / 2\n }\n // Snap to top edge\n if (Math.abs(position.y - node.position.y) < threshold) {\n snapY = node.position.y\n snappedY = node.position.y\n }\n // Snap to bottom edge\n if (Math.abs(position.y + h - (node.position.y + nh)) < threshold) {\n snapY = node.position.y + nh\n snappedY = node.position.y + nh - h\n }\n }\n\n return { x: snapX, y: snapY, snappedPosition: { x: snappedX, y: snappedY } }\n }\n\n // ── Sub-flows / Groups ──────────────────────────────────────────────────\n\n function getChildNodes(parentId: string): FlowNode[] {\n return nodes.peek().filter((n) => n.parentId === parentId)\n }\n\n function getAbsolutePosition(nodeId: string): XYPosition {\n const node = getNode(nodeId)\n if (!node) return { x: 0, y: 0 }\n\n if (node.parentId) {\n const parentPos = getAbsolutePosition(node.parentId)\n return {\n x: parentPos.x + node.position.x,\n y: parentPos.y + node.position.y,\n }\n }\n\n return node.position\n }\n\n // ── Edge reconnecting ──────────────────────────────────────────────────\n\n function reconnectEdge(\n targetEdgeId: string,\n newConnection: {\n source?: string\n target?: string\n sourceHandle?: string\n targetHandle?: string\n },\n ): void {\n edges.update((eds) =>\n eds.map((e) => {\n if (e.id !== targetEdgeId) return e\n const updated: typeof e = {\n ...e,\n source: newConnection.source ?? e.source,\n target: newConnection.target ?? e.target,\n }\n const sh = newConnection.sourceHandle ?? e.sourceHandle\n const th = newConnection.targetHandle ?? e.targetHandle\n if (sh != null) updated.sourceHandle = sh\n if (th != null) updated.targetHandle = th\n return updated\n }),\n )\n }\n\n // ── Edge waypoints ──────────────────────────────────────────────────────\n\n function addEdgeWaypoint(edgeIdentifier: string, point: XYPosition, index?: number): void {\n edges.update((eds) =>\n eds.map((e) => {\n if (e.id !== edgeIdentifier) return e\n const waypoints = [...(e.waypoints ?? [])]\n if (index !== undefined) {\n waypoints.splice(index, 0, point)\n } else {\n waypoints.push(point)\n }\n return { ...e, waypoints }\n }),\n )\n }\n\n function removeEdgeWaypoint(edgeIdentifier: string, index: number): void {\n edges.update((eds) =>\n eds.map((e) => {\n if (e.id !== edgeIdentifier) return e\n const waypoints = [...(e.waypoints ?? [])]\n waypoints.splice(index, 1)\n const { waypoints: _wp, ...rest } = e\n return waypoints.length > 0 ? { ...rest, waypoints } : rest\n }),\n )\n }\n\n function updateEdgeWaypoint(edgeIdentifier: string, index: number, point: XYPosition): void {\n edges.update((eds) =>\n eds.map((e) => {\n if (e.id !== edgeIdentifier) return e\n const waypoints = [...(e.waypoints ?? [])]\n if (index >= 0 && index < waypoints.length) {\n waypoints[index] = point\n }\n return { ...e, waypoints }\n }),\n )\n }\n\n // ── Proximity connect ───────────────────────────────────────────────────\n\n function getProximityConnection(nodeId: string, threshold = 50): Connection | null {\n const node = getNode(nodeId)\n if (!node) return null\n\n const w = node.width ?? 150\n const h = node.height ?? 40\n const centerX = node.position.x + w / 2\n const centerY = node.position.y + h / 2\n\n let closest: { nodeId: string; dist: number } | null = null\n\n for (const other of nodes.peek()) {\n if (other.id === nodeId) continue\n // Skip if already connected\n const alreadyConnected = edges\n .peek()\n .some(\n (e) =>\n (e.source === nodeId && e.target === other.id) ||\n (e.source === other.id && e.target === nodeId),\n )\n if (alreadyConnected) continue\n\n const ow = other.width ?? 150\n const oh = other.height ?? 40\n const ocx = other.position.x + ow / 2\n const ocy = other.position.y + oh / 2\n const dist = Math.hypot(centerX - ocx, centerY - ocy)\n\n if (dist < threshold && (!closest || dist < closest.dist)) {\n closest = { nodeId: other.id, dist }\n }\n }\n\n if (!closest) return null\n\n const connection: Connection = {\n source: nodeId,\n target: closest.nodeId,\n }\n\n return isValidConnection(connection) ? connection : null\n }\n\n // ── Collision detection ────────────────────────────────────────────────\n\n function getOverlappingNodes(nodeId: string): FlowNode[] {\n const node = getNode(nodeId)\n if (!node) return []\n\n const w = node.width ?? 150\n const h = node.height ?? 40\n const ax1 = node.position.x\n const ay1 = node.position.y\n const ax2 = ax1 + w\n const ay2 = ay1 + h\n\n return nodes.peek().filter((other) => {\n if (other.id === nodeId) return false\n const ow = other.width ?? 150\n const oh = other.height ?? 40\n const bx1 = other.position.x\n const by1 = other.position.y\n const bx2 = bx1 + ow\n const by2 = by1 + oh\n\n return ax1 < bx2 && ax2 > bx1 && ay1 < by2 && ay2 > by1\n })\n }\n\n function resolveCollisions(nodeId: string, spacing = 10): void {\n const overlapping = getOverlappingNodes(nodeId)\n if (overlapping.length === 0) return\n\n const node = getNode(nodeId)\n if (!node) return\n\n const w = node.width ?? 150\n const h = node.height ?? 40\n\n for (const other of overlapping) {\n const ow = other.width ?? 150\n const oh = other.height ?? 40\n\n // Calculate overlap amounts\n const overlapX = Math.min(\n node.position.x + w - other.position.x,\n other.position.x + ow - node.position.x,\n )\n const overlapY = Math.min(\n node.position.y + h - other.position.y,\n other.position.y + oh - node.position.y,\n )\n\n // Push in the direction of least overlap\n if (overlapX < overlapY) {\n const dx =\n node.position.x < other.position.x ? -(overlapX + spacing) / 2 : (overlapX + spacing) / 2\n updateNodePosition(other.id, {\n x: other.position.x - dx,\n y: other.position.y,\n })\n } else {\n const dy =\n node.position.y < other.position.y ? -(overlapY + spacing) / 2 : (overlapY + spacing) / 2\n updateNodePosition(other.id, {\n x: other.position.x,\n y: other.position.y - dy,\n })\n }\n }\n }\n\n // ── Node extent (drag boundaries) ──────────────────────────────────────\n\n function setNodeExtent(extent: [[number, number], [number, number]] | null): void {\n nodeExtent = extent\n }\n\n let nodeExtent: [[number, number], [number, number]] | null = config.nodeExtent ?? null\n\n function clampToExtent(position: XYPosition, nodeWidth = 150, nodeHeight = 40): XYPosition {\n if (!nodeExtent) return position\n return {\n x: Math.min(Math.max(position.x, nodeExtent[0][0]), nodeExtent[1][0] - nodeWidth),\n y: Math.min(Math.max(position.y, nodeExtent[0][1]), nodeExtent[1][1] - nodeHeight),\n }\n }\n\n // ── Custom edge types ──────────────────────────────────────────────────\n // Custom edge rendering is handled in the Flow component via edgeTypes prop.\n // The flow instance provides the data; rendering is delegated to components.\n\n // ── Search / Filter ─────────────────────────────────────────────────────\n\n function findNodes(predicate: (node: FlowNode) => boolean): FlowNode[] {\n return nodes.peek().filter(predicate)\n }\n\n function searchNodes(query: string): FlowNode[] {\n const q = query.toLowerCase()\n return nodes.peek().filter((n) => {\n const label = (n.data?.label as string) ?? n.id\n return label.toLowerCase().includes(q)\n })\n }\n\n function focusNode(nodeId: string, focusZoom?: number): void {\n const node = getNode(nodeId)\n if (!node) return\n\n const w = node.width ?? 150\n const h = node.height ?? 40\n const centerX = node.position.x + w / 2\n const centerY = node.position.y + h / 2\n const z = focusZoom ?? viewport.peek().zoom\n const { width: cw, height: ch } = containerSize.peek()\n\n animateViewport({\n x: -centerX * z + cw / 2,\n y: -centerY * z + ch / 2,\n zoom: z,\n })\n\n // Select the focused node\n selectNode(nodeId)\n }\n\n // ── Export / Import ────────────────────────────────────────────────────\n\n function toJSON(): {\n nodes: FlowNode[]\n edges: FlowEdge[]\n viewport: { x: number; y: number; zoom: number }\n } {\n return {\n nodes: structuredClone(nodes.peek()),\n edges: structuredClone(edges.peek()),\n viewport: { ...viewport.peek() },\n }\n }\n\n function fromJSON(data: {\n nodes: FlowNode[]\n edges: FlowEdge[]\n viewport?: { x: number; y: number; zoom: number }\n }): void {\n batch(() => {\n nodes.set(data.nodes)\n edges.set(\n data.edges.map((e) => ({\n ...e,\n id: e.id ?? edgeId(e),\n type: e.type ?? defaultEdgeType,\n })),\n )\n if (data.viewport) viewport.set(data.viewport)\n clearSelection()\n })\n }\n\n // ── Viewport animation ─────────────────────────────────────────────────\n\n function animateViewport(\n target: Partial<{ x: number; y: number; zoom: number }>,\n duration = 300,\n ): void {\n const start = { ...viewport.peek() }\n const end = {\n x: target.x ?? start.x,\n y: target.y ?? start.y,\n zoom: target.zoom ?? start.zoom,\n }\n const startTime = performance.now()\n\n const frame = () => {\n const elapsed = performance.now() - startTime\n const t = Math.min(elapsed / duration, 1)\n const eased = 1 - (1 - t) ** 3 // ease-out cubic\n\n viewport.set({\n x: start.x + (end.x - start.x) * eased,\n y: start.y + (end.y - start.y) * eased,\n zoom: start.zoom + (end.zoom - start.zoom) * eased,\n })\n\n if (t < 1) requestAnimationFrame(frame)\n }\n\n requestAnimationFrame(frame)\n }\n\n // ── Dispose ──────────────────────────────────────────────────────────────\n\n function dispose(): void {\n connectListeners.clear()\n nodesChangeListeners.clear()\n nodeClickListeners.clear()\n edgeClickListeners.clear()\n nodeDragStartListeners.clear()\n nodeDragEndListeners.clear()\n nodeDoubleClickListeners.clear()\n }\n\n // ── Initial fitView ──────────────────────────────────────────────────────\n\n if (config.fitView) {\n fitView()\n }\n\n return {\n nodes,\n edges,\n viewport,\n zoom,\n containerSize,\n selectedNodes,\n selectedEdges,\n getNode,\n addNode,\n removeNode,\n updateNode,\n updateNodePosition,\n getEdge,\n addEdge,\n removeEdge,\n isValidConnection,\n selectNode,\n deselectNode,\n selectEdge,\n clearSelection,\n selectAll,\n deleteSelected,\n fitView,\n zoomTo,\n zoomIn,\n zoomOut,\n panTo,\n isNodeVisible,\n layout,\n batch: batchOp,\n getConnectedEdges,\n getIncomers,\n getOutgoers,\n onConnect,\n onNodesChange,\n onNodeClick,\n onEdgeClick,\n onNodeDragStart,\n onNodeDragEnd,\n onNodeDoubleClick,\n /** @internal — used by Flow component to emit events */\n _emit: {\n nodeDragStart: (node: FlowNode) => {\n for (const cb of nodeDragStartListeners) cb(node)\n },\n nodeDragEnd: (node: FlowNode) => {\n for (const cb of nodeDragEndListeners) cb(node)\n },\n nodeDoubleClick: (node: FlowNode) => {\n for (const cb of nodeDoubleClickListeners) cb(node)\n },\n nodeClick: (node: FlowNode) => {\n for (const cb of nodeClickListeners) cb(node)\n },\n edgeClick: (edge: FlowEdge) => {\n for (const cb of edgeClickListeners) cb(edge)\n },\n },\n copySelected,\n paste,\n pushHistory,\n undo,\n redo,\n moveSelectedNodes,\n getSnapLines,\n getChildNodes,\n getAbsolutePosition,\n addEdgeWaypoint,\n removeEdgeWaypoint,\n updateEdgeWaypoint,\n reconnectEdge,\n getProximityConnection,\n getOverlappingNodes,\n resolveCollisions,\n setNodeExtent,\n clampToExtent,\n findNodes,\n searchNodes,\n focusNode,\n toJSON,\n fromJSON,\n animateViewport,\n config,\n dispose,\n }\n}\n","/**\n * Default CSS styles for the flow diagram.\n * Inject via `<style>` tag or import in your CSS.\n *\n * @example\n * ```tsx\n * import { flowStyles } from '@pyreon/flow'\n *\n * // Inject once at app root\n * const style = document.createElement('style')\n * style.textContent = flowStyles\n * document.head.appendChild(style)\n * ```\n */\nexport const flowStyles = `\n/* ── Animated edges ────────────────────────────────────────────────────────── */\n\n.pyreon-flow-edge-animated {\n stroke-dasharray: 5;\n animation: pyreon-flow-edge-dash 0.5s linear infinite;\n}\n\n@keyframes pyreon-flow-edge-dash {\n to {\n stroke-dashoffset: -10;\n }\n}\n\n/* ── Node states ──────────────────────────────────────────────────────────── */\n\n.pyreon-flow-node {\n transition: box-shadow 0.15s ease;\n}\n\n.pyreon-flow-node.dragging {\n opacity: 0.9;\n filter: drop-shadow(0 4px 12px rgba(0, 0, 0, 0.15));\n cursor: grabbing;\n}\n\n.pyreon-flow-node.selected {\n filter: drop-shadow(0 0 0 2px rgba(59, 130, 246, 0.3));\n}\n\n/* ── Handles ──────────────────────────────────────────────────────────────── */\n\n.pyreon-flow-handle {\n transition: transform 0.1s ease, background 0.1s ease;\n}\n\n.pyreon-flow-handle:hover {\n transform: scale(1.4);\n background: #3b82f6 !important;\n}\n\n.pyreon-flow-handle-target:hover {\n background: #22c55e !important;\n border-color: #22c55e !important;\n}\n\n/* ── Resizer ──────────────────────────────────────────────────────────────── */\n\n.pyreon-flow-resizer {\n transition: background 0.1s ease, transform 0.1s ease;\n}\n\n.pyreon-flow-resizer:hover {\n background: #3b82f6 !important;\n transform: scale(1.2);\n}\n\n/* ── Selection box ────────────────────────────────────────────────────────── */\n\n.pyreon-flow-selection-box {\n pointer-events: none;\n border-radius: 2px;\n}\n\n/* ── MiniMap ──────────────────────────────────────────────────────────────── */\n\n.pyreon-flow-minimap {\n transition: opacity 0.2s ease;\n}\n\n.pyreon-flow-minimap:hover {\n opacity: 1 !important;\n}\n\n/* ── Node toolbar ─────────────────────────────────────────────────────────── */\n\n.pyreon-flow-node-toolbar {\n animation: pyreon-flow-toolbar-enter 0.15s ease;\n}\n\n@keyframes pyreon-flow-toolbar-enter {\n from {\n opacity: 0;\n transform: translateX(-50%) translateY(4px);\n }\n to {\n opacity: 1;\n transform: translateX(-50%) translateY(0);\n }\n}\n\n/* ── Controls ─────────────────────────────────────────────────────────────── */\n\n.pyreon-flow-controls button:hover {\n background: #f3f4f6 !important;\n}\n\n.pyreon-flow-controls button:active {\n background: #e5e7eb !important;\n}\n`\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["positionStyles","positionStyles"],"sources":["../../../core/core/lib/jsx-runtime.js","../src/components/background.tsx","../src/components/controls.tsx","../src/types.ts","../src/edges.ts","../src/components/flow-component.tsx","../src/components/handle.tsx","../src/components/minimap.tsx","../src/components/node-resizer.tsx","../src/components/node-toolbar.tsx","../src/components/panel.tsx","../src/layout.ts","../src/flow.ts","../src/styles.ts"],"sourcesContent":["//#region src/h.ts\n/** Marker for fragment nodes — renders children without a wrapper element */\nconst Fragment = Symbol(\"Pyreon.Fragment\");\n/**\n* Hyperscript function — the compiled output of JSX.\n* `<div class=\"x\">hello</div>` → `h(\"div\", { class: \"x\" }, \"hello\")`\n*\n* Generic on P so TypeScript validates props match the component's signature\n* at the call site, then stores the result in the loosely-typed VNode.\n*/\n/** Shared empty props sentinel — identity-checked in mountElement to skip applyProps. */\nconst EMPTY_PROPS = {};\nfunction h(type, props, ...children) {\n\treturn {\n\t\ttype,\n\t\tprops: props ?? EMPTY_PROPS,\n\t\tchildren: normalizeChildren(children),\n\t\tkey: props?.key ?? null\n\t};\n}\nfunction normalizeChildren(children) {\n\tfor (let i = 0; i < children.length; i++) if (Array.isArray(children[i])) return flattenChildren(children);\n\treturn children;\n}\nfunction flattenChildren(children) {\n\tconst result = [];\n\tfor (const child of children) if (Array.isArray(child)) result.push(...flattenChildren(child));\n\telse result.push(child);\n\treturn result;\n}\n\n//#endregion\n//#region src/jsx-runtime.ts\n/**\n* JSX automatic runtime.\n*\n* When tsconfig has `\"jsxImportSource\": \"@pyreon/core\"`, the TS/bundler compiler\n* rewrites JSX to imports from this file automatically:\n* <div class=\"x\" /> → jsx(\"div\", { class: \"x\" })\n*/\nfunction jsx(type, props, key) {\n\tconst { children, ...rest } = props;\n\tconst propsWithKey = key != null ? {\n\t\t...rest,\n\t\tkey\n\t} : rest;\n\tif (typeof type === \"function\") return h(type, children !== void 0 ? {\n\t\t...propsWithKey,\n\t\tchildren\n\t} : propsWithKey);\n\treturn h(type, propsWithKey, ...children === void 0 ? [] : Array.isArray(children) ? children : [children]);\n}\nconst jsxs = jsx;\n\n//#endregion\nexport { Fragment, jsx, jsxs };\n//# sourceMappingURL=jsx-runtime.js.map","import type { VNodeChild } from '@pyreon/core'\nimport type { BackgroundProps } from '../types'\n\n/**\n * Background pattern for the flow canvas.\n * Renders dots, lines, or cross patterns that move with the viewport.\n *\n * @example\n * ```tsx\n * <Flow instance={flow}>\n * <Background variant=\"dots\" gap={20} />\n * </Flow>\n * ```\n */\nexport function Background(props: BackgroundProps): VNodeChild {\n const { variant = 'dots', gap = 20, size = 1, color = '#ddd' } = props\n\n const patternId = `flow-bg-${variant}`\n\n if (variant === 'dots') {\n return (\n <svg\n role=\"img\"\n aria-label=\"background pattern\"\n class=\"pyreon-flow-background\"\n style=\"position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none;\"\n >\n <defs>\n <pattern\n id={patternId}\n x=\"0\"\n y=\"0\"\n width={String(gap)}\n height={String(gap)}\n {...{ patternUnits: 'userSpaceOnUse' }}\n >\n <circle cx={String(size)} cy={String(size)} r={String(size)} fill={color} />\n </pattern>\n </defs>\n <rect width=\"100%\" height=\"100%\" fill={`url(#${patternId})`} />\n </svg>\n )\n }\n\n if (variant === 'lines') {\n return (\n <svg\n role=\"img\"\n aria-label=\"background pattern\"\n class=\"pyreon-flow-background\"\n style=\"position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none;\"\n >\n <defs>\n <pattern\n id={patternId}\n x=\"0\"\n y=\"0\"\n width={String(gap)}\n height={String(gap)}\n {...{ patternUnits: 'userSpaceOnUse' }}\n >\n <line\n x1=\"0\"\n y1={String(gap)}\n x2={String(gap)}\n y2={String(gap)}\n stroke={color}\n stroke-width={String(size)}\n />\n <line\n x1={String(gap)}\n y1=\"0\"\n x2={String(gap)}\n y2={String(gap)}\n stroke={color}\n stroke-width={String(size)}\n />\n </pattern>\n </defs>\n <rect width=\"100%\" height=\"100%\" fill={`url(#${patternId})`} />\n </svg>\n )\n }\n\n // cross\n return (\n <svg\n role=\"img\"\n aria-label=\"background pattern\"\n class=\"pyreon-flow-background\"\n style=\"position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none;\"\n >\n <defs>\n <pattern\n id={patternId}\n x=\"0\"\n y=\"0\"\n width={String(gap)}\n height={String(gap)}\n {...{ patternUnits: 'userSpaceOnUse' }}\n >\n <line\n x1={String(gap / 2 - size * 2)}\n y1={String(gap / 2)}\n x2={String(gap / 2 + size * 2)}\n y2={String(gap / 2)}\n stroke={color}\n stroke-width={String(size)}\n />\n <line\n x1={String(gap / 2)}\n y1={String(gap / 2 - size * 2)}\n x2={String(gap / 2)}\n y2={String(gap / 2 + size * 2)}\n stroke={color}\n stroke-width={String(size)}\n />\n </pattern>\n </defs>\n <rect width=\"100%\" height=\"100%\" fill={`url(#${patternId})`} />\n </svg>\n )\n}\n","import type { VNodeChild } from '@pyreon/core'\nimport type { ControlsProps, FlowInstance } from '../types'\n\nconst positionStyles: Record<string, string> = {\n 'top-left': 'top: 10px; left: 10px;',\n 'top-right': 'top: 10px; right: 10px;',\n 'bottom-left': 'bottom: 10px; left: 10px;',\n 'bottom-right': 'bottom: 10px; right: 10px;',\n}\n\n// Simple SVG icons\nconst ZoomInIcon = () => (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n >\n <circle cx=\"7\" cy=\"7\" r=\"5\" />\n <line x1=\"7\" y1=\"5\" x2=\"7\" y2=\"9\" />\n <line x1=\"5\" y1=\"7\" x2=\"9\" y2=\"7\" />\n <line x1=\"11\" y1=\"11\" x2=\"14\" y2=\"14\" />\n </svg>\n)\n\nconst ZoomOutIcon = () => (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n >\n <circle cx=\"7\" cy=\"7\" r=\"5\" />\n <line x1=\"5\" y1=\"7\" x2=\"9\" y2=\"7\" />\n <line x1=\"11\" y1=\"11\" x2=\"14\" y2=\"14\" />\n </svg>\n)\n\nconst FitViewIcon = () => (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n >\n <rect x=\"2\" y=\"2\" width=\"12\" height=\"12\" rx=\"2\" />\n <line x1=\"2\" y1=\"6\" x2=\"14\" y2=\"6\" />\n <line x1=\"6\" y1=\"2\" x2=\"6\" y2=\"14\" />\n </svg>\n)\n\nconst LockIcon = () => (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n >\n <rect x=\"3\" y=\"7\" width=\"10\" height=\"7\" rx=\"1\" />\n <path d=\"M5 7V5a3 3 0 0 1 6 0v2\" />\n </svg>\n)\n\n/**\n * Zoom and viewport controls for the flow canvas.\n * Shows zoom in, zoom out, fit view, and optional lock button.\n *\n * @example\n * ```tsx\n * <Flow instance={flow}>\n * <Controls />\n * </Flow>\n * ```\n */\nexport function Controls(props: ControlsProps & { instance?: FlowInstance }): VNodeChild {\n const {\n showZoomIn = true,\n showZoomOut = true,\n showFitView = true,\n showLock = false,\n position = 'bottom-left',\n instance,\n } = props\n\n if (!instance) return null\n\n const baseStyle = `position: absolute; ${positionStyles[position] ?? positionStyles['bottom-left']} display: flex; flex-direction: column; gap: 2px; z-index: 5; background: white; border: 1px solid #ddd; border-radius: 6px; padding: 2px; box-shadow: 0 1px 4px rgba(0,0,0,0.08);`\n const btnStyle =\n 'width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; border: none; background: transparent; border-radius: 4px; cursor: pointer; color: #555; padding: 0;'\n\n return () => {\n const zoomPercent = Math.round(instance.zoom() * 100)\n\n return (\n <div class=\"pyreon-flow-controls\" style={baseStyle}>\n {showZoomIn && (\n <button type=\"button\" style={btnStyle} title=\"Zoom in\" onClick={() => instance.zoomIn()}>\n <ZoomInIcon />\n </button>\n )}\n {showZoomOut && (\n <button\n type=\"button\"\n style={btnStyle}\n title=\"Zoom out\"\n onClick={() => instance.zoomOut()}\n >\n <ZoomOutIcon />\n </button>\n )}\n {showFitView && (\n <button\n type=\"button\"\n style={btnStyle}\n title=\"Fit view\"\n onClick={() => instance.fitView()}\n >\n <FitViewIcon />\n </button>\n )}\n {showLock && (\n <button\n type=\"button\"\n style={btnStyle}\n title=\"Lock/unlock\"\n onClick={() => {\n // Toggle pan/zoom by updating config\n // This is a simple toggle — could be improved with state\n }}\n >\n <LockIcon />\n </button>\n )}\n <div\n style=\"font-size: 10px; text-align: center; color: #999; padding: 2px 0; user-select: none;\"\n title=\"Current zoom level\"\n >\n {zoomPercent}%\n </div>\n </div>\n )\n }\n}\n","import type { VNodeChild } from '@pyreon/core'\nimport type { Computed, Signal } from '@pyreon/reactivity'\n\n// ─── Position & Geometry ─────────────────────────────────────────────────────\n\nexport interface XYPosition {\n x: number\n y: number\n}\n\nexport interface Dimensions {\n width: number\n height: number\n}\n\nexport interface Rect extends XYPosition, Dimensions {}\n\n// ─── Viewport ────────────────────────────────────────────────────────────────\n\nexport interface Viewport {\n x: number\n y: number\n zoom: number\n}\n\n// ─── Handle ──────────────────────────────────────────────────────────────────\n\nexport type HandleType = 'source' | 'target'\n\nexport enum Position {\n Top = 'top',\n Right = 'right',\n Bottom = 'bottom',\n Left = 'left',\n}\n\nexport interface HandleConfig {\n id?: string\n type: HandleType\n position: Position\n}\n\n// ─── Node ────────────────────────────────────────────────────────────────────\n\nexport interface FlowNode<TData = Record<string, unknown>> {\n id: string\n type?: string\n position: XYPosition\n data: TData\n width?: number\n height?: number\n /** Whether the node can be dragged */\n draggable?: boolean\n /** Whether the node can be selected */\n selectable?: boolean\n /** Whether the node can be connected to */\n connectable?: boolean\n /** Custom class name */\n class?: string\n /** Custom style */\n style?: string\n /** Source handles */\n sourceHandles?: HandleConfig[]\n /** Target handles */\n targetHandles?: HandleConfig[]\n /** Parent node id for grouping */\n parentId?: string\n /** Whether this node is a group */\n group?: boolean\n}\n\n// ─── Edge ────────────────────────────────────────────────────────────────────\n\nexport type EdgeType = 'bezier' | 'smoothstep' | 'straight' | 'step'\n\nexport interface FlowEdge {\n id?: string\n source: string\n target: string\n sourceHandle?: string\n targetHandle?: string\n type?: EdgeType\n label?: string\n animated?: boolean\n class?: string\n style?: string\n /** Custom data attached to the edge */\n data?: Record<string, unknown>\n /** Waypoints — intermediate points the edge passes through */\n waypoints?: XYPosition[]\n}\n\n// ─── Connection ──────────────────────────────────────────────────────────────\n\nexport interface Connection {\n source: string\n target: string\n sourceHandle?: string\n targetHandle?: string\n}\n\nexport type ConnectionRule = Record<string, { outputs: string[] }>\n\n// ─── Node Change Events ──────────────────────────────────────────────────────\n\nexport type NodeChange =\n | { type: 'position'; id: string; position: XYPosition }\n | { type: 'dimensions'; id: string; dimensions: Dimensions }\n | { type: 'select'; id: string; selected: boolean }\n | { type: 'remove'; id: string }\n\n// ─── Edge path result ────────────────────────────────────────────────────────\n\nexport interface EdgePathResult {\n path: string\n labelX: number\n labelY: number\n}\n\n// ─── Flow config ─────────────────────────────────────────────────────────────\n\nexport interface FlowConfig {\n nodes?: FlowNode[]\n edges?: FlowEdge[]\n /** Default edge type */\n defaultEdgeType?: EdgeType\n /** Min zoom level — default: 0.1 */\n minZoom?: number\n /** Max zoom level — default: 4 */\n maxZoom?: number\n /** Snap to grid */\n snapToGrid?: boolean\n /** Grid size for snapping — default: 15 */\n snapGrid?: number\n /** Connection rules — which node types can connect */\n connectionRules?: ConnectionRule\n /** Whether nodes are draggable by default — default: true */\n nodesDraggable?: boolean\n /** Whether nodes are connectable by default — default: true */\n nodesConnectable?: boolean\n /** Whether nodes are selectable by default — default: true */\n nodesSelectable?: boolean\n /** Whether to allow multi-selection — default: true */\n multiSelect?: boolean\n /** Drag boundaries for nodes — [[minX, minY], [maxX, maxY]] */\n nodeExtent?: [[number, number], [number, number]]\n /** Whether panning is enabled — default: true */\n pannable?: boolean\n /** Whether zooming is enabled — default: true */\n zoomable?: boolean\n /** Fit view on initial render — default: false */\n fitView?: boolean\n /** Padding for fitView — default: 0.1 */\n fitViewPadding?: number\n}\n\n// ─── Flow instance ───────────────────────────────────────────────────────────\n\nexport interface FlowInstance {\n // ── State (signals) ──────────────────────────────────────────────────────\n\n /** All nodes — reactive */\n nodes: Signal<FlowNode[]>\n /** All edges — reactive */\n edges: Signal<FlowEdge[]>\n /** Viewport state — reactive */\n viewport: Signal<Viewport>\n /** Current zoom level — computed */\n zoom: Computed<number>\n /** Selected node ids — computed */\n selectedNodes: Computed<string[]>\n /** Selected edge ids — computed */\n selectedEdges: Computed<string[]>\n /** Container dimensions — updated by the Flow component via ResizeObserver */\n containerSize: Signal<{ width: number; height: number }>\n\n // ── Node operations ──────────────────────────────────────────────────────\n\n /** Get a single node by id */\n getNode: (id: string) => FlowNode | undefined\n /** Add a node */\n addNode: (node: FlowNode) => void\n /** Remove a node and its connected edges */\n removeNode: (id: string) => void\n /** Update a node's properties */\n updateNode: (id: string, update: Partial<FlowNode>) => void\n /** Update a node's position */\n updateNodePosition: (id: string, position: XYPosition) => void\n\n // ── Edge operations ──────────────────────────────────────────────────────\n\n /** Get a single edge by id */\n getEdge: (id: string) => FlowEdge | undefined\n /** Add an edge */\n addEdge: (edge: FlowEdge) => void\n /** Remove an edge */\n removeEdge: (id: string) => void\n /** Check if a connection is valid (based on rules) */\n isValidConnection: (connection: Connection) => boolean\n\n // ── Selection ────────────────────────────────────────────────────────────\n\n /** Select a node */\n selectNode: (id: string, additive?: boolean) => void\n /** Deselect a node */\n deselectNode: (id: string) => void\n /** Select an edge */\n selectEdge: (id: string, additive?: boolean) => void\n /** Clear all selection */\n clearSelection: () => void\n /** Select all nodes */\n selectAll: () => void\n /** Delete selected nodes/edges */\n deleteSelected: () => void\n\n // ── Viewport ─────────────────────────────────────────────────────────────\n\n /** Fit view to show all nodes */\n fitView: (nodeIds?: string[], padding?: number) => void\n /** Set zoom level */\n zoomTo: (zoom: number) => void\n /** Zoom in */\n zoomIn: () => void\n /** Zoom out */\n zoomOut: () => void\n /** Pan to position */\n panTo: (position: XYPosition) => void\n /** Check if a node is visible in the current viewport */\n isNodeVisible: (id: string) => boolean\n\n // ── Layout ───────────────────────────────────────────────────────────────\n\n /** Apply auto-layout using elkjs */\n layout: (algorithm?: LayoutAlgorithm, options?: LayoutOptions) => Promise<void>\n\n // ── Batch ────────────────────────────────────────────────────────────────\n\n /** Batch multiple operations */\n batch: (fn: () => void) => void\n\n // ── Graph queries ────────────────────────────────────────────────────────\n\n /** Get edges connected to a node */\n getConnectedEdges: (nodeId: string) => FlowEdge[]\n /** Get incoming edges for a node */\n getIncomers: (nodeId: string) => FlowNode[]\n /** Get outgoing edges from a node */\n getOutgoers: (nodeId: string) => FlowNode[]\n\n // ── Listeners ────────────────────────────────────────────────────────────\n\n /** Called when a connection is made */\n onConnect: (callback: (connection: Connection) => void) => () => void\n /** Called when nodes change */\n onNodesChange: (callback: (changes: NodeChange[]) => void) => () => void\n /** Called when a node is clicked */\n onNodeClick: (callback: (node: FlowNode) => void) => () => void\n /** Called when an edge is clicked */\n onEdgeClick: (callback: (edge: FlowEdge) => void) => () => void\n /** Called when a node starts being dragged */\n onNodeDragStart: (callback: (node: FlowNode) => void) => () => void\n /** Called when a node stops being dragged */\n onNodeDragEnd: (callback: (node: FlowNode) => void) => () => void\n /** Called when a node is double-clicked */\n onNodeDoubleClick: (callback: (node: FlowNode) => void) => () => void\n\n // ── Copy / Paste ─────────────────────────────────────────────────────────\n\n /** Copy selected nodes and their edges to clipboard */\n copySelected: () => void\n /** Paste clipboard contents with offset */\n paste: (offset?: XYPosition) => void\n\n // ── Undo / Redo ─────────────────────────────────────────────────────────\n\n /** Save current state to undo history */\n pushHistory: () => void\n /** Undo last change */\n undo: () => void\n /** Redo last undone change */\n redo: () => void\n\n // ── Multi-node drag ─────────────────────────────────────────────────────\n\n /** Move all selected nodes by dx/dy */\n moveSelectedNodes: (dx: number, dy: number) => void\n\n // ── Helper lines ────────────────────────────────────────────────────────\n\n /** Get snap guide lines for a dragged node */\n getSnapLines: (\n dragNodeId: string,\n position: XYPosition,\n threshold?: number,\n ) => { x: number | null; y: number | null; snappedPosition: XYPosition }\n\n // ── Sub-flows / Groups ───────────────────────────────────────────────────\n\n /** Get child nodes of a group node */\n getChildNodes: (parentId: string) => FlowNode[]\n /** Get absolute position of a node (accounting for parent offsets) */\n getAbsolutePosition: (nodeId: string) => XYPosition\n\n // ── Edge reconnecting ──────────────────────────────────────────────────\n\n // ── Edge waypoints ──────────────────────────────────────────────────────\n\n /** Add a waypoint (bend point) to an edge */\n addEdgeWaypoint: (edgeId: string, point: XYPosition, index?: number) => void\n /** Remove a waypoint from an edge */\n removeEdgeWaypoint: (edgeId: string, index: number) => void\n /** Update a waypoint position */\n updateEdgeWaypoint: (edgeId: string, index: number, point: XYPosition) => void\n\n // ── Edge reconnecting ──────────────────────────────────────────────────\n\n /** Reconnect an edge to a new source/target */\n reconnectEdge: (\n edgeId: string,\n newConnection: {\n source?: string\n target?: string\n sourceHandle?: string\n targetHandle?: string\n },\n ) => void\n\n // ── Proximity connect ────────────────────────────────────────────────────\n\n /** Find the nearest unconnected node within threshold distance */\n getProximityConnection: (nodeId: string, threshold?: number) => Connection | null\n\n // ── Collision detection ─────────────────────────────────────────────────\n\n /** Get nodes that overlap with the given node */\n getOverlappingNodes: (nodeId: string) => FlowNode[]\n /** Push overlapping nodes apart */\n resolveCollisions: (nodeId: string, spacing?: number) => void\n\n // ── Node extent ─────────────────────────────────────────────────────────\n\n /** Set drag boundaries for all nodes — [[minX, minY], [maxX, maxY]] or null to remove */\n setNodeExtent: (extent: [[number, number], [number, number]] | null) => void\n /** Clamp a position to the current node extent */\n clampToExtent: (position: XYPosition, nodeWidth?: number, nodeHeight?: number) => XYPosition\n\n // ── Search / Filter ─────────────────────────────────────────────────────\n\n /** Find nodes matching a predicate */\n findNodes: (predicate: (node: FlowNode) => boolean) => FlowNode[]\n /** Find nodes by label text (case-insensitive) */\n searchNodes: (query: string) => FlowNode[]\n /** Focus viewport on a specific node (pan + optional zoom) */\n focusNode: (nodeId: string, zoom?: number) => void\n\n // ── Export ─────────────────────────────────────────────────────────────\n\n /** Export the flow as a JSON-serializable object */\n toJSON: () => { nodes: FlowNode[]; edges: FlowEdge[]; viewport: Viewport }\n /** Import flow state from a JSON object */\n fromJSON: (data: { nodes: FlowNode[]; edges: FlowEdge[]; viewport?: Viewport }) => void\n\n // ── Viewport animation ─────────────────────────────────────────────────\n\n /** Animate viewport to a new position/zoom */\n animateViewport: (target: Partial<Viewport>, duration?: number) => void\n\n // ── Internal emitters (used by Flow component) ──────────────────────────\n\n /** @internal */\n _emit: {\n nodeDragStart: (node: FlowNode) => void\n nodeDragEnd: (node: FlowNode) => void\n nodeDoubleClick: (node: FlowNode) => void\n nodeClick: (node: FlowNode) => void\n edgeClick: (edge: FlowEdge) => void\n }\n\n // ── Config ───────────────────────────────────────────────────────────────\n\n /** The flow configuration */\n config: FlowConfig\n\n // ── Cleanup ──────────────────────────────────────────────────────────────\n\n /** Dispose all listeners and clean up */\n dispose: () => void\n}\n\n// ─── Layout ──────────────────────────────────────────────────────────────────\n\nexport type LayoutAlgorithm =\n | 'layered'\n | 'force'\n | 'stress'\n | 'tree'\n | 'radial'\n | 'box'\n | 'rectpacking'\n\nexport interface LayoutOptions {\n /** Layout direction — default: 'DOWN' */\n direction?: 'UP' | 'DOWN' | 'LEFT' | 'RIGHT'\n /** Spacing between nodes — default: 50 */\n nodeSpacing?: number\n /** Spacing between layers — default: 80 */\n layerSpacing?: number\n /** Edge routing — default: 'orthogonal' */\n edgeRouting?: 'orthogonal' | 'splines' | 'polyline'\n /** Whether to animate the layout transition — default: true */\n animate?: boolean\n /** Animation duration in ms — default: 300 */\n animationDuration?: number\n}\n\n// ─── Component props ─────────────────────────────────────────────────────────\n\nexport interface FlowProps {\n instance: FlowInstance\n style?: string\n class?: string\n children?: VNodeChild\n}\n\nexport interface BackgroundProps {\n variant?: 'dots' | 'lines' | 'cross'\n gap?: number\n size?: number\n color?: string\n}\n\nexport interface MiniMapProps {\n style?: string\n class?: string\n nodeColor?: string | ((node: FlowNode) => string)\n maskColor?: string\n width?: number\n height?: number\n}\n\nexport interface ControlsProps {\n showZoomIn?: boolean\n showZoomOut?: boolean\n showFitView?: boolean\n showLock?: boolean\n position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'\n}\n\nexport interface PanelProps {\n position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'\n style?: string\n class?: string\n children?: VNodeChild\n}\n\nexport interface HandleProps {\n type: HandleType\n position: Position\n id?: string\n style?: string\n class?: string\n}\n\nexport type NodeComponentProps<TData = Record<string, unknown>> = {\n id: string\n data: TData\n selected: boolean\n dragging: boolean\n}\n","import type { EdgePathResult, FlowNode, XYPosition } from './types'\nimport { Position } from './types'\n\n/**\n * Auto-detect the best handle position based on relative node positions.\n * If the node has configured handles, uses those. Otherwise picks the\n * closest edge (top/right/bottom/left) based on direction to the other node.\n */\nexport function getSmartHandlePositions(\n sourceNode: FlowNode,\n targetNode: FlowNode,\n): { sourcePosition: Position; targetPosition: Position } {\n const sw = sourceNode.width ?? 150\n const sh = sourceNode.height ?? 40\n const tw = targetNode.width ?? 150\n const th = targetNode.height ?? 40\n\n const dx = targetNode.position.x + tw / 2 - (sourceNode.position.x + sw / 2)\n const dy = targetNode.position.y + th / 2 - (sourceNode.position.y + sh / 2)\n\n const sourceHandle = sourceNode.sourceHandles?.[0]\n const targetHandle = targetNode.targetHandles?.[0]\n\n const sourcePosition = sourceHandle\n ? sourceHandle.position\n : Math.abs(dx) > Math.abs(dy)\n ? dx > 0\n ? Position.Right\n : Position.Left\n : dy > 0\n ? Position.Bottom\n : Position.Top\n\n const targetPosition = targetHandle\n ? targetHandle.position\n : Math.abs(dx) > Math.abs(dy)\n ? dx > 0\n ? Position.Left\n : Position.Right\n : dy > 0\n ? Position.Top\n : Position.Bottom\n\n return { sourcePosition, targetPosition }\n}\n\n/**\n * Get the center point between source and target positions.\n */\nfunction getCenter(source: XYPosition, target: XYPosition): XYPosition {\n return {\n x: (source.x + target.x) / 2,\n y: (source.y + target.y) / 2,\n }\n}\n\n/**\n * Get the handle position offset for a given position (top/right/bottom/left).\n */\nexport function getHandlePosition(\n position: Position,\n nodeX: number,\n nodeY: number,\n nodeWidth: number,\n nodeHeight: number,\n _handleId?: string,\n): XYPosition {\n switch (position) {\n case Position.Top:\n return { x: nodeX + nodeWidth / 2, y: nodeY }\n case Position.Right:\n return { x: nodeX + nodeWidth, y: nodeY + nodeHeight / 2 }\n case Position.Bottom:\n return { x: nodeX + nodeWidth / 2, y: nodeY + nodeHeight }\n case Position.Left:\n return { x: nodeX, y: nodeY + nodeHeight / 2 }\n }\n}\n\n/**\n * Calculate a cubic bezier edge path between two points.\n *\n * @example\n * ```ts\n * const { path, labelX, labelY } = getBezierPath({\n * sourceX: 0, sourceY: 0, sourcePosition: Position.Right,\n * targetX: 200, targetY: 100, targetPosition: Position.Left,\n * })\n * // path = \"M0,0 C100,0 100,100 200,100\"\n * ```\n */\nexport function getBezierPath(params: {\n sourceX: number\n sourceY: number\n sourcePosition?: Position\n targetX: number\n targetY: number\n targetPosition?: Position\n curvature?: number\n}): EdgePathResult {\n const {\n sourceX,\n sourceY,\n sourcePosition = Position.Bottom,\n targetX,\n targetY,\n targetPosition = Position.Top,\n curvature = 0.25,\n } = params\n\n const distX = Math.abs(targetX - sourceX)\n const distY = Math.abs(targetY - sourceY)\n const dist = Math.sqrt(distX * distX + distY * distY)\n const offset = dist * curvature\n\n let sourceControlX = sourceX\n let sourceControlY = sourceY\n let targetControlX = targetX\n let targetControlY = targetY\n\n switch (sourcePosition) {\n case Position.Top:\n sourceControlY = sourceY - offset\n break\n case Position.Bottom:\n sourceControlY = sourceY + offset\n break\n case Position.Left:\n sourceControlX = sourceX - offset\n break\n case Position.Right:\n sourceControlX = sourceX + offset\n break\n }\n\n switch (targetPosition) {\n case Position.Top:\n targetControlY = targetY - offset\n break\n case Position.Bottom:\n targetControlY = targetY + offset\n break\n case Position.Left:\n targetControlX = targetX - offset\n break\n case Position.Right:\n targetControlX = targetX + offset\n break\n }\n\n const center = getCenter({ x: sourceX, y: sourceY }, { x: targetX, y: targetY })\n\n return {\n path: `M${sourceX},${sourceY} C${sourceControlX},${sourceControlY} ${targetControlX},${targetControlY} ${targetX},${targetY}`,\n labelX: center.x,\n labelY: center.y,\n }\n}\n\n/**\n * Calculate a smoothstep edge path — horizontal/vertical segments with rounded corners.\n */\nexport function getSmoothStepPath(params: {\n sourceX: number\n sourceY: number\n sourcePosition?: Position\n targetX: number\n targetY: number\n targetPosition?: Position\n borderRadius?: number\n offset?: number\n}): EdgePathResult {\n const {\n sourceX,\n sourceY,\n sourcePosition = Position.Bottom,\n targetX,\n targetY,\n targetPosition = Position.Top,\n borderRadius = 5,\n offset = 20,\n } = params\n\n const isHorizontalSource = sourcePosition === Position.Left || sourcePosition === Position.Right\n const isHorizontalTarget = targetPosition === Position.Left || targetPosition === Position.Right\n\n // Calculate offset points\n const sourceOffsetX =\n sourcePosition === Position.Right ? offset : sourcePosition === Position.Left ? -offset : 0\n const sourceOffsetY =\n sourcePosition === Position.Bottom ? offset : sourcePosition === Position.Top ? -offset : 0\n const targetOffsetX =\n targetPosition === Position.Right ? offset : targetPosition === Position.Left ? -offset : 0\n const targetOffsetY =\n targetPosition === Position.Bottom ? offset : targetPosition === Position.Top ? -offset : 0\n\n const sX = sourceX + sourceOffsetX\n const sY = sourceY + sourceOffsetY\n const tX = targetX + targetOffsetX\n const tY = targetY + targetOffsetY\n\n const center = getCenter({ x: sourceX, y: sourceY }, { x: targetX, y: targetY })\n\n // Simple smoothstep: source → midpoint → target with rounded corners\n const midX = (sX + tX) / 2\n const midY = (sY + tY) / 2\n const r = borderRadius\n\n let path: string\n\n if (isHorizontalSource && !isHorizontalTarget) {\n // Horizontal source → vertical target\n const cornerY = tY\n path = `M${sourceX},${sourceY} L${sX},${sY} L${sX},${cornerY > sY ? cornerY - r : cornerY + r} Q${sX},${cornerY} ${sX + (tX > sX ? r : -r)},${cornerY} L${tX},${cornerY} L${targetX},${targetY}`\n } else if (!isHorizontalSource && isHorizontalTarget) {\n // Vertical source → horizontal target\n const cornerX = tX\n path = `M${sourceX},${sourceY} L${sX},${sY} L${cornerX > sX ? cornerX - r : cornerX + r},${sY} Q${cornerX},${sY} ${cornerX},${sY + (tY > sY ? r : -r)} L${cornerX},${tY} L${targetX},${targetY}`\n } else if (isHorizontalSource && isHorizontalTarget) {\n // Both horizontal — go through middle Y\n path = `M${sourceX},${sourceY} L${sX},${sourceY} L${midX},${sourceY} Q${midX},${sourceY} ${midX},${midY} L${midX},${targetY} L${tX},${targetY} L${targetX},${targetY}`\n } else {\n // Both vertical — go through middle X\n path = `M${sourceX},${sourceY} L${sourceX},${sY} L${sourceX},${midY} Q${sourceX},${midY} ${midX},${midY} L${targetX},${midY} L${targetX},${tY} L${targetX},${targetY}`\n }\n\n return { path, labelX: center.x, labelY: center.y }\n}\n\n/**\n * Calculate a straight edge path — direct line between two points.\n */\nexport function getStraightPath(params: {\n sourceX: number\n sourceY: number\n targetX: number\n targetY: number\n}): EdgePathResult {\n const { sourceX, sourceY, targetX, targetY } = params\n const center = getCenter({ x: sourceX, y: sourceY }, { x: targetX, y: targetY })\n\n return {\n path: `M${sourceX},${sourceY} L${targetX},${targetY}`,\n labelX: center.x,\n labelY: center.y,\n }\n}\n\n/**\n * Calculate a step edge path — right-angle segments with no rounding.\n */\nexport function getStepPath(params: {\n sourceX: number\n sourceY: number\n sourcePosition?: Position\n targetX: number\n targetY: number\n targetPosition?: Position\n}): EdgePathResult {\n return getSmoothStepPath({ ...params, borderRadius: 0 })\n}\n\n/**\n * Calculate an edge path that passes through waypoints.\n * Uses line segments with optional smoothing.\n */\nexport function getWaypointPath(params: {\n sourceX: number\n sourceY: number\n targetX: number\n targetY: number\n waypoints: XYPosition[]\n}): EdgePathResult {\n const { sourceX, sourceY, targetX, targetY, waypoints } = params\n\n if (waypoints.length === 0) {\n return getStraightPath({ sourceX, sourceY, targetX, targetY })\n }\n\n const allPoints = [{ x: sourceX, y: sourceY }, ...waypoints, { x: targetX, y: targetY }]\n\n const segments = allPoints.map((p) => `${p.x},${p.y}`)\n const path = `M${segments.join(' L')}`\n\n // Label at the middle waypoint\n const midIdx = Math.floor(waypoints.length / 2)\n const midPoint = waypoints[midIdx] ?? {\n x: (sourceX + targetX) / 2,\n y: (sourceY + targetY) / 2,\n }\n\n return { path, labelX: midPoint.x, labelY: midPoint.y }\n}\n\n/**\n * Get the edge path for a given edge type.\n */\nexport function getEdgePath(\n type: string,\n sourceX: number,\n sourceY: number,\n sourcePosition: Position,\n targetX: number,\n targetY: number,\n targetPosition: Position,\n): EdgePathResult {\n switch (type) {\n case 'smoothstep':\n return getSmoothStepPath({\n sourceX,\n sourceY,\n sourcePosition,\n targetX,\n targetY,\n targetPosition,\n })\n case 'straight':\n return getStraightPath({ sourceX, sourceY, targetX, targetY })\n case 'step':\n return getStepPath({\n sourceX,\n sourceY,\n sourcePosition,\n targetX,\n targetY,\n targetPosition,\n })\n default:\n return getBezierPath({\n sourceX,\n sourceY,\n sourcePosition,\n targetX,\n targetY,\n targetPosition,\n })\n }\n}\n","import type { VNodeChild } from '@pyreon/core'\nimport { signal } from '@pyreon/reactivity'\nimport { getEdgePath, getHandlePosition, getSmartHandlePositions, getWaypointPath } from '../edges'\nimport type { Connection, FlowInstance, FlowNode, NodeComponentProps } from '../types'\nimport { Position } from '../types'\n\n// ─── Node type registry ──────────────────────────────────────────────────────\n\ntype NodeTypeMap = Record<string, (props: NodeComponentProps<any>) => VNodeChild>\n\n/**\n * Default node renderer — simple labeled box.\n */\nfunction DefaultNode(props: NodeComponentProps) {\n const borderColor = props.selected ? '#3b82f6' : '#ddd'\n const cursor = props.dragging ? 'grabbing' : 'grab'\n return (\n <div\n style={`padding: 8px 16px; background: white; border: 2px solid ${borderColor}; border-radius: 6px; font-size: 13px; min-width: 80px; text-align: center; cursor: ${cursor}; user-select: none;`}\n >\n {(props.data?.label as string) ?? props.id}\n </div>\n )\n}\n\n// ─── Connection line state ───────────────────────────────────────────────────\n\ninterface ConnectionState {\n active: boolean\n sourceNodeId: string\n sourceHandleId: string\n sourcePosition: Position\n sourceX: number\n sourceY: number\n currentX: number\n currentY: number\n}\n\nconst emptyConnection: ConnectionState = {\n active: false,\n sourceNodeId: '',\n sourceHandleId: '',\n sourcePosition: Position.Right,\n sourceX: 0,\n sourceY: 0,\n currentX: 0,\n currentY: 0,\n}\n\n// ─── Selection box state ─────────────────────────────────────────────────────\n\ninterface SelectionBoxState {\n active: boolean\n startX: number\n startY: number\n currentX: number\n currentY: number\n}\n\nconst emptySelectionBox: SelectionBoxState = {\n active: false,\n startX: 0,\n startY: 0,\n currentX: 0,\n currentY: 0,\n}\n\n// ─── Drag state ──────────────────────────────────────────────────────────────\n\ninterface DragState {\n active: boolean\n nodeId: string\n startX: number\n startY: number\n /** Starting positions of all nodes being dragged (for multi-drag) */\n startPositions: Map<string, { x: number; y: number }>\n}\n\nconst emptyDrag: DragState = {\n active: false,\n nodeId: '',\n startX: 0,\n startY: 0,\n startPositions: new Map(),\n}\n\n// ─── Edge Layer ──────────────────────────────────────────────────────────────\n\nfunction EdgeLayer(props: {\n instance: FlowInstance\n connectionState: () => ConnectionState\n edgeTypes?: EdgeTypeMap\n}): VNodeChild {\n const { instance, connectionState, edgeTypes } = props\n\n return () => {\n const nodes = instance.nodes()\n const edges = instance.edges()\n const nodeMap = new Map(nodes.map((n) => [n.id, n]))\n const conn = connectionState()\n\n return (\n <svg\n role=\"img\"\n aria-label=\"flow edges\"\n class=\"pyreon-flow-edges\"\n style=\"position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; overflow: visible;\"\n >\n <defs>\n <marker\n id=\"flow-arrowhead\"\n {...{\n markerWidth: '10',\n markerHeight: '7',\n refX: '10',\n refY: '3.5',\n orient: 'auto',\n }}\n >\n <polygon points=\"0 0, 10 3.5, 0 7\" fill=\"#999\" />\n </marker>\n </defs>\n {edges.map((edge) => {\n const sourceNode = nodeMap.get(edge.source)\n const targetNode = nodeMap.get(edge.target)\n if (!sourceNode || !targetNode) return <g key={edge.id} />\n\n const sourceW = sourceNode.width ?? 150\n const sourceH = sourceNode.height ?? 40\n const targetW = targetNode.width ?? 150\n const targetH = targetNode.height ?? 40\n\n const { sourcePosition, targetPosition } = getSmartHandlePositions(sourceNode, targetNode)\n\n const sourcePos = getHandlePosition(\n sourcePosition,\n sourceNode.position.x,\n sourceNode.position.y,\n sourceW,\n sourceH,\n )\n const targetPos = getHandlePosition(\n targetPosition,\n targetNode.position.x,\n targetNode.position.y,\n targetW,\n targetH,\n )\n\n const { path, labelX, labelY } = edge.waypoints?.length\n ? getWaypointPath({\n sourceX: sourcePos.x,\n sourceY: sourcePos.y,\n targetX: targetPos.x,\n targetY: targetPos.y,\n waypoints: edge.waypoints,\n })\n : getEdgePath(\n edge.type ?? 'bezier',\n sourcePos.x,\n sourcePos.y,\n sourcePosition,\n targetPos.x,\n targetPos.y,\n targetPosition,\n )\n\n const selectedEdges = instance.selectedEdges()\n const isSelected = edge.id ? selectedEdges.includes(edge.id) : false\n\n // Custom edge renderer\n const CustomEdge = edge.type && edgeTypes?.[edge.type]\n if (CustomEdge) {\n return (\n <g key={edge.id} onClick={() => edge.id && instance.selectEdge(edge.id)}>\n <CustomEdge\n edge={edge}\n sourceX={sourcePos.x}\n sourceY={sourcePos.y}\n targetX={targetPos.x}\n targetY={targetPos.y}\n selected={isSelected}\n />\n </g>\n )\n }\n\n return (\n <g key={edge.id}>\n <path\n d={path}\n fill=\"none\"\n stroke={isSelected ? '#3b82f6' : '#999'}\n stroke-width={isSelected ? '2' : '1.5'}\n marker-end=\"url(#flow-arrowhead)\"\n class={edge.animated ? 'pyreon-flow-edge-animated' : ''}\n style={`pointer-events: stroke; cursor: pointer; ${edge.style ?? ''}`}\n onClick={() => {\n if (edge.id) instance.selectEdge(edge.id)\n instance._emit.edgeClick(edge)\n }}\n />\n {edge.label && (\n <text\n x={String(labelX)}\n y={String(labelY)}\n text-anchor=\"middle\"\n dominant-baseline=\"central\"\n style=\"font-size: 11px; fill: #666; pointer-events: none;\"\n >\n {edge.label}\n </text>\n )}\n </g>\n )\n })}\n {conn.active && (\n <path\n d={\n getEdgePath(\n 'bezier',\n conn.sourceX,\n conn.sourceY,\n conn.sourcePosition,\n conn.currentX,\n conn.currentY,\n Position.Left,\n ).path\n }\n fill=\"none\"\n stroke=\"#3b82f6\"\n stroke-width=\"2\"\n stroke-dasharray=\"5,5\"\n />\n )}\n </svg>\n )\n }\n}\n\n// ─── Node Layer ──────────────────────────────────────────────────────────────\n\nfunction NodeLayer(props: {\n instance: FlowInstance\n nodeTypes: NodeTypeMap\n draggingNodeId: () => string\n onNodePointerDown: (e: PointerEvent, node: FlowNode) => void\n onHandlePointerDown: (\n e: PointerEvent,\n nodeId: string,\n handleType: string,\n handleId: string,\n position: Position,\n ) => void\n}): VNodeChild {\n const { instance, nodeTypes, draggingNodeId, onNodePointerDown, onHandlePointerDown } = props\n\n return () => {\n const nodes = instance.nodes()\n const selectedIds = instance.selectedNodes()\n const dragId = draggingNodeId()\n\n return (\n <>\n {nodes.map((node) => {\n const isSelected = selectedIds.includes(node.id)\n const isDragging = dragId === node.id\n const NodeComponent = (node.type && nodeTypes[node.type]) || nodeTypes.default!\n\n return (\n <div\n key={node.id}\n class={`pyreon-flow-node ${node.class ?? ''} ${isSelected ? 'selected' : ''} ${isDragging ? 'dragging' : ''}`}\n style={`position: absolute; transform: translate(${node.position.x}px, ${node.position.y}px); z-index: ${isDragging ? 1000 : isSelected ? 100 : 0}; ${node.style ?? ''}`}\n data-nodeid={node.id}\n onClick={(e: MouseEvent) => {\n e.stopPropagation()\n instance.selectNode(node.id, e.shiftKey)\n instance._emit.nodeClick(node)\n }}\n onDblClick={(e: MouseEvent) => {\n e.stopPropagation()\n instance._emit.nodeDoubleClick(node)\n }}\n onPointerDown={(e: PointerEvent) => {\n // Check if clicking a handle\n const target = e.target as HTMLElement\n const handle = target.closest('.pyreon-flow-handle')\n if (handle) {\n const hType = handle.getAttribute('data-handletype') ?? 'source'\n const hId = handle.getAttribute('data-handleid') ?? 'source'\n const hPos =\n (handle.getAttribute('data-handleposition') as Position) ?? Position.Right\n onHandlePointerDown(e, node.id, hType, hId, hPos)\n return\n }\n // Otherwise start dragging node\n if (node.draggable !== false && instance.config.nodesDraggable !== false) {\n onNodePointerDown(e, node)\n }\n }}\n >\n <NodeComponent\n id={node.id}\n data={node.data}\n selected={isSelected}\n dragging={isDragging}\n />\n </div>\n )\n })}\n </>\n )\n }\n}\n\n// ─── Flow Component ──────────────────────────────────────────────────────────\n\ntype EdgeTypeMap = Record<\n string,\n (props: {\n edge: import('../types').FlowEdge\n sourceX: number\n sourceY: number\n targetX: number\n targetY: number\n selected: boolean\n }) => VNodeChild\n>\n\nexport interface FlowComponentProps {\n instance: FlowInstance\n /** Custom node type renderers */\n nodeTypes?: NodeTypeMap\n /** Custom edge type renderers */\n edgeTypes?: EdgeTypeMap\n style?: string\n class?: string\n children?: VNodeChild\n}\n\n/**\n * The main Flow component — renders the interactive flow diagram.\n *\n * Supports node dragging, connection drawing, custom node types,\n * pan/zoom, and all standard flow interactions.\n *\n * @example\n * ```tsx\n * const flow = createFlow({\n * nodes: [...],\n * edges: [...],\n * })\n *\n * <Flow instance={flow} nodeTypes={{ custom: CustomNode }}>\n * <Background />\n * <MiniMap />\n * <Controls />\n * </Flow>\n * ```\n */\nexport function Flow(props: FlowComponentProps): VNodeChild {\n const { instance, children, edgeTypes } = props\n const nodeTypes: NodeTypeMap = {\n default: DefaultNode,\n input: DefaultNode,\n output: DefaultNode,\n ...props.nodeTypes,\n }\n\n // ── Drag state ─────────────────────────────────────────────────────────\n\n const dragState = signal<DragState>({ ...emptyDrag })\n const connectionState = signal<ConnectionState>({ ...emptyConnection })\n const selectionBox = signal<SelectionBoxState>({ ...emptySelectionBox })\n const helperLines = signal<{ x: number | null; y: number | null }>({\n x: null,\n y: null,\n })\n\n const draggingNodeId = () => (dragState().active ? dragState().nodeId : '')\n\n // ── Node dragging ──────────────────────────────────────────────────────\n\n const handleNodePointerDown = (e: PointerEvent, node: FlowNode) => {\n e.stopPropagation()\n\n // Capture starting positions of all selected nodes (for multi-drag)\n const selected = instance.selectedNodes()\n const startPositions = new Map<string, { x: number; y: number }>()\n\n // Always include the dragged node\n startPositions.set(node.id, { ...node.position })\n\n // Include other selected nodes if this node is part of selection\n if (selected.includes(node.id)) {\n for (const nid of selected) {\n if (nid === node.id) continue\n const n = instance.getNode(nid)\n if (n) startPositions.set(nid, { ...n.position })\n }\n }\n\n // Save undo state before drag\n instance.pushHistory()\n\n dragState.set({\n active: true,\n nodeId: node.id,\n startX: e.clientX,\n startY: e.clientY,\n startPositions,\n })\n\n instance.selectNode(node.id, e.shiftKey)\n\n instance._emit.nodeDragStart(node)\n\n const container = (e.currentTarget as HTMLElement).closest('.pyreon-flow') as HTMLElement\n if (container) container.setPointerCapture(e.pointerId)\n }\n\n // ── Connection drawing ─────────────────────────────────────────────────\n\n const handleHandlePointerDown = (\n e: PointerEvent,\n nodeId: string,\n _handleType: string,\n handleId: string,\n position: Position,\n ) => {\n e.stopPropagation()\n e.preventDefault()\n\n const node = instance.getNode(nodeId)\n if (!node) return\n\n const w = node.width ?? 150\n const h = node.height ?? 40\n const handlePos = getHandlePosition(position, node.position.x, node.position.y, w, h)\n\n connectionState.set({\n active: true,\n sourceNodeId: nodeId,\n sourceHandleId: handleId,\n sourcePosition: position,\n sourceX: handlePos.x,\n sourceY: handlePos.y,\n currentX: handlePos.x,\n currentY: handlePos.y,\n })\n\n const container = (e.target as HTMLElement).closest('.pyreon-flow') as HTMLElement\n if (container) container.setPointerCapture(e.pointerId)\n }\n\n // ── Zoom ───────────────────────────────────────────────────────────────\n\n const handleWheel = (e: WheelEvent) => {\n if (instance.config.zoomable === false) return\n e.preventDefault()\n\n const delta = -e.deltaY * 0.001\n const newZoom = Math.min(\n Math.max(instance.viewport.peek().zoom * (1 + delta), instance.config.minZoom ?? 0.1),\n instance.config.maxZoom ?? 4,\n )\n\n const rect = (e.currentTarget as HTMLElement).getBoundingClientRect()\n const mouseX = e.clientX - rect.left\n const mouseY = e.clientY - rect.top\n const vp = instance.viewport.peek()\n const scale = newZoom / vp.zoom\n\n instance.viewport.set({\n x: mouseX - (mouseX - vp.x) * scale,\n y: mouseY - (mouseY - vp.y) * scale,\n zoom: newZoom,\n })\n }\n\n // ── Pan ────────────────────────────────────────────────────────────────\n\n let isPanning = false\n let panStartX = 0\n let panStartY = 0\n let panStartVpX = 0\n let panStartVpY = 0\n\n const handlePointerDown = (e: PointerEvent) => {\n if (instance.config.pannable === false) return\n\n const target = e.target as HTMLElement\n if (target.closest('.pyreon-flow-node')) return\n if (target.closest('.pyreon-flow-handle')) return\n\n // Shift+drag on empty space → selection box\n if (e.shiftKey && instance.config.multiSelect !== false) {\n const container = e.currentTarget as HTMLElement\n const rect = container.getBoundingClientRect()\n const vp = instance.viewport.peek()\n const flowX = (e.clientX - rect.left - vp.x) / vp.zoom\n const flowY = (e.clientY - rect.top - vp.y) / vp.zoom\n\n selectionBox.set({\n active: true,\n startX: flowX,\n startY: flowY,\n currentX: flowX,\n currentY: flowY,\n })\n container.setPointerCapture(e.pointerId)\n return\n }\n\n isPanning = true\n panStartX = e.clientX\n panStartY = e.clientY\n const vp = instance.viewport.peek()\n panStartVpX = vp.x\n panStartVpY = vp.y\n ;(e.currentTarget as HTMLElement).setPointerCapture(e.pointerId)\n\n instance.clearSelection()\n }\n\n // ── Unified pointer move/up ────────────────────────────────────────────\n\n const handlePointerMove = (e: PointerEvent) => {\n const drag = dragState.peek()\n const conn = connectionState.peek()\n const sel = selectionBox.peek()\n\n if (sel.active) {\n const container = e.currentTarget as HTMLElement\n const rect = container.getBoundingClientRect()\n const vp = instance.viewport.peek()\n const flowX = (e.clientX - rect.left - vp.x) / vp.zoom\n const flowY = (e.clientY - rect.top - vp.y) / vp.zoom\n selectionBox.set({ ...sel, currentX: flowX, currentY: flowY })\n return\n }\n\n if (drag.active) {\n // Node dragging with snap guides\n const vp = instance.viewport.peek()\n const dx = (e.clientX - drag.startX) / vp.zoom\n const dy = (e.clientY - drag.startY) / vp.zoom\n\n const primaryStart = drag.startPositions.get(drag.nodeId)\n if (!primaryStart) return\n\n const rawPos = { x: primaryStart.x + dx, y: primaryStart.y + dy }\n const snap = instance.getSnapLines(drag.nodeId, rawPos)\n helperLines.set({ x: snap.x, y: snap.y })\n\n // Calculate actual delta (including snap adjustment)\n const actualDx = snap.snappedPosition.x - primaryStart.x\n const actualDy = snap.snappedPosition.y - primaryStart.y\n\n // Update all dragged nodes from their starting positions\n instance.nodes.update((nds) =>\n nds.map((n) => {\n const start = drag.startPositions.get(n.id)\n if (!start) return n\n return {\n ...n,\n position: { x: start.x + actualDx, y: start.y + actualDy },\n }\n }),\n )\n return\n }\n\n if (conn.active) {\n // Connection drawing — convert screen to flow coordinates\n const container = e.currentTarget as HTMLElement\n const rect = container.getBoundingClientRect()\n const vp = instance.viewport.peek()\n const flowX = (e.clientX - rect.left - vp.x) / vp.zoom\n const flowY = (e.clientY - rect.top - vp.y) / vp.zoom\n\n connectionState.set({\n ...conn,\n currentX: flowX,\n currentY: flowY,\n })\n return\n }\n\n if (isPanning) {\n const dx = e.clientX - panStartX\n const dy = e.clientY - panStartY\n instance.viewport.set({\n ...instance.viewport.peek(),\n x: panStartVpX + dx,\n y: panStartVpY + dy,\n })\n }\n }\n\n const handlePointerUp = (e: PointerEvent) => {\n const drag = dragState.peek()\n const conn = connectionState.peek()\n const sel = selectionBox.peek()\n\n if (sel.active) {\n // Select all nodes within the selection rectangle\n const minX = Math.min(sel.startX, sel.currentX)\n const minY = Math.min(sel.startY, sel.currentY)\n const maxX = Math.max(sel.startX, sel.currentX)\n const maxY = Math.max(sel.startY, sel.currentY)\n\n instance.clearSelection()\n for (const node of instance.nodes.peek()) {\n const w = node.width ?? 150\n const h = node.height ?? 40\n const nx = node.position.x\n const ny = node.position.y\n // Node is within box if any part overlaps\n if (nx + w > minX && nx < maxX && ny + h > minY && ny < maxY) {\n instance.selectNode(node.id, true)\n }\n }\n\n selectionBox.set({ ...emptySelectionBox })\n return\n }\n\n if (drag.active) {\n const node = instance.getNode(drag.nodeId)\n if (node) instance._emit.nodeDragEnd(node)\n dragState.set({ ...emptyDrag })\n helperLines.set({ x: null, y: null })\n }\n\n if (conn.active) {\n // Check if we released over a handle target\n const target = e.target as HTMLElement\n const handle = target.closest('.pyreon-flow-handle')\n if (handle) {\n const targetNodeId = handle.closest('.pyreon-flow-node')?.getAttribute('data-nodeid') ?? ''\n const targetHandleId = handle.getAttribute('data-handleid') ?? 'target'\n\n if (targetNodeId && targetNodeId !== conn.sourceNodeId) {\n const connection: Connection = {\n source: conn.sourceNodeId,\n target: targetNodeId,\n sourceHandle: conn.sourceHandleId,\n targetHandle: targetHandleId,\n }\n\n if (instance.isValidConnection(connection)) {\n instance.addEdge({\n source: connection.source,\n target: connection.target,\n ...(connection.sourceHandle != null ? { sourceHandle: connection.sourceHandle } : {}),\n ...(connection.targetHandle != null ? { targetHandle: connection.targetHandle } : {}),\n })\n }\n }\n }\n\n connectionState.set({ ...emptyConnection })\n }\n\n isPanning = false\n }\n\n // ── Keyboard ───────────────────────────────────────────────────────────\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Delete' || e.key === 'Backspace') {\n const target = e.target as HTMLElement\n if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA') return\n instance.pushHistory()\n instance.deleteSelected()\n }\n if (e.key === 'Escape') {\n instance.clearSelection()\n connectionState.set({ ...emptyConnection })\n }\n if (e.key === 'a' && (e.metaKey || e.ctrlKey)) {\n e.preventDefault()\n instance.selectAll()\n }\n if (e.key === 'c' && (e.metaKey || e.ctrlKey)) {\n instance.copySelected()\n }\n if (e.key === 'v' && (e.metaKey || e.ctrlKey)) {\n instance.paste()\n }\n if (e.key === 'z' && (e.metaKey || e.ctrlKey) && !e.shiftKey) {\n e.preventDefault()\n instance.undo()\n }\n if (e.key === 'z' && (e.metaKey || e.ctrlKey) && e.shiftKey) {\n e.preventDefault()\n instance.redo()\n }\n }\n\n // ── Touch support (pinch zoom) ──────────────────────────────────────────\n\n let lastTouchDist = 0\n let lastTouchCenter = { x: 0, y: 0 }\n\n const handleTouchStart = (e: TouchEvent) => {\n if (e.touches.length === 2) {\n e.preventDefault()\n const t1 = e.touches[0]!\n const t2 = e.touches[1]!\n lastTouchDist = Math.hypot(t2.clientX - t1.clientX, t2.clientY - t1.clientY)\n lastTouchCenter = {\n x: (t1.clientX + t2.clientX) / 2,\n y: (t1.clientY + t2.clientY) / 2,\n }\n }\n }\n\n const handleTouchMove = (e: TouchEvent) => {\n if (e.touches.length === 2 && instance.config.zoomable !== false) {\n e.preventDefault()\n const t1 = e.touches[0]!\n const t2 = e.touches[1]!\n const dist = Math.hypot(t2.clientX - t1.clientX, t2.clientY - t1.clientY)\n const center = {\n x: (t1.clientX + t2.clientX) / 2,\n y: (t1.clientY + t2.clientY) / 2,\n }\n\n const vp = instance.viewport.peek()\n const scaleFactor = dist / lastTouchDist\n const newZoom = Math.min(\n Math.max(vp.zoom * scaleFactor, instance.config.minZoom ?? 0.1),\n instance.config.maxZoom ?? 4,\n )\n\n const rect = (e.currentTarget as HTMLElement).getBoundingClientRect()\n const mouseX = center.x - rect.left\n const mouseY = center.y - rect.top\n const scale = newZoom / vp.zoom\n\n // Pan with touch center movement\n const panDx = center.x - lastTouchCenter.x\n const panDy = center.y - lastTouchCenter.y\n\n instance.viewport.set({\n x: mouseX - (mouseX - vp.x) * scale + panDx,\n y: mouseY - (mouseY - vp.y) * scale + panDy,\n zoom: newZoom,\n })\n\n lastTouchDist = dist\n lastTouchCenter = center\n }\n }\n\n // ── Container size tracking ─────────────────────────────────────────────\n\n let resizeObserver: ResizeObserver | null = null\n\n const containerRef = (el: Element | null) => {\n if (resizeObserver) {\n resizeObserver.disconnect()\n resizeObserver = null\n }\n if (!el) return\n\n const updateSize = () => {\n const rect = el.getBoundingClientRect()\n instance.containerSize.set({\n width: rect.width,\n height: rect.height,\n })\n }\n\n updateSize()\n resizeObserver = new ResizeObserver(updateSize)\n resizeObserver.observe(el)\n }\n\n const containerStyle = `position: relative; width: 100%; height: 100%; overflow: hidden; outline: none; touch-action: none; ${props.style ?? ''}`\n\n return (\n <div\n ref={containerRef}\n class={`pyreon-flow ${props.class ?? ''}`}\n style={containerStyle}\n tabIndex={0}\n onWheel={handleWheel}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onTouchStart={handleTouchStart}\n onTouchMove={handleTouchMove}\n onKeyDown={handleKeyDown}\n >\n {children}\n {() => {\n const vp = instance.viewport()\n return (\n <div\n class=\"pyreon-flow-viewport\"\n style={`position: absolute; transform-origin: 0 0; transform: translate(${vp.x}px, ${vp.y}px) scale(${vp.zoom});`}\n >\n <EdgeLayer\n instance={instance}\n connectionState={() => connectionState()}\n {...(edgeTypes != null ? { edgeTypes } : {})}\n />\n {() => {\n const sel = selectionBox()\n if (!sel.active) return null\n const x = Math.min(sel.startX, sel.currentX)\n const y = Math.min(sel.startY, sel.currentY)\n const w = Math.abs(sel.currentX - sel.startX)\n const h = Math.abs(sel.currentY - sel.startY)\n return (\n <div\n class=\"pyreon-flow-selection-box\"\n style={`position: absolute; left: ${x}px; top: ${y}px; width: ${w}px; height: ${h}px; border: 1px dashed #3b82f6; background: rgba(59, 130, 246, 0.08); pointer-events: none; z-index: 10;`}\n />\n )\n }}\n {() => {\n const lines = helperLines()\n if (!lines.x && !lines.y) return null\n return (\n <svg\n role=\"img\"\n aria-label=\"helper lines\"\n style=\"position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; overflow: visible; z-index: 5;\"\n >\n {lines.x !== null && (\n <line\n x1={String(lines.x)}\n y1=\"-10000\"\n x2={String(lines.x)}\n y2=\"10000\"\n stroke=\"#3b82f6\"\n stroke-width=\"0.5\"\n stroke-dasharray=\"4,4\"\n />\n )}\n {lines.y !== null && (\n <line\n x1=\"-10000\"\n y1={String(lines.y)}\n x2=\"10000\"\n y2={String(lines.y)}\n stroke=\"#3b82f6\"\n stroke-width=\"0.5\"\n stroke-dasharray=\"4,4\"\n />\n )}\n </svg>\n )\n }}\n <NodeLayer\n instance={instance}\n nodeTypes={nodeTypes}\n draggingNodeId={draggingNodeId}\n onNodePointerDown={handleNodePointerDown}\n onHandlePointerDown={handleHandlePointerDown}\n />\n </div>\n )\n }}\n </div>\n )\n}\n","import type { VNodeChild } from '@pyreon/core'\nimport type { HandleProps } from '../types'\n\nconst positionOffset: Record<string, string> = {\n top: 'top: -4px; left: 50%; transform: translateX(-50%);',\n right: 'right: -4px; top: 50%; transform: translateY(-50%);',\n bottom: 'bottom: -4px; left: 50%; transform: translateX(-50%);',\n left: 'left: -4px; top: 50%; transform: translateY(-50%);',\n}\n\n/**\n * Connection handle — attachment point on a node where edges connect.\n * Place inside custom node components.\n *\n * @example\n * ```tsx\n * function CustomNode({ data }: NodeComponentProps) {\n * return (\n * <div class=\"custom-node\">\n * <Handle type=\"target\" position={Position.Left} />\n * <span>{data.label}</span>\n * <Handle type=\"source\" position={Position.Right} />\n * </div>\n * )\n * }\n * ```\n */\nexport function Handle(props: HandleProps): VNodeChild {\n const { type, position, id, style = '' } = props\n const posStyle = positionOffset[position] ?? positionOffset.bottom\n const baseStyle = `position: absolute; ${posStyle} width: 8px; height: 8px; background: #555; border: 2px solid white; border-radius: 50%; cursor: crosshair; z-index: 1; ${style}`\n\n return (\n <div\n class={`pyreon-flow-handle pyreon-flow-handle-${type} ${props.class ?? ''}`}\n style={baseStyle}\n data-handletype={type}\n data-handleid={id ?? type}\n data-handleposition={position}\n />\n )\n}\n","import type { VNodeChild } from '@pyreon/core'\nimport type { FlowInstance, MiniMapProps } from '../types'\n\n/**\n * Miniature overview of the flow diagram showing all nodes\n * and the current viewport position. Click to navigate.\n *\n * @example\n * ```tsx\n * <Flow instance={flow}>\n * <MiniMap nodeColor={(n) => n.type === 'error' ? 'red' : '#ddd'} />\n * </Flow>\n * ```\n */\nexport function MiniMap(props: MiniMapProps & { instance?: FlowInstance }): VNodeChild {\n const {\n width = 200,\n height = 150,\n nodeColor = '#e2e8f0',\n maskColor = 'rgba(0, 0, 0, 0.08)',\n instance,\n } = props\n\n if (!instance) return null\n\n const containerStyle = `position: absolute; bottom: 10px; right: 10px; width: ${width}px; height: ${height}px; border: 1px solid #ddd; background: white; border-radius: 4px; overflow: hidden; z-index: 5; cursor: pointer;`\n\n return () => {\n const nodes = instance.nodes()\n if (nodes.length === 0) return <div class=\"pyreon-flow-minimap\" style={containerStyle} />\n\n // Calculate graph bounds\n let minX = Number.POSITIVE_INFINITY\n let minY = Number.POSITIVE_INFINITY\n let maxX = Number.NEGATIVE_INFINITY\n let maxY = Number.NEGATIVE_INFINITY\n\n for (const node of nodes) {\n const w = node.width ?? 150\n const h = node.height ?? 40\n minX = Math.min(minX, node.position.x)\n minY = Math.min(minY, node.position.y)\n maxX = Math.max(maxX, node.position.x + w)\n maxY = Math.max(maxY, node.position.y + h)\n }\n\n const padding = 40\n const graphW = maxX - minX + padding * 2\n const graphH = maxY - minY + padding * 2\n const scale = Math.min(width / graphW, height / graphH)\n\n // Viewport rectangle in minimap coordinates\n const vp = instance.viewport()\n const cs = instance.containerSize()\n const vpLeft = (-vp.x / vp.zoom - minX + padding) * scale\n const vpTop = (-vp.y / vp.zoom - minY + padding) * scale\n const vpWidth = (cs.width / vp.zoom) * scale\n const vpHeight = (cs.height / vp.zoom) * scale\n\n const handleClick = (e: MouseEvent) => {\n const rect = (e.currentTarget as HTMLElement).getBoundingClientRect()\n const clickX = e.clientX - rect.left\n const clickY = e.clientY - rect.top\n\n // Convert minimap click to flow coordinates\n const flowX = clickX / scale + minX - padding\n const flowY = clickY / scale + minY - padding\n\n // Center viewport on clicked point\n instance.viewport.set({\n ...vp,\n x: -(flowX * vp.zoom) + cs.width / 2,\n y: -(flowY * vp.zoom) + cs.height / 2,\n })\n }\n\n return (\n <div class=\"pyreon-flow-minimap\" style={containerStyle} onClick={handleClick}>\n <svg role=\"img\" aria-label=\"minimap\" width={String(width)} height={String(height)}>\n {/* Mask outside viewport */}\n <rect width={String(width)} height={String(height)} fill={maskColor} />\n\n {/* Nodes */}\n {nodes.map((node) => {\n const w = (node.width ?? 150) * scale\n const h = (node.height ?? 40) * scale\n const x = (node.position.x - minX + padding) * scale\n const y = (node.position.y - minY + padding) * scale\n const color = typeof nodeColor === 'function' ? nodeColor(node) : nodeColor\n\n return (\n <rect\n key={node.id}\n x={String(x)}\n y={String(y)}\n width={String(w)}\n height={String(h)}\n fill={color}\n rx=\"2\"\n />\n )\n })}\n\n {/* Viewport indicator */}\n <rect\n x={String(Math.max(0, vpLeft))}\n y={String(Math.max(0, vpTop))}\n width={String(Math.min(vpWidth, width))}\n height={String(Math.min(vpHeight, height))}\n fill=\"none\"\n stroke=\"#3b82f6\"\n stroke-width=\"1.5\"\n rx=\"2\"\n />\n </svg>\n </div>\n )\n }\n}\n","import type { VNodeChild } from '@pyreon/core'\nimport type { FlowInstance } from '../types'\n\nexport interface NodeResizerProps {\n nodeId: string\n instance: FlowInstance\n /** Minimum width — default: 50 */\n minWidth?: number\n /** Minimum height — default: 30 */\n minHeight?: number\n /** Handle size in px — default: 8 */\n handleSize?: number\n /** Also show edge (non-corner) resize handles — default: false */\n showEdgeHandles?: boolean\n}\n\ntype ResizeDirection = 'nw' | 'ne' | 'sw' | 'se' | 'n' | 's' | 'e' | 'w'\n\nconst directionCursors: Record<ResizeDirection, string> = {\n nw: 'nw-resize',\n ne: 'ne-resize',\n sw: 'sw-resize',\n se: 'se-resize',\n n: 'n-resize',\n s: 's-resize',\n e: 'e-resize',\n w: 'w-resize',\n}\n\nconst directionPositions: Record<ResizeDirection, string> = {\n nw: 'top: -4px; left: -4px;',\n ne: 'top: -4px; right: -4px;',\n sw: 'bottom: -4px; left: -4px;',\n se: 'bottom: -4px; right: -4px;',\n n: 'top: -4px; left: 50%; transform: translateX(-50%);',\n s: 'bottom: -4px; left: 50%; transform: translateX(-50%);',\n e: 'right: -4px; top: 50%; transform: translateY(-50%);',\n w: 'left: -4px; top: 50%; transform: translateY(-50%);',\n}\n\n/**\n * Node resize handles. Place inside a custom node component\n * to allow users to resize the node by dragging corners or edges.\n *\n * Uses pointer capture for clean event handling — no document listener leaks.\n *\n * @example\n * ```tsx\n * function ResizableNode({ id, data, selected }: NodeComponentProps) {\n * return (\n * <div style=\"min-width: 100px; min-height: 50px; position: relative;\">\n * {data.label}\n * <NodeResizer nodeId={id} instance={flow} />\n * </div>\n * )\n * }\n * ```\n */\nexport function NodeResizer(props: NodeResizerProps): VNodeChild {\n const {\n nodeId,\n instance,\n minWidth = 50,\n minHeight = 30,\n handleSize = 8,\n showEdgeHandles = false,\n } = props\n\n const directions: ResizeDirection[] = showEdgeHandles\n ? ['nw', 'ne', 'sw', 'se', 'n', 's', 'e', 'w']\n : ['nw', 'ne', 'sw', 'se']\n\n const createHandler = (dir: ResizeDirection) => {\n let startX = 0\n let startY = 0\n let startWidth = 0\n let startHeight = 0\n let startNodeX = 0\n let startNodeY = 0\n let zoomAtStart = 1\n\n const onPointerDown = (e: PointerEvent) => {\n e.stopPropagation()\n e.preventDefault()\n\n const node = instance.getNode(nodeId)\n if (!node) return\n\n startX = e.clientX\n startY = e.clientY\n startWidth = node.width ?? 150\n startHeight = node.height ?? 40\n startNodeX = node.position.x\n startNodeY = node.position.y\n zoomAtStart = instance.viewport.peek().zoom\n\n // Use pointer capture — clean, no leaks\n const el = e.currentTarget as HTMLElement\n el.setPointerCapture(e.pointerId)\n }\n\n const onPointerMove = (e: PointerEvent) => {\n const el = e.currentTarget as HTMLElement\n if (!el.hasPointerCapture(e.pointerId)) return\n\n const dx = (e.clientX - startX) / zoomAtStart\n const dy = (e.clientY - startY) / zoomAtStart\n\n let newW = startWidth\n let newH = startHeight\n let newX = startNodeX\n let newY = startNodeY\n\n // Horizontal\n if (dir === 'e' || dir === 'se' || dir === 'ne') {\n newW = Math.max(minWidth, startWidth + dx)\n }\n if (dir === 'w' || dir === 'sw' || dir === 'nw') {\n newW = Math.max(minWidth, startWidth - dx)\n newX = startNodeX + startWidth - newW\n }\n\n // Vertical\n if (dir === 's' || dir === 'se' || dir === 'sw') {\n newH = Math.max(minHeight, startHeight + dy)\n }\n if (dir === 'n' || dir === 'ne' || dir === 'nw') {\n newH = Math.max(minHeight, startHeight - dy)\n newY = startNodeY + startHeight - newH\n }\n\n instance.updateNode(nodeId, {\n width: newW,\n height: newH,\n position: { x: newX, y: newY },\n })\n }\n\n const onPointerUp = (e: PointerEvent) => {\n const el = e.currentTarget as HTMLElement\n if (el.hasPointerCapture(e.pointerId)) {\n el.releasePointerCapture(e.pointerId)\n }\n }\n\n return { onPointerDown, onPointerMove, onPointerUp }\n }\n\n const size = `${handleSize}px`\n const baseStyle = `position: absolute; width: ${size}; height: ${size}; background: white; border: 1.5px solid #3b82f6; border-radius: 2px; z-index: 2;`\n\n return (\n <>\n {directions.map((dir) => {\n const handler = createHandler(dir)\n return (\n <div\n key={dir}\n class={`pyreon-flow-resizer pyreon-flow-resizer-${dir}`}\n style={`${baseStyle} ${directionPositions[dir]} cursor: ${directionCursors[dir]};`}\n onPointerDown={handler.onPointerDown}\n onPointerMove={handler.onPointerMove}\n onPointerUp={handler.onPointerUp}\n />\n )\n })}\n </>\n )\n}\n","import type { VNodeChild } from '@pyreon/core'\n\nexport interface NodeToolbarProps {\n /** Position relative to node — default: 'top' */\n position?: 'top' | 'bottom' | 'left' | 'right'\n /** Offset from node in px — default: 8 */\n offset?: number\n /** Only show when node is selected — default: true */\n showOnSelect?: boolean\n /** Whether the node is currently selected */\n selected?: boolean\n style?: string\n class?: string\n children?: VNodeChild\n}\n\nconst positionStyles: Record<string, string> = {\n top: 'bottom: 100%; left: 50%; transform: translateX(-50%);',\n bottom: 'top: 100%; left: 50%; transform: translateX(-50%);',\n left: 'right: 100%; top: 50%; transform: translateY(-50%);',\n right: 'left: 100%; top: 50%; transform: translateY(-50%);',\n}\n\n/**\n * Floating toolbar that appears near a node, typically when selected.\n * Place inside a custom node component.\n *\n * @example\n * ```tsx\n * function EditableNode({ id, data, selected }: NodeComponentProps) {\n * return (\n * <div class=\"node\">\n * {data.label}\n * <NodeToolbar selected={selected}>\n * <button onClick={() => duplicate(id)}>Duplicate</button>\n * <button onClick={() => remove(id)}>Delete</button>\n * </NodeToolbar>\n * </div>\n * )\n * }\n * ```\n */\nexport function NodeToolbar(props: NodeToolbarProps): VNodeChild {\n const { position = 'top', offset = 8, showOnSelect = true, selected = false, children } = props\n\n if (showOnSelect && !selected) return null\n\n const posStyle = positionStyles[position] ?? positionStyles.top\n const marginProp =\n position === 'top'\n ? `margin-bottom: ${offset}px;`\n : position === 'bottom'\n ? `margin-top: ${offset}px;`\n : position === 'left'\n ? `margin-right: ${offset}px;`\n : `margin-left: ${offset}px;`\n\n const baseStyle = `position: absolute; ${posStyle} ${marginProp} z-index: 10; display: flex; gap: 4px; background: white; border: 1px solid #ddd; border-radius: 6px; padding: 4px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); ${props.style ?? ''}`\n\n return (\n <div class={`pyreon-flow-node-toolbar ${props.class ?? ''}`} style={baseStyle}>\n {children}\n </div>\n )\n}\n","import type { VNodeChild } from '@pyreon/core'\nimport type { PanelProps } from '../types'\n\nconst positionStyles: Record<string, string> = {\n 'top-left': 'top: 10px; left: 10px;',\n 'top-right': 'top: 10px; right: 10px;',\n 'bottom-left': 'bottom: 10px; left: 10px;',\n 'bottom-right': 'bottom: 10px; right: 10px;',\n}\n\n/**\n * Positioned overlay panel for custom content inside the flow canvas.\n *\n * @example\n * ```tsx\n * <Flow instance={flow}>\n * <Panel position=\"top-right\">\n * <SearchBar />\n * </Panel>\n * </Flow>\n * ```\n */\nexport function Panel(props: PanelProps): VNodeChild {\n const { position = 'top-left', style = '', children } = props\n const posStyle = positionStyles[position] ?? positionStyles['top-left']\n const baseStyle = `position: absolute; ${posStyle} z-index: 5; ${style}`\n\n return (\n <div class={`pyreon-flow-panel ${props.class ?? ''}`} style={baseStyle}>\n {children}\n </div>\n )\n}\n","import type { FlowEdge, FlowNode, LayoutAlgorithm, LayoutOptions } from './types'\n\n// ─── ELK algorithm mapping ───────────────────────────────────────────────────\n\nconst ELK_ALGORITHMS: Record<LayoutAlgorithm, string> = {\n layered: 'org.eclipse.elk.layered',\n force: 'org.eclipse.elk.force',\n stress: 'org.eclipse.elk.stress',\n tree: 'org.eclipse.elk.mrtree',\n radial: 'org.eclipse.elk.radial',\n box: 'org.eclipse.elk.box',\n rectpacking: 'org.eclipse.elk.rectpacking',\n}\n\nconst ELK_DIRECTIONS: Record<string, string> = {\n UP: 'UP',\n DOWN: 'DOWN',\n LEFT: 'LEFT',\n RIGHT: 'RIGHT',\n}\n\n// ─── Lazy-loaded ELK instance ────────────────────────────────────────────────\n\nlet elkInstance: any = null\nlet elkPromise: Promise<any> | null = null\n\nasync function getELK(): Promise<any> {\n if (elkInstance) return elkInstance\n if (elkPromise) return elkPromise\n\n elkPromise = import('elkjs/lib/elk.bundled.js').then((mod) => {\n const ELK = mod.default || mod\n elkInstance = new ELK()\n return elkInstance\n })\n\n return elkPromise\n}\n\n// ─── Convert flow graph to ELK format ────────────────────────────────────────\n\ninterface ElkNode {\n id: string\n width: number\n height: number\n}\n\ninterface ElkEdge {\n id: string\n sources: string[]\n targets: string[]\n}\n\ninterface ElkGraph {\n id: string\n layoutOptions: Record<string, string>\n children: ElkNode[]\n edges: ElkEdge[]\n}\n\ninterface ElkResult {\n children: Array<{ id: string; x: number; y: number }>\n}\n\nfunction toElkGraph(\n nodes: FlowNode[],\n edges: FlowEdge[],\n algorithm: LayoutAlgorithm,\n options: LayoutOptions,\n): ElkGraph {\n const layoutOptions: Record<string, string> = {\n 'elk.algorithm': ELK_ALGORITHMS[algorithm] ?? ELK_ALGORITHMS.layered,\n }\n\n if (options.direction) {\n layoutOptions['elk.direction'] = ELK_DIRECTIONS[options.direction] ?? 'DOWN'\n }\n\n if (options.nodeSpacing !== undefined) {\n layoutOptions['elk.spacing.nodeNode'] = String(options.nodeSpacing)\n }\n\n if (options.layerSpacing !== undefined) {\n layoutOptions['elk.layered.spacing.nodeNodeBetweenLayers'] = String(options.layerSpacing)\n }\n\n if (options.edgeRouting) {\n const routingMap: Record<string, string> = {\n orthogonal: 'ORTHOGONAL',\n splines: 'SPLINES',\n polyline: 'POLYLINE',\n }\n layoutOptions['elk.edgeRouting'] = routingMap[options.edgeRouting] ?? 'ORTHOGONAL'\n }\n\n return {\n id: 'root',\n layoutOptions,\n children: nodes.map((node) => ({\n id: node.id,\n width: node.width ?? 150,\n height: node.height ?? 40,\n })),\n edges: edges.map((edge, i) => ({\n id: edge.id ?? `e-${i}`,\n sources: [edge.source],\n targets: [edge.target],\n })),\n }\n}\n\n// ─── Public API ──────────────────────────────────────────────────────────────\n\n/**\n * Compute a layout for the given nodes and edges using elkjs.\n * Returns an array of { id, position } for each node.\n *\n * elkjs is lazy-loaded — zero bundle cost until this function is called.\n *\n * @example\n * ```ts\n * const positions = await computeLayout(nodes, edges, 'layered', {\n * direction: 'RIGHT',\n * nodeSpacing: 50,\n * layerSpacing: 100,\n * })\n * // positions: [{ id: '1', position: { x: 0, y: 0 } }, ...]\n * ```\n */\nexport async function computeLayout(\n nodes: FlowNode[],\n edges: FlowEdge[],\n algorithm: LayoutAlgorithm = 'layered',\n options: LayoutOptions = {},\n): Promise<Array<{ id: string; position: { x: number; y: number } }>> {\n const elk = await getELK()\n const graph = toElkGraph(nodes, edges, algorithm, options)\n const result: ElkResult = await elk.layout(graph)\n\n return (result.children ?? []).map((child) => ({\n id: child.id,\n position: { x: child.x ?? 0, y: child.y ?? 0 },\n }))\n}\n","import { batch, computed, signal } from '@pyreon/reactivity'\nimport { computeLayout } from './layout'\nimport type {\n Connection,\n FlowConfig,\n FlowEdge,\n FlowInstance,\n FlowNode,\n LayoutAlgorithm,\n LayoutOptions,\n NodeChange,\n XYPosition,\n} from './types'\n\n/**\n * Generate a unique edge id from source/target.\n */\nfunction edgeId(edge: FlowEdge): string {\n if (edge.id) return edge.id\n const sh = edge.sourceHandle ? `-${edge.sourceHandle}` : ''\n const th = edge.targetHandle ? `-${edge.targetHandle}` : ''\n return `e-${edge.source}${sh}-${edge.target}${th}`\n}\n\n/**\n * Create a reactive flow instance — the core state manager for flow diagrams.\n *\n * All state is signal-based. Nodes, edges, viewport, and selection are\n * reactive and update the UI automatically when modified.\n *\n * @param config - Initial configuration with nodes, edges, and options\n * @returns A FlowInstance with signals and methods for managing the diagram\n *\n * @example\n * ```tsx\n * const flow = createFlow({\n * nodes: [\n * { id: '1', position: { x: 0, y: 0 }, data: { label: 'Start' } },\n * { id: '2', position: { x: 200, y: 100 }, data: { label: 'End' } },\n * ],\n * edges: [{ source: '1', target: '2' }],\n * })\n *\n * flow.nodes() // reactive node list\n * flow.viewport() // { x: 0, y: 0, zoom: 1 }\n * flow.addNode({ id: '3', position: { x: 400, y: 0 }, data: { label: 'New' } })\n * flow.layout('layered', { direction: 'RIGHT' })\n * ```\n */\nexport function createFlow(config: FlowConfig = {}): FlowInstance {\n const {\n nodes: initialNodes = [],\n edges: initialEdges = [],\n defaultEdgeType = 'bezier',\n minZoom = 0.1,\n maxZoom = 4,\n snapToGrid = false,\n snapGrid = 15,\n connectionRules,\n } = config\n\n // Ensure all edges have ids\n const edgesWithIds = initialEdges.map((e) => ({\n ...e,\n id: edgeId(e),\n type: e.type ?? defaultEdgeType,\n }))\n\n // ── Core signals ─────────────────────────────────────────────────────────\n\n const nodes = signal<FlowNode[]>([...initialNodes])\n const edges = signal<FlowEdge[]>(edgesWithIds)\n const viewport = signal({ x: 0, y: 0, zoom: 1 })\n const containerSize = signal({ width: 800, height: 600 })\n\n // Track selected state separately for O(1) lookups\n const selectedNodeIds = signal(new Set<string>())\n const selectedEdgeIds = signal(new Set<string>())\n\n // ── Computed ─────────────────────────────────────────────────────────────\n\n const zoom = computed(() => viewport().zoom)\n\n const selectedNodes = computed(() => [...selectedNodeIds()])\n const selectedEdges = computed(() => [...selectedEdgeIds()])\n\n // ── Listeners ────────────────────────────────────────────────────────────\n\n const connectListeners = new Set<(connection: Connection) => void>()\n const nodesChangeListeners = new Set<(changes: NodeChange[]) => void>()\n const nodeClickListeners = new Set<(node: FlowNode) => void>()\n const edgeClickListeners = new Set<(edge: FlowEdge) => void>()\n const nodeDragStartListeners = new Set<(node: FlowNode) => void>()\n const nodeDragEndListeners = new Set<(node: FlowNode) => void>()\n const nodeDoubleClickListeners = new Set<(node: FlowNode) => void>()\n\n function emitNodeChanges(changes: NodeChange[]) {\n for (const cb of nodesChangeListeners) cb(changes)\n }\n\n // ── Node operations ──────────────────────────────────────────────────────\n\n function getNode(id: string): FlowNode | undefined {\n return nodes.peek().find((n) => n.id === id)\n }\n\n function addNode(node: FlowNode): void {\n nodes.update((nds) => [...nds, node])\n }\n\n function removeNode(id: string): void {\n batch(() => {\n nodes.update((nds) => nds.filter((n) => n.id !== id))\n // Remove connected edges\n edges.update((eds) => eds.filter((e) => e.source !== id && e.target !== id))\n selectedNodeIds.update((set) => {\n const next = new Set(set)\n next.delete(id)\n return next\n })\n })\n emitNodeChanges([{ type: 'remove', id }])\n }\n\n function updateNode(id: string, update: Partial<FlowNode>): void {\n nodes.update((nds) => nds.map((n) => (n.id === id ? { ...n, ...update } : n)))\n }\n\n function updateNodePosition(id: string, position: XYPosition): void {\n let pos = snapToGrid\n ? {\n x: Math.round(position.x / snapGrid) * snapGrid,\n y: Math.round(position.y / snapGrid) * snapGrid,\n }\n : position\n\n // Apply extent clamping\n const node = getNode(id)\n pos = clampToExtent(pos, node?.width, node?.height)\n\n nodes.update((nds) => nds.map((n) => (n.id === id ? { ...n, position: pos } : n)))\n emitNodeChanges([{ type: 'position', id, position: pos }])\n }\n\n // ── Edge operations ──────────────────────────────────────────────────────\n\n function getEdge(id: string): FlowEdge | undefined {\n return edges.peek().find((e) => e.id === id)\n }\n\n function addEdge(edge: FlowEdge): void {\n const newEdge = {\n ...edge,\n id: edgeId(edge),\n type: edge.type ?? defaultEdgeType,\n }\n\n // Don't add duplicate edges\n const existing = edges.peek()\n if (existing.some((e) => e.id === newEdge.id)) return\n\n edges.update((eds) => [...eds, newEdge])\n\n // Notify connect listeners\n const connection: Connection = {\n source: edge.source,\n target: edge.target,\n ...(edge.sourceHandle != null ? { sourceHandle: edge.sourceHandle } : {}),\n ...(edge.targetHandle != null ? { targetHandle: edge.targetHandle } : {}),\n }\n for (const cb of connectListeners) cb(connection)\n }\n\n function removeEdge(id: string): void {\n edges.update((eds) => eds.filter((e) => e.id !== id))\n selectedEdgeIds.update((set) => {\n const next = new Set(set)\n next.delete(id)\n return next\n })\n }\n\n function isValidConnection(connection: Connection): boolean {\n if (!connectionRules) return true\n\n // Find source node type\n const sourceNode = getNode(connection.source)\n if (!sourceNode) return false\n\n const sourceType = sourceNode.type ?? 'default'\n const rule = connectionRules[sourceType]\n if (!rule) return true // no rule = allow\n\n // Find target node type\n const targetNode = getNode(connection.target)\n if (!targetNode) return false\n\n const targetType = targetNode.type ?? 'default'\n return rule.outputs.includes(targetType)\n }\n\n // ── Selection ────────────────────────────────────────────────────────────\n\n function selectNode(id: string, additive = false): void {\n selectedNodeIds.update((set) => {\n const next = additive ? new Set(set) : new Set<string>()\n next.add(id)\n return next\n })\n if (!additive) {\n selectedEdgeIds.set(new Set())\n }\n }\n\n function deselectNode(id: string): void {\n selectedNodeIds.update((set) => {\n const next = new Set(set)\n next.delete(id)\n return next\n })\n }\n\n function selectEdge(id: string, additive = false): void {\n selectedEdgeIds.update((set) => {\n const next = additive ? new Set(set) : new Set<string>()\n next.add(id)\n return next\n })\n if (!additive) {\n selectedNodeIds.set(new Set())\n }\n }\n\n function clearSelection(): void {\n batch(() => {\n selectedNodeIds.set(new Set())\n selectedEdgeIds.set(new Set())\n })\n }\n\n function selectAll(): void {\n selectedNodeIds.set(new Set(nodes.peek().map((n) => n.id)))\n }\n\n function deleteSelected(): void {\n batch(() => {\n const nodeIdsToRemove = selectedNodeIds.peek()\n const edgeIdsToRemove = selectedEdgeIds.peek()\n\n if (nodeIdsToRemove.size > 0) {\n nodes.update((nds) => nds.filter((n) => !nodeIdsToRemove.has(n.id)))\n // Also remove edges connected to deleted nodes\n edges.update((eds) =>\n eds.filter(\n (e) =>\n !nodeIdsToRemove.has(e.source) &&\n !nodeIdsToRemove.has(e.target) &&\n !edgeIdsToRemove.has(e.id!),\n ),\n )\n } else if (edgeIdsToRemove.size > 0) {\n edges.update((eds) => eds.filter((e) => !edgeIdsToRemove.has(e.id!)))\n }\n\n selectedNodeIds.set(new Set())\n selectedEdgeIds.set(new Set())\n })\n }\n\n // ── Viewport ─────────────────────────────────────────────────────────────\n\n function fitView(nodeIds?: string[], padding = config.fitViewPadding ?? 0.1): void {\n const targetNodes = nodeIds ? nodes.peek().filter((n) => nodeIds.includes(n.id)) : nodes.peek()\n\n if (targetNodes.length === 0) return\n\n let minX = Number.POSITIVE_INFINITY\n let minY = Number.POSITIVE_INFINITY\n let maxX = Number.NEGATIVE_INFINITY\n let maxY = Number.NEGATIVE_INFINITY\n\n for (const node of targetNodes) {\n const w = node.width ?? 150\n const h = node.height ?? 40\n minX = Math.min(minX, node.position.x)\n minY = Math.min(minY, node.position.y)\n maxX = Math.max(maxX, node.position.x + w)\n maxY = Math.max(maxY, node.position.y + h)\n }\n\n const graphWidth = maxX - minX\n const graphHeight = maxY - minY\n\n const { width: containerWidth, height: containerHeight } = containerSize.peek()\n\n const zoomX = containerWidth / (graphWidth * (1 + padding * 2))\n const zoomY = containerHeight / (graphHeight * (1 + padding * 2))\n const newZoom = Math.min(Math.max(Math.min(zoomX, zoomY), minZoom), maxZoom)\n\n const centerX = (minX + maxX) / 2\n const centerY = (minY + maxY) / 2\n\n viewport.set({\n x: containerWidth / 2 - centerX * newZoom,\n y: containerHeight / 2 - centerY * newZoom,\n zoom: newZoom,\n })\n }\n\n function zoomTo(z: number): void {\n viewport.update((v) => ({\n ...v,\n zoom: Math.min(Math.max(z, minZoom), maxZoom),\n }))\n }\n\n function zoomIn(): void {\n viewport.update((v) => ({\n ...v,\n zoom: Math.min(v.zoom * 1.2, maxZoom),\n }))\n }\n\n function zoomOut(): void {\n viewport.update((v) => ({\n ...v,\n zoom: Math.max(v.zoom / 1.2, minZoom),\n }))\n }\n\n function panTo(position: XYPosition): void {\n viewport.update((v) => ({\n ...v,\n x: -position.x * v.zoom,\n y: -position.y * v.zoom,\n }))\n }\n\n function isNodeVisible(id: string): boolean {\n const node = getNode(id)\n if (!node) return false\n // Simplified check — actual implementation would use container dimensions\n const v = viewport.peek()\n const w = node.width ?? 150\n const h = node.height ?? 40\n const screenX = node.position.x * v.zoom + v.x\n const screenY = node.position.y * v.zoom + v.y\n const screenW = w * v.zoom\n const screenH = h * v.zoom\n const { width: cw, height: ch } = containerSize.peek()\n return screenX + screenW > 0 && screenX < cw && screenY + screenH > 0 && screenY < ch\n }\n\n // ── Layout ───────────────────────────────────────────────────────────────\n\n async function layout(\n algorithm: LayoutAlgorithm = 'layered',\n options: LayoutOptions = {},\n ): Promise<void> {\n const currentNodes = nodes.peek()\n const currentEdges = edges.peek()\n\n const positions = await computeLayout(currentNodes, currentEdges, algorithm, options)\n\n const animate = options.animate !== false\n const duration = options.animationDuration ?? 300\n\n if (!animate) {\n batch(() => {\n nodes.update((nds) =>\n nds.map((node) => {\n const pos = positions.find((p) => p.id === node.id)\n return pos ? { ...node, position: pos.position } : node\n }),\n )\n })\n return\n }\n\n // Animated transition — interpolate positions over duration\n const startPositions = new Map(currentNodes.map((n) => [n.id, { ...n.position }]))\n const targetPositions = new Map(positions.map((p) => [p.id, p.position]))\n\n const startTime = performance.now()\n\n const animateFrame = () => {\n const elapsed = performance.now() - startTime\n const t = Math.min(elapsed / duration, 1)\n // Ease-out cubic\n const eased = 1 - (1 - t) ** 3\n\n batch(() => {\n nodes.update((nds) =>\n nds.map((node) => {\n const start = startPositions.get(node.id)\n const end = targetPositions.get(node.id)\n if (!start || !end) return node\n return {\n ...node,\n position: {\n x: start.x + (end.x - start.x) * eased,\n y: start.y + (end.y - start.y) * eased,\n },\n }\n }),\n )\n })\n\n if (t < 1) requestAnimationFrame(animateFrame)\n }\n\n requestAnimationFrame(animateFrame)\n }\n\n // ── Batch ────────────────────────────────────────────────────────────────\n\n function batchOp(fn: () => void): void {\n batch(fn)\n }\n\n // ── Graph queries ────────────────────────────────────────────────────────\n\n function getConnectedEdges(nodeId: string): FlowEdge[] {\n return edges.peek().filter((e) => e.source === nodeId || e.target === nodeId)\n }\n\n function getIncomers(nodeId: string): FlowNode[] {\n const incomingEdges = edges.peek().filter((e) => e.target === nodeId)\n const sourceIds = new Set(incomingEdges.map((e) => e.source))\n return nodes.peek().filter((n) => sourceIds.has(n.id))\n }\n\n function getOutgoers(nodeId: string): FlowNode[] {\n const outgoingEdges = edges.peek().filter((e) => e.source === nodeId)\n const targetIds = new Set(outgoingEdges.map((e) => e.target))\n return nodes.peek().filter((n) => targetIds.has(n.id))\n }\n\n // ── Listeners ────────────────────────────────────────────────────────────\n\n function onConnect(callback: (connection: Connection) => void): () => void {\n connectListeners.add(callback)\n return () => connectListeners.delete(callback)\n }\n\n function onNodesChange(callback: (changes: NodeChange[]) => void): () => void {\n nodesChangeListeners.add(callback)\n return () => nodesChangeListeners.delete(callback)\n }\n\n function onNodeClick(callback: (node: FlowNode) => void): () => void {\n nodeClickListeners.add(callback)\n return () => nodeClickListeners.delete(callback)\n }\n\n function onEdgeClick(callback: (edge: FlowEdge) => void): () => void {\n edgeClickListeners.add(callback)\n return () => edgeClickListeners.delete(callback)\n }\n\n function onNodeDragStart(callback: (node: FlowNode) => void): () => void {\n nodeDragStartListeners.add(callback)\n return () => nodeDragStartListeners.delete(callback)\n }\n\n function onNodeDragEnd(callback: (node: FlowNode) => void): () => void {\n nodeDragEndListeners.add(callback)\n return () => nodeDragEndListeners.delete(callback)\n }\n\n function onNodeDoubleClick(callback: (node: FlowNode) => void): () => void {\n nodeDoubleClickListeners.add(callback)\n return () => nodeDoubleClickListeners.delete(callback)\n }\n\n // ── Copy / Paste ────────────────────────────────────────────────────────\n\n let clipboard: { nodes: FlowNode[]; edges: FlowEdge[] } | null = null\n\n function copySelected(): void {\n const selectedNodeSet = selectedNodeIds.peek()\n if (selectedNodeSet.size === 0) return\n\n const copiedNodes = nodes.peek().filter((n) => selectedNodeSet.has(n.id))\n const nodeIdSet = new Set(copiedNodes.map((n) => n.id))\n const copiedEdges = edges\n .peek()\n .filter((e) => nodeIdSet.has(e.source) && nodeIdSet.has(e.target))\n\n clipboard = { nodes: copiedNodes, edges: copiedEdges }\n }\n\n function paste(offset: XYPosition = { x: 50, y: 50 }): void {\n if (!clipboard) return\n\n const idMap = new Map<string, string>()\n const newNodes: FlowNode[] = []\n\n // Create new nodes with offset positions and new ids\n for (const node of clipboard.nodes) {\n const newId = `${node.id}-copy-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`\n idMap.set(node.id, newId)\n newNodes.push({\n ...node,\n id: newId,\n position: {\n x: node.position.x + offset.x,\n y: node.position.y + offset.y,\n },\n })\n }\n\n const newEdges: FlowEdge[] = clipboard.edges.map((e) => {\n const { id: _id, ...rest } = e\n return {\n ...rest,\n source: idMap.get(e.source) ?? e.source,\n target: idMap.get(e.target) ?? e.target,\n }\n })\n\n batch(() => {\n for (const node of newNodes) addNode(node)\n for (const edge of newEdges) addEdge(edge)\n\n // Select pasted nodes\n selectedNodeIds.set(new Set(newNodes.map((n) => n.id)))\n selectedEdgeIds.set(new Set())\n })\n }\n\n // ── Undo / Redo ────────────────────────────────────────────────────────\n\n const undoStack: Array<{ nodes: FlowNode[]; edges: FlowEdge[] }> = []\n const redoStack: Array<{ nodes: FlowNode[]; edges: FlowEdge[] }> = []\n const maxHistory = 50\n\n function pushHistory(): void {\n undoStack.push({\n nodes: structuredClone(nodes.peek()),\n edges: structuredClone(edges.peek()),\n })\n if (undoStack.length > maxHistory) undoStack.shift()\n redoStack.length = 0\n }\n\n function undo(): void {\n const prev = undoStack.pop()\n if (!prev) return\n\n redoStack.push({\n nodes: structuredClone(nodes.peek()),\n edges: structuredClone(edges.peek()),\n })\n\n batch(() => {\n nodes.set(prev.nodes)\n edges.set(prev.edges)\n clearSelection()\n })\n }\n\n function redo(): void {\n const next = redoStack.pop()\n if (!next) return\n\n undoStack.push({\n nodes: structuredClone(nodes.peek()),\n edges: structuredClone(edges.peek()),\n })\n\n batch(() => {\n nodes.set(next.nodes)\n edges.set(next.edges)\n clearSelection()\n })\n }\n\n // ── Multi-node drag ────────────────────────────────────────────────────\n\n function moveSelectedNodes(dx: number, dy: number): void {\n const selected = selectedNodeIds.peek()\n if (selected.size === 0) return\n\n nodes.update((nds) =>\n nds.map((n) => {\n if (!selected.has(n.id)) return n\n return {\n ...n,\n position: {\n x: n.position.x + dx,\n y: n.position.y + dy,\n },\n }\n }),\n )\n }\n\n // ── Helper lines (snap guides) ─────────────────────────────────────────\n\n function getSnapLines(\n dragNodeId: string,\n position: XYPosition,\n threshold = 5,\n ): { x: number | null; y: number | null; snappedPosition: XYPosition } {\n const dragNode = getNode(dragNodeId)\n if (!dragNode) return { x: null, y: null, snappedPosition: position }\n\n const w = dragNode.width ?? 150\n const h = dragNode.height ?? 40\n const dragCenterX = position.x + w / 2\n const dragCenterY = position.y + h / 2\n\n let snapX: number | null = null\n let snapY: number | null = null\n let snappedX = position.x\n let snappedY = position.y\n\n for (const node of nodes.peek()) {\n if (node.id === dragNodeId) continue\n const nw = node.width ?? 150\n const nh = node.height ?? 40\n const nodeCenterX = node.position.x + nw / 2\n const nodeCenterY = node.position.y + nh / 2\n\n // Snap to center X\n if (Math.abs(dragCenterX - nodeCenterX) < threshold) {\n snapX = nodeCenterX\n snappedX = nodeCenterX - w / 2\n }\n // Snap to left edge\n if (Math.abs(position.x - node.position.x) < threshold) {\n snapX = node.position.x\n snappedX = node.position.x\n }\n // Snap to right edge\n if (Math.abs(position.x + w - (node.position.x + nw)) < threshold) {\n snapX = node.position.x + nw\n snappedX = node.position.x + nw - w\n }\n\n // Snap to center Y\n if (Math.abs(dragCenterY - nodeCenterY) < threshold) {\n snapY = nodeCenterY\n snappedY = nodeCenterY - h / 2\n }\n // Snap to top edge\n if (Math.abs(position.y - node.position.y) < threshold) {\n snapY = node.position.y\n snappedY = node.position.y\n }\n // Snap to bottom edge\n if (Math.abs(position.y + h - (node.position.y + nh)) < threshold) {\n snapY = node.position.y + nh\n snappedY = node.position.y + nh - h\n }\n }\n\n return { x: snapX, y: snapY, snappedPosition: { x: snappedX, y: snappedY } }\n }\n\n // ── Sub-flows / Groups ──────────────────────────────────────────────────\n\n function getChildNodes(parentId: string): FlowNode[] {\n return nodes.peek().filter((n) => n.parentId === parentId)\n }\n\n function getAbsolutePosition(nodeId: string): XYPosition {\n const node = getNode(nodeId)\n if (!node) return { x: 0, y: 0 }\n\n if (node.parentId) {\n const parentPos = getAbsolutePosition(node.parentId)\n return {\n x: parentPos.x + node.position.x,\n y: parentPos.y + node.position.y,\n }\n }\n\n return node.position\n }\n\n // ── Edge reconnecting ──────────────────────────────────────────────────\n\n function reconnectEdge(\n targetEdgeId: string,\n newConnection: {\n source?: string\n target?: string\n sourceHandle?: string\n targetHandle?: string\n },\n ): void {\n edges.update((eds) =>\n eds.map((e) => {\n if (e.id !== targetEdgeId) return e\n const updated: typeof e = {\n ...e,\n source: newConnection.source ?? e.source,\n target: newConnection.target ?? e.target,\n }\n const sh = newConnection.sourceHandle ?? e.sourceHandle\n const th = newConnection.targetHandle ?? e.targetHandle\n if (sh != null) updated.sourceHandle = sh\n if (th != null) updated.targetHandle = th\n return updated\n }),\n )\n }\n\n // ── Edge waypoints ──────────────────────────────────────────────────────\n\n function addEdgeWaypoint(edgeIdentifier: string, point: XYPosition, index?: number): void {\n edges.update((eds) =>\n eds.map((e) => {\n if (e.id !== edgeIdentifier) return e\n const waypoints = [...(e.waypoints ?? [])]\n if (index !== undefined) {\n waypoints.splice(index, 0, point)\n } else {\n waypoints.push(point)\n }\n return { ...e, waypoints }\n }),\n )\n }\n\n function removeEdgeWaypoint(edgeIdentifier: string, index: number): void {\n edges.update((eds) =>\n eds.map((e) => {\n if (e.id !== edgeIdentifier) return e\n const waypoints = [...(e.waypoints ?? [])]\n waypoints.splice(index, 1)\n const { waypoints: _wp, ...rest } = e\n return waypoints.length > 0 ? { ...rest, waypoints } : rest\n }),\n )\n }\n\n function updateEdgeWaypoint(edgeIdentifier: string, index: number, point: XYPosition): void {\n edges.update((eds) =>\n eds.map((e) => {\n if (e.id !== edgeIdentifier) return e\n const waypoints = [...(e.waypoints ?? [])]\n if (index >= 0 && index < waypoints.length) {\n waypoints[index] = point\n }\n return { ...e, waypoints }\n }),\n )\n }\n\n // ── Proximity connect ───────────────────────────────────────────────────\n\n function getProximityConnection(nodeId: string, threshold = 50): Connection | null {\n const node = getNode(nodeId)\n if (!node) return null\n\n const w = node.width ?? 150\n const h = node.height ?? 40\n const centerX = node.position.x + w / 2\n const centerY = node.position.y + h / 2\n\n let closest: { nodeId: string; dist: number } | null = null\n\n for (const other of nodes.peek()) {\n if (other.id === nodeId) continue\n // Skip if already connected\n const alreadyConnected = edges\n .peek()\n .some(\n (e) =>\n (e.source === nodeId && e.target === other.id) ||\n (e.source === other.id && e.target === nodeId),\n )\n if (alreadyConnected) continue\n\n const ow = other.width ?? 150\n const oh = other.height ?? 40\n const ocx = other.position.x + ow / 2\n const ocy = other.position.y + oh / 2\n const dist = Math.hypot(centerX - ocx, centerY - ocy)\n\n if (dist < threshold && (!closest || dist < closest.dist)) {\n closest = { nodeId: other.id, dist }\n }\n }\n\n if (!closest) return null\n\n const connection: Connection = {\n source: nodeId,\n target: closest.nodeId,\n }\n\n return isValidConnection(connection) ? connection : null\n }\n\n // ── Collision detection ────────────────────────────────────────────────\n\n function getOverlappingNodes(nodeId: string): FlowNode[] {\n const node = getNode(nodeId)\n if (!node) return []\n\n const w = node.width ?? 150\n const h = node.height ?? 40\n const ax1 = node.position.x\n const ay1 = node.position.y\n const ax2 = ax1 + w\n const ay2 = ay1 + h\n\n return nodes.peek().filter((other) => {\n if (other.id === nodeId) return false\n const ow = other.width ?? 150\n const oh = other.height ?? 40\n const bx1 = other.position.x\n const by1 = other.position.y\n const bx2 = bx1 + ow\n const by2 = by1 + oh\n\n return ax1 < bx2 && ax2 > bx1 && ay1 < by2 && ay2 > by1\n })\n }\n\n function resolveCollisions(nodeId: string, spacing = 10): void {\n const overlapping = getOverlappingNodes(nodeId)\n if (overlapping.length === 0) return\n\n const node = getNode(nodeId)\n if (!node) return\n\n const w = node.width ?? 150\n const h = node.height ?? 40\n\n for (const other of overlapping) {\n const ow = other.width ?? 150\n const oh = other.height ?? 40\n\n // Calculate overlap amounts\n const overlapX = Math.min(\n node.position.x + w - other.position.x,\n other.position.x + ow - node.position.x,\n )\n const overlapY = Math.min(\n node.position.y + h - other.position.y,\n other.position.y + oh - node.position.y,\n )\n\n // Push in the direction of least overlap\n if (overlapX < overlapY) {\n const dx =\n node.position.x < other.position.x ? -(overlapX + spacing) / 2 : (overlapX + spacing) / 2\n updateNodePosition(other.id, {\n x: other.position.x - dx,\n y: other.position.y,\n })\n } else {\n const dy =\n node.position.y < other.position.y ? -(overlapY + spacing) / 2 : (overlapY + spacing) / 2\n updateNodePosition(other.id, {\n x: other.position.x,\n y: other.position.y - dy,\n })\n }\n }\n }\n\n // ── Node extent (drag boundaries) ──────────────────────────────────────\n\n function setNodeExtent(extent: [[number, number], [number, number]] | null): void {\n nodeExtent = extent\n }\n\n let nodeExtent: [[number, number], [number, number]] | null = config.nodeExtent ?? null\n\n function clampToExtent(position: XYPosition, nodeWidth = 150, nodeHeight = 40): XYPosition {\n if (!nodeExtent) return position\n return {\n x: Math.min(Math.max(position.x, nodeExtent[0][0]), nodeExtent[1][0] - nodeWidth),\n y: Math.min(Math.max(position.y, nodeExtent[0][1]), nodeExtent[1][1] - nodeHeight),\n }\n }\n\n // ── Custom edge types ──────────────────────────────────────────────────\n // Custom edge rendering is handled in the Flow component via edgeTypes prop.\n // The flow instance provides the data; rendering is delegated to components.\n\n // ── Search / Filter ─────────────────────────────────────────────────────\n\n function findNodes(predicate: (node: FlowNode) => boolean): FlowNode[] {\n return nodes.peek().filter(predicate)\n }\n\n function searchNodes(query: string): FlowNode[] {\n const q = query.toLowerCase()\n return nodes.peek().filter((n) => {\n const label = (n.data?.label as string) ?? n.id\n return label.toLowerCase().includes(q)\n })\n }\n\n function focusNode(nodeId: string, focusZoom?: number): void {\n const node = getNode(nodeId)\n if (!node) return\n\n const w = node.width ?? 150\n const h = node.height ?? 40\n const centerX = node.position.x + w / 2\n const centerY = node.position.y + h / 2\n const z = focusZoom ?? viewport.peek().zoom\n const { width: cw, height: ch } = containerSize.peek()\n\n animateViewport({\n x: -centerX * z + cw / 2,\n y: -centerY * z + ch / 2,\n zoom: z,\n })\n\n // Select the focused node\n selectNode(nodeId)\n }\n\n // ── Export / Import ────────────────────────────────────────────────────\n\n function toJSON(): {\n nodes: FlowNode[]\n edges: FlowEdge[]\n viewport: { x: number; y: number; zoom: number }\n } {\n return {\n nodes: structuredClone(nodes.peek()),\n edges: structuredClone(edges.peek()),\n viewport: { ...viewport.peek() },\n }\n }\n\n function fromJSON(data: {\n nodes: FlowNode[]\n edges: FlowEdge[]\n viewport?: { x: number; y: number; zoom: number }\n }): void {\n batch(() => {\n nodes.set(data.nodes)\n edges.set(\n data.edges.map((e) => ({\n ...e,\n id: e.id ?? edgeId(e),\n type: e.type ?? defaultEdgeType,\n })),\n )\n if (data.viewport) viewport.set(data.viewport)\n clearSelection()\n })\n }\n\n // ── Viewport animation ─────────────────────────────────────────────────\n\n function animateViewport(\n target: Partial<{ x: number; y: number; zoom: number }>,\n duration = 300,\n ): void {\n const start = { ...viewport.peek() }\n const end = {\n x: target.x ?? start.x,\n y: target.y ?? start.y,\n zoom: target.zoom ?? start.zoom,\n }\n const startTime = performance.now()\n\n const frame = () => {\n const elapsed = performance.now() - startTime\n const t = Math.min(elapsed / duration, 1)\n const eased = 1 - (1 - t) ** 3 // ease-out cubic\n\n viewport.set({\n x: start.x + (end.x - start.x) * eased,\n y: start.y + (end.y - start.y) * eased,\n zoom: start.zoom + (end.zoom - start.zoom) * eased,\n })\n\n if (t < 1) requestAnimationFrame(frame)\n }\n\n requestAnimationFrame(frame)\n }\n\n // ── Dispose ──────────────────────────────────────────────────────────────\n\n function dispose(): void {\n connectListeners.clear()\n nodesChangeListeners.clear()\n nodeClickListeners.clear()\n edgeClickListeners.clear()\n nodeDragStartListeners.clear()\n nodeDragEndListeners.clear()\n nodeDoubleClickListeners.clear()\n }\n\n // ── Initial fitView ──────────────────────────────────────────────────────\n\n if (config.fitView) {\n fitView()\n }\n\n return {\n nodes,\n edges,\n viewport,\n zoom,\n containerSize,\n selectedNodes,\n selectedEdges,\n getNode,\n addNode,\n removeNode,\n updateNode,\n updateNodePosition,\n getEdge,\n addEdge,\n removeEdge,\n isValidConnection,\n selectNode,\n deselectNode,\n selectEdge,\n clearSelection,\n selectAll,\n deleteSelected,\n fitView,\n zoomTo,\n zoomIn,\n zoomOut,\n panTo,\n isNodeVisible,\n layout,\n batch: batchOp,\n getConnectedEdges,\n getIncomers,\n getOutgoers,\n onConnect,\n onNodesChange,\n onNodeClick,\n onEdgeClick,\n onNodeDragStart,\n onNodeDragEnd,\n onNodeDoubleClick,\n /** @internal — used by Flow component to emit events */\n _emit: {\n nodeDragStart: (node: FlowNode) => {\n for (const cb of nodeDragStartListeners) cb(node)\n },\n nodeDragEnd: (node: FlowNode) => {\n for (const cb of nodeDragEndListeners) cb(node)\n },\n nodeDoubleClick: (node: FlowNode) => {\n for (const cb of nodeDoubleClickListeners) cb(node)\n },\n nodeClick: (node: FlowNode) => {\n for (const cb of nodeClickListeners) cb(node)\n },\n edgeClick: (edge: FlowEdge) => {\n for (const cb of edgeClickListeners) cb(edge)\n },\n },\n copySelected,\n paste,\n pushHistory,\n undo,\n redo,\n moveSelectedNodes,\n getSnapLines,\n getChildNodes,\n getAbsolutePosition,\n addEdgeWaypoint,\n removeEdgeWaypoint,\n updateEdgeWaypoint,\n reconnectEdge,\n getProximityConnection,\n getOverlappingNodes,\n resolveCollisions,\n setNodeExtent,\n clampToExtent,\n findNodes,\n searchNodes,\n focusNode,\n toJSON,\n fromJSON,\n animateViewport,\n config,\n dispose,\n }\n}\n","/**\n * Default CSS styles for the flow diagram.\n * Inject via `<style>` tag or import in your CSS.\n *\n * @example\n * ```tsx\n * import { flowStyles } from '@pyreon/flow'\n *\n * // Inject once at app root\n * const style = document.createElement('style')\n * style.textContent = flowStyles\n * document.head.appendChild(style)\n * ```\n */\nexport const flowStyles = `\n/* ── Animated edges ────────────────────────────────────────────────────────── */\n\n.pyreon-flow-edge-animated {\n stroke-dasharray: 5;\n animation: pyreon-flow-edge-dash 0.5s linear infinite;\n}\n\n@keyframes pyreon-flow-edge-dash {\n to {\n stroke-dashoffset: -10;\n }\n}\n\n/* ── Node states ──────────────────────────────────────────────────────────── */\n\n.pyreon-flow-node {\n transition: box-shadow 0.15s ease;\n}\n\n.pyreon-flow-node.dragging {\n opacity: 0.9;\n filter: drop-shadow(0 4px 12px rgba(0, 0, 0, 0.15));\n cursor: grabbing;\n}\n\n.pyreon-flow-node.selected {\n filter: drop-shadow(0 0 0 2px rgba(59, 130, 246, 0.3));\n}\n\n/* ── Handles ──────────────────────────────────────────────────────────────── */\n\n.pyreon-flow-handle {\n transition: transform 0.1s ease, background 0.1s ease;\n}\n\n.pyreon-flow-handle:hover {\n transform: scale(1.4);\n background: #3b82f6 !important;\n}\n\n.pyreon-flow-handle-target:hover {\n background: #22c55e !important;\n border-color: #22c55e !important;\n}\n\n/* ── Resizer ──────────────────────────────────────────────────────────────── */\n\n.pyreon-flow-resizer {\n transition: background 0.1s ease, transform 0.1s ease;\n}\n\n.pyreon-flow-resizer:hover {\n background: #3b82f6 !important;\n transform: scale(1.2);\n}\n\n/* ── Selection box ────────────────────────────────────────────────────────── */\n\n.pyreon-flow-selection-box {\n pointer-events: none;\n border-radius: 2px;\n}\n\n/* ── MiniMap ──────────────────────────────────────────────────────────────── */\n\n.pyreon-flow-minimap {\n transition: opacity 0.2s ease;\n}\n\n.pyreon-flow-minimap:hover {\n opacity: 1 !important;\n}\n\n/* ── Node toolbar ─────────────────────────────────────────────────────────── */\n\n.pyreon-flow-node-toolbar {\n animation: pyreon-flow-toolbar-enter 0.15s ease;\n}\n\n@keyframes pyreon-flow-toolbar-enter {\n from {\n opacity: 0;\n transform: translateX(-50%) translateY(4px);\n }\n to {\n opacity: 1;\n transform: translateX(-50%) translateY(0);\n }\n}\n\n/* ── Controls ─────────────────────────────────────────────────────────────── */\n\n.pyreon-flow-controls button:hover {\n background: #f3f4f6 !important;\n}\n\n.pyreon-flow-controls button:active {\n background: #e5e7eb !important;\n}\n`\n"],"mappings":"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"}
|