void
+export type LayoutFunc = (nodes: Node[], edges: Edge[]) => Node[]
-export function useLayoutEngine(engine: LayoutEngine): LayoutFunc {
+export function useLayoutEngine() {
const { getNodes, getEdges, setNodes } = useReactFlow()
- return useCallback(() => {
+ return useCallback((engine?: LayoutEngine) => {
+ if (!engine) return
setNodes(computeLayout(engine, getNodes, getEdges))
- }, [engine])
+ }, [])
}
function computeLayout(
@@ -25,11 +23,19 @@ function computeLayout(
return layoutFn(getNodes(), getEdges())
}
+const layoutEngines: Record
= {}
+
+export function registerLayoutEngine(
+ engine: LayoutEngine,
+ layoutFn: LayoutFunc,
+) {
+ layoutEngines[engine] = layoutFn
+}
+
export function getLayoutFunction(
- engine: LayoutEngine | undefined,
+ engine: LayoutEngine,
): ((nodes: Node[], edges: Edge[]) => Node[]) | undefined {
- switch (engine) {
- case LayoutEngine.Dagre:
- return computeDagreLayout
- }
+ const layoutFn = layoutEngines[engine]
+ if (!layoutFn) throw new Error(`Unknown layout engine ${engine}`)
+ return layoutFn
}
diff --git a/lib/stories/ExampleNodeGraphEditor.tsx b/lib/stories/ExampleNodeGraphEditor.tsx
new file mode 100644
index 0000000..998d968
--- /dev/null
+++ b/lib/stories/ExampleNodeGraphEditor.tsx
@@ -0,0 +1,33 @@
+import {
+ Background,
+ BackgroundVariant,
+ Edge,
+ Node,
+} from '@xyflow/react'
+import { forwardRef } from "react"
+import { NodeGraphEditor, NodeGraphHandle } from "../NodeGraphEditor"
+import { GraphConfigProvider } from "../context/GraphConfigContext"
+import { useBuildGraphConfig } from '../hooks/config'
+import { IGraphConfig } from "../config"
+
+type ExampleNodeGraphEditorProps = {
+ nodes: Node[]
+ edges: Edge[]
+ config: IGraphConfig
+ }
+
+ export const ExampleNodeGraphEditor = forwardRef<
+ NodeGraphHandle,
+ ExampleNodeGraphEditorProps
+ >(({ nodes, edges, config: _config }: ExampleNodeGraphEditorProps, ref) => {
+ const config = useBuildGraphConfig(_config)
+ return (
+
+
+
+
+
+ )
+ })
+
+
\ No newline at end of file
diff --git a/lib/NodeGraphEditor.stories.tsx b/lib/stories/NodeGraphEditor.stories.tsx
similarity index 99%
rename from lib/NodeGraphEditor.stories.tsx
rename to lib/stories/NodeGraphEditor.stories.tsx
index bd61a79..be5bd20 100644
--- a/lib/NodeGraphEditor.stories.tsx
+++ b/lib/stories/NodeGraphEditor.stories.tsx
@@ -1,6 +1,6 @@
-import { ExampleNodeGraphEditor } from './NodeGraphEditor'
+import { ExampleNodeGraphEditor } from './ExampleNodeGraphEditor'
import { Meta, StoryObj } from '@storybook/react'
-import { IGraphConfig } from './config'
+import { IGraphConfig } from '../config'
const simpleConfig: IGraphConfig = {
valueTypes: {
diff --git a/lib/NodeGraphEditorCustomInput.stories.tsx b/lib/stories/NodeGraphEditorCustomInput.stories.tsx
similarity index 88%
rename from lib/NodeGraphEditorCustomInput.stories.tsx
rename to lib/stories/NodeGraphEditorCustomInput.stories.tsx
index 6fc0448..2fe3df0 100644
--- a/lib/NodeGraphEditorCustomInput.stories.tsx
+++ b/lib/stories/NodeGraphEditorCustomInput.stories.tsx
@@ -1,15 +1,15 @@
-import { NodeGraphEditor } from './NodeGraphEditor'
+import { NodeGraphEditor } from '../NodeGraphEditor.tsx'
import { Meta, StoryObj } from '@storybook/react'
-import { GraphConfigProvider } from './context/GraphConfigContext'
+import { GraphConfigProvider } from '../context/GraphConfigContext.tsx'
import {
Background,
BackgroundVariant,
Edge,
Node,
} from '@xyflow/react'
-import { useBuildGraphConfig } from './hooks/config.ts'
-import { NodeInputField } from './components/NodeInputField.tsx'
-import { InputProps } from './config.ts'
+import { useBuildGraphConfig } from '../hooks/config.ts'
+import { NodeInputField } from '../components/NodeInputField.tsx'
+import { InputProps } from '../config.ts'
const meta = {
title: 'Node Graph Editor',
diff --git a/lib/NodeGraphEditorCustomNode.stories.tsx b/lib/stories/NodeGraphEditorCustomNode.stories.tsx
similarity index 88%
rename from lib/NodeGraphEditorCustomNode.stories.tsx
rename to lib/stories/NodeGraphEditorCustomNode.stories.tsx
index ff41291..50a8cbb 100644
--- a/lib/NodeGraphEditorCustomNode.stories.tsx
+++ b/lib/stories/NodeGraphEditorCustomNode.stories.tsx
@@ -1,7 +1,7 @@
-import { NodeGraphEditor } from './NodeGraphEditor'
+import { NodeGraphEditor } from '../NodeGraphEditor'
import { Meta, StoryObj } from '@storybook/react'
-import { GraphConfigProvider } from './context/GraphConfigContext'
-import { GraphConfig } from './config'
+import { GraphConfigProvider } from '../context/GraphConfigContext'
+import { GraphConfig } from '../config'
import { useMemo } from 'react'
import {
Background,
@@ -10,9 +10,9 @@ import {
Node,
Position,
} from '@xyflow/react'
-import { NodeContainer } from './components/NodeContainer'
-import { useFocusBlur } from './hooks/focus'
-import { Handle } from './components/Handle'
+import { NodeContainer } from '../components/NodeContainer'
+import { useFocusBlur } from '../hooks/focus'
+import { Handle } from '../components/Handle'
const meta = {
title: 'Node Graph Editor',
diff --git a/lib/NodeGraphEditorInputGroups.stories.tsx b/lib/stories/NodeGraphEditorInputGroups.stories.tsx
similarity index 93%
rename from lib/NodeGraphEditorInputGroups.stories.tsx
rename to lib/stories/NodeGraphEditorInputGroups.stories.tsx
index 99ab04d..8f96c63 100644
--- a/lib/NodeGraphEditorInputGroups.stories.tsx
+++ b/lib/stories/NodeGraphEditorInputGroups.stories.tsx
@@ -1,16 +1,20 @@
-import { NodeGraphEditor } from './NodeGraphEditor'
+import { NodeGraphEditor } from '../NodeGraphEditor.tsx'
import { Meta, StoryObj } from '@storybook/react'
-import { GraphConfigProvider } from './context/GraphConfigContext'
+import { GraphConfigProvider } from '../context/GraphConfigContext.tsx'
import {
Background,
BackgroundVariant,
Edge,
Node,
} from '@xyflow/react'
-import { useBuildGraphConfig } from './hooks/config.ts'
-import { InputProps } from './config.ts'
+import { useBuildGraphConfig } from '../hooks/config.ts'
+import { InputProps } from '../config.ts'
import { Wheel } from '@uiw/react-color'
-import { useNodeFieldValue } from './hooks/node.ts'
+import { useNodeFieldValue } from '../hooks/node.ts'
+import { registerLayoutEngine } from '../layout/layout.ts'
+import { computeDagreLayout } from '../layout/dagre.ts'
+
+registerLayoutEngine('dagre', computeDagreLayout)
const meta = {
title: 'Node Graph Editor',
@@ -201,8 +205,8 @@ const meta = {
)
return (
-
-
+
+
)
diff --git a/lib/NodeGraphEditorLayout.stories.tsx b/lib/stories/NodeGraphEditorLayout.stories.tsx
similarity index 86%
rename from lib/NodeGraphEditorLayout.stories.tsx
rename to lib/stories/NodeGraphEditorLayout.stories.tsx
index d394a3d..d09df4f 100644
--- a/lib/NodeGraphEditorLayout.stories.tsx
+++ b/lib/stories/NodeGraphEditorLayout.stories.tsx
@@ -1,6 +1,11 @@
-import { ExampleNodeGraphEditor, NodeGraphHandle } from './NodeGraphEditor'
+import { ExampleNodeGraphEditor } from './ExampleNodeGraphEditor'
+import { NodeGraphHandle } from '../NodeGraphEditor'
import { Meta, StoryObj } from '@storybook/react'
import { useRef } from 'react'
+import { registerLayoutEngine } from '../layout/layout'
+import { computeDagreLayout } from '../layout/dagre'
+
+registerLayoutEngine('dagre', computeDagreLayout)
const meta = {
title: 'Node Graph Editor',
@@ -8,12 +13,14 @@ const meta = {
const ref = useRef(null)
return (
-
+
+
+