@dryui/ui 0.5.2 → 1.0.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/alert/{alert-root.svelte → alert.svelte} +78 -20
- package/dist/alert/alert.svelte.d.ts +15 -0
- package/dist/alert/index.d.ts +15 -14
- package/dist/alert/index.js +3 -12
- package/dist/breadcrumb/breadcrumb-link.svelte +1 -1
- package/dist/button/button.svelte +1 -1
- package/dist/card/card-root.svelte +2 -2
- package/dist/chromatic-shift/chromatic-shift.svelte +2 -2
- package/dist/code-block/code-block-button.svelte +1 -1
- package/dist/color-picker/color-picker-area.svelte +2 -2
- package/dist/color-picker/color-picker-channel-input.svelte +2 -2
- package/dist/color-picker/color-picker-input-alpha-slider.svelte +2 -2
- package/dist/color-picker/color-picker-input-hue-slider.svelte +2 -2
- package/dist/color-picker/color-picker-input.svelte +9 -9
- package/dist/color-picker/color-picker-swatch.svelte +2 -2
- package/dist/combobox/combobox-input.svelte +9 -9
- package/dist/command-palette/command-palette-item.svelte +1 -1
- package/dist/data-grid/data-grid-button-input-column.svelte +1 -1
- package/dist/diagram/diagram.svelte +222 -32
- package/dist/diagram/diagram.svelte.d.ts +1 -0
- package/dist/diagram/edge-routing.d.ts +63 -1
- package/dist/diagram/edge-routing.js +316 -26
- package/dist/diagram/layout.js +633 -62
- package/dist/diagram/types.d.ts +58 -0
- package/dist/drag-and-drop/drag-and-drop-handle.svelte +1 -1
- package/dist/drag-and-drop/drag-and-drop-item.svelte +1 -1
- package/dist/file-select/file-select-root.svelte +2 -2
- package/dist/file-upload/file-upload-dropzone.svelte +2 -2
- package/dist/gauge/gauge.svelte +1 -1
- package/dist/image-comparison/image-comparison.svelte +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1 -1
- package/dist/input/input.svelte +10 -11
- package/dist/label/label.svelte +1 -1
- package/dist/link/link.svelte +1 -1
- package/dist/list/list-item.svelte +2 -2
- package/dist/multi-select-combobox/multi-select-combobox-selection-item.svelte +9 -3
- package/dist/multi-select-combobox/multi-select-combobox-selection-remove-button.svelte +2 -0
- package/dist/navigation-menu/navigation-menu-link.svelte +1 -1
- package/dist/notification-center/notification-center-item.svelte +1 -1
- package/dist/number-input/number-input-button.svelte +3 -3
- package/dist/option-picker/context.svelte.d.ts +9 -0
- package/dist/option-picker/context.svelte.js +2 -0
- package/dist/option-picker/option-picker-item.svelte +31 -4
- package/dist/option-picker/option-picker-preview.svelte +2 -2
- package/dist/option-picker/option-picker-root.svelte +2 -2
- package/dist/phone-input/phone-input-select.svelte +2 -2
- package/dist/pin-input/pin-input-cell.svelte +1 -1
- package/dist/pin-input/pin-input-root.svelte +1 -1
- package/dist/progress/progress.svelte +1 -1
- package/dist/scroll-area/scroll-area.svelte +1 -1
- package/dist/shimmer/index.d.ts +8 -0
- package/dist/shimmer/index.js +1 -0
- package/dist/shimmer/shimmer.svelte +87 -0
- package/dist/shimmer/shimmer.svelte.d.ts +10 -0
- package/dist/sidebar/sidebar-item.svelte +1 -1
- package/dist/slider/slider-input.svelte +2 -2
- package/dist/splitter/splitter-handle.svelte +1 -1
- package/dist/table-of-contents/table-of-contents-item.svelte +1 -1
- package/dist/table-of-contents/table-of-contents-list.svelte +1 -1
- package/dist/tags-input/tags-input-root.svelte +1 -1
- package/dist/tags-input/tags-input-tag-delete-button.svelte +2 -0
- package/dist/tags-input/tags-input-tag.svelte +9 -3
- package/dist/textarea/textarea.svelte +11 -11
- package/dist/themes/default.css +31 -0
- package/dist/toast/toast-root.svelte +1 -1
- package/dist/tour/tour-root.css +3 -3
- package/dist/tree/tree-item-children.svelte +1 -1
- package/dist/tree/tree-item-label.svelte +1 -1
- package/dist/video-embed/video-embed-button.svelte +1 -1
- package/package.json +11 -750
- package/skills/dryui/SKILL.md +26 -21
- package/skills/dryui/rules/compound-components.md +3 -3
- package/skills/dryui/rules/theming.md +1 -1
- package/dist/alert/alert-button-close.svelte +0 -29
- package/dist/alert/alert-button-close.svelte.d.ts +0 -8
- package/dist/alert/alert-description.svelte +0 -28
- package/dist/alert/alert-description.svelte.d.ts +0 -8
- package/dist/alert/alert-icon.svelte +0 -26
- package/dist/alert/alert-icon.svelte.d.ts +0 -8
- package/dist/alert/alert-root.svelte.d.ts +0 -12
- package/dist/alert/alert-title.svelte +0 -29
- package/dist/alert/alert-title.svelte.d.ts +0 -8
- package/dist/alert/context.svelte.d.ts +0 -9
- package/dist/alert/context.svelte.js +0 -10
- package/dist/option-swatch-group/context.svelte.d.ts +0 -9
- package/dist/option-swatch-group/context.svelte.js +0 -2
- package/dist/option-swatch-group/index.d.ts +0 -29
- package/dist/option-swatch-group/index.js +0 -12
- package/dist/option-swatch-group/option-swatch-group-item-button.svelte +0 -214
- package/dist/option-swatch-group/option-swatch-group-item-button.svelte.d.ts +0 -12
- package/dist/option-swatch-group/option-swatch-group-label.svelte +0 -24
- package/dist/option-swatch-group/option-swatch-group-label.svelte.d.ts +0 -8
- package/dist/option-swatch-group/option-swatch-group-meta.svelte +0 -24
- package/dist/option-swatch-group/option-swatch-group-meta.svelte.d.ts +0 -8
- package/dist/option-swatch-group/option-swatch-group-root.svelte +0 -81
- package/dist/option-swatch-group/option-swatch-group-root.svelte.d.ts +0 -12
- package/dist/option-swatch-group/option-swatch-group-swatch.svelte +0 -52
- package/dist/option-swatch-group/option-swatch-group-swatch.svelte.d.ts +0 -10
|
@@ -7,9 +7,10 @@
|
|
|
7
7
|
config: DiagramConfig;
|
|
8
8
|
width?: number;
|
|
9
9
|
height?: number;
|
|
10
|
+
fit?: 'contain' | 'native';
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
let { config, width, height, class: className, ...rest }: Props = $props();
|
|
13
|
+
let { config, width, height, fit = 'contain', class: className, ...rest }: Props = $props();
|
|
13
14
|
|
|
14
15
|
const layout = $derived(computeLayout(config));
|
|
15
16
|
const vbW = $derived(width ?? layout.viewBox.width);
|
|
@@ -18,8 +19,10 @@
|
|
|
18
19
|
const uid = Math.random().toString(36).slice(2, 8);
|
|
19
20
|
</script>
|
|
20
21
|
|
|
21
|
-
<div data-diagram-container>
|
|
22
|
+
<div data-diagram-container data-fit={fit}>
|
|
22
23
|
<svg
|
|
24
|
+
width={fit === 'native' ? vbW : undefined}
|
|
25
|
+
height={fit === 'native' ? vbH : undefined}
|
|
23
26
|
viewBox="0 0 {vbW} {vbH}"
|
|
24
27
|
preserveAspectRatio="xMidYMin meet"
|
|
25
28
|
role="img"
|
|
@@ -56,6 +59,8 @@
|
|
|
56
59
|
{#if layout.clusters.length > 0}
|
|
57
60
|
<g data-part="clusters">
|
|
58
61
|
{#each layout.clusters as cluster (cluster.id)}
|
|
62
|
+
{@const ClusterIcon = cluster.iconComponent}
|
|
63
|
+
{@const labelOnLeft = cluster.labelPosition === 'left'}
|
|
59
64
|
<g data-part="cluster" data-color={cluster.color}>
|
|
60
65
|
<rect
|
|
61
66
|
data-part="cluster-box"
|
|
@@ -63,13 +68,57 @@
|
|
|
63
68
|
y={cluster.y}
|
|
64
69
|
width={cluster.width}
|
|
65
70
|
height={cluster.height}
|
|
66
|
-
rx="
|
|
71
|
+
rx="16"
|
|
67
72
|
data-dashed={cluster.dashed || undefined}
|
|
68
73
|
/>
|
|
69
74
|
{#if cluster.label}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
75
|
+
{#if labelOnLeft}
|
|
76
|
+
{@const lcx = cluster.x + 16}
|
|
77
|
+
{@const lcy = cluster.y + cluster.height / 2}
|
|
78
|
+
{#if ClusterIcon}
|
|
79
|
+
{@const lw = Math.max(cluster.height - 32, 80)}
|
|
80
|
+
<g transform="rotate(-90 {lcx} {lcy})">
|
|
81
|
+
<foreignObject x={lcx - lw / 2} y={lcy - 12} width={lw} height={24}>
|
|
82
|
+
<div
|
|
83
|
+
xmlns="http://www.w3.org/1999/xhtml"
|
|
84
|
+
data-part="cluster-label-row"
|
|
85
|
+
data-color={cluster.color}
|
|
86
|
+
>
|
|
87
|
+
<ClusterIcon size={14} aria-hidden="true" />
|
|
88
|
+
<span>{cluster.label}</span>
|
|
89
|
+
</div>
|
|
90
|
+
</foreignObject>
|
|
91
|
+
</g>
|
|
92
|
+
{:else}
|
|
93
|
+
<text
|
|
94
|
+
data-part="cluster-label"
|
|
95
|
+
x={lcx}
|
|
96
|
+
y={lcy}
|
|
97
|
+
text-anchor="middle"
|
|
98
|
+
transform="rotate(-90 {lcx} {lcy})">{cluster.label}</text
|
|
99
|
+
>
|
|
100
|
+
{/if}
|
|
101
|
+
{:else if ClusterIcon}
|
|
102
|
+
<foreignObject
|
|
103
|
+
x={cluster.x + 16}
|
|
104
|
+
y={cluster.y + 10}
|
|
105
|
+
width={Math.max(cluster.width - 32, 80)}
|
|
106
|
+
height={24}
|
|
107
|
+
>
|
|
108
|
+
<div
|
|
109
|
+
xmlns="http://www.w3.org/1999/xhtml"
|
|
110
|
+
data-part="cluster-label-row"
|
|
111
|
+
data-color={cluster.color}
|
|
112
|
+
>
|
|
113
|
+
<ClusterIcon size={14} aria-hidden="true" />
|
|
114
|
+
<span>{cluster.label}</span>
|
|
115
|
+
</div>
|
|
116
|
+
</foreignObject>
|
|
117
|
+
{:else}
|
|
118
|
+
<text data-part="cluster-label" x={cluster.x + 20} y={cluster.y + 22}
|
|
119
|
+
>{cluster.label}</text
|
|
120
|
+
>
|
|
121
|
+
{/if}
|
|
73
122
|
{/if}
|
|
74
123
|
</g>
|
|
75
124
|
{/each}
|
|
@@ -214,12 +263,13 @@
|
|
|
214
263
|
<!-- Layer 2: Edges -->
|
|
215
264
|
<g data-part="edges">
|
|
216
265
|
{#each layout.edges as edge, index (`${edge.from}:${edge.to}:${index}`)}
|
|
266
|
+
{@const isEntry = edge.kind === 'entry'}
|
|
217
267
|
{@const markerEnd =
|
|
218
|
-
edge.arrow === 'end' || edge.arrow === 'both'
|
|
268
|
+
!isEntry && (edge.arrow === 'end' || edge.arrow === 'both')
|
|
219
269
|
? `url(#dry-diagram-${uid}-arrow-${edge.color})`
|
|
220
270
|
: undefined}
|
|
221
271
|
{@const markerStart =
|
|
222
|
-
edge.arrow === 'start' || edge.arrow === 'both'
|
|
272
|
+
!isEntry && (edge.arrow === 'start' || edge.arrow === 'both')
|
|
223
273
|
? `url(#dry-diagram-${uid}-arrow-${edge.color})`
|
|
224
274
|
: undefined}
|
|
225
275
|
{@const isSelfLoop = edge.from === edge.to}
|
|
@@ -243,9 +293,60 @@
|
|
|
243
293
|
{/each}
|
|
244
294
|
</g>
|
|
245
295
|
|
|
296
|
+
<!-- Layer 2b: Waypoints (cards sitting on edges) -->
|
|
297
|
+
{#if layout.waypoints.length > 0}
|
|
298
|
+
<g data-part="waypoints">
|
|
299
|
+
{#each layout.waypoints as wp (wp.id)}
|
|
300
|
+
{@const WpIcon = wp.iconComponent}
|
|
301
|
+
<g
|
|
302
|
+
data-part="waypoint"
|
|
303
|
+
data-variant={wp.variant}
|
|
304
|
+
data-color={wp.color}
|
|
305
|
+
transform="translate({wp.x},{wp.y})"
|
|
306
|
+
>
|
|
307
|
+
<rect
|
|
308
|
+
data-part="node-box"
|
|
309
|
+
width={wp.width}
|
|
310
|
+
height={wp.height}
|
|
311
|
+
rx={wp.variant === 'pill' ? wp.height / 2 : 16}
|
|
312
|
+
/>
|
|
313
|
+
{#if wp.variant === 'filled'}
|
|
314
|
+
<rect
|
|
315
|
+
data-part="node-texture"
|
|
316
|
+
width={wp.width}
|
|
317
|
+
height={wp.height}
|
|
318
|
+
rx={16}
|
|
319
|
+
fill="url(#dry-diagram-{uid}-dots)"
|
|
320
|
+
/>
|
|
321
|
+
{/if}
|
|
322
|
+
<foreignObject x="0" y="0" width={wp.width} height={wp.height}>
|
|
323
|
+
<div
|
|
324
|
+
data-part="node-content"
|
|
325
|
+
data-has-description={wp.description ? '' : undefined}
|
|
326
|
+
data-has-icon-component={WpIcon ? '' : undefined}
|
|
327
|
+
>
|
|
328
|
+
{#if WpIcon}
|
|
329
|
+
<span data-part="node-icon" data-icon-svg=""
|
|
330
|
+
><WpIcon size={22} aria-hidden="true" /></span
|
|
331
|
+
>
|
|
332
|
+
{:else if wp.icon}
|
|
333
|
+
<span data-part="node-icon">{wp.icon}</span>
|
|
334
|
+
{/if}
|
|
335
|
+
<span data-part="node-label">{wp.label}</span>
|
|
336
|
+
{#if wp.description}
|
|
337
|
+
<span data-part="node-description">{wp.description}</span>
|
|
338
|
+
{/if}
|
|
339
|
+
</div>
|
|
340
|
+
</foreignObject>
|
|
341
|
+
</g>
|
|
342
|
+
{/each}
|
|
343
|
+
</g>
|
|
344
|
+
{/if}
|
|
345
|
+
|
|
246
346
|
<!-- Layer 3: Nodes -->
|
|
247
347
|
<g data-part="nodes">
|
|
248
348
|
{#each layout.nodes as node (node.id)}
|
|
349
|
+
{@const NodeIcon = node.iconComponent}
|
|
249
350
|
<g
|
|
250
351
|
data-part="node"
|
|
251
352
|
data-variant={node.variant}
|
|
@@ -270,8 +371,16 @@
|
|
|
270
371
|
/>
|
|
271
372
|
{/if}
|
|
272
373
|
<foreignObject x="0" y="0" width={node.width} height={node.height}>
|
|
273
|
-
<div
|
|
274
|
-
|
|
374
|
+
<div
|
|
375
|
+
data-part="node-content"
|
|
376
|
+
data-has-description={node.description ? '' : undefined}
|
|
377
|
+
data-has-icon-component={NodeIcon ? '' : undefined}
|
|
378
|
+
>
|
|
379
|
+
{#if NodeIcon}
|
|
380
|
+
<span data-part="node-icon" data-icon-svg=""
|
|
381
|
+
><NodeIcon size={22} aria-hidden="true" /></span
|
|
382
|
+
>
|
|
383
|
+
{:else if node.icon}
|
|
275
384
|
<span data-part="node-icon">{node.icon}</span>
|
|
276
385
|
{/if}
|
|
277
386
|
<span data-part="node-label">{node.label}</span>
|
|
@@ -299,9 +408,31 @@
|
|
|
299
408
|
/* ── Container ──────────────────────────────────── */
|
|
300
409
|
[data-diagram-container] {
|
|
301
410
|
display: grid;
|
|
411
|
+
grid-template-columns: minmax(0, 1fr);
|
|
412
|
+
align-content: start;
|
|
413
|
+
container-type: inline-size;
|
|
414
|
+
container-name: dry-diagram;
|
|
302
415
|
min-height: 120px;
|
|
303
416
|
max-block-size: var(--dry-diagram-max-height, none);
|
|
304
|
-
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
[data-diagram-container][data-fit='native'] {
|
|
420
|
+
grid-template-columns: auto;
|
|
421
|
+
justify-content: start;
|
|
422
|
+
overflow-x: auto;
|
|
423
|
+
overflow-y: hidden;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
@container dry-diagram (max-width: 480px) {
|
|
427
|
+
[data-part='node-content'] {
|
|
428
|
+
padding: 12px 14px;
|
|
429
|
+
}
|
|
430
|
+
[data-part='node-content'][data-has-description] {
|
|
431
|
+
padding: 14px 16px;
|
|
432
|
+
}
|
|
433
|
+
[data-part='node-description'] {
|
|
434
|
+
display: none;
|
|
435
|
+
}
|
|
305
436
|
}
|
|
306
437
|
|
|
307
438
|
/* ── SVG root ───────────────────────────────────── */
|
|
@@ -309,10 +440,7 @@
|
|
|
309
440
|
--_node-bg: var(--dry-diagram-node-bg, var(--dry-color-bg-base));
|
|
310
441
|
--_node-border: var(--dry-diagram-node-border, var(--dry-color-stroke-weak));
|
|
311
442
|
--_node-color: var(--dry-diagram-node-color, var(--dry-color-text-strong));
|
|
312
|
-
--_edge-color: var(
|
|
313
|
-
--dry-diagram-edge-color,
|
|
314
|
-
color-mix(in srgb, var(--dry-color-text-strong) 24%, var(--dry-color-bg-base))
|
|
315
|
-
);
|
|
443
|
+
--_edge-color: var(--dry-diagram-edge-color, var(--dry-color-text-strong));
|
|
316
444
|
--_cluster-bg: var(
|
|
317
445
|
--dry-diagram-cluster-bg,
|
|
318
446
|
color-mix(in srgb, var(--dry-color-fill) 30%, transparent)
|
|
@@ -371,42 +499,62 @@
|
|
|
371
499
|
[data-part='node-content'] {
|
|
372
500
|
display: grid;
|
|
373
501
|
place-items: center;
|
|
374
|
-
gap:
|
|
375
|
-
padding:
|
|
502
|
+
gap: 8px;
|
|
503
|
+
padding: 16px 22px;
|
|
376
504
|
height: 100%;
|
|
377
505
|
box-sizing: border-box;
|
|
506
|
+
font-family: var(--dry-font-sans);
|
|
378
507
|
}
|
|
379
508
|
|
|
380
509
|
[data-part='node-label'] {
|
|
381
|
-
font-
|
|
382
|
-
font-
|
|
383
|
-
font-weight: 500;
|
|
510
|
+
font-size: 15px;
|
|
511
|
+
font-weight: 600;
|
|
384
512
|
color: var(--_node-color);
|
|
385
513
|
text-align: center;
|
|
386
|
-
line-height: 1.
|
|
387
|
-
letter-spacing: 0.
|
|
514
|
+
line-height: 1.2;
|
|
515
|
+
letter-spacing: 0.005em;
|
|
388
516
|
white-space: nowrap;
|
|
389
517
|
}
|
|
390
518
|
|
|
391
519
|
[data-part='node-icon'] {
|
|
392
|
-
font-size:
|
|
520
|
+
font-size: 18px;
|
|
393
521
|
line-height: 1;
|
|
394
522
|
text-align: center;
|
|
395
523
|
}
|
|
396
524
|
|
|
525
|
+
[data-part='node-icon'][data-icon-svg] {
|
|
526
|
+
display: grid;
|
|
527
|
+
place-items: center;
|
|
528
|
+
color: var(--_node-color);
|
|
529
|
+
line-height: 0;
|
|
530
|
+
}
|
|
531
|
+
|
|
397
532
|
[data-part='node-description'] {
|
|
398
|
-
font-
|
|
399
|
-
font-size: 11px;
|
|
533
|
+
font-size: 12px;
|
|
400
534
|
font-weight: 400;
|
|
401
535
|
color: var(--_text-muted);
|
|
402
536
|
text-align: center;
|
|
403
|
-
line-height: 1.
|
|
537
|
+
line-height: 1.35;
|
|
404
538
|
}
|
|
405
539
|
|
|
406
540
|
[data-part='node-content'][data-has-description] {
|
|
407
|
-
padding:
|
|
541
|
+
padding: 18px 22px;
|
|
542
|
+
gap: 6px;
|
|
408
543
|
text-align: left;
|
|
409
544
|
place-items: start;
|
|
545
|
+
grid-template-rows: auto auto 1fr;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
[data-part='node-content'][data-has-description] [data-part='node-icon'] {
|
|
549
|
+
padding-block-end: 4px;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
[data-part='node-content'][data-has-description] [data-part='node-label'] {
|
|
553
|
+
font-size: 16px;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
[data-part='node-content'][data-has-description] [data-part='node-description'] {
|
|
557
|
+
text-align: left;
|
|
410
558
|
}
|
|
411
559
|
|
|
412
560
|
/* ── Node variant: outlined ──────────────────── */
|
|
@@ -422,27 +570,38 @@
|
|
|
422
570
|
}
|
|
423
571
|
|
|
424
572
|
/* ── Node colors via custom property indirection ─ */
|
|
425
|
-
[data-part='node'][data-color='brand']
|
|
573
|
+
[data-part='node'][data-color='brand'],
|
|
574
|
+
[data-part='waypoint'][data-color='brand'] {
|
|
426
575
|
--_node-border: var(--dry-color-stroke-brand);
|
|
427
576
|
--_node-color: var(--dry-color-text-brand);
|
|
428
577
|
}
|
|
429
|
-
[data-part='node'][data-color='success']
|
|
578
|
+
[data-part='node'][data-color='success'],
|
|
579
|
+
[data-part='waypoint'][data-color='success'] {
|
|
430
580
|
--_node-border: var(--dry-color-stroke-success);
|
|
431
581
|
--_node-color: var(--dry-color-text-success);
|
|
432
582
|
}
|
|
433
|
-
[data-part='node'][data-color='warning']
|
|
583
|
+
[data-part='node'][data-color='warning'],
|
|
584
|
+
[data-part='waypoint'][data-color='warning'] {
|
|
434
585
|
--_node-border: var(--dry-color-stroke-warning);
|
|
435
586
|
--_node-color: var(--dry-color-text-warning);
|
|
436
587
|
}
|
|
437
|
-
[data-part='node'][data-color='error']
|
|
588
|
+
[data-part='node'][data-color='error'],
|
|
589
|
+
[data-part='waypoint'][data-color='error'] {
|
|
438
590
|
--_node-border: var(--dry-color-stroke-error);
|
|
439
591
|
--_node-color: var(--dry-color-text-error);
|
|
440
592
|
}
|
|
441
|
-
[data-part='node'][data-color='info']
|
|
593
|
+
[data-part='node'][data-color='info'],
|
|
594
|
+
[data-part='waypoint'][data-color='info'] {
|
|
442
595
|
--_node-border: var(--dry-color-stroke-info);
|
|
443
596
|
--_node-color: var(--dry-color-text-info);
|
|
444
597
|
}
|
|
445
598
|
|
|
599
|
+
[data-part='waypoint'] [data-part='node-box'] {
|
|
600
|
+
fill: var(--_node-bg);
|
|
601
|
+
stroke: var(--_node-border);
|
|
602
|
+
stroke-width: 2;
|
|
603
|
+
}
|
|
604
|
+
|
|
446
605
|
/* ── Node states ────────────────────────────────── */
|
|
447
606
|
[data-part='node'][data-state='active'] [data-part='node-box'] {
|
|
448
607
|
stroke-width: 2;
|
|
@@ -529,6 +688,37 @@
|
|
|
529
688
|
fill: var(--_text-muted);
|
|
530
689
|
}
|
|
531
690
|
|
|
691
|
+
[data-part='cluster-label-row'] {
|
|
692
|
+
display: grid;
|
|
693
|
+
grid-template-columns: auto auto;
|
|
694
|
+
align-items: center;
|
|
695
|
+
justify-content: start;
|
|
696
|
+
gap: 8px;
|
|
697
|
+
font-family: var(--dry-font-sans);
|
|
698
|
+
font-size: 12px;
|
|
699
|
+
font-weight: 600;
|
|
700
|
+
color: var(--_text-muted);
|
|
701
|
+
letter-spacing: 0.04em;
|
|
702
|
+
text-transform: uppercase;
|
|
703
|
+
line-height: 1;
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
[data-part='cluster-label-row'][data-color='brand'] {
|
|
707
|
+
color: var(--dry-color-text-brand);
|
|
708
|
+
}
|
|
709
|
+
[data-part='cluster-label-row'][data-color='success'] {
|
|
710
|
+
color: var(--dry-color-text-success);
|
|
711
|
+
}
|
|
712
|
+
[data-part='cluster-label-row'][data-color='warning'] {
|
|
713
|
+
color: var(--dry-color-text-warning);
|
|
714
|
+
}
|
|
715
|
+
[data-part='cluster-label-row'][data-color='error'] {
|
|
716
|
+
color: var(--dry-color-text-error);
|
|
717
|
+
}
|
|
718
|
+
[data-part='cluster-label-row'][data-color='info'] {
|
|
719
|
+
color: var(--dry-color-text-info);
|
|
720
|
+
}
|
|
721
|
+
|
|
532
722
|
/* ── Regions ────────────────────────────────────── */
|
|
533
723
|
[data-part='region-box'] {
|
|
534
724
|
fill: var(--_cluster-bg);
|
|
@@ -1,9 +1,71 @@
|
|
|
1
1
|
import type { DiagramEdge, DiagramDirection, PositionedEdge } from './types.js';
|
|
2
|
+
/** Minimum distance (in path units, measured along the polyline) between a
|
|
3
|
+
* forward edge label and a directed-cluster boundary. Cross-boundary edges
|
|
4
|
+
* whose natural midpoint sits closer than this to the cluster are slid along
|
|
5
|
+
* the polyline toward the outside endpoint. */
|
|
6
|
+
export declare const LABEL_BORDER_AVOID_PX = 28;
|
|
7
|
+
interface Point {
|
|
8
|
+
x: number;
|
|
9
|
+
y: number;
|
|
10
|
+
}
|
|
11
|
+
export interface EdgeRouteBounds {
|
|
12
|
+
minX: number;
|
|
13
|
+
minY: number;
|
|
14
|
+
maxX: number;
|
|
15
|
+
maxY: number;
|
|
16
|
+
}
|
|
17
|
+
export interface ComputedEdges {
|
|
18
|
+
edges: PositionedEdge[];
|
|
19
|
+
collapsed: (Point[] | null)[];
|
|
20
|
+
}
|
|
21
|
+
export interface ComputeEdgePathsOptions {
|
|
22
|
+
cornerRadius?: number;
|
|
23
|
+
reversedEdges?: Set<string>;
|
|
24
|
+
bounds?: EdgeRouteBounds;
|
|
25
|
+
backEdgeLaneGap?: number;
|
|
26
|
+
/** Set of node IDs that are super-nodes representing directed-cluster
|
|
27
|
+
* boundaries. Forward edge labels touching a super-node endpoint are
|
|
28
|
+
* biased away from that side along the polyline. */
|
|
29
|
+
superNodeIds?: Set<string>;
|
|
30
|
+
/** For cross-boundary back edges only: optionally anchor source and/or
|
|
31
|
+
* target to a different node ID than the edge's `from`/`to`. The layered
|
|
32
|
+
* orchestrator uses this to re-anchor a cross-boundary back edge from
|
|
33
|
+
* the cluster super-node to a specific inner node. The override is
|
|
34
|
+
* applied only when the edge is in `reversedEdges`, so forward
|
|
35
|
+
* cross-boundary edges keep super-node anchoring. */
|
|
36
|
+
backEdgeAnchorOverrides?: Map<string, {
|
|
37
|
+
source?: string;
|
|
38
|
+
target?: string;
|
|
39
|
+
}>;
|
|
40
|
+
}
|
|
2
41
|
export declare function computeEdgePaths(edges: DiagramEdge[], positions: Map<string, {
|
|
3
42
|
x: number;
|
|
4
43
|
y: number;
|
|
5
44
|
}>, nodeDims: Map<string, {
|
|
6
45
|
w: number;
|
|
7
46
|
h: number;
|
|
8
|
-
}>, direction: DiagramDirection):
|
|
47
|
+
}>, direction: DiagramDirection, opts?: ComputeEdgePathsOptions): ComputedEdges;
|
|
48
|
+
declare function buildPathFromCollapsed(collapsed: Point[], cornerRadius?: number): string;
|
|
49
|
+
declare function collapsePoints(points: Point[]): Point[];
|
|
50
|
+
export interface PointAtFraction {
|
|
51
|
+
point: Point;
|
|
52
|
+
segmentIndex: number;
|
|
53
|
+
axis: 'h' | 'v';
|
|
54
|
+
}
|
|
55
|
+
export declare function getPointAtFraction(collapsed: Point[], t: number): PointAtFraction;
|
|
56
|
+
export interface WaypointBox {
|
|
57
|
+
x: number;
|
|
58
|
+
y: number;
|
|
59
|
+
width: number;
|
|
60
|
+
height: number;
|
|
61
|
+
}
|
|
62
|
+
/** Split a collapsed polyline at the entry/exit intersections with a box centered on a point.
|
|
63
|
+
* The box is placed perpendicular to the segment containing the split point, so the polyline
|
|
64
|
+
* enters one side of the box and exits the opposite side. Returns null if the split is degenerate.
|
|
65
|
+
*/
|
|
66
|
+
export declare function splitCollapsedAtBox(collapsed: Point[], segmentIndex: number, box: WaypointBox, axis: 'h' | 'v'): {
|
|
67
|
+
entry: Point[];
|
|
68
|
+
exit: Point[];
|
|
69
|
+
} | null;
|
|
70
|
+
export { collapsePoints, buildPathFromCollapsed };
|
|
9
71
|
export declare function emptyEdge(edge: DiagramEdge): PositionedEdge;
|