@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
@@ -232,7 +232,6 @@
232
232
 
233
233
  .chat-input__wrapper:focus-within {
234
234
  border-color: var(--fd-primary);
235
- box-shadow: 0 0 0 3px var(--fd-primary-muted);
236
235
  }
237
236
 
238
237
  .chat-input__textarea {
@@ -8,6 +8,9 @@
8
8
 
9
9
  <script lang="ts">
10
10
  import Icon from '@iconify/svelte';
11
+ import Input from '../Input.svelte';
12
+ import Select from '../Select.svelte';
13
+ import Textarea from '../Textarea.svelte';
11
14
  import { slide } from 'svelte/transition';
12
15
  import type { PlaygroundInputField } from '../../types/playground.js';
13
16
  import { getInstance } from '../../stores/getInstance.svelte.js';
@@ -171,9 +174,8 @@
171
174
 
172
175
  {#if hasEnumOptions(field)}
173
176
  <!-- Select for enum fields -->
174
- <select
177
+ <Select
175
178
  id="input-{field.nodeId}-{field.fieldId}"
176
- class="input-collector__select"
177
179
  value={getValue(field)}
178
180
  onchange={(e) => updateValue(field, e.currentTarget.value)}
179
181
  >
@@ -181,17 +183,16 @@
181
183
  {#each field.schema?.enum ?? [] as option (option)}
182
184
  <option value={String(option)}>{option}</option>
183
185
  {/each}
184
- </select>
186
+ </Select>
185
187
  {:else if getInputType(field) === 'textarea'}
186
188
  <!-- Textarea for multiline -->
187
- <textarea
189
+ <Textarea
188
190
  id="input-{field.nodeId}-{field.fieldId}"
189
- class="input-collector__textarea"
190
191
  placeholder={field.schema?.description ?? `Enter ${field.label}`}
191
192
  value={String(getValue(field) ?? '')}
192
193
  oninput={(e) => updateValue(field, e.currentTarget.value)}
193
- rows="3"
194
- ></textarea>
194
+ rows={3}
195
+ />
195
196
  {:else if getInputType(field) === 'checkbox'}
196
197
  <!-- Checkbox for boolean -->
197
198
  <label class="input-collector__checkbox-wrapper">
@@ -208,10 +209,10 @@
208
209
  </label>
209
210
  {:else if getInputType(field) === 'number'}
210
211
  <!-- Number input -->
211
- <input
212
+ <Input
212
213
  id="input-{field.nodeId}-{field.fieldId}"
213
214
  type="number"
214
- class="input-collector__input"
215
+ class="flowdrop-input--numeric"
215
216
  placeholder={field.schema?.description ?? `Enter ${field.label}`}
216
217
  value={Number(getValue(field) ?? 0)}
217
218
  min={field.schema?.minimum}
@@ -220,10 +221,9 @@
220
221
  />
221
222
  {:else}
222
223
  <!-- Text input (default) -->
223
- <input
224
+ <Input
224
225
  id="input-{field.nodeId}-{field.fieldId}"
225
226
  type="text"
226
- class="input-collector__input"
227
227
  placeholder={field.schema?.description ?? `Enter ${field.label}`}
228
228
  value={String(getValue(field) ?? '')}
229
229
  oninput={(e) => updateValue(field, e.currentTarget.value)}
@@ -351,43 +351,6 @@
351
351
  color: var(--fd-error);
352
352
  }
353
353
 
354
- .input-collector__input,
355
- .input-collector__select,
356
- .input-collector__textarea {
357
- padding: var(--fd-space-xs) var(--fd-space-md);
358
- border: 1px solid var(--fd-border);
359
- border-radius: var(--fd-radius-lg);
360
- font-size: var(--fd-text-sm);
361
- font-family: inherit;
362
- color: var(--fd-foreground);
363
- background-color: var(--fd-background);
364
- transition:
365
- border-color var(--fd-transition-normal),
366
- box-shadow var(--fd-transition-normal);
367
- }
368
-
369
- .input-collector__input:focus,
370
- .input-collector__select:focus,
371
- .input-collector__textarea:focus {
372
- outline: none;
373
- border-color: var(--fd-primary);
374
- box-shadow: 0 0 0 3px var(--fd-primary-muted);
375
- }
376
-
377
- .input-collector__input::placeholder,
378
- .input-collector__textarea::placeholder {
379
- color: var(--fd-muted-foreground);
380
- }
381
-
382
- .input-collector__textarea {
383
- resize: vertical;
384
- min-height: 80px;
385
- }
386
-
387
- .input-collector__select {
388
- cursor: pointer;
389
- }
390
-
391
354
  .input-collector__checkbox-wrapper {
392
355
  display: flex;
393
356
  align-items: center;
@@ -52,7 +52,7 @@
52
52
  endpointConfig,
53
53
  authProvider,
54
54
  config = {},
55
- showNavbar = true,
55
+ showNavbar = false,
56
56
  navbarTitle,
57
57
  primaryActions = [],
58
58
  showSettings = true,
@@ -463,11 +463,6 @@
463
463
  .playground-studio__back-to-chat:hover {
464
464
  background-color: var(--fd-muted);
465
465
  }
466
-
467
- .playground-studio__back-to-chat:focus-visible {
468
- outline: 2px solid var(--fd-ring);
469
- outline-offset: 2px;
470
- }
471
466
  }
472
467
 
473
468
  @media (prefers-reduced-motion: reduce) {
@@ -2,7 +2,7 @@
2
2
  * Messages module — typed, overridable, translation-ready user-facing strings.
3
3
  *
4
4
  * See `./defaults.ts` for the canonical shape, `./context.ts` for the runtime
5
- * plumbing, and the i18n guide in `apps/docs` for consumer recipes.
5
+ * plumbing, and the i18n guide in the docs site (`.docs/`) for consumer recipes.
6
6
  */
7
7
  export { defaultMessages } from './defaults.js';
8
8
  export { mergeMessages } from './merge.js';
@@ -2,7 +2,7 @@
2
2
  * Messages module — typed, overridable, translation-ready user-facing strings.
3
3
  *
4
4
  * See `./defaults.ts` for the canonical shape, `./context.ts` for the runtime
5
- * plumbing, and the i18n guide in `apps/docs` for consumer recipes.
5
+ * plumbing, and the i18n guide in the docs site (`.docs/`) for consumer recipes.
6
6
  */
7
7
  export { defaultMessages } from './defaults.js';
8
8
  export { mergeMessages } from './merge.js';
@@ -37,8 +37,8 @@ info:
37
37
  email: shibinkidd@gmail.com
38
38
  url: https://www.drupal.org/project/issues/flowdrop?categories=All
39
39
  servers:
40
- - url: http://localhost:5173/api/flowdrop
41
- description: Local development server (Svelte)
40
+ - url: http://localhost:7104/api/flowdrop
41
+ description: Local development server
42
42
  - url: https://flowdrop.ddev.site/api/flowdrop
43
43
  description: Local Drupal server
44
44
  security:
@@ -252,7 +252,7 @@ export interface PlaygroundAppMountOptions extends Omit<PlaygroundStudioMountOpt
252
252
  * @default "standalone"
253
253
  */
254
254
  mode?: 'standalone' | 'embedded';
255
- /** Render the FlowDrop Navbar above the playground (default: true). */
255
+ /** Render the FlowDrop Navbar above the playground (default: false). */
256
256
  showNavbar?: boolean;
257
257
  /** Title shown in the navbar. Falls back to the workflow name, then "Playground". */
258
258
  navbarTitle?: string;
@@ -268,17 +268,21 @@ export interface PlaygroundAppMountOptions extends Omit<PlaygroundStudioMountOpt
268
268
  showSettingsResetButton?: boolean;
269
269
  }
270
270
  /**
271
- * Mount the full-page PlaygroundApp (Navbar + PlaygroundStudio) into a container.
271
+ * Mount the full-page PlaygroundApp (PlaygroundStudio, optionally wrapped in the
272
+ * FlowDrop Navbar) into a container.
272
273
  *
273
- * Use this when you want the same chrome as the FlowDrop editor logo,
274
- * branding, and settings modal wrapped around the playground. For an
275
- * embeddable split-pane without the navbar, use mountPlaygroundStudio().
274
+ * The navbar is opt-in (`showNavbar: true`) matching the editor mount, so
275
+ * embedding into a page that already has its own header never double-stacks a
276
+ * header. Pass `showNavbar: true` when FlowDrop owns the whole page and you want
277
+ * its chrome (logo, branding, settings modal). For a leaner embeddable
278
+ * split-pane, mountPlaygroundStudio() omits the navbar wrapper entirely.
276
279
  *
277
280
  * @example
278
281
  * ```typescript
279
282
  * const app = await mountPlaygroundApp(container, {
280
283
  * workflowId: 'wf-123',
281
284
  * endpointConfig: createEndpointConfig('/api/flowdrop'),
285
+ * showNavbar: true,
282
286
  * navbarTitle: 'My Workflow',
283
287
  * primaryActions: [
284
288
  * { label: 'Edit', href: '/workflows/wf-123/edit', icon: 'mdi:pencil-outline', variant: 'secondary' },
@@ -287,17 +287,21 @@ export async function mountPlaygroundStudio(container, options) {
287
287
  return buildMountedPlayground(svelteApp, workflowId, config, fd, ownsInstance, onSessionStatusChange);
288
288
  }
289
289
  /**
290
- * Mount the full-page PlaygroundApp (Navbar + PlaygroundStudio) into a container.
290
+ * Mount the full-page PlaygroundApp (PlaygroundStudio, optionally wrapped in the
291
+ * FlowDrop Navbar) into a container.
291
292
  *
292
- * Use this when you want the same chrome as the FlowDrop editor logo,
293
- * branding, and settings modal wrapped around the playground. For an
294
- * embeddable split-pane without the navbar, use mountPlaygroundStudio().
293
+ * The navbar is opt-in (`showNavbar: true`) matching the editor mount, so
294
+ * embedding into a page that already has its own header never double-stacks a
295
+ * header. Pass `showNavbar: true` when FlowDrop owns the whole page and you want
296
+ * its chrome (logo, branding, settings modal). For a leaner embeddable
297
+ * split-pane, mountPlaygroundStudio() omits the navbar wrapper entirely.
295
298
  *
296
299
  * @example
297
300
  * ```typescript
298
301
  * const app = await mountPlaygroundApp(container, {
299
302
  * workflowId: 'wf-123',
300
303
  * endpointConfig: createEndpointConfig('/api/flowdrop'),
304
+ * showNavbar: true,
301
305
  * navbarTitle: 'My Workflow',
302
306
  * primaryActions: [
303
307
  * { label: 'Edit', href: '/workflows/wf-123/edit', icon: 'mdi:pencil-outline', variant: 'secondary' },
@@ -307,7 +311,7 @@ export async function mountPlaygroundStudio(container, options) {
307
311
  * ```
308
312
  */
309
313
  export async function mountPlaygroundApp(container, options) {
310
- const { workflowId, workflow, mode = 'standalone', initialSessionId, endpointConfig, authProvider, config = {}, height, width, showNavbar = true, navbarTitle, primaryActions, showSettings = true, settingsCategories, showSettingsSyncButton, showSettingsResetButton, initialPipelineOpen, minChatWidth, initialPipelineWidth, settings: initialSettings, onClose, onSessionNavigate, onSessionStatusChange, instanceId } = options;
314
+ const { workflowId, workflow, mode = 'standalone', initialSessionId, endpointConfig, authProvider, config = {}, height, width, showNavbar = false, navbarTitle, primaryActions, showSettings = true, settingsCategories, showSettingsSyncButton, showSettingsResetButton, initialPipelineOpen, minChatWidth, initialPipelineWidth, settings: initialSettings, onClose, onSessionNavigate, onSessionStatusChange, instanceId } = options;
311
315
  if (!workflowId) {
312
316
  throw new Error('workflowId is required for mountPlaygroundApp()');
313
317
  }
@@ -0,0 +1,30 @@
1
+ import type { FlowDropSkin } from '../types/skin';
2
+ /**
3
+ * Drafter — a fresh, modern "drafting workspace" skin for the whole editor
4
+ * environment (see ref-image.png): a fresh white shell around a mint/aqua
5
+ * canvas with soft cyan/teal technical grid lines, crisp engineering geometry
6
+ * and clean teal-ink text — not a neutral admin UI and not an all-cyan shell.
7
+ *
8
+ * Unlike a canvas-only skin, Drafter themes the entire shell so it reads as one
9
+ * designed environment:
10
+ * - App chrome (navbar, sidebars, inspector, status bars, form fields) stays
11
+ * white/near-white for a clean fresh product feel.
12
+ * - The mint/aqua personality lives in the canvas, node glass, focus rings,
13
+ * selected states and small technical accents.
14
+ * - Disabled/read-only surfaces use quiet light grey so state remains obvious.
15
+ * - Borders are mostly neutral hairlines; strong/focus borders + node outlines
16
+ * are teal/cyan ink (--fd-ring / --fd-border-strong / --fd-node-border).
17
+ * - Focus rings are cyan (--fd-ring), not the default blue.
18
+ * - Nodes are frosted glass with a faint inner highlight; the minimap + zoom
19
+ * controls share the same vocabulary.
20
+ * - Note/instruction cards read as cool annotations (translucent tint + slate
21
+ * ink border), never as a filled "success" card.
22
+ * - Emerald/green is reserved for primary actions, selection and live edges
23
+ * (--fd-primary) — it is not used for every outline.
24
+ *
25
+ * Data-type port colors and category icon colors are left untouched so they keep
26
+ * their full color against the draft surface. The square grid is rendered by
27
+ * WorkflowEditor via config.canvas.grid = 'lines'; --fd-grid-pattern-color
28
+ * colors it. Ships light + dark variants.
29
+ */
30
+ export declare const drafterSkin: FlowDropSkin;
@@ -0,0 +1,198 @@
1
+ /**
2
+ * Drafter — a fresh, modern "drafting workspace" skin for the whole editor
3
+ * environment (see ref-image.png): a fresh white shell around a mint/aqua
4
+ * canvas with soft cyan/teal technical grid lines, crisp engineering geometry
5
+ * and clean teal-ink text — not a neutral admin UI and not an all-cyan shell.
6
+ *
7
+ * Unlike a canvas-only skin, Drafter themes the entire shell so it reads as one
8
+ * designed environment:
9
+ * - App chrome (navbar, sidebars, inspector, status bars, form fields) stays
10
+ * white/near-white for a clean fresh product feel.
11
+ * - The mint/aqua personality lives in the canvas, node glass, focus rings,
12
+ * selected states and small technical accents.
13
+ * - Disabled/read-only surfaces use quiet light grey so state remains obvious.
14
+ * - Borders are mostly neutral hairlines; strong/focus borders + node outlines
15
+ * are teal/cyan ink (--fd-ring / --fd-border-strong / --fd-node-border).
16
+ * - Focus rings are cyan (--fd-ring), not the default blue.
17
+ * - Nodes are frosted glass with a faint inner highlight; the minimap + zoom
18
+ * controls share the same vocabulary.
19
+ * - Note/instruction cards read as cool annotations (translucent tint + slate
20
+ * ink border), never as a filled "success" card.
21
+ * - Emerald/green is reserved for primary actions, selection and live edges
22
+ * (--fd-primary) — it is not used for every outline.
23
+ *
24
+ * Data-type port colors and category icon colors are left untouched so they keep
25
+ * their full color against the draft surface. The square grid is rendered by
26
+ * WorkflowEditor via config.canvas.grid = 'lines'; --fd-grid-pattern-color
27
+ * colors it. Ships light + dark variants.
28
+ */
29
+ export const drafterSkin = {
30
+ tokens: {
31
+ /* ----- Shell surfaces: fresh white shell + pale mint chrome ----- */
32
+ /* Neutral greys read as cold admin chrome and fight the mint canvas, so the
33
+ quiet surfaces carry a faint aqua-mint tint instead. muted-foreground is
34
+ a darker teal-slate (≈6.5:1 on white) so secondary/helper text clears
35
+ WCAG AA comfortably — grey body text was the accessibility problem. */
36
+ background: '#ffffff',
37
+ foreground: '#10201c',
38
+ muted: '#eaf5f0',
39
+ 'muted-foreground': '#46635b',
40
+ subtle: '#e1f0ea',
41
+ card: '#ffffff',
42
+ 'card-foreground': '#10201c',
43
+ header: '#ffffff',
44
+ 'header-foreground': '#10201c',
45
+ 'header-gradient': 'linear-gradient(180deg, #ffffff 0%, #fbfefd 100%)',
46
+ 'surface-tint': 'rgba(20, 184, 166, 0.015)',
47
+ /* White sidebars/inspector with only a whisper of technical glass */
48
+ 'panel-bg': 'rgba(255, 255, 255, 0.94)',
49
+ 'panel-backdrop-filter': 'blur(10px) saturate(1.04)',
50
+ backdrop: 'rgba(255, 255, 255, 0.92)',
51
+ /* ----- Borders: soft mint hairlines; strong/focus = teal-cyan accent ----- */
52
+ border: '#d3e6df',
53
+ 'border-muted': '#e4f0eb',
54
+ 'border-strong': 'rgba(15, 118, 110, 0.42)',
55
+ ring: '#06b6d4',
56
+ /* ----- Canvas: fresh aqua-mint, soft cyan/teal square grid ----- */
57
+ 'canvas-bg': '#fbfefd',
58
+ 'grid-pattern-color': 'rgba(20, 184, 166, 0.08)',
59
+ /* ----- Nodes: frosted glass, faint inner highlight ----- */
60
+ 'node-bg': 'rgba(247, 252, 250, 0.7)',
61
+ 'node-header-bg': 'rgba(214, 245, 236, 0.6)',
62
+ 'node-backdrop-filter': 'blur(10px) saturate(1.15)',
63
+ 'node-radius': '2px',
64
+ 'node-shadow': 'inset 0 1px 0 0 rgba(255, 255, 255, 0.6)',
65
+ 'node-shadow-hover': 'inset 0 1px 0 0 rgba(255, 255, 255, 0.85)',
66
+ 'node-border': '#0f766e',
67
+ 'node-border-hover': '#0c5f59',
68
+ 'node-border-width': '1.25px',
69
+ /* Header divider matches the node outline ink (tracks light/dark node-border) */
70
+ 'node-header-divider-color': 'var(--fd-node-border)',
71
+ 'handle-border': '#ffffff',
72
+ /* Notes read as cool annotations, not filled success cards */
73
+ 'note-border': '#5b7891',
74
+ 'note-border-hover': '#48617a',
75
+ /* Status hues tuned to the cool palette: danger = rose (teal's warm
76
+ complement, not a generic red), warning = golden amber. Success/info stay
77
+ on the emerald/cyan family so they read as part of the theme. */
78
+ success: '#0d9488',
79
+ 'success-hover': '#0f766e',
80
+ info: '#0891b2',
81
+ 'info-hover': '#0e7490',
82
+ warning: '#d97706',
83
+ 'warning-hover': '#b45309',
84
+ error: '#e11d48',
85
+ 'error-hover': '#be123c',
86
+ /* Status/accent tints are FLAT + OPAQUE (not alpha) so the action buttons
87
+ that use them as fills (form add/move/delete, canvas toggles, secondary)
88
+ read as solid chips, never see-through to the grid. Values are the opaque
89
+ equivalent of the former translucent tints over the white shell. */
90
+ 'info-muted': '#e6f4f7',
91
+ 'success-muted': '#e7f4f3',
92
+ 'warning-muted': '#faefe1',
93
+ 'error-muted': '#fce8ed',
94
+ /* ----- Crisp drafting geometry + flat chrome (2–6px radius, no soft shadow) ----- */
95
+ 'radius-sm': '2px',
96
+ 'radius-md': '3px',
97
+ 'radius-lg': '4px',
98
+ 'radius-xl': '6px',
99
+ /* Form controls + their group containers (fields, array item boxes,
100
+ fieldsets) get the sharpest 2px corner so the config panel reads as
101
+ crisp drafting geometry, not rounded admin chrome. */
102
+ 'control-radius': '2px',
103
+ 'scrollbar-radius': '0',
104
+ 'shadow-sm': 'none',
105
+ 'shadow-md': 'none',
106
+ /* ----- Canvas overlays: light, instrument-like ----- */
107
+ 'minimap-bg': 'rgba(255, 255, 255, 0.72)',
108
+ 'minimap-mask-bg': 'rgba(15, 118, 110, 0.08)',
109
+ 'minimap-mask-stroke': 'rgba(15, 118, 110, 0.35)',
110
+ 'minimap-node-bg': 'rgba(15, 118, 110, 0.3)',
111
+ 'minimap-node-stroke': 'rgba(15, 118, 110, 0.45)',
112
+ 'controls-button-bg': '#ffffff',
113
+ 'controls-button-bg-hover': '#ccfbf1',
114
+ 'controls-button-color': '#0f766e',
115
+ 'controls-button-color-hover': '#0c5f59',
116
+ 'controls-button-border': 'rgba(15, 118, 110, 0.25)',
117
+ /* ----- Secondary = mint, accent = cyan, primary = the one allowed green ----- */
118
+ secondary: '#e4f1ed',
119
+ 'secondary-hover': '#cfe6e0',
120
+ 'secondary-foreground': '#0f3d36',
121
+ accent: '#06b6d4',
122
+ 'accent-hover': '#0891b2',
123
+ 'accent-foreground': '#ffffff',
124
+ 'accent-muted': '#e1f6fa',
125
+ primary: '#10b981',
126
+ 'primary-hover': '#059669',
127
+ 'primary-foreground': '#ffffff',
128
+ 'primary-muted': '#def5ed'
129
+ },
130
+ darkTokens: {
131
+ /* ----- Shell surfaces: deep teal-slate glass ----- */
132
+ background: '#0e2421',
133
+ foreground: '#d8f0ea',
134
+ muted: 'rgba(20, 60, 54, 0.6)',
135
+ 'muted-foreground': '#8fb3aa',
136
+ subtle: 'rgba(13, 47, 44, 0.7)',
137
+ card: 'rgba(18, 42, 38, 0.96)',
138
+ 'card-foreground': '#d8f0ea',
139
+ header: 'rgba(13, 40, 37, 0.7)',
140
+ 'header-foreground': '#d8f0ea',
141
+ 'header-gradient': 'linear-gradient(180deg, rgba(17, 42, 38, 0.9) 0%, rgba(12, 33, 30, 0.9) 100%)',
142
+ 'surface-tint': 'rgba(45, 212, 191, 0.04)',
143
+ 'panel-bg': 'rgba(14, 36, 33, 0.8)',
144
+ 'panel-backdrop-filter': 'blur(14px) saturate(1.2)',
145
+ backdrop: 'rgba(11, 31, 28, 0.8)',
146
+ border: 'rgba(45, 212, 191, 0.22)',
147
+ 'border-muted': 'rgba(45, 212, 191, 0.12)',
148
+ 'border-strong': 'rgba(45, 212, 191, 0.4)',
149
+ ring: '#22d3ee',
150
+ 'canvas-bg': '#0b1f1c',
151
+ 'grid-pattern-color': 'rgba(45, 212, 191, 0.16)',
152
+ 'node-bg': 'rgba(17, 38, 35, 0.62)',
153
+ 'node-header-bg': 'rgba(13, 47, 44, 0.6)',
154
+ 'node-backdrop-filter': 'blur(10px) saturate(1.2)',
155
+ 'node-shadow': 'inset 0 1px 0 0 rgba(255, 255, 255, 0.08)',
156
+ 'node-shadow-hover': 'inset 0 1px 0 0 rgba(255, 255, 255, 0.14)',
157
+ 'node-border': '#0d9488',
158
+ 'node-border-hover': '#2dd4bf',
159
+ 'handle-border': '#0b1f1c',
160
+ 'note-border': '#7d96b0',
161
+ 'note-border-hover': '#9fb4cb',
162
+ success: '#2dd4bf',
163
+ 'success-hover': '#5eead4',
164
+ info: '#22d3ee',
165
+ 'info-hover': '#67e8f9',
166
+ warning: '#fbbf24',
167
+ 'warning-hover': '#fcd34d',
168
+ error: '#fb7185',
169
+ 'error-hover': '#fda4af',
170
+ /* Flat + opaque tints (opaque equivalent of the former alpha tints over the
171
+ deep teal-slate shell) so button fills never go see-through. */
172
+ 'info-muted': '#10393a',
173
+ 'success-muted': '#123934',
174
+ 'warning-muted': '#2f3a21',
175
+ 'error-muted': '#2a2d2d',
176
+ 'minimap-bg': 'rgba(11, 31, 28, 0.7)',
177
+ 'minimap-mask-bg': 'rgba(45, 212, 191, 0.06)',
178
+ 'minimap-mask-stroke': 'rgba(45, 212, 191, 0.3)',
179
+ 'minimap-node-bg': 'rgba(45, 212, 191, 0.28)',
180
+ 'minimap-node-stroke': 'rgba(45, 212, 191, 0.45)',
181
+ 'controls-button-bg': '#102522',
182
+ 'controls-button-bg-hover': '#0d2d2a',
183
+ 'controls-button-color': '#2dd4bf',
184
+ 'controls-button-color-hover': '#5eead4',
185
+ 'controls-button-border': 'rgba(45, 212, 191, 0.3)',
186
+ secondary: '#0d2d2a',
187
+ 'secondary-hover': '#133a34',
188
+ 'secondary-foreground': '#d8f0ea',
189
+ accent: '#22d3ee',
190
+ 'accent-hover': '#67e8f9',
191
+ 'accent-foreground': '#03291c',
192
+ 'accent-muted': '#113d3e',
193
+ primary: '#34d399',
194
+ 'primary-hover': '#6ee7b7',
195
+ 'primary-foreground': '#03291c',
196
+ 'primary-muted': '#144034'
197
+ }
198
+ };
@@ -1,6 +1,7 @@
1
1
  import type { FlowDropSkin, FlowDropSkinName } from '../types/skin';
2
2
  import { defaultSkin } from './default';
3
3
  import { slateSkin } from './slate';
4
+ import { drafterSkin } from './drafter';
4
5
  /**
5
6
  * Resolve a skin prop to a complete FlowDropSkin object.
6
7
  *
@@ -10,4 +11,4 @@ import { slateSkin } from './slate';
10
11
  * → minimal skin tokens + { primary: '#e11d48' }
11
12
  */
12
13
  export declare function resolveSkin(skin: FlowDropSkin | FlowDropSkinName | undefined): FlowDropSkin;
13
- export { defaultSkin, slateSkin };
14
+ export { defaultSkin, slateSkin, drafterSkin };
@@ -1,8 +1,10 @@
1
1
  import { defaultSkin } from './default';
2
2
  import { slateSkin } from './slate';
3
+ import { drafterSkin } from './drafter';
3
4
  const builtinSkins = {
4
5
  default: defaultSkin,
5
- slate: slateSkin
6
+ slate: slateSkin,
7
+ drafter: drafterSkin
6
8
  };
7
9
  /**
8
10
  * Resolve a skin prop to a complete FlowDropSkin object.
@@ -27,4 +29,4 @@ export function resolveSkin(skin) {
27
29
  }
28
30
  return skin;
29
31
  }
30
- export { defaultSkin, slateSkin };
32
+ export { defaultSkin, slateSkin, drafterSkin };