@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
package/README.md
CHANGED
|
@@ -4,6 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
<h1 align="center">FlowDrop</h1>
|
|
6
6
|
|
|
7
|
+
<p align="center">
|
|
8
|
+
<img src="https://img.shields.io/github/actions/workflow/status/d34dman/flowdrop/docker-publish.yml?style=flat-square&label=Build" alt="GitHub pages build status" />
|
|
9
|
+
<a href="https://www.npmjs.com/package/@d34dman/flowdrop"><img src="https://img.shields.io/npm/v/@d34dman/flowdrop?style=flat-square" alt="npm" /></a>
|
|
10
|
+
<img src="https://img.shields.io/npm/unpacked-size/%40d34dman%2Fflowdrop?style=flat-square" alt="NPM Unpacked Size" />
|
|
11
|
+
<img src="https://img.shields.io/npm/types/@d34dman/flowdrop?style=flat-square" alt="npm type definitions" />
|
|
12
|
+
<a href="http://npmjs.com/package/@d34dman/flowdrop"><img src="https://img.shields.io/npm/dt/@d34dman/flowdrop.svg?maxAge=2592000&style=flat-square" alt="npm downloads" /></a>
|
|
13
|
+
</p>
|
|
14
|
+
|
|
7
15
|
<p align="center">
|
|
8
16
|
<strong>Build beautiful workflow editors in minutes, not months.</strong>
|
|
9
17
|
</p>
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
<script lang="ts">
|
|
8
8
|
import { onMount, tick } from 'svelte';
|
|
9
9
|
import { page } from '$app/stores';
|
|
10
|
+
import MainLayout from './layouts/MainLayout.svelte';
|
|
10
11
|
import WorkflowEditor from './WorkflowEditor.svelte';
|
|
11
12
|
import NodeSidebar from './NodeSidebar.svelte';
|
|
12
13
|
import ConfigSidebar from './ConfigSidebar.svelte';
|
|
@@ -563,15 +564,25 @@
|
|
|
563
564
|
<meta name="description" content="A modern drag-and-drop workflow editor for LLM applications" />
|
|
564
565
|
</svelte:head>
|
|
565
566
|
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
567
|
+
<!-- MainLayout wrapper for workflow editor -->
|
|
568
|
+
<MainLayout
|
|
569
|
+
showHeader={showNavbar && !$page.url.pathname.includes('/edit')}
|
|
570
|
+
showLeftSidebar={!disableSidebar}
|
|
571
|
+
showRightSidebar={!disableSidebar && (isWorkflowSettingsOpen || !!selectedNodeForConfig())}
|
|
572
|
+
showFooter={false}
|
|
573
|
+
headerHeight={60}
|
|
574
|
+
leftSidebarWidth={320}
|
|
575
|
+
rightSidebarWidth={400}
|
|
576
|
+
leftSidebarMinWidth={280}
|
|
577
|
+
leftSidebarMaxWidth={450}
|
|
578
|
+
rightSidebarMinWidth={320}
|
|
579
|
+
rightSidebarMaxWidth={550}
|
|
580
|
+
enableLeftSplitPane={false}
|
|
581
|
+
enableRightSplitPane={true}
|
|
582
|
+
class="flowdrop-app-layout"
|
|
572
583
|
>
|
|
573
|
-
<!-- Navbar
|
|
574
|
-
{#
|
|
584
|
+
<!-- Header: Navbar -->
|
|
585
|
+
{#snippet header()}
|
|
575
586
|
<Navbar
|
|
576
587
|
title={breadcrumbTitle()}
|
|
577
588
|
primaryActions={navbarActions.length > 0
|
|
@@ -610,231 +621,225 @@
|
|
|
610
621
|
]}
|
|
611
622
|
showStatus={true}
|
|
612
623
|
/>
|
|
613
|
-
{/
|
|
614
|
-
|
|
615
|
-
<!--
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
<button
|
|
644
|
-
class="flowdrop-btn flowdrop-btn--sm flowdrop-btn--outline"
|
|
645
|
-
onclick={() => {
|
|
646
|
-
const defaultUrl = '/api/flowdrop';
|
|
647
|
-
const newUrl = prompt('Enter Backend API URL:', defaultUrl);
|
|
648
|
-
if (newUrl) {
|
|
649
|
-
const endpointConfig = createEndpointConfig(newUrl);
|
|
650
|
-
setEndpointConfig(endpointConfig);
|
|
651
|
-
fetchNodeTypes();
|
|
652
|
-
}
|
|
653
|
-
}}
|
|
654
|
-
type="button"
|
|
655
|
-
>
|
|
656
|
-
Set API URL
|
|
657
|
-
</button>
|
|
658
|
-
<button
|
|
659
|
-
class="flowdrop-btn flowdrop-btn--sm flowdrop-btn--outline"
|
|
660
|
-
onclick={testApiConnection}
|
|
661
|
-
type="button"
|
|
662
|
-
>
|
|
663
|
-
Test API
|
|
664
|
-
</button>
|
|
665
|
-
<button
|
|
666
|
-
class="flowdrop-btn flowdrop-btn--ghost flowdrop-btn--sm"
|
|
667
|
-
onclick={() => (error = null)}
|
|
668
|
-
type="button"
|
|
669
|
-
>
|
|
670
|
-
✕
|
|
671
|
-
</button>
|
|
672
|
-
</div>
|
|
673
|
-
</div>
|
|
674
|
-
</div>
|
|
675
|
-
{/if}
|
|
676
|
-
|
|
677
|
-
<!-- Workflow Editor with Sidebars -->
|
|
678
|
-
<div class="flowdrop-editor-container">
|
|
679
|
-
<!-- Left Sidebar - Node Components (conditionally rendered) -->
|
|
680
|
-
{#if !disableSidebar}
|
|
681
|
-
<div class="flowdrop-sidebar flowdrop-sidebar--left">
|
|
682
|
-
<NodeSidebar {nodes} />
|
|
624
|
+
{/snippet}
|
|
625
|
+
|
|
626
|
+
<!-- Left Sidebar: Node Components -->
|
|
627
|
+
{#snippet leftSidebar()}
|
|
628
|
+
<NodeSidebar {nodes} />
|
|
629
|
+
{/snippet}
|
|
630
|
+
|
|
631
|
+
<!-- Right Sidebar: Configuration or Workflow Settings -->
|
|
632
|
+
{#snippet rightSidebar()}
|
|
633
|
+
{#if isWorkflowSettingsOpen}
|
|
634
|
+
<ConfigSidebar
|
|
635
|
+
isOpen={isWorkflowSettingsOpen}
|
|
636
|
+
title="Workflow Settings"
|
|
637
|
+
configSchema={workflowConfigSchema}
|
|
638
|
+
configValues={workflowConfigValues}
|
|
639
|
+
onSave={handleWorkflowSave}
|
|
640
|
+
onClose={() => (isWorkflowSettingsOpen = false)}
|
|
641
|
+
/>
|
|
642
|
+
{:else if selectedNodeForConfig()}
|
|
643
|
+
<div class="flowdrop-config-sidebar">
|
|
644
|
+
<!-- Header -->
|
|
645
|
+
<div class="flowdrop-config-sidebar__header">
|
|
646
|
+
<h2 class="flowdrop-config-sidebar__title">{selectedNodeForConfig().data.label}</h2>
|
|
647
|
+
<button
|
|
648
|
+
class="flowdrop-config-sidebar__close"
|
|
649
|
+
onclick={closeConfigSidebar}
|
|
650
|
+
aria-label="Close configuration sidebar"
|
|
651
|
+
>
|
|
652
|
+
×
|
|
653
|
+
</button>
|
|
683
654
|
</div>
|
|
684
|
-
{/if}
|
|
685
|
-
|
|
686
|
-
<!-- Main Editor Area -->
|
|
687
|
-
<div
|
|
688
|
-
class="flowdrop-editor-main"
|
|
689
|
-
class:pipeline-view={!!pipelineId}
|
|
690
|
-
onclick={handleCanvasClick}
|
|
691
|
-
onkeydown={(e) => e.key === 'Escape' && closeConfigSidebar()}
|
|
692
|
-
role="button"
|
|
693
|
-
tabindex="0"
|
|
694
|
-
aria-label="Workflow canvas - click to close sidebar"
|
|
695
|
-
>
|
|
696
|
-
<WorkflowEditor
|
|
697
|
-
bind:this={workflowEditorRef}
|
|
698
|
-
{nodes}
|
|
699
|
-
{height}
|
|
700
|
-
{width}
|
|
701
|
-
{endpointConfig}
|
|
702
|
-
{isConfigSidebarOpen}
|
|
703
|
-
selectedNodeForConfig={selectedNodeForConfig()}
|
|
704
|
-
{openConfigSidebar}
|
|
705
|
-
{closeConfigSidebar}
|
|
706
|
-
{lockWorkflow}
|
|
707
|
-
{readOnly}
|
|
708
|
-
{nodeStatuses}
|
|
709
|
-
{pipelineId}
|
|
710
|
-
/>
|
|
711
|
-
</div>
|
|
712
655
|
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
<div class="flowdrop-config-sidebar__detail-value-with-copy">
|
|
747
|
-
<span
|
|
748
|
-
class="flowdrop-config-sidebar__detail-value"
|
|
749
|
-
style="font-family: monospace;"
|
|
750
|
-
>
|
|
751
|
-
{selectedNodeForConfig().id}
|
|
752
|
-
</span>
|
|
753
|
-
<button
|
|
754
|
-
class="flowdrop-config-sidebar__copy-btn"
|
|
755
|
-
onclick={() => {
|
|
756
|
-
navigator.clipboard.writeText(selectedNodeForConfig().id);
|
|
757
|
-
}}
|
|
758
|
-
title="Copy Node ID"
|
|
759
|
-
aria-label="Copy node ID to clipboard"
|
|
760
|
-
>
|
|
761
|
-
📋
|
|
762
|
-
</button>
|
|
763
|
-
</div>
|
|
764
|
-
</div>
|
|
765
|
-
<div class="flowdrop-config-sidebar__detail">
|
|
766
|
-
<span class="flowdrop-config-sidebar__detail-label">Type:</span>
|
|
767
|
-
<span class="flowdrop-config-sidebar__detail-value"
|
|
768
|
-
>{selectedNodeForConfig().data.metadata?.type ||
|
|
769
|
-
selectedNodeForConfig().type}</span
|
|
770
|
-
>
|
|
771
|
-
</div>
|
|
772
|
-
<div class="flowdrop-config-sidebar__detail">
|
|
773
|
-
<span class="flowdrop-config-sidebar__detail-label">Category:</span>
|
|
774
|
-
<span class="flowdrop-config-sidebar__detail-value"
|
|
775
|
-
>{selectedNodeForConfig().data.metadata?.category || 'general'}</span
|
|
656
|
+
<!-- Content -->
|
|
657
|
+
<div class="flowdrop-config-sidebar__content">
|
|
658
|
+
<!-- Node Details -->
|
|
659
|
+
<div class="flowdrop-config-sidebar__section">
|
|
660
|
+
<h3 class="flowdrop-config-sidebar__section-title">Node Details</h3>
|
|
661
|
+
<div class="flowdrop-config-sidebar__details">
|
|
662
|
+
<div class="flowdrop-config-sidebar__detail">
|
|
663
|
+
<span class="flowdrop-config-sidebar__detail-label">Node ID:</span>
|
|
664
|
+
<div class="flowdrop-config-sidebar__detail-value-with-copy">
|
|
665
|
+
<span
|
|
666
|
+
class="flowdrop-config-sidebar__detail-value"
|
|
667
|
+
style="font-family: monospace;"
|
|
668
|
+
>
|
|
669
|
+
{selectedNodeForConfig().id}
|
|
670
|
+
</span>
|
|
671
|
+
<button
|
|
672
|
+
class="flowdrop-config-sidebar__copy-btn"
|
|
673
|
+
onclick={() => {
|
|
674
|
+
navigator.clipboard.writeText(selectedNodeForConfig().id);
|
|
675
|
+
}}
|
|
676
|
+
title="Copy Node ID"
|
|
677
|
+
aria-label="Copy node ID to clipboard"
|
|
678
|
+
>
|
|
679
|
+
<svg
|
|
680
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
681
|
+
fill="none"
|
|
682
|
+
role="img"
|
|
683
|
+
width="1em"
|
|
684
|
+
height="1em"
|
|
685
|
+
viewBox="0 0 24 24"
|
|
686
|
+
stroke-width="1.5"
|
|
687
|
+
stroke="currentColor"
|
|
688
|
+
class="size-6"
|
|
776
689
|
>
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
</
|
|
783
|
-
</
|
|
690
|
+
<path
|
|
691
|
+
stroke-linecap="round"
|
|
692
|
+
stroke-linejoin="round"
|
|
693
|
+
d="M9 12h3.75M9 15h3.75M9 18h3.75m3 .75H18a2.25 2.25 0 0 0 2.25-2.25V6.108c0-1.135-.845-2.098-1.976-2.192a48.424 48.424 0 0 0-1.123-.08m-5.801 0c-.065.21-.1.433-.1.664 0 .414.336.75.75.75h4.5a.75.75 0 0 0 .75-.75 2.25 2.25 0 0 0-.1-.664m-5.8 0A2.251 2.251 0 0 1 13.5 2.25H15c1.012 0 1.867.668 2.15 1.586m-5.8 0c-.376.023-.75.05-1.124.08C9.095 4.01 8.25 4.973 8.25 6.108V8.25m0 0H4.875c-.621 0-1.125.504-1.125 1.125v11.25c0 .621.504 1.125 1.125 1.125h9.75c.621 0 1.125-.504 1.125-1.125V9.375c0-.621-.504-1.125-1.125-1.125H8.25ZM6.75 12h.008v.008H6.75V12Zm0 3h.008v.008H6.75V15Zm0 3h.008v.008H6.75V18Z"
|
|
694
|
+
/>
|
|
695
|
+
</svg>
|
|
696
|
+
</button>
|
|
784
697
|
</div>
|
|
785
698
|
</div>
|
|
699
|
+
<div class="flowdrop-config-sidebar__detail">
|
|
700
|
+
<span class="flowdrop-config-sidebar__detail-label">Type:</span>
|
|
701
|
+
<span class="flowdrop-config-sidebar__detail-value"
|
|
702
|
+
>{selectedNodeForConfig().data.metadata?.type ||
|
|
703
|
+
selectedNodeForConfig().type}</span
|
|
704
|
+
>
|
|
705
|
+
</div>
|
|
706
|
+
<div class="flowdrop-config-sidebar__detail">
|
|
707
|
+
<span class="flowdrop-config-sidebar__detail-label">Category:</span>
|
|
708
|
+
<span class="flowdrop-config-sidebar__detail-value"
|
|
709
|
+
>{selectedNodeForConfig().data.metadata?.category || 'general'}</span
|
|
710
|
+
>
|
|
711
|
+
</div>
|
|
712
|
+
<div class="flowdrop-config-sidebar__detail">
|
|
713
|
+
<span class="flowdrop-config-sidebar__detail-label">Description:</span>
|
|
714
|
+
<p class="flowdrop-config-sidebar__detail-description">
|
|
715
|
+
{selectedNodeForConfig().data.metadata?.description || 'Node configuration'}
|
|
716
|
+
</p>
|
|
717
|
+
</div>
|
|
718
|
+
</div>
|
|
719
|
+
</div>
|
|
786
720
|
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
}
|
|
801
|
-
};
|
|
802
|
-
|
|
803
|
-
// NOTE: We do NOT change the node's type field anymore
|
|
804
|
-
// All nodes use 'universalNode' and UniversalNode handles internal switching
|
|
805
|
-
workflowActions.updateNode(selectedNodeId, nodeUpdates);
|
|
721
|
+
<!-- Configuration Form -->
|
|
722
|
+
<div class="flowdrop-config-sidebar__section">
|
|
723
|
+
<h3 class="flowdrop-config-sidebar__section-title">Configuration</h3>
|
|
724
|
+
<ConfigForm
|
|
725
|
+
node={selectedNodeForConfig()}
|
|
726
|
+
onSave={(updatedConfig) => {
|
|
727
|
+
const currentNode = selectedNodeForConfig();
|
|
728
|
+
if (selectedNodeId && currentNode) {
|
|
729
|
+
// Handle nodeType switching if nodeType is in the config
|
|
730
|
+
let nodeUpdates: Record<string, unknown> = {
|
|
731
|
+
data: {
|
|
732
|
+
...currentNode.data,
|
|
733
|
+
config: updatedConfig
|
|
806
734
|
}
|
|
735
|
+
};
|
|
807
736
|
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
737
|
+
// NOTE: We do NOT change the node's type field anymore
|
|
738
|
+
// All nodes use 'universalNode' and UniversalNode handles internal switching
|
|
739
|
+
workflowActions.updateNode(selectedNodeId, nodeUpdates);
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
closeConfigSidebar();
|
|
743
|
+
}}
|
|
744
|
+
onCancel={closeConfigSidebar}
|
|
745
|
+
/>
|
|
814
746
|
</div>
|
|
815
747
|
</div>
|
|
816
|
-
|
|
748
|
+
</div>
|
|
749
|
+
{/if}
|
|
750
|
+
{/snippet}
|
|
751
|
+
|
|
752
|
+
<!-- Main Content: Workflow Editor with Error Status -->
|
|
753
|
+
<!-- Status Display -->
|
|
754
|
+
{#if error}
|
|
755
|
+
<div class="flowdrop-status flowdrop-status--error">
|
|
756
|
+
<div class="flowdrop-status__content">
|
|
757
|
+
<div class="flowdrop-flex flowdrop-gap--3">
|
|
758
|
+
<div class="flowdrop-status__indicator flowdrop-status__indicator--error"></div>
|
|
759
|
+
<span class="flowdrop-text--sm flowdrop-font--medium">Error: {error}</span>
|
|
760
|
+
</div>
|
|
761
|
+
<div class="flowdrop-flex flowdrop-gap--2">
|
|
762
|
+
<button
|
|
763
|
+
class="flowdrop-btn flowdrop-btn--sm flowdrop-btn--outline"
|
|
764
|
+
onclick={retryLoad}
|
|
765
|
+
type="button"
|
|
766
|
+
>
|
|
767
|
+
Retry
|
|
768
|
+
</button>
|
|
769
|
+
<button
|
|
770
|
+
class="flowdrop-btn flowdrop-btn--sm flowdrop-btn--primary"
|
|
771
|
+
onclick={() => {
|
|
772
|
+
nodes = sampleNodes;
|
|
773
|
+
error = null;
|
|
774
|
+
}}
|
|
775
|
+
type="button"
|
|
776
|
+
>
|
|
777
|
+
Use Sample Data
|
|
778
|
+
</button>
|
|
779
|
+
<button
|
|
780
|
+
class="flowdrop-btn flowdrop-btn--sm flowdrop-btn--outline"
|
|
781
|
+
onclick={() => {
|
|
782
|
+
const defaultUrl = '/api/flowdrop';
|
|
783
|
+
const newUrl = prompt('Enter Backend API URL:', defaultUrl);
|
|
784
|
+
if (newUrl) {
|
|
785
|
+
const endpointConfig = createEndpointConfig(newUrl);
|
|
786
|
+
setEndpointConfig(endpointConfig);
|
|
787
|
+
fetchNodeTypes();
|
|
788
|
+
}
|
|
789
|
+
}}
|
|
790
|
+
type="button"
|
|
791
|
+
>
|
|
792
|
+
Set API URL
|
|
793
|
+
</button>
|
|
794
|
+
<button
|
|
795
|
+
class="flowdrop-btn flowdrop-btn--sm flowdrop-btn--outline"
|
|
796
|
+
onclick={testApiConnection}
|
|
797
|
+
type="button"
|
|
798
|
+
>
|
|
799
|
+
Test API
|
|
800
|
+
</button>
|
|
801
|
+
<button
|
|
802
|
+
class="flowdrop-btn flowdrop-btn--ghost flowdrop-btn--sm"
|
|
803
|
+
onclick={() => (error = null)}
|
|
804
|
+
type="button"
|
|
805
|
+
>
|
|
806
|
+
✕
|
|
807
|
+
</button>
|
|
808
|
+
</div>
|
|
809
|
+
</div>
|
|
817
810
|
</div>
|
|
818
|
-
|
|
819
|
-
</div>
|
|
820
|
-
|
|
821
|
-
<style>
|
|
822
|
-
.flowdrop-app {
|
|
823
|
-
background: linear-gradient(135deg, #f9fafb 0%, #e0e7ff 50%, #c7d2fe 100%);
|
|
824
|
-
display: flex;
|
|
825
|
-
flex-direction: column;
|
|
826
|
-
overflow: hidden;
|
|
827
|
-
}
|
|
811
|
+
{/if}
|
|
828
812
|
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
813
|
+
<!-- Main Editor Area -->
|
|
814
|
+
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
|
|
815
|
+
<div
|
|
816
|
+
class="flowdrop-editor-main"
|
|
817
|
+
class:pipeline-view={!!pipelineId}
|
|
818
|
+
onclick={handleCanvasClick}
|
|
819
|
+
onkeydown={(e) => e.key === 'Escape' && closeConfigSidebar()}
|
|
820
|
+
role="region"
|
|
821
|
+
aria-label="Workflow canvas"
|
|
822
|
+
>
|
|
823
|
+
<WorkflowEditor
|
|
824
|
+
bind:this={workflowEditorRef}
|
|
825
|
+
{nodes}
|
|
826
|
+
{height}
|
|
827
|
+
{width}
|
|
828
|
+
{endpointConfig}
|
|
829
|
+
{isConfigSidebarOpen}
|
|
830
|
+
selectedNodeForConfig={selectedNodeForConfig()}
|
|
831
|
+
{openConfigSidebar}
|
|
832
|
+
{closeConfigSidebar}
|
|
833
|
+
{lockWorkflow}
|
|
834
|
+
{readOnly}
|
|
835
|
+
{nodeStatuses}
|
|
836
|
+
{pipelineId}
|
|
837
|
+
/>
|
|
838
|
+
</div>
|
|
839
|
+
</MainLayout>
|
|
837
840
|
|
|
841
|
+
<style>
|
|
842
|
+
/* Status bar styles */
|
|
838
843
|
.flowdrop-status {
|
|
839
844
|
background-color: #eff6ff;
|
|
840
845
|
border-bottom: 1px solid #bfdbfe;
|
|
@@ -864,6 +869,7 @@
|
|
|
864
869
|
background-color: #ef4444;
|
|
865
870
|
}
|
|
866
871
|
|
|
872
|
+
/* Button styles */
|
|
867
873
|
.flowdrop-btn {
|
|
868
874
|
padding: 0.375rem 0.75rem;
|
|
869
875
|
border-radius: 0.375rem;
|
|
@@ -912,6 +918,7 @@
|
|
|
912
918
|
color: #374151;
|
|
913
919
|
}
|
|
914
920
|
|
|
921
|
+
/* Utility classes */
|
|
915
922
|
.flowdrop-flex {
|
|
916
923
|
display: flex;
|
|
917
924
|
}
|
|
@@ -933,72 +940,12 @@
|
|
|
933
940
|
font-weight: 500;
|
|
934
941
|
}
|
|
935
942
|
|
|
936
|
-
|
|
937
|
-
0% {
|
|
938
|
-
transform: rotate(0deg);
|
|
939
|
-
}
|
|
940
|
-
100% {
|
|
941
|
-
transform: rotate(360deg);
|
|
942
|
-
}
|
|
943
|
-
}
|
|
944
|
-
|
|
945
|
-
.flowdrop-editor-container {
|
|
946
|
-
flex: 1;
|
|
947
|
-
position: relative;
|
|
948
|
-
min-height: 0;
|
|
949
|
-
overflow: hidden;
|
|
950
|
-
display: flex;
|
|
951
|
-
}
|
|
952
|
-
|
|
953
|
-
.flowdrop-sidebar {
|
|
954
|
-
background-color: #ffffff;
|
|
955
|
-
border: 1px solid #e5e7eb;
|
|
956
|
-
overflow-y: auto;
|
|
957
|
-
overflow-x: hidden;
|
|
958
|
-
height: 100%;
|
|
959
|
-
display: flex;
|
|
960
|
-
flex-direction: column;
|
|
961
|
-
/* Custom scrollbar styling */
|
|
962
|
-
scrollbar-width: thin;
|
|
963
|
-
scrollbar-color: #cbd5e1 #f1f5f9;
|
|
964
|
-
}
|
|
965
|
-
|
|
966
|
-
.flowdrop-sidebar::-webkit-scrollbar {
|
|
967
|
-
width: 8px;
|
|
968
|
-
}
|
|
969
|
-
|
|
970
|
-
.flowdrop-sidebar::-webkit-scrollbar-track {
|
|
971
|
-
background: #f1f5f9;
|
|
972
|
-
border-radius: 4px;
|
|
973
|
-
}
|
|
974
|
-
|
|
975
|
-
.flowdrop-sidebar::-webkit-scrollbar-thumb {
|
|
976
|
-
background: #cbd5e1;
|
|
977
|
-
border-radius: 4px;
|
|
978
|
-
}
|
|
979
|
-
|
|
980
|
-
.flowdrop-sidebar::-webkit-scrollbar-thumb:hover {
|
|
981
|
-
background: #94a3b8;
|
|
982
|
-
}
|
|
983
|
-
|
|
984
|
-
.flowdrop-sidebar--left {
|
|
985
|
-
width: 320px;
|
|
986
|
-
min-width: 320px;
|
|
987
|
-
border-right: 1px solid #e5e7eb;
|
|
988
|
-
box-shadow: 2px 0 4px rgba(0, 0, 0, 0.1);
|
|
989
|
-
display: flex;
|
|
990
|
-
flex-direction: column;
|
|
991
|
-
}
|
|
992
|
-
|
|
993
|
-
.flowdrop-sidebar--right {
|
|
994
|
-
border-left: 1px solid #e5e7eb;
|
|
995
|
-
box-shadow: -2px 0 4px rgba(0, 0, 0, 0.1);
|
|
996
|
-
}
|
|
997
|
-
|
|
943
|
+
/* Main editor area */
|
|
998
944
|
.flowdrop-editor-main {
|
|
999
945
|
flex: 1;
|
|
1000
946
|
position: relative;
|
|
1001
947
|
min-width: 0;
|
|
948
|
+
height: 100%;
|
|
1002
949
|
overflow: hidden;
|
|
1003
950
|
background-color: #1f2937;
|
|
1004
951
|
}
|
|
@@ -450,6 +450,9 @@
|
|
|
450
450
|
|
|
451
451
|
<!-- Footer -->
|
|
452
452
|
<div class="config-sidebar__footer">
|
|
453
|
+
{#if hasChanges}
|
|
454
|
+
<p class="config-sidebar__changes-text">You have unsaved changes</p>
|
|
455
|
+
{/if}
|
|
453
456
|
<div class="config-sidebar__actions">
|
|
454
457
|
<button
|
|
455
458
|
type="button"
|
|
@@ -471,10 +474,6 @@
|
|
|
471
474
|
Save Changes
|
|
472
475
|
</button>
|
|
473
476
|
</div>
|
|
474
|
-
|
|
475
|
-
{#if hasChanges}
|
|
476
|
-
<p class="config-sidebar__changes-text">You have unsaved changes</p>
|
|
477
|
-
{/if}
|
|
478
477
|
</div>
|
|
479
478
|
</div>
|
|
480
479
|
|
|
@@ -482,16 +481,6 @@
|
|
|
482
481
|
/* Overlay styles removed to avoid darkening the canvas */
|
|
483
482
|
|
|
484
483
|
.config-sidebar {
|
|
485
|
-
position: fixed;
|
|
486
|
-
top: var(--flowdrop-navbar-height, 60px); /* Start below navbar */
|
|
487
|
-
right: 0;
|
|
488
|
-
width: 400px;
|
|
489
|
-
height: calc(100vh - var(--flowdrop-navbar-height, 60px)); /* Account for navbar height */
|
|
490
|
-
background-color: #ffffff;
|
|
491
|
-
border-left: 1px solid #e5e7eb;
|
|
492
|
-
box-shadow: -4px 0 20px rgba(0, 0, 0, 0.15);
|
|
493
|
-
transform: translateX(100%);
|
|
494
|
-
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
495
484
|
z-index: -1;
|
|
496
485
|
display: flex;
|
|
497
486
|
flex-direction: column;
|
|
@@ -835,19 +824,13 @@
|
|
|
835
824
|
}
|
|
836
825
|
|
|
837
826
|
.config-sidebar__footer {
|
|
838
|
-
padding: 1rem 1.5rem;
|
|
839
|
-
border-top: 1px solid #e5e7eb;
|
|
840
|
-
background-color: #f9fafb;
|
|
841
827
|
flex-shrink: 0;
|
|
842
|
-
position: sticky;
|
|
843
|
-
bottom: 0;
|
|
844
|
-
z-index: 10; /* Ensure footer stays on top */
|
|
845
|
-
height: 80px; /* Increased height for footer */
|
|
846
828
|
display: flex;
|
|
847
829
|
align-items: center;
|
|
848
830
|
justify-content: flex-end;
|
|
849
831
|
gap: 0.75rem;
|
|
850
|
-
|
|
832
|
+
height: 40px;
|
|
833
|
+
align-items: center;
|
|
851
834
|
}
|
|
852
835
|
|
|
853
836
|
.config-sidebar__actions {
|
|
@@ -860,7 +843,6 @@
|
|
|
860
843
|
display: flex;
|
|
861
844
|
align-items: center;
|
|
862
845
|
gap: 0.5rem;
|
|
863
|
-
padding: 0.5rem 1rem;
|
|
864
846
|
border: 1px solid;
|
|
865
847
|
border-radius: 0.375rem;
|
|
866
848
|
font-size: 0.875rem;
|
|
@@ -184,13 +184,14 @@
|
|
|
184
184
|
<style>
|
|
185
185
|
.flowdrop-navbar {
|
|
186
186
|
height: var(--flowdrop-navbar-height, 60px);
|
|
187
|
+
width: 100%;
|
|
188
|
+
max-width: 100%;
|
|
187
189
|
display: flex;
|
|
188
190
|
align-items: center;
|
|
189
191
|
justify-content: space-between;
|
|
190
192
|
padding: 0 1rem;
|
|
191
193
|
background-color: #ffffff;
|
|
192
194
|
border-bottom: 1px solid #e5e7eb;
|
|
193
|
-
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);
|
|
194
195
|
z-index: 10;
|
|
195
196
|
}
|
|
196
197
|
|