@d34dman/flowdrop 0.0.21 → 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.
@@ -1,7 +1,14 @@
1
- import type { WorkflowNode } from '../types/index.js';
1
+ import type { ConfigSchema, WorkflowNode } from '../types/index.js';
2
2
  interface Props {
3
- node: WorkflowNode;
3
+ /** Optional workflow node (if provided, schema and values are derived from it) */
4
+ node?: WorkflowNode;
5
+ /** Direct config schema (used when node is not provided) */
6
+ schema?: ConfigSchema;
7
+ /** Direct config values (used when node is not provided) */
8
+ values?: Record<string, unknown>;
9
+ /** Callback when form is saved */
4
10
  onSave: (config: Record<string, unknown>) => void;
11
+ /** Callback when form is cancelled */
5
12
  onCancel: () => void;
6
13
  }
7
14
  declare const ConfigForm: import("svelte").Component<Props, {}, "">;
@@ -0,0 +1,160 @@
1
+ <!--
2
+ ConfigPanel Component
3
+ A generic panel for displaying details and configuration
4
+ Can be used for node config, workflow settings, or any entity with an ID
5
+ Accepts a slot for custom form content
6
+ Styled with BEM syntax
7
+ -->
8
+
9
+ <script lang="ts">
10
+ import type { Snippet } from 'svelte';
11
+ import ReadOnlyDetails from './ReadOnlyDetails.svelte';
12
+
13
+ /**
14
+ * A single detail item with label and value
15
+ */
16
+ interface DetailItem {
17
+ /** The label to display */
18
+ label: string;
19
+ /** The value to display */
20
+ value: string;
21
+ }
22
+
23
+ /**
24
+ * Props interface for ConfigPanel component
25
+ */
26
+ interface Props {
27
+ /** Panel title displayed in the header */
28
+ title: string;
29
+ /** Unique identifier to display with copy button */
30
+ id?: string;
31
+ /** Optional description text */
32
+ description?: string;
33
+ /** Array of label-value pairs to display */
34
+ details?: DetailItem[];
35
+ /** Title for the configuration section */
36
+ configTitle?: string;
37
+ /** Callback function when the panel is closed */
38
+ onClose: () => void;
39
+ /** Slot content for the configuration form */
40
+ children?: Snippet;
41
+ }
42
+
43
+ const {
44
+ title,
45
+ id,
46
+ description,
47
+ details = [],
48
+ configTitle = 'Configuration',
49
+ onClose,
50
+ children
51
+ }: Props = $props();
52
+
53
+ /**
54
+ * Check if details section should be shown
55
+ */
56
+ const hasDetails = $derived(id !== undefined || details.length > 0 || description !== undefined);
57
+ </script>
58
+
59
+ <div class="config-panel">
60
+ <!-- Header -->
61
+ <div class="config-panel__header">
62
+ <h2 class="config-panel__title">{title}</h2>
63
+ <button
64
+ class="config-panel__close"
65
+ onclick={onClose}
66
+ aria-label="Close panel"
67
+ >
68
+ ×
69
+ </button>
70
+ </div>
71
+
72
+ <!-- Details Section (between header and content) -->
73
+ {#if hasDetails && id}
74
+ <div class="config-panel__details">
75
+ <ReadOnlyDetails {id} {description} {details} />
76
+ </div>
77
+ {/if}
78
+
79
+ <!-- Content -->
80
+ <div class="config-panel__content">
81
+ {#if children}
82
+ <div class="config-panel__section">
83
+ <h3 class="config-panel__section-title">{configTitle}</h3>
84
+ {@render children()}
85
+ </div>
86
+ {/if}
87
+ </div>
88
+ </div>
89
+
90
+ <style>
91
+ .config-panel {
92
+ height: 100%;
93
+ display: flex;
94
+ flex-direction: column;
95
+ background-color: #ffffff;
96
+ }
97
+
98
+ .config-panel__header {
99
+ display: flex;
100
+ justify-content: space-between;
101
+ align-items: center;
102
+ padding: 0.875rem 1rem;
103
+ border-bottom: 1px solid #e5e7eb;
104
+ background-color: #f9fafb;
105
+ flex-shrink: 0;
106
+ }
107
+
108
+ .config-panel__title {
109
+ margin: 0;
110
+ font-size: 1rem;
111
+ font-weight: 600;
112
+ color: #111827;
113
+ }
114
+
115
+ .config-panel__close {
116
+ background: none;
117
+ border: none;
118
+ font-size: 1.25rem;
119
+ line-height: 1;
120
+ cursor: pointer;
121
+ color: #6b7280;
122
+ padding: 0.25rem;
123
+ border-radius: 0.25rem;
124
+ transition: color 0.15s, background-color 0.15s;
125
+ }
126
+
127
+ .config-panel__close:hover {
128
+ color: #374151;
129
+ background-color: #f3f4f6;
130
+ }
131
+
132
+ .config-panel__details {
133
+ padding: 0.75rem 1rem;
134
+ border-bottom: 1px solid #f3f4f6;
135
+ background-color: #fafafa;
136
+ flex-shrink: 0;
137
+ }
138
+
139
+ .config-panel__content {
140
+ flex: 1;
141
+ overflow-y: auto;
142
+ padding: 1rem;
143
+ }
144
+
145
+ .config-panel__section {
146
+ display: flex;
147
+ flex-direction: column;
148
+ gap: 0.75rem;
149
+ }
150
+
151
+ .config-panel__section-title {
152
+ margin: 0;
153
+ font-size: 0.75rem;
154
+ font-weight: 600;
155
+ color: #6b7280;
156
+ text-transform: uppercase;
157
+ letter-spacing: 0.05em;
158
+ }
159
+ </style>
160
+
@@ -0,0 +1,32 @@
1
+ import type { Snippet } from 'svelte';
2
+ /**
3
+ * A single detail item with label and value
4
+ */
5
+ interface DetailItem {
6
+ /** The label to display */
7
+ label: string;
8
+ /** The value to display */
9
+ value: string;
10
+ }
11
+ /**
12
+ * Props interface for ConfigPanel component
13
+ */
14
+ interface Props {
15
+ /** Panel title displayed in the header */
16
+ title: string;
17
+ /** Unique identifier to display with copy button */
18
+ id?: string;
19
+ /** Optional description text */
20
+ description?: string;
21
+ /** Array of label-value pairs to display */
22
+ details?: DetailItem[];
23
+ /** Title for the configuration section */
24
+ configTitle?: string;
25
+ /** Callback function when the panel is closed */
26
+ onClose: () => void;
27
+ /** Slot content for the configuration form */
28
+ children?: Snippet;
29
+ }
30
+ declare const ConfigPanel: import("svelte").Component<Props, {}, "">;
31
+ type ConfigPanel = ReturnType<typeof ConfigPanel>;
32
+ export default ConfigPanel;
@@ -0,0 +1,168 @@
1
+ <!--
2
+ ReadOnlyDetails Component
3
+ Displays readonly information with an ID (with copy button), title, description, and label-value pairs
4
+ Compact inline layout with BEM syntax
5
+ -->
6
+
7
+ <script lang="ts">
8
+ /**
9
+ * A single detail item with label and value
10
+ */
11
+ interface DetailItem {
12
+ /** The label to display */
13
+ label: string;
14
+ /** The value to display */
15
+ value: string;
16
+ }
17
+
18
+ /**
19
+ * Props interface for ReadOnlyDetails component
20
+ */
21
+ interface Props {
22
+ /** The unique identifier to display with a copy button */
23
+ id: string;
24
+ /** Optional section title */
25
+ title?: string;
26
+ /** Optional description text */
27
+ description?: string;
28
+ /** Array of label-value pairs to display */
29
+ details: DetailItem[];
30
+ }
31
+
32
+ const { id, title, description, details }: Props = $props();
33
+
34
+ /**
35
+ * Copy the ID to clipboard
36
+ */
37
+ function copyId(): void {
38
+ navigator.clipboard.writeText(id);
39
+ }
40
+ </script>
41
+
42
+ <div class="readonly-details">
43
+ {#if title}
44
+ <h3 class="readonly-details__title">{title}</h3>
45
+ {/if}
46
+
47
+ <div class="readonly-details__grid">
48
+ <!-- ID row -->
49
+ <span class="readonly-details__label">ID</span>
50
+ <div class="readonly-details__id-row">
51
+ <code class="readonly-details__id">{id}</code>
52
+ <button
53
+ class="readonly-details__copy-btn"
54
+ onclick={copyId}
55
+ title="Copy ID"
56
+ aria-label="Copy ID to clipboard"
57
+ >
58
+ <svg
59
+ xmlns="http://www.w3.org/2000/svg"
60
+ fill="none"
61
+ width="12"
62
+ height="12"
63
+ viewBox="0 0 24 24"
64
+ stroke-width="2"
65
+ stroke="currentColor"
66
+ >
67
+ <path
68
+ stroke-linecap="round"
69
+ stroke-linejoin="round"
70
+ d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75"
71
+ />
72
+ </svg>
73
+ </button>
74
+ </div>
75
+
76
+ <!-- Dynamic label-value pairs -->
77
+ {#each details as detail (detail.label)}
78
+ <span class="readonly-details__label">{detail.label}</span>
79
+ <span class="readonly-details__value">{detail.value}</span>
80
+ {/each}
81
+ </div>
82
+
83
+ <!-- Description (if provided) -->
84
+ {#if description}
85
+ <p class="readonly-details__description">{description}</p>
86
+ {/if}
87
+ </div>
88
+
89
+ <style>
90
+ .readonly-details {
91
+ display: flex;
92
+ flex-direction: column;
93
+ gap: 0.5rem;
94
+ }
95
+
96
+ .readonly-details__title {
97
+ margin: 0;
98
+ font-size: 0.75rem;
99
+ font-weight: 600;
100
+ color: #6b7280;
101
+ text-transform: uppercase;
102
+ letter-spacing: 0.05em;
103
+ }
104
+
105
+ .readonly-details__grid {
106
+ display: grid;
107
+ grid-template-columns: auto 1fr;
108
+ gap: 0.25rem 0.75rem;
109
+ align-items: center;
110
+ }
111
+
112
+ .readonly-details__label {
113
+ font-size: 0.75rem;
114
+ font-weight: 500;
115
+ color: #9ca3af;
116
+ }
117
+
118
+ .readonly-details__value {
119
+ font-size: 0.8125rem;
120
+ color: #374151;
121
+ font-weight: 500;
122
+ }
123
+
124
+ .readonly-details__id-row {
125
+ display: flex;
126
+ align-items: center;
127
+ gap: 0.375rem;
128
+ }
129
+
130
+ .readonly-details__id {
131
+ font-size: 0.75rem;
132
+ font-family: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, monospace;
133
+ color: #6b7280;
134
+ background-color: #f3f4f6;
135
+ padding: 0.125rem 0.375rem;
136
+ border-radius: 0.25rem;
137
+ word-break: break-all;
138
+ }
139
+
140
+ .readonly-details__copy-btn {
141
+ background: transparent;
142
+ border: none;
143
+ padding: 0.25rem;
144
+ cursor: pointer;
145
+ color: #9ca3af;
146
+ border-radius: 0.25rem;
147
+ display: flex;
148
+ align-items: center;
149
+ justify-content: center;
150
+ transition: color 0.15s, background-color 0.15s;
151
+ }
152
+
153
+ .readonly-details__copy-btn:hover {
154
+ color: #374151;
155
+ background-color: #f3f4f6;
156
+ }
157
+
158
+ .readonly-details__copy-btn:active {
159
+ color: #111827;
160
+ }
161
+
162
+ .readonly-details__description {
163
+ margin: 0;
164
+ font-size: 0.8125rem;
165
+ color: #6b7280;
166
+ line-height: 1.5;
167
+ }
168
+ </style>
@@ -0,0 +1,25 @@
1
+ /**
2
+ * A single detail item with label and value
3
+ */
4
+ interface DetailItem {
5
+ /** The label to display */
6
+ label: string;
7
+ /** The value to display */
8
+ value: string;
9
+ }
10
+ /**
11
+ * Props interface for ReadOnlyDetails component
12
+ */
13
+ interface Props {
14
+ /** The unique identifier to display with a copy button */
15
+ id: string;
16
+ /** Optional section title */
17
+ title?: string;
18
+ /** Optional description text */
19
+ description?: string;
20
+ /** Array of label-value pairs to display */
21
+ details: DetailItem[];
22
+ }
23
+ declare const ReadOnlyDetails: import("svelte").Component<Props, {}, "">;
24
+ type ReadOnlyDetails = ReturnType<typeof ReadOnlyDetails>;
25
+ export default ReadOnlyDetails;
@@ -522,7 +522,7 @@
522
522
  height: 18px;
523
523
  border: 2px solid white;
524
524
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
525
- z-index: 10;
525
+ z-index: 20;
526
526
  }
527
527
 
528
528
  /* Ensure our custom handles are clickable */