@bemedev/mind-flow 0.3.0 → 0.3.2

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.
@@ -39,12 +39,14 @@ type Props = {
39
39
  */
40
40
  export const NodeComponent: Component<Props> = props => {
41
41
  const service = useFlow();
42
+ const newEdge = createState(service, { selector: s => s.context.newEdge });
43
+ const draggable = createDraggable(props.id);
44
+ void draggable;
42
45
 
43
46
  const node = createState(service, {
44
47
  selector: ({ context }) => {
45
48
  const list = toArray.typed(context.data?.nodes);
46
- const item = list.find(n => n.id === props.id);
47
- if (!item) return undefined;
49
+ const item = list.find(n => n.id === props.id)!;
48
50
  return {
49
51
  x: item.position.x,
50
52
  y: item.position.y,
@@ -56,10 +58,8 @@ export const NodeComponent: Component<Props> = props => {
56
58
  equals: dequal,
57
59
  });
58
60
 
59
- const newEdge = createState(service, { selector: s => s.context.newEdge });
60
-
61
61
  const selected = createState(service, {
62
- selector: s => s.context.selected === props.id,
62
+ selector: ({ context }) => context.selected === props.id,
63
63
  });
64
64
 
65
65
  const hasParent = createState(service, {
@@ -70,9 +70,6 @@ export const NodeComponent: Component<Props> = props => {
70
70
  },
71
71
  });
72
72
 
73
- const draggable = createDraggable(props.id);
74
- void draggable;
75
-
76
73
  return (
77
74
  <div
78
75
  classList={{
@@ -81,7 +78,7 @@ export const NodeComponent: Component<Props> = props => {
81
78
  'border border-[#e6d4be] z-[1]': !selected(),
82
79
  }}
83
80
 
84
- style={{ top: `${node()?.y ?? 0}px`, left: `${node()?.x ?? 0}px` }}
81
+ style={{ top: `${node().y}px`, left: `${node().x}px` }}
85
82
  class='min-w-48'
86
83
  use:draggable={{ skipTransform: true }}
87
84
  id={props.id}
@@ -122,6 +119,7 @@ export const NodeComponent: Component<Props> = props => {
122
119
  <Show when={hasParent()}>
123
120
  <svg
124
121
  class='cursor-pointer overflow-visible rounded-full bg-green-500 p-0.5 text-center font-bold hover:bg-green-600'
122
+
125
123
  style={{
126
124
  'pointer-events': 'all',
127
125
  'fill-rule': 'evenodd',
@@ -145,6 +143,7 @@ export const NodeComponent: Component<Props> = props => {
145
143
  </g>
146
144
  </svg>
147
145
  </Show>
146
+
148
147
  <svg
149
148
  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'
150
149
  onClick={() => service.send({ type: 'ADD_CHILD', payload: props.id })}
@@ -162,7 +161,7 @@ export const NodeComponent: Component<Props> = props => {
162
161
  </svg>
163
162
  </div>
164
163
 
165
- <Show when={node()?.label} keyed>
164
+ <Show when={node().label} keyed>
166
165
  {label => (
167
166
  <span class='min-w-max border-b border-[#f0f0f0] p-3 whitespace-nowrap text-red-600 select-none'>
168
167
  {label}
@@ -170,13 +169,13 @@ export const NodeComponent: Component<Props> = props => {
170
169
  )}
171
170
  </Show>
172
171
 
173
- <Show when={node()?.content} keyed>
172
+ <Show when={node().content} keyed>
174
173
  {content => <div class='p-3 select-none'>{content}</div>}
175
174
  </Show>
176
175
 
177
- <Show when={node()?.input || hasParent()}>
176
+ <Show when={node().input || hasParent()}>
178
177
  <div
179
- id='outputs'
178
+ id='inputs'
180
179
  class='pointer-events-none absolute top-0 z-10 flex cursor-default flex-col'
181
180
  style={{ left: `-${HANDLE_CONTAINER_OFFSET_X}px` }}
182
181
  >
@@ -206,7 +205,7 @@ export const NodeComponent: Component<Props> = props => {
206
205
  </div>
207
206
  </Show>
208
207
  <div
209
- id='inputs'
208
+ id='outputs'
210
209
  class='pointer-events-none absolute top-0 z-10 flex flex-col'
211
210
  style={{ right: `-${HANDLE_CONTAINER_OFFSET_X}px` }}
212
211
  >
@@ -34,7 +34,6 @@ export const NodesBoard: Component = () => {
34
34
  let containerRef: HTMLDivElement;
35
35
  const [isPanning, setIsPanning] = createSignal(false);
36
36
  const [transform, setTransform] = createSignal({ x: 0, y: 0 });
37
- const [id, setId] = createSignal<string | number>('');
38
37
  const [ref, setRef] = createSignal<HTMLDivElement | undefined>();
39
38
  let percentX = 0;
40
39
  let percentY = 0;
@@ -107,15 +106,6 @@ export const NodesBoard: Component = () => {
107
106
 
108
107
  const selectedId = createState(service, { selector: s => s.context?.selected });
109
108
 
110
- /**
111
- * Determines whether the given element ID matches the currently selected entity.
112
- *
113
- * @param id - The node or edge identifier to check.
114
- *
115
- * @returns `true` if the item is currently selected, otherwise `false`.
116
- */
117
- const selected = (id: string | number) => selectedId() === id;
118
-
119
109
  const nodeIds = createState(service, {
120
110
  selector: ({ context }) => {
121
111
  const list = toArray.typed(context.data?.nodes);
@@ -149,44 +139,38 @@ export const NodesBoard: Component = () => {
149
139
  >
150
140
  <DragDropProvider
151
141
  onDragMove={({ draggable: { transform: _transform, node, id } }) => {
152
- setId(id);
153
- if (selected(id)) {
154
- const grandParent = node.parentElement?.parentElement;
155
- const currentZoom = zoom();
156
- const minX = 0;
157
- const maxX = grandParent
158
- ? Math.max(0, grandParent.clientWidth / currentZoom - node.offsetWidth)
159
- : Infinity;
160
- const minY = 0;
161
- const maxY = grandParent
162
- ? Math.max(
163
- 0,
164
- grandParent.clientHeight / currentZoom - node.offsetHeight,
165
- )
166
- : Infinity;
167
-
168
- const targetX = node.offsetLeft + _transform.x / currentZoom;
169
- const targetY = node.offsetTop + _transform.y / currentZoom;
170
-
171
- const x = Math.min(Math.max(targetX, minX), maxX);
172
- const y = Math.min(Math.max(targetY, minY), maxY);
173
-
174
- const deltaX = x - node.offsetLeft;
175
- const deltaY = y - node.offsetTop;
176
-
177
- // Directly update the draggable node's CSS transform adjusted for zoom:
178
- node.style.setProperty(
179
- 'transform',
180
- `translate3d(${deltaX}px, ${deltaY}px, 0)`,
181
- );
182
-
183
- service.send({ type: 'MOVE_IMMEDIATE', payload: { id: `${id}`, x, y } });
184
- setTransform({ x: deltaX * currentZoom, y: deltaY * currentZoom });
185
- }
142
+ const grandParent = node.parentElement?.parentElement;
143
+ const currentZoom = zoom();
144
+ const minX = 0;
145
+ const maxX = grandParent
146
+ ? Math.max(0, grandParent.clientWidth / currentZoom - node.offsetWidth)
147
+ : Infinity;
148
+ const minY = 0;
149
+ const maxY = grandParent
150
+ ? Math.max(0, grandParent.clientHeight / currentZoom - node.offsetHeight)
151
+ : Infinity;
152
+
153
+ const targetX = node.offsetLeft + _transform.x / currentZoom;
154
+ const targetY = node.offsetTop + _transform.y / currentZoom;
155
+
156
+ const x = Math.min(Math.max(targetX, minX), maxX);
157
+ const y = Math.min(Math.max(targetY, minY), maxY);
158
+
159
+ const deltaX = x - node.offsetLeft;
160
+ const deltaY = y - node.offsetTop;
161
+
162
+ // Directly update the draggable node's CSS transform adjusted for zoom:
163
+ node.style.setProperty(
164
+ 'transform',
165
+ `translate3d(${deltaX}px, ${deltaY}px, 0)`,
166
+ );
167
+
168
+ service.send({ type: 'MOVE_IMMEDIATE', payload: { id: `${id}`, x, y } });
169
+ setTransform({ x: deltaX * currentZoom, y: deltaY * currentZoom });
186
170
  }}
187
171
 
188
172
  onDragEnd={({ draggable: { node, id } }) => {
189
- if (!selected(id)) return;
173
+ // if (!selected(id)) return;
190
174
 
191
175
  const grandParent = node.parentElement?.parentElement;
192
176
  const currentZoom = zoom();
@@ -227,11 +211,12 @@ export const NodesBoard: Component = () => {
227
211
  class='relative cursor-crosshair overflow-hidden'
228
212
  classList={{ 'cursor-grabbing': isPanning() }}
229
213
  style={{ height: cHeight(), width: cWidth() }}
230
- onScroll={() => {}}
214
+ // onScroll={() => {}}
231
215
 
232
216
  onMouseDown={e => {
233
217
  if (newEdge() || e.button !== 0) return;
234
218
  service.send('DESELECT');
219
+ setIsPanning(true);
235
220
 
236
221
  // #region Props
237
222
  const startX = e.clientX;
@@ -240,8 +225,6 @@ export const NodesBoard: Component = () => {
240
225
  const startScrollTop = containerRef.scrollTop;
241
226
  // #endregion
242
227
 
243
- setIsPanning(true);
244
-
245
228
  const handleMouseMove = (moveEvent: MouseEvent) => {
246
229
  const dx = moveEvent.clientX - startX;
247
230
  const dy = moveEvent.clientY - startY;
@@ -325,7 +308,7 @@ export const NodesBoard: Component = () => {
325
308
  </svg>
326
309
  </button>
327
310
  </div>
328
- <Show when={!id() || !selected(id())}>
311
+ <Show when={!selectedId()}>
329
312
  <DragOverlay children='' />
330
313
  </Show>
331
314
  </DragDropProvider>