Skip to content

Commit f96f749

Browse files
committed
pr feedback
1 parent 6222c4e commit f96f749

File tree

3 files changed

+110
-6
lines changed

3 files changed

+110
-6
lines changed
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import type { Attachment } from 'svelte/attachments';
2+
3+
export interface DragAndDropOptions {
4+
index: number;
5+
onDragStart?: (index: number) => void;
6+
onDragEnter?: (index: number) => void;
7+
onDrop?: (e: DragEvent, index: number) => void;
8+
onDragEnd?: () => void;
9+
isDragging?: boolean;
10+
isDragOver?: boolean;
11+
}
12+
13+
export function dragAndDrop(options: DragAndDropOptions): Attachment {
14+
return (node: Element) => {
15+
const element = node as HTMLElement;
16+
const { index, onDragStart, onDragEnter, onDrop, onDragEnd, isDragging, isDragOver } = options;
17+
18+
const isFormElement = (el: HTMLElement) => {
19+
return el.tagName === 'INPUT' || el.tagName === 'TEXTAREA' || el.tagName === 'SELECT';
20+
};
21+
22+
const handleDragStart = (e: DragEvent) => {
23+
// Prevent drag if it originated from an input, textarea, or select element
24+
const target = e.target as HTMLElement;
25+
if (isFormElement(target)) {
26+
e.preventDefault();
27+
return;
28+
}
29+
onDragStart?.(index);
30+
};
31+
32+
const handleDragEnter = () => {
33+
onDragEnter?.(index);
34+
};
35+
36+
const handleDragOver = (e: DragEvent) => {
37+
e.preventDefault();
38+
};
39+
40+
const handleDrop = (e: DragEvent) => {
41+
onDrop?.(e, index);
42+
};
43+
44+
const handleDragEnd = () => {
45+
onDragEnd?.();
46+
};
47+
48+
// Disable draggable when focusing on form elements (fixes Firefox input interaction)
49+
const handleFocusIn = (e: FocusEvent) => {
50+
const target = e.target as HTMLElement;
51+
if (isFormElement(target)) {
52+
element.setAttribute('draggable', 'false');
53+
}
54+
};
55+
56+
const handleFocusOut = (e: FocusEvent) => {
57+
const target = e.target as HTMLElement;
58+
if (isFormElement(target)) {
59+
element.setAttribute('draggable', 'true');
60+
}
61+
};
62+
63+
// Update classes based on drag state
64+
const updateClasses = (dragging: boolean, dragOver: boolean) => {
65+
// Remove all drag-related classes first
66+
element.classList.remove('opacity-50', 'border-light-500', 'border-solid');
67+
68+
// Add back only the active ones
69+
if (dragging) {
70+
element.classList.add('opacity-50');
71+
}
72+
73+
if (dragOver) {
74+
element.classList.add('border-light-500', 'border-solid');
75+
element.classList.remove('border-transparent');
76+
} else {
77+
element.classList.add('border-transparent');
78+
}
79+
};
80+
81+
element.setAttribute('draggable', 'true');
82+
element.setAttribute('role', 'button');
83+
element.setAttribute('tabindex', '0');
84+
85+
element.addEventListener('dragstart', handleDragStart);
86+
element.addEventListener('dragenter', handleDragEnter);
87+
element.addEventListener('dragover', handleDragOver);
88+
element.addEventListener('drop', handleDrop);
89+
element.addEventListener('dragend', handleDragEnd);
90+
element.addEventListener('focusin', handleFocusIn);
91+
element.addEventListener('focusout', handleFocusOut);
92+
93+
updateClasses(isDragging || false, isDragOver || false);
94+
95+
return () => {
96+
element.removeEventListener('dragstart', handleDragStart);
97+
element.removeEventListener('dragenter', handleDragEnter);
98+
element.removeEventListener('dragover', handleDragOver);
99+
element.removeEventListener('drop', handleDrop);
100+
element.removeEventListener('dragend', handleDragEnd);
101+
element.removeEventListener('focusin', handleFocusIn);
102+
element.removeEventListener('focusout', handleFocusOut);
103+
};
104+
};
105+
}

web/src/routes/(user)/utilities/workflows/+page.svelte

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,6 @@
248248
icon: mdiPencil,
249249
onAction: () => void handleEditWorkflow(workflow),
250250
},
251-
252251
{
253252
title: expandedWorkflows.has(workflow.id) ? $t('hide_schema') : $t('show_schema'),
254253
icon: mdiCodeJson,

web/src/routes/(user)/utilities/workflows/[workflowId]/+page.svelte

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script lang="ts">
22
import { beforeNavigate, goto } from '$app/navigation';
3-
import { dragAndDrop } from '$lib/actions/drag-and-drop';
3+
import { dragAndDrop } from '$lib/attachments/drag-and-drop.svelte';
44
import ControlAppBar from '$lib/components/shared-components/control-app-bar.svelte';
55
import SchemaFormFields from '$lib/components/workflows/SchemaFormFields.svelte';
66
import WorkflowCardConnector from '$lib/components/workflows/WorkflowCardConnector.svelte';
@@ -455,15 +455,15 @@
455455
{@render stepSeparator()}
456456
{/if}
457457
<div
458-
use:dragAndDrop={{
458+
{@attach dragAndDrop({
459459
index,
460460
onDragStart: handleFilterDragStart,
461461
onDragEnter: handleFilterDragEnter,
462462
onDrop: handleFilterDrop,
463463
onDragEnd: handleFilterDragEnd,
464464
isDragging: draggedFilterIndex === index,
465465
isDragOver: dragOverFilterIndex === index,
466-
}}
466+
})}
467467
class="mb-4 cursor-move rounded-2xl border-2 p-4 transition-all bg-light-50 border-dashed hover:border-light-300"
468468
>
469469
<div class="flex items-start gap-4">
@@ -524,15 +524,15 @@
524524
{@render stepSeparator()}
525525
{/if}
526526
<div
527-
use:dragAndDrop={{
527+
{@attach dragAndDrop({
528528
index,
529529
onDragStart: handleActionDragStart,
530530
onDragEnter: handleActionDragEnter,
531531
onDrop: handleActionDrop,
532532
onDragEnd: handleActionDragEnd,
533533
isDragging: draggedActionIndex === index,
534534
isDragOver: dragOverActionIndex === index,
535-
}}
535+
})}
536536
class="mb-4 cursor-move rounded-2xl border-2 p-4 transition-all bg-light-50 border-dashed hover:border-light-300"
537537
>
538538
<div class="flex items-start gap-4">

0 commit comments

Comments
 (0)