@diagrammo/dgmo 0.23.0 → 0.25.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/LICENSE +1 -1
- package/dist/advanced.cjs +166 -91
- package/dist/advanced.d.cts +35 -19
- package/dist/advanced.d.ts +35 -19
- package/dist/advanced.js +166 -91
- package/dist/auto.cjs +167 -92
- package/dist/auto.js +110 -110
- package/dist/auto.mjs +167 -92
- package/dist/cli.cjs +150 -150
- package/dist/index.cjs +298 -91
- package/dist/index.d.cts +37 -1
- package/dist/index.d.ts +37 -1
- package/dist/index.js +296 -91
- package/dist/internal.cjs +166 -91
- package/dist/internal.d.cts +35 -19
- package/dist/internal.d.ts +35 -19
- package/dist/internal.js +166 -91
- package/docs/language-reference.md +3 -2
- package/package.json +1 -1
- package/src/boxes-and-lines/renderer.ts +98 -51
- package/src/d3.ts +22 -10
- package/src/diagnostics.ts +0 -19
- package/src/index.ts +8 -0
- package/src/map/dimensions.ts +21 -5
- package/src/map/geo.ts +0 -5
- package/src/map/layout.ts +57 -46
- package/src/map/legend-band.ts +99 -0
- package/src/map/renderer.ts +10 -28
- package/src/map/resolver.ts +43 -1
- package/src/map/types.ts +20 -0
- package/src/sequence/parser.ts +0 -4
- package/src/utils/brand.ts +0 -17
- package/src/utils/legend-d3.ts +18 -8
- package/src/utils/parsing.ts +0 -16
- package/src/utils/reserved-key-registry.ts +0 -12
- package/src/utils/svg-embed.ts +193 -0
package/dist/internal.cjs
CHANGED
|
@@ -840,7 +840,7 @@ function withTagAliases(base, aliases) {
|
|
|
840
840
|
function isReservedKey(registry, key) {
|
|
841
841
|
return registry.keys.has(key) || registry.tagAliases.has(key);
|
|
842
842
|
}
|
|
843
|
-
var SEQUENCE_REGISTRY, INFRA_REGISTRY, MAP_REGISTRY, ORG_REGISTRY, C4_REGISTRY, ER_REGISTRY,
|
|
843
|
+
var SEQUENCE_REGISTRY, INFRA_REGISTRY, MAP_REGISTRY, ORG_REGISTRY, C4_REGISTRY, ER_REGISTRY, KANBAN_REGISTRY, SITEMAP_REGISTRY, GANTT_REGISTRY, PERT_REGISTRY, BOXES_AND_LINES_REGISTRY, TIMELINE_REGISTRY, MINDMAP_REGISTRY, TECH_RADAR_REGISTRY, CYCLE_REGISTRY, JOURNEY_MAP_REGISTRY, PYRAMID_REGISTRY, RING_REGISTRY, RACI_REGISTRY;
|
|
844
844
|
var init_reserved_key_registry = __esm({
|
|
845
845
|
"src/utils/reserved-key-registry.ts"() {
|
|
846
846
|
"use strict";
|
|
@@ -884,10 +884,6 @@ var init_reserved_key_registry = __esm({
|
|
|
884
884
|
"description",
|
|
885
885
|
"domain"
|
|
886
886
|
]);
|
|
887
|
-
CLASS_REGISTRY = staticRegistry([
|
|
888
|
-
"color",
|
|
889
|
-
"description"
|
|
890
|
-
]);
|
|
891
887
|
KANBAN_REGISTRY = staticRegistry([
|
|
892
888
|
"color",
|
|
893
889
|
"description",
|
|
@@ -963,7 +959,6 @@ var init_reserved_key_registry = __esm({
|
|
|
963
959
|
"color",
|
|
964
960
|
"description"
|
|
965
961
|
]);
|
|
966
|
-
WIREFRAME_REGISTRY = staticRegistry([]);
|
|
967
962
|
}
|
|
968
963
|
});
|
|
969
964
|
|
|
@@ -4236,6 +4231,9 @@ var init_legend_layout = __esm({
|
|
|
4236
4231
|
});
|
|
4237
4232
|
|
|
4238
4233
|
// src/utils/legend-d3.ts
|
|
4234
|
+
function centerText(sel) {
|
|
4235
|
+
return sel.attr("dy", LEGEND_TEXT_DY);
|
|
4236
|
+
}
|
|
4239
4237
|
function renderLegendD3(container, config, state, palette, isDark, callbacks, containerWidth) {
|
|
4240
4238
|
const width = containerWidth ?? parseFloat(container.attr("width") || "800");
|
|
4241
4239
|
let currentState = { ...state };
|
|
@@ -4318,21 +4316,21 @@ function renderCapsule(parent, capsule, palette, groupBg, pillBorder, _isDark, c
|
|
|
4318
4316
|
const pill = capsule.pill;
|
|
4319
4317
|
g.append("rect").attr("x", pill.x).attr("y", pill.y).attr("width", pill.width).attr("height", pill.height).attr("rx", pill.height / 2).attr("fill", palette.bg);
|
|
4320
4318
|
g.append("rect").attr("x", pill.x).attr("y", pill.y).attr("width", pill.width).attr("height", pill.height).attr("rx", pill.height / 2).attr("fill", "none").attr("stroke", pillBorder).attr("stroke-width", 0.75);
|
|
4321
|
-
g.append("text").attr("x", pill.x + pill.width / 2).attr("y", LEGEND_HEIGHT / 2).attr("text-anchor", "middle").
|
|
4319
|
+
g.append("text").attr("x", pill.x + pill.width / 2).attr("y", LEGEND_HEIGHT / 2).attr("text-anchor", "middle").call(centerText).attr("font-size", LEGEND_PILL_FONT_SIZE).attr("font-weight", 500).attr("fill", palette.text).attr("pointer-events", "none").attr("font-family", FONT_FAMILY).text(capsule.groupName);
|
|
4322
4320
|
if (capsule.gradient) {
|
|
4323
4321
|
const gr = capsule.gradient;
|
|
4324
4322
|
const gradId = `dgmo-legend-ramp-${capsule.groupName.toLowerCase().replace(/[^a-z0-9]+/g, "-")}`;
|
|
4325
4323
|
const def = g.append("defs").append("linearGradient").attr("id", gradId);
|
|
4326
4324
|
def.append("stop").attr("offset", "0%").attr("stop-color", mix(gr.hue, gr.base, 15));
|
|
4327
4325
|
def.append("stop").attr("offset", "100%").attr("stop-color", gr.hue);
|
|
4328
|
-
g.append("text").attr("x", gr.minX).attr("y", gr.textY).
|
|
4326
|
+
g.append("text").attr("x", gr.minX).attr("y", gr.textY).call(centerText).attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("fill", palette.textMuted).attr("pointer-events", "none").attr("font-family", FONT_FAMILY).text(gr.minText);
|
|
4329
4327
|
g.append("rect").attr("class", "dgmo-legend-gradient-ramp").attr("data-ramp-min", gr.min).attr("data-ramp-max", gr.max).attr("x", gr.rampX).attr("y", gr.rampY).attr("width", gr.rampW).attr("height", gr.rampH).attr("rx", 2).attr("fill", `url(#${gradId})`);
|
|
4330
|
-
g.append("text").attr("x", gr.maxX).attr("y", gr.textY).
|
|
4328
|
+
g.append("text").attr("x", gr.maxX).attr("y", gr.textY).call(centerText).attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("fill", palette.textMuted).attr("pointer-events", "none").attr("font-family", FONT_FAMILY).text(gr.maxText);
|
|
4331
4329
|
}
|
|
4332
4330
|
for (const entry of capsule.entries) {
|
|
4333
4331
|
const entryG = g.append("g").attr("data-legend-entry", entry.value.toLowerCase()).attr("data-series-name", entry.value).style("cursor", "pointer");
|
|
4334
4332
|
entryG.append("circle").attr("cx", entry.dotCx).attr("cy", entry.dotCy).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
4335
|
-
entryG.append("text").attr("x", entry.textX).attr("y", entry.textY).
|
|
4333
|
+
entryG.append("text").attr("x", entry.textX).attr("y", entry.textY).call(centerText).attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("fill", palette.textMuted).attr("font-family", FONT_FAMILY).text(entry.displayValue ?? entry.value);
|
|
4336
4334
|
if (callbacks?.onEntryHover) {
|
|
4337
4335
|
const groupName = capsule.groupName;
|
|
4338
4336
|
const entryValue = entry.value;
|
|
@@ -4352,7 +4350,7 @@ function renderCapsule(parent, capsule, palette, groupBg, pillBorder, _isDark, c
|
|
|
4352
4350
|
function renderPill(parent, pill, palette, groupBg, callbacks) {
|
|
4353
4351
|
const g = parent.append("g").attr("transform", `translate(${pill.x},${pill.y})`).attr("data-legend-group", pill.groupName.toLowerCase()).style("cursor", "pointer");
|
|
4354
4352
|
g.append("rect").attr("width", pill.width).attr("height", pill.height).attr("rx", pill.height / 2).attr("fill", groupBg);
|
|
4355
|
-
g.append("text").attr("x", pill.width / 2).attr("y", pill.height / 2).attr("text-anchor", "middle").
|
|
4353
|
+
g.append("text").attr("x", pill.width / 2).attr("y", pill.height / 2).attr("text-anchor", "middle").call(centerText).attr("font-size", LEGEND_PILL_FONT_SIZE).attr("font-weight", 500).attr("fill", palette.textMuted).attr("pointer-events", "none").attr("font-family", FONT_FAMILY).text(pill.groupName);
|
|
4356
4354
|
if (callbacks?.onGroupToggle) {
|
|
4357
4355
|
const cb = callbacks.onGroupToggle;
|
|
4358
4356
|
const name = pill.groupName;
|
|
@@ -4375,7 +4373,7 @@ function renderControl(parent, ctrl, palette, _groupBg, pillBorder, _isDark, con
|
|
|
4375
4373
|
textX = 8 + 14 + LEGEND_ENTRY_DOT_GAP + measureLegendText(ctrl.label, LEGEND_PILL_FONT_SIZE) / 2;
|
|
4376
4374
|
}
|
|
4377
4375
|
if (ctrl.label) {
|
|
4378
|
-
g.append("text").attr("x", textX).attr("y", ctrl.height / 2).attr("text-anchor", "middle").
|
|
4376
|
+
g.append("text").attr("x", textX).attr("y", ctrl.height / 2).attr("text-anchor", "middle").call(centerText).attr("font-size", LEGEND_PILL_FONT_SIZE).attr("font-weight", 500).attr("fill", palette.textMuted).attr("pointer-events", "none").attr("font-family", FONT_FAMILY).text(ctrl.label);
|
|
4379
4377
|
}
|
|
4380
4378
|
if (ctrl.children) {
|
|
4381
4379
|
let cx = ctrl.width + 4;
|
|
@@ -4385,7 +4383,7 @@ function renderControl(parent, ctrl, palette, _groupBg, pillBorder, _isDark, con
|
|
|
4385
4383
|
"fill",
|
|
4386
4384
|
child.isActive ? palette.primary ?? palette.text : "none"
|
|
4387
4385
|
).attr("stroke", pillBorder).attr("stroke-width", 0.75);
|
|
4388
|
-
childG.append("text").attr("x", child.width / 2).attr("y", ctrl.height / 2).attr("text-anchor", "middle").
|
|
4386
|
+
childG.append("text").attr("x", child.width / 2).attr("y", ctrl.height / 2).attr("text-anchor", "middle").call(centerText).attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("fill", child.isActive ? palette.bg : palette.textMuted).attr("font-family", FONT_FAMILY).text(child.label);
|
|
4389
4387
|
const configCtrl2 = configControls?.find((c) => c.id === ctrl.id);
|
|
4390
4388
|
const configChild = configCtrl2?.children?.find((c) => c.id === child.id);
|
|
4391
4389
|
if (configChild?.onClick) {
|
|
@@ -4439,7 +4437,7 @@ function renderControlsGroup(parent, layout, palette, groupBg, pillBorder, callb
|
|
|
4439
4437
|
} else {
|
|
4440
4438
|
entryG.append("circle").attr("cx", tl.dotCx).attr("cy", tl.dotCy).attr("r", LEGEND_TOGGLE_DOT_R).attr("fill", "none").attr("stroke", palette.textMuted).attr("stroke-width", 1);
|
|
4441
4439
|
}
|
|
4442
|
-
entryG.append("text").attr("x", tl.textX).attr("y", tl.textY).
|
|
4440
|
+
entryG.append("text").attr("x", tl.textX).attr("y", tl.textY).call(centerText).attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("fill", palette.textMuted).attr("opacity", tl.active ? 1 : LEGEND_TOGGLE_OFF_OPACITY).attr("font-family", FONT_FAMILY).text(tl.label);
|
|
4443
4441
|
if (callbacks?.onControlsToggle && toggle) {
|
|
4444
4442
|
const cb = callbacks.onControlsToggle;
|
|
4445
4443
|
const id = tl.id;
|
|
@@ -4452,6 +4450,7 @@ function renderControlsGroup(parent, layout, palette, groupBg, pillBorder, callb
|
|
|
4452
4450
|
}
|
|
4453
4451
|
}
|
|
4454
4452
|
}
|
|
4453
|
+
var LEGEND_TEXT_DY;
|
|
4455
4454
|
var init_legend_d3 = __esm({
|
|
4456
4455
|
"src/utils/legend-d3.ts"() {
|
|
4457
4456
|
"use strict";
|
|
@@ -4459,6 +4458,7 @@ var init_legend_d3 = __esm({
|
|
|
4459
4458
|
init_legend_layout();
|
|
4460
4459
|
init_color_utils();
|
|
4461
4460
|
init_fonts();
|
|
4461
|
+
LEGEND_TEXT_DY = "0.32em";
|
|
4462
4462
|
}
|
|
4463
4463
|
});
|
|
4464
4464
|
|
|
@@ -4644,7 +4644,6 @@ var init_name_normalize = __esm({
|
|
|
4644
4644
|
var parser_exports = {};
|
|
4645
4645
|
__export(parser_exports, {
|
|
4646
4646
|
isSequenceBlock: () => isSequenceBlock,
|
|
4647
|
-
isSequenceMessage: () => isSequenceMessage,
|
|
4648
4647
|
isSequenceNote: () => isSequenceNote,
|
|
4649
4648
|
isSequenceSection: () => isSequenceSection,
|
|
4650
4649
|
looksLikeSequence: () => looksLikeSequence,
|
|
@@ -4660,9 +4659,6 @@ function isHardRemovedToken(remainder) {
|
|
|
4660
4659
|
}
|
|
4661
4660
|
return { removed: false };
|
|
4662
4661
|
}
|
|
4663
|
-
function isSequenceMessage(el) {
|
|
4664
|
-
return el.kind === "message";
|
|
4665
|
-
}
|
|
4666
4662
|
function isSequenceBlock(el) {
|
|
4667
4663
|
return el.kind === "block";
|
|
4668
4664
|
}
|
|
@@ -26631,7 +26627,7 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26631
26627
|
const VALUE_NAME = hasRamp ? parsed.boxMetric?.trim() || "Value" : null;
|
|
26632
26628
|
const matchColorGroup = (v) => {
|
|
26633
26629
|
const lv = v.trim().toLowerCase();
|
|
26634
|
-
if (lv === "none") return null;
|
|
26630
|
+
if (lv === "" || lv === "none") return null;
|
|
26635
26631
|
const tg = parsed.tagGroups.find((g) => g.name.toLowerCase() === lv);
|
|
26636
26632
|
if (tg) return tg.name;
|
|
26637
26633
|
if (lv === VALUE_NAME?.toLowerCase()) return VALUE_NAME;
|
|
@@ -26972,6 +26968,22 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26972
26968
|
const tooltipText = fullText.length > 200 ? fullText.slice(0, 199) + "\u2026" : fullText;
|
|
26973
26969
|
nodeG.append("title").text(tooltipText);
|
|
26974
26970
|
}
|
|
26971
|
+
} else if (parsed.showValues && node.value !== void 0) {
|
|
26972
|
+
const valueLabel = parsed.boxMetric ? `${parsed.boxMetric}: ${node.value}` : String(node.value);
|
|
26973
|
+
const headerH = ln.height / 2;
|
|
26974
|
+
const sepY = -ln.height / 2 + headerH;
|
|
26975
|
+
const fitted = fitLabelToHeader(node.label, ln.width, 2);
|
|
26976
|
+
const labelLineH = fitted.fontSize * 1.3;
|
|
26977
|
+
const labelTotalH = fitted.lines.length * labelLineH;
|
|
26978
|
+
const headerCenterY = -ln.height / 2 + headerH / 2;
|
|
26979
|
+
for (let li = 0; li < fitted.lines.length; li++) {
|
|
26980
|
+
nodeG.append("text").attr("x", 0).attr(
|
|
26981
|
+
"y",
|
|
26982
|
+
headerCenterY - labelTotalH / 2 + labelLineH / 2 + li * labelLineH
|
|
26983
|
+
).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-size", fitted.fontSize).attr("font-weight", "600").attr("fill", colors.text).text(fitted.lines[li]);
|
|
26984
|
+
}
|
|
26985
|
+
nodeG.append("line").attr("x1", -ln.width / 2).attr("y1", sepY).attr("x2", ln.width / 2).attr("y2", sepY).attr("stroke", colors.stroke).attr("stroke-opacity", 0.3).attr("stroke-width", 1);
|
|
26986
|
+
nodeG.append("text").attr("class", "bl-node-value").attr("x", 0).attr("y", (sepY + ln.height / 2) / 2).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-size", VALUE_FONT_SIZE).attr("fill", colors.text).attr("opacity", 0.85).text(valueLabel);
|
|
26975
26987
|
} else {
|
|
26976
26988
|
const maxLabelLines = Math.max(
|
|
26977
26989
|
2,
|
|
@@ -26984,21 +26996,16 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26984
26996
|
nodeG.append("text").attr("x", 0).attr("y", -totalH / 2 + lineH / 2 + li * lineH).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-size", fitted.fontSize).attr("font-weight", "600").attr("fill", colors.text).text(fitted.lines[li]);
|
|
26985
26997
|
}
|
|
26986
26998
|
}
|
|
26987
|
-
if (parsed.showValues && node.value !== void 0) {
|
|
26999
|
+
if (parsed.showValues && node.value !== void 0 && desc && desc.length > 0 && !hideDescriptions) {
|
|
26988
27000
|
const valueText = String(node.value);
|
|
26989
|
-
const
|
|
26990
|
-
|
|
26991
|
-
|
|
26992
|
-
|
|
26993
|
-
|
|
26994
|
-
|
|
26995
|
-
|
|
26996
|
-
|
|
26997
|
-
nodeG.append("rect").attr("x", bx).attr("y", by).attr("width", bw).attr("height", bh).attr("rx", 3).attr("fill", palette.bg).attr("opacity", 0.85);
|
|
26998
|
-
nodeG.append("text").attr("class", "bl-node-value").attr("x", bx + bw - padX).attr("y", by + padY).attr("text-anchor", "end").attr("dominant-baseline", "central").attr("font-size", VALUE_FONT_SIZE).attr("font-weight", "600").attr("fill", palette.textMuted).text(valueText);
|
|
26999
|
-
} else {
|
|
27000
|
-
nodeG.append("text").attr("class", "bl-node-value").attr("x", 0).attr("y", ln.height / 2 - VALUE_FONT_SIZE).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-size", VALUE_FONT_SIZE).attr("font-weight", "600").attr("fill", colors.text).attr("opacity", 0.8).text(valueText);
|
|
27001
|
-
}
|
|
27001
|
+
const padX = 6;
|
|
27002
|
+
const padY = 5;
|
|
27003
|
+
const bw = valueText.length * VALUE_FONT_SIZE * CHAR_WIDTH_RATIO2 + 8;
|
|
27004
|
+
const bh = VALUE_FONT_SIZE + 4;
|
|
27005
|
+
const bx = Math.max(-ln.width / 2 + 4, ln.width / 2 - bw - 4);
|
|
27006
|
+
const by = -ln.height / 2 + 4;
|
|
27007
|
+
nodeG.append("rect").attr("x", bx).attr("y", by).attr("width", bw).attr("height", bh).attr("rx", 3).attr("fill", palette.bg).attr("opacity", 0.85);
|
|
27008
|
+
nodeG.append("text").attr("class", "bl-node-value").attr("x", bx + bw - padX).attr("y", by + padY).attr("text-anchor", "end").attr("dominant-baseline", "central").attr("font-size", VALUE_FONT_SIZE).attr("font-weight", "600").attr("fill", palette.textMuted).text(valueText);
|
|
27002
27009
|
}
|
|
27003
27010
|
}
|
|
27004
27011
|
const hasDescriptions = parsed.nodes.some(
|
|
@@ -27094,7 +27101,7 @@ var init_renderer6 = __esm({
|
|
|
27094
27101
|
init_wrapped_desc();
|
|
27095
27102
|
init_scaling();
|
|
27096
27103
|
DIAGRAM_PADDING6 = 20;
|
|
27097
|
-
NODE_FONT_SIZE =
|
|
27104
|
+
NODE_FONT_SIZE = 11;
|
|
27098
27105
|
MIN_NODE_FONT_SIZE = 9;
|
|
27099
27106
|
EDGE_LABEL_FONT_SIZE4 = 11;
|
|
27100
27107
|
EDGE_STROKE_WIDTH5 = 1.5;
|
|
@@ -47054,7 +47061,11 @@ function resolveMap(parsed, data) {
|
|
|
47054
47061
|
if (bb && !isWholeSphere(bb)) containerBoxes.push(bb);
|
|
47055
47062
|
}
|
|
47056
47063
|
const containerUnion = unionExtent(containerBoxes, points);
|
|
47057
|
-
if (containerUnion)
|
|
47064
|
+
if (containerUnion)
|
|
47065
|
+
extent2 = pad(
|
|
47066
|
+
clampContainerToCluster(containerUnion, points),
|
|
47067
|
+
PAD_FRACTION
|
|
47068
|
+
);
|
|
47058
47069
|
}
|
|
47059
47070
|
if (isPoiOnly) {
|
|
47060
47071
|
const cx = (extent2[0][0] + extent2[1][0]) / 2;
|
|
@@ -47135,6 +47146,22 @@ function mostCommonCountry(regions, poiCountries) {
|
|
|
47135
47146
|
}
|
|
47136
47147
|
return best;
|
|
47137
47148
|
}
|
|
47149
|
+
function clampContainerToCluster(container, points) {
|
|
47150
|
+
const poi = unionExtent([], points);
|
|
47151
|
+
if (!poi) return container;
|
|
47152
|
+
let [[west, south], [east, north]] = container;
|
|
47153
|
+
const [[pWest, pSouth], [pEast, pNorth]] = poi;
|
|
47154
|
+
south = Math.max(south, pSouth - CONTAINER_OVERSHOOT_DEG);
|
|
47155
|
+
north = Math.min(north, pNorth + CONTAINER_OVERSHOOT_DEG);
|
|
47156
|
+
if (east <= 180 && pEast <= 180) {
|
|
47157
|
+
west = Math.max(west, pWest - CONTAINER_OVERSHOOT_DEG);
|
|
47158
|
+
east = Math.min(east, pEast + CONTAINER_OVERSHOOT_DEG);
|
|
47159
|
+
}
|
|
47160
|
+
return [
|
|
47161
|
+
[west, south],
|
|
47162
|
+
[east, north]
|
|
47163
|
+
];
|
|
47164
|
+
}
|
|
47138
47165
|
function pad(e, frac) {
|
|
47139
47166
|
const dLon = (e[1][0] - e[0][0]) * frac || 1;
|
|
47140
47167
|
const dLat = (e[1][1] - e[0][1]) * frac || 1;
|
|
@@ -47147,7 +47174,7 @@ function firstError(diags) {
|
|
|
47147
47174
|
const e = diags.find((d) => d.severity === "error");
|
|
47148
47175
|
return e ? formatDgmoError(e) : null;
|
|
47149
47176
|
}
|
|
47150
|
-
var WORLD_SPAN, MERCATOR_MAX_LAT, PAD_FRACTION, REGION_PAD_FRACTION, WORLD_LAT_SOUTH, WORLD_LAT_NORTH, POI_ZOOM_FLOOR_DEG, US_NATIONAL_LON_SPAN, REGION_ALIASES, US_STATE_POSTAL;
|
|
47177
|
+
var WORLD_SPAN, MERCATOR_MAX_LAT, PAD_FRACTION, REGION_PAD_FRACTION, WORLD_LAT_SOUTH, WORLD_LAT_NORTH, POI_ZOOM_FLOOR_DEG, CONTAINER_OVERSHOOT_DEG, US_NATIONAL_LON_SPAN, REGION_ALIASES, US_STATE_POSTAL;
|
|
47151
47178
|
var init_resolver2 = __esm({
|
|
47152
47179
|
"src/map/resolver.ts"() {
|
|
47153
47180
|
"use strict";
|
|
@@ -47160,6 +47187,7 @@ var init_resolver2 = __esm({
|
|
|
47160
47187
|
WORLD_LAT_SOUTH = -58;
|
|
47161
47188
|
WORLD_LAT_NORTH = 78;
|
|
47162
47189
|
POI_ZOOM_FLOOR_DEG = 7;
|
|
47190
|
+
CONTAINER_OVERSHOOT_DEG = 8;
|
|
47163
47191
|
US_NATIONAL_LON_SPAN = 48;
|
|
47164
47192
|
REGION_ALIASES = {
|
|
47165
47193
|
// Common everyday names → the Natural-Earth display name actually shipped.
|
|
@@ -47238,6 +47266,55 @@ var init_resolver2 = __esm({
|
|
|
47238
47266
|
}
|
|
47239
47267
|
});
|
|
47240
47268
|
|
|
47269
|
+
// src/map/legend-band.ts
|
|
47270
|
+
function mapLegendGroups(legend) {
|
|
47271
|
+
const ramp = legend.ramp;
|
|
47272
|
+
const scoreGroup = ramp ? {
|
|
47273
|
+
name: ramp.metric?.trim() || "Value",
|
|
47274
|
+
entries: [],
|
|
47275
|
+
gradient: {
|
|
47276
|
+
min: ramp.min,
|
|
47277
|
+
max: ramp.max,
|
|
47278
|
+
hue: ramp.hue,
|
|
47279
|
+
base: ramp.base
|
|
47280
|
+
}
|
|
47281
|
+
} : null;
|
|
47282
|
+
const tagGroups = legend.tagGroups.filter((g) => g.entries.length > 0).map((g) => ({ name: g.name, entries: [...g.entries] }));
|
|
47283
|
+
return [...scoreGroup ? [scoreGroup] : [], ...tagGroups];
|
|
47284
|
+
}
|
|
47285
|
+
function mapLegendConfig(groups, mode) {
|
|
47286
|
+
return {
|
|
47287
|
+
groups,
|
|
47288
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
47289
|
+
mode,
|
|
47290
|
+
showEmptyGroups: false,
|
|
47291
|
+
showInactivePills: true
|
|
47292
|
+
};
|
|
47293
|
+
}
|
|
47294
|
+
function mapLegendTop(hasTitle, hasSubtitle) {
|
|
47295
|
+
return (hasTitle ? TITLE_Y + TITLE_FONT_SIZE : 0) + (hasSubtitle ? TITLE_FONT_SIZE : 0) + LEGEND_TOP_GAP2;
|
|
47296
|
+
}
|
|
47297
|
+
function mapLegendBand(legend, opts) {
|
|
47298
|
+
if (!legend) return 0;
|
|
47299
|
+
const groups = mapLegendGroups(legend);
|
|
47300
|
+
if (groups.length === 0) return 0;
|
|
47301
|
+
const config = mapLegendConfig(groups, opts.mode);
|
|
47302
|
+
const state = { activeGroup: legend.activeGroup };
|
|
47303
|
+
const { height } = computeLegendLayout(config, state, opts.width);
|
|
47304
|
+
if (height <= 0) return 0;
|
|
47305
|
+
return mapLegendTop(opts.hasTitle, opts.hasSubtitle) + height + LEGEND_BOTTOM_GAP2;
|
|
47306
|
+
}
|
|
47307
|
+
var LEGEND_TOP_GAP2, LEGEND_BOTTOM_GAP2;
|
|
47308
|
+
var init_legend_band = __esm({
|
|
47309
|
+
"src/map/legend-band.ts"() {
|
|
47310
|
+
"use strict";
|
|
47311
|
+
init_legend_layout();
|
|
47312
|
+
init_title_constants();
|
|
47313
|
+
LEGEND_TOP_GAP2 = 8;
|
|
47314
|
+
LEGEND_BOTTOM_GAP2 = 10;
|
|
47315
|
+
}
|
|
47316
|
+
});
|
|
47317
|
+
|
|
47241
47318
|
// src/map/colorize.ts
|
|
47242
47319
|
function assignColors(isos, adjacency) {
|
|
47243
47320
|
const sorted = [...isos].sort();
|
|
@@ -47818,12 +47895,43 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47818
47895
|
return tagFill(r.tags, activeGroup) ?? neutralFill;
|
|
47819
47896
|
};
|
|
47820
47897
|
const regionById = new Map(resolved.regions.map((r) => [r.iso, r]));
|
|
47898
|
+
let legend = null;
|
|
47899
|
+
if (!resolved.directives.noLegend) {
|
|
47900
|
+
const legendTagGroups = resolved.tagGroups.map((g) => ({
|
|
47901
|
+
name: g.name,
|
|
47902
|
+
entries: g.entries.map((e) => ({ value: e.value, color: e.color }))
|
|
47903
|
+
}));
|
|
47904
|
+
if (legendTagGroups.length > 0 || hasRamp) {
|
|
47905
|
+
legend = {
|
|
47906
|
+
tagGroups: legendTagGroups,
|
|
47907
|
+
activeGroup,
|
|
47908
|
+
...hasRamp && {
|
|
47909
|
+
ramp: {
|
|
47910
|
+
...resolved.directives.regionMetric !== void 0 && {
|
|
47911
|
+
metric: resolved.directives.regionMetric
|
|
47912
|
+
},
|
|
47913
|
+
min: rampMin,
|
|
47914
|
+
max: rampMax,
|
|
47915
|
+
hue: rampHue,
|
|
47916
|
+
base: rampBase
|
|
47917
|
+
}
|
|
47918
|
+
}
|
|
47919
|
+
};
|
|
47920
|
+
}
|
|
47921
|
+
}
|
|
47821
47922
|
const TITLE_GAP2 = 16;
|
|
47822
47923
|
let topPad = FIT_PAD;
|
|
47823
47924
|
if (resolved.title && resolved.pois.length > 0) {
|
|
47824
47925
|
const bannerBottom = (resolved.subtitle ? TITLE_Y + TITLE_FONT_SIZE : TITLE_Y) + TITLE_FONT_SIZE / 2;
|
|
47825
47926
|
topPad = Math.max(FIT_PAD, bannerBottom + TITLE_GAP2);
|
|
47826
47927
|
}
|
|
47928
|
+
const legendBand = mapLegendBand(legend, {
|
|
47929
|
+
width,
|
|
47930
|
+
mode: opts.legendMode ?? "preview",
|
|
47931
|
+
hasTitle: Boolean(resolved.title),
|
|
47932
|
+
hasSubtitle: Boolean(resolved.subtitle)
|
|
47933
|
+
});
|
|
47934
|
+
if (legendBand > topPad) topPad = legendBand;
|
|
47827
47935
|
const fitBox = [
|
|
47828
47936
|
[FIT_PAD, topPad],
|
|
47829
47937
|
[
|
|
@@ -47841,7 +47949,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47841
47949
|
const by0 = cb[0][1];
|
|
47842
47950
|
const cw = cb[1][0] - bx0;
|
|
47843
47951
|
const ch = cb[1][1] - by0;
|
|
47844
|
-
const topReserve = resolved.title && resolved.pois.length > 0 ? topPad : 0;
|
|
47952
|
+
const topReserve = resolved.title && resolved.pois.length > 0 || legendBand > 0 ? topPad : 0;
|
|
47845
47953
|
const ox = 0;
|
|
47846
47954
|
const oy = topReserve;
|
|
47847
47955
|
const sx = cw > 0 ? width / cw : 1;
|
|
@@ -48905,30 +49013,6 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
48905
49013
|
});
|
|
48906
49014
|
labels.push(...contextLabels);
|
|
48907
49015
|
}
|
|
48908
|
-
let legend = null;
|
|
48909
|
-
if (!resolved.directives.noLegend) {
|
|
48910
|
-
const tagGroups = resolved.tagGroups.map((g) => ({
|
|
48911
|
-
name: g.name,
|
|
48912
|
-
entries: g.entries.map((e) => ({ value: e.value, color: e.color }))
|
|
48913
|
-
}));
|
|
48914
|
-
if (tagGroups.length > 0 || hasRamp) {
|
|
48915
|
-
legend = {
|
|
48916
|
-
tagGroups,
|
|
48917
|
-
activeGroup,
|
|
48918
|
-
...hasRamp && {
|
|
48919
|
-
ramp: {
|
|
48920
|
-
...resolved.directives.regionMetric !== void 0 && {
|
|
48921
|
-
metric: resolved.directives.regionMetric
|
|
48922
|
-
},
|
|
48923
|
-
min: rampMin,
|
|
48924
|
-
max: rampMax,
|
|
48925
|
-
hue: rampHue,
|
|
48926
|
-
base: rampBase
|
|
48927
|
-
}
|
|
48928
|
-
}
|
|
48929
|
-
};
|
|
48930
|
-
}
|
|
48931
|
-
}
|
|
48932
49016
|
return {
|
|
48933
49017
|
width,
|
|
48934
49018
|
height,
|
|
@@ -48966,6 +49050,7 @@ var init_layout15 = __esm({
|
|
|
48966
49050
|
init_label_layout();
|
|
48967
49051
|
init_legend_constants();
|
|
48968
49052
|
init_title_constants();
|
|
49053
|
+
init_legend_band();
|
|
48969
49054
|
init_context_labels();
|
|
48970
49055
|
FIT_PAD = 24;
|
|
48971
49056
|
RAMP_FLOOR2 = 15;
|
|
@@ -49165,6 +49250,9 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
49165
49250
|
// stretch-distorting. The in-app preview pane passes no exportDims → unset →
|
|
49166
49251
|
// keeps the global stretch-fill.
|
|
49167
49252
|
preferContain: exportDims?.preferContain ?? false,
|
|
49253
|
+
// Reserve the legend band for the mode actually drawn below (export shows
|
|
49254
|
+
// only the active group; preview keeps the inactive pills).
|
|
49255
|
+
legendMode: exportDims ? "export" : "preview",
|
|
49168
49256
|
...activeGroupOverride !== void 0 && {
|
|
49169
49257
|
activeGroup: activeGroupOverride
|
|
49170
49258
|
}
|
|
@@ -49456,30 +49544,12 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
49456
49544
|
if (layout.legend) {
|
|
49457
49545
|
const legendY = (layout.title ? TITLE_Y + TITLE_FONT_SIZE : 0) + (layout.subtitle ? TITLE_FONT_SIZE : 0) + 8;
|
|
49458
49546
|
const legendG = svg.append("g").attr("class", "dgmo-map-legend").attr("transform", `translate(0, ${legendY})`);
|
|
49459
|
-
const
|
|
49460
|
-
const scoreGroup = ramp ? {
|
|
49461
|
-
name: ramp.metric?.trim() || "Value",
|
|
49462
|
-
entries: [],
|
|
49463
|
-
gradient: {
|
|
49464
|
-
min: ramp.min,
|
|
49465
|
-
max: ramp.max,
|
|
49466
|
-
hue: ramp.hue,
|
|
49467
|
-
base: ramp.base
|
|
49468
|
-
}
|
|
49469
|
-
} : null;
|
|
49470
|
-
const tagGroups = layout.legend.tagGroups.filter((g) => g.entries.length > 0).map((g) => ({ name: g.name, entries: [...g.entries] }));
|
|
49471
|
-
const groups = [...scoreGroup ? [scoreGroup] : [], ...tagGroups];
|
|
49547
|
+
const groups = mapLegendGroups(layout.legend);
|
|
49472
49548
|
if (groups.length > 0) {
|
|
49473
|
-
const config =
|
|
49549
|
+
const config = mapLegendConfig(
|
|
49474
49550
|
groups,
|
|
49475
|
-
|
|
49476
|
-
|
|
49477
|
-
showEmptyGroups: false,
|
|
49478
|
-
// Keep inactive siblings visible as pills so the user can click to flip
|
|
49479
|
-
// the active colouring dimension (preview only — export shows just the
|
|
49480
|
-
// active group).
|
|
49481
|
-
showInactivePills: true
|
|
49482
|
-
};
|
|
49551
|
+
exportDims ? "export" : "preview"
|
|
49552
|
+
);
|
|
49483
49553
|
const state = { activeGroup: layout.legend.activeGroup };
|
|
49484
49554
|
renderLegendD3(legendG, config, state, palette, isDark, void 0, width);
|
|
49485
49555
|
}
|
|
@@ -49524,6 +49594,7 @@ var init_renderer16 = __esm({
|
|
|
49524
49594
|
init_title_constants();
|
|
49525
49595
|
init_color_utils();
|
|
49526
49596
|
init_legend_d3();
|
|
49597
|
+
init_legend_band();
|
|
49527
49598
|
init_layout15();
|
|
49528
49599
|
LABEL_FONT = 11;
|
|
49529
49600
|
}
|
|
@@ -49544,9 +49615,10 @@ function mapContentAspect(resolved, data, ref = REF) {
|
|
|
49544
49615
|
const aspect = w / h;
|
|
49545
49616
|
return Number.isFinite(aspect) && aspect > 0 ? aspect : FALLBACK_ASPECT;
|
|
49546
49617
|
}
|
|
49547
|
-
function mapExportDimensions(resolved, data, baseWidth = 1200) {
|
|
49548
|
-
const
|
|
49549
|
-
const
|
|
49618
|
+
function mapExportDimensions(resolved, data, baseWidth = 1200, aspectOverride) {
|
|
49619
|
+
const useOverride = aspectOverride !== void 0 && Number.isFinite(aspectOverride) && aspectOverride > 0;
|
|
49620
|
+
const raw = useOverride ? aspectOverride : mapContentAspect(resolved, data);
|
|
49621
|
+
const clamped = useOverride ? raw : Math.max(ASPECT_MIN, Math.min(ASPECT_MAX, raw));
|
|
49550
49622
|
const width = baseWidth;
|
|
49551
49623
|
let height = Math.round(width / clamped);
|
|
49552
49624
|
let chromeReserve = 0;
|
|
@@ -49559,7 +49631,7 @@ function mapExportDimensions(resolved, data, baseWidth = 1200) {
|
|
|
49559
49631
|
height = Math.round(chromeReserve + MIN_MAP_BAND);
|
|
49560
49632
|
floored = true;
|
|
49561
49633
|
}
|
|
49562
|
-
const preferContain = clamped !== raw || floored;
|
|
49634
|
+
const preferContain = useOverride ? floored : clamped !== raw || floored;
|
|
49563
49635
|
return { width, height, preferContain };
|
|
49564
49636
|
}
|
|
49565
49637
|
var import_d3_geo3, FIT_PAD2, TITLE_GAP, ASPECT_MAX, ASPECT_MIN, MIN_MAP_BAND, FALLBACK_ASPECT, REF;
|
|
@@ -55266,7 +55338,6 @@ function renderTimelineTagLegendOverlay(container, parsed, palette, isDark, setu
|
|
|
55266
55338
|
function renderTimelineHorizontalTimeSort(container, parsed, palette, isDark, setup, hovers, onClickItem, _exportDims, _swimlaneTagGroup, _activeTagGroup, _onTagStateChange, _viewMode) {
|
|
55267
55339
|
const {
|
|
55268
55340
|
width,
|
|
55269
|
-
height,
|
|
55270
55341
|
tooltip,
|
|
55271
55342
|
solid,
|
|
55272
55343
|
textColor,
|
|
@@ -55315,8 +55386,7 @@ function renderTimelineHorizontalTimeSort(container, parsed, palette, isDark, se
|
|
|
55315
55386
|
const markerLabelY = markerReserve ? -(topScaleH + MARKER_ROW_H / 2) : 0;
|
|
55316
55387
|
const eraLabelY = eraReserve ? -(topScaleH + markerReserve + ERA_ROW_H / 2) : 0;
|
|
55317
55388
|
const innerWidth = width - margin.left - margin.right;
|
|
55318
|
-
const
|
|
55319
|
-
const rowH = Math.min(ctx.structural(28), availInnerHeight / sorted.length);
|
|
55389
|
+
const rowH = ctx.structural(28);
|
|
55320
55390
|
const innerHeight = rowH * sorted.length;
|
|
55321
55391
|
const usedHeight = margin.top + innerHeight + margin.bottom;
|
|
55322
55392
|
const xScale = d3Scale2.scaleLinear().domain([minDate - datePadding, maxDate + datePadding]).range([0, innerWidth]);
|
|
@@ -57897,7 +57967,12 @@ async function renderForExport(content, theme, palette, viewState, options) {
|
|
|
57897
57967
|
}
|
|
57898
57968
|
}
|
|
57899
57969
|
const mapResolved = resolveMap2(mapParsed, mapData);
|
|
57900
|
-
const dims2 = mapExportDimensions2(
|
|
57970
|
+
const dims2 = mapExportDimensions2(
|
|
57971
|
+
mapResolved,
|
|
57972
|
+
mapData,
|
|
57973
|
+
EXPORT_WIDTH,
|
|
57974
|
+
options?.mapAspect
|
|
57975
|
+
);
|
|
57901
57976
|
const container2 = createExportContainer(dims2.width, dims2.height);
|
|
57902
57977
|
renderMapForExport2(
|
|
57903
57978
|
container2,
|
package/dist/internal.d.cts
CHANGED
|
@@ -236,6 +236,28 @@ interface ParsedMap {
|
|
|
236
236
|
readonly diagnostics: readonly DgmoError[];
|
|
237
237
|
readonly error: string | null;
|
|
238
238
|
}
|
|
239
|
+
/** Legend descriptor for a rendered map (a layout-stage output, re-exported from
|
|
240
|
+
* `layout.ts`). It lives here so the `legend-band` helper can consume it without
|
|
241
|
+
* importing `layout` — `layout` already value-imports `mapLegendBand`, so the
|
|
242
|
+
* reverse type import would form a layout↔legend-band cycle. */
|
|
243
|
+
interface MapLayoutLegend {
|
|
244
|
+
readonly tagGroups: ReadonlyArray<{
|
|
245
|
+
name: string;
|
|
246
|
+
entries: ReadonlyArray<{
|
|
247
|
+
value: string;
|
|
248
|
+
color: string;
|
|
249
|
+
}>;
|
|
250
|
+
}>;
|
|
251
|
+
readonly activeGroup: string | null;
|
|
252
|
+
readonly ramp?: {
|
|
253
|
+
metric?: string;
|
|
254
|
+
min: number;
|
|
255
|
+
max: number;
|
|
256
|
+
hue: string;
|
|
257
|
+
/** Low end of the ramp gradient (the land colour the fills blend from). */
|
|
258
|
+
base: string;
|
|
259
|
+
};
|
|
260
|
+
}
|
|
239
261
|
|
|
240
262
|
/** A TopoJSON topology (world-coarse/world-detail keyed by ISO 3166-1 alpha-2;
|
|
241
263
|
* us-states keyed by ISO 3166-2). Geometry feature `id` is the ISO code;
|
|
@@ -1568,6 +1590,7 @@ declare function renderForExport(content: string, theme: 'light' | 'dark' | 'tra
|
|
|
1568
1590
|
tagGroup?: string;
|
|
1569
1591
|
exportMode?: boolean;
|
|
1570
1592
|
mapData?: MapData;
|
|
1593
|
+
mapAspect?: number;
|
|
1571
1594
|
}): Promise<string>;
|
|
1572
1595
|
|
|
1573
1596
|
/**
|
|
@@ -4839,24 +4862,7 @@ interface PlacedLabel {
|
|
|
4839
4862
|
readonly clusterMember?: string;
|
|
4840
4863
|
readonly lineNumber: number;
|
|
4841
4864
|
}
|
|
4842
|
-
|
|
4843
|
-
readonly tagGroups: ReadonlyArray<{
|
|
4844
|
-
name: string;
|
|
4845
|
-
entries: ReadonlyArray<{
|
|
4846
|
-
value: string;
|
|
4847
|
-
color: string;
|
|
4848
|
-
}>;
|
|
4849
|
-
}>;
|
|
4850
|
-
readonly activeGroup: string | null;
|
|
4851
|
-
readonly ramp?: {
|
|
4852
|
-
metric?: string;
|
|
4853
|
-
min: number;
|
|
4854
|
-
max: number;
|
|
4855
|
-
hue: string;
|
|
4856
|
-
/** Low end of the ramp gradient (the land colour the fills blend from). */
|
|
4857
|
-
base: string;
|
|
4858
|
-
};
|
|
4859
|
-
}
|
|
4865
|
+
|
|
4860
4866
|
/** A drawn river centerline — an open stroked path (no fill). */
|
|
4861
4867
|
interface MapLayoutRiver {
|
|
4862
4868
|
readonly d: string;
|
|
@@ -4955,6 +4961,10 @@ interface LayoutOptions {
|
|
|
4955
4961
|
* canvas away from the content aspect, so the off-aspect canvas doesn't
|
|
4956
4962
|
* re-distort. The in-app preview pane leaves this unset (keeps stretch-fill). */
|
|
4957
4963
|
readonly preferContain?: boolean;
|
|
4964
|
+
/** Which legend variant gets drawn — `'export'` shows only the active group,
|
|
4965
|
+
* `'preview'` keeps inactive pills. Used to size the reserved legend band so
|
|
4966
|
+
* the projected land starts below the legend. Defaults to `'preview'`. */
|
|
4967
|
+
readonly legendMode?: LegendMode;
|
|
4958
4968
|
}
|
|
4959
4969
|
interface Size {
|
|
4960
4970
|
readonly width: number;
|
|
@@ -5007,7 +5017,13 @@ interface MapExportDimensions {
|
|
|
5007
5017
|
readonly height: number;
|
|
5008
5018
|
readonly preferContain: boolean;
|
|
5009
5019
|
}
|
|
5010
|
-
declare function mapExportDimensions(resolved: ResolvedMap, data: MapData, baseWidth?: number
|
|
5020
|
+
declare function mapExportDimensions(resolved: ResolvedMap, data: MapData, baseWidth?: number,
|
|
5021
|
+
/** WYSIWYG override (app export): the live preview pane's displayed aspect
|
|
5022
|
+
* (width / height). When provided, the canvas adopts it verbatim and
|
|
5023
|
+
* stretch-fills (no clamp, no contain) so the PNG matches exactly what's on
|
|
5024
|
+
* screen. Omitted by every headless consumer (CLI / MCP / SSG / Obsidian),
|
|
5025
|
+
* which keep the intrinsic-aspect sizing below. */
|
|
5026
|
+
aspectOverride?: number): MapExportDimensions;
|
|
5011
5027
|
|
|
5012
5028
|
/** Nearest gazetteer city to a point: the real haversine distance, plus the
|
|
5013
5029
|
* canonical name + ISO + (US-only) subdivision for token shaping. `lon`/`lat`
|