@diagrammo/dgmo 0.86.0 → 0.88.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/advanced.d.ts +6 -18
- package/dist/advanced.js +40 -37
- package/dist/block.js +6 -17
- package/dist/{chunk-FAV4RDVT.js → chunk-2A4DQAXG.js} +1 -1
- package/dist/{chunk-JIPUBFAM.js → chunk-5KGM44TG.js} +2 -2
- package/dist/{chunk-VEE777MD.js → chunk-5LD7SHXO.js} +3 -3
- package/dist/{chunk-QJ2JOLFN.js → chunk-6I5UN4FD.js} +2 -2
- package/dist/{chunk-ETBXIKK6.js → chunk-ABP5BUD6.js} +9 -430
- package/dist/{chunk-PKXKWHDW.js → chunk-AUS7V54P.js} +1 -1
- package/dist/{chunk-BF7JAFJI.js → chunk-B7CU2HW5.js} +2 -2
- package/dist/{chunk-X2VEJ5NT.js → chunk-BMUWF77V.js} +2 -2
- package/dist/{chunk-BP4BT5TH.js → chunk-CLQIXD2C.js} +1 -1
- package/dist/{chunk-QJFT5MAH.js → chunk-DSG6GBUQ.js} +2 -2
- package/dist/{chunk-EWSESGC2.js → chunk-EJS3K44P.js} +117 -78
- package/dist/{chunk-5JO443MB.js → chunk-HAH5X345.js} +1 -1
- package/dist/{chunk-HBCAY3KR.js → chunk-HTNLLT34.js} +1 -1
- package/dist/{chunk-HUMQIRJK.js → chunk-HTPZDZKQ.js} +2 -2
- package/dist/{chunk-VPVWG2GH.js → chunk-J7Q4VPBJ.js} +1 -1
- package/dist/{chunk-QPE646M2.js → chunk-JLETTWUJ.js} +30 -10
- package/dist/{chunk-3CQS3CIO.js → chunk-LL6D3MES.js} +1 -1
- package/dist/{chunk-ERYHC4KJ.js → chunk-LSQGJN5H.js} +1 -1
- package/dist/{chunk-AGO3PFGS.js → chunk-MVCPO6LI.js} +15 -10
- package/dist/{chunk-E6S2K6O2.js → chunk-N7XRBWXA.js} +2 -2
- package/dist/{chunk-WMIKC5XO.js → chunk-NPWVOFB3.js} +1 -1
- package/dist/{chunk-MYHPRQHR.js → chunk-O6MMQQLF.js} +3 -3
- package/dist/{chunk-GYORDNOM.js → chunk-P5V63L35.js} +1 -1
- package/dist/{chunk-BHZE36F7.js → chunk-PUVTFUNH.js} +1 -1
- package/dist/{chunk-TW6WMZFW.js → chunk-QT3KDDXK.js} +156 -7
- package/dist/{chunk-ZGHV4QLK.js → chunk-RJNZHFNG.js} +1 -1
- package/dist/{chunk-FWNJDD4U.js → chunk-S7W75MIM.js} +3 -20
- package/dist/{chunk-4YA5XW43.js → chunk-VW52W5F6.js} +981 -107
- package/dist/chunk-WXPBP4IT.js +438 -0
- package/dist/{chunk-C6FZZFYD.js → chunk-WZ23JJ7U.js} +1 -1
- package/dist/{chunk-LIYWJ6DV.js → chunk-XIFK423U.js} +108 -13
- package/dist/{chunk-4ELXLATB.js → chunk-XUDGZJTJ.js} +2 -2
- package/dist/{chunk-H6AFNCN3.js → chunk-XVSJYAK7.js} +1 -1
- package/dist/{chunk-LHBMQJC3.js → chunk-XWYR5T52.js} +2 -2
- package/dist/{chunk-QNKHJ5CK.js → chunk-YK4N6TBN.js} +4 -2
- package/dist/{chunk-XFMQSFS4.js → chunk-YMG7JDEY.js} +16 -6
- package/dist/chunk-Z6DXWULM.js +23 -0
- package/dist/{chunk-PBEH52A2.js → chunk-ZNNVI5SR.js} +1 -1
- package/dist/{flowchart-renderer-H72L7BEC.js → flowchart-renderer-THC6Y7EH.js} +7 -6
- package/dist/index.d.ts +68 -1
- package/dist/index.js +76 -7
- package/dist/{layout-QIPCNUSB.js → layout-BOVTLAOT.js} +7 -6
- package/dist/{layout-6JARW64V.js → layout-EHTYSMV4.js} +6 -5
- package/dist/{layout-YELNBVPC.js → layout-P6DTD4RT.js} +6 -5
- package/dist/{layout-T6TAB5OI.js → layout-RANVNAKI.js} +3 -3
- package/dist/{layout-FMKSENGL.js → layout-XUW444O5.js} +5 -4
- package/dist/{layout-search-AW5VBDCV.js → layout-search-VKSBUCDM.js} +57 -28
- package/dist/{renderer-AI2MD52D.js → renderer-222OTVQV.js} +3 -2
- package/dist/{renderer-UUWR7NGF.js → renderer-2KVQGGTT.js} +4 -3
- package/dist/{renderer-E5EKGIX2.js → renderer-2OOPQ4CH.js} +4 -3
- package/dist/{renderer-CZJ4AMYV.js → renderer-3FF4QVGW.js} +3 -2
- package/dist/{renderer-R6VJDZFO.js → renderer-4BHOELCE.js} +4 -3
- package/dist/{renderer-425QUIYO.js → renderer-4BIMRO4X.js} +4 -3
- package/dist/{renderer-5JVVJBAS.js → renderer-A4LMOBZL.js} +8 -7
- package/dist/{renderer-3AOOLHJU.js → renderer-A6ACVK4X.js} +3 -2
- package/dist/{renderer-ML2CLU25.js → renderer-DCFQDBGJ.js} +4 -3
- package/dist/{renderer-RH4U3UVM.js → renderer-LODEVN3V.js} +3 -2
- package/dist/{renderer-E7WF75GY.js → renderer-NHPKNNBD.js} +5 -4
- package/dist/{renderer-JEEGPLMM.js → renderer-R34GJL7U.js} +8 -7
- package/dist/{renderer-2BWRW23Z.js → renderer-RENDISO5.js} +1 -1
- package/dist/{renderer-NX4YKWCJ.js → renderer-RNCYODNF.js} +1 -1
- package/dist/{renderer-VKAJ52UO.js → renderer-SDUSBCJI.js} +3 -2
- package/dist/{renderer-RLSR7N6I.js → renderer-TPOZOAXR.js} +5 -4
- package/dist/{renderer-RUGMKHX5.js → renderer-WH2HWE5Z.js} +3 -2
- package/dist/{renderer-V6LLASGN.js → renderer-X5A5VIRD.js} +5 -4
- package/dist/{renderer-ADX4DWRJ.js → renderer-XUPLAO4B.js} +4 -2
- package/dist/{renderer-EWJS2RAZ.js → renderer-YDAVCRTP.js} +3 -2
- package/dist/{state-renderer-DDVJ43HR.js → state-renderer-5IQ4OJUI.js} +7 -6
- package/gallery/fixtures/journey-map.dgmo +28 -0
- package/gallery/fixtures/mindmap.dgmo +31 -0
- package/gallery/fixtures/pert.dgmo +27 -0
- package/gallery/fixtures/wireframe.dgmo +30 -0
- package/package.json +2 -2
|
@@ -4,7 +4,10 @@ import {
|
|
|
4
4
|
NODE_HEIGHT,
|
|
5
5
|
NODE_WIDTH,
|
|
6
6
|
measureEdgeLabel
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-QT3KDDXK.js";
|
|
8
|
+
import {
|
|
9
|
+
measureText
|
|
10
|
+
} from "./chunk-KAO7JL4I.js";
|
|
8
11
|
|
|
9
12
|
// src/boxes-and-lines/edge-clip.ts
|
|
10
13
|
function rectBorderPoint(rect, toward) {
|
|
@@ -48,6 +51,8 @@ var DUMMY_THICK = 10;
|
|
|
48
51
|
var MARGIN = 40;
|
|
49
52
|
var GROUP_PAD = 16;
|
|
50
53
|
var GROUP_LABEL_ZONE = 32;
|
|
54
|
+
var GROUP_TITLE_FONT_SIZE = 14;
|
|
55
|
+
var TITLE_CLEAR = 6;
|
|
51
56
|
var GROUP_GAP = 24;
|
|
52
57
|
var TIER_GAP = GROUP_LABEL_ZONE + 2 * GROUP_PAD;
|
|
53
58
|
var W_REAL_REAL = 1;
|
|
@@ -556,6 +561,70 @@ function groupedTierCandidates(parsed, sizes, opts) {
|
|
|
556
561
|
});
|
|
557
562
|
const chainById = /* @__PURE__ */ new Map();
|
|
558
563
|
for (const ch of chains) chainById.set(ch.edgeIdx, ch.chain);
|
|
564
|
+
const nodeBox = new Map(
|
|
565
|
+
layoutNodes.map((n) => [
|
|
566
|
+
n.label,
|
|
567
|
+
{
|
|
568
|
+
l: n.x - n.width / 2,
|
|
569
|
+
r: n.x + n.width / 2,
|
|
570
|
+
t: n.y - n.height / 2,
|
|
571
|
+
b: n.y + n.height / 2
|
|
572
|
+
}
|
|
573
|
+
])
|
|
574
|
+
);
|
|
575
|
+
const depthOf = (label) => {
|
|
576
|
+
let d = 0;
|
|
577
|
+
let cur = label;
|
|
578
|
+
const guard = /* @__PURE__ */ new Set();
|
|
579
|
+
while (cur && !guard.has(cur)) {
|
|
580
|
+
guard.add(cur);
|
|
581
|
+
cur = groupByLabel.get(cur)?.parentGroup;
|
|
582
|
+
if (cur) d++;
|
|
583
|
+
}
|
|
584
|
+
return d;
|
|
585
|
+
};
|
|
586
|
+
const childGroups = /* @__PURE__ */ new Map();
|
|
587
|
+
for (const g of parsed.groups)
|
|
588
|
+
if (g.parentGroup)
|
|
589
|
+
(childGroups.get(g.parentGroup) ?? childGroups.set(g.parentGroup, []).get(g.parentGroup)).push(g.label);
|
|
590
|
+
const rectByGroup = /* @__PURE__ */ new Map();
|
|
591
|
+
const ordered = [...parsed.groups].sort(
|
|
592
|
+
(a, b) => depthOf(b.label) - depthOf(a.label)
|
|
593
|
+
);
|
|
594
|
+
const layoutGroups = [];
|
|
595
|
+
for (const grp of ordered) {
|
|
596
|
+
let l = Infinity, r = -Infinity, t = Infinity, bm = -Infinity;
|
|
597
|
+
const acc2 = (box) => {
|
|
598
|
+
l = Math.min(l, box.l);
|
|
599
|
+
r = Math.max(r, box.r);
|
|
600
|
+
t = Math.min(t, box.t);
|
|
601
|
+
bm = Math.max(bm, box.b);
|
|
602
|
+
};
|
|
603
|
+
for (const c of grp.children) {
|
|
604
|
+
const nb = nodeBox.get(c);
|
|
605
|
+
if (nb) acc2(nb);
|
|
606
|
+
}
|
|
607
|
+
for (const sub of childGroups.get(grp.label) ?? []) {
|
|
608
|
+
const sr = rectByGroup.get(sub);
|
|
609
|
+
if (sr) acc2(sr);
|
|
610
|
+
}
|
|
611
|
+
if (!Number.isFinite(l)) continue;
|
|
612
|
+
const x0 = l - GROUP_PAD;
|
|
613
|
+
const x1 = r + GROUP_PAD;
|
|
614
|
+
const y0 = t - GROUP_LABEL_ZONE;
|
|
615
|
+
const y1 = bm + GROUP_PAD;
|
|
616
|
+
rectByGroup.set(grp.label, { l: x0, r: x1, t: y0, b: y1 });
|
|
617
|
+
layoutGroups.push({
|
|
618
|
+
label: grp.label,
|
|
619
|
+
lineNumber: grp.lineNumber,
|
|
620
|
+
x: (x0 + x1) / 2,
|
|
621
|
+
y: (y0 + y1) / 2,
|
|
622
|
+
width: x1 - x0,
|
|
623
|
+
height: y1 - y0,
|
|
624
|
+
collapsed: false,
|
|
625
|
+
childCount: grp.children.length
|
|
626
|
+
});
|
|
627
|
+
}
|
|
559
628
|
let minCross = Infinity, maxCross = -Infinity;
|
|
560
629
|
for (const n of node.values()) {
|
|
561
630
|
if (n.dummy) continue;
|
|
@@ -574,35 +643,69 @@ function groupedTierCandidates(parsed, sizes, opts) {
|
|
|
574
643
|
side: sideOf(b),
|
|
575
644
|
span: Math.abs(node.get(b.src).rank - node.get(b.tgt).rank)
|
|
576
645
|
})).sort((a, b) => a.side - b.side || a.span - b.span);
|
|
577
|
-
const sideCounts = /* @__PURE__ */ new Map();
|
|
578
|
-
for (const b of backSorted)
|
|
579
|
-
sideCounts.set(b.side, (sideCounts.get(b.side) ?? 0) + 1);
|
|
580
646
|
const laneCounter = /* @__PURE__ */ new Map();
|
|
581
647
|
const backPoints = /* @__PURE__ */ new Map();
|
|
648
|
+
const faceKey = (id, side) => `${id}\0${side}`;
|
|
649
|
+
const faceCount = /* @__PURE__ */ new Map();
|
|
650
|
+
for (const b of backSorted)
|
|
651
|
+
for (const id of [b.src, b.tgt])
|
|
652
|
+
faceCount.set(
|
|
653
|
+
faceKey(id, b.side),
|
|
654
|
+
(faceCount.get(faceKey(id, b.side)) ?? 0) + 1
|
|
655
|
+
);
|
|
656
|
+
const faceSeen = /* @__PURE__ */ new Map();
|
|
657
|
+
const portSlot = (id, side) => {
|
|
658
|
+
const key = faceKey(id, side);
|
|
659
|
+
const j = faceSeen.get(key) ?? 0;
|
|
660
|
+
faceSeen.set(key, j + 1);
|
|
661
|
+
return 2 * (j + 1) / (faceCount.get(key) + 1) - 1;
|
|
662
|
+
};
|
|
663
|
+
const titleStrips = layoutGroups.map((g) => {
|
|
664
|
+
const tw = measureText(g.label, GROUP_TITLE_FONT_SIZE, { bold: true });
|
|
665
|
+
const x0 = g.x - tw / 2 - TITLE_CLEAR;
|
|
666
|
+
const x1 = g.x + tw / 2 + TITLE_CLEAR;
|
|
667
|
+
const y0 = g.y - g.height / 2;
|
|
668
|
+
const y1 = y0 + GROUP_LABEL_ZONE;
|
|
669
|
+
return isTB ? { c0: x0, c1: x1, r0: y0, r1: y1 } : { c0: y0, c1: y1, r0: x0, r1: x1 };
|
|
670
|
+
});
|
|
671
|
+
const stubHitsTitle = (r, ca, cb) => titleStrips.some(
|
|
672
|
+
(t) => r > t.r0 && r < t.r1 && Math.min(ca, cb) < t.c1 && Math.max(ca, cb) > t.c0
|
|
673
|
+
);
|
|
674
|
+
const gapMid = (rank, dir) => {
|
|
675
|
+
const nb = rank + dir;
|
|
676
|
+
if (nb < 0 || nb > maxRank) return void 0;
|
|
677
|
+
const a = bandCenter[rank] + dir * bandDepth[rank] / 2;
|
|
678
|
+
const b = bandCenter[nb] - dir * bandDepth[nb] / 2;
|
|
679
|
+
return (a + b) / 2;
|
|
680
|
+
};
|
|
582
681
|
for (const b of backSorted) {
|
|
583
682
|
const s = b.side;
|
|
584
683
|
const k = laneCounter.get(s) ?? 0;
|
|
585
684
|
laneCounter.set(s, k + 1);
|
|
586
|
-
const K = sideCounts.get(s);
|
|
587
685
|
const src = node.get(b.src);
|
|
588
686
|
const tgt = node.get(b.tgt);
|
|
589
687
|
const laneC = s > 0 ? maxCross + GAP + k * LANE : minCross - GAP - k * LANE;
|
|
590
688
|
const srcCtr = bandCenter[src.rank];
|
|
591
689
|
const tgtCtr = bandCenter[tgt.rank];
|
|
592
|
-
const
|
|
593
|
-
const srcR = srcCtr
|
|
594
|
-
const tgtR = tgtCtr
|
|
690
|
+
const dir = srcCtr >= tgtCtr ? 1 : -1;
|
|
691
|
+
const srcR = srcCtr + dir * portSlot(b.src, s) * faceLim(src.depth);
|
|
692
|
+
const tgtR = tgtCtr - dir * portSlot(b.tgt, s) * faceLim(tgt.depth);
|
|
595
693
|
const m = (c, rr) => isTB ? { x: c, y: rr } : { x: rr, y: c };
|
|
596
694
|
const off = 10;
|
|
597
695
|
const srcEdgeC = src.cross + s * (src.thick / 2 + off);
|
|
598
696
|
const tgtEdgeC = tgt.cross + s * (tgt.thick / 2 + off);
|
|
697
|
+
const end = (n, ctr, r, edgeC, toward) => {
|
|
698
|
+
if (stubHitsTitle(r, n.cross, laneC)) {
|
|
699
|
+
const g = gapMid(n.rank, toward);
|
|
700
|
+
if (g !== void 0 && !stubHitsTitle(g, n.cross, laneC))
|
|
701
|
+
return [m(n.cross, ctr), m(n.cross, g), m(laneC, g)];
|
|
702
|
+
}
|
|
703
|
+
return [m(n.cross, ctr), m(edgeC, r), m(laneC, r)];
|
|
704
|
+
};
|
|
705
|
+
const toTgt = tgt.rank >= src.rank ? 1 : -1;
|
|
599
706
|
backPoints.set(b.edgeIdx, [
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
m(laneC, srcR),
|
|
603
|
-
m(laneC, tgtR),
|
|
604
|
-
m(tgtEdgeC, tgtR),
|
|
605
|
-
m(tgt.cross, tgtCtr)
|
|
707
|
+
...end(src, srcCtr, srcR, srcEdgeC, toTgt),
|
|
708
|
+
...end(tgt, tgtCtr, tgtR, tgtEdgeC, -toTgt).reverse()
|
|
606
709
|
]);
|
|
607
710
|
}
|
|
608
711
|
const flatPoints = /* @__PURE__ */ new Map();
|
|
@@ -659,70 +762,6 @@ function groupedTierCandidates(parsed, sizes, opts) {
|
|
|
659
762
|
metadata: e.metadata
|
|
660
763
|
});
|
|
661
764
|
}
|
|
662
|
-
const nodeBox = new Map(
|
|
663
|
-
layoutNodes.map((n) => [
|
|
664
|
-
n.label,
|
|
665
|
-
{
|
|
666
|
-
l: n.x - n.width / 2,
|
|
667
|
-
r: n.x + n.width / 2,
|
|
668
|
-
t: n.y - n.height / 2,
|
|
669
|
-
b: n.y + n.height / 2
|
|
670
|
-
}
|
|
671
|
-
])
|
|
672
|
-
);
|
|
673
|
-
const depthOf = (label) => {
|
|
674
|
-
let d = 0;
|
|
675
|
-
let cur = label;
|
|
676
|
-
const guard = /* @__PURE__ */ new Set();
|
|
677
|
-
while (cur && !guard.has(cur)) {
|
|
678
|
-
guard.add(cur);
|
|
679
|
-
cur = groupByLabel.get(cur)?.parentGroup;
|
|
680
|
-
if (cur) d++;
|
|
681
|
-
}
|
|
682
|
-
return d;
|
|
683
|
-
};
|
|
684
|
-
const childGroups = /* @__PURE__ */ new Map();
|
|
685
|
-
for (const g of parsed.groups)
|
|
686
|
-
if (g.parentGroup)
|
|
687
|
-
(childGroups.get(g.parentGroup) ?? childGroups.set(g.parentGroup, []).get(g.parentGroup)).push(g.label);
|
|
688
|
-
const rectByGroup = /* @__PURE__ */ new Map();
|
|
689
|
-
const ordered = [...parsed.groups].sort(
|
|
690
|
-
(a, b) => depthOf(b.label) - depthOf(a.label)
|
|
691
|
-
);
|
|
692
|
-
const layoutGroups = [];
|
|
693
|
-
for (const grp of ordered) {
|
|
694
|
-
let l = Infinity, r = -Infinity, t = Infinity, bm = -Infinity;
|
|
695
|
-
const acc2 = (box) => {
|
|
696
|
-
l = Math.min(l, box.l);
|
|
697
|
-
r = Math.max(r, box.r);
|
|
698
|
-
t = Math.min(t, box.t);
|
|
699
|
-
bm = Math.max(bm, box.b);
|
|
700
|
-
};
|
|
701
|
-
for (const c of grp.children) {
|
|
702
|
-
const nb = nodeBox.get(c);
|
|
703
|
-
if (nb) acc2(nb);
|
|
704
|
-
}
|
|
705
|
-
for (const sub of childGroups.get(grp.label) ?? []) {
|
|
706
|
-
const sr = rectByGroup.get(sub);
|
|
707
|
-
if (sr) acc2(sr);
|
|
708
|
-
}
|
|
709
|
-
if (!Number.isFinite(l)) continue;
|
|
710
|
-
const x0 = l - GROUP_PAD;
|
|
711
|
-
const x1 = r + GROUP_PAD;
|
|
712
|
-
const y0 = t - GROUP_LABEL_ZONE;
|
|
713
|
-
const y1 = bm + GROUP_PAD;
|
|
714
|
-
rectByGroup.set(grp.label, { l: x0, r: x1, t: y0, b: y1 });
|
|
715
|
-
layoutGroups.push({
|
|
716
|
-
label: grp.label,
|
|
717
|
-
lineNumber: grp.lineNumber,
|
|
718
|
-
x: (x0 + x1) / 2,
|
|
719
|
-
y: (y0 + y1) / 2,
|
|
720
|
-
width: x1 - x0,
|
|
721
|
-
height: y1 - y0,
|
|
722
|
-
collapsed: false,
|
|
723
|
-
childCount: grp.children.length
|
|
724
|
-
});
|
|
725
|
-
}
|
|
726
765
|
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
|
|
727
766
|
const ext = (x0, y0, x1, y1) => {
|
|
728
767
|
minX = Math.min(minX, x0);
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
layoutERDiagram
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-2A4DQAXG.js";
|
|
4
4
|
import {
|
|
5
5
|
NOTE_BADGE_RADIUS,
|
|
6
6
|
noteConnectorPoints,
|
|
7
7
|
renderNoteBadge,
|
|
8
8
|
renderNoteBox,
|
|
9
9
|
renderNoteConnector
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-HAH5X345.js";
|
|
11
11
|
import {
|
|
12
12
|
ScaleContext
|
|
13
13
|
} from "./chunk-24YPR5EH.js";
|
|
@@ -54,9 +54,26 @@ import {
|
|
|
54
54
|
themeBaseBg
|
|
55
55
|
} from "./chunk-7HWY4QAJ.js";
|
|
56
56
|
|
|
57
|
+
// src/embed/escape.ts
|
|
58
|
+
var HTML_ENTITIES = {
|
|
59
|
+
"&": "&",
|
|
60
|
+
"<": "<",
|
|
61
|
+
">": ">",
|
|
62
|
+
'"': """,
|
|
63
|
+
"'": "'"
|
|
64
|
+
};
|
|
65
|
+
function escapeHtml(s) {
|
|
66
|
+
return s.replace(/[&<>"']/g, (ch) => HTML_ENTITIES[ch] ?? ch);
|
|
67
|
+
}
|
|
68
|
+
function escapeAttr(s) {
|
|
69
|
+
return s.replace(/[&<>"']/g, (ch) => HTML_ENTITIES[ch] ?? ch);
|
|
70
|
+
}
|
|
71
|
+
|
|
57
72
|
// src/timeline/renderer.ts
|
|
58
73
|
import * as d3Scale from "d3-scale";
|
|
59
74
|
import * as d3Selection from "d3-selection";
|
|
75
|
+
var MIN_TOP_SCALE_BAND = 26;
|
|
76
|
+
var MIN_BOTTOM_BAND = 30;
|
|
60
77
|
function renderEras(g, eras, scale, isVertical, innerWidth, innerHeight, onEnter, onLeave, hasScale = false, _tooltip = null, palette, reservedLabelY, fillMode, outlineBg) {
|
|
61
78
|
const eraColors = getEraColors(
|
|
62
79
|
palette ?? getPalette(DEFAULT_PALETTE_ID).light
|
|
@@ -281,7 +298,7 @@ function hideEventDatesOnScale(g) {
|
|
|
281
298
|
}
|
|
282
299
|
function buildEventTooltipHtml(ev) {
|
|
283
300
|
const datePart = ev.endDate ? `${formatDateLabel(ev.date)} \u2192 ${formatDateLabel(ev.endDate)}` : formatDateLabel(ev.date);
|
|
284
|
-
return `<strong>${ev.label}</strong><br>${datePart}`;
|
|
301
|
+
return `<strong>${escapeHtml(ev.label)}</strong><br>${datePart}`;
|
|
285
302
|
}
|
|
286
303
|
function renderTimelineGroupLegend(g, groups, groupColorMap, textColor, palette, isDark, legendY, onHover, onLeave) {
|
|
287
304
|
const PILL_H = 22;
|
|
@@ -784,11 +801,12 @@ function renderTimelineHorizontalTimeSort(container, parsed, palette, isDark, se
|
|
|
784
801
|
const MARKER_ROW_H = ctx.structural(22);
|
|
785
802
|
const eraReserve = timelineEras.length > 0 ? ERA_ROW_H : 0;
|
|
786
803
|
const markerReserve = timelineMarkers.length > 0 ? MARKER_ROW_H : 0;
|
|
787
|
-
const topScaleH = timelineScale ? ctx.structural(40) : 0;
|
|
804
|
+
const topScaleH = timelineScale ? Math.max(ctx.structural(40), MIN_TOP_SCALE_BAND) : 0;
|
|
805
|
+
const hasGroupLegend = timelineGroups.length > 0 && !parsed.noLegend;
|
|
788
806
|
const margin = {
|
|
789
|
-
top: ctx.aesthetic(
|
|
807
|
+
top: 50 + (hasGroupLegend ? 54 : ctx.aesthetic(54)) + topScaleH + eraReserve + markerReserve + tagLegendReserve,
|
|
790
808
|
right: ctx.aesthetic(40),
|
|
791
|
-
bottom: ctx.aesthetic(40) + scaleMargin,
|
|
809
|
+
bottom: Math.max(ctx.aesthetic(40), MIN_BOTTOM_BAND) + scaleMargin,
|
|
792
810
|
left: ctx.aesthetic(60)
|
|
793
811
|
};
|
|
794
812
|
const markerLabelY = markerReserve ? -(topScaleH + MARKER_ROW_H / 2) : 0;
|
|
@@ -859,8 +877,8 @@ function renderTimelineHorizontalTimeSort(container, parsed, palette, isDark, se
|
|
|
859
877
|
formatBoundaryLabel(latestEndDateStr, earliestStartDateStr)
|
|
860
878
|
);
|
|
861
879
|
}
|
|
862
|
-
if (
|
|
863
|
-
const legendY = timelineScale ? -
|
|
880
|
+
if (hasGroupLegend) {
|
|
881
|
+
const legendY = timelineScale ? -(topScaleH + 35) : -55;
|
|
864
882
|
renderTimelineGroupLegend(
|
|
865
883
|
g,
|
|
866
884
|
timelineGroups,
|
|
@@ -1018,7 +1036,7 @@ function renderTimelineHorizontalGrouped(container, parsed, palette, isDark, set
|
|
|
1018
1036
|
const MARKER_ROW_H = ctx.structural(22);
|
|
1019
1037
|
const eraReserve = timelineEras.length > 0 ? ERA_ROW_H : 0;
|
|
1020
1038
|
const markerReserve = timelineMarkers.length > 0 ? MARKER_ROW_H : 0;
|
|
1021
|
-
const topScaleH = timelineScale ? ctx.structural(40) : 0;
|
|
1039
|
+
const topScaleH = timelineScale ? Math.max(ctx.structural(40), MIN_TOP_SCALE_BAND) : 0;
|
|
1022
1040
|
const maxGroupNameLen = Math.max(...lanes.map((l) => l.name.length)) + 2;
|
|
1023
1041
|
const maxEventLabelLen = Math.max(
|
|
1024
1042
|
0,
|
|
@@ -1029,11 +1047,11 @@ function renderTimelineHorizontalGrouped(container, parsed, palette, isDark, set
|
|
|
1029
1047
|
ctx.aesthetic(140),
|
|
1030
1048
|
maxLeftLabelLen * sCharW + ctx.aesthetic(30)
|
|
1031
1049
|
);
|
|
1032
|
-
const baseTopMargin = title ?
|
|
1050
|
+
const baseTopMargin = title ? 50 : ctx.aesthetic(20);
|
|
1033
1051
|
const margin = {
|
|
1034
1052
|
top: baseTopMargin + topScaleH + eraReserve + markerReserve + tagLegendReserve,
|
|
1035
1053
|
right: ctx.aesthetic(40),
|
|
1036
|
-
bottom: ctx.aesthetic(40) + scaleMargin,
|
|
1054
|
+
bottom: Math.max(ctx.aesthetic(40), MIN_BOTTOM_BAND) + scaleMargin,
|
|
1037
1055
|
left: dynamicLeftMargin
|
|
1038
1056
|
};
|
|
1039
1057
|
const markerLabelY = markerReserve ? -(topScaleH + MARKER_ROW_H / 2) : 0;
|
|
@@ -1121,7 +1139,7 @@ function renderTimelineHorizontalGrouped(container, parsed, palette, isDark, set
|
|
|
1121
1139
|
g.append("rect").attr("class", "tl-group-header-bg").attr("data-group", lane.name).attr("x", bandX).attr("y", bandY).attr("width", bandW).attr("height", bandH).attr("rx", sBandRx).attr("fill", shapeFill(palette, laneColor, isDark, { mode: fillMode })).style("pointer-events", "none");
|
|
1122
1140
|
g.append("rect").attr("class", "tl-group-header-accent").attr("data-group", lane.name).attr("x", bandX).attr("y", bandY).attr("width", sBandAccentW).attr("height", bandH).attr("fill", laneColor).attr("clip-path", `url(#${clipId})`).style("pointer-events", "none");
|
|
1123
1141
|
const headerG = g.append("g").attr("class", "tl-group-header").attr("data-group", lane.name).style("cursor", "pointer").on("mouseenter", () => fadeToGroup(g, lane.name)).on("mouseleave", () => fadeReset(g)).on("click", () => toggleGroup(lane.name));
|
|
1124
|
-
headerG.append("text").attr("x",
|
|
1142
|
+
headerG.append("text").attr("x", bandX + 5).attr("y", curY + sBarH / 2).attr("dy", "0.35em").attr("text-anchor", "start").attr("fill", textColor).attr("font-size", sLaneHeaderFont).attr("font-weight", "bold").text(`${toggleIcon} ${lane.name}`);
|
|
1125
1143
|
if (lane.events.length > 0) {
|
|
1126
1144
|
const evDates = lane.events.map((ev) => parseTimelineDate(ev.date));
|
|
1127
1145
|
const evEndDates = lane.events.filter((ev) => ev.endDate).map((ev) => parseTimelineDate(ev.endDate));
|
|
@@ -1672,6 +1690,8 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
|
|
|
1672
1690
|
}
|
|
1673
1691
|
|
|
1674
1692
|
export {
|
|
1693
|
+
escapeHtml,
|
|
1694
|
+
escapeAttr,
|
|
1675
1695
|
formatDateLabel,
|
|
1676
1696
|
renderTimeline
|
|
1677
1697
|
};
|
|
@@ -72,10 +72,10 @@ import * as d3Scale from "d3-scale";
|
|
|
72
72
|
import * as d3Selection from "d3-selection";
|
|
73
73
|
var BAR_H = 22;
|
|
74
74
|
var ROW_GAP = 6;
|
|
75
|
-
var GROUP_GAP = 14;
|
|
76
75
|
var MILESTONE_SIZE = 10;
|
|
77
76
|
var MIN_LEFT_MARGIN = 120;
|
|
78
77
|
var BOTTOM_MARGIN = 40;
|
|
78
|
+
var BOTTOM_AXIS_LABEL_RESERVE = 30;
|
|
79
79
|
var RIGHT_MARGIN = 20;
|
|
80
80
|
var LABEL_PAD = 8;
|
|
81
81
|
var LABEL_GAP = 5;
|
|
@@ -213,9 +213,11 @@ function renderGantt(container, resolved, palette, isDark, options, exportDims)
|
|
|
213
213
|
const ctx = exportDims ? ScaleContext.identity() : ScaleContext.from(containerWidth, idealWidth);
|
|
214
214
|
const sBarH = ctx.structural(BAR_H);
|
|
215
215
|
const sRowGap = ctx.structural(ROW_GAP);
|
|
216
|
-
const sGroupGap = ctx.structural(GROUP_GAP);
|
|
217
216
|
const sMilestoneSize = ctx.structural(MILESTONE_SIZE);
|
|
218
|
-
const sBottomMargin =
|
|
217
|
+
const sBottomMargin = Math.max(
|
|
218
|
+
ctx.aesthetic(BOTTOM_MARGIN),
|
|
219
|
+
BOTTOM_AXIS_LABEL_RESERVE
|
|
220
|
+
);
|
|
219
221
|
const sRightMargin = ctx.aesthetic(RIGHT_MARGIN);
|
|
220
222
|
const sLabelPad = ctx.structural(LABEL_PAD);
|
|
221
223
|
const sLabelGap = ctx.structural(LABEL_GAP);
|
|
@@ -225,10 +227,10 @@ function renderGantt(container, resolved, palette, isDark, options, exportDims)
|
|
|
225
227
|
const sTitleY = ctx.aesthetic(TITLE_Y);
|
|
226
228
|
const sHeaderRowH = ctx.structural(HEADER_ROW_H);
|
|
227
229
|
const sContentTopPad = ctx.aesthetic(CONTENT_TOP_PAD);
|
|
228
|
-
const sTopDateLabelReserve =
|
|
230
|
+
const sTopDateLabelReserve = topDateLabelReserve;
|
|
229
231
|
const sSprintLabelReserve = ctx.structural(sprintLabelReserve);
|
|
230
232
|
const sTitleHeight = ctx.aesthetic(titleHeight);
|
|
231
|
-
const sTagLegendReserve =
|
|
233
|
+
const sTagLegendReserve = tagLegendReserve;
|
|
232
234
|
const inlineRequested = resolved.options.legendInline === true && resolved.tagGroups.length > 0;
|
|
233
235
|
const legendExtent = inlineRequested ? getLegendExtent(
|
|
234
236
|
{
|
|
@@ -267,15 +269,17 @@ function renderGantt(container, resolved, palette, isDark, options, exportDims)
|
|
|
267
269
|
const sTodayLabelY = sTodayReserve ? -(sTopDateLabelReserve + sHeaderRowH / 2) : 0;
|
|
268
270
|
const sMarkerLabelY = sMarkerReserve ? -(sTopDateLabelReserve + sTodayReserve + sHeaderRowH / 2) : 0;
|
|
269
271
|
const sEraLabelY = sEraReserve ? -(sTopDateLabelReserve + sTodayReserve + sMarkerReserve + sHeaderRowH / 2) : 0;
|
|
270
|
-
const sContentH = isTagMode ? totalRows * (sBarH + sRowGap) : totalRows * (sBarH + sRowGap)
|
|
272
|
+
const sContentH = isTagMode ? totalRows * (sBarH + sRowGap) : totalRows * (sBarH + sRowGap);
|
|
271
273
|
const sInnerHeight = sContentTopPad + sContentH;
|
|
272
274
|
const sOuterHeight = sMarginTop + sInnerHeight + sBottomMargin;
|
|
273
275
|
const sprintRightPad = resolved.sprints.length > 0 ? 50 : 0;
|
|
274
|
-
const
|
|
275
|
-
const
|
|
276
|
+
const containerHeight = options?.fitToContainer ? container.clientHeight : 0;
|
|
277
|
+
const layoutWidth = !exportDims && containerHeight > 0 && sOuterHeight > containerHeight ? containerWidth * sOuterHeight / containerHeight : containerWidth;
|
|
278
|
+
const innerWidth = layoutWidth - leftMargin - sRightMargin - sprintRightPad;
|
|
279
|
+
const svg = d3Selection.select(container).append("svg").attr("viewBox", `0 0 ${layoutWidth} ${sOuterHeight}`).attr("width", exportDims ? containerWidth : "100%").attr("preserveAspectRatio", "xMidYMin meet").attr("font-family", FONT_FAMILY).style("overflow", "visible");
|
|
276
280
|
const g = svg.append("g").attr("transform", `translate(${leftMargin}, ${sMarginTop})`);
|
|
277
281
|
if (showTitle) {
|
|
278
|
-
svg.append("text").attr("class", "chart-title").attr("x", header.titleX).attr("y", sTitleY).attr("text-anchor", header.titleAnchor).attr("font-size", sTitleFontSize).attr("font-weight", TITLE_FONT_WEIGHT).attr("fill", palette.text).text(title);
|
|
282
|
+
svg.append("text").attr("class", "chart-title").attr("x", header.inline ? header.titleX : layoutWidth / 2).attr("y", sTitleY).attr("text-anchor", header.titleAnchor).attr("font-size", sTitleFontSize).attr("font-weight", TITLE_FONT_WEIGHT).attr("fill", palette.text).text(title);
|
|
279
283
|
}
|
|
280
284
|
function drawLegend() {
|
|
281
285
|
svg.selectAll(".gantt-tag-legend-container").remove();
|
|
@@ -362,7 +366,8 @@ function renderGantt(container, resolved, palette, isDark, options, exportDims)
|
|
|
362
366
|
drawLegend();
|
|
363
367
|
const startTime = dateToFractionalYear(resolved.startDate);
|
|
364
368
|
const endTime = dateToFractionalYear(resolved.endDate);
|
|
365
|
-
const
|
|
369
|
+
const span = endTime - startTime;
|
|
370
|
+
const domainPad = span > 0 ? span * 0.02 : 1 / 365;
|
|
366
371
|
const domainMin = startTime - domainPad;
|
|
367
372
|
const domainMax = endTime + domainPad;
|
|
368
373
|
const xScale = d3Scale.scaleLinear().domain([domainMin, domainMax]).range([0, innerWidth]);
|
|
@@ -6,13 +6,13 @@ import {
|
|
|
6
6
|
} from "./chunk-DOXBS7F5.js";
|
|
7
7
|
import {
|
|
8
8
|
wrapNoteBody
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-RJNZHFNG.js";
|
|
10
10
|
import {
|
|
11
11
|
NOTE_BULLET_INDENT
|
|
12
12
|
} from "./chunk-5DH3KYFH.js";
|
|
13
13
|
import {
|
|
14
14
|
renderInlineText
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-S7W75MIM.js";
|
|
16
16
|
import {
|
|
17
17
|
ScaleContext
|
|
18
18
|
} from "./chunk-24YPR5EH.js";
|
|
@@ -4,18 +4,18 @@ import {
|
|
|
4
4
|
renderNoteBadge,
|
|
5
5
|
renderNoteBox,
|
|
6
6
|
renderNoteConnector
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-HAH5X345.js";
|
|
8
8
|
import {
|
|
9
9
|
appendArrowheadMarkers,
|
|
10
10
|
appendReverseArrowheadMarkers
|
|
11
11
|
} from "./chunk-XBJJP2HN.js";
|
|
12
12
|
import {
|
|
13
13
|
wrapDescriptionLines
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-NPWVOFB3.js";
|
|
15
15
|
import {
|
|
16
16
|
renderInlineText,
|
|
17
17
|
stripInlineMarkdown
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-S7W75MIM.js";
|
|
19
19
|
import {
|
|
20
20
|
ScaleContext
|
|
21
21
|
} from "./chunk-24YPR5EH.js";
|
|
@@ -1579,7 +1579,7 @@ function renderScurveBlock(svg, data, args) {
|
|
|
1579
1579
|
}));
|
|
1580
1580
|
const curve = d3Shape.line().x((d) => d.x).y((d) => d.y).curve(d3Shape.curveMonotoneX)(points);
|
|
1581
1581
|
if (curve) {
|
|
1582
|
-
const clipId = `pert-scurve-clip-${
|
|
1582
|
+
const clipId = `pert-scurve-clip-${[plotLeft, plotTop, plotW, plotH].map((v) => Math.round(v)).join("-")}`;
|
|
1583
1583
|
block.append("clipPath").attr("id", clipId).append("rect").attr("x", plotLeft).attr("y", plotTop).attr("width", plotW).attr("height", plotH);
|
|
1584
1584
|
block.append("path").attr("class", "pert-scurve-line").attr("d", curve).attr("fill", "none").attr("stroke", palette.colors.red).attr("stroke-width", 2).attr("clip-path", `url(#${clipId})`);
|
|
1585
1585
|
}
|