@flowdrop/flowdrop 2.0.0-beta.1 → 2.0.0-beta.3
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/CHANGELOG.md +67 -0
- package/MIGRATION-2.0.md +173 -3
- package/dist/api/enhanced-client.js +6 -11
- package/dist/components/App.svelte +22 -45
- package/dist/components/App.svelte.d.ts +2 -7
- package/dist/components/CanvasIconButton.svelte +76 -0
- package/dist/components/CanvasIconButton.svelte.d.ts +18 -0
- package/dist/components/ConfigForm.svelte +6 -21
- package/dist/components/ConfigPanel.svelte +4 -3
- package/dist/components/LogoWordmark.svelte +113 -0
- package/dist/components/LogoWordmark.svelte.d.ts +26 -0
- package/dist/components/Navbar.svelte +8 -59
- package/dist/components/NodeSidebar.svelte +4 -11
- package/dist/components/NodeSwapPicker.svelte +0 -2
- package/dist/components/PipelineStatus.svelte +6 -1
- package/dist/components/PipelineStatus.svelte.d.ts +3 -0
- package/dist/components/PortMappingRow.svelte +0 -2
- package/dist/components/SchemaForm.svelte +4 -14
- package/dist/components/SettingsModal.svelte +0 -5
- package/dist/components/SettingsPanel.svelte +2 -6
- package/dist/components/ThemeToggle.svelte +0 -5
- package/dist/components/UniversalNode.svelte +32 -1
- package/dist/components/WorkflowEditor.svelte +66 -52
- package/dist/components/WorkflowEditor.svelte.d.ts +21 -0
- package/dist/components/chat/AIChatPanel.svelte +7 -2
- package/dist/components/console/ConsoleAutocomplete.svelte +1 -1
- package/dist/components/console/ConsoleOutput.svelte +2 -2
- package/dist/components/form/FormArray.svelte +0 -16
- package/dist/components/form/FormAutocomplete.svelte +18 -15
- package/dist/components/form/FormCheckboxGroup.svelte +0 -4
- package/dist/components/form/FormCodeEditor.svelte +9 -7
- package/dist/components/form/FormFieldLight.svelte +33 -4
- package/dist/components/form/FormFieldLight.svelte.d.ts +12 -0
- package/dist/components/form/FormMarkdownEditor.svelte +8 -5
- package/dist/components/form/FormNumberField.svelte +0 -4
- package/dist/components/form/FormRangeField.svelte +1 -20
- package/dist/components/form/FormSelect.svelte +10 -6
- package/dist/components/form/FormTemplateEditor.svelte +6 -4
- package/dist/components/form/FormTextField.svelte +10 -6
- package/dist/components/form/FormTextarea.svelte +10 -6
- package/dist/components/form/FormToggle.svelte +0 -4
- package/dist/components/form/FormUISchemaRenderer.svelte +3 -1
- package/dist/components/icons/CommandLineIcon.svelte +15 -0
- package/dist/components/icons/CommandLineIcon.svelte.d.ts +26 -0
- package/dist/components/icons/MenuIcon.svelte +4 -0
- package/dist/components/icons/MenuIcon.svelte.d.ts +26 -0
- package/dist/components/icons/MenuOpenIcon.svelte +6 -0
- package/dist/components/icons/MenuOpenIcon.svelte.d.ts +26 -0
- package/dist/components/interrupt/ChoicePrompt.svelte +0 -10
- package/dist/components/interrupt/ConfirmationPrompt.svelte +0 -5
- package/dist/components/interrupt/InterruptBubble.svelte +11 -12
- package/dist/components/interrupt/ReviewPrompt.svelte +0 -20
- package/dist/components/interrupt/TextInputPrompt.svelte +0 -6
- package/dist/components/layouts/MainLayout.svelte +4 -5
- package/dist/components/nodes/AtomNode.svelte +46 -34
- package/dist/components/nodes/GatewayNode.svelte +91 -99
- package/dist/components/nodes/IdeaNode.svelte +62 -90
- package/dist/components/nodes/NodeConfigButton.svelte +86 -0
- package/dist/components/nodes/NodeConfigButton.svelte.d.ts +15 -0
- package/dist/components/nodes/NotesNode.svelte +70 -81
- package/dist/components/nodes/SimpleNode.svelte +28 -78
- package/dist/components/nodes/SquareNode.svelte +79 -109
- package/dist/components/nodes/TerminalNode.svelte +28 -86
- package/dist/components/nodes/ToolNode.svelte +82 -95
- package/dist/components/nodes/WorkflowNode.svelte +91 -100
- package/dist/components/playground/ChatInput.svelte +0 -1
- package/dist/components/playground/InputCollector.svelte +0 -2
- package/dist/components/playground/PipelineKanbanView.svelte +4 -2
- package/dist/components/playground/PipelineKanbanView.svelte.d.ts +2 -0
- package/dist/components/playground/PipelinePanel.svelte +20 -3
- package/dist/components/playground/PipelinePanel.svelte.d.ts +2 -0
- package/dist/components/playground/PipelineTableView.svelte +4 -2
- package/dist/components/playground/PipelineTableView.svelte.d.ts +2 -0
- package/dist/components/playground/Playground.svelte +76 -25
- package/dist/components/playground/Playground.svelte.d.ts +3 -0
- package/dist/components/playground/PlaygroundApp.svelte +6 -1
- package/dist/components/playground/PlaygroundApp.svelte.d.ts +3 -0
- package/dist/components/playground/PlaygroundModal.svelte +5 -0
- package/dist/components/playground/PlaygroundModal.svelte.d.ts +3 -0
- package/dist/components/playground/PlaygroundStudio.svelte +7 -6
- package/dist/components/playground/PlaygroundStudio.svelte.d.ts +3 -0
- package/dist/components/playground/pipelineViewUtils.svelte.d.ts +2 -1
- package/dist/components/playground/pipelineViewUtils.svelte.js +2 -2
- package/dist/config/endpoints.d.ts +23 -0
- package/dist/config/endpoints.js +28 -0
- package/dist/core/index.d.ts +1 -2
- package/dist/core/index.js +2 -6
- package/dist/display/index.d.ts +6 -1
- package/dist/display/index.js +9 -1
- package/dist/editor/index.d.ts +1 -1
- package/dist/editor/index.js +1 -1
- package/dist/form/full.d.ts +2 -1
- package/dist/form/full.js +4 -1
- package/dist/form/index.d.ts +0 -1
- package/dist/form/index.js +3 -2
- package/dist/helpers/workflowEditorHelper.d.ts +4 -2
- package/dist/helpers/workflowEditorHelper.js +4 -3
- package/dist/playground/index.d.ts +2 -2
- package/dist/playground/index.js +2 -2
- package/dist/playground/mount.d.ts +19 -5
- package/dist/playground/mount.js +16 -8
- package/dist/registry/builtinNodeTypes.d.ts +53 -0
- package/dist/registry/builtinNodeTypes.js +67 -0
- package/dist/registry/builtinNodes.d.ts +2 -39
- package/dist/registry/builtinNodes.js +6 -53
- package/dist/services/agentSpecExecutionService.d.ts +0 -2
- package/dist/services/agentSpecExecutionService.js +0 -2
- package/dist/services/apiVariableService.js +12 -26
- package/dist/services/categoriesApi.js +3 -6
- package/dist/services/chatService.d.ts +4 -3
- package/dist/services/chatService.js +13 -18
- package/dist/services/interruptService.d.ts +7 -6
- package/dist/services/interruptService.js +19 -21
- package/dist/services/playgroundService.d.ts +9 -8
- package/dist/services/playgroundService.js +23 -25
- package/dist/services/portConfigApi.js +3 -6
- package/dist/services/settingsService.d.ts +9 -4
- package/dist/services/settingsService.js +23 -12
- package/dist/skins/drafter.d.ts +30 -0
- package/dist/skins/drafter.js +185 -0
- package/dist/skins/index.d.ts +2 -1
- package/dist/skins/index.js +4 -2
- package/dist/stores/apiContext.d.ts +11 -0
- package/dist/stores/apiContext.js +15 -0
- package/dist/stores/categoriesStore.svelte.js +0 -1
- package/dist/stores/playgroundStore.svelte.js +0 -2
- package/dist/styles/base.css +38 -9
- package/dist/styles/tokens.css +54 -2
- package/dist/svelte-app.d.ts +6 -0
- package/dist/svelte-app.js +4 -2
- package/dist/themes/drafter.d.ts +2 -0
- package/dist/themes/drafter.js +15 -0
- package/dist/themes/index.d.ts +2 -1
- package/dist/themes/index.js +8 -2
- package/dist/types/auth.d.ts +9 -51
- package/dist/types/auth.js +4 -54
- package/dist/types/events.d.ts +18 -0
- package/dist/types/events.js +2 -1
- package/dist/types/index.d.ts +4 -2
- package/dist/types/index.js +0 -1
- package/dist/types/settings.d.ts +1 -1
- package/dist/types/settings.js +1 -1
- package/dist/types/skin.d.ts +1 -1
- package/dist/types/theme.d.ts +16 -2
- package/dist/utils/edgeStyling.js +9 -5
- package/dist/utils/fetchWithAuth.d.ts +36 -15
- package/dist/utils/fetchWithAuth.js +53 -23
- package/dist/utils/nodeTypes.js +1 -1
- package/package.json +2 -1
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
import { Position, Handle } from '@xyflow/svelte';
|
|
13
13
|
import type { WorkflowNode, NodePort, Branch } from '../../types/index.js';
|
|
14
14
|
import Icon from '@iconify/svelte';
|
|
15
|
+
import NodeConfigButton from './NodeConfigButton.svelte';
|
|
15
16
|
import { getNodeIcon } from '../../utils/icons.js';
|
|
16
17
|
import {
|
|
17
18
|
getDataTypeColorToken,
|
|
@@ -120,13 +121,6 @@
|
|
|
120
121
|
*/
|
|
121
122
|
const visibleBranches = $derived(branches.filter((branch) => isBranchVisible(branch.name)));
|
|
122
123
|
|
|
123
|
-
/**
|
|
124
|
-
* Handle node click - only handle selection, no config opening
|
|
125
|
-
*/
|
|
126
|
-
function handleNodeClick(): void {
|
|
127
|
-
// Node selection is handled by Svelte Flow
|
|
128
|
-
}
|
|
129
|
-
|
|
130
124
|
/**
|
|
131
125
|
* Handle double-click to open config
|
|
132
126
|
*/
|
|
@@ -140,16 +134,6 @@
|
|
|
140
134
|
}
|
|
141
135
|
}
|
|
142
136
|
|
|
143
|
-
/**
|
|
144
|
-
* Handle keyboard events for accessibility
|
|
145
|
-
*/
|
|
146
|
-
function handleKeydown(event: KeyboardEvent): void {
|
|
147
|
-
if (event.key === 'Enter' || event.key === ' ') {
|
|
148
|
-
event.preventDefault();
|
|
149
|
-
handleNodeClick();
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
137
|
/**
|
|
154
138
|
* Check if a branch is active
|
|
155
139
|
*/
|
|
@@ -159,14 +143,13 @@
|
|
|
159
143
|
</script>
|
|
160
144
|
|
|
161
145
|
<!-- Node Container -->
|
|
146
|
+
<!-- Presentational: focus, keyboard and selection live on xyflow's node
|
|
147
|
+
wrapper (see UniversalNode). double-click is a mouse convenience. -->
|
|
148
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
162
149
|
<div
|
|
163
150
|
class="flowdrop-workflow-node flowdrop-workflow-node--gateway"
|
|
164
151
|
class:flowdrop-workflow-node--selected={props.selected}
|
|
165
|
-
onclick={handleNodeClick}
|
|
166
152
|
ondblclick={handleNodeDoubleClick}
|
|
167
|
-
onkeydown={handleKeydown}
|
|
168
|
-
role="button"
|
|
169
|
-
tabindex="0"
|
|
170
153
|
aria-label={graph.gatewayNode({ title: displayTitle })}
|
|
171
154
|
aria-describedby="node-description-{props.data.nodeId || 'unknown'}"
|
|
172
155
|
>
|
|
@@ -185,7 +168,7 @@
|
|
|
185
168
|
</div>
|
|
186
169
|
|
|
187
170
|
<!-- Node Title - uses instanceTitle override if set -->
|
|
188
|
-
<h3 class="flowdrop-text--sm flowdrop-font--medium flowdrop-
|
|
171
|
+
<h3 class="flowdrop-text--sm flowdrop-font--medium flowdrop-flex--1">
|
|
189
172
|
{displayTitle}
|
|
190
173
|
</h3>
|
|
191
174
|
</div>
|
|
@@ -204,13 +187,13 @@
|
|
|
204
187
|
<div class="flowdrop-workflow-node__ports-list">
|
|
205
188
|
{#each visibleInputPorts as port (port.id)}
|
|
206
189
|
<div class="flowdrop-workflow-node__port">
|
|
207
|
-
<!-- Input Handle:
|
|
190
|
+
<!-- Input Handle: one grid row (20px) from the top so it aligns with the label, at node edge -->
|
|
208
191
|
<Handle
|
|
209
192
|
type="target"
|
|
210
193
|
position={Position.Left}
|
|
211
194
|
id={`${props.data.nodeId}-input-${port.id}`}
|
|
212
195
|
class="flowdrop-workflow-node__handle"
|
|
213
|
-
style="top:
|
|
196
|
+
style="top: var(--fd-node-port-row-height); transform: translateY(-50%); --fd-handle-fill: {getDataTypeColorToken(
|
|
214
197
|
checker,
|
|
215
198
|
port.dataType
|
|
216
199
|
)}; --fd-handle-border-color: var(--fd-handle-border);"
|
|
@@ -293,13 +276,13 @@
|
|
|
293
276
|
</div>
|
|
294
277
|
</div>
|
|
295
278
|
|
|
296
|
-
<!-- Output Handle:
|
|
279
|
+
<!-- Output Handle: one grid row (20px) from the top so it aligns with the label, at node edge -->
|
|
297
280
|
<Handle
|
|
298
281
|
type="source"
|
|
299
282
|
position={Position.Right}
|
|
300
283
|
id={`${props.data.nodeId}-output-${branch.name}`}
|
|
301
284
|
class={`flowdrop-workflow-node__handle ${isActive ? 'flowdrop-workflow-node__handle--active' : ''}`}
|
|
302
|
-
style="top:
|
|
285
|
+
style="top: var(--fd-node-port-row-height); transform: translateY(-50%); --fd-handle-fill: {isActive
|
|
303
286
|
? getDataTypeColorToken(checker, 'trigger')
|
|
304
287
|
: getDataTypeColorToken(
|
|
305
288
|
checker,
|
|
@@ -323,22 +306,17 @@
|
|
|
323
306
|
<!-- Note: When all branches are hidden due to hideUnconnectedHandles, we don't show anything -->
|
|
324
307
|
|
|
325
308
|
<!-- Config button -->
|
|
326
|
-
<
|
|
327
|
-
class="flowdrop-workflow-node__config-btn"
|
|
328
|
-
onclick={handleNodeDoubleClick}
|
|
329
|
-
title="Configure node"
|
|
330
|
-
>
|
|
331
|
-
<Icon icon="mdi:cog" />
|
|
332
|
-
</button>
|
|
309
|
+
<NodeConfigButton onclick={handleNodeDoubleClick} title="Configure node" />
|
|
333
310
|
</div>
|
|
334
311
|
|
|
335
312
|
<style>
|
|
336
313
|
.flowdrop-workflow-node {
|
|
337
314
|
position: relative;
|
|
338
|
-
background-color: var(--fd-
|
|
339
|
-
|
|
340
|
-
border
|
|
341
|
-
|
|
315
|
+
background-color: var(--fd-node-bg);
|
|
316
|
+
backdrop-filter: var(--fd-node-backdrop-filter);
|
|
317
|
+
border: var(--fd-node-border-width) solid var(--fd-node-border);
|
|
318
|
+
border-radius: var(--fd-node-radius);
|
|
319
|
+
box-shadow: var(--fd-node-shadow);
|
|
342
320
|
width: var(--fd-node-default-width);
|
|
343
321
|
z-index: 10;
|
|
344
322
|
color: var(--fd-foreground);
|
|
@@ -350,42 +328,49 @@
|
|
|
350
328
|
}
|
|
351
329
|
|
|
352
330
|
.flowdrop-workflow-node:hover {
|
|
353
|
-
box-shadow: var(--fd-shadow-
|
|
331
|
+
box-shadow: var(--fd-node-shadow-hover);
|
|
354
332
|
border-color: var(--fd-node-border-hover);
|
|
355
333
|
}
|
|
356
334
|
|
|
357
335
|
.flowdrop-workflow-node--selected {
|
|
358
336
|
box-shadow:
|
|
359
337
|
0 0 0 2px var(--fd-primary-muted),
|
|
360
|
-
var(--fd-shadow-
|
|
338
|
+
var(--fd-node-shadow-hover);
|
|
361
339
|
border-color: var(--fd-primary);
|
|
362
340
|
}
|
|
363
341
|
|
|
364
342
|
.flowdrop-workflow-node--selected:hover {
|
|
365
343
|
box-shadow:
|
|
366
344
|
0 0 0 2px var(--fd-primary-muted),
|
|
367
|
-
var(--fd-shadow-
|
|
345
|
+
var(--fd-node-shadow-hover);
|
|
368
346
|
border-color: var(--fd-primary);
|
|
369
347
|
}
|
|
370
348
|
|
|
371
|
-
.
|
|
372
|
-
|
|
373
|
-
outline-offset: 2px;
|
|
374
|
-
}
|
|
349
|
+
/* Focus ring is centralized in base.css (drawn on the .svelte-flow__node
|
|
350
|
+
wrapper, which is the focusable element). */
|
|
375
351
|
|
|
376
352
|
.flowdrop-workflow-node__header {
|
|
377
353
|
box-sizing: border-box;
|
|
378
|
-
padding
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
354
|
+
/* Bottom padding absorbs BOTH the node's own top border and the header
|
|
355
|
+
divider, so the body below the header lands on the 20px grid measured
|
|
356
|
+
from the node's outer top edge: node-border + header = 100/120/140. */
|
|
357
|
+
padding: var(--fd-node-header-gap) var(--fd-space-xl)
|
|
358
|
+
calc(
|
|
359
|
+
var(--fd-node-header-gap) - var(--fd-node-border-width) -
|
|
360
|
+
var(--fd-node-header-divider-width)
|
|
361
|
+
);
|
|
362
|
+
border-bottom: var(--fd-node-header-divider-width) solid var(--fd-node-header-divider-color);
|
|
363
|
+
background: var(--fd-node-header-bg);
|
|
364
|
+
border-top-left-radius: var(--fd-node-radius);
|
|
365
|
+
border-top-right-radius: var(--fd-node-radius);
|
|
383
366
|
display: flex;
|
|
384
367
|
flex-direction: column;
|
|
385
|
-
gap: var(--fd-node-header-gap);
|
|
368
|
+
gap: calc(var(--fd-node-header-gap) * 2);
|
|
369
|
+
/* node-border (1.5) + header = 100/120/140. Header itself is
|
|
370
|
+
4*gap + title + desc-line - node-border; each extra desc line adds 20. */
|
|
386
371
|
min-height: calc(
|
|
387
|
-
var(--fd-node-header-gap) *
|
|
388
|
-
var(--fd-node-header-desc-line)
|
|
372
|
+
var(--fd-node-header-gap) * 4 + var(--fd-node-header-title-height) +
|
|
373
|
+
var(--fd-node-header-desc-line) - var(--fd-node-border-width)
|
|
389
374
|
);
|
|
390
375
|
}
|
|
391
376
|
|
|
@@ -416,9 +401,10 @@
|
|
|
416
401
|
display: flex;
|
|
417
402
|
align-items: center;
|
|
418
403
|
justify-content: center;
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
404
|
+
/* px (not rem) so the icon stays grid-locked regardless of root font-size */
|
|
405
|
+
width: 36px;
|
|
406
|
+
height: 36px;
|
|
407
|
+
border-radius: 8px;
|
|
422
408
|
background: color-mix(in srgb, var(--_icon-color) var(--fd-node-icon-bg-opacity), transparent);
|
|
423
409
|
flex-shrink: 0;
|
|
424
410
|
transition: all var(--fd-transition-normal);
|
|
@@ -434,15 +420,22 @@
|
|
|
434
420
|
}
|
|
435
421
|
|
|
436
422
|
.flowdrop-workflow-node__icon-wrapper :global(.flowdrop-workflow-node__icon) {
|
|
437
|
-
width:
|
|
438
|
-
height:
|
|
423
|
+
width: 20px;
|
|
424
|
+
height: 20px;
|
|
439
425
|
color: var(--fd-node-icon);
|
|
440
426
|
}
|
|
441
427
|
|
|
442
428
|
.flowdrop-workflow-node__header-title h3 {
|
|
443
429
|
margin: 0;
|
|
444
|
-
|
|
430
|
+
/* half the title block so two lines fill it exactly on the 20px grid */
|
|
431
|
+
line-height: calc(var(--fd-node-header-title-height) / 2);
|
|
445
432
|
color: var(--fd-foreground);
|
|
433
|
+
display: -webkit-box;
|
|
434
|
+
-webkit-line-clamp: 2;
|
|
435
|
+
line-clamp: 2;
|
|
436
|
+
-webkit-box-orient: vertical;
|
|
437
|
+
overflow: hidden;
|
|
438
|
+
min-width: 0;
|
|
446
439
|
}
|
|
447
440
|
|
|
448
441
|
.flowdrop-workflow-node__ports {
|
|
@@ -452,27 +445,52 @@
|
|
|
452
445
|
.flowdrop-workflow-node__ports-list {
|
|
453
446
|
display: flex;
|
|
454
447
|
flex-direction: column;
|
|
455
|
-
gap:
|
|
456
|
-
padding:
|
|
448
|
+
gap: 0;
|
|
449
|
+
/* No vertical padding: sections stack flush and node height stays a
|
|
450
|
+
multiple of 20. The one exception is the clearance below the header
|
|
451
|
+
divider, applied to the first section only (below). */
|
|
452
|
+
padding: 0;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/* The first port section sits directly below the header divider; give it a
|
|
456
|
+
full 20px grid row of clearance so the first port lands on the grid. */
|
|
457
|
+
.flowdrop-workflow-node__header
|
|
458
|
+
+ .flowdrop-workflow-node__ports
|
|
459
|
+
.flowdrop-workflow-node__ports-list {
|
|
460
|
+
padding-top: calc(var(--fd-node-header-gap) * 2);
|
|
457
461
|
}
|
|
458
462
|
|
|
459
463
|
.flowdrop-workflow-node__port {
|
|
460
464
|
display: flex;
|
|
461
|
-
align-items:
|
|
465
|
+
align-items: flex-start;
|
|
462
466
|
gap: 0;
|
|
463
|
-
|
|
464
|
-
|
|
467
|
+
/* Fixed three-row (60px) height for every port — node height stays
|
|
468
|
+
predictable whether or not a port carries a description. */
|
|
469
|
+
height: calc(var(--fd-node-port-row-height) * 3);
|
|
470
|
+
padding: 0;
|
|
465
471
|
position: relative;
|
|
466
472
|
}
|
|
467
473
|
|
|
468
474
|
.flowdrop-workflow-node__port-content {
|
|
469
|
-
padding:
|
|
475
|
+
padding: var(--fd-node-header-gap) var(--fd-space-xl) 0;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/* Each line in a port occupies one 20px grid row: a label-only port
|
|
479
|
+
centers its single row, a label + description fills both. */
|
|
480
|
+
.flowdrop-workflow-node__port-content > div {
|
|
481
|
+
min-height: var(--fd-node-port-row-height);
|
|
482
|
+
align-items: center;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
.flowdrop-workflow-node__port-content > p {
|
|
486
|
+
min-height: var(--fd-node-port-row-height);
|
|
487
|
+
line-height: var(--fd-node-port-row-height);
|
|
470
488
|
}
|
|
471
489
|
|
|
472
490
|
.flowdrop-badge {
|
|
473
|
-
padding:
|
|
491
|
+
padding: 2px 4px;
|
|
474
492
|
border-radius: var(--fd-radius-sm);
|
|
475
|
-
font-size:
|
|
493
|
+
font-size: 10px;
|
|
476
494
|
font-weight: 500;
|
|
477
495
|
text-transform: uppercase;
|
|
478
496
|
letter-spacing: 0.05em;
|
|
@@ -484,8 +502,8 @@
|
|
|
484
502
|
}
|
|
485
503
|
|
|
486
504
|
.flowdrop-badge--sm {
|
|
487
|
-
font-size:
|
|
488
|
-
padding:
|
|
505
|
+
font-size: 10px;
|
|
506
|
+
padding: 2px 4px;
|
|
489
507
|
}
|
|
490
508
|
|
|
491
509
|
.workflow-node__no-branches {
|
|
@@ -537,12 +555,12 @@
|
|
|
537
555
|
|
|
538
556
|
.flowdrop-text--xs {
|
|
539
557
|
font-size: var(--fd-text-xs);
|
|
540
|
-
line-height:
|
|
558
|
+
line-height: 16px;
|
|
541
559
|
}
|
|
542
560
|
|
|
543
561
|
.flowdrop-text--sm {
|
|
544
562
|
font-size: var(--fd-text-sm);
|
|
545
|
-
line-height:
|
|
563
|
+
line-height: 20px;
|
|
546
564
|
}
|
|
547
565
|
|
|
548
566
|
.flowdrop-text--gray {
|
|
@@ -568,34 +586,8 @@
|
|
|
568
586
|
text-align: right;
|
|
569
587
|
}
|
|
570
588
|
|
|
571
|
-
.
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
right: var(--fd-space-xs);
|
|
575
|
-
width: 1.5rem;
|
|
576
|
-
height: 1.5rem;
|
|
577
|
-
background-color: var(--fd-backdrop);
|
|
578
|
-
border: 1px solid var(--fd-border);
|
|
579
|
-
border-radius: var(--fd-radius-sm);
|
|
580
|
-
color: var(--fd-muted-foreground);
|
|
581
|
-
cursor: pointer;
|
|
582
|
-
display: flex;
|
|
583
|
-
align-items: center;
|
|
584
|
-
justify-content: center;
|
|
585
|
-
opacity: 0;
|
|
586
|
-
transition: all var(--fd-transition-normal);
|
|
587
|
-
backdrop-filter: blur(4px);
|
|
588
|
-
z-index: 15;
|
|
589
|
-
font-size: var(--fd-text-sm);
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
.flowdrop-workflow-node:hover .flowdrop-workflow-node__config-btn {
|
|
593
|
-
opacity: 1;
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
.flowdrop-workflow-node__config-btn:hover {
|
|
597
|
-
background-color: var(--fd-muted);
|
|
598
|
-
border-color: var(--fd-border-strong);
|
|
599
|
-
color: var(--fd-foreground);
|
|
589
|
+
/* Reveal the NodeConfigButton (gear) when the node is hovered. */
|
|
590
|
+
.flowdrop-workflow-node:hover {
|
|
591
|
+
--fd-config-btn-opacity: 1;
|
|
600
592
|
}
|
|
601
593
|
</style>
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
import { Position, Handle } from '@xyflow/svelte';
|
|
11
11
|
import type { ConfigValues, NodeMetadata } from '../../types/index.js';
|
|
12
12
|
import Icon from '@iconify/svelte';
|
|
13
|
+
import NodeConfigButton from './NodeConfigButton.svelte';
|
|
13
14
|
import { getDataTypeColor } from '../../utils/colors.js';
|
|
14
15
|
import { getInstance } from '../../stores/getInstance.svelte.js';
|
|
15
16
|
import { m } from '../../messages/index.js';
|
|
@@ -114,38 +115,19 @@
|
|
|
114
115
|
function handleDoubleClick(): void {
|
|
115
116
|
openConfigSidebar();
|
|
116
117
|
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Handle single click - selection handled by SvelteFlow
|
|
120
|
-
*/
|
|
121
|
-
function handleClick(): void {
|
|
122
|
-
// Node selection is handled by Svelte Flow
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Handles keyboard events for accessibility
|
|
127
|
-
* @param event - The keyboard event
|
|
128
|
-
*/
|
|
129
|
-
function handleKeydown(event: KeyboardEvent): void {
|
|
130
|
-
if (event.key === 'Enter' || event.key === ' ') {
|
|
131
|
-
event.preventDefault();
|
|
132
|
-
handleDoubleClick();
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
118
|
</script>
|
|
136
119
|
|
|
137
120
|
<!-- Idea Node -->
|
|
121
|
+
<!-- Presentational: focus, keyboard and selection live on xyflow's node
|
|
122
|
+
wrapper (see UniversalNode). double-click is a mouse convenience. -->
|
|
123
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
138
124
|
<div
|
|
139
125
|
class="flowdrop-idea-node"
|
|
140
126
|
class:flowdrop-idea-node--selected={props.selected}
|
|
141
127
|
class:flowdrop-idea-node--processing={props.isProcessing}
|
|
142
128
|
class:flowdrop-idea-node--error={props.isError}
|
|
143
129
|
style="--idea-accent-color: {ideaColor};"
|
|
144
|
-
onclick={handleClick}
|
|
145
130
|
ondblclick={handleDoubleClick}
|
|
146
|
-
onkeydown={handleKeydown}
|
|
147
|
-
role="button"
|
|
148
|
-
tabindex="0"
|
|
149
131
|
aria-label={m().nodes.graph.ideaNode({ title: displayTitle })}
|
|
150
132
|
>
|
|
151
133
|
<!-- Left Port (Target/Input): center at top 40px (multiple of 10), 20px connection area -->
|
|
@@ -161,7 +143,7 @@
|
|
|
161
143
|
/>
|
|
162
144
|
{/if}
|
|
163
145
|
|
|
164
|
-
<!-- Top Port (Target/Input): center at left
|
|
146
|
+
<!-- Top Port (Target/Input): center at left 140px (node midpoint, 20px grid), 20px connection area -->
|
|
165
147
|
{#if enableTopPort}
|
|
166
148
|
<Handle
|
|
167
149
|
type="target"
|
|
@@ -169,7 +151,7 @@
|
|
|
169
151
|
style="--fd-handle-fill: {getDataTypeColor(
|
|
170
152
|
checker,
|
|
171
153
|
IDEA_DATA_TYPE
|
|
172
|
-
)}; --fd-handle-border-color: var(--fd-handle-border); left:
|
|
154
|
+
)}; --fd-handle-border-color: var(--fd-handle-border); left: 140px; transform: translateX(-50%); z-index: 30;"
|
|
173
155
|
id={`${props.data.nodeId}-input-top`}
|
|
174
156
|
/>
|
|
175
157
|
{/if}
|
|
@@ -210,9 +192,7 @@
|
|
|
210
192
|
</div>
|
|
211
193
|
|
|
212
194
|
<!-- Config button -->
|
|
213
|
-
<
|
|
214
|
-
<Icon icon="mdi:cog" />
|
|
215
|
-
</button>
|
|
195
|
+
<NodeConfigButton onclick={openConfigSidebar} title="Configure idea" />
|
|
216
196
|
|
|
217
197
|
<!-- Right Port (Source/Output): center at top 40px (multiple of 10), 20px connection area -->
|
|
218
198
|
{#if enableRightPort}
|
|
@@ -227,7 +207,7 @@
|
|
|
227
207
|
/>
|
|
228
208
|
{/if}
|
|
229
209
|
|
|
230
|
-
<!-- Bottom Port (Source/Output): center at left
|
|
210
|
+
<!-- Bottom Port (Source/Output): center at left 140px (node midpoint, 20px grid), 20px connection area -->
|
|
231
211
|
{#if enableBottomPort}
|
|
232
212
|
<Handle
|
|
233
213
|
type="source"
|
|
@@ -235,7 +215,7 @@
|
|
|
235
215
|
style="--fd-handle-fill: {getDataTypeColor(
|
|
236
216
|
checker,
|
|
237
217
|
IDEA_DATA_TYPE
|
|
238
|
-
)}; --fd-handle-border-color: var(--fd-handle-border); left:
|
|
218
|
+
)}; --fd-handle-border-color: var(--fd-handle-border); left: 140px; transform: translateX(-50%); z-index: 30;"
|
|
239
219
|
id={`${props.data.nodeId}-output-bottom`}
|
|
240
220
|
/>
|
|
241
221
|
{/if}
|
|
@@ -245,7 +225,11 @@
|
|
|
245
225
|
.flowdrop-idea-node {
|
|
246
226
|
position: relative;
|
|
247
227
|
width: var(--fd-node-default-width);
|
|
248
|
-
|
|
228
|
+
/* Floor at 80px, then grow in 20px steps. Fixed chrome = accent 4px +
|
|
229
|
+
header 48px + body bottom 6px = 58px, plus the card's 1px×2 border = 60px;
|
|
230
|
+
each description line adds 20px (line-height), so the card lands on
|
|
231
|
+
80 / 100 / 120px gridlines. */
|
|
232
|
+
min-height: 80px;
|
|
249
233
|
cursor: pointer;
|
|
250
234
|
transition: all var(--fd-transition-normal);
|
|
251
235
|
z-index: 10;
|
|
@@ -254,22 +238,21 @@
|
|
|
254
238
|
|
|
255
239
|
.flowdrop-idea-node__card {
|
|
256
240
|
background-color: var(--fd-background);
|
|
257
|
-
border-radius: var(--fd-radius
|
|
241
|
+
border-radius: var(--fd-node-radius);
|
|
258
242
|
border: 1px solid var(--fd-border);
|
|
259
|
-
box-shadow: var(--fd-shadow
|
|
243
|
+
box-shadow: var(--fd-node-shadow);
|
|
260
244
|
overflow: hidden;
|
|
261
245
|
transition: all var(--fd-transition-normal);
|
|
262
246
|
}
|
|
263
247
|
|
|
264
248
|
.flowdrop-idea-node:hover .flowdrop-idea-node__card {
|
|
265
|
-
box-shadow: var(--fd-shadow-
|
|
266
|
-
transform: translateY(-1px);
|
|
249
|
+
box-shadow: var(--fd-node-shadow-hover);
|
|
267
250
|
}
|
|
268
251
|
|
|
269
252
|
.flowdrop-idea-node--selected .flowdrop-idea-node__card {
|
|
270
253
|
border-color: var(--fd-primary);
|
|
271
254
|
box-shadow:
|
|
272
|
-
var(--fd-shadow-
|
|
255
|
+
var(--fd-node-shadow-hover),
|
|
273
256
|
0 0 0 3px color-mix(in srgb, var(--fd-primary) 30%, transparent);
|
|
274
257
|
}
|
|
275
258
|
|
|
@@ -293,52 +276,69 @@
|
|
|
293
276
|
.flowdrop-idea-node__header {
|
|
294
277
|
display: flex;
|
|
295
278
|
align-items: center;
|
|
296
|
-
|
|
297
|
-
|
|
279
|
+
/* px (not rem) on the 20px grid; 8px top/bottom + 32px icon = 48px header */
|
|
280
|
+
gap: 10px;
|
|
281
|
+
padding: 8px 16px;
|
|
298
282
|
}
|
|
299
283
|
|
|
284
|
+
/* Squircle icon wrapper - px (not rem) so the icon stays grid-locked
|
|
285
|
+
regardless of root font-size */
|
|
300
286
|
.flowdrop-idea-node__icon-wrapper {
|
|
301
287
|
display: flex;
|
|
302
288
|
align-items: center;
|
|
303
289
|
justify-content: center;
|
|
304
|
-
width:
|
|
305
|
-
height:
|
|
290
|
+
width: 32px;
|
|
291
|
+
height: 32px;
|
|
306
292
|
background-color: color-mix(
|
|
307
293
|
in srgb,
|
|
308
294
|
var(--idea-accent-color, var(--fd-accent)) var(--fd-node-icon-bg-opacity),
|
|
309
295
|
transparent
|
|
310
296
|
);
|
|
311
|
-
border-radius:
|
|
297
|
+
border-radius: 8px;
|
|
312
298
|
flex-shrink: 0;
|
|
299
|
+
transition: all var(--fd-transition-normal);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/* Icon hover effect — matches SimpleNode/ToolNode/NotesNode */
|
|
303
|
+
.flowdrop-idea-node:hover .flowdrop-idea-node__icon-wrapper {
|
|
304
|
+
background-color: color-mix(
|
|
305
|
+
in srgb,
|
|
306
|
+
var(--idea-accent-color, var(--fd-accent)) var(--fd-node-icon-bg-opacity-hover),
|
|
307
|
+
transparent
|
|
308
|
+
);
|
|
309
|
+
transform: scale(1.05);
|
|
313
310
|
}
|
|
314
311
|
|
|
315
312
|
:global(.flowdrop-idea-node__icon) {
|
|
316
|
-
width:
|
|
317
|
-
height:
|
|
313
|
+
width: 20px;
|
|
314
|
+
height: 20px;
|
|
318
315
|
color: var(--fd-node-icon);
|
|
319
316
|
}
|
|
320
317
|
|
|
321
318
|
.flowdrop-idea-node__title {
|
|
322
|
-
font-size:
|
|
319
|
+
font-size: 15px;
|
|
323
320
|
font-weight: 600;
|
|
324
321
|
color: var(--fd-foreground);
|
|
325
322
|
margin: 0;
|
|
326
|
-
line-height
|
|
323
|
+
/* px line-height so multi-line text stays on the 20px grid */
|
|
324
|
+
line-height: 20px;
|
|
327
325
|
overflow: hidden;
|
|
328
326
|
text-overflow: ellipsis;
|
|
329
327
|
white-space: nowrap;
|
|
330
328
|
}
|
|
331
329
|
|
|
332
|
-
/* Body section
|
|
330
|
+
/* Body section: 6px bottom (not 8px) compensates the card's 1px×2 border
|
|
331
|
+
so the card height stays a multiple of 20px. */
|
|
333
332
|
.flowdrop-idea-node__body {
|
|
334
|
-
padding: 0
|
|
333
|
+
padding: 0 16px 6px;
|
|
335
334
|
}
|
|
336
335
|
|
|
337
336
|
.flowdrop-idea-node__description {
|
|
338
|
-
font-size:
|
|
337
|
+
font-size: 13px;
|
|
339
338
|
color: var(--fd-muted-foreground);
|
|
340
339
|
margin: 0;
|
|
341
|
-
line-height
|
|
340
|
+
/* px line-height so the 3-line clamp lands on the 20px grid (3 × 20px) */
|
|
341
|
+
line-height: 20px;
|
|
342
342
|
display: -webkit-box;
|
|
343
343
|
-webkit-line-clamp: 3;
|
|
344
344
|
line-clamp: 3;
|
|
@@ -350,16 +350,16 @@
|
|
|
350
350
|
.flowdrop-idea-node__processing {
|
|
351
351
|
display: flex;
|
|
352
352
|
align-items: center;
|
|
353
|
-
gap:
|
|
354
|
-
padding:
|
|
353
|
+
gap: 8px;
|
|
354
|
+
padding: 8px 16px;
|
|
355
355
|
font-size: var(--fd-text-xs);
|
|
356
356
|
color: var(--fd-muted-foreground);
|
|
357
357
|
border-top: 1px solid var(--fd-border-muted);
|
|
358
358
|
}
|
|
359
359
|
|
|
360
360
|
.flowdrop-idea-node__spinner {
|
|
361
|
-
width:
|
|
362
|
-
height:
|
|
361
|
+
width: 14px;
|
|
362
|
+
height: 14px;
|
|
363
363
|
border: 2px solid var(--fd-border);
|
|
364
364
|
border-top-color: var(--idea-accent-color, var(--fd-accent));
|
|
365
365
|
border-radius: 50%;
|
|
@@ -370,8 +370,8 @@
|
|
|
370
370
|
.flowdrop-idea-node__error {
|
|
371
371
|
display: flex;
|
|
372
372
|
align-items: center;
|
|
373
|
-
gap:
|
|
374
|
-
padding:
|
|
373
|
+
gap: 8px;
|
|
374
|
+
padding: 8px 16px;
|
|
375
375
|
font-size: var(--fd-text-xs);
|
|
376
376
|
color: var(--fd-error);
|
|
377
377
|
border-top: 1px solid color-mix(in srgb, var(--fd-error) 30%, transparent);
|
|
@@ -379,8 +379,8 @@
|
|
|
379
379
|
}
|
|
380
380
|
|
|
381
381
|
:global(.flowdrop-idea-node__error-icon) {
|
|
382
|
-
width:
|
|
383
|
-
height:
|
|
382
|
+
width: 14px;
|
|
383
|
+
height: 14px;
|
|
384
384
|
}
|
|
385
385
|
|
|
386
386
|
@keyframes idea-spin {
|
|
@@ -389,37 +389,9 @@
|
|
|
389
389
|
}
|
|
390
390
|
}
|
|
391
391
|
|
|
392
|
-
/*
|
|
393
|
-
.flowdrop-idea-
|
|
394
|
-
|
|
395
|
-
top: 0.625rem;
|
|
396
|
-
right: 0.625rem;
|
|
397
|
-
width: 1.5rem;
|
|
398
|
-
height: 1.5rem;
|
|
399
|
-
background-color: var(--fd-backdrop);
|
|
400
|
-
border: 1px solid var(--fd-border);
|
|
401
|
-
border-radius: var(--fd-radius-md);
|
|
402
|
-
color: var(--fd-muted-foreground);
|
|
403
|
-
cursor: pointer;
|
|
404
|
-
display: flex;
|
|
405
|
-
align-items: center;
|
|
406
|
-
justify-content: center;
|
|
407
|
-
opacity: 0;
|
|
408
|
-
transition: all var(--fd-transition-normal);
|
|
409
|
-
backdrop-filter: var(--fd-backdrop-blur);
|
|
410
|
-
z-index: 15;
|
|
411
|
-
font-size: var(--fd-text-sm);
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
.flowdrop-idea-node:hover .flowdrop-idea-node__config-btn {
|
|
415
|
-
opacity: 1;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
.flowdrop-idea-node__config-btn:hover {
|
|
419
|
-
background-color: var(--fd-muted);
|
|
420
|
-
border-color: var(--fd-border-strong);
|
|
421
|
-
color: var(--fd-foreground);
|
|
422
|
-
transform: scale(1.05);
|
|
392
|
+
/* Reveal the NodeConfigButton (gear) when the node is hovered. */
|
|
393
|
+
.flowdrop-idea-node:hover {
|
|
394
|
+
--fd-config-btn-opacity: 1;
|
|
423
395
|
}
|
|
424
396
|
|
|
425
397
|
/* Handle: 20px/12px from base.css; position offsets for 20px handle */
|
|
@@ -441,15 +413,15 @@
|
|
|
441
413
|
/* Responsive design */
|
|
442
414
|
@media (max-width: 640px) {
|
|
443
415
|
.flowdrop-idea-node {
|
|
444
|
-
width:
|
|
416
|
+
width: 256px;
|
|
445
417
|
}
|
|
446
418
|
|
|
447
419
|
.flowdrop-idea-node__header {
|
|
448
|
-
padding:
|
|
420
|
+
padding: 8px 12px;
|
|
449
421
|
}
|
|
450
422
|
|
|
451
423
|
.flowdrop-idea-node__body {
|
|
452
|
-
padding: 0
|
|
424
|
+
padding: 0 12px 6px;
|
|
453
425
|
}
|
|
454
426
|
|
|
455
427
|
.flowdrop-idea-node__title {
|