@flowdrop/flowdrop 2.0.0-beta.2 → 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 (85) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/MIGRATION-2.0.md +13 -0
  3. package/dist/components/App.svelte +21 -45
  4. package/dist/components/App.svelte.d.ts +2 -7
  5. package/dist/components/CanvasIconButton.svelte +76 -0
  6. package/dist/components/CanvasIconButton.svelte.d.ts +18 -0
  7. package/dist/components/ConfigForm.svelte +0 -19
  8. package/dist/components/ConfigPanel.svelte +4 -3
  9. package/dist/components/LogoWordmark.svelte +113 -0
  10. package/dist/components/LogoWordmark.svelte.d.ts +26 -0
  11. package/dist/components/Navbar.svelte +8 -59
  12. package/dist/components/NodeSidebar.svelte +4 -11
  13. package/dist/components/NodeSwapPicker.svelte +0 -2
  14. package/dist/components/PortMappingRow.svelte +0 -2
  15. package/dist/components/SchemaForm.svelte +0 -12
  16. package/dist/components/SettingsModal.svelte +0 -5
  17. package/dist/components/SettingsPanel.svelte +2 -6
  18. package/dist/components/ThemeToggle.svelte +0 -5
  19. package/dist/components/UniversalNode.svelte +32 -1
  20. package/dist/components/WorkflowEditor.svelte +62 -51
  21. package/dist/components/WorkflowEditor.svelte.d.ts +18 -0
  22. package/dist/components/chat/AIChatPanel.svelte +1 -1
  23. package/dist/components/console/ConsoleAutocomplete.svelte +1 -1
  24. package/dist/components/console/ConsoleOutput.svelte +2 -2
  25. package/dist/components/form/FormArray.svelte +0 -16
  26. package/dist/components/form/FormAutocomplete.svelte +10 -6
  27. package/dist/components/form/FormCheckboxGroup.svelte +0 -4
  28. package/dist/components/form/FormCodeEditor.svelte +9 -7
  29. package/dist/components/form/FormFieldLight.svelte +3 -3
  30. package/dist/components/form/FormMarkdownEditor.svelte +8 -5
  31. package/dist/components/form/FormNumberField.svelte +0 -4
  32. package/dist/components/form/FormRangeField.svelte +1 -20
  33. package/dist/components/form/FormSelect.svelte +10 -6
  34. package/dist/components/form/FormTemplateEditor.svelte +6 -4
  35. package/dist/components/form/FormTextField.svelte +10 -6
  36. package/dist/components/form/FormTextarea.svelte +10 -6
  37. package/dist/components/form/FormToggle.svelte +0 -4
  38. package/dist/components/icons/CommandLineIcon.svelte +15 -0
  39. package/dist/components/icons/CommandLineIcon.svelte.d.ts +26 -0
  40. package/dist/components/icons/MenuIcon.svelte +4 -0
  41. package/dist/components/icons/MenuIcon.svelte.d.ts +26 -0
  42. package/dist/components/icons/MenuOpenIcon.svelte +6 -0
  43. package/dist/components/icons/MenuOpenIcon.svelte.d.ts +26 -0
  44. package/dist/components/interrupt/ChoicePrompt.svelte +0 -10
  45. package/dist/components/interrupt/ConfirmationPrompt.svelte +0 -5
  46. package/dist/components/interrupt/InterruptBubble.svelte +0 -10
  47. package/dist/components/interrupt/ReviewPrompt.svelte +0 -20
  48. package/dist/components/interrupt/TextInputPrompt.svelte +0 -6
  49. package/dist/components/layouts/MainLayout.svelte +4 -5
  50. package/dist/components/nodes/AtomNode.svelte +46 -34
  51. package/dist/components/nodes/GatewayNode.svelte +91 -99
  52. package/dist/components/nodes/IdeaNode.svelte +62 -90
  53. package/dist/components/nodes/NodeConfigButton.svelte +86 -0
  54. package/dist/components/nodes/NodeConfigButton.svelte.d.ts +15 -0
  55. package/dist/components/nodes/NotesNode.svelte +70 -81
  56. package/dist/components/nodes/SimpleNode.svelte +28 -78
  57. package/dist/components/nodes/SquareNode.svelte +79 -109
  58. package/dist/components/nodes/TerminalNode.svelte +28 -86
  59. package/dist/components/nodes/ToolNode.svelte +82 -95
  60. package/dist/components/nodes/WorkflowNode.svelte +91 -100
  61. package/dist/components/playground/ChatInput.svelte +0 -1
  62. package/dist/components/playground/InputCollector.svelte +0 -2
  63. package/dist/components/playground/PlaygroundApp.svelte +1 -1
  64. package/dist/components/playground/PlaygroundStudio.svelte +0 -5
  65. package/dist/playground/mount.d.ts +9 -5
  66. package/dist/playground/mount.js +9 -5
  67. package/dist/skins/drafter.d.ts +30 -0
  68. package/dist/skins/drafter.js +185 -0
  69. package/dist/skins/index.d.ts +2 -1
  70. package/dist/skins/index.js +4 -2
  71. package/dist/styles/base.css +38 -9
  72. package/dist/styles/tokens.css +54 -2
  73. package/dist/svelte-app.d.ts +6 -0
  74. package/dist/svelte-app.js +3 -2
  75. package/dist/themes/drafter.d.ts +2 -0
  76. package/dist/themes/drafter.js +15 -0
  77. package/dist/themes/index.d.ts +2 -1
  78. package/dist/themes/index.js +8 -2
  79. package/dist/types/events.d.ts +18 -0
  80. package/dist/types/events.js +2 -1
  81. package/dist/types/settings.d.ts +1 -1
  82. package/dist/types/settings.js +1 -1
  83. package/dist/types/skin.d.ts +1 -1
  84. package/dist/types/theme.d.ts +16 -2
  85. package/package.json +1 -1
@@ -623,7 +623,8 @@
623
623
  border: 1px solid var(--fd-border);
624
624
  border-radius: var(--fd-radius-lg);
625
625
  overflow: hidden;
626
- background-color: var(--fd-muted);
626
+ /* Match plain form fields: rest on the input surface, not --fd-muted. */
627
+ background-color: var(--fd-background);
627
628
  transition: all var(--fd-transition-normal);
628
629
  box-shadow: var(--fd-shadow-sm);
629
630
  }
@@ -633,12 +634,13 @@
633
634
  background-color: var(--fd-background);
634
635
  }
635
636
 
637
+ /* Compound widget: ring drawn on the container via :focus-within, using the
638
+ standard --fd-ring tokens (outline isn't clipped by the container overflow). */
636
639
  .form-template-editor__container:focus-within {
637
640
  border-color: var(--fd-accent);
638
641
  background-color: var(--fd-background);
639
- box-shadow:
640
- 0 0 0 3px rgba(168, 85, 247, 0.12),
641
- var(--fd-shadow-sm);
642
+ outline: var(--fd-ring-width) solid var(--fd-ring);
643
+ outline-offset: var(--fd-ring-offset);
642
644
  }
643
645
 
644
646
  /* Dark theme overrides */
@@ -66,7 +66,7 @@
66
66
  font-size: var(--fd-text-sm);
67
67
  font-family: inherit;
68
68
  color: var(--fd-foreground);
69
- background-color: var(--fd-muted);
69
+ background-color: var(--fd-background);
70
70
  transition: all var(--fd-transition-normal);
71
71
  box-shadow: var(--fd-shadow-sm);
72
72
  }
@@ -81,11 +81,15 @@
81
81
  }
82
82
 
83
83
  .form-text-field:focus {
84
- outline: none;
85
- border-color: var(--fd-primary);
84
+ border-color: var(--fd-ring);
86
85
  background-color: var(--fd-background);
87
- box-shadow:
88
- 0 0 0 3px rgba(59, 130, 246, 0.12),
89
- var(--fd-shadow-sm);
86
+ }
87
+
88
+ .form-text-field:disabled {
89
+ background-color: var(--fd-muted);
90
+ border-color: var(--fd-border-muted);
91
+ color: var(--fd-muted-foreground);
92
+ cursor: not-allowed;
93
+ opacity: 1;
90
94
  }
91
95
  </style>
@@ -69,7 +69,7 @@
69
69
  font-size: var(--fd-text-sm);
70
70
  font-family: inherit;
71
71
  color: var(--fd-foreground);
72
- background-color: var(--fd-muted);
72
+ background-color: var(--fd-background);
73
73
  transition: all var(--fd-transition-normal);
74
74
  box-shadow: var(--fd-shadow-sm);
75
75
  resize: vertical;
@@ -87,11 +87,15 @@
87
87
  }
88
88
 
89
89
  .form-textarea:focus {
90
- outline: none;
91
- border-color: var(--fd-primary);
90
+ border-color: var(--fd-ring);
92
91
  background-color: var(--fd-background);
93
- box-shadow:
94
- 0 0 0 3px rgba(59, 130, 246, 0.12),
95
- var(--fd-shadow-sm);
92
+ }
93
+
94
+ .form-textarea:disabled {
95
+ background-color: var(--fd-muted);
96
+ border-color: var(--fd-border-muted);
97
+ color: var(--fd-muted-foreground);
98
+ cursor: not-allowed;
99
+ opacity: 1;
96
100
  }
97
101
  </style>
@@ -120,10 +120,6 @@
120
120
  transform: translateX(1.25rem);
121
121
  }
122
122
 
123
- .form-toggle__input:focus-visible + .form-toggle__track {
124
- box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2);
125
- }
126
-
127
123
  .form-toggle__label {
128
124
  font-size: var(--fd-text-sm);
129
125
  color: var(--fd-muted-foreground);
@@ -0,0 +1,15 @@
1
+ <!-- Inline SVG equivalent of heroicons:command-line (outline) -->
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ viewBox="0 0 24 24"
5
+ fill="none"
6
+ stroke="currentColor"
7
+ stroke-width="1.5"
8
+ stroke-linecap="round"
9
+ stroke-linejoin="round"
10
+ aria-hidden="true"
11
+ >
12
+ <path
13
+ d="M6.75 7.5l3 2.25-3 2.25m4.5 0h3m-9 8.25h13.5A2.25 2.25 0 0021 18V6a2.25 2.25 0 00-2.25-2.25H5.25A2.25 2.25 0 003 6v12a2.25 2.25 0 002.25 2.25z"
14
+ />
15
+ </svg>
@@ -0,0 +1,26 @@
1
+ export default CommandLineIcon;
2
+ type CommandLineIcon = SvelteComponent<{
3
+ [x: string]: never;
4
+ }, {
5
+ [evt: string]: CustomEvent<any>;
6
+ }, {}> & {
7
+ $$bindings?: string | undefined;
8
+ };
9
+ declare const CommandLineIcon: $$__sveltets_2_IsomorphicComponent<{
10
+ [x: string]: never;
11
+ }, {
12
+ [evt: string]: CustomEvent<any>;
13
+ }, {}, {}, string>;
14
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
15
+ new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
16
+ $$bindings?: Bindings;
17
+ } & Exports;
18
+ (internal: unknown, props: {
19
+ $$events?: Events;
20
+ $$slots?: Slots;
21
+ }): Exports & {
22
+ $set?: any;
23
+ $on?: any;
24
+ };
25
+ z_$$bindings?: Bindings;
26
+ }
@@ -0,0 +1,4 @@
1
+ <!-- Inline SVG equivalent of mdi:menu (Material Design Icons) -->
2
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
3
+ <path d="M3,6H21V8H3V6M3,11H21V13H3V11M3,16H21V18H3V16Z" />
4
+ </svg>
@@ -0,0 +1,26 @@
1
+ export default MenuIcon;
2
+ type MenuIcon = SvelteComponent<{
3
+ [x: string]: never;
4
+ }, {
5
+ [evt: string]: CustomEvent<any>;
6
+ }, {}> & {
7
+ $$bindings?: string | undefined;
8
+ };
9
+ declare const MenuIcon: $$__sveltets_2_IsomorphicComponent<{
10
+ [x: string]: never;
11
+ }, {
12
+ [evt: string]: CustomEvent<any>;
13
+ }, {}, {}, string>;
14
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
15
+ new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
16
+ $$bindings?: Bindings;
17
+ } & Exports;
18
+ (internal: unknown, props: {
19
+ $$events?: Events;
20
+ $$slots?: Slots;
21
+ }): Exports & {
22
+ $set?: any;
23
+ $on?: any;
24
+ };
25
+ z_$$bindings?: Bindings;
26
+ }
@@ -0,0 +1,6 @@
1
+ <!-- Inline SVG equivalent of mdi:menu-open (Material Design Icons) -->
2
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
3
+ <path
4
+ d="M21,15.61L19.59,17L14.58,12L19.59,7L21,8.39L17.44,12L21,15.61M3,6H16V8H3V6M3,13V11H13V13H3M3,18V16H16V18H3Z"
5
+ />
6
+ </svg>
@@ -0,0 +1,26 @@
1
+ export default MenuOpenIcon;
2
+ type MenuOpenIcon = SvelteComponent<{
3
+ [x: string]: never;
4
+ }, {
5
+ [evt: string]: CustomEvent<any>;
6
+ }, {}> & {
7
+ $$bindings?: string | undefined;
8
+ };
9
+ declare const MenuOpenIcon: $$__sveltets_2_IsomorphicComponent<{
10
+ [x: string]: never;
11
+ }, {
12
+ [evt: string]: CustomEvent<any>;
13
+ }, {}, {}, string>;
14
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
15
+ new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
16
+ $$bindings?: Bindings;
17
+ } & Exports;
18
+ (internal: unknown, props: {
19
+ $$events?: Events;
20
+ $$slots?: Slots;
21
+ }): Exports & {
22
+ $set?: any;
23
+ $on?: any;
24
+ };
25
+ z_$$bindings?: Bindings;
26
+ }
@@ -313,11 +313,6 @@
313
313
  border: 0;
314
314
  }
315
315
 
316
- .choice-prompt__option:focus-within {
317
- outline: 2px solid var(--fd-ring);
318
- outline-offset: 2px;
319
- }
320
-
321
316
  .choice-prompt__checkmark {
322
317
  flex-shrink: 0;
323
318
  font-size: 1.25rem;
@@ -390,11 +385,6 @@
390
385
  transform: translateY(-1px);
391
386
  }
392
387
 
393
- .choice-prompt__submit:focus-visible {
394
- outline: 2px solid var(--fd-ring);
395
- outline-offset: 2px;
396
- }
397
-
398
388
  .choice-prompt__submit:disabled {
399
389
  opacity: 0.5;
400
390
  cursor: not-allowed;
@@ -184,11 +184,6 @@
184
184
  min-width: 100px;
185
185
  }
186
186
 
187
- .confirmation-prompt__button:focus-visible {
188
- outline: 2px solid var(--fd-ring);
189
- outline-offset: 2px;
190
- }
191
-
192
187
  .confirmation-prompt__button:disabled {
193
188
  cursor: not-allowed;
194
189
  }
@@ -561,11 +561,6 @@
561
561
  background-color: var(--fd-error-hover);
562
562
  }
563
563
 
564
- .interrupt-bubble__retry-btn:focus-visible {
565
- outline: 2px solid var(--fd-ring);
566
- outline-offset: 2px;
567
- }
568
-
569
564
  /* Body - prompt content area, full width */
570
565
  .interrupt-bubble__body {
571
566
  padding: var(--fd-space-xl);
@@ -648,11 +643,6 @@
648
643
  background-color: var(--fd-error-muted);
649
644
  }
650
645
 
651
- .interrupt-bubble__cancel-btn:focus-visible {
652
- outline: 2px solid var(--fd-ring);
653
- outline-offset: 2px;
654
- }
655
-
656
646
  .interrupt-bubble__cancel-btn:disabled {
657
647
  opacity: 0.5;
658
648
  cursor: not-allowed;
@@ -540,11 +540,6 @@
540
540
  color: var(--fd-error);
541
541
  }
542
542
 
543
- .review-prompt__bulk-btn:focus-visible {
544
- outline: 2px solid var(--fd-ring);
545
- outline-offset: 2px;
546
- }
547
-
548
543
  .review-prompt__bulk-btn:disabled {
549
544
  opacity: 0.5;
550
545
  cursor: not-allowed;
@@ -642,11 +637,6 @@
642
637
  color: var(--fd-error-foreground);
643
638
  }
644
639
 
645
- .review-prompt__toggle-btn:focus-visible {
646
- outline: 2px solid var(--fd-ring);
647
- outline-offset: 2px;
648
- }
649
-
650
640
  .review-prompt__toggle-btn:disabled {
651
641
  opacity: 0.5;
652
642
  cursor: not-allowed;
@@ -739,11 +729,6 @@
739
729
  border-color: var(--fd-border-strong);
740
730
  }
741
731
 
742
- .review-prompt__html-toggle-btn:focus-visible {
743
- outline: 2px solid var(--fd-ring);
744
- outline-offset: 2px;
745
- }
746
-
747
732
  /* Raw HTML code display */
748
733
  .review-prompt__raw-html {
749
734
  font-family: var(--fd-review-font-mono);
@@ -842,11 +827,6 @@
842
827
  transform: translateY(-1px);
843
828
  }
844
829
 
845
- .review-prompt__submit:focus-visible {
846
- outline: 2px solid var(--fd-ring);
847
- outline-offset: 2px;
848
- }
849
-
850
830
  .review-prompt__submit:disabled {
851
831
  opacity: 0.5;
852
832
  cursor: not-allowed;
@@ -254,7 +254,6 @@
254
254
  .text-prompt__input:focus,
255
255
  .text-prompt__textarea:focus {
256
256
  border-color: var(--fd-interrupt-completed-border);
257
- box-shadow: 0 0 0 3px var(--fd-interrupt-completed-shadow);
258
257
  }
259
258
 
260
259
  .text-prompt__input:disabled,
@@ -316,11 +315,6 @@
316
315
  transform: translateY(-1px);
317
316
  }
318
317
 
319
- .text-prompt__submit:focus-visible {
320
- outline: 2px solid var(--fd-ring);
321
- outline-offset: 2px;
322
- }
323
-
324
318
  .text-prompt__submit:disabled {
325
319
  opacity: 0.5;
326
320
  cursor: not-allowed;
@@ -510,12 +510,12 @@
510
510
 
511
511
  .flowdrop-main-layout__sidebar::-webkit-scrollbar-track {
512
512
  background: var(--fd-scrollbar-track);
513
- border-radius: 4px;
513
+ border-radius: var(--fd-scrollbar-radius);
514
514
  }
515
515
 
516
516
  .flowdrop-main-layout__sidebar::-webkit-scrollbar-thumb {
517
517
  background: var(--fd-scrollbar-thumb);
518
- border-radius: 4px;
518
+ border-radius: var(--fd-scrollbar-radius);
519
519
  }
520
520
 
521
521
  .flowdrop-main-layout__sidebar::-webkit-scrollbar-thumb:hover {
@@ -585,7 +585,6 @@
585
585
  }
586
586
 
587
587
  .flowdrop-main-layout__divider:focus {
588
- outline: none;
589
588
  background-color: var(--fd-primary-muted);
590
589
  }
591
590
 
@@ -669,12 +668,12 @@
669
668
 
670
669
  .flowdrop-main-layout__panel--bottom::-webkit-scrollbar-track {
671
670
  background: var(--fd-scrollbar-track);
672
- border-radius: 4px;
671
+ border-radius: var(--fd-scrollbar-radius);
673
672
  }
674
673
 
675
674
  .flowdrop-main-layout__panel--bottom::-webkit-scrollbar-thumb {
676
675
  background: var(--fd-scrollbar-thumb);
677
- border-radius: 4px;
676
+ border-radius: var(--fd-scrollbar-radius);
678
677
  }
679
678
 
680
679
  .flowdrop-main-layout__panel--bottom::-webkit-scrollbar-thumb:hover {
@@ -141,7 +141,7 @@
141
141
  return { text: atomCfg.placeholder ?? '', empty: true };
142
142
  });
143
143
 
144
- // Pill height is content-driven (~28px), so fixed px offsets don't fit.
144
+ // Pill is a fixed 40px tall (20px grid), so a single port centers at 20px.
145
145
  // Distribute handles as a % of node height: 50% for one port, evenly otherwise.
146
146
  function portTopPct(index: number, count: number): number {
147
147
  return ((index + 1) / (count + 1)) * 100;
@@ -150,12 +150,6 @@
150
150
  function openConfig(): void {
151
151
  data.onConfigOpen?.({ id: nodeId, type: nodeType, data });
152
152
  }
153
- function handleKeydown(event: KeyboardEvent): void {
154
- if (event.key === 'Enter' || event.key === ' ') {
155
- event.preventDefault();
156
- openConfig();
157
- }
158
- }
159
153
  </script>
160
154
 
161
155
  {#each inPorts as port, index (port.id)}
@@ -170,6 +164,11 @@
170
164
  />
171
165
  {/each}
172
166
 
167
+ <!-- Presentational: focus, keyboard and selection live on xyflow's node wrapper
168
+ (see UniversalNode, which maps Enter/Space to opening config). click is a
169
+ mouse convenience. -->
170
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
171
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
173
172
  <div
174
173
  class="flowdrop-atom-node"
175
174
  class:flowdrop-atom-node--selected={selected}
@@ -179,14 +178,13 @@
179
178
  class:flowdrop-atom-node--rect={isRect}
180
179
  style={nodeStyle}
181
180
  onclick={openConfig}
182
- onkeydown={handleKeydown}
183
- role="button"
184
- tabindex="0"
185
181
  >
186
- {#if atomCfg.prefix && !display.empty}
187
- <span class="flowdrop-atom-node__prefix" aria-hidden="true">{atomCfg.prefix}</span>
188
- {/if}
189
- <span class="flowdrop-atom-node__body" title={display.text}>{display.text}</span>
182
+ <div class="flowdrop-atom-node__pill">
183
+ {#if atomCfg.prefix && !display.empty}
184
+ <span class="flowdrop-atom-node__prefix" aria-hidden="true">{atomCfg.prefix}</span>
185
+ {/if}
186
+ <span class="flowdrop-atom-node__body" title={display.text}>{display.text}</span>
187
+ </div>
190
188
  </div>
191
189
 
192
190
  {#each outPorts as port, index (port.id)}
@@ -202,54 +200,68 @@
202
200
  {/each}
203
201
 
204
202
  <style>
203
+ /* Transparent slot: defines the node's bounding box so handles anchor
204
+ consistently, while the pill sits narrow and vertically centered inside. */
205
205
  .flowdrop-atom-node {
206
206
  position: relative;
207
- display: inline-flex;
207
+ box-sizing: border-box;
208
+ display: flex;
208
209
  align-items: center;
210
+ justify-content: center;
209
211
  width: fit-content;
210
- min-width: 2rem;
211
- min-height: 28px;
212
- padding: 2px var(--fd-space-sm);
213
- background-color: var(--fd-card);
212
+ /* 40px tall → a single port centers at 20px (50%); capped at 60px / 120px. */
213
+ min-height: 40px;
214
+ max-height: 60px;
215
+ max-width: 120px;
216
+ cursor: pointer;
217
+ z-index: 10;
218
+ }
219
+
220
+ /* The visible, themed pill — hugs its text and stays compact. */
221
+ .flowdrop-atom-node__pill {
222
+ box-sizing: border-box;
223
+ display: inline-flex;
224
+ align-items: center;
225
+ max-width: 100%;
226
+ min-width: 32px;
227
+ padding: 4px 10px;
228
+ background-color: var(--fd-node-bg);
229
+ backdrop-filter: var(--fd-node-backdrop-filter);
214
230
  /* --fd-atom-node-color is set inline only when the server provides a color;
215
231
  otherwise it falls back to the neutral border token. */
216
- border: 1.5px solid var(--fd-atom-node-color, var(--fd-node-border));
232
+ border: var(--fd-node-border-width) solid var(--fd-atom-node-color, var(--fd-node-border));
217
233
  border-radius: 999px;
218
234
  box-shadow: var(--fd-shadow-sm);
219
235
  color: var(--fd-foreground);
220
- cursor: pointer;
221
236
  transition:
222
237
  box-shadow var(--fd-transition-fast),
223
238
  border-color var(--fd-transition-fast);
224
- z-index: 10;
225
239
  }
226
240
 
227
- .flowdrop-atom-node--rect {
241
+ .flowdrop-atom-node--rect .flowdrop-atom-node__pill {
228
242
  border-radius: var(--fd-radius-md);
229
243
  }
230
244
 
231
- .flowdrop-atom-node:hover {
232
- box-shadow: var(--fd-shadow-md);
245
+ .flowdrop-atom-node:hover .flowdrop-atom-node__pill {
246
+ box-shadow: var(--fd-node-shadow);
233
247
  border-color: var(--fd-atom-node-color, var(--fd-node-border-hover));
234
248
  }
235
249
 
236
- .flowdrop-atom-node--selected {
250
+ .flowdrop-atom-node--selected .flowdrop-atom-node__pill {
237
251
  box-shadow:
238
252
  0 0 0 2px color-mix(in srgb, var(--fd-atom-node-color, var(--fd-primary)) 30%, transparent),
239
- var(--fd-shadow-md);
253
+ var(--fd-node-shadow);
240
254
  border-color: var(--fd-atom-node-color, var(--fd-primary));
241
255
  }
242
256
 
243
- .flowdrop-atom-node:focus-visible {
244
- outline: 2px solid var(--fd-ring);
245
- outline-offset: 2px;
246
- }
257
+ /* Focus ring is centralized in base.css (drawn on the .svelte-flow__node
258
+ wrapper, which is the focusable element). */
247
259
 
248
260
  .flowdrop-atom-node--processing {
249
261
  opacity: 0.7;
250
262
  }
251
263
 
252
- .flowdrop-atom-node--error {
264
+ .flowdrop-atom-node--error .flowdrop-atom-node__pill {
253
265
  border-color: var(--fd-error) !important;
254
266
  background-color: var(--fd-error-muted) !important;
255
267
  }
@@ -264,14 +276,14 @@
264
276
  margin-right: 2px;
265
277
  color: var(--fd-muted-foreground);
266
278
  font-size: var(--fd-text-sm);
267
- line-height: 1.2;
279
+ line-height: 20px;
268
280
  }
269
281
 
270
282
  .flowdrop-atom-node__body {
271
283
  /* min-width:0 lets the body ellipsize as a flex sibling of the prefix */
272
284
  min-width: 0;
273
285
  font-size: var(--fd-text-sm);
274
- line-height: 1.2;
286
+ line-height: 20px;
275
287
  white-space: nowrap;
276
288
  overflow: hidden;
277
289
  text-overflow: ellipsis;