@d34dman/flowdrop 0.0.52 → 0.0.54
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 +9 -6
- package/dist/components/ConfigForm.svelte +1 -0
- package/dist/components/NodeSidebar.svelte +0 -2
- package/dist/components/PortCoordinateTracker.svelte +58 -0
- package/dist/components/PortCoordinateTracker.svelte.d.ts +12 -0
- package/dist/components/SettingsPanel.svelte +1 -2
- package/dist/components/ThemeToggle.svelte +1 -1
- package/dist/components/WorkflowEditor.svelte +44 -11
- package/dist/components/form/FormAutocomplete.svelte +3 -12
- package/dist/components/form/FormField.svelte +1 -1
- package/dist/components/form/FormFieldLight.svelte +1 -1
- package/dist/components/nodes/SimpleNode.svelte +0 -6
- package/dist/components/nodes/SquareNode.svelte +0 -4
- package/dist/components/nodes/TerminalNode.svelte +45 -9
- package/dist/components/nodes/TerminalNode.svelte.d.ts +2 -1
- package/dist/components/nodes/ToolNode.svelte +17 -11
- package/dist/components/nodes/WorkflowNode.svelte +0 -10
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js +1 -1
- package/dist/editor/index.d.ts +1 -0
- package/dist/editor/index.js +2 -0
- package/dist/helpers/proximityConnect.d.ts +19 -3
- package/dist/helpers/proximityConnect.js +109 -7
- package/dist/playground/index.d.ts +1 -1
- package/dist/playground/index.js +1 -1
- package/dist/services/portConfigApi.js +0 -11
- package/dist/settings/index.d.ts +2 -1
- package/dist/settings/index.js +2 -1
- package/dist/stores/interruptStore.d.ts +8 -30
- package/dist/stores/interruptStore.js +7 -76
- package/dist/stores/portCoordinateStore.d.ts +60 -0
- package/dist/stores/portCoordinateStore.js +186 -0
- package/dist/stores/settingsStore.d.ts +44 -2
- package/dist/stores/settingsStore.js +37 -15
- package/dist/types/index.d.ts +22 -0
- package/dist/utils/fetchWithAuth.d.ts +25 -0
- package/dist/utils/fetchWithAuth.js +34 -0
- package/package.json +1 -1
- package/dist/stores/themeStore.d.ts +0 -68
- package/dist/stores/themeStore.js +0 -213
|
@@ -36,6 +36,8 @@
|
|
|
36
36
|
import { apiToasts, dismissToast } from '../services/toastService.js';
|
|
37
37
|
import { initAutoSave } from '../services/autoSaveService.js';
|
|
38
38
|
import { uiSettings } from '../stores/settingsStore.js';
|
|
39
|
+
import { initializePortCompatibility } from '../utils/connections.js';
|
|
40
|
+
import { DEFAULT_PORT_CONFIG } from '../config/defaultPortConfig.js';
|
|
39
41
|
|
|
40
42
|
/**
|
|
41
43
|
* Configuration props for runtime customization
|
|
@@ -177,9 +179,6 @@
|
|
|
177
179
|
// WorkflowEditor reference for save functionality
|
|
178
180
|
let workflowEditorRef: WorkflowEditor | null = null;
|
|
179
181
|
|
|
180
|
-
// Removed currentWorkflowState - no longer needed
|
|
181
|
-
// The global store ($workflowStore) serves as the single source of truth
|
|
182
|
-
|
|
183
182
|
/**
|
|
184
183
|
* Fetch node types from the server
|
|
185
184
|
*
|
|
@@ -383,9 +382,6 @@
|
|
|
383
382
|
}
|
|
384
383
|
}
|
|
385
384
|
|
|
386
|
-
// Removed handleWorkflowChange function - no longer needed
|
|
387
|
-
// The global store serves as the single source of truth and is already reactive
|
|
388
|
-
|
|
389
385
|
/**
|
|
390
386
|
* Save workflow - exposed API function
|
|
391
387
|
*
|
|
@@ -591,6 +587,11 @@
|
|
|
591
587
|
onMount(() => {
|
|
592
588
|
(async () => {
|
|
593
589
|
await initializeApiEndpoints();
|
|
590
|
+
|
|
591
|
+
// Ensure port compatibility checker is initialized (needed for proximity connect, etc.)
|
|
592
|
+
// mountFlowDropApp initializes this before mounting, but SvelteKit routes need it here.
|
|
593
|
+
initializePortCompatibility(DEFAULT_PORT_CONFIG);
|
|
594
|
+
|
|
594
595
|
await fetchNodeTypes();
|
|
595
596
|
|
|
596
597
|
// Initialize the workflow store if we have an initial workflow
|
|
@@ -738,6 +739,7 @@
|
|
|
738
739
|
onClose={() => (isWorkflowSettingsOpen = false)}
|
|
739
740
|
>
|
|
740
741
|
<ConfigForm
|
|
742
|
+
{authProvider}
|
|
741
743
|
schema={workflowConfigSchema}
|
|
742
744
|
values={workflowConfigValues}
|
|
743
745
|
showUIExtensions={false}
|
|
@@ -765,6 +767,7 @@
|
|
|
765
767
|
onClose={closeConfigSidebar}
|
|
766
768
|
>
|
|
767
769
|
<ConfigForm
|
|
770
|
+
{authProvider}
|
|
768
771
|
node={currentNode}
|
|
769
772
|
workflowId={$workflowStore?.id}
|
|
770
773
|
workflowNodes={$workflowStore?.nodes}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Port Coordinate Tracker Component
|
|
3
|
+
Bridge component that exposes SvelteFlow's getInternalNode to the parent.
|
|
4
|
+
Must be rendered inside SvelteFlowProvider context.
|
|
5
|
+
|
|
6
|
+
Uses the same pattern as EdgeRefresher - a renderless component that hooks
|
|
7
|
+
into the SvelteFlow context.
|
|
8
|
+
-->
|
|
9
|
+
|
|
10
|
+
<script lang="ts">
|
|
11
|
+
import { useSvelteFlow, type InternalNode } from '@xyflow/svelte';
|
|
12
|
+
import type { WorkflowNode as WorkflowNodeType } from '../types/index.js';
|
|
13
|
+
import {
|
|
14
|
+
rebuildAllPortCoordinates,
|
|
15
|
+
updateNodePortCoordinates
|
|
16
|
+
} from '../stores/portCoordinateStore.js';
|
|
17
|
+
|
|
18
|
+
interface Props {
|
|
19
|
+
/** Node to update coordinates for (e.g., during drag). Set to null when not dragging. */
|
|
20
|
+
nodeToUpdate: WorkflowNodeType | null;
|
|
21
|
+
/** Set to trigger a full rebuild of all port coordinates */
|
|
22
|
+
rebuildTrigger: number;
|
|
23
|
+
/** All workflow nodes - used for full rebuild */
|
|
24
|
+
nodes: WorkflowNodeType[];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let { nodeToUpdate, rebuildTrigger, nodes }: Props = $props();
|
|
28
|
+
|
|
29
|
+
const { getInternalNode } = useSvelteFlow();
|
|
30
|
+
|
|
31
|
+
// Cast the getInternalNode function for our use
|
|
32
|
+
const getInternal = getInternalNode as (id: string) => InternalNode | undefined;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Rebuild all port coordinates when rebuildTrigger changes.
|
|
36
|
+
* Debounced to batch rapid position updates (e.g., animated auto-layout,
|
|
37
|
+
* magnetic child nodes following a parent drag).
|
|
38
|
+
*/
|
|
39
|
+
$effect(() => {
|
|
40
|
+
const _trigger = rebuildTrigger;
|
|
41
|
+
if (_trigger > 0) {
|
|
42
|
+
const timeout = setTimeout(() => {
|
|
43
|
+
rebuildAllPortCoordinates(nodes, getInternal);
|
|
44
|
+
}, 150);
|
|
45
|
+
return () => clearTimeout(timeout);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Update a single node's coordinates when nodeToUpdate changes.
|
|
51
|
+
* This is used during drag for efficient per-node updates.
|
|
52
|
+
*/
|
|
53
|
+
$effect(() => {
|
|
54
|
+
if (nodeToUpdate) {
|
|
55
|
+
updateNodePortCoordinates(nodeToUpdate, getInternal);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
</script>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { WorkflowNode as WorkflowNodeType } from '../types/index.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
/** Node to update coordinates for (e.g., during drag). Set to null when not dragging. */
|
|
4
|
+
nodeToUpdate: WorkflowNodeType | null;
|
|
5
|
+
/** Set to trigger a full rebuild of all port coordinates */
|
|
6
|
+
rebuildTrigger: number;
|
|
7
|
+
/** All workflow nodes - used for full rebuild */
|
|
8
|
+
nodes: WorkflowNodeType[];
|
|
9
|
+
}
|
|
10
|
+
declare const PortCoordinateTracker: import("svelte").Component<Props, {}, "">;
|
|
11
|
+
type PortCoordinateTracker = ReturnType<typeof PortCoordinateTracker>;
|
|
12
|
+
export default PortCoordinateTracker;
|
|
@@ -144,8 +144,7 @@
|
|
|
144
144
|
proximityConnect: {
|
|
145
145
|
type: 'boolean',
|
|
146
146
|
title: 'Proximity Connect',
|
|
147
|
-
description:
|
|
148
|
-
'Auto-connect compatible ports when dragging nodes near each other',
|
|
147
|
+
description: 'Auto-connect compatible ports when dragging nodes near each other',
|
|
149
148
|
default: false
|
|
150
149
|
},
|
|
151
150
|
proximityConnectDistance: {
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
<script lang="ts">
|
|
9
9
|
import Icon from '@iconify/svelte';
|
|
10
|
-
import { theme, resolvedTheme, cycleTheme } from '../stores/
|
|
10
|
+
import { theme, resolvedTheme, cycleTheme } from '../stores/settingsStore.js';
|
|
11
11
|
import type { ThemePreference } from '../types/settings.js';
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -16,8 +16,7 @@
|
|
|
16
16
|
type ColorMode
|
|
17
17
|
} from '@xyflow/svelte';
|
|
18
18
|
import '@xyflow/svelte/dist/style.css';
|
|
19
|
-
import { resolvedTheme } from '../stores/
|
|
20
|
-
import { editorSettings, behaviorSettings } from '../stores/settingsStore.js';
|
|
19
|
+
import { resolvedTheme, editorSettings, behaviorSettings } from '../stores/settingsStore.js';
|
|
21
20
|
import type {
|
|
22
21
|
WorkflowNode as WorkflowNodeType,
|
|
23
22
|
NodeMetadata,
|
|
@@ -47,10 +46,11 @@
|
|
|
47
46
|
ProximityConnectHelper,
|
|
48
47
|
type ProximityEdgeCandidate
|
|
49
48
|
} from '../helpers/proximityConnect.js';
|
|
49
|
+
import PortCoordinateTracker from './PortCoordinateTracker.svelte';
|
|
50
|
+
import { getPortCoordinateSnapshot } from '../stores/portCoordinateStore.js';
|
|
50
51
|
|
|
51
52
|
interface Props {
|
|
52
53
|
nodes?: NodeMetadata[];
|
|
53
|
-
// workflow?: Workflow; // Removed - use global store directly
|
|
54
54
|
endpointConfig?: EndpointConfig;
|
|
55
55
|
height?: string | number;
|
|
56
56
|
width?: string | number;
|
|
@@ -77,6 +77,10 @@
|
|
|
77
77
|
// Proximity connect state
|
|
78
78
|
let currentProximityCandidates = $state<ProximityEdgeCandidate[]>([]);
|
|
79
79
|
|
|
80
|
+
// Port coordinate tracker state
|
|
81
|
+
let portCoordNodeToUpdate = $state<WorkflowNodeType | null>(null);
|
|
82
|
+
let portCoordRebuildTrigger = $state(0);
|
|
83
|
+
|
|
80
84
|
// Track the workflow ID we're currently editing to detect workflow switches
|
|
81
85
|
let currentWorkflowId: string | null = null;
|
|
82
86
|
|
|
@@ -179,6 +183,14 @@
|
|
|
179
183
|
);
|
|
180
184
|
flowEdges = styledEdges;
|
|
181
185
|
|
|
186
|
+
// Trigger port coordinate rebuild after workflow load
|
|
187
|
+
// (PortCoordinateTracker will wait for SvelteFlow to render before reading handleBounds)
|
|
188
|
+
// Note: Using Date.now() instead of ++ to avoid reading the old value,
|
|
189
|
+
// which would make this effect depend on portCoordRebuildTrigger and loop.
|
|
190
|
+
if ($editorSettings.proximityConnect) {
|
|
191
|
+
portCoordRebuildTrigger = Date.now();
|
|
192
|
+
}
|
|
193
|
+
|
|
182
194
|
// Only load execution info if we have a pipelineId (pipeline status mode)
|
|
183
195
|
// and if the workflow or pipeline has changed
|
|
184
196
|
const workflowChanged = currentWorkflow.id !== previousWorkflowId;
|
|
@@ -348,7 +360,8 @@
|
|
|
348
360
|
|
|
349
361
|
/**
|
|
350
362
|
* Handle node drag - compute proximity connect preview edges
|
|
351
|
-
* Called continuously during drag if proximity connect is enabled
|
|
363
|
+
* Called continuously during drag if proximity connect is enabled.
|
|
364
|
+
* Uses port-to-port distance via the port coordinate store.
|
|
352
365
|
*/
|
|
353
366
|
function handleNodeDrag({
|
|
354
367
|
targetNode
|
|
@@ -362,19 +375,31 @@
|
|
|
362
375
|
flowEdges = ProximityConnectHelper.removePreviewEdges(flowEdges);
|
|
363
376
|
currentProximityCandidates = [];
|
|
364
377
|
}
|
|
378
|
+
portCoordNodeToUpdate = null;
|
|
365
379
|
return;
|
|
366
380
|
}
|
|
367
381
|
|
|
382
|
+
// Update the dragged node's port coordinates (position changed during drag)
|
|
383
|
+
portCoordNodeToUpdate = targetNode;
|
|
384
|
+
|
|
368
385
|
// Remove previous preview edges
|
|
369
386
|
const baseEdges = ProximityConnectHelper.removePreviewEdges(flowEdges);
|
|
370
387
|
|
|
371
|
-
// Find the best compatible edge
|
|
372
|
-
const
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
388
|
+
// Find the best compatible edge using port-to-port distance
|
|
389
|
+
const portCoordinates = getPortCoordinateSnapshot();
|
|
390
|
+
const candidates = portCoordinates.size > 0
|
|
391
|
+
? ProximityConnectHelper.findCompatibleEdgesByPortCoordinates(
|
|
392
|
+
targetNode.id,
|
|
393
|
+
portCoordinates,
|
|
394
|
+
baseEdges,
|
|
395
|
+
$editorSettings.proximityConnectDistance
|
|
396
|
+
)
|
|
397
|
+
: ProximityConnectHelper.findCompatibleEdges(
|
|
398
|
+
targetNode,
|
|
399
|
+
flowNodes,
|
|
400
|
+
baseEdges,
|
|
401
|
+
$editorSettings.proximityConnectDistance
|
|
402
|
+
);
|
|
378
403
|
|
|
379
404
|
// Create preview edges
|
|
380
405
|
const previews = ProximityConnectHelper.createPreviewEdges(candidates);
|
|
@@ -392,6 +417,7 @@
|
|
|
392
417
|
*/
|
|
393
418
|
function handleNodeDragStop(): void {
|
|
394
419
|
isDraggingNode = false;
|
|
420
|
+
portCoordNodeToUpdate = null;
|
|
395
421
|
|
|
396
422
|
// Finalize proximity connect if there are candidates
|
|
397
423
|
if ($editorSettings.proximityConnect && currentProximityCandidates.length > 0) {
|
|
@@ -700,6 +726,13 @@
|
|
|
700
726
|
<!-- EdgeRefresher component - handles updateNodeInternals calls -->
|
|
701
727
|
<EdgeRefresher {nodeIdToRefresh} onRefreshComplete={handleEdgeRefreshComplete} />
|
|
702
728
|
|
|
729
|
+
<!-- Port Coordinate Tracker - maintains port positions for proximity connect -->
|
|
730
|
+
<PortCoordinateTracker
|
|
731
|
+
nodeToUpdate={portCoordNodeToUpdate}
|
|
732
|
+
rebuildTrigger={portCoordRebuildTrigger}
|
|
733
|
+
nodes={flowNodes}
|
|
734
|
+
/>
|
|
735
|
+
|
|
703
736
|
<div class="flowdrop-workflow-editor">
|
|
704
737
|
<!-- Main Editor Area -->
|
|
705
738
|
<div class="flowdrop-workflow-editor__main">
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
import Icon from '@iconify/svelte';
|
|
26
26
|
import type { AutocompleteConfig, AuthProvider } from '../../types/index.js';
|
|
27
27
|
import type { FieldOption } from './types.js';
|
|
28
|
+
import { buildFetchHeaders } from '../../utils/fetchWithAuth.js';
|
|
28
29
|
|
|
29
30
|
/**
|
|
30
31
|
* Props interface for FormAutocomplete component
|
|
@@ -192,18 +193,8 @@
|
|
|
192
193
|
abortController = new AbortController();
|
|
193
194
|
|
|
194
195
|
try {
|
|
195
|
-
// Build headers with authentication
|
|
196
|
-
const headers
|
|
197
|
-
Accept: 'application/json',
|
|
198
|
-
'Content-Type': 'application/json'
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
// Add auth headers if provider is available (call getter to get current value)
|
|
202
|
-
const authProvider = getAuthProvider?.();
|
|
203
|
-
if (authProvider) {
|
|
204
|
-
const authHeaders = await authProvider.getAuthHeaders();
|
|
205
|
-
Object.assign(headers, authHeaders);
|
|
206
|
-
}
|
|
196
|
+
// Build headers with authentication (call getter to get current value)
|
|
197
|
+
const headers = await buildFetchHeaders(getAuthProvider?.());
|
|
207
198
|
|
|
208
199
|
// Fetch with timeout
|
|
209
200
|
const timeoutId = setTimeout(() => {
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
import type { FieldSchema } from './types.js';
|
|
45
45
|
import { getSchemaOptions } from './types.js';
|
|
46
46
|
import type { WorkflowNode, WorkflowEdge, AuthProvider } from '../../types/index.js';
|
|
47
|
-
import { resolvedTheme } from '../../stores/
|
|
47
|
+
import { resolvedTheme } from '../../stores/settingsStore.js';
|
|
48
48
|
|
|
49
49
|
interface Props {
|
|
50
50
|
/** Unique key/id for the field */
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
import FormCheckboxGroup from './FormCheckboxGroup.svelte';
|
|
44
44
|
import FormArray from './FormArray.svelte';
|
|
45
45
|
import { resolveFieldComponent } from '../../form/fieldRegistry.js';
|
|
46
|
-
import { resolvedTheme } from '../../stores/
|
|
46
|
+
import { resolvedTheme } from '../../stores/settingsStore.js';
|
|
47
47
|
import type { FieldSchema } from './types.js';
|
|
48
48
|
import { getSchemaOptions } from './types.js';
|
|
49
49
|
|
|
@@ -42,8 +42,6 @@
|
|
|
42
42
|
return instanceOverride ?? typeDefault;
|
|
43
43
|
});
|
|
44
44
|
|
|
45
|
-
// Removed local config state - now using global ConfigSidebar
|
|
46
|
-
|
|
47
45
|
// Prioritize metadata icon over config icon for simple nodes (metadata is the node definition)
|
|
48
46
|
let nodeIcon = $derived(
|
|
49
47
|
(props.data.metadata?.icon as string) || (props.data.config?.icon as string) || 'mdi:square'
|
|
@@ -265,8 +263,6 @@
|
|
|
265
263
|
/>
|
|
266
264
|
{/each}
|
|
267
265
|
|
|
268
|
-
<!-- ConfigSidebar removed - now using global ConfigSidebar in WorkflowEditor -->
|
|
269
|
-
|
|
270
266
|
<style>
|
|
271
267
|
.flowdrop-simple-node {
|
|
272
268
|
position: relative;
|
|
@@ -379,8 +375,6 @@
|
|
|
379
375
|
color: var(--fd-node-icon);
|
|
380
376
|
}
|
|
381
377
|
|
|
382
|
-
/* Label styling removed - now using header title */
|
|
383
|
-
|
|
384
378
|
.flowdrop-simple-node__processing {
|
|
385
379
|
position: absolute;
|
|
386
380
|
top: 4px;
|
|
@@ -43,8 +43,6 @@
|
|
|
43
43
|
return instanceOverride ?? typeDefault;
|
|
44
44
|
});
|
|
45
45
|
|
|
46
|
-
// Removed local config state - now using global ConfigSidebar
|
|
47
|
-
|
|
48
46
|
/**
|
|
49
47
|
* Get icon using the same resolution as WorkflowNode
|
|
50
48
|
* Uses getNodeIcon utility with category fallback
|
|
@@ -333,8 +331,6 @@
|
|
|
333
331
|
color: var(--fd-node-icon);
|
|
334
332
|
}
|
|
335
333
|
|
|
336
|
-
/* Label styling removed - now using header title */
|
|
337
|
-
|
|
338
334
|
.flowdrop-square-node__processing {
|
|
339
335
|
position: absolute;
|
|
340
336
|
top: 4px;
|
|
@@ -10,11 +10,12 @@
|
|
|
10
10
|
|
|
11
11
|
<script lang="ts">
|
|
12
12
|
import { Position, Handle } from '@xyflow/svelte';
|
|
13
|
-
import type { ConfigValues, NodeMetadata } from '../../types/index.js';
|
|
13
|
+
import type { ConfigValues, NodeMetadata, NodeExtensions, NodePort } from '../../types/index.js';
|
|
14
14
|
import Icon from '@iconify/svelte';
|
|
15
15
|
import { getDataTypeColor, getCategoryColorToken } from '../../utils/colors.js';
|
|
16
16
|
import { getNodeIcon } from '../../utils/icons.js';
|
|
17
17
|
import { getCircleHandlePosition } from '../../utils/handlePositioning.js';
|
|
18
|
+
import { connectedHandles } from '../../stores/workflowStore.js';
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* Terminal node variant types
|
|
@@ -70,6 +71,7 @@
|
|
|
70
71
|
config: ConfigValues;
|
|
71
72
|
metadata: NodeMetadata;
|
|
72
73
|
nodeId?: string;
|
|
74
|
+
extensions?: NodeExtensions;
|
|
73
75
|
onConfigOpen?: (node: {
|
|
74
76
|
id: string;
|
|
75
77
|
type: string;
|
|
@@ -133,6 +135,30 @@
|
|
|
133
135
|
*/
|
|
134
136
|
let variantConfig = $derived(VARIANT_CONFIGS[variant]);
|
|
135
137
|
|
|
138
|
+
/**
|
|
139
|
+
* Get the hideUnconnectedHandles setting from extensions
|
|
140
|
+
* Merges node type defaults with instance overrides
|
|
141
|
+
*/
|
|
142
|
+
const hideUnconnectedHandles = $derived(() => {
|
|
143
|
+
const typeDefault = props.data.metadata?.extensions?.ui?.hideUnconnectedHandles ?? false;
|
|
144
|
+
const instanceOverride = props.data.extensions?.ui?.hideUnconnectedHandles;
|
|
145
|
+
return instanceOverride ?? typeDefault;
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Check if a port should be visible based on connection state and settings
|
|
150
|
+
*/
|
|
151
|
+
function isPortVisible(port: NodePort, type: 'input' | 'output'): boolean {
|
|
152
|
+
if (!hideUnconnectedHandles()) {
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
if (port.required) {
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
const handleId = `${props.data.nodeId}-${type}-${port.id}`;
|
|
159
|
+
return $connectedHandles.has(handleId);
|
|
160
|
+
}
|
|
161
|
+
|
|
136
162
|
/**
|
|
137
163
|
* Get icon using the same resolution as WorkflowNode
|
|
138
164
|
* Uses getNodeIcon utility with category fallback, or variant default
|
|
@@ -239,14 +265,24 @@
|
|
|
239
265
|
);
|
|
240
266
|
|
|
241
267
|
/**
|
|
242
|
-
*
|
|
268
|
+
* Visible input ports filtered by hideUnconnectedHandles setting
|
|
269
|
+
*/
|
|
270
|
+
let visibleInputPorts = $derived(inputPorts.filter((port) => isPortVisible(port, 'input')));
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Visible output ports filtered by hideUnconnectedHandles setting
|
|
274
|
+
*/
|
|
275
|
+
let visibleOutputPorts = $derived(outputPorts.filter((port) => isPortVisible(port, 'output')));
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Determine if we should show inputs based on visible ports
|
|
243
279
|
*/
|
|
244
|
-
let showInputs = $derived(
|
|
280
|
+
let showInputs = $derived(visibleInputPorts.length > 0);
|
|
245
281
|
|
|
246
282
|
/**
|
|
247
|
-
* Determine if we should show outputs based on ports
|
|
283
|
+
* Determine if we should show outputs based on visible ports
|
|
248
284
|
*/
|
|
249
|
-
let showOutputs = $derived(
|
|
285
|
+
let showOutputs = $derived(visibleOutputPorts.length > 0);
|
|
250
286
|
|
|
251
287
|
/**
|
|
252
288
|
* Handle configuration sidebar - using global ConfigSidebar
|
|
@@ -317,8 +353,8 @@
|
|
|
317
353
|
<div class="flowdrop-terminal-node__circle-wrapper">
|
|
318
354
|
<!-- Input Handles (for end/exit variants) -->
|
|
319
355
|
{#if showInputs}
|
|
320
|
-
{#each
|
|
321
|
-
{@const pos = getCircleHandlePosition(index,
|
|
356
|
+
{#each visibleInputPorts as port, index (`${port.id}-${visibleInputPorts.length}`)}
|
|
357
|
+
{@const pos = getCircleHandlePosition(index, visibleInputPorts.length, 'left')}
|
|
322
358
|
<Handle
|
|
323
359
|
type="target"
|
|
324
360
|
position={Position.Left}
|
|
@@ -339,8 +375,8 @@
|
|
|
339
375
|
|
|
340
376
|
<!-- Output Handles (for start variant) -->
|
|
341
377
|
{#if showOutputs}
|
|
342
|
-
{#each
|
|
343
|
-
{@const pos = getCircleHandlePosition(index,
|
|
378
|
+
{#each visibleOutputPorts as port, index (`${port.id}-${visibleOutputPorts.length}`)}
|
|
379
|
+
{@const pos = getCircleHandlePosition(index, visibleOutputPorts.length, 'right')}
|
|
344
380
|
<Handle
|
|
345
381
|
type="source"
|
|
346
382
|
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;
|
|
@@ -67,9 +67,7 @@
|
|
|
67
67
|
* This allows users to customize the badge text per-instance via config.
|
|
68
68
|
*/
|
|
69
69
|
const displayBadge = $derived(
|
|
70
|
-
(props.data.config?.instanceBadge as string) ||
|
|
71
|
-
(props.data.metadata?.badge as string) ||
|
|
72
|
-
'TOOL'
|
|
70
|
+
(props.data.config?.instanceBadge as string) || (props.data.metadata?.badge as string) || 'TOOL'
|
|
73
71
|
);
|
|
74
72
|
|
|
75
73
|
/**
|
|
@@ -96,20 +94,28 @@
|
|
|
96
94
|
*/
|
|
97
95
|
let nodeStyle = $derived(`--fd-tool-node-color: ${toolColor}`);
|
|
98
96
|
|
|
99
|
-
|
|
97
|
+
/**
|
|
98
|
+
* Configurable port dataType to expose on this tool node.
|
|
99
|
+
* Defaults to 'tool', but can be overridden via metadata.portDataType
|
|
100
|
+
* to show a different port type (e.g., 'trigger') when the node is
|
|
101
|
+
* repurposed with a custom badge.
|
|
102
|
+
*/
|
|
103
|
+
let portDataType = $derived((props.data.metadata?.portDataType as string) || 'tool');
|
|
104
|
+
|
|
105
|
+
// Check for matching interface ports in metadata
|
|
100
106
|
let hasToolInputPort = $derived(
|
|
101
|
-
props.data.metadata?.inputs?.some((port) => port.dataType ===
|
|
107
|
+
props.data.metadata?.inputs?.some((port) => port.dataType === portDataType) || false
|
|
102
108
|
);
|
|
103
109
|
let hasToolOutputPort = $derived(
|
|
104
|
-
props.data.metadata?.outputs?.some((port) => port.dataType ===
|
|
110
|
+
props.data.metadata?.outputs?.some((port) => port.dataType === portDataType) || false
|
|
105
111
|
);
|
|
106
112
|
|
|
107
|
-
// Get the actual
|
|
113
|
+
// Get the actual matching ports for proper handle generation
|
|
108
114
|
let toolInputPort = $derived(
|
|
109
|
-
props.data.metadata?.inputs?.find((port) => port.dataType ===
|
|
115
|
+
props.data.metadata?.inputs?.find((port) => port.dataType === portDataType)
|
|
110
116
|
);
|
|
111
117
|
let toolOutputPort = $derived(
|
|
112
|
-
props.data.metadata?.outputs?.find((port) => port.dataType ===
|
|
118
|
+
props.data.metadata?.outputs?.find((port) => port.dataType === portDataType)
|
|
113
119
|
);
|
|
114
120
|
|
|
115
121
|
/**
|
|
@@ -159,7 +165,7 @@
|
|
|
159
165
|
position={Position.Left}
|
|
160
166
|
id={`${props.data.nodeId}-input-${toolInputPort.id}`}
|
|
161
167
|
style="top: 40px; transform: translateY(-50%); margin-left: -10px; --fd-handle-fill: {getDataTypeColor(
|
|
162
|
-
|
|
168
|
+
portDataType
|
|
163
169
|
)}; --fd-handle-border-color: var(--fd-handle-border);"
|
|
164
170
|
/>
|
|
165
171
|
{/if}
|
|
@@ -232,7 +238,7 @@
|
|
|
232
238
|
position={Position.Right}
|
|
233
239
|
id={`${props.data.nodeId}-output-${toolOutputPort.id}`}
|
|
234
240
|
style="top: 40px; transform: translateY(-50%); margin-right: -10px; --fd-handle-fill: {getDataTypeColor(
|
|
235
|
-
|
|
241
|
+
portDataType
|
|
236
242
|
)}; --fd-handle-border-color: var(--fd-handle-border);"
|
|
237
243
|
/>
|
|
238
244
|
{/if}
|
|
@@ -124,11 +124,6 @@
|
|
|
124
124
|
allOutputPorts.filter((port) => isPortVisible(port, 'output'))
|
|
125
125
|
);
|
|
126
126
|
|
|
127
|
-
/**
|
|
128
|
-
* Handle configuration value changes - now handled by global ConfigSidebar
|
|
129
|
-
*/
|
|
130
|
-
// Removed local config handling - now using global ConfigSidebar
|
|
131
|
-
|
|
132
127
|
/**
|
|
133
128
|
* Handle node click - only handle selection, no config opening
|
|
134
129
|
*/
|
|
@@ -201,7 +196,6 @@
|
|
|
201
196
|
|
|
202
197
|
<!-- Status Indicators -->
|
|
203
198
|
<div class="flowdrop-flex flowdrop-gap--2 flowdrop-items--center">
|
|
204
|
-
<!-- Status indicators removed - using outer NodeStatusOverlay instead -->
|
|
205
199
|
</div>
|
|
206
200
|
</div>
|
|
207
201
|
<!-- Node Description - line-height 20px so header grows in steps of 10 -->
|
|
@@ -326,8 +320,6 @@
|
|
|
326
320
|
</button>
|
|
327
321
|
</div>
|
|
328
322
|
|
|
329
|
-
<!-- ConfigSidebar removed - now using global ConfigSidebar in WorkflowEditor -->
|
|
330
|
-
|
|
331
323
|
<style>
|
|
332
324
|
.flowdrop-workflow-node {
|
|
333
325
|
position: relative;
|
|
@@ -436,8 +428,6 @@
|
|
|
436
428
|
line-height: 1;
|
|
437
429
|
}
|
|
438
430
|
|
|
439
|
-
/* Status indicator styles removed - using outer NodeStatusOverlay instead */
|
|
440
|
-
|
|
441
431
|
@keyframes pulse {
|
|
442
432
|
0%,
|
|
443
433
|
100% {
|
package/dist/core/index.d.ts
CHANGED
|
@@ -40,5 +40,5 @@ export { isFieldOptionArray, normalizeOptions } from '../components/form/types.j
|
|
|
40
40
|
export { DEFAULT_PORT_CONFIG } from '../config/defaultPortConfig.js';
|
|
41
41
|
export { defaultEndpointConfig, createEndpointConfig } from '../config/endpoints.js';
|
|
42
42
|
export * from '../adapters/WorkflowAdapter.js';
|
|
43
|
-
export type { ThemePreference, ResolvedTheme } from '../stores/
|
|
44
|
-
export { theme, resolvedTheme, setTheme, toggleTheme, cycleTheme, initializeTheme, isThemeInitialized } from '../stores/
|
|
43
|
+
export type { ThemePreference, ResolvedTheme } from '../stores/settingsStore.js';
|
|
44
|
+
export { theme, resolvedTheme, setTheme, toggleTheme, cycleTheme, initializeTheme, isThemeInitialized } from '../stores/settingsStore.js';
|
package/dist/core/index.js
CHANGED
|
@@ -51,4 +51,4 @@ export { defaultEndpointConfig, createEndpointConfig } from '../config/endpoints
|
|
|
51
51
|
// Adapters
|
|
52
52
|
// ============================================================================
|
|
53
53
|
export * from '../adapters/WorkflowAdapter.js';
|
|
54
|
-
export { theme, resolvedTheme, setTheme, toggleTheme, cycleTheme, initializeTheme, isThemeInitialized } from '../stores/
|
|
54
|
+
export { theme, resolvedTheme, setTheme, toggleTheme, cycleTheme, initializeTheme, isThemeInitialized } from '../stores/settingsStore.js';
|
package/dist/editor/index.d.ts
CHANGED
|
@@ -64,6 +64,7 @@ export { mountWorkflowEditor, mountFlowDropApp, unmountFlowDropApp } from '../sv
|
|
|
64
64
|
export { nodeComponentRegistry, createNamespacedType, parseNamespacedType, BUILTIN_NODE_COMPONENTS, BUILTIN_NODE_TYPES, FLOWDROP_SOURCE, registerBuiltinNodes, areBuiltinsRegistered, isBuiltinType, getBuiltinTypes, resolveBuiltinAlias, registerFlowDropPlugin, unregisterFlowDropPlugin, registerCustomNode, createPlugin, isValidNamespace, getRegisteredPlugins, getPluginNodeCount } from '../registry/index.js';
|
|
65
65
|
export { EdgeStylingHelper, NodeOperationsHelper, WorkflowOperationsHelper, ConfigurationHelper } from '../helpers/workflowEditorHelper.js';
|
|
66
66
|
export { workflowStore, workflowActions, workflowId, workflowName, workflowNodes, workflowEdges, workflowMetadata, workflowChanged, workflowValidation, workflowMetadataChanged, connectedHandles, isDirtyStore, isDirty, markAsSaved, getWorkflow as getWorkflowFromStore, setOnDirtyStateChange, setOnWorkflowChange, setHistoryEnabled, isHistoryEnabled, setRestoringFromHistory } from '../stores/workflowStore.js';
|
|
67
|
+
export { portCoordinateStore, rebuildAllPortCoordinates, updateNodePortCoordinates, removeNodePortCoordinates, getPortCoordinate, getNodePortCoordinates, getPortCoordinateSnapshot } from '../stores/portCoordinateStore.js';
|
|
67
68
|
export { historyStateStore, canUndo, canRedo, historyActions, setOnRestoreCallback, historyService, HistoryService } from '../stores/historyStore.js';
|
|
68
69
|
export type { HistoryEntry, HistoryState, PushOptions } from '../stores/historyStore.js';
|
|
69
70
|
export * from '../services/api.js';
|
package/dist/editor/index.js
CHANGED
|
@@ -101,6 +101,8 @@ export { workflowStore, workflowActions, workflowId, workflowName, workflowNodes
|
|
|
101
101
|
isDirtyStore, isDirty, markAsSaved, getWorkflow as getWorkflowFromStore, setOnDirtyStateChange, setOnWorkflowChange,
|
|
102
102
|
// History control
|
|
103
103
|
setHistoryEnabled, isHistoryEnabled, setRestoringFromHistory } from '../stores/workflowStore.js';
|
|
104
|
+
// Port Coordinate Store
|
|
105
|
+
export { portCoordinateStore, rebuildAllPortCoordinates, updateNodePortCoordinates, removeNodePortCoordinates, getPortCoordinate, getNodePortCoordinates, getPortCoordinateSnapshot } from '../stores/portCoordinateStore.js';
|
|
104
106
|
// History Store and Service
|
|
105
107
|
export { historyStateStore, canUndo, canRedo, historyActions, setOnRestoreCallback, historyService, HistoryService } from '../stores/historyStore.js';
|
|
106
108
|
// ============================================================================
|