@d34dman/flowdrop 0.0.13 → 0.0.14

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.
@@ -0,0 +1,68 @@
1
+ <!--
2
+ Flow Drop Zone Component
3
+ Handles drag and drop with proper coordinate transformation
4
+ Must be used inside SvelteFlowProvider
5
+ -->
6
+
7
+ <script lang="ts">
8
+ import { useSvelteFlow } from "@xyflow/svelte";
9
+ import type { Snippet } from "svelte";
10
+
11
+ interface Props {
12
+ ondrop: (nodeTypeData: string, position: { x: number; y: number }) => void;
13
+ children: Snippet;
14
+ }
15
+
16
+ let props: Props = $props();
17
+
18
+ // Access SvelteFlow instance for coordinate transformation
19
+ const { screenToFlowPosition } = useSvelteFlow();
20
+
21
+ /**
22
+ * Handle drag over event
23
+ */
24
+ function handleDragOver(e: DragEvent): void {
25
+ e.preventDefault();
26
+ if (e.dataTransfer) {
27
+ e.dataTransfer.dropEffect = "copy";
28
+ }
29
+ }
30
+
31
+ /**
32
+ * Handle drop event with proper coordinate transformation
33
+ */
34
+ function handleDrop(e: DragEvent): void {
35
+ e.preventDefault();
36
+
37
+ // Get the data from the drag event
38
+ const nodeTypeData = e.dataTransfer?.getData("application/json");
39
+ if (nodeTypeData) {
40
+ // Convert screen coordinates to flow coordinates (accounts for zoom and pan)
41
+ const position = screenToFlowPosition({
42
+ x: e.clientX,
43
+ y: e.clientY
44
+ });
45
+
46
+ // Call the parent handler with the converted position
47
+ props.ondrop(nodeTypeData, position);
48
+ }
49
+ }
50
+ </script>
51
+
52
+ <div
53
+ class="flow-drop-zone"
54
+ role="application"
55
+ aria-label="Workflow canvas"
56
+ ondragover={handleDragOver}
57
+ ondrop={handleDrop}
58
+ >
59
+ {@render props.children()}
60
+ </div>
61
+
62
+ <style>
63
+ .flow-drop-zone {
64
+ width: 100%;
65
+ height: 100%;
66
+ }
67
+ </style>
68
+
@@ -0,0 +1,11 @@
1
+ import type { Snippet } from "svelte";
2
+ interface Props {
3
+ ondrop: (nodeTypeData: string, position: {
4
+ x: number;
5
+ y: number;
6
+ }) => void;
7
+ children: Snippet;
8
+ }
9
+ declare const FlowDropZone: import("svelte").Component<Props, {}, "">;
10
+ type FlowDropZone = ReturnType<typeof FlowDropZone>;
11
+ export default FlowDropZone;
@@ -22,6 +22,7 @@
22
22
  WorkflowEdge
23
23
  } from '../types/index.js';
24
24
  import CanvasBanner from './CanvasBanner.svelte';
25
+ import FlowDropZone from './FlowDropZone.svelte';
25
26
  import { tick } from 'svelte';
26
27
  import type { EndpointConfig } from '../config/endpoints.js';
27
28
  import ConnectionLine from './ConnectionLine.svelte';
@@ -277,8 +278,8 @@
277
278
  /**
278
279
  * Handle node deletion - automatically remove connected edges
279
280
  */
280
- function handleNodesDelete(event: { detail: { nodes: WorkflowNodeType[] } }): void {
281
- const deletedNodeIds = new Set(event.detail.nodes.map((node) => node.id));
281
+ function handleNodesDelete(params: { nodes: WorkflowNodeType[]; edges: WorkflowEdge[] }): void {
282
+ const deletedNodeIds = new Set(params.nodes.map((node) => node.id));
282
283
 
283
284
  // Filter out edges connected to deleted nodes
284
285
  flowEdges = flowEdges.filter(
@@ -329,6 +330,30 @@
329
330
  function checkWorkflowCycles(): boolean {
330
331
  return WorkflowOperationsHelper.checkWorkflowCycles(flowNodes, flowEdges);
331
332
  }
333
+
334
+ /**
335
+ * Handle drop event and add new node to canvas
336
+ * This will be called from the inner DropZone component
337
+ */
338
+ async function handleNodeDrop(
339
+ nodeTypeData: string,
340
+ position: { x: number; y: number }
341
+ ): Promise<void> {
342
+ // Create the node using the helper, passing existing nodes for ID generation
343
+ const newNode = NodeOperationsHelper.createNodeFromDrop(nodeTypeData, position, flowNodes);
344
+
345
+ if (newNode && currentWorkflow) {
346
+ currentWorkflow = WorkflowOperationsHelper.addNode(currentWorkflow, newNode);
347
+
348
+ // Update the global store
349
+ updateGlobalStore();
350
+
351
+ // Wait for DOM update to ensure SvelteFlow updates
352
+ await tick();
353
+ } else if (!currentWorkflow) {
354
+ console.warn('No currentWorkflow available for new node');
355
+ }
356
+ }
332
357
  </script>
333
358
 
334
359
  <SvelteFlowProvider>
@@ -336,80 +361,41 @@
336
361
  <!-- Main Editor Area -->
337
362
  <div class="flowdrop-workflow-editor__main">
338
363
  <!-- Flow Canvas -->
339
- <div
340
- class="flowdrop-canvas"
341
- role="application"
342
- aria-label="Workflow canvas"
343
- ondragover={(e: DragEvent) => {
344
- e.preventDefault();
345
- e.dataTransfer!.dropEffect = 'copy';
346
- }}
347
- ondrop={async (e: DragEvent) => {
348
- e.preventDefault();
349
-
350
- // Get the data from the drag event
351
- const nodeTypeData = e.dataTransfer?.getData('application/json');
352
- if (nodeTypeData) {
353
- // Get the position relative to the canvas
354
- const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();
355
- const position = {
356
- x: e.clientX - rect.left,
357
- y: e.clientY - rect.top
358
- };
359
-
360
- // Create the node using the helper, passing existing nodes for ID generation
361
- const newNode = NodeOperationsHelper.createNodeFromDrop(
362
- nodeTypeData,
363
- position,
364
- flowNodes
365
- );
366
-
367
- if (newNode && currentWorkflow) {
368
- currentWorkflow = WorkflowOperationsHelper.addNode(currentWorkflow, newNode);
369
-
370
- // Update the global store
371
- updateGlobalStore();
372
-
373
- // Wait for DOM update to ensure SvelteFlow updates
374
- await tick();
375
- } else if (!currentWorkflow) {
376
- console.warn('No currentWorkflow available for new node');
377
- }
378
- }
379
- }}
380
- >
381
- <SvelteFlow
382
- bind:nodes={flowNodes}
383
- bind:edges={flowEdges}
384
- {nodeTypes}
385
- {defaultEdgeOptions}
386
- onconnect={handleConnect}
387
- onnodesdelete={handleNodesDelete}
388
- minZoom={0.2}
389
- maxZoom={3}
390
- clickConnect={true}
391
- elevateEdgesOnSelect={true}
392
- connectionLineType={ConnectionLineType.Bezier}
393
- connectionLineComponent={ConnectionLine}
394
- snapGrid={[10, 10]}
395
- fitView
396
- >
397
- <Controls />
398
- <Background
399
- gap={10}
400
- bgColor="var(--flowdrop-background-color)"
401
- variant={BackgroundVariant.Dots}
402
- />
403
- <MiniMap />
404
- </SvelteFlow>
405
- <!-- Drop Zone Indicator -->
406
- {#if flowNodes.length === 0}
407
- <CanvasBanner
408
- title="Drag components here to start building"
409
- description="Use the sidebar to add components to your workflow"
410
- iconName="mdi:graph"
411
- />
412
- {/if}
364
+ <div class="flowdrop-canvas">
365
+ <FlowDropZone ondrop={handleNodeDrop}>
366
+ <SvelteFlow
367
+ bind:nodes={flowNodes}
368
+ bind:edges={flowEdges}
369
+ {nodeTypes}
370
+ {defaultEdgeOptions}
371
+ onconnect={handleConnect}
372
+ ondelete={handleNodesDelete}
373
+ minZoom={0.2}
374
+ maxZoom={3}
375
+ clickConnect={true}
376
+ elevateEdgesOnSelect={true}
377
+ connectionLineType={ConnectionLineType.Bezier}
378
+ connectionLineComponent={ConnectionLine}
379
+ snapGrid={[10, 10]}
380
+ fitView
381
+ >
382
+ <Controls />
383
+ <Background
384
+ gap={10}
385
+ bgColor="var(--flowdrop-background-color)"
386
+ variant={BackgroundVariant.Dots}
387
+ />
388
+ <MiniMap />
389
+ </SvelteFlow>
390
+ <!-- Drop Zone Indicator -->
391
+ {#if flowNodes.length === 0}
392
+ <CanvasBanner
393
+ title="Drag components here to start building"
394
+ description="Use the sidebar to add components to your workflow"
395
+ iconName="mdi:graph"
396
+ />
397
+ {/if}
398
+ </FlowDropZone>
413
399
  </div>
414
400
 
415
401
  <!-- Status Bar -->
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@d34dman/flowdrop",
3
3
  "license": "MIT",
4
4
  "private": false,
5
- "version": "0.0.13",
5
+ "version": "0.0.14",
6
6
  "scripts": {
7
7
  "dev": "vite dev",
8
8
  "build": "vite build && npm run prepack",