@d34dman/flowdrop 0.0.20 → 0.0.21
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 +8 -0
- package/dist/components/App.svelte +229 -282
- package/dist/components/ConfigForm.svelte +0 -3
- package/dist/components/ConfigSidebar.svelte +5 -23
- package/dist/components/Navbar.svelte +2 -1
- package/dist/components/NodeStatusOverlay.svelte +1 -0
- package/dist/components/NodeStatusOverlay.svelte.d.ts +1 -0
- package/dist/components/WorkflowEditor.svelte +33 -25
- package/dist/components/layouts/MainLayout.svelte +513 -0
- package/dist/components/layouts/MainLayout.svelte.d.ts +50 -0
- package/dist/components/{GatewayNode.svelte → nodes/GatewayNode.svelte} +3 -3
- package/dist/components/{GatewayNode.svelte.d.ts → nodes/GatewayNode.svelte.d.ts} +1 -1
- package/dist/components/{NotesNode.svelte → nodes/NotesNode.svelte} +2 -2
- package/dist/components/{NotesNode.svelte.d.ts → nodes/NotesNode.svelte.d.ts} +1 -1
- package/dist/components/{SimpleNode.svelte → nodes/SimpleNode.svelte} +2 -2
- package/dist/components/{SimpleNode.svelte.d.ts → nodes/SimpleNode.svelte.d.ts} +1 -1
- package/dist/components/{SquareNode.svelte → nodes/SquareNode.svelte} +2 -2
- package/dist/components/{SquareNode.svelte.d.ts → nodes/SquareNode.svelte.d.ts} +1 -1
- package/dist/components/{TerminalNode.svelte → nodes/TerminalNode.svelte} +2 -2
- package/dist/components/{TerminalNode.svelte.d.ts → nodes/TerminalNode.svelte.d.ts} +1 -1
- package/dist/components/{ToolNode.svelte → nodes/ToolNode.svelte} +2 -2
- package/dist/components/{ToolNode.svelte.d.ts → nodes/ToolNode.svelte.d.ts} +1 -1
- package/dist/components/{WorkflowNode.svelte → nodes/WorkflowNode.svelte} +3 -3
- package/dist/components/{WorkflowNode.svelte.d.ts → nodes/WorkflowNode.svelte.d.ts} +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.js +6 -6
- package/dist/registry/builtinNodes.js +7 -7
- package/dist/styles/base.css +15 -1
- package/package.json +1 -1
|
@@ -78,6 +78,12 @@
|
|
|
78
78
|
let previousWorkflowId: string | null = null;
|
|
79
79
|
let previousPipelineId: string | undefined = undefined;
|
|
80
80
|
|
|
81
|
+
/**
|
|
82
|
+
* Key for SvelteFlow component - changes when workflow ID changes
|
|
83
|
+
* This forces SvelteFlow to remount with fresh state, allowing fitView to work correctly
|
|
84
|
+
*/
|
|
85
|
+
let svelteFlowKey = $derived(currentWorkflow?.id ?? 'default');
|
|
86
|
+
|
|
81
87
|
$effect(() => {
|
|
82
88
|
if (currentWorkflow) {
|
|
83
89
|
const nodesWithCallbacks = currentWorkflow.nodes.map((node) => ({
|
|
@@ -362,30 +368,32 @@
|
|
|
362
368
|
<!-- Flow Canvas -->
|
|
363
369
|
<div class="flowdrop-canvas">
|
|
364
370
|
<FlowDropZone ondrop={handleNodeDrop}>
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
371
|
+
{#key svelteFlowKey}
|
|
372
|
+
<SvelteFlow
|
|
373
|
+
bind:nodes={flowNodes}
|
|
374
|
+
bind:edges={flowEdges}
|
|
375
|
+
{nodeTypes}
|
|
376
|
+
{defaultEdgeOptions}
|
|
377
|
+
onconnect={handleConnect}
|
|
378
|
+
ondelete={handleNodesDelete}
|
|
379
|
+
minZoom={0.2}
|
|
380
|
+
maxZoom={3}
|
|
381
|
+
clickConnect={true}
|
|
382
|
+
elevateEdgesOnSelect={true}
|
|
383
|
+
connectionLineType={ConnectionLineType.Bezier}
|
|
384
|
+
connectionLineComponent={ConnectionLine}
|
|
385
|
+
snapGrid={[10, 10]}
|
|
386
|
+
fitView
|
|
387
|
+
>
|
|
388
|
+
<Controls />
|
|
389
|
+
<Background
|
|
390
|
+
gap={10}
|
|
391
|
+
bgColor="var(--flowdrop-background-color)"
|
|
392
|
+
variant={BackgroundVariant.Dots}
|
|
393
|
+
/>
|
|
394
|
+
<MiniMap />
|
|
395
|
+
</SvelteFlow>
|
|
396
|
+
{/key}
|
|
389
397
|
<!-- Drop Zone Indicator -->
|
|
390
398
|
{#if flowNodes.length === 0}
|
|
391
399
|
<CanvasBanner
|
|
@@ -436,7 +444,7 @@
|
|
|
436
444
|
}
|
|
437
445
|
|
|
438
446
|
.flowdrop-text--error {
|
|
439
|
-
color:
|
|
447
|
+
color: var(--flowdrop-text-color-error);
|
|
440
448
|
}
|
|
441
449
|
|
|
442
450
|
.flowdrop-canvas {
|
|
@@ -0,0 +1,513 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
MainLayout Component
|
|
3
|
+
Provides a flexible layout with:
|
|
4
|
+
- Full width fixed-height header (optional)
|
|
5
|
+
- Three-column main area with optional resizable split panes
|
|
6
|
+
- Left sidebar, center main content, right sidebar
|
|
7
|
+
- Full width fixed-height footer (optional)
|
|
8
|
+
|
|
9
|
+
Uses Svelte 5 runes and BEM syntax
|
|
10
|
+
-->
|
|
11
|
+
|
|
12
|
+
<script lang="ts">
|
|
13
|
+
import { onMount } from 'svelte';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Configuration props for the MainLayout component
|
|
17
|
+
*/
|
|
18
|
+
interface Props {
|
|
19
|
+
/** Height of the header in pixels */
|
|
20
|
+
headerHeight?: number;
|
|
21
|
+
/** Height of the footer in pixels */
|
|
22
|
+
footerHeight?: number;
|
|
23
|
+
/** Whether to show the header */
|
|
24
|
+
showHeader?: boolean;
|
|
25
|
+
/** Whether to show the footer */
|
|
26
|
+
showFooter?: boolean;
|
|
27
|
+
/** Whether to show the left sidebar */
|
|
28
|
+
showLeftSidebar?: boolean;
|
|
29
|
+
/** Whether to show the right sidebar */
|
|
30
|
+
showRightSidebar?: boolean;
|
|
31
|
+
/** Initial width of the left sidebar in pixels */
|
|
32
|
+
leftSidebarWidth?: number;
|
|
33
|
+
/** Initial width of the right sidebar in pixels */
|
|
34
|
+
rightSidebarWidth?: number;
|
|
35
|
+
/** Minimum width for left sidebar in pixels */
|
|
36
|
+
leftSidebarMinWidth?: number;
|
|
37
|
+
/** Maximum width for left sidebar in pixels */
|
|
38
|
+
leftSidebarMaxWidth?: number;
|
|
39
|
+
/** Minimum width for right sidebar in pixels */
|
|
40
|
+
rightSidebarMinWidth?: number;
|
|
41
|
+
/** Maximum width for right sidebar in pixels */
|
|
42
|
+
rightSidebarMaxWidth?: number;
|
|
43
|
+
/** Whether to enable split pane resizing for left sidebar */
|
|
44
|
+
enableLeftSplitPane?: boolean;
|
|
45
|
+
/** Whether to enable split pane resizing for right sidebar */
|
|
46
|
+
enableRightSplitPane?: boolean;
|
|
47
|
+
/** Background color for the main layout */
|
|
48
|
+
backgroundColor?: string;
|
|
49
|
+
/** Custom CSS class for the layout container */
|
|
50
|
+
class?: string;
|
|
51
|
+
/** Slot for header content */
|
|
52
|
+
header?: import('svelte').Snippet;
|
|
53
|
+
/** Slot for left sidebar content */
|
|
54
|
+
leftSidebar?: import('svelte').Snippet;
|
|
55
|
+
/** Slot for right sidebar content */
|
|
56
|
+
rightSidebar?: import('svelte').Snippet;
|
|
57
|
+
/** Slot for footer content */
|
|
58
|
+
footer?: import('svelte').Snippet;
|
|
59
|
+
/** Slot for main content (default slot) */
|
|
60
|
+
children?: import('svelte').Snippet;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
let {
|
|
64
|
+
headerHeight = 60,
|
|
65
|
+
footerHeight = 48,
|
|
66
|
+
showHeader = true,
|
|
67
|
+
showFooter = false,
|
|
68
|
+
showLeftSidebar = true,
|
|
69
|
+
showRightSidebar = true,
|
|
70
|
+
leftSidebarWidth: initialLeftWidth = 280,
|
|
71
|
+
rightSidebarWidth: initialRightWidth = 320,
|
|
72
|
+
leftSidebarMinWidth = 200,
|
|
73
|
+
leftSidebarMaxWidth = 500,
|
|
74
|
+
rightSidebarMinWidth = 200,
|
|
75
|
+
rightSidebarMaxWidth = 500,
|
|
76
|
+
enableLeftSplitPane = true,
|
|
77
|
+
enableRightSplitPane = true,
|
|
78
|
+
backgroundColor = 'linear-gradient(135deg, #f9fafb 0%, #e0e7ff 50%, #c7d2fe 100%)',
|
|
79
|
+
class: customClass = '',
|
|
80
|
+
header,
|
|
81
|
+
leftSidebar,
|
|
82
|
+
rightSidebar,
|
|
83
|
+
footer,
|
|
84
|
+
children
|
|
85
|
+
}: Props = $props();
|
|
86
|
+
|
|
87
|
+
/** Current width of the left sidebar */
|
|
88
|
+
let leftSidebarWidth = $state(initialLeftWidth);
|
|
89
|
+
|
|
90
|
+
/** Current width of the right sidebar */
|
|
91
|
+
let rightSidebarWidth = $state(initialRightWidth);
|
|
92
|
+
|
|
93
|
+
/** Whether the user is currently dragging the left divider */
|
|
94
|
+
let isDraggingLeft = $state(false);
|
|
95
|
+
|
|
96
|
+
/** Whether the user is currently dragging the right divider */
|
|
97
|
+
let isDraggingRight = $state(false);
|
|
98
|
+
|
|
99
|
+
/** Reference to the layout container element */
|
|
100
|
+
let layoutRef: HTMLDivElement | null = null;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Handles the start of a drag operation on the left divider
|
|
104
|
+
* @param event - The mouse event that triggered the drag
|
|
105
|
+
*/
|
|
106
|
+
function handleLeftDragStart(event: MouseEvent): void {
|
|
107
|
+
if (!enableLeftSplitPane) return;
|
|
108
|
+
event.preventDefault();
|
|
109
|
+
isDraggingLeft = true;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Handles the start of a drag operation on the right divider
|
|
114
|
+
* @param event - The mouse event that triggered the drag
|
|
115
|
+
*/
|
|
116
|
+
function handleRightDragStart(event: MouseEvent): void {
|
|
117
|
+
if (!enableRightSplitPane) return;
|
|
118
|
+
event.preventDefault();
|
|
119
|
+
isDraggingRight = true;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Handles mouse movement during drag operations
|
|
124
|
+
* Updates sidebar widths based on mouse position
|
|
125
|
+
* @param event - The mouse event during drag
|
|
126
|
+
*/
|
|
127
|
+
function handleMouseMove(event: MouseEvent): void {
|
|
128
|
+
if (!layoutRef) return;
|
|
129
|
+
|
|
130
|
+
const layoutRect = layoutRef.getBoundingClientRect();
|
|
131
|
+
|
|
132
|
+
if (isDraggingLeft) {
|
|
133
|
+
// Calculate new width from the left edge of the layout
|
|
134
|
+
const newWidth = event.clientX - layoutRect.left;
|
|
135
|
+
// Clamp the width between min and max values
|
|
136
|
+
leftSidebarWidth = Math.min(Math.max(newWidth, leftSidebarMinWidth), leftSidebarMaxWidth);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (isDraggingRight) {
|
|
140
|
+
// Calculate new width from the right edge of the layout
|
|
141
|
+
const newWidth = layoutRect.right - event.clientX;
|
|
142
|
+
// Clamp the width between min and max values
|
|
143
|
+
rightSidebarWidth = Math.min(Math.max(newWidth, rightSidebarMinWidth), rightSidebarMaxWidth);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Handles the end of a drag operation
|
|
149
|
+
* Resets dragging state for both dividers
|
|
150
|
+
*/
|
|
151
|
+
function handleMouseUp(): void {
|
|
152
|
+
isDraggingLeft = false;
|
|
153
|
+
isDraggingRight = false;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Handles keyboard navigation for accessibility
|
|
158
|
+
* Allows resizing with arrow keys when divider is focused
|
|
159
|
+
* @param event - The keyboard event
|
|
160
|
+
* @param side - Which sidebar divider is being adjusted
|
|
161
|
+
*/
|
|
162
|
+
function handleKeyDown(event: KeyboardEvent, side: 'left' | 'right'): void {
|
|
163
|
+
// Check if the specific side's split pane is enabled
|
|
164
|
+
if (side === 'left' && !enableLeftSplitPane) return;
|
|
165
|
+
if (side === 'right' && !enableRightSplitPane) return;
|
|
166
|
+
|
|
167
|
+
const step = event.shiftKey ? 50 : 10;
|
|
168
|
+
|
|
169
|
+
if (side === 'left') {
|
|
170
|
+
if (event.key === 'ArrowRight') {
|
|
171
|
+
event.preventDefault();
|
|
172
|
+
leftSidebarWidth = Math.min(leftSidebarWidth + step, leftSidebarMaxWidth);
|
|
173
|
+
} else if (event.key === 'ArrowLeft') {
|
|
174
|
+
event.preventDefault();
|
|
175
|
+
leftSidebarWidth = Math.max(leftSidebarWidth - step, leftSidebarMinWidth);
|
|
176
|
+
}
|
|
177
|
+
} else {
|
|
178
|
+
if (event.key === 'ArrowLeft') {
|
|
179
|
+
event.preventDefault();
|
|
180
|
+
rightSidebarWidth = Math.min(rightSidebarWidth + step, rightSidebarMaxWidth);
|
|
181
|
+
} else if (event.key === 'ArrowRight') {
|
|
182
|
+
event.preventDefault();
|
|
183
|
+
rightSidebarWidth = Math.max(rightSidebarWidth - step, rightSidebarMinWidth);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Set up global mouse event listeners for drag operations
|
|
189
|
+
onMount(() => {
|
|
190
|
+
/**
|
|
191
|
+
* Global mouse move handler for tracking drag operations
|
|
192
|
+
*/
|
|
193
|
+
const mouseMoveHandler = (e: MouseEvent) => {
|
|
194
|
+
if (isDraggingLeft || isDraggingRight) {
|
|
195
|
+
handleMouseMove(e);
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Global mouse up handler to end drag operations
|
|
201
|
+
*/
|
|
202
|
+
const mouseUpHandler = () => {
|
|
203
|
+
handleMouseUp();
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
// Attach event listeners to window for drag tracking
|
|
207
|
+
window.addEventListener('mousemove', mouseMoveHandler);
|
|
208
|
+
window.addEventListener('mouseup', mouseUpHandler);
|
|
209
|
+
|
|
210
|
+
// Cleanup on component unmount
|
|
211
|
+
return () => {
|
|
212
|
+
window.removeEventListener('mousemove', mouseMoveHandler);
|
|
213
|
+
window.removeEventListener('mouseup', mouseUpHandler);
|
|
214
|
+
};
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
/** Computed CSS variable for header height */
|
|
218
|
+
const headerHeightVar = $derived(`${headerHeight}px`);
|
|
219
|
+
|
|
220
|
+
/** Computed CSS variable for footer height */
|
|
221
|
+
const footerHeightVar = $derived(`${footerHeight}px`);
|
|
222
|
+
|
|
223
|
+
/** Computed CSS variable for left sidebar width */
|
|
224
|
+
const leftWidthVar = $derived(`${leftSidebarWidth}px`);
|
|
225
|
+
|
|
226
|
+
/** Computed CSS variable for right sidebar width */
|
|
227
|
+
const rightWidthVar = $derived(`${rightSidebarWidth}px`);
|
|
228
|
+
</script>
|
|
229
|
+
|
|
230
|
+
<div
|
|
231
|
+
bind:this={layoutRef}
|
|
232
|
+
class="flowdrop-main-layout {customClass}"
|
|
233
|
+
class:flowdrop-main-layout--dragging={isDraggingLeft || isDraggingRight}
|
|
234
|
+
style="
|
|
235
|
+
--layout-header-height: {headerHeightVar};
|
|
236
|
+
--layout-footer-height: {footerHeightVar};
|
|
237
|
+
--layout-left-sidebar-width: {leftWidthVar};
|
|
238
|
+
--layout-right-sidebar-width: {rightWidthVar};
|
|
239
|
+
--layout-background: {backgroundColor};
|
|
240
|
+
"
|
|
241
|
+
>
|
|
242
|
+
<!-- Header Section -->
|
|
243
|
+
{#if showHeader && header}
|
|
244
|
+
<header class="flowdrop-main-layout__header">
|
|
245
|
+
{@render header()}
|
|
246
|
+
</header>
|
|
247
|
+
{/if}
|
|
248
|
+
|
|
249
|
+
<!-- Main Content Area -->
|
|
250
|
+
<div class="flowdrop-main-layout__body">
|
|
251
|
+
<!-- Left Sidebar -->
|
|
252
|
+
{#if showLeftSidebar && leftSidebar}
|
|
253
|
+
<aside class="flowdrop-main-layout__sidebar flowdrop-main-layout__sidebar--left">
|
|
254
|
+
{@render leftSidebar()}
|
|
255
|
+
</aside>
|
|
256
|
+
|
|
257
|
+
<!-- Left Divider (Resizable Handle) -->
|
|
258
|
+
{#if enableLeftSplitPane}
|
|
259
|
+
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
|
|
260
|
+
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
|
|
261
|
+
<div
|
|
262
|
+
class="flowdrop-main-layout__divider flowdrop-main-layout__divider--left"
|
|
263
|
+
class:flowdrop-main-layout__divider--active={isDraggingLeft}
|
|
264
|
+
onmousedown={handleLeftDragStart}
|
|
265
|
+
onkeydown={(e) => handleKeyDown(e, 'left')}
|
|
266
|
+
role="separator"
|
|
267
|
+
aria-orientation="vertical"
|
|
268
|
+
aria-valuenow={leftSidebarWidth}
|
|
269
|
+
aria-valuemin={leftSidebarMinWidth}
|
|
270
|
+
aria-valuemax={leftSidebarMaxWidth}
|
|
271
|
+
aria-label="Resize left sidebar"
|
|
272
|
+
tabindex="0"
|
|
273
|
+
>
|
|
274
|
+
<div class="flowdrop-main-layout__divider-handle"></div>
|
|
275
|
+
</div>
|
|
276
|
+
{/if}
|
|
277
|
+
{/if}
|
|
278
|
+
|
|
279
|
+
<!-- Center Main Content -->
|
|
280
|
+
<main class="flowdrop-main-layout__main">
|
|
281
|
+
{#if children}
|
|
282
|
+
{@render children()}
|
|
283
|
+
{/if}
|
|
284
|
+
</main>
|
|
285
|
+
|
|
286
|
+
<!-- Right Divider (Resizable Handle) -->
|
|
287
|
+
{#if showRightSidebar && rightSidebar && enableRightSplitPane}
|
|
288
|
+
<!-- svelte-ignore a11y_no_noninteractive_tabindex -->
|
|
289
|
+
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
|
|
290
|
+
<div
|
|
291
|
+
class="flowdrop-main-layout__divider flowdrop-main-layout__divider--right"
|
|
292
|
+
class:flowdrop-main-layout__divider--active={isDraggingRight}
|
|
293
|
+
onmousedown={handleRightDragStart}
|
|
294
|
+
onkeydown={(e) => handleKeyDown(e, 'right')}
|
|
295
|
+
role="separator"
|
|
296
|
+
aria-orientation="vertical"
|
|
297
|
+
aria-valuenow={rightSidebarWidth}
|
|
298
|
+
aria-valuemin={rightSidebarMinWidth}
|
|
299
|
+
aria-valuemax={rightSidebarMaxWidth}
|
|
300
|
+
aria-label="Resize right sidebar"
|
|
301
|
+
tabindex="0"
|
|
302
|
+
>
|
|
303
|
+
<div class="flowdrop-main-layout__divider-handle"></div>
|
|
304
|
+
</div>
|
|
305
|
+
{/if}
|
|
306
|
+
|
|
307
|
+
<!-- Right Sidebar -->
|
|
308
|
+
{#if showRightSidebar && rightSidebar}
|
|
309
|
+
<aside class="flowdrop-main-layout__sidebar flowdrop-main-layout__sidebar--right">
|
|
310
|
+
{@render rightSidebar()}
|
|
311
|
+
</aside>
|
|
312
|
+
{/if}
|
|
313
|
+
</div>
|
|
314
|
+
|
|
315
|
+
<!-- Footer Section -->
|
|
316
|
+
{#if showFooter && footer}
|
|
317
|
+
<footer class="flowdrop-main-layout__footer">
|
|
318
|
+
{@render footer()}
|
|
319
|
+
</footer>
|
|
320
|
+
{/if}
|
|
321
|
+
</div>
|
|
322
|
+
|
|
323
|
+
<style>
|
|
324
|
+
/* Main Layout Container */
|
|
325
|
+
.flowdrop-main-layout {
|
|
326
|
+
display: flex;
|
|
327
|
+
flex-direction: column;
|
|
328
|
+
height: 100vh;
|
|
329
|
+
width: 100%;
|
|
330
|
+
background: var(--layout-background);
|
|
331
|
+
overflow: hidden;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/* Disable text selection and pointer events during drag */
|
|
335
|
+
.flowdrop-main-layout--dragging {
|
|
336
|
+
user-select: none;
|
|
337
|
+
cursor: col-resize;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
.flowdrop-main-layout--dragging * {
|
|
341
|
+
pointer-events: none;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
.flowdrop-main-layout--dragging .flowdrop-main-layout__divider {
|
|
345
|
+
pointer-events: auto;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/* Header Section */
|
|
349
|
+
.flowdrop-main-layout__header {
|
|
350
|
+
height: var(--layout-header-height);
|
|
351
|
+
min-height: var(--layout-header-height);
|
|
352
|
+
max-height: var(--layout-header-height);
|
|
353
|
+
width: 100%;
|
|
354
|
+
background-color: #ffffff;
|
|
355
|
+
border-bottom: 1px solid #e5e7eb;
|
|
356
|
+
display: flex;
|
|
357
|
+
align-items: center;
|
|
358
|
+
z-index: 100;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/* Main Body Container */
|
|
362
|
+
.flowdrop-main-layout__body {
|
|
363
|
+
flex: 1;
|
|
364
|
+
display: flex;
|
|
365
|
+
min-height: 0;
|
|
366
|
+
overflow: hidden;
|
|
367
|
+
position: relative;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/* Sidebar Base Styles */
|
|
371
|
+
.flowdrop-main-layout__sidebar {
|
|
372
|
+
height: 100%;
|
|
373
|
+
background-color: #ffffff;
|
|
374
|
+
overflow-y: auto;
|
|
375
|
+
overflow-x: hidden;
|
|
376
|
+
display: flex;
|
|
377
|
+
flex-direction: column;
|
|
378
|
+
z-index: 10;
|
|
379
|
+
|
|
380
|
+
/* Custom scrollbar styling */
|
|
381
|
+
scrollbar-width: thin;
|
|
382
|
+
scrollbar-color: #cbd5e1 #f1f5f9;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
.flowdrop-main-layout__sidebar::-webkit-scrollbar {
|
|
386
|
+
width: 8px;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
.flowdrop-main-layout__sidebar::-webkit-scrollbar-track {
|
|
390
|
+
background: #f1f5f9;
|
|
391
|
+
border-radius: 4px;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
.flowdrop-main-layout__sidebar::-webkit-scrollbar-thumb {
|
|
395
|
+
background: #cbd5e1;
|
|
396
|
+
border-radius: 4px;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
.flowdrop-main-layout__sidebar::-webkit-scrollbar-thumb:hover {
|
|
400
|
+
background: #94a3b8;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/* Left Sidebar */
|
|
404
|
+
.flowdrop-main-layout__sidebar--left {
|
|
405
|
+
width: var(--layout-left-sidebar-width);
|
|
406
|
+
min-width: var(--layout-left-sidebar-width);
|
|
407
|
+
border-right: 1px solid #e5e7eb;
|
|
408
|
+
box-shadow: 2px 0 4px rgba(0, 0, 0, 0.05);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/* Right Sidebar */
|
|
412
|
+
.flowdrop-main-layout__sidebar--right {
|
|
413
|
+
width: var(--layout-right-sidebar-width);
|
|
414
|
+
min-width: var(--layout-right-sidebar-width);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/* Main Content Area */
|
|
418
|
+
.flowdrop-main-layout__main {
|
|
419
|
+
flex: 1;
|
|
420
|
+
min-width: 0;
|
|
421
|
+
height: 100%;
|
|
422
|
+
overflow: auto;
|
|
423
|
+
position: relative;
|
|
424
|
+
display: flex;
|
|
425
|
+
flex-direction: column;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/* Divider (Resize Handle) Base Styles */
|
|
429
|
+
.flowdrop-main-layout__divider {
|
|
430
|
+
width: 8px;
|
|
431
|
+
height: 100%;
|
|
432
|
+
display: flex;
|
|
433
|
+
align-items: center;
|
|
434
|
+
justify-content: center;
|
|
435
|
+
cursor: col-resize;
|
|
436
|
+
background-color: white;
|
|
437
|
+
position: relative;
|
|
438
|
+
z-index: 20;
|
|
439
|
+
flex-shrink: 0;
|
|
440
|
+
transition: background-color 0.2s ease;
|
|
441
|
+
border-right: 1px solid #e5e7eb;
|
|
442
|
+
border-left: 1px solid #e5e7eb;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
.flowdrop-main-layout__divider:hover,
|
|
446
|
+
.flowdrop-main-layout__divider:focus {
|
|
447
|
+
background-color: rgba(59, 130, 246, 0.1);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
.flowdrop-main-layout__divider:focus {
|
|
451
|
+
outline: none;
|
|
452
|
+
background-color: rgba(59, 130, 246, 0.15);
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
.flowdrop-main-layout__divider--active {
|
|
456
|
+
background-color: rgba(59, 130, 246, 0.2);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/* Divider Handle (Visual Indicator) */
|
|
460
|
+
.flowdrop-main-layout__divider-handle {
|
|
461
|
+
width: 4px;
|
|
462
|
+
height: 48px;
|
|
463
|
+
background-color: #e5e7eb;
|
|
464
|
+
border-radius: 4px;
|
|
465
|
+
transition:
|
|
466
|
+
background-color 0.2s ease,
|
|
467
|
+
transform 0.2s ease;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
.flowdrop-main-layout__divider:hover .flowdrop-main-layout__divider-handle,
|
|
471
|
+
.flowdrop-main-layout__divider:focus .flowdrop-main-layout__divider-handle {
|
|
472
|
+
background-color: #3b82f6;
|
|
473
|
+
transform: scaleY(1.2);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
.flowdrop-main-layout__divider--active .flowdrop-main-layout__divider-handle {
|
|
477
|
+
background-color: #2563eb;
|
|
478
|
+
transform: scaleY(1.4);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/* Footer Section */
|
|
482
|
+
.flowdrop-main-layout__footer {
|
|
483
|
+
height: var(--layout-footer-height);
|
|
484
|
+
min-height: var(--layout-footer-height);
|
|
485
|
+
max-height: var(--layout-footer-height);
|
|
486
|
+
width: 100%;
|
|
487
|
+
background-color: #ffffff;
|
|
488
|
+
border-top: 1px solid #e5e7eb;
|
|
489
|
+
display: flex;
|
|
490
|
+
align-items: center;
|
|
491
|
+
z-index: 100;
|
|
492
|
+
box-shadow: 0 -1px 3px rgba(0, 0, 0, 0.05);
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
/* Responsive Adjustments */
|
|
496
|
+
@media (max-width: 768px) {
|
|
497
|
+
.flowdrop-main-layout__sidebar--left,
|
|
498
|
+
.flowdrop-main-layout__sidebar--right {
|
|
499
|
+
position: absolute;
|
|
500
|
+
top: 0;
|
|
501
|
+
bottom: 0;
|
|
502
|
+
z-index: 50;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
.flowdrop-main-layout__sidebar--left {
|
|
506
|
+
left: 0;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
.flowdrop-main-layout__sidebar--right {
|
|
510
|
+
right: 0;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
</style>
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration props for the MainLayout component
|
|
3
|
+
*/
|
|
4
|
+
interface Props {
|
|
5
|
+
/** Height of the header in pixels */
|
|
6
|
+
headerHeight?: number;
|
|
7
|
+
/** Height of the footer in pixels */
|
|
8
|
+
footerHeight?: number;
|
|
9
|
+
/** Whether to show the header */
|
|
10
|
+
showHeader?: boolean;
|
|
11
|
+
/** Whether to show the footer */
|
|
12
|
+
showFooter?: boolean;
|
|
13
|
+
/** Whether to show the left sidebar */
|
|
14
|
+
showLeftSidebar?: boolean;
|
|
15
|
+
/** Whether to show the right sidebar */
|
|
16
|
+
showRightSidebar?: boolean;
|
|
17
|
+
/** Initial width of the left sidebar in pixels */
|
|
18
|
+
leftSidebarWidth?: number;
|
|
19
|
+
/** Initial width of the right sidebar in pixels */
|
|
20
|
+
rightSidebarWidth?: number;
|
|
21
|
+
/** Minimum width for left sidebar in pixels */
|
|
22
|
+
leftSidebarMinWidth?: number;
|
|
23
|
+
/** Maximum width for left sidebar in pixels */
|
|
24
|
+
leftSidebarMaxWidth?: number;
|
|
25
|
+
/** Minimum width for right sidebar in pixels */
|
|
26
|
+
rightSidebarMinWidth?: number;
|
|
27
|
+
/** Maximum width for right sidebar in pixels */
|
|
28
|
+
rightSidebarMaxWidth?: number;
|
|
29
|
+
/** Whether to enable split pane resizing for left sidebar */
|
|
30
|
+
enableLeftSplitPane?: boolean;
|
|
31
|
+
/** Whether to enable split pane resizing for right sidebar */
|
|
32
|
+
enableRightSplitPane?: boolean;
|
|
33
|
+
/** Background color for the main layout */
|
|
34
|
+
backgroundColor?: string;
|
|
35
|
+
/** Custom CSS class for the layout container */
|
|
36
|
+
class?: string;
|
|
37
|
+
/** Slot for header content */
|
|
38
|
+
header?: import('svelte').Snippet;
|
|
39
|
+
/** Slot for left sidebar content */
|
|
40
|
+
leftSidebar?: import('svelte').Snippet;
|
|
41
|
+
/** Slot for right sidebar content */
|
|
42
|
+
rightSidebar?: import('svelte').Snippet;
|
|
43
|
+
/** Slot for footer content */
|
|
44
|
+
footer?: import('svelte').Snippet;
|
|
45
|
+
/** Slot for main content (default slot) */
|
|
46
|
+
children?: import('svelte').Snippet;
|
|
47
|
+
}
|
|
48
|
+
declare const MainLayout: import("svelte").Component<Props, {}, "">;
|
|
49
|
+
type MainLayout = ReturnType<typeof MainLayout>;
|
|
50
|
+
export default MainLayout;
|
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
|
|
8
8
|
<script lang="ts">
|
|
9
9
|
import { Position, Handle } from '@xyflow/svelte';
|
|
10
|
-
import type { WorkflowNode } from '
|
|
10
|
+
import type { WorkflowNode } from '../../types/index.js';
|
|
11
11
|
import Icon from '@iconify/svelte';
|
|
12
|
-
import { getNodeIcon } from '
|
|
13
|
-
import { getDataTypeColorToken, getCategoryColorToken } from '
|
|
12
|
+
import { getNodeIcon } from '../../utils/icons.js';
|
|
13
|
+
import { getDataTypeColorToken, getCategoryColorToken } from '../../utils/colors.js';
|
|
14
14
|
|
|
15
15
|
// Define simplified branch interface - conditions are handled by backend
|
|
16
16
|
interface Branch {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import type { ConfigValues, NodeMetadata } from '
|
|
2
|
+
import type { ConfigValues, NodeMetadata } from '../../types/index.js';
|
|
3
3
|
import Icon from '@iconify/svelte';
|
|
4
4
|
import { createEventDispatcher } from 'svelte';
|
|
5
|
-
import MarkdownDisplay from '
|
|
5
|
+
import MarkdownDisplay from '../MarkdownDisplay.svelte';
|
|
6
6
|
|
|
7
7
|
const dispatch = createEventDispatcher();
|
|
8
8
|
|