@d34dman/flowdrop 0.0.47 → 0.0.49
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 +11 -0
- package/dist/components/App.svelte.d.ts +2 -0
- package/dist/components/ConfigForm.svelte +31 -5
- package/dist/components/ConfigForm.svelte.d.ts +3 -1
- package/dist/components/NodeSidebar.svelte +1 -0
- package/dist/components/SchemaForm.svelte +4 -2
- package/dist/components/SettingsPanel.svelte +3 -3
- package/dist/components/form/FormAutocomplete.svelte +9 -4
- package/dist/components/form/FormCodeEditor.svelte +17 -15
- package/dist/components/form/FormField.svelte +32 -4
- package/dist/components/form/FormField.svelte.d.ts +11 -0
- package/dist/components/form/FormFieldLight.svelte +0 -1
- package/dist/components/form/FormTemplateEditor.svelte +300 -79
- package/dist/components/form/FormTemplateEditor.svelte.d.ts +11 -7
- package/dist/components/form/index.d.ts +1 -1
- package/dist/components/form/index.js +1 -1
- package/dist/components/form/templateAutocomplete.d.ts +2 -11
- package/dist/components/form/templateAutocomplete.js +49 -104
- package/dist/components/form/types.d.ts +0 -6
- package/dist/components/nodes/TerminalNode.svelte +27 -15
- package/dist/components/nodes/ToolNode.svelte +4 -6
- package/dist/services/apiVariableService.d.ts +116 -0
- package/dist/services/apiVariableService.js +338 -0
- package/dist/services/globalSave.js +6 -0
- package/dist/services/variableService.d.ts +50 -9
- package/dist/services/variableService.js +139 -44
- package/dist/svelte-app.d.ts +5 -0
- package/dist/svelte-app.js +7 -1
- package/dist/types/index.d.ts +138 -1
- package/dist/types/settings.js +4 -4
- package/dist/utils/colors.js +1 -0
- package/dist/utils/handlePositioning.d.ts +31 -0
- package/dist/utils/handlePositioning.js +35 -0
- package/dist/utils/icons.js +1 -0
- package/dist/utils/nodeTypes.js +3 -3
- package/package.json +8 -4
|
@@ -27,21 +27,24 @@
|
|
|
27
27
|
highlightSpecialChars,
|
|
28
28
|
highlightActiveLine,
|
|
29
29
|
keymap,
|
|
30
|
+
tooltips,
|
|
30
31
|
Decoration,
|
|
31
|
-
type DecorationSet,
|
|
32
32
|
ViewPlugin,
|
|
33
|
-
type ViewUpdate,
|
|
34
33
|
MatchDecorator
|
|
35
34
|
} from '@codemirror/view';
|
|
36
|
-
import { EditorState } from '@codemirror/state';
|
|
35
|
+
import { EditorState, Compartment } from '@codemirror/state';
|
|
37
36
|
import { history, historyKeymap, defaultKeymap, indentWithTab } from '@codemirror/commands';
|
|
38
|
-
import { syntaxHighlighting, defaultHighlightStyle
|
|
37
|
+
import { syntaxHighlighting, defaultHighlightStyle } from '@codemirror/language';
|
|
39
38
|
import { oneDark } from '@codemirror/theme-one-dark';
|
|
40
|
-
import type {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
import type {
|
|
40
|
+
VariableSchema,
|
|
41
|
+
TemplateVariablesConfig,
|
|
42
|
+
WorkflowNode,
|
|
43
|
+
WorkflowEdge,
|
|
44
|
+
AuthProvider
|
|
45
|
+
} from '../../types/index.js';
|
|
46
|
+
import { createTemplateAutocomplete } from './templateAutocomplete.js';
|
|
47
|
+
import { getVariableSchema } from '../../services/variableService.js';
|
|
45
48
|
|
|
46
49
|
interface Props {
|
|
47
50
|
/** Field identifier */
|
|
@@ -67,12 +70,6 @@
|
|
|
67
70
|
* @deprecated Use `variables.schema` instead
|
|
68
71
|
*/
|
|
69
72
|
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
73
|
/** Placeholder variable example for the hint */
|
|
77
74
|
placeholderExample?: string;
|
|
78
75
|
/** Whether the field is disabled (read-only) */
|
|
@@ -81,6 +78,16 @@
|
|
|
81
78
|
ariaDescribedBy?: string;
|
|
82
79
|
/** Callback when value changes */
|
|
83
80
|
onChange: (value: string) => void;
|
|
81
|
+
/** Current workflow node (required for API mode) */
|
|
82
|
+
node?: WorkflowNode;
|
|
83
|
+
/** All workflow nodes (required for port-derived variables) */
|
|
84
|
+
nodes?: WorkflowNode[];
|
|
85
|
+
/** All workflow edges (required for port-derived variables) */
|
|
86
|
+
edges?: WorkflowEdge[];
|
|
87
|
+
/** Workflow ID (required for API mode) */
|
|
88
|
+
workflowId?: string;
|
|
89
|
+
/** Auth provider for API requests */
|
|
90
|
+
authProvider?: AuthProvider;
|
|
84
91
|
}
|
|
85
92
|
|
|
86
93
|
let {
|
|
@@ -92,26 +99,83 @@
|
|
|
92
99
|
height = '250px',
|
|
93
100
|
variables,
|
|
94
101
|
variableSchema,
|
|
95
|
-
variableHints = [],
|
|
96
102
|
placeholderExample = 'Hello {{ name }}, your order #{{ order_id }} is ready!',
|
|
97
103
|
disabled = false,
|
|
98
104
|
ariaDescribedBy,
|
|
99
|
-
onChange
|
|
105
|
+
onChange,
|
|
106
|
+
node,
|
|
107
|
+
nodes = [],
|
|
108
|
+
edges = [],
|
|
109
|
+
workflowId,
|
|
110
|
+
authProvider
|
|
100
111
|
}: Props = $props();
|
|
101
112
|
|
|
113
|
+
/** Loading state for API variable fetching */
|
|
114
|
+
let isLoadingVariables = $state(false);
|
|
115
|
+
|
|
116
|
+
/** Error state for API variable fetching */
|
|
117
|
+
let variableLoadError = $state<string | null>(null);
|
|
118
|
+
|
|
119
|
+
/** The effective variable schema (loaded synchronously or asynchronously) */
|
|
120
|
+
let effectiveVariableSchema = $state<VariableSchema | undefined>(undefined);
|
|
121
|
+
|
|
102
122
|
/**
|
|
103
|
-
*
|
|
104
|
-
*
|
|
123
|
+
* Load variable schema on mount or when configuration changes.
|
|
124
|
+
* Handles both synchronous (schema-based) and asynchronous (API-based) loading.
|
|
105
125
|
*/
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
126
|
+
async function loadVariableSchema() {
|
|
127
|
+
// Reset error state
|
|
128
|
+
variableLoadError = null;
|
|
129
|
+
|
|
130
|
+
// If we have deprecated variableSchema prop, use it directly
|
|
110
131
|
if (variableSchema && Object.keys(variableSchema.variables).length > 0) {
|
|
111
|
-
|
|
132
|
+
effectiveVariableSchema = variableSchema;
|
|
133
|
+
return;
|
|
112
134
|
}
|
|
113
|
-
|
|
114
|
-
|
|
135
|
+
|
|
136
|
+
// If no variables config, clear schema
|
|
137
|
+
if (!variables) {
|
|
138
|
+
effectiveVariableSchema = undefined;
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// If variables config has static schema only (no API), use it directly
|
|
143
|
+
if (variables.schema && !variables.api && Object.keys(variables.schema.variables).length > 0) {
|
|
144
|
+
effectiveVariableSchema = variables.schema;
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// If variables config requires node context (ports or API mode)
|
|
149
|
+
if ((variables.ports !== undefined || variables.api) && node && nodes && edges) {
|
|
150
|
+
try {
|
|
151
|
+
isLoadingVariables = true;
|
|
152
|
+
effectiveVariableSchema = await getVariableSchema(
|
|
153
|
+
node,
|
|
154
|
+
nodes,
|
|
155
|
+
edges,
|
|
156
|
+
variables,
|
|
157
|
+
workflowId,
|
|
158
|
+
authProvider
|
|
159
|
+
);
|
|
160
|
+
} catch (error) {
|
|
161
|
+
console.error('Failed to load variable schema:', error);
|
|
162
|
+
variableLoadError = error instanceof Error ? error.message : 'Failed to load variables';
|
|
163
|
+
effectiveVariableSchema = undefined;
|
|
164
|
+
} finally {
|
|
165
|
+
isLoadingVariables = false;
|
|
166
|
+
}
|
|
167
|
+
} else {
|
|
168
|
+
// No schema available
|
|
169
|
+
effectiveVariableSchema = undefined;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Retry loading variables after an error
|
|
175
|
+
*/
|
|
176
|
+
function retryLoadVariables() {
|
|
177
|
+
loadVariableSchema();
|
|
178
|
+
}
|
|
115
179
|
|
|
116
180
|
/**
|
|
117
181
|
* Whether to show the variable hints section.
|
|
@@ -121,13 +185,12 @@
|
|
|
121
185
|
|
|
122
186
|
/**
|
|
123
187
|
* Derive the list of top-level variable names for the hints display.
|
|
124
|
-
* Prefers effectiveVariableSchema if available, falls back to variableHints.
|
|
125
188
|
*/
|
|
126
189
|
const displayVariables = $derived.by(() => {
|
|
127
190
|
if (effectiveVariableSchema) {
|
|
128
191
|
return Object.keys(effectiveVariableSchema.variables);
|
|
129
192
|
}
|
|
130
|
-
return
|
|
193
|
+
return [];
|
|
131
194
|
});
|
|
132
195
|
|
|
133
196
|
/** Reference to the container element */
|
|
@@ -139,37 +202,41 @@
|
|
|
139
202
|
/** Flag to prevent update loops */
|
|
140
203
|
let isInternalUpdate = false;
|
|
141
204
|
|
|
205
|
+
/** Compartment for dynamic autocomplete reconfiguration */
|
|
206
|
+
const autocompleteCompartment = new Compartment();
|
|
207
|
+
|
|
142
208
|
/**
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
* -
|
|
147
|
-
* -
|
|
148
|
-
* - Array access: {{ items[0] }}, {{ items[0].name }}
|
|
149
|
-
* - Mixed: {{ orders[0].items[1].price }}
|
|
209
|
+
* Custom Twig syntax highlighter using MatchDecorator
|
|
210
|
+
* Highlights three Twig delimiter types with different styles:
|
|
211
|
+
* - {{ expression }} — variables/output (purple)
|
|
212
|
+
* - {% block %} — control structures (teal)
|
|
213
|
+
* - {# comment #} — comments (gray/italic)
|
|
150
214
|
*/
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
215
|
+
const twigMatcher = new MatchDecorator({
|
|
216
|
+
regexp: /\{\{.*?\}\}|\{%.*?%\}|\{#.*?#\}/g,
|
|
217
|
+
decoration: (match) => {
|
|
218
|
+
const text = match[0];
|
|
219
|
+
if (text.startsWith('{{')) {
|
|
220
|
+
return Decoration.mark({ class: 'cm-twig-expression' });
|
|
221
|
+
} else if (text.startsWith('{%')) {
|
|
222
|
+
return Decoration.mark({ class: 'cm-twig-block' });
|
|
223
|
+
} else {
|
|
224
|
+
return Decoration.mark({ class: 'cm-twig-comment' });
|
|
225
|
+
}
|
|
226
|
+
}
|
|
155
227
|
});
|
|
156
228
|
|
|
157
|
-
|
|
158
|
-
* ViewPlugin that applies the variable highlighting decorations
|
|
159
|
-
*/
|
|
160
|
-
const variableHighlighter = ViewPlugin.fromClass(
|
|
229
|
+
const twigHighlighter = ViewPlugin.fromClass(
|
|
161
230
|
class {
|
|
162
|
-
decorations
|
|
231
|
+
decorations;
|
|
163
232
|
constructor(view: EditorView) {
|
|
164
|
-
this.decorations =
|
|
233
|
+
this.decorations = twigMatcher.createDeco(view);
|
|
165
234
|
}
|
|
166
|
-
update(update: ViewUpdate) {
|
|
167
|
-
this.decorations =
|
|
235
|
+
update(update: import('@codemirror/view').ViewUpdate) {
|
|
236
|
+
this.decorations = twigMatcher.updateDeco(update, this.decorations);
|
|
168
237
|
}
|
|
169
238
|
},
|
|
170
|
-
{
|
|
171
|
-
decorations: (v) => v.decorations
|
|
172
|
-
}
|
|
239
|
+
{ decorations: (v) => v.decorations }
|
|
173
240
|
);
|
|
174
241
|
|
|
175
242
|
/**
|
|
@@ -191,6 +258,9 @@
|
|
|
191
258
|
*/
|
|
192
259
|
function createExtensions() {
|
|
193
260
|
const extensions = [
|
|
261
|
+
// Position tooltips using fixed strategy so they aren't clipped by container overflow
|
|
262
|
+
tooltips({ position: 'fixed' }),
|
|
263
|
+
|
|
194
264
|
// Essential visual features
|
|
195
265
|
lineNumbers(),
|
|
196
266
|
highlightActiveLineGutter(),
|
|
@@ -201,20 +271,16 @@
|
|
|
201
271
|
// Editing features (skip when read-only)
|
|
202
272
|
...(disabled
|
|
203
273
|
? []
|
|
204
|
-
: [
|
|
205
|
-
history(),
|
|
206
|
-
indentOnInput(),
|
|
207
|
-
keymap.of([...defaultKeymap, ...historyKeymap, indentWithTab])
|
|
208
|
-
]),
|
|
274
|
+
: [history(), keymap.of([...defaultKeymap, ...historyKeymap, indentWithTab])]),
|
|
209
275
|
|
|
210
276
|
// Read-only: prevent document changes and mark content as non-editable
|
|
211
277
|
...(disabled ? [EditorState.readOnly.of(true), EditorView.editable.of(false)] : []),
|
|
212
278
|
|
|
213
|
-
// Syntax highlighting
|
|
214
|
-
syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
|
|
279
|
+
// Syntax highlighting - use default for light mode, oneDark handles dark mode
|
|
280
|
+
...(darkTheme ? [] : [syntaxHighlighting(defaultHighlightStyle, { fallback: true })]),
|
|
215
281
|
|
|
216
|
-
//
|
|
217
|
-
|
|
282
|
+
// Twig syntax highlighting ({{ expressions }}, {% blocks %}, {# comments #})
|
|
283
|
+
twigHighlighter,
|
|
218
284
|
|
|
219
285
|
// Update listener (only fires on user edit when not disabled)
|
|
220
286
|
EditorView.updateListener.of(handleUpdate),
|
|
@@ -239,14 +305,27 @@
|
|
|
239
305
|
'.cm-line': {
|
|
240
306
|
padding: '0 0.5rem'
|
|
241
307
|
},
|
|
242
|
-
//
|
|
243
|
-
'.cm-
|
|
308
|
+
// Twig expression: {{ variable }}
|
|
309
|
+
'.cm-twig-expression': {
|
|
244
310
|
color: '#a855f7',
|
|
245
311
|
backgroundColor: 'rgba(168, 85, 247, 0.1)',
|
|
246
312
|
borderRadius: '3px',
|
|
247
313
|
padding: '1px 2px',
|
|
248
314
|
fontWeight: '500'
|
|
249
315
|
},
|
|
316
|
+
// Twig block: {% for ... %}
|
|
317
|
+
'.cm-twig-block': {
|
|
318
|
+
color: '#14b8a6',
|
|
319
|
+
backgroundColor: 'rgba(20, 184, 166, 0.1)',
|
|
320
|
+
borderRadius: '3px',
|
|
321
|
+
padding: '1px 2px',
|
|
322
|
+
fontWeight: '500'
|
|
323
|
+
},
|
|
324
|
+
// Twig comment: {# ... #}
|
|
325
|
+
'.cm-twig-comment': {
|
|
326
|
+
color: '#6b7280',
|
|
327
|
+
fontStyle: 'italic'
|
|
328
|
+
},
|
|
250
329
|
// Autocomplete dropdown styling
|
|
251
330
|
'.cm-tooltip.cm-tooltip-autocomplete': {
|
|
252
331
|
backgroundColor: 'var(--fd-background, #ffffff)',
|
|
@@ -285,26 +364,32 @@
|
|
|
285
364
|
EditorState.tabSize.of(2)
|
|
286
365
|
];
|
|
287
366
|
|
|
288
|
-
// Add autocomplete
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
}
|
|
367
|
+
// Add autocomplete compartment (can be reconfigured dynamically)
|
|
368
|
+
// When disabled or no schema, use empty array
|
|
369
|
+
if (!disabled && effectiveVariableSchema) {
|
|
370
|
+
extensions.push(
|
|
371
|
+
autocompleteCompartment.of(createTemplateAutocomplete(effectiveVariableSchema))
|
|
372
|
+
);
|
|
373
|
+
} else {
|
|
374
|
+
extensions.push(autocompleteCompartment.of([]));
|
|
297
375
|
}
|
|
298
376
|
|
|
299
377
|
if (darkTheme) {
|
|
300
378
|
extensions.push(oneDark);
|
|
301
|
-
// Add dark theme
|
|
379
|
+
// Add dark theme overrides for Twig highlighting and autocomplete
|
|
302
380
|
extensions.push(
|
|
303
381
|
EditorView.theme({
|
|
304
|
-
'.cm-
|
|
382
|
+
'.cm-twig-expression': {
|
|
305
383
|
color: '#c084fc',
|
|
306
384
|
backgroundColor: 'rgba(192, 132, 252, 0.15)'
|
|
307
385
|
},
|
|
386
|
+
'.cm-twig-block': {
|
|
387
|
+
color: '#5eead4',
|
|
388
|
+
backgroundColor: 'rgba(94, 234, 212, 0.1)'
|
|
389
|
+
},
|
|
390
|
+
'.cm-twig-comment': {
|
|
391
|
+
color: '#6b7280'
|
|
392
|
+
},
|
|
308
393
|
'.cm-tooltip.cm-tooltip-autocomplete': {
|
|
309
394
|
backgroundColor: '#1e1e1e',
|
|
310
395
|
border: '1px solid #3e4451',
|
|
@@ -341,19 +426,23 @@
|
|
|
341
426
|
}
|
|
342
427
|
|
|
343
428
|
/**
|
|
344
|
-
* Initialize CodeMirror editor on mount
|
|
429
|
+
* Initialize CodeMirror editor and load variables on mount
|
|
345
430
|
*/
|
|
346
431
|
onMount(() => {
|
|
347
432
|
if (!containerRef) {
|
|
348
433
|
return;
|
|
349
434
|
}
|
|
350
435
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
436
|
+
// Load variables first
|
|
437
|
+
loadVariableSchema().then(() => {
|
|
438
|
+
// Then create editor with loaded schema
|
|
439
|
+
editorView = new EditorView({
|
|
440
|
+
state: EditorState.create({
|
|
441
|
+
doc: value,
|
|
442
|
+
extensions: createExtensions()
|
|
443
|
+
}),
|
|
444
|
+
parent: containerRef
|
|
445
|
+
});
|
|
357
446
|
});
|
|
358
447
|
});
|
|
359
448
|
|
|
@@ -389,6 +478,26 @@
|
|
|
389
478
|
isInternalUpdate = false;
|
|
390
479
|
}
|
|
391
480
|
});
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* Reconfigure editor when variable schema changes (e.g., after async loading)
|
|
484
|
+
*/
|
|
485
|
+
$effect(() => {
|
|
486
|
+
// Only track effectiveVariableSchema changes
|
|
487
|
+
const schema = effectiveVariableSchema;
|
|
488
|
+
|
|
489
|
+
if (!editorView) {
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// When effectiveVariableSchema changes, reconfigure the autocomplete compartment
|
|
494
|
+
// This happens after async API loading completes
|
|
495
|
+
const newAutocomplete = !disabled && schema ? createTemplateAutocomplete(schema) : [];
|
|
496
|
+
|
|
497
|
+
editorView.dispatch({
|
|
498
|
+
effects: [autocompleteCompartment.reconfigure(newAutocomplete)]
|
|
499
|
+
});
|
|
500
|
+
});
|
|
392
501
|
</script>
|
|
393
502
|
|
|
394
503
|
<div class="form-template-editor">
|
|
@@ -412,6 +521,54 @@
|
|
|
412
521
|
aria-label="Template editor"
|
|
413
522
|
></div>
|
|
414
523
|
|
|
524
|
+
<!-- Loading banner (shown while fetching variables from API) -->
|
|
525
|
+
{#if isLoadingVariables}
|
|
526
|
+
<div class="form-template-editor__banner form-template-editor__banner--loading">
|
|
527
|
+
<svg
|
|
528
|
+
class="form-template-editor__banner-icon form-template-editor__banner-icon--spin"
|
|
529
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
530
|
+
fill="none"
|
|
531
|
+
viewBox="0 0 24 24"
|
|
532
|
+
>
|
|
533
|
+
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"
|
|
534
|
+
></circle>
|
|
535
|
+
<path
|
|
536
|
+
class="opacity-75"
|
|
537
|
+
fill="currentColor"
|
|
538
|
+
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"
|
|
539
|
+
></path>
|
|
540
|
+
</svg>
|
|
541
|
+
<span>Loading variables...</span>
|
|
542
|
+
</div>
|
|
543
|
+
{/if}
|
|
544
|
+
|
|
545
|
+
<!-- Error banner (shown when API fetch fails) -->
|
|
546
|
+
{#if variableLoadError}
|
|
547
|
+
<div class="form-template-editor__banner form-template-editor__banner--error">
|
|
548
|
+
<svg
|
|
549
|
+
class="form-template-editor__banner-icon"
|
|
550
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
551
|
+
viewBox="0 0 20 20"
|
|
552
|
+
fill="currentColor"
|
|
553
|
+
>
|
|
554
|
+
<path
|
|
555
|
+
fill-rule="evenodd"
|
|
556
|
+
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"
|
|
557
|
+
clip-rule="evenodd"
|
|
558
|
+
/>
|
|
559
|
+
</svg>
|
|
560
|
+
<span>{variableLoadError}</span>
|
|
561
|
+
<button
|
|
562
|
+
type="button"
|
|
563
|
+
class="form-template-editor__banner-btn"
|
|
564
|
+
onclick={retryLoadVariables}
|
|
565
|
+
title="Retry loading variables"
|
|
566
|
+
>
|
|
567
|
+
Retry
|
|
568
|
+
</button>
|
|
569
|
+
</div>
|
|
570
|
+
{/if}
|
|
571
|
+
|
|
415
572
|
<!-- Variable hints section (shown when variables are available and showHints is true) -->
|
|
416
573
|
{#if showHints && displayVariables.length > 0}
|
|
417
574
|
<div class="form-template-editor__hints">
|
|
@@ -613,4 +770,68 @@
|
|
|
613
770
|
font-family: 'JetBrains Mono', 'Fira Code', 'Monaco', 'Menlo', monospace;
|
|
614
771
|
font-size: 0.625rem;
|
|
615
772
|
}
|
|
773
|
+
|
|
774
|
+
/* Loading and error banners */
|
|
775
|
+
.form-template-editor__banner {
|
|
776
|
+
display: flex;
|
|
777
|
+
align-items: center;
|
|
778
|
+
gap: 0.5rem;
|
|
779
|
+
margin-top: 0.625rem;
|
|
780
|
+
padding: 0.625rem 0.75rem;
|
|
781
|
+
border-radius: var(--fd-radius-md);
|
|
782
|
+
font-size: 0.75rem;
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
.form-template-editor__banner--loading {
|
|
786
|
+
background-color: rgba(59, 130, 246, 0.1);
|
|
787
|
+
border: 1px solid rgba(59, 130, 246, 0.3);
|
|
788
|
+
color: rgb(29, 78, 216);
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
.form-template-editor__banner--error {
|
|
792
|
+
background-color: rgba(239, 68, 68, 0.1);
|
|
793
|
+
border: 1px solid rgba(239, 68, 68, 0.3);
|
|
794
|
+
color: rgb(185, 28, 28);
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
.form-template-editor__banner-icon {
|
|
798
|
+
width: 1rem;
|
|
799
|
+
height: 1rem;
|
|
800
|
+
flex-shrink: 0;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
.form-template-editor__banner-icon--spin {
|
|
804
|
+
animation: spin 1s linear infinite;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
@keyframes spin {
|
|
808
|
+
from {
|
|
809
|
+
transform: rotate(0deg);
|
|
810
|
+
}
|
|
811
|
+
to {
|
|
812
|
+
transform: rotate(360deg);
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
.form-template-editor__banner-btn {
|
|
817
|
+
margin-left: auto;
|
|
818
|
+
padding: 0.25rem 0.625rem;
|
|
819
|
+
background-color: rgba(239, 68, 68, 0.15);
|
|
820
|
+
border: 1px solid rgba(239, 68, 68, 0.3);
|
|
821
|
+
border-radius: var(--fd-radius-sm);
|
|
822
|
+
font-size: 0.6875rem;
|
|
823
|
+
font-weight: 500;
|
|
824
|
+
color: rgb(185, 28, 28);
|
|
825
|
+
cursor: pointer;
|
|
826
|
+
transition: all var(--fd-transition-fast);
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
.form-template-editor__banner-btn:hover {
|
|
830
|
+
background-color: rgba(239, 68, 68, 0.25);
|
|
831
|
+
border-color: rgba(239, 68, 68, 0.5);
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
.form-template-editor__banner-btn:active {
|
|
835
|
+
transform: scale(0.98);
|
|
836
|
+
}
|
|
616
837
|
</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
|
|
47
|
+
export { createTemplateAutocomplete } from './templateAutocomplete.js';
|
|
@@ -49,4 +49,4 @@ export { default as FormMarkdownEditor } from './FormMarkdownEditor.svelte';
|
|
|
49
49
|
export { default as FormTemplateEditor } from './FormTemplateEditor.svelte';
|
|
50
50
|
export { default as FormAutocomplete } from './FormAutocomplete.svelte';
|
|
51
51
|
// Template autocomplete utilities
|
|
52
|
-
export { createTemplateAutocomplete
|
|
52
|
+
export { createTemplateAutocomplete } from './templateAutocomplete.js';
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
*
|
|
11
11
|
* @module components/form/templateAutocomplete
|
|
12
12
|
*/
|
|
13
|
-
import type { Extension } from
|
|
14
|
-
import type { VariableSchema } from
|
|
13
|
+
import type { Extension } from '@codemirror/state';
|
|
14
|
+
import type { VariableSchema } from '../../types/index.js';
|
|
15
15
|
/**
|
|
16
16
|
* Creates a CodeMirror extension for template variable autocomplete.
|
|
17
17
|
*
|
|
@@ -27,12 +27,3 @@ import type { VariableSchema } from "../../types/index.js";
|
|
|
27
27
|
* ```
|
|
28
28
|
*/
|
|
29
29
|
export declare function createTemplateAutocomplete(schema: VariableSchema): Extension;
|
|
30
|
-
/**
|
|
31
|
-
* Creates a simple autocomplete extension that triggers when user types {{
|
|
32
|
-
* and shows top-level variables only (no drilling).
|
|
33
|
-
* Used as a fallback when full variable schema is not available.
|
|
34
|
-
*
|
|
35
|
-
* @param variableHints - Simple array of variable names
|
|
36
|
-
* @returns A CodeMirror extension that provides basic autocomplete
|
|
37
|
-
*/
|
|
38
|
-
export declare function createSimpleTemplateAutocomplete(variableHints: string[]): Extension;
|