@particle-academy/react-fancy 2.9.0 → 2.10.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/index.cjs +752 -104
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +27 -3
- package/dist/index.d.ts +27 -3
- package/dist/index.js +752 -104
- package/dist/index.js.map +1 -1
- package/docs/Diagram.md +34 -2
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -12284,65 +12284,615 @@ function DiagramEntity({
|
|
|
12284
12284
|
) });
|
|
12285
12285
|
}
|
|
12286
12286
|
DiagramEntity.displayName = "DiagramEntity";
|
|
12287
|
-
|
|
12288
|
-
|
|
12289
|
-
|
|
12290
|
-
|
|
12291
|
-
|
|
12287
|
+
|
|
12288
|
+
// src/components/Diagram/diagram.markers.ts
|
|
12289
|
+
function defaultMarkersForType(type) {
|
|
12290
|
+
switch (type) {
|
|
12291
|
+
case "one-to-one":
|
|
12292
|
+
return { fromMarker: "one", toMarker: "one", lineStyle: "solid" };
|
|
12293
|
+
case "one-to-many":
|
|
12294
|
+
return { fromMarker: "one", toMarker: "many", lineStyle: "solid" };
|
|
12295
|
+
case "many-to-one":
|
|
12296
|
+
return { fromMarker: "many", toMarker: "one", lineStyle: "solid" };
|
|
12297
|
+
case "many-to-many":
|
|
12298
|
+
return { fromMarker: "many", toMarker: "many", lineStyle: "solid" };
|
|
12299
|
+
case "association":
|
|
12300
|
+
return { fromMarker: "none", toMarker: "arrow", lineStyle: "solid" };
|
|
12301
|
+
case "aggregation":
|
|
12302
|
+
return { fromMarker: "diamond-open", toMarker: "none", lineStyle: "solid" };
|
|
12303
|
+
case "composition":
|
|
12304
|
+
return { fromMarker: "diamond", toMarker: "none", lineStyle: "solid" };
|
|
12305
|
+
case "inheritance":
|
|
12306
|
+
return { fromMarker: "none", toMarker: "triangle-open", lineStyle: "solid" };
|
|
12307
|
+
case "implementation":
|
|
12308
|
+
return { fromMarker: "none", toMarker: "triangle-open", lineStyle: "dashed" };
|
|
12309
|
+
case "dependency":
|
|
12310
|
+
return { fromMarker: "none", toMarker: "arrow", lineStyle: "dashed" };
|
|
12311
|
+
default:
|
|
12312
|
+
return { fromMarker: "none", toMarker: "none", lineStyle: "solid" };
|
|
12313
|
+
}
|
|
12314
|
+
}
|
|
12315
|
+
var SIZE = 12;
|
|
12316
|
+
function renderMarker(marker, pt, direction) {
|
|
12317
|
+
if (typeof marker === "string" && marker.startsWith("emoji:")) {
|
|
12318
|
+
return { paths: [], text: marker.slice(6) };
|
|
12319
|
+
}
|
|
12320
|
+
switch (marker) {
|
|
12321
|
+
case "none":
|
|
12322
|
+
return null;
|
|
12323
|
+
case "arrow":
|
|
12324
|
+
return { paths: [{ d: arrowPath(pt, direction), fill: "stroke" }] };
|
|
12325
|
+
case "arrow-open":
|
|
12326
|
+
return { paths: [{ d: arrowPath(pt, direction), fill: "none" }] };
|
|
12327
|
+
case "circle":
|
|
12328
|
+
return { paths: [{ d: circlePath(pt), fill: "stroke" }] };
|
|
12329
|
+
case "circle-open":
|
|
12330
|
+
return { paths: [{ d: circlePath(pt), fill: "background" }] };
|
|
12331
|
+
case "square":
|
|
12332
|
+
return { paths: [{ d: squarePath(pt, direction), fill: "stroke" }] };
|
|
12333
|
+
case "square-open":
|
|
12334
|
+
return { paths: [{ d: squarePath(pt, direction), fill: "background" }] };
|
|
12335
|
+
case "diamond":
|
|
12336
|
+
return { paths: [{ d: diamondPath(pt, direction), fill: "stroke" }] };
|
|
12337
|
+
case "diamond-open":
|
|
12338
|
+
return { paths: [{ d: diamondPath(pt, direction), fill: "background" }] };
|
|
12339
|
+
case "triangle":
|
|
12340
|
+
return { paths: [{ d: trianglePath(pt, direction), fill: "stroke" }] };
|
|
12341
|
+
case "triangle-open":
|
|
12342
|
+
return { paths: [{ d: trianglePath(pt, direction), fill: "background" }] };
|
|
12343
|
+
case "cross":
|
|
12344
|
+
return { paths: [{ d: crossPath(pt, direction), fill: "none" }] };
|
|
12345
|
+
case "one":
|
|
12346
|
+
return { paths: [{ d: oneSymbol(pt, direction), fill: "none" }] };
|
|
12347
|
+
case "many":
|
|
12348
|
+
return { paths: [{ d: crowFootSymbol(pt, direction), fill: "none" }] };
|
|
12349
|
+
case "optional-one":
|
|
12350
|
+
return {
|
|
12351
|
+
paths: [
|
|
12352
|
+
{ d: circleOuter(pt, direction), fill: "background" },
|
|
12353
|
+
{ d: oneSymbolOffset(pt, direction), fill: "none" }
|
|
12354
|
+
]
|
|
12355
|
+
};
|
|
12356
|
+
case "optional-many":
|
|
12357
|
+
return {
|
|
12358
|
+
paths: [
|
|
12359
|
+
{ d: circleOuter(pt, direction), fill: "background" },
|
|
12360
|
+
{ d: crowFootSymbolOffset(pt, direction), fill: "none" }
|
|
12361
|
+
]
|
|
12362
|
+
};
|
|
12363
|
+
default:
|
|
12364
|
+
if (typeof marker === "string" && marker !== "") {
|
|
12365
|
+
return { paths: [], text: marker };
|
|
12366
|
+
}
|
|
12367
|
+
return null;
|
|
12368
|
+
}
|
|
12369
|
+
}
|
|
12370
|
+
function markerInset(marker) {
|
|
12371
|
+
if (marker === "none" || marker === void 0) return 0;
|
|
12372
|
+
if (typeof marker === "string" && (marker.startsWith("emoji:") || !KNOWN_MARKERS.has(marker))) {
|
|
12373
|
+
return SIZE;
|
|
12374
|
+
}
|
|
12375
|
+
switch (marker) {
|
|
12376
|
+
case "circle":
|
|
12377
|
+
case "circle-open":
|
|
12378
|
+
return SIZE * 0.6;
|
|
12379
|
+
case "one":
|
|
12380
|
+
return 0;
|
|
12381
|
+
// bar sits AT endpoint
|
|
12382
|
+
case "many":
|
|
12383
|
+
return SIZE;
|
|
12384
|
+
case "optional-one":
|
|
12385
|
+
return SIZE * 1.2;
|
|
12386
|
+
case "optional-many":
|
|
12387
|
+
return SIZE * 1.8;
|
|
12388
|
+
default:
|
|
12389
|
+
return SIZE;
|
|
12390
|
+
}
|
|
12391
|
+
}
|
|
12392
|
+
var KNOWN_MARKERS = /* @__PURE__ */ new Set([
|
|
12393
|
+
"none",
|
|
12394
|
+
"arrow",
|
|
12395
|
+
"arrow-open",
|
|
12396
|
+
"circle",
|
|
12397
|
+
"circle-open",
|
|
12398
|
+
"square",
|
|
12399
|
+
"square-open",
|
|
12400
|
+
"diamond",
|
|
12401
|
+
"diamond-open",
|
|
12402
|
+
"triangle",
|
|
12403
|
+
"triangle-open",
|
|
12404
|
+
"one",
|
|
12405
|
+
"many",
|
|
12406
|
+
"optional-one",
|
|
12407
|
+
"optional-many",
|
|
12408
|
+
"cross"
|
|
12409
|
+
]);
|
|
12410
|
+
function dirVec(direction) {
|
|
12292
12411
|
switch (direction) {
|
|
12293
12412
|
case "left":
|
|
12413
|
+
return [-1, 0];
|
|
12294
12414
|
case "right":
|
|
12295
|
-
return
|
|
12415
|
+
return [1, 0];
|
|
12296
12416
|
case "up":
|
|
12417
|
+
return [0, -1];
|
|
12297
12418
|
case "down":
|
|
12298
|
-
return
|
|
12419
|
+
return [0, 1];
|
|
12299
12420
|
}
|
|
12300
12421
|
}
|
|
12301
|
-
function
|
|
12302
|
-
const s = SYMBOL_SIZE;
|
|
12303
|
-
const spread = s * 0.8;
|
|
12304
|
-
let tip;
|
|
12422
|
+
function perpVec(direction) {
|
|
12305
12423
|
switch (direction) {
|
|
12306
|
-
case "right":
|
|
12307
|
-
tip = { x: pt.x - s, y: pt.y };
|
|
12308
|
-
return [
|
|
12309
|
-
`M${pt.x},${pt.y - spread} L${tip.x},${tip.y}`,
|
|
12310
|
-
`M${pt.x},${pt.y} L${tip.x},${tip.y}`,
|
|
12311
|
-
`M${pt.x},${pt.y + spread} L${tip.x},${tip.y}`,
|
|
12312
|
-
// bar at entity edge
|
|
12313
|
-
`M${pt.x},${pt.y - spread} L${pt.x},${pt.y + spread}`
|
|
12314
|
-
].join(" ");
|
|
12315
12424
|
case "left":
|
|
12316
|
-
|
|
12317
|
-
return [
|
|
12318
|
-
`M${pt.x},${pt.y - spread} L${tip.x},${tip.y}`,
|
|
12319
|
-
`M${pt.x},${pt.y} L${tip.x},${tip.y}`,
|
|
12320
|
-
`M${pt.x},${pt.y + spread} L${tip.x},${tip.y}`,
|
|
12321
|
-
`M${pt.x},${pt.y - spread} L${pt.x},${pt.y + spread}`
|
|
12322
|
-
].join(" ");
|
|
12323
|
-
case "down":
|
|
12324
|
-
tip = { x: pt.x, y: pt.y - s };
|
|
12325
|
-
return [
|
|
12326
|
-
`M${pt.x - spread},${pt.y} L${tip.x},${tip.y}`,
|
|
12327
|
-
`M${pt.x},${pt.y} L${tip.x},${tip.y}`,
|
|
12328
|
-
`M${pt.x + spread},${pt.y} L${tip.x},${tip.y}`,
|
|
12329
|
-
`M${pt.x - spread},${pt.y} L${pt.x + spread},${pt.y}`
|
|
12330
|
-
].join(" ");
|
|
12425
|
+
case "right":
|
|
12426
|
+
return [0, 1];
|
|
12331
12427
|
case "up":
|
|
12332
|
-
|
|
12333
|
-
return [
|
|
12334
|
-
|
|
12335
|
-
|
|
12336
|
-
|
|
12337
|
-
|
|
12338
|
-
|
|
12339
|
-
|
|
12340
|
-
|
|
12341
|
-
|
|
12342
|
-
const
|
|
12343
|
-
|
|
12344
|
-
|
|
12345
|
-
return
|
|
12428
|
+
case "down":
|
|
12429
|
+
return [1, 0];
|
|
12430
|
+
}
|
|
12431
|
+
}
|
|
12432
|
+
function arrowPath(pt, direction, _filled) {
|
|
12433
|
+
const [dx, dy] = dirVec(direction);
|
|
12434
|
+
const [px, py] = perpVec(direction);
|
|
12435
|
+
const tipX = pt.x + dx * SIZE;
|
|
12436
|
+
const tipY = pt.y + dy * SIZE;
|
|
12437
|
+
const baseAX = pt.x + px * (SIZE * 0.55);
|
|
12438
|
+
const baseAY = pt.y + py * (SIZE * 0.55);
|
|
12439
|
+
const baseBX = pt.x - px * (SIZE * 0.55);
|
|
12440
|
+
const baseBY = pt.y - py * (SIZE * 0.55);
|
|
12441
|
+
return `M${baseAX},${baseAY} L${tipX},${tipY} L${baseBX},${baseBY} Z`;
|
|
12442
|
+
}
|
|
12443
|
+
function circlePath(pt, _filled) {
|
|
12444
|
+
const r = SIZE * 0.45;
|
|
12445
|
+
return `M${pt.x - r},${pt.y} a${r},${r} 0 1 0 ${r * 2},0 a${r},${r} 0 1 0 ${-r * 2},0 Z`;
|
|
12446
|
+
}
|
|
12447
|
+
function squarePath(pt, direction, _filled) {
|
|
12448
|
+
const [dx, dy] = dirVec(direction);
|
|
12449
|
+
const [px, py] = perpVec(direction);
|
|
12450
|
+
const half = SIZE * 0.5;
|
|
12451
|
+
const cx = pt.x + dx * half;
|
|
12452
|
+
const cy = pt.y + dy * half;
|
|
12453
|
+
const tlX = cx - px * half - dx * half;
|
|
12454
|
+
const tlY = cy - py * half - dy * half;
|
|
12455
|
+
const trX = cx + px * half - dx * half;
|
|
12456
|
+
const trY = cy + py * half - dy * half;
|
|
12457
|
+
const brX = cx + px * half + dx * half;
|
|
12458
|
+
const brY = cy + py * half + dy * half;
|
|
12459
|
+
const blX = cx - px * half + dx * half;
|
|
12460
|
+
const blY = cy - py * half + dy * half;
|
|
12461
|
+
return `M${tlX},${tlY} L${trX},${trY} L${brX},${brY} L${blX},${blY} Z`;
|
|
12462
|
+
}
|
|
12463
|
+
function diamondPath(pt, direction, _filled) {
|
|
12464
|
+
const [dx, dy] = dirVec(direction);
|
|
12465
|
+
const [px, py] = perpVec(direction);
|
|
12466
|
+
const len = SIZE * 1.2;
|
|
12467
|
+
const cx = pt.x + dx * (len / 2);
|
|
12468
|
+
const cy = pt.y + dy * (len / 2);
|
|
12469
|
+
const aX = pt.x;
|
|
12470
|
+
const aY = pt.y;
|
|
12471
|
+
const bX = cx + px * (SIZE * 0.45);
|
|
12472
|
+
const bY = cy + py * (SIZE * 0.45);
|
|
12473
|
+
const tX = pt.x + dx * len;
|
|
12474
|
+
const tY = pt.y + dy * len;
|
|
12475
|
+
const dX = cx - px * (SIZE * 0.45);
|
|
12476
|
+
const dY = cy - py * (SIZE * 0.45);
|
|
12477
|
+
return `M${aX},${aY} L${bX},${bY} L${tX},${tY} L${dX},${dY} Z`;
|
|
12478
|
+
}
|
|
12479
|
+
function trianglePath(pt, direction, _filled) {
|
|
12480
|
+
const [dx, dy] = dirVec(direction);
|
|
12481
|
+
const [px, py] = perpVec(direction);
|
|
12482
|
+
const len = SIZE * 1.1;
|
|
12483
|
+
const baseCX = pt.x + dx * len;
|
|
12484
|
+
const baseCY = pt.y + dy * len;
|
|
12485
|
+
const baseAX = baseCX + px * (SIZE * 0.6);
|
|
12486
|
+
const baseAY = baseCY + py * (SIZE * 0.6);
|
|
12487
|
+
const baseBX = baseCX - px * (SIZE * 0.6);
|
|
12488
|
+
const baseBY = baseCY - py * (SIZE * 0.6);
|
|
12489
|
+
return `M${pt.x},${pt.y} L${baseAX},${baseAY} L${baseBX},${baseBY} Z`;
|
|
12490
|
+
}
|
|
12491
|
+
function crossPath(pt, direction) {
|
|
12492
|
+
const [dx, dy] = dirVec(direction);
|
|
12493
|
+
const [px, py] = perpVec(direction);
|
|
12494
|
+
const s = SIZE * 0.5;
|
|
12495
|
+
const cx = pt.x + dx * (SIZE * 0.5);
|
|
12496
|
+
const cy = pt.y + dy * (SIZE * 0.5);
|
|
12497
|
+
return [
|
|
12498
|
+
`M${cx - s * (px + dx)},${cy - s * (py + dy)} L${cx + s * (px + dx)},${cy + s * (py + dy)}`,
|
|
12499
|
+
`M${cx - s * (px - dx)},${cy - s * (py - dy)} L${cx + s * (px - dx)},${cy + s * (py - dy)}`
|
|
12500
|
+
].join(" ");
|
|
12501
|
+
}
|
|
12502
|
+
function oneSymbol(pt, direction) {
|
|
12503
|
+
const [, py] = perpVec(direction);
|
|
12504
|
+
const [px] = perpVec(direction);
|
|
12505
|
+
const half = SIZE * 0.6;
|
|
12506
|
+
return `M${pt.x - px * half},${pt.y - py * half} L${pt.x + px * half},${pt.y + py * half}`;
|
|
12507
|
+
}
|
|
12508
|
+
function crowFootSymbol(pt, direction) {
|
|
12509
|
+
const [dx, dy] = dirVec(direction);
|
|
12510
|
+
const [px, py] = perpVec(direction);
|
|
12511
|
+
const tipX = pt.x + dx * SIZE;
|
|
12512
|
+
const tipY = pt.y + dy * SIZE;
|
|
12513
|
+
const spread = SIZE * 0.8;
|
|
12514
|
+
const aX = pt.x + px * spread, aY = pt.y + py * spread;
|
|
12515
|
+
const cX = pt.x - px * spread, cY = pt.y - py * spread;
|
|
12516
|
+
return [
|
|
12517
|
+
`M${aX},${aY} L${tipX},${tipY}`,
|
|
12518
|
+
`M${pt.x},${pt.y} L${tipX},${tipY}`,
|
|
12519
|
+
`M${cX},${cY} L${tipX},${tipY}`,
|
|
12520
|
+
`M${aX},${aY} L${cX},${cY}`
|
|
12521
|
+
].join(" ");
|
|
12522
|
+
}
|
|
12523
|
+
function circleOuter(pt, direction) {
|
|
12524
|
+
const [dx, dy] = dirVec(direction);
|
|
12525
|
+
const r = SIZE * 0.4;
|
|
12526
|
+
const cx = pt.x + dx * (SIZE * 0.4 + r);
|
|
12527
|
+
const cy = pt.y + dy * (SIZE * 0.4 + r);
|
|
12528
|
+
return `M${cx - r},${cy} a${r},${r} 0 1 0 ${r * 2},0 a${r},${r} 0 1 0 ${-r * 2},0 Z`;
|
|
12529
|
+
}
|
|
12530
|
+
function oneSymbolOffset(pt, direction) {
|
|
12531
|
+
const [px, py] = perpVec(direction);
|
|
12532
|
+
const half = SIZE * 0.6;
|
|
12533
|
+
return `M${pt.x - px * half},${pt.y - py * half} L${pt.x + px * half},${pt.y + py * half}`;
|
|
12534
|
+
}
|
|
12535
|
+
function crowFootSymbolOffset(pt, direction) {
|
|
12536
|
+
const [dx, dy] = dirVec(direction);
|
|
12537
|
+
const [px, py] = perpVec(direction);
|
|
12538
|
+
const inset = SIZE * 0.8;
|
|
12539
|
+
const startX = pt.x + dx * inset;
|
|
12540
|
+
const startY = pt.y + dy * inset;
|
|
12541
|
+
const tipX = pt.x + dx * (inset + SIZE);
|
|
12542
|
+
const tipY = pt.y + dy * (inset + SIZE);
|
|
12543
|
+
const spread = SIZE * 0.8;
|
|
12544
|
+
const aX = startX + px * spread, aY = startY + py * spread;
|
|
12545
|
+
const cX = startX - px * spread, cY = startY - py * spread;
|
|
12546
|
+
return [
|
|
12547
|
+
`M${aX},${aY} L${tipX},${tipY}`,
|
|
12548
|
+
`M${startX},${startY} L${tipX},${tipY}`,
|
|
12549
|
+
`M${cX},${cY} L${tipX},${tipY}`
|
|
12550
|
+
].join(" ");
|
|
12551
|
+
}
|
|
12552
|
+
|
|
12553
|
+
// src/components/Diagram/diagram.routing.ts
|
|
12554
|
+
var STUB = 24;
|
|
12555
|
+
var DODGE_PADDING = 16;
|
|
12556
|
+
var MAX_DODGE_ITERATIONS = 6;
|
|
12557
|
+
function pickAnchors(from, to, fromY, toY) {
|
|
12558
|
+
const fcx = from.x + from.width / 2;
|
|
12559
|
+
const fcy = from.y + from.height / 2;
|
|
12560
|
+
const tcx = to.x + to.width / 2;
|
|
12561
|
+
const tcy = to.y + to.height / 2;
|
|
12562
|
+
const dx = tcx - fcx;
|
|
12563
|
+
const dy = tcy - fcy;
|
|
12564
|
+
let fromSide, toSide;
|
|
12565
|
+
if (Math.abs(dx) >= Math.abs(dy)) {
|
|
12566
|
+
fromSide = dx >= 0 ? "right" : "left";
|
|
12567
|
+
toSide = dx >= 0 ? "left" : "right";
|
|
12568
|
+
} else {
|
|
12569
|
+
fromSide = dy >= 0 ? "bottom" : "top";
|
|
12570
|
+
toSide = dy >= 0 ? "top" : "bottom";
|
|
12571
|
+
}
|
|
12572
|
+
return {
|
|
12573
|
+
from: anchorOnSide(from, fromSide, fromY),
|
|
12574
|
+
to: anchorOnSide(to, toSide, toY)
|
|
12575
|
+
};
|
|
12576
|
+
}
|
|
12577
|
+
function anchorOnSide(box, side, fieldY) {
|
|
12578
|
+
switch (side) {
|
|
12579
|
+
case "right":
|
|
12580
|
+
return { side, x: box.x + box.width, y: box.y + (fieldY ?? box.height / 2) };
|
|
12581
|
+
case "left":
|
|
12582
|
+
return { side, x: box.x, y: box.y + (fieldY ?? box.height / 2) };
|
|
12583
|
+
case "top":
|
|
12584
|
+
return { side, x: box.x + box.width / 2, y: box.y };
|
|
12585
|
+
case "bottom":
|
|
12586
|
+
return { side, x: box.x + box.width / 2, y: box.y + box.height };
|
|
12587
|
+
}
|
|
12588
|
+
}
|
|
12589
|
+
function stubOut(a, distance2 = STUB) {
|
|
12590
|
+
switch (a.side) {
|
|
12591
|
+
case "right":
|
|
12592
|
+
return { x: a.x + distance2, y: a.y };
|
|
12593
|
+
case "left":
|
|
12594
|
+
return { x: a.x - distance2, y: a.y };
|
|
12595
|
+
case "top":
|
|
12596
|
+
return { x: a.x, y: a.y - distance2 };
|
|
12597
|
+
case "bottom":
|
|
12598
|
+
return { x: a.x, y: a.y + distance2 };
|
|
12599
|
+
}
|
|
12600
|
+
}
|
|
12601
|
+
function manhattanPath(from, to, obstacles = []) {
|
|
12602
|
+
const f = { x: from.x, y: from.y };
|
|
12603
|
+
const t = { x: to.x, y: to.y };
|
|
12604
|
+
const fs = stubOut(from);
|
|
12605
|
+
const ts = stubOut(to);
|
|
12606
|
+
const fHoriz = from.side === "left" || from.side === "right";
|
|
12607
|
+
const tHoriz = to.side === "left" || to.side === "right";
|
|
12608
|
+
if (fHoriz && tHoriz) {
|
|
12609
|
+
const midX = pickClearMidX((fs.x + ts.x) / 2, fs.y, ts.y, obstacles);
|
|
12610
|
+
return uniqPath([
|
|
12611
|
+
f,
|
|
12612
|
+
fs,
|
|
12613
|
+
{ x: midX, y: fs.y },
|
|
12614
|
+
{ x: midX, y: ts.y },
|
|
12615
|
+
ts,
|
|
12616
|
+
t
|
|
12617
|
+
]);
|
|
12618
|
+
}
|
|
12619
|
+
if (!fHoriz && !tHoriz) {
|
|
12620
|
+
const midY = pickClearMidY((fs.y + ts.y) / 2, fs.x, ts.x, obstacles);
|
|
12621
|
+
return uniqPath([
|
|
12622
|
+
f,
|
|
12623
|
+
fs,
|
|
12624
|
+
{ x: fs.x, y: midY },
|
|
12625
|
+
{ x: ts.x, y: midY },
|
|
12626
|
+
ts,
|
|
12627
|
+
t
|
|
12628
|
+
]);
|
|
12629
|
+
}
|
|
12630
|
+
if (fHoriz) {
|
|
12631
|
+
return uniqPath([
|
|
12632
|
+
f,
|
|
12633
|
+
fs,
|
|
12634
|
+
{ x: ts.x, y: fs.y },
|
|
12635
|
+
ts,
|
|
12636
|
+
t
|
|
12637
|
+
]);
|
|
12638
|
+
}
|
|
12639
|
+
return uniqPath([
|
|
12640
|
+
f,
|
|
12641
|
+
fs,
|
|
12642
|
+
{ x: fs.x, y: ts.y },
|
|
12643
|
+
ts,
|
|
12644
|
+
t
|
|
12645
|
+
]);
|
|
12646
|
+
}
|
|
12647
|
+
function pickClearMidX(idealX, y1, y2, obstacles) {
|
|
12648
|
+
if (obstacles.length === 0) return idealX;
|
|
12649
|
+
const yMin = Math.min(y1, y2);
|
|
12650
|
+
const yMax = Math.max(y1, y2);
|
|
12651
|
+
let midX = idealX;
|
|
12652
|
+
for (let i = 0; i < 4; i++) {
|
|
12653
|
+
let shifted = false;
|
|
12654
|
+
for (const ob of obstacles) {
|
|
12655
|
+
if (ob.y + ob.height + DODGE_PADDING < yMin) continue;
|
|
12656
|
+
if (ob.y - DODGE_PADDING > yMax) continue;
|
|
12657
|
+
const left = ob.x - DODGE_PADDING;
|
|
12658
|
+
const right = ob.x + ob.width + DODGE_PADDING;
|
|
12659
|
+
if (midX > left && midX < right) {
|
|
12660
|
+
midX = Math.abs(midX - left) <= Math.abs(midX - right) ? left - 1 : right + 1;
|
|
12661
|
+
shifted = true;
|
|
12662
|
+
}
|
|
12663
|
+
}
|
|
12664
|
+
if (!shifted) break;
|
|
12665
|
+
}
|
|
12666
|
+
return midX;
|
|
12667
|
+
}
|
|
12668
|
+
function pickClearMidY(idealY, x1, x2, obstacles) {
|
|
12669
|
+
if (obstacles.length === 0) return idealY;
|
|
12670
|
+
const xMin = Math.min(x1, x2);
|
|
12671
|
+
const xMax = Math.max(x1, x2);
|
|
12672
|
+
let midY = idealY;
|
|
12673
|
+
for (let i = 0; i < 4; i++) {
|
|
12674
|
+
let shifted = false;
|
|
12675
|
+
for (const ob of obstacles) {
|
|
12676
|
+
if (ob.x + ob.width + DODGE_PADDING < xMin) continue;
|
|
12677
|
+
if (ob.x - DODGE_PADDING > xMax) continue;
|
|
12678
|
+
const top = ob.y - DODGE_PADDING;
|
|
12679
|
+
const bot = ob.y + ob.height + DODGE_PADDING;
|
|
12680
|
+
if (midY > top && midY < bot) {
|
|
12681
|
+
midY = Math.abs(midY - top) <= Math.abs(midY - bot) ? top - 1 : bot + 1;
|
|
12682
|
+
shifted = true;
|
|
12683
|
+
}
|
|
12684
|
+
}
|
|
12685
|
+
if (!shifted) break;
|
|
12686
|
+
}
|
|
12687
|
+
return midY;
|
|
12688
|
+
}
|
|
12689
|
+
function uniqPath(points) {
|
|
12690
|
+
const out = [];
|
|
12691
|
+
for (const p of points) {
|
|
12692
|
+
const last = out[out.length - 1];
|
|
12693
|
+
if (!last || Math.abs(last.x - p.x) > 0.5 || Math.abs(last.y - p.y) > 0.5) {
|
|
12694
|
+
out.push(p);
|
|
12695
|
+
}
|
|
12696
|
+
}
|
|
12697
|
+
return out;
|
|
12698
|
+
}
|
|
12699
|
+
function dodgeObstacles(path, obstacles, padding = DODGE_PADDING) {
|
|
12700
|
+
if (obstacles.length === 0 || path.length < 2) return path;
|
|
12701
|
+
let working = path.slice();
|
|
12702
|
+
for (let iter = 0; iter < MAX_DODGE_ITERATIONS; iter++) {
|
|
12703
|
+
let dodged = false;
|
|
12704
|
+
const result = [working[0]];
|
|
12705
|
+
for (let i = 1; i < working.length; i++) {
|
|
12706
|
+
const a = result[result.length - 1];
|
|
12707
|
+
const b = working[i];
|
|
12708
|
+
const detour = detourAround(a, b, obstacles, padding);
|
|
12709
|
+
if (detour.length === 0) {
|
|
12710
|
+
result.push(b);
|
|
12711
|
+
} else {
|
|
12712
|
+
for (const p of detour) result.push(p);
|
|
12713
|
+
result.push(b);
|
|
12714
|
+
dodged = true;
|
|
12715
|
+
}
|
|
12716
|
+
}
|
|
12717
|
+
working = uniqPath(result);
|
|
12718
|
+
if (!dodged) break;
|
|
12719
|
+
}
|
|
12720
|
+
return working;
|
|
12721
|
+
}
|
|
12722
|
+
function detourAround(a, b, obstacles, padding) {
|
|
12723
|
+
const isHorizontal = Math.abs(a.y - b.y) < 0.5;
|
|
12724
|
+
const isVertical = Math.abs(a.x - b.x) < 0.5;
|
|
12725
|
+
if (!isHorizontal && !isVertical) return [];
|
|
12726
|
+
let best = null;
|
|
12727
|
+
for (const r of obstacles) {
|
|
12728
|
+
const expanded = expandRect(r, padding);
|
|
12729
|
+
if (!segmentCrossesRect(a, b, expanded)) continue;
|
|
12730
|
+
let entry, exit;
|
|
12731
|
+
if (isHorizontal) {
|
|
12732
|
+
entry = b.x > a.x ? expanded.x : expanded.x + expanded.width;
|
|
12733
|
+
exit = b.x > a.x ? expanded.x + expanded.width : expanded.x;
|
|
12734
|
+
} else {
|
|
12735
|
+
entry = b.y > a.y ? expanded.y : expanded.y + expanded.height;
|
|
12736
|
+
exit = b.y > a.y ? expanded.y + expanded.height : expanded.y;
|
|
12737
|
+
}
|
|
12738
|
+
const dist = isHorizontal ? Math.abs(entry - a.x) : Math.abs(entry - a.y);
|
|
12739
|
+
if (!best || dist < (isHorizontal ? Math.abs(best.entry - a.x) : Math.abs(best.entry - a.y))) {
|
|
12740
|
+
best = { rect: expanded, entry, exit };
|
|
12741
|
+
}
|
|
12742
|
+
}
|
|
12743
|
+
if (!best) return [];
|
|
12744
|
+
if (isHorizontal) {
|
|
12745
|
+
const aboveY = best.rect.y - 1;
|
|
12746
|
+
const belowY = best.rect.y + best.rect.height + 1;
|
|
12747
|
+
const detourY = Math.abs(a.y - aboveY) <= Math.abs(a.y - belowY) ? aboveY : belowY;
|
|
12748
|
+
return [
|
|
12749
|
+
{ x: best.entry, y: a.y },
|
|
12750
|
+
{ x: best.entry, y: detourY },
|
|
12751
|
+
{ x: best.exit, y: detourY },
|
|
12752
|
+
{ x: best.exit, y: a.y }
|
|
12753
|
+
];
|
|
12754
|
+
} else {
|
|
12755
|
+
const leftX = best.rect.x - 1;
|
|
12756
|
+
const rightX = best.rect.x + best.rect.width + 1;
|
|
12757
|
+
const detourX = Math.abs(a.x - leftX) <= Math.abs(a.x - rightX) ? leftX : rightX;
|
|
12758
|
+
return [
|
|
12759
|
+
{ x: a.x, y: best.entry },
|
|
12760
|
+
{ x: detourX, y: best.entry },
|
|
12761
|
+
{ x: detourX, y: best.exit },
|
|
12762
|
+
{ x: a.x, y: best.exit }
|
|
12763
|
+
];
|
|
12764
|
+
}
|
|
12765
|
+
}
|
|
12766
|
+
function expandRect(r, padding) {
|
|
12767
|
+
return {
|
|
12768
|
+
x: r.x - padding,
|
|
12769
|
+
y: r.y - padding,
|
|
12770
|
+
width: r.width + padding * 2,
|
|
12771
|
+
height: r.height + padding * 2
|
|
12772
|
+
};
|
|
12773
|
+
}
|
|
12774
|
+
function segmentCrossesRect(a, b, rect) {
|
|
12775
|
+
const xMin = Math.min(a.x, b.x);
|
|
12776
|
+
const xMax = Math.max(a.x, b.x);
|
|
12777
|
+
const yMin = Math.min(a.y, b.y);
|
|
12778
|
+
const yMax = Math.max(a.y, b.y);
|
|
12779
|
+
if (xMax < rect.x) return false;
|
|
12780
|
+
if (xMin > rect.x + rect.width) return false;
|
|
12781
|
+
if (yMax < rect.y) return false;
|
|
12782
|
+
if (yMin > rect.y + rect.height) return false;
|
|
12783
|
+
if (a.x >= rect.x + 1 && a.x <= rect.x + rect.width - 1 && a.y >= rect.y + 1 && a.y <= rect.y + rect.height - 1) return false;
|
|
12784
|
+
if (b.x >= rect.x + 1 && b.x <= rect.x + rect.width - 1 && b.y >= rect.y + 1 && b.y <= rect.y + rect.height - 1) return false;
|
|
12785
|
+
return true;
|
|
12786
|
+
}
|
|
12787
|
+
function pathFromPoints(points, cornerRadius = 8) {
|
|
12788
|
+
if (points.length === 0) return "";
|
|
12789
|
+
if (points.length === 1) return `M${points[0].x},${points[0].y}`;
|
|
12790
|
+
if (points.length === 2 || cornerRadius <= 0) {
|
|
12791
|
+
return points.map((p, i) => `${i === 0 ? "M" : "L"}${p.x},${p.y}`).join(" ");
|
|
12792
|
+
}
|
|
12793
|
+
let d = `M${points[0].x},${points[0].y}`;
|
|
12794
|
+
for (let i = 1; i < points.length - 1; i++) {
|
|
12795
|
+
const prev = points[i - 1];
|
|
12796
|
+
const curr = points[i];
|
|
12797
|
+
const next = points[i + 1];
|
|
12798
|
+
const r = Math.min(
|
|
12799
|
+
cornerRadius,
|
|
12800
|
+
distance(prev, curr) / 2,
|
|
12801
|
+
distance(curr, next) / 2
|
|
12802
|
+
);
|
|
12803
|
+
if (r < 1) {
|
|
12804
|
+
d += ` L${curr.x},${curr.y}`;
|
|
12805
|
+
continue;
|
|
12806
|
+
}
|
|
12807
|
+
const beforeX = curr.x + Math.sign(prev.x - curr.x) * r;
|
|
12808
|
+
const beforeY = curr.y + Math.sign(prev.y - curr.y) * r;
|
|
12809
|
+
const afterX = curr.x + Math.sign(next.x - curr.x) * r;
|
|
12810
|
+
const afterY = curr.y + Math.sign(next.y - curr.y) * r;
|
|
12811
|
+
d += ` L${beforeX},${beforeY} Q${curr.x},${curr.y} ${afterX},${afterY}`;
|
|
12812
|
+
}
|
|
12813
|
+
const last = points[points.length - 1];
|
|
12814
|
+
d += ` L${last.x},${last.y}`;
|
|
12815
|
+
return d;
|
|
12816
|
+
}
|
|
12817
|
+
function distance(a, b) {
|
|
12818
|
+
return Math.hypot(b.x - a.x, b.y - a.y);
|
|
12819
|
+
}
|
|
12820
|
+
function bezierPath2(from, to) {
|
|
12821
|
+
const fs = stubOut(from, Math.max(40, distance(from, to) * 0.3));
|
|
12822
|
+
const ts = stubOut(to, Math.max(40, distance(from, to) * 0.3));
|
|
12823
|
+
return `M${from.x},${from.y} C${fs.x},${fs.y} ${ts.x},${ts.y} ${to.x},${to.y}`;
|
|
12824
|
+
}
|
|
12825
|
+
function midPoint(points) {
|
|
12826
|
+
if (points.length === 0) return { x: 0, y: 0 };
|
|
12827
|
+
if (points.length === 1) return points[0];
|
|
12828
|
+
let total = 0;
|
|
12829
|
+
const segLens = [];
|
|
12830
|
+
for (let i = 1; i < points.length; i++) {
|
|
12831
|
+
const len = distance(points[i - 1], points[i]);
|
|
12832
|
+
segLens.push(len);
|
|
12833
|
+
total += len;
|
|
12834
|
+
}
|
|
12835
|
+
let target = total / 2;
|
|
12836
|
+
for (let i = 0; i < segLens.length; i++) {
|
|
12837
|
+
if (target <= segLens[i]) {
|
|
12838
|
+
const t = segLens[i] === 0 ? 0 : target / segLens[i];
|
|
12839
|
+
const a = points[i];
|
|
12840
|
+
const b = points[i + 1];
|
|
12841
|
+
return { x: a.x + (b.x - a.x) * t, y: a.y + (b.y - a.y) * t };
|
|
12842
|
+
}
|
|
12843
|
+
target -= segLens[i];
|
|
12844
|
+
}
|
|
12845
|
+
return points[points.length - 1];
|
|
12846
|
+
}
|
|
12847
|
+
function insetEndpoints(points, inset) {
|
|
12848
|
+
if (points.length < 2) return points;
|
|
12849
|
+
const result = points.slice();
|
|
12850
|
+
if (inset.from > 0) {
|
|
12851
|
+
const a = result[0];
|
|
12852
|
+
const b = result[1];
|
|
12853
|
+
const len = distance(a, b);
|
|
12854
|
+
if (len > inset.from) {
|
|
12855
|
+
const t = inset.from / len;
|
|
12856
|
+
result[0] = { x: a.x + (b.x - a.x) * t, y: a.y + (b.y - a.y) * t };
|
|
12857
|
+
}
|
|
12858
|
+
}
|
|
12859
|
+
if (inset.to > 0) {
|
|
12860
|
+
const lastIdx = result.length - 1;
|
|
12861
|
+
const a = result[lastIdx];
|
|
12862
|
+
const b = result[lastIdx - 1];
|
|
12863
|
+
const len = distance(a, b);
|
|
12864
|
+
if (len > inset.to) {
|
|
12865
|
+
const t = inset.to / len;
|
|
12866
|
+
result[lastIdx] = { x: a.x + (b.x - a.x) * t, y: a.y + (b.y - a.y) * t };
|
|
12867
|
+
}
|
|
12868
|
+
}
|
|
12869
|
+
return result;
|
|
12870
|
+
}
|
|
12871
|
+
var HEADER_HEIGHT = 36;
|
|
12872
|
+
var FIELD_HEIGHT = 29;
|
|
12873
|
+
var DEFAULT_COLOR2 = "#71717a";
|
|
12874
|
+
function markerDirection(side) {
|
|
12875
|
+
switch (side) {
|
|
12876
|
+
case "left":
|
|
12877
|
+
return "right";
|
|
12878
|
+
// entity body is to the right of a left-side anchor
|
|
12879
|
+
case "right":
|
|
12880
|
+
return "left";
|
|
12881
|
+
case "top":
|
|
12882
|
+
return "down";
|
|
12883
|
+
case "bottom":
|
|
12884
|
+
return "up";
|
|
12885
|
+
}
|
|
12886
|
+
}
|
|
12887
|
+
function strokeDashArray(style) {
|
|
12888
|
+
switch (style) {
|
|
12889
|
+
case "dashed":
|
|
12890
|
+
return "8 4";
|
|
12891
|
+
case "dotted":
|
|
12892
|
+
return "2 4";
|
|
12893
|
+
default:
|
|
12894
|
+
return void 0;
|
|
12895
|
+
}
|
|
12346
12896
|
}
|
|
12347
12897
|
function DiagramRelation({
|
|
12348
12898
|
from,
|
|
@@ -12350,6 +12900,12 @@ function DiagramRelation({
|
|
|
12350
12900
|
fromField: fromFieldProp,
|
|
12351
12901
|
toField: toFieldProp,
|
|
12352
12902
|
type,
|
|
12903
|
+
fromMarker: fromMarkerProp,
|
|
12904
|
+
toMarker: toMarkerProp,
|
|
12905
|
+
lineStyle: lineStyleProp,
|
|
12906
|
+
routing = "manhattan",
|
|
12907
|
+
color = DEFAULT_COLOR2,
|
|
12908
|
+
strokeWidth = 2,
|
|
12353
12909
|
label
|
|
12354
12910
|
}) {
|
|
12355
12911
|
const { nodeRects, registryVersion } = useCanvas();
|
|
@@ -12358,68 +12914,160 @@ function DiagramRelation({
|
|
|
12358
12914
|
const fromRect = nodeRects.get(from);
|
|
12359
12915
|
const toRect = nodeRects.get(to);
|
|
12360
12916
|
if (!fromRect || !toRect) return null;
|
|
12917
|
+
const defaults = defaultMarkersForType(type);
|
|
12918
|
+
const fromMarker = fromMarkerProp ?? defaults.fromMarker;
|
|
12919
|
+
const toMarker = toMarkerProp ?? defaults.toMarker;
|
|
12920
|
+
const lineStyle = lineStyleProp ?? defaults.lineStyle;
|
|
12361
12921
|
const fromEntity = schema.entities.find((e) => (e.id ?? e.name) === from);
|
|
12362
12922
|
const toEntity = schema.entities.find((e) => (e.id ?? e.name) === to);
|
|
12363
|
-
|
|
12364
|
-
|
|
12365
|
-
|
|
12366
|
-
|
|
12367
|
-
|
|
12368
|
-
|
|
12369
|
-
|
|
12370
|
-
|
|
12371
|
-
|
|
12372
|
-
|
|
12373
|
-
|
|
12374
|
-
|
|
12375
|
-
|
|
12376
|
-
|
|
12377
|
-
|
|
12378
|
-
|
|
12379
|
-
|
|
12380
|
-
}
|
|
12381
|
-
const fromFieldY = fromFieldIdx >= 0 ? HEADER_HEIGHT + fromFieldIdx * FIELD_HEIGHT + FIELD_HEIGHT / 2 : fromRect.height / 2;
|
|
12382
|
-
const toFieldY = toFieldIdx >= 0 ? HEADER_HEIGHT + toFieldIdx * FIELD_HEIGHT + FIELD_HEIGHT / 2 : toRect.height / 2;
|
|
12383
|
-
const fromCx = fromRect.x + fromRect.width / 2;
|
|
12384
|
-
const toCx = toRect.x + toRect.width / 2;
|
|
12385
|
-
let fromPt, toPt;
|
|
12386
|
-
let fromDir;
|
|
12387
|
-
let toDir;
|
|
12388
|
-
if (fromCx <= toCx) {
|
|
12389
|
-
fromPt = { x: fromRect.x + fromRect.width, y: fromRect.y + fromFieldY };
|
|
12390
|
-
toPt = { x: toRect.x, y: toRect.y + toFieldY };
|
|
12391
|
-
fromDir = "right";
|
|
12392
|
-
toDir = "left";
|
|
12923
|
+
const fromFieldY = resolveFieldY(fromRect, fromEntity?.fields, fromFieldProp, true);
|
|
12924
|
+
const toFieldY = resolveFieldY(toRect, toEntity?.fields, toFieldProp, false, fromEntity?.name ?? from);
|
|
12925
|
+
const anchors = pickAnchors(fromRect, toRect, fromFieldY, toFieldY);
|
|
12926
|
+
if (anchors.from.side === "top" || anchors.from.side === "bottom") {
|
|
12927
|
+
anchors.from.x = fromRect.x + fromRect.width / 2;
|
|
12928
|
+
}
|
|
12929
|
+
if (anchors.to.side === "top" || anchors.to.side === "bottom") {
|
|
12930
|
+
anchors.to.x = toRect.x + toRect.width / 2;
|
|
12931
|
+
}
|
|
12932
|
+
let points;
|
|
12933
|
+
if (routing === "straight") {
|
|
12934
|
+
points = [
|
|
12935
|
+
{ x: anchors.from.x, y: anchors.from.y },
|
|
12936
|
+
{ x: anchors.to.x, y: anchors.to.y }
|
|
12937
|
+
];
|
|
12938
|
+
} else if (routing === "bezier") {
|
|
12939
|
+
points = [];
|
|
12393
12940
|
} else {
|
|
12394
|
-
|
|
12395
|
-
|
|
12396
|
-
|
|
12397
|
-
|
|
12398
|
-
|
|
12399
|
-
|
|
12400
|
-
|
|
12401
|
-
|
|
12402
|
-
|
|
12403
|
-
if (
|
|
12404
|
-
|
|
12405
|
-
|
|
12406
|
-
const
|
|
12407
|
-
const
|
|
12408
|
-
|
|
12409
|
-
|
|
12410
|
-
|
|
12411
|
-
|
|
12412
|
-
const
|
|
12413
|
-
|
|
12414
|
-
|
|
12941
|
+
const obstacles = [];
|
|
12942
|
+
nodeRects.forEach((rect, id) => {
|
|
12943
|
+
if (id === from || id === to) return;
|
|
12944
|
+
obstacles.push(rect);
|
|
12945
|
+
});
|
|
12946
|
+
const initial = manhattanPath(anchors.from, anchors.to, obstacles);
|
|
12947
|
+
points = dodgeObstacles(initial, obstacles);
|
|
12948
|
+
}
|
|
12949
|
+
const insetAmount = { from: markerInset(fromMarker), to: markerInset(toMarker) };
|
|
12950
|
+
if (routing !== "bezier") {
|
|
12951
|
+
points = insetEndpoints(points, insetAmount);
|
|
12952
|
+
}
|
|
12953
|
+
const linePath = routing === "bezier" ? bezierPath2(anchors.from, anchors.to) : pathFromPoints(points);
|
|
12954
|
+
const fromMarkerRenderable = renderMarker(
|
|
12955
|
+
fromMarker,
|
|
12956
|
+
{ x: anchors.from.x, y: anchors.from.y },
|
|
12957
|
+
markerDirection(anchors.from.side)
|
|
12958
|
+
);
|
|
12959
|
+
const toMarkerRenderable = renderMarker(
|
|
12960
|
+
toMarker,
|
|
12961
|
+
{ x: anchors.to.x, y: anchors.to.y },
|
|
12962
|
+
markerDirection(anchors.to.side)
|
|
12963
|
+
);
|
|
12964
|
+
const mid = routing === "bezier" ? { x: (anchors.from.x + anchors.to.x) / 2, y: (anchors.from.y + anchors.to.y) / 2 } : midPoint(points);
|
|
12965
|
+
return {
|
|
12966
|
+
linePath,
|
|
12967
|
+
fromMarker: fromMarkerRenderable,
|
|
12968
|
+
toMarker: toMarkerRenderable,
|
|
12969
|
+
fromAnchor: anchors.from,
|
|
12970
|
+
toAnchor: anchors.to,
|
|
12971
|
+
mid,
|
|
12972
|
+
lineStyle
|
|
12973
|
+
};
|
|
12974
|
+
}, [
|
|
12975
|
+
from,
|
|
12976
|
+
to,
|
|
12977
|
+
fromFieldProp,
|
|
12978
|
+
toFieldProp,
|
|
12979
|
+
type,
|
|
12980
|
+
fromMarkerProp,
|
|
12981
|
+
toMarkerProp,
|
|
12982
|
+
lineStyleProp,
|
|
12983
|
+
routing,
|
|
12984
|
+
schema,
|
|
12985
|
+
nodeRects,
|
|
12986
|
+
registryVersion
|
|
12987
|
+
]);
|
|
12415
12988
|
if (!result) return null;
|
|
12989
|
+
const dashArray = strokeDashArray(result.lineStyle);
|
|
12416
12990
|
return /* @__PURE__ */ jsxRuntime.jsxs("g", { "data-react-fancy-diagram-relation": "", children: [
|
|
12417
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12418
|
-
|
|
12419
|
-
|
|
12420
|
-
|
|
12991
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12992
|
+
"path",
|
|
12993
|
+
{
|
|
12994
|
+
d: result.linePath,
|
|
12995
|
+
fill: "none",
|
|
12996
|
+
stroke: color,
|
|
12997
|
+
strokeWidth,
|
|
12998
|
+
strokeDasharray: dashArray,
|
|
12999
|
+
strokeLinecap: "round",
|
|
13000
|
+
strokeLinejoin: "round"
|
|
13001
|
+
}
|
|
13002
|
+
),
|
|
13003
|
+
result.fromMarker?.paths.map((shape, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
13004
|
+
"path",
|
|
13005
|
+
{
|
|
13006
|
+
d: shape.d,
|
|
13007
|
+
fill: shape.fill === "stroke" ? color : shape.fill === "background" ? "#ffffff" : "none",
|
|
13008
|
+
stroke: color,
|
|
13009
|
+
strokeWidth,
|
|
13010
|
+
strokeLinecap: "round",
|
|
13011
|
+
strokeLinejoin: "round"
|
|
13012
|
+
},
|
|
13013
|
+
`fm-${i}`
|
|
13014
|
+
)),
|
|
13015
|
+
result.fromMarker?.text && /* @__PURE__ */ jsxRuntime.jsx(
|
|
13016
|
+
"text",
|
|
13017
|
+
{
|
|
13018
|
+
x: result.fromAnchor.x,
|
|
13019
|
+
y: result.fromAnchor.y,
|
|
13020
|
+
fontSize: 16,
|
|
13021
|
+
textAnchor: "middle",
|
|
13022
|
+
dominantBaseline: "middle",
|
|
13023
|
+
style: { userSelect: "none" },
|
|
13024
|
+
children: result.fromMarker.text
|
|
13025
|
+
}
|
|
13026
|
+
),
|
|
13027
|
+
result.toMarker?.text && /* @__PURE__ */ jsxRuntime.jsx(
|
|
13028
|
+
"text",
|
|
13029
|
+
{
|
|
13030
|
+
x: result.toAnchor.x,
|
|
13031
|
+
y: result.toAnchor.y,
|
|
13032
|
+
fontSize: 16,
|
|
13033
|
+
textAnchor: "middle",
|
|
13034
|
+
dominantBaseline: "middle",
|
|
13035
|
+
style: { userSelect: "none" },
|
|
13036
|
+
children: result.toMarker.text
|
|
13037
|
+
}
|
|
13038
|
+
),
|
|
13039
|
+
result.toMarker?.paths.map((shape, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
13040
|
+
"path",
|
|
13041
|
+
{
|
|
13042
|
+
d: shape.d,
|
|
13043
|
+
fill: shape.fill === "stroke" ? color : shape.fill === "background" ? "#ffffff" : "none",
|
|
13044
|
+
stroke: color,
|
|
13045
|
+
strokeWidth,
|
|
13046
|
+
strokeLinecap: "round",
|
|
13047
|
+
strokeLinejoin: "round"
|
|
13048
|
+
},
|
|
13049
|
+
`tm-${i}`
|
|
13050
|
+
)),
|
|
13051
|
+
label && /* @__PURE__ */ jsxRuntime.jsx("foreignObject", { x: result.mid.x - 50, y: result.mid.y - 12, width: 100, height: 24, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center text-xs text-zinc-500", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rounded bg-white/90 px-1.5 py-0.5 dark:bg-zinc-900/90", children: label }) }) })
|
|
12421
13052
|
] });
|
|
12422
13053
|
}
|
|
13054
|
+
function resolveFieldY(rect, fields, fieldProp, isFrom, fromName) {
|
|
13055
|
+
if (!fields || fields.length === 0) return void 0;
|
|
13056
|
+
let idx = -1;
|
|
13057
|
+
if (fieldProp) {
|
|
13058
|
+
idx = fields.findIndex((f) => f.name === fieldProp);
|
|
13059
|
+
} else if (isFrom) {
|
|
13060
|
+
idx = fields.findIndex((f) => f.primary);
|
|
13061
|
+
} else {
|
|
13062
|
+
const lower = (fromName ?? "").toLowerCase();
|
|
13063
|
+
idx = fields.findIndex(
|
|
13064
|
+
(f) => f.foreign && (f.name === `${lower}_id` || f.name === `${lower}Id`)
|
|
13065
|
+
);
|
|
13066
|
+
if (idx === -1) idx = fields.findIndex((f) => f.foreign);
|
|
13067
|
+
}
|
|
13068
|
+
if (idx < 0) return void 0;
|
|
13069
|
+
return HEADER_HEIGHT + idx * FIELD_HEIGHT + FIELD_HEIGHT / 2;
|
|
13070
|
+
}
|
|
12423
13071
|
DiagramRelation._isCanvasEdge = true;
|
|
12424
13072
|
DiagramRelation.displayName = "DiagramRelation";
|
|
12425
13073
|
var FORMAT_LABELS = {
|