@d34dman/flowdrop 0.0.21 → 0.0.23
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/dist/components/App.svelte +69 -260
- package/dist/components/ConfigForm.svelte +357 -267
- package/dist/components/ConfigForm.svelte.d.ts +12 -3
- package/dist/components/ConfigPanel.svelte +160 -0
- package/dist/components/ConfigPanel.svelte.d.ts +32 -0
- package/dist/components/ReadOnlyDetails.svelte +168 -0
- package/dist/components/ReadOnlyDetails.svelte.d.ts +25 -0
- package/dist/components/WorkflowEditor.svelte +1 -1
- package/dist/components/form/FormArray.svelte +1049 -0
- package/dist/components/form/FormArray.svelte.d.ts +22 -0
- package/dist/components/form/FormCheckboxGroup.svelte +152 -0
- package/dist/components/form/FormCheckboxGroup.svelte.d.ts +15 -0
- package/dist/components/form/FormField.svelte +279 -0
- package/dist/components/form/FormField.svelte.d.ts +18 -0
- package/dist/components/form/FormFieldWrapper.svelte +133 -0
- package/dist/components/form/FormFieldWrapper.svelte.d.ts +18 -0
- package/dist/components/form/FormNumberField.svelte +109 -0
- package/dist/components/form/FormNumberField.svelte.d.ts +23 -0
- package/dist/components/form/FormSelect.svelte +126 -0
- package/dist/components/form/FormSelect.svelte.d.ts +18 -0
- package/dist/components/form/FormTextField.svelte +88 -0
- package/dist/components/form/FormTextField.svelte.d.ts +17 -0
- package/dist/components/form/FormTextarea.svelte +94 -0
- package/dist/components/form/FormTextarea.svelte.d.ts +19 -0
- package/dist/components/form/FormToggle.svelte +123 -0
- package/dist/components/form/FormToggle.svelte.d.ts +17 -0
- package/dist/components/form/index.d.ts +41 -0
- package/dist/components/form/index.js +45 -0
- package/dist/components/form/types.d.ts +208 -0
- package/dist/components/form/types.js +29 -0
- package/dist/components/nodes/GatewayNode.svelte +84 -12
- package/dist/components/nodes/NotesNode.svelte +89 -307
- package/dist/components/nodes/NotesNode.svelte.d.ts +3 -22
- package/dist/components/nodes/SimpleNode.svelte +41 -5
- package/dist/components/nodes/SimpleNode.svelte.d.ts +2 -1
- package/dist/components/nodes/SquareNode.svelte +41 -5
- package/dist/components/nodes/SquareNode.svelte.d.ts +2 -1
- package/dist/components/nodes/WorkflowNode.svelte +88 -5
- package/dist/index.d.ts +4 -4
- package/dist/index.js +3 -4
- package/dist/stores/workflowStore.d.ts +15 -0
- package/dist/stores/workflowStore.js +28 -0
- package/dist/types/index.d.ts +77 -0
- package/dist/types/index.js +16 -0
- package/package.json +3 -3
- package/dist/components/ConfigSidebar.svelte +0 -916
- package/dist/components/ConfigSidebar.svelte.d.ts +0 -51
- package/dist/config/demo.d.ts +0 -58
- package/dist/config/demo.js +0 -142
- package/dist/data/samples.d.ts +0 -51
- package/dist/data/samples.js +0 -3245
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import type { ConfigValues, NodeMetadata } from
|
|
3
|
-
import Icon from
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
import type { ConfigValues, NodeMetadata } from "../../types/index.js";
|
|
3
|
+
import Icon from "@iconify/svelte";
|
|
4
|
+
import MarkdownDisplay from "../MarkdownDisplay.svelte";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* NotesNode component props
|
|
8
|
+
* Displays a styled note with markdown content
|
|
9
|
+
*/
|
|
9
10
|
const props = $props<{
|
|
10
11
|
data: {
|
|
11
12
|
label: string;
|
|
@@ -21,131 +22,94 @@
|
|
|
21
22
|
selected?: boolean;
|
|
22
23
|
isProcessing?: boolean;
|
|
23
24
|
isError?: boolean;
|
|
24
|
-
isEditing?: boolean;
|
|
25
25
|
}>();
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
let noteContent = $state((props.data.config?.content as string) || 'Add your notes here...');
|
|
32
|
-
let noteType = $state((props.data.config?.noteType as string) || 'info');
|
|
27
|
+
/** Note content derived from config */
|
|
28
|
+
const noteContent = $derived(
|
|
29
|
+
(props.data.config?.content as string) || "Add your notes here..."
|
|
30
|
+
);
|
|
33
31
|
|
|
34
|
-
|
|
35
|
-
$
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if (noteContent !== newContent) {
|
|
40
|
-
noteContent = newContent;
|
|
41
|
-
}
|
|
42
|
-
if (noteType !== newType) {
|
|
43
|
-
noteType = newType;
|
|
44
|
-
}
|
|
45
|
-
});
|
|
32
|
+
/** Note type derived from config */
|
|
33
|
+
const noteType = $derived(
|
|
34
|
+
(props.data.config?.noteType as string) || "info"
|
|
35
|
+
);
|
|
46
36
|
|
|
47
|
-
|
|
37
|
+
/** Note type configuration with styling for each type */
|
|
48
38
|
const noteTypes = {
|
|
49
39
|
info: {
|
|
50
|
-
name:
|
|
51
|
-
bgColor:
|
|
52
|
-
borderColor:
|
|
53
|
-
textColor:
|
|
54
|
-
iconColor:
|
|
55
|
-
icon:
|
|
40
|
+
name: "Info",
|
|
41
|
+
bgColor: "bg-blue-50",
|
|
42
|
+
borderColor: "border-blue-200",
|
|
43
|
+
textColor: "text-blue-800",
|
|
44
|
+
iconColor: "text-blue-500",
|
|
45
|
+
icon: "mdi:information"
|
|
56
46
|
},
|
|
57
47
|
warning: {
|
|
58
|
-
name:
|
|
59
|
-
bgColor:
|
|
60
|
-
borderColor:
|
|
61
|
-
textColor:
|
|
62
|
-
iconColor:
|
|
63
|
-
icon:
|
|
48
|
+
name: "Warning",
|
|
49
|
+
bgColor: "bg-yellow-50",
|
|
50
|
+
borderColor: "border-yellow-200",
|
|
51
|
+
textColor: "text-yellow-800",
|
|
52
|
+
iconColor: "text-yellow-500",
|
|
53
|
+
icon: "mdi:alert"
|
|
64
54
|
},
|
|
65
55
|
success: {
|
|
66
|
-
name:
|
|
67
|
-
bgColor:
|
|
68
|
-
borderColor:
|
|
69
|
-
textColor:
|
|
70
|
-
iconColor:
|
|
71
|
-
icon:
|
|
56
|
+
name: "Success",
|
|
57
|
+
bgColor: "bg-green-50",
|
|
58
|
+
borderColor: "border-green-200",
|
|
59
|
+
textColor: "text-green-800",
|
|
60
|
+
iconColor: "text-green-500",
|
|
61
|
+
icon: "mdi:check-circle"
|
|
72
62
|
},
|
|
73
63
|
error: {
|
|
74
|
-
name:
|
|
75
|
-
bgColor:
|
|
76
|
-
borderColor:
|
|
77
|
-
textColor:
|
|
78
|
-
iconColor:
|
|
79
|
-
icon:
|
|
64
|
+
name: "Error",
|
|
65
|
+
bgColor: "bg-red-50",
|
|
66
|
+
borderColor: "border-red-200",
|
|
67
|
+
textColor: "text-red-800",
|
|
68
|
+
iconColor: "text-red-500",
|
|
69
|
+
icon: "mdi:close-circle"
|
|
80
70
|
},
|
|
81
71
|
note: {
|
|
82
|
-
name:
|
|
83
|
-
bgColor:
|
|
84
|
-
borderColor:
|
|
85
|
-
textColor:
|
|
86
|
-
iconColor:
|
|
87
|
-
icon:
|
|
72
|
+
name: "Note",
|
|
73
|
+
bgColor: "bg-gray-50",
|
|
74
|
+
borderColor: "border-gray-200",
|
|
75
|
+
textColor: "text-gray-800",
|
|
76
|
+
iconColor: "text-gray-500",
|
|
77
|
+
icon: "mdi:note-text"
|
|
88
78
|
}
|
|
89
79
|
};
|
|
90
80
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
function handleContentChange(event: Event) {
|
|
96
|
-
const target = event.target as HTMLTextAreaElement;
|
|
97
|
-
noteContent = target.value;
|
|
98
|
-
if (props.data.config) {
|
|
99
|
-
props.data.config.content = target.value;
|
|
100
|
-
// Dispatch event to notify parent of config change
|
|
101
|
-
dispatch('configChange', { config: props.data.config });
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Handle note type changes
|
|
106
|
-
function handleTypeChange(event: Event) {
|
|
107
|
-
const target = event.target as HTMLSelectElement;
|
|
108
|
-
noteType = target.value;
|
|
109
|
-
if (props.data.config) {
|
|
110
|
-
props.data.config.noteType = target.value;
|
|
111
|
-
// Dispatch event to notify parent of config change
|
|
112
|
-
dispatch('configChange', { config: props.data.config });
|
|
113
|
-
}
|
|
114
|
-
}
|
|
81
|
+
/** Current note type configuration based on selected type */
|
|
82
|
+
const currentType = $derived(
|
|
83
|
+
noteTypes[noteType as keyof typeof noteTypes] || noteTypes.info
|
|
84
|
+
);
|
|
115
85
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
// Dispatch event to notify parent of state change
|
|
120
|
-
dispatch('editModeChange', { isEditing: isInternalEditing });
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// Handle configuration sidebar - now using global ConfigSidebar
|
|
86
|
+
/**
|
|
87
|
+
* Opens the configuration sidebar for editing note properties
|
|
88
|
+
*/
|
|
124
89
|
function openConfigSidebar(): void {
|
|
125
90
|
if (props.data.onConfigOpen) {
|
|
126
|
-
// Create a WorkflowNodeType-like object for the global ConfigSidebar
|
|
127
91
|
const nodeForConfig = {
|
|
128
|
-
id: props.data.nodeId ||
|
|
129
|
-
type:
|
|
92
|
+
id: props.data.nodeId || "unknown",
|
|
93
|
+
type: "note",
|
|
130
94
|
data: props.data
|
|
131
95
|
};
|
|
132
96
|
props.data.onConfigOpen(nodeForConfig);
|
|
133
97
|
}
|
|
134
98
|
}
|
|
135
99
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// Handle double-click to open config
|
|
100
|
+
/**
|
|
101
|
+
* Handles double-click to open config sidebar
|
|
102
|
+
*/
|
|
142
103
|
function handleDoubleClick(): void {
|
|
143
104
|
openConfigSidebar();
|
|
144
105
|
}
|
|
145
106
|
|
|
146
|
-
|
|
107
|
+
/**
|
|
108
|
+
* Handles keyboard events for accessibility
|
|
109
|
+
* @param event - The keyboard event
|
|
110
|
+
*/
|
|
147
111
|
function handleKeydown(event: KeyboardEvent): void {
|
|
148
|
-
if (event.key ===
|
|
112
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
149
113
|
event.preventDefault();
|
|
150
114
|
handleDoubleClick();
|
|
151
115
|
}
|
|
@@ -157,96 +121,42 @@
|
|
|
157
121
|
class:flowdrop-notes-node--selected={props.selected}
|
|
158
122
|
class:flowdrop-notes-node--processing={props.isProcessing}
|
|
159
123
|
class:flowdrop-notes-node--error={props.isError}
|
|
160
|
-
onclick={handleNodeClick}
|
|
161
124
|
ondblclick={handleDoubleClick}
|
|
162
125
|
onkeydown={handleKeydown}
|
|
163
126
|
role="button"
|
|
164
127
|
tabindex="0"
|
|
165
128
|
>
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
<div class="flowdrop-notes-
|
|
171
|
-
<
|
|
172
|
-
<
|
|
173
|
-
id="note-type"
|
|
174
|
-
class="flowdrop-notes-node__select"
|
|
175
|
-
value={noteType}
|
|
176
|
-
onchange={handleTypeChange}
|
|
177
|
-
>
|
|
178
|
-
{#each Object.entries(noteTypes) as [key, type] (key)}
|
|
179
|
-
<option value={key}>{type.name}</option>
|
|
180
|
-
{/each}
|
|
181
|
-
</select>
|
|
182
|
-
</div>
|
|
183
|
-
|
|
184
|
-
<!-- Markdown Textarea -->
|
|
185
|
-
<div class="flowdrop-notes-node__textarea-container">
|
|
186
|
-
<label for="note-content" class="flowdrop-notes-node__label">Content (Markdown):</label>
|
|
187
|
-
<textarea
|
|
188
|
-
id="note-content"
|
|
189
|
-
class="flowdrop-notes-node__textarea"
|
|
190
|
-
placeholder="Write your note in Markdown..."
|
|
191
|
-
value={noteContent}
|
|
192
|
-
oninput={handleContentChange}
|
|
193
|
-
></textarea>
|
|
129
|
+
<!-- Display Mode -->
|
|
130
|
+
<div class="flowdrop-notes-node__content {currentType.borderColor} {currentType.textColor}">
|
|
131
|
+
<!-- Header with icon and type -->
|
|
132
|
+
<div class="flowdrop-notes-node__header">
|
|
133
|
+
<div class="flowdrop-notes-node__header-left">
|
|
134
|
+
<Icon icon={currentType.icon} class="flowdrop-notes-node__icon {currentType.iconColor}" />
|
|
135
|
+
<span class="flowdrop-notes-node__type">{currentType.name}</span>
|
|
194
136
|
</div>
|
|
137
|
+
</div>
|
|
195
138
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
class="flowdrop-notes-node__btn flowdrop-notes-node__btn--save"
|
|
200
|
-
onclick={toggleEditMode}
|
|
201
|
-
>
|
|
202
|
-
<Icon icon="mdi:check" />
|
|
203
|
-
Save
|
|
204
|
-
</button>
|
|
205
|
-
<button
|
|
206
|
-
class="flowdrop-notes-node__btn flowdrop-notes-node__btn--cancel"
|
|
207
|
-
onclick={toggleEditMode}
|
|
208
|
-
>
|
|
209
|
-
<Icon icon="mdi:close" />
|
|
210
|
-
Cancel
|
|
211
|
-
</button>
|
|
212
|
-
</div>
|
|
139
|
+
<!-- Rendered markdown content -->
|
|
140
|
+
<div class="flowdrop-notes-node__body">
|
|
141
|
+
<MarkdownDisplay content={noteContent} className="flowdrop-notes-node__markdown" />
|
|
213
142
|
</div>
|
|
214
|
-
{:else}
|
|
215
|
-
<!-- Display Mode -->
|
|
216
|
-
<div class="flowdrop-notes-node__content {currentType.borderColor} {currentType.textColor}">
|
|
217
|
-
<!-- Header with icon, type, and edit button -->
|
|
218
|
-
<div class="flowdrop-notes-node__header">
|
|
219
|
-
<div class="flowdrop-notes-node__header-left">
|
|
220
|
-
<Icon icon={currentType.icon} class="flowdrop-notes-node__icon {currentType.iconColor}" />
|
|
221
|
-
<span class="flowdrop-notes-node__type">{currentType.name}</span>
|
|
222
|
-
</div>
|
|
223
|
-
<button class="flowdrop-notes-node__edit-btn" onclick={toggleEditMode} title="Edit note">
|
|
224
|
-
<Icon icon="mdi:pencil" />
|
|
225
|
-
</button>
|
|
226
|
-
</div>
|
|
227
143
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
144
|
+
<!-- Processing indicator -->
|
|
145
|
+
{#if props.isProcessing}
|
|
146
|
+
<div class="flowdrop-notes-node__processing">
|
|
147
|
+
<div class="flowdrop-notes-node__spinner"></div>
|
|
148
|
+
<span>Processing...</span>
|
|
231
149
|
</div>
|
|
150
|
+
{/if}
|
|
232
151
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
<!-- Error indicator -->
|
|
242
|
-
{#if props.isError}
|
|
243
|
-
<div class="flowdrop-notes-node__error">
|
|
244
|
-
<Icon icon="mdi:alert-circle" class="flowdrop-notes-node__error-icon" />
|
|
245
|
-
<span>Error occurred</span>
|
|
246
|
-
</div>
|
|
247
|
-
{/if}
|
|
248
|
-
</div>
|
|
249
|
-
{/if}
|
|
152
|
+
<!-- Error indicator -->
|
|
153
|
+
{#if props.isError}
|
|
154
|
+
<div class="flowdrop-notes-node__error">
|
|
155
|
+
<Icon icon="mdi:alert-circle" class="flowdrop-notes-node__error-icon" />
|
|
156
|
+
<span>Error occurred</span>
|
|
157
|
+
</div>
|
|
158
|
+
{/if}
|
|
159
|
+
</div>
|
|
250
160
|
|
|
251
161
|
<!-- Config button -->
|
|
252
162
|
<button
|
|
@@ -258,9 +168,6 @@
|
|
|
258
168
|
</button>
|
|
259
169
|
</div>
|
|
260
170
|
|
|
261
|
-
<!-- Configuration Sidebar -->
|
|
262
|
-
<!-- ConfigSidebar removed - now using global ConfigSidebar in WorkflowEditor -->
|
|
263
|
-
|
|
264
171
|
<style>
|
|
265
172
|
.flowdrop-notes-node {
|
|
266
173
|
min-width: var(--notes-node-min-width);
|
|
@@ -319,106 +226,6 @@
|
|
|
319
226
|
border-color: #ef4444 !important;
|
|
320
227
|
}
|
|
321
228
|
|
|
322
|
-
/* Edit Mode Styles */
|
|
323
|
-
.flowdrop-notes-node__edit {
|
|
324
|
-
padding: var(--notes-node-padding);
|
|
325
|
-
height: 100%;
|
|
326
|
-
display: flex;
|
|
327
|
-
flex-direction: column;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
.flowdrop-notes-node__type-selector {
|
|
331
|
-
margin-bottom: 1rem;
|
|
332
|
-
flex-shrink: 0;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
.flowdrop-notes-node__label {
|
|
336
|
-
display: block;
|
|
337
|
-
font-size: 0.875rem;
|
|
338
|
-
font-weight: 600;
|
|
339
|
-
margin-bottom: 0.5rem;
|
|
340
|
-
color: #374151;
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
.flowdrop-notes-node__select {
|
|
344
|
-
width: 100%;
|
|
345
|
-
padding: 0.5rem;
|
|
346
|
-
border: 1px solid #d1d5db;
|
|
347
|
-
border-radius: 0.375rem;
|
|
348
|
-
font-size: 0.875rem;
|
|
349
|
-
background-color: white;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
.flowdrop-notes-node__textarea-container {
|
|
353
|
-
margin-bottom: 1rem;
|
|
354
|
-
flex: 1;
|
|
355
|
-
display: flex;
|
|
356
|
-
flex-direction: column;
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
.flowdrop-notes-node__textarea {
|
|
360
|
-
width: 100%;
|
|
361
|
-
min-height: 120px;
|
|
362
|
-
flex: 1;
|
|
363
|
-
padding: 0.75rem;
|
|
364
|
-
border: 1px solid #d1d5db;
|
|
365
|
-
border-radius: 0.375rem;
|
|
366
|
-
font-size: 0.875rem;
|
|
367
|
-
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
|
|
368
|
-
line-height: 1.5;
|
|
369
|
-
resize: none; /* Prevent resizing to maintain consistent size */
|
|
370
|
-
background-color: white;
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
.flowdrop-notes-node__textarea:focus {
|
|
374
|
-
outline: none;
|
|
375
|
-
border-color: #3b82f6;
|
|
376
|
-
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
.flowdrop-notes-node__edit-actions {
|
|
380
|
-
display: flex;
|
|
381
|
-
gap: 0.5rem;
|
|
382
|
-
margin-top: 1rem;
|
|
383
|
-
justify-content: flex-end;
|
|
384
|
-
flex-shrink: 0;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
.flowdrop-notes-node__btn {
|
|
388
|
-
display: flex;
|
|
389
|
-
align-items: center;
|
|
390
|
-
gap: 0.25rem;
|
|
391
|
-
padding: 0.5rem 1rem;
|
|
392
|
-
border: 1px solid;
|
|
393
|
-
border-radius: 0.375rem;
|
|
394
|
-
font-size: 0.875rem;
|
|
395
|
-
font-weight: 500;
|
|
396
|
-
cursor: pointer;
|
|
397
|
-
transition: all 0.2s ease-in-out;
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
.flowdrop-notes-node__btn--save {
|
|
401
|
-
background-color: #10b981;
|
|
402
|
-
border-color: #10b981;
|
|
403
|
-
color: white;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
.flowdrop-notes-node__btn--save:hover {
|
|
407
|
-
background-color: #059669;
|
|
408
|
-
border-color: #059669;
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
.flowdrop-notes-node__btn--cancel {
|
|
412
|
-
background-color: transparent;
|
|
413
|
-
border-color: #d1d5db;
|
|
414
|
-
color: #374151;
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
.flowdrop-notes-node__btn--cancel:hover {
|
|
418
|
-
background-color: #f3f4f6;
|
|
419
|
-
border-color: #9ca3af;
|
|
420
|
-
}
|
|
421
|
-
|
|
422
229
|
/* Display Mode Styles */
|
|
423
230
|
.flowdrop-notes-node__content {
|
|
424
231
|
padding: var(--notes-node-padding);
|
|
@@ -443,26 +250,6 @@
|
|
|
443
250
|
gap: 0.5rem;
|
|
444
251
|
}
|
|
445
252
|
|
|
446
|
-
.flowdrop-notes-node__edit-btn {
|
|
447
|
-
display: flex;
|
|
448
|
-
align-items: center;
|
|
449
|
-
justify-content: center;
|
|
450
|
-
width: 2rem;
|
|
451
|
-
height: 2rem;
|
|
452
|
-
border: none;
|
|
453
|
-
background: transparent;
|
|
454
|
-
color: currentColor;
|
|
455
|
-
opacity: 0.7;
|
|
456
|
-
cursor: pointer;
|
|
457
|
-
border-radius: 0.25rem;
|
|
458
|
-
transition: all 0.2s ease-in-out;
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
.flowdrop-notes-node__edit-btn:hover {
|
|
462
|
-
opacity: 1;
|
|
463
|
-
background-color: rgba(0, 0, 0, 0.1);
|
|
464
|
-
}
|
|
465
|
-
|
|
466
253
|
.flowdrop-notes-node__icon {
|
|
467
254
|
width: 1.75rem;
|
|
468
255
|
height: 1.75rem;
|
|
@@ -554,13 +341,8 @@
|
|
|
554
341
|
max-width: 350px;
|
|
555
342
|
}
|
|
556
343
|
|
|
557
|
-
.flowdrop-notes-node__edit,
|
|
558
344
|
.flowdrop-notes-node__content {
|
|
559
345
|
padding: 0.75rem;
|
|
560
346
|
}
|
|
561
|
-
|
|
562
|
-
.flowdrop-notes-node__textarea {
|
|
563
|
-
min-height: 100px;
|
|
564
|
-
}
|
|
565
347
|
}
|
|
566
348
|
</style>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ConfigValues, NodeMetadata } from
|
|
1
|
+
import type { ConfigValues, NodeMetadata } from "../../types/index.js";
|
|
2
2
|
type $$ComponentProps = {
|
|
3
3
|
data: {
|
|
4
4
|
label: string;
|
|
@@ -18,26 +18,7 @@ type $$ComponentProps = {
|
|
|
18
18
|
selected?: boolean;
|
|
19
19
|
isProcessing?: boolean;
|
|
20
20
|
isError?: boolean;
|
|
21
|
-
isEditing?: boolean;
|
|
22
21
|
};
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
$$bindings?: Bindings;
|
|
26
|
-
} & Exports;
|
|
27
|
-
(internal: unknown, props: Props & {
|
|
28
|
-
$$events?: Events;
|
|
29
|
-
$$slots?: Slots;
|
|
30
|
-
}): Exports & {
|
|
31
|
-
$set?: any;
|
|
32
|
-
$on?: any;
|
|
33
|
-
};
|
|
34
|
-
z_$$bindings?: Bindings;
|
|
35
|
-
}
|
|
36
|
-
declare const NotesNode: $$__sveltets_2_IsomorphicComponent<$$ComponentProps, {
|
|
37
|
-
configChange: CustomEvent<any>;
|
|
38
|
-
editModeChange: CustomEvent<any>;
|
|
39
|
-
} & {
|
|
40
|
-
[evt: string]: CustomEvent<any>;
|
|
41
|
-
}, {}, {}, "">;
|
|
42
|
-
type NotesNode = InstanceType<typeof NotesNode>;
|
|
22
|
+
declare const NotesNode: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
23
|
+
type NotesNode = ReturnType<typeof NotesNode>;
|
|
43
24
|
export default NotesNode;
|
|
@@ -2,13 +2,17 @@
|
|
|
2
2
|
Simple Node Component
|
|
3
3
|
A simple node with optional input and output ports
|
|
4
4
|
Styled with BEM syntax
|
|
5
|
+
|
|
6
|
+
UI Extensions Support:
|
|
7
|
+
- hideUnconnectedHandles: Hides trigger ports that are not connected to reduce visual clutter
|
|
5
8
|
-->
|
|
6
9
|
|
|
7
10
|
<script lang="ts">
|
|
8
11
|
import { Position, Handle } from '@xyflow/svelte';
|
|
9
|
-
import type { ConfigValues, NodeMetadata } from '../../types/index.js';
|
|
12
|
+
import type { ConfigValues, NodeMetadata, NodeExtensions } from '../../types/index.js';
|
|
10
13
|
import Icon from '@iconify/svelte';
|
|
11
14
|
import { getDataTypeColor } from '../../utils/colors.js';
|
|
15
|
+
import { connectedHandles } from '../../stores/workflowStore.js';
|
|
12
16
|
|
|
13
17
|
const props = $props<{
|
|
14
18
|
data: {
|
|
@@ -16,6 +20,7 @@
|
|
|
16
20
|
config: ConfigValues;
|
|
17
21
|
metadata: NodeMetadata;
|
|
18
22
|
nodeId?: string;
|
|
23
|
+
extensions?: NodeExtensions;
|
|
19
24
|
onConfigOpen?: (node: {
|
|
20
25
|
id: string;
|
|
21
26
|
type: string;
|
|
@@ -27,6 +32,37 @@
|
|
|
27
32
|
isError?: boolean;
|
|
28
33
|
}>();
|
|
29
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Get the hideUnconnectedHandles setting from extensions
|
|
37
|
+
* Merges node type defaults with instance overrides
|
|
38
|
+
*/
|
|
39
|
+
const hideUnconnectedHandles = $derived(() => {
|
|
40
|
+
const typeDefault = props.data.metadata?.extensions?.ui?.hideUnconnectedHandles ?? false;
|
|
41
|
+
const instanceOverride = props.data.extensions?.ui?.hideUnconnectedHandles;
|
|
42
|
+
return instanceOverride ?? typeDefault;
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Check if a trigger port is connected
|
|
47
|
+
* @param portId - The port ID to check
|
|
48
|
+
* @param type - Whether this is an 'input' or 'output' port
|
|
49
|
+
*/
|
|
50
|
+
function isTriggerPortConnected(portId: string, type: 'input' | 'output'): boolean {
|
|
51
|
+
const handleId = `${props.data.nodeId}-${type}-${portId}`;
|
|
52
|
+
return $connectedHandles.has(handleId);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Check if a trigger port should be visible
|
|
57
|
+
* Always shows if hideUnconnectedHandles is disabled or if port is connected
|
|
58
|
+
*/
|
|
59
|
+
function shouldShowTriggerPort(portId: string, type: 'input' | 'output'): boolean {
|
|
60
|
+
if (!hideUnconnectedHandles()) {
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
return isTriggerPortConnected(portId, type);
|
|
64
|
+
}
|
|
65
|
+
|
|
30
66
|
// Removed local config state - now using global ConfigSidebar
|
|
31
67
|
|
|
32
68
|
// Prioritize metadata icon over config icon for simple nodes (metadata is the node definition)
|
|
@@ -124,8 +160,8 @@
|
|
|
124
160
|
id={`${props.data.nodeId}-input-${firstDataInputPort.id}`}
|
|
125
161
|
/>
|
|
126
162
|
{/if}
|
|
127
|
-
{#if triggerInputPort}
|
|
128
|
-
<!-- Trigger Input - positioned at bottom-left -->
|
|
163
|
+
{#if triggerInputPort && shouldShowTriggerPort(triggerInputPort.id, 'input')}
|
|
164
|
+
<!-- Trigger Input - positioned at bottom-left (hidden if hideUnconnectedHandles enabled and not connected) -->
|
|
129
165
|
<Handle
|
|
130
166
|
type="target"
|
|
131
167
|
position={Position.Left}
|
|
@@ -217,8 +253,8 @@
|
|
|
217
253
|
)}; border-color: '#ffffff'; top: {hasBothOutputTypes ? '25%' : '50%'}; z-index: 30;"
|
|
218
254
|
/>
|
|
219
255
|
{/if}
|
|
220
|
-
{#if triggerOutputPort}
|
|
221
|
-
<!-- Trigger Output - positioned at bottom-right -->
|
|
256
|
+
{#if triggerOutputPort && shouldShowTriggerPort(triggerOutputPort.id, 'output')}
|
|
257
|
+
<!-- Trigger Output - positioned at bottom-right (hidden if hideUnconnectedHandles enabled and not connected) -->
|
|
222
258
|
<Handle
|
|
223
259
|
type="source"
|
|
224
260
|
position={Position.Right}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import type { ConfigValues, NodeMetadata } from '../../types/index.js';
|
|
1
|
+
import type { ConfigValues, NodeMetadata, NodeExtensions } from '../../types/index.js';
|
|
2
2
|
type $$ComponentProps = {
|
|
3
3
|
data: {
|
|
4
4
|
label: string;
|
|
5
5
|
config: ConfigValues;
|
|
6
6
|
metadata: NodeMetadata;
|
|
7
7
|
nodeId?: string;
|
|
8
|
+
extensions?: NodeExtensions;
|
|
8
9
|
onConfigOpen?: (node: {
|
|
9
10
|
id: string;
|
|
10
11
|
type: string;
|