@d34dman/flowdrop 0.0.43 → 0.0.44

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 (95) hide show
  1. package/README.md +8 -8
  2. package/dist/api/enhanced-client.d.ts +3 -1
  3. package/dist/api/enhanced-client.js +35 -5
  4. package/dist/components/App.svelte +68 -34
  5. package/dist/components/ConfigForm.svelte +169 -142
  6. package/dist/components/ConfigForm.svelte.d.ts +4 -2
  7. package/dist/components/ConfigPanel.svelte +42 -15
  8. package/dist/components/LogsSidebar.svelte +20 -19
  9. package/dist/components/Navbar.svelte +150 -80
  10. package/dist/components/Navbar.svelte.d.ts +8 -0
  11. package/dist/components/NodeSidebar.svelte +330 -217
  12. package/dist/components/PipelineStatus.svelte +6 -1
  13. package/dist/components/ReadOnlyDetails.svelte +14 -14
  14. package/dist/components/SchemaForm.svelte +49 -30
  15. package/dist/components/SchemaForm.svelte.d.ts +11 -1
  16. package/dist/components/SettingsModal.svelte +279 -0
  17. package/dist/components/SettingsModal.svelte.d.ts +23 -0
  18. package/dist/components/SettingsPanel.svelte +615 -0
  19. package/dist/components/SettingsPanel.svelte.d.ts +21 -0
  20. package/dist/components/ThemeToggle.svelte +186 -0
  21. package/dist/components/ThemeToggle.svelte.d.ts +14 -0
  22. package/dist/components/WorkflowEditor.svelte +110 -36
  23. package/dist/components/form/FormArray.svelte +81 -81
  24. package/dist/components/form/FormAutocomplete.svelte +1014 -0
  25. package/dist/components/form/FormAutocomplete.svelte.d.ts +25 -0
  26. package/dist/components/form/FormCheckboxGroup.svelte +16 -16
  27. package/dist/components/form/FormCodeEditor.svelte +26 -26
  28. package/dist/components/form/FormField.svelte +52 -21
  29. package/dist/components/form/FormFieldLight.svelte +19 -19
  30. package/dist/components/form/FormFieldWrapper.svelte +4 -4
  31. package/dist/components/form/FormMarkdownEditor.svelte +124 -57
  32. package/dist/components/form/FormNumberField.svelte +13 -13
  33. package/dist/components/form/FormRangeField.svelte +16 -16
  34. package/dist/components/form/FormSelect.svelte +15 -15
  35. package/dist/components/form/FormTemplateEditor.svelte +34 -34
  36. package/dist/components/form/FormTextField.svelte +13 -13
  37. package/dist/components/form/FormTextarea.svelte +13 -13
  38. package/dist/components/form/FormToggle.svelte +8 -8
  39. package/dist/components/form/index.d.ts +1 -0
  40. package/dist/components/form/index.js +1 -0
  41. package/dist/components/form/types.d.ts +133 -8
  42. package/dist/components/form/types.js +50 -1
  43. package/dist/components/interrupt/ChoicePrompt.svelte +45 -38
  44. package/dist/components/interrupt/ConfirmationPrompt.svelte +35 -35
  45. package/dist/components/interrupt/FormPrompt.svelte +27 -20
  46. package/dist/components/interrupt/InterruptBubble.svelte +50 -50
  47. package/dist/components/interrupt/TextInputPrompt.svelte +39 -32
  48. package/dist/components/layouts/MainLayout.svelte +233 -34
  49. package/dist/components/layouts/MainLayout.svelte.d.ts +12 -0
  50. package/dist/components/nodes/GatewayNode.svelte +102 -73
  51. package/dist/components/nodes/IdeaNode.svelte +53 -52
  52. package/dist/components/nodes/NotesNode.svelte +120 -88
  53. package/dist/components/nodes/SimpleNode.svelte +67 -47
  54. package/dist/components/nodes/SquareNode.svelte +86 -49
  55. package/dist/components/nodes/TerminalNode.svelte +122 -72
  56. package/dist/components/nodes/ToolNode.svelte +96 -65
  57. package/dist/components/nodes/WorkflowNode.svelte +91 -67
  58. package/dist/components/playground/ChatPanel.svelte +76 -76
  59. package/dist/components/playground/ExecutionLogs.svelte +71 -69
  60. package/dist/components/playground/InputCollector.svelte +59 -59
  61. package/dist/components/playground/MessageBubble.svelte +111 -112
  62. package/dist/components/playground/Playground.svelte +184 -138
  63. package/dist/components/playground/PlaygroundModal.svelte +18 -19
  64. package/dist/components/playground/SessionManager.svelte +68 -67
  65. package/dist/config/defaultPortConfig.js +22 -22
  66. package/dist/core/index.d.ts +2 -0
  67. package/dist/core/index.js +1 -0
  68. package/dist/form/fieldRegistry.d.ts +17 -1
  69. package/dist/form/fieldRegistry.js +18 -2
  70. package/dist/form/index.d.ts +20 -2
  71. package/dist/form/index.js +19 -1
  72. package/dist/helpers/workflowEditorHelper.js +23 -11
  73. package/dist/index.d.ts +5 -0
  74. package/dist/index.js +13 -0
  75. package/dist/services/autoSaveService.d.ts +112 -0
  76. package/dist/services/autoSaveService.js +223 -0
  77. package/dist/services/settingsService.d.ts +92 -0
  78. package/dist/services/settingsService.js +202 -0
  79. package/dist/services/toastService.d.ts +9 -0
  80. package/dist/services/toastService.js +30 -1
  81. package/dist/stores/settingsStore.d.ts +128 -0
  82. package/dist/stores/settingsStore.js +488 -0
  83. package/dist/stores/themeStore.d.ts +68 -0
  84. package/dist/stores/themeStore.js +215 -0
  85. package/dist/styles/base.css +298 -621
  86. package/dist/styles/toast.css +33 -0
  87. package/dist/styles/tokens.css +366 -0
  88. package/dist/types/index.d.ts +78 -0
  89. package/dist/types/index.js +2 -0
  90. package/dist/types/playground.d.ts +12 -0
  91. package/dist/types/settings.d.ts +185 -0
  92. package/dist/types/settings.js +101 -0
  93. package/dist/utils/colors.d.ts +100 -7
  94. package/dist/utils/colors.js +228 -67
  95. package/package.json +3 -3
@@ -11,6 +11,7 @@
11
11
  import { getNodeIcon, getCategoryIcon } from '../utils/icons.js';
12
12
  import { getCategoryColorToken } from '../utils/colors.js';
13
13
  import { SvelteSet } from 'svelte/reactivity';
14
+ import { uiSettings, updateSettings } from '../stores/settingsStore.js';
14
15
 
15
16
  interface Props {
16
17
  nodes: NodeMetadata[];
@@ -21,6 +22,14 @@
21
22
  let searchInput = $state('');
22
23
  let selectedCategory = $state(props.selectedCategory || 'all');
23
24
 
25
+ /**
26
+ * Toggle the sidebar collapsed state
27
+ * Persists the new state to settings
28
+ */
29
+ function toggleSidebar(): void {
30
+ updateSettings({ ui: { sidebarCollapsed: !$uiSettings.sidebarCollapsed } });
31
+ }
32
+
24
33
  let filteredNodes = $derived(getFilteredNodes());
25
34
  let categories = $derived(getCategories());
26
35
 
@@ -188,208 +197,226 @@
188
197
  </script>
189
198
 
190
199
  <!-- Components Sidebar - Always Visible -->
191
- <div
200
+ <aside
192
201
  class="flowdrop-sidebar flowdrop-sidebar--container"
193
- role="complementary"
202
+ class:flowdrop-sidebar--collapsed={$uiSettings.sidebarCollapsed}
203
+ class:flowdrop-sidebar--compact={$uiSettings.compactMode}
204
+ style:width="{$uiSettings.sidebarCollapsed ? 48 : $uiSettings.sidebarWidth}px"
194
205
  aria-label="Components sidebar"
195
206
  >
196
207
  <!-- Header -->
197
208
  <div class="flowdrop-sidebar__header">
198
- <div class="flowdrop-sidebar__title">
199
- <h2 class="flowdrop-text--lg flowdrop-font--bold">Components</h2>
200
- </div>
209
+ <button
210
+ class="flowdrop-sidebar__toggle"
211
+ onclick={toggleSidebar}
212
+ aria-label={$uiSettings.sidebarCollapsed ? 'Expand sidebar' : 'Collapse sidebar'}
213
+ title={$uiSettings.sidebarCollapsed ? 'Expand sidebar' : 'Collapse sidebar'}
214
+ >
215
+ <Icon icon={$uiSettings.sidebarCollapsed ? 'mdi:chevron-right' : 'mdi:chevron-left'} />
216
+ </button>
217
+ {#if !$uiSettings.sidebarCollapsed}
218
+ <div class="flowdrop-sidebar__title">
219
+ <h2 class="flowdrop-text--lg flowdrop-font--bold">Components</h2>
220
+ </div>
221
+ {/if}
201
222
  </div>
202
223
 
203
- <!-- Search Section -->
204
- <div class="flowdrop-sidebar__search">
205
- <div class="flowdrop-join flowdrop-w--full">
206
- <div class="flowdrop-join__item flowdrop-flex--1">
207
- <input
208
- type="text"
209
- placeholder="Search components..."
210
- class="flowdrop-input flowdrop-join__item flowdrop-w--full"
211
- bind:value={searchInput}
212
- oninput={handleSearchChange}
213
- />
224
+ {#if !$uiSettings.sidebarCollapsed}
225
+ <!-- Search Section -->
226
+ <div class="flowdrop-sidebar__search">
227
+ <div class="flowdrop-join flowdrop-w--full">
228
+ <div class="flowdrop-join__item flowdrop-flex--1">
229
+ <input
230
+ type="text"
231
+ placeholder="Search components..."
232
+ class="flowdrop-input flowdrop-join__item flowdrop-w--full"
233
+ bind:value={searchInput}
234
+ oninput={handleSearchChange}
235
+ />
236
+ </div>
237
+ <button class="flowdrop-btn flowdrop-join__item" aria-label="Search components">
238
+ <Icon icon="mdi:magnify" class="flowdrop-icon" />
239
+ </button>
214
240
  </div>
215
- <button class="flowdrop-btn flowdrop-join__item" aria-label="Search components">
216
- <Icon icon="mdi:magnify" class="flowdrop-icon" />
217
- </button>
218
241
  </div>
219
- </div>
220
242
 
221
- <!-- Node Types List -->
222
- <div class="flowdrop-sidebar__content">
223
- {#if props.nodes?.length === 0}
224
- <!-- No node types available -->
225
- <div class="flowdrop-hero">
226
- <div class="flowdrop-hero__content">
227
- <div class="flowdrop-hero__icon">📦</div>
228
- <h3 class="flowdrop-hero__title">No node types available</h3>
229
- <p class="flowdrop-hero__description">Node type definitions will appear here</p>
230
- <div class="flowdrop-mb--4">
231
- <LoadingSpinner size="md" text="Loading from server..." />
243
+ <!-- Node Types List -->
244
+ <div class="flowdrop-sidebar__content">
245
+ {#if props.nodes?.length === 0}
246
+ <!-- No node types available -->
247
+ <div class="flowdrop-hero">
248
+ <div class="flowdrop-hero__content">
249
+ <div class="flowdrop-hero__icon">📦</div>
250
+ <h3 class="flowdrop-hero__title">No node types available</h3>
251
+ <p class="flowdrop-hero__description">Node type definitions will appear here</p>
252
+ <div class="flowdrop-mb--4">
253
+ <LoadingSpinner size="md" text="Loading from server..." />
254
+ </div>
232
255
  </div>
233
256
  </div>
234
- </div>
235
- {:else if searchInput.trim()}
236
- <!-- Search Results -->
237
- <div class="flowdrop-p--4">
238
- <div class="flowdrop-divider">
239
- <h3 class="flowdrop-divider__text">Search Results</h3>
240
- </div>
241
- {#if filteredNodes.length === 0}
242
- <div class="flowdrop-hero">
243
- <div class="flowdrop-hero__content">
244
- <div class="flowdrop-hero__icon">🔍</div>
245
- <h3 class="flowdrop-hero__title">No components found</h3>
246
- <p class="flowdrop-hero__description">Try adjusting your search</p>
247
- {#if props.nodes?.length === 0}
248
- <div class="flowdrop-mb--4">
249
- <LoadingSpinner size="sm" text="Loading components..." />
250
- </div>
251
- {/if}
252
- </div>
257
+ {:else if searchInput.trim()}
258
+ <!-- Search Results -->
259
+ <div class="flowdrop-p--4">
260
+ <div class="flowdrop-divider">
261
+ <h3 class="flowdrop-divider__text">Search Results</h3>
253
262
  </div>
254
- {:else}
255
- <div class="flowdrop-node-list">
256
- {#each filteredNodes as nodeType (nodeType.id)}
257
- <div
258
- class="flowdrop-card flowdrop-card--compact flowdrop-node-item"
259
- draggable="true"
260
- ondragstart={(e) => handleNodeDragStart(e, nodeType)}
261
- role="button"
262
- tabindex="0"
263
- >
264
- <div class="flowdrop-card__body flowdrop-p--1 flowdrop-py--1">
265
- <div class="flowdrop-flex flowdrop-gap--2 flowdrop-items--center">
266
- <!-- Node Type Icon -->
267
- <div
268
- class="flowdrop-node-icon"
269
- style="background-color: {getCategoryColorToken(nodeType.category)}"
270
- >
271
- <Icon icon={getNodeIcon(nodeType.icon, nodeType.category)} />
272
- </div>
273
-
274
- <!-- Node Type Info - Icon and Title only -->
275
- <h4
276
- class="flowdrop-text--sm flowdrop-font--medium flowdrop-truncate flowdrop-flex--1"
277
- >
278
- {nodeType.name}
279
- </h4>
263
+ {#if filteredNodes.length === 0}
264
+ <div class="flowdrop-hero">
265
+ <div class="flowdrop-hero__content">
266
+ <div class="flowdrop-hero__icon">🔍</div>
267
+ <h3 class="flowdrop-hero__title">No components found</h3>
268
+ <p class="flowdrop-hero__description">Try adjusting your search</p>
269
+ {#if props.nodes?.length === 0}
270
+ <div class="flowdrop-mb--4">
271
+ <LoadingSpinner size="sm" text="Loading components..." />
280
272
  </div>
281
- <p
282
- class="flowdrop-text--xs flowdrop-text--gray flowdrop-truncate flowdrop-mt--1 flowdrop-ml--0"
283
- >
284
- {nodeType.description}
285
- </p>
286
- </div>
273
+ {/if}
287
274
  </div>
288
- {/each}
289
- </div>
290
- {/if}
291
- </div>
292
- {:else}
293
- <!-- Show categories with details when no search is active -->
294
- <div class="flowdrop-p--4">
295
- <!-- Category-specific details -->
296
- <div class="flowdrop-category-list">
297
- {#each categories as category (category)}
298
- {@const categoryNodes = getFilteredNodesForCategory(category)}
299
- {#if categoryNodes.length > 0}
300
- <details class="flowdrop-details">
301
- <summary class="flowdrop-details__summary">
302
- <div class="flowdrop-flex flowdrop-gap--2 flowdrop-items--center">
303
- <span
304
- class="flowdrop-node-icon"
305
- style="background-color: {getCategoryColorToken(category)}"
275
+ </div>
276
+ {:else}
277
+ <div class="flowdrop-node-list">
278
+ {#each filteredNodes as nodeType (nodeType.id)}
279
+ <div
280
+ class="flowdrop-card flowdrop-card--compact flowdrop-node-item"
281
+ draggable="true"
282
+ ondragstart={(e) => handleNodeDragStart(e, nodeType)}
283
+ role="button"
284
+ tabindex="0"
285
+ >
286
+ <div class="flowdrop-card__body flowdrop-p--1 flowdrop-py--1">
287
+ <div class="flowdrop-flex flowdrop-gap--2 flowdrop-items--center">
288
+ <!-- Node Type Icon with Squircle Background -->
289
+ <span
290
+ class="flowdrop-node-icon"
291
+ style="--_icon-color: {getCategoryColorToken(nodeType.category)}"
292
+ >
293
+ <Icon icon={getNodeIcon(nodeType.icon, nodeType.category)} />
294
+ </span>
295
+
296
+ <!-- Node Type Info - Icon and Title only -->
297
+ <h4
298
+ class="flowdrop-text--sm flowdrop-font--medium flowdrop-truncate flowdrop-flex--1"
299
+ >
300
+ {nodeType.name}
301
+ </h4>
302
+ </div>
303
+ <p
304
+ class="flowdrop-text--xs flowdrop-text--gray flowdrop-truncate flowdrop-mt--1 flowdrop-ml--0"
306
305
  >
307
- <Icon icon={getCategoryIcon(category)} />
308
- </span>
309
- <span>{getCategoryDisplayName(category)}</span>
306
+ {nodeType.description}
307
+ </p>
310
308
  </div>
311
- <div class="flowdrop-badge flowdrop-badge--secondary">{categoryNodes.length}</div>
312
- </summary>
313
- <div class="flowdrop-details__content">
314
- <div class="flowdrop-node-list">
315
- {#each categoryNodes as nodeType (nodeType.id)}
316
- <div
317
- class="flowdrop-card flowdrop-card--compact flowdrop-node-item"
318
- draggable="true"
319
- ondragstart={(e) => handleNodeDragStart(e, nodeType)}
320
- onclick={() => handleNodeClick(nodeType)}
321
- role="button"
322
- tabindex="0"
323
- onkeydown={(e) => {
324
- if (e.key === 'Enter' || e.key === ' ') {
325
- e.preventDefault();
326
- handleNodeClick(nodeType);
327
- }
328
- }}
309
+ </div>
310
+ {/each}
311
+ </div>
312
+ {/if}
313
+ </div>
314
+ {:else}
315
+ <!-- Show categories with details when no search is active -->
316
+ <div class="flowdrop-p--4">
317
+ <!-- Category-specific details -->
318
+ <div class="flowdrop-category-list">
319
+ {#each categories as category (category)}
320
+ {@const categoryNodes = getFilteredNodesForCategory(category)}
321
+ {#if categoryNodes.length > 0}
322
+ <details class="flowdrop-details">
323
+ <summary class="flowdrop-details__summary">
324
+ <div class="flowdrop-flex flowdrop-gap--2 flowdrop-items--center">
325
+ <span
326
+ class="flowdrop-node-icon"
327
+ style="--_icon-color: {getCategoryColorToken(category)}"
329
328
  >
330
- <div class="flowdrop-card__body flowdrop-p--1 flowdrop-py--1">
331
- <div class="flowdrop-flex flowdrop-gap--2 flowdrop-items--center">
332
- <!-- Node Type Icon -->
333
- <div
334
- class="flowdrop-node-icon"
335
- style="background-color: {getCategoryColorToken(nodeType.category)}"
336
- >
337
- <Icon icon={getNodeIcon(nodeType.icon, nodeType.category)} />
329
+ <Icon icon={getCategoryIcon(category)} />
330
+ </span>
331
+ <span>{getCategoryDisplayName(category)}</span>
332
+ </div>
333
+ <div class="flowdrop-badge flowdrop-badge--secondary">
334
+ {categoryNodes.length}
335
+ </div>
336
+ </summary>
337
+ <div class="flowdrop-details__content">
338
+ <div class="flowdrop-node-list">
339
+ {#each categoryNodes as nodeType (nodeType.id)}
340
+ <div
341
+ class="flowdrop-card flowdrop-card--compact flowdrop-node-item"
342
+ draggable="true"
343
+ ondragstart={(e) => handleNodeDragStart(e, nodeType)}
344
+ onclick={() => handleNodeClick(nodeType)}
345
+ role="button"
346
+ tabindex="0"
347
+ onkeydown={(e) => {
348
+ if (e.key === 'Enter' || e.key === ' ') {
349
+ e.preventDefault();
350
+ handleNodeClick(nodeType);
351
+ }
352
+ }}
353
+ >
354
+ <div class="flowdrop-card__body flowdrop-p--1 flowdrop-py--1">
355
+ <div class="flowdrop-flex flowdrop-gap--2 flowdrop-items--center">
356
+ <!-- Node Type Icon with Squircle Background -->
357
+ <span
358
+ class="flowdrop-node-icon"
359
+ style="--_icon-color: {getCategoryColorToken(nodeType.category)}"
360
+ >
361
+ <Icon icon={getNodeIcon(nodeType.icon, nodeType.category)} />
362
+ </span>
363
+
364
+ <!-- Node Type Info - Icon and Title only -->
365
+ <h4
366
+ class="flowdrop-text--sm flowdrop-font--medium flowdrop-truncate flowdrop-flex--1"
367
+ >
368
+ {nodeType.name}
369
+ </h4>
338
370
  </div>
339
-
340
- <!-- Node Type Info - Icon and Title only -->
341
- <h4
342
- class="flowdrop-text--sm flowdrop-font--medium flowdrop-truncate flowdrop-flex--1"
371
+ <p
372
+ class="flowdrop-text--xs flowdrop-text--gray flowdrop-truncate flowdrop-mt--1 flowdrop-ml--0"
343
373
  >
344
- {nodeType.name}
345
- </h4>
374
+ {nodeType.description}
375
+ </p>
346
376
  </div>
347
- <p
348
- class="flowdrop-text--xs flowdrop-text--gray flowdrop-truncate flowdrop-mt--1 flowdrop-ml--0"
349
- >
350
- {nodeType.description}
351
- </p>
352
377
  </div>
353
- </div>
354
- {/each}
378
+ {/each}
379
+ </div>
355
380
  </div>
356
- </div>
357
- </details>
358
- {/if}
359
- {/each}
381
+ </details>
382
+ {/if}
383
+ {/each}
384
+ </div>
360
385
  </div>
361
- </div>
362
- {/if}
363
- </div>
386
+ {/if}
387
+ </div>
364
388
 
365
- <!-- Footer -->
366
- <div class="flowdrop-sidebar__footer">
367
- <div class="flowdrop-flex flowdrop-gap--4">
389
+ <!-- Footer -->
390
+ <div class="flowdrop-sidebar__footer">
368
391
  <div class="flowdrop-flex flowdrop-gap--4">
369
- {#if props.nodes?.length === 0}
370
- <span class="flowdrop-text--xs flowdrop-text--gray">Loading components...</span>
371
- {:else}
372
- <span class="flowdrop-text--xs flowdrop-text--gray"
373
- >Total: {props.nodes?.length || 0} components</span
374
- >
375
- <span class="flowdrop-text--xs flowdrop-text--gray">Showing: {filteredNodes.length}</span>
376
- {/if}
392
+ <div class="flowdrop-flex flowdrop-gap--4">
393
+ {#if props.nodes?.length === 0}
394
+ <span class="flowdrop-text--xs flowdrop-text--gray">Loading components...</span>
395
+ {:else}
396
+ <span class="flowdrop-text--xs flowdrop-text--gray"
397
+ >Total: {props.nodes?.length || 0} components</span
398
+ >
399
+ <span class="flowdrop-text--xs flowdrop-text--gray"
400
+ >Showing: {filteredNodes.length}</span
401
+ >
402
+ {/if}
403
+ </div>
377
404
  </div>
378
405
  </div>
379
- </div>
380
- </div>
406
+ {/if}
407
+ </aside>
381
408
 
382
409
  <style>
383
410
  /* Components Sidebar - Always Visible */
384
411
  .flowdrop-sidebar {
385
- width: 320px;
386
- height: calc(100vh - var(--flowdrop-navbar-height, 60px)); /* Account for navbar height */
387
- background-color: #ffffff;
388
- border-right: 1px solid #e5e7eb;
412
+ height: calc(100vh - var(--fd-navbar-height)); /* Account for navbar height */
413
+ background-color: var(--fd-background);
414
+ border-right: 1px solid var(--fd-border);
389
415
  display: flex;
390
416
  flex-direction: column;
391
- box-shadow: 2px 0 8px rgba(0, 0, 0, 0.1);
417
+ box-shadow: var(--fd-shadow-md);
392
418
  flex-shrink: 0;
419
+ transition: width 0.2s ease;
393
420
  }
394
421
 
395
422
  .flowdrop-sidebar--container {
@@ -398,9 +425,79 @@
398
425
  height: 100%;
399
426
  }
400
427
 
428
+ /* Collapsed state */
429
+ .flowdrop-sidebar--collapsed {
430
+ overflow: hidden;
431
+ }
432
+
433
+ .flowdrop-sidebar--collapsed .flowdrop-sidebar__header {
434
+ justify-content: center;
435
+ padding: 0.75rem 0.5rem;
436
+ }
437
+
438
+ /* Compact mode styles */
439
+ .flowdrop-sidebar--compact .flowdrop-sidebar__header {
440
+ padding: 0.5rem 0.75rem;
441
+ }
442
+
443
+ .flowdrop-sidebar--compact .flowdrop-sidebar__search {
444
+ padding: 0.5rem 0.75rem;
445
+ }
446
+
447
+ .flowdrop-sidebar--compact .flowdrop-sidebar__content {
448
+ padding-bottom: 2rem;
449
+ }
450
+
451
+ .flowdrop-sidebar--compact .flowdrop-sidebar__footer {
452
+ padding: 0.375rem 0.5rem;
453
+ height: 32px;
454
+ }
455
+
456
+ .flowdrop-sidebar--compact .flowdrop-node-icon {
457
+ width: 1.5rem;
458
+ height: 1.5rem;
459
+ font-size: var(--fd-text-xs);
460
+ }
461
+
462
+ .flowdrop-sidebar--compact .flowdrop-node-list {
463
+ gap: 0.25rem;
464
+ }
465
+
466
+ .flowdrop-sidebar--compact .flowdrop-category-list {
467
+ gap: 0.25rem;
468
+ }
469
+
470
+ /* Toggle button */
471
+ .flowdrop-sidebar__toggle {
472
+ display: flex;
473
+ align-items: center;
474
+ justify-content: center;
475
+ width: 2rem;
476
+ height: 2rem;
477
+ border: none;
478
+ background: transparent;
479
+ color: var(--fd-muted-foreground);
480
+ border-radius: var(--fd-radius-md);
481
+ cursor: pointer;
482
+ transition:
483
+ color var(--fd-transition-fast),
484
+ background-color var(--fd-transition-fast);
485
+ flex-shrink: 0;
486
+ }
487
+
488
+ .flowdrop-sidebar__toggle:hover {
489
+ color: var(--fd-foreground);
490
+ background-color: var(--fd-subtle);
491
+ }
492
+
493
+ .flowdrop-sidebar__toggle:focus {
494
+ outline: none;
495
+ box-shadow: 0 0 0 2px var(--fd-ring);
496
+ }
497
+
401
498
  .flowdrop-sidebar__header {
402
- background-color: #f8fafc;
403
- border-bottom: 1px solid #e5e7eb;
499
+ background: var(--fd-header);
500
+ border-bottom: 1px solid var(--fd-border);
404
501
  padding: 0.75rem 1rem;
405
502
  display: flex;
406
503
  align-items: center;
@@ -419,19 +516,20 @@
419
516
  font-size: 1rem;
420
517
  font-weight: 600;
421
518
  margin: 0;
519
+ color: var(--fd-foreground);
422
520
  }
423
521
 
424
522
  .flowdrop-sidebar__search {
425
523
  padding: 0.75rem 1rem;
426
- background-color: #ffffff;
427
- border-bottom: 1px solid #e5e7eb;
524
+ background-color: var(--fd-background);
525
+ border-bottom: 1px solid var(--fd-border);
428
526
  }
429
527
 
430
528
  .flowdrop-sidebar__content {
431
529
  flex: 1;
432
530
  overflow-y: scroll; /* Changed from auto to scroll to always show scrollbar */
433
531
  scrollbar-width: thin;
434
- scrollbar-color: #d1d5db #f3f4f6;
532
+ scrollbar-color: var(--fd-scrollbar-thumb) var(--fd-scrollbar-track);
435
533
  padding-bottom: 4rem; /* Add padding to ensure content is scrollable above footer */
436
534
  min-height: 0; /* Allow flex item to shrink below content size */
437
535
  }
@@ -442,23 +540,23 @@
442
540
  }
443
541
 
444
542
  .flowdrop-sidebar__content::-webkit-scrollbar-track {
445
- background: #f3f4f6;
543
+ background: var(--fd-scrollbar-track);
446
544
  }
447
545
 
448
546
  .flowdrop-sidebar__content::-webkit-scrollbar-thumb {
449
- background: #d1d5db;
547
+ background: var(--fd-scrollbar-thumb);
450
548
  border-radius: 4px;
451
549
  min-height: 20px; /* Ensure thumb has minimum height for visibility */
452
550
  }
453
551
 
454
552
  .flowdrop-sidebar__content::-webkit-scrollbar-thumb:hover {
455
- background: #9ca3af;
553
+ background: var(--fd-scrollbar-thumb-hover);
456
554
  }
457
555
 
458
556
  .flowdrop-sidebar__footer {
459
- background-color: rgba(255, 255, 255, 0.8);
460
- backdrop-filter: blur(8px);
461
- border-top: 1px solid #e5e7eb;
557
+ background-color: var(--fd-backdrop);
558
+ backdrop-filter: var(--fd-backdrop-blur);
559
+ border-top: 1px solid var(--fd-border);
462
560
  padding: 0.5rem 0.75rem;
463
561
  flex-shrink: 0; /* Prevent footer from shrinking */
464
562
  position: relative;
@@ -476,30 +574,44 @@
476
574
 
477
575
  .flowdrop-node-item {
478
576
  cursor: grab;
479
- transition: all 0.2s ease-in-out;
480
- border-radius: 0.375rem;
577
+ transition: all var(--fd-transition-fast);
578
+ border-radius: var(--fd-radius-md);
481
579
  border: 1px solid transparent;
580
+ background-color: var(--fd-card);
482
581
  }
483
582
 
484
583
  .flowdrop-node-item:hover {
485
- border-color: #d1d5db;
486
- background-color: #f9fafb;
584
+ border-color: var(--fd-border);
585
+ background-color: var(--fd-muted);
586
+ box-shadow: var(--fd-shadow-sm);
587
+ transform: translateY(-1px);
487
588
  }
488
589
 
489
590
  .flowdrop-node-item:active {
490
591
  cursor: grabbing;
592
+ transform: translateY(0);
593
+ box-shadow: none;
491
594
  }
492
595
 
596
+ /* Squircle icon wrapper - Apple-style rounded square background */
493
597
  .flowdrop-node-icon {
494
598
  width: 2rem;
495
599
  height: 2rem;
496
- border-radius: 0.375rem;
497
- color: #ffffff;
498
- font-size: 0.875rem;
600
+ border-radius: 0.5rem;
601
+ background: color-mix(in srgb, var(--_icon-color) 15%, transparent);
602
+ color: var(--fd-node-icon);
603
+ font-size: var(--fd-text-sm);
499
604
  display: flex;
500
605
  align-items: center;
501
606
  justify-content: center;
502
607
  flex-shrink: 0;
608
+ transition: all var(--fd-transition-normal);
609
+ }
610
+
611
+ .flowdrop-node-item:hover .flowdrop-node-icon,
612
+ .flowdrop-details__summary:hover .flowdrop-node-icon {
613
+ background: color-mix(in srgb, var(--_icon-color) 22%, transparent);
614
+ transform: scale(1.05);
503
615
  }
504
616
 
505
617
  .flowdrop-category-list {
@@ -521,6 +633,7 @@
521
633
  .flowdrop-card__body h4 {
522
634
  margin: 0;
523
635
  line-height: 1;
636
+ color: var(--fd-foreground);
524
637
  }
525
638
 
526
639
  .flowdrop-p--4 {
@@ -539,14 +652,14 @@
539
652
  /* Form Elements - Matching App Design System */
540
653
  .flowdrop-input {
541
654
  padding: 0.625rem 0.75rem;
542
- border: 1px solid #d1d5db;
543
- border-radius: 0.375rem;
544
- font-size: 0.875rem;
545
- color: #111827;
546
- background-color: #ffffff;
655
+ border: 1px solid var(--fd-border-strong);
656
+ border-radius: var(--fd-radius-md);
657
+ font-size: var(--fd-text-sm);
658
+ color: var(--fd-foreground);
659
+ background-color: var(--fd-background);
547
660
  transition:
548
- border-color 0.2s ease-in-out,
549
- box-shadow 0.2s ease-in-out;
661
+ border-color var(--fd-transition-normal),
662
+ box-shadow var(--fd-transition-normal);
550
663
  width: 100%;
551
664
  height: 2.5rem;
552
665
  box-sizing: border-box;
@@ -554,51 +667,51 @@
554
667
 
555
668
  .flowdrop-input:focus {
556
669
  outline: none;
557
- border-color: #6b7280;
558
- box-shadow: 0 0 0 3px rgba(107, 114, 128, 0.1);
670
+ border-color: var(--fd-ring);
671
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--fd-ring) 20%, transparent);
559
672
  }
560
673
 
561
674
  .flowdrop-input::placeholder {
562
- color: #9ca3af;
675
+ color: var(--fd-muted-foreground);
563
676
  }
564
677
 
565
678
  .flowdrop-btn {
566
679
  padding: 0.625rem 0.75rem;
567
- border-radius: 0.375rem;
568
- font-size: 0.875rem;
680
+ border-radius: var(--fd-radius-md);
681
+ font-size: var(--fd-text-sm);
569
682
  font-weight: 500;
570
683
  cursor: pointer;
571
- transition: all 0.2s ease-in-out;
572
- border: 1px solid #d1d5db;
684
+ transition: all var(--fd-transition-normal);
685
+ border: 1px solid var(--fd-border-strong);
573
686
  display: flex;
574
687
  align-items: center;
575
688
  justify-content: center;
576
689
  gap: 0.5rem;
577
- background-color: #f9fafb;
578
- color: #374151;
690
+ background-color: var(--fd-muted);
691
+ color: var(--fd-foreground);
579
692
  height: 2.5rem;
580
693
  min-width: 2.5rem;
581
694
  box-sizing: border-box;
582
695
  }
583
696
 
584
697
  .flowdrop-btn:hover {
585
- background-color: #f3f4f6;
586
- border-color: #9ca3af;
698
+ background-color: var(--fd-subtle);
699
+ border-color: var(--fd-border-strong);
587
700
  }
588
701
 
589
702
  .flowdrop-btn:active {
590
- background-color: #e5e7eb;
591
- border-color: #6b7280;
703
+ background-color: var(--fd-border);
704
+ border-color: var(--fd-muted-foreground);
592
705
  }
593
706
 
594
707
  .flowdrop-btn:focus {
595
708
  outline: none;
596
- box-shadow: 0 0 0 3px rgba(107, 114, 128, 0.1);
709
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--fd-ring) 20%, transparent);
597
710
  }
598
711
 
599
712
  .flowdrop-btn:disabled {
600
- background-color: #9ca3af;
601
- border-color: #9ca3af;
713
+ background-color: var(--fd-muted-foreground);
714
+ border-color: var(--fd-muted-foreground);
602
715
  cursor: not-allowed;
603
716
  opacity: 0.6;
604
717
  }
@@ -607,10 +720,10 @@
607
720
  .flowdrop-join {
608
721
  display: flex;
609
722
  width: 100%;
610
- border-radius: 0.375rem;
723
+ border-radius: var(--fd-radius-md);
611
724
  overflow: hidden;
612
- border: 1px solid #d1d5db;
613
- background-color: #ffffff;
725
+ border: 1px solid var(--fd-border-strong);
726
+ background-color: var(--fd-background);
614
727
  }
615
728
 
616
729
  .flowdrop-join__item {
@@ -620,23 +733,23 @@
620
733
  }
621
734
 
622
735
  .flowdrop-join__item:first-child {
623
- border-right: 1px solid #d1d5db;
736
+ border-right: 1px solid var(--fd-border-strong);
624
737
  flex: 1;
625
738
  }
626
739
 
627
740
  .flowdrop-join__item:last-child {
628
741
  border-left: none;
629
- background-color: #f9fafb;
630
- color: #374151;
742
+ background-color: var(--fd-muted);
743
+ color: var(--fd-foreground);
631
744
  }
632
745
 
633
746
  .flowdrop-join__item:last-child:hover {
634
- background-color: #f3f4f6;
747
+ background-color: var(--fd-subtle);
635
748
  }
636
749
 
637
750
  .flowdrop-join:focus-within {
638
- border-color: #6b7280;
639
- box-shadow: 0 0 0 3px rgba(107, 114, 128, 0.1);
751
+ border-color: var(--fd-ring);
752
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--fd-ring) 20%, transparent);
640
753
  }
641
754
 
642
755
  /* Utility classes */