@flowdrop/flowdrop 2.0.0-beta.1 → 2.0.0-beta.3

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 (149) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/MIGRATION-2.0.md +173 -3
  3. package/dist/api/enhanced-client.js +6 -11
  4. package/dist/components/App.svelte +22 -45
  5. package/dist/components/App.svelte.d.ts +2 -7
  6. package/dist/components/CanvasIconButton.svelte +76 -0
  7. package/dist/components/CanvasIconButton.svelte.d.ts +18 -0
  8. package/dist/components/ConfigForm.svelte +6 -21
  9. package/dist/components/ConfigPanel.svelte +4 -3
  10. package/dist/components/LogoWordmark.svelte +113 -0
  11. package/dist/components/LogoWordmark.svelte.d.ts +26 -0
  12. package/dist/components/Navbar.svelte +8 -59
  13. package/dist/components/NodeSidebar.svelte +4 -11
  14. package/dist/components/NodeSwapPicker.svelte +0 -2
  15. package/dist/components/PipelineStatus.svelte +6 -1
  16. package/dist/components/PipelineStatus.svelte.d.ts +3 -0
  17. package/dist/components/PortMappingRow.svelte +0 -2
  18. package/dist/components/SchemaForm.svelte +4 -14
  19. package/dist/components/SettingsModal.svelte +0 -5
  20. package/dist/components/SettingsPanel.svelte +2 -6
  21. package/dist/components/ThemeToggle.svelte +0 -5
  22. package/dist/components/UniversalNode.svelte +32 -1
  23. package/dist/components/WorkflowEditor.svelte +66 -52
  24. package/dist/components/WorkflowEditor.svelte.d.ts +21 -0
  25. package/dist/components/chat/AIChatPanel.svelte +7 -2
  26. package/dist/components/console/ConsoleAutocomplete.svelte +1 -1
  27. package/dist/components/console/ConsoleOutput.svelte +2 -2
  28. package/dist/components/form/FormArray.svelte +0 -16
  29. package/dist/components/form/FormAutocomplete.svelte +18 -15
  30. package/dist/components/form/FormCheckboxGroup.svelte +0 -4
  31. package/dist/components/form/FormCodeEditor.svelte +9 -7
  32. package/dist/components/form/FormFieldLight.svelte +33 -4
  33. package/dist/components/form/FormFieldLight.svelte.d.ts +12 -0
  34. package/dist/components/form/FormMarkdownEditor.svelte +8 -5
  35. package/dist/components/form/FormNumberField.svelte +0 -4
  36. package/dist/components/form/FormRangeField.svelte +1 -20
  37. package/dist/components/form/FormSelect.svelte +10 -6
  38. package/dist/components/form/FormTemplateEditor.svelte +6 -4
  39. package/dist/components/form/FormTextField.svelte +10 -6
  40. package/dist/components/form/FormTextarea.svelte +10 -6
  41. package/dist/components/form/FormToggle.svelte +0 -4
  42. package/dist/components/form/FormUISchemaRenderer.svelte +3 -1
  43. package/dist/components/icons/CommandLineIcon.svelte +15 -0
  44. package/dist/components/icons/CommandLineIcon.svelte.d.ts +26 -0
  45. package/dist/components/icons/MenuIcon.svelte +4 -0
  46. package/dist/components/icons/MenuIcon.svelte.d.ts +26 -0
  47. package/dist/components/icons/MenuOpenIcon.svelte +6 -0
  48. package/dist/components/icons/MenuOpenIcon.svelte.d.ts +26 -0
  49. package/dist/components/interrupt/ChoicePrompt.svelte +0 -10
  50. package/dist/components/interrupt/ConfirmationPrompt.svelte +0 -5
  51. package/dist/components/interrupt/InterruptBubble.svelte +11 -12
  52. package/dist/components/interrupt/ReviewPrompt.svelte +0 -20
  53. package/dist/components/interrupt/TextInputPrompt.svelte +0 -6
  54. package/dist/components/layouts/MainLayout.svelte +4 -5
  55. package/dist/components/nodes/AtomNode.svelte +46 -34
  56. package/dist/components/nodes/GatewayNode.svelte +91 -99
  57. package/dist/components/nodes/IdeaNode.svelte +62 -90
  58. package/dist/components/nodes/NodeConfigButton.svelte +86 -0
  59. package/dist/components/nodes/NodeConfigButton.svelte.d.ts +15 -0
  60. package/dist/components/nodes/NotesNode.svelte +70 -81
  61. package/dist/components/nodes/SimpleNode.svelte +28 -78
  62. package/dist/components/nodes/SquareNode.svelte +79 -109
  63. package/dist/components/nodes/TerminalNode.svelte +28 -86
  64. package/dist/components/nodes/ToolNode.svelte +82 -95
  65. package/dist/components/nodes/WorkflowNode.svelte +91 -100
  66. package/dist/components/playground/ChatInput.svelte +0 -1
  67. package/dist/components/playground/InputCollector.svelte +0 -2
  68. package/dist/components/playground/PipelineKanbanView.svelte +4 -2
  69. package/dist/components/playground/PipelineKanbanView.svelte.d.ts +2 -0
  70. package/dist/components/playground/PipelinePanel.svelte +20 -3
  71. package/dist/components/playground/PipelinePanel.svelte.d.ts +2 -0
  72. package/dist/components/playground/PipelineTableView.svelte +4 -2
  73. package/dist/components/playground/PipelineTableView.svelte.d.ts +2 -0
  74. package/dist/components/playground/Playground.svelte +76 -25
  75. package/dist/components/playground/Playground.svelte.d.ts +3 -0
  76. package/dist/components/playground/PlaygroundApp.svelte +6 -1
  77. package/dist/components/playground/PlaygroundApp.svelte.d.ts +3 -0
  78. package/dist/components/playground/PlaygroundModal.svelte +5 -0
  79. package/dist/components/playground/PlaygroundModal.svelte.d.ts +3 -0
  80. package/dist/components/playground/PlaygroundStudio.svelte +7 -6
  81. package/dist/components/playground/PlaygroundStudio.svelte.d.ts +3 -0
  82. package/dist/components/playground/pipelineViewUtils.svelte.d.ts +2 -1
  83. package/dist/components/playground/pipelineViewUtils.svelte.js +2 -2
  84. package/dist/config/endpoints.d.ts +23 -0
  85. package/dist/config/endpoints.js +28 -0
  86. package/dist/core/index.d.ts +1 -2
  87. package/dist/core/index.js +2 -6
  88. package/dist/display/index.d.ts +6 -1
  89. package/dist/display/index.js +9 -1
  90. package/dist/editor/index.d.ts +1 -1
  91. package/dist/editor/index.js +1 -1
  92. package/dist/form/full.d.ts +2 -1
  93. package/dist/form/full.js +4 -1
  94. package/dist/form/index.d.ts +0 -1
  95. package/dist/form/index.js +3 -2
  96. package/dist/helpers/workflowEditorHelper.d.ts +4 -2
  97. package/dist/helpers/workflowEditorHelper.js +4 -3
  98. package/dist/playground/index.d.ts +2 -2
  99. package/dist/playground/index.js +2 -2
  100. package/dist/playground/mount.d.ts +19 -5
  101. package/dist/playground/mount.js +16 -8
  102. package/dist/registry/builtinNodeTypes.d.ts +53 -0
  103. package/dist/registry/builtinNodeTypes.js +67 -0
  104. package/dist/registry/builtinNodes.d.ts +2 -39
  105. package/dist/registry/builtinNodes.js +6 -53
  106. package/dist/services/agentSpecExecutionService.d.ts +0 -2
  107. package/dist/services/agentSpecExecutionService.js +0 -2
  108. package/dist/services/apiVariableService.js +12 -26
  109. package/dist/services/categoriesApi.js +3 -6
  110. package/dist/services/chatService.d.ts +4 -3
  111. package/dist/services/chatService.js +13 -18
  112. package/dist/services/interruptService.d.ts +7 -6
  113. package/dist/services/interruptService.js +19 -21
  114. package/dist/services/playgroundService.d.ts +9 -8
  115. package/dist/services/playgroundService.js +23 -25
  116. package/dist/services/portConfigApi.js +3 -6
  117. package/dist/services/settingsService.d.ts +9 -4
  118. package/dist/services/settingsService.js +23 -12
  119. package/dist/skins/drafter.d.ts +30 -0
  120. package/dist/skins/drafter.js +185 -0
  121. package/dist/skins/index.d.ts +2 -1
  122. package/dist/skins/index.js +4 -2
  123. package/dist/stores/apiContext.d.ts +11 -0
  124. package/dist/stores/apiContext.js +15 -0
  125. package/dist/stores/categoriesStore.svelte.js +0 -1
  126. package/dist/stores/playgroundStore.svelte.js +0 -2
  127. package/dist/styles/base.css +38 -9
  128. package/dist/styles/tokens.css +54 -2
  129. package/dist/svelte-app.d.ts +6 -0
  130. package/dist/svelte-app.js +4 -2
  131. package/dist/themes/drafter.d.ts +2 -0
  132. package/dist/themes/drafter.js +15 -0
  133. package/dist/themes/index.d.ts +2 -1
  134. package/dist/themes/index.js +8 -2
  135. package/dist/types/auth.d.ts +9 -51
  136. package/dist/types/auth.js +4 -54
  137. package/dist/types/events.d.ts +18 -0
  138. package/dist/types/events.js +2 -1
  139. package/dist/types/index.d.ts +4 -2
  140. package/dist/types/index.js +0 -1
  141. package/dist/types/settings.d.ts +1 -1
  142. package/dist/types/settings.js +1 -1
  143. package/dist/types/skin.d.ts +1 -1
  144. package/dist/types/theme.d.ts +16 -2
  145. package/dist/utils/edgeStyling.js +9 -5
  146. package/dist/utils/fetchWithAuth.d.ts +36 -15
  147. package/dist/utils/fetchWithAuth.js +53 -23
  148. package/dist/utils/nodeTypes.js +1 -1
  149. package/package.json +2 -1
@@ -26,13 +26,15 @@
26
26
  import CanvasController from './CanvasController.svelte';
27
27
  import FlowDropZone from './FlowDropZone.svelte';
28
28
  import EdgeRefresher from './EdgeRefresher.svelte';
29
- import { tick, untrack } from 'svelte';
29
+ import { tick, untrack, onMount } from 'svelte';
30
30
  import type { EndpointConfig } from '../config/endpoints.js';
31
+ import type { AuthProvider } from '../types/auth.js';
31
32
  import ConnectionLine from './ConnectionLine.svelte';
32
33
  import FlowDropEdge from './FlowDropEdge.svelte';
33
34
  import { m } from '../messages/index.js';
34
35
  import { provideInstance } from '../stores/getInstance.svelte.js';
35
36
  import type { FlowDropInstance } from '../stores/instanceContainer.svelte.js';
37
+ import type { FlowDropGridVariant } from '../types/theme.js';
36
38
  import UniversalNode from './UniversalNode.svelte';
37
39
  import {
38
40
  EdgeStylingHelper,
@@ -55,11 +57,14 @@
55
57
  import { logger } from '../utils/logger.js';
56
58
  import { validateWorkflowData } from '../utils/validation.js';
57
59
  import { createEditorStateMachine } from '../stores/editorStateMachine.svelte.js';
58
- import Icon from '@iconify/svelte';
60
+ import CanvasIconButton from './CanvasIconButton.svelte';
61
+ import CommandLineIcon from './icons/CommandLineIcon.svelte';
59
62
  import { DEV } from 'esm-env';
60
63
 
61
64
  interface Props {
62
65
  endpointConfig?: EndpointConfig;
66
+ /** Auth provider applied to this instance's API requests. */
67
+ authProvider?: AuthProvider;
63
68
  openConfigSidebar?: (node: WorkflowNodeType) => void;
64
69
  /**
65
70
  * Editor interaction mode. `'edit'` allows node drag/connect/select and
@@ -82,6 +87,23 @@
82
87
  onToggleConsole?: () => void;
83
88
  /** Per-instance state container (created by mount functions). Defaults to the page-default instance. */
84
89
  instance?: FlowDropInstance;
90
+ /**
91
+ * Canvas background grid pattern. Supplied by App from the active theme's
92
+ * `config.canvas.grid` default; any theme can opt into 'lines' / 'cross'.
93
+ * Color is driven separately by the `--fd-grid-pattern-color` token.
94
+ * @default 'dots'
95
+ */
96
+ gridVariant?: FlowDropGridVariant;
97
+ /**
98
+ * Register the built-in heavy form editors (markdown / code / template)
99
+ * on this instance's field registry. Batteries-included by default — node
100
+ * config fields with `format: 'markdown' | 'code' | 'template'` render real
101
+ * CodeMirror editors. The chunks are code-split (loaded lazily here), so
102
+ * the `/editor` static bundle stays light. Set `false` to keep the textarea
103
+ * fallback or register your own field components. See `features.builtinEditors`.
104
+ * @default true
105
+ */
106
+ builtinEditors?: boolean;
85
107
  }
86
108
 
87
109
  let props: Props = $props();
@@ -92,10 +114,36 @@
92
114
  // svelte-ignore state_referenced_locally
93
115
  const fd = provideInstance(props.instance);
94
116
 
117
+ // Batteries-included: register the built-in heavy form editors (markdown /
118
+ // code / template) on this instance's field registry so node config fields
119
+ // render real editors out of the box. Dynamic import is deliberate — the
120
+ // bundle guard only inspects *static* imports, and `form/markdown`/`form/code`
121
+ // statically re-export their CodeMirror components, so a static import here
122
+ // would leak CodeMirror into the light `/editor` entry. Importing lazily on
123
+ // mount keeps the static graph clean while the chunks load on demand.
124
+ // register*Field is idempotent per registry, so re-mounts are safe.
125
+ onMount(() => {
126
+ if (props.builtinEditors === false) return;
127
+ void (async () => {
128
+ const [code, markdown] = await Promise.all([
129
+ import('../form/code.js'),
130
+ import('../form/markdown.js')
131
+ ]);
132
+ code.registerCodeEditorField(fd.fields);
133
+ code.registerTemplateEditorField(fd.fields);
134
+ markdown.registerMarkdownEditorField(fd.fields);
135
+ })();
136
+ });
137
+
95
138
  // `mode` is the public API; the canvas only needs to know whether editing is
96
139
  // enabled. 'readonly' and 'locked' both disable interaction identically.
97
140
  const canvasEditable = $derived((props.mode ?? 'edit') === 'edit');
98
141
 
142
+ // Canvas grid pattern, supplied by the active theme's config.canvas.grid
143
+ // (App passes it down). BackgroundVariant's enum values are the same strings
144
+ // ('dots' | 'lines' | 'cross'), so the theme config maps straight through.
145
+ const gridVariant = $derived((props.gridVariant ?? 'dots') as BackgroundVariant);
146
+
99
147
  // ---------------------------------------------------------------------------
100
148
  // Editor State Machine
101
149
  // Centralizes reactive guards — replaces scattered boolean flags
@@ -596,7 +644,7 @@
596
644
  // Configure endpoints when props change
597
645
  $effect(() => {
598
646
  if (props.endpointConfig) {
599
- ConfigurationHelper.configureEndpoints(fd.api, props.endpointConfig);
647
+ ConfigurationHelper.configureEndpoints(fd.api, props.endpointConfig, props.authProvider);
600
648
  }
601
649
  });
602
650
 
@@ -872,23 +920,26 @@
872
920
  >
873
921
  <Controls />
874
922
  {#if canvasEditable && props.onToggleConsole}
875
- <button
923
+ <CanvasIconButton
876
924
  class="flowdrop-console-toggle"
877
- class:flowdrop-console-toggle--active={props.consoleOpen}
925
+ label={m().layout.commandConsole}
926
+ active={props.consoleOpen}
878
927
  onclick={props.onToggleConsole}
879
- aria-label={m().layout.commandConsole}
880
- title={m().layout.commandConsole}
881
- type="button"
882
928
  >
883
- <Icon icon="heroicons:command-line" width="18" height="18" />
884
- </button>
929
+ {#snippet icon()}
930
+ <CommandLineIcon />
931
+ {/snippet}
932
+ </CanvasIconButton>
885
933
  {/if}
886
934
  <!-- Always render Background for consistent bg color in dark/light mode -->
887
935
  <Background
888
936
  gap={getEditorSettings().gridSize}
889
- bgColor="var(--fd-background)"
890
- variant={BackgroundVariant.Dots}
891
- patternColor={getEditorSettings().showGrid ? undefined : 'transparent'}
937
+ bgColor="var(--fd-canvas-bg)"
938
+ variant={gridVariant}
939
+ lineWidth={1}
940
+ patternColor={getEditorSettings().showGrid
941
+ ? 'var(--fd-grid-pattern-color)'
942
+ : 'transparent'}
892
943
  />
893
944
  {#if getEditorSettings().showMinimap}
894
945
  <MiniMap />
@@ -1003,48 +1054,11 @@
1003
1054
  justify-content: space-between;
1004
1055
  }
1005
1056
 
1006
- .flowdrop-console-toggle {
1007
- position: absolute;
1057
+ /* Console toggle — placement only; visuals live in CanvasIconButton */
1058
+ :global(.flowdrop-console-toggle) {
1008
1059
  bottom: 140px;
1009
1060
  left: 12px;
1010
1061
  z-index: 5;
1011
- display: flex;
1012
- align-items: center;
1013
- justify-content: center;
1014
- width: 2rem;
1015
- height: 2rem;
1016
- border: 1px solid var(--fd-border);
1017
- border-radius: var(--fd-radius-md);
1018
- background-color: var(--fd-background);
1019
- color: var(--fd-muted-foreground);
1020
- cursor: pointer;
1021
- box-shadow: var(--fd-shadow-sm);
1022
- transition:
1023
- color var(--fd-transition-fast),
1024
- background-color var(--fd-transition-fast),
1025
- box-shadow var(--fd-transition-fast);
1026
- }
1027
-
1028
- .flowdrop-console-toggle:hover {
1029
- color: var(--fd-foreground);
1030
- background-color: var(--fd-subtle);
1031
- box-shadow: var(--fd-shadow-md);
1032
- }
1033
-
1034
- .flowdrop-console-toggle:focus {
1035
- outline: none;
1036
- box-shadow: 0 0 0 2px var(--fd-ring);
1037
- }
1038
-
1039
- .flowdrop-console-toggle--active {
1040
- color: var(--fd-primary);
1041
- background-color: var(--fd-primary-muted);
1042
- border-color: var(--fd-primary);
1043
- }
1044
-
1045
- .flowdrop-console-toggle--active:hover {
1046
- color: var(--fd-primary);
1047
- background-color: var(--fd-primary-muted);
1048
1062
  }
1049
1063
 
1050
1064
  :global(.flowdrop-workflow-editor .svelte-flow__node:hover) {
@@ -1,9 +1,13 @@
1
1
  import '@xyflow/svelte/dist/style.css';
2
2
  import type { WorkflowNode as WorkflowNodeType } from '../types/index.js';
3
3
  import type { EndpointConfig } from '../config/endpoints.js';
4
+ import type { AuthProvider } from '../types/auth.js';
4
5
  import type { FlowDropInstance } from '../stores/instanceContainer.svelte.js';
6
+ import type { FlowDropGridVariant } from '../types/theme.js';
5
7
  interface Props {
6
8
  endpointConfig?: EndpointConfig;
9
+ /** Auth provider applied to this instance's API requests. */
10
+ authProvider?: AuthProvider;
7
11
  openConfigSidebar?: (node: WorkflowNodeType) => void;
8
12
  /**
9
13
  * Editor interaction mode. `'edit'` allows node drag/connect/select and
@@ -24,6 +28,23 @@ interface Props {
24
28
  onToggleConsole?: () => void;
25
29
  /** Per-instance state container (created by mount functions). Defaults to the page-default instance. */
26
30
  instance?: FlowDropInstance;
31
+ /**
32
+ * Canvas background grid pattern. Supplied by App from the active theme's
33
+ * `config.canvas.grid` default; any theme can opt into 'lines' / 'cross'.
34
+ * Color is driven separately by the `--fd-grid-pattern-color` token.
35
+ * @default 'dots'
36
+ */
37
+ gridVariant?: FlowDropGridVariant;
38
+ /**
39
+ * Register the built-in heavy form editors (markdown / code / template)
40
+ * on this instance's field registry. Batteries-included by default — node
41
+ * config fields with `format: 'markdown' | 'code' | 'template'` render real
42
+ * CodeMirror editors. The chunks are code-split (loaded lazily here), so
43
+ * the `/editor` static bundle stays light. Set `false` to keep the textarea
44
+ * fallback or register your own field components. See `features.builtinEditors`.
45
+ * @default true
46
+ */
47
+ builtinEditors?: boolean;
27
48
  }
28
49
  declare const WorkflowEditor: import("svelte").Component<Props, {
29
50
  updateNodeData: (nodeId: string, dataUpdates: Partial<WorkflowNodeType["data"]>) => void;
@@ -369,7 +369,12 @@
369
369
  history: history.slice(0, -1) // all except current message
370
370
  };
371
371
 
372
- const response = await chatService.sendMessage(fd.api.config, workflowId, request);
372
+ const response = await chatService.sendMessage(
373
+ fd.api.config,
374
+ workflowId,
375
+ request,
376
+ fd.api.authProvider
377
+ );
373
378
  const displayMsg = processResponse(response.content);
374
379
  displayMessages.push(displayMsg);
375
380
  } catch (err) {
@@ -547,7 +552,7 @@
547
552
 
548
553
  .ai-chat-panel__messages::-webkit-scrollbar-thumb {
549
554
  background: var(--fd-scrollbar-thumb);
550
- border-radius: 4px;
555
+ border-radius: var(--fd-scrollbar-radius);
551
556
  }
552
557
 
553
558
  .ai-chat-panel__messages::-webkit-scrollbar-thumb:hover {
@@ -98,7 +98,7 @@
98
98
 
99
99
  .console-autocomplete::-webkit-scrollbar-thumb {
100
100
  background: var(--fd-scrollbar-thumb);
101
- border-radius: 3px;
101
+ border-radius: var(--fd-scrollbar-radius);
102
102
  }
103
103
 
104
104
  .console-autocomplete__item {
@@ -68,12 +68,12 @@
68
68
 
69
69
  .console-output::-webkit-scrollbar-track {
70
70
  background: var(--fd-scrollbar-track);
71
- border-radius: 4px;
71
+ border-radius: var(--fd-scrollbar-radius);
72
72
  }
73
73
 
74
74
  .console-output::-webkit-scrollbar-thumb {
75
75
  background: var(--fd-scrollbar-thumb);
76
- border-radius: 4px;
76
+ border-radius: var(--fd-scrollbar-radius);
77
77
  }
78
78
 
79
79
  .console-output::-webkit-scrollbar-thumb:hover {
@@ -670,9 +670,7 @@
670
670
  }
671
671
 
672
672
  .form-array__item-toggle:focus-visible {
673
- outline: none;
674
673
  border-color: var(--fd-primary);
675
- box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.2);
676
674
  }
677
675
 
678
676
  .form-array__item-toggle :global(svg) {
@@ -717,11 +715,6 @@
717
715
  height: 1rem;
718
716
  }
719
717
 
720
- .form-array__action-btn:focus-visible {
721
- outline: none;
722
- box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.3);
723
- }
724
-
725
718
  .form-array__action-btn:disabled {
726
719
  opacity: 0.35;
727
720
  cursor: not-allowed;
@@ -800,9 +793,7 @@
800
793
  }
801
794
 
802
795
  .form-array__input:focus {
803
- outline: none;
804
796
  border-color: var(--fd-primary);
805
- box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);
806
797
  }
807
798
 
808
799
  .form-array__input--number {
@@ -837,9 +828,7 @@
837
828
  }
838
829
 
839
830
  .form-array__select:focus {
840
- outline: none;
841
831
  border-color: var(--fd-primary);
842
- box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);
843
832
  }
844
833
 
845
834
  /* ============================================
@@ -1002,11 +991,6 @@
1002
991
  color: var(--fd-success-hover);
1003
992
  }
1004
993
 
1005
- .form-array__add-btn:focus-visible {
1006
- outline: none;
1007
- box-shadow: 0 0 0 2px rgba(34, 197, 94, 0.3);
1008
- }
1009
-
1010
994
  .form-array__add-btn:active:not(:disabled) {
1011
995
  background-color: var(--fd-success);
1012
996
  }
@@ -25,7 +25,7 @@
25
25
  import Icon from '@iconify/svelte';
26
26
  import type { AutocompleteConfig, AuthProvider } from '../../types/index.js';
27
27
  import type { FieldOption } from './types.js';
28
- import { buildFetchHeaders } from '../../utils/fetchWithAuth.js';
28
+ import { authenticatedFetch } from '../../utils/fetchWithAuth.js';
29
29
  import { logger } from '../../utils/logger.js';
30
30
  import { m } from '../../messages/index.js';
31
31
 
@@ -245,16 +245,15 @@
245
245
 
246
246
  let timeoutId: ReturnType<typeof setTimeout> | null = null;
247
247
  try {
248
- // Build headers with authentication (call getter to get current value)
249
- const headers = await buildFetchHeaders(getAuthProvider?.());
250
-
251
248
  timeoutId = setTimeout(() => controller.abort(), 5000);
252
249
 
253
- const response = await fetch(buildUrl(query), {
254
- method: 'GET',
255
- headers,
256
- signal: controller.signal
257
- });
250
+ // authenticatedFetch merges auth headers (call getter for current value)
251
+ // and applies the 401/403 lifecycle consistently with the rest of the lib.
252
+ const response = await authenticatedFetch(
253
+ buildUrl(query),
254
+ { method: 'GET', signal: controller.signal },
255
+ { authProvider: getAuthProvider?.() }
256
+ );
258
257
 
259
258
  if (!response.ok) {
260
259
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
@@ -788,7 +787,6 @@
788
787
  }
789
788
 
790
789
  .form-autocomplete--disabled {
791
- opacity: 0.6;
792
790
  pointer-events: none;
793
791
  }
794
792
 
@@ -805,7 +803,7 @@
805
803
  font-size: var(--fd-text-sm);
806
804
  font-family: inherit;
807
805
  color: var(--fd-foreground);
808
- background-color: var(--fd-muted);
806
+ background-color: var(--fd-background);
809
807
  transition: all var(--fd-transition-normal);
810
808
  box-shadow: var(--fd-shadow-sm);
811
809
  cursor: text;
@@ -818,11 +816,16 @@
818
816
  }
819
817
 
820
818
  .form-autocomplete__field--focused {
821
- border-color: var(--fd-primary);
819
+ border-color: var(--fd-ring);
822
820
  background-color: var(--fd-background);
823
- box-shadow:
824
- 0 0 0 3px rgba(59, 130, 246, 0.12),
825
- var(--fd-shadow-sm);
821
+ }
822
+
823
+ .form-autocomplete--disabled .form-autocomplete__field {
824
+ background-color: var(--fd-muted);
825
+ border-color: var(--fd-border-muted);
826
+ color: var(--fd-muted-foreground);
827
+ cursor: not-allowed;
828
+ opacity: 1;
826
829
  }
827
830
 
828
831
  /* Multiple mode - textarea-like styling */
@@ -143,10 +143,6 @@
143
143
  transform: scale(1);
144
144
  }
145
145
 
146
- .form-checkbox__input:focus-visible + .form-checkbox__custom {
147
- box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2);
148
- }
149
-
150
146
  .form-checkbox__label {
151
147
  font-size: var(--fd-text-sm);
152
148
  color: var(--fd-foreground);
@@ -364,7 +364,9 @@
364
364
  border: 1px solid var(--fd-border);
365
365
  border-radius: var(--fd-radius-lg);
366
366
  overflow: hidden;
367
- background-color: var(--fd-muted);
367
+ /* Match plain form fields (FormTextField/Textarea/Select): rest on the
368
+ input surface, not the recessed --fd-muted. */
369
+ background-color: var(--fd-background);
368
370
  transition: all var(--fd-transition-normal);
369
371
  box-shadow: var(--fd-shadow-sm);
370
372
  }
@@ -374,12 +376,15 @@
374
376
  background-color: var(--fd-background);
375
377
  }
376
378
 
379
+ /* Compound widget: the focusable CodeMirror lives inside this container, so
380
+ the standard ring (centralized for simple elements) is drawn here via
381
+ :focus-within using the same --fd-ring tokens. Outline paints outside the
382
+ container's overflow, so it isn't clipped. */
377
383
  .form-code-editor__container:focus-within {
378
384
  border-color: var(--fd-primary);
379
385
  background-color: var(--fd-background);
380
- box-shadow:
381
- 0 0 0 3px rgba(59, 130, 246, 0.12),
382
- var(--fd-shadow-sm);
386
+ outline: var(--fd-ring-width) solid var(--fd-ring);
387
+ outline-offset: var(--fd-ring-offset);
383
388
  }
384
389
 
385
390
  .form-code-editor--error .form-code-editor__container {
@@ -388,9 +393,6 @@
388
393
 
389
394
  .form-code-editor--error .form-code-editor__container:focus-within {
390
395
  border-color: var(--fd-error);
391
- box-shadow:
392
- 0 0 0 3px rgba(239, 68, 68, 0.12),
393
- var(--fd-shadow-sm);
394
396
  }
395
397
 
396
398
  /* Dark theme overrides */
@@ -48,6 +48,8 @@
48
48
  const fd = getInstance();
49
49
  import type { FieldSchema } from './types.js';
50
50
  import { getSchemaOptions } from './types.js';
51
+ import type { WorkflowNode, WorkflowEdge } from '../../types/index.js';
52
+ import type { AuthProvider } from '../../types/auth.js';
51
53
 
52
54
  interface Props {
53
55
  /** Unique key/id for the field */
@@ -60,11 +62,33 @@
60
62
  required?: boolean;
61
63
  /** Animation delay index for staggered animations */
62
64
  animationIndex?: number;
65
+ /** Current workflow node (optional, forwarded to registered editors for template variable API mode) */
66
+ node?: WorkflowNode;
67
+ /** All workflow nodes (optional, forwarded to registered editors for port-derived variables) */
68
+ nodes?: WorkflowNode[];
69
+ /** All workflow edges (optional, forwarded to registered editors for port-derived variables) */
70
+ edges?: WorkflowEdge[];
71
+ /** Workflow ID (optional, forwarded to registered editors for template variable API mode) */
72
+ workflowId?: string;
73
+ /** Auth provider (optional, forwarded to registered editors for API requests) */
74
+ authProvider?: AuthProvider;
63
75
  /** Callback when the field value changes */
64
76
  onChange: (value: unknown) => void;
65
77
  }
66
78
 
67
- let { fieldKey, schema, value, required = false, animationIndex = 0, onChange }: Props = $props();
79
+ let {
80
+ fieldKey,
81
+ schema,
82
+ value,
83
+ required = false,
84
+ animationIndex = 0,
85
+ node,
86
+ nodes,
87
+ edges,
88
+ workflowId,
89
+ authProvider,
90
+ onChange
91
+ }: Props = $props();
68
92
 
69
93
  /**
70
94
  * Computed description ID for ARIA association
@@ -209,11 +233,11 @@
209
233
  function getEditorHint(editorType: string): string {
210
234
  switch (editorType) {
211
235
  case 'code-editor-fallback':
212
- return "Code editor requires: import { registerCodeEditorField } from '@flowdrop/flowdrop/form/code'; registerCodeEditorField();";
236
+ return "Code editor not registered. Register it on the instance's field registry: import { registerCodeEditorField } from '@flowdrop/flowdrop/form/code'; registerCodeEditorField(instance.fields);";
213
237
  case 'markdown-editor-fallback':
214
- return "Markdown editor requires: import { registerMarkdownEditorField } from '@flowdrop/flowdrop/form/markdown'; registerMarkdownEditorField();";
238
+ return "Markdown editor not registered. Register it on the instance's field registry: import { registerMarkdownEditorField } from '@flowdrop/flowdrop/form/markdown'; registerMarkdownEditorField(instance.fields);";
215
239
  case 'template-editor-fallback':
216
- return "Template editor requires: import { registerTemplateEditorField } from '@flowdrop/flowdrop/form/code'; registerTemplateEditorField();";
240
+ return "Template editor not registered. Register it on the instance's field registry: import { registerTemplateEditorField } from '@flowdrop/flowdrop/form/code'; registerTemplateEditorField(instance.fields);";
217
241
  default:
218
242
  return 'This field type requires additional registration.';
219
243
  }
@@ -246,6 +270,11 @@
246
270
  variables={schema.variables}
247
271
  placeholderExample={schema.placeholderExample as string | undefined}
248
272
  autocomplete={schema.autocomplete}
273
+ {node}
274
+ {nodes}
275
+ {edges}
276
+ {workflowId}
277
+ {authProvider}
249
278
  onChange={(val: unknown) => onChange(val)}
250
279
  />
251
280
  {:else if fieldType === 'checkbox-group'}
@@ -1,4 +1,6 @@
1
1
  import type { FieldSchema } from './types.js';
2
+ import type { WorkflowNode, WorkflowEdge } from '../../types/index.js';
3
+ import type { AuthProvider } from '../../types/auth.js';
2
4
  interface Props {
3
5
  /** Unique key/id for the field */
4
6
  fieldKey: string;
@@ -10,6 +12,16 @@ interface Props {
10
12
  required?: boolean;
11
13
  /** Animation delay index for staggered animations */
12
14
  animationIndex?: number;
15
+ /** Current workflow node (optional, forwarded to registered editors for template variable API mode) */
16
+ node?: WorkflowNode;
17
+ /** All workflow nodes (optional, forwarded to registered editors for port-derived variables) */
18
+ nodes?: WorkflowNode[];
19
+ /** All workflow edges (optional, forwarded to registered editors for port-derived variables) */
20
+ edges?: WorkflowEdge[];
21
+ /** Workflow ID (optional, forwarded to registered editors for template variable API mode) */
22
+ workflowId?: string;
23
+ /** Auth provider (optional, forwarded to registered editors for API requests) */
24
+ authProvider?: AuthProvider;
13
25
  /** Callback when the field value changes */
14
26
  onChange: (value: unknown) => void;
15
27
  }
@@ -641,7 +641,8 @@
641
641
  border: 1px solid var(--fd-border);
642
642
  border-radius: var(--fd-radius-lg);
643
643
  overflow: hidden;
644
- background-color: var(--fd-muted);
644
+ /* Match plain form fields: rest on the input surface, not --fd-muted. */
645
+ background-color: var(--fd-background);
645
646
  transition: border-color var(--fd-transition-normal);
646
647
  }
647
648
 
@@ -655,12 +656,13 @@
655
656
  border-color: var(--fd-border-strong);
656
657
  }
657
658
 
659
+ /* Compound widget: ring drawn on the body via :focus-within, using the
660
+ standard --fd-ring tokens (outline isn't clipped by the container overflow). */
658
661
  .form-markdown-editor__body:focus-within {
659
662
  border-color: var(--fd-primary);
660
663
  background-color: var(--fd-background);
661
- box-shadow:
662
- 0 0 0 3px var(--fd-primary-muted),
663
- var(--fd-shadow-sm);
664
+ outline: var(--fd-ring-width) solid var(--fd-ring);
665
+ outline-offset: var(--fd-ring-offset);
664
666
  }
665
667
 
666
668
  /* ── Status bar ────────────────────────────────── */
@@ -702,7 +704,8 @@
702
704
 
703
705
  .form-markdown-editor__body :global(.cm-editor) {
704
706
  height: var(--editor-height, 300px);
705
- background-color: var(--fd-muted) !important;
707
+ /* Match plain form fields: white input surface (overrides oneDark in dark mode). */
708
+ background-color: var(--fd-background) !important;
706
709
  color: var(--fd-foreground) !important;
707
710
  }
708
711
 
@@ -102,11 +102,7 @@
102
102
  }
103
103
 
104
104
  .form-number-field:focus {
105
- outline: none;
106
105
  border-color: var(--fd-primary);
107
106
  background-color: var(--fd-background);
108
- box-shadow:
109
- 0 0 0 3px rgba(59, 130, 246, 0.12),
110
- var(--fd-shadow-sm);
111
107
  }
112
108
  </style>
@@ -165,12 +165,6 @@
165
165
  0 2px 4px rgba(0, 0, 0, 0.1);
166
166
  }
167
167
 
168
- .form-range-field:focus::-webkit-slider-thumb {
169
- box-shadow:
170
- 0 0 0 3px rgba(59, 130, 246, 0.2),
171
- 0 4px 12px rgba(59, 130, 246, 0.35);
172
- }
173
-
174
168
  /* Firefox - Track */
175
169
  .form-range-field::-moz-range-track {
176
170
  height: 6px;
@@ -205,20 +199,7 @@
205
199
  0 2px 4px rgba(0, 0, 0, 0.1);
206
200
  }
207
201
 
208
- .form-range-field:focus::-moz-range-thumb {
209
- box-shadow:
210
- 0 0 0 3px rgba(59, 130, 246, 0.2),
211
- 0 4px 12px rgba(59, 130, 246, 0.35);
212
- }
213
-
214
- /* Focus styles */
215
- .form-range-field:focus {
216
- outline: none;
217
- }
218
-
219
- .form-range-field:focus-visible {
220
- outline: none;
221
- }
202
+ /* Focus ring is centralized in base.css (outline on the range input). */
222
203
 
223
204
  /* Value display row */
224
205
  .form-range-values {
@@ -85,7 +85,7 @@
85
85
  font-size: var(--fd-text-sm);
86
86
  font-family: inherit;
87
87
  color: var(--fd-foreground);
88
- background-color: var(--fd-muted);
88
+ background-color: var(--fd-background);
89
89
  transition: all var(--fd-transition-normal);
90
90
  box-shadow: var(--fd-shadow-sm);
91
91
  cursor: pointer;
@@ -98,12 +98,16 @@
98
98
  }
99
99
 
100
100
  .form-select:focus {
101
- outline: none;
102
- border-color: var(--fd-primary);
101
+ border-color: var(--fd-ring);
103
102
  background-color: var(--fd-background);
104
- box-shadow:
105
- 0 0 0 3px rgba(59, 130, 246, 0.12),
106
- var(--fd-shadow-sm);
103
+ }
104
+
105
+ .form-select:disabled {
106
+ background-color: var(--fd-muted);
107
+ border-color: var(--fd-border-muted);
108
+ color: var(--fd-muted-foreground);
109
+ cursor: not-allowed;
110
+ opacity: 1;
107
111
  }
108
112
 
109
113
  .form-select__icon {