@d34dman/flowdrop 0.0.45 → 0.0.47

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.
Files changed (75) hide show
  1. package/README.md +2 -2
  2. package/dist/components/App.svelte +6 -0
  3. package/dist/components/ConfigForm.svelte +56 -22
  4. package/dist/components/ConfigForm.svelte.d.ts +11 -1
  5. package/dist/components/Navbar.svelte +6 -7
  6. package/dist/components/SchemaForm.svelte +2 -10
  7. package/dist/components/SettingsPanel.svelte +5 -2
  8. package/dist/components/WorkflowEditor.svelte +158 -4
  9. package/dist/components/WorkflowEditor.svelte.d.ts +1 -0
  10. package/dist/components/form/FormAutocomplete.svelte +5 -9
  11. package/dist/components/form/FormCheckboxGroup.svelte +11 -1
  12. package/dist/components/form/FormCheckboxGroup.svelte.d.ts +2 -0
  13. package/dist/components/form/FormCodeEditor.svelte +16 -7
  14. package/dist/components/form/FormCodeEditor.svelte.d.ts +2 -0
  15. package/dist/components/form/FormField.svelte +33 -12
  16. package/dist/components/form/FormFieldLight.svelte +16 -12
  17. package/dist/components/form/FormMarkdownEditor.svelte +29 -19
  18. package/dist/components/form/FormMarkdownEditor.svelte.d.ts +2 -0
  19. package/dist/components/form/FormNumberField.svelte +4 -0
  20. package/dist/components/form/FormNumberField.svelte.d.ts +2 -0
  21. package/dist/components/form/FormRangeField.svelte +4 -0
  22. package/dist/components/form/FormRangeField.svelte.d.ts +2 -0
  23. package/dist/components/form/FormSelect.svelte +4 -0
  24. package/dist/components/form/FormSelect.svelte.d.ts +2 -0
  25. package/dist/components/form/FormTemplateEditor.svelte +140 -17
  26. package/dist/components/form/FormTemplateEditor.svelte.d.ts +19 -1
  27. package/dist/components/form/FormTextField.svelte +4 -0
  28. package/dist/components/form/FormTextField.svelte.d.ts +2 -0
  29. package/dist/components/form/FormTextarea.svelte +4 -0
  30. package/dist/components/form/FormTextarea.svelte.d.ts +2 -0
  31. package/dist/components/form/FormToggle.svelte +4 -0
  32. package/dist/components/form/FormToggle.svelte.d.ts +2 -0
  33. package/dist/components/form/index.d.ts +1 -0
  34. package/dist/components/form/index.js +2 -0
  35. package/dist/components/form/templateAutocomplete.d.ts +38 -0
  36. package/dist/components/form/templateAutocomplete.js +309 -0
  37. package/dist/components/form/types.d.ts +39 -2
  38. package/dist/components/form/types.js +1 -1
  39. package/dist/components/layouts/MainLayout.svelte +5 -2
  40. package/dist/components/nodes/GatewayNode.svelte +0 -8
  41. package/dist/components/nodes/SimpleNode.svelte +2 -3
  42. package/dist/components/nodes/WorkflowNode.svelte +0 -8
  43. package/dist/components/playground/Playground.svelte +43 -38
  44. package/dist/editor/index.d.ts +3 -1
  45. package/dist/editor/index.js +5 -1
  46. package/dist/helpers/workflowEditorHelper.js +1 -2
  47. package/dist/registry/nodeComponentRegistry.d.ts +9 -9
  48. package/dist/registry/nodeComponentRegistry.js +10 -10
  49. package/dist/services/autoSaveService.js +5 -5
  50. package/dist/services/historyService.d.ts +207 -0
  51. package/dist/services/historyService.js +317 -0
  52. package/dist/services/settingsService.d.ts +2 -2
  53. package/dist/services/settingsService.js +15 -21
  54. package/dist/services/toastService.d.ts +1 -1
  55. package/dist/services/toastService.js +10 -10
  56. package/dist/services/variableService.d.ts +100 -0
  57. package/dist/services/variableService.js +367 -0
  58. package/dist/stores/historyStore.d.ts +133 -0
  59. package/dist/stores/historyStore.js +188 -0
  60. package/dist/stores/settingsStore.d.ts +1 -1
  61. package/dist/stores/settingsStore.js +40 -42
  62. package/dist/stores/themeStore.d.ts +2 -2
  63. package/dist/stores/themeStore.js +30 -32
  64. package/dist/stores/workflowStore.d.ts +52 -2
  65. package/dist/stores/workflowStore.js +102 -2
  66. package/dist/styles/base.css +28 -8
  67. package/dist/styles/toast.css +3 -1
  68. package/dist/styles/tokens.css +2 -2
  69. package/dist/types/index.d.ts +120 -0
  70. package/dist/types/settings.d.ts +3 -3
  71. package/dist/types/settings.js +13 -19
  72. package/dist/utils/colors.js +17 -17
  73. package/dist/utils/nodeTypes.d.ts +15 -10
  74. package/dist/utils/nodeTypes.js +24 -22
  75. package/package.json +1 -1
@@ -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:
@@ -34,6 +37,11 @@
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 { VariableSchema, TemplateVariablesConfig } from '../../types/index.js';
41
+ import {
42
+ createTemplateAutocomplete,
43
+ createSimpleTemplateAutocomplete
44
+ } from './templateAutocomplete.js';
37
45
 
38
46
  interface Props {
39
47
  /** Field identifier */
@@ -48,10 +56,27 @@
48
56
  darkTheme?: boolean;
49
57
  /** Editor height in pixels or CSS value */
50
58
  height?: string;
51
- /** Available variable names for hints (optional) */
59
+ /**
60
+ * Configuration for template variable autocomplete.
61
+ * Controls which variables are available and how they are displayed.
62
+ */
63
+ variables?: TemplateVariablesConfig;
64
+ /**
65
+ * Variable schema for advanced autocomplete with nested drilling.
66
+ * When provided, enables dot notation (user.name) and array access (items[0]).
67
+ * @deprecated Use `variables.schema` instead
68
+ */
69
+ 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
+ */
52
75
  variableHints?: string[];
53
76
  /** Placeholder variable example for the hint */
54
77
  placeholderExample?: string;
78
+ /** Whether the field is disabled (read-only) */
79
+ disabled?: boolean;
55
80
  /** ARIA description ID */
56
81
  ariaDescribedBy?: string;
57
82
  /** Callback when value changes */
@@ -65,12 +90,46 @@
65
90
  required = false,
66
91
  darkTheme = false,
67
92
  height = '250px',
93
+ variables,
94
+ variableSchema,
68
95
  variableHints = [],
69
96
  placeholderExample = 'Hello {{ name }}, your order #{{ order_id }} is ready!',
97
+ disabled = false,
70
98
  ariaDescribedBy,
71
99
  onChange
72
100
  }: Props = $props();
73
101
 
102
+ /**
103
+ * Get the effective variable schema.
104
+ * Prefers variables.schema, falls back to deprecated variableSchema prop.
105
+ */
106
+ const effectiveVariableSchema = $derived.by<VariableSchema | undefined>(() => {
107
+ if (variables?.schema && Object.keys(variables.schema.variables).length > 0) {
108
+ return variables.schema;
109
+ }
110
+ if (variableSchema && Object.keys(variableSchema.variables).length > 0) {
111
+ return variableSchema;
112
+ }
113
+ return undefined;
114
+ });
115
+
116
+ /**
117
+ * Whether to show the variable hints section.
118
+ * Controlled by variables.showHints (defaults to true).
119
+ */
120
+ const showHints = $derived(variables?.showHints !== false);
121
+
122
+ /**
123
+ * Derive the list of top-level variable names for the hints display.
124
+ * Prefers effectiveVariableSchema if available, falls back to variableHints.
125
+ */
126
+ const displayVariables = $derived.by(() => {
127
+ if (effectiveVariableSchema) {
128
+ return Object.keys(effectiveVariableSchema.variables);
129
+ }
130
+ return variableHints;
131
+ });
132
+
74
133
  /** Reference to the container element */
75
134
  let containerRef: HTMLDivElement | undefined = $state(undefined);
76
135
 
@@ -83,10 +142,15 @@
83
142
  /**
84
143
  * Create a MatchDecorator for {{ variable }} patterns
85
144
  * This highlights the entire {{ variable }} expression
145
+ * Supports:
146
+ * - Simple variables: {{ name }}
147
+ * - Dot notation: {{ user.name }}, {{ user.address.city }}
148
+ * - Array access: {{ items[0] }}, {{ items[0].name }}
149
+ * - Mixed: {{ orders[0].items[1].price }}
86
150
  */
87
151
  const variableMatcher = new MatchDecorator({
88
- // Match {{ variable_name }} patterns (with optional whitespace)
89
- regexp: /\{\{\s*[\w.]+\s*\}\}/g,
152
+ // Match {{ variable_name }} patterns with dot notation and array indices
153
+ regexp: /\{\{\s*[\w]+(?:\.[\w]+|\[\d+\]|\[\*\])*\s*\}\}/g,
90
154
  decoration: Decoration.mark({ class: 'cm-template-variable' })
91
155
  });
92
156
 
@@ -122,7 +186,8 @@
122
186
 
123
187
  /**
124
188
  * Create editor extensions array for template editing
125
- * Uses minimal setup for better performance (no auto-closing brackets, no autocompletion)
189
+ * Includes autocomplete when variables are available
190
+ * When disabled is true, adds readOnly/editable so the editor cannot be modified
126
191
  */
127
192
  function createExtensions() {
128
193
  const extensions = [
@@ -133,23 +198,28 @@
133
198
  highlightActiveLine(),
134
199
  drawSelection(),
135
200
 
136
- // Editing features
137
- history(),
138
- indentOnInput(),
201
+ // Editing features (skip when read-only)
202
+ ...(disabled
203
+ ? []
204
+ : [
205
+ history(),
206
+ indentOnInput(),
207
+ keymap.of([...defaultKeymap, ...historyKeymap, indentWithTab])
208
+ ]),
209
+
210
+ // Read-only: prevent document changes and mark content as non-editable
211
+ ...(disabled ? [EditorState.readOnly.of(true), EditorView.editable.of(false)] : []),
139
212
 
140
213
  // Syntax highlighting
141
214
  syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
142
215
 
143
- // Keymaps for basic editing
144
- keymap.of([...defaultKeymap, ...historyKeymap, indentWithTab]),
145
-
146
216
  // Template-specific variable highlighter
147
217
  variableHighlighter,
148
218
 
149
- // Update listener
219
+ // Update listener (only fires on user edit when not disabled)
150
220
  EditorView.updateListener.of(handleUpdate),
151
221
 
152
- // Custom theme
222
+ // Custom theme with autocomplete styling
153
223
  EditorView.theme({
154
224
  '&': {
155
225
  height: height,
@@ -176,20 +246,73 @@
176
246
  borderRadius: '3px',
177
247
  padding: '1px 2px',
178
248
  fontWeight: '500'
249
+ },
250
+ // Autocomplete dropdown styling
251
+ '.cm-tooltip.cm-tooltip-autocomplete': {
252
+ backgroundColor: 'var(--fd-background, #ffffff)',
253
+ border: '1px solid var(--fd-border, #e5e7eb)',
254
+ borderRadius: 'var(--fd-radius-lg, 0.5rem)',
255
+ boxShadow: 'var(--fd-shadow-lg, 0 10px 15px -3px rgba(0, 0, 0, 0.1))',
256
+ padding: '0.25rem',
257
+ maxHeight: '200px',
258
+ overflow: 'auto'
259
+ },
260
+ '.cm-tooltip.cm-tooltip-autocomplete > ul': {
261
+ fontFamily: "'JetBrains Mono', 'Fira Code', 'Monaco', 'Menlo', monospace",
262
+ fontSize: '0.8125rem'
263
+ },
264
+ '.cm-tooltip.cm-tooltip-autocomplete > ul > li': {
265
+ padding: '0.375rem 0.625rem',
266
+ borderRadius: 'var(--fd-radius-md, 0.375rem)',
267
+ display: 'flex',
268
+ alignItems: 'center',
269
+ gap: '0.5rem'
270
+ },
271
+ '.cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected]': {
272
+ backgroundColor: 'var(--fd-accent-muted, rgba(168, 85, 247, 0.1))',
273
+ color: 'var(--fd-accent-hover, #7c3aed)'
274
+ },
275
+ '.cm-completionLabel': {
276
+ flex: '1'
277
+ },
278
+ '.cm-completionDetail': {
279
+ fontSize: '0.6875rem',
280
+ color: 'var(--fd-muted-foreground, #6b7280)',
281
+ opacity: '0.8'
179
282
  }
180
283
  }),
181
284
  EditorView.lineWrapping,
182
285
  EditorState.tabSize.of(2)
183
286
  ];
184
287
 
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
+ }
297
+ }
298
+
185
299
  if (darkTheme) {
186
300
  extensions.push(oneDark);
187
- // Add dark theme override for variable highlighting
301
+ // Add dark theme override for variable highlighting and autocomplete
188
302
  extensions.push(
189
303
  EditorView.theme({
190
304
  '.cm-template-variable': {
191
305
  color: '#c084fc',
192
306
  backgroundColor: 'rgba(192, 132, 252, 0.15)'
307
+ },
308
+ '.cm-tooltip.cm-tooltip-autocomplete': {
309
+ backgroundColor: '#1e1e1e',
310
+ border: '1px solid #3e4451',
311
+ boxShadow: '0 10px 15px -3px rgba(0, 0, 0, 0.3)'
312
+ },
313
+ '.cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected]': {
314
+ backgroundColor: 'rgba(192, 132, 252, 0.2)',
315
+ color: '#c084fc'
193
316
  }
194
317
  })
195
318
  );
@@ -289,12 +412,12 @@
289
412
  aria-label="Template editor"
290
413
  ></div>
291
414
 
292
- <!-- Variable hints section (shown when variables are available) -->
293
- {#if variableHints.length > 0}
415
+ <!-- Variable hints section (shown when variables are available and showHints is true) -->
416
+ {#if showHints && displayVariables.length > 0}
294
417
  <div class="form-template-editor__hints">
295
418
  <span class="form-template-editor__hints-label">Available variables:</span>
296
419
  <div class="form-template-editor__hints-list">
297
- {#each variableHints as varName (varName)}
420
+ {#each displayVariables as varName (varName)}
298
421
  <button
299
422
  type="button"
300
423
  class="form-template-editor__hint-btn"
@@ -1,3 +1,4 @@
1
+ import type { VariableSchema, TemplateVariablesConfig } from '../../types/index.js';
1
2
  interface Props {
2
3
  /** Field identifier */
3
4
  id: string;
@@ -11,10 +12,27 @@ interface Props {
11
12
  darkTheme?: boolean;
12
13
  /** Editor height in pixels or CSS value */
13
14
  height?: string;
14
- /** Available variable names for hints (optional) */
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;
26
+ /**
27
+ * Simple variable names for basic hints (backward compatible).
28
+ * Used when variableSchema is not provided.
29
+ * @deprecated Use `variables.schema` instead
30
+ */
15
31
  variableHints?: string[];
16
32
  /** Placeholder variable example for the hint */
17
33
  placeholderExample?: string;
34
+ /** Whether the field is disabled (read-only) */
35
+ disabled?: boolean;
18
36
  /** ARIA description ID */
19
37
  ariaDescribedBy?: string;
20
38
  /** Callback when value changes */
@@ -18,6 +18,8 @@
18
18
  placeholder?: string;
19
19
  /** Whether the field is required */
20
20
  required?: boolean;
21
+ /** Whether the field is disabled (read-only) */
22
+ disabled?: boolean;
21
23
  /** ARIA description ID */
22
24
  ariaDescribedBy?: string;
23
25
  /** Callback when value changes */
@@ -29,6 +31,7 @@
29
31
  value = '',
30
32
  placeholder = '',
31
33
  required = false,
34
+ disabled = false,
32
35
  ariaDescribedBy,
33
36
  onChange
34
37
  }: Props = $props();
@@ -48,6 +51,7 @@
48
51
  class="form-text-field"
49
52
  value={value ?? ''}
50
53
  {placeholder}
54
+ {disabled}
51
55
  aria-describedby={ariaDescribedBy}
52
56
  aria-required={required}
53
57
  oninput={handleInput}
@@ -7,6 +7,8 @@ interface Props {
7
7
  placeholder?: string;
8
8
  /** Whether the field is required */
9
9
  required?: boolean;
10
+ /** Whether the field is disabled (read-only) */
11
+ disabled?: boolean;
10
12
  /** ARIA description ID */
11
13
  ariaDescribedBy?: string;
12
14
  /** Callback when value changes */
@@ -20,6 +20,8 @@
20
20
  rows?: number;
21
21
  /** Whether the field is required */
22
22
  required?: boolean;
23
+ /** Whether the field is disabled (read-only) */
24
+ disabled?: boolean;
23
25
  /** ARIA description ID */
24
26
  ariaDescribedBy?: string;
25
27
  /** Callback when value changes */
@@ -32,6 +34,7 @@
32
34
  placeholder = '',
33
35
  rows = 4,
34
36
  required = false,
37
+ disabled = false,
35
38
  ariaDescribedBy,
36
39
  onChange
37
40
  }: Props = $props();
@@ -51,6 +54,7 @@
51
54
  value={value ?? ''}
52
55
  {placeholder}
53
56
  {rows}
57
+ {disabled}
54
58
  aria-describedby={ariaDescribedBy}
55
59
  aria-required={required}
56
60
  oninput={handleInput}
@@ -9,6 +9,8 @@ interface Props {
9
9
  rows?: number;
10
10
  /** Whether the field is required */
11
11
  required?: boolean;
12
+ /** Whether the field is disabled (read-only) */
13
+ disabled?: boolean;
12
14
  /** ARIA description ID */
13
15
  ariaDescribedBy?: string;
14
16
  /** Callback when value changes */
@@ -18,6 +18,8 @@
18
18
  onLabel?: string;
19
19
  /** Label shown when toggle is off */
20
20
  offLabel?: string;
21
+ /** Whether the field is disabled (read-only) */
22
+ disabled?: boolean;
21
23
  /** ARIA description ID */
22
24
  ariaDescribedBy?: string;
23
25
  /** Callback when value changes */
@@ -29,6 +31,7 @@
29
31
  value = false,
30
32
  onLabel = 'Enabled',
31
33
  offLabel = 'Disabled',
34
+ disabled = false,
32
35
  ariaDescribedBy,
33
36
  onChange
34
37
  }: Props = $props();
@@ -48,6 +51,7 @@
48
51
  type="checkbox"
49
52
  class="form-toggle__input"
50
53
  checked={value}
54
+ {disabled}
51
55
  aria-describedby={ariaDescribedBy}
52
56
  onchange={handleChange}
53
57
  />
@@ -7,6 +7,8 @@ interface Props {
7
7
  onLabel?: string;
8
8
  /** Label shown when toggle is off */
9
9
  offLabel?: string;
10
+ /** Whether the field is disabled (read-only) */
11
+ disabled?: boolean;
10
12
  /** ARIA description ID */
11
13
  ariaDescribedBy?: string;
12
14
  /** Callback when value changes */
@@ -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, createSimpleTemplateAutocomplete } 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, createSimpleTemplateAutocomplete } from './templateAutocomplete.js';
@@ -0,0 +1,38 @@
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;
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;