@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
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
- <div
567
- class="flowdrop-app"
568
- style="height: {typeof height === 'number' ? `${height}px` : height}; width: {typeof width ===
569
- 'number'
570
- ? `${width}px`
571
- : width};"
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 (conditionally rendered) - hide on workflow edit pages -->
574
- {#if showNavbar && !$page.url.pathname.includes('/edit')}
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
- {/if}
614
-
615
- <!-- Main Content -->
616
- <main class="flowdrop-main">
617
- <!-- Status Display -->
618
- {#if error}
619
- <div class="flowdrop-status flowdrop-status--error">
620
- <div class="flowdrop-status__content">
621
- <div class="flowdrop-flex flowdrop-gap--3">
622
- <div class="flowdrop-status__indicator flowdrop-status__indicator--error"></div>
623
- <span class="flowdrop-text--sm flowdrop-font--medium">Error: {error}</span>
624
- </div>
625
- <div class="flowdrop-flex flowdrop-gap--2">
626
- <button
627
- class="flowdrop-btn flowdrop-btn--sm flowdrop-btn--outline"
628
- onclick={retryLoad}
629
- type="button"
630
- >
631
- Retry
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} />
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
- <!-- Right Sidebar - Configuration or Workflow Settings (conditionally rendered) -->
714
- {#if !disableSidebar && isWorkflowSettingsOpen}
715
- <ConfigSidebar
716
- isOpen={isWorkflowSettingsOpen}
717
- title="Workflow Settings"
718
- configSchema={workflowConfigSchema}
719
- configValues={workflowConfigValues}
720
- onSave={handleWorkflowSave}
721
- onClose={() => (isWorkflowSettingsOpen = false)}
722
- />
723
- {:else if !disableSidebar && selectedNodeForConfig()}
724
- <div class="flowdrop-sidebar flowdrop-sidebar--right">
725
- <div class="flowdrop-config-sidebar">
726
- <!-- Header -->
727
- <div class="flowdrop-config-sidebar__header">
728
- <h2 class="flowdrop-config-sidebar__title">{selectedNodeForConfig().data.label}</h2>
729
- <button
730
- class="flowdrop-config-sidebar__close"
731
- onclick={closeConfigSidebar}
732
- aria-label="Close configuration sidebar"
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
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
- </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>
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
- <!-- 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);
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
- closeConfigSidebar();
809
- }}
810
- onCancel={closeConfigSidebar}
811
- />
812
- </div>
813
- </div>
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
- {/if}
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
- </main>
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
- .flowdrop-main {
830
- flex: 1;
831
- position: relative;
832
- display: flex;
833
- flex-direction: column;
834
- min-height: 0;
835
- overflow: hidden;
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
- @keyframes spin {
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
  }
@@ -335,9 +335,6 @@
335
335
  }
336
336
 
337
337
  .flowdrop-config-sidebar__footer {
338
- padding: 1rem;
339
- border-top: 1px solid #e5e7eb;
340
- background-color: #f9fafb;
341
338
  display: flex;
342
339
  gap: 0.75rem;
343
340
  justify-content: flex-end;
@@ -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
- min-height: 80px; /* Ensure minimum height */
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