@flowdrop/flowdrop 1.2.2 → 1.4.0
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.
- package/dist/components/App.svelte +80 -5
- package/dist/components/App.svelte.d.ts +7 -0
- package/dist/components/CanvasBanner.stories.svelte +6 -2
- package/dist/components/ConfigForm.svelte +421 -0
- package/dist/components/FlowDropEdge.svelte +7 -48
- package/dist/components/Logo.svelte +14 -14
- package/dist/components/Navbar.svelte +58 -10
- package/dist/components/Navbar.svelte.d.ts +7 -0
- package/dist/components/NodeSidebar.svelte +236 -304
- package/dist/components/WorkflowEditor.svelte +16 -6
- package/dist/components/nodes/GatewayNode.svelte +8 -9
- package/dist/components/nodes/SimpleNode.stories.svelte +64 -0
- package/dist/components/nodes/SimpleNode.svelte +93 -104
- package/dist/components/nodes/SquareNode.stories.svelte +45 -0
- package/dist/components/nodes/SquareNode.svelte +94 -104
- package/dist/components/nodes/TerminalNode.svelte +6 -7
- package/dist/components/nodes/WorkflowNode.stories.svelte +63 -0
- package/dist/components/nodes/WorkflowNode.svelte +54 -19
- package/dist/schemas/v1/workflow.schema.json +22 -107
- package/dist/skins/slate.js +16 -0
- package/dist/stories/EdgeDecorator.svelte +4 -4
- package/dist/styles/base.css +48 -0
- package/dist/svelte-app.d.ts +7 -1
- package/dist/svelte-app.js +4 -1
- package/dist/types/index.d.ts +17 -0
- package/dist/utils/portUtils.d.ts +24 -0
- package/dist/utils/portUtils.js +42 -0
- package/package.json +3 -3
|
@@ -16,10 +16,7 @@
|
|
|
16
16
|
import { getCategoryColorToken } from "../utils/colors.js";
|
|
17
17
|
import { getCategoryLabel } from "../stores/categoriesStore.svelte.js";
|
|
18
18
|
import { SvelteSet } from "svelte/reactivity";
|
|
19
|
-
import {
|
|
20
|
-
getUiSettings,
|
|
21
|
-
updateSettings,
|
|
22
|
-
} from "../stores/settingsStore.svelte.js";
|
|
19
|
+
import { getUiSettings } from "../stores/settingsStore.svelte.js";
|
|
23
20
|
|
|
24
21
|
interface Props {
|
|
25
22
|
nodes: NodeMetadata[];
|
|
@@ -36,16 +33,6 @@
|
|
|
36
33
|
// svelte-ignore state_referenced_locally — initial default, user selects interactively
|
|
37
34
|
let selectedCategory = $state(props.selectedCategory || "all");
|
|
38
35
|
|
|
39
|
-
/**
|
|
40
|
-
* Toggle the sidebar collapsed state
|
|
41
|
-
* Persists the new state to settings
|
|
42
|
-
*/
|
|
43
|
-
function toggleSidebar(): void {
|
|
44
|
-
updateSettings({
|
|
45
|
-
ui: { sidebarCollapsed: !getUiSettings().sidebarCollapsed },
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
|
|
49
36
|
/**
|
|
50
37
|
* Check if a node is compatible with the active workflow format.
|
|
51
38
|
* Nodes without formats are universal (compatible with all formats).
|
|
@@ -217,165 +204,218 @@
|
|
|
217
204
|
}
|
|
218
205
|
</script>
|
|
219
206
|
|
|
220
|
-
<!-- Components Sidebar
|
|
207
|
+
<!-- Components Sidebar -->
|
|
221
208
|
<aside
|
|
222
209
|
class="flowdrop-sidebar flowdrop-sidebar--container"
|
|
223
210
|
class:flowdrop-sidebar--collapsed={isCollapsed}
|
|
224
211
|
class:flowdrop-sidebar--compact={getUiSettings().compactMode}
|
|
225
|
-
style:width="{isCollapsed ?
|
|
212
|
+
style:width="{isCollapsed ? 0 : getUiSettings().sidebarWidth}px"
|
|
226
213
|
aria-label="Components sidebar"
|
|
227
214
|
>
|
|
228
|
-
<!--
|
|
229
|
-
<div class="flowdrop-
|
|
230
|
-
<
|
|
231
|
-
class="flowdrop-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
<div class="flowdrop-sidebar__title">
|
|
240
|
-
<h2 class="flowdrop-text--lg flowdrop-font--bold">Components</h2>
|
|
215
|
+
<!-- Search Section — visibility controlled by --fd-sidebar-search-display -->
|
|
216
|
+
<div class="flowdrop-sidebar__search">
|
|
217
|
+
<div class="flowdrop-join flowdrop-w--full">
|
|
218
|
+
<div class="flowdrop-join__item flowdrop-flex--1">
|
|
219
|
+
<input
|
|
220
|
+
type="text"
|
|
221
|
+
placeholder="Search components..."
|
|
222
|
+
class="flowdrop-input flowdrop-join__item flowdrop-w--full"
|
|
223
|
+
bind:value={searchInput}
|
|
224
|
+
oninput={handleSearchChange}
|
|
225
|
+
/>
|
|
241
226
|
</div>
|
|
242
|
-
|
|
227
|
+
<button
|
|
228
|
+
class="flowdrop-btn flowdrop-join__item"
|
|
229
|
+
aria-label="Search components"
|
|
230
|
+
>
|
|
231
|
+
<Icon icon="mdi:magnify" class="flowdrop-icon" />
|
|
232
|
+
</button>
|
|
233
|
+
</div>
|
|
243
234
|
</div>
|
|
244
235
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
236
|
+
<!-- Node Types List -->
|
|
237
|
+
<div class="flowdrop-sidebar__content">
|
|
238
|
+
{#if props.nodes?.length === 0}
|
|
239
|
+
<!-- No node types available -->
|
|
240
|
+
<div class="flowdrop-hero">
|
|
241
|
+
<div class="flowdrop-hero__content">
|
|
242
|
+
{#if props.loading}
|
|
243
|
+
<div class="flowdrop-mb--4">
|
|
244
|
+
<LoadingSpinner size="md" text="Loading from server..." />
|
|
245
|
+
</div>
|
|
246
|
+
{:else}
|
|
247
|
+
<div class="flowdrop-hero__icon">
|
|
248
|
+
<svg
|
|
249
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
250
|
+
width="1em"
|
|
251
|
+
height="1em"
|
|
252
|
+
viewBox="0 0 24 24"
|
|
253
|
+
fill="none"
|
|
254
|
+
stroke="currentColor"
|
|
255
|
+
stroke-width="1.5"
|
|
256
|
+
stroke-linecap="round"
|
|
257
|
+
stroke-linejoin="round"
|
|
258
|
+
>
|
|
259
|
+
<path
|
|
260
|
+
d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"
|
|
261
|
+
/>
|
|
262
|
+
<polyline points="3.27 6.96 12 12.01 20.73 6.96" />
|
|
263
|
+
<line x1="12" y1="22.08" x2="12" y2="12" />
|
|
264
|
+
</svg>
|
|
265
|
+
</div>
|
|
266
|
+
<h3 class="flowdrop-hero__title">No node types available</h3>
|
|
267
|
+
<p class="flowdrop-hero__description">
|
|
268
|
+
Node type definitions will appear here
|
|
269
|
+
</p>
|
|
270
|
+
{/if}
|
|
257
271
|
</div>
|
|
258
|
-
<button
|
|
259
|
-
class="flowdrop-btn flowdrop-join__item"
|
|
260
|
-
aria-label="Search components"
|
|
261
|
-
>
|
|
262
|
-
<Icon icon="mdi:magnify" class="flowdrop-icon" />
|
|
263
|
-
</button>
|
|
264
272
|
</div>
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
<div class="flowdrop-
|
|
273
|
-
|
|
274
|
-
<div class="flowdrop-mb--4">
|
|
275
|
-
<LoadingSpinner size="md" text="Loading from server..." />
|
|
276
|
-
</div>
|
|
277
|
-
{:else}
|
|
273
|
+
{:else if searchInput.trim()}
|
|
274
|
+
<!-- Search Results -->
|
|
275
|
+
<div class="flowdrop-p--4">
|
|
276
|
+
<div class="flowdrop-divider">
|
|
277
|
+
<h3 class="flowdrop-divider__text">Search Results</h3>
|
|
278
|
+
</div>
|
|
279
|
+
{#if filteredNodes.length === 0}
|
|
280
|
+
<div class="flowdrop-hero">
|
|
281
|
+
<div class="flowdrop-hero__content">
|
|
278
282
|
<div class="flowdrop-hero__icon">
|
|
279
|
-
<svg
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
+
<svg
|
|
284
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
285
|
+
width="1em"
|
|
286
|
+
height="1em"
|
|
287
|
+
viewBox="0 0 24 24"
|
|
288
|
+
fill="none"
|
|
289
|
+
stroke="currentColor"
|
|
290
|
+
stroke-width="1.5"
|
|
291
|
+
stroke-linecap="round"
|
|
292
|
+
stroke-linejoin="round"
|
|
293
|
+
>
|
|
294
|
+
<circle cx="11" cy="11" r="8" />
|
|
295
|
+
<line x1="21" y1="21" x2="16.65" y2="16.65" />
|
|
283
296
|
</svg>
|
|
284
297
|
</div>
|
|
285
|
-
<h3 class="flowdrop-hero__title">No
|
|
298
|
+
<h3 class="flowdrop-hero__title">No components found</h3>
|
|
286
299
|
<p class="flowdrop-hero__description">
|
|
287
|
-
|
|
300
|
+
Try adjusting your search
|
|
288
301
|
</p>
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
{:else if searchInput.trim()}
|
|
293
|
-
<!-- Search Results -->
|
|
294
|
-
<div class="flowdrop-p--4">
|
|
295
|
-
<div class="flowdrop-divider">
|
|
296
|
-
<h3 class="flowdrop-divider__text">Search Results</h3>
|
|
297
|
-
</div>
|
|
298
|
-
{#if filteredNodes.length === 0}
|
|
299
|
-
<div class="flowdrop-hero">
|
|
300
|
-
<div class="flowdrop-hero__content">
|
|
301
|
-
<div class="flowdrop-hero__icon">
|
|
302
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
|
303
|
-
<circle cx="11" cy="11" r="8"/>
|
|
304
|
-
<line x1="21" y1="21" x2="16.65" y2="16.65"/>
|
|
305
|
-
</svg>
|
|
302
|
+
{#if props.loading}
|
|
303
|
+
<div class="flowdrop-mb--4">
|
|
304
|
+
<LoadingSpinner size="sm" text="Loading components..." />
|
|
306
305
|
</div>
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
306
|
+
{/if}
|
|
307
|
+
</div>
|
|
308
|
+
</div>
|
|
309
|
+
{:else}
|
|
310
|
+
<div class="flowdrop-node-list">
|
|
311
|
+
{#each filteredNodes as nodeType (nodeType.id)}
|
|
312
|
+
<div
|
|
313
|
+
class="flowdrop-card flowdrop-card--compact flowdrop-node-item"
|
|
314
|
+
draggable="true"
|
|
315
|
+
ondragstart={(e) => handleNodeDragStart(e, nodeType)}
|
|
316
|
+
role="button"
|
|
317
|
+
tabindex="0"
|
|
318
|
+
>
|
|
319
|
+
<div class="flowdrop-card__body flowdrop-p--1 flowdrop-py--1">
|
|
320
|
+
<div
|
|
321
|
+
class="flowdrop-flex flowdrop-gap--2 flowdrop-items--center"
|
|
322
|
+
>
|
|
323
|
+
<!-- Node Type Icon with Squircle Background -->
|
|
324
|
+
<span
|
|
325
|
+
class="flowdrop-node-icon"
|
|
326
|
+
style="--_icon-color: {getCategoryColorToken(
|
|
327
|
+
nodeType.category,
|
|
328
|
+
)}"
|
|
329
|
+
>
|
|
330
|
+
<Icon
|
|
331
|
+
icon={getNodeIcon(nodeType.icon, nodeType.category)}
|
|
332
|
+
/>
|
|
333
|
+
</span>
|
|
334
|
+
|
|
335
|
+
<!-- Node Type Info - Icon and Title only -->
|
|
336
|
+
<h4
|
|
337
|
+
class="flowdrop-text--sm flowdrop-font--medium flowdrop-truncate flowdrop-flex--1"
|
|
338
|
+
>
|
|
339
|
+
{nodeType.name}
|
|
340
|
+
</h4>
|
|
314
341
|
</div>
|
|
315
|
-
|
|
342
|
+
<p
|
|
343
|
+
class="flowdrop-text--xs flowdrop-text--gray flowdrop-truncate flowdrop-mt--1 flowdrop-ml--0"
|
|
344
|
+
>
|
|
345
|
+
{nodeType.description}
|
|
346
|
+
</p>
|
|
347
|
+
</div>
|
|
316
348
|
</div>
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
349
|
+
{/each}
|
|
350
|
+
</div>
|
|
351
|
+
{/if}
|
|
352
|
+
</div>
|
|
353
|
+
{:else}
|
|
354
|
+
<!-- Show categories with details when no search is active -->
|
|
355
|
+
<div class="flowdrop-p--4">
|
|
356
|
+
<!-- Category-specific details -->
|
|
357
|
+
<div class="flowdrop-category-list">
|
|
358
|
+
{#each categories as category (category)}
|
|
359
|
+
{@const categoryNodes = getFilteredNodesForCategory(category)}
|
|
360
|
+
{#if categoryNodes.length > 0}
|
|
361
|
+
<!-- Flat style: label + dot+name rows (shown/hidden via CSS token) -->
|
|
362
|
+
<div class="fd-sidebar-flat-section">
|
|
363
|
+
<div class="fd-sidebar-flat-category">
|
|
364
|
+
{getCategoryDisplayName(category).toUpperCase()}
|
|
365
|
+
</div>
|
|
366
|
+
<div class="fd-sidebar-flat-list">
|
|
367
|
+
{#each categoryNodes as nodeType (nodeType.id)}
|
|
329
368
|
<div
|
|
330
|
-
class="
|
|
369
|
+
class="fd-sidebar-flat-item"
|
|
370
|
+
draggable="true"
|
|
371
|
+
ondragstart={(e) => handleNodeDragStart(e, nodeType)}
|
|
372
|
+
onclick={() => handleNodeClick(nodeType)}
|
|
373
|
+
role="button"
|
|
374
|
+
tabindex="0"
|
|
375
|
+
onkeydown={(e) => {
|
|
376
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
377
|
+
e.preventDefault();
|
|
378
|
+
handleNodeClick(nodeType);
|
|
379
|
+
}
|
|
380
|
+
}}
|
|
331
381
|
>
|
|
332
|
-
<!-- Node Type Icon with Squircle Background -->
|
|
333
382
|
<span
|
|
334
|
-
class="
|
|
335
|
-
style="
|
|
383
|
+
class="fd-sidebar-flat-dot"
|
|
384
|
+
style="background: {getCategoryColorToken(
|
|
336
385
|
nodeType.category,
|
|
337
386
|
)}"
|
|
338
|
-
>
|
|
339
|
-
|
|
340
|
-
icon={getNodeIcon(nodeType.icon, nodeType.category)}
|
|
341
|
-
/>
|
|
342
|
-
</span>
|
|
343
|
-
|
|
344
|
-
<!-- Node Type Info - Icon and Title only -->
|
|
345
|
-
<h4
|
|
346
|
-
class="flowdrop-text--sm flowdrop-font--medium flowdrop-truncate flowdrop-flex--1"
|
|
347
|
-
>
|
|
348
|
-
{nodeType.name}
|
|
349
|
-
</h4>
|
|
387
|
+
></span>
|
|
388
|
+
<span class="fd-sidebar-flat-name">{nodeType.name}</span>
|
|
350
389
|
</div>
|
|
351
|
-
|
|
352
|
-
|
|
390
|
+
{/each}
|
|
391
|
+
</div>
|
|
392
|
+
</div>
|
|
393
|
+
<!-- Card style: <details> accordion (shown/hidden via CSS token) -->
|
|
394
|
+
<details
|
|
395
|
+
class="flowdrop-details fd-sidebar-card-section"
|
|
396
|
+
open={props.categoriesDefaultOpen || undefined}
|
|
397
|
+
>
|
|
398
|
+
<summary class="flowdrop-details__summary">
|
|
399
|
+
<div
|
|
400
|
+
class="flowdrop-flex flowdrop-gap--2 flowdrop-items--center"
|
|
401
|
+
>
|
|
402
|
+
<span
|
|
403
|
+
class="flowdrop-node-icon"
|
|
404
|
+
style="--_icon-color: {getCategoryColorToken(category)}"
|
|
353
405
|
>
|
|
354
|
-
{
|
|
355
|
-
</
|
|
406
|
+
<Icon icon={getCategoryIcon(category)} />
|
|
407
|
+
</span>
|
|
408
|
+
<span>{getCategoryDisplayName(category)}</span>
|
|
356
409
|
</div>
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
</div>
|
|
360
|
-
{/if}
|
|
361
|
-
</div>
|
|
362
|
-
{:else}
|
|
363
|
-
<!-- Show categories with details when no search is active -->
|
|
364
|
-
<div class="flowdrop-p--4">
|
|
365
|
-
<!-- Category-specific details -->
|
|
366
|
-
<div class="flowdrop-category-list">
|
|
367
|
-
{#each categories as category (category)}
|
|
368
|
-
{@const categoryNodes = getFilteredNodesForCategory(category)}
|
|
369
|
-
{#if categoryNodes.length > 0}
|
|
370
|
-
<!-- Flat style: label + dot+name rows (shown/hidden via CSS token) -->
|
|
371
|
-
<div class="fd-sidebar-flat-section">
|
|
372
|
-
<div class="fd-sidebar-flat-category">
|
|
373
|
-
{getCategoryDisplayName(category).toUpperCase()}
|
|
410
|
+
<div class="flowdrop-badge flowdrop-badge--secondary">
|
|
411
|
+
{categoryNodes.length}
|
|
374
412
|
</div>
|
|
375
|
-
|
|
413
|
+
</summary>
|
|
414
|
+
<div class="flowdrop-details__content">
|
|
415
|
+
<div class="flowdrop-node-list">
|
|
376
416
|
{#each categoryNodes as nodeType (nodeType.id)}
|
|
377
417
|
<div
|
|
378
|
-
class="
|
|
418
|
+
class="flowdrop-card flowdrop-card--compact flowdrop-node-item"
|
|
379
419
|
draggable="true"
|
|
380
420
|
ondragstart={(e) => handleNodeDragStart(e, nodeType)}
|
|
381
421
|
onclick={() => handleNodeClick(nodeType)}
|
|
@@ -388,122 +428,71 @@
|
|
|
388
428
|
}
|
|
389
429
|
}}
|
|
390
430
|
>
|
|
391
|
-
<span
|
|
392
|
-
class="fd-sidebar-flat-dot"
|
|
393
|
-
style="background: {getCategoryColorToken(
|
|
394
|
-
nodeType.category,
|
|
395
|
-
)}"
|
|
396
|
-
></span>
|
|
397
|
-
<span class="fd-sidebar-flat-name">{nodeType.name}</span
|
|
398
|
-
>
|
|
399
|
-
</div>
|
|
400
|
-
{/each}
|
|
401
|
-
</div>
|
|
402
|
-
</div>
|
|
403
|
-
<!-- Card style: <details> accordion (shown/hidden via CSS token) -->
|
|
404
|
-
<details
|
|
405
|
-
class="flowdrop-details fd-sidebar-card-section"
|
|
406
|
-
open={props.categoriesDefaultOpen || undefined}
|
|
407
|
-
>
|
|
408
|
-
<summary class="flowdrop-details__summary">
|
|
409
|
-
<div
|
|
410
|
-
class="flowdrop-flex flowdrop-gap--2 flowdrop-items--center"
|
|
411
|
-
>
|
|
412
|
-
<span
|
|
413
|
-
class="flowdrop-node-icon"
|
|
414
|
-
style="--_icon-color: {getCategoryColorToken(category)}"
|
|
415
|
-
>
|
|
416
|
-
<Icon icon={getCategoryIcon(category)} />
|
|
417
|
-
</span>
|
|
418
|
-
<span>{getCategoryDisplayName(category)}</span>
|
|
419
|
-
</div>
|
|
420
|
-
<div class="flowdrop-badge flowdrop-badge--secondary">
|
|
421
|
-
{categoryNodes.length}
|
|
422
|
-
</div>
|
|
423
|
-
</summary>
|
|
424
|
-
<div class="flowdrop-details__content">
|
|
425
|
-
<div class="flowdrop-node-list">
|
|
426
|
-
{#each categoryNodes as nodeType (nodeType.id)}
|
|
427
431
|
<div
|
|
428
|
-
class="flowdrop-
|
|
429
|
-
draggable="true"
|
|
430
|
-
ondragstart={(e) => handleNodeDragStart(e, nodeType)}
|
|
431
|
-
onclick={() => handleNodeClick(nodeType)}
|
|
432
|
-
role="button"
|
|
433
|
-
tabindex="0"
|
|
434
|
-
onkeydown={(e) => {
|
|
435
|
-
if (e.key === "Enter" || e.key === " ") {
|
|
436
|
-
e.preventDefault();
|
|
437
|
-
handleNodeClick(nodeType);
|
|
438
|
-
}
|
|
439
|
-
}}
|
|
432
|
+
class="flowdrop-card__body flowdrop-p--1 flowdrop-py--1"
|
|
440
433
|
>
|
|
441
434
|
<div
|
|
442
|
-
class="flowdrop-
|
|
435
|
+
class="flowdrop-flex flowdrop-gap--2 flowdrop-items--center"
|
|
443
436
|
>
|
|
444
|
-
|
|
445
|
-
|
|
437
|
+
<!-- Node Type Icon with Squircle Background -->
|
|
438
|
+
<span
|
|
439
|
+
class="flowdrop-node-icon"
|
|
440
|
+
style="--_icon-color: {getCategoryColorToken(
|
|
441
|
+
nodeType.category,
|
|
442
|
+
)}"
|
|
446
443
|
>
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
style="--_icon-color: {getCategoryColorToken(
|
|
444
|
+
<Icon
|
|
445
|
+
icon={getNodeIcon(
|
|
446
|
+
nodeType.icon,
|
|
451
447
|
nodeType.category,
|
|
452
|
-
)}
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
/>
|
|
460
|
-
</span>
|
|
461
|
-
|
|
462
|
-
<!-- Node Type Info - Icon and Title only -->
|
|
463
|
-
<h4
|
|
464
|
-
class="flowdrop-text--sm flowdrop-font--medium flowdrop-truncate flowdrop-flex--1"
|
|
465
|
-
>
|
|
466
|
-
{nodeType.name}
|
|
467
|
-
</h4>
|
|
468
|
-
</div>
|
|
469
|
-
<p
|
|
470
|
-
class="flowdrop-text--xs flowdrop-text--gray flowdrop-truncate flowdrop-mt--1 flowdrop-ml--0"
|
|
448
|
+
)}
|
|
449
|
+
/>
|
|
450
|
+
</span>
|
|
451
|
+
|
|
452
|
+
<!-- Node Type Info - Icon and Title only -->
|
|
453
|
+
<h4
|
|
454
|
+
class="flowdrop-text--sm flowdrop-font--medium flowdrop-truncate flowdrop-flex--1"
|
|
471
455
|
>
|
|
472
|
-
{nodeType.
|
|
473
|
-
</
|
|
456
|
+
{nodeType.name}
|
|
457
|
+
</h4>
|
|
474
458
|
</div>
|
|
459
|
+
<p
|
|
460
|
+
class="flowdrop-text--xs flowdrop-text--gray flowdrop-truncate flowdrop-mt--1 flowdrop-ml--0"
|
|
461
|
+
>
|
|
462
|
+
{nodeType.description}
|
|
463
|
+
</p>
|
|
475
464
|
</div>
|
|
476
|
-
|
|
477
|
-
|
|
465
|
+
</div>
|
|
466
|
+
{/each}
|
|
478
467
|
</div>
|
|
479
|
-
</
|
|
480
|
-
|
|
481
|
-
{/
|
|
482
|
-
|
|
468
|
+
</div>
|
|
469
|
+
</details>
|
|
470
|
+
{/if}
|
|
471
|
+
{/each}
|
|
483
472
|
</div>
|
|
484
|
-
|
|
485
|
-
|
|
473
|
+
</div>
|
|
474
|
+
{/if}
|
|
475
|
+
</div>
|
|
486
476
|
|
|
487
|
-
|
|
488
|
-
|
|
477
|
+
<!-- Footer -->
|
|
478
|
+
<div class="flowdrop-sidebar__footer">
|
|
479
|
+
<div class="flowdrop-flex flowdrop-gap--4">
|
|
489
480
|
<div class="flowdrop-flex flowdrop-gap--4">
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
{/if}
|
|
503
|
-
</div>
|
|
481
|
+
{#if props.loading && props.nodes?.length === 0}
|
|
482
|
+
<span class="flowdrop-text--xs flowdrop-text--gray"
|
|
483
|
+
>Loading components...</span
|
|
484
|
+
>
|
|
485
|
+
{:else}
|
|
486
|
+
<span class="flowdrop-text--xs flowdrop-text--gray"
|
|
487
|
+
>Total: {props.nodes?.length || 0} components</span
|
|
488
|
+
>
|
|
489
|
+
<span class="flowdrop-text--xs flowdrop-text--gray"
|
|
490
|
+
>Showing: {filteredNodes.length}</span
|
|
491
|
+
>
|
|
492
|
+
{/if}
|
|
504
493
|
</div>
|
|
505
494
|
</div>
|
|
506
|
-
|
|
495
|
+
</div>
|
|
507
496
|
</aside>
|
|
508
497
|
|
|
509
498
|
<style>
|
|
@@ -527,21 +516,14 @@
|
|
|
527
516
|
height: 100%;
|
|
528
517
|
}
|
|
529
518
|
|
|
530
|
-
/* Collapsed state */
|
|
519
|
+
/* Collapsed state — fully hidden */
|
|
531
520
|
.flowdrop-sidebar--collapsed {
|
|
532
521
|
overflow: hidden;
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
.flowdrop-sidebar--collapsed .flowdrop-sidebar__header {
|
|
536
|
-
justify-content: center;
|
|
537
|
-
padding: 0.75rem 0.5rem;
|
|
522
|
+
border-right: none;
|
|
523
|
+
box-shadow: none;
|
|
538
524
|
}
|
|
539
525
|
|
|
540
526
|
/* Compact mode styles */
|
|
541
|
-
.flowdrop-sidebar--compact .flowdrop-sidebar__header {
|
|
542
|
-
padding: 0.5rem 0.75rem;
|
|
543
|
-
}
|
|
544
|
-
|
|
545
527
|
.flowdrop-sidebar--compact .flowdrop-sidebar__search {
|
|
546
528
|
padding: 0.5rem 0.75rem;
|
|
547
529
|
}
|
|
@@ -569,56 +551,6 @@
|
|
|
569
551
|
gap: 0.25rem;
|
|
570
552
|
}
|
|
571
553
|
|
|
572
|
-
/* Toggle button */
|
|
573
|
-
.flowdrop-sidebar__toggle {
|
|
574
|
-
display: flex;
|
|
575
|
-
align-items: center;
|
|
576
|
-
justify-content: center;
|
|
577
|
-
width: 2rem;
|
|
578
|
-
height: 2rem;
|
|
579
|
-
border: none;
|
|
580
|
-
background: transparent;
|
|
581
|
-
color: var(--fd-muted-foreground);
|
|
582
|
-
border-radius: var(--fd-radius-md);
|
|
583
|
-
cursor: pointer;
|
|
584
|
-
transition:
|
|
585
|
-
color var(--fd-transition-fast),
|
|
586
|
-
background-color var(--fd-transition-fast);
|
|
587
|
-
flex-shrink: 0;
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
.flowdrop-sidebar__toggle:hover {
|
|
591
|
-
color: var(--fd-foreground);
|
|
592
|
-
background-color: var(--fd-subtle);
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
.flowdrop-sidebar__toggle:focus {
|
|
596
|
-
outline: none;
|
|
597
|
-
box-shadow: 0 0 0 2px var(--fd-ring);
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
.flowdrop-sidebar__header {
|
|
601
|
-
background: var(--fd-header);
|
|
602
|
-
border-bottom: 1px solid var(--fd-border);
|
|
603
|
-
padding: 0.75rem 1rem;
|
|
604
|
-
display: var(--fd-sidebar-header-display, flex);
|
|
605
|
-
align-items: center;
|
|
606
|
-
justify-content: space-between;
|
|
607
|
-
flex-shrink: 0;
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
.flowdrop-sidebar__title {
|
|
611
|
-
display: flex;
|
|
612
|
-
align-items: center;
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
.flowdrop-sidebar__title h2 {
|
|
616
|
-
font-size: 1rem;
|
|
617
|
-
font-weight: 600;
|
|
618
|
-
margin: 0;
|
|
619
|
-
color: var(--fd-foreground);
|
|
620
|
-
}
|
|
621
|
-
|
|
622
554
|
.flowdrop-sidebar__search {
|
|
623
555
|
padding: 0.75rem 1rem;
|
|
624
556
|
background-color: var(--fd-background);
|
|
@@ -859,12 +859,22 @@
|
|
|
859
859
|
description="Use the sidebar to add components to your workflow"
|
|
860
860
|
>
|
|
861
861
|
{#snippet icon()}
|
|
862
|
-
<svg
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
862
|
+
<svg
|
|
863
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
864
|
+
width="1em"
|
|
865
|
+
height="1em"
|
|
866
|
+
viewBox="0 0 24 24"
|
|
867
|
+
fill="none"
|
|
868
|
+
stroke="currentColor"
|
|
869
|
+
stroke-width="1.5"
|
|
870
|
+
stroke-linecap="round"
|
|
871
|
+
stroke-linejoin="round"
|
|
872
|
+
>
|
|
873
|
+
<circle cx="18" cy="5" r="3" />
|
|
874
|
+
<circle cx="6" cy="12" r="3" />
|
|
875
|
+
<circle cx="18" cy="19" r="3" />
|
|
876
|
+
<line x1="8.59" y1="13.51" x2="15.42" y2="17.49" />
|
|
877
|
+
<line x1="15.41" y1="6.51" x2="8.59" y2="10.49" />
|
|
868
878
|
</svg>
|
|
869
879
|
{/snippet}
|
|
870
880
|
</CanvasBanner>
|