@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.
Files changed (99) hide show
  1. package/dist/alert/{alert-root.svelte → alert.svelte} +78 -20
  2. package/dist/alert/alert.svelte.d.ts +15 -0
  3. package/dist/alert/index.d.ts +15 -14
  4. package/dist/alert/index.js +3 -12
  5. package/dist/breadcrumb/breadcrumb-link.svelte +1 -1
  6. package/dist/button/button.svelte +1 -1
  7. package/dist/card/card-root.svelte +2 -2
  8. package/dist/chromatic-shift/chromatic-shift.svelte +2 -2
  9. package/dist/code-block/code-block-button.svelte +9 -1
  10. package/dist/color-picker/color-picker-area.svelte +2 -2
  11. package/dist/color-picker/color-picker-channel-input.svelte +2 -2
  12. package/dist/color-picker/color-picker-input-alpha-slider.svelte +2 -2
  13. package/dist/color-picker/color-picker-input-hue-slider.svelte +2 -2
  14. package/dist/color-picker/color-picker-input.svelte +9 -9
  15. package/dist/color-picker/color-picker-swatch.svelte +2 -2
  16. package/dist/combobox/combobox-input.svelte +9 -9
  17. package/dist/command-palette/command-palette-item.svelte +1 -1
  18. package/dist/data-grid/data-grid-button-input-column.svelte +1 -1
  19. package/dist/diagram/diagram.svelte +230 -32
  20. package/dist/diagram/diagram.svelte.d.ts +1 -0
  21. package/dist/diagram/edge-routing.d.ts +63 -1
  22. package/dist/diagram/edge-routing.js +316 -26
  23. package/dist/diagram/layout.js +647 -62
  24. package/dist/diagram/types.d.ts +55 -0
  25. package/dist/drag-and-drop/drag-and-drop-handle.svelte +1 -1
  26. package/dist/drag-and-drop/drag-and-drop-item.svelte +1 -1
  27. package/dist/file-select/file-select-root.svelte +2 -2
  28. package/dist/file-upload/file-upload-dropzone.svelte +2 -2
  29. package/dist/gauge/gauge.svelte +1 -1
  30. package/dist/image-comparison/image-comparison.svelte +1 -1
  31. package/dist/index.d.ts +3 -3
  32. package/dist/index.js +1 -1
  33. package/dist/input/input.svelte +10 -11
  34. package/dist/label/label.svelte +1 -1
  35. package/dist/link/link.svelte +1 -1
  36. package/dist/list/list-item.svelte +2 -2
  37. package/dist/multi-select-combobox/multi-select-combobox-selection-item.svelte +9 -3
  38. package/dist/multi-select-combobox/multi-select-combobox-selection-remove-button.svelte +2 -0
  39. package/dist/navigation-menu/navigation-menu-link.svelte +1 -1
  40. package/dist/notification-center/notification-center-item.svelte +1 -1
  41. package/dist/number-input/number-input-button.svelte +3 -3
  42. package/dist/option-picker/context.svelte.d.ts +9 -0
  43. package/dist/option-picker/context.svelte.js +2 -0
  44. package/dist/option-picker/option-picker-item.svelte +31 -4
  45. package/dist/option-picker/option-picker-preview.svelte +2 -2
  46. package/dist/option-picker/option-picker-root.svelte +2 -2
  47. package/dist/phone-input/phone-input-select.svelte +2 -2
  48. package/dist/pin-input/pin-input-cell.svelte +1 -1
  49. package/dist/pin-input/pin-input-root.svelte +1 -1
  50. package/dist/progress/progress.svelte +1 -1
  51. package/dist/scroll-area/scroll-area.svelte +1 -1
  52. package/dist/shimmer/index.d.ts +8 -0
  53. package/dist/shimmer/index.js +1 -0
  54. package/dist/shimmer/shimmer.svelte +87 -0
  55. package/dist/shimmer/shimmer.svelte.d.ts +10 -0
  56. package/dist/sidebar/sidebar-item.svelte +1 -1
  57. package/dist/slider/slider-input.svelte +2 -2
  58. package/dist/splitter/splitter-handle.svelte +1 -1
  59. package/dist/table-of-contents/table-of-contents-item.svelte +1 -1
  60. package/dist/table-of-contents/table-of-contents-list.svelte +1 -1
  61. package/dist/tags-input/tags-input-root.svelte +1 -1
  62. package/dist/tags-input/tags-input-tag-delete-button.svelte +2 -0
  63. package/dist/tags-input/tags-input-tag.svelte +9 -3
  64. package/dist/textarea/textarea.svelte +11 -11
  65. package/dist/themes/default.css +31 -0
  66. package/dist/toast/toast-root.svelte +1 -1
  67. package/dist/tour/tour-root.css +3 -3
  68. package/dist/tree/tree-item-children.svelte +1 -1
  69. package/dist/tree/tree-item-label.svelte +1 -1
  70. package/dist/video-embed/video-embed-button.svelte +1 -1
  71. package/package.json +11 -750
  72. package/skills/dryui/SKILL.md +26 -21
  73. package/skills/dryui/rules/compound-components.md +3 -3
  74. package/skills/dryui/rules/theming.md +1 -1
  75. package/dist/alert/alert-button-close.svelte +0 -29
  76. package/dist/alert/alert-button-close.svelte.d.ts +0 -8
  77. package/dist/alert/alert-description.svelte +0 -28
  78. package/dist/alert/alert-description.svelte.d.ts +0 -8
  79. package/dist/alert/alert-icon.svelte +0 -26
  80. package/dist/alert/alert-icon.svelte.d.ts +0 -8
  81. package/dist/alert/alert-root.svelte.d.ts +0 -12
  82. package/dist/alert/alert-title.svelte +0 -29
  83. package/dist/alert/alert-title.svelte.d.ts +0 -8
  84. package/dist/alert/context.svelte.d.ts +0 -9
  85. package/dist/alert/context.svelte.js +0 -10
  86. package/dist/option-swatch-group/context.svelte.d.ts +0 -9
  87. package/dist/option-swatch-group/context.svelte.js +0 -2
  88. package/dist/option-swatch-group/index.d.ts +0 -29
  89. package/dist/option-swatch-group/index.js +0 -12
  90. package/dist/option-swatch-group/option-swatch-group-item-button.svelte +0 -214
  91. package/dist/option-swatch-group/option-swatch-group-item-button.svelte.d.ts +0 -12
  92. package/dist/option-swatch-group/option-swatch-group-label.svelte +0 -24
  93. package/dist/option-swatch-group/option-swatch-group-label.svelte.d.ts +0 -8
  94. package/dist/option-swatch-group/option-swatch-group-meta.svelte +0 -24
  95. package/dist/option-swatch-group/option-swatch-group-meta.svelte.d.ts +0 -8
  96. package/dist/option-swatch-group/option-swatch-group-root.svelte +0 -81
  97. package/dist/option-swatch-group/option-swatch-group-root.svelte.d.ts +0 -12
  98. package/dist/option-swatch-group/option-swatch-group-swatch.svelte +0 -52
  99. 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="12"
71
+ rx="16"
67
72
  data-dashed={cluster.dashed || undefined}
68
73
  />
69
74
  {#if cluster.label}
70
- <text data-part="cluster-label" x={cluster.x + 20} y={cluster.y + 22}
71
- >{cluster.label}</text
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 data-part="node-content" data-has-description={node.description ? '' : undefined}>
274
- {#if node.icon}
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
- overflow: auto;
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: 2px;
375
- padding: 8px 20px;
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-family: var(--dry-font-mono);
382
- font-size: 14px;
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.3;
387
- letter-spacing: 0.02em;
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: 16px;
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-family: var(--dry-font-mono);
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.3;
545
+ line-height: 1.35;
404
546
  }
405
547
 
406
548
  [data-part='node-content'][data-has-description] {
407
- padding: 10px 24px;
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);
@@ -4,6 +4,7 @@ interface Props extends SVGAttributes<SVGSVGElement> {
4
4
  config: DiagramConfig;
5
5
  width?: number;
6
6
  height?: number;
7
+ fit?: 'contain' | 'native';
7
8
  }
8
9
  declare const Diagram: import("svelte").Component<Props, {}, "">;
9
10
  type Diagram = ReturnType<typeof Diagram>;
@@ -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): PositionedEdge[];
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;