@d34dman/flowdrop 0.0.30 → 0.0.31

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 (51) hide show
  1. package/dist/components/App.svelte +54 -6
  2. package/dist/components/NodeSidebar.svelte +1 -1
  3. package/dist/components/SchemaForm.svelte +14 -14
  4. package/dist/components/SchemaForm.svelte.d.ts +1 -1
  5. package/dist/components/form/FormFieldLight.svelte +66 -66
  6. package/dist/components/form/FormFieldLight.svelte.d.ts +1 -1
  7. package/dist/components/form/types.d.ts +1 -1
  8. package/dist/components/playground/ChatPanel.svelte +523 -0
  9. package/dist/components/playground/ChatPanel.svelte.d.ts +20 -0
  10. package/dist/components/playground/ExecutionLogs.svelte +486 -0
  11. package/dist/components/playground/ExecutionLogs.svelte.d.ts +14 -0
  12. package/dist/components/playground/InputCollector.svelte +444 -0
  13. package/dist/components/playground/InputCollector.svelte.d.ts +16 -0
  14. package/dist/components/playground/MessageBubble.svelte +398 -0
  15. package/dist/components/playground/MessageBubble.svelte.d.ts +15 -0
  16. package/dist/components/playground/Playground.svelte +851 -0
  17. package/dist/components/playground/Playground.svelte.d.ts +25 -0
  18. package/dist/components/playground/SessionManager.svelte +537 -0
  19. package/dist/components/playground/SessionManager.svelte.d.ts +20 -0
  20. package/dist/config/endpoints.d.ts +16 -0
  21. package/dist/config/endpoints.js +9 -0
  22. package/dist/core/index.d.ts +25 -23
  23. package/dist/core/index.js +13 -12
  24. package/dist/display/index.d.ts +2 -2
  25. package/dist/display/index.js +2 -2
  26. package/dist/editor/index.d.ts +57 -49
  27. package/dist/editor/index.js +52 -42
  28. package/dist/form/code.d.ts +4 -4
  29. package/dist/form/code.js +11 -11
  30. package/dist/form/fieldRegistry.d.ts +2 -2
  31. package/dist/form/fieldRegistry.js +8 -10
  32. package/dist/form/full.d.ts +5 -5
  33. package/dist/form/full.js +7 -7
  34. package/dist/form/index.d.ts +16 -16
  35. package/dist/form/index.js +14 -14
  36. package/dist/form/markdown.d.ts +3 -3
  37. package/dist/form/markdown.js +6 -6
  38. package/dist/index.d.ts +6 -4
  39. package/dist/index.js +9 -4
  40. package/dist/playground/index.d.ts +92 -0
  41. package/dist/playground/index.js +114 -0
  42. package/dist/playground/mount.d.ts +183 -0
  43. package/dist/playground/mount.js +178 -0
  44. package/dist/services/playgroundService.d.ts +129 -0
  45. package/dist/services/playgroundService.js +317 -0
  46. package/dist/stores/playgroundStore.d.ts +199 -0
  47. package/dist/stores/playgroundStore.js +350 -0
  48. package/dist/types/playground.d.ts +230 -0
  49. package/dist/types/playground.js +28 -0
  50. package/dist/utils/colors.js +4 -4
  51. package/package.json +6 -1
@@ -0,0 +1,444 @@
1
+ <!--
2
+ InputCollector Component
3
+
4
+ Auto-generates input forms from workflow input nodes.
5
+ Supports various field types and pre-fills with defaults.
6
+ Styled with BEM syntax.
7
+ -->
8
+
9
+ <script lang="ts">
10
+ import Icon from '@iconify/svelte';
11
+ import { slide } from 'svelte/transition';
12
+ import type { PlaygroundInputField } from '../../types/playground.js';
13
+ import { inputFields, hasChatInput } from '../../stores/playgroundStore.js';
14
+
15
+ /**
16
+ * Component props
17
+ */
18
+ interface Props {
19
+ /** Whether the inputs panel is expanded */
20
+ isExpanded?: boolean;
21
+ /** Callback when expansion state changes */
22
+ onToggle?: (expanded: boolean) => void;
23
+ /** Current input values */
24
+ values?: Record<string, unknown>;
25
+ /** Callback when values change */
26
+ onValuesChange?: (values: Record<string, unknown>) => void;
27
+ }
28
+
29
+ let {
30
+ isExpanded = $bindable(true),
31
+ onToggle,
32
+ values = $bindable({}),
33
+ onValuesChange
34
+ }: Props = $props();
35
+
36
+ /** Flag to track if we've initialized default values */
37
+ let hasInitializedDefaults = false;
38
+
39
+ /**
40
+ * Initialize values from field defaults (runs once when fields are available)
41
+ */
42
+ $effect(() => {
43
+ // Only initialize once when we have input fields and haven't initialized yet
44
+ if ($inputFields.length > 0 && !hasInitializedDefaults) {
45
+ hasInitializedDefaults = true;
46
+
47
+ // Only set values if there are actual defaults to set
48
+ const initialValues: Record<string, unknown> = {};
49
+ let hasDefaults = false;
50
+
51
+ $inputFields.forEach((field) => {
52
+ if (field.defaultValue !== undefined) {
53
+ initialValues[`${field.nodeId}:${field.fieldId}`] = field.defaultValue;
54
+ hasDefaults = true;
55
+ }
56
+ });
57
+
58
+ if (hasDefaults) {
59
+ values = initialValues;
60
+ onValuesChange?.(values);
61
+ }
62
+ }
63
+ });
64
+
65
+ /**
66
+ * Toggle expansion
67
+ */
68
+ function toggleExpanded(): void {
69
+ isExpanded = !isExpanded;
70
+ onToggle?.(isExpanded);
71
+ }
72
+
73
+ /**
74
+ * Update a field value
75
+ */
76
+ function updateValue(field: PlaygroundInputField, value: unknown): void {
77
+ const key = `${field.nodeId}:${field.fieldId}`;
78
+ values = { ...values, [key]: value };
79
+ onValuesChange?.(values);
80
+ }
81
+
82
+ /**
83
+ * Get the current value for a field
84
+ */
85
+ function getValue(field: PlaygroundInputField): unknown {
86
+ const key = `${field.nodeId}:${field.fieldId}`;
87
+ return values[key] ?? field.defaultValue ?? '';
88
+ }
89
+
90
+ /**
91
+ * Get input type from field schema
92
+ */
93
+ function getInputType(field: PlaygroundInputField): string {
94
+ if (field.schema?.format === 'multiline') {
95
+ return 'textarea';
96
+ }
97
+ switch (field.type) {
98
+ case 'number':
99
+ case 'integer':
100
+ return 'number';
101
+ case 'boolean':
102
+ return 'checkbox';
103
+ default:
104
+ return 'text';
105
+ }
106
+ }
107
+
108
+ /**
109
+ * Check if field has enum options
110
+ */
111
+ function hasEnumOptions(field: PlaygroundInputField): boolean {
112
+ return Array.isArray(field.schema?.enum) && field.schema.enum.length > 0;
113
+ }
114
+
115
+ /**
116
+ * Reset all values to defaults
117
+ */
118
+ function resetToDefaults(): void {
119
+ const defaultValues: Record<string, unknown> = {};
120
+ $inputFields.forEach((field) => {
121
+ if (field.defaultValue !== undefined) {
122
+ defaultValues[`${field.nodeId}:${field.fieldId}`] = field.defaultValue;
123
+ }
124
+ });
125
+ values = defaultValues;
126
+ onValuesChange?.(values);
127
+ }
128
+ </script>
129
+
130
+ {#if $inputFields.length > 0}
131
+ <div class="input-collector" class:input-collector--expanded={isExpanded}>
132
+ <!-- Header -->
133
+ <button
134
+ type="button"
135
+ class="input-collector__header"
136
+ onclick={toggleExpanded}
137
+ aria-expanded={isExpanded}
138
+ >
139
+ <div class="input-collector__title">
140
+ <Icon icon="mdi:form-textbox" />
141
+ <span>Workflow Inputs</span>
142
+ <span class="input-collector__count">{$inputFields.length}</span>
143
+ </div>
144
+ <Icon
145
+ icon="mdi:chevron-down"
146
+ class="input-collector__chevron {isExpanded ? 'input-collector__chevron--expanded' : ''}"
147
+ />
148
+ </button>
149
+
150
+ <!-- Content -->
151
+ {#if isExpanded}
152
+ <div class="input-collector__content" transition:slide={{ duration: 200 }}>
153
+ {#if $hasChatInput}
154
+ <div class="input-collector__hint">
155
+ <Icon icon="mdi:information-outline" />
156
+ <span>Chat input will be collected from the message field below</span>
157
+ </div>
158
+ {/if}
159
+
160
+ <div class="input-collector__fields">
161
+ {#each $inputFields as field (field.nodeId + ':' + field.fieldId)}
162
+ <div class="input-collector__field">
163
+ <label class="input-collector__label" for="input-{field.nodeId}-{field.fieldId}">
164
+ {field.label}
165
+ {#if field.required}
166
+ <span class="input-collector__required">*</span>
167
+ {/if}
168
+ </label>
169
+
170
+ {#if hasEnumOptions(field)}
171
+ <!-- Select for enum fields -->
172
+ <select
173
+ id="input-{field.nodeId}-{field.fieldId}"
174
+ class="input-collector__select"
175
+ value={getValue(field)}
176
+ onchange={(e) => updateValue(field, e.currentTarget.value)}
177
+ >
178
+ <option value="">Select {field.label}</option>
179
+ {#each field.schema?.enum ?? [] as option}
180
+ <option value={String(option)}>{option}</option>
181
+ {/each}
182
+ </select>
183
+ {:else if getInputType(field) === 'textarea'}
184
+ <!-- Textarea for multiline -->
185
+ <textarea
186
+ id="input-{field.nodeId}-{field.fieldId}"
187
+ class="input-collector__textarea"
188
+ placeholder={field.schema?.description ?? `Enter ${field.label}`}
189
+ value={String(getValue(field) ?? '')}
190
+ oninput={(e) => updateValue(field, e.currentTarget.value)}
191
+ rows="3"
192
+ ></textarea>
193
+ {:else if getInputType(field) === 'checkbox'}
194
+ <!-- Checkbox for boolean -->
195
+ <label class="input-collector__checkbox-wrapper">
196
+ <input
197
+ id="input-{field.nodeId}-{field.fieldId}"
198
+ type="checkbox"
199
+ class="input-collector__checkbox"
200
+ checked={Boolean(getValue(field))}
201
+ onchange={(e) => updateValue(field, e.currentTarget.checked)}
202
+ />
203
+ <span class="input-collector__checkbox-label">
204
+ {field.schema?.description ?? 'Enable'}
205
+ </span>
206
+ </label>
207
+ {:else if getInputType(field) === 'number'}
208
+ <!-- Number input -->
209
+ <input
210
+ id="input-{field.nodeId}-{field.fieldId}"
211
+ type="number"
212
+ class="input-collector__input"
213
+ placeholder={field.schema?.description ?? `Enter ${field.label}`}
214
+ value={Number(getValue(field) ?? 0)}
215
+ min={field.schema?.minimum}
216
+ max={field.schema?.maximum}
217
+ oninput={(e) => updateValue(field, parseFloat(e.currentTarget.value) || 0)}
218
+ />
219
+ {:else}
220
+ <!-- Text input (default) -->
221
+ <input
222
+ id="input-{field.nodeId}-{field.fieldId}"
223
+ type="text"
224
+ class="input-collector__input"
225
+ placeholder={field.schema?.description ?? `Enter ${field.label}`}
226
+ value={String(getValue(field) ?? '')}
227
+ oninput={(e) => updateValue(field, e.currentTarget.value)}
228
+ />
229
+ {/if}
230
+
231
+ {#if field.schema?.description && getInputType(field) !== 'checkbox'}
232
+ <p class="input-collector__description">{field.schema.description}</p>
233
+ {/if}
234
+ </div>
235
+ {/each}
236
+ </div>
237
+
238
+ <!-- Actions -->
239
+ <div class="input-collector__actions">
240
+ <button
241
+ type="button"
242
+ class="input-collector__reset"
243
+ onclick={resetToDefaults}
244
+ title="Reset to default values"
245
+ >
246
+ <Icon icon="mdi:refresh" />
247
+ Reset to Defaults
248
+ </button>
249
+ </div>
250
+ </div>
251
+ {/if}
252
+ </div>
253
+ {/if}
254
+
255
+ <style>
256
+ .input-collector {
257
+ border-bottom: 1px solid #e2e8f0;
258
+ background-color: #ffffff;
259
+ }
260
+
261
+ /* Header */
262
+ .input-collector__header {
263
+ display: flex;
264
+ align-items: center;
265
+ justify-content: space-between;
266
+ width: 100%;
267
+ padding: 0.75rem 1rem;
268
+ border: none;
269
+ background: transparent;
270
+ cursor: pointer;
271
+ transition: background-color 0.2s ease-in-out;
272
+ }
273
+
274
+ .input-collector__header:hover {
275
+ background-color: #f8fafc;
276
+ }
277
+
278
+ .input-collector__title {
279
+ display: flex;
280
+ align-items: center;
281
+ gap: 0.5rem;
282
+ font-size: 0.875rem;
283
+ font-weight: 500;
284
+ color: #1e293b;
285
+ }
286
+
287
+ .input-collector__count {
288
+ display: inline-flex;
289
+ align-items: center;
290
+ justify-content: center;
291
+ min-width: 1.25rem;
292
+ height: 1.25rem;
293
+ padding: 0 0.375rem;
294
+ border-radius: 0.625rem;
295
+ font-size: 0.6875rem;
296
+ font-weight: 600;
297
+ background-color: #dbeafe;
298
+ color: #2563eb;
299
+ }
300
+
301
+ :global(.input-collector__chevron) {
302
+ transition: transform 0.2s ease-in-out;
303
+ color: #94a3b8;
304
+ }
305
+
306
+ :global(.input-collector__chevron--expanded) {
307
+ transform: rotate(180deg);
308
+ }
309
+
310
+ /* Content */
311
+ .input-collector__content {
312
+ padding: 0 1rem 1rem;
313
+ }
314
+
315
+ .input-collector__hint {
316
+ display: flex;
317
+ align-items: center;
318
+ gap: 0.5rem;
319
+ padding: 0.5rem 0.75rem;
320
+ margin-bottom: 1rem;
321
+ background-color: #dbeafe;
322
+ border-radius: 0.5rem;
323
+ font-size: 0.8125rem;
324
+ color: #1d4ed8;
325
+ }
326
+
327
+ /* Fields */
328
+ .input-collector__fields {
329
+ display: flex;
330
+ flex-direction: column;
331
+ gap: 1rem;
332
+ }
333
+
334
+ .input-collector__field {
335
+ display: flex;
336
+ flex-direction: column;
337
+ gap: 0.375rem;
338
+ }
339
+
340
+ .input-collector__label {
341
+ font-size: 0.8125rem;
342
+ font-weight: 500;
343
+ color: #374151;
344
+ }
345
+
346
+ .input-collector__required {
347
+ color: #dc2626;
348
+ }
349
+
350
+ .input-collector__input,
351
+ .input-collector__select,
352
+ .input-collector__textarea {
353
+ padding: 0.5rem 0.75rem;
354
+ border: 1px solid #e2e8f0;
355
+ border-radius: 0.5rem;
356
+ font-size: 0.875rem;
357
+ font-family: inherit;
358
+ color: #1e293b;
359
+ background-color: #ffffff;
360
+ transition:
361
+ border-color 0.2s ease-in-out,
362
+ box-shadow 0.2s ease-in-out;
363
+ }
364
+
365
+ .input-collector__input:focus,
366
+ .input-collector__select:focus,
367
+ .input-collector__textarea:focus {
368
+ outline: none;
369
+ border-color: #3b82f6;
370
+ box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
371
+ }
372
+
373
+ .input-collector__input::placeholder,
374
+ .input-collector__textarea::placeholder {
375
+ color: #94a3b8;
376
+ }
377
+
378
+ .input-collector__textarea {
379
+ resize: vertical;
380
+ min-height: 80px;
381
+ }
382
+
383
+ .input-collector__select {
384
+ cursor: pointer;
385
+ }
386
+
387
+ .input-collector__checkbox-wrapper {
388
+ display: flex;
389
+ align-items: center;
390
+ gap: 0.5rem;
391
+ cursor: pointer;
392
+ }
393
+
394
+ .input-collector__checkbox {
395
+ width: 1rem;
396
+ height: 1rem;
397
+ accent-color: #3b82f6;
398
+ cursor: pointer;
399
+ }
400
+
401
+ .input-collector__checkbox-label {
402
+ font-size: 0.875rem;
403
+ color: #64748b;
404
+ }
405
+
406
+ .input-collector__description {
407
+ font-size: 0.75rem;
408
+ color: #94a3b8;
409
+ margin: 0;
410
+ }
411
+
412
+ /* Actions */
413
+ .input-collector__actions {
414
+ margin-top: 1rem;
415
+ padding-top: 1rem;
416
+ border-top: 1px solid #f1f5f9;
417
+ }
418
+
419
+ .input-collector__reset {
420
+ display: flex;
421
+ align-items: center;
422
+ gap: 0.375rem;
423
+ padding: 0.375rem 0.75rem;
424
+ border: 1px solid #e2e8f0;
425
+ border-radius: 0.375rem;
426
+ background: #ffffff;
427
+ font-size: 0.8125rem;
428
+ color: #64748b;
429
+ cursor: pointer;
430
+ transition: all 0.2s ease-in-out;
431
+ }
432
+
433
+ .input-collector__reset:hover {
434
+ background-color: #f8fafc;
435
+ color: #1e293b;
436
+ }
437
+
438
+ /* Responsive */
439
+ @media (max-width: 640px) {
440
+ .input-collector__content {
441
+ padding: 0 0.75rem 0.75rem;
442
+ }
443
+ }
444
+ </style>
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Component props
3
+ */
4
+ interface Props {
5
+ /** Whether the inputs panel is expanded */
6
+ isExpanded?: boolean;
7
+ /** Callback when expansion state changes */
8
+ onToggle?: (expanded: boolean) => void;
9
+ /** Current input values */
10
+ values?: Record<string, unknown>;
11
+ /** Callback when values change */
12
+ onValuesChange?: (values: Record<string, unknown>) => void;
13
+ }
14
+ declare const InputCollector: import("svelte").Component<Props, {}, "values" | "isExpanded">;
15
+ type InputCollector = ReturnType<typeof InputCollector>;
16
+ export default InputCollector;