@flowdrop/flowdrop 2.0.0-beta.2 → 2.0.0-beta.4

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 (113) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/MIGRATION-2.0.md +13 -0
  3. package/README.md +5 -5
  4. package/dist/components/App.svelte +36 -191
  5. package/dist/components/App.svelte.d.ts +2 -7
  6. package/dist/components/Button.stories.svelte +65 -0
  7. package/dist/components/Button.stories.svelte.d.ts +19 -0
  8. package/dist/components/Button.svelte +62 -0
  9. package/dist/components/Button.svelte.d.ts +24 -0
  10. package/dist/components/CanvasIconButton.svelte +76 -0
  11. package/dist/components/CanvasIconButton.svelte.d.ts +18 -0
  12. package/dist/components/ConfigForm.svelte +4 -23
  13. package/dist/components/ConfigPanel.svelte +4 -3
  14. package/dist/components/EditorStatusBar.stories.svelte +44 -0
  15. package/dist/components/EditorStatusBar.stories.svelte.d.ts +27 -0
  16. package/dist/components/EditorStatusBar.svelte +99 -0
  17. package/dist/components/EditorStatusBar.svelte.d.ts +15 -0
  18. package/dist/components/IconButton.svelte +80 -0
  19. package/dist/components/IconButton.svelte.d.ts +30 -0
  20. package/dist/components/Input.svelte +74 -0
  21. package/dist/components/Input.svelte.d.ts +17 -0
  22. package/dist/components/LogoWordmark.svelte +113 -0
  23. package/dist/components/LogoWordmark.svelte.d.ts +26 -0
  24. package/dist/components/Navbar.svelte +17 -63
  25. package/dist/components/Navbar.svelte.d.ts +3 -0
  26. package/dist/components/NodeSidebar.svelte +17 -122
  27. package/dist/components/NodeSwapPicker.svelte +10 -28
  28. package/dist/components/PortMappingRow.svelte +0 -2
  29. package/dist/components/SchemaForm.svelte +0 -12
  30. package/dist/components/Select.svelte +53 -0
  31. package/dist/components/Select.svelte.d.ts +15 -0
  32. package/dist/components/SettingsModal.svelte +0 -5
  33. package/dist/components/SettingsPanel.svelte +2 -6
  34. package/dist/components/Textarea.svelte +39 -0
  35. package/dist/components/Textarea.svelte.d.ts +12 -0
  36. package/dist/components/ThemeToggle.svelte +15 -94
  37. package/dist/components/UniversalNode.svelte +32 -1
  38. package/dist/components/WorkflowEditor.svelte +62 -51
  39. package/dist/components/WorkflowEditor.svelte.d.ts +18 -0
  40. package/dist/components/chat/AIChatPanel.svelte +1 -1
  41. package/dist/components/console/ConsoleAutocomplete.svelte +1 -1
  42. package/dist/components/console/ConsoleOutput.svelte +2 -2
  43. package/dist/components/form/FormArray.svelte +37 -173
  44. package/dist/components/form/FormAutocomplete.svelte +10 -6
  45. package/dist/components/form/FormCheckboxGroup.svelte +1 -5
  46. package/dist/components/form/FormCodeEditor.svelte +9 -7
  47. package/dist/components/form/FormField.svelte +5 -44
  48. package/dist/components/form/FormFieldLight.svelte +8 -47
  49. package/dist/components/form/FormFieldset.svelte +1 -1
  50. package/dist/components/form/FormMarkdownEditor.svelte +8 -5
  51. package/dist/components/form/FormNumberField.svelte +4 -36
  52. package/dist/components/form/FormRangeField.svelte +18 -27
  53. package/dist/components/form/FormSelect.svelte +13 -75
  54. package/dist/components/form/FormTemplateEditor.svelte +6 -4
  55. package/dist/components/form/FormTextField.svelte +3 -35
  56. package/dist/components/form/FormTextarea.svelte +4 -39
  57. package/dist/components/form/FormToggle.svelte +0 -4
  58. package/dist/components/form/resolveFieldType.d.ts +24 -0
  59. package/dist/components/form/resolveFieldType.js +55 -0
  60. package/dist/components/icons/CloseIcon.svelte +6 -0
  61. package/dist/components/icons/CloseIcon.svelte.d.ts +26 -0
  62. package/dist/components/icons/CommandLineIcon.svelte +15 -0
  63. package/dist/components/icons/CommandLineIcon.svelte.d.ts +26 -0
  64. package/dist/components/icons/MenuIcon.svelte +4 -0
  65. package/dist/components/icons/MenuIcon.svelte.d.ts +26 -0
  66. package/dist/components/icons/MenuOpenIcon.svelte +6 -0
  67. package/dist/components/icons/MenuOpenIcon.svelte.d.ts +26 -0
  68. package/dist/components/interrupt/ChoicePrompt.svelte +0 -10
  69. package/dist/components/interrupt/ConfirmationPrompt.svelte +0 -5
  70. package/dist/components/interrupt/InterruptBubble.svelte +0 -10
  71. package/dist/components/interrupt/ReviewPrompt.svelte +0 -20
  72. package/dist/components/interrupt/TextInputPrompt.svelte +0 -6
  73. package/dist/components/layouts/MainLayout.svelte +4 -5
  74. package/dist/components/nodes/AtomNode.svelte +46 -34
  75. package/dist/components/nodes/GatewayNode.svelte +91 -99
  76. package/dist/components/nodes/IdeaNode.svelte +62 -90
  77. package/dist/components/nodes/NodeConfigButton.svelte +86 -0
  78. package/dist/components/nodes/NodeConfigButton.svelte.d.ts +15 -0
  79. package/dist/components/nodes/NotesNode.svelte +70 -81
  80. package/dist/components/nodes/SimpleNode.svelte +28 -78
  81. package/dist/components/nodes/SquareNode.svelte +79 -109
  82. package/dist/components/nodes/TerminalNode.svelte +28 -86
  83. package/dist/components/nodes/ToolNode.svelte +82 -95
  84. package/dist/components/nodes/WorkflowNode.svelte +91 -100
  85. package/dist/components/playground/ChatInput.svelte +0 -1
  86. package/dist/components/playground/InputCollector.svelte +11 -48
  87. package/dist/components/playground/PlaygroundApp.svelte +1 -1
  88. package/dist/components/playground/PlaygroundStudio.svelte +0 -5
  89. package/dist/messages/index.d.ts +1 -1
  90. package/dist/messages/index.js +1 -1
  91. package/dist/openapi/v1/openapi.yaml +2 -2
  92. package/dist/playground/mount.d.ts +9 -5
  93. package/dist/playground/mount.js +9 -5
  94. package/dist/skins/drafter.d.ts +30 -0
  95. package/dist/skins/drafter.js +198 -0
  96. package/dist/skins/index.d.ts +2 -1
  97. package/dist/skins/index.js +4 -2
  98. package/dist/styles/base.css +285 -14
  99. package/dist/styles/tokens.css +60 -2
  100. package/dist/svelte-app.d.ts +6 -0
  101. package/dist/svelte-app.js +71 -109
  102. package/dist/themes/drafter.d.ts +2 -0
  103. package/dist/themes/drafter.js +15 -0
  104. package/dist/themes/index.d.ts +2 -1
  105. package/dist/themes/index.js +8 -2
  106. package/dist/types/events.d.ts +18 -0
  107. package/dist/types/events.js +2 -1
  108. package/dist/types/settings.d.ts +1 -1
  109. package/dist/types/settings.js +1 -1
  110. package/dist/types/skin.d.ts +1 -1
  111. package/dist/types/theme.d.ts +16 -2
  112. package/dist/utils/connections.js +14 -50
  113. package/package.json +1 -1
@@ -198,7 +198,8 @@
198
198
  description: 'Visual style and layout of the editor',
199
199
  oneOf: [
200
200
  { const: 'default', title: 'Default' },
201
- { const: 'minimal', title: 'Minimal' }
201
+ { const: 'minimal', title: 'Minimal' },
202
+ { const: 'drafter', title: 'Drafter' }
202
203
  ],
203
204
  default: 'default'
204
205
  }
@@ -538,11 +539,6 @@
538
539
  color: var(--fd-primary-foreground);
539
540
  }
540
541
 
541
- .flowdrop-settings-panel__tab:focus {
542
- outline: none;
543
- box-shadow: 0 0 0 2px var(--fd-ring);
544
- }
545
-
546
542
  :global(.flowdrop-settings-panel__tab-icon) {
547
543
  font-size: var(--fd-text-base);
548
544
  }
@@ -0,0 +1,39 @@
1
+ <!--
2
+ Textarea — typed wrapper over the shared `.flowdrop-input` system (base.css),
3
+ with the `.flowdrop-input--textarea` modifier (min-height + vertical resize).
4
+
5
+ Shares the exact field look of Input/Select so multiline fields render
6
+ identically. All styling lives in base.css. Native attributes (value,
7
+ placeholder, rows, disabled, id, aria-*, oninput…) forward to <textarea>.
8
+
9
+ Internal for now; see Button.svelte / Input.svelte for the pattern.
10
+ -->
11
+
12
+ <script lang="ts">
13
+ import type { HTMLTextareaAttributes } from 'svelte/elements';
14
+
15
+ interface Props extends HTMLTextareaAttributes {
16
+ /** Size — `md` is the base; `sm`/`lg` add a modifier */
17
+ size?: 'sm' | 'md' | 'lg';
18
+ /** Renders the error-border state */
19
+ invalid?: boolean;
20
+ /** Extra classes appended to the textarea */
21
+ class?: string;
22
+ }
23
+
24
+ let { size = 'md', invalid = false, class: className = '', ...rest }: Props = $props();
25
+
26
+ const textareaClass = $derived(
27
+ [
28
+ 'flowdrop-input',
29
+ 'flowdrop-input--textarea',
30
+ size === 'md' ? '' : `flowdrop-input--${size}`,
31
+ invalid ? 'flowdrop-input--invalid' : '',
32
+ className
33
+ ]
34
+ .filter(Boolean)
35
+ .join(' ')
36
+ );
37
+ </script>
38
+
39
+ <textarea class={textareaClass} {...rest}></textarea>
@@ -0,0 +1,12 @@
1
+ import type { HTMLTextareaAttributes } from 'svelte/elements';
2
+ interface Props extends HTMLTextareaAttributes {
3
+ /** Size — `md` is the base; `sm`/`lg` add a modifier */
4
+ size?: 'sm' | 'md' | 'lg';
5
+ /** Renders the error-border state */
6
+ invalid?: boolean;
7
+ /** Extra classes appended to the textarea */
8
+ class?: string;
9
+ }
10
+ declare const Textarea: import("svelte").Component<Props, {}, "">;
11
+ type Textarea = ReturnType<typeof Textarea>;
12
+ export default Textarea;
@@ -1,12 +1,15 @@
1
1
  <!--
2
2
  Theme Toggle Component
3
- A button that cycles through light, dark, and auto theme modes
4
- Displays appropriate icon for current theme state
5
- Styled with BEM syntax
3
+ A button that cycles through light, dark, and auto theme modes.
4
+ Displays the icon for the current theme state.
5
+
6
+ Built on the shared Button primitive so it stays visually and dimensionally
7
+ aligned with every other control (height, focus ring, hover) for free.
6
8
  -->
7
9
 
8
10
  <script lang="ts">
9
11
  import Icon from '@iconify/svelte';
12
+ import Button from './Button.svelte';
10
13
  import { getTheme, getResolvedTheme, cycleTheme } from '../stores/settingsStore.svelte.js';
11
14
  import type { ThemePreference } from '../types/settings.js';
12
15
 
@@ -47,7 +50,7 @@
47
50
  }
48
51
 
49
52
  /**
50
- * Get accessible label for the current theme
53
+ * Get the label text for the current theme
51
54
  */
52
55
  const themeLabel = $derived(getThemeLabel(getTheme()));
53
56
 
@@ -80,105 +83,23 @@
80
83
  const next = currentTheme === 'light' ? 'Dark' : 'Auto';
81
84
  return `Theme: ${currentTheme === 'light' ? 'Light' : 'Dark'}. Click to switch to ${next}`;
82
85
  }
83
-
84
- /**
85
- * Handle click to cycle theme
86
- */
87
- function handleClick(): void {
88
- cycleTheme();
89
- }
90
-
91
- /**
92
- * Handle keyboard events for accessibility
93
- */
94
- function handleKeydown(event: KeyboardEvent): void {
95
- if (event.key === 'Enter' || event.key === ' ') {
96
- event.preventDefault();
97
- cycleTheme();
98
- }
99
- }
100
86
  </script>
101
87
 
102
- <button
103
- class="flowdrop-theme-toggle flowdrop-theme-toggle--{size} {className}"
104
- onclick={handleClick}
105
- onkeydown={handleKeydown}
88
+ <Button
89
+ variant="outline"
90
+ {size}
91
+ class={className}
106
92
  title={tooltipText}
107
- aria-label={tooltipText}
108
- type="button"
93
+ ariaLabel={tooltipText}
94
+ onclick={cycleTheme}
109
95
  >
110
- <span class="flowdrop-theme-toggle__icon">
111
- <Icon icon={themeIcon} />
112
- </span>
96
+ <Icon icon={themeIcon} />
113
97
  {#if showLabel}
114
98
  <span class="flowdrop-theme-toggle__label">{themeLabel}</span>
115
99
  {/if}
116
- </button>
100
+ </Button>
117
101
 
118
102
  <style>
119
- .flowdrop-theme-toggle {
120
- display: inline-flex;
121
- align-items: center;
122
- justify-content: center;
123
- gap: var(--fd-space-xs);
124
- border: 1px solid var(--fd-border);
125
- border-radius: var(--fd-radius-md);
126
- background-color: var(--fd-background);
127
- color: var(--fd-foreground);
128
- cursor: pointer;
129
- transition: all var(--fd-transition-normal);
130
- font-family: inherit;
131
- }
132
-
133
- .flowdrop-theme-toggle:hover {
134
- background-color: var(--fd-muted);
135
- border-color: var(--fd-border-strong);
136
- }
137
-
138
- .flowdrop-theme-toggle:focus {
139
- outline: none;
140
- box-shadow: 0 0 0 2px var(--fd-ring);
141
- }
142
-
143
- .flowdrop-theme-toggle:active {
144
- transform: scale(0.98);
145
- }
146
-
147
- /* Size variants */
148
- .flowdrop-theme-toggle--sm {
149
- padding: var(--fd-space-3xs) var(--fd-space-xs);
150
- font-size: var(--fd-text-xs);
151
- }
152
-
153
- .flowdrop-theme-toggle--sm .flowdrop-theme-toggle__icon {
154
- font-size: var(--fd-text-sm);
155
- }
156
-
157
- .flowdrop-theme-toggle--md {
158
- padding: var(--fd-space-xs) var(--fd-space-md);
159
- font-size: var(--fd-text-sm);
160
- }
161
-
162
- .flowdrop-theme-toggle--md .flowdrop-theme-toggle__icon {
163
- font-size: var(--fd-text-base);
164
- }
165
-
166
- .flowdrop-theme-toggle--lg {
167
- padding: var(--fd-space-md) var(--fd-space-xl);
168
- font-size: var(--fd-text-base);
169
- }
170
-
171
- .flowdrop-theme-toggle--lg .flowdrop-theme-toggle__icon {
172
- font-size: var(--fd-text-lg);
173
- }
174
-
175
- .flowdrop-theme-toggle__icon {
176
- display: flex;
177
- align-items: center;
178
- justify-content: center;
179
- line-height: 1;
180
- }
181
-
182
103
  .flowdrop-theme-toggle__label {
183
104
  font-weight: 500;
184
105
  }
@@ -17,6 +17,9 @@
17
17
 
18
18
  const fd = getInstance();
19
19
 
20
+ // Element ref used only to reach xyflow's node wrapper (our ancestor).
21
+ let universalNodeEl: HTMLDivElement;
22
+
20
23
  let {
21
24
  data,
22
25
  selected = false
@@ -61,6 +64,34 @@
61
64
  shouldShowNodeStatus(executionInfo) && resolvedComponentName !== 'note'
62
65
  );
63
66
 
67
+ // Keyboard activation lives on xyflow's node wrapper — the single focusable,
68
+ // arrow-movable element SvelteFlow manages. Because the wrapper is our
69
+ // ancestor, its keydown events never bubble down into our markup, so we bind
70
+ // directly to it. Enter/Space opens the node's config, mirroring the
71
+ // double-click (and single-click for square/atom) mouse paths. Node selection
72
+ // and arrow-key movement remain SvelteFlow's job.
73
+ $effect(() => {
74
+ const wrapper = universalNodeEl?.closest<HTMLElement>('.svelte-flow__node');
75
+ if (!wrapper) return;
76
+
77
+ function onWrapperKeydown(event: KeyboardEvent): void {
78
+ // Only when the node itself is focused — not an inner field (e.g. an
79
+ // editable note) — so we don't hijack typing.
80
+ if (event.target !== wrapper) return;
81
+ if (event.key === 'Enter' || event.key === ' ') {
82
+ event.preventDefault();
83
+ data.onConfigOpen?.({
84
+ id: data.nodeId ?? 'unknown',
85
+ type: resolvedComponentName,
86
+ data
87
+ });
88
+ }
89
+ }
90
+
91
+ wrapper.addEventListener('keydown', onWrapperKeydown);
92
+ return () => wrapper.removeEventListener('keydown', onWrapperKeydown);
93
+ });
94
+
64
95
  /**
65
96
  * Get the node component for the given type from the registry.
66
97
  *
@@ -129,7 +160,7 @@
129
160
  }
130
161
  </script>
131
162
 
132
- <div class="universal-node">
163
+ <div class="universal-node" bind:this={universalNodeEl}>
133
164
  <!-- Render the node component dynamically (Svelte 5 dynamic component syntax) -->
134
165
  {#if nodeComponent}
135
166
  <!-- Svelte 5 dynamic component limitation; reactivity maintained via $derived -->
@@ -26,7 +26,7 @@
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
31
  import type { AuthProvider } from '../types/auth.js';
32
32
  import ConnectionLine from './ConnectionLine.svelte';
@@ -34,6 +34,7 @@
34
34
  import { m } from '../messages/index.js';
35
35
  import { provideInstance } from '../stores/getInstance.svelte.js';
36
36
  import type { FlowDropInstance } from '../stores/instanceContainer.svelte.js';
37
+ import type { FlowDropGridVariant } from '../types/theme.js';
37
38
  import UniversalNode from './UniversalNode.svelte';
38
39
  import {
39
40
  EdgeStylingHelper,
@@ -56,7 +57,8 @@
56
57
  import { logger } from '../utils/logger.js';
57
58
  import { validateWorkflowData } from '../utils/validation.js';
58
59
  import { createEditorStateMachine } from '../stores/editorStateMachine.svelte.js';
59
- import Icon from '@iconify/svelte';
60
+ import CanvasIconButton from './CanvasIconButton.svelte';
61
+ import CommandLineIcon from './icons/CommandLineIcon.svelte';
60
62
  import { DEV } from 'esm-env';
61
63
 
62
64
  interface Props {
@@ -85,6 +87,23 @@
85
87
  onToggleConsole?: () => void;
86
88
  /** Per-instance state container (created by mount functions). Defaults to the page-default instance. */
87
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;
88
107
  }
89
108
 
90
109
  let props: Props = $props();
@@ -95,10 +114,36 @@
95
114
  // svelte-ignore state_referenced_locally
96
115
  const fd = provideInstance(props.instance);
97
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
+
98
138
  // `mode` is the public API; the canvas only needs to know whether editing is
99
139
  // enabled. 'readonly' and 'locked' both disable interaction identically.
100
140
  const canvasEditable = $derived((props.mode ?? 'edit') === 'edit');
101
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
+
102
147
  // ---------------------------------------------------------------------------
103
148
  // Editor State Machine
104
149
  // Centralizes reactive guards — replaces scattered boolean flags
@@ -875,23 +920,26 @@
875
920
  >
876
921
  <Controls />
877
922
  {#if canvasEditable && props.onToggleConsole}
878
- <button
923
+ <CanvasIconButton
879
924
  class="flowdrop-console-toggle"
880
- class:flowdrop-console-toggle--active={props.consoleOpen}
925
+ label={m().layout.commandConsole}
926
+ active={props.consoleOpen}
881
927
  onclick={props.onToggleConsole}
882
- aria-label={m().layout.commandConsole}
883
- title={m().layout.commandConsole}
884
- type="button"
885
928
  >
886
- <Icon icon="heroicons:command-line" width="18" height="18" />
887
- </button>
929
+ {#snippet icon()}
930
+ <CommandLineIcon />
931
+ {/snippet}
932
+ </CanvasIconButton>
888
933
  {/if}
889
934
  <!-- Always render Background for consistent bg color in dark/light mode -->
890
935
  <Background
891
936
  gap={getEditorSettings().gridSize}
892
- bgColor="var(--fd-background)"
893
- variant={BackgroundVariant.Dots}
894
- 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'}
895
943
  />
896
944
  {#if getEditorSettings().showMinimap}
897
945
  <MiniMap />
@@ -1006,48 +1054,11 @@
1006
1054
  justify-content: space-between;
1007
1055
  }
1008
1056
 
1009
- .flowdrop-console-toggle {
1010
- position: absolute;
1057
+ /* Console toggle — placement only; visuals live in CanvasIconButton */
1058
+ :global(.flowdrop-console-toggle) {
1011
1059
  bottom: 140px;
1012
1060
  left: 12px;
1013
1061
  z-index: 5;
1014
- display: flex;
1015
- align-items: center;
1016
- justify-content: center;
1017
- width: 2rem;
1018
- height: 2rem;
1019
- border: 1px solid var(--fd-border);
1020
- border-radius: var(--fd-radius-md);
1021
- background-color: var(--fd-background);
1022
- color: var(--fd-muted-foreground);
1023
- cursor: pointer;
1024
- box-shadow: var(--fd-shadow-sm);
1025
- transition:
1026
- color var(--fd-transition-fast),
1027
- background-color var(--fd-transition-fast),
1028
- box-shadow var(--fd-transition-fast);
1029
- }
1030
-
1031
- .flowdrop-console-toggle:hover {
1032
- color: var(--fd-foreground);
1033
- background-color: var(--fd-subtle);
1034
- box-shadow: var(--fd-shadow-md);
1035
- }
1036
-
1037
- .flowdrop-console-toggle:focus {
1038
- outline: none;
1039
- box-shadow: 0 0 0 2px var(--fd-ring);
1040
- }
1041
-
1042
- .flowdrop-console-toggle--active {
1043
- color: var(--fd-primary);
1044
- background-color: var(--fd-primary-muted);
1045
- border-color: var(--fd-primary);
1046
- }
1047
-
1048
- .flowdrop-console-toggle--active:hover {
1049
- color: var(--fd-primary);
1050
- background-color: var(--fd-primary-muted);
1051
1062
  }
1052
1063
 
1053
1064
  :global(.flowdrop-workflow-editor .svelte-flow__node:hover) {
@@ -3,6 +3,7 @@ import type { WorkflowNode as WorkflowNodeType } from '../types/index.js';
3
3
  import type { EndpointConfig } from '../config/endpoints.js';
4
4
  import type { AuthProvider } from '../types/auth.js';
5
5
  import type { FlowDropInstance } from '../stores/instanceContainer.svelte.js';
6
+ import type { FlowDropGridVariant } from '../types/theme.js';
6
7
  interface Props {
7
8
  endpointConfig?: EndpointConfig;
8
9
  /** Auth provider applied to this instance's API requests. */
@@ -27,6 +28,23 @@ interface Props {
27
28
  onToggleConsole?: () => void;
28
29
  /** Per-instance state container (created by mount functions). Defaults to the page-default instance. */
29
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;
30
48
  }
31
49
  declare const WorkflowEditor: import("svelte").Component<Props, {
32
50
  updateNodeData: (nodeId: string, dataUpdates: Partial<WorkflowNodeType["data"]>) => void;
@@ -552,7 +552,7 @@
552
552
 
553
553
  .ai-chat-panel__messages::-webkit-scrollbar-thumb {
554
554
  background: var(--fd-scrollbar-thumb);
555
- border-radius: 4px;
555
+ border-radius: var(--fd-scrollbar-radius);
556
556
  }
557
557
 
558
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 {