sample-ui-component-library 0.0.40-dev → 0.0.43-dev

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sample-ui-component-library",
3
- "version": "0.0.40-dev",
3
+ "version": "0.0.43-dev",
4
4
  "description": "A library which contains sample UI elements that can be used for populating layouts.",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -68,6 +68,8 @@
68
68
  "@dagrejs/dagre": "^1.1.4",
69
69
  "@monaco-editor/react": "^4.7.0",
70
70
  "@xyflow/react": "^12.6.0",
71
- "react-bootstrap-icons": "^1.11.5"
71
+ "dal-engine-core-js-lib-dev": "^0.0.4",
72
+ "react-bootstrap-icons": "^1.11.5",
73
+ "reaflow": "^5.4.1"
72
74
  }
73
75
  }
@@ -1,32 +1,107 @@
1
- import { Flow } from "./Flow";
2
- import { ReactFlowProvider } from "@xyflow/react";
3
- import { useEffect, useState } from "react";
4
- import { designToReactFlowElements } from "./helper";
5
-
6
- export const BehavioralGraphBuilder = ({
7
- activeTool,
8
- onBehaviorSelect,
9
- onAddBehavior,
10
- onAddEdge,
11
- design,
12
- }) => {
13
- const [initialElements, setInitialElements] = useState(null);
1
+ import { useEffect, useState, useRef, useImperativeHandle, forwardRef, useMemo, useCallback } from "react";
2
+ import { Canvas, Node, Edge, removeAndUpsertNodes } from 'reaflow';
3
+ import PropTypes from 'prop-types';
14
4
 
5
+ import { designToNodes } from "./helper";
6
+
7
+ import "./BehavioralGraphBuilder.scss";
8
+
9
+ /**
10
+ * Renders a behavioral graph editor component using reaflow.
11
+ *
12
+ * @return {JSX}
13
+ */
14
+ export const BehavioralGraphBuilder = forwardRef(({connectBehaviors, deleteTransition, deleteBehavior}, ref) => {
15
+ const canvasRef = useRef();
16
+
17
+ // Resizer to set canvas size to match container
18
+ // TODO: Issues with zooming and resizing, need to explore.
19
+ const containerRef = useRef();
20
+ const [size, setSize] = useState({ width: 0, height: 0 });
15
21
  useEffect(() => {
16
- if (design) {
17
- setInitialElements(designToReactFlowElements(design));
22
+ const observer = new ResizeObserver(([entry]) => {
23
+ const { width, height } = entry.contentRect;
24
+ setSize({ width, height });
25
+ });
26
+
27
+ if (containerRef.current) observer.observe(containerRef.current);
28
+ return () => observer.disconnect();
29
+ }, []);
30
+
31
+
32
+ const [edges, setEdges] = useState([]);
33
+ const [nodes, setNodes] = useState([]);
34
+ const [selections, setSelections] = useState([]);
35
+ '1'
36
+ const onNodeLink =(_event, from, to) => {
37
+ connectBehaviors(from, to);
38
+ }
39
+
40
+ const updateEngine = useCallback((engine) => {
41
+ if (engine) {
42
+ const { nodes, edges } = designToNodes(engine);
43
+ setNodes(nodes);
44
+ setEdges(edges);
18
45
  }
19
- }, [design]);
46
+ }, [setNodes, setEdges]);
47
+
48
+ const api = useMemo(() => {
49
+ return {
50
+ updateEngine
51
+ };
52
+ }, [updateEngine]);
53
+
54
+ useImperativeHandle(ref, () => api, [api]);
55
+
56
+ const handleWheel = useCallback((e) => {
57
+ if (e.deltaY < 0) {
58
+ canvasRef.current.zoomIn()
59
+ } else {
60
+ canvasRef.current.zoomOut();
61
+ }
62
+ }, [canvasRef]);
20
63
 
21
64
  return (
22
- <ReactFlowProvider>
23
- <Flow
24
- initialElements={initialElements}
25
- activeTool={activeTool}
26
- onBehaviorSelect={onBehaviorSelect}
27
- onAddBehavior={onAddBehavior}
28
- onAddEdge={onAddEdge}
65
+ <div onWheel={handleWheel} ref={containerRef} className="canvas-wrapper">
66
+ <Canvas
67
+ ref={canvasRef}
68
+ nodes={nodes}
69
+ edges={edges}
70
+ width={size.width}
71
+ height={size.height}
72
+ onNodeLink={onNodeLink}
73
+ panType="drag"
74
+ selections={selections}node={
75
+ <Node
76
+ onClick={(event, node) => {
77
+ setSelections([node.id]);
78
+ }}
79
+ onRemove={(event, node) => {
80
+ deleteBehavior(node);
81
+ setSelections([]);
82
+ }}
83
+ />
84
+ }
85
+ edge={
86
+ <Edge
87
+ onClick={(event, edge) => {
88
+ setSelections([edge.id]);
89
+ }}
90
+ onRemove={(event, edge) => {
91
+ deleteTransition(edge);
92
+ setSelections([]);
93
+ }}
94
+ />
95
+ }
96
+ onCanvasClick={(event) => {setSelections([]);}}
97
+ fit
98
+ center
29
99
  />
30
- </ReactFlowProvider>
31
- );
32
- };
100
+ </div>
101
+ )
102
+ });
103
+
104
+ BehavioralGraphBuilder.propTypes = {
105
+ connectBehaviors: PropTypes.func.isRequired,
106
+ deleteBehavior: PropTypes.func.isRequired
107
+ }
@@ -0,0 +1,12 @@
1
+
2
+ .canvas-wrapper {
3
+ position: relative;
4
+ width: 100%;
5
+ height: 100%;
6
+ background-color: #1b1c1d;
7
+ overflow:hidden;
8
+ }
9
+
10
+ canvas {
11
+ overflow: hidden;
12
+ }
@@ -4,32 +4,36 @@
4
4
  * @param {Object} design
5
5
  * @returns {Object} An object containing nodes and edges for React Flow
6
6
  */
7
- export const designToReactFlowElements = (design) => {
7
+ export const designToNodes = (engine) => {
8
8
 
9
9
  let edges = [];
10
10
  let nodes = [];
11
- design.nodes.forEach((node) => {
11
+
12
+ for (let i = 0; i < engine.graph.nodes.length; i++) {
13
+ const node = engine.graph.nodes[i];
12
14
  nodes.push({
13
- id: node.behavior.uid,
14
- type: 'default',
15
- data: { label: node.behavior.name },
16
- position: { x: 10, y: 10 },
15
+ id: node.getBehavior().name,
16
+ text: node.getBehavior().name,
17
17
  });
18
+ }
19
+
20
+ for (let i = 0; i < engine.graph.nodes.length; i++) {
21
+ const node = engine.graph.nodes[i];
22
+ if (!node?.getGoToBehaviors()) {
23
+ continue;
24
+ }
18
25
 
19
- node.goToBehaviors.forEach((goTo) => {
26
+ node.getGoToBehaviors().forEach((goTo) => {
20
27
  edges.push({
21
- id: `${node.behavior.uid}->${goTo.uid}`,
22
- type: "bezier",
23
- source: node.behavior.uid,
24
- target: goTo.uid,
25
- animated: true
28
+ id: `${node.getBehavior().name}->${goTo}`,
29
+ from: node.getBehavior().name,
30
+ to: goTo,
26
31
  });
27
32
  });
28
- });
33
+ }
29
34
 
30
35
  return {
31
36
  nodes: nodes,
32
37
  edges: edges
33
38
  };
34
-
35
39
  }
@@ -13,5 +13,8 @@
13
13
  }
14
14
 
15
15
  .flow {
16
+ display: flex;
16
17
  flex-grow: 1;
17
- }
18
+ flex-direction: column;
19
+ overflow:hidden;
20
+ }
@@ -1,66 +1,115 @@
1
- import { useCallback, useState, useEffect } from "react";
2
- import { BehavioralGraphBuilder } from "../components/BehavioralGraphBuilder";
3
- import { ToolBar } from "./components/ToolBar/ToolBar";
1
+ import { useEffect, useState, useCallback, useRef } from "react";
4
2
  import { useArgs } from "@storybook/preview-api";
5
3
  import { action } from "@storybook/addon-actions";
6
4
 
7
- import design from "./data/Designs/simple_design_temp.json";
8
- import "./BehavioralGraphBuilderStories.scss"
5
+ import { BehavioralGraphBuilder } from "../components/BehavioralGraphBuilder/BehavioralGraphBuilder";
6
+ import { ToolBar } from "./components/ToolBar/ToolBar";
7
+
8
+ import { DALEngine } from "dal-engine-core-js-lib-dev";
9
+
10
+ import design from "./data/Designs/simple_designs_temp.json";
11
+
12
+ import "./BehavioralGraphBuilder.scss";
9
13
 
10
14
  export default {
11
- title: 'BehavioralGraphBuilder',
15
+ title: "BehavioralGraphBuilder",
12
16
  component: BehavioralGraphBuilder,
13
- argTypes: {
14
- }
17
+ argTypes: {},
15
18
  };
16
19
 
20
+ let count = 0;
21
+
17
22
  const Template = (args) => {
18
23
  const [, updateArgs] = useArgs();
19
24
 
25
+ const editorRef = useRef();
26
+
27
+ const [engine, setEngine] = useState();
28
+
20
29
  const [activeTool, setActiveTool] = useState("select");
21
30
 
22
- const selectTool = useCallback((tool) => {
23
- updateArgs({activeTool : tool});
24
- }, [activeTool, setActiveTool]);
31
+ const selectTool = useCallback(
32
+ (tool) => {
33
+ updateArgs({ activeTool: tool });
34
+ setActiveTool(tool);
25
35
 
26
- const onBehaviorSelect = useCallback((behavior) => {
27
- action('Selected Behavior:')(behavior);
28
- }, []);
36
+ if (tool === "add-node") {
37
+ engine.addNode("node-" + count++, []);
38
+ editorRef.current.updateEngine(engine);
39
+ }
40
+ },
41
+ [activeTool, setActiveTool, engine],
42
+ );
29
43
 
30
- const onAddBehavior = useCallback((behavior) => {
31
- action('Added Behavior:')(behavior);
44
+ useEffect(() => {
45
+ updateArgs({
46
+ activeTool: activeTool,
47
+ design: design,
48
+ });
32
49
  }, []);
33
50
 
34
- const onAddEdge = useCallback((edge) => {
35
- action('Added Edge:')(edge);
36
- }, []);
37
-
38
51
  useEffect(() => {
39
- updateArgs(
40
- {
41
- activeTool: activeTool,
42
- design: design,
43
- onBehaviorSelect: onBehaviorSelect,
44
- onAddBehavior: onAddBehavior,
45
- onAddEdge: onAddEdge
46
- }
47
- );
48
- }, []);
52
+ if (editorRef.current) {
53
+ const engine = new DALEngine({ name: "testEngine" });
54
+ // engine.deserialize(JSON.stringify(design));
55
+ setEngine(engine);
56
+ editorRef.current.updateEngine(engine);
57
+ setTimeout(() => {
58
+ engine.addNode("testBehavior", []);
59
+ engine.addNode("testBehavior2", []);
60
+ editorRef.current.updateEngine(engine);
61
+ }, 4000);
62
+ }
63
+ }, [design, editorRef]);
49
64
 
65
+ const connectBehaviors = useCallback(
66
+ (from, to) => {
67
+ if (!to) return;
68
+ action("Connect Behaviors")(from, to);
69
+ engine.getNode(from.id).addGoToBehavior(to.id);
70
+ editorRef.current.updateEngine(engine);
71
+ },
72
+ [editorRef, engine],
73
+ );
74
+
75
+ const deleteBehavior = useCallback(
76
+ (node) => {
77
+ action("Delete Behavior")(node);
78
+ engine.removeNode(node.id);
79
+ editorRef.current.updateEngine(engine);
80
+ },
81
+ [engine, editorRef],
82
+ );
83
+
84
+ const deleteTransition = useCallback(
85
+ (edge) => {
86
+ action("Delete Transition")(edge);
87
+ const fromNode = engine.getNode(edge.from);
88
+ fromNode.removeGoToBehavior(edge.to);
89
+ editorRef.current.updateEngine(engine);
90
+ },
91
+ [engine, editorRef],
92
+ );
50
93
  return (
51
94
  <div className="graphBuilderRootContainer">
52
95
  <div className="toolbar">
53
- <ToolBar onSelectTool={selectTool}/>
96
+ <ToolBar onSelectTool={selectTool} />
54
97
  </div>
55
98
  <div className="flow">
56
- <BehavioralGraphBuilder {...args}/>
99
+ <BehavioralGraphBuilder
100
+ ref={editorRef}
101
+ {...args}
102
+ connectBehaviors={connectBehaviors}
103
+ deleteTransition={deleteTransition}
104
+ deleteBehavior={deleteBehavior}
105
+ />
57
106
  </div>
58
107
  </div>
59
- )
60
- }
108
+ );
109
+ };
61
110
 
62
- export const Default = Template.bind({})
111
+ export const Default = Template.bind({});
63
112
 
64
113
  Default.args = {
65
- design: design
66
- }
114
+ design: design,
115
+ };
@@ -1,10 +1,8 @@
1
1
  import React, { useState } from "react";
2
2
 
3
3
  import {
4
- Cursor,
5
- Square,
6
- NodePlus,
7
- Trash
4
+ PlusSquare,
5
+ Floppy
8
6
  } from "react-bootstrap-icons";
9
7
 
10
8
  import "./ToolBar.scss";
@@ -26,32 +24,18 @@ export function ToolBar({ onSelectTool }) {
26
24
  return (
27
25
  <div className="toolbarWrapper">
28
26
  <div className="toolbarContainer">
29
- <Cursor
30
- onClick={(e) => selectTool("select")}
31
- style={{color: selectedTool === "select" ? "white": "grey"}}
32
- title="Select"
33
- className="icon"
34
- />
35
- <Square
36
- onClick={(e) => selectTool("drop")}
37
- style={{color: selectedTool === "drop" ? "white": "grey"}}
27
+ <PlusSquare
28
+ onClick={(e) => selectTool("add-node")}
38
29
  title="Add Node"
39
30
  className="icon"
40
31
  />
41
- <NodePlus
42
- onClick={(e) => selectTool("connect")}
43
- style={{color: selectedTool === "connect" ? "white": "grey"}}
44
- title="Connect Node"
45
- className="icon"
46
- />
47
- <Trash
48
- onClick={(e) => selectTool("delete")}
49
- style={{color: selectedTool === "delete" ? "white": "grey"}}
50
- title="Delete Node"
51
- className="icon"
52
- />
53
32
  </div>
54
33
  <div className="toolbarContainer bottom"></div>
34
+ <Floppy
35
+ onClick={(e) => selectTool("save")}
36
+ title="Save Design"
37
+ className="icon"
38
+ />
55
39
  </div>
56
40
  );
57
41
  }
@@ -0,0 +1 @@
1
+ {"uid":"3b9b65ab-5e3e-48a7-871c-c76de3e20187","type":5,"nodes":[{"uid":"2038c653-587d-4c33-9103-43b59d85c5be","type":6,"_behavior":{"uid":"19ffb9d9-772b-4aca-89b5-6278e0cbee89","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"AcceptChoiceToAddBookToBasket"},"_goToBehaviorIds":["AcceptBookFromUser"]},{"uid":"98d6a9b8-3867-49c8-a93a-f0e11f70af3b","type":6,"_behavior":{"uid":"d1157a53-5938-42ca-92ad-d2d34d99c704","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"AcceptBookFromUser"},"_goToBehaviorIds":["AddBookToBasket"]},{"uid":"2aeb336f-37cc-4f28-8301-f3464c387603","type":6,"_behavior":{"uid":"0dc90e9c-6342-4c3d-90f7-5e5e89b48b76","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"AddBookToBasket"},"_goToBehaviorIds":[]},{"uid":"763e440b-8c09-4893-8e21-b7af11722d93","type":6,"_behavior":{"uid":"555f261d-00b8-4f2d-ad1d-7d18fb68a035","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"AcceptChoiceToAuditLibrary"},"_goToBehaviorIds":["GenerateAuditReport"]},{"uid":"92ba2c22-3beb-442c-a198-562779d7936c","type":6,"_behavior":{"uid":"d44d5d9c-f0f5-4542-9b7d-21793ea1995c","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"GenerateAuditReport"},"_goToBehaviorIds":["HandAuditToUser"]},{"uid":"f2e7e018-2596-4aeb-abeb-55948a17157c","type":6,"_behavior":{"uid":"17ac5068-a521-4fbd-9dcb-783d365e01fd","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"HandAuditToUser"},"_goToBehaviorIds":[]},{"uid":"e89cefaa-cdda-450e-808e-ffee9250db01","type":6,"_behavior":{"uid":"4db0dab8-3d4c-4668-88de-e73f38d8c28e","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"AcceptChoiceToPlaceBooksOnShelf"},"_goToBehaviorIds":[]},{"uid":"4d1de6bd-cd98-48de-81ed-9754b40c3a36","type":6,"_behavior":{"uid":"0ddc2e33-2b01-411b-a3ae-9f0198fafaf8","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"GetFirstLetterOfBookName"},"_goToBehaviorIds":["CreateSlotOnBookShelf","AddBookToShelf"]},{"uid":"e8e5ffe7-ba16-4c3e-a87f-2083c2502812","type":6,"_behavior":{"uid":"eefbf993-c76b-4c80-bb8d-e3093aaa17cb","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"CreateSlotOnBookShelf"},"_goToBehaviorIds":["AddBookToShelf"]},{"uid":"2fb19dc7-7647-44c1-afd1-4a157ab3d833","type":6,"_behavior":{"uid":"e4092d6e-49bb-4c54-9573-0379466c4ae6","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"AddBookToShelf"},"_goToBehaviorIds":[]}]}
@@ -1,33 +0,0 @@
1
-
2
- import Dagre from '@dagrejs/dagre';
3
-
4
- export const getLayoutedElements = (nodes, edges, options) => {
5
- // Reference: https://reactflow.dev/learn/layouting/layouting
6
-
7
- const g = new Dagre.graphlib.Graph().setDefaultEdgeLabel(() => ({}));
8
- g.setGraph({ rankdir: options.direction, ranksep: 100, nodesep: 170});
9
-
10
- edges.forEach((edge) => g.setEdge(edge.source, edge.target));
11
- nodes.forEach((node) =>
12
- g.setNode(node.id, {
13
- ...node,
14
- width: node.measured?.width ?? 0,
15
- height: node.measured?.height ?? 0,
16
- }),
17
- );
18
-
19
- Dagre.layout(g);
20
-
21
- return {
22
- nodes: nodes.map((node) => {
23
- const position = g.node(node.id);
24
- // We are shifting the dagre node position (anchor=center center) to the top left
25
- // so it matches the React Flow node anchor point (top left).
26
- const x = position.x - (node.measured?.width ?? 0) / 2;
27
- const y = position.y - (node.measured?.height ?? 0) / 2;
28
-
29
- return { ...node, position: { x, y } };
30
- }),
31
- edges,
32
- };
33
- };
@@ -1,164 +0,0 @@
1
- import { useCallback, useEffect, useState } from "react";
2
- import {
3
- ReactFlow,
4
- ReactFlowProvider,
5
- useNodesState,
6
- useEdgesState,
7
- Background,
8
- Controls,
9
- useReactFlow,
10
- addEdge,
11
- BezierEdge ,
12
- applyNodeChanges,
13
- applyEdgeChanges
14
- } from "@xyflow/react";
15
- import "@xyflow/react/dist/style.css";
16
-
17
- import { getLayoutedElements } from "./DagreLayout.js";
18
-
19
- const edgeTypes = {
20
- bezier: BezierEdge,
21
- };
22
-
23
- const NODE_WIDTH = 150;
24
- const NODE_HEIGHT = 40;
25
- export const Flow = ({ activeTool, onBehaviorSelect, onAddBehavior, onAddEdge, initialElements }) => {
26
- const { screenToFlowPosition } = useReactFlow();
27
- const [nodes, setNodes] = useState([]);
28
- const [edges, setEdges] = useState([]);
29
- const [ghostNode, setGhostNode] = useState(null);
30
-
31
- useEffect(() => {
32
- if (!initialElements) return;
33
- const layouted = getLayoutedElements(
34
- initialElements.nodes,
35
- initialElements.edges,
36
- {direction:"TB"}
37
- );
38
-
39
- setNodes([...layouted.nodes]);
40
- setEdges([...layouted.edges]);
41
- }, [initialElements]);
42
-
43
- // Callbacks to apply node changes
44
- const onNodesChange = useCallback((changes) => {
45
- setNodes((nds) => applyNodeChanges(changes, nds));
46
- }, []);
47
- const onEdgesChange = useCallback((changes) => {
48
- setEdges((eds) => applyEdgeChanges(changes, eds));
49
- }, []);
50
-
51
- // Console messages for debugging
52
- useEffect(() => {
53
- console.log("Active Tool:", activeTool);
54
- }, [activeTool]);
55
-
56
- // Callback for mouse pane move
57
- const onPaneMouseMove = useCallback( (event) => {
58
- const pos = screenToFlowPosition({
59
- x: event.clientX,
60
- y: event.clientY,
61
- });
62
-
63
- if (activeTool === "drop") {
64
- setGhostNode({
65
- id: "ghost",
66
- position: {
67
- x: pos.x - NODE_WIDTH / 2,
68
- y: pos.y - NODE_HEIGHT / 2,
69
- },
70
- data: { label: "Behavior" },
71
- draggable: false,
72
- selectable: false,
73
- style: {
74
- opacity: 0.5,
75
- pointerEvents: "none",
76
- width: NODE_WIDTH,
77
- height: NODE_HEIGHT,
78
- },
79
- });
80
- }
81
- }, [activeTool]);
82
-
83
- // Callback for when mouse leaves pane
84
- const onPaneMouseLeave = useCallback(() => {
85
- setGhostNode(null);
86
- }, []);
87
-
88
- // Callback for pane click
89
- const onPaneClick = useCallback((event, node) => {
90
- if (activeTool === "drop") {
91
- if (!ghostNode) return;
92
- setNodes((nds) => [
93
- ...nds,
94
- {
95
- ...ghostNode,
96
- draggable: true,
97
- selectable: true,
98
- id: crypto.randomUUID(),
99
- style: {},
100
- },
101
- ]);
102
- onAddBehavior(ghostNode);
103
- setGhostNode(null);
104
- }
105
- }, [ghostNode, activeTool, onAddBehavior]);
106
-
107
- // Callback for node click to delete it (if tool is active)
108
- const onNodeClick = useCallback((event, node) => {
109
- if (activeTool === "delete") {
110
- setNodes((nds) => nds.filter((n) => n.id !== node.id));
111
- setEdges((eds) =>
112
- eds.filter((e) => e.source !== node.id && e.target !== node.id)
113
- );
114
- }
115
- }, [activeTool, onBehaviorSelect]);
116
-
117
- // Callback for edge click to delete it (if tool is active)
118
- const onEdgeClick = useCallback((event, edge) => {
119
- if (activeTool === "delete") {
120
- setEdges((eds) => eds.filter((e) => e.id !== edge.id));
121
- }
122
- }, [activeTool]);
123
-
124
- const onSelectionChange = useCallback((selection) => {
125
- if (selection.nodes.length > 0) {
126
- onBehaviorSelect(selection.nodes[0]);
127
- }
128
- }, [ onBehaviorSelect]);
129
-
130
- // Callback for when edge is connected, nodesConnectable={activeTool === "connect"}
131
- // is used to determine connectability
132
- const onConnect = useCallback((connection) => {
133
- const edge = {
134
- ...connection,
135
- id: crypto.randomUUID(),
136
- type: "smoothstep",
137
- animated: true,
138
- };
139
- setEdges((eds) => [...eds, edge]);
140
- onAddEdge(edge);
141
- }, [activeTool, onAddEdge]);
142
-
143
- return (
144
- <ReactFlow
145
- nodes={ghostNode ? [...nodes, ghostNode] : nodes}
146
- edges={edges}
147
- onPaneMouseMove={onPaneMouseMove}
148
- onPaneMouseLeave={onPaneMouseLeave}
149
- onPaneClick={onPaneClick}
150
- onConnect={onConnect}
151
- onNodesChange={onNodesChange}
152
- onEdgesChange={onEdgesChange}
153
- onNodeClick={onNodeClick}
154
- onEdgeClick={onEdgeClick}
155
- colorMode={"dark"}
156
- edgeTypes={edgeTypes}
157
- onSelectionChange={onSelectionChange}
158
- fitView
159
- >
160
- <Background />
161
- <Controls />
162
- </ReactFlow>
163
- );
164
- };
@@ -1 +0,0 @@
1
- {"uid":"60e79b4f-fc4b-4237-989f-e1b1559c2ee9","type":5,"nodes":[{"uid":"08a4e18c-f293-4ba1-be0a-c8451b50e819","type":6,"goToBehaviors":[{"uid":"35a2759b-e0df-47db-93b7-1f18c216922d","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"AcceptBookFromUser"}],"behavior":{"uid":"a873c4ba-3a63-4097-80df-46ed361f2e26","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"AcceptChoiceToAddBookToBasket"}},{"uid":"db74773a-2f47-4873-b66f-08da9aaf196f","type":6,"goToBehaviors":[{"uid":"ac522716-13d2-48e5-b241-f2366b37efdb","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"AddBookToBasket"}],"behavior":{"uid":"35a2759b-e0df-47db-93b7-1f18c216922d","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"AcceptBookFromUser"}},{"uid":"31bba9d3-9af2-41bc-bd70-d757f62b40c6","type":6,"goToBehaviors":[{"uid":"d4ec5fe5-acd2-4a8b-8e09-9ea3d5212a1f","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"GenerateAuditReport"}],"behavior":{"uid":"53cebd65-5c19-4dde-8e50-4acc581dc166","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"AcceptChoiceToAuditLibrary"}},{"uid":"836fdec5-db3e-4770-95fe-70c2d2c1261c","type":6,"goToBehaviors":[{"uid":"3e0b400c-f92a-48b5-b67b-e65d69f18a21","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"HandAuditToUser"}],"behavior":{"uid":"d4ec5fe5-acd2-4a8b-8e09-9ea3d5212a1f","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"GenerateAuditReport"}},{"uid":"f79c407e-66fc-4d64-bcce-4a1c4841d098","type":6,"goToBehaviors":[{"uid":"1c75d75c-8970-4dd1-b91e-c79590354bd9","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"GetBookFromBasket"}],"behavior":{"uid":"b39dfb15-d121-4ded-aa29-d317149308e9","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"AcceptChoiceToPlaceBooksOnShelf"}},{"uid":"0e266610-d498-4857-9249-7e6c98a1077f","type":6,"goToBehaviors":[{"uid":"7e80caf3-7fa9-4684-af89-fe2556addb87","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"GetFirstLetterOfBookName"}],"behavior":{"uid":"1c75d75c-8970-4dd1-b91e-c79590354bd9","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"GetBookFromBasket"}},{"uid":"b009ee09-e037-4864-99a2-15f80187623f","type":6,"goToBehaviors":[{"uid":"457332a3-3c79-4c04-83c7-2b5b0539c0da","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"CreateSlotOnBookShelf"}],"behavior":{"uid":"7e80caf3-7fa9-4684-af89-fe2556addb87","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"GetFirstLetterOfBookName"}},{"uid":"b2acd6d3-d6b8-41de-b8a1-f22b4db4fcbe","type":6,"goToBehaviors":[{"uid":"a666f210-c00c-48bc-a13f-aea72f068e37","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"AddBookToShelf"}],"behavior":{"uid":"7e80caf3-7fa9-4684-af89-fe2556addb87","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"GetFirstLetterOfBookName"}},{"uid":"3baca40a-9584-4ba7-be1b-235a660ca472","type":6,"goToBehaviors":[{"uid":"a666f210-c00c-48bc-a13f-aea72f068e37","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"AddBookToShelf"}],"behavior":{"uid":"457332a3-3c79-4c04-83c7-2b5b0539c0da","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"CreateSlotOnBookShelf"}},{"uid":"14acf45d-ca77-48f4-9ff0-5692133a6258","type":6,"goToBehaviors":[{"uid":"1c75d75c-8970-4dd1-b91e-c79590354bd9","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"GetBookFromBasket"}],"behavior":{"uid":"a666f210-c00c-48bc-a13f-aea72f068e37","type":1,"participants":[],"abstractionIds":[],"invalidWorldState":false,"name":"AddBookToShelf"}}]}