@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
|
@@ -4,10 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
Features:
|
|
6
6
|
- Custom syntax highlighting for {{ variable }} placeholders
|
|
7
|
+
- Inline autocomplete for template variables (triggered on {{ and .)
|
|
8
|
+
- Support for nested object drilling (user.address.city)
|
|
9
|
+
- Support for array index access (items[0].name)
|
|
7
10
|
- Dark/light theme support
|
|
8
11
|
- Consistent styling with other form components
|
|
9
12
|
- Line wrapping for better template readability
|
|
10
|
-
- Optional variable hints display
|
|
13
|
+
- Optional variable hints display (clickable buttons)
|
|
11
14
|
- Proper ARIA attributes for accessibility
|
|
12
15
|
|
|
13
16
|
Usage:
|
|
@@ -30,10 +33,19 @@
|
|
|
30
33
|
type ViewUpdate,
|
|
31
34
|
MatchDecorator
|
|
32
35
|
} from '@codemirror/view';
|
|
33
|
-
import { EditorState } from '@codemirror/state';
|
|
36
|
+
import { EditorState, Compartment } from '@codemirror/state';
|
|
34
37
|
import { history, historyKeymap, defaultKeymap, indentWithTab } from '@codemirror/commands';
|
|
35
38
|
import { syntaxHighlighting, defaultHighlightStyle, indentOnInput } from '@codemirror/language';
|
|
36
39
|
import { oneDark } from '@codemirror/theme-one-dark';
|
|
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';
|
|
37
49
|
|
|
38
50
|
interface Props {
|
|
39
51
|
/** Field identifier */
|
|
@@ -48,8 +60,17 @@
|
|
|
48
60
|
darkTheme?: boolean;
|
|
49
61
|
/** Editor height in pixels or CSS value */
|
|
50
62
|
height?: string;
|
|
51
|
-
/**
|
|
52
|
-
|
|
63
|
+
/**
|
|
64
|
+
* Configuration for template variable autocomplete.
|
|
65
|
+
* Controls which variables are available and how they are displayed.
|
|
66
|
+
*/
|
|
67
|
+
variables?: TemplateVariablesConfig;
|
|
68
|
+
/**
|
|
69
|
+
* Variable schema for advanced autocomplete with nested drilling.
|
|
70
|
+
* When provided, enables dot notation (user.name) and array access (items[0]).
|
|
71
|
+
* @deprecated Use `variables.schema` instead
|
|
72
|
+
*/
|
|
73
|
+
variableSchema?: VariableSchema;
|
|
53
74
|
/** Placeholder variable example for the hint */
|
|
54
75
|
placeholderExample?: string;
|
|
55
76
|
/** Whether the field is disabled (read-only) */
|
|
@@ -58,6 +79,16 @@
|
|
|
58
79
|
ariaDescribedBy?: string;
|
|
59
80
|
/** Callback when value changes */
|
|
60
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;
|
|
61
92
|
}
|
|
62
93
|
|
|
63
94
|
let {
|
|
@@ -67,13 +98,102 @@
|
|
|
67
98
|
required = false,
|
|
68
99
|
darkTheme = false,
|
|
69
100
|
height = '250px',
|
|
70
|
-
|
|
101
|
+
variables,
|
|
102
|
+
variableSchema,
|
|
71
103
|
placeholderExample = 'Hello {{ name }}, your order #{{ order_id }} is ready!',
|
|
72
104
|
disabled = false,
|
|
73
105
|
ariaDescribedBy,
|
|
74
|
-
onChange
|
|
106
|
+
onChange,
|
|
107
|
+
node,
|
|
108
|
+
nodes = [],
|
|
109
|
+
edges = [],
|
|
110
|
+
workflowId,
|
|
111
|
+
authProvider
|
|
75
112
|
}: Props = $props();
|
|
76
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
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Load variable schema on mount or when configuration changes.
|
|
125
|
+
* Handles both synchronous (schema-based) and asynchronous (API-based) loading.
|
|
126
|
+
*/
|
|
127
|
+
async function loadVariableSchema() {
|
|
128
|
+
// Reset error state
|
|
129
|
+
variableLoadError = null;
|
|
130
|
+
|
|
131
|
+
// If we have deprecated variableSchema prop, use it directly
|
|
132
|
+
if (variableSchema && Object.keys(variableSchema.variables).length > 0) {
|
|
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;
|
|
147
|
+
}
|
|
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
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Whether to show the variable hints section.
|
|
183
|
+
* Controlled by variables.showHints (defaults to true).
|
|
184
|
+
*/
|
|
185
|
+
const showHints = $derived(variables?.showHints !== false);
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Derive the list of top-level variable names for the hints display.
|
|
189
|
+
*/
|
|
190
|
+
const displayVariables = $derived.by(() => {
|
|
191
|
+
if (effectiveVariableSchema) {
|
|
192
|
+
return Object.keys(effectiveVariableSchema.variables);
|
|
193
|
+
}
|
|
194
|
+
return [];
|
|
195
|
+
});
|
|
196
|
+
|
|
77
197
|
/** Reference to the container element */
|
|
78
198
|
let containerRef: HTMLDivElement | undefined = $state(undefined);
|
|
79
199
|
|
|
@@ -83,13 +203,21 @@
|
|
|
83
203
|
/** Flag to prevent update loops */
|
|
84
204
|
let isInternalUpdate = false;
|
|
85
205
|
|
|
206
|
+
/** Compartment for dynamic autocomplete reconfiguration */
|
|
207
|
+
const autocompleteCompartment = new Compartment();
|
|
208
|
+
|
|
86
209
|
/**
|
|
87
210
|
* Create a MatchDecorator for {{ variable }} patterns
|
|
88
211
|
* This highlights the entire {{ variable }} expression
|
|
212
|
+
* Supports:
|
|
213
|
+
* - Simple variables: {{ name }}
|
|
214
|
+
* - Dot notation: {{ user.name }}, {{ user.address.city }}
|
|
215
|
+
* - Array access: {{ items[0] }}, {{ items[0].name }}
|
|
216
|
+
* - Mixed: {{ orders[0].items[1].price }}
|
|
89
217
|
*/
|
|
90
218
|
const variableMatcher = new MatchDecorator({
|
|
91
|
-
// Match {{ variable_name }} patterns
|
|
92
|
-
regexp: /\{\{\s*[\w
|
|
219
|
+
// Match {{ variable_name }} patterns with dot notation and array indices
|
|
220
|
+
regexp: /\{\{\s*[\w]+(?:\.[\w]+|\[\d+\]|\[\*\])*\s*\}\}/g,
|
|
93
221
|
decoration: Decoration.mark({ class: 'cm-template-variable' })
|
|
94
222
|
});
|
|
95
223
|
|
|
@@ -125,7 +253,7 @@
|
|
|
125
253
|
|
|
126
254
|
/**
|
|
127
255
|
* Create editor extensions array for template editing
|
|
128
|
-
*
|
|
256
|
+
* Includes autocomplete when variables are available
|
|
129
257
|
* When disabled is true, adds readOnly/editable so the editor cannot be modified
|
|
130
258
|
*/
|
|
131
259
|
function createExtensions() {
|
|
@@ -158,7 +286,7 @@
|
|
|
158
286
|
// Update listener (only fires on user edit when not disabled)
|
|
159
287
|
EditorView.updateListener.of(handleUpdate),
|
|
160
288
|
|
|
161
|
-
// Custom theme
|
|
289
|
+
// Custom theme with autocomplete styling
|
|
162
290
|
EditorView.theme({
|
|
163
291
|
'&': {
|
|
164
292
|
height: height,
|
|
@@ -185,20 +313,70 @@
|
|
|
185
313
|
borderRadius: '3px',
|
|
186
314
|
padding: '1px 2px',
|
|
187
315
|
fontWeight: '500'
|
|
316
|
+
},
|
|
317
|
+
// Autocomplete dropdown styling
|
|
318
|
+
'.cm-tooltip.cm-tooltip-autocomplete': {
|
|
319
|
+
backgroundColor: 'var(--fd-background, #ffffff)',
|
|
320
|
+
border: '1px solid var(--fd-border, #e5e7eb)',
|
|
321
|
+
borderRadius: 'var(--fd-radius-lg, 0.5rem)',
|
|
322
|
+
boxShadow: 'var(--fd-shadow-lg, 0 10px 15px -3px rgba(0, 0, 0, 0.1))',
|
|
323
|
+
padding: '0.25rem',
|
|
324
|
+
maxHeight: '200px',
|
|
325
|
+
overflow: 'auto'
|
|
326
|
+
},
|
|
327
|
+
'.cm-tooltip.cm-tooltip-autocomplete > ul': {
|
|
328
|
+
fontFamily: "'JetBrains Mono', 'Fira Code', 'Monaco', 'Menlo', monospace",
|
|
329
|
+
fontSize: '0.8125rem'
|
|
330
|
+
},
|
|
331
|
+
'.cm-tooltip.cm-tooltip-autocomplete > ul > li': {
|
|
332
|
+
padding: '0.375rem 0.625rem',
|
|
333
|
+
borderRadius: 'var(--fd-radius-md, 0.375rem)',
|
|
334
|
+
display: 'flex',
|
|
335
|
+
alignItems: 'center',
|
|
336
|
+
gap: '0.5rem'
|
|
337
|
+
},
|
|
338
|
+
'.cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected]': {
|
|
339
|
+
backgroundColor: 'var(--fd-accent-muted, rgba(168, 85, 247, 0.1))',
|
|
340
|
+
color: 'var(--fd-accent-hover, #7c3aed)'
|
|
341
|
+
},
|
|
342
|
+
'.cm-completionLabel': {
|
|
343
|
+
flex: '1'
|
|
344
|
+
},
|
|
345
|
+
'.cm-completionDetail': {
|
|
346
|
+
fontSize: '0.6875rem',
|
|
347
|
+
color: 'var(--fd-muted-foreground, #6b7280)',
|
|
348
|
+
opacity: '0.8'
|
|
188
349
|
}
|
|
189
350
|
}),
|
|
190
351
|
EditorView.lineWrapping,
|
|
191
352
|
EditorState.tabSize.of(2)
|
|
192
353
|
];
|
|
193
354
|
|
|
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([]));
|
|
361
|
+
}
|
|
362
|
+
|
|
194
363
|
if (darkTheme) {
|
|
195
364
|
extensions.push(oneDark);
|
|
196
|
-
// Add dark theme override for variable highlighting
|
|
365
|
+
// Add dark theme override for variable highlighting and autocomplete
|
|
197
366
|
extensions.push(
|
|
198
367
|
EditorView.theme({
|
|
199
368
|
'.cm-template-variable': {
|
|
200
369
|
color: '#c084fc',
|
|
201
370
|
backgroundColor: 'rgba(192, 132, 252, 0.15)'
|
|
371
|
+
},
|
|
372
|
+
'.cm-tooltip.cm-tooltip-autocomplete': {
|
|
373
|
+
backgroundColor: '#1e1e1e',
|
|
374
|
+
border: '1px solid #3e4451',
|
|
375
|
+
boxShadow: '0 10px 15px -3px rgba(0, 0, 0, 0.3)'
|
|
376
|
+
},
|
|
377
|
+
'.cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected]': {
|
|
378
|
+
backgroundColor: 'rgba(192, 132, 252, 0.2)',
|
|
379
|
+
color: '#c084fc'
|
|
202
380
|
}
|
|
203
381
|
})
|
|
204
382
|
);
|
|
@@ -227,19 +405,23 @@
|
|
|
227
405
|
}
|
|
228
406
|
|
|
229
407
|
/**
|
|
230
|
-
* Initialize CodeMirror editor on mount
|
|
408
|
+
* Initialize CodeMirror editor and load variables on mount
|
|
231
409
|
*/
|
|
232
410
|
onMount(() => {
|
|
233
411
|
if (!containerRef) {
|
|
234
412
|
return;
|
|
235
413
|
}
|
|
236
414
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
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
|
+
});
|
|
243
425
|
});
|
|
244
426
|
});
|
|
245
427
|
|
|
@@ -275,6 +457,28 @@
|
|
|
275
457
|
isInternalUpdate = false;
|
|
276
458
|
}
|
|
277
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
|
+
});
|
|
278
482
|
</script>
|
|
279
483
|
|
|
280
484
|
<div class="form-template-editor">
|
|
@@ -298,12 +502,66 @@
|
|
|
298
502
|
aria-label="Template editor"
|
|
299
503
|
></div>
|
|
300
504
|
|
|
301
|
-
<!--
|
|
302
|
-
{#if
|
|
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
|
+
|
|
559
|
+
<!-- Variable hints section (shown when variables are available and showHints is true) -->
|
|
560
|
+
{#if showHints && displayVariables.length > 0}
|
|
303
561
|
<div class="form-template-editor__hints">
|
|
304
562
|
<span class="form-template-editor__hints-label">Available variables:</span>
|
|
305
563
|
<div class="form-template-editor__hints-list">
|
|
306
|
-
{#each
|
|
564
|
+
{#each displayVariables as varName (varName)}
|
|
307
565
|
<button
|
|
308
566
|
type="button"
|
|
309
567
|
class="form-template-editor__hint-btn"
|
|
@@ -499,4 +757,68 @@
|
|
|
499
757
|
font-family: 'JetBrains Mono', 'Fira Code', 'Monaco', 'Menlo', monospace;
|
|
500
758
|
font-size: 0.625rem;
|
|
501
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
|
+
}
|
|
502
824
|
</style>
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { VariableSchema, TemplateVariablesConfig, WorkflowNode, WorkflowEdge, AuthProvider } from '../../types/index.js';
|
|
1
2
|
interface Props {
|
|
2
3
|
/** Field identifier */
|
|
3
4
|
id: string;
|
|
@@ -11,8 +12,17 @@ interface Props {
|
|
|
11
12
|
darkTheme?: boolean;
|
|
12
13
|
/** Editor height in pixels or CSS value */
|
|
13
14
|
height?: string;
|
|
14
|
-
/**
|
|
15
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Configuration for template variable autocomplete.
|
|
17
|
+
* Controls which variables are available and how they are displayed.
|
|
18
|
+
*/
|
|
19
|
+
variables?: TemplateVariablesConfig;
|
|
20
|
+
/**
|
|
21
|
+
* Variable schema for advanced autocomplete with nested drilling.
|
|
22
|
+
* When provided, enables dot notation (user.name) and array access (items[0]).
|
|
23
|
+
* @deprecated Use `variables.schema` instead
|
|
24
|
+
*/
|
|
25
|
+
variableSchema?: VariableSchema;
|
|
16
26
|
/** Placeholder variable example for the hint */
|
|
17
27
|
placeholderExample?: string;
|
|
18
28
|
/** Whether the field is disabled (read-only) */
|
|
@@ -21,6 +31,16 @@ interface Props {
|
|
|
21
31
|
ariaDescribedBy?: string;
|
|
22
32
|
/** Callback when value changes */
|
|
23
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;
|
|
24
44
|
}
|
|
25
45
|
declare const FormTemplateEditor: import("svelte").Component<Props, {}, "">;
|
|
26
46
|
type FormTemplateEditor = ReturnType<typeof FormTemplateEditor>;
|
|
@@ -44,3 +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 } from './templateAutocomplete.js';
|
|
@@ -48,3 +48,5 @@ export { default as FormCodeEditor } from './FormCodeEditor.svelte';
|
|
|
48
48
|
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
|
+
// Template autocomplete utilities
|
|
52
|
+
export { createTemplateAutocomplete } from './templateAutocomplete.js';
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template Variable Autocomplete Extension for CodeMirror
|
|
3
|
+
* Provides autocomplete suggestions for {{ variable }} syntax in template editors.
|
|
4
|
+
*
|
|
5
|
+
* Features:
|
|
6
|
+
* - Triggers on `{{` to show top-level variables
|
|
7
|
+
* - Triggers on `.` to show child properties for objects
|
|
8
|
+
* - Triggers on `[` to show array index options
|
|
9
|
+
* - Supports deep nesting (e.g., `user.address.city`)
|
|
10
|
+
*
|
|
11
|
+
* @module components/form/templateAutocomplete
|
|
12
|
+
*/
|
|
13
|
+
import type { Extension } from "@codemirror/state";
|
|
14
|
+
import type { VariableSchema } from "../../types/index.js";
|
|
15
|
+
/**
|
|
16
|
+
* Creates a CodeMirror extension for template variable autocomplete.
|
|
17
|
+
*
|
|
18
|
+
* @param schema - The variable schema containing available variables
|
|
19
|
+
* @returns A CodeMirror extension that provides autocomplete
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const extensions = [
|
|
24
|
+
* // ... other extensions
|
|
25
|
+
* createTemplateAutocomplete(variableSchema)
|
|
26
|
+
* ];
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare function createTemplateAutocomplete(schema: VariableSchema): Extension;
|