@d34dman/flowdrop 0.0.24 → 0.0.26

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 (38) hide show
  1. package/README.md +52 -62
  2. package/dist/components/App.svelte +15 -2
  3. package/dist/components/ConfigForm.svelte +4 -1
  4. package/dist/components/ConfigModal.svelte +4 -70
  5. package/dist/components/ConfigPanel.svelte +4 -9
  6. package/dist/components/EdgeRefresher.svelte +42 -0
  7. package/dist/components/EdgeRefresher.svelte.d.ts +9 -0
  8. package/dist/components/ReadOnlyDetails.svelte +3 -1
  9. package/dist/components/UniversalNode.svelte +6 -3
  10. package/dist/components/WorkflowEditor.svelte +33 -0
  11. package/dist/components/WorkflowEditor.svelte.d.ts +3 -1
  12. package/dist/components/form/FormCheckboxGroup.svelte +2 -9
  13. package/dist/components/form/FormCodeEditor.svelte +416 -0
  14. package/dist/components/form/FormCodeEditor.svelte.d.ts +23 -0
  15. package/dist/components/form/FormField.svelte +125 -85
  16. package/dist/components/form/FormField.svelte.d.ts +1 -1
  17. package/dist/components/form/FormFieldWrapper.svelte +2 -10
  18. package/dist/components/form/FormFieldWrapper.svelte.d.ts +1 -1
  19. package/dist/components/form/FormMarkdownEditor.svelte +553 -0
  20. package/dist/components/form/FormMarkdownEditor.svelte.d.ts +29 -0
  21. package/dist/components/form/FormNumberField.svelte +5 -6
  22. package/dist/components/form/FormRangeField.svelte +3 -13
  23. package/dist/components/form/FormSelect.svelte +4 -5
  24. package/dist/components/form/FormSelect.svelte.d.ts +1 -1
  25. package/dist/components/form/FormTemplateEditor.svelte +463 -0
  26. package/dist/components/form/FormTemplateEditor.svelte.d.ts +25 -0
  27. package/dist/components/form/FormTextField.svelte +3 -4
  28. package/dist/components/form/FormTextarea.svelte +3 -4
  29. package/dist/components/form/FormToggle.svelte +2 -3
  30. package/dist/components/form/index.d.ts +14 -11
  31. package/dist/components/form/index.js +14 -11
  32. package/dist/components/form/types.d.ts +55 -2
  33. package/dist/components/form/types.js +1 -1
  34. package/dist/components/nodes/NotesNode.svelte +39 -45
  35. package/dist/components/nodes/NotesNode.svelte.d.ts +1 -1
  36. package/dist/components/nodes/WorkflowNode.svelte +1 -3
  37. package/dist/styles/base.css +1 -1
  38. package/package.json +162 -148
@@ -0,0 +1,463 @@
1
+ <!--
2
+ FormTemplateEditor Component
3
+ CodeMirror-based template editor for Twig/Liquid-style templates
4
+
5
+ Features:
6
+ - Custom syntax highlighting for {{ variable }} placeholders
7
+ - Dark/light theme support
8
+ - Consistent styling with other form components
9
+ - Line wrapping for better template readability
10
+ - Optional variable hints display
11
+ - Proper ARIA attributes for accessibility
12
+
13
+ Usage:
14
+ Use with schema format: "template" to render this editor
15
+ -->
16
+
17
+ <script lang="ts">
18
+ import { onMount, onDestroy } from 'svelte';
19
+ import { EditorView, basicSetup } from 'codemirror';
20
+ import { EditorState } from '@codemirror/state';
21
+ import {
22
+ Decoration,
23
+ type DecorationSet,
24
+ ViewPlugin,
25
+ type ViewUpdate,
26
+ MatchDecorator
27
+ } from '@codemirror/view';
28
+ import { oneDark } from '@codemirror/theme-one-dark';
29
+
30
+ interface Props {
31
+ /** Field identifier */
32
+ id: string;
33
+ /** Current template value */
34
+ value: string;
35
+ /** Placeholder text shown when empty */
36
+ placeholder?: string;
37
+ /** Whether the field is required */
38
+ required?: boolean;
39
+ /** Whether to use dark theme */
40
+ darkTheme?: boolean;
41
+ /** Editor height in pixels or CSS value */
42
+ height?: string;
43
+ /** Available variable names for hints (optional) */
44
+ variableHints?: string[];
45
+ /** Placeholder variable example for the hint */
46
+ placeholderExample?: string;
47
+ /** ARIA description ID */
48
+ ariaDescribedBy?: string;
49
+ /** Callback when value changes */
50
+ onChange: (value: string) => void;
51
+ }
52
+
53
+ let {
54
+ id,
55
+ value = '',
56
+ placeholder = 'Enter your template here...\nUse {{ variable }} for dynamic values.',
57
+ required = false,
58
+ darkTheme = false,
59
+ height = '250px',
60
+ variableHints = [],
61
+ placeholderExample = 'Hello {{ name }}, your order #{{ order_id }} is ready!',
62
+ ariaDescribedBy,
63
+ onChange
64
+ }: Props = $props();
65
+
66
+ /** Reference to the container element */
67
+ let containerRef: HTMLDivElement | undefined = $state(undefined);
68
+
69
+ /** CodeMirror editor instance */
70
+ let editorView: EditorView | undefined = $state(undefined);
71
+
72
+ /** Flag to prevent update loops */
73
+ let isInternalUpdate = false;
74
+
75
+ /**
76
+ * Create a MatchDecorator for {{ variable }} patterns
77
+ * This highlights the entire {{ variable }} expression
78
+ */
79
+ const variableMatcher = new MatchDecorator({
80
+ // Match {{ variable_name }} patterns (with optional whitespace)
81
+ regexp: /\{\{\s*[\w.]+\s*\}\}/g,
82
+ decoration: Decoration.mark({ class: 'cm-template-variable' })
83
+ });
84
+
85
+ /**
86
+ * ViewPlugin that applies the variable highlighting decorations
87
+ */
88
+ const variableHighlighter = ViewPlugin.fromClass(
89
+ class {
90
+ decorations: DecorationSet;
91
+ constructor(view: EditorView) {
92
+ this.decorations = variableMatcher.createDeco(view);
93
+ }
94
+ update(update: ViewUpdate) {
95
+ this.decorations = variableMatcher.updateDeco(update, this.decorations);
96
+ }
97
+ },
98
+ {
99
+ decorations: (v) => v.decorations
100
+ }
101
+ );
102
+
103
+ /**
104
+ * Handle editor content changes
105
+ */
106
+ function handleUpdate(update: { docChanged: boolean; state: EditorState }): void {
107
+ if (!update.docChanged || isInternalUpdate) {
108
+ return;
109
+ }
110
+
111
+ const content = update.state.doc.toString();
112
+ onChange(content);
113
+ }
114
+
115
+ /**
116
+ * Create editor extensions array for template editing
117
+ */
118
+ function createExtensions() {
119
+ const extensions = [
120
+ basicSetup,
121
+ variableHighlighter,
122
+ EditorView.updateListener.of(handleUpdate),
123
+ EditorView.theme({
124
+ '&': {
125
+ height: height,
126
+ fontSize: '0.875rem',
127
+ fontFamily: "'JetBrains Mono', 'Fira Code', 'Monaco', 'Menlo', monospace"
128
+ },
129
+ '.cm-scroller': {
130
+ overflow: 'auto'
131
+ },
132
+ '.cm-content': {
133
+ minHeight: '100px',
134
+ padding: '0.5rem 0'
135
+ },
136
+ '&.cm-focused': {
137
+ outline: 'none'
138
+ },
139
+ '.cm-line': {
140
+ padding: '0 0.5rem'
141
+ },
142
+ // Style for the highlighted {{ variable }} pattern
143
+ '.cm-template-variable': {
144
+ color: '#a855f7',
145
+ backgroundColor: 'rgba(168, 85, 247, 0.1)',
146
+ borderRadius: '3px',
147
+ padding: '1px 2px',
148
+ fontWeight: '500'
149
+ }
150
+ }),
151
+ EditorView.lineWrapping,
152
+ EditorState.tabSize.of(2)
153
+ ];
154
+
155
+ if (darkTheme) {
156
+ extensions.push(oneDark);
157
+ // Add dark theme override for variable highlighting
158
+ extensions.push(
159
+ EditorView.theme({
160
+ '.cm-template-variable': {
161
+ color: '#c084fc',
162
+ backgroundColor: 'rgba(192, 132, 252, 0.15)'
163
+ }
164
+ })
165
+ );
166
+ }
167
+
168
+ return extensions;
169
+ }
170
+
171
+ /**
172
+ * Insert a variable placeholder at current cursor position
173
+ */
174
+ function insertVariable(varName: string): void {
175
+ if (!editorView) {
176
+ return;
177
+ }
178
+
179
+ const insertText = `{{ ${varName} }}`;
180
+ const { from, to } = editorView.state.selection.main;
181
+
182
+ editorView.dispatch({
183
+ changes: { from, to, insert: insertText },
184
+ selection: { anchor: from + insertText.length }
185
+ });
186
+
187
+ editorView.focus();
188
+ }
189
+
190
+ /**
191
+ * Initialize CodeMirror editor on mount
192
+ */
193
+ onMount(() => {
194
+ if (!containerRef) {
195
+ return;
196
+ }
197
+
198
+ editorView = new EditorView({
199
+ state: EditorState.create({
200
+ doc: value,
201
+ extensions: createExtensions()
202
+ }),
203
+ parent: containerRef
204
+ });
205
+ });
206
+
207
+ /**
208
+ * Clean up editor on destroy
209
+ */
210
+ onDestroy(() => {
211
+ if (editorView) {
212
+ editorView.destroy();
213
+ }
214
+ });
215
+
216
+ /**
217
+ * Update editor content when value prop changes externally
218
+ */
219
+ $effect(() => {
220
+ if (!editorView) {
221
+ return;
222
+ }
223
+
224
+ const currentContent = editorView.state.doc.toString();
225
+
226
+ // Only update if content actually changed and wasn't from internal edit
227
+ if (value !== currentContent && !isInternalUpdate) {
228
+ isInternalUpdate = true;
229
+ editorView.dispatch({
230
+ changes: {
231
+ from: 0,
232
+ to: editorView.state.doc.length,
233
+ insert: value
234
+ }
235
+ });
236
+ isInternalUpdate = false;
237
+ }
238
+ });
239
+ </script>
240
+
241
+ <div class="form-template-editor">
242
+ <!-- Hidden input for form submission compatibility -->
243
+ <input
244
+ type="hidden"
245
+ {id}
246
+ name={id}
247
+ {value}
248
+ aria-describedby={ariaDescribedBy}
249
+ aria-required={required}
250
+ />
251
+
252
+ <!-- CodeMirror container -->
253
+ <div
254
+ bind:this={containerRef}
255
+ class="form-template-editor__container"
256
+ class:form-template-editor__container--dark={darkTheme}
257
+ role="textbox"
258
+ aria-multiline="true"
259
+ aria-label="Template editor"
260
+ ></div>
261
+
262
+ <!-- Variable hints section (shown when variables are available) -->
263
+ {#if variableHints.length > 0}
264
+ <div class="form-template-editor__hints">
265
+ <span class="form-template-editor__hints-label">Available variables:</span>
266
+ <div class="form-template-editor__hints-list">
267
+ {#each variableHints as varName (varName)}
268
+ <button
269
+ type="button"
270
+ class="form-template-editor__hint-btn"
271
+ onclick={() => insertVariable(varName)}
272
+ title={`Insert {{ ${varName} }}`}
273
+ >
274
+ <code>{'{{ '}{varName}{' }}'}</code>
275
+ </button>
276
+ {/each}
277
+ </div>
278
+ </div>
279
+ {/if}
280
+
281
+ <!-- Placeholder hint when empty -->
282
+ {#if !value && placeholderExample}
283
+ <div class="form-template-editor__placeholder">
284
+ <span class="form-template-editor__placeholder-label">Example template:</span>
285
+ <code class="form-template-editor__placeholder-example">{placeholderExample}</code>
286
+ </div>
287
+ {/if}
288
+
289
+ <!-- Syntax help -->
290
+ <div class="form-template-editor__help">
291
+ <svg
292
+ xmlns="http://www.w3.org/2000/svg"
293
+ viewBox="0 0 20 20"
294
+ fill="currentColor"
295
+ class="form-template-editor__help-icon"
296
+ >
297
+ <path
298
+ fill-rule="evenodd"
299
+ d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9z"
300
+ clip-rule="evenodd"
301
+ />
302
+ </svg>
303
+ <span
304
+ >Use <code>{'{{ variable }}'}</code> syntax to insert dynamic values from the data input</span
305
+ >
306
+ </div>
307
+ </div>
308
+
309
+ <style>
310
+ .form-template-editor {
311
+ position: relative;
312
+ width: 100%;
313
+ }
314
+
315
+ .form-template-editor__container {
316
+ border: 1px solid var(--color-ref-gray-200, #e5e7eb);
317
+ border-radius: 0.5rem;
318
+ overflow: hidden;
319
+ background-color: var(--color-ref-gray-50, #f9fafb);
320
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
321
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
322
+ }
323
+
324
+ .form-template-editor__container:hover {
325
+ border-color: var(--color-ref-gray-300, #d1d5db);
326
+ background-color: #ffffff;
327
+ }
328
+
329
+ .form-template-editor__container:focus-within {
330
+ border-color: var(--color-ref-purple-500, #a855f7);
331
+ background-color: #ffffff;
332
+ box-shadow:
333
+ 0 0 0 3px rgba(168, 85, 247, 0.12),
334
+ 0 1px 2px rgba(0, 0, 0, 0.04);
335
+ }
336
+
337
+ /* Dark theme overrides */
338
+ .form-template-editor__container--dark {
339
+ background-color: #282c34;
340
+ }
341
+
342
+ .form-template-editor__container--dark:hover,
343
+ .form-template-editor__container--dark:focus-within {
344
+ background-color: #282c34;
345
+ }
346
+
347
+ /* CodeMirror styling overrides */
348
+ .form-template-editor__container :global(.cm-editor) {
349
+ border-radius: 0.5rem;
350
+ }
351
+
352
+ .form-template-editor__container :global(.cm-gutters) {
353
+ background-color: var(--color-ref-gray-100, #f3f4f6);
354
+ border-right: 1px solid var(--color-ref-gray-200, #e5e7eb);
355
+ border-radius: 0.5rem 0 0 0.5rem;
356
+ }
357
+
358
+ .form-template-editor__container--dark :global(.cm-gutters) {
359
+ background-color: #21252b;
360
+ border-right-color: #3e4451;
361
+ }
362
+
363
+ /* Variable hints section */
364
+ .form-template-editor__hints {
365
+ margin-top: 0.625rem;
366
+ padding: 0.625rem;
367
+ background-color: var(--color-ref-purple-50, #faf5ff);
368
+ border: 1px solid var(--color-ref-purple-200, #e9d5ff);
369
+ border-radius: 0.375rem;
370
+ }
371
+
372
+ .form-template-editor__hints-label {
373
+ display: block;
374
+ font-size: 0.6875rem;
375
+ font-weight: 500;
376
+ color: var(--color-ref-purple-700, #7e22ce);
377
+ text-transform: uppercase;
378
+ letter-spacing: 0.05em;
379
+ margin-bottom: 0.375rem;
380
+ }
381
+
382
+ .form-template-editor__hints-list {
383
+ display: flex;
384
+ flex-wrap: wrap;
385
+ gap: 0.375rem;
386
+ }
387
+
388
+ .form-template-editor__hint-btn {
389
+ padding: 0.25rem 0.5rem;
390
+ background-color: var(--color-ref-purple-100, #f3e8ff);
391
+ border: 1px solid var(--color-ref-purple-300, #d8b4fe);
392
+ border-radius: 0.25rem;
393
+ cursor: pointer;
394
+ transition: all 0.15s ease;
395
+ }
396
+
397
+ .form-template-editor__hint-btn:hover {
398
+ background-color: var(--color-ref-purple-200, #e9d5ff);
399
+ border-color: var(--color-ref-purple-400, #c084fc);
400
+ }
401
+
402
+ .form-template-editor__hint-btn:active {
403
+ transform: scale(0.98);
404
+ }
405
+
406
+ .form-template-editor__hint-btn code {
407
+ font-family: 'JetBrains Mono', 'Fira Code', 'Monaco', 'Menlo', monospace;
408
+ font-size: 0.6875rem;
409
+ color: var(--color-ref-purple-800, #6b21a8);
410
+ }
411
+
412
+ /* Placeholder hint */
413
+ .form-template-editor__placeholder {
414
+ margin-top: 0.5rem;
415
+ padding: 0.5rem 0.75rem;
416
+ background-color: var(--color-ref-gray-50, #f9fafb);
417
+ border: 1px dashed var(--color-ref-gray-300, #d1d5db);
418
+ border-radius: 0.375rem;
419
+ }
420
+
421
+ .form-template-editor__placeholder-label {
422
+ display: block;
423
+ font-size: 0.6875rem;
424
+ font-weight: 500;
425
+ color: var(--color-ref-gray-500, #6b7280);
426
+ text-transform: uppercase;
427
+ letter-spacing: 0.05em;
428
+ margin-bottom: 0.25rem;
429
+ }
430
+
431
+ .form-template-editor__placeholder-example {
432
+ display: block;
433
+ font-family: 'JetBrains Mono', 'Fira Code', 'Monaco', 'Menlo', monospace;
434
+ font-size: 0.75rem;
435
+ color: var(--color-ref-gray-700, #374151);
436
+ word-break: break-all;
437
+ }
438
+
439
+ /* Help text */
440
+ .form-template-editor__help {
441
+ display: flex;
442
+ align-items: flex-start;
443
+ gap: 0.375rem;
444
+ margin-top: 0.5rem;
445
+ font-size: 0.6875rem;
446
+ color: var(--color-ref-gray-500, #6b7280);
447
+ }
448
+
449
+ .form-template-editor__help-icon {
450
+ width: 0.875rem;
451
+ height: 0.875rem;
452
+ flex-shrink: 0;
453
+ margin-top: 0.0625rem;
454
+ }
455
+
456
+ .form-template-editor__help code {
457
+ padding: 0.0625rem 0.25rem;
458
+ background-color: var(--color-ref-gray-100, #f3f4f6);
459
+ border-radius: 0.1875rem;
460
+ font-family: 'JetBrains Mono', 'Fira Code', 'Monaco', 'Menlo', monospace;
461
+ font-size: 0.625rem;
462
+ }
463
+ </style>
@@ -0,0 +1,25 @@
1
+ interface Props {
2
+ /** Field identifier */
3
+ id: string;
4
+ /** Current template value */
5
+ value: string;
6
+ /** Placeholder text shown when empty */
7
+ placeholder?: string;
8
+ /** Whether the field is required */
9
+ required?: boolean;
10
+ /** Whether to use dark theme */
11
+ darkTheme?: boolean;
12
+ /** Editor height in pixels or CSS value */
13
+ height?: string;
14
+ /** Available variable names for hints (optional) */
15
+ variableHints?: string[];
16
+ /** Placeholder variable example for the hint */
17
+ placeholderExample?: string;
18
+ /** ARIA description ID */
19
+ ariaDescribedBy?: string;
20
+ /** Callback when value changes */
21
+ onChange: (value: string) => void;
22
+ }
23
+ declare const FormTemplateEditor: import("svelte").Component<Props, {}, "">;
24
+ type FormTemplateEditor = ReturnType<typeof FormTemplateEditor>;
25
+ export default FormTemplateEditor;
@@ -26,8 +26,8 @@
26
26
 
27
27
  let {
28
28
  id,
29
- value = "",
30
- placeholder = "",
29
+ value = '',
30
+ placeholder = '',
31
31
  required = false,
32
32
  ariaDescribedBy,
33
33
  onChange
@@ -46,7 +46,7 @@
46
46
  {id}
47
47
  type="text"
48
48
  class="form-text-field"
49
- value={value ?? ""}
49
+ value={value ?? ''}
50
50
  {placeholder}
51
51
  aria-describedby={ariaDescribedBy}
52
52
  aria-required={required}
@@ -85,4 +85,3 @@
85
85
  0 1px 2px rgba(0, 0, 0, 0.04);
86
86
  }
87
87
  </style>
88
-
@@ -28,8 +28,8 @@
28
28
 
29
29
  let {
30
30
  id,
31
- value = "",
32
- placeholder = "",
31
+ value = '',
32
+ placeholder = '',
33
33
  rows = 4,
34
34
  required = false,
35
35
  ariaDescribedBy,
@@ -48,7 +48,7 @@
48
48
  <textarea
49
49
  {id}
50
50
  class="form-textarea"
51
- value={value ?? ""}
51
+ value={value ?? ''}
52
52
  {placeholder}
53
53
  {rows}
54
54
  aria-describedby={ariaDescribedBy}
@@ -91,4 +91,3 @@
91
91
  0 1px 2px rgba(0, 0, 0, 0.04);
92
92
  }
93
93
  </style>
94
-
@@ -27,8 +27,8 @@
27
27
  let {
28
28
  id,
29
29
  value = false,
30
- onLabel = "Enabled",
31
- offLabel = "Disabled",
30
+ onLabel = 'Enabled',
31
+ offLabel = 'Disabled',
32
32
  ariaDescribedBy,
33
33
  onChange
34
34
  }: Props = $props();
@@ -120,4 +120,3 @@
120
120
  color: var(--color-ref-blue-600, #2563eb);
121
121
  }
122
122
  </style>
123
-
@@ -29,14 +29,17 @@
29
29
  * />
30
30
  * ```
31
31
  */
32
- export * from "./types.js";
33
- export { default as FormField } from "./FormField.svelte";
34
- export { default as FormFieldWrapper } from "./FormFieldWrapper.svelte";
35
- export { default as FormTextField } from "./FormTextField.svelte";
36
- export { default as FormTextarea } from "./FormTextarea.svelte";
37
- export { default as FormNumberField } from "./FormNumberField.svelte";
38
- export { default as FormRangeField } from "./FormRangeField.svelte";
39
- export { default as FormToggle } from "./FormToggle.svelte";
40
- export { default as FormSelect } from "./FormSelect.svelte";
41
- export { default as FormCheckboxGroup } from "./FormCheckboxGroup.svelte";
42
- export { default as FormArray } from "./FormArray.svelte";
32
+ export * from './types.js';
33
+ export { default as FormField } from './FormField.svelte';
34
+ export { default as FormFieldWrapper } from './FormFieldWrapper.svelte';
35
+ export { default as FormTextField } from './FormTextField.svelte';
36
+ export { default as FormTextarea } from './FormTextarea.svelte';
37
+ export { default as FormNumberField } from './FormNumberField.svelte';
38
+ export { default as FormRangeField } from './FormRangeField.svelte';
39
+ export { default as FormToggle } from './FormToggle.svelte';
40
+ export { default as FormSelect } from './FormSelect.svelte';
41
+ export { default as FormCheckboxGroup } from './FormCheckboxGroup.svelte';
42
+ export { default as FormArray } from './FormArray.svelte';
43
+ export { default as FormCodeEditor } from './FormCodeEditor.svelte';
44
+ export { default as FormMarkdownEditor } from './FormMarkdownEditor.svelte';
45
+ export { default as FormTemplateEditor } from './FormTemplateEditor.svelte';
@@ -30,17 +30,20 @@
30
30
  * ```
31
31
  */
32
32
  // Types
33
- export * from "./types.js";
33
+ export * from './types.js';
34
34
  // Main factory component
35
- export { default as FormField } from "./FormField.svelte";
35
+ export { default as FormField } from './FormField.svelte';
36
36
  // Wrapper component
37
- export { default as FormFieldWrapper } from "./FormFieldWrapper.svelte";
37
+ export { default as FormFieldWrapper } from './FormFieldWrapper.svelte';
38
38
  // Individual field components
39
- export { default as FormTextField } from "./FormTextField.svelte";
40
- export { default as FormTextarea } from "./FormTextarea.svelte";
41
- export { default as FormNumberField } from "./FormNumberField.svelte";
42
- export { default as FormRangeField } from "./FormRangeField.svelte";
43
- export { default as FormToggle } from "./FormToggle.svelte";
44
- export { default as FormSelect } from "./FormSelect.svelte";
45
- export { default as FormCheckboxGroup } from "./FormCheckboxGroup.svelte";
46
- export { default as FormArray } from "./FormArray.svelte";
39
+ export { default as FormTextField } from './FormTextField.svelte';
40
+ export { default as FormTextarea } from './FormTextarea.svelte';
41
+ export { default as FormNumberField } from './FormNumberField.svelte';
42
+ export { default as FormRangeField } from './FormRangeField.svelte';
43
+ export { default as FormToggle } from './FormToggle.svelte';
44
+ export { default as FormSelect } from './FormSelect.svelte';
45
+ export { default as FormCheckboxGroup } from './FormCheckboxGroup.svelte';
46
+ export { default as FormArray } from './FormArray.svelte';
47
+ export { default as FormCodeEditor } from './FormCodeEditor.svelte';
48
+ export { default as FormMarkdownEditor } from './FormMarkdownEditor.svelte';
49
+ export { default as FormTemplateEditor } from './FormTemplateEditor.svelte';
@@ -9,14 +9,18 @@
9
9
  * Supported field types for form rendering
10
10
  * Can be extended to support complex types like 'array' and 'object'
11
11
  */
12
- export type FieldType = "string" | "number" | "integer" | "boolean" | "select" | "array" | "object";
12
+ export type FieldType = 'string' | 'number' | 'integer' | 'boolean' | 'select' | 'array' | 'object';
13
13
  /**
14
14
  * Field format for specialized rendering
15
15
  * - multiline: Renders as textarea
16
16
  * - hidden: Field is hidden from UI but included in form submission
17
17
  * - range: Renders as range slider for numeric values
18
+ * - json: Renders as CodeMirror JSON editor
19
+ * - code: Alias for json, renders as CodeMirror editor
20
+ * - markdown: Renders as SimpleMDE Markdown editor
21
+ * - template: Renders as CodeMirror editor with Twig/Liquid syntax highlighting
18
22
  */
19
- export type FieldFormat = "multiline" | "hidden" | "range" | string;
23
+ export type FieldFormat = 'multiline' | 'hidden' | 'range' | 'json' | 'code' | 'markdown' | 'template' | string;
20
24
  /**
21
25
  * Option type for select and checkbox group fields
22
26
  */
@@ -131,6 +135,55 @@ export interface ArrayFieldProps extends BaseFieldProps {
131
135
  addLabel?: string;
132
136
  onChange: (value: unknown[]) => void;
133
137
  }
138
+ /**
139
+ * Properties for code editor fields (CodeMirror-based)
140
+ */
141
+ export interface CodeEditorFieldProps extends BaseFieldProps {
142
+ /** Current value - can be string (raw JSON) or object */
143
+ value: unknown;
144
+ /** Whether to use dark theme */
145
+ darkTheme?: boolean;
146
+ /** Editor height in pixels or CSS value */
147
+ height?: string;
148
+ /** Whether to auto-format JSON on blur */
149
+ autoFormat?: boolean;
150
+ /** Callback when value changes */
151
+ onChange: (value: unknown) => void;
152
+ }
153
+ /**
154
+ * Properties for markdown editor fields (SimpleMDE-based)
155
+ */
156
+ export interface MarkdownEditorFieldProps extends BaseFieldProps {
157
+ /** Current value (markdown string) */
158
+ value: string;
159
+ /** Editor height in pixels or CSS value */
160
+ height?: string;
161
+ /** Whether to show the toolbar */
162
+ showToolbar?: boolean;
163
+ /** Whether to show the status bar */
164
+ showStatusBar?: boolean;
165
+ /** Whether to enable spell checking */
166
+ spellChecker?: boolean;
167
+ /** Callback when value changes */
168
+ onChange: (value: string) => void;
169
+ }
170
+ /**
171
+ * Properties for template editor fields (CodeMirror with Twig/Liquid syntax)
172
+ */
173
+ export interface TemplateEditorFieldProps extends BaseFieldProps {
174
+ /** Current template value */
175
+ value: string;
176
+ /** Whether to use dark theme */
177
+ darkTheme?: boolean;
178
+ /** Editor height in pixels or CSS value */
179
+ height?: string;
180
+ /** Available variable names for hints (optional) */
181
+ variableHints?: string[];
182
+ /** Placeholder variable example for the hint */
183
+ placeholderExample?: string;
184
+ /** Callback when value changes */
185
+ onChange: (value: string) => void;
186
+ }
134
187
  /**
135
188
  * Field schema definition derived from JSON Schema property
136
189
  * Used to determine which field component to render