@flowdrop/flowdrop 2.0.0-beta.2 → 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 +34 -0
- package/MIGRATION-2.0.md +13 -0
- package/dist/components/App.svelte +21 -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 +0 -19
- 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/PortMappingRow.svelte +0 -2
- package/dist/components/SchemaForm.svelte +0 -12
- 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 +62 -51
- package/dist/components/WorkflowEditor.svelte.d.ts +18 -0
- package/dist/components/chat/AIChatPanel.svelte +1 -1
- 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 +10 -6
- package/dist/components/form/FormCheckboxGroup.svelte +0 -4
- package/dist/components/form/FormCodeEditor.svelte +9 -7
- package/dist/components/form/FormFieldLight.svelte +3 -3
- 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/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 +0 -10
- 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/PlaygroundApp.svelte +1 -1
- package/dist/components/playground/PlaygroundStudio.svelte +0 -5
- package/dist/playground/mount.d.ts +9 -5
- package/dist/playground/mount.js +9 -5
- 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/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 +3 -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/events.d.ts +18 -0
- package/dist/types/events.js +2 -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/package.json +1 -1
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
import { getNodeIcon } from '../../utils/icons.js';
|
|
25
25
|
import { getInstance } from '../../stores/getInstance.svelte.js';
|
|
26
26
|
import { applyPortOrder, getPortTop, isPortVisible } from '../../utils/portUtils.js';
|
|
27
|
-
import
|
|
27
|
+
import NodeConfigButton from './NodeConfigButton.svelte';
|
|
28
28
|
import AlertCircleIcon from '../icons/AlertCircleIcon.svelte';
|
|
29
29
|
|
|
30
30
|
const props = $props<{
|
|
@@ -102,13 +102,6 @@
|
|
|
102
102
|
openConfigSidebar();
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
// Handle keyboard events
|
|
106
|
-
function handleKeydown(event: KeyboardEvent): void {
|
|
107
|
-
if (event.key === 'Enter' || event.key === ' ') {
|
|
108
|
-
event.preventDefault();
|
|
109
|
-
openConfigSidebar();
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
105
|
const dynamicInputs = $derived(
|
|
113
106
|
((props.data.config?.dynamicInputs as DynamicPort[]) || []).map((port) =>
|
|
114
107
|
dynamicPortToNodePort(port, 'input')
|
|
@@ -187,54 +180,54 @@
|
|
|
187
180
|
/>
|
|
188
181
|
{/each}
|
|
189
182
|
|
|
190
|
-
<!-- Square Node
|
|
183
|
+
<!-- Square Node: outer is a transparent bounding box (height grows with ports so
|
|
184
|
+
handles anchor in-bounds); the visible square inside stays a fixed 80×80. -->
|
|
185
|
+
<!-- Presentational: focus, keyboard and selection live on xyflow's node wrapper
|
|
186
|
+
(see UniversalNode, which maps Enter/Space to opening config). click/
|
|
187
|
+
double-click are mouse conveniences. -->
|
|
188
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
189
|
+
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
191
190
|
<div
|
|
192
|
-
class="flowdrop-square-node
|
|
191
|
+
class="flowdrop-square-node"
|
|
193
192
|
class:flowdrop-square-node--selected={props.selected}
|
|
194
193
|
class:flowdrop-square-node--processing={props.isProcessing}
|
|
195
194
|
class:flowdrop-square-node--error={props.isError}
|
|
196
|
-
style="height: {nodeSize}px
|
|
195
|
+
style="height: {nodeSize}px"
|
|
197
196
|
onclick={handleClick}
|
|
198
197
|
ondblclick={handleDoubleClick}
|
|
199
|
-
onkeydown={handleKeydown}
|
|
200
|
-
role="button"
|
|
201
|
-
tabindex="0"
|
|
202
198
|
>
|
|
203
|
-
<!--
|
|
204
|
-
<div class="flowdrop-square-
|
|
205
|
-
<!--
|
|
206
|
-
<div class="flowdrop-square-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
<!-- Processing indicator -->
|
|
217
|
-
{#if props.isProcessing}
|
|
218
|
-
<div class="flowdrop-square-node__processing">
|
|
219
|
-
<div class="flowdrop-square-node__spinner"></div>
|
|
199
|
+
<!-- The visible, themed square — fixed 80×80, vertically centered in the slot -->
|
|
200
|
+
<div class="flowdrop-square-node__square">
|
|
201
|
+
<!-- Square Layout: Always compact with centered icon in squircle wrapper -->
|
|
202
|
+
<div class="flowdrop-square-node__compact-content">
|
|
203
|
+
<!-- Squircle icon — visibility controlled by --fd-node-icon-display -->
|
|
204
|
+
<div class="flowdrop-square-node__icon-wrapper" style="--_icon-color: {squareColor}">
|
|
205
|
+
<Icon icon={squareIcon} class="flowdrop-square-node__icon" />
|
|
206
|
+
</div>
|
|
207
|
+
<!-- Circle dot — visibility controlled by --fd-node-circle-display -->
|
|
208
|
+
<span
|
|
209
|
+
class="flowdrop-square-node__color-dot"
|
|
210
|
+
style="background: {getCategoryColorToken(fd.categories, props.data.metadata?.category)}"
|
|
211
|
+
></span>
|
|
220
212
|
</div>
|
|
221
|
-
{/if}
|
|
222
213
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
214
|
+
<!-- Processing indicator -->
|
|
215
|
+
{#if props.isProcessing}
|
|
216
|
+
<div class="flowdrop-square-node__processing">
|
|
217
|
+
<div class="flowdrop-square-node__spinner"></div>
|
|
218
|
+
</div>
|
|
219
|
+
{/if}
|
|
220
|
+
|
|
221
|
+
<!-- Error indicator -->
|
|
222
|
+
{#if props.isError}
|
|
223
|
+
<div class="flowdrop-square-node__error">
|
|
224
|
+
<AlertCircleIcon />
|
|
225
|
+
</div>
|
|
226
|
+
{/if}
|
|
227
|
+
|
|
228
|
+
<!-- Config button -->
|
|
229
|
+
<NodeConfigButton onclick={openConfigSidebar} title="Configure node" />
|
|
230
|
+
</div>
|
|
238
231
|
</div>
|
|
239
232
|
|
|
240
233
|
<!-- Output Handles: 1 port centered at 40px; N ports at 20px start, 40px gap -->
|
|
@@ -254,58 +247,65 @@
|
|
|
254
247
|
{/each}
|
|
255
248
|
|
|
256
249
|
<style>
|
|
250
|
+
/* Transparent slot: defines the node's bounding box so handles anchor
|
|
251
|
+
consistently (height grows with port count), while the square sits fixed
|
|
252
|
+
and vertically centered inside. */
|
|
257
253
|
.flowdrop-square-node {
|
|
258
254
|
position: relative;
|
|
259
|
-
background-color: var(--fd-card);
|
|
260
|
-
border: 1.5px solid var(--fd-node-border);
|
|
261
|
-
border-radius: var(--fd-radius-xl);
|
|
262
255
|
display: flex;
|
|
263
|
-
|
|
256
|
+
align-items: center;
|
|
257
|
+
justify-content: center;
|
|
258
|
+
width: var(--fd-node-square-size);
|
|
264
259
|
cursor: pointer;
|
|
265
|
-
transition: all var(--fd-transition-fast);
|
|
266
|
-
box-shadow: var(--fd-shadow-md);
|
|
267
|
-
overflow: visible; /* Changed from hidden to visible to allow handles to be properly accessible */
|
|
268
260
|
z-index: 10;
|
|
269
261
|
color: var(--fd-foreground);
|
|
270
262
|
}
|
|
271
263
|
|
|
272
|
-
/*
|
|
273
|
-
.flowdrop-square-
|
|
264
|
+
/* The visible, themed square — fixed 80×80, never expands. */
|
|
265
|
+
.flowdrop-square-node__square {
|
|
266
|
+
position: relative;
|
|
267
|
+
box-sizing: border-box;
|
|
268
|
+
display: flex;
|
|
269
|
+
align-items: center;
|
|
270
|
+
justify-content: center;
|
|
274
271
|
width: var(--fd-node-square-size);
|
|
275
272
|
height: var(--fd-node-square-size);
|
|
276
|
-
|
|
277
|
-
|
|
273
|
+
background-color: var(--fd-node-bg);
|
|
274
|
+
backdrop-filter: var(--fd-node-backdrop-filter);
|
|
275
|
+
border: var(--fd-node-border-width) solid var(--fd-node-border);
|
|
276
|
+
border-radius: var(--fd-node-radius);
|
|
277
|
+
box-shadow: var(--fd-node-shadow);
|
|
278
|
+
transition: all var(--fd-transition-fast);
|
|
279
|
+
color: var(--fd-foreground);
|
|
278
280
|
}
|
|
279
281
|
|
|
280
|
-
.flowdrop-square-node:hover {
|
|
281
|
-
box-shadow: var(--fd-shadow-
|
|
282
|
+
.flowdrop-square-node:hover .flowdrop-square-node__square {
|
|
283
|
+
box-shadow: var(--fd-node-shadow-hover);
|
|
282
284
|
border-color: var(--fd-node-border-hover);
|
|
283
285
|
}
|
|
284
286
|
|
|
285
|
-
.flowdrop-square-node--selected {
|
|
287
|
+
.flowdrop-square-node--selected .flowdrop-square-node__square {
|
|
286
288
|
box-shadow:
|
|
287
289
|
0 0 0 2px var(--fd-primary-muted),
|
|
288
|
-
var(--fd-shadow-
|
|
290
|
+
var(--fd-node-shadow-hover);
|
|
289
291
|
border-color: var(--fd-primary);
|
|
290
292
|
}
|
|
291
293
|
|
|
292
|
-
.flowdrop-square-node--selected:hover {
|
|
294
|
+
.flowdrop-square-node--selected:hover .flowdrop-square-node__square {
|
|
293
295
|
box-shadow:
|
|
294
296
|
0 0 0 2px var(--fd-primary-muted),
|
|
295
|
-
var(--fd-shadow-
|
|
297
|
+
var(--fd-node-shadow-hover);
|
|
296
298
|
border-color: var(--fd-primary);
|
|
297
299
|
}
|
|
298
300
|
|
|
299
|
-
.
|
|
300
|
-
|
|
301
|
-
outline-offset: 2px;
|
|
302
|
-
}
|
|
301
|
+
/* Focus ring is centralized in base.css (drawn on the .svelte-flow__node
|
|
302
|
+
wrapper, which is the focusable element). */
|
|
303
303
|
|
|
304
304
|
.flowdrop-square-node--processing {
|
|
305
305
|
opacity: 0.7;
|
|
306
306
|
}
|
|
307
307
|
|
|
308
|
-
.flowdrop-square-node--error {
|
|
308
|
+
.flowdrop-square-node--error .flowdrop-square-node__square {
|
|
309
309
|
border-color: var(--fd-error) !important;
|
|
310
310
|
background-color: var(--fd-error-muted) !important;
|
|
311
311
|
}
|
|
@@ -319,14 +319,15 @@
|
|
|
319
319
|
height: 100%;
|
|
320
320
|
}
|
|
321
321
|
|
|
322
|
-
/* Squircle icon wrapper -
|
|
322
|
+
/* Squircle icon wrapper - px (not rem) so the icon stays grid-locked
|
|
323
|
+
regardless of root font-size */
|
|
323
324
|
.flowdrop-square-node__icon-wrapper {
|
|
324
325
|
display: var(--fd-node-icon-display, flex);
|
|
325
326
|
align-items: center;
|
|
326
327
|
justify-content: center;
|
|
327
|
-
width:
|
|
328
|
-
height:
|
|
329
|
-
border-radius:
|
|
328
|
+
width: 48px;
|
|
329
|
+
height: 48px;
|
|
330
|
+
border-radius: 10px;
|
|
330
331
|
background: color-mix(in srgb, var(--_icon-color) var(--fd-node-icon-bg-opacity), transparent);
|
|
331
332
|
flex-shrink: 0;
|
|
332
333
|
transition: all var(--fd-transition-normal);
|
|
@@ -342,8 +343,8 @@
|
|
|
342
343
|
}
|
|
343
344
|
|
|
344
345
|
.flowdrop-square-node__icon-wrapper :global(.flowdrop-square-node__icon) {
|
|
345
|
-
width:
|
|
346
|
-
height:
|
|
346
|
+
width: 28px;
|
|
347
|
+
height: 28px;
|
|
347
348
|
color: var(--fd-node-icon);
|
|
348
349
|
}
|
|
349
350
|
|
|
@@ -383,40 +384,9 @@
|
|
|
383
384
|
height: 12px;
|
|
384
385
|
}
|
|
385
386
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
.flowdrop-square-node__config-btn {
|
|
392
|
-
position: absolute;
|
|
393
|
-
top: var(--fd-space-xs);
|
|
394
|
-
right: var(--fd-space-xs);
|
|
395
|
-
width: 1.5rem;
|
|
396
|
-
height: 1.5rem;
|
|
397
|
-
background-color: var(--fd-backdrop);
|
|
398
|
-
border: 1px solid var(--fd-border);
|
|
399
|
-
border-radius: var(--fd-radius-sm);
|
|
400
|
-
color: var(--fd-muted-foreground);
|
|
401
|
-
cursor: pointer;
|
|
402
|
-
display: flex;
|
|
403
|
-
align-items: center;
|
|
404
|
-
justify-content: center;
|
|
405
|
-
opacity: 0;
|
|
406
|
-
transition: all var(--fd-transition-normal);
|
|
407
|
-
backdrop-filter: var(--fd-backdrop-blur);
|
|
408
|
-
z-index: 15;
|
|
409
|
-
font-size: var(--fd-text-sm);
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
.flowdrop-square-node:hover .flowdrop-square-node__config-btn {
|
|
413
|
-
opacity: 1;
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
.flowdrop-square-node__config-btn:hover {
|
|
417
|
-
background-color: var(--fd-muted);
|
|
418
|
-
border-color: var(--fd-border-strong);
|
|
419
|
-
color: var(--fd-foreground);
|
|
387
|
+
/* Reveal the NodeConfigButton (gear) when the node is hovered. */
|
|
388
|
+
.flowdrop-square-node:hover {
|
|
389
|
+
--fd-config-btn-opacity: 1;
|
|
420
390
|
}
|
|
421
391
|
|
|
422
392
|
@keyframes spin {
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
import { Position, Handle } from '@xyflow/svelte';
|
|
13
13
|
import type { ConfigValues, NodeMetadata, NodeExtensions, NodePort } from '../../types/index.js';
|
|
14
14
|
import Icon from '@iconify/svelte';
|
|
15
|
+
import NodeConfigButton from './NodeConfigButton.svelte';
|
|
15
16
|
import { getDataTypeColor, getCategoryColorToken } from '../../utils/colors.js';
|
|
16
17
|
import { getNodeIcon } from '../../utils/icons.js';
|
|
17
18
|
import { getCircleHandlePosition } from '../../utils/handlePositioning.js';
|
|
@@ -311,26 +312,12 @@
|
|
|
311
312
|
function handleDoubleClick(): void {
|
|
312
313
|
openConfigSidebar();
|
|
313
314
|
}
|
|
314
|
-
|
|
315
|
-
/**
|
|
316
|
-
* Handle single click - only handle selection
|
|
317
|
-
*/
|
|
318
|
-
function handleClick(): void {
|
|
319
|
-
// Node selection is handled by Svelte Flow
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
/**
|
|
323
|
-
* Handle keyboard events for accessibility
|
|
324
|
-
*/
|
|
325
|
-
function handleKeydown(event: KeyboardEvent): void {
|
|
326
|
-
if (event.key === 'Enter' || event.key === ' ') {
|
|
327
|
-
event.preventDefault();
|
|
328
|
-
handleDoubleClick();
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
315
|
</script>
|
|
332
316
|
|
|
333
317
|
<!-- Terminal Node -->
|
|
318
|
+
<!-- Presentational: focus, keyboard and selection live on xyflow's node
|
|
319
|
+
wrapper (see UniversalNode). double-click is a mouse convenience. -->
|
|
320
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
334
321
|
<div
|
|
335
322
|
class="flowdrop-terminal-node"
|
|
336
323
|
class:flowdrop-terminal-node--selected={props.selected}
|
|
@@ -340,21 +327,11 @@
|
|
|
340
327
|
class:flowdrop-terminal-node--end={variant === 'end'}
|
|
341
328
|
class:flowdrop-terminal-node--exit={variant === 'exit'}
|
|
342
329
|
style="--terminal-color: {terminalColor};"
|
|
343
|
-
onclick={handleClick}
|
|
344
330
|
ondblclick={handleDoubleClick}
|
|
345
|
-
onkeydown={handleKeydown}
|
|
346
|
-
role="button"
|
|
347
|
-
tabindex="0"
|
|
348
331
|
aria-label="{variant} node: {displayTitle}"
|
|
349
332
|
>
|
|
350
333
|
<!-- Config button at top -->
|
|
351
|
-
<
|
|
352
|
-
class="flowdrop-terminal-node__config-btn"
|
|
353
|
-
onclick={openConfigSidebar}
|
|
354
|
-
title="Configure node"
|
|
355
|
-
>
|
|
356
|
-
<Icon icon="mdi:cog" />
|
|
357
|
-
</button>
|
|
334
|
+
<NodeConfigButton onclick={openConfigSidebar} title="Configure node" placement="top-center" />
|
|
358
335
|
|
|
359
336
|
<!-- Circle wrapper for proper handle positioning -->
|
|
360
337
|
<div class="flowdrop-terminal-node__circle-wrapper">
|
|
@@ -431,7 +408,8 @@
|
|
|
431
408
|
display: flex;
|
|
432
409
|
flex-direction: column;
|
|
433
410
|
align-items: center;
|
|
434
|
-
|
|
411
|
+
/* px (not rem) on the 20px grid */
|
|
412
|
+
gap: 8px;
|
|
435
413
|
cursor: pointer;
|
|
436
414
|
transition: all var(--fd-transition-normal);
|
|
437
415
|
z-index: 10;
|
|
@@ -455,34 +433,32 @@
|
|
|
455
433
|
display: flex;
|
|
456
434
|
align-items: center;
|
|
457
435
|
justify-content: center;
|
|
458
|
-
box-shadow: var(--fd-shadow
|
|
436
|
+
box-shadow: var(--fd-node-shadow);
|
|
459
437
|
transition: all var(--fd-transition-normal);
|
|
460
438
|
}
|
|
461
439
|
|
|
462
440
|
.flowdrop-terminal-node:hover .flowdrop-terminal-node__content {
|
|
463
|
-
box-shadow: var(--fd-shadow-
|
|
441
|
+
box-shadow: var(--fd-node-shadow-hover);
|
|
464
442
|
transform: scale(1.05);
|
|
465
443
|
}
|
|
466
444
|
|
|
467
445
|
.flowdrop-terminal-node--selected .flowdrop-terminal-node__content {
|
|
468
446
|
box-shadow:
|
|
469
|
-
var(--fd-shadow-
|
|
447
|
+
var(--fd-node-shadow-hover),
|
|
470
448
|
0 0 0 3px color-mix(in srgb, var(--fd-primary) 50%, transparent);
|
|
471
449
|
border-color: var(--fd-primary);
|
|
472
450
|
}
|
|
473
451
|
|
|
474
452
|
.flowdrop-terminal-node--selected:hover .flowdrop-terminal-node__content {
|
|
475
453
|
box-shadow:
|
|
476
|
-
var(--fd-shadow-
|
|
454
|
+
var(--fd-node-shadow-hover),
|
|
477
455
|
0 0 0 3px color-mix(in srgb, var(--fd-primary) 50%, transparent);
|
|
478
456
|
border-color: var(--fd-primary);
|
|
479
457
|
transform: scale(1.05);
|
|
480
458
|
}
|
|
481
459
|
|
|
482
|
-
.
|
|
483
|
-
|
|
484
|
-
outline-offset: 2px;
|
|
485
|
-
}
|
|
460
|
+
/* Focus ring is centralized in base.css (drawn on the .svelte-flow__node
|
|
461
|
+
wrapper, which is the focusable element). */
|
|
486
462
|
|
|
487
463
|
.flowdrop-terminal-node--processing .flowdrop-terminal-node__content {
|
|
488
464
|
opacity: 0.7;
|
|
@@ -534,14 +510,15 @@
|
|
|
534
510
|
0 0 0 3px color-mix(in srgb, var(--fd-primary) 50%, transparent);
|
|
535
511
|
}
|
|
536
512
|
|
|
537
|
-
/* Squircle icon wrapper -
|
|
513
|
+
/* Squircle icon wrapper - px (not rem) so the icon stays grid-locked
|
|
514
|
+
regardless of root font-size */
|
|
538
515
|
.flowdrop-terminal-node__icon-wrapper {
|
|
539
516
|
display: flex;
|
|
540
517
|
align-items: center;
|
|
541
518
|
justify-content: center;
|
|
542
|
-
width:
|
|
543
|
-
height:
|
|
544
|
-
border-radius:
|
|
519
|
+
width: 44px;
|
|
520
|
+
height: 44px;
|
|
521
|
+
border-radius: 10px;
|
|
545
522
|
background: color-mix(in srgb, var(--_icon-color) var(--fd-node-icon-bg-opacity), transparent);
|
|
546
523
|
flex-shrink: 0;
|
|
547
524
|
transition: all var(--fd-transition-normal);
|
|
@@ -556,8 +533,8 @@
|
|
|
556
533
|
}
|
|
557
534
|
|
|
558
535
|
.flowdrop-terminal-node__icon-wrapper :global(.flowdrop-terminal-node__icon) {
|
|
559
|
-
width:
|
|
560
|
-
height:
|
|
536
|
+
width: 24px;
|
|
537
|
+
height: 24px;
|
|
561
538
|
color: var(--fd-node-icon);
|
|
562
539
|
}
|
|
563
540
|
|
|
@@ -565,9 +542,9 @@
|
|
|
565
542
|
display: flex;
|
|
566
543
|
flex-direction: column;
|
|
567
544
|
align-items: center;
|
|
568
|
-
gap:
|
|
545
|
+
gap: 2px;
|
|
569
546
|
background-color: var(--fd-backdrop);
|
|
570
|
-
padding:
|
|
547
|
+
padding: 4px 8px;
|
|
571
548
|
border-radius: var(--fd-radius-sm);
|
|
572
549
|
box-shadow: var(--fd-shadow-sm);
|
|
573
550
|
max-width: 140px;
|
|
@@ -585,7 +562,7 @@
|
|
|
585
562
|
}
|
|
586
563
|
|
|
587
564
|
.flowdrop-terminal-node__description {
|
|
588
|
-
font-size:
|
|
565
|
+
font-size: 10px;
|
|
589
566
|
color: var(--fd-muted-foreground);
|
|
590
567
|
text-align: center;
|
|
591
568
|
overflow: hidden;
|
|
@@ -596,7 +573,7 @@
|
|
|
596
573
|
|
|
597
574
|
.flowdrop-terminal-node__processing {
|
|
598
575
|
position: absolute;
|
|
599
|
-
top:
|
|
576
|
+
top: 24px;
|
|
600
577
|
right: 0;
|
|
601
578
|
}
|
|
602
579
|
|
|
@@ -611,7 +588,7 @@
|
|
|
611
588
|
|
|
612
589
|
.flowdrop-terminal-node__error {
|
|
613
590
|
position: absolute;
|
|
614
|
-
top:
|
|
591
|
+
top: 24px;
|
|
615
592
|
right: 0;
|
|
616
593
|
color: var(--fd-error);
|
|
617
594
|
}
|
|
@@ -621,39 +598,9 @@
|
|
|
621
598
|
height: 14px;
|
|
622
599
|
}
|
|
623
600
|
|
|
624
|
-
/*
|
|
625
|
-
.flowdrop-terminal-
|
|
626
|
-
|
|
627
|
-
top: -1.5rem;
|
|
628
|
-
left: 50%;
|
|
629
|
-
transform: translateX(-50%);
|
|
630
|
-
width: 1.5rem;
|
|
631
|
-
height: 1.5rem;
|
|
632
|
-
background-color: var(--fd-backdrop);
|
|
633
|
-
border: 1px solid var(--fd-border);
|
|
634
|
-
border-radius: 50%;
|
|
635
|
-
color: var(--fd-muted-foreground);
|
|
636
|
-
cursor: pointer;
|
|
637
|
-
display: flex;
|
|
638
|
-
align-items: center;
|
|
639
|
-
justify-content: center;
|
|
640
|
-
opacity: 0;
|
|
641
|
-
transition: all var(--fd-transition-normal);
|
|
642
|
-
backdrop-filter: var(--fd-backdrop-blur);
|
|
643
|
-
z-index: 15;
|
|
644
|
-
font-size: var(--fd-text-xs);
|
|
645
|
-
box-shadow: var(--fd-shadow-sm);
|
|
646
|
-
}
|
|
647
|
-
|
|
648
|
-
.flowdrop-terminal-node:hover .flowdrop-terminal-node__config-btn {
|
|
649
|
-
opacity: 1;
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
.flowdrop-terminal-node__config-btn:hover {
|
|
653
|
-
background-color: var(--fd-muted);
|
|
654
|
-
border-color: var(--fd-border-strong);
|
|
655
|
-
color: var(--fd-foreground);
|
|
656
|
-
transform: translateX(-50%) scale(1.1);
|
|
601
|
+
/* Reveal the NodeConfigButton (gear) when the node is hovered. */
|
|
602
|
+
.flowdrop-terminal-node:hover {
|
|
603
|
+
--fd-config-btn-opacity: 1;
|
|
657
604
|
}
|
|
658
605
|
|
|
659
606
|
@keyframes spin {
|
|
@@ -678,11 +625,6 @@
|
|
|
678
625
|
transform: translate(-50%, -50%) scale(1.2) !important;
|
|
679
626
|
}
|
|
680
627
|
|
|
681
|
-
:global(.flowdrop-terminal-node__circle-wrapper .svelte-flow__handle:focus) {
|
|
682
|
-
outline: 2px solid var(--fd-ring) !important;
|
|
683
|
-
outline-offset: 2px !important;
|
|
684
|
-
}
|
|
685
|
-
|
|
686
628
|
/* Also keep node-level handle styles for fallback */
|
|
687
629
|
:global(.svelte-flow__node-terminal .svelte-flow__handle) {
|
|
688
630
|
z-index: 20 !important;
|