@d34dman/flowdrop 0.0.23 → 0.0.25
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/ConfigForm.svelte +1 -1
- package/dist/components/form/FormCodeEditor.svelte +415 -0
- package/dist/components/form/FormCodeEditor.svelte.d.ts +23 -0
- package/dist/components/form/FormField.svelte +137 -68
- package/dist/components/form/FormField.svelte.d.ts +1 -1
- package/dist/components/form/FormMarkdownEditor.svelte +553 -0
- package/dist/components/form/FormMarkdownEditor.svelte.d.ts +29 -0
- package/dist/components/form/FormRangeField.svelte +252 -0
- package/dist/components/form/FormRangeField.svelte.d.ts +21 -0
- package/dist/components/form/FormTemplateEditor.svelte +463 -0
- package/dist/components/form/FormTemplateEditor.svelte.d.ts +25 -0
- package/dist/components/form/index.d.ts +4 -0
- package/dist/components/form/index.js +4 -0
- package/dist/components/form/types.d.ts +70 -1
- package/dist/components/nodes/GatewayNode.svelte +1 -13
- package/dist/index.d.ts +1 -1
- package/dist/types/index.d.ts +99 -1
- package/package.json +9 -3
|
@@ -5,31 +5,40 @@
|
|
|
5
5
|
Features:
|
|
6
6
|
- Automatically selects the correct field component based on schema
|
|
7
7
|
- Wraps fields with FormFieldWrapper for consistent layout
|
|
8
|
-
- Supports all current field types (string, number, boolean, select, checkbox group)
|
|
8
|
+
- Supports all current field types (string, number, boolean, select, checkbox group, range, json, markdown, template)
|
|
9
9
|
- Extensible architecture for future complex types (array, object)
|
|
10
10
|
|
|
11
11
|
Type Resolution Order:
|
|
12
12
|
1. format: 'hidden' -> skip rendering (return nothing)
|
|
13
|
-
2.
|
|
14
|
-
3.
|
|
15
|
-
4. format: '
|
|
16
|
-
5.
|
|
17
|
-
6.
|
|
18
|
-
7.
|
|
19
|
-
8.
|
|
20
|
-
9.
|
|
13
|
+
2. format: 'json' or 'code' -> FormCodeEditor (CodeMirror JSON editor)
|
|
14
|
+
3. format: 'markdown' -> FormMarkdownEditor (SimpleMDE Markdown editor)
|
|
15
|
+
4. format: 'template' -> FormTemplateEditor (CodeMirror with Twig/Liquid syntax)
|
|
16
|
+
5. enum with multiple: true -> FormCheckboxGroup
|
|
17
|
+
6. enum -> FormSelect
|
|
18
|
+
7. format: 'multiline' -> FormTextarea
|
|
19
|
+
8. format: 'range' (number/integer) -> FormRangeField
|
|
20
|
+
9. type: 'string' -> FormTextField
|
|
21
|
+
10. type: 'number' or 'integer' -> FormNumberField
|
|
22
|
+
11. type: 'boolean' -> FormToggle
|
|
23
|
+
12. type: 'select' or has options -> FormSelect
|
|
24
|
+
13. type: 'object' (without format) -> FormCodeEditor (for JSON objects)
|
|
25
|
+
14. fallback -> FormTextField
|
|
21
26
|
-->
|
|
22
27
|
|
|
23
28
|
<script lang="ts">
|
|
24
|
-
import FormFieldWrapper from
|
|
25
|
-
import FormTextField from
|
|
26
|
-
import FormTextarea from
|
|
27
|
-
import FormNumberField from
|
|
28
|
-
import
|
|
29
|
-
import
|
|
30
|
-
import
|
|
31
|
-
import
|
|
32
|
-
import
|
|
29
|
+
import FormFieldWrapper from './FormFieldWrapper.svelte';
|
|
30
|
+
import FormTextField from './FormTextField.svelte';
|
|
31
|
+
import FormTextarea from './FormTextarea.svelte';
|
|
32
|
+
import FormNumberField from './FormNumberField.svelte';
|
|
33
|
+
import FormRangeField from './FormRangeField.svelte';
|
|
34
|
+
import FormToggle from './FormToggle.svelte';
|
|
35
|
+
import FormSelect from './FormSelect.svelte';
|
|
36
|
+
import FormCheckboxGroup from './FormCheckboxGroup.svelte';
|
|
37
|
+
import FormArray from './FormArray.svelte';
|
|
38
|
+
import FormCodeEditor from './FormCodeEditor.svelte';
|
|
39
|
+
import FormMarkdownEditor from './FormMarkdownEditor.svelte';
|
|
40
|
+
import FormTemplateEditor from './FormTemplateEditor.svelte';
|
|
41
|
+
import type { FieldSchema, FieldOption } from './types.js';
|
|
33
42
|
|
|
34
43
|
interface Props {
|
|
35
44
|
/** Unique key/id for the field */
|
|
@@ -46,19 +55,14 @@
|
|
|
46
55
|
onChange: (value: unknown) => void;
|
|
47
56
|
}
|
|
48
57
|
|
|
49
|
-
let {
|
|
50
|
-
fieldKey,
|
|
51
|
-
schema,
|
|
52
|
-
value,
|
|
53
|
-
required = false,
|
|
54
|
-
animationIndex = 0,
|
|
55
|
-
onChange
|
|
56
|
-
}: Props = $props();
|
|
58
|
+
let { fieldKey, schema, value, required = false, animationIndex = 0, onChange }: Props = $props();
|
|
57
59
|
|
|
58
60
|
/**
|
|
59
61
|
* Computed description ID for ARIA association
|
|
60
62
|
*/
|
|
61
|
-
const descriptionId = $derived(
|
|
63
|
+
const descriptionId = $derived(
|
|
64
|
+
schema.description && schema.title ? `${fieldKey}-description` : undefined
|
|
65
|
+
);
|
|
62
66
|
|
|
63
67
|
/**
|
|
64
68
|
* Animation delay based on index
|
|
@@ -75,57 +79,77 @@
|
|
|
75
79
|
*/
|
|
76
80
|
const fieldType = $derived.by(() => {
|
|
77
81
|
// Hidden fields should not be rendered
|
|
78
|
-
if (schema.format ===
|
|
79
|
-
return
|
|
82
|
+
if (schema.format === 'hidden') {
|
|
83
|
+
return 'hidden';
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// JSON/code editor for format: "json" or "code"
|
|
87
|
+
if (schema.format === 'json' || schema.format === 'code') {
|
|
88
|
+
return 'code-editor';
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Markdown editor for format: "markdown"
|
|
92
|
+
if (schema.format === 'markdown') {
|
|
93
|
+
return 'markdown-editor';
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Template editor for format: "template" (Twig/Liquid syntax)
|
|
97
|
+
if (schema.format === 'template') {
|
|
98
|
+
return 'template-editor';
|
|
80
99
|
}
|
|
81
100
|
|
|
82
101
|
// Enum with multiple selection -> checkbox group
|
|
83
102
|
if (schema.enum && schema.multiple) {
|
|
84
|
-
return
|
|
103
|
+
return 'checkbox-group';
|
|
85
104
|
}
|
|
86
105
|
|
|
87
106
|
// Enum with single selection -> select
|
|
88
107
|
if (schema.enum) {
|
|
89
|
-
return
|
|
108
|
+
return 'select-enum';
|
|
90
109
|
}
|
|
91
110
|
|
|
92
111
|
// Multiline string -> textarea
|
|
93
|
-
if (schema.type ===
|
|
94
|
-
return
|
|
112
|
+
if (schema.type === 'string' && schema.format === 'multiline') {
|
|
113
|
+
return 'textarea';
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Range slider for number/integer with format: "range"
|
|
117
|
+
if ((schema.type === 'number' || schema.type === 'integer') && schema.format === 'range') {
|
|
118
|
+
return 'range';
|
|
95
119
|
}
|
|
96
120
|
|
|
97
121
|
// String -> text field
|
|
98
|
-
if (schema.type ===
|
|
99
|
-
return
|
|
122
|
+
if (schema.type === 'string') {
|
|
123
|
+
return 'text';
|
|
100
124
|
}
|
|
101
125
|
|
|
102
126
|
// Number or integer -> number field
|
|
103
|
-
if (schema.type ===
|
|
104
|
-
return
|
|
127
|
+
if (schema.type === 'number' || schema.type === 'integer') {
|
|
128
|
+
return 'number';
|
|
105
129
|
}
|
|
106
130
|
|
|
107
131
|
// Boolean -> toggle
|
|
108
|
-
if (schema.type ===
|
|
109
|
-
return
|
|
132
|
+
if (schema.type === 'boolean') {
|
|
133
|
+
return 'toggle';
|
|
110
134
|
}
|
|
111
135
|
|
|
112
136
|
// Select type or has options -> select
|
|
113
|
-
if (schema.type ===
|
|
114
|
-
return
|
|
137
|
+
if (schema.type === 'select' || schema.options) {
|
|
138
|
+
return 'select-options';
|
|
115
139
|
}
|
|
116
140
|
|
|
117
141
|
// Future: Array type support
|
|
118
|
-
if (schema.type ===
|
|
119
|
-
return
|
|
142
|
+
if (schema.type === 'array') {
|
|
143
|
+
return 'array';
|
|
120
144
|
}
|
|
121
145
|
|
|
122
|
-
//
|
|
123
|
-
if (schema.type ===
|
|
124
|
-
return
|
|
146
|
+
// Object type without specific format -> CodeMirror JSON editor
|
|
147
|
+
if (schema.type === 'object') {
|
|
148
|
+
return 'code-editor';
|
|
125
149
|
}
|
|
126
150
|
|
|
127
151
|
// Fallback to text
|
|
128
|
-
return
|
|
152
|
+
return 'text';
|
|
129
153
|
});
|
|
130
154
|
|
|
131
155
|
/**
|
|
@@ -147,7 +171,7 @@
|
|
|
147
171
|
/**
|
|
148
172
|
* Get current value as the appropriate type
|
|
149
173
|
*/
|
|
150
|
-
const stringValue = $derived(String(value ??
|
|
174
|
+
const stringValue = $derived(String(value ?? ''));
|
|
151
175
|
const numberValue = $derived(value as number | string);
|
|
152
176
|
const booleanValue = $derived(Boolean(value ?? schema.default ?? false));
|
|
153
177
|
const arrayValue = $derived.by((): string[] => {
|
|
@@ -164,7 +188,7 @@
|
|
|
164
188
|
});
|
|
165
189
|
</script>
|
|
166
190
|
|
|
167
|
-
{#if fieldType !==
|
|
191
|
+
{#if fieldType !== 'hidden'}
|
|
168
192
|
<FormFieldWrapper
|
|
169
193
|
id={fieldKey}
|
|
170
194
|
label={fieldLabel}
|
|
@@ -172,7 +196,7 @@
|
|
|
172
196
|
description={schema.title ? schema.description : undefined}
|
|
173
197
|
{animationDelay}
|
|
174
198
|
>
|
|
175
|
-
{#if fieldType ===
|
|
199
|
+
{#if fieldType === 'checkbox-group'}
|
|
176
200
|
<FormCheckboxGroup
|
|
177
201
|
id={fieldKey}
|
|
178
202
|
value={arrayValue}
|
|
@@ -180,7 +204,7 @@
|
|
|
180
204
|
ariaDescribedBy={descriptionId}
|
|
181
205
|
onChange={(val) => onChange(val)}
|
|
182
206
|
/>
|
|
183
|
-
{:else if fieldType ===
|
|
207
|
+
{:else if fieldType === 'select-enum'}
|
|
184
208
|
<FormSelect
|
|
185
209
|
id={fieldKey}
|
|
186
210
|
value={stringValue}
|
|
@@ -189,43 +213,54 @@
|
|
|
189
213
|
ariaDescribedBy={descriptionId}
|
|
190
214
|
onChange={(val) => onChange(val)}
|
|
191
215
|
/>
|
|
192
|
-
{:else if fieldType ===
|
|
216
|
+
{:else if fieldType === 'textarea'}
|
|
193
217
|
<FormTextarea
|
|
194
218
|
id={fieldKey}
|
|
195
219
|
value={stringValue}
|
|
196
|
-
placeholder={schema.placeholder ??
|
|
220
|
+
placeholder={schema.placeholder ?? ''}
|
|
197
221
|
{required}
|
|
198
222
|
ariaDescribedBy={descriptionId}
|
|
199
223
|
onChange={(val) => onChange(val)}
|
|
200
224
|
/>
|
|
201
|
-
{:else if fieldType ===
|
|
225
|
+
{:else if fieldType === 'text'}
|
|
202
226
|
<FormTextField
|
|
203
227
|
id={fieldKey}
|
|
204
228
|
value={stringValue}
|
|
205
|
-
placeholder={schema.placeholder ??
|
|
229
|
+
placeholder={schema.placeholder ?? ''}
|
|
206
230
|
{required}
|
|
207
231
|
ariaDescribedBy={descriptionId}
|
|
208
232
|
onChange={(val) => onChange(val)}
|
|
209
233
|
/>
|
|
210
|
-
{:else if fieldType ===
|
|
234
|
+
{:else if fieldType === 'number'}
|
|
211
235
|
<FormNumberField
|
|
212
236
|
id={fieldKey}
|
|
213
237
|
value={numberValue}
|
|
214
|
-
placeholder={schema.placeholder ??
|
|
238
|
+
placeholder={schema.placeholder ?? ''}
|
|
215
239
|
min={schema.minimum}
|
|
216
240
|
max={schema.maximum}
|
|
217
241
|
{required}
|
|
218
242
|
ariaDescribedBy={descriptionId}
|
|
219
243
|
onChange={(val) => onChange(val)}
|
|
220
244
|
/>
|
|
221
|
-
{:else if fieldType ===
|
|
245
|
+
{:else if fieldType === 'range'}
|
|
246
|
+
<FormRangeField
|
|
247
|
+
id={fieldKey}
|
|
248
|
+
value={numberValue}
|
|
249
|
+
min={schema.minimum}
|
|
250
|
+
max={schema.maximum}
|
|
251
|
+
step={schema.step}
|
|
252
|
+
{required}
|
|
253
|
+
ariaDescribedBy={descriptionId}
|
|
254
|
+
onChange={(val) => onChange(val)}
|
|
255
|
+
/>
|
|
256
|
+
{:else if fieldType === 'toggle'}
|
|
222
257
|
<FormToggle
|
|
223
258
|
id={fieldKey}
|
|
224
259
|
value={booleanValue}
|
|
225
260
|
ariaDescribedBy={descriptionId}
|
|
226
261
|
onChange={(val) => onChange(val)}
|
|
227
262
|
/>
|
|
228
|
-
{:else if fieldType ===
|
|
263
|
+
{:else if fieldType === 'select-options'}
|
|
229
264
|
<FormSelect
|
|
230
265
|
id={fieldKey}
|
|
231
266
|
value={stringValue}
|
|
@@ -234,27 +269,62 @@
|
|
|
234
269
|
ariaDescribedBy={descriptionId}
|
|
235
270
|
onChange={(val) => onChange(val)}
|
|
236
271
|
/>
|
|
237
|
-
{:else if fieldType ===
|
|
272
|
+
{:else if fieldType === 'array' && schema.items}
|
|
238
273
|
<FormArray
|
|
239
274
|
id={fieldKey}
|
|
240
275
|
value={arrayItems}
|
|
241
276
|
itemSchema={schema.items}
|
|
242
277
|
minItems={schema.minItems}
|
|
243
278
|
maxItems={schema.maxItems}
|
|
244
|
-
addLabel={`Add ${schema.items.title ??
|
|
279
|
+
addLabel={`Add ${schema.items.title ?? 'Item'}`}
|
|
280
|
+
onChange={(val) => onChange(val)}
|
|
281
|
+
/>
|
|
282
|
+
{:else if fieldType === 'code-editor'}
|
|
283
|
+
<FormCodeEditor
|
|
284
|
+
id={fieldKey}
|
|
285
|
+
{value}
|
|
286
|
+
placeholder={schema.placeholder ?? '{}'}
|
|
287
|
+
{required}
|
|
288
|
+
height={(schema.height as string | undefined) ?? '200px'}
|
|
289
|
+
darkTheme={(schema.darkTheme as boolean | undefined) ?? false}
|
|
290
|
+
autoFormat={(schema.autoFormat as boolean | undefined) ?? true}
|
|
291
|
+
ariaDescribedBy={descriptionId}
|
|
292
|
+
onChange={(val) => onChange(val)}
|
|
293
|
+
/>
|
|
294
|
+
{:else if fieldType === 'markdown-editor'}
|
|
295
|
+
<FormMarkdownEditor
|
|
296
|
+
id={fieldKey}
|
|
297
|
+
value={stringValue}
|
|
298
|
+
placeholder={schema.placeholder ?? 'Write your markdown here...'}
|
|
299
|
+
{required}
|
|
300
|
+
height={(schema.height as string | undefined) ?? '300px'}
|
|
301
|
+
showToolbar={(schema.showToolbar as boolean | undefined) ?? true}
|
|
302
|
+
showStatusBar={(schema.showStatusBar as boolean | undefined) ?? true}
|
|
303
|
+
spellChecker={(schema.spellChecker as boolean | undefined) ?? false}
|
|
304
|
+
ariaDescribedBy={descriptionId}
|
|
305
|
+
onChange={(val) => onChange(val)}
|
|
306
|
+
/>
|
|
307
|
+
{:else if fieldType === 'template-editor'}
|
|
308
|
+
<FormTemplateEditor
|
|
309
|
+
id={fieldKey}
|
|
310
|
+
value={stringValue}
|
|
311
|
+
placeholder={schema.placeholder ??
|
|
312
|
+
'Enter your template here...\nUse {{ variable }} for dynamic values.'}
|
|
313
|
+
{required}
|
|
314
|
+
height={(schema.height as string | undefined) ?? '250px'}
|
|
315
|
+
darkTheme={(schema.darkTheme as boolean | undefined) ?? false}
|
|
316
|
+
variableHints={(schema.variableHints as string[] | undefined) ?? []}
|
|
317
|
+
placeholderExample={(schema.placeholderExample as string | undefined) ??
|
|
318
|
+
'Hello {{ name }}, your order #{{ order_id }} is ready!'}
|
|
319
|
+
ariaDescribedBy={descriptionId}
|
|
245
320
|
onChange={(val) => onChange(val)}
|
|
246
321
|
/>
|
|
247
|
-
{:else if fieldType === "object"}
|
|
248
|
-
<!-- Future: Object field component -->
|
|
249
|
-
<div class="form-field__unsupported">
|
|
250
|
-
<p>Object fields are not yet supported. Coming soon!</p>
|
|
251
|
-
</div>
|
|
252
322
|
{:else}
|
|
253
323
|
<!-- Fallback to text input -->
|
|
254
324
|
<FormTextField
|
|
255
325
|
id={fieldKey}
|
|
256
326
|
value={stringValue}
|
|
257
|
-
placeholder={schema.placeholder ??
|
|
327
|
+
placeholder={schema.placeholder ?? ''}
|
|
258
328
|
ariaDescribedBy={descriptionId}
|
|
259
329
|
onChange={(val) => onChange(val)}
|
|
260
330
|
/>
|
|
@@ -276,4 +346,3 @@
|
|
|
276
346
|
margin: 0;
|
|
277
347
|
}
|
|
278
348
|
</style>
|
|
279
|
-
|