@d34dman/flowdrop 0.0.46 → 0.0.48
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 +10 -0
- package/dist/components/App.svelte.d.ts +2 -0
- package/dist/components/ConfigForm.svelte +72 -6
- package/dist/components/ConfigForm.svelte.d.ts +13 -1
- package/dist/components/SchemaForm.svelte +4 -2
- package/dist/components/SettingsPanel.svelte +5 -2
- package/dist/components/WorkflowEditor.svelte +26 -0
- package/dist/components/WorkflowEditor.svelte.d.ts +1 -0
- package/dist/components/form/FormAutocomplete.svelte +7 -4
- package/dist/components/form/FormField.svelte +42 -13
- package/dist/components/form/FormField.svelte.d.ts +11 -0
- package/dist/components/form/FormFieldLight.svelte +16 -13
- package/dist/components/form/FormTemplateEditor.svelte +343 -21
- package/dist/components/form/FormTemplateEditor.svelte.d.ts +22 -2
- package/dist/components/form/index.d.ts +1 -0
- package/dist/components/form/index.js +2 -0
- package/dist/components/form/templateAutocomplete.d.ts +29 -0
- package/dist/components/form/templateAutocomplete.js +253 -0
- package/dist/components/form/types.d.ts +29 -3
- package/dist/components/nodes/TerminalNode.svelte +27 -15
- package/dist/registry/nodeComponentRegistry.d.ts +9 -9
- package/dist/registry/nodeComponentRegistry.js +10 -10
- package/dist/services/apiVariableService.d.ts +116 -0
- package/dist/services/apiVariableService.js +338 -0
- package/dist/services/variableService.d.ts +141 -0
- package/dist/services/variableService.js +462 -0
- package/dist/svelte-app.d.ts +2 -0
- package/dist/svelte-app.js +2 -1
- package/dist/types/index.d.ts +257 -0
- package/dist/utils/handlePositioning.d.ts +31 -0
- package/dist/utils/handlePositioning.js +35 -0
- package/dist/utils/nodeTypes.d.ts +15 -10
- package/dist/utils/nodeTypes.js +24 -22
- package/package.json +7 -3
|
@@ -71,6 +71,8 @@
|
|
|
71
71
|
variant?: 'primary' | 'secondary' | 'outline';
|
|
72
72
|
onclick?: (event: Event) => void;
|
|
73
73
|
}>;
|
|
74
|
+
/** Show settings gear icon in navbar */
|
|
75
|
+
showSettings?: boolean;
|
|
74
76
|
/** API base URL */
|
|
75
77
|
apiBaseUrl?: string;
|
|
76
78
|
/** Endpoint configuration */
|
|
@@ -96,6 +98,7 @@
|
|
|
96
98
|
pipelineId,
|
|
97
99
|
navbarTitle,
|
|
98
100
|
navbarActions = [],
|
|
101
|
+
showSettings = true,
|
|
99
102
|
apiBaseUrl,
|
|
100
103
|
endpointConfig: propEndpointConfig,
|
|
101
104
|
authProvider,
|
|
@@ -705,6 +708,7 @@
|
|
|
705
708
|
}
|
|
706
709
|
]}
|
|
707
710
|
showStatus={true}
|
|
711
|
+
{showSettings}
|
|
708
712
|
/>
|
|
709
713
|
{/snippet}
|
|
710
714
|
|
|
@@ -756,6 +760,8 @@
|
|
|
756
760
|
<ConfigForm
|
|
757
761
|
node={currentNode}
|
|
758
762
|
workflowId={$workflowStore?.id}
|
|
763
|
+
workflowNodes={$workflowStore?.nodes}
|
|
764
|
+
workflowEdges={$workflowStore?.edges}
|
|
759
765
|
onChange={async (updatedConfig, uiExtensions) => {
|
|
760
766
|
// Sync config changes to workflow immediately on field blur
|
|
761
767
|
if (selectedNodeId && currentNode) {
|
|
@@ -780,6 +786,10 @@
|
|
|
780
786
|
|
|
781
787
|
workflowActions.updateNode(selectedNodeId, nodeUpdates);
|
|
782
788
|
|
|
789
|
+
// Update the local editor state to reflect config changes immediately
|
|
790
|
+
// This is needed for nodeType changes to take effect visually
|
|
791
|
+
workflowEditorRef.updateNodeData(selectedNodeId, updatedData);
|
|
792
|
+
|
|
783
793
|
// Refresh edge positions in case config changes affect handles
|
|
784
794
|
await workflowEditorRef.refreshEdgePositions(selectedNodeId);
|
|
785
795
|
}
|
|
@@ -36,6 +36,8 @@ interface Props {
|
|
|
36
36
|
variant?: 'primary' | 'secondary' | 'outline';
|
|
37
37
|
onclick?: (event: Event) => void;
|
|
38
38
|
}>;
|
|
39
|
+
/** Show settings gear icon in navbar */
|
|
40
|
+
showSettings?: boolean;
|
|
39
41
|
/** API base URL */
|
|
40
42
|
apiBaseUrl?: string;
|
|
41
43
|
/** Endpoint configuration */
|
|
@@ -18,12 +18,15 @@
|
|
|
18
18
|
-->
|
|
19
19
|
|
|
20
20
|
<script lang="ts">
|
|
21
|
+
import { setContext } from 'svelte';
|
|
21
22
|
import Icon from '@iconify/svelte';
|
|
22
23
|
import type {
|
|
23
24
|
ConfigSchema,
|
|
24
25
|
WorkflowNode,
|
|
26
|
+
WorkflowEdge,
|
|
25
27
|
NodeUIExtensions,
|
|
26
|
-
ConfigEditOptions
|
|
28
|
+
ConfigEditOptions,
|
|
29
|
+
AuthProvider
|
|
27
30
|
} from '../types/index.js';
|
|
28
31
|
import { FormField, FormFieldWrapper, FormToggle } from './form/index.js';
|
|
29
32
|
import type { FieldSchema } from './form/index.js';
|
|
@@ -35,6 +38,7 @@
|
|
|
35
38
|
type DynamicSchemaResult
|
|
36
39
|
} from '../services/dynamicSchemaService.js';
|
|
37
40
|
import { globalSaveWorkflow } from '../services/globalSave.js';
|
|
41
|
+
import { getAvailableVariables } from '../services/variableService.js';
|
|
38
42
|
|
|
39
43
|
interface Props {
|
|
40
44
|
/** Optional workflow node (if provided, schema and values are derived from it) */
|
|
@@ -49,6 +53,18 @@
|
|
|
49
53
|
workflowId?: string;
|
|
50
54
|
/** Whether to also save the workflow when saving config */
|
|
51
55
|
saveWorkflowWhenSavingConfig?: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* All workflow nodes (used for deriving template variables from connected nodes).
|
|
58
|
+
* When provided along with workflowEdges, enables autocomplete for template fields.
|
|
59
|
+
*/
|
|
60
|
+
workflowNodes?: WorkflowNode[];
|
|
61
|
+
/**
|
|
62
|
+
* All workflow edges (used for finding connections to derive template variables).
|
|
63
|
+
* When provided along with workflowNodes, enables autocomplete for template fields.
|
|
64
|
+
*/
|
|
65
|
+
workflowEdges?: WorkflowEdge[];
|
|
66
|
+
/** Auth provider for API requests (used for template variable API mode) */
|
|
67
|
+
authProvider?: AuthProvider;
|
|
52
68
|
/** Callback when any field value changes (fired on blur for immediate sync) */
|
|
53
69
|
onChange?: (config: Record<string, unknown>, uiExtensions?: NodeUIExtensions) => void;
|
|
54
70
|
/** Callback when form is saved (includes both config and extensions if enabled) */
|
|
@@ -64,11 +80,19 @@
|
|
|
64
80
|
showUIExtensions = true,
|
|
65
81
|
workflowId,
|
|
66
82
|
saveWorkflowWhenSavingConfig = false,
|
|
83
|
+
workflowNodes = [],
|
|
84
|
+
workflowEdges = [],
|
|
85
|
+
authProvider,
|
|
67
86
|
onChange,
|
|
68
87
|
onSave,
|
|
69
88
|
onCancel
|
|
70
89
|
}: Props = $props();
|
|
71
90
|
|
|
91
|
+
// Set context for child components (e.g., FormAutocomplete)
|
|
92
|
+
// Use getter functions to ensure child components always get the current prop value,
|
|
93
|
+
// even if the prop changes after initial mount
|
|
94
|
+
setContext<() => AuthProvider | undefined>('flowdrop:getAuthProvider', () => authProvider);
|
|
95
|
+
|
|
72
96
|
/**
|
|
73
97
|
* State for dynamic schema loading
|
|
74
98
|
*/
|
|
@@ -118,13 +142,14 @@
|
|
|
118
142
|
});
|
|
119
143
|
|
|
120
144
|
/**
|
|
121
|
-
* Check if the node
|
|
145
|
+
* Check if the node needs dynamic schema loading
|
|
146
|
+
* Loads when: no static schema OR preferDynamicSchema is true
|
|
122
147
|
*/
|
|
123
148
|
const needsDynamicSchemaLoad = $derived.by(() => {
|
|
124
149
|
if (!node) return false;
|
|
125
150
|
const staticSchema = schema ?? node.data.metadata?.configSchema;
|
|
126
|
-
// Need to load if: no static schema AND dynamic schema is configured
|
|
127
|
-
return !staticSchema && useDynamicSchema && !fetchedDynamicSchema && !dynamicSchemaLoading;
|
|
151
|
+
// Need to load if: (no static schema OR preferDynamicSchema is true) AND dynamic schema is configured
|
|
152
|
+
return (!staticSchema || configEditOptions?.preferDynamicSchema === true) && useDynamicSchema && !fetchedDynamicSchema && !dynamicSchemaLoading;
|
|
128
153
|
});
|
|
129
154
|
|
|
130
155
|
/**
|
|
@@ -364,10 +389,46 @@
|
|
|
364
389
|
}
|
|
365
390
|
|
|
366
391
|
/**
|
|
367
|
-
* Convert ConfigProperty to FieldSchema for FormField component
|
|
392
|
+
* Convert ConfigProperty to FieldSchema for FormField component.
|
|
393
|
+
* Processes template fields to inject computed variable schema.
|
|
394
|
+
*
|
|
395
|
+
* For template fields, the `variables` config controls which input ports
|
|
396
|
+
* provide variables for autocomplete.
|
|
368
397
|
*/
|
|
369
398
|
function toFieldSchema(property: Record<string, unknown>): FieldSchema {
|
|
370
|
-
|
|
399
|
+
const fieldSchema = property as FieldSchema;
|
|
400
|
+
|
|
401
|
+
// Process template fields to compute variable schema
|
|
402
|
+
if (fieldSchema.format === 'template' && node && workflowNodes.length > 0 && workflowEdges.length > 0) {
|
|
403
|
+
// Get the variables config (may be undefined or partially defined)
|
|
404
|
+
const variablesConfig = fieldSchema.variables;
|
|
405
|
+
|
|
406
|
+
// Compute the variable schema with optional port filtering and port name prefixing
|
|
407
|
+
const computedSchema = getAvailableVariables(node, workflowNodes, workflowEdges, {
|
|
408
|
+
targetPortIds: variablesConfig?.ports,
|
|
409
|
+
includePortName: variablesConfig?.includePortName
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
// Merge computed schema with any pre-defined schema
|
|
413
|
+
const mergedSchema = variablesConfig?.schema
|
|
414
|
+
? {
|
|
415
|
+
variables: {
|
|
416
|
+
...computedSchema.variables,
|
|
417
|
+
...variablesConfig.schema.variables
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
: computedSchema;
|
|
421
|
+
|
|
422
|
+
return {
|
|
423
|
+
...fieldSchema,
|
|
424
|
+
variables: {
|
|
425
|
+
...variablesConfig,
|
|
426
|
+
schema: mergedSchema
|
|
427
|
+
}
|
|
428
|
+
} as FieldSchema;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
return fieldSchema;
|
|
371
432
|
}
|
|
372
433
|
</script>
|
|
373
434
|
|
|
@@ -487,6 +548,11 @@
|
|
|
487
548
|
value={configValues[key]}
|
|
488
549
|
{required}
|
|
489
550
|
animationIndex={index}
|
|
551
|
+
{node}
|
|
552
|
+
nodes={workflowNodes}
|
|
553
|
+
edges={workflowEdges}
|
|
554
|
+
{workflowId}
|
|
555
|
+
{authProvider}
|
|
490
556
|
onChange={(val) => handleFieldChange(key, val)}
|
|
491
557
|
/>
|
|
492
558
|
{/each}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ConfigSchema, WorkflowNode, NodeUIExtensions } from '../types/index.js';
|
|
1
|
+
import type { ConfigSchema, WorkflowNode, WorkflowEdge, NodeUIExtensions, AuthProvider } from '../types/index.js';
|
|
2
2
|
interface Props {
|
|
3
3
|
/** Optional workflow node (if provided, schema and values are derived from it) */
|
|
4
4
|
node?: WorkflowNode;
|
|
@@ -12,6 +12,18 @@ interface Props {
|
|
|
12
12
|
workflowId?: string;
|
|
13
13
|
/** Whether to also save the workflow when saving config */
|
|
14
14
|
saveWorkflowWhenSavingConfig?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* All workflow nodes (used for deriving template variables from connected nodes).
|
|
17
|
+
* When provided along with workflowEdges, enables autocomplete for template fields.
|
|
18
|
+
*/
|
|
19
|
+
workflowNodes?: WorkflowNode[];
|
|
20
|
+
/**
|
|
21
|
+
* All workflow edges (used for finding connections to derive template variables).
|
|
22
|
+
* When provided along with workflowNodes, enables autocomplete for template fields.
|
|
23
|
+
*/
|
|
24
|
+
workflowEdges?: WorkflowEdge[];
|
|
25
|
+
/** Auth provider for API requests (used for template variable API mode) */
|
|
26
|
+
authProvider?: AuthProvider;
|
|
15
27
|
/** Callback when any field value changes (fired on blur for immediate sync) */
|
|
16
28
|
onChange?: (config: Record<string, unknown>, uiExtensions?: NodeUIExtensions) => void;
|
|
17
29
|
/** Callback when form is saved (includes both config and extensions if enabled) */
|
|
@@ -157,8 +157,10 @@
|
|
|
157
157
|
}: Props = $props();
|
|
158
158
|
|
|
159
159
|
// Set context for child components (e.g., FormAutocomplete)
|
|
160
|
-
|
|
161
|
-
|
|
160
|
+
// Use getter functions to ensure child components always get the current prop value,
|
|
161
|
+
// even if the prop changes after initial mount
|
|
162
|
+
setContext<() => AuthProvider | undefined>('flowdrop:getAuthProvider', () => authProvider);
|
|
163
|
+
setContext<() => string>('flowdrop:getBaseUrl', () => baseUrl);
|
|
162
164
|
|
|
163
165
|
/**
|
|
164
166
|
* Internal reactive state for form values
|
|
@@ -89,8 +89,11 @@
|
|
|
89
89
|
type: 'string',
|
|
90
90
|
title: 'Theme Preference',
|
|
91
91
|
description: 'Choose your preferred color scheme',
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
oneOf: [
|
|
93
|
+
{ const: 'light', title: 'Light' },
|
|
94
|
+
{ const: 'dark', title: 'Dark' },
|
|
95
|
+
{ const: 'auto', title: 'Auto (System)' }
|
|
96
|
+
],
|
|
94
97
|
default: 'auto'
|
|
95
98
|
}
|
|
96
99
|
}
|
|
@@ -515,6 +515,32 @@
|
|
|
515
515
|
*/
|
|
516
516
|
let nodeIdToRefresh = $state<string | null>(null);
|
|
517
517
|
|
|
518
|
+
/**
|
|
519
|
+
* Update a node's data in the local editor state.
|
|
520
|
+
* This should be called after updating the node in the global store to ensure
|
|
521
|
+
* the visual representation is updated immediately (e.g., for nodeType changes).
|
|
522
|
+
*
|
|
523
|
+
* @param nodeId - The ID of the node to update
|
|
524
|
+
* @param dataUpdates - Partial data updates to merge into the node's data
|
|
525
|
+
*/
|
|
526
|
+
export function updateNodeData(
|
|
527
|
+
nodeId: string,
|
|
528
|
+
dataUpdates: Partial<WorkflowNodeType['data']>
|
|
529
|
+
): void {
|
|
530
|
+
flowNodes = flowNodes.map((node) => {
|
|
531
|
+
if (node.id === nodeId) {
|
|
532
|
+
return {
|
|
533
|
+
...node,
|
|
534
|
+
data: {
|
|
535
|
+
...node.data,
|
|
536
|
+
...dataUpdates
|
|
537
|
+
}
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
return node;
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
|
|
518
544
|
/**
|
|
519
545
|
* Force edge position recalculation after node config changes
|
|
520
546
|
* This should be called after saving gateway/switch node configs where branches are reordered
|
|
@@ -16,6 +16,7 @@ interface Props {
|
|
|
16
16
|
pipelineId?: string;
|
|
17
17
|
}
|
|
18
18
|
declare const WorkflowEditor: import("svelte").Component<Props, {
|
|
19
|
+
updateNodeData: (nodeId: string, dataUpdates: Partial<WorkflowNodeType["data"]>) => void;
|
|
19
20
|
refreshEdgePositions: (nodeId: string) => Promise<void>;
|
|
20
21
|
}, "">;
|
|
21
22
|
type WorkflowEditor = ReturnType<typeof WorkflowEditor>;
|
|
@@ -59,9 +59,10 @@
|
|
|
59
59
|
onChange
|
|
60
60
|
}: Props = $props();
|
|
61
61
|
|
|
62
|
-
// Get AuthProvider from context
|
|
63
|
-
|
|
64
|
-
const
|
|
62
|
+
// Get AuthProvider and baseUrl from context via getter functions
|
|
63
|
+
// This pattern ensures we always get the current value, even if props change after mount
|
|
64
|
+
const getAuthProvider = getContext<(() => AuthProvider | undefined) | undefined>('flowdrop:getAuthProvider');
|
|
65
|
+
const getBaseUrl = getContext<(() => string) | undefined>('flowdrop:getBaseUrl');
|
|
65
66
|
|
|
66
67
|
// Configuration with defaults
|
|
67
68
|
const queryParam = $derived(autocomplete.queryParam ?? 'q');
|
|
@@ -142,6 +143,7 @@
|
|
|
142
143
|
* @returns Full URL with query parameter
|
|
143
144
|
*/
|
|
144
145
|
function buildUrl(query: string): string {
|
|
146
|
+
const baseUrl = getBaseUrl?.() ?? '';
|
|
145
147
|
const url = autocomplete.url.startsWith('http')
|
|
146
148
|
? autocomplete.url
|
|
147
149
|
: `${baseUrl}${autocomplete.url}`;
|
|
@@ -194,7 +196,8 @@
|
|
|
194
196
|
'Content-Type': 'application/json'
|
|
195
197
|
};
|
|
196
198
|
|
|
197
|
-
// Add auth headers if provider is available
|
|
199
|
+
// Add auth headers if provider is available (call getter to get current value)
|
|
200
|
+
const authProvider = getAuthProvider?.();
|
|
198
201
|
if (authProvider) {
|
|
199
202
|
const authHeaders = await authProvider.getAuthHeaders();
|
|
200
203
|
Object.assign(headers, authHeaders);
|
|
@@ -17,12 +17,12 @@
|
|
|
17
17
|
5. format: 'template' -> FormTemplateEditor (CodeMirror with Twig/Liquid syntax)
|
|
18
18
|
6. enum with multiple: true -> FormCheckboxGroup
|
|
19
19
|
7. enum -> FormSelect (simple values without labels)
|
|
20
|
-
8.
|
|
21
|
-
9. format: '
|
|
22
|
-
10.
|
|
23
|
-
11. type: '
|
|
24
|
-
12. type: '
|
|
25
|
-
13.
|
|
20
|
+
8. oneOf with const/title (labeled options) -> FormSelect
|
|
21
|
+
9. format: 'multiline' -> FormTextarea
|
|
22
|
+
10. format: 'range' (number/integer) -> FormRangeField
|
|
23
|
+
11. type: 'string' -> FormTextField
|
|
24
|
+
12. type: 'number' or 'integer' -> FormNumberField
|
|
25
|
+
13. type: 'boolean' -> FormToggle
|
|
26
26
|
14. type: 'object' (without format) -> FormCodeEditor (for JSON objects)
|
|
27
27
|
15. fallback -> FormTextField
|
|
28
28
|
-->
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
import FormAutocomplete from './FormAutocomplete.svelte';
|
|
44
44
|
import type { FieldSchema } from './types.js';
|
|
45
45
|
import { getSchemaOptions } from './types.js';
|
|
46
|
+
import type { WorkflowNode, WorkflowEdge, AuthProvider } from '../../types/index.js';
|
|
46
47
|
|
|
47
48
|
interface Props {
|
|
48
49
|
/** Unique key/id for the field */
|
|
@@ -57,9 +58,31 @@
|
|
|
57
58
|
animationIndex?: number;
|
|
58
59
|
/** Callback when the field value changes */
|
|
59
60
|
onChange: (value: unknown) => void;
|
|
61
|
+
/** Current workflow node (optional, used for template variable API mode) */
|
|
62
|
+
node?: WorkflowNode;
|
|
63
|
+
/** All workflow nodes (optional, used for port-derived variables) */
|
|
64
|
+
nodes?: WorkflowNode[];
|
|
65
|
+
/** All workflow edges (optional, used for port-derived variables) */
|
|
66
|
+
edges?: WorkflowEdge[];
|
|
67
|
+
/** Workflow ID (optional, used for template variable API mode) */
|
|
68
|
+
workflowId?: string;
|
|
69
|
+
/** Auth provider (optional, used for API requests) */
|
|
70
|
+
authProvider?: AuthProvider;
|
|
60
71
|
}
|
|
61
72
|
|
|
62
|
-
let {
|
|
73
|
+
let {
|
|
74
|
+
fieldKey,
|
|
75
|
+
schema,
|
|
76
|
+
value,
|
|
77
|
+
required = false,
|
|
78
|
+
animationIndex = 0,
|
|
79
|
+
onChange,
|
|
80
|
+
node,
|
|
81
|
+
nodes,
|
|
82
|
+
edges,
|
|
83
|
+
workflowId,
|
|
84
|
+
authProvider
|
|
85
|
+
}: Props = $props();
|
|
63
86
|
|
|
64
87
|
/**
|
|
65
88
|
* When schema.readOnly is true, disable all inputs (no editing).
|
|
@@ -122,6 +145,12 @@
|
|
|
122
145
|
return 'select-enum';
|
|
123
146
|
}
|
|
124
147
|
|
|
148
|
+
// oneOf with labeled options (standard JSON Schema) or legacy options -> select
|
|
149
|
+
// Must be checked before basic type checks since oneOf schemas often have type: 'string'
|
|
150
|
+
if ((schema.oneOf && schema.oneOf.length > 0) || schema.options) {
|
|
151
|
+
return 'select-options';
|
|
152
|
+
}
|
|
153
|
+
|
|
125
154
|
// Multiline string -> textarea
|
|
126
155
|
if (schema.type === 'string' && schema.format === 'multiline') {
|
|
127
156
|
return 'textarea';
|
|
@@ -147,11 +176,6 @@
|
|
|
147
176
|
return 'toggle';
|
|
148
177
|
}
|
|
149
178
|
|
|
150
|
-
// oneOf with labeled options (standard JSON Schema) or legacy options -> select
|
|
151
|
-
if ((schema.oneOf && schema.oneOf.length > 0) || schema.options) {
|
|
152
|
-
return 'select-options';
|
|
153
|
-
}
|
|
154
|
-
|
|
155
179
|
// Future: Array type support
|
|
156
180
|
if (schema.type === 'array') {
|
|
157
181
|
return 'array';
|
|
@@ -350,11 +374,16 @@
|
|
|
350
374
|
{required}
|
|
351
375
|
height={(schema.height as string | undefined) ?? '250px'}
|
|
352
376
|
darkTheme={(schema.darkTheme as boolean | undefined) ?? false}
|
|
353
|
-
|
|
377
|
+
variables={schema.variables}
|
|
354
378
|
placeholderExample={(schema.placeholderExample as string | undefined) ??
|
|
355
379
|
'Hello {{ name }}, your order #{{ order_id }} is ready!'}
|
|
356
380
|
ariaDescribedBy={descriptionId}
|
|
357
381
|
disabled={isReadOnly}
|
|
382
|
+
{node}
|
|
383
|
+
{nodes}
|
|
384
|
+
{edges}
|
|
385
|
+
{workflowId}
|
|
386
|
+
{authProvider}
|
|
358
387
|
onChange={(val) => onChange(val)}
|
|
359
388
|
/>
|
|
360
389
|
{:else if fieldType === 'autocomplete' && schema.autocomplete}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { FieldSchema } from './types.js';
|
|
2
|
+
import type { WorkflowNode, WorkflowEdge, AuthProvider } from '../../types/index.js';
|
|
2
3
|
interface Props {
|
|
3
4
|
/** Unique key/id for the field */
|
|
4
5
|
fieldKey: string;
|
|
@@ -12,6 +13,16 @@ interface Props {
|
|
|
12
13
|
animationIndex?: number;
|
|
13
14
|
/** Callback when the field value changes */
|
|
14
15
|
onChange: (value: unknown) => void;
|
|
16
|
+
/** Current workflow node (optional, used for template variable API mode) */
|
|
17
|
+
node?: WorkflowNode;
|
|
18
|
+
/** All workflow nodes (optional, used for port-derived variables) */
|
|
19
|
+
nodes?: WorkflowNode[];
|
|
20
|
+
/** All workflow edges (optional, used for port-derived variables) */
|
|
21
|
+
edges?: WorkflowEdge[];
|
|
22
|
+
/** Workflow ID (optional, used for template variable API mode) */
|
|
23
|
+
workflowId?: string;
|
|
24
|
+
/** Auth provider (optional, used for API requests) */
|
|
25
|
+
authProvider?: AuthProvider;
|
|
15
26
|
}
|
|
16
27
|
declare const FormField: import("svelte").Component<Props, {}, "">;
|
|
17
28
|
type FormField = ReturnType<typeof FormField>;
|
|
@@ -22,12 +22,12 @@
|
|
|
22
22
|
2. format: 'hidden' -> skip rendering (return nothing)
|
|
23
23
|
3. enum with multiple: true -> FormCheckboxGroup
|
|
24
24
|
4. enum -> FormSelect (simple values without labels)
|
|
25
|
-
5.
|
|
26
|
-
6. format: '
|
|
27
|
-
7.
|
|
28
|
-
8. type: '
|
|
29
|
-
9. type: '
|
|
30
|
-
10.
|
|
25
|
+
5. oneOf with const/title (labeled options) -> FormSelect
|
|
26
|
+
6. format: 'multiline' -> FormTextarea
|
|
27
|
+
7. format: 'range' (number/integer) -> FormRangeField
|
|
28
|
+
8. type: 'string' -> FormTextField
|
|
29
|
+
9. type: 'number' or 'integer' -> FormNumberField
|
|
30
|
+
10. type: 'boolean' -> FormToggle
|
|
31
31
|
11. type: 'array' -> FormArray
|
|
32
32
|
12. fallback -> FormTextField
|
|
33
33
|
-->
|
|
@@ -43,6 +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/settingsStore.js';
|
|
46
47
|
import type { FieldSchema } from './types.js';
|
|
47
48
|
import { getSchemaOptions } from './types.js';
|
|
48
49
|
|
|
@@ -127,6 +128,12 @@
|
|
|
127
128
|
return 'select-enum';
|
|
128
129
|
}
|
|
129
130
|
|
|
131
|
+
// oneOf with labeled options (standard JSON Schema) or legacy options -> select
|
|
132
|
+
// Must be checked before basic type checks since oneOf schemas often have type: 'string'
|
|
133
|
+
if ((schema.oneOf && schema.oneOf.length > 0) || schema.options) {
|
|
134
|
+
return 'select-options';
|
|
135
|
+
}
|
|
136
|
+
|
|
130
137
|
// Multiline string -> textarea
|
|
131
138
|
if (schema.type === 'string' && schema.format === 'multiline') {
|
|
132
139
|
return 'textarea';
|
|
@@ -152,11 +159,6 @@
|
|
|
152
159
|
return 'toggle';
|
|
153
160
|
}
|
|
154
161
|
|
|
155
|
-
// oneOf with labeled options (standard JSON Schema) or legacy options -> select
|
|
156
|
-
if ((schema.oneOf && schema.oneOf.length > 0) || schema.options) {
|
|
157
|
-
return 'select-options';
|
|
158
|
-
}
|
|
159
|
-
|
|
160
162
|
// Array type
|
|
161
163
|
if (schema.type === 'array') {
|
|
162
164
|
return 'array';
|
|
@@ -226,6 +228,7 @@
|
|
|
226
228
|
>
|
|
227
229
|
{#if fieldType === 'registered' && registeredComponent}
|
|
228
230
|
<!-- Render registered custom component -->
|
|
231
|
+
<!-- darkTheme: use schema value if explicitly set, otherwise derive from resolved theme -->
|
|
229
232
|
<registeredComponent.component
|
|
230
233
|
id={fieldKey}
|
|
231
234
|
{value}
|
|
@@ -233,12 +236,12 @@
|
|
|
233
236
|
{required}
|
|
234
237
|
ariaDescribedBy={descriptionId}
|
|
235
238
|
height={schema.height as string | undefined}
|
|
236
|
-
darkTheme={schema.darkTheme
|
|
239
|
+
darkTheme={schema.darkTheme ?? $resolvedTheme === 'dark'}
|
|
237
240
|
autoFormat={schema.autoFormat as boolean | undefined}
|
|
238
241
|
showToolbar={schema.showToolbar as boolean | undefined}
|
|
239
242
|
showStatusBar={schema.showStatusBar as boolean | undefined}
|
|
240
243
|
spellChecker={schema.spellChecker as boolean | undefined}
|
|
241
|
-
|
|
244
|
+
variables={schema.variables}
|
|
242
245
|
placeholderExample={schema.placeholderExample as string | undefined}
|
|
243
246
|
onChange={(val: unknown) => onChange(val)}
|
|
244
247
|
/>
|