@bemedev/mind-flow 0.0.1 → 0.1.0
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 +95 -0
- package/lib/helpers/createContext.d.ts +5 -8
- package/lib/helpers/createContext.d.ts.map +1 -1
- package/lib/index.cjs.js +1 -1
- package/lib/index.es.js +240 -235
- package/lib/server.cjs.js +148 -117
- package/lib/server.es.js +148 -117
- package/lib/services/main.machine.d.ts +7 -9
- package/lib/services/main.machine.d.ts.map +1 -1
- package/lib/services/main.typings.d.ts +2 -2
- package/lib/ui/Flow.d.ts +2 -2
- package/lib/ui/Flow.d.ts.map +1 -1
- package/lib/ui/components/Bounds.d.ts +4 -4
- package/lib/ui/components/Bounds.d.ts.map +1 -1
- package/lib/ui/components/EdgeComponent.d.ts +2 -2
- package/lib/ui/components/EdgeComponent.d.ts.map +1 -1
- package/lib/ui/components/EdgesBoard.d.ts +2 -2
- package/lib/ui/components/EdgesBoard.d.ts.map +1 -1
- package/lib/ui/components/FlowChart.context.d.ts +10 -18
- package/lib/ui/components/FlowChart.context.d.ts.map +1 -1
- package/lib/ui/components/FlowChart.d.ts +4 -10
- package/lib/ui/components/FlowChart.d.ts.map +1 -1
- package/lib/ui/components/FlowChart.data.d.ts +6 -10
- package/lib/ui/components/FlowChart.data.d.ts.map +1 -1
- package/lib/ui/components/NodeComponent.d.ts +2 -2
- package/lib/ui/components/NodeComponent.d.ts.map +1 -1
- package/lib/ui/components/NodesBoard.d.ts +2 -2
- package/lib/ui/components/NodesBoard.d.ts.map +1 -1
- package/lib/ui/components/classes.d.ts +2 -2
- package/package.json +2 -2
- package/src/README.md +2 -2
- package/src/helpers/createContext.ts +5 -8
- package/src/services/main.machine.ts +18 -46
- package/src/services/main.typings.ts +2 -2
- package/src/ui/Flow.tsx +3 -2
- package/src/ui/components/Bounds.tsx +35 -44
- package/src/ui/components/EdgeComponent.tsx +7 -8
- package/src/ui/components/EdgesBoard.tsx +3 -2
- package/src/ui/components/FlowChart.context.ts +56 -82
- package/src/ui/components/FlowChart.data.ts +8 -14
- package/src/ui/components/FlowChart.tsx +6 -11
- package/src/ui/components/NodeComponent.tsx +13 -25
- package/src/ui/components/NodesBoard.tsx +109 -111
- package/src/ui/components/classes.ts +2 -2
|
@@ -2,6 +2,7 @@ import { interpret } from '@bemedev/app';
|
|
|
2
2
|
import { dequal } from 'dequal/lite';
|
|
3
3
|
import { createSignal } from 'solid-js';
|
|
4
4
|
import { produce } from 'solid-js/store';
|
|
5
|
+
|
|
5
6
|
import { createContext } from '../../helpers/createContext';
|
|
6
7
|
import { machine } from '../../services/main.machine';
|
|
7
8
|
import type { Point, Vector } from '../../services/main.typings';
|
|
@@ -29,56 +30,50 @@ type Dimensions = {
|
|
|
29
30
|
};
|
|
30
31
|
|
|
31
32
|
/** Connection edge coordinate representation between two endpoints. */
|
|
32
|
-
|
|
33
|
+
type Edge = {
|
|
33
34
|
/** Source node identifier. */
|
|
34
35
|
from: string;
|
|
35
|
-
|
|
36
|
-
x0: number;
|
|
37
|
-
/** Starting Y-coordinate. */
|
|
38
|
-
y0: number;
|
|
39
|
-
/** Ending X-coordinate. */
|
|
40
|
-
x1: number;
|
|
41
|
-
/** Ending Y-coordinate. */
|
|
42
|
-
y1: number;
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Shared state machine interpreter service instance for flowchart state
|
|
47
|
-
* management.
|
|
48
|
-
*/
|
|
49
|
-
const service = interpret(machine, {
|
|
50
|
-
context: {},
|
|
51
|
-
pContext: { generatedId: null },
|
|
52
|
-
});
|
|
36
|
+
} & Vector;
|
|
53
37
|
|
|
54
38
|
/**
|
|
55
|
-
* Solid Context Provider component and hook for accessing flowchart board
|
|
56
|
-
*
|
|
39
|
+
* Solid Context Provider component and hook for accessing flowchart board state,
|
|
40
|
+
* services, and zoom.
|
|
57
41
|
*/
|
|
58
42
|
export const [Provider, useFlow] = createContext(
|
|
59
43
|
() => {
|
|
44
|
+
/**
|
|
45
|
+
* Shared state machine interpreter service instance for flowchart state
|
|
46
|
+
* management.
|
|
47
|
+
*/
|
|
48
|
+
const service = interpret(machine, {
|
|
49
|
+
context: {},
|
|
50
|
+
pContext: { generatedId: null },
|
|
51
|
+
});
|
|
52
|
+
|
|
60
53
|
const zoom = createSignal(1);
|
|
61
54
|
const newEdge = createSignal<Edge>();
|
|
62
55
|
const [boardRef, setBoardRef] = createSignal<HTMLDivElement>();
|
|
63
56
|
|
|
64
|
-
const [dimensions, setDimensions] = createSignal<
|
|
65
|
-
|
|
66
|
-
|
|
57
|
+
const [dimensions, setDimensions] = createSignal<Record<string, Dimensions>>(
|
|
58
|
+
{},
|
|
59
|
+
{ equals: dequal },
|
|
60
|
+
);
|
|
67
61
|
|
|
68
62
|
const getBoardPoint = (clientX: number, clientY: number): Point => {
|
|
69
63
|
const el = boardRef();
|
|
70
64
|
if (!el) return { x: clientX, y: clientY };
|
|
65
|
+
|
|
71
66
|
const rect = el.getBoundingClientRect();
|
|
72
67
|
const currentZoom = zoom[0]();
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
};
|
|
68
|
+
const x = clientX - rect.left / currentZoom;
|
|
69
|
+
const y = clientY - rect.top / currentZoom;
|
|
70
|
+
return { x, y };
|
|
77
71
|
};
|
|
78
72
|
|
|
79
|
-
const [edgesPositions, setEdgesPositions] = createSignal<
|
|
80
|
-
|
|
81
|
-
|
|
73
|
+
const [edgesPositions, setEdgesPositions] = createSignal<Record<string, Vector>>(
|
|
74
|
+
{},
|
|
75
|
+
{ equals: false },
|
|
76
|
+
);
|
|
82
77
|
|
|
83
78
|
const clampPosition = (
|
|
84
79
|
x: number,
|
|
@@ -88,10 +83,12 @@ export const [Provider, useFlow] = createContext(
|
|
|
88
83
|
): Point => {
|
|
89
84
|
const container = boardRef()?.parentElement;
|
|
90
85
|
if (!container) return { x, y };
|
|
86
|
+
|
|
91
87
|
const currentZoom = zoom[0]();
|
|
92
88
|
|
|
93
89
|
const minX =
|
|
94
90
|
container.scrollLeft / currentZoom + BOUNDS_CONSTRAINTS.horizontal;
|
|
91
|
+
|
|
95
92
|
const maxX = Math.max(
|
|
96
93
|
minX,
|
|
97
94
|
(container.scrollLeft + container.clientWidth) / currentZoom -
|
|
@@ -99,8 +96,8 @@ export const [Provider, useFlow] = createContext(
|
|
|
99
96
|
nodeWidth,
|
|
100
97
|
);
|
|
101
98
|
|
|
102
|
-
const minY =
|
|
103
|
-
|
|
99
|
+
const minY = container.scrollTop / currentZoom + BOUNDS_CONSTRAINTS.vertical;
|
|
100
|
+
|
|
104
101
|
const maxY = Math.max(
|
|
105
102
|
minY,
|
|
106
103
|
(container.scrollTop + container.clientHeight) / currentZoom -
|
|
@@ -117,11 +114,7 @@ export const [Provider, useFlow] = createContext(
|
|
|
117
114
|
service.addOptions(({ voidAction, batch, assign }) => ({
|
|
118
115
|
actions: {
|
|
119
116
|
placeChild: assign('context.data.nodes', {
|
|
120
|
-
ADD_CHILD: ({
|
|
121
|
-
payload,
|
|
122
|
-
context: { data },
|
|
123
|
-
pContext: { generatedId },
|
|
124
|
-
}) => {
|
|
117
|
+
ADD_CHILD: ({ payload, context: { data }, pContext: { generatedId } }) => {
|
|
125
118
|
const nodes = data?.nodes ?? [];
|
|
126
119
|
if (!payload) return nodes;
|
|
127
120
|
|
|
@@ -131,33 +124,19 @@ export const [Provider, useFlow] = createContext(
|
|
|
131
124
|
const id = `node-${generatedId}`;
|
|
132
125
|
const width = dimensions()[payload]?.width ?? 0;
|
|
133
126
|
const height = dimensions()[payload]?.height ?? 0;
|
|
134
|
-
const initialX =
|
|
135
|
-
parentNode.position.x + width + PARENT_CHILD_GAP_WIDTH;
|
|
127
|
+
const initialX = parentNode.position.x + width + PARENT_CHILD_GAP_WIDTH;
|
|
136
128
|
const initialY = parentNode.position.y;
|
|
137
|
-
const position = clampPosition(
|
|
138
|
-
initialX,
|
|
139
|
-
initialY,
|
|
140
|
-
width,
|
|
141
|
-
height,
|
|
142
|
-
);
|
|
129
|
+
const position = clampPosition(initialX, initialY, width, height);
|
|
143
130
|
|
|
144
131
|
return [
|
|
145
132
|
...nodes,
|
|
146
|
-
{
|
|
147
|
-
id,
|
|
148
|
-
data: { content: '<Nouveau nœud>' },
|
|
149
|
-
input: true,
|
|
150
|
-
position,
|
|
151
|
-
},
|
|
133
|
+
{ id, data: { content: '<Nouveau nœud>' }, input: true, position },
|
|
152
134
|
];
|
|
153
135
|
},
|
|
154
136
|
}),
|
|
155
137
|
|
|
156
138
|
placeParent: assign('context.data.nodes', {
|
|
157
|
-
ADD_PARENT: ({
|
|
158
|
-
context: { data },
|
|
159
|
-
pContext: { generatedId },
|
|
160
|
-
}) => {
|
|
139
|
+
ADD_PARENT: ({ context: { data }, pContext: { generatedId } }) => {
|
|
161
140
|
const nodes = data?.nodes ?? [];
|
|
162
141
|
const id = `node-${generatedId}`;
|
|
163
142
|
const container = boardRef()?.parentElement;
|
|
@@ -189,7 +168,6 @@ export const [Provider, useFlow] = createContext(
|
|
|
189
168
|
}) => {
|
|
190
169
|
const edges = data?.edges ?? [];
|
|
191
170
|
const nodes = data?.nodes ?? [];
|
|
192
|
-
|
|
193
171
|
const parentID = edges.find(edge => edge.to === payload)?.from;
|
|
194
172
|
if (!parentID) return nodes;
|
|
195
173
|
|
|
@@ -199,24 +177,13 @@ export const [Provider, useFlow] = createContext(
|
|
|
199
177
|
const id = `node-${generatedId}`;
|
|
200
178
|
const width = dimensions()[parentID]?.width ?? 0;
|
|
201
179
|
const height = dimensions()[parentID]?.height ?? 0;
|
|
202
|
-
const initialX =
|
|
203
|
-
parentNode.position.x + width + PARENT_CHILD_GAP_WIDTH;
|
|
180
|
+
const initialX = parentNode.position.x + width + PARENT_CHILD_GAP_WIDTH;
|
|
204
181
|
const initialY = parentNode.position.y + 100;
|
|
205
|
-
const position = clampPosition(
|
|
206
|
-
initialX,
|
|
207
|
-
initialY,
|
|
208
|
-
width,
|
|
209
|
-
height,
|
|
210
|
-
);
|
|
182
|
+
const position = clampPosition(initialX, initialY, width, height);
|
|
211
183
|
|
|
212
184
|
return [
|
|
213
185
|
...nodes,
|
|
214
|
-
{
|
|
215
|
-
id,
|
|
216
|
-
data: { content: '<Nouveau nœud>' },
|
|
217
|
-
input: true,
|
|
218
|
-
position,
|
|
219
|
-
},
|
|
186
|
+
{ id, data: { content: '<Nouveau nœud>' }, input: true, position },
|
|
220
187
|
];
|
|
221
188
|
},
|
|
222
189
|
}),
|
|
@@ -225,9 +192,9 @@ export const [Provider, useFlow] = createContext(
|
|
|
225
192
|
voidAction(({ context: { data } }) => {
|
|
226
193
|
const edges = data?.edges ?? [];
|
|
227
194
|
setEdgesPositions(data => {
|
|
228
|
-
const array = Object.entries({ ...data }).filter(([id]) =>
|
|
229
|
-
|
|
230
|
-
|
|
195
|
+
const array = Object.entries({ ...data }).filter(([id]) =>
|
|
196
|
+
edges.some(edge => edge.id === id),
|
|
197
|
+
);
|
|
231
198
|
|
|
232
199
|
return Object.fromEntries(array);
|
|
233
200
|
});
|
|
@@ -240,6 +207,7 @@ export const [Provider, useFlow] = createContext(
|
|
|
240
207
|
edges?.forEach(({ from, id, to }) => {
|
|
241
208
|
const output = dimensions()[from]?.output;
|
|
242
209
|
const input = dimensions()[to]?.input;
|
|
210
|
+
|
|
243
211
|
if (output && input) {
|
|
244
212
|
next[id] = {
|
|
245
213
|
x0: output.x,
|
|
@@ -261,12 +229,12 @@ export const [Provider, useFlow] = createContext(
|
|
|
261
229
|
if (from === payload.id) {
|
|
262
230
|
const offset =
|
|
263
231
|
dimensions()[payload.id]?.outputOffset ??
|
|
264
|
-
getDefaultOutputOffset(
|
|
265
|
-
|
|
266
|
-
);
|
|
232
|
+
getDefaultOutputOffset(dimensions()[payload.id]?.width);
|
|
233
|
+
|
|
267
234
|
const x0 = payload.x + offset.x;
|
|
268
235
|
const y0 = payload.y + offset.y;
|
|
269
236
|
next[id] = { ...next[id], x0, y0 };
|
|
237
|
+
|
|
270
238
|
setDimensions(
|
|
271
239
|
produce(data => {
|
|
272
240
|
if (data[payload.id]) {
|
|
@@ -282,9 +250,11 @@ export const [Provider, useFlow] = createContext(
|
|
|
282
250
|
const offset =
|
|
283
251
|
dimensions()[payload.id]?.inputOffset ??
|
|
284
252
|
DEFAULT_INPUT_OFFSET;
|
|
253
|
+
|
|
285
254
|
const x1 = payload.x + offset.x;
|
|
286
255
|
const y1 = payload.y + offset.y;
|
|
287
256
|
next[id] = { ...next[id], x1, y1 };
|
|
257
|
+
|
|
288
258
|
setDimensions(
|
|
289
259
|
produce(data => {
|
|
290
260
|
if (data[payload.id]) {
|
|
@@ -301,6 +271,7 @@ export const [Provider, useFlow] = createContext(
|
|
|
301
271
|
);
|
|
302
272
|
},
|
|
303
273
|
}),
|
|
274
|
+
|
|
304
275
|
assign('context.updatingUI', () => true),
|
|
305
276
|
),
|
|
306
277
|
|
|
@@ -314,12 +285,12 @@ export const [Provider, useFlow] = createContext(
|
|
|
314
285
|
if (from === payload.id) {
|
|
315
286
|
const offset =
|
|
316
287
|
dimensions()[payload.id]?.outputOffset ??
|
|
317
|
-
getDefaultOutputOffset(
|
|
318
|
-
|
|
319
|
-
);
|
|
288
|
+
getDefaultOutputOffset(dimensions()[payload.id]?.width);
|
|
289
|
+
|
|
320
290
|
const x0 = payload.x + offset.x;
|
|
321
291
|
const y0 = payload.y + offset.y;
|
|
322
292
|
next[id] = { ...next[id], x0, y0 };
|
|
293
|
+
|
|
323
294
|
setDimensions(
|
|
324
295
|
produce(data => {
|
|
325
296
|
if (data[payload.id]) {
|
|
@@ -331,13 +302,15 @@ export const [Provider, useFlow] = createContext(
|
|
|
331
302
|
}),
|
|
332
303
|
);
|
|
333
304
|
}
|
|
305
|
+
|
|
334
306
|
if (to === payload.id) {
|
|
335
307
|
const offset =
|
|
336
|
-
dimensions()[payload.id]?.inputOffset ??
|
|
337
|
-
|
|
308
|
+
dimensions()[payload.id]?.inputOffset ?? DEFAULT_INPUT_OFFSET;
|
|
309
|
+
|
|
338
310
|
const x1 = payload.x + offset.x;
|
|
339
311
|
const y1 = payload.y + offset.y;
|
|
340
312
|
next[id] = { ...next[id], x1, y1 };
|
|
313
|
+
|
|
341
314
|
setDimensions(
|
|
342
315
|
produce(data => {
|
|
343
316
|
if (data[payload.id]) {
|
|
@@ -367,6 +340,7 @@ export const [Provider, useFlow] = createContext(
|
|
|
367
340
|
edgesPositions: [edgesPositions, setEdgesPositions] as const,
|
|
368
341
|
service,
|
|
369
342
|
zoom,
|
|
343
|
+
clampPosition,
|
|
370
344
|
};
|
|
371
345
|
},
|
|
372
346
|
{ name: 'FlowContext' },
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import type { NodeProps } from './FlowChart';
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* Horizontal gap in pixels between a parent node and newly created child
|
|
5
|
-
* node.
|
|
6
|
-
*/
|
|
3
|
+
/** Horizontal gap in pixels between a parent node and newly created child node. */
|
|
7
4
|
export const PARENT_CHILD_GAP_WIDTH = 100;
|
|
8
5
|
|
|
9
6
|
// #region Node & Handle Layout Constants & Formulas
|
|
@@ -41,10 +38,7 @@ export const DEFAULT_INPUT_OFFSET = {
|
|
|
41
38
|
y: DEFAULT_INPUT_OFFSET_Y,
|
|
42
39
|
};
|
|
43
40
|
|
|
44
|
-
/**
|
|
45
|
-
* Dimensions representing width and height of the flow chart container
|
|
46
|
-
* canvas.
|
|
47
|
-
*/
|
|
41
|
+
/** Dimensions representing width and height of the flow chart container canvas. */
|
|
48
42
|
export const CONTAINER_DIMENSIONS = { WIDTH: 5000, HEIGHT: 3500 };
|
|
49
43
|
|
|
50
44
|
/**
|
|
@@ -66,16 +60,16 @@ export const TOOLBAR_TOP_OFFSET = 30;
|
|
|
66
60
|
export const TOOLBAR_BUFFER = 5;
|
|
67
61
|
|
|
68
62
|
/**
|
|
69
|
-
* Boundary padding constraints for node dragging and positioning within
|
|
70
|
-
*
|
|
63
|
+
* Boundary padding constraints for node dragging and positioning within the
|
|
64
|
+
* viewport.
|
|
71
65
|
*/
|
|
72
|
-
export const BOUNDS_CONSTRAINTS = {
|
|
73
|
-
horizontal: HANDLE_CONTAINER_OFFSET_X + 2,
|
|
74
|
-
vertical: TOOLBAR_TOP_OFFSET + TOOLBAR_BUFFER,
|
|
75
|
-
};
|
|
66
|
+
export const BOUNDS_CONSTRAINTS = { horizontal: 55, vertical: 40 };
|
|
76
67
|
|
|
77
68
|
/** Multiplier factor used to compute canvas virtual scroll dimensions. */
|
|
78
69
|
export const CANVAS_FACTOR = 5;
|
|
70
|
+
|
|
71
|
+
/** Multiplier factor used to compute canvas scroll dimensions. */
|
|
72
|
+
export const SCROLL_MULTIPLIER = 3;
|
|
79
73
|
// #endregion
|
|
80
74
|
|
|
81
75
|
/** Default node items provided when no initial configuration is given. */
|
|
@@ -1,20 +1,15 @@
|
|
|
1
1
|
import type { inferT } from '@bemedev/app/typings';
|
|
2
2
|
import { Component, onCleanup, onMount } from 'solid-js';
|
|
3
|
+
|
|
3
4
|
import type { edgeJSON, nodeJSON } from '../../services/main.typings';
|
|
4
5
|
import { useFlow } from './FlowChart.context';
|
|
5
|
-
import { NodesBoard } from './NodesBoard';
|
|
6
6
|
import { DEFAULT_NODES } from './FlowChart.data';
|
|
7
|
+
import { NodesBoard } from './NodesBoard';
|
|
7
8
|
|
|
8
|
-
/**
|
|
9
|
-
* Serialized node properties type inferred from schema
|
|
10
|
-
* {@linkcode nodeJSON}.
|
|
11
|
-
*/
|
|
9
|
+
/** Serialized node properties type inferred from schema {@linkcode nodeJSON}. */
|
|
12
10
|
export type NodeProps = inferT<typeof nodeJSON>;
|
|
13
11
|
|
|
14
|
-
/**
|
|
15
|
-
* Serialized edge properties type inferred from schema
|
|
16
|
-
* {@linkcode edgeJSON}.
|
|
17
|
-
*/
|
|
12
|
+
/** Serialized edge properties type inferred from schema {@linkcode edgeJSON}. */
|
|
18
13
|
export type EdgeProps = inferT<typeof edgeJSON>;
|
|
19
14
|
|
|
20
15
|
/**
|
|
@@ -56,8 +51,8 @@ export type FlowProps = {
|
|
|
56
51
|
// const PARENT_CHILD_GAP_WIDTH = 75;
|
|
57
52
|
|
|
58
53
|
/**
|
|
59
|
-
* Flowchart board canvas component that renders interactive nodes, edges,
|
|
60
|
-
*
|
|
54
|
+
* Flowchart board canvas component that renders interactive nodes, edges, pan/zoom,
|
|
55
|
+
* and toolbar controls.
|
|
61
56
|
*
|
|
62
57
|
* @param props - Flowchart configuration and event handlers of type
|
|
63
58
|
* {@linkcode FlowProps}.
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-namespace */
|
|
2
2
|
import { useState } from '@bemedev/app-solidjs';
|
|
3
3
|
import { createDraggable } from '@thisbeyond/solid-dnd';
|
|
4
|
-
import { Component,
|
|
4
|
+
import { Component, createSignal, onMount, Show } from 'solid-js';
|
|
5
5
|
import { produce } from 'solid-js/store';
|
|
6
|
+
|
|
6
7
|
import { useFlow } from './FlowChart.context';
|
|
7
8
|
import {
|
|
8
9
|
DEFAULT_INPUT_OFFSET_X,
|
|
@@ -37,8 +38,8 @@ type Props = {
|
|
|
37
38
|
};
|
|
38
39
|
|
|
39
40
|
/**
|
|
40
|
-
* Interactive flowchart node component supporting dragging, selection,
|
|
41
|
-
*
|
|
41
|
+
* Interactive flowchart node component supporting dragging, selection, handle
|
|
42
|
+
* connections, and child/sibling creation.
|
|
42
43
|
*
|
|
43
44
|
* @param props - Node rendering properties of type {@linkcode Props}.
|
|
44
45
|
*
|
|
@@ -60,7 +61,7 @@ export const NodeComponent: Component<Props> = props => {
|
|
|
60
61
|
selector: s => s.context.selected === props.id,
|
|
61
62
|
});
|
|
62
63
|
|
|
63
|
-
|
|
64
|
+
onMount(() => {
|
|
64
65
|
const _inputRef = inputRef;
|
|
65
66
|
const _outputRef = outputRef;
|
|
66
67
|
const _rootRef = ref();
|
|
@@ -73,15 +74,12 @@ export const NodeComponent: Component<Props> = props => {
|
|
|
73
74
|
const inputRect = _inputRef?.getBoundingClientRect();
|
|
74
75
|
|
|
75
76
|
const outputOffsetX =
|
|
76
|
-
(outputRect.left - rootRect.left + outputRect.width / 2) /
|
|
77
|
-
currentZoom;
|
|
77
|
+
(outputRect.left - rootRect.left + outputRect.width / 2) / currentZoom;
|
|
78
78
|
const outputOffsetY =
|
|
79
|
-
(outputRect.top - rootRect.top + outputRect.height / 2) /
|
|
80
|
-
currentZoom;
|
|
79
|
+
(outputRect.top - rootRect.top + outputRect.height / 2) / currentZoom;
|
|
81
80
|
|
|
82
81
|
const inputOffsetX = inputRect
|
|
83
|
-
? (inputRect.left - rootRect.left + inputRect.width / 2) /
|
|
84
|
-
currentZoom
|
|
82
|
+
? (inputRect.left - rootRect.left + inputRect.width / 2) / currentZoom
|
|
85
83
|
: DEFAULT_INPUT_OFFSET_X;
|
|
86
84
|
const inputOffsetY = inputRect
|
|
87
85
|
? (inputRect.top - rootRect.top + inputRect.height / 2) / currentZoom
|
|
@@ -90,10 +88,7 @@ export const NodeComponent: Component<Props> = props => {
|
|
|
90
88
|
const width = rootRect.width / currentZoom;
|
|
91
89
|
const height = rootRect.height / currentZoom;
|
|
92
90
|
|
|
93
|
-
const output = {
|
|
94
|
-
x: props.x + outputOffsetX,
|
|
95
|
-
y: props.y + outputOffsetY,
|
|
96
|
-
};
|
|
91
|
+
const output = { x: props.x + outputOffsetX, y: props.y + outputOffsetY };
|
|
97
92
|
|
|
98
93
|
const input = { x: props.x + inputOffsetX, y: props.y + inputOffsetY };
|
|
99
94
|
|
|
@@ -115,7 +110,7 @@ export const NodeComponent: Component<Props> = props => {
|
|
|
115
110
|
selector: ({ context: { data } }) => {
|
|
116
111
|
const edges = data?.edges;
|
|
117
112
|
if (!edges) return false;
|
|
118
|
-
return
|
|
113
|
+
return edges.some(({ to }) => to === props.id);
|
|
119
114
|
},
|
|
120
115
|
});
|
|
121
116
|
|
|
@@ -182,9 +177,7 @@ export const NodeComponent: Component<Props> = props => {
|
|
|
182
177
|
preserveAspectRatio='xMaxYMax'
|
|
183
178
|
xmlns='http://www.w3.org/2000/svg'
|
|
184
179
|
fill='white'
|
|
185
|
-
onClick={() =>
|
|
186
|
-
service.send({ type: 'ADD_SIBLING', payload: props.id })
|
|
187
|
-
}
|
|
180
|
+
onClick={() => service.send({ type: 'ADD_SIBLING', payload: props.id })}
|
|
188
181
|
>
|
|
189
182
|
<g id='background'>
|
|
190
183
|
<path d='M467.40667,277.66696c-0.05948,-14.53055 5.75527,-22.95613 -8.62044,-20.90487c-112.55699,16.0607 -222.1609,112.14558 -245.06161,239.85765c-46.52056,259.43466 231.33083,443.06705 449.51209,316.97506c117.31668,-67.80002 160.95215,-190.43324 151.34416,-288.29849c-5.92276,-60.32819 -27.80273,-107.95668 -53.44246,-144.25469l59.39269,-42.05363c111.72214,156.309 73.11535,351.55635 -25.06953,459.45565c-184.18877,202.4124 -470.46624,145.52064 -592.95027,-32.92123c-156.18269,-227.53604 -27.15324,-543.64371 261.18883,-582.44416c5.0579,-0.68061 3.56556,-7.04079 3.56442,-8.58985c-0.05594,-76.3354 -0.11021,-76.7687 1.10909,-77.24589c2.06886,-0.80969 151.41433,118.4561 151.92482,118.95524c4.65592,4.55233 -0.99548,7.829 -29.07828,30.50907c-120.49369,97.31245 -120.4977,98.55675 -123.0691,97.87586c-0.43639,-0.11555 -0.80698,-0.31322 -0.74442,-66.91571Z' />
|
|
@@ -194,9 +187,7 @@ export const NodeComponent: Component<Props> = props => {
|
|
|
194
187
|
</Show>
|
|
195
188
|
<svg
|
|
196
189
|
class='flex cursor-pointer items-center justify-center rounded-lg bg-blue-500 p-0.5 text-center font-bold text-white hover:bg-blue-600'
|
|
197
|
-
onClick={() =>
|
|
198
|
-
service.send({ type: 'ADD_CHILD', payload: props.id })
|
|
199
|
-
}
|
|
190
|
+
onClick={() => service.send({ type: 'ADD_CHILD', payload: props.id })}
|
|
200
191
|
style={{
|
|
201
192
|
'pointer-events': 'all',
|
|
202
193
|
width: `${HANDLE_SIZE * 2}px`,
|
|
@@ -242,10 +233,7 @@ export const NodeComponent: Component<Props> = props => {
|
|
|
242
233
|
const from = newEdge()?.from;
|
|
243
234
|
|
|
244
235
|
if (from) {
|
|
245
|
-
service.send({
|
|
246
|
-
type: 'ADD_EDGE',
|
|
247
|
-
payload: { from, to: props.id },
|
|
248
|
-
});
|
|
236
|
+
service.send({ type: 'ADD_EDGE', payload: { from, to: props.id } });
|
|
249
237
|
}
|
|
250
238
|
|
|
251
239
|
setNewEdge();
|