@flowdrop/flowdrop 1.3.0 → 1.5.0

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 (114) hide show
  1. package/README.md +68 -24
  2. package/dist/adapters/WorkflowAdapter.js +2 -22
  3. package/dist/adapters/agentspec/autoLayout.d.ts +51 -5
  4. package/dist/adapters/agentspec/autoLayout.js +120 -23
  5. package/dist/chat/commandClassifier.d.ts +19 -0
  6. package/dist/chat/commandClassifier.js +30 -0
  7. package/dist/chat/index.d.ts +27 -0
  8. package/dist/chat/index.js +32 -0
  9. package/dist/chat/responseParser.d.ts +21 -0
  10. package/dist/chat/responseParser.js +87 -0
  11. package/dist/commands/batch.d.ts +18 -0
  12. package/dist/commands/batch.js +56 -0
  13. package/dist/commands/executor.d.ts +37 -0
  14. package/dist/commands/executor.js +1044 -0
  15. package/dist/commands/index.d.ts +14 -0
  16. package/dist/commands/index.js +17 -0
  17. package/dist/commands/parser.d.ts +16 -0
  18. package/dist/commands/parser.js +278 -0
  19. package/dist/commands/positioner.d.ts +19 -0
  20. package/dist/commands/positioner.js +33 -0
  21. package/dist/commands/storeIntegration.svelte.d.ts +16 -0
  22. package/dist/commands/storeIntegration.svelte.js +67 -0
  23. package/dist/commands/types.d.ts +343 -0
  24. package/dist/commands/types.js +45 -0
  25. package/dist/components/App.svelte +431 -17
  26. package/dist/components/App.svelte.d.ts +10 -0
  27. package/dist/components/CanvasBanner.stories.svelte +6 -2
  28. package/dist/components/CanvasController.svelte +38 -0
  29. package/dist/components/CanvasController.svelte.d.ts +32 -0
  30. package/dist/components/ConfigMappingRow.svelte +130 -0
  31. package/dist/components/ConfigMappingRow.svelte.d.ts +8 -0
  32. package/dist/components/ConfigPanel.svelte +56 -7
  33. package/dist/components/ConfigPanel.svelte.d.ts +2 -0
  34. package/dist/components/FlowDropEdge.svelte +8 -57
  35. package/dist/components/Logo.svelte +14 -14
  36. package/dist/components/LogsSidebar.svelte +5 -5
  37. package/dist/components/Navbar.svelte +58 -10
  38. package/dist/components/Navbar.svelte.d.ts +7 -0
  39. package/dist/components/NodeSidebar.svelte +238 -362
  40. package/dist/components/NodeSwapPicker.svelte +537 -0
  41. package/dist/components/NodeSwapPicker.svelte.d.ts +16 -0
  42. package/dist/components/PortMappingRow.svelte +209 -0
  43. package/dist/components/PortMappingRow.svelte.d.ts +12 -0
  44. package/dist/components/SwapMappingEditor.svelte +550 -0
  45. package/dist/components/SwapMappingEditor.svelte.d.ts +12 -0
  46. package/dist/components/WorkflowEditor.svelte +99 -4
  47. package/dist/components/WorkflowEditor.svelte.d.ts +8 -0
  48. package/dist/components/chat/AIChatPanel.svelte +658 -0
  49. package/dist/components/chat/AIChatPanel.svelte.d.ts +13 -0
  50. package/dist/components/chat/CommandPreview.svelte +184 -0
  51. package/dist/components/chat/CommandPreview.svelte.d.ts +9 -0
  52. package/dist/components/console/CommandConsole.stories.svelte +93 -0
  53. package/dist/components/console/CommandConsole.stories.svelte.d.ts +27 -0
  54. package/dist/components/console/CommandConsole.svelte +259 -0
  55. package/dist/components/console/CommandConsole.svelte.d.ts +11 -0
  56. package/dist/components/console/ConsoleAutocomplete.svelte +139 -0
  57. package/dist/components/console/ConsoleAutocomplete.svelte.d.ts +21 -0
  58. package/dist/components/console/ConsoleInput.svelte +712 -0
  59. package/dist/components/console/ConsoleInput.svelte.d.ts +16 -0
  60. package/dist/components/console/ConsoleOutput.svelte +121 -0
  61. package/dist/components/console/ConsoleOutput.svelte.d.ts +11 -0
  62. package/dist/components/console/formatters.d.ts +26 -0
  63. package/dist/components/console/formatters.js +118 -0
  64. package/dist/components/interrupt/index.d.ts +1 -0
  65. package/dist/components/interrupt/index.js +1 -0
  66. package/dist/components/nodes/SimpleNode.stories.svelte +64 -0
  67. package/dist/components/nodes/SimpleNode.svelte +27 -11
  68. package/dist/components/nodes/SquareNode.stories.svelte +45 -0
  69. package/dist/components/nodes/SquareNode.svelte +27 -11
  70. package/dist/components/nodes/WorkflowNode.stories.svelte +63 -0
  71. package/dist/config/endpoints.d.ts +8 -0
  72. package/dist/config/endpoints.js +5 -0
  73. package/dist/core/index.d.ts +5 -0
  74. package/dist/core/index.js +9 -0
  75. package/dist/editor/index.d.ts +3 -1
  76. package/dist/editor/index.js +4 -2
  77. package/dist/helpers/proximityConnect.js +8 -1
  78. package/dist/helpers/workflowEditorHelper.d.ts +3 -53
  79. package/dist/helpers/workflowEditorHelper.js +13 -228
  80. package/dist/playground/index.d.ts +1 -1
  81. package/dist/playground/index.js +1 -1
  82. package/dist/schemas/v1/workflow.schema.json +107 -22
  83. package/dist/services/chatService.d.ts +65 -0
  84. package/dist/services/chatService.js +131 -0
  85. package/dist/services/historyService.d.ts +6 -4
  86. package/dist/services/historyService.js +21 -6
  87. package/dist/skins/slate.js +16 -0
  88. package/dist/stores/interruptStore.svelte.js +6 -1
  89. package/dist/stores/playgroundStore.svelte.d.ts +1 -1
  90. package/dist/stores/playgroundStore.svelte.js +11 -2
  91. package/dist/stores/portCoordinateStore.svelte.d.ts +4 -0
  92. package/dist/stores/portCoordinateStore.svelte.js +20 -26
  93. package/dist/stores/workflowStore.svelte.d.ts +31 -2
  94. package/dist/stores/workflowStore.svelte.js +84 -64
  95. package/dist/stories/EdgeDecorator.svelte +4 -4
  96. package/dist/styles/base.css +48 -0
  97. package/dist/svelte-app.d.ts +7 -1
  98. package/dist/svelte-app.js +4 -1
  99. package/dist/types/chat.d.ts +63 -0
  100. package/dist/types/chat.js +9 -0
  101. package/dist/types/events.d.ts +28 -2
  102. package/dist/types/events.js +1 -0
  103. package/dist/types/index.d.ts +8 -0
  104. package/dist/types/settings.d.ts +6 -0
  105. package/dist/types/settings.js +3 -0
  106. package/dist/utils/edgeStyling.d.ts +42 -0
  107. package/dist/utils/edgeStyling.js +176 -0
  108. package/dist/utils/nodeIds.d.ts +31 -0
  109. package/dist/utils/nodeIds.js +42 -0
  110. package/dist/utils/nodeSwap.d.ts +221 -0
  111. package/dist/utils/nodeSwap.js +686 -0
  112. package/package.json +6 -1
  113. package/dist/helpers/nodeLayoutHelper.d.ts +0 -14
  114. package/dist/helpers/nodeLayoutHelper.js +0 -19
@@ -0,0 +1,537 @@
1
+ <!--
2
+ NodeSwapPicker Component
3
+ Displays available node types for swapping, with search/filter and version upgrade badge.
4
+ Reuses patterns from NodeSidebar.
5
+ Styled with BEM syntax.
6
+ -->
7
+
8
+ <script lang="ts">
9
+ import type {
10
+ NodeMetadata,
11
+ NodeCategory,
12
+ WorkflowFormat,
13
+ WorkflowNode,
14
+ } from "../types/index.js";
15
+ import Icon from "@iconify/svelte";
16
+ import { getNodeIcon, getCategoryIcon } from "../utils/icons.js";
17
+ import { getCategoryColorToken } from "../utils/colors.js";
18
+ import { getCategoryLabel } from "../stores/categoriesStore.svelte.js";
19
+ import { getVersionUpgrade } from "../utils/nodeSwap.js";
20
+
21
+
22
+ interface Props {
23
+ /** The node being swapped */
24
+ currentNode: WorkflowNode;
25
+ /** All available node types */
26
+ availableNodes: NodeMetadata[];
27
+ /** Active workflow format for filtering */
28
+ activeFormat?: WorkflowFormat;
29
+ /** Callback when a node type is selected */
30
+ onSelect: (metadata: NodeMetadata) => void;
31
+ /** Callback to cancel swap */
32
+ onCancel: () => void;
33
+ }
34
+
35
+ const {
36
+ currentNode,
37
+ availableNodes,
38
+ activeFormat,
39
+ onSelect,
40
+ onCancel,
41
+ }: Props = $props();
42
+
43
+ let searchInput = $state("");
44
+
45
+ /** Check version upgrade availability */
46
+ let versionUpgrade = $derived(
47
+ getVersionUpgrade(currentNode.data.metadata, availableNodes),
48
+ );
49
+
50
+ /** Filter nodes compatible with active format */
51
+ function isNodeCompatibleWithFormat(node: NodeMetadata): boolean {
52
+ if (!activeFormat) return true;
53
+ if (!node.formats || node.formats.length === 0) return true;
54
+ return node.formats.includes(activeFormat);
55
+ }
56
+
57
+ /** Nodes filtered by format compatibility */
58
+ let formatCompatibleNodes = $derived(
59
+ availableNodes.filter((n) => isNodeCompatibleWithFormat(n)),
60
+ );
61
+
62
+ /** Apply search filter */
63
+ let filteredNodes = $derived.by(() => {
64
+ let nodes = formatCompatibleNodes;
65
+ if (searchInput.trim()) {
66
+ const query = searchInput.toLowerCase();
67
+ nodes = nodes.filter(
68
+ (node) =>
69
+ node.name.toLowerCase().includes(query) ||
70
+ node.description.toLowerCase().includes(query) ||
71
+ node.tags?.some((tag) => tag.toLowerCase().includes(query)),
72
+ );
73
+ }
74
+ return nodes;
75
+ });
76
+
77
+ /** Get unique categories preserving API order */
78
+ let categories = $derived.by(() => {
79
+ const seen = new Set<NodeCategory>();
80
+ const ordered: NodeCategory[] = [];
81
+ for (const node of filteredNodes) {
82
+ if (!seen.has(node.category)) {
83
+ seen.add(node.category);
84
+ ordered.push(node.category);
85
+ }
86
+ }
87
+ return ordered;
88
+ });
89
+
90
+ /** Get filtered nodes for a specific category */
91
+ function getNodesForCategory(category: NodeCategory): NodeMetadata[] {
92
+ return filteredNodes.filter((n) => n.category === category);
93
+ }
94
+ </script>
95
+
96
+ <div class="swap-picker">
97
+ <!-- Header -->
98
+ <div class="swap-picker__header">
99
+ <button
100
+ class="swap-picker__back"
101
+ onclick={onCancel}
102
+ aria-label="Back to configuration"
103
+ >
104
+ <Icon icon="heroicons:arrow-left" />
105
+ </button>
106
+ <h2 class="swap-picker__title">Swap Node</h2>
107
+ </div>
108
+
109
+ <!-- Current node info -->
110
+ <div class="swap-picker__current">
111
+ <span class="swap-picker__current-label">Current:</span>
112
+ <span class="swap-picker__current-name">{currentNode.data.label}</span>
113
+ </div>
114
+
115
+ <!-- Version upgrade banner -->
116
+ {#if versionUpgrade}
117
+ <button
118
+ class="swap-picker__upgrade"
119
+ onclick={() => onSelect(versionUpgrade!)}
120
+ >
121
+ <Icon icon="heroicons:arrow-up-circle" />
122
+ <div class="swap-picker__upgrade-info">
123
+ <span class="swap-picker__upgrade-title">Upgrade Available</span>
124
+ <span class="swap-picker__upgrade-detail">
125
+ v{currentNode.data.metadata.version} &rarr; v{versionUpgrade.version}
126
+ </span>
127
+ </div>
128
+ <Icon icon="heroicons:chevron-right" />
129
+ </button>
130
+ {/if}
131
+
132
+ <!-- Search (hidden in minimal via --fd-sidebar-search-display) -->
133
+ <div class="swap-picker__search">
134
+ <input
135
+ type="text"
136
+ placeholder="Search node types..."
137
+ class="swap-picker__input"
138
+ bind:value={searchInput}
139
+ />
140
+ </div>
141
+
142
+ <!-- Node list -->
143
+ <div class="swap-picker__list">
144
+ {#if filteredNodes.length === 0}
145
+ <div class="swap-picker__empty">
146
+ <p>No matching node types found</p>
147
+ </div>
148
+ {:else}
149
+ {#each categories as category (category)}
150
+ {@const categoryNodes = getNodesForCategory(category)}
151
+ {#if categoryNodes.length > 0}
152
+ <!-- Flat style: dot + name rows (shown in minimal skin) -->
153
+ <div class="swap-picker__flat-section">
154
+ <div class="swap-picker__flat-category">
155
+ {getCategoryLabel(category).toUpperCase()}
156
+ </div>
157
+ <div class="swap-picker__flat-list">
158
+ {#each categoryNodes as nodeType (nodeType.id)}
159
+ <button
160
+ class="swap-picker__flat-item"
161
+ onclick={() => onSelect(nodeType)}
162
+ >
163
+ <span
164
+ class="swap-picker__flat-dot"
165
+ style="background: {getCategoryColorToken(nodeType.category)}"
166
+ ></span>
167
+ <span class="swap-picker__flat-name">{nodeType.name}</span>
168
+ </button>
169
+ {/each}
170
+ </div>
171
+ </div>
172
+
173
+ <!-- Card style: icon + name + desc rows (shown in default skin) -->
174
+ <div class="swap-picker__card-section">
175
+ <div class="swap-picker__category-header">
176
+ <span
177
+ class="swap-picker__category-icon"
178
+ style="--_icon-color: {getCategoryColorToken(category)}"
179
+ >
180
+ <Icon icon={getCategoryIcon(category)} />
181
+ </span>
182
+ <span class="swap-picker__category-name">
183
+ {getCategoryLabel(category)}
184
+ </span>
185
+ <span class="swap-picker__category-count">
186
+ {categoryNodes.length}
187
+ </span>
188
+ </div>
189
+ <div class="swap-picker__category-items">
190
+ {#each categoryNodes as nodeType (nodeType.id)}
191
+ <button
192
+ class="swap-picker__item"
193
+ onclick={() => onSelect(nodeType)}
194
+ >
195
+ <span
196
+ class="swap-picker__item-icon"
197
+ style="--_icon-color: {getCategoryColorToken(
198
+ nodeType.category,
199
+ )}"
200
+ >
201
+ <Icon
202
+ icon={getNodeIcon(nodeType.icon, nodeType.category)}
203
+ />
204
+ </span>
205
+ <div class="swap-picker__item-info">
206
+ <span class="swap-picker__item-name">{nodeType.name}</span>
207
+ <span class="swap-picker__item-desc">
208
+ {nodeType.description}
209
+ </span>
210
+ </div>
211
+ <Icon
212
+ icon="heroicons:chevron-right"
213
+ class="swap-picker__item-arrow"
214
+ />
215
+ </button>
216
+ {/each}
217
+ </div>
218
+ </div>
219
+ {/if}
220
+ {/each}
221
+ {/if}
222
+ </div>
223
+ </div>
224
+
225
+ <style>
226
+ .swap-picker {
227
+ height: 100%;
228
+ display: flex;
229
+ flex-direction: column;
230
+ background-color: var(--fd-background);
231
+ }
232
+
233
+ .swap-picker__header {
234
+ display: flex;
235
+ align-items: center;
236
+ gap: 0.5rem;
237
+ padding: 0.875rem 1rem;
238
+ border-bottom: 1px solid var(--fd-border);
239
+ background-color: var(--fd-muted);
240
+ flex-shrink: 0;
241
+ }
242
+
243
+ .swap-picker__back {
244
+ background: none;
245
+ border: none;
246
+ cursor: pointer;
247
+ color: var(--fd-muted-foreground);
248
+ padding: 0.25rem;
249
+ border-radius: var(--fd-radius-sm);
250
+ display: flex;
251
+ align-items: center;
252
+ transition:
253
+ color var(--fd-transition-fast),
254
+ background-color var(--fd-transition-fast);
255
+ }
256
+
257
+ .swap-picker__back:hover {
258
+ color: var(--fd-foreground);
259
+ background-color: var(--fd-subtle);
260
+ }
261
+
262
+ .swap-picker__title {
263
+ margin: 0;
264
+ font-size: 1rem;
265
+ font-weight: 600;
266
+ color: var(--fd-foreground);
267
+ }
268
+
269
+ .swap-picker__current {
270
+ padding: 0.5rem 1rem;
271
+ border-bottom: 1px solid var(--fd-border-muted);
272
+ background-color: var(--fd-muted);
273
+ font-size: var(--fd-text-xs);
274
+ display: flex;
275
+ gap: 0.375rem;
276
+ align-items: center;
277
+ }
278
+
279
+ .swap-picker__current-label {
280
+ color: var(--fd-muted-foreground);
281
+ }
282
+
283
+ .swap-picker__current-name {
284
+ color: var(--fd-foreground);
285
+ font-weight: 500;
286
+ }
287
+
288
+ .swap-picker__upgrade {
289
+ display: flex;
290
+ align-items: center;
291
+ gap: 0.5rem;
292
+ padding: 0.625rem 1rem;
293
+ border: none;
294
+ border-bottom: 1px solid var(--fd-border-muted);
295
+ background-color: color-mix(in srgb, var(--fd-primary) 8%, transparent);
296
+ color: var(--fd-primary);
297
+ cursor: pointer;
298
+ width: 100%;
299
+ text-align: left;
300
+ transition: background-color var(--fd-transition-fast);
301
+ }
302
+
303
+ .swap-picker__upgrade:hover {
304
+ background-color: color-mix(in srgb, var(--fd-primary) 15%, transparent);
305
+ }
306
+
307
+ .swap-picker__upgrade-info {
308
+ flex: 1;
309
+ display: flex;
310
+ flex-direction: column;
311
+ }
312
+
313
+ .swap-picker__upgrade-title {
314
+ font-size: var(--fd-text-sm);
315
+ font-weight: 600;
316
+ }
317
+
318
+ .swap-picker__upgrade-detail {
319
+ font-size: var(--fd-text-xs);
320
+ opacity: 0.8;
321
+ }
322
+
323
+ .swap-picker__search {
324
+ display: var(--fd-sidebar-search-display, flex);
325
+ padding: 0.75rem 1rem;
326
+ border-bottom: 1px solid var(--fd-border);
327
+ flex-shrink: 0;
328
+ }
329
+
330
+ .swap-picker__input {
331
+ width: 100%;
332
+ padding: 0.5rem 0.75rem;
333
+ border: 1px solid var(--fd-border-strong);
334
+ border-radius: var(--fd-radius-md);
335
+ font-size: var(--fd-text-sm);
336
+ color: var(--fd-foreground);
337
+ background-color: var(--fd-background);
338
+ box-sizing: border-box;
339
+ transition:
340
+ border-color var(--fd-transition-normal),
341
+ box-shadow var(--fd-transition-normal);
342
+ }
343
+
344
+ .swap-picker__input:focus {
345
+ outline: none;
346
+ border-color: var(--fd-ring);
347
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--fd-ring) 20%, transparent);
348
+ }
349
+
350
+ .swap-picker__input::placeholder {
351
+ color: var(--fd-muted-foreground);
352
+ }
353
+
354
+ .swap-picker__list {
355
+ flex: 1;
356
+ overflow-y: auto;
357
+ padding: 0.75rem;
358
+ scrollbar-width: thin;
359
+ scrollbar-color: var(--fd-scrollbar-thumb) var(--fd-scrollbar-track);
360
+ }
361
+
362
+ .swap-picker__empty {
363
+ padding: 2rem 1rem;
364
+ text-align: center;
365
+ color: var(--fd-muted-foreground);
366
+ font-size: var(--fd-text-sm);
367
+ }
368
+
369
+ /* Display-control token wiring for skin variants */
370
+ .swap-picker__flat-section {
371
+ display: var(--fd-sidebar-flat-display, none);
372
+ }
373
+
374
+ .swap-picker__card-section {
375
+ display: var(--fd-sidebar-card-display, block);
376
+ margin-bottom: 0.75rem;
377
+ }
378
+
379
+ /* Flat style (minimal skin) */
380
+ .swap-picker__flat-category {
381
+ font-size: var(--fd-text-xs);
382
+ font-weight: 600;
383
+ color: var(--fd-sidebar-category-color, var(--fd-muted-foreground));
384
+ letter-spacing: 0.08em;
385
+ padding: 1.25rem 0.75rem 0.375rem 0.75rem;
386
+ text-transform: uppercase;
387
+ }
388
+
389
+ .swap-picker__flat-list {
390
+ display: flex;
391
+ flex-direction: column;
392
+ gap: 1px;
393
+ margin-bottom: 0.25rem;
394
+ }
395
+
396
+ .swap-picker__flat-item {
397
+ display: flex;
398
+ align-items: center;
399
+ gap: 0.625rem;
400
+ padding: 0.5rem 0.75rem;
401
+ border: none;
402
+ border-radius: var(--fd-radius-sm);
403
+ background: none;
404
+ cursor: pointer;
405
+ width: 100%;
406
+ text-align: left;
407
+ transition: background-color var(--fd-transition-fast);
408
+ }
409
+
410
+ .swap-picker__flat-item:hover {
411
+ background-color: var(--fd-muted);
412
+ }
413
+
414
+ .swap-picker__flat-dot {
415
+ width: 8px;
416
+ height: 8px;
417
+ border-radius: 50%;
418
+ flex-shrink: 0;
419
+ display: inline-block;
420
+ }
421
+
422
+ .swap-picker__flat-name {
423
+ font-size: var(--fd-text-sm);
424
+ color: var(--fd-sidebar-flat-item-color, var(--fd-foreground));
425
+ white-space: nowrap;
426
+ overflow: hidden;
427
+ text-overflow: ellipsis;
428
+ }
429
+
430
+ .swap-picker__category-header {
431
+ display: flex;
432
+ align-items: center;
433
+ gap: 0.5rem;
434
+ padding: 0.375rem 0.25rem;
435
+ margin-bottom: 0.25rem;
436
+ }
437
+
438
+ .swap-picker__category-icon {
439
+ width: 1.25rem;
440
+ height: 1.25rem;
441
+ border-radius: 0.25rem;
442
+ background: color-mix(
443
+ in srgb,
444
+ var(--_icon-color) var(--fd-node-icon-bg-opacity),
445
+ transparent
446
+ );
447
+ color: var(--fd-node-icon);
448
+ font-size: 0.625rem;
449
+ display: flex;
450
+ align-items: center;
451
+ justify-content: center;
452
+ flex-shrink: 0;
453
+ }
454
+
455
+ .swap-picker__category-name {
456
+ font-size: var(--fd-text-xs);
457
+ font-weight: 600;
458
+ color: var(--fd-muted-foreground);
459
+ text-transform: uppercase;
460
+ letter-spacing: 0.05em;
461
+ flex: 1;
462
+ }
463
+
464
+ .swap-picker__category-count {
465
+ font-size: var(--fd-text-xs);
466
+ color: var(--fd-muted-foreground);
467
+ background-color: var(--fd-subtle);
468
+ padding: 0.125rem 0.375rem;
469
+ border-radius: var(--fd-radius-sm);
470
+ }
471
+
472
+ .swap-picker__category-items {
473
+ display: flex;
474
+ flex-direction: column;
475
+ gap: 2px;
476
+ }
477
+
478
+ .swap-picker__item {
479
+ display: flex;
480
+ align-items: center;
481
+ gap: 0.5rem;
482
+ padding: 0.5rem;
483
+ border: 1px solid transparent;
484
+ border-radius: var(--fd-radius-md);
485
+ background: none;
486
+ cursor: pointer;
487
+ width: 100%;
488
+ text-align: left;
489
+ transition: all var(--fd-transition-fast);
490
+ }
491
+
492
+ .swap-picker__item:hover {
493
+ background-color: var(--fd-muted);
494
+ border-color: var(--fd-border);
495
+ }
496
+
497
+ .swap-picker__item-icon {
498
+ width: 1.75rem;
499
+ height: 1.75rem;
500
+ border-radius: 0.375rem;
501
+ background: color-mix(
502
+ in srgb,
503
+ var(--_icon-color) var(--fd-node-icon-bg-opacity),
504
+ transparent
505
+ );
506
+ color: var(--fd-node-icon);
507
+ font-size: var(--fd-text-xs);
508
+ display: flex;
509
+ align-items: center;
510
+ justify-content: center;
511
+ flex-shrink: 0;
512
+ }
513
+
514
+ .swap-picker__item-info {
515
+ flex: 1;
516
+ min-width: 0;
517
+ }
518
+
519
+ .swap-picker__item-name {
520
+ display: block;
521
+ font-size: var(--fd-text-sm);
522
+ font-weight: 500;
523
+ color: var(--fd-foreground);
524
+ overflow: hidden;
525
+ text-overflow: ellipsis;
526
+ white-space: nowrap;
527
+ }
528
+
529
+ .swap-picker__item-desc {
530
+ display: block;
531
+ font-size: var(--fd-text-xs);
532
+ color: var(--fd-muted-foreground);
533
+ overflow: hidden;
534
+ text-overflow: ellipsis;
535
+ white-space: nowrap;
536
+ }
537
+ </style>
@@ -0,0 +1,16 @@
1
+ import type { NodeMetadata, WorkflowFormat, WorkflowNode } from "../types/index.js";
2
+ interface Props {
3
+ /** The node being swapped */
4
+ currentNode: WorkflowNode;
5
+ /** All available node types */
6
+ availableNodes: NodeMetadata[];
7
+ /** Active workflow format for filtering */
8
+ activeFormat?: WorkflowFormat;
9
+ /** Callback when a node type is selected */
10
+ onSelect: (metadata: NodeMetadata) => void;
11
+ /** Callback to cancel swap */
12
+ onCancel: () => void;
13
+ }
14
+ declare const NodeSwapPicker: import("svelte").Component<Props, {}, "">;
15
+ type NodeSwapPicker = ReturnType<typeof NodeSwapPicker>;
16
+ export default NodeSwapPicker;