@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
@@ -0,0 +1,615 @@
1
+ <!--
2
+ Settings Panel Component
3
+
4
+ A comprehensive settings panel with tabbed categories for configuring
5
+ FlowDrop preferences. Uses SchemaForm for dynamic form generation.
6
+
7
+ Features:
8
+ - Tabbed interface for settings categories (Theme, Editor, UI, Behavior, API)
9
+ - Real-time settings updates via settingsStore
10
+ - Optional API sync with "Sync to Cloud" button
11
+ - Reset to defaults functionality
12
+
13
+ @example
14
+ ```svelte
15
+ <script>
16
+ import { SettingsPanel } from "@d34dman/flowdrop";
17
+ </script>
18
+
19
+ <SettingsPanel
20
+ showSyncButton={true}
21
+ onClose={() => console.log("Closed")}
22
+ />
23
+ ```
24
+ -->
25
+
26
+ <script lang="ts">
27
+ import Icon from '@iconify/svelte';
28
+ import { SchemaForm } from '../form/index.js';
29
+ import type { ConfigSchema } from '../types/index.js';
30
+ import type { SettingsCategory } from '../types/settings.js';
31
+ import {
32
+ SETTINGS_CATEGORIES,
33
+ SETTINGS_CATEGORY_LABELS,
34
+ SETTINGS_CATEGORY_ICONS
35
+ } from '../types/settings.js';
36
+ import {
37
+ settingsStore,
38
+ updateSettings,
39
+ resetSettings,
40
+ syncSettingsToApi,
41
+ syncStatusStore
42
+ } from '../stores/settingsStore.js';
43
+
44
+ /**
45
+ * Props interface for SettingsPanel component
46
+ */
47
+ interface Props {
48
+ /** Categories to display (defaults to all) */
49
+ categories?: SettingsCategory[];
50
+ /** Show the "Sync to Cloud" button */
51
+ showSyncButton?: boolean;
52
+ /** Show the reset button */
53
+ showResetButton?: boolean;
54
+ /** Callback when settings change */
55
+ onSettingsChange?: (category: SettingsCategory, values: Record<string, unknown>) => void;
56
+ /** Callback when close is requested */
57
+ onClose?: () => void;
58
+ /** Custom CSS class */
59
+ class?: string;
60
+ }
61
+
62
+ const {
63
+ categories = SETTINGS_CATEGORIES,
64
+ showSyncButton = true,
65
+ showResetButton = true,
66
+ onSettingsChange,
67
+ onClose,
68
+ class: className = ''
69
+ }: Props = $props();
70
+
71
+ /**
72
+ * Currently active tab
73
+ */
74
+ let activeTab = $state<SettingsCategory>(categories[0] ?? 'theme');
75
+
76
+ /**
77
+ * Whether sync is in progress
78
+ */
79
+ let isSyncing = $derived($syncStatusStore.status === 'syncing');
80
+
81
+ /**
82
+ * JSON Schema definitions for each settings category
83
+ */
84
+ const schemas: Record<SettingsCategory, ConfigSchema> = {
85
+ theme: {
86
+ type: 'object',
87
+ properties: {
88
+ preference: {
89
+ type: 'string',
90
+ title: 'Theme Preference',
91
+ description: 'Choose your preferred color scheme',
92
+ enum: ['light', 'dark', 'auto'],
93
+ enumLabels: ['Light', 'Dark', 'Auto (System)'],
94
+ default: 'auto'
95
+ }
96
+ }
97
+ },
98
+ editor: {
99
+ type: 'object',
100
+ properties: {
101
+ showGrid: {
102
+ type: 'boolean',
103
+ title: 'Show Grid',
104
+ description: 'Display grid lines on the canvas',
105
+ default: true
106
+ },
107
+ snapToGrid: {
108
+ type: 'boolean',
109
+ title: 'Snap to Grid',
110
+ description: 'Snap nodes to grid when dragging',
111
+ default: true
112
+ },
113
+ gridSize: {
114
+ type: 'number',
115
+ title: 'Grid Size',
116
+ description: 'Grid cell size in pixels',
117
+ minimum: 5,
118
+ maximum: 50,
119
+ default: 20
120
+ },
121
+ showMinimap: {
122
+ type: 'boolean',
123
+ title: 'Show Minimap',
124
+ description: 'Display navigation minimap',
125
+ default: true
126
+ },
127
+ defaultZoom: {
128
+ type: 'number',
129
+ title: 'Default Zoom',
130
+ description: 'Initial zoom level (1 = 100%)',
131
+ minimum: 0.25,
132
+ maximum: 2,
133
+ default: 1
134
+ },
135
+ fitViewOnLoad: {
136
+ type: 'boolean',
137
+ title: 'Fit View on Load',
138
+ description: 'Automatically fit workflow to view when loading',
139
+ default: true
140
+ }
141
+ }
142
+ },
143
+ ui: {
144
+ type: 'object',
145
+ properties: {
146
+ sidebarWidth: {
147
+ type: 'number',
148
+ title: 'Sidebar Width',
149
+ description: 'Width of the node sidebar in pixels',
150
+ minimum: 200,
151
+ maximum: 500,
152
+ default: 280
153
+ },
154
+ sidebarCollapsed: {
155
+ type: 'boolean',
156
+ title: 'Sidebar Collapsed',
157
+ description: 'Start with sidebar collapsed',
158
+ default: false
159
+ },
160
+ compactMode: {
161
+ type: 'boolean',
162
+ title: 'Compact Mode',
163
+ description: 'Use compact UI with smaller spacing',
164
+ default: false
165
+ }
166
+ }
167
+ },
168
+ behavior: {
169
+ type: 'object',
170
+ properties: {
171
+ autoSave: {
172
+ type: 'boolean',
173
+ title: 'Auto Save',
174
+ description: 'Automatically save changes',
175
+ default: false
176
+ },
177
+ autoSaveInterval: {
178
+ type: 'number',
179
+ title: 'Auto Save Interval',
180
+ description: 'Time between auto-saves in milliseconds',
181
+ minimum: 5000,
182
+ maximum: 300000,
183
+ default: 30000
184
+ },
185
+ undoHistoryLimit: {
186
+ type: 'number',
187
+ title: 'Undo History Limit',
188
+ description: 'Maximum number of undo steps',
189
+ minimum: 10,
190
+ maximum: 200,
191
+ default: 50
192
+ },
193
+ confirmDelete: {
194
+ type: 'boolean',
195
+ title: 'Confirm Delete',
196
+ description: 'Show confirmation before deleting nodes',
197
+ default: true
198
+ }
199
+ }
200
+ },
201
+ api: {
202
+ type: 'object',
203
+ properties: {
204
+ timeout: {
205
+ type: 'number',
206
+ title: 'Request Timeout',
207
+ description: 'API request timeout in milliseconds',
208
+ minimum: 5000,
209
+ maximum: 120000,
210
+ default: 30000
211
+ },
212
+ retryEnabled: {
213
+ type: 'boolean',
214
+ title: 'Enable Retry',
215
+ description: 'Automatically retry failed requests',
216
+ default: true
217
+ },
218
+ retryAttempts: {
219
+ type: 'number',
220
+ title: 'Retry Attempts',
221
+ description: 'Maximum number of retry attempts',
222
+ minimum: 1,
223
+ maximum: 10,
224
+ default: 3
225
+ },
226
+ cacheEnabled: {
227
+ type: 'boolean',
228
+ title: 'Enable Caching',
229
+ description: 'Cache API responses for better performance',
230
+ default: true
231
+ }
232
+ }
233
+ }
234
+ };
235
+
236
+ /**
237
+ * Get current values for a category from the store
238
+ */
239
+ function getCategoryValues(category: SettingsCategory): Record<string, unknown> {
240
+ const settings = $settingsStore;
241
+ const categorySettings = settings[category];
242
+ // Convert to Record<string, unknown> for SchemaForm compatibility
243
+ return Object.fromEntries(Object.entries(categorySettings));
244
+ }
245
+
246
+ /**
247
+ * Handle form value changes
248
+ */
249
+ function handleChange(category: SettingsCategory, values: Record<string, unknown>): void {
250
+ // Update the store
251
+ updateSettings({ [category]: values });
252
+
253
+ // Notify parent if callback provided
254
+ if (onSettingsChange) {
255
+ onSettingsChange(category, values);
256
+ }
257
+ }
258
+
259
+ /**
260
+ * Handle sync to cloud button click
261
+ */
262
+ async function handleSync(): Promise<void> {
263
+ try {
264
+ await syncSettingsToApi();
265
+ } catch (error) {
266
+ console.error('Failed to sync settings:', error);
267
+ }
268
+ }
269
+
270
+ /**
271
+ * Handle reset button click
272
+ */
273
+ function handleReset(): void {
274
+ if (confirm(`Reset ${SETTINGS_CATEGORY_LABELS[activeTab]} settings to defaults?`)) {
275
+ resetSettings([activeTab]);
276
+ }
277
+ }
278
+
279
+ /**
280
+ * Handle reset all button click
281
+ */
282
+ function handleResetAll(): void {
283
+ if (confirm('Reset all settings to defaults?')) {
284
+ resetSettings();
285
+ }
286
+ }
287
+
288
+ /**
289
+ * Handle tab keyboard navigation
290
+ */
291
+ function handleTabKeydown(event: KeyboardEvent, index: number): void {
292
+ const tabs = categories;
293
+ let newIndex = index;
294
+
295
+ switch (event.key) {
296
+ case 'ArrowLeft':
297
+ newIndex = index > 0 ? index - 1 : tabs.length - 1;
298
+ break;
299
+ case 'ArrowRight':
300
+ newIndex = index < tabs.length - 1 ? index + 1 : 0;
301
+ break;
302
+ case 'Home':
303
+ newIndex = 0;
304
+ break;
305
+ case 'End':
306
+ newIndex = tabs.length - 1;
307
+ break;
308
+ default:
309
+ return;
310
+ }
311
+
312
+ event.preventDefault();
313
+ activeTab = tabs[newIndex];
314
+
315
+ // Focus the new tab
316
+ const tabElement = document.querySelector(
317
+ `[data-tab="${tabs[newIndex]}"]`
318
+ ) as HTMLElement | null;
319
+ tabElement?.focus();
320
+ }
321
+ </script>
322
+
323
+ <div class="flowdrop-settings-panel {className}">
324
+ <!-- Tab Navigation -->
325
+ <div class="flowdrop-settings-panel__tabs" role="tablist" aria-label="Settings categories">
326
+ {#each categories as category, index (category)}
327
+ <button
328
+ class="flowdrop-settings-panel__tab"
329
+ class:flowdrop-settings-panel__tab--active={activeTab === category}
330
+ role="tab"
331
+ aria-selected={activeTab === category}
332
+ aria-controls="panel-{category}"
333
+ data-tab={category}
334
+ tabindex={activeTab === category ? 0 : -1}
335
+ onclick={() => (activeTab = category)}
336
+ onkeydown={(e) => handleTabKeydown(e, index)}
337
+ >
338
+ <Icon icon={SETTINGS_CATEGORY_ICONS[category]} class="flowdrop-settings-panel__tab-icon" />
339
+ <span class="flowdrop-settings-panel__tab-label">{SETTINGS_CATEGORY_LABELS[category]}</span>
340
+ </button>
341
+ {/each}
342
+ </div>
343
+
344
+ <!-- Tab Panels -->
345
+ <div class="flowdrop-settings-panel__content">
346
+ {#each categories as category (category)}
347
+ <div
348
+ id="panel-{category}"
349
+ class="flowdrop-settings-panel__panel"
350
+ class:flowdrop-settings-panel__panel--active={activeTab === category}
351
+ role="tabpanel"
352
+ aria-labelledby="tab-{category}"
353
+ hidden={activeTab !== category}
354
+ >
355
+ {#if activeTab === category}
356
+ <SchemaForm
357
+ schema={schemas[category]}
358
+ values={getCategoryValues(category)}
359
+ onChange={(values) => handleChange(category, values)}
360
+ showActions={false}
361
+ />
362
+ {/if}
363
+ </div>
364
+ {/each}
365
+ </div>
366
+
367
+ <!-- Footer Actions -->
368
+ <div class="flowdrop-settings-panel__footer">
369
+ <div class="flowdrop-settings-panel__footer-start">
370
+ {#if showResetButton}
371
+ <button
372
+ class="flowdrop-settings-panel__btn flowdrop-settings-panel__btn--outline"
373
+ onclick={handleReset}
374
+ title="Reset current category to defaults"
375
+ >
376
+ <Icon icon="mdi:refresh" />
377
+ <span>Reset</span>
378
+ </button>
379
+ <button
380
+ class="flowdrop-settings-panel__btn flowdrop-settings-panel__btn--ghost"
381
+ onclick={handleResetAll}
382
+ title="Reset all settings to defaults"
383
+ >
384
+ Reset All
385
+ </button>
386
+ {/if}
387
+ </div>
388
+
389
+ <div class="flowdrop-settings-panel__footer-end">
390
+ {#if showSyncButton}
391
+ <button
392
+ class="flowdrop-settings-panel__btn flowdrop-settings-panel__btn--secondary"
393
+ onclick={handleSync}
394
+ disabled={isSyncing}
395
+ title="Sync settings to cloud"
396
+ >
397
+ {#if isSyncing}
398
+ <Icon icon="mdi:loading" class="flowdrop-settings-panel__spin" />
399
+ <span>Syncing...</span>
400
+ {:else}
401
+ <Icon icon="mdi:cloud-upload" />
402
+ <span>Sync to Cloud</span>
403
+ {/if}
404
+ </button>
405
+ {/if}
406
+
407
+ {#if onClose}
408
+ <button
409
+ class="flowdrop-settings-panel__btn flowdrop-settings-panel__btn--primary"
410
+ onclick={onClose}
411
+ >
412
+ <span>Close</span>
413
+ </button>
414
+ {/if}
415
+ </div>
416
+ </div>
417
+
418
+ <!-- Sync Status Indicator -->
419
+ {#if $syncStatusStore.error}
420
+ <div class="flowdrop-settings-panel__error">
421
+ <Icon icon="mdi:alert-circle" />
422
+ <span>{$syncStatusStore.error}</span>
423
+ </div>
424
+ {:else if $syncStatusStore.status === 'synced' && $syncStatusStore.lastSyncedAt}
425
+ <div class="flowdrop-settings-panel__synced">
426
+ <Icon icon="mdi:check-circle" />
427
+ <span>Synced {new Date($syncStatusStore.lastSyncedAt).toLocaleTimeString()}</span>
428
+ </div>
429
+ {/if}
430
+ </div>
431
+
432
+ <style>
433
+ .flowdrop-settings-panel {
434
+ display: flex;
435
+ flex-direction: column;
436
+ height: 100%;
437
+ background-color: var(--fd-background);
438
+ color: var(--fd-foreground);
439
+ }
440
+
441
+ /* Tabs */
442
+ .flowdrop-settings-panel__tabs {
443
+ display: flex;
444
+ gap: var(--fd-space-1);
445
+ padding: var(--fd-space-3);
446
+ border-bottom: 1px solid var(--fd-border);
447
+ overflow-x: auto;
448
+ }
449
+
450
+ .flowdrop-settings-panel__tab {
451
+ display: flex;
452
+ align-items: center;
453
+ gap: var(--fd-space-2);
454
+ padding: var(--fd-space-2) var(--fd-space-3);
455
+ border: none;
456
+ border-radius: var(--fd-radius-md);
457
+ background-color: transparent;
458
+ color: var(--fd-muted-foreground);
459
+ font-size: var(--fd-text-sm);
460
+ font-weight: 500;
461
+ cursor: pointer;
462
+ transition: all var(--fd-transition-fast);
463
+ white-space: nowrap;
464
+ }
465
+
466
+ .flowdrop-settings-panel__tab:hover {
467
+ background-color: var(--fd-muted);
468
+ color: var(--fd-foreground);
469
+ }
470
+
471
+ .flowdrop-settings-panel__tab--active {
472
+ background-color: var(--fd-primary);
473
+ color: var(--fd-primary-foreground);
474
+ }
475
+
476
+ .flowdrop-settings-panel__tab--active:hover {
477
+ background-color: var(--fd-primary);
478
+ color: var(--fd-primary-foreground);
479
+ }
480
+
481
+ .flowdrop-settings-panel__tab:focus {
482
+ outline: none;
483
+ box-shadow: 0 0 0 2px var(--fd-ring);
484
+ }
485
+
486
+ :global(.flowdrop-settings-panel__tab-icon) {
487
+ font-size: var(--fd-text-base);
488
+ }
489
+
490
+ /* Content */
491
+ .flowdrop-settings-panel__content {
492
+ flex: 1;
493
+ overflow-y: auto;
494
+ padding: var(--fd-space-4);
495
+ }
496
+
497
+ .flowdrop-settings-panel__panel {
498
+ display: none;
499
+ }
500
+
501
+ .flowdrop-settings-panel__panel--active {
502
+ display: block;
503
+ }
504
+
505
+ /* Footer */
506
+ .flowdrop-settings-panel__footer {
507
+ display: flex;
508
+ justify-content: space-between;
509
+ align-items: center;
510
+ padding: var(--fd-space-3) var(--fd-space-4);
511
+ border-top: 1px solid var(--fd-border);
512
+ gap: var(--fd-space-3);
513
+ }
514
+
515
+ .flowdrop-settings-panel__footer-start,
516
+ .flowdrop-settings-panel__footer-end {
517
+ display: flex;
518
+ gap: var(--fd-space-2);
519
+ align-items: center;
520
+ }
521
+
522
+ /* Buttons */
523
+ .flowdrop-settings-panel__btn {
524
+ display: inline-flex;
525
+ align-items: center;
526
+ gap: var(--fd-space-2);
527
+ padding: var(--fd-space-2) var(--fd-space-3);
528
+ border-radius: var(--fd-radius-md);
529
+ font-size: var(--fd-text-sm);
530
+ font-weight: 500;
531
+ cursor: pointer;
532
+ transition: all var(--fd-transition-fast);
533
+ border: 1px solid transparent;
534
+ }
535
+
536
+ .flowdrop-settings-panel__btn:disabled {
537
+ opacity: 0.5;
538
+ cursor: not-allowed;
539
+ }
540
+
541
+ .flowdrop-settings-panel__btn--primary {
542
+ background-color: var(--fd-primary);
543
+ color: var(--fd-primary-foreground);
544
+ border-color: var(--fd-primary);
545
+ }
546
+
547
+ .flowdrop-settings-panel__btn--primary:hover:not(:disabled) {
548
+ opacity: 0.9;
549
+ }
550
+
551
+ .flowdrop-settings-panel__btn--secondary {
552
+ background-color: var(--fd-secondary);
553
+ color: var(--fd-secondary-foreground);
554
+ border-color: var(--fd-border);
555
+ }
556
+
557
+ .flowdrop-settings-panel__btn--secondary:hover:not(:disabled) {
558
+ background-color: var(--fd-muted);
559
+ }
560
+
561
+ .flowdrop-settings-panel__btn--outline {
562
+ background-color: transparent;
563
+ color: var(--fd-foreground);
564
+ border-color: var(--fd-border);
565
+ }
566
+
567
+ .flowdrop-settings-panel__btn--outline:hover:not(:disabled) {
568
+ background-color: var(--fd-muted);
569
+ }
570
+
571
+ .flowdrop-settings-panel__btn--ghost {
572
+ background-color: transparent;
573
+ color: var(--fd-muted-foreground);
574
+ border-color: transparent;
575
+ }
576
+
577
+ .flowdrop-settings-panel__btn--ghost:hover:not(:disabled) {
578
+ background-color: var(--fd-muted);
579
+ color: var(--fd-foreground);
580
+ }
581
+
582
+ /* Status Indicators */
583
+ .flowdrop-settings-panel__error,
584
+ .flowdrop-settings-panel__synced {
585
+ display: flex;
586
+ align-items: center;
587
+ gap: var(--fd-space-2);
588
+ padding: var(--fd-space-2) var(--fd-space-4);
589
+ font-size: var(--fd-text-xs);
590
+ }
591
+
592
+ .flowdrop-settings-panel__error {
593
+ background-color: var(--fd-destructive);
594
+ color: var(--fd-destructive-foreground);
595
+ }
596
+
597
+ .flowdrop-settings-panel__synced {
598
+ background-color: var(--fd-success, #22c55e);
599
+ color: white;
600
+ }
601
+
602
+ /* Spin Animation */
603
+ :global(.flowdrop-settings-panel__spin) {
604
+ animation: flowdrop-spin 1s linear infinite;
605
+ }
606
+
607
+ @keyframes flowdrop-spin {
608
+ from {
609
+ transform: rotate(0deg);
610
+ }
611
+ to {
612
+ transform: rotate(360deg);
613
+ }
614
+ }
615
+ </style>
@@ -0,0 +1,21 @@
1
+ import type { SettingsCategory } from '../types/settings.js';
2
+ /**
3
+ * Props interface for SettingsPanel component
4
+ */
5
+ interface Props {
6
+ /** Categories to display (defaults to all) */
7
+ categories?: SettingsCategory[];
8
+ /** Show the "Sync to Cloud" button */
9
+ showSyncButton?: boolean;
10
+ /** Show the reset button */
11
+ showResetButton?: boolean;
12
+ /** Callback when settings change */
13
+ onSettingsChange?: (category: SettingsCategory, values: Record<string, unknown>) => void;
14
+ /** Callback when close is requested */
15
+ onClose?: () => void;
16
+ /** Custom CSS class */
17
+ class?: string;
18
+ }
19
+ declare const SettingsPanel: import("svelte").Component<Props, {}, "">;
20
+ type SettingsPanel = ReturnType<typeof SettingsPanel>;
21
+ export default SettingsPanel;