@d34dman/flowdrop 0.0.1 → 0.0.2

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 (119) hide show
  1. package/README.md +307 -215
  2. package/dist/adapters/WorkflowAdapter.d.ts +1 -1
  3. package/dist/adapters/WorkflowAdapter.js +30 -30
  4. package/dist/api/client.d.ts +24 -1
  5. package/dist/api/client.js +55 -38
  6. package/dist/api/enhanced-client.d.ts +46 -0
  7. package/dist/api/enhanced-client.js +211 -0
  8. package/dist/clients/ApiClient.d.ts +19 -23
  9. package/dist/clients/ApiClient.js +36 -34
  10. package/dist/components/App.svelte +1299 -230
  11. package/dist/components/App.svelte.d.ts +21 -1
  12. package/dist/components/CanvasBanner.svelte +50 -44
  13. package/dist/components/CanvasBanner.svelte.d.ts +5 -19
  14. package/dist/components/ConfigForm.svelte +555 -0
  15. package/dist/components/ConfigForm.svelte.d.ts +32 -0
  16. package/dist/components/ConfigModal.svelte +261 -0
  17. package/dist/components/ConfigModal.svelte.d.ts +31 -0
  18. package/dist/components/ConfigSidebar.svelte +934 -0
  19. package/dist/components/ConfigSidebar.svelte.d.ts +51 -0
  20. package/dist/components/ConnectionLine.svelte +32 -0
  21. package/dist/components/ConnectionLine.svelte.d.ts +3 -0
  22. package/dist/components/GatewayNode.svelte +471 -0
  23. package/dist/components/GatewayNode.svelte.d.ts +15 -0
  24. package/dist/components/LoadingSpinner.svelte +23 -23
  25. package/dist/components/LoadingSpinner.svelte.d.ts +1 -1
  26. package/dist/components/Logo.svelte +82 -0
  27. package/dist/components/Logo.svelte.d.ts +26 -0
  28. package/dist/components/LogsSidebar.svelte +565 -0
  29. package/dist/components/LogsSidebar.svelte.d.ts +34 -0
  30. package/dist/components/MarkdownDisplay.svelte +28 -0
  31. package/dist/components/MarkdownDisplay.svelte.d.ts +7 -0
  32. package/dist/components/Navbar.svelte +663 -0
  33. package/dist/components/Navbar.svelte.d.ts +21 -0
  34. package/dist/components/NodeSidebar.svelte +629 -488
  35. package/dist/components/NodeSidebar.svelte.d.ts +1 -2
  36. package/dist/components/NodeStatusOverlay.svelte +327 -0
  37. package/dist/components/NodeStatusOverlay.svelte.d.ts +11 -0
  38. package/dist/components/NotesNode.svelte +566 -0
  39. package/dist/components/NotesNode.svelte.d.ts +43 -0
  40. package/dist/components/PipelineStatus.svelte +331 -0
  41. package/dist/components/PipelineStatus.svelte.d.ts +18 -0
  42. package/dist/components/SimpleNode.svelte +447 -0
  43. package/dist/components/SimpleNode.svelte.d.ts +24 -0
  44. package/dist/components/SquareNode.svelte +346 -0
  45. package/dist/components/SquareNode.svelte.d.ts +24 -0
  46. package/dist/components/StatusIcon.svelte +112 -0
  47. package/dist/components/StatusIcon.svelte.d.ts +10 -0
  48. package/dist/components/StatusLabel.svelte +33 -0
  49. package/dist/components/StatusLabel.svelte.d.ts +7 -0
  50. package/dist/components/ToolNode.svelte +385 -0
  51. package/dist/components/ToolNode.svelte.d.ts +36 -0
  52. package/dist/components/UniversalNode.svelte +126 -0
  53. package/dist/components/UniversalNode.svelte.d.ts +15 -0
  54. package/dist/components/WorkflowEditor.svelte +871 -528
  55. package/dist/components/WorkflowEditor.svelte.d.ts +15 -5
  56. package/dist/components/WorkflowNode.svelte +428 -542
  57. package/dist/components/WorkflowNode.svelte.d.ts +7 -3
  58. package/dist/config/apiConfig.d.ts +33 -0
  59. package/dist/config/apiConfig.js +39 -0
  60. package/dist/config/defaultPortConfig.d.ts +6 -0
  61. package/dist/config/defaultPortConfig.js +192 -0
  62. package/dist/config/demo.d.ts +58 -0
  63. package/dist/config/demo.js +142 -0
  64. package/dist/config/endpoints.d.ts +106 -0
  65. package/dist/config/endpoints.js +128 -0
  66. package/dist/data/samples.d.ts +38 -4
  67. package/dist/data/samples.js +2789 -737
  68. package/dist/examples/adapter-usage.d.ts +4 -4
  69. package/dist/examples/adapter-usage.js +21 -26
  70. package/dist/examples/api-client-usage.d.ts +6 -6
  71. package/dist/examples/api-client-usage.js +55 -54
  72. package/dist/index.d.ts +23 -15
  73. package/dist/index.js +23 -15
  74. package/dist/mocks/app-environment.d.ts +8 -0
  75. package/dist/mocks/app-environment.js +16 -0
  76. package/dist/mocks/app-forms.d.ts +2 -0
  77. package/dist/mocks/app-forms.js +21 -0
  78. package/dist/mocks/app-navigation.d.ts +5 -0
  79. package/dist/mocks/app-navigation.js +34 -0
  80. package/dist/mocks/app-stores.d.ts +14 -0
  81. package/dist/mocks/app-stores.js +26 -0
  82. package/dist/services/api.d.ts +13 -3
  83. package/dist/services/api.js +91 -36
  84. package/dist/services/globalSave.d.ts +20 -0
  85. package/dist/services/globalSave.js +165 -0
  86. package/dist/services/nodeExecutionService.d.ts +63 -0
  87. package/dist/services/nodeExecutionService.js +261 -0
  88. package/dist/services/portConfigApi.d.ts +14 -0
  89. package/dist/services/portConfigApi.js +69 -0
  90. package/dist/services/toastService.d.ts +147 -0
  91. package/dist/services/toastService.js +235 -0
  92. package/dist/services/workflowStorage.d.ts +2 -2
  93. package/dist/services/workflowStorage.js +10 -10
  94. package/dist/stores/workflowStore.d.ts +53 -0
  95. package/dist/stores/workflowStore.js +264 -0
  96. package/dist/styles/base.css +896 -363
  97. package/dist/svelte-app.d.ts +52 -5
  98. package/dist/svelte-app.js +128 -6
  99. package/dist/types/config.d.ts +291 -0
  100. package/dist/types/config.js +4 -0
  101. package/dist/types/index.d.ts +231 -19
  102. package/dist/types/index.js +1 -1
  103. package/dist/utils/colors.d.ts +67 -33
  104. package/dist/utils/colors.js +183 -118
  105. package/dist/utils/config.d.ts +41 -0
  106. package/dist/utils/config.js +248 -0
  107. package/dist/utils/connections.d.ts +40 -3
  108. package/dist/utils/connections.js +115 -44
  109. package/dist/utils/icons.d.ts +1 -1
  110. package/dist/utils/icons.js +71 -70
  111. package/dist/utils/nodeStatus.d.ts +53 -0
  112. package/dist/utils/nodeStatus.js +183 -0
  113. package/dist/utils/nodeTypes.d.ts +57 -0
  114. package/dist/utils/nodeTypes.js +109 -0
  115. package/dist/utils/nodeWrapper.d.ts +39 -0
  116. package/dist/utils/nodeWrapper.js +62 -0
  117. package/package.json +129 -97
  118. package/dist/components/Node.svelte +0 -38
  119. package/dist/components/Node.svelte.d.ts +0 -4
@@ -0,0 +1,82 @@
1
+ <div class="flowdrop-logo">
2
+ <svg
3
+ viewBox="0 0 500 499.99999"
4
+ version="1.1"
5
+ id="svg47"
6
+ width="500"
7
+ height="500"
8
+ xmlns="http://www.w3.org/2000/svg"
9
+ >
10
+ <defs id="defs2"></defs>
11
+ <g id="g6669-7-7-3-3" transform="translate(472.2413,571.30469)">
12
+ <rect
13
+ style="fill:#f9f9f9;stroke:#000000;stroke-width:10px"
14
+ x="-462.2413"
15
+ y="-561.30469"
16
+ width="480"
17
+ height="480"
18
+ rx="20"
19
+ ry="20"
20
+ id="rect15-5-0-8-9-7"
21
+ />
22
+ <g id="g6893-4-9-5-2" transform="matrix(1.2053353,0,0,1.2053353,-1246.7763,-599.46548)">
23
+ <path
24
+ style="fill:#000000;stroke-width:10;stroke-dasharray:none"
25
+ d="M 850,120 V 310 Z"
26
+ id="path1152-1-7-1-4"
27
+ />
28
+ <path
29
+ style="fill:#000000;stroke:#000000;stroke-width:8.29645;stroke-dasharray:none;stroke-opacity:1"
30
+ d="M 850,110 V 310"
31
+ id="path1160-08-5-7-1"
32
+ />
33
+ <path
34
+ style="fill:none;stroke:#000000;stroke-width:7.49273;stroke-dasharray:none;stroke-opacity:1"
35
+ d="m 850,158.973 v 36.70355 8.15635 c 0,0 1.19184,39.5038 -36.01255,65.25076 -29.46481,20.39086 -52.3819,16.31269 -55.65576,65.25076 v 44.8599"
36
+ id="path6610-14-5-4-8"
37
+ />
38
+ <path
39
+ style="fill:none;stroke:#000000;stroke-width:7.5253;stroke-dasharray:none;stroke-opacity:1"
40
+ d="m 850,158.973 v 37.02335 8.22741 c 0,0 -1.19184,39.84799 36.01255,65.81929 29.46481,20.56853 52.3819,16.45482 55.65576,65.81929 v 45.25076"
41
+ id="path6610-14-7-2-5-2"
42
+ />
43
+ <path
44
+ d="m 849.41763,64.456369 25.36824,31.087262 c 6.23336,6.364119 10.06921,15.063569 10.06921,24.656839 0,19.50109 -15.85132,35.30988 -35.42373,35.30988 -19.57241,0 -35.43242,-15.80879 -35.43242,-35.30988 0,-9.49405 3.75813,-18.11351 9.87536,-24.458879 z"
45
+ style="fill:#009cde;stroke:#000000;stroke-width:8.29645;stroke-dasharray:none;paint-order:fill"
46
+ id="path21-6-4-4-1-6"
47
+ />
48
+ <circle
49
+ style="fill:#f46351;stroke:#000000;stroke-width:8.29645;stroke-dasharray:none"
50
+ cx="849.427"
51
+ cy="326.5929"
52
+ id="ellipse23-6-57-9-4-0"
53
+ r="30"
54
+ />
55
+ <ellipse
56
+ style="fill:#ccbaf4;stroke:#000000;stroke-width:8.29645;stroke-dasharray:none"
57
+ cx="759.99994"
58
+ cy="369.44669"
59
+ id="ellipse25-7-9-4-6-3"
60
+ rx="29.999952"
61
+ ry="30.000004"
62
+ />
63
+ <ellipse
64
+ style="fill:#ffc423;stroke:#000000;stroke-width:8.29645;stroke-dasharray:none"
65
+ cx="939.99963"
66
+ cy="369.44669"
67
+ id="ellipse27-8-8-4-0-9"
68
+ rx="29.999952"
69
+ ry="30.000004"
70
+ />
71
+ </g>
72
+ </g>
73
+ <g id="g6663-4" transform="matrix(0.87890795,0,0,0.87890795,3770.6486,2734.4692)" />
74
+ </svg>
75
+ </div>
76
+
77
+ <style>
78
+ .flowdrop-logo :global(svg) {
79
+ width: 100%;
80
+ height: 100%;
81
+ }
82
+ </style>
@@ -0,0 +1,26 @@
1
+ export default Logo;
2
+ type Logo = SvelteComponent<{
3
+ [x: string]: never;
4
+ }, {
5
+ [evt: string]: CustomEvent<any>;
6
+ }, {}> & {
7
+ $$bindings?: string;
8
+ };
9
+ declare const Logo: $$__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,565 @@
1
+ <!--
2
+ Logs Sidebar Component
3
+ Right-side sliding sidebar for real-time execution logs
4
+ Similar to ConfigSidebar but for logs display
5
+ Styled with BEM syntax
6
+ -->
7
+
8
+ <script lang="ts">
9
+ import Icon from '@iconify/svelte';
10
+ import { createEventDispatcher } from 'svelte';
11
+ import type { WorkflowNode as WorkflowNodeType } from '../types/index.js';
12
+
13
+ const dispatch = createEventDispatcher();
14
+
15
+ interface LogEntry {
16
+ timestamp: string;
17
+ level: string;
18
+ message: string;
19
+ nodeId?: string;
20
+ }
21
+
22
+ interface Props {
23
+ isOpen: boolean;
24
+ logs: LogEntry[];
25
+ selectedNode?: WorkflowNodeType | null;
26
+ onClose?: () => void;
27
+ }
28
+
29
+ let props: Props = $props();
30
+
31
+ // Focus management and body scroll control
32
+ $effect(() => {
33
+ if (props.isOpen) {
34
+ // Focus management - focus the sidebar when it opens
35
+ setTimeout(() => {
36
+ const sidebar = document.querySelector('.logs-sidebar--open');
37
+ if (sidebar) {
38
+ (sidebar as HTMLElement).focus();
39
+ }
40
+ }, 100);
41
+
42
+ // Prevent body scroll
43
+ document.body.style.overflow = 'hidden';
44
+ } else {
45
+ // Restore body scroll
46
+ document.body.style.overflow = '';
47
+ }
48
+ });
49
+
50
+ /**
51
+ * Handle close action
52
+ */
53
+ function handleClose(): void {
54
+ props.onClose?.();
55
+ dispatch('close');
56
+ }
57
+
58
+ /**
59
+ * Handle keyboard shortcuts
60
+ */
61
+ function handleKeydown(event: KeyboardEvent): void {
62
+ if (event.key === 'Escape') {
63
+ handleClose();
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Get log level color
69
+ */
70
+ function getLogLevelColor(level: string): string {
71
+ switch (level) {
72
+ case 'error':
73
+ return '#ef4444';
74
+ case 'warning':
75
+ return '#f59e0b';
76
+ case 'success':
77
+ return '#10b981';
78
+ case 'info':
79
+ return '#3b82f6';
80
+ default:
81
+ return '#6b7280';
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Get log level icon
87
+ */
88
+ function getLogLevelIcon(level: string): string {
89
+ switch (level) {
90
+ case 'error':
91
+ return 'mdi:alert-circle';
92
+ case 'warning':
93
+ return 'mdi:alert';
94
+ case 'success':
95
+ return 'mdi:check-circle';
96
+ case 'info':
97
+ return 'mdi:information';
98
+ default:
99
+ return 'mdi:circle';
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Format timestamp for display
105
+ */
106
+ function formatTimestamp(timestamp: string): string {
107
+ const date = new Date(timestamp);
108
+ return date.toLocaleTimeString('en-US', {
109
+ hour12: false,
110
+ hour: '2-digit',
111
+ minute: '2-digit',
112
+ second: '2-digit',
113
+ fractionalSecondDigits: 3
114
+ });
115
+ }
116
+
117
+ /**
118
+ * Filter logs by selected node
119
+ */
120
+ let filteredLogs = $derived(() => {
121
+ if (props.selectedNode) {
122
+ return props.logs.filter((log) => log.nodeId === props.selectedNode?.id);
123
+ }
124
+ return props.logs;
125
+ });
126
+
127
+ /**
128
+ * Clear logs
129
+ */
130
+ function clearLogs(): void {
131
+ dispatch('clear');
132
+ }
133
+
134
+ /**
135
+ * Export logs
136
+ */
137
+ function exportLogs(): void {
138
+ const logText = filteredLogs()
139
+ .map(
140
+ (log) =>
141
+ `[${formatTimestamp(log.timestamp)}] ${log.level.toUpperCase()}: ${log.message}${log.nodeId ? ` (Node: ${log.nodeId})` : ''}`
142
+ )
143
+ .join('\n');
144
+
145
+ const blob = new Blob([logText], { type: 'text/plain' });
146
+ const url = URL.createObjectURL(blob);
147
+ const link = document.createElement('a');
148
+ link.href = url;
149
+ link.download = `pipeline-logs-${new Date().toISOString().split('T')[0]}.txt`;
150
+ link.click();
151
+ URL.revokeObjectURL(url);
152
+ }
153
+
154
+ // Auto-scroll to bottom when new logs arrive
155
+ let logsContainer = $state<HTMLElement>();
156
+ $effect(() => {
157
+ if (logsContainer && props.logs.length > 0) {
158
+ logsContainer.scrollTop = logsContainer.scrollHeight;
159
+ }
160
+ });
161
+ </script>
162
+
163
+ <!-- Sidebar -->
164
+ <div
165
+ class="logs-sidebar"
166
+ class:logs-sidebar--open={props.isOpen}
167
+ role="dialog"
168
+ aria-label="Execution logs sidebar"
169
+ aria-modal="true"
170
+ tabindex="-1"
171
+ onkeydown={handleKeydown}
172
+ >
173
+ <!-- Header -->
174
+ <div class="logs-sidebar__header">
175
+ <div class="logs-sidebar__title-section">
176
+ <h2 class="logs-sidebar__title">
177
+ {#if props.selectedNode}
178
+ Logs: {props.selectedNode.data.label}
179
+ {:else}
180
+ Execution Logs
181
+ {/if}
182
+ </h2>
183
+ {#if props.logs.length > 0}
184
+ <div class="logs-sidebar__count" title="Total log entries">
185
+ <Icon icon="mdi:file-document-outline" />
186
+ {props.logs.length}
187
+ </div>
188
+ {/if}
189
+ </div>
190
+ <button
191
+ class="logs-sidebar__close-btn"
192
+ onclick={handleClose}
193
+ title="Close logs sidebar (Esc)"
194
+ aria-label="Close logs sidebar"
195
+ >
196
+ <Icon icon="mdi:close" />
197
+ </button>
198
+ </div>
199
+
200
+ <!-- Content -->
201
+ <div class="logs-sidebar__content">
202
+ <!-- Logs List -->
203
+ {#if filteredLogs().length > 0}
204
+ <div class="logs-sidebar__logs" bind:this={logsContainer}>
205
+ {#each filteredLogs() as log, index (index)}
206
+ <div
207
+ class="logs-sidebar__log-entry"
208
+ class:logs-sidebar__log-entry--error={log.level === 'error'}
209
+ class:logs-sidebar__log-entry--warning={log.level === 'warning'}
210
+ class:logs-sidebar__log-entry--success={log.level === 'success'}
211
+ class:logs-sidebar__log-entry--info={log.level === 'info'}
212
+ >
213
+ <div class="logs-sidebar__log-header">
214
+ <div class="logs-sidebar__log-level">
215
+ <Icon
216
+ icon={getLogLevelIcon(log.level)}
217
+ style="color: {getLogLevelColor(log.level)}"
218
+ />
219
+ <span class="logs-sidebar__log-level-text">{log.level.toUpperCase()}</span>
220
+ </div>
221
+ <div class="logs-sidebar__log-timestamp">
222
+ {formatTimestamp(log.timestamp)}
223
+ </div>
224
+ </div>
225
+ <div class="logs-sidebar__log-message">
226
+ {log.message}
227
+ </div>
228
+ {#if log.nodeId}
229
+ <div class="logs-sidebar__log-node">
230
+ <Icon icon="mdi:graph" />
231
+ Node: {log.nodeId}
232
+ </div>
233
+ {/if}
234
+ </div>
235
+ {/each}
236
+ </div>
237
+ {:else}
238
+ <div class="logs-sidebar__empty">
239
+ <Icon icon="mdi:file-document-outline" class="logs-sidebar__empty-icon" />
240
+ <p class="logs-sidebar__empty-text">
241
+ {#if props.selectedNode}
242
+ No logs available for this node
243
+ {:else}
244
+ No execution logs yet
245
+ {/if}
246
+ </p>
247
+ </div>
248
+ {/if}
249
+ </div>
250
+
251
+ <!-- Footer -->
252
+ <div class="logs-sidebar__footer">
253
+ <div class="logs-sidebar__actions">
254
+ <button
255
+ type="button"
256
+ class="logs-sidebar__btn logs-sidebar__btn--secondary"
257
+ onclick={clearLogs}
258
+ disabled={props.logs.length === 0}
259
+ >
260
+ <Icon icon="mdi:delete" />
261
+ Clear
262
+ </button>
263
+ <button
264
+ type="button"
265
+ class="logs-sidebar__btn logs-sidebar__btn--outline"
266
+ onclick={exportLogs}
267
+ disabled={props.logs.length === 0}
268
+ >
269
+ <Icon icon="mdi:download" />
270
+ Export
271
+ </button>
272
+ </div>
273
+
274
+ {#if props.logs.length > 0}
275
+ <p class="logs-sidebar__info-text">
276
+ {filteredLogs().length} of {props.logs.length} log entries
277
+ </p>
278
+ {/if}
279
+ </div>
280
+ </div>
281
+
282
+ <style>
283
+ .logs-sidebar {
284
+ position: fixed;
285
+ top: var(--flowdrop-navbar-height, 60px); /* Start below navbar */
286
+ right: 0;
287
+ width: 400px;
288
+ height: calc(100vh - var(--flowdrop-navbar-height, 60px)); /* Account for navbar height */
289
+ background-color: #ffffff;
290
+ border-left: 1px solid #e5e7eb;
291
+ box-shadow: -4px 0 20px rgba(0, 0, 0, 0.15);
292
+ transform: translateX(100%);
293
+ transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
294
+ z-index: -1;
295
+ display: flex;
296
+ flex-direction: column;
297
+ pointer-events: none;
298
+ }
299
+
300
+ /* Mobile responsive */
301
+ @media (max-width: 768px) {
302
+ .logs-sidebar {
303
+ width: 100vw;
304
+ border-left: none;
305
+ }
306
+ }
307
+
308
+ @media (max-width: 480px) {
309
+ .logs-sidebar {
310
+ width: 100vw;
311
+ }
312
+ }
313
+
314
+ .logs-sidebar--open {
315
+ transform: translateX(0);
316
+ z-index: 999;
317
+ pointer-events: auto;
318
+ }
319
+
320
+ /* Prevent body scroll when sidebar is open */
321
+ :global(body:has(.logs-sidebar--open)) {
322
+ overflow: hidden;
323
+ }
324
+
325
+ .logs-sidebar__header {
326
+ display: flex;
327
+ align-items: center;
328
+ justify-content: space-between;
329
+ padding: 1rem 1.5rem;
330
+ border-bottom: 1px solid #e5e7eb;
331
+ background-color: #f9fafb;
332
+ flex-shrink: 0;
333
+ }
334
+
335
+ .logs-sidebar__title-section {
336
+ display: flex;
337
+ align-items: center;
338
+ gap: 0.5rem;
339
+ }
340
+
341
+ .logs-sidebar__title {
342
+ font-size: 1.125rem;
343
+ font-weight: 600;
344
+ color: #111827;
345
+ margin: 0;
346
+ }
347
+
348
+ .logs-sidebar__count {
349
+ display: flex;
350
+ align-items: center;
351
+ gap: 0.25rem;
352
+ font-size: 0.75rem;
353
+ color: #6b7280;
354
+ background-color: #f3f4f6;
355
+ padding: 0.25rem 0.5rem;
356
+ border-radius: 0.375rem;
357
+ }
358
+
359
+ .logs-sidebar__close-btn {
360
+ display: flex;
361
+ align-items: center;
362
+ justify-content: center;
363
+ width: 2rem;
364
+ height: 2rem;
365
+ border: none;
366
+ background: transparent;
367
+ color: #6b7280;
368
+ cursor: pointer;
369
+ border-radius: 0.375rem;
370
+ transition: all 0.2s ease-in-out;
371
+ }
372
+
373
+ .logs-sidebar__close-btn:hover {
374
+ background-color: #f3f4f6;
375
+ color: #374151;
376
+ }
377
+
378
+ .logs-sidebar__content {
379
+ flex: 1;
380
+ overflow-y: auto;
381
+ padding: 1.5rem;
382
+ }
383
+
384
+ .logs-sidebar__logs {
385
+ display: flex;
386
+ flex-direction: column;
387
+ gap: 0.75rem;
388
+ }
389
+
390
+ .logs-sidebar__log-entry {
391
+ background-color: #f9fafb;
392
+ border: 1px solid #e5e7eb;
393
+ border-radius: 0.5rem;
394
+ padding: 0.75rem;
395
+ transition: all 0.2s ease-in-out;
396
+ }
397
+
398
+ .logs-sidebar__log-entry--error {
399
+ border-left: 4px solid #ef4444;
400
+ background-color: #fef2f2;
401
+ }
402
+
403
+ .logs-sidebar__log-entry--warning {
404
+ border-left: 4px solid #f59e0b;
405
+ background-color: #fffbeb;
406
+ }
407
+
408
+ .logs-sidebar__log-entry--success {
409
+ border-left: 4px solid #10b981;
410
+ background-color: #f0fdf4;
411
+ }
412
+
413
+ .logs-sidebar__log-entry--info {
414
+ border-left: 4px solid #3b82f6;
415
+ background-color: #eff6ff;
416
+ }
417
+
418
+ .logs-sidebar__log-header {
419
+ display: flex;
420
+ align-items: center;
421
+ justify-content: space-between;
422
+ margin-bottom: 0.5rem;
423
+ }
424
+
425
+ .logs-sidebar__log-level {
426
+ display: flex;
427
+ align-items: center;
428
+ gap: 0.25rem;
429
+ font-size: 0.75rem;
430
+ font-weight: 600;
431
+ text-transform: uppercase;
432
+ letter-spacing: 0.05em;
433
+ }
434
+
435
+ .logs-sidebar__log-level-text {
436
+ font-size: 0.75rem;
437
+ font-weight: 600;
438
+ }
439
+
440
+ .logs-sidebar__log-timestamp {
441
+ font-size: 0.75rem;
442
+ color: #6b7280;
443
+ font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
444
+ }
445
+
446
+ .logs-sidebar__log-message {
447
+ font-size: 0.875rem;
448
+ color: #374151;
449
+ line-height: 1.5;
450
+ margin-bottom: 0.5rem;
451
+ word-break: break-word;
452
+ }
453
+
454
+ .logs-sidebar__log-node {
455
+ display: flex;
456
+ align-items: center;
457
+ gap: 0.25rem;
458
+ font-size: 0.75rem;
459
+ color: #6b7280;
460
+ background-color: #ffffff;
461
+ padding: 0.25rem 0.5rem;
462
+ border-radius: 0.25rem;
463
+ border: 1px solid #e5e7eb;
464
+ width: fit-content;
465
+ }
466
+
467
+ .logs-sidebar__empty {
468
+ display: flex;
469
+ flex-direction: column;
470
+ align-items: center;
471
+ justify-content: center;
472
+ padding: 3rem 1rem;
473
+ text-align: center;
474
+ color: #6b7280;
475
+ }
476
+
477
+ :global(.logs-sidebar__empty-icon) {
478
+ font-size: 3rem;
479
+ margin-bottom: 1rem;
480
+ opacity: 0.5;
481
+ }
482
+
483
+ .logs-sidebar__empty-text {
484
+ font-size: 0.875rem;
485
+ margin: 0;
486
+ }
487
+
488
+ .logs-sidebar__footer {
489
+ padding: 1rem 1.5rem;
490
+ border-top: 1px solid #e5e7eb;
491
+ background-color: #f9fafb;
492
+ flex-shrink: 0;
493
+ }
494
+
495
+ .logs-sidebar__actions {
496
+ display: flex;
497
+ gap: 0.75rem;
498
+ margin-bottom: 0.5rem;
499
+ }
500
+
501
+ .logs-sidebar__btn {
502
+ display: flex;
503
+ align-items: center;
504
+ gap: 0.5rem;
505
+ padding: 0.5rem 1rem;
506
+ border: 1px solid;
507
+ border-radius: 0.375rem;
508
+ font-size: 0.875rem;
509
+ font-weight: 500;
510
+ cursor: pointer;
511
+ transition: all 0.2s ease-in-out;
512
+ flex: 1;
513
+ justify-content: center;
514
+ }
515
+
516
+ .logs-sidebar__btn:disabled {
517
+ opacity: 0.5;
518
+ cursor: not-allowed;
519
+ }
520
+
521
+ .logs-sidebar__btn--secondary {
522
+ background-color: #ef4444;
523
+ border-color: #ef4444;
524
+ color: #ffffff;
525
+ }
526
+
527
+ .logs-sidebar__btn--secondary:hover:not(:disabled) {
528
+ background-color: #dc2626;
529
+ border-color: #dc2626;
530
+ }
531
+
532
+ .logs-sidebar__btn--outline {
533
+ background-color: transparent;
534
+ border-color: #d1d5db;
535
+ color: #374151;
536
+ }
537
+
538
+ .logs-sidebar__btn--outline:hover:not(:disabled) {
539
+ background-color: #f3f4f6;
540
+ border-color: #9ca3af;
541
+ }
542
+
543
+ .logs-sidebar__info-text {
544
+ font-size: 0.75rem;
545
+ color: #6b7280;
546
+ margin: 0;
547
+ text-align: center;
548
+ }
549
+
550
+ /* Responsive design */
551
+ @media (max-width: 640px) {
552
+ .logs-sidebar {
553
+ width: 100vw;
554
+ }
555
+ }
556
+
557
+ @media (max-width: 480px) {
558
+ .logs-sidebar__header,
559
+ .logs-sidebar__content,
560
+ .logs-sidebar__footer {
561
+ padding-left: 1rem;
562
+ padding-right: 1rem;
563
+ }
564
+ }
565
+ </style>
@@ -0,0 +1,34 @@
1
+ import type { WorkflowNode as WorkflowNodeType } from '../types/index.js';
2
+ interface LogEntry {
3
+ timestamp: string;
4
+ level: string;
5
+ message: string;
6
+ nodeId?: string;
7
+ }
8
+ interface Props {
9
+ isOpen: boolean;
10
+ logs: LogEntry[];
11
+ selectedNode?: WorkflowNodeType | null;
12
+ onClose?: () => void;
13
+ }
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: Props & {
19
+ $$events?: Events;
20
+ $$slots?: Slots;
21
+ }): Exports & {
22
+ $set?: any;
23
+ $on?: any;
24
+ };
25
+ z_$$bindings?: Bindings;
26
+ }
27
+ declare const LogsSidebar: $$__sveltets_2_IsomorphicComponent<Props, {
28
+ close: CustomEvent<any>;
29
+ clear: CustomEvent<any>;
30
+ } & {
31
+ [evt: string]: CustomEvent<any>;
32
+ }, {}, {}, "">;
33
+ type LogsSidebar = InstanceType<typeof LogsSidebar>;
34
+ export default LogsSidebar;