@dryui/ui 0.5.2 → 1.1.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 +9 -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 +230 -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 +647 -62
- package/dist/diagram/types.d.ts +55 -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: var(--dry-diagram-node-padding-mobile, 12px 14px);
|
|
429
|
+
}
|
|
430
|
+
[data-part='node-content'][data-has-description] {
|
|
431
|
+
padding: var(--dry-diagram-node-padding-with-description-mobile, 14px 16px);
|
|
432
|
+
}
|
|
433
|
+
[data-part='node-description'] {
|
|
434
|
+
display: none;
|
|
435
|
+
}
|
|
305
436
|
}
|
|
306
437
|
|
|
307
438
|
/* ── SVG root ───────────────────────────────────── */
|
|
@@ -309,16 +440,21 @@
|
|
|
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)
|
|
319
447
|
);
|
|
320
448
|
--_cluster-border: var(--dry-diagram-cluster-border, var(--dry-color-stroke-weak));
|
|
321
449
|
--_text-muted: var(--dry-diagram-text-muted, var(--dry-color-text-weak));
|
|
450
|
+
--_node-padding: var(--dry-diagram-node-padding, 16px 22px);
|
|
451
|
+
--_node-padding-with-description: var(--dry-diagram-node-padding-with-description, 18px 22px);
|
|
452
|
+
--_node-gap: var(--dry-diagram-node-gap, 8px);
|
|
453
|
+
--_node-gap-with-description: var(--dry-diagram-node-gap-with-description, 6px);
|
|
454
|
+
--_node-label-size: var(--dry-diagram-node-label-size, 15px);
|
|
455
|
+
--_node-label-size-with-description: var(--dry-diagram-node-label-size-with-description, 16px);
|
|
456
|
+
--_node-description-size: var(--dry-diagram-node-description-size, 12px);
|
|
457
|
+
--_cluster-label-size: var(--dry-diagram-cluster-label-size, 12px);
|
|
322
458
|
|
|
323
459
|
display: block;
|
|
324
460
|
overflow: visible;
|
|
@@ -371,42 +507,62 @@
|
|
|
371
507
|
[data-part='node-content'] {
|
|
372
508
|
display: grid;
|
|
373
509
|
place-items: center;
|
|
374
|
-
gap:
|
|
375
|
-
padding:
|
|
510
|
+
gap: var(--_node-gap);
|
|
511
|
+
padding: var(--_node-padding);
|
|
376
512
|
height: 100%;
|
|
377
513
|
box-sizing: border-box;
|
|
514
|
+
font-family: var(--dry-font-sans);
|
|
378
515
|
}
|
|
379
516
|
|
|
380
517
|
[data-part='node-label'] {
|
|
381
|
-
font-
|
|
382
|
-
font-
|
|
383
|
-
font-weight: 500;
|
|
518
|
+
font-size: var(--_node-label-size);
|
|
519
|
+
font-weight: 600;
|
|
384
520
|
color: var(--_node-color);
|
|
385
521
|
text-align: center;
|
|
386
|
-
line-height: 1.
|
|
387
|
-
letter-spacing: 0.
|
|
522
|
+
line-height: 1.2;
|
|
523
|
+
letter-spacing: 0.005em;
|
|
388
524
|
white-space: nowrap;
|
|
389
525
|
}
|
|
390
526
|
|
|
391
527
|
[data-part='node-icon'] {
|
|
392
|
-
font-size:
|
|
528
|
+
font-size: 18px;
|
|
393
529
|
line-height: 1;
|
|
394
530
|
text-align: center;
|
|
395
531
|
}
|
|
396
532
|
|
|
533
|
+
[data-part='node-icon'][data-icon-svg] {
|
|
534
|
+
display: grid;
|
|
535
|
+
place-items: center;
|
|
536
|
+
color: var(--_node-color);
|
|
537
|
+
line-height: 0;
|
|
538
|
+
}
|
|
539
|
+
|
|
397
540
|
[data-part='node-description'] {
|
|
398
|
-
font-
|
|
399
|
-
font-size: 11px;
|
|
541
|
+
font-size: var(--_node-description-size);
|
|
400
542
|
font-weight: 400;
|
|
401
543
|
color: var(--_text-muted);
|
|
402
544
|
text-align: center;
|
|
403
|
-
line-height: 1.
|
|
545
|
+
line-height: 1.35;
|
|
404
546
|
}
|
|
405
547
|
|
|
406
548
|
[data-part='node-content'][data-has-description] {
|
|
407
|
-
padding:
|
|
549
|
+
padding: var(--_node-padding-with-description);
|
|
550
|
+
gap: var(--_node-gap-with-description);
|
|
408
551
|
text-align: left;
|
|
409
552
|
place-items: start;
|
|
553
|
+
grid-template-rows: auto auto 1fr;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
[data-part='node-content'][data-has-description] [data-part='node-icon'] {
|
|
557
|
+
padding-block-end: 4px;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
[data-part='node-content'][data-has-description] [data-part='node-label'] {
|
|
561
|
+
font-size: var(--_node-label-size-with-description);
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
[data-part='node-content'][data-has-description] [data-part='node-description'] {
|
|
565
|
+
text-align: left;
|
|
410
566
|
}
|
|
411
567
|
|
|
412
568
|
/* ── Node variant: outlined ──────────────────── */
|
|
@@ -422,27 +578,38 @@
|
|
|
422
578
|
}
|
|
423
579
|
|
|
424
580
|
/* ── Node colors via custom property indirection ─ */
|
|
425
|
-
[data-part='node'][data-color='brand']
|
|
581
|
+
[data-part='node'][data-color='brand'],
|
|
582
|
+
[data-part='waypoint'][data-color='brand'] {
|
|
426
583
|
--_node-border: var(--dry-color-stroke-brand);
|
|
427
584
|
--_node-color: var(--dry-color-text-brand);
|
|
428
585
|
}
|
|
429
|
-
[data-part='node'][data-color='success']
|
|
586
|
+
[data-part='node'][data-color='success'],
|
|
587
|
+
[data-part='waypoint'][data-color='success'] {
|
|
430
588
|
--_node-border: var(--dry-color-stroke-success);
|
|
431
589
|
--_node-color: var(--dry-color-text-success);
|
|
432
590
|
}
|
|
433
|
-
[data-part='node'][data-color='warning']
|
|
591
|
+
[data-part='node'][data-color='warning'],
|
|
592
|
+
[data-part='waypoint'][data-color='warning'] {
|
|
434
593
|
--_node-border: var(--dry-color-stroke-warning);
|
|
435
594
|
--_node-color: var(--dry-color-text-warning);
|
|
436
595
|
}
|
|
437
|
-
[data-part='node'][data-color='error']
|
|
596
|
+
[data-part='node'][data-color='error'],
|
|
597
|
+
[data-part='waypoint'][data-color='error'] {
|
|
438
598
|
--_node-border: var(--dry-color-stroke-error);
|
|
439
599
|
--_node-color: var(--dry-color-text-error);
|
|
440
600
|
}
|
|
441
|
-
[data-part='node'][data-color='info']
|
|
601
|
+
[data-part='node'][data-color='info'],
|
|
602
|
+
[data-part='waypoint'][data-color='info'] {
|
|
442
603
|
--_node-border: var(--dry-color-stroke-info);
|
|
443
604
|
--_node-color: var(--dry-color-text-info);
|
|
444
605
|
}
|
|
445
606
|
|
|
607
|
+
[data-part='waypoint'] [data-part='node-box'] {
|
|
608
|
+
fill: var(--_node-bg);
|
|
609
|
+
stroke: var(--_node-border);
|
|
610
|
+
stroke-width: 2;
|
|
611
|
+
}
|
|
612
|
+
|
|
446
613
|
/* ── Node states ────────────────────────────────── */
|
|
447
614
|
[data-part='node'][data-state='active'] [data-part='node-box'] {
|
|
448
615
|
stroke-width: 2;
|
|
@@ -529,6 +696,37 @@
|
|
|
529
696
|
fill: var(--_text-muted);
|
|
530
697
|
}
|
|
531
698
|
|
|
699
|
+
[data-part='cluster-label-row'] {
|
|
700
|
+
display: grid;
|
|
701
|
+
grid-template-columns: auto auto;
|
|
702
|
+
align-items: center;
|
|
703
|
+
justify-content: start;
|
|
704
|
+
gap: 8px;
|
|
705
|
+
font-family: var(--dry-font-sans);
|
|
706
|
+
font-size: var(--_cluster-label-size);
|
|
707
|
+
font-weight: 600;
|
|
708
|
+
color: var(--_text-muted);
|
|
709
|
+
letter-spacing: 0.04em;
|
|
710
|
+
text-transform: uppercase;
|
|
711
|
+
line-height: 1;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
[data-part='cluster-label-row'][data-color='brand'] {
|
|
715
|
+
color: var(--dry-color-text-brand);
|
|
716
|
+
}
|
|
717
|
+
[data-part='cluster-label-row'][data-color='success'] {
|
|
718
|
+
color: var(--dry-color-text-success);
|
|
719
|
+
}
|
|
720
|
+
[data-part='cluster-label-row'][data-color='warning'] {
|
|
721
|
+
color: var(--dry-color-text-warning);
|
|
722
|
+
}
|
|
723
|
+
[data-part='cluster-label-row'][data-color='error'] {
|
|
724
|
+
color: var(--dry-color-text-error);
|
|
725
|
+
}
|
|
726
|
+
[data-part='cluster-label-row'][data-color='info'] {
|
|
727
|
+
color: var(--dry-color-text-info);
|
|
728
|
+
}
|
|
729
|
+
|
|
532
730
|
/* ── Regions ────────────────────────────────────── */
|
|
533
731
|
[data-part='region-box'] {
|
|
534
732
|
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;
|