@diagrammo/dgmo 0.92.0 → 0.92.1
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 +8 -1
- package/dist/advanced.js +5 -5
- package/dist/block.js +3 -3
- package/dist/{chunk-LMP6Y7QO.js → chunk-4QLGGQNO.js} +42 -10
- package/dist/{chunk-F7326NVM.js → chunk-O5WUZGPV.js} +41 -8
- package/dist/{chunk-62BP7AJU.js → chunk-QQPNCXAO.js} +1 -1
- package/dist/{chunk-YRYKTYMQ.js → chunk-VSOZZYLK.js} +106 -12
- package/dist/{chunk-RJ2JW3FG.js → chunk-Y2V5AEVG.js} +3 -3
- package/dist/index.js +3 -3
- package/dist/{renderer-J67LMOD5.js → renderer-DVNMCYHZ.js} +3 -3
- package/dist/{renderer-NIE5IW24.js → renderer-RUSFL7WU.js} +2 -2
- package/gallery/fixtures/map-undirected-edges.dgmo +5 -5
- package/package.json +3 -1
package/dist/advanced.d.ts
CHANGED
|
@@ -979,6 +979,13 @@ declare function getSimpleChartLegendGroups(parsed: ParsedChart, colors: string[
|
|
|
979
979
|
*/
|
|
980
980
|
declare function getExtendedChartLegendGroups(parsed: ParsedExtendedChart, colors: string[]): LegendGroupData[];
|
|
981
981
|
|
|
982
|
+
/** How the axis draws its tick labels, so they can be measured (#1426). */
|
|
983
|
+
interface TickLabelFit {
|
|
984
|
+
/** Font size the labels are drawn at. */
|
|
985
|
+
fontSize: number;
|
|
986
|
+
/** True when labels stack down a vertical axis rather than along a row. */
|
|
987
|
+
vertical?: boolean;
|
|
988
|
+
}
|
|
982
989
|
/**
|
|
983
990
|
* Generates adaptive tick marks along a time axis.
|
|
984
991
|
* Picks the right granularity (years, months, weeks, days, hours, minutes)
|
|
@@ -988,7 +995,7 @@ declare function getExtendedChartLegendGroups(parsed: ParsedExtendedChart, color
|
|
|
988
995
|
* - boundaryStart/boundaryEnd: numeric date values
|
|
989
996
|
* - boundaryStartLabel/boundaryEndLabel: formatted labels for those dates
|
|
990
997
|
*/
|
|
991
|
-
declare function computeTimeTicks(domainMin: number, domainMax: number, scale: d3Scale.ScaleLinear<number, number>, boundaryStart?: number, boundaryEnd?: number, boundaryStartLabel?: string, boundaryEndLabel?: string): {
|
|
998
|
+
declare function computeTimeTicks(domainMin: number, domainMax: number, scale: d3Scale.ScaleLinear<number, number>, boundaryStart?: number, boundaryEnd?: number, boundaryStartLabel?: string, boundaryEndLabel?: string, labelFit?: TickLabelFit): {
|
|
992
999
|
pos: number;
|
|
993
1000
|
label: string;
|
|
994
1001
|
}[];
|
package/dist/advanced.js
CHANGED
|
@@ -146,7 +146,7 @@ import {
|
|
|
146
146
|
import {
|
|
147
147
|
buildTagLaneRowList,
|
|
148
148
|
renderGantt
|
|
149
|
-
} from "./chunk-
|
|
149
|
+
} from "./chunk-4QLGGQNO.js";
|
|
150
150
|
import {
|
|
151
151
|
renderFamily,
|
|
152
152
|
renderFamilyForExport
|
|
@@ -326,7 +326,7 @@ import {
|
|
|
326
326
|
focusEventLine,
|
|
327
327
|
renderEventLine,
|
|
328
328
|
renderEventLineForExport
|
|
329
|
-
} from "./chunk-
|
|
329
|
+
} from "./chunk-QQPNCXAO.js";
|
|
330
330
|
import "./chunk-NPWVOFB3.js";
|
|
331
331
|
import {
|
|
332
332
|
parseInlineMarkdown,
|
|
@@ -350,7 +350,7 @@ import {
|
|
|
350
350
|
renderSlopeChart,
|
|
351
351
|
renderVenn,
|
|
352
352
|
renderWordCloud
|
|
353
|
-
} from "./chunk-
|
|
353
|
+
} from "./chunk-Y2V5AEVG.js";
|
|
354
354
|
import {
|
|
355
355
|
layoutBracket
|
|
356
356
|
} from "./chunk-ZI6WC24V.js";
|
|
@@ -430,10 +430,10 @@ import "./chunk-2CW5ZTNH.js";
|
|
|
430
430
|
import {
|
|
431
431
|
formatDateLabel,
|
|
432
432
|
renderTimeline
|
|
433
|
-
} from "./chunk-
|
|
433
|
+
} from "./chunk-O5WUZGPV.js";
|
|
434
434
|
import {
|
|
435
435
|
computeTimeTicks
|
|
436
|
-
} from "./chunk-
|
|
436
|
+
} from "./chunk-VSOZZYLK.js";
|
|
437
437
|
import {
|
|
438
438
|
ScaleContext
|
|
439
439
|
} from "./chunk-24YPR5EH.js";
|
package/dist/block.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-D3K4U3ZM.js";
|
|
5
5
|
import {
|
|
6
6
|
render
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-Y2V5AEVG.js";
|
|
8
8
|
import "./chunk-ZI6WC24V.js";
|
|
9
9
|
import {
|
|
10
10
|
docsLink,
|
|
@@ -34,8 +34,8 @@ import "./chunk-2CW5ZTNH.js";
|
|
|
34
34
|
import {
|
|
35
35
|
escapeAttr,
|
|
36
36
|
escapeHtml
|
|
37
|
-
} from "./chunk-
|
|
38
|
-
import "./chunk-
|
|
37
|
+
} from "./chunk-O5WUZGPV.js";
|
|
38
|
+
import "./chunk-VSOZZYLK.js";
|
|
39
39
|
import "./chunk-24YPR5EH.js";
|
|
40
40
|
import "./chunk-NMS5XSLX.js";
|
|
41
41
|
import "./chunk-XCKNFFKM.js";
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MONTH_ABBR,
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
capLabelColumn,
|
|
4
|
+
computeTimeTicks,
|
|
5
|
+
showFullOnHover
|
|
6
|
+
} from "./chunk-VSOZZYLK.js";
|
|
5
7
|
import {
|
|
6
8
|
ScaleContext
|
|
7
9
|
} from "./chunk-24YPR5EH.js";
|
|
@@ -130,7 +132,7 @@ function renderLabelBand(svg, y, leftMargin, color, palette, isDark, cssPrefix,
|
|
|
130
132
|
function appendTaskIcon(textEl, label, isMilestone, iconColor, textColor) {
|
|
131
133
|
const icon = isMilestone ? "\u25C6" : "\u25CF";
|
|
132
134
|
textEl.append("tspan").attr("fill", iconColor).text(icon);
|
|
133
|
-
textEl.append("tspan").attr("fill", textColor).text(" " + label);
|
|
135
|
+
return textEl.append("tspan").attr("fill", textColor).text(" " + label);
|
|
134
136
|
}
|
|
135
137
|
function renderGantt(container, resolved, palette, isDark, options, exportDims) {
|
|
136
138
|
keepSwimlaneToggleFocus(
|
|
@@ -182,7 +184,14 @@ function drawGantt(container, resolved, palette, isDark, options, exportDims) {
|
|
|
182
184
|
...labelWidths,
|
|
183
185
|
measureText("0000000000", LABEL_FONT)
|
|
184
186
|
);
|
|
185
|
-
const
|
|
187
|
+
const containerWidth = exportDims?.width ?? (container.clientWidth || 800);
|
|
188
|
+
const labelColumn = capLabelColumn(
|
|
189
|
+
Math.max(MIN_LEFT_MARGIN, maxLabelWidth + 30),
|
|
190
|
+
containerWidth,
|
|
191
|
+
MIN_LEFT_MARGIN
|
|
192
|
+
);
|
|
193
|
+
const leftMargin = labelColumn.width;
|
|
194
|
+
const fitLabel = labelColumn.fit;
|
|
186
195
|
const totalRows = rows.length;
|
|
187
196
|
const hasCriticalPath = resolved.options.criticalPath && resolved.tasks.some((t) => t.isCriticalPath);
|
|
188
197
|
const hasDependencies = resolved.options.dependencies && resolved.tasks.some((t) => t.task.dependencies.length > 0);
|
|
@@ -196,7 +205,6 @@ function drawGantt(container, resolved, palette, isDark, options, exportDims) {
|
|
|
196
205
|
const title = resolved.options.title;
|
|
197
206
|
const showTitle = !!title && !resolved.options.noTitle;
|
|
198
207
|
const titleHeight = showTitle ? 50 : 20;
|
|
199
|
-
const containerWidth = exportDims?.width ?? (container.clientWidth || 800);
|
|
200
208
|
const hasTagLegend = !resolved.options.noLegend && (resolved.tagGroups.length > 0 || hasCriticalPath || hasDependencies);
|
|
201
209
|
const tagLegendReserve = hasTagLegend ? getMaxLegendReservedHeight(
|
|
202
210
|
{
|
|
@@ -492,8 +500,14 @@ function drawGantt(container, resolved, palette, isDark, options, exportDims) {
|
|
|
492
500
|
restoreHighlight();
|
|
493
501
|
hideGanttDateIndicators(g);
|
|
494
502
|
});
|
|
495
|
-
|
|
496
|
-
|
|
503
|
+
const laneFullText = toggleIcon + " " + row.laneName + (row.aggregateProgress !== null ? ` ${Math.round(row.aggregateProgress)}%` : "");
|
|
504
|
+
const laneText = labelG.append("text").attr("x", labelX).attr("y", sMarginTop + yOffset + sBarH / 2).attr("dy", "0.35em").attr("text-anchor", "start").attr("font-size", sFont11).attr("font-weight", "bold").attr("fill", laneColor);
|
|
505
|
+
showFullOnHover(
|
|
506
|
+
labelG,
|
|
507
|
+
laneText,
|
|
508
|
+
laneText,
|
|
509
|
+
laneFullText,
|
|
510
|
+
fitLabel(laneFullText, labelX, sFont11, true)
|
|
497
511
|
);
|
|
498
512
|
if (laneBarWidth > 0) {
|
|
499
513
|
const barFill = shapeFill(palette, laneColor, isDark, {
|
|
@@ -567,8 +581,14 @@ function drawGantt(container, resolved, palette, isDark, options, exportDims) {
|
|
|
567
581
|
});
|
|
568
582
|
const groupIndent = group.depth <= 2 ? group.depth * 14 : 2 * 14 + (group.depth - 2) * 8;
|
|
569
583
|
const labelX = 10 + groupIndent;
|
|
570
|
-
|
|
571
|
-
|
|
584
|
+
const groupFullText = toggleIcon + " " + group.name + (group.progress !== null ? ` ${Math.round(group.progress)}%` : "");
|
|
585
|
+
const groupText = labelG.append("text").attr("x", labelX).attr("y", sMarginTop + yOffset + sBarH / 2).attr("dy", "0.35em").attr("text-anchor", "start").attr("font-size", sFont11).attr("font-weight", "bold").attr("fill", palette.text);
|
|
586
|
+
showFullOnHover(
|
|
587
|
+
labelG,
|
|
588
|
+
groupText,
|
|
589
|
+
groupText,
|
|
590
|
+
groupFullText,
|
|
591
|
+
fitLabel(groupFullText, labelX, sFont11, true)
|
|
572
592
|
);
|
|
573
593
|
const gStart = dateToFractionalYear(group.startDate);
|
|
574
594
|
const gEnd = dateToFractionalYear(group.endDate);
|
|
@@ -696,13 +716,25 @@ function drawGantt(container, resolved, palette, isDark, options, exportDims) {
|
|
|
696
716
|
}).on("mouseleave", () => {
|
|
697
717
|
resetHighlight(g, svg);
|
|
698
718
|
});
|
|
699
|
-
appendTaskIcon(
|
|
719
|
+
const taskLabelText = appendTaskIcon(
|
|
700
720
|
taskLabel,
|
|
701
721
|
task.label,
|
|
702
722
|
rt.isMilestone,
|
|
703
723
|
barColor,
|
|
704
724
|
palette.text
|
|
705
725
|
);
|
|
726
|
+
const taskIconW = measureText(
|
|
727
|
+
(rt.isMilestone ? "\u25C6" : "\u25CF") + " ",
|
|
728
|
+
sFont11
|
|
729
|
+
);
|
|
730
|
+
showFullOnHover(
|
|
731
|
+
taskLabel,
|
|
732
|
+
taskLabel,
|
|
733
|
+
taskLabelText,
|
|
734
|
+
task.label,
|
|
735
|
+
fitLabel(task.label, taskLabelX + taskIconW, sFont11),
|
|
736
|
+
" "
|
|
737
|
+
);
|
|
706
738
|
for (const [key, value] of Object.entries(rt.effectiveMetadata)) {
|
|
707
739
|
taskLabel.attr(`data-tag-${tagAttrKey(key)}`, value.toLowerCase());
|
|
708
740
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MONTH_ABBR,
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
capLabelColumn,
|
|
4
|
+
computeTimeTicks,
|
|
5
|
+
showFullOnHover
|
|
6
|
+
} from "./chunk-VSOZZYLK.js";
|
|
5
7
|
import {
|
|
6
8
|
ScaleContext
|
|
7
9
|
} from "./chunk-24YPR5EH.js";
|
|
@@ -48,6 +50,9 @@ import {
|
|
|
48
50
|
measureLegendText,
|
|
49
51
|
truncateLegendText
|
|
50
52
|
} from "./chunk-UOCWYLYT.js";
|
|
53
|
+
import {
|
|
54
|
+
measureText
|
|
55
|
+
} from "./chunk-KAO7JL4I.js";
|
|
51
56
|
import {
|
|
52
57
|
getEraColors,
|
|
53
58
|
getSeriesColors,
|
|
@@ -252,7 +257,8 @@ function renderTimeScale(g, scale, isVertical, innerWidth, innerHeight, textColo
|
|
|
252
257
|
boundaryStart,
|
|
253
258
|
boundaryEnd,
|
|
254
259
|
boundaryStartLabel,
|
|
255
|
-
boundaryEndLabel
|
|
260
|
+
boundaryEndLabel,
|
|
261
|
+
{ fontSize: 10, vertical: isVertical }
|
|
256
262
|
);
|
|
257
263
|
if (ticks.length < 2) return;
|
|
258
264
|
const tickLen = 6;
|
|
@@ -1054,10 +1060,12 @@ function renderTimelineHorizontalGrouped(container, parsed, palette, isDark, set
|
|
|
1054
1060
|
...lanes.flatMap((l) => l.events.map((ev) => ev.label.length + 2))
|
|
1055
1061
|
);
|
|
1056
1062
|
const maxLeftLabelLen = Math.max(maxGroupNameLen, maxEventLabelLen);
|
|
1057
|
-
const
|
|
1058
|
-
ctx.aesthetic(140),
|
|
1059
|
-
|
|
1063
|
+
const labelColumn = capLabelColumn(
|
|
1064
|
+
Math.max(ctx.aesthetic(140), maxLeftLabelLen * sCharW + ctx.aesthetic(30)),
|
|
1065
|
+
width,
|
|
1066
|
+
ctx.aesthetic(140)
|
|
1060
1067
|
);
|
|
1068
|
+
const dynamicLeftMargin = labelColumn.width;
|
|
1061
1069
|
const baseTopMargin = title ? 50 : ctx.aesthetic(20);
|
|
1062
1070
|
const margin = {
|
|
1063
1071
|
top: baseTopMargin + topScaleH + eraReserve + markerReserve + tagLegendReserve,
|
|
@@ -1150,7 +1158,20 @@ function renderTimelineHorizontalGrouped(container, parsed, palette, isDark, set
|
|
|
1150
1158
|
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");
|
|
1151
1159
|
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");
|
|
1152
1160
|
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));
|
|
1153
|
-
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")
|
|
1161
|
+
const headerText = 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");
|
|
1162
|
+
const headerFull = `${toggleIcon} ${lane.name}`;
|
|
1163
|
+
showFullOnHover(
|
|
1164
|
+
headerG,
|
|
1165
|
+
headerText,
|
|
1166
|
+
headerText,
|
|
1167
|
+
headerFull,
|
|
1168
|
+
labelColumn.fit(
|
|
1169
|
+
headerFull,
|
|
1170
|
+
bandX + 5 + margin.left,
|
|
1171
|
+
sLaneHeaderFont,
|
|
1172
|
+
true
|
|
1173
|
+
)
|
|
1174
|
+
);
|
|
1154
1175
|
if (lane.events.length > 0) {
|
|
1155
1176
|
const evDates = lane.events.map((ev) => parseTimelineDate(ev.date));
|
|
1156
1177
|
const evEndDates = lane.events.filter((ev) => ev.endDate).map((ev) => parseTimelineDate(ev.endDate));
|
|
@@ -1206,7 +1227,19 @@ function renderTimelineHorizontalGrouped(container, parsed, palette, isDark, set
|
|
|
1206
1227
|
const icon = isPoint ? "\u25C6" : "\u25CF";
|
|
1207
1228
|
const labelEl = evG.append("text").attr("class", "tl-event-label").attr("x", -margin.left + ctx.aesthetic(20)).attr("y", y).attr("dy", "0.35em").attr("text-anchor", "start").attr("font-size", sEventFont).attr("fill", textColor);
|
|
1208
1229
|
labelEl.append("tspan").attr("fill", evColor).text(icon);
|
|
1209
|
-
labelEl.append("tspan").attr("fill", textColor)
|
|
1230
|
+
const labelTextEl = labelEl.append("tspan").attr("fill", textColor);
|
|
1231
|
+
showFullOnHover(
|
|
1232
|
+
evG,
|
|
1233
|
+
labelEl,
|
|
1234
|
+
labelTextEl,
|
|
1235
|
+
ev.label,
|
|
1236
|
+
labelColumn.fit(
|
|
1237
|
+
ev.label,
|
|
1238
|
+
ctx.aesthetic(20) + measureText(icon + " ", sEventFont),
|
|
1239
|
+
sEventFont
|
|
1240
|
+
),
|
|
1241
|
+
" "
|
|
1242
|
+
);
|
|
1210
1243
|
if (ev.endDate) {
|
|
1211
1244
|
const x2 = xScale(parseTimelineDate(ev.endDate));
|
|
1212
1245
|
const rectW = Math.max(x2 - x, 4);
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
+
import {
|
|
2
|
+
measureText,
|
|
3
|
+
truncateText
|
|
4
|
+
} from "./chunk-KAO7JL4I.js";
|
|
5
|
+
|
|
1
6
|
// src/utils/time-ticks.ts
|
|
7
|
+
var TICK_LABEL_GAP = 8;
|
|
2
8
|
var MONTH_ABBR = [
|
|
3
9
|
"Jan",
|
|
4
10
|
"Feb",
|
|
@@ -35,11 +41,12 @@ function dateToFractionalYear(d) {
|
|
|
35
41
|
function formatYearTick(y) {
|
|
36
42
|
return y < 0 ? `${-y} BCE` : String(y);
|
|
37
43
|
}
|
|
38
|
-
function computeTimeTicks(domainMin, domainMax, scale, boundaryStart, boundaryEnd, boundaryStartLabel, boundaryEndLabel) {
|
|
44
|
+
function computeTimeTicks(domainMin, domainMax, scale, boundaryStart, boundaryEnd, boundaryStartLabel, boundaryEndLabel, labelFit = { fontSize: 10 }) {
|
|
39
45
|
const minYear = Math.floor(domainMin);
|
|
40
46
|
const maxYear = Math.floor(domainMax);
|
|
41
47
|
const span = domainMax - domainMin;
|
|
42
48
|
let ticks = [];
|
|
49
|
+
let strides = [];
|
|
43
50
|
const firstYear = Math.ceil(domainMin);
|
|
44
51
|
const lastYear = Math.floor(domainMax);
|
|
45
52
|
if (lastYear >= firstYear + 1) {
|
|
@@ -52,9 +59,12 @@ function computeTimeTicks(domainMin, domainMax, scale, boundaryStart, boundaryEn
|
|
|
52
59
|
else if (yearSpan > 40) step = 10;
|
|
53
60
|
else if (yearSpan > 20) step = 5;
|
|
54
61
|
else if (yearSpan > 10) step = 2;
|
|
62
|
+
strides = [1, 2, 5, 10, 20, 50, 100, 200, 500, 1e3, 2e3, 5e3].filter(
|
|
63
|
+
(c) => c % step === 0
|
|
64
|
+
);
|
|
55
65
|
const alignedFirst = Math.ceil(firstYear / step) * step;
|
|
56
66
|
for (let y = alignedFirst; y <= lastYear; y += step) {
|
|
57
|
-
ticks.push({ pos: scale(y), label: formatYearTick(y) });
|
|
67
|
+
ticks.push({ pos: scale(y), label: formatYearTick(y), slot: y });
|
|
58
68
|
}
|
|
59
69
|
} else if (span > 0.25) {
|
|
60
70
|
const crossesYear = maxYear > minYear;
|
|
@@ -66,7 +76,9 @@ function computeTimeTicks(domainMin, domainMax, scale, boundaryStart, boundaryEn
|
|
|
66
76
|
const abbr = MONTH_ABBR[m - 1];
|
|
67
77
|
ticks.push({
|
|
68
78
|
pos: scale(val),
|
|
69
|
-
label: crossesYear ? `${abbr} '${String(y).slice(-2)}` : abbr
|
|
79
|
+
label: crossesYear ? `${abbr} '${String(y).slice(-2)}` : abbr,
|
|
80
|
+
// Month index, so a stride of 3 lands on Jan, Apr, Jul, Oct.
|
|
81
|
+
slot: y * 12 + (m - 1)
|
|
70
82
|
});
|
|
71
83
|
}
|
|
72
84
|
}
|
|
@@ -89,7 +101,11 @@ function computeTimeTicks(domainMin, domainMax, scale, boundaryStart, boundaryEn
|
|
|
89
101
|
const hh = String(startDate.getHours()).padStart(2, "0");
|
|
90
102
|
const mm = String(startDate.getMinutes()).padStart(2, "0");
|
|
91
103
|
const ss = String(startDate.getSeconds()).padStart(2, "0");
|
|
92
|
-
ticks.push({
|
|
104
|
+
ticks.push({
|
|
105
|
+
pos: scale(val),
|
|
106
|
+
label: `${hh}:${mm}:${ss}`,
|
|
107
|
+
slot: ticks.length
|
|
108
|
+
});
|
|
93
109
|
}
|
|
94
110
|
startDate.setSeconds(startDate.getSeconds() + stepSec);
|
|
95
111
|
}
|
|
@@ -111,7 +127,11 @@ function computeTimeTicks(domainMin, domainMax, scale, boundaryStart, boundaryEn
|
|
|
111
127
|
if (val >= domainMin) {
|
|
112
128
|
const hh = String(startDate.getHours()).padStart(2, "0");
|
|
113
129
|
const mm = String(startDate.getMinutes()).padStart(2, "0");
|
|
114
|
-
ticks.push({
|
|
130
|
+
ticks.push({
|
|
131
|
+
pos: scale(val),
|
|
132
|
+
label: `${hh}:${mm}`,
|
|
133
|
+
slot: ticks.length
|
|
134
|
+
});
|
|
115
135
|
}
|
|
116
136
|
startDate.setMinutes(startDate.getMinutes() + stepMin);
|
|
117
137
|
}
|
|
@@ -136,11 +156,19 @@ function computeTimeTicks(domainMin, domainMax, scale, boundaryStart, boundaryEn
|
|
|
136
156
|
const hh = String(startDate.getHours()).padStart(2, "0");
|
|
137
157
|
const mm = String(startDate.getMinutes()).padStart(2, "0");
|
|
138
158
|
if (singleDay) {
|
|
139
|
-
ticks.push({
|
|
159
|
+
ticks.push({
|
|
160
|
+
pos: scale(val),
|
|
161
|
+
label: `${hh}:${mm}`,
|
|
162
|
+
slot: ticks.length
|
|
163
|
+
});
|
|
140
164
|
} else {
|
|
141
165
|
const mon = MONTH_ABBR[startDate.getMonth()];
|
|
142
166
|
const d = startDate.getDate();
|
|
143
|
-
ticks.push({
|
|
167
|
+
ticks.push({
|
|
168
|
+
pos: scale(val),
|
|
169
|
+
label: `${mon} ${d} ${hh}:${mm}`,
|
|
170
|
+
slot: ticks.length
|
|
171
|
+
});
|
|
144
172
|
}
|
|
145
173
|
}
|
|
146
174
|
startDate.setHours(startDate.getHours() + stepHour);
|
|
@@ -154,32 +182,98 @@ function computeTimeTicks(domainMin, domainMax, scale, boundaryStart, boundaryEn
|
|
|
154
182
|
if (val >= domainMin) {
|
|
155
183
|
ticks.push({
|
|
156
184
|
pos: scale(val),
|
|
157
|
-
label: `${MONTH_ABBR[m - 1]} ${d}
|
|
185
|
+
label: `${MONTH_ABBR[m - 1]} ${d}`,
|
|
186
|
+
slot: ticks.length
|
|
158
187
|
});
|
|
159
188
|
}
|
|
160
189
|
}
|
|
161
190
|
}
|
|
162
191
|
}
|
|
163
192
|
}
|
|
193
|
+
if (strides.length === 0) strides = [1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48];
|
|
164
194
|
const collisionThreshold = 40;
|
|
195
|
+
let startBoundary = null;
|
|
196
|
+
let endBoundary = null;
|
|
165
197
|
if (boundaryStart !== void 0 && boundaryStartLabel) {
|
|
166
198
|
const boundaryPos = scale(boundaryStart);
|
|
167
199
|
ticks = ticks.filter(
|
|
168
200
|
(t) => Math.abs(t.pos - boundaryPos) >= collisionThreshold
|
|
169
201
|
);
|
|
170
|
-
|
|
202
|
+
startBoundary = { pos: boundaryPos, label: boundaryStartLabel };
|
|
171
203
|
}
|
|
172
204
|
if (boundaryEnd !== void 0 && boundaryEndLabel) {
|
|
173
205
|
const boundaryPos = scale(boundaryEnd);
|
|
174
206
|
ticks = ticks.filter(
|
|
175
207
|
(t) => Math.abs(t.pos - boundaryPos) >= collisionThreshold
|
|
176
208
|
);
|
|
177
|
-
|
|
209
|
+
endBoundary = { pos: boundaryPos, label: boundaryEndLabel };
|
|
178
210
|
}
|
|
179
|
-
return ticks;
|
|
211
|
+
return fitTickLabels(ticks, startBoundary, endBoundary, strides, labelFit);
|
|
212
|
+
}
|
|
213
|
+
function fitTickLabels(standard, startBoundary, endBoundary, strides, fit) {
|
|
214
|
+
const extent = (label) => fit.vertical ? fit.fontSize * 1.2 : measureText(label, fit.fontSize);
|
|
215
|
+
const span = (t) => {
|
|
216
|
+
const half = extent(t.label) / 2;
|
|
217
|
+
return { pos: t.pos, label: t.label, lo: t.pos - half, hi: t.pos + half };
|
|
218
|
+
};
|
|
219
|
+
const apart = (a, b) => a.hi + TICK_LABEL_GAP <= b.lo || b.hi + TICK_LABEL_GAP <= a.lo;
|
|
220
|
+
const fitsInOrder = (spans) => {
|
|
221
|
+
const sorted = [...spans].sort((a, b) => a.lo - b.lo);
|
|
222
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
223
|
+
if (!apart(sorted[i - 1], sorted[i])) return false;
|
|
224
|
+
}
|
|
225
|
+
return true;
|
|
226
|
+
};
|
|
227
|
+
const start = startBoundary ? span(startBoundary) : null;
|
|
228
|
+
let end = endBoundary ? span(endBoundary) : null;
|
|
229
|
+
if (start && end && !apart(start, end)) end = null;
|
|
230
|
+
const pinned = [start, end].filter((p) => p !== null);
|
|
231
|
+
const withPinned = (kept) => [
|
|
232
|
+
...start ? [start] : [],
|
|
233
|
+
...kept,
|
|
234
|
+
...end ? [end] : []
|
|
235
|
+
];
|
|
236
|
+
const strip = (s) => ({
|
|
237
|
+
pos: s.pos,
|
|
238
|
+
label: s.label
|
|
239
|
+
});
|
|
240
|
+
for (const stride of strides) {
|
|
241
|
+
const kept = standard.filter((t) => t.slot % stride === 0).map(span).filter((s) => pinned.every((p) => apart(p, s)));
|
|
242
|
+
if (kept.length === 0 && pinned.length === 0) continue;
|
|
243
|
+
if (fitsInOrder(kept)) {
|
|
244
|
+
return withPinned(kept).map(strip);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return withPinned([]).map(strip);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// src/utils/label-column.ts
|
|
251
|
+
var LABEL_COLUMN_MAX_SHARE = 1 / 3;
|
|
252
|
+
var LABEL_COLUMN_END_PAD = 12;
|
|
253
|
+
function capLabelColumn(natural, chartWidth, floor) {
|
|
254
|
+
const cap = Math.max(floor, Math.floor(chartWidth * LABEL_COLUMN_MAX_SHARE));
|
|
255
|
+
const width = Math.min(natural, cap);
|
|
256
|
+
const capped = natural > cap;
|
|
257
|
+
return {
|
|
258
|
+
width,
|
|
259
|
+
fit: (text, labelX, fontSize, bold = false) => capped ? truncateText(
|
|
260
|
+
text,
|
|
261
|
+
fontSize,
|
|
262
|
+
Math.max(0, width - labelX - LABEL_COLUMN_END_PAD),
|
|
263
|
+
{ bold }
|
|
264
|
+
) : text
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
function showFullOnHover(hoverEl, labelEl, drawEl, full, shown, prefix = "") {
|
|
268
|
+
drawEl.text(prefix + shown);
|
|
269
|
+
if (shown === full) return;
|
|
270
|
+
labelEl.attr("data-full-label", full);
|
|
271
|
+
hoverEl.on("mouseenter.reveal", () => drawEl.text(prefix + full)).on("mouseleave.reveal", () => drawEl.text(prefix + shown));
|
|
180
272
|
}
|
|
181
273
|
|
|
182
274
|
export {
|
|
183
275
|
MONTH_ABBR,
|
|
184
|
-
computeTimeTicks
|
|
276
|
+
computeTimeTicks,
|
|
277
|
+
capLabelColumn,
|
|
278
|
+
showFullOnHover
|
|
185
279
|
};
|
|
@@ -46,7 +46,7 @@ import {
|
|
|
46
46
|
} from "./chunk-H6BT45SN.js";
|
|
47
47
|
import {
|
|
48
48
|
renderTimeline
|
|
49
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-O5WUZGPV.js";
|
|
50
50
|
import {
|
|
51
51
|
ScaleContext
|
|
52
52
|
} from "./chunk-24YPR5EH.js";
|
|
@@ -2123,7 +2123,7 @@ function ctxTagOverride(ctx) {
|
|
|
2123
2123
|
async function exportEventLine(ctx) {
|
|
2124
2124
|
const { content, theme, palette } = ctx;
|
|
2125
2125
|
const { parseEventLine: parseEventLine2 } = await import("./parser-YG625J5H.js");
|
|
2126
|
-
const { renderEventLineForExport } = await import("./renderer-
|
|
2126
|
+
const { renderEventLineForExport } = await import("./renderer-DVNMCYHZ.js");
|
|
2127
2127
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2128
2128
|
const parsed = parseEventLine2(content, effectivePalette);
|
|
2129
2129
|
if (parsed.error || parsed.events.length === 0) return "";
|
|
@@ -2786,7 +2786,7 @@ async function exportGantt(ctx) {
|
|
|
2786
2786
|
const { content, theme, palette, viewState, exportMode } = ctx;
|
|
2787
2787
|
const { parseGantt: parseGantt2 } = await import("./parser-2NWH5JUS.js");
|
|
2788
2788
|
const { calculateSchedule } = await import("./calculator-BNH3GSJE.js");
|
|
2789
|
-
const { renderGantt } = await import("./renderer-
|
|
2789
|
+
const { renderGantt } = await import("./renderer-RUSFL7WU.js");
|
|
2790
2790
|
const effectivePalette = await resolveExportPalette(theme, palette);
|
|
2791
2791
|
const ganttParsed = parseGantt2(content, effectivePalette);
|
|
2792
2792
|
const resolved = calculateSchedule(ganttParsed);
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
} from "./chunk-Z6DXWULM.js";
|
|
15
15
|
import {
|
|
16
16
|
render
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-Y2V5AEVG.js";
|
|
18
18
|
import "./chunk-ZI6WC24V.js";
|
|
19
19
|
import {
|
|
20
20
|
renderErrorCard
|
|
@@ -44,8 +44,8 @@ import "./chunk-KMU65FYM.js";
|
|
|
44
44
|
import "./chunk-EPDBWATV.js";
|
|
45
45
|
import "./chunk-H6BT45SN.js";
|
|
46
46
|
import "./chunk-2CW5ZTNH.js";
|
|
47
|
-
import "./chunk-
|
|
48
|
-
import "./chunk-
|
|
47
|
+
import "./chunk-O5WUZGPV.js";
|
|
48
|
+
import "./chunk-VSOZZYLK.js";
|
|
49
49
|
import "./chunk-24YPR5EH.js";
|
|
50
50
|
import "./chunk-NMS5XSLX.js";
|
|
51
51
|
import {
|
|
@@ -3,13 +3,13 @@ import {
|
|
|
3
3
|
focusEventLine,
|
|
4
4
|
renderEventLine,
|
|
5
5
|
renderEventLineForExport
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-QQPNCXAO.js";
|
|
7
7
|
import "./chunk-NPWVOFB3.js";
|
|
8
8
|
import "./chunk-S7W75MIM.js";
|
|
9
9
|
import "./chunk-R2K5L4UA.js";
|
|
10
10
|
import "./chunk-Z6DXWULM.js";
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-O5WUZGPV.js";
|
|
12
|
+
import "./chunk-VSOZZYLK.js";
|
|
13
13
|
import "./chunk-24YPR5EH.js";
|
|
14
14
|
import "./chunk-NMS5XSLX.js";
|
|
15
15
|
import "./chunk-XCKNFFKM.js";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildTagLaneRowList,
|
|
3
3
|
renderGantt
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-4QLGGQNO.js";
|
|
5
|
+
import "./chunk-VSOZZYLK.js";
|
|
6
6
|
import "./chunk-24YPR5EH.js";
|
|
7
7
|
import "./chunk-NMS5XSLX.js";
|
|
8
8
|
import "./chunk-XCKNFFKM.js";
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
map Sister Ports of the Spanish Main
|
|
2
2
|
flow-width Shared cargo runs
|
|
3
3
|
|
|
4
|
-
poi Tortuga
|
|
5
|
-
poi Port Royal
|
|
6
|
-
poi Nassau
|
|
4
|
+
poi 20.05 -72.82 as Tortuga label: Tortuga
|
|
5
|
+
poi 17.94 -76.84 as royal label: Port Royal
|
|
6
|
+
poi 25.06 -77.35 as Nassau label: Nassau
|
|
7
7
|
poi Havana
|
|
8
8
|
|
|
9
|
-
Tortuga -ferry-
|
|
10
|
-
|
|
9
|
+
Tortuga -ferry- royal width: 18
|
|
10
|
+
royal ~cable~ Nassau
|
|
11
11
|
Nassau -- Havana
|
|
12
12
|
Havana -ships-> Tortuga width: 30
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@diagrammo/dgmo",
|
|
3
|
-
"version": "0.92.
|
|
3
|
+
"version": "0.92.1",
|
|
4
4
|
"description": "DGMO diagram markup language — parser, renderer, and color system",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Diagrammo LLC",
|
|
@@ -98,6 +98,8 @@
|
|
|
98
98
|
"bench:bl-options": "vitest run --config vitest.bench.config.ts tests/bl-options.ts",
|
|
99
99
|
"bench:bl-overlap": "vitest run --config vitest.bench.config.ts tests/bl-overlap-debug.ts",
|
|
100
100
|
"bl-gallery": "vitest run --config vitest.bench.config.ts tests/bl-gallery.ts",
|
|
101
|
+
"stress:render": "TZ=UTC vitest run --config vitest.bench.config.ts tests/stress-render.ts",
|
|
102
|
+
"stress:sheet": "node scripts/stress-sheet.mjs",
|
|
101
103
|
"test:watch": "TZ=UTC vitest",
|
|
102
104
|
"test:auto": "pnpm build && TZ=UTC vitest run tests/auto.test.ts tests/safe-href.test.ts",
|
|
103
105
|
"sri": "node scripts/sri.mjs",
|