@diagrammo/dgmo 0.22.0 → 0.24.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.cjs +372 -103
- package/dist/advanced.d.cts +52 -19
- package/dist/advanced.d.ts +52 -19
- package/dist/advanced.js +372 -103
- package/dist/auto.cjs +370 -97
- package/dist/auto.js +117 -117
- package/dist/auto.mjs +370 -97
- package/dist/cli.cjs +151 -151
- package/dist/editor.cjs +3 -0
- package/dist/editor.js +3 -0
- package/dist/highlight.cjs +3 -0
- package/dist/highlight.js +3 -0
- package/dist/index.cjs +498 -96
- package/dist/index.d.cts +37 -1
- package/dist/index.d.ts +37 -1
- package/dist/index.js +496 -96
- package/dist/internal.cjs +372 -103
- package/dist/internal.d.cts +52 -19
- package/dist/internal.d.ts +52 -19
- package/dist/internal.js +372 -103
- package/dist/map-data/PROVENANCE.json +1 -1
- package/dist/map-data/gazetteer.json +1 -1
- package/dist/map-data/mountain-ranges.json +1 -1
- package/dist/map-data/water-bodies.json +1 -1
- package/dist/map-data/world-coarse.json +1 -1
- package/dist/map-data/world-detail.json +1 -1
- package/docs/language-reference.md +38 -2
- package/gallery/fixtures/boxes-and-lines.dgmo +6 -4
- package/package.json +1 -1
- package/src/boxes-and-lines/parser.ts +39 -0
- package/src/boxes-and-lines/renderer.ts +219 -14
- package/src/boxes-and-lines/types.ts +9 -0
- package/src/completion.ts +4 -5
- package/src/d3.ts +26 -6
- package/src/editor/keywords.ts +3 -0
- package/src/index.ts +8 -0
- package/src/map/data/PROVENANCE.json +1 -1
- package/src/map/data/README.md +6 -0
- package/src/map/data/gazetteer.json +1 -1
- package/src/map/data/mountain-ranges.json +1 -1
- package/src/map/data/water-bodies.json +1 -1
- package/src/map/data/world-coarse.json +1 -1
- package/src/map/data/world-detail.json +1 -1
- package/src/map/dimensions.ts +21 -5
- package/src/map/layout.ts +167 -63
- package/src/map/legend-band.ts +99 -0
- package/src/map/renderer.ts +105 -32
- package/src/map/resolver.ts +43 -1
- package/src/map/types.ts +20 -0
- package/src/utils/reserved-key-registry.ts +5 -3
- package/src/utils/svg-embed.ts +193 -0
package/dist/advanced.cjs
CHANGED
|
@@ -917,9 +917,7 @@ var init_reserved_key_registry = __esm({
|
|
|
917
917
|
BOXES_AND_LINES_REGISTRY = staticRegistry([
|
|
918
918
|
"color",
|
|
919
919
|
"description",
|
|
920
|
-
"
|
|
921
|
-
"split",
|
|
922
|
-
"fanout"
|
|
920
|
+
"value"
|
|
923
921
|
]);
|
|
924
922
|
TIMELINE_REGISTRY = staticRegistry([
|
|
925
923
|
"color",
|
|
@@ -16873,6 +16871,21 @@ function parseBoxesAndLines(content) {
|
|
|
16873
16871
|
}
|
|
16874
16872
|
continue;
|
|
16875
16873
|
}
|
|
16874
|
+
if (!contentStarted) {
|
|
16875
|
+
const metricMatch = trimmed.match(/^box-metric\s+(.+)$/i);
|
|
16876
|
+
if (metricMatch) {
|
|
16877
|
+
const { label, colorName } = peelTrailingColorName(
|
|
16878
|
+
metricMatch[1].trim()
|
|
16879
|
+
);
|
|
16880
|
+
result.boxMetric = label;
|
|
16881
|
+
if (colorName !== void 0) result.boxMetricColor = colorName;
|
|
16882
|
+
continue;
|
|
16883
|
+
}
|
|
16884
|
+
if (/^show-values$/i.test(trimmed)) {
|
|
16885
|
+
result.showValues = true;
|
|
16886
|
+
continue;
|
|
16887
|
+
}
|
|
16888
|
+
}
|
|
16876
16889
|
if (!contentStarted) {
|
|
16877
16890
|
const optMatch = trimmed.match(OPTION_NOCOLON_RE);
|
|
16878
16891
|
if (optMatch) {
|
|
@@ -17251,6 +17264,19 @@ function parseNodeLine(trimmed, lineNum, metaAliasMap, diagnostics, nameAliasMap
|
|
|
17251
17264
|
description = [metadata["description"]];
|
|
17252
17265
|
delete metadata["description"];
|
|
17253
17266
|
}
|
|
17267
|
+
let value;
|
|
17268
|
+
if (metadata["value"] !== void 0) {
|
|
17269
|
+
const raw = metadata["value"];
|
|
17270
|
+
const num = Number(raw);
|
|
17271
|
+
if (Number.isFinite(num)) {
|
|
17272
|
+
value = num;
|
|
17273
|
+
} else {
|
|
17274
|
+
diagnostics.push(
|
|
17275
|
+
makeDgmoError(lineNum, `value must be a number (got "${raw}")`, "error")
|
|
17276
|
+
);
|
|
17277
|
+
}
|
|
17278
|
+
delete metadata["value"];
|
|
17279
|
+
}
|
|
17254
17280
|
if (split.alias) {
|
|
17255
17281
|
nameAliasMap?.set(normalizeName(split.alias), label);
|
|
17256
17282
|
}
|
|
@@ -17259,7 +17285,8 @@ function parseNodeLine(trimmed, lineNum, metaAliasMap, diagnostics, nameAliasMap
|
|
|
17259
17285
|
label,
|
|
17260
17286
|
lineNumber: lineNum,
|
|
17261
17287
|
metadata,
|
|
17262
|
-
...description !== void 0 && { description }
|
|
17288
|
+
...description !== void 0 && { description },
|
|
17289
|
+
...value !== void 0 && { value }
|
|
17263
17290
|
};
|
|
17264
17291
|
}
|
|
17265
17292
|
function splitTargetAndMeta(rest, metaAliasMap) {
|
|
@@ -26469,7 +26496,18 @@ function fitLabelToHeader(label, nodeWidth, maxLines) {
|
|
|
26469
26496
|
const truncated = label.length > maxChars ? label.slice(0, maxChars - 1) + "\u2026" : label;
|
|
26470
26497
|
return { lines: [truncated], fontSize: MIN_NODE_FONT_SIZE };
|
|
26471
26498
|
}
|
|
26472
|
-
function nodeColors(node, tagGroups, activeGroupName, palette, isDark, solid) {
|
|
26499
|
+
function nodeColors(node, tagGroups, activeGroupName, palette, isDark, value, solid) {
|
|
26500
|
+
const neutralFill = mix(palette.bg, palette.text, isDark ? 90 : 95);
|
|
26501
|
+
if (value.active) {
|
|
26502
|
+
const fill3 = node.value !== void 0 ? value.fillForValue(node.value) : neutralFill;
|
|
26503
|
+
const stroke3 = value.hue;
|
|
26504
|
+
const text2 = contrastText(
|
|
26505
|
+
fill3,
|
|
26506
|
+
palette.textOnFillLight,
|
|
26507
|
+
palette.textOnFillDark
|
|
26508
|
+
);
|
|
26509
|
+
return { fill: fill3, stroke: stroke3, text: text2 };
|
|
26510
|
+
}
|
|
26473
26511
|
const tagColor = resolveTagColor(
|
|
26474
26512
|
node.metadata,
|
|
26475
26513
|
[...tagGroups],
|
|
@@ -26578,25 +26616,65 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26578
26616
|
const sGroupLabelZone = sctx.structural(GROUP_LABEL_ZONE);
|
|
26579
26617
|
const sTitleFontSize = sctx.text(TITLE_FONT_SIZE);
|
|
26580
26618
|
const sTitleY = sctx.structural(TITLE_Y);
|
|
26619
|
+
const nodeValues = parsed.nodes.filter((n) => n.value !== void 0).map((n) => n.value);
|
|
26620
|
+
const hasRamp = nodeValues.length > 0;
|
|
26621
|
+
const allNonNegative = hasRamp && nodeValues.every((v) => v >= 0);
|
|
26622
|
+
const rampMin = allNonNegative ? 0 : Math.min(...nodeValues);
|
|
26623
|
+
const rampMax = Math.max(...nodeValues);
|
|
26624
|
+
const rampHue = resolveColor(parsed.boxMetricColor ?? "", palette) ?? palette.primary;
|
|
26625
|
+
const rampBase = isDark ? mix(palette.surface, palette.text, 28) : palette.bg;
|
|
26626
|
+
const fillForValue = (v) => {
|
|
26627
|
+
const t = rampMax > rampMin ? (v - rampMin) / (rampMax - rampMin) : 1;
|
|
26628
|
+
const pct = RAMP_FLOOR + Math.max(0, Math.min(1, t)) * (100 - RAMP_FLOOR);
|
|
26629
|
+
return mix(rampHue, rampBase, pct);
|
|
26630
|
+
};
|
|
26631
|
+
const VALUE_NAME = hasRamp ? parsed.boxMetric?.trim() || "Value" : null;
|
|
26632
|
+
const matchColorGroup = (v) => {
|
|
26633
|
+
const lv = v.trim().toLowerCase();
|
|
26634
|
+
if (lv === "" || lv === "none") return null;
|
|
26635
|
+
const tg = parsed.tagGroups.find((g) => g.name.toLowerCase() === lv);
|
|
26636
|
+
if (tg) return tg.name;
|
|
26637
|
+
if (lv === VALUE_NAME?.toLowerCase()) return VALUE_NAME;
|
|
26638
|
+
return v;
|
|
26639
|
+
};
|
|
26640
|
+
const override = activeTagGroup;
|
|
26641
|
+
let activeGroup;
|
|
26642
|
+
if (override !== void 0) {
|
|
26643
|
+
activeGroup = override === null ? null : matchColorGroup(override);
|
|
26644
|
+
} else if (parsed.options["active-tag"] !== void 0) {
|
|
26645
|
+
activeGroup = matchColorGroup(parsed.options["active-tag"]);
|
|
26646
|
+
} else {
|
|
26647
|
+
activeGroup = VALUE_NAME ?? (parsed.tagGroups.length > 0 ? parsed.tagGroups[0].name : null);
|
|
26648
|
+
}
|
|
26649
|
+
const activeIsValue = VALUE_NAME !== null && activeGroup === VALUE_NAME;
|
|
26650
|
+
const valueGroup = VALUE_NAME !== null ? {
|
|
26651
|
+
name: VALUE_NAME,
|
|
26652
|
+
entries: [],
|
|
26653
|
+
gradient: {
|
|
26654
|
+
min: rampMin,
|
|
26655
|
+
max: rampMax,
|
|
26656
|
+
hue: rampHue,
|
|
26657
|
+
base: rampBase
|
|
26658
|
+
}
|
|
26659
|
+
} : null;
|
|
26660
|
+
const legendGroups = [
|
|
26661
|
+
...valueGroup ? [valueGroup] : [],
|
|
26662
|
+
...parsed.tagGroups
|
|
26663
|
+
];
|
|
26581
26664
|
const reserveHasDescriptions = parsed.nodes.some(
|
|
26582
26665
|
(n) => n.description && n.description.length > 0
|
|
26583
26666
|
);
|
|
26584
|
-
const willRenderLegend =
|
|
26667
|
+
const willRenderLegend = legendGroups.length > 0 || reserveHasDescriptions && controlsHost !== "app";
|
|
26585
26668
|
const sLegendHeight = willRenderLegend ? sctx.structural(
|
|
26586
26669
|
getMaxLegendReservedHeight(
|
|
26587
26670
|
{
|
|
26588
|
-
groups:
|
|
26671
|
+
groups: legendGroups,
|
|
26589
26672
|
position: { placement: "top-center", titleRelation: "below-title" },
|
|
26590
26673
|
mode: exportMode ? "export" : "preview"
|
|
26591
26674
|
},
|
|
26592
26675
|
width
|
|
26593
26676
|
)
|
|
26594
26677
|
) : 0;
|
|
26595
|
-
const activeGroup = resolveActiveTagGroup(
|
|
26596
|
-
parsed.tagGroups,
|
|
26597
|
-
parsed.options["active-tag"],
|
|
26598
|
-
activeTagGroup
|
|
26599
|
-
);
|
|
26600
26678
|
const hidden = hiddenTagValues ?? parsed.initialHiddenTagValues;
|
|
26601
26679
|
const nodeMap = /* @__PURE__ */ new Map();
|
|
26602
26680
|
for (const node of parsed.nodes) nodeMap.set(node.label, node);
|
|
@@ -26607,7 +26685,7 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26607
26685
|
const hasAnyDescriptions = parsed.nodes.some(
|
|
26608
26686
|
(n) => n.description && n.description.length > 0
|
|
26609
26687
|
);
|
|
26610
|
-
const needsLegend =
|
|
26688
|
+
const needsLegend = legendGroups.length > 0 || hasAnyDescriptions && onToggleDescriptions;
|
|
26611
26689
|
const legendH = needsLegend ? sLegendHeight + 8 : 0;
|
|
26612
26690
|
const groupLabelsSet = new Set(layout.groups.map((g) => g.label));
|
|
26613
26691
|
let labelZoneExtension = 0;
|
|
@@ -26813,12 +26891,16 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26813
26891
|
activeGroup,
|
|
26814
26892
|
palette,
|
|
26815
26893
|
isDark,
|
|
26894
|
+
{ active: activeIsValue, hue: rampHue, fillForValue },
|
|
26816
26895
|
parsed.options["solid-fill"] === "on"
|
|
26817
26896
|
);
|
|
26818
26897
|
const nodeG = diagramG.append("g").attr("class", "bl-node").attr("transform", `translate(${ln.x},${ln.y})`).attr("data-line-number", node.lineNumber).attr("data-node-id", node.label).style("cursor", onClickItem ? "pointer" : "default").style("--bl-node-stroke", colors.stroke);
|
|
26819
26898
|
for (const [key, val] of Object.entries(node.metadata)) {
|
|
26820
26899
|
nodeG.attr(`data-tag-${key.toLowerCase()}`, val.toLowerCase());
|
|
26821
26900
|
}
|
|
26901
|
+
if (node.value !== void 0) {
|
|
26902
|
+
nodeG.attr("data-value", node.value);
|
|
26903
|
+
}
|
|
26822
26904
|
if (onClickItem) {
|
|
26823
26905
|
nodeG.on("click", (event) => {
|
|
26824
26906
|
const target = event.target;
|
|
@@ -26890,6 +26972,22 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26890
26972
|
const tooltipText = fullText.length > 200 ? fullText.slice(0, 199) + "\u2026" : fullText;
|
|
26891
26973
|
nodeG.append("title").text(tooltipText);
|
|
26892
26974
|
}
|
|
26975
|
+
} else if (parsed.showValues && node.value !== void 0) {
|
|
26976
|
+
const valueLabel = parsed.boxMetric ? `${parsed.boxMetric}: ${node.value}` : String(node.value);
|
|
26977
|
+
const headerH = ln.height / 2;
|
|
26978
|
+
const sepY = -ln.height / 2 + headerH;
|
|
26979
|
+
const fitted = fitLabelToHeader(node.label, ln.width, 2);
|
|
26980
|
+
const labelLineH = fitted.fontSize * 1.3;
|
|
26981
|
+
const labelTotalH = fitted.lines.length * labelLineH;
|
|
26982
|
+
const headerCenterY = -ln.height / 2 + headerH / 2;
|
|
26983
|
+
for (let li = 0; li < fitted.lines.length; li++) {
|
|
26984
|
+
nodeG.append("text").attr("x", 0).attr(
|
|
26985
|
+
"y",
|
|
26986
|
+
headerCenterY - labelTotalH / 2 + labelLineH / 2 + li * labelLineH
|
|
26987
|
+
).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]);
|
|
26988
|
+
}
|
|
26989
|
+
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);
|
|
26990
|
+
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);
|
|
26893
26991
|
} else {
|
|
26894
26992
|
const maxLabelLines = Math.max(
|
|
26895
26993
|
2,
|
|
@@ -26902,11 +27000,22 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26902
27000
|
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]);
|
|
26903
27001
|
}
|
|
26904
27002
|
}
|
|
27003
|
+
if (parsed.showValues && node.value !== void 0 && desc && desc.length > 0 && !hideDescriptions) {
|
|
27004
|
+
const valueText = String(node.value);
|
|
27005
|
+
const padX = 6;
|
|
27006
|
+
const padY = 5;
|
|
27007
|
+
const bw = valueText.length * VALUE_FONT_SIZE * CHAR_WIDTH_RATIO2 + 8;
|
|
27008
|
+
const bh = VALUE_FONT_SIZE + 4;
|
|
27009
|
+
const bx = Math.max(-ln.width / 2 + 4, ln.width / 2 - bw - 4);
|
|
27010
|
+
const by = -ln.height / 2 + 4;
|
|
27011
|
+
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);
|
|
27012
|
+
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);
|
|
27013
|
+
}
|
|
26905
27014
|
}
|
|
26906
27015
|
const hasDescriptions = parsed.nodes.some(
|
|
26907
27016
|
(n) => n.description && n.description.length > 0
|
|
26908
27017
|
);
|
|
26909
|
-
const hasLegend =
|
|
27018
|
+
const hasLegend = legendGroups.length > 0 || hasDescriptions && controlsHost !== "app";
|
|
26910
27019
|
if (hasLegend) {
|
|
26911
27020
|
let controlsGroup;
|
|
26912
27021
|
if (hasDescriptions && (onToggleDescriptions || controlsHost === "app")) {
|
|
@@ -26924,7 +27033,7 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26924
27033
|
};
|
|
26925
27034
|
}
|
|
26926
27035
|
const legendConfig = {
|
|
26927
|
-
groups:
|
|
27036
|
+
groups: legendGroups,
|
|
26928
27037
|
position: { placement: "top-center", titleRelation: "below-title" },
|
|
26929
27038
|
mode: exportMode ? "export" : "preview",
|
|
26930
27039
|
// Keep inactive sibling tag groups visible as collapsed pills so the user
|
|
@@ -26979,7 +27088,7 @@ function renderBoxesAndLinesForExport(container, parsed, layout, palette, isDark
|
|
|
26979
27088
|
}
|
|
26980
27089
|
});
|
|
26981
27090
|
}
|
|
26982
|
-
var d3Selection6, d3Shape4, DIAGRAM_PADDING6, NODE_FONT_SIZE, MIN_NODE_FONT_SIZE, EDGE_LABEL_FONT_SIZE4, EDGE_STROKE_WIDTH5, NODE_STROKE_WIDTH5, NODE_RX, COLLAPSE_BAR_HEIGHT3, ARROWHEAD_W2, ARROWHEAD_H2, DESC_FONT_SIZE, DESC_LINE_HEIGHT, MAX_DESC_LINES, CHAR_WIDTH_RATIO2, NODE_TEXT_PADDING, GROUP_RX, GROUP_LABEL_FONT_SIZE, GROUP_LABEL_ZONE, lineGeneratorLR, lineGeneratorTB;
|
|
27091
|
+
var d3Selection6, d3Shape4, DIAGRAM_PADDING6, NODE_FONT_SIZE, MIN_NODE_FONT_SIZE, EDGE_LABEL_FONT_SIZE4, EDGE_STROKE_WIDTH5, NODE_STROKE_WIDTH5, NODE_RX, COLLAPSE_BAR_HEIGHT3, ARROWHEAD_W2, ARROWHEAD_H2, DESC_FONT_SIZE, DESC_LINE_HEIGHT, MAX_DESC_LINES, CHAR_WIDTH_RATIO2, NODE_TEXT_PADDING, GROUP_RX, GROUP_LABEL_FONT_SIZE, GROUP_LABEL_ZONE, RAMP_FLOOR, VALUE_FONT_SIZE, lineGeneratorLR, lineGeneratorTB;
|
|
26983
27092
|
var init_renderer6 = __esm({
|
|
26984
27093
|
"src/boxes-and-lines/renderer.ts"() {
|
|
26985
27094
|
"use strict";
|
|
@@ -26990,12 +27099,13 @@ var init_renderer6 = __esm({
|
|
|
26990
27099
|
init_legend_layout();
|
|
26991
27100
|
init_title_constants();
|
|
26992
27101
|
init_color_utils();
|
|
27102
|
+
init_colors();
|
|
26993
27103
|
init_tag_groups();
|
|
26994
27104
|
init_inline_markdown();
|
|
26995
27105
|
init_wrapped_desc();
|
|
26996
27106
|
init_scaling();
|
|
26997
27107
|
DIAGRAM_PADDING6 = 20;
|
|
26998
|
-
NODE_FONT_SIZE =
|
|
27108
|
+
NODE_FONT_SIZE = 11;
|
|
26999
27109
|
MIN_NODE_FONT_SIZE = 9;
|
|
27000
27110
|
EDGE_LABEL_FONT_SIZE4 = 11;
|
|
27001
27111
|
EDGE_STROKE_WIDTH5 = 1.5;
|
|
@@ -27012,6 +27122,8 @@ var init_renderer6 = __esm({
|
|
|
27012
27122
|
GROUP_RX = 8;
|
|
27013
27123
|
GROUP_LABEL_FONT_SIZE = 14;
|
|
27014
27124
|
GROUP_LABEL_ZONE = 32;
|
|
27125
|
+
RAMP_FLOOR = 15;
|
|
27126
|
+
VALUE_FONT_SIZE = 11;
|
|
27015
27127
|
lineGeneratorLR = d3Shape4.line().x((d) => d.x).y((d) => d.y).curve(d3Shape4.curveBasis);
|
|
27016
27128
|
lineGeneratorTB = d3Shape4.line().x((d) => d.x).y((d) => d.y).curve(d3Shape4.curveBasis);
|
|
27017
27129
|
}
|
|
@@ -46953,7 +47065,11 @@ function resolveMap(parsed, data) {
|
|
|
46953
47065
|
if (bb && !isWholeSphere(bb)) containerBoxes.push(bb);
|
|
46954
47066
|
}
|
|
46955
47067
|
const containerUnion = unionExtent(containerBoxes, points);
|
|
46956
|
-
if (containerUnion)
|
|
47068
|
+
if (containerUnion)
|
|
47069
|
+
extent2 = pad(
|
|
47070
|
+
clampContainerToCluster(containerUnion, points),
|
|
47071
|
+
PAD_FRACTION
|
|
47072
|
+
);
|
|
46957
47073
|
}
|
|
46958
47074
|
if (isPoiOnly) {
|
|
46959
47075
|
const cx = (extent2[0][0] + extent2[1][0]) / 2;
|
|
@@ -47034,6 +47150,22 @@ function mostCommonCountry(regions, poiCountries) {
|
|
|
47034
47150
|
}
|
|
47035
47151
|
return best;
|
|
47036
47152
|
}
|
|
47153
|
+
function clampContainerToCluster(container, points) {
|
|
47154
|
+
const poi = unionExtent([], points);
|
|
47155
|
+
if (!poi) return container;
|
|
47156
|
+
let [[west, south], [east, north]] = container;
|
|
47157
|
+
const [[pWest, pSouth], [pEast, pNorth]] = poi;
|
|
47158
|
+
south = Math.max(south, pSouth - CONTAINER_OVERSHOOT_DEG);
|
|
47159
|
+
north = Math.min(north, pNorth + CONTAINER_OVERSHOOT_DEG);
|
|
47160
|
+
if (east <= 180 && pEast <= 180) {
|
|
47161
|
+
west = Math.max(west, pWest - CONTAINER_OVERSHOOT_DEG);
|
|
47162
|
+
east = Math.min(east, pEast + CONTAINER_OVERSHOOT_DEG);
|
|
47163
|
+
}
|
|
47164
|
+
return [
|
|
47165
|
+
[west, south],
|
|
47166
|
+
[east, north]
|
|
47167
|
+
];
|
|
47168
|
+
}
|
|
47037
47169
|
function pad(e, frac) {
|
|
47038
47170
|
const dLon = (e[1][0] - e[0][0]) * frac || 1;
|
|
47039
47171
|
const dLat = (e[1][1] - e[0][1]) * frac || 1;
|
|
@@ -47046,7 +47178,7 @@ function firstError(diags) {
|
|
|
47046
47178
|
const e = diags.find((d) => d.severity === "error");
|
|
47047
47179
|
return e ? formatDgmoError(e) : null;
|
|
47048
47180
|
}
|
|
47049
|
-
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;
|
|
47181
|
+
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;
|
|
47050
47182
|
var init_resolver2 = __esm({
|
|
47051
47183
|
"src/map/resolver.ts"() {
|
|
47052
47184
|
"use strict";
|
|
@@ -47059,6 +47191,7 @@ var init_resolver2 = __esm({
|
|
|
47059
47191
|
WORLD_LAT_SOUTH = -58;
|
|
47060
47192
|
WORLD_LAT_NORTH = 78;
|
|
47061
47193
|
POI_ZOOM_FLOOR_DEG = 7;
|
|
47194
|
+
CONTAINER_OVERSHOOT_DEG = 8;
|
|
47062
47195
|
US_NATIONAL_LON_SPAN = 48;
|
|
47063
47196
|
REGION_ALIASES = {
|
|
47064
47197
|
// Common everyday names → the Natural-Earth display name actually shipped.
|
|
@@ -47137,6 +47270,55 @@ var init_resolver2 = __esm({
|
|
|
47137
47270
|
}
|
|
47138
47271
|
});
|
|
47139
47272
|
|
|
47273
|
+
// src/map/legend-band.ts
|
|
47274
|
+
function mapLegendGroups(legend) {
|
|
47275
|
+
const ramp = legend.ramp;
|
|
47276
|
+
const scoreGroup = ramp ? {
|
|
47277
|
+
name: ramp.metric?.trim() || "Value",
|
|
47278
|
+
entries: [],
|
|
47279
|
+
gradient: {
|
|
47280
|
+
min: ramp.min,
|
|
47281
|
+
max: ramp.max,
|
|
47282
|
+
hue: ramp.hue,
|
|
47283
|
+
base: ramp.base
|
|
47284
|
+
}
|
|
47285
|
+
} : null;
|
|
47286
|
+
const tagGroups = legend.tagGroups.filter((g) => g.entries.length > 0).map((g) => ({ name: g.name, entries: [...g.entries] }));
|
|
47287
|
+
return [...scoreGroup ? [scoreGroup] : [], ...tagGroups];
|
|
47288
|
+
}
|
|
47289
|
+
function mapLegendConfig(groups, mode) {
|
|
47290
|
+
return {
|
|
47291
|
+
groups,
|
|
47292
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
47293
|
+
mode,
|
|
47294
|
+
showEmptyGroups: false,
|
|
47295
|
+
showInactivePills: true
|
|
47296
|
+
};
|
|
47297
|
+
}
|
|
47298
|
+
function mapLegendTop(hasTitle, hasSubtitle) {
|
|
47299
|
+
return (hasTitle ? TITLE_Y + TITLE_FONT_SIZE : 0) + (hasSubtitle ? TITLE_FONT_SIZE : 0) + LEGEND_TOP_GAP2;
|
|
47300
|
+
}
|
|
47301
|
+
function mapLegendBand(legend, opts) {
|
|
47302
|
+
if (!legend) return 0;
|
|
47303
|
+
const groups = mapLegendGroups(legend);
|
|
47304
|
+
if (groups.length === 0) return 0;
|
|
47305
|
+
const config = mapLegendConfig(groups, opts.mode);
|
|
47306
|
+
const state = { activeGroup: legend.activeGroup };
|
|
47307
|
+
const { height } = computeLegendLayout(config, state, opts.width);
|
|
47308
|
+
if (height <= 0) return 0;
|
|
47309
|
+
return mapLegendTop(opts.hasTitle, opts.hasSubtitle) + height + LEGEND_BOTTOM_GAP2;
|
|
47310
|
+
}
|
|
47311
|
+
var LEGEND_TOP_GAP2, LEGEND_BOTTOM_GAP2;
|
|
47312
|
+
var init_legend_band = __esm({
|
|
47313
|
+
"src/map/legend-band.ts"() {
|
|
47314
|
+
"use strict";
|
|
47315
|
+
init_legend_layout();
|
|
47316
|
+
init_title_constants();
|
|
47317
|
+
LEGEND_TOP_GAP2 = 8;
|
|
47318
|
+
LEGEND_BOTTOM_GAP2 = 10;
|
|
47319
|
+
}
|
|
47320
|
+
});
|
|
47321
|
+
|
|
47140
47322
|
// src/map/colorize.ts
|
|
47141
47323
|
function assignColors(isos, adjacency) {
|
|
47142
47324
|
const sorted = [...isos].sort();
|
|
@@ -47566,6 +47748,38 @@ function parsePathRings(d) {
|
|
|
47566
47748
|
if (cur.length) rings.push(cur);
|
|
47567
47749
|
return rings;
|
|
47568
47750
|
}
|
|
47751
|
+
function dropAntimeridianWrapSlivers(d, width, height) {
|
|
47752
|
+
const rings = parsePathRings(d);
|
|
47753
|
+
if (rings.length <= 1) return d;
|
|
47754
|
+
const eps = 0.75;
|
|
47755
|
+
const minArea = 3e-3 * width * height;
|
|
47756
|
+
const ringArea = (r) => {
|
|
47757
|
+
let s = 0;
|
|
47758
|
+
for (let i = 0; i < r.length; i++) {
|
|
47759
|
+
const a = r[i];
|
|
47760
|
+
const b = r[(i + 1) % r.length];
|
|
47761
|
+
s += a[0] * b[1] - b[0] * a[1];
|
|
47762
|
+
}
|
|
47763
|
+
return Math.abs(s) / 2;
|
|
47764
|
+
};
|
|
47765
|
+
const areas = rings.map(ringArea);
|
|
47766
|
+
const maxArea = Math.max(...areas);
|
|
47767
|
+
const onVEdge = (a, b) => Math.abs(a[0]) <= eps && Math.abs(b[0]) <= eps || Math.abs(a[0] - width) <= eps && Math.abs(b[0] - width) <= eps;
|
|
47768
|
+
let dropped = false;
|
|
47769
|
+
const kept = rings.filter((r, idx) => {
|
|
47770
|
+
if (areas[idx] >= maxArea || areas[idx] >= minArea) return true;
|
|
47771
|
+
const touches = r.some((p, i) => onVEdge(p, r[(i + 1) % r.length]));
|
|
47772
|
+
if (touches) {
|
|
47773
|
+
dropped = true;
|
|
47774
|
+
return false;
|
|
47775
|
+
}
|
|
47776
|
+
return true;
|
|
47777
|
+
});
|
|
47778
|
+
if (!dropped) return d;
|
|
47779
|
+
return kept.map(
|
|
47780
|
+
(r) => r.map((p, i) => (i ? "L" : "M") + p[0] + "," + p[1]).join("") + "Z"
|
|
47781
|
+
).join("");
|
|
47782
|
+
}
|
|
47569
47783
|
function layoutMap(resolved, data, size, opts) {
|
|
47570
47784
|
const { palette, isDark } = opts;
|
|
47571
47785
|
const { width, height } = size;
|
|
@@ -47649,7 +47863,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47649
47863
|
const rampBase = isDark ? mix(palette.surface, palette.text, 28) : palette.bg;
|
|
47650
47864
|
const fillForValue = (s) => {
|
|
47651
47865
|
const t = rampMax > rampMin ? (s - rampMin) / (rampMax - rampMin) : 1;
|
|
47652
|
-
const pct =
|
|
47866
|
+
const pct = RAMP_FLOOR2 + Math.max(0, Math.min(1, t)) * (100 - RAMP_FLOOR2);
|
|
47653
47867
|
return mix(rampHue, rampBase, pct);
|
|
47654
47868
|
};
|
|
47655
47869
|
const tagFill = (tags, groupName) => {
|
|
@@ -47685,12 +47899,43 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47685
47899
|
return tagFill(r.tags, activeGroup) ?? neutralFill;
|
|
47686
47900
|
};
|
|
47687
47901
|
const regionById = new Map(resolved.regions.map((r) => [r.iso, r]));
|
|
47902
|
+
let legend = null;
|
|
47903
|
+
if (!resolved.directives.noLegend) {
|
|
47904
|
+
const legendTagGroups = resolved.tagGroups.map((g) => ({
|
|
47905
|
+
name: g.name,
|
|
47906
|
+
entries: g.entries.map((e) => ({ value: e.value, color: e.color }))
|
|
47907
|
+
}));
|
|
47908
|
+
if (legendTagGroups.length > 0 || hasRamp) {
|
|
47909
|
+
legend = {
|
|
47910
|
+
tagGroups: legendTagGroups,
|
|
47911
|
+
activeGroup,
|
|
47912
|
+
...hasRamp && {
|
|
47913
|
+
ramp: {
|
|
47914
|
+
...resolved.directives.regionMetric !== void 0 && {
|
|
47915
|
+
metric: resolved.directives.regionMetric
|
|
47916
|
+
},
|
|
47917
|
+
min: rampMin,
|
|
47918
|
+
max: rampMax,
|
|
47919
|
+
hue: rampHue,
|
|
47920
|
+
base: rampBase
|
|
47921
|
+
}
|
|
47922
|
+
}
|
|
47923
|
+
};
|
|
47924
|
+
}
|
|
47925
|
+
}
|
|
47688
47926
|
const TITLE_GAP2 = 16;
|
|
47689
47927
|
let topPad = FIT_PAD;
|
|
47690
47928
|
if (resolved.title && resolved.pois.length > 0) {
|
|
47691
47929
|
const bannerBottom = (resolved.subtitle ? TITLE_Y + TITLE_FONT_SIZE : TITLE_Y) + TITLE_FONT_SIZE / 2;
|
|
47692
47930
|
topPad = Math.max(FIT_PAD, bannerBottom + TITLE_GAP2);
|
|
47693
47931
|
}
|
|
47932
|
+
const legendBand = mapLegendBand(legend, {
|
|
47933
|
+
width,
|
|
47934
|
+
mode: opts.legendMode ?? "preview",
|
|
47935
|
+
hasTitle: Boolean(resolved.title),
|
|
47936
|
+
hasSubtitle: Boolean(resolved.subtitle)
|
|
47937
|
+
});
|
|
47938
|
+
if (legendBand > topPad) topPad = legendBand;
|
|
47694
47939
|
const fitBox = [
|
|
47695
47940
|
[FIT_PAD, topPad],
|
|
47696
47941
|
[
|
|
@@ -47708,10 +47953,11 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47708
47953
|
const by0 = cb[0][1];
|
|
47709
47954
|
const cw = cb[1][0] - bx0;
|
|
47710
47955
|
const ch = cb[1][1] - by0;
|
|
47711
|
-
const
|
|
47712
|
-
const
|
|
47713
|
-
const
|
|
47714
|
-
const
|
|
47956
|
+
const topReserve = resolved.title && resolved.pois.length > 0 || legendBand > 0 ? topPad : 0;
|
|
47957
|
+
const ox = 0;
|
|
47958
|
+
const oy = topReserve;
|
|
47959
|
+
const sx = cw > 0 ? width / cw : 1;
|
|
47960
|
+
const sy = ch > 0 ? (height - topReserve) / ch : 1;
|
|
47715
47961
|
stretchParams = { sx, sy, ox, oy, bx0, by0 };
|
|
47716
47962
|
const stretch = (x, y) => [
|
|
47717
47963
|
ox + (x - bx0) * sx,
|
|
@@ -47984,7 +48230,8 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47984
48230
|
const r = regionById.get(iso);
|
|
47985
48231
|
const viewF = shouldCull ? cullFeatureToView(f) : dropFrameFillers(f);
|
|
47986
48232
|
if (!viewF) continue;
|
|
47987
|
-
const
|
|
48233
|
+
const raw = path(viewF) ?? "";
|
|
48234
|
+
const d = fitIsGlobal ? dropAntimeridianWrapSlivers(raw, width, height) : raw;
|
|
47988
48235
|
if (!d) continue;
|
|
47989
48236
|
const isThisLayer = r?.layer === layerKind;
|
|
47990
48237
|
const isForeign = layerKind === "country" && usContext && iso !== "US";
|
|
@@ -48001,6 +48248,9 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
48001
48248
|
} else {
|
|
48002
48249
|
label = f.properties?.name;
|
|
48003
48250
|
}
|
|
48251
|
+
const labelAnchor = WORLD_LABEL_ANCHORS[iso];
|
|
48252
|
+
const c = labelAnchor ? project(labelAnchor[0], labelAnchor[1]) : path.centroid(viewF);
|
|
48253
|
+
const hasCentroid = c != null && Number.isFinite(c[0]) && Number.isFinite(c[1]);
|
|
48004
48254
|
regions.push({
|
|
48005
48255
|
id: iso,
|
|
48006
48256
|
d,
|
|
@@ -48009,6 +48259,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
48009
48259
|
lineNumber,
|
|
48010
48260
|
layer,
|
|
48011
48261
|
...label !== void 0 && { label },
|
|
48262
|
+
...hasCentroid && { labelX: c[0], labelY: c[1] },
|
|
48012
48263
|
...isThisLayer && r.value !== void 0 && { value: r.value },
|
|
48013
48264
|
...isThisLayer && Object.keys(r.tags).length > 0 && { tags: r.tags }
|
|
48014
48265
|
});
|
|
@@ -48449,10 +48700,6 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
48449
48700
|
lineNumber
|
|
48450
48701
|
});
|
|
48451
48702
|
};
|
|
48452
|
-
const WORLD_LABEL_ANCHORS = {
|
|
48453
|
-
US: [-98.5, 39.5]
|
|
48454
|
-
// CONUS geographic centre (near Lebanon, Kansas)
|
|
48455
|
-
};
|
|
48456
48703
|
const REGION_LABEL_GAP = 2;
|
|
48457
48704
|
const regionLabelRect = (cx, cy, text) => {
|
|
48458
48705
|
const w = measureLegendText(text, FONT2) + 2 * REGION_LABEL_GAP;
|
|
@@ -48770,30 +49017,6 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
48770
49017
|
});
|
|
48771
49018
|
labels.push(...contextLabels);
|
|
48772
49019
|
}
|
|
48773
|
-
let legend = null;
|
|
48774
|
-
if (!resolved.directives.noLegend) {
|
|
48775
|
-
const tagGroups = resolved.tagGroups.map((g) => ({
|
|
48776
|
-
name: g.name,
|
|
48777
|
-
entries: g.entries.map((e) => ({ value: e.value, color: e.color }))
|
|
48778
|
-
}));
|
|
48779
|
-
if (tagGroups.length > 0 || hasRamp) {
|
|
48780
|
-
legend = {
|
|
48781
|
-
tagGroups,
|
|
48782
|
-
activeGroup,
|
|
48783
|
-
...hasRamp && {
|
|
48784
|
-
ramp: {
|
|
48785
|
-
...resolved.directives.regionMetric !== void 0 && {
|
|
48786
|
-
metric: resolved.directives.regionMetric
|
|
48787
|
-
},
|
|
48788
|
-
min: rampMin,
|
|
48789
|
-
max: rampMax,
|
|
48790
|
-
hue: rampHue,
|
|
48791
|
-
base: rampBase
|
|
48792
|
-
}
|
|
48793
|
-
}
|
|
48794
|
-
};
|
|
48795
|
-
}
|
|
48796
|
-
}
|
|
48797
49020
|
return {
|
|
48798
49021
|
width,
|
|
48799
49022
|
height,
|
|
@@ -48818,7 +49041,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
48818
49041
|
diagnostics: []
|
|
48819
49042
|
};
|
|
48820
49043
|
}
|
|
48821
|
-
var import_d3_geo2, import_topojson_client2, FIT_PAD,
|
|
49044
|
+
var import_d3_geo2, import_topojson_client2, FIT_PAD, RAMP_FLOOR2, R_DEFAULT, R_MIN, R_MAX, W_MIN, W_MAX, FONT2, WORLD_LABEL_ANCHORS, MAX_CLUSTER_EXTENT_FACTOR, MAX_COLUMN_ROWS, REGION_LABEL_HALO_RATIO, LAND_TINT_LIGHT, LAND_TINT_DARK, TAG_TINT_LIGHT, TAG_TINT_DARK, WATER_TINT_LIGHT, WATER_TINT_DARK, RIVER_WIDTH, COMPACT_WIDTH_PX, RELIEF_MIN_AREA, RELIEF_MIN_DIM, RELIEF_HATCH_SPACING, RELIEF_HATCH_WIDTH, RELIEF_HATCH_STRENGTH, COASTLINE_RING_COUNT, COASTLINE_D0, COASTLINE_STEP, COASTLINE_THICKNESS, COASTLINE_OPACITY_NEAR, COASTLINE_OPACITY_FAR, COASTLINE_MIN_EXTENT, COASTLINE_MIN_EXTENT_GLOBAL, COASTLINE_STROKE_MIX, FOREIGN_TINT_LIGHT, FOREIGN_TINT_DARK, MUTED_FOREIGN_LIGHT, MUTED_FOREIGN_DARK, COLO_R, GOLDEN_ANGLE, STACK_OVERLAP, STACK_RING_MAX, STACK_RING_GAP, FAN_STEP, ARC_CURVE_FRAC, decodeCache, usConusProjection, alaskaProjection, hawaiiProjection, INSET_STATES, inAlaska, inHawaii, FOREIGN_BORDER, US_NON_CONUS;
|
|
48822
49045
|
var init_layout15 = __esm({
|
|
48823
49046
|
"src/map/layout.ts"() {
|
|
48824
49047
|
"use strict";
|
|
@@ -48831,15 +49054,20 @@ var init_layout15 = __esm({
|
|
|
48831
49054
|
init_label_layout();
|
|
48832
49055
|
init_legend_constants();
|
|
48833
49056
|
init_title_constants();
|
|
49057
|
+
init_legend_band();
|
|
48834
49058
|
init_context_labels();
|
|
48835
49059
|
FIT_PAD = 24;
|
|
48836
|
-
|
|
49060
|
+
RAMP_FLOOR2 = 15;
|
|
48837
49061
|
R_DEFAULT = 6;
|
|
48838
49062
|
R_MIN = 4;
|
|
48839
49063
|
R_MAX = 22;
|
|
48840
49064
|
W_MIN = 1.25;
|
|
48841
49065
|
W_MAX = 8;
|
|
48842
49066
|
FONT2 = 11;
|
|
49067
|
+
WORLD_LABEL_ANCHORS = {
|
|
49068
|
+
US: [-98.5, 39.5]
|
|
49069
|
+
// CONUS geographic centre (near Lebanon, Kansas)
|
|
49070
|
+
};
|
|
48843
49071
|
MAX_CLUSTER_EXTENT_FACTOR = 0.18;
|
|
48844
49072
|
MAX_COLUMN_ROWS = 7;
|
|
48845
49073
|
REGION_LABEL_HALO_RATIO = 4.5;
|
|
@@ -48853,9 +49081,9 @@ var init_layout15 = __esm({
|
|
|
48853
49081
|
COMPACT_WIDTH_PX = 480;
|
|
48854
49082
|
RELIEF_MIN_AREA = 12;
|
|
48855
49083
|
RELIEF_MIN_DIM = 2;
|
|
48856
|
-
RELIEF_HATCH_SPACING =
|
|
48857
|
-
RELIEF_HATCH_WIDTH = 0.
|
|
48858
|
-
RELIEF_HATCH_STRENGTH =
|
|
49084
|
+
RELIEF_HATCH_SPACING = 1.5;
|
|
49085
|
+
RELIEF_HATCH_WIDTH = 0.2;
|
|
49086
|
+
RELIEF_HATCH_STRENGTH = 26;
|
|
48859
49087
|
COASTLINE_RING_COUNT = 5;
|
|
48860
49088
|
COASTLINE_D0 = 16e-4;
|
|
48861
49089
|
COASTLINE_STEP = 28e-4;
|
|
@@ -48933,7 +49161,47 @@ function ringToPath(ring) {
|
|
|
48933
49161
|
d += (i ? "L" : "M") + ring[i][0] + "," + ring[i][1];
|
|
48934
49162
|
return d + "Z";
|
|
48935
49163
|
}
|
|
48936
|
-
function
|
|
49164
|
+
function polylineToPath(pts) {
|
|
49165
|
+
let d = "";
|
|
49166
|
+
for (let i = 0; i < pts.length; i++)
|
|
49167
|
+
d += (i ? "L" : "M") + pts[i][0] + "," + pts[i][1];
|
|
49168
|
+
return d;
|
|
49169
|
+
}
|
|
49170
|
+
function ringToCoastPaths(ring, frame) {
|
|
49171
|
+
if (!frame) return [ringToPath(ring)];
|
|
49172
|
+
const n = ring.length;
|
|
49173
|
+
const eps = 0.75;
|
|
49174
|
+
const onL = (x) => Math.abs(x) <= eps;
|
|
49175
|
+
const onR = (x) => Math.abs(x - frame.w) <= eps;
|
|
49176
|
+
const onT = (y) => Math.abs(y) <= eps;
|
|
49177
|
+
const onB = (y) => Math.abs(y - frame.h) <= eps;
|
|
49178
|
+
const isFrameEdge = (a, b) => onL(a[0]) && onL(b[0]) || onR(a[0]) && onR(b[0]) || onT(a[1]) && onT(b[1]) || onB(a[1]) && onB(b[1]);
|
|
49179
|
+
let firstBreak = -1;
|
|
49180
|
+
for (let i = 0; i < n; i++)
|
|
49181
|
+
if (isFrameEdge(ring[i], ring[(i + 1) % n])) {
|
|
49182
|
+
firstBreak = i;
|
|
49183
|
+
break;
|
|
49184
|
+
}
|
|
49185
|
+
if (firstBreak === -1) return [ringToPath(ring)];
|
|
49186
|
+
const paths = [];
|
|
49187
|
+
let cur = [];
|
|
49188
|
+
const start = (firstBreak + 1) % n;
|
|
49189
|
+
for (let k = 0; k < n; k++) {
|
|
49190
|
+
const i = (start + k) % n;
|
|
49191
|
+
const a = ring[i];
|
|
49192
|
+
const b = ring[(i + 1) % n];
|
|
49193
|
+
if (isFrameEdge(a, b)) {
|
|
49194
|
+
if (cur.length >= 2) paths.push(polylineToPath(cur));
|
|
49195
|
+
cur = [];
|
|
49196
|
+
continue;
|
|
49197
|
+
}
|
|
49198
|
+
if (cur.length === 0) cur.push(a);
|
|
49199
|
+
cur.push(b);
|
|
49200
|
+
}
|
|
49201
|
+
if (cur.length >= 2) paths.push(polylineToPath(cur));
|
|
49202
|
+
return paths;
|
|
49203
|
+
}
|
|
49204
|
+
function coastlineOuterRings(regions, minExtent, frame) {
|
|
48937
49205
|
const paths = [];
|
|
48938
49206
|
for (const r of regions) {
|
|
48939
49207
|
const rings = parsePathRings(r.d);
|
|
@@ -48956,7 +49224,7 @@ function coastlineOuterRings(regions, minExtent) {
|
|
|
48956
49224
|
for (let j = 0; j < rings.length; j++)
|
|
48957
49225
|
if (j !== i && pointInRing2(fx, fy, rings[j])) depth++;
|
|
48958
49226
|
if (depth % 2 === 1) continue;
|
|
48959
|
-
paths.push(
|
|
49227
|
+
paths.push(...ringToCoastPaths(ring, frame));
|
|
48960
49228
|
}
|
|
48961
49229
|
}
|
|
48962
49230
|
return paths;
|
|
@@ -48986,6 +49254,9 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
48986
49254
|
// stretch-distorting. The in-app preview pane passes no exportDims → unset →
|
|
48987
49255
|
// keeps the global stretch-fill.
|
|
48988
49256
|
preferContain: exportDims?.preferContain ?? false,
|
|
49257
|
+
// Reserve the legend band for the mode actually drawn below (export shows
|
|
49258
|
+
// only the active group; preview keeps the inactive pills).
|
|
49259
|
+
legendMode: exportDims ? "export" : "preview",
|
|
48989
49260
|
...activeGroupOverride !== void 0 && {
|
|
48990
49261
|
activeGroup: activeGroupOverride
|
|
48991
49262
|
}
|
|
@@ -49000,6 +49271,10 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
49000
49271
|
const drawRegion = (g, r, strokeWidth) => {
|
|
49001
49272
|
const p = g.append("path").attr("d", r.d).attr("fill", r.fill).attr("stroke", r.stroke).attr("stroke-width", strokeWidth);
|
|
49002
49273
|
if (r.label) p.attr("data-region-name", r.label);
|
|
49274
|
+
if (r.id && r.id !== "lake") p.attr("data-iso", r.id);
|
|
49275
|
+
if (r.labelX !== void 0 && r.labelY !== void 0) {
|
|
49276
|
+
p.attr("data-label-x", r.labelX).attr("data-label-y", r.labelY);
|
|
49277
|
+
}
|
|
49003
49278
|
if (r.layer !== "base") {
|
|
49004
49279
|
p.classed("dgmo-map-region", true).attr("data-region", r.id);
|
|
49005
49280
|
if (r.value !== void 0) p.attr("data-value", r.value);
|
|
@@ -49029,7 +49304,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
49029
49304
|
const landClip = defs.append("clipPath").attr("id", landClipId);
|
|
49030
49305
|
for (const r of layout.regions)
|
|
49031
49306
|
if (r.id !== "lake") landClip.append("path").attr("d", r.d);
|
|
49032
|
-
const gRelief = svg.append("g").attr("clip-path", `url(#${landClipId})`).append("g").attr("class", "dgmo-map-relief").attr("clip-path", `url(#${rangeClipId})`).attr("stroke", h.color).attr("stroke-width", h.width).attr("vector-effect", "non-scaling-stroke");
|
|
49307
|
+
const gRelief = svg.append("g").attr("clip-path", `url(#${landClipId})`).style("pointer-events", "none").append("g").attr("class", "dgmo-map-relief").attr("clip-path", `url(#${rangeClipId})`).attr("stroke", h.color).attr("stroke-width", h.width).attr("vector-effect", "non-scaling-stroke");
|
|
49033
49308
|
for (let y = h.spacing; y < height; y += h.spacing) {
|
|
49034
49309
|
gRelief.append("line").attr("x1", 0).attr("y1", y).attr("x2", width).attr("y2", y);
|
|
49035
49310
|
}
|
|
@@ -49050,10 +49325,16 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
49050
49325
|
mask.append("path").attr("d", d).attr("fill", "black").attr("stroke", "black").attr("stroke-width", 2 * reach).attr("stroke-linejoin", "round");
|
|
49051
49326
|
}
|
|
49052
49327
|
}
|
|
49053
|
-
const gWater = svg.append("g").attr("class", "dgmo-map-water-lines").attr("fill", "none").attr("mask", `url(#${maskId})`);
|
|
49328
|
+
const gWater = svg.append("g").attr("class", "dgmo-map-water-lines").attr("fill", "none").style("pointer-events", "none").attr("mask", `url(#${maskId})`);
|
|
49054
49329
|
appendWaterLines(
|
|
49055
49330
|
gWater,
|
|
49056
|
-
|
|
49331
|
+
// Pass the canvas frame so edges collinear with it (the antimeridian on a
|
|
49332
|
+
// world map, regional clipExtent cuts) don't get ringed as fake coast —
|
|
49333
|
+
// land runs cleanly to the render-area edge.
|
|
49334
|
+
coastlineOuterRings(layout.regions, cs.minExtent, {
|
|
49335
|
+
w: width,
|
|
49336
|
+
h: height
|
|
49337
|
+
}),
|
|
49057
49338
|
cs,
|
|
49058
49339
|
layout.background
|
|
49059
49340
|
);
|
|
@@ -49067,7 +49348,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
49067
49348
|
gWater.append("path").attr("d", ds.join(" ")).attr("stroke", stroke2).attr("stroke-width", 0.5).attr("stroke-linejoin", "round");
|
|
49068
49349
|
}
|
|
49069
49350
|
if (layout.rivers.length) {
|
|
49070
|
-
const gRivers = svg.append("g").attr("class", "dgmo-map-rivers").attr("fill", "none");
|
|
49351
|
+
const gRivers = svg.append("g").attr("class", "dgmo-map-rivers").attr("fill", "none").style("pointer-events", "none");
|
|
49071
49352
|
for (const r of layout.rivers) {
|
|
49072
49353
|
gRivers.append("path").attr("d", r.d).attr("stroke", r.color).attr("stroke-width", r.width).attr("stroke-linecap", "round").attr("stroke-linejoin", "round");
|
|
49073
49354
|
}
|
|
@@ -49108,7 +49389,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
49108
49389
|
const d = box.points.map((p, i) => `${i ? "L" : "M"}${p[0]},${p[1]}`).join("") + "Z";
|
|
49109
49390
|
clip.append("path").attr("d", d);
|
|
49110
49391
|
}
|
|
49111
|
-
const gInsetWater = insetG.append("g").attr("clip-path", `url(#${clipId})`).append("g").attr("class", "dgmo-map-inset-water-lines").attr("fill", "none").attr("mask", `url(#${maskId})`);
|
|
49392
|
+
const gInsetWater = insetG.append("g").attr("clip-path", `url(#${clipId})`).append("g").attr("class", "dgmo-map-inset-water-lines").attr("fill", "none").style("pointer-events", "none").attr("mask", `url(#${maskId})`);
|
|
49112
49393
|
appendWaterLines(
|
|
49113
49394
|
gInsetWater,
|
|
49114
49395
|
coastlineOuterRings(layout.insetRegions, cs.minExtent),
|
|
@@ -49267,30 +49548,12 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
49267
49548
|
if (layout.legend) {
|
|
49268
49549
|
const legendY = (layout.title ? TITLE_Y + TITLE_FONT_SIZE : 0) + (layout.subtitle ? TITLE_FONT_SIZE : 0) + 8;
|
|
49269
49550
|
const legendG = svg.append("g").attr("class", "dgmo-map-legend").attr("transform", `translate(0, ${legendY})`);
|
|
49270
|
-
const
|
|
49271
|
-
const scoreGroup = ramp ? {
|
|
49272
|
-
name: ramp.metric?.trim() || "Value",
|
|
49273
|
-
entries: [],
|
|
49274
|
-
gradient: {
|
|
49275
|
-
min: ramp.min,
|
|
49276
|
-
max: ramp.max,
|
|
49277
|
-
hue: ramp.hue,
|
|
49278
|
-
base: ramp.base
|
|
49279
|
-
}
|
|
49280
|
-
} : null;
|
|
49281
|
-
const tagGroups = layout.legend.tagGroups.filter((g) => g.entries.length > 0).map((g) => ({ name: g.name, entries: [...g.entries] }));
|
|
49282
|
-
const groups = [...scoreGroup ? [scoreGroup] : [], ...tagGroups];
|
|
49551
|
+
const groups = mapLegendGroups(layout.legend);
|
|
49283
49552
|
if (groups.length > 0) {
|
|
49284
|
-
const config =
|
|
49553
|
+
const config = mapLegendConfig(
|
|
49285
49554
|
groups,
|
|
49286
|
-
|
|
49287
|
-
|
|
49288
|
-
showEmptyGroups: false,
|
|
49289
|
-
// Keep inactive siblings visible as pills so the user can click to flip
|
|
49290
|
-
// the active colouring dimension (preview only — export shows just the
|
|
49291
|
-
// active group).
|
|
49292
|
-
showInactivePills: true
|
|
49293
|
-
};
|
|
49555
|
+
exportDims ? "export" : "preview"
|
|
49556
|
+
);
|
|
49294
49557
|
const state = { activeGroup: layout.legend.activeGroup };
|
|
49295
49558
|
renderLegendD3(legendG, config, state, palette, isDark, void 0, width);
|
|
49296
49559
|
}
|
|
@@ -49335,6 +49598,7 @@ var init_renderer16 = __esm({
|
|
|
49335
49598
|
init_title_constants();
|
|
49336
49599
|
init_color_utils();
|
|
49337
49600
|
init_legend_d3();
|
|
49601
|
+
init_legend_band();
|
|
49338
49602
|
init_layout15();
|
|
49339
49603
|
LABEL_FONT = 11;
|
|
49340
49604
|
}
|
|
@@ -49355,9 +49619,10 @@ function mapContentAspect(resolved, data, ref = REF) {
|
|
|
49355
49619
|
const aspect = w / h;
|
|
49356
49620
|
return Number.isFinite(aspect) && aspect > 0 ? aspect : FALLBACK_ASPECT;
|
|
49357
49621
|
}
|
|
49358
|
-
function mapExportDimensions(resolved, data, baseWidth = 1200) {
|
|
49359
|
-
const
|
|
49360
|
-
const
|
|
49622
|
+
function mapExportDimensions(resolved, data, baseWidth = 1200, aspectOverride) {
|
|
49623
|
+
const useOverride = aspectOverride !== void 0 && Number.isFinite(aspectOverride) && aspectOverride > 0;
|
|
49624
|
+
const raw = useOverride ? aspectOverride : mapContentAspect(resolved, data);
|
|
49625
|
+
const clamped = useOverride ? raw : Math.max(ASPECT_MIN, Math.min(ASPECT_MAX, raw));
|
|
49361
49626
|
const width = baseWidth;
|
|
49362
49627
|
let height = Math.round(width / clamped);
|
|
49363
49628
|
let chromeReserve = 0;
|
|
@@ -49370,7 +49635,7 @@ function mapExportDimensions(resolved, data, baseWidth = 1200) {
|
|
|
49370
49635
|
height = Math.round(chromeReserve + MIN_MAP_BAND);
|
|
49371
49636
|
floored = true;
|
|
49372
49637
|
}
|
|
49373
|
-
const preferContain = clamped !== raw || floored;
|
|
49638
|
+
const preferContain = useOverride ? floored : clamped !== raw || floored;
|
|
49374
49639
|
return { width, height, preferContain };
|
|
49375
49640
|
}
|
|
49376
49641
|
var import_d3_geo3, FIT_PAD2, TITLE_GAP, ASPECT_MAX, ASPECT_MIN, MIN_MAP_BAND, FALLBACK_ASPECT, REF;
|
|
@@ -55077,7 +55342,6 @@ function renderTimelineTagLegendOverlay(container, parsed, palette, isDark, setu
|
|
|
55077
55342
|
function renderTimelineHorizontalTimeSort(container, parsed, palette, isDark, setup, hovers, onClickItem, _exportDims, _swimlaneTagGroup, _activeTagGroup, _onTagStateChange, _viewMode) {
|
|
55078
55343
|
const {
|
|
55079
55344
|
width,
|
|
55080
|
-
height,
|
|
55081
55345
|
tooltip,
|
|
55082
55346
|
solid,
|
|
55083
55347
|
textColor,
|
|
@@ -55126,10 +55390,11 @@ function renderTimelineHorizontalTimeSort(container, parsed, palette, isDark, se
|
|
|
55126
55390
|
const markerLabelY = markerReserve ? -(topScaleH + MARKER_ROW_H / 2) : 0;
|
|
55127
55391
|
const eraLabelY = eraReserve ? -(topScaleH + markerReserve + ERA_ROW_H / 2) : 0;
|
|
55128
55392
|
const innerWidth = width - margin.left - margin.right;
|
|
55129
|
-
const
|
|
55130
|
-
const
|
|
55393
|
+
const rowH = ctx.structural(28);
|
|
55394
|
+
const innerHeight = rowH * sorted.length;
|
|
55395
|
+
const usedHeight = margin.top + innerHeight + margin.bottom;
|
|
55131
55396
|
const xScale = d3Scale2.scaleLinear().domain([minDate - datePadding, maxDate + datePadding]).range([0, innerWidth]);
|
|
55132
|
-
const svg = d3Selection23.select(container).append("svg").attr("width", width).attr("height",
|
|
55397
|
+
const svg = d3Selection23.select(container).append("svg").attr("width", width).attr("height", usedHeight).attr("viewBox", `0 0 ${width} ${usedHeight}`).attr("preserveAspectRatio", "xMidYMin meet").style("background", bgColor);
|
|
55133
55398
|
if (ctx.isBelowFloor) {
|
|
55134
55399
|
svg.attr("width", "100%");
|
|
55135
55400
|
}
|
|
@@ -57706,7 +57971,12 @@ async function renderForExport(content, theme, palette, viewState, options) {
|
|
|
57706
57971
|
}
|
|
57707
57972
|
}
|
|
57708
57973
|
const mapResolved = resolveMap2(mapParsed, mapData);
|
|
57709
|
-
const dims2 = mapExportDimensions2(
|
|
57974
|
+
const dims2 = mapExportDimensions2(
|
|
57975
|
+
mapResolved,
|
|
57976
|
+
mapData,
|
|
57977
|
+
EXPORT_WIDTH,
|
|
57978
|
+
options?.mapAspect
|
|
57979
|
+
);
|
|
57710
57980
|
const container2 = createExportContainer(dims2.width, dims2.height);
|
|
57711
57981
|
renderMapForExport2(
|
|
57712
57982
|
container2,
|
|
@@ -60504,7 +60774,9 @@ var COMPLETION_REGISTRY = /* @__PURE__ */ new Map([
|
|
|
60504
60774
|
withGlobals({
|
|
60505
60775
|
direction: { description: "Layout direction", values: ["LR", "TB"] },
|
|
60506
60776
|
"active-tag": { description: "Active tag group name" },
|
|
60507
|
-
hide: { description: "Hide tag:value pairs" }
|
|
60777
|
+
hide: { description: "Hide tag:value pairs" },
|
|
60778
|
+
"box-metric": { description: "Metric label for the value ramp" },
|
|
60779
|
+
"show-values": { description: "Print box values as text" }
|
|
60508
60780
|
})
|
|
60509
60781
|
],
|
|
60510
60782
|
[
|
|
@@ -60732,13 +61004,10 @@ var PIPE_METADATA = /* @__PURE__ */ new Map([
|
|
|
60732
61004
|
"boxes-and-lines",
|
|
60733
61005
|
{
|
|
60734
61006
|
node: {
|
|
60735
|
-
description: { description: "Node description text" }
|
|
61007
|
+
description: { description: "Node description text" },
|
|
61008
|
+
value: { description: "Numeric value for the metric ramp" }
|
|
60736
61009
|
},
|
|
60737
|
-
edge: {
|
|
60738
|
-
width: { description: "Edge stroke width in pixels" },
|
|
60739
|
-
split: { description: "Traffic split percentage" },
|
|
60740
|
-
fanout: { description: "Fanout multiplier (integer >= 1)" }
|
|
60741
|
-
}
|
|
61010
|
+
edge: {}
|
|
60742
61011
|
}
|
|
60743
61012
|
],
|
|
60744
61013
|
[
|