@flowdrop/flowdrop 1.14.0 → 2.0.0-beta.1
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/CHANGELOG.md +475 -0
- package/MIGRATION-2.0.md +472 -0
- package/README.md +23 -23
- package/dist/adapters/WorkflowAdapter.d.ts +1 -1
- package/dist/adapters/WorkflowAdapter.js +14 -8
- package/dist/adapters/agentspec/AgentSpecAdapter.js +7 -7
- package/dist/chat/batchFeedback.d.ts +39 -0
- package/dist/chat/batchFeedback.js +51 -0
- package/dist/commands/executor.js +15 -1
- package/dist/commands/storeIntegration.svelte.d.ts +4 -1
- package/dist/commands/storeIntegration.svelte.js +26 -21
- package/dist/commands/types.d.ts +2 -0
- package/dist/components/App.svelte +162 -192
- package/dist/components/App.svelte.d.ts +47 -8
- package/dist/components/ConfigForm.svelte +110 -66
- package/dist/components/ConfigModal.svelte +7 -2
- package/dist/components/ConnectionLine.svelte +4 -2
- package/dist/components/Navbar.svelte +61 -1
- package/dist/components/NodeSidebar.svelte +27 -45
- package/dist/components/NodeStatusOverlay.svelte +94 -6
- package/dist/components/NodeSwapPicker.svelte +10 -8
- package/dist/components/PipelineStatus.svelte +16 -67
- package/dist/components/PortCoordinateTracker.svelte +5 -6
- package/dist/components/SchemaForm.stories.svelte +1 -3
- package/dist/components/SchemaForm.svelte +45 -40
- package/dist/components/SchemaForm.svelte.d.ts +0 -8
- package/dist/components/SettingsModal.svelte +8 -3
- package/dist/components/SettingsPanel.svelte +20 -4
- package/dist/components/SwapMappingEditor.svelte +67 -49
- package/dist/components/SwapMappingEditor.svelte.d.ts +0 -2
- package/dist/components/UniversalNode.svelte +9 -7
- package/dist/components/WorkflowEditor.svelte +118 -111
- package/dist/components/WorkflowEditor.svelte.d.ts +18 -10
- package/dist/components/chat/AIChatPanel.svelte +93 -89
- package/dist/components/chat/AIChatPanel.svelte.d.ts +0 -4
- package/dist/components/chat/CommandPreview.svelte +2 -1
- package/dist/components/console/CommandConsole.svelte +7 -5
- package/dist/components/console/ConsoleAutocomplete.svelte +10 -11
- package/dist/components/console/ConsoleAutocomplete.svelte.d.ts +6 -0
- package/dist/components/console/ConsoleInput.svelte +15 -6
- package/dist/components/console/ConsoleOutput.svelte +2 -1
- package/dist/components/form/FormArray.svelte +5 -9
- package/dist/components/form/FormArray.svelte.d.ts +2 -1
- package/dist/components/form/FormAutocomplete.svelte +29 -13
- package/dist/components/form/FormField.svelte +4 -2
- package/dist/components/form/FormFieldLight.svelte +4 -2
- package/dist/components/form/FormMarkdownEditor.svelte +9 -4
- package/dist/components/form/FormRangeField.svelte +1 -0
- package/dist/components/form/FormTemplateEditor.svelte +11 -3
- package/dist/components/form/FormToggle.svelte +5 -12
- package/dist/components/form/FormToggle.svelte.d.ts +4 -2
- package/dist/components/form/templateAutocomplete.js +1 -5
- package/dist/components/form/types.d.ts +1 -14
- package/dist/components/interrupt/FormPrompt.svelte +3 -2
- package/dist/components/interrupt/InterruptBubble.svelte +16 -17
- package/dist/components/interrupt/ReviewPrompt.svelte +10 -3
- package/dist/components/interrupt/TextInputPrompt.svelte +2 -1
- package/dist/components/layouts/MainLayout.svelte +20 -13
- package/dist/components/layouts/MainLayout.svelte.d.ts +4 -0
- package/dist/components/nodes/AtomNode.svelte +292 -0
- package/dist/components/nodes/AtomNode.svelte.d.ts +26 -0
- package/dist/components/nodes/GatewayNode.svelte +19 -10
- package/dist/components/nodes/IdeaNode.svelte +7 -0
- package/dist/components/nodes/SimpleNode.svelte +11 -6
- package/dist/components/nodes/SquareNode.svelte +15 -8
- package/dist/components/nodes/TerminalNode.svelte +9 -4
- package/dist/components/nodes/ToolNode.svelte +7 -1
- package/dist/components/nodes/WorkflowNode.svelte +16 -7
- package/dist/components/playground/ChatInput.svelte +11 -14
- package/dist/components/playground/ChatPanel.svelte +6 -49
- package/dist/components/playground/ChatPanel.svelte.d.ts +0 -14
- package/dist/components/playground/ControlPanel.svelte +134 -123
- package/dist/components/playground/ControlPanel.svelte.d.ts +3 -0
- package/dist/components/playground/ExecutionLogs.svelte +11 -9
- package/dist/components/playground/InputCollector.svelte +11 -9
- package/dist/components/playground/MessageStream.svelte +17 -23
- package/dist/components/playground/PipelineKanbanView.svelte +65 -6
- package/dist/components/playground/PipelinePanel.svelte +11 -5
- package/dist/components/playground/PipelineTableView.svelte +186 -44
- package/dist/components/playground/Playground.svelte +95 -92
- package/dist/components/playground/Playground.svelte.d.ts +2 -0
- package/dist/components/playground/PlaygroundApp.svelte +6 -1
- package/dist/components/playground/PlaygroundApp.svelte.d.ts +3 -0
- package/dist/components/playground/PlaygroundModal.svelte +13 -3
- package/dist/components/playground/PlaygroundModal.svelte.d.ts +3 -0
- package/dist/components/playground/PlaygroundStudio.svelte +34 -32
- package/dist/components/playground/PlaygroundStudio.svelte.d.ts +3 -0
- package/dist/components/playground/SessionManager.svelte +9 -12
- package/dist/components/playground/pipelineViewUtils.svelte.d.ts +28 -0
- package/dist/components/playground/pipelineViewUtils.svelte.js +38 -1
- package/dist/config/endpoints.d.ts +0 -7
- package/dist/config/endpoints.js +2 -10
- package/dist/core/index.d.ts +4 -4
- package/dist/core/index.js +6 -6
- package/dist/display/index.d.ts +0 -2
- package/dist/display/index.js +0 -6
- package/dist/editor/index.d.ts +19 -20
- package/dist/editor/index.js +25 -35
- package/dist/form/code.d.ts +25 -15
- package/dist/form/code.js +44 -41
- package/dist/form/fieldRegistry.d.ts +17 -13
- package/dist/form/fieldRegistry.js +32 -12
- package/dist/form/full.d.ts +17 -13
- package/dist/form/full.js +22 -27
- package/dist/form/index.d.ts +3 -3
- package/dist/form/index.js +3 -3
- package/dist/form/markdown.d.ts +13 -8
- package/dist/form/markdown.js +22 -23
- package/dist/helpers/proximityConnect.d.ts +7 -3
- package/dist/helpers/proximityConnect.js +19 -6
- package/dist/helpers/workflowEditorHelper.d.ts +12 -5
- package/dist/helpers/workflowEditorHelper.js +27 -25
- package/dist/index.d.ts +28 -24
- package/dist/index.js +27 -50
- package/dist/messages/defaults.d.ts +2 -5
- package/dist/messages/defaults.js +3 -6
- package/dist/messages/index.d.ts +0 -1
- package/dist/messages/index.js +0 -1
- package/dist/mocks/app-forms.d.ts +6 -2
- package/dist/mocks/app-forms.js +11 -4
- package/dist/openapi/v1/openapi.yaml +227 -164
- package/dist/playground/index.d.ts +2 -3
- package/dist/playground/index.js +2 -30
- package/dist/playground/mount.d.ts +15 -0
- package/dist/playground/mount.js +46 -20
- package/dist/registry/{BaseRegistry.d.ts → BaseRegistry.svelte.d.ts} +22 -1
- package/dist/registry/{BaseRegistry.js → BaseRegistry.svelte.js} +37 -1
- package/dist/registry/builtinFormats.d.ts +9 -18
- package/dist/registry/builtinFormats.js +9 -39
- package/dist/registry/builtinNodes.d.ts +1 -26
- package/dist/registry/builtinNodes.js +14 -50
- package/dist/registry/index.d.ts +3 -4
- package/dist/registry/index.js +4 -6
- package/dist/registry/nodeComponentRegistry.d.ts +182 -15
- package/dist/registry/nodeComponentRegistry.js +235 -17
- package/dist/registry/workflowFormatRegistry.d.ts +14 -9
- package/dist/registry/workflowFormatRegistry.js +24 -8
- package/dist/{schema → schemas}/index.d.ts +2 -2
- package/dist/{schema → schemas}/index.js +2 -2
- package/dist/schemas/v1/workflow.schema.json +53 -6
- package/dist/services/agentSpecExecutionService.js +0 -1
- package/dist/services/apiVariableService.d.ts +2 -1
- package/dist/services/apiVariableService.js +5 -22
- package/dist/services/autoSaveService.d.ts +7 -0
- package/dist/services/autoSaveService.js +6 -4
- package/dist/services/chatService.d.ts +8 -4
- package/dist/services/chatService.js +15 -15
- package/dist/services/draftStorage.d.ts +129 -13
- package/dist/services/draftStorage.js +185 -37
- package/dist/services/dynamicSchemaService.d.ts +2 -1
- package/dist/services/dynamicSchemaService.js +5 -22
- package/dist/services/globalSave.d.ts +13 -12
- package/dist/services/globalSave.js +29 -51
- package/dist/services/historyService.d.ts +9 -3
- package/dist/services/historyService.js +9 -3
- package/dist/services/interruptService.d.ts +14 -9
- package/dist/services/interruptService.js +27 -27
- package/dist/services/nodeExecutionService.d.ts +18 -3
- package/dist/services/nodeExecutionService.js +71 -45
- package/dist/services/playgroundService.d.ts +14 -9
- package/dist/services/playgroundService.js +31 -30
- package/dist/services/variableService.d.ts +2 -1
- package/dist/services/variableService.js +2 -2
- package/dist/services/workflowStorage.js +6 -6
- package/dist/stores/apiContext.d.ts +45 -0
- package/dist/stores/apiContext.js +65 -0
- package/dist/stores/categoriesStore.svelte.d.ts +28 -23
- package/dist/stores/categoriesStore.svelte.js +70 -64
- package/dist/stores/getInstance.svelte.d.ts +39 -0
- package/dist/stores/getInstance.svelte.js +65 -0
- package/dist/stores/historyStore.svelte.d.ts +77 -93
- package/dist/stores/historyStore.svelte.js +134 -160
- package/dist/stores/instanceContainer.svelte.d.ts +111 -0
- package/dist/stores/instanceContainer.svelte.js +114 -0
- package/dist/stores/interruptStore.svelte.d.ts +112 -82
- package/dist/stores/interruptStore.svelte.js +253 -226
- package/dist/stores/pipelinePanelStore.svelte.d.ts +27 -3
- package/dist/stores/pipelinePanelStore.svelte.js +61 -14
- package/dist/stores/playgroundStore.svelte.d.ts +169 -216
- package/dist/stores/playgroundStore.svelte.js +515 -572
- package/dist/stores/portCoordinateStore.svelte.d.ts +57 -51
- package/dist/stores/portCoordinateStore.svelte.js +109 -98
- package/dist/stores/settingsStore.svelte.d.ts +4 -1
- package/dist/stores/settingsStore.svelte.js +47 -12
- package/dist/stores/workflowStore.svelte.d.ts +178 -213
- package/dist/stores/workflowStore.svelte.js +449 -501
- package/dist/stories/EdgeDecorator.svelte +5 -2
- package/dist/stories/NodeDecorator.svelte +5 -3
- package/dist/svelte-app.d.ts +60 -10
- package/dist/svelte-app.js +157 -53
- package/dist/types/events.d.ts +6 -3
- package/dist/types/index.d.ts +71 -6
- package/dist/types/navbar.d.ts +7 -0
- package/dist/types/playground.d.ts +18 -3
- package/dist/types/settings.d.ts +13 -0
- package/dist/types/settings.js +1 -0
- package/dist/utils/colors.d.ts +47 -21
- package/dist/utils/colors.js +69 -68
- package/dist/utils/connections.d.ts +9 -15
- package/dist/utils/connections.js +13 -32
- package/dist/utils/duration.d.ts +13 -0
- package/dist/utils/duration.js +45 -0
- package/dist/utils/formMerge.d.ts +36 -0
- package/dist/utils/formMerge.js +70 -0
- package/dist/utils/icons.d.ts +5 -2
- package/dist/utils/icons.js +6 -5
- package/dist/utils/nodeSwap.d.ts +6 -2
- package/dist/utils/nodeSwap.js +62 -126
- package/dist/utils/nodeTypes.d.ts +17 -8
- package/dist/utils/nodeTypes.js +27 -19
- package/dist/utils/performanceUtils.js +7 -0
- package/package.json +6 -5
- package/dist/messages/deprecation.d.ts +0 -20
- package/dist/messages/deprecation.js +0 -33
- package/dist/registry/plugin.d.ts +0 -215
- package/dist/registry/plugin.js +0 -249
- package/dist/services/api.d.ts +0 -129
- package/dist/services/api.js +0 -217
|
@@ -121,7 +121,8 @@
|
|
|
121
121
|
// Stable fingerprint — any change triggers selection clearing.
|
|
122
122
|
// JSON.stringify gives a canonical string without null-byte ambiguity.
|
|
123
123
|
const depFingerprint = $derived(JSON.stringify(depParamValues));
|
|
124
|
-
//
|
|
124
|
+
// intentional initial snapshot; the effect below tracks subsequent changes
|
|
125
|
+
// svelte-ignore state_referenced_locally
|
|
125
126
|
let prevDepFingerprint = depFingerprint;
|
|
126
127
|
|
|
127
128
|
$effect(() => {
|
|
@@ -135,9 +136,9 @@
|
|
|
135
136
|
});
|
|
136
137
|
|
|
137
138
|
// Generate unique IDs for accessibility
|
|
138
|
-
//
|
|
139
|
-
const listboxId = `${id}-listbox`;
|
|
139
|
+
// id prop never changes
|
|
140
140
|
// svelte-ignore state_referenced_locally
|
|
141
|
+
const listboxId = `${id}-listbox`;
|
|
141
142
|
const getOptionId = (index: number): string => `${id}-option-${index}`;
|
|
142
143
|
|
|
143
144
|
/**
|
|
@@ -309,10 +310,9 @@
|
|
|
309
310
|
// Open dropdown
|
|
310
311
|
showDropdown();
|
|
311
312
|
|
|
312
|
-
//
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
}
|
|
313
|
+
// Free-text single mode commits on intent signals (Enter, blur, option select),
|
|
314
|
+
// NOT per keystroke — see issue #32. Treating the search-box text as the field's
|
|
315
|
+
// committed value pollutes the parent form's edits buffer and history.
|
|
316
316
|
|
|
317
317
|
// Fetch suggestions with debounce
|
|
318
318
|
debouncedFetch(inputValue);
|
|
@@ -353,6 +353,19 @@
|
|
|
353
353
|
inputValue = '';
|
|
354
354
|
}
|
|
355
355
|
}
|
|
356
|
+
|
|
357
|
+
// Free-text single mode — commit on blur if the user typed something
|
|
358
|
+
// that differs from the current value. An empty inputValue is just the
|
|
359
|
+
// resting state of the search box (the value lives in the chip), so it
|
|
360
|
+
// is NOT an intent signal; clearing happens via the X button or
|
|
361
|
+
// Backspace-on-empty. Replaces the per-keystroke commit dropped from
|
|
362
|
+
// handleInput; see issue #32.
|
|
363
|
+
if (allowFreeText && !multiple && inputValue !== '') {
|
|
364
|
+
const currentSingle = selectedValues[0] ?? '';
|
|
365
|
+
if (inputValue !== currentSingle) {
|
|
366
|
+
onChange(inputValue);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
356
369
|
}, 200);
|
|
357
370
|
}
|
|
358
371
|
|
|
@@ -592,12 +605,14 @@
|
|
|
592
605
|
const current = depFingerprint;
|
|
593
606
|
if (current === prevDepFingerprint) return;
|
|
594
607
|
prevDepFingerprint = current;
|
|
595
|
-
// A dependency field changed — abort any in-flight fetch
|
|
608
|
+
// A dependency field changed — abort any in-flight fetch and invalidate
|
|
609
|
+
// cached suggestions/labels (they were keyed by the previous dependency
|
|
610
|
+
// values). Do NOT clear this field's value here: that policy lives in the
|
|
611
|
+
// parent form's handleFieldChange so it only fires on user-driven changes,
|
|
612
|
+
// not on undo/redo, programmatic resets, or collaborative edits (#33).
|
|
596
613
|
abortController?.abort();
|
|
597
614
|
suggestions = [];
|
|
598
615
|
labelCache = new Map();
|
|
599
|
-
if (multiple) onChange([]);
|
|
600
|
-
else onChange('');
|
|
601
616
|
});
|
|
602
617
|
|
|
603
618
|
/**
|
|
@@ -625,7 +640,7 @@
|
|
|
625
640
|
class:form-autocomplete--has-value={selectedValues.length > 0}
|
|
626
641
|
>
|
|
627
642
|
<!-- Main input container styled like a textfield/textarea -->
|
|
628
|
-
<!--
|
|
643
|
+
<!-- role="presentation"; keyboard interaction is handled by the <input> inside -->
|
|
629
644
|
<div
|
|
630
645
|
class="form-autocomplete__field"
|
|
631
646
|
class:form-autocomplete__field--focused={isOpen}
|
|
@@ -712,7 +727,7 @@
|
|
|
712
727
|
</div>
|
|
713
728
|
|
|
714
729
|
<!-- Dropdown popover (uses Popover API to render in top layer, bypassing stacking contexts) -->
|
|
715
|
-
<!--
|
|
730
|
+
<!-- role="presentation" container; onmousedown prevents focus loss from input -->
|
|
716
731
|
<div
|
|
717
732
|
bind:this={popoverElement}
|
|
718
733
|
id={listboxId}
|
|
@@ -743,7 +758,8 @@
|
|
|
743
758
|
</li>
|
|
744
759
|
{:else}
|
|
745
760
|
{#each suggestions as option, index (option.value)}
|
|
746
|
-
<!--
|
|
761
|
+
<!-- WAI-ARIA combobox: keyboard nav handled on input, not individual options -->
|
|
762
|
+
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
747
763
|
<li
|
|
748
764
|
id={getOptionId(index)}
|
|
749
765
|
class="form-autocomplete__option"
|
|
@@ -45,7 +45,9 @@
|
|
|
45
45
|
import { getSchemaOptions } from './types.js';
|
|
46
46
|
import type { WorkflowNode, WorkflowEdge, AuthProvider } from '../../types/index.js';
|
|
47
47
|
import { getResolvedTheme } from '../../stores/settingsStore.svelte.js';
|
|
48
|
-
import {
|
|
48
|
+
import { getInstance } from '../../stores/getInstance.svelte.js';
|
|
49
|
+
|
|
50
|
+
const fd = getInstance();
|
|
49
51
|
|
|
50
52
|
interface Props {
|
|
51
53
|
/** Unique key/id for the field */
|
|
@@ -226,7 +228,7 @@
|
|
|
226
228
|
});
|
|
227
229
|
|
|
228
230
|
const registeredAutocompleteComponent = $derived(
|
|
229
|
-
fieldType === 'autocomplete' ?
|
|
231
|
+
fieldType === 'autocomplete' ? fd.fields.resolveFieldComponent(schema) : null
|
|
230
232
|
);
|
|
231
233
|
|
|
232
234
|
/**
|
|
@@ -42,8 +42,10 @@
|
|
|
42
42
|
import FormSelect from './FormSelect.svelte';
|
|
43
43
|
import FormCheckboxGroup from './FormCheckboxGroup.svelte';
|
|
44
44
|
import FormArray from './FormArray.svelte';
|
|
45
|
-
import {
|
|
45
|
+
import { getInstance } from '../../stores/getInstance.svelte.js';
|
|
46
46
|
import { getResolvedTheme } from '../../stores/settingsStore.svelte.js';
|
|
47
|
+
|
|
48
|
+
const fd = getInstance();
|
|
47
49
|
import type { FieldSchema } from './types.js';
|
|
48
50
|
import { getSchemaOptions } from './types.js';
|
|
49
51
|
|
|
@@ -84,7 +86,7 @@
|
|
|
84
86
|
/**
|
|
85
87
|
* Check if there's a registered custom component for this schema
|
|
86
88
|
*/
|
|
87
|
-
const registeredComponent = $derived(
|
|
89
|
+
const registeredComponent = $derived(fd.fields.resolveFieldComponent(schema));
|
|
88
90
|
|
|
89
91
|
/**
|
|
90
92
|
* Determine the field type to render (for non-registered components)
|
|
@@ -409,11 +409,12 @@
|
|
|
409
409
|
}),
|
|
410
410
|
EditorView.lineWrapping,
|
|
411
411
|
|
|
412
|
-
// Accessibility
|
|
412
|
+
// Accessibility + browser spellcheck (off by default, opt-in via spellChecker)
|
|
413
413
|
ariaLabelCompartment.of(
|
|
414
414
|
EditorView.contentAttributes.of({
|
|
415
415
|
'aria-label': m().form.markdown.editor,
|
|
416
|
-
'aria-multiline': 'true'
|
|
416
|
+
'aria-multiline': 'true',
|
|
417
|
+
spellcheck: String(spellChecker)
|
|
417
418
|
})
|
|
418
419
|
)
|
|
419
420
|
];
|
|
@@ -495,7 +496,8 @@
|
|
|
495
496
|
ariaLabelCompartment.reconfigure(
|
|
496
497
|
EditorView.contentAttributes.of({
|
|
497
498
|
'aria-label': ariaLabel,
|
|
498
|
-
'aria-multiline': 'true'
|
|
499
|
+
'aria-multiline': 'true',
|
|
500
|
+
spellcheck: String(spellChecker)
|
|
499
501
|
})
|
|
500
502
|
)
|
|
501
503
|
]
|
|
@@ -525,7 +527,8 @@
|
|
|
525
527
|
role="toolbar"
|
|
526
528
|
aria-label={m().form.markdown.toolbar}
|
|
527
529
|
>
|
|
528
|
-
|
|
530
|
+
<!-- Separators have no identity of their own — disambiguate repeats by position -->
|
|
531
|
+
{#each toolbarActions as item, i (item === '|' ? `separator-${i}` : item.id)}
|
|
529
532
|
{#if item === '|'}
|
|
530
533
|
<span class="form-markdown-editor__separator"></span>
|
|
531
534
|
{:else}
|
|
@@ -536,6 +539,8 @@
|
|
|
536
539
|
onclick={item.action}
|
|
537
540
|
>
|
|
538
541
|
{#if item.isSvg}
|
|
542
|
+
<!-- item.icon is a compile-time SVG constant from toolbarActions, never user input -->
|
|
543
|
+
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
|
539
544
|
<span class="form-markdown-editor__btn-svg">{@html item.icon}</span>
|
|
540
545
|
{:else}
|
|
541
546
|
<span
|
|
@@ -30,7 +30,8 @@
|
|
|
30
30
|
tooltips,
|
|
31
31
|
Decoration,
|
|
32
32
|
ViewPlugin,
|
|
33
|
-
MatchDecorator
|
|
33
|
+
MatchDecorator,
|
|
34
|
+
placeholder as cmPlaceholder
|
|
34
35
|
} from '@codemirror/view';
|
|
35
36
|
import { EditorState, Compartment } from '@codemirror/state';
|
|
36
37
|
import { history, historyKeymap, defaultKeymap, indentWithTab } from '@codemirror/commands';
|
|
@@ -45,6 +46,7 @@
|
|
|
45
46
|
} from '../../types/index.js';
|
|
46
47
|
import { createTemplateAutocomplete } from './templateAutocomplete.js';
|
|
47
48
|
import { getVariableSchema } from '../../services/variableService.js';
|
|
49
|
+
import { getInstance } from '../../stores/getInstance.svelte.js';
|
|
48
50
|
import { logger } from '../../utils/logger.js';
|
|
49
51
|
import { m } from '../../messages/index.js';
|
|
50
52
|
|
|
@@ -105,6 +107,9 @@
|
|
|
105
107
|
authProvider
|
|
106
108
|
}: Props = $props();
|
|
107
109
|
|
|
110
|
+
// Active instance — supplies endpoint configuration for API variable fetching.
|
|
111
|
+
const fd = getInstance();
|
|
112
|
+
|
|
108
113
|
/** Loading state for API variable fetching */
|
|
109
114
|
let isLoadingVariables = $state(false);
|
|
110
115
|
|
|
@@ -139,6 +144,7 @@
|
|
|
139
144
|
try {
|
|
140
145
|
isLoadingVariables = true;
|
|
141
146
|
effectiveVariableSchema = await getVariableSchema(
|
|
147
|
+
fd.api.config,
|
|
142
148
|
node,
|
|
143
149
|
nodes,
|
|
144
150
|
edges,
|
|
@@ -350,7 +356,9 @@
|
|
|
350
356
|
}
|
|
351
357
|
}),
|
|
352
358
|
EditorView.lineWrapping,
|
|
353
|
-
EditorState.tabSize.of(2)
|
|
359
|
+
EditorState.tabSize.of(2),
|
|
360
|
+
// Shown inside the editor while the document is empty
|
|
361
|
+
cmPlaceholder(placeholder)
|
|
354
362
|
];
|
|
355
363
|
|
|
356
364
|
// Add autocomplete compartment (can be reconfigured dynamically)
|
|
@@ -570,7 +578,7 @@
|
|
|
570
578
|
onclick={() => insertVariable(varName)}
|
|
571
579
|
title={`Insert {{ ${varName} }}`}
|
|
572
580
|
>
|
|
573
|
-
<code>{
|
|
581
|
+
<code>{`{{ ${varName} }}`}</code>
|
|
574
582
|
</button>
|
|
575
583
|
{/each}
|
|
576
584
|
</div>
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
-->
|
|
10
10
|
|
|
11
11
|
<script lang="ts">
|
|
12
|
-
import { m
|
|
12
|
+
import { m } from '../../messages/index.js';
|
|
13
13
|
|
|
14
14
|
interface Props {
|
|
15
15
|
/** Field identifier */
|
|
@@ -17,11 +17,13 @@
|
|
|
17
17
|
/** Current value */
|
|
18
18
|
value: boolean;
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
20
|
+
* Per-instance label for the on state (e.g. "Hidden" for a visibility
|
|
21
|
+
* toggle). Falls back to the global `messages.form.toggle.enabled`.
|
|
21
22
|
*/
|
|
22
23
|
onLabel?: string;
|
|
23
24
|
/**
|
|
24
|
-
*
|
|
25
|
+
* Per-instance label for the off state. Falls back to the global
|
|
26
|
+
* `messages.form.toggle.disabled`.
|
|
25
27
|
*/
|
|
26
28
|
offLabel?: string;
|
|
27
29
|
/** Whether the field is disabled (read-only) */
|
|
@@ -42,15 +44,6 @@
|
|
|
42
44
|
onChange
|
|
43
45
|
}: Props = $props();
|
|
44
46
|
|
|
45
|
-
// svelte-ignore state_referenced_locally — deprecation warns once per mount; later prop rebinds aren't relevant
|
|
46
|
-
if (onLabel !== undefined) {
|
|
47
|
-
warnDeprecatedProp('FormToggle', 'onLabel', 'messages.form.toggle.enabled');
|
|
48
|
-
}
|
|
49
|
-
// svelte-ignore state_referenced_locally
|
|
50
|
-
if (offLabel !== undefined) {
|
|
51
|
-
warnDeprecatedProp('FormToggle', 'offLabel', 'messages.form.toggle.disabled');
|
|
52
|
-
}
|
|
53
|
-
|
|
54
47
|
const resolvedOnLabel = $derived(onLabel ?? m().form.toggle.enabled);
|
|
55
48
|
const resolvedOffLabel = $derived(offLabel ?? m().form.toggle.disabled);
|
|
56
49
|
|
|
@@ -4,11 +4,13 @@ interface Props {
|
|
|
4
4
|
/** Current value */
|
|
5
5
|
value: boolean;
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
7
|
+
* Per-instance label for the on state (e.g. "Hidden" for a visibility
|
|
8
|
+
* toggle). Falls back to the global `messages.form.toggle.enabled`.
|
|
8
9
|
*/
|
|
9
10
|
onLabel?: string;
|
|
10
11
|
/**
|
|
11
|
-
*
|
|
12
|
+
* Per-instance label for the off state. Falls back to the global
|
|
13
|
+
* `messages.form.toggle.disabled`.
|
|
12
14
|
*/
|
|
13
15
|
offLabel?: string;
|
|
14
16
|
/** Whether the field is disabled (read-only) */
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* @module components/form/templateAutocomplete
|
|
12
12
|
*/
|
|
13
13
|
import { autocompletion } from '@codemirror/autocomplete';
|
|
14
|
-
import { getChildVariables, getArrayIndexSuggestions, isArrayVariable
|
|
14
|
+
import { getChildVariables, getArrayIndexSuggestions, isArrayVariable } from '../../services/variableService.js';
|
|
15
15
|
/**
|
|
16
16
|
* Icon type hints for different variable types in autocomplete dropdown.
|
|
17
17
|
*/
|
|
@@ -56,10 +56,6 @@ function extractVariablePath(text, pos) {
|
|
|
56
56
|
if (openBracePos === -1) {
|
|
57
57
|
return null;
|
|
58
58
|
}
|
|
59
|
-
// Check if there's a closing }} after cursor (still inside expression)
|
|
60
|
-
const afterCursor = text.slice(pos);
|
|
61
|
-
const closingMatch = afterCursor.match(/^\s*\}\}/);
|
|
62
|
-
const hasClosing = closingMatch !== null;
|
|
63
59
|
// Extract the content between {{ and cursor
|
|
64
60
|
const contentStart = openBracePos + 2;
|
|
65
61
|
const content = text.slice(contentStart, pos).trimStart();
|
|
@@ -95,8 +95,7 @@ export interface BaseFieldProps<T = unknown> {
|
|
|
95
95
|
/**
|
|
96
96
|
* Properties for text input fields
|
|
97
97
|
*/
|
|
98
|
-
export
|
|
99
|
-
}
|
|
98
|
+
export type TextFieldProps = BaseFieldProps<string>;
|
|
100
99
|
/**
|
|
101
100
|
* Properties for multiline text fields (textarea)
|
|
102
101
|
*/
|
|
@@ -432,18 +431,6 @@ export interface SchemaFormProps {
|
|
|
432
431
|
* @default false
|
|
433
432
|
*/
|
|
434
433
|
showActions?: boolean;
|
|
435
|
-
/**
|
|
436
|
-
* Label text for the save button.
|
|
437
|
-
* Only used when showActions is true.
|
|
438
|
-
* @default "Save"
|
|
439
|
-
*/
|
|
440
|
-
saveLabel?: string;
|
|
441
|
-
/**
|
|
442
|
-
* Label text for the cancel button.
|
|
443
|
-
* Only used when showActions is true.
|
|
444
|
-
* @default "Cancel"
|
|
445
|
-
*/
|
|
446
|
-
cancelLabel?: string;
|
|
447
434
|
/**
|
|
448
435
|
* Callback fired when the Save button is clicked.
|
|
449
436
|
* Receives the final form values after collecting from DOM.
|
|
@@ -44,7 +44,8 @@
|
|
|
44
44
|
}: Props = $props();
|
|
45
45
|
|
|
46
46
|
/** Local state for form values */
|
|
47
|
-
//
|
|
47
|
+
// initial default, user fills the form
|
|
48
|
+
// svelte-ignore state_referenced_locally
|
|
48
49
|
let formValues = $state<Record<string, unknown>>(config.defaultValues ?? {});
|
|
49
50
|
|
|
50
51
|
/** Display values - either resolved or current form values */
|
|
@@ -131,7 +132,7 @@
|
|
|
131
132
|
<div class="form-prompt__resolved-values">
|
|
132
133
|
<h4 class="form-prompt__resolved-title">{interrupt.form.submittedValuesTitle}</h4>
|
|
133
134
|
<div class="form-prompt__values-list">
|
|
134
|
-
{#each Object.entries(config.schema.properties ?? {}) as [key, field]}
|
|
135
|
+
{#each Object.entries(config.schema.properties ?? {}) as [key, field] (key)}
|
|
135
136
|
{@const value = displayValues[key]}
|
|
136
137
|
{@const fieldTitle = ((field as Record<string, unknown>).title as string) ?? key}
|
|
137
138
|
<div class="form-prompt__value-item">
|
|
@@ -33,11 +33,8 @@
|
|
|
33
33
|
getErrorMessage,
|
|
34
34
|
getResolvedValue
|
|
35
35
|
} from '../../types/interruptState.js';
|
|
36
|
-
import {
|
|
37
|
-
|
|
38
|
-
interruptActions,
|
|
39
|
-
type InterruptWithState
|
|
40
|
-
} from '../../stores/interruptStore.svelte.js';
|
|
36
|
+
import { type InterruptWithState } from '../../stores/interruptStore.svelte.js';
|
|
37
|
+
import { getInstance } from '../../stores/getInstance.svelte.js';
|
|
41
38
|
import { interruptService } from '../../services/interruptService.js';
|
|
42
39
|
import { logger } from '../../utils/logger.js';
|
|
43
40
|
import { m } from '../../messages/index.js';
|
|
@@ -72,12 +69,14 @@
|
|
|
72
69
|
tags
|
|
73
70
|
}: Props = $props();
|
|
74
71
|
|
|
72
|
+
const fd = getInstance();
|
|
73
|
+
|
|
75
74
|
/**
|
|
76
75
|
* Get the current interrupt state from the store.
|
|
77
76
|
* This ensures we react to store updates (like status changes).
|
|
78
77
|
*/
|
|
79
78
|
const currentInterrupt = $derived(
|
|
80
|
-
|
|
79
|
+
fd.interrupts.getMap().get(initialInterrupt.id) ?? addMachineState(initialInterrupt)
|
|
81
80
|
);
|
|
82
81
|
|
|
83
82
|
const hierarchyItems = $derived(hierarchy ?? []);
|
|
@@ -191,7 +190,7 @@
|
|
|
191
190
|
*/
|
|
192
191
|
async function handleResolve(value: unknown): Promise<void> {
|
|
193
192
|
// Start the submission - state machine validates this transition
|
|
194
|
-
const startResult =
|
|
193
|
+
const startResult = fd.interrupts.startSubmit(currentInterrupt.id, value);
|
|
195
194
|
if (!startResult.valid) {
|
|
196
195
|
logger.warn('[InterruptBubble] Cannot submit:', startResult.error);
|
|
197
196
|
return;
|
|
@@ -199,19 +198,19 @@
|
|
|
199
198
|
|
|
200
199
|
try {
|
|
201
200
|
// Call API if service is configured
|
|
202
|
-
if (interruptService.isConfigured()) {
|
|
203
|
-
await interruptService.resolveInterrupt(currentInterrupt.id, value);
|
|
201
|
+
if (interruptService.isConfigured(fd.api.config)) {
|
|
202
|
+
await interruptService.resolveInterrupt(fd.api.config, currentInterrupt.id, value);
|
|
204
203
|
}
|
|
205
204
|
|
|
206
205
|
// Mark as successful - transitions to resolved state
|
|
207
|
-
|
|
206
|
+
fd.interrupts.submitSuccess(currentInterrupt.id);
|
|
208
207
|
|
|
209
208
|
// Notify parent to refresh messages
|
|
210
209
|
onResolved?.();
|
|
211
210
|
} catch (err) {
|
|
212
211
|
// Mark as failed - transitions to error state (can retry)
|
|
213
212
|
const errorMessage = err instanceof Error ? err.message : 'Failed to submit response';
|
|
214
|
-
|
|
213
|
+
fd.interrupts.submitFailure(currentInterrupt.id, errorMessage);
|
|
215
214
|
logger.error('[InterruptBubble] Resolve error:', err);
|
|
216
215
|
}
|
|
217
216
|
}
|
|
@@ -221,7 +220,7 @@
|
|
|
221
220
|
*/
|
|
222
221
|
async function handleCancel(): Promise<void> {
|
|
223
222
|
// Start the cancel - state machine validates this transition
|
|
224
|
-
const startResult =
|
|
223
|
+
const startResult = fd.interrupts.startCancel(currentInterrupt.id);
|
|
225
224
|
if (!startResult.valid) {
|
|
226
225
|
logger.warn('[InterruptBubble] Cannot cancel:', startResult.error);
|
|
227
226
|
return;
|
|
@@ -229,19 +228,19 @@
|
|
|
229
228
|
|
|
230
229
|
try {
|
|
231
230
|
// Call API if service is configured
|
|
232
|
-
if (interruptService.isConfigured()) {
|
|
233
|
-
await interruptService.cancelInterrupt(currentInterrupt.id);
|
|
231
|
+
if (interruptService.isConfigured(fd.api.config)) {
|
|
232
|
+
await interruptService.cancelInterrupt(fd.api.config, currentInterrupt.id);
|
|
234
233
|
}
|
|
235
234
|
|
|
236
235
|
// Mark as successful - transitions to cancelled state
|
|
237
|
-
|
|
236
|
+
fd.interrupts.submitSuccess(currentInterrupt.id);
|
|
238
237
|
|
|
239
238
|
// Notify parent to refresh messages
|
|
240
239
|
onResolved?.();
|
|
241
240
|
} catch (err) {
|
|
242
241
|
// Mark as failed - transitions to error state (can retry)
|
|
243
242
|
const errorMessage = err instanceof Error ? err.message : 'Failed to cancel';
|
|
244
|
-
|
|
243
|
+
fd.interrupts.submitFailure(currentInterrupt.id, errorMessage);
|
|
245
244
|
logger.error('[InterruptBubble] Cancel error:', err);
|
|
246
245
|
}
|
|
247
246
|
}
|
|
@@ -250,7 +249,7 @@
|
|
|
250
249
|
* Handle retry after error
|
|
251
250
|
*/
|
|
252
251
|
function handleRetry(): void {
|
|
253
|
-
|
|
252
|
+
fd.interrupts.retry(currentInterrupt.id);
|
|
254
253
|
}
|
|
255
254
|
|
|
256
255
|
// Typed config getters for each prompt type
|
|
@@ -51,7 +51,8 @@
|
|
|
51
51
|
}: Props = $props();
|
|
52
52
|
|
|
53
53
|
/** Local state: map of field -> accepted boolean. Default all to true (accept). */
|
|
54
|
-
//
|
|
54
|
+
// initial default, user toggles during review
|
|
55
|
+
// svelte-ignore state_referenced_locally
|
|
55
56
|
let decisions = $state<Record<string, boolean>>(
|
|
56
57
|
Object.fromEntries(config.changes.map((c) => [c.field, true]))
|
|
57
58
|
);
|
|
@@ -346,9 +347,12 @@
|
|
|
346
347
|
<div class="review-prompt__diff-row">
|
|
347
348
|
<span class="review-prompt__diff-label">{t.original}</span>
|
|
348
349
|
{#if isHtml && !isRawView}
|
|
350
|
+
<!-- Output of sanitizeHtml() (DOMPurify allowlist) — see utils/sanitize.ts -->
|
|
351
|
+
<!-- eslint-disable svelte/no-at-html-tags -->
|
|
349
352
|
<span class="review-prompt__diff-value review-prompt__html-content"
|
|
350
353
|
>{@html sanitizeHtml(String(change.original))}</span
|
|
351
354
|
>
|
|
355
|
+
<!-- eslint-enable svelte/no-at-html-tags -->
|
|
352
356
|
{:else if isHtml && isRawView}
|
|
353
357
|
<code class="review-prompt__diff-value review-prompt__raw-html"
|
|
354
358
|
>{change.original}</code
|
|
@@ -362,10 +366,13 @@
|
|
|
362
366
|
<div class="review-prompt__diff-row">
|
|
363
367
|
<span class="review-prompt__diff-label">{t.proposed}</span>
|
|
364
368
|
{#if isHtml && !isRawView}
|
|
369
|
+
<!-- Output of sanitizeHtml() (DOMPurify allowlist) — see utils/sanitize.ts -->
|
|
370
|
+
<!-- eslint-disable svelte/no-at-html-tags -->
|
|
365
371
|
<span
|
|
366
372
|
class="review-prompt__diff-value review-prompt__diff-value--proposed review-prompt__html-content"
|
|
367
373
|
>{@html sanitizeHtml(String(change.proposed))}</span
|
|
368
374
|
>
|
|
375
|
+
<!-- eslint-enable svelte/no-at-html-tags -->
|
|
369
376
|
{:else if isHtml && isRawView}
|
|
370
377
|
<code
|
|
371
378
|
class="review-prompt__diff-value review-prompt__diff-value--proposed review-prompt__raw-html"
|
|
@@ -382,14 +389,14 @@
|
|
|
382
389
|
<span class="review-prompt__diff-label">{t.diff}</span>
|
|
383
390
|
{#if isMultiLineDiff(diff)}
|
|
384
391
|
<pre
|
|
385
|
-
class="review-prompt__diff-value review-prompt__diff-block">{#each diff as part}{#if part.added}<span
|
|
392
|
+
class="review-prompt__diff-value review-prompt__diff-block">{#each diff as part, i (i)}{#if part.added}<span
|
|
386
393
|
class="review-prompt__diff-token--added">{part.value}</span
|
|
387
394
|
>{:else if part.removed}<span class="review-prompt__diff-token--removed"
|
|
388
395
|
>{part.value}</span
|
|
389
396
|
>{:else}<span>{part.value}</span>{/if}{/each}</pre>
|
|
390
397
|
{:else}
|
|
391
398
|
<span class="review-prompt__diff-value review-prompt__diff-inline">
|
|
392
|
-
{#each diff as part}
|
|
399
|
+
{#each diff as part, i (i)}
|
|
393
400
|
{#if part.added}
|
|
394
401
|
<span class="review-prompt__diff-token--added">{part.value}</span>
|
|
395
402
|
{:else if part.removed}
|
|
@@ -47,7 +47,8 @@
|
|
|
47
47
|
const t = $derived(m().interrupt.text);
|
|
48
48
|
|
|
49
49
|
/** Local state for input value */
|
|
50
|
-
//
|
|
50
|
+
// initial default, user edits the input
|
|
51
|
+
// svelte-ignore state_referenced_locally
|
|
51
52
|
let inputValue = $state(config.defaultValue ?? '');
|
|
52
53
|
|
|
53
54
|
/** Display value - either resolved or current input */
|
|
@@ -17,6 +17,10 @@
|
|
|
17
17
|
* Configuration props for the MainLayout component
|
|
18
18
|
*/
|
|
19
19
|
interface Props {
|
|
20
|
+
/** Overall layout height (CSS length, or a number of pixels) */
|
|
21
|
+
height?: string | number;
|
|
22
|
+
/** Overall layout width (CSS length, or a number of pixels) */
|
|
23
|
+
width?: string | number;
|
|
20
24
|
/** Height of the header in pixels */
|
|
21
25
|
headerHeight?: number;
|
|
22
26
|
/** Height of the footer in pixels */
|
|
@@ -74,6 +78,8 @@
|
|
|
74
78
|
}
|
|
75
79
|
|
|
76
80
|
let {
|
|
81
|
+
height = '100vh',
|
|
82
|
+
width = '100%',
|
|
77
83
|
headerHeight = 60,
|
|
78
84
|
footerHeight = 48,
|
|
79
85
|
showHeader = true,
|
|
@@ -103,9 +109,12 @@
|
|
|
103
109
|
children
|
|
104
110
|
}: Props = $props();
|
|
105
111
|
|
|
106
|
-
/**
|
|
107
|
-
|
|
108
|
-
|
|
112
|
+
/**
|
|
113
|
+
* Current width of the left sidebar.
|
|
114
|
+
* Writable derived: recomputes when the prop changes (external control,
|
|
115
|
+
* e.g. collapsed state), while drag/keyboard resizing assigns over it.
|
|
116
|
+
*/
|
|
117
|
+
let leftSidebarWidth = $derived(initialLeftWidth);
|
|
109
118
|
|
|
110
119
|
/** Current width of the right sidebar */
|
|
111
120
|
// svelte-ignore state_referenced_locally
|
|
@@ -115,14 +124,6 @@
|
|
|
115
124
|
// svelte-ignore state_referenced_locally
|
|
116
125
|
let bottomPanelHeightState = $state(initialBottomHeight);
|
|
117
126
|
|
|
118
|
-
/**
|
|
119
|
-
* Sync left sidebar width with prop changes
|
|
120
|
-
* This allows external control (e.g., collapsed state) to update the width
|
|
121
|
-
*/
|
|
122
|
-
$effect(() => {
|
|
123
|
-
leftSidebarWidth = initialLeftWidth;
|
|
124
|
-
});
|
|
125
|
-
|
|
126
127
|
/** Whether the user is currently dragging the left divider */
|
|
127
128
|
let isDraggingLeft = $state(false);
|
|
128
129
|
|
|
@@ -298,6 +299,10 @@
|
|
|
298
299
|
|
|
299
300
|
/** Computed CSS variable for bottom panel height */
|
|
300
301
|
const bottomHeightVar = $derived(`${bottomPanelHeightState}px`);
|
|
302
|
+
|
|
303
|
+
/** Bare numbers mean pixels; strings pass through as CSS lengths */
|
|
304
|
+
const layoutHeightVar = $derived(typeof height === 'number' ? `${height}px` : height);
|
|
305
|
+
const layoutWidthVar = $derived(typeof width === 'number' ? `${width}px` : width);
|
|
301
306
|
</script>
|
|
302
307
|
|
|
303
308
|
<div
|
|
@@ -306,6 +311,8 @@
|
|
|
306
311
|
class:flowdrop-main-layout--dragging={isDraggingLeft || isDraggingRight || isDraggingBottom}
|
|
307
312
|
class:flowdrop-main-layout--dragging-vertical={isDraggingBottom}
|
|
308
313
|
style="
|
|
314
|
+
--layout-height: {layoutHeightVar};
|
|
315
|
+
--layout-width: {layoutWidthVar};
|
|
309
316
|
--layout-header-height: {headerHeightVar};
|
|
310
317
|
--layout-footer-height: {footerHeightVar};
|
|
311
318
|
--layout-left-sidebar-width: {leftWidthVar};
|
|
@@ -437,8 +444,8 @@
|
|
|
437
444
|
.flowdrop-main-layout {
|
|
438
445
|
display: flex;
|
|
439
446
|
flex-direction: column;
|
|
440
|
-
height: 100vh;
|
|
441
|
-
width: 100
|
|
447
|
+
height: var(--layout-height, 100vh);
|
|
448
|
+
width: var(--layout-width, 100%);
|
|
442
449
|
background: var(
|
|
443
450
|
--fd-layout-background,
|
|
444
451
|
linear-gradient(135deg, #f9fafb 0%, #e0e7ff 50%, #c7d2fe 100%)
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
* Configuration props for the MainLayout component
|
|
3
3
|
*/
|
|
4
4
|
interface Props {
|
|
5
|
+
/** Overall layout height (CSS length, or a number of pixels) */
|
|
6
|
+
height?: string | number;
|
|
7
|
+
/** Overall layout width (CSS length, or a number of pixels) */
|
|
8
|
+
width?: string | number;
|
|
5
9
|
/** Height of the header in pixels */
|
|
6
10
|
headerHeight?: number;
|
|
7
11
|
/** Height of the footer in pixels */
|