@flowdrop/flowdrop 1.3.0 → 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/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 +224 -314
- package/dist/components/nodes/SimpleNode.stories.svelte +64 -0
- package/dist/components/nodes/SimpleNode.svelte +27 -11
- package/dist/components/nodes/SquareNode.stories.svelte +45 -0
- package/dist/components/nodes/SquareNode.svelte +27 -11
- package/dist/components/nodes/WorkflowNode.stories.svelte +63 -0
- 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/package.json +1 -1
|
@@ -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,64 +204,81 @@
|
|
|
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
283
|
<svg
|
|
280
284
|
xmlns="http://www.w3.org/2000/svg"
|
|
@@ -287,117 +291,131 @@
|
|
|
287
291
|
stroke-linecap="round"
|
|
288
292
|
stroke-linejoin="round"
|
|
289
293
|
>
|
|
290
|
-
<
|
|
291
|
-
|
|
292
|
-
/>
|
|
293
|
-
<polyline points="3.27 6.96 12 12.01 20.73 6.96" />
|
|
294
|
-
<line x1="12" y1="22.08" x2="12" y2="12" />
|
|
294
|
+
<circle cx="11" cy="11" r="8" />
|
|
295
|
+
<line x1="21" y1="21" x2="16.65" y2="16.65" />
|
|
295
296
|
</svg>
|
|
296
297
|
</div>
|
|
297
|
-
<h3 class="flowdrop-hero__title">No
|
|
298
|
+
<h3 class="flowdrop-hero__title">No components found</h3>
|
|
298
299
|
<p class="flowdrop-hero__description">
|
|
299
|
-
|
|
300
|
+
Try adjusting your search
|
|
300
301
|
</p>
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
<div class="flowdrop-divider">
|
|
308
|
-
<h3 class="flowdrop-divider__text">Search Results</h3>
|
|
302
|
+
{#if props.loading}
|
|
303
|
+
<div class="flowdrop-mb--4">
|
|
304
|
+
<LoadingSpinner size="sm" text="Loading components..." />
|
|
305
|
+
</div>
|
|
306
|
+
{/if}
|
|
307
|
+
</div>
|
|
309
308
|
</div>
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
stroke-linejoin="round"
|
|
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"
|
|
324
322
|
>
|
|
325
|
-
|
|
326
|
-
<
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
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>
|
|
336
341
|
</div>
|
|
337
|
-
|
|
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>
|
|
338
348
|
</div>
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
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)}
|
|
351
368
|
<div
|
|
352
|
-
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
|
+
}}
|
|
353
381
|
>
|
|
354
|
-
<!-- Node Type Icon with Squircle Background -->
|
|
355
382
|
<span
|
|
356
|
-
class="
|
|
357
|
-
style="
|
|
383
|
+
class="fd-sidebar-flat-dot"
|
|
384
|
+
style="background: {getCategoryColorToken(
|
|
358
385
|
nodeType.category,
|
|
359
386
|
)}"
|
|
360
|
-
>
|
|
361
|
-
|
|
362
|
-
icon={getNodeIcon(nodeType.icon, nodeType.category)}
|
|
363
|
-
/>
|
|
364
|
-
</span>
|
|
365
|
-
|
|
366
|
-
<!-- Node Type Info - Icon and Title only -->
|
|
367
|
-
<h4
|
|
368
|
-
class="flowdrop-text--sm flowdrop-font--medium flowdrop-truncate flowdrop-flex--1"
|
|
369
|
-
>
|
|
370
|
-
{nodeType.name}
|
|
371
|
-
</h4>
|
|
387
|
+
></span>
|
|
388
|
+
<span class="fd-sidebar-flat-name">{nodeType.name}</span>
|
|
372
389
|
</div>
|
|
373
|
-
|
|
374
|
-
|
|
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)}"
|
|
375
405
|
>
|
|
376
|
-
{
|
|
377
|
-
</
|
|
406
|
+
<Icon icon={getCategoryIcon(category)} />
|
|
407
|
+
</span>
|
|
408
|
+
<span>{getCategoryDisplayName(category)}</span>
|
|
378
409
|
</div>
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
</div>
|
|
382
|
-
{/if}
|
|
383
|
-
</div>
|
|
384
|
-
{:else}
|
|
385
|
-
<!-- Show categories with details when no search is active -->
|
|
386
|
-
<div class="flowdrop-p--4">
|
|
387
|
-
<!-- Category-specific details -->
|
|
388
|
-
<div class="flowdrop-category-list">
|
|
389
|
-
{#each categories as category (category)}
|
|
390
|
-
{@const categoryNodes = getFilteredNodesForCategory(category)}
|
|
391
|
-
{#if categoryNodes.length > 0}
|
|
392
|
-
<!-- Flat style: label + dot+name rows (shown/hidden via CSS token) -->
|
|
393
|
-
<div class="fd-sidebar-flat-section">
|
|
394
|
-
<div class="fd-sidebar-flat-category">
|
|
395
|
-
{getCategoryDisplayName(category).toUpperCase()}
|
|
410
|
+
<div class="flowdrop-badge flowdrop-badge--secondary">
|
|
411
|
+
{categoryNodes.length}
|
|
396
412
|
</div>
|
|
397
|
-
|
|
413
|
+
</summary>
|
|
414
|
+
<div class="flowdrop-details__content">
|
|
415
|
+
<div class="flowdrop-node-list">
|
|
398
416
|
{#each categoryNodes as nodeType (nodeType.id)}
|
|
399
417
|
<div
|
|
400
|
-
class="
|
|
418
|
+
class="flowdrop-card flowdrop-card--compact flowdrop-node-item"
|
|
401
419
|
draggable="true"
|
|
402
420
|
ondragstart={(e) => handleNodeDragStart(e, nodeType)}
|
|
403
421
|
onclick={() => handleNodeClick(nodeType)}
|
|
@@ -410,122 +428,71 @@
|
|
|
410
428
|
}
|
|
411
429
|
}}
|
|
412
430
|
>
|
|
413
|
-
<span
|
|
414
|
-
class="fd-sidebar-flat-dot"
|
|
415
|
-
style="background: {getCategoryColorToken(
|
|
416
|
-
nodeType.category,
|
|
417
|
-
)}"
|
|
418
|
-
></span>
|
|
419
|
-
<span class="fd-sidebar-flat-name">{nodeType.name}</span
|
|
420
|
-
>
|
|
421
|
-
</div>
|
|
422
|
-
{/each}
|
|
423
|
-
</div>
|
|
424
|
-
</div>
|
|
425
|
-
<!-- Card style: <details> accordion (shown/hidden via CSS token) -->
|
|
426
|
-
<details
|
|
427
|
-
class="flowdrop-details fd-sidebar-card-section"
|
|
428
|
-
open={props.categoriesDefaultOpen || undefined}
|
|
429
|
-
>
|
|
430
|
-
<summary class="flowdrop-details__summary">
|
|
431
|
-
<div
|
|
432
|
-
class="flowdrop-flex flowdrop-gap--2 flowdrop-items--center"
|
|
433
|
-
>
|
|
434
|
-
<span
|
|
435
|
-
class="flowdrop-node-icon"
|
|
436
|
-
style="--_icon-color: {getCategoryColorToken(category)}"
|
|
437
|
-
>
|
|
438
|
-
<Icon icon={getCategoryIcon(category)} />
|
|
439
|
-
</span>
|
|
440
|
-
<span>{getCategoryDisplayName(category)}</span>
|
|
441
|
-
</div>
|
|
442
|
-
<div class="flowdrop-badge flowdrop-badge--secondary">
|
|
443
|
-
{categoryNodes.length}
|
|
444
|
-
</div>
|
|
445
|
-
</summary>
|
|
446
|
-
<div class="flowdrop-details__content">
|
|
447
|
-
<div class="flowdrop-node-list">
|
|
448
|
-
{#each categoryNodes as nodeType (nodeType.id)}
|
|
449
431
|
<div
|
|
450
|
-
class="flowdrop-
|
|
451
|
-
draggable="true"
|
|
452
|
-
ondragstart={(e) => handleNodeDragStart(e, nodeType)}
|
|
453
|
-
onclick={() => handleNodeClick(nodeType)}
|
|
454
|
-
role="button"
|
|
455
|
-
tabindex="0"
|
|
456
|
-
onkeydown={(e) => {
|
|
457
|
-
if (e.key === "Enter" || e.key === " ") {
|
|
458
|
-
e.preventDefault();
|
|
459
|
-
handleNodeClick(nodeType);
|
|
460
|
-
}
|
|
461
|
-
}}
|
|
432
|
+
class="flowdrop-card__body flowdrop-p--1 flowdrop-py--1"
|
|
462
433
|
>
|
|
463
434
|
<div
|
|
464
|
-
class="flowdrop-
|
|
435
|
+
class="flowdrop-flex flowdrop-gap--2 flowdrop-items--center"
|
|
465
436
|
>
|
|
466
|
-
|
|
467
|
-
|
|
437
|
+
<!-- Node Type Icon with Squircle Background -->
|
|
438
|
+
<span
|
|
439
|
+
class="flowdrop-node-icon"
|
|
440
|
+
style="--_icon-color: {getCategoryColorToken(
|
|
441
|
+
nodeType.category,
|
|
442
|
+
)}"
|
|
468
443
|
>
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
style="--_icon-color: {getCategoryColorToken(
|
|
444
|
+
<Icon
|
|
445
|
+
icon={getNodeIcon(
|
|
446
|
+
nodeType.icon,
|
|
473
447
|
nodeType.category,
|
|
474
|
-
)}
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
/>
|
|
482
|
-
</span>
|
|
483
|
-
|
|
484
|
-
<!-- Node Type Info - Icon and Title only -->
|
|
485
|
-
<h4
|
|
486
|
-
class="flowdrop-text--sm flowdrop-font--medium flowdrop-truncate flowdrop-flex--1"
|
|
487
|
-
>
|
|
488
|
-
{nodeType.name}
|
|
489
|
-
</h4>
|
|
490
|
-
</div>
|
|
491
|
-
<p
|
|
492
|
-
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"
|
|
493
455
|
>
|
|
494
|
-
{nodeType.
|
|
495
|
-
</
|
|
456
|
+
{nodeType.name}
|
|
457
|
+
</h4>
|
|
496
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>
|
|
497
464
|
</div>
|
|
498
|
-
|
|
499
|
-
|
|
465
|
+
</div>
|
|
466
|
+
{/each}
|
|
500
467
|
</div>
|
|
501
|
-
</
|
|
502
|
-
|
|
503
|
-
{/
|
|
504
|
-
|
|
468
|
+
</div>
|
|
469
|
+
</details>
|
|
470
|
+
{/if}
|
|
471
|
+
{/each}
|
|
505
472
|
</div>
|
|
506
|
-
|
|
507
|
-
|
|
473
|
+
</div>
|
|
474
|
+
{/if}
|
|
475
|
+
</div>
|
|
508
476
|
|
|
509
|
-
|
|
510
|
-
|
|
477
|
+
<!-- Footer -->
|
|
478
|
+
<div class="flowdrop-sidebar__footer">
|
|
479
|
+
<div class="flowdrop-flex flowdrop-gap--4">
|
|
511
480
|
<div class="flowdrop-flex flowdrop-gap--4">
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
{/if}
|
|
525
|
-
</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}
|
|
526
493
|
</div>
|
|
527
494
|
</div>
|
|
528
|
-
|
|
495
|
+
</div>
|
|
529
496
|
</aside>
|
|
530
497
|
|
|
531
498
|
<style>
|
|
@@ -549,21 +516,14 @@
|
|
|
549
516
|
height: 100%;
|
|
550
517
|
}
|
|
551
518
|
|
|
552
|
-
/* Collapsed state */
|
|
519
|
+
/* Collapsed state — fully hidden */
|
|
553
520
|
.flowdrop-sidebar--collapsed {
|
|
554
521
|
overflow: hidden;
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
.flowdrop-sidebar--collapsed .flowdrop-sidebar__header {
|
|
558
|
-
justify-content: center;
|
|
559
|
-
padding: 0.75rem 0.5rem;
|
|
522
|
+
border-right: none;
|
|
523
|
+
box-shadow: none;
|
|
560
524
|
}
|
|
561
525
|
|
|
562
526
|
/* Compact mode styles */
|
|
563
|
-
.flowdrop-sidebar--compact .flowdrop-sidebar__header {
|
|
564
|
-
padding: 0.5rem 0.75rem;
|
|
565
|
-
}
|
|
566
|
-
|
|
567
527
|
.flowdrop-sidebar--compact .flowdrop-sidebar__search {
|
|
568
528
|
padding: 0.5rem 0.75rem;
|
|
569
529
|
}
|
|
@@ -591,56 +551,6 @@
|
|
|
591
551
|
gap: 0.25rem;
|
|
592
552
|
}
|
|
593
553
|
|
|
594
|
-
/* Toggle button */
|
|
595
|
-
.flowdrop-sidebar__toggle {
|
|
596
|
-
display: flex;
|
|
597
|
-
align-items: center;
|
|
598
|
-
justify-content: center;
|
|
599
|
-
width: 2rem;
|
|
600
|
-
height: 2rem;
|
|
601
|
-
border: none;
|
|
602
|
-
background: transparent;
|
|
603
|
-
color: var(--fd-muted-foreground);
|
|
604
|
-
border-radius: var(--fd-radius-md);
|
|
605
|
-
cursor: pointer;
|
|
606
|
-
transition:
|
|
607
|
-
color var(--fd-transition-fast),
|
|
608
|
-
background-color var(--fd-transition-fast);
|
|
609
|
-
flex-shrink: 0;
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
.flowdrop-sidebar__toggle:hover {
|
|
613
|
-
color: var(--fd-foreground);
|
|
614
|
-
background-color: var(--fd-subtle);
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
.flowdrop-sidebar__toggle:focus {
|
|
618
|
-
outline: none;
|
|
619
|
-
box-shadow: 0 0 0 2px var(--fd-ring);
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
.flowdrop-sidebar__header {
|
|
623
|
-
background: var(--fd-header);
|
|
624
|
-
border-bottom: 1px solid var(--fd-border);
|
|
625
|
-
padding: 0.75rem 1rem;
|
|
626
|
-
display: var(--fd-sidebar-header-display, flex);
|
|
627
|
-
align-items: center;
|
|
628
|
-
justify-content: space-between;
|
|
629
|
-
flex-shrink: 0;
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
.flowdrop-sidebar__title {
|
|
633
|
-
display: flex;
|
|
634
|
-
align-items: center;
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
.flowdrop-sidebar__title h2 {
|
|
638
|
-
font-size: 1rem;
|
|
639
|
-
font-weight: 600;
|
|
640
|
-
margin: 0;
|
|
641
|
-
color: var(--fd-foreground);
|
|
642
|
-
}
|
|
643
|
-
|
|
644
554
|
.flowdrop-sidebar__search {
|
|
645
555
|
padding: 0.75rem 1rem;
|
|
646
556
|
background-color: var(--fd-background);
|