@d34dman/flowdrop 0.0.20 → 0.0.22
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 +172 -417
- package/dist/components/ConfigForm.svelte +707 -241
- package/dist/components/ConfigForm.svelte.d.ts +9 -2
- package/dist/components/ConfigPanel.svelte +160 -0
- package/dist/components/ConfigPanel.svelte.d.ts +32 -0
- 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/ReadOnlyDetails.svelte +168 -0
- package/dist/components/ReadOnlyDetails.svelte.d.ts +25 -0
- package/dist/components/WorkflowEditor.svelte +34 -26
- 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/nodes/NotesNode.svelte +348 -0
- package/dist/components/nodes/NotesNode.svelte.d.ts +24 -0
- 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 +8 -7
- package/dist/index.js +8 -7
- package/dist/registry/builtinNodes.js +7 -7
- package/dist/styles/base.css +15 -1
- package/package.json +1 -1
- package/dist/components/ConfigSidebar.svelte +0 -934
- package/dist/components/ConfigSidebar.svelte.d.ts +0 -51
- package/dist/components/NotesNode.svelte +0 -566
- package/dist/components/NotesNode.svelte.d.ts +0 -43
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,10 +7,11 @@
|
|
|
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
|
-
import ConfigSidebar from './ConfigSidebar.svelte';
|
|
13
13
|
import ConfigForm from './ConfigForm.svelte';
|
|
14
|
+
import ConfigPanel from './ConfigPanel.svelte';
|
|
14
15
|
import Navbar from './Navbar.svelte';
|
|
15
16
|
import { api, setEndpointConfig } from '../services/api.js';
|
|
16
17
|
import type { NodeMetadata, Workflow, WorkflowNode, ConfigSchema } from '../types/index.js';
|
|
@@ -137,6 +138,7 @@
|
|
|
137
138
|
type: 'string',
|
|
138
139
|
title: 'Description',
|
|
139
140
|
description: 'A description of the workflow',
|
|
141
|
+
format: 'multiline',
|
|
140
142
|
default: ''
|
|
141
143
|
}
|
|
142
144
|
},
|
|
@@ -563,15 +565,25 @@
|
|
|
563
565
|
<meta name="description" content="A modern drag-and-drop workflow editor for LLM applications" />
|
|
564
566
|
</svelte:head>
|
|
565
567
|
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
568
|
+
<!-- MainLayout wrapper for workflow editor -->
|
|
569
|
+
<MainLayout
|
|
570
|
+
showHeader={showNavbar && !$page.url.pathname.includes('/edit')}
|
|
571
|
+
showLeftSidebar={!disableSidebar}
|
|
572
|
+
showRightSidebar={!disableSidebar && (isWorkflowSettingsOpen || !!selectedNodeForConfig())}
|
|
573
|
+
showFooter={false}
|
|
574
|
+
headerHeight={60}
|
|
575
|
+
leftSidebarWidth={320}
|
|
576
|
+
rightSidebarWidth={400}
|
|
577
|
+
leftSidebarMinWidth={280}
|
|
578
|
+
leftSidebarMaxWidth={450}
|
|
579
|
+
rightSidebarMinWidth={320}
|
|
580
|
+
rightSidebarMaxWidth={550}
|
|
581
|
+
enableLeftSplitPane={false}
|
|
582
|
+
enableRightSplitPane={true}
|
|
583
|
+
class="flowdrop-app-layout"
|
|
572
584
|
>
|
|
573
|
-
<!-- Navbar
|
|
574
|
-
{#
|
|
585
|
+
<!-- Header: Navbar -->
|
|
586
|
+
{#snippet header()}
|
|
575
587
|
<Navbar
|
|
576
588
|
title={breadcrumbTitle()}
|
|
577
589
|
primaryActions={navbarActions.length > 0
|
|
@@ -610,231 +622,161 @@
|
|
|
610
622
|
]}
|
|
611
623
|
showStatus={true}
|
|
612
624
|
/>
|
|
613
|
-
{/
|
|
614
|
-
|
|
615
|
-
<!--
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
</button>
|
|
633
|
-
<button
|
|
634
|
-
class="flowdrop-btn flowdrop-btn--sm flowdrop-btn--primary"
|
|
635
|
-
onclick={() => {
|
|
636
|
-
nodes = sampleNodes;
|
|
637
|
-
error = null;
|
|
638
|
-
}}
|
|
639
|
-
type="button"
|
|
640
|
-
>
|
|
641
|
-
Use Sample Data
|
|
642
|
-
</button>
|
|
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} />
|
|
683
|
-
</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"
|
|
625
|
+
{/snippet}
|
|
626
|
+
|
|
627
|
+
<!-- Left Sidebar: Node Components -->
|
|
628
|
+
{#snippet leftSidebar()}
|
|
629
|
+
<NodeSidebar {nodes} />
|
|
630
|
+
{/snippet}
|
|
631
|
+
|
|
632
|
+
<!-- Right Sidebar: Configuration or Workflow Settings -->
|
|
633
|
+
{#snippet rightSidebar()}
|
|
634
|
+
{#if isWorkflowSettingsOpen}
|
|
635
|
+
<ConfigPanel
|
|
636
|
+
title="Workflow Settings"
|
|
637
|
+
id={$workflowStore?.id}
|
|
638
|
+
details={[
|
|
639
|
+
{ label: 'Nodes', value: String($workflowStore?.nodes?.length ?? 0) },
|
|
640
|
+
{ label: 'Connections', value: String($workflowStore?.edges?.length ?? 0) }
|
|
641
|
+
]}
|
|
642
|
+
configTitle="Settings"
|
|
643
|
+
onClose={() => (isWorkflowSettingsOpen = false)}
|
|
695
644
|
>
|
|
696
|
-
<
|
|
697
|
-
|
|
698
|
-
{
|
|
699
|
-
{
|
|
700
|
-
{
|
|
701
|
-
{endpointConfig}
|
|
702
|
-
{isConfigSidebarOpen}
|
|
703
|
-
selectedNodeForConfig={selectedNodeForConfig()}
|
|
704
|
-
{openConfigSidebar}
|
|
705
|
-
{closeConfigSidebar}
|
|
706
|
-
{lockWorkflow}
|
|
707
|
-
{readOnly}
|
|
708
|
-
{nodeStatuses}
|
|
709
|
-
{pipelineId}
|
|
645
|
+
<ConfigForm
|
|
646
|
+
schema={workflowConfigSchema}
|
|
647
|
+
values={workflowConfigValues}
|
|
648
|
+
onSave={handleWorkflowSave}
|
|
649
|
+
onCancel={() => (isWorkflowSettingsOpen = false)}
|
|
710
650
|
/>
|
|
711
|
-
</
|
|
651
|
+
</ConfigPanel>
|
|
652
|
+
{:else if selectedNodeForConfig()}
|
|
653
|
+
{@const currentNode = selectedNodeForConfig()}
|
|
654
|
+
<ConfigPanel
|
|
655
|
+
title={currentNode.data.label}
|
|
656
|
+
id={currentNode.id}
|
|
657
|
+
description={currentNode.data.metadata?.description || 'Node configuration'}
|
|
658
|
+
details={[
|
|
659
|
+
{ label: 'Type', value: currentNode.data.metadata?.type || currentNode.type },
|
|
660
|
+
{ label: 'Category', value: currentNode.data.metadata?.category || 'general' }
|
|
661
|
+
]}
|
|
662
|
+
onClose={closeConfigSidebar}
|
|
663
|
+
>
|
|
664
|
+
<ConfigForm
|
|
665
|
+
node={currentNode}
|
|
666
|
+
onSave={(updatedConfig) => {
|
|
667
|
+
if (selectedNodeId && currentNode) {
|
|
668
|
+
// Handle nodeType switching if nodeType is in the config
|
|
669
|
+
let nodeUpdates: Record<string, unknown> = {
|
|
670
|
+
data: {
|
|
671
|
+
...currentNode.data,
|
|
672
|
+
config: updatedConfig
|
|
673
|
+
}
|
|
674
|
+
};
|
|
712
675
|
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
onClose={() => (isWorkflowSettingsOpen = false)}
|
|
676
|
+
// NOTE: We do NOT change the node's type field anymore
|
|
677
|
+
// All nodes use 'universalNode' and UniversalNode handles internal switching
|
|
678
|
+
workflowActions.updateNode(selectedNodeId, nodeUpdates);
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
closeConfigSidebar();
|
|
682
|
+
}}
|
|
683
|
+
onCancel={closeConfigSidebar}
|
|
722
684
|
/>
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
</button>
|
|
736
|
-
</div>
|
|
737
|
-
|
|
738
|
-
<!-- Content -->
|
|
739
|
-
<div class="flowdrop-config-sidebar__content">
|
|
740
|
-
<!-- Node Details -->
|
|
741
|
-
<div class="flowdrop-config-sidebar__section">
|
|
742
|
-
<h3 class="flowdrop-config-sidebar__section-title">Node Details</h3>
|
|
743
|
-
<div class="flowdrop-config-sidebar__details">
|
|
744
|
-
<div class="flowdrop-config-sidebar__detail">
|
|
745
|
-
<span class="flowdrop-config-sidebar__detail-label">Node ID:</span>
|
|
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
|
|
776
|
-
>
|
|
777
|
-
</div>
|
|
778
|
-
<div class="flowdrop-config-sidebar__detail">
|
|
779
|
-
<span class="flowdrop-config-sidebar__detail-label">Description:</span>
|
|
780
|
-
<p class="flowdrop-config-sidebar__detail-description">
|
|
781
|
-
{selectedNodeForConfig().data.metadata?.description || 'Node configuration'}
|
|
782
|
-
</p>
|
|
783
|
-
</div>
|
|
784
|
-
</div>
|
|
785
|
-
</div>
|
|
786
|
-
|
|
787
|
-
<!-- Configuration Form -->
|
|
788
|
-
<div class="flowdrop-config-sidebar__section">
|
|
789
|
-
<h3 class="flowdrop-config-sidebar__section-title">Configuration</h3>
|
|
790
|
-
<ConfigForm
|
|
791
|
-
node={selectedNodeForConfig()}
|
|
792
|
-
onSave={(updatedConfig) => {
|
|
793
|
-
const currentNode = selectedNodeForConfig();
|
|
794
|
-
if (selectedNodeId && currentNode) {
|
|
795
|
-
// Handle nodeType switching if nodeType is in the config
|
|
796
|
-
let nodeUpdates: Record<string, unknown> = {
|
|
797
|
-
data: {
|
|
798
|
-
...currentNode.data,
|
|
799
|
-
config: updatedConfig
|
|
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);
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
closeConfigSidebar();
|
|
809
|
-
}}
|
|
810
|
-
onCancel={closeConfigSidebar}
|
|
811
|
-
/>
|
|
812
|
-
</div>
|
|
813
|
-
</div>
|
|
814
|
-
</div>
|
|
685
|
+
</ConfigPanel>
|
|
686
|
+
{/if}
|
|
687
|
+
{/snippet}
|
|
688
|
+
|
|
689
|
+
<!-- Main Content: Workflow Editor with Error Status -->
|
|
690
|
+
<!-- Status Display -->
|
|
691
|
+
{#if error}
|
|
692
|
+
<div class="flowdrop-status flowdrop-status--error">
|
|
693
|
+
<div class="flowdrop-status__content">
|
|
694
|
+
<div class="flowdrop-flex flowdrop-gap--3">
|
|
695
|
+
<div class="flowdrop-status__indicator flowdrop-status__indicator--error"></div>
|
|
696
|
+
<span class="flowdrop-text--sm flowdrop-font--medium">Error: {error}</span>
|
|
815
697
|
</div>
|
|
816
|
-
|
|
698
|
+
<div class="flowdrop-flex flowdrop-gap--2">
|
|
699
|
+
<button
|
|
700
|
+
class="flowdrop-btn flowdrop-btn--sm flowdrop-btn--outline"
|
|
701
|
+
onclick={retryLoad}
|
|
702
|
+
type="button"
|
|
703
|
+
>
|
|
704
|
+
Retry
|
|
705
|
+
</button>
|
|
706
|
+
<button
|
|
707
|
+
class="flowdrop-btn flowdrop-btn--sm flowdrop-btn--primary"
|
|
708
|
+
onclick={() => {
|
|
709
|
+
nodes = sampleNodes;
|
|
710
|
+
error = null;
|
|
711
|
+
}}
|
|
712
|
+
type="button"
|
|
713
|
+
>
|
|
714
|
+
Use Sample Data
|
|
715
|
+
</button>
|
|
716
|
+
<button
|
|
717
|
+
class="flowdrop-btn flowdrop-btn--sm flowdrop-btn--outline"
|
|
718
|
+
onclick={() => {
|
|
719
|
+
const defaultUrl = '/api/flowdrop';
|
|
720
|
+
const newUrl = prompt('Enter Backend API URL:', defaultUrl);
|
|
721
|
+
if (newUrl) {
|
|
722
|
+
const endpointConfig = createEndpointConfig(newUrl);
|
|
723
|
+
setEndpointConfig(endpointConfig);
|
|
724
|
+
fetchNodeTypes();
|
|
725
|
+
}
|
|
726
|
+
}}
|
|
727
|
+
type="button"
|
|
728
|
+
>
|
|
729
|
+
Set API URL
|
|
730
|
+
</button>
|
|
731
|
+
<button
|
|
732
|
+
class="flowdrop-btn flowdrop-btn--sm flowdrop-btn--outline"
|
|
733
|
+
onclick={testApiConnection}
|
|
734
|
+
type="button"
|
|
735
|
+
>
|
|
736
|
+
Test API
|
|
737
|
+
</button>
|
|
738
|
+
<button
|
|
739
|
+
class="flowdrop-btn flowdrop-btn--ghost flowdrop-btn--sm"
|
|
740
|
+
onclick={() => (error = null)}
|
|
741
|
+
type="button"
|
|
742
|
+
>
|
|
743
|
+
✕
|
|
744
|
+
</button>
|
|
745
|
+
</div>
|
|
746
|
+
</div>
|
|
817
747
|
</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
|
-
}
|
|
748
|
+
{/if}
|
|
828
749
|
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
750
|
+
<!-- Main Editor Area -->
|
|
751
|
+
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
|
|
752
|
+
<div
|
|
753
|
+
class="flowdrop-editor-main"
|
|
754
|
+
class:pipeline-view={!!pipelineId}
|
|
755
|
+
onclick={handleCanvasClick}
|
|
756
|
+
onkeydown={(e) => e.key === 'Escape' && closeConfigSidebar()}
|
|
757
|
+
role="region"
|
|
758
|
+
aria-label="Workflow canvas"
|
|
759
|
+
>
|
|
760
|
+
<WorkflowEditor
|
|
761
|
+
bind:this={workflowEditorRef}
|
|
762
|
+
{nodes}
|
|
763
|
+
{height}
|
|
764
|
+
{width}
|
|
765
|
+
{endpointConfig}
|
|
766
|
+
{isConfigSidebarOpen}
|
|
767
|
+
selectedNodeForConfig={selectedNodeForConfig()}
|
|
768
|
+
{openConfigSidebar}
|
|
769
|
+
{closeConfigSidebar}
|
|
770
|
+
{lockWorkflow}
|
|
771
|
+
{readOnly}
|
|
772
|
+
{nodeStatuses}
|
|
773
|
+
{pipelineId}
|
|
774
|
+
/>
|
|
775
|
+
</div>
|
|
776
|
+
</MainLayout>
|
|
837
777
|
|
|
778
|
+
<style>
|
|
779
|
+
/* Status bar styles */
|
|
838
780
|
.flowdrop-status {
|
|
839
781
|
background-color: #eff6ff;
|
|
840
782
|
border-bottom: 1px solid #bfdbfe;
|
|
@@ -864,6 +806,7 @@
|
|
|
864
806
|
background-color: #ef4444;
|
|
865
807
|
}
|
|
866
808
|
|
|
809
|
+
/* Button styles */
|
|
867
810
|
.flowdrop-btn {
|
|
868
811
|
padding: 0.375rem 0.75rem;
|
|
869
812
|
border-radius: 0.375rem;
|
|
@@ -912,6 +855,7 @@
|
|
|
912
855
|
color: #374151;
|
|
913
856
|
}
|
|
914
857
|
|
|
858
|
+
/* Utility classes */
|
|
915
859
|
.flowdrop-flex {
|
|
916
860
|
display: flex;
|
|
917
861
|
}
|
|
@@ -933,202 +877,13 @@
|
|
|
933
877
|
font-weight: 500;
|
|
934
878
|
}
|
|
935
879
|
|
|
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
|
-
|
|
880
|
+
/* Main editor area */
|
|
998
881
|
.flowdrop-editor-main {
|
|
999
882
|
flex: 1;
|
|
1000
883
|
position: relative;
|
|
1001
884
|
min-width: 0;
|
|
885
|
+
height: 100%;
|
|
1002
886
|
overflow: hidden;
|
|
1003
887
|
background-color: #1f2937;
|
|
1004
888
|
}
|
|
1005
|
-
|
|
1006
|
-
/* Configuration Sidebar Styles */
|
|
1007
|
-
.flowdrop-config-sidebar {
|
|
1008
|
-
height: 100%;
|
|
1009
|
-
display: flex;
|
|
1010
|
-
flex-direction: column;
|
|
1011
|
-
background-color: #ffffff;
|
|
1012
|
-
}
|
|
1013
|
-
|
|
1014
|
-
.flowdrop-config-sidebar__header {
|
|
1015
|
-
display: flex;
|
|
1016
|
-
justify-content: space-between;
|
|
1017
|
-
align-items: center;
|
|
1018
|
-
padding: 1rem;
|
|
1019
|
-
border-bottom: 1px solid #e5e7eb;
|
|
1020
|
-
background-color: #f9fafb;
|
|
1021
|
-
}
|
|
1022
|
-
|
|
1023
|
-
.flowdrop-config-sidebar__title {
|
|
1024
|
-
margin: 0;
|
|
1025
|
-
font-size: 1.125rem;
|
|
1026
|
-
font-weight: 600;
|
|
1027
|
-
color: #111827;
|
|
1028
|
-
}
|
|
1029
|
-
|
|
1030
|
-
.flowdrop-config-sidebar__close {
|
|
1031
|
-
background: none;
|
|
1032
|
-
border: none;
|
|
1033
|
-
font-size: 1.5rem;
|
|
1034
|
-
cursor: pointer;
|
|
1035
|
-
color: #6b7280;
|
|
1036
|
-
padding: 0.25rem;
|
|
1037
|
-
border-radius: 0.25rem;
|
|
1038
|
-
transition: color 0.2s;
|
|
1039
|
-
}
|
|
1040
|
-
|
|
1041
|
-
.flowdrop-config-sidebar__close:hover {
|
|
1042
|
-
color: #374151;
|
|
1043
|
-
background-color: #f3f4f6;
|
|
1044
|
-
}
|
|
1045
|
-
|
|
1046
|
-
.flowdrop-config-sidebar__content {
|
|
1047
|
-
flex: 1;
|
|
1048
|
-
overflow-y: auto;
|
|
1049
|
-
padding: 1rem;
|
|
1050
|
-
}
|
|
1051
|
-
|
|
1052
|
-
.flowdrop-config-sidebar__section {
|
|
1053
|
-
margin-bottom: 1.5rem;
|
|
1054
|
-
}
|
|
1055
|
-
|
|
1056
|
-
.flowdrop-config-sidebar__section-title {
|
|
1057
|
-
margin: 0 0 0.75rem 0;
|
|
1058
|
-
font-size: 0.875rem;
|
|
1059
|
-
font-weight: 600;
|
|
1060
|
-
color: #374151;
|
|
1061
|
-
text-transform: uppercase;
|
|
1062
|
-
letter-spacing: 0.05em;
|
|
1063
|
-
}
|
|
1064
|
-
|
|
1065
|
-
.flowdrop-config-sidebar__details {
|
|
1066
|
-
display: flex;
|
|
1067
|
-
flex-direction: column;
|
|
1068
|
-
gap: 0.5rem;
|
|
1069
|
-
}
|
|
1070
|
-
|
|
1071
|
-
.flowdrop-config-sidebar__detail {
|
|
1072
|
-
display: flex;
|
|
1073
|
-
flex-direction: column;
|
|
1074
|
-
gap: 0.25rem;
|
|
1075
|
-
}
|
|
1076
|
-
|
|
1077
|
-
.flowdrop-config-sidebar__detail-label {
|
|
1078
|
-
font-size: 0.75rem;
|
|
1079
|
-
font-weight: 500;
|
|
1080
|
-
color: #6b7280;
|
|
1081
|
-
text-transform: uppercase;
|
|
1082
|
-
letter-spacing: 0.05em;
|
|
1083
|
-
}
|
|
1084
|
-
|
|
1085
|
-
.flowdrop-config-sidebar__detail-value {
|
|
1086
|
-
font-size: 0.875rem;
|
|
1087
|
-
color: #111827;
|
|
1088
|
-
font-weight: 500;
|
|
1089
|
-
}
|
|
1090
|
-
|
|
1091
|
-
.flowdrop-config-sidebar__detail-value-with-copy {
|
|
1092
|
-
display: flex;
|
|
1093
|
-
align-items: center;
|
|
1094
|
-
gap: 0.5rem;
|
|
1095
|
-
background-color: #f3f4f6;
|
|
1096
|
-
padding: 0.5rem;
|
|
1097
|
-
border-radius: 0.375rem;
|
|
1098
|
-
border: 1px solid #e5e7eb;
|
|
1099
|
-
}
|
|
1100
|
-
|
|
1101
|
-
.flowdrop-config-sidebar__detail-value-with-copy .flowdrop-config-sidebar__detail-value {
|
|
1102
|
-
flex: 1;
|
|
1103
|
-
font-size: 0.8125rem;
|
|
1104
|
-
word-break: break-all;
|
|
1105
|
-
}
|
|
1106
|
-
|
|
1107
|
-
.flowdrop-config-sidebar__copy-btn {
|
|
1108
|
-
background: white;
|
|
1109
|
-
border: 1px solid #d1d5db;
|
|
1110
|
-
border-radius: 0.25rem;
|
|
1111
|
-
padding: 0.25rem 0.5rem;
|
|
1112
|
-
cursor: pointer;
|
|
1113
|
-
font-size: 1rem;
|
|
1114
|
-
transition: all 0.2s;
|
|
1115
|
-
flex-shrink: 0;
|
|
1116
|
-
}
|
|
1117
|
-
|
|
1118
|
-
.flowdrop-config-sidebar__copy-btn:hover {
|
|
1119
|
-
background-color: #f9fafb;
|
|
1120
|
-
border-color: #9ca3af;
|
|
1121
|
-
transform: scale(1.05);
|
|
1122
|
-
}
|
|
1123
|
-
|
|
1124
|
-
.flowdrop-config-sidebar__copy-btn:active {
|
|
1125
|
-
transform: scale(0.95);
|
|
1126
|
-
}
|
|
1127
|
-
|
|
1128
|
-
.flowdrop-config-sidebar__detail-description {
|
|
1129
|
-
margin: 0;
|
|
1130
|
-
font-size: 0.875rem;
|
|
1131
|
-
color: #6b7280;
|
|
1132
|
-
line-height: 1.4;
|
|
1133
|
-
}
|
|
1134
889
|
</style>
|