@d34dman/flowdrop 0.0.47 → 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.
@@ -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
 
@@ -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,13 +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,
25
26
  WorkflowEdge,
26
27
  NodeUIExtensions,
27
- ConfigEditOptions
28
+ ConfigEditOptions,
29
+ AuthProvider
28
30
  } from '../types/index.js';
29
31
  import { FormField, FormFieldWrapper, FormToggle } from './form/index.js';
30
32
  import type { FieldSchema } from './form/index.js';
@@ -61,6 +63,8 @@
61
63
  * When provided along with workflowNodes, enables autocomplete for template fields.
62
64
  */
63
65
  workflowEdges?: WorkflowEdge[];
66
+ /** Auth provider for API requests (used for template variable API mode) */
67
+ authProvider?: AuthProvider;
64
68
  /** Callback when any field value changes (fired on blur for immediate sync) */
65
69
  onChange?: (config: Record<string, unknown>, uiExtensions?: NodeUIExtensions) => void;
66
70
  /** Callback when form is saved (includes both config and extensions if enabled) */
@@ -78,11 +82,17 @@
78
82
  saveWorkflowWhenSavingConfig = false,
79
83
  workflowNodes = [],
80
84
  workflowEdges = [],
85
+ authProvider,
81
86
  onChange,
82
87
  onSave,
83
88
  onCancel
84
89
  }: Props = $props();
85
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
+
86
96
  /**
87
97
  * State for dynamic schema loading
88
98
  */
@@ -132,13 +142,14 @@
132
142
  });
133
143
 
134
144
  /**
135
- * Check if the node has no static schema and needs dynamic loading
145
+ * Check if the node needs dynamic schema loading
146
+ * Loads when: no static schema OR preferDynamicSchema is true
136
147
  */
137
148
  const needsDynamicSchemaLoad = $derived.by(() => {
138
149
  if (!node) return false;
139
150
  const staticSchema = schema ?? node.data.metadata?.configSchema;
140
- // Need to load if: no static schema AND dynamic schema is configured
141
- 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;
142
153
  });
143
154
 
144
155
  /**
@@ -537,6 +548,11 @@
537
548
  value={configValues[key]}
538
549
  {required}
539
550
  animationIndex={index}
551
+ {node}
552
+ nodes={workflowNodes}
553
+ edges={workflowEdges}
554
+ {workflowId}
555
+ {authProvider}
540
556
  onChange={(val) => handleFieldChange(key, val)}
541
557
  />
542
558
  {/each}
@@ -1,4 +1,4 @@
1
- import type { ConfigSchema, WorkflowNode, WorkflowEdge, 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;
@@ -22,6 +22,8 @@ interface Props {
22
22
  * When provided along with workflowNodes, enables autocomplete for template fields.
23
23
  */
24
24
  workflowEdges?: WorkflowEdge[];
25
+ /** Auth provider for API requests (used for template variable API mode) */
26
+ authProvider?: AuthProvider;
25
27
  /** Callback when any field value changes (fired on blur for immediate sync) */
26
28
  onChange?: (config: Record<string, unknown>, uiExtensions?: NodeUIExtensions) => void;
27
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
- setContext<AuthProvider | undefined>('flowdrop:authProvider', authProvider);
161
- setContext<string>('flowdrop:baseUrl', baseUrl);
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
@@ -59,9 +59,10 @@
59
59
  onChange
60
60
  }: Props = $props();
61
61
 
62
- // Get AuthProvider from context (set by SchemaForm or parent)
63
- const authProvider = getContext<AuthProvider | undefined>('flowdrop:authProvider');
64
- const baseUrl = getContext<string | undefined>('flowdrop:baseUrl') ?? '';
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);
@@ -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 { fieldKey, schema, value, required = false, animationIndex = 0, onChange }: Props = $props();
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).
@@ -352,11 +375,15 @@
352
375
  height={(schema.height as string | undefined) ?? '250px'}
353
376
  darkTheme={(schema.darkTheme as boolean | undefined) ?? false}
354
377
  variables={schema.variables}
355
- variableHints={(schema.variableHints as string[] | undefined) ?? []}
356
378
  placeholderExample={(schema.placeholderExample as string | undefined) ??
357
379
  'Hello {{ name }}, your order #{{ order_id }} is ready!'}
358
380
  ariaDescribedBy={descriptionId}
359
381
  disabled={isReadOnly}
382
+ {node}
383
+ {nodes}
384
+ {edges}
385
+ {workflowId}
386
+ {authProvider}
360
387
  onChange={(val) => onChange(val)}
361
388
  />
362
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>;
@@ -242,7 +242,6 @@
242
242
  showStatusBar={schema.showStatusBar as boolean | undefined}
243
243
  spellChecker={schema.spellChecker as boolean | undefined}
244
244
  variables={schema.variables}
245
- variableHints={schema.variableHints as string[] | undefined}
246
245
  placeholderExample={schema.placeholderExample as string | undefined}
247
246
  onChange={(val: unknown) => onChange(val)}
248
247
  />
@@ -33,15 +33,19 @@
33
33
  type ViewUpdate,
34
34
  MatchDecorator
35
35
  } from '@codemirror/view';
36
- import { EditorState } from '@codemirror/state';
36
+ import { EditorState, Compartment } from '@codemirror/state';
37
37
  import { history, historyKeymap, defaultKeymap, indentWithTab } from '@codemirror/commands';
38
38
  import { syntaxHighlighting, defaultHighlightStyle, indentOnInput } from '@codemirror/language';
39
39
  import { oneDark } from '@codemirror/theme-one-dark';
40
- import type { VariableSchema, TemplateVariablesConfig } from '../../types/index.js';
41
- import {
42
- createTemplateAutocomplete,
43
- createSimpleTemplateAutocomplete
44
- } from './templateAutocomplete.js';
40
+ import type {
41
+ VariableSchema,
42
+ TemplateVariablesConfig,
43
+ WorkflowNode,
44
+ WorkflowEdge,
45
+ AuthProvider
46
+ } from '../../types/index.js';
47
+ import { createTemplateAutocomplete } from './templateAutocomplete.js';
48
+ import { getVariableSchema } from '../../services/variableService.js';
45
49
 
46
50
  interface Props {
47
51
  /** Field identifier */
@@ -67,12 +71,6 @@
67
71
  * @deprecated Use `variables.schema` instead
68
72
  */
69
73
  variableSchema?: VariableSchema;
70
- /**
71
- * Simple variable names for basic hints (backward compatible).
72
- * Used when variableSchema is not provided.
73
- * @deprecated Use `variables.schema` instead
74
- */
75
- variableHints?: string[];
76
74
  /** Placeholder variable example for the hint */
77
75
  placeholderExample?: string;
78
76
  /** Whether the field is disabled (read-only) */
@@ -81,6 +79,16 @@
81
79
  ariaDescribedBy?: string;
82
80
  /** Callback when value changes */
83
81
  onChange: (value: string) => void;
82
+ /** Current workflow node (required for API mode) */
83
+ node?: WorkflowNode;
84
+ /** All workflow nodes (required for port-derived variables) */
85
+ nodes?: WorkflowNode[];
86
+ /** All workflow edges (required for port-derived variables) */
87
+ edges?: WorkflowEdge[];
88
+ /** Workflow ID (required for API mode) */
89
+ workflowId?: string;
90
+ /** Auth provider for API requests */
91
+ authProvider?: AuthProvider;
84
92
  }
85
93
 
86
94
  let {
@@ -92,26 +100,83 @@
92
100
  height = '250px',
93
101
  variables,
94
102
  variableSchema,
95
- variableHints = [],
96
103
  placeholderExample = 'Hello {{ name }}, your order #{{ order_id }} is ready!',
97
104
  disabled = false,
98
105
  ariaDescribedBy,
99
- onChange
106
+ onChange,
107
+ node,
108
+ nodes = [],
109
+ edges = [],
110
+ workflowId,
111
+ authProvider
100
112
  }: Props = $props();
101
113
 
114
+ /** Loading state for API variable fetching */
115
+ let isLoadingVariables = $state(false);
116
+
117
+ /** Error state for API variable fetching */
118
+ let variableLoadError = $state<string | null>(null);
119
+
120
+ /** The effective variable schema (loaded synchronously or asynchronously) */
121
+ let effectiveVariableSchema = $state<VariableSchema | undefined>(undefined);
122
+
102
123
  /**
103
- * Get the effective variable schema.
104
- * Prefers variables.schema, falls back to deprecated variableSchema prop.
124
+ * Load variable schema on mount or when configuration changes.
125
+ * Handles both synchronous (schema-based) and asynchronous (API-based) loading.
105
126
  */
106
- const effectiveVariableSchema = $derived.by<VariableSchema | undefined>(() => {
107
- if (variables?.schema && Object.keys(variables.schema.variables).length > 0) {
108
- return variables.schema;
109
- }
127
+ async function loadVariableSchema() {
128
+ // Reset error state
129
+ variableLoadError = null;
130
+
131
+ // If we have deprecated variableSchema prop, use it directly
110
132
  if (variableSchema && Object.keys(variableSchema.variables).length > 0) {
111
- return variableSchema;
133
+ effectiveVariableSchema = variableSchema;
134
+ return;
135
+ }
136
+
137
+ // If no variables config, clear schema
138
+ if (!variables) {
139
+ effectiveVariableSchema = undefined;
140
+ return;
141
+ }
142
+
143
+ // If variables config has static schema only (no API), use it directly
144
+ if (variables.schema && !variables.api && Object.keys(variables.schema.variables).length > 0) {
145
+ effectiveVariableSchema = variables.schema;
146
+ return;
112
147
  }
113
- return undefined;
114
- });
148
+
149
+ // If variables config requires node context (ports or API mode)
150
+ if ((variables.ports !== undefined || variables.api) && node && nodes && edges) {
151
+ try {
152
+ isLoadingVariables = true;
153
+ effectiveVariableSchema = await getVariableSchema(
154
+ node,
155
+ nodes,
156
+ edges,
157
+ variables,
158
+ workflowId,
159
+ authProvider
160
+ );
161
+ } catch (error) {
162
+ console.error('Failed to load variable schema:', error);
163
+ variableLoadError = error instanceof Error ? error.message : 'Failed to load variables';
164
+ effectiveVariableSchema = undefined;
165
+ } finally {
166
+ isLoadingVariables = false;
167
+ }
168
+ } else {
169
+ // No schema available
170
+ effectiveVariableSchema = undefined;
171
+ }
172
+ }
173
+
174
+ /**
175
+ * Retry loading variables after an error
176
+ */
177
+ function retryLoadVariables() {
178
+ loadVariableSchema();
179
+ }
115
180
 
116
181
  /**
117
182
  * Whether to show the variable hints section.
@@ -121,13 +186,12 @@
121
186
 
122
187
  /**
123
188
  * Derive the list of top-level variable names for the hints display.
124
- * Prefers effectiveVariableSchema if available, falls back to variableHints.
125
189
  */
126
190
  const displayVariables = $derived.by(() => {
127
191
  if (effectiveVariableSchema) {
128
192
  return Object.keys(effectiveVariableSchema.variables);
129
193
  }
130
- return variableHints;
194
+ return [];
131
195
  });
132
196
 
133
197
  /** Reference to the container element */
@@ -139,6 +203,9 @@
139
203
  /** Flag to prevent update loops */
140
204
  let isInternalUpdate = false;
141
205
 
206
+ /** Compartment for dynamic autocomplete reconfiguration */
207
+ const autocompleteCompartment = new Compartment();
208
+
142
209
  /**
143
210
  * Create a MatchDecorator for {{ variable }} patterns
144
211
  * This highlights the entire {{ variable }} expression
@@ -285,15 +352,12 @@
285
352
  EditorState.tabSize.of(2)
286
353
  ];
287
354
 
288
- // Add autocomplete extension when variables are available (and not disabled)
289
- if (!disabled) {
290
- if (effectiveVariableSchema) {
291
- // Use full autocomplete with nested drilling
292
- extensions.push(createTemplateAutocomplete(effectiveVariableSchema));
293
- } else if (variableHints.length > 0) {
294
- // Fallback to simple autocomplete with just variable names
295
- extensions.push(createSimpleTemplateAutocomplete(variableHints));
296
- }
355
+ // Add autocomplete compartment (can be reconfigured dynamically)
356
+ // When disabled or no schema, use empty array
357
+ if (!disabled && effectiveVariableSchema) {
358
+ extensions.push(autocompleteCompartment.of(createTemplateAutocomplete(effectiveVariableSchema)));
359
+ } else {
360
+ extensions.push(autocompleteCompartment.of([]));
297
361
  }
298
362
 
299
363
  if (darkTheme) {
@@ -341,19 +405,23 @@
341
405
  }
342
406
 
343
407
  /**
344
- * Initialize CodeMirror editor on mount
408
+ * Initialize CodeMirror editor and load variables on mount
345
409
  */
346
410
  onMount(() => {
347
411
  if (!containerRef) {
348
412
  return;
349
413
  }
350
414
 
351
- editorView = new EditorView({
352
- state: EditorState.create({
353
- doc: value,
354
- extensions: createExtensions()
355
- }),
356
- parent: containerRef
415
+ // Load variables first
416
+ loadVariableSchema().then(() => {
417
+ // Then create editor with loaded schema
418
+ editorView = new EditorView({
419
+ state: EditorState.create({
420
+ doc: value,
421
+ extensions: createExtensions()
422
+ }),
423
+ parent: containerRef
424
+ });
357
425
  });
358
426
  });
359
427
 
@@ -389,6 +457,28 @@
389
457
  isInternalUpdate = false;
390
458
  }
391
459
  });
460
+
461
+ /**
462
+ * Reconfigure editor when variable schema changes (e.g., after async loading)
463
+ */
464
+ $effect(() => {
465
+ // Only track effectiveVariableSchema changes
466
+ const schema = effectiveVariableSchema;
467
+
468
+ if (!editorView) {
469
+ return;
470
+ }
471
+
472
+ // When effectiveVariableSchema changes, reconfigure the autocomplete compartment
473
+ // This happens after async API loading completes
474
+ const newAutocomplete = !disabled && schema
475
+ ? createTemplateAutocomplete(schema)
476
+ : [];
477
+
478
+ editorView.dispatch({
479
+ effects: [autocompleteCompartment.reconfigure(newAutocomplete)]
480
+ });
481
+ });
392
482
  </script>
393
483
 
394
484
  <div class="form-template-editor">
@@ -412,6 +502,60 @@
412
502
  aria-label="Template editor"
413
503
  ></div>
414
504
 
505
+ <!-- Loading banner (shown while fetching variables from API) -->
506
+ {#if isLoadingVariables}
507
+ <div class="form-template-editor__banner form-template-editor__banner--loading">
508
+ <svg
509
+ class="form-template-editor__banner-icon form-template-editor__banner-icon--spin"
510
+ xmlns="http://www.w3.org/2000/svg"
511
+ fill="none"
512
+ viewBox="0 0 24 24"
513
+ >
514
+ <circle
515
+ class="opacity-25"
516
+ cx="12"
517
+ cy="12"
518
+ r="10"
519
+ stroke="currentColor"
520
+ stroke-width="4"
521
+ ></circle>
522
+ <path
523
+ class="opacity-75"
524
+ fill="currentColor"
525
+ d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
526
+ ></path>
527
+ </svg>
528
+ <span>Loading variables...</span>
529
+ </div>
530
+ {/if}
531
+
532
+ <!-- Error banner (shown when API fetch fails) -->
533
+ {#if variableLoadError}
534
+ <div class="form-template-editor__banner form-template-editor__banner--error">
535
+ <svg
536
+ class="form-template-editor__banner-icon"
537
+ xmlns="http://www.w3.org/2000/svg"
538
+ viewBox="0 0 20 20"
539
+ fill="currentColor"
540
+ >
541
+ <path
542
+ fill-rule="evenodd"
543
+ d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-8-5a.75.75 0 01.75.75v4.5a.75.75 0 01-1.5 0v-4.5A.75.75 0 0110 5zm0 10a1 1 0 100-2 1 1 0 000 2z"
544
+ clip-rule="evenodd"
545
+ />
546
+ </svg>
547
+ <span>{variableLoadError}</span>
548
+ <button
549
+ type="button"
550
+ class="form-template-editor__banner-btn"
551
+ onclick={retryLoadVariables}
552
+ title="Retry loading variables"
553
+ >
554
+ Retry
555
+ </button>
556
+ </div>
557
+ {/if}
558
+
415
559
  <!-- Variable hints section (shown when variables are available and showHints is true) -->
416
560
  {#if showHints && displayVariables.length > 0}
417
561
  <div class="form-template-editor__hints">
@@ -613,4 +757,68 @@
613
757
  font-family: 'JetBrains Mono', 'Fira Code', 'Monaco', 'Menlo', monospace;
614
758
  font-size: 0.625rem;
615
759
  }
760
+
761
+ /* Loading and error banners */
762
+ .form-template-editor__banner {
763
+ display: flex;
764
+ align-items: center;
765
+ gap: 0.5rem;
766
+ margin-top: 0.625rem;
767
+ padding: 0.625rem 0.75rem;
768
+ border-radius: var(--fd-radius-md);
769
+ font-size: 0.75rem;
770
+ }
771
+
772
+ .form-template-editor__banner--loading {
773
+ background-color: rgba(59, 130, 246, 0.1);
774
+ border: 1px solid rgba(59, 130, 246, 0.3);
775
+ color: rgb(29, 78, 216);
776
+ }
777
+
778
+ .form-template-editor__banner--error {
779
+ background-color: rgba(239, 68, 68, 0.1);
780
+ border: 1px solid rgba(239, 68, 68, 0.3);
781
+ color: rgb(185, 28, 28);
782
+ }
783
+
784
+ .form-template-editor__banner-icon {
785
+ width: 1rem;
786
+ height: 1rem;
787
+ flex-shrink: 0;
788
+ }
789
+
790
+ .form-template-editor__banner-icon--spin {
791
+ animation: spin 1s linear infinite;
792
+ }
793
+
794
+ @keyframes spin {
795
+ from {
796
+ transform: rotate(0deg);
797
+ }
798
+ to {
799
+ transform: rotate(360deg);
800
+ }
801
+ }
802
+
803
+ .form-template-editor__banner-btn {
804
+ margin-left: auto;
805
+ padding: 0.25rem 0.625rem;
806
+ background-color: rgba(239, 68, 68, 0.15);
807
+ border: 1px solid rgba(239, 68, 68, 0.3);
808
+ border-radius: var(--fd-radius-sm);
809
+ font-size: 0.6875rem;
810
+ font-weight: 500;
811
+ color: rgb(185, 28, 28);
812
+ cursor: pointer;
813
+ transition: all var(--fd-transition-fast);
814
+ }
815
+
816
+ .form-template-editor__banner-btn:hover {
817
+ background-color: rgba(239, 68, 68, 0.25);
818
+ border-color: rgba(239, 68, 68, 0.5);
819
+ }
820
+
821
+ .form-template-editor__banner-btn:active {
822
+ transform: scale(0.98);
823
+ }
616
824
  </style>
@@ -1,4 +1,4 @@
1
- import type { VariableSchema, TemplateVariablesConfig } from '../../types/index.js';
1
+ import type { VariableSchema, TemplateVariablesConfig, WorkflowNode, WorkflowEdge, AuthProvider } from '../../types/index.js';
2
2
  interface Props {
3
3
  /** Field identifier */
4
4
  id: string;
@@ -23,12 +23,6 @@ interface Props {
23
23
  * @deprecated Use `variables.schema` instead
24
24
  */
25
25
  variableSchema?: VariableSchema;
26
- /**
27
- * Simple variable names for basic hints (backward compatible).
28
- * Used when variableSchema is not provided.
29
- * @deprecated Use `variables.schema` instead
30
- */
31
- variableHints?: string[];
32
26
  /** Placeholder variable example for the hint */
33
27
  placeholderExample?: string;
34
28
  /** Whether the field is disabled (read-only) */
@@ -37,6 +31,16 @@ interface Props {
37
31
  ariaDescribedBy?: string;
38
32
  /** Callback when value changes */
39
33
  onChange: (value: string) => void;
34
+ /** Current workflow node (required for API mode) */
35
+ node?: WorkflowNode;
36
+ /** All workflow nodes (required for port-derived variables) */
37
+ nodes?: WorkflowNode[];
38
+ /** All workflow edges (required for port-derived variables) */
39
+ edges?: WorkflowEdge[];
40
+ /** Workflow ID (required for API mode) */
41
+ workflowId?: string;
42
+ /** Auth provider for API requests */
43
+ authProvider?: AuthProvider;
40
44
  }
41
45
  declare const FormTemplateEditor: import("svelte").Component<Props, {}, "">;
42
46
  type FormTemplateEditor = ReturnType<typeof FormTemplateEditor>;
@@ -44,4 +44,4 @@ export { default as FormCodeEditor } from './FormCodeEditor.svelte';
44
44
  export { default as FormMarkdownEditor } from './FormMarkdownEditor.svelte';
45
45
  export { default as FormTemplateEditor } from './FormTemplateEditor.svelte';
46
46
  export { default as FormAutocomplete } from './FormAutocomplete.svelte';
47
- export { createTemplateAutocomplete, createSimpleTemplateAutocomplete } from './templateAutocomplete.js';
47
+ export { createTemplateAutocomplete } from './templateAutocomplete.js';