@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.
Files changed (29) hide show
  1. package/README.md +8 -0
  2. package/dist/components/App.svelte +229 -282
  3. package/dist/components/ConfigForm.svelte +0 -3
  4. package/dist/components/ConfigSidebar.svelte +5 -23
  5. package/dist/components/Navbar.svelte +2 -1
  6. package/dist/components/NodeStatusOverlay.svelte +1 -0
  7. package/dist/components/NodeStatusOverlay.svelte.d.ts +1 -0
  8. package/dist/components/WorkflowEditor.svelte +33 -25
  9. package/dist/components/layouts/MainLayout.svelte +513 -0
  10. package/dist/components/layouts/MainLayout.svelte.d.ts +50 -0
  11. package/dist/components/{GatewayNode.svelte → nodes/GatewayNode.svelte} +3 -3
  12. package/dist/components/{GatewayNode.svelte.d.ts → nodes/GatewayNode.svelte.d.ts} +1 -1
  13. package/dist/components/{NotesNode.svelte → nodes/NotesNode.svelte} +2 -2
  14. package/dist/components/{NotesNode.svelte.d.ts → nodes/NotesNode.svelte.d.ts} +1 -1
  15. package/dist/components/{SimpleNode.svelte → nodes/SimpleNode.svelte} +2 -2
  16. package/dist/components/{SimpleNode.svelte.d.ts → nodes/SimpleNode.svelte.d.ts} +1 -1
  17. package/dist/components/{SquareNode.svelte → nodes/SquareNode.svelte} +2 -2
  18. package/dist/components/{SquareNode.svelte.d.ts → nodes/SquareNode.svelte.d.ts} +1 -1
  19. package/dist/components/{TerminalNode.svelte → nodes/TerminalNode.svelte} +2 -2
  20. package/dist/components/{TerminalNode.svelte.d.ts → nodes/TerminalNode.svelte.d.ts} +1 -1
  21. package/dist/components/{ToolNode.svelte → nodes/ToolNode.svelte} +2 -2
  22. package/dist/components/{ToolNode.svelte.d.ts → nodes/ToolNode.svelte.d.ts} +1 -1
  23. package/dist/components/{WorkflowNode.svelte → nodes/WorkflowNode.svelte} +3 -3
  24. package/dist/components/{WorkflowNode.svelte.d.ts → nodes/WorkflowNode.svelte.d.ts} +1 -1
  25. package/dist/index.d.ts +6 -6
  26. package/dist/index.js +6 -6
  27. package/dist/registry/builtinNodes.js +7 -7
  28. package/dist/styles/base.css +15 -1
  29. package/package.json +1 -1
@@ -19,6 +19,7 @@
19
19
  } from '../utils/nodeStatus.js';
20
20
 
21
21
  interface Props {
22
+ nodeId?: string;
22
23
  executionInfo?: NodeExecutionInfo;
23
24
  position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
24
25
  size?: 'sm' | 'md' | 'lg';
@@ -1,5 +1,6 @@
1
1
  import type { NodeExecutionInfo } from '../types/index.js';
2
2
  interface Props {
3
+ nodeId?: string;
3
4
  executionInfo?: NodeExecutionInfo;
4
5
  position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
5
6
  size?: 'sm' | 'md' | 'lg';
@@ -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
- <SvelteFlow
366
- bind:nodes={flowNodes}
367
- bind:edges={flowEdges}
368
- {nodeTypes}
369
- {defaultEdgeOptions}
370
- onconnect={handleConnect}
371
- ondelete={handleNodesDelete}
372
- minZoom={0.2}
373
- maxZoom={3}
374
- clickConnect={true}
375
- elevateEdgesOnSelect={true}
376
- connectionLineType={ConnectionLineType.Bezier}
377
- connectionLineComponent={ConnectionLine}
378
- snapGrid={[10, 10]}
379
- fitView
380
- >
381
- <Controls />
382
- <Background
383
- gap={10}
384
- bgColor="var(--flowdrop-background-color)"
385
- variant={BackgroundVariant.Dots}
386
- />
387
- <MiniMap />
388
- </SvelteFlow>
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: #dc2626;
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 '../types/index.js';
10
+ import type { WorkflowNode } from '../../types/index.js';
11
11
  import Icon from '@iconify/svelte';
12
- import { getNodeIcon } from '../utils/icons.js';
13
- import { getDataTypeColorToken, getCategoryColorToken } from '../utils/colors.js';
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,4 +1,4 @@
1
- import type { WorkflowNode } from '../types/index.js';
1
+ import type { WorkflowNode } from '../../types/index.js';
2
2
  interface Props {
3
3
  data: WorkflowNode['data'] & {
4
4
  nodeId?: string;
@@ -1,8 +1,8 @@
1
1
  <script lang="ts">
2
- import type { ConfigValues, NodeMetadata } from '../types/index.js';
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 './MarkdownDisplay.svelte';
5
+ import MarkdownDisplay from '../MarkdownDisplay.svelte';
6
6
 
7
7
  const dispatch = createEventDispatcher();
8
8
 
@@ -1,4 +1,4 @@
1
- import type { ConfigValues, NodeMetadata } from '../types/index.js';
1
+ import type { ConfigValues, NodeMetadata } from '../../types/index.js';
2
2
  type $$ComponentProps = {
3
3
  data: {
4
4
  label: string;