@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/internal.js
CHANGED
|
@@ -915,9 +915,7 @@ var init_reserved_key_registry = __esm({
|
|
|
915
915
|
BOXES_AND_LINES_REGISTRY = staticRegistry([
|
|
916
916
|
"color",
|
|
917
917
|
"description",
|
|
918
|
-
"
|
|
919
|
-
"split",
|
|
920
|
-
"fanout"
|
|
918
|
+
"value"
|
|
921
919
|
]);
|
|
922
920
|
TIMELINE_REGISTRY = staticRegistry([
|
|
923
921
|
"color",
|
|
@@ -16889,6 +16887,21 @@ function parseBoxesAndLines(content) {
|
|
|
16889
16887
|
}
|
|
16890
16888
|
continue;
|
|
16891
16889
|
}
|
|
16890
|
+
if (!contentStarted) {
|
|
16891
|
+
const metricMatch = trimmed.match(/^box-metric\s+(.+)$/i);
|
|
16892
|
+
if (metricMatch) {
|
|
16893
|
+
const { label, colorName } = peelTrailingColorName(
|
|
16894
|
+
metricMatch[1].trim()
|
|
16895
|
+
);
|
|
16896
|
+
result.boxMetric = label;
|
|
16897
|
+
if (colorName !== void 0) result.boxMetricColor = colorName;
|
|
16898
|
+
continue;
|
|
16899
|
+
}
|
|
16900
|
+
if (/^show-values$/i.test(trimmed)) {
|
|
16901
|
+
result.showValues = true;
|
|
16902
|
+
continue;
|
|
16903
|
+
}
|
|
16904
|
+
}
|
|
16892
16905
|
if (!contentStarted) {
|
|
16893
16906
|
const optMatch = trimmed.match(OPTION_NOCOLON_RE);
|
|
16894
16907
|
if (optMatch) {
|
|
@@ -17267,6 +17280,19 @@ function parseNodeLine(trimmed, lineNum, metaAliasMap, diagnostics, nameAliasMap
|
|
|
17267
17280
|
description = [metadata["description"]];
|
|
17268
17281
|
delete metadata["description"];
|
|
17269
17282
|
}
|
|
17283
|
+
let value;
|
|
17284
|
+
if (metadata["value"] !== void 0) {
|
|
17285
|
+
const raw = metadata["value"];
|
|
17286
|
+
const num = Number(raw);
|
|
17287
|
+
if (Number.isFinite(num)) {
|
|
17288
|
+
value = num;
|
|
17289
|
+
} else {
|
|
17290
|
+
diagnostics.push(
|
|
17291
|
+
makeDgmoError(lineNum, `value must be a number (got "${raw}")`, "error")
|
|
17292
|
+
);
|
|
17293
|
+
}
|
|
17294
|
+
delete metadata["value"];
|
|
17295
|
+
}
|
|
17270
17296
|
if (split.alias) {
|
|
17271
17297
|
nameAliasMap?.set(normalizeName(split.alias), label);
|
|
17272
17298
|
}
|
|
@@ -17275,7 +17301,8 @@ function parseNodeLine(trimmed, lineNum, metaAliasMap, diagnostics, nameAliasMap
|
|
|
17275
17301
|
label,
|
|
17276
17302
|
lineNumber: lineNum,
|
|
17277
17303
|
metadata,
|
|
17278
|
-
...description !== void 0 && { description }
|
|
17304
|
+
...description !== void 0 && { description },
|
|
17305
|
+
...value !== void 0 && { value }
|
|
17279
17306
|
};
|
|
17280
17307
|
}
|
|
17281
17308
|
function splitTargetAndMeta(rest, metaAliasMap) {
|
|
@@ -26487,7 +26514,18 @@ function fitLabelToHeader(label, nodeWidth, maxLines) {
|
|
|
26487
26514
|
const truncated = label.length > maxChars ? label.slice(0, maxChars - 1) + "\u2026" : label;
|
|
26488
26515
|
return { lines: [truncated], fontSize: MIN_NODE_FONT_SIZE };
|
|
26489
26516
|
}
|
|
26490
|
-
function nodeColors(node, tagGroups, activeGroupName, palette, isDark, solid) {
|
|
26517
|
+
function nodeColors(node, tagGroups, activeGroupName, palette, isDark, value, solid) {
|
|
26518
|
+
const neutralFill = mix(palette.bg, palette.text, isDark ? 90 : 95);
|
|
26519
|
+
if (value.active) {
|
|
26520
|
+
const fill3 = node.value !== void 0 ? value.fillForValue(node.value) : neutralFill;
|
|
26521
|
+
const stroke3 = value.hue;
|
|
26522
|
+
const text2 = contrastText(
|
|
26523
|
+
fill3,
|
|
26524
|
+
palette.textOnFillLight,
|
|
26525
|
+
palette.textOnFillDark
|
|
26526
|
+
);
|
|
26527
|
+
return { fill: fill3, stroke: stroke3, text: text2 };
|
|
26528
|
+
}
|
|
26491
26529
|
const tagColor = resolveTagColor(
|
|
26492
26530
|
node.metadata,
|
|
26493
26531
|
[...tagGroups],
|
|
@@ -26596,25 +26634,65 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26596
26634
|
const sGroupLabelZone = sctx.structural(GROUP_LABEL_ZONE);
|
|
26597
26635
|
const sTitleFontSize = sctx.text(TITLE_FONT_SIZE);
|
|
26598
26636
|
const sTitleY = sctx.structural(TITLE_Y);
|
|
26637
|
+
const nodeValues = parsed.nodes.filter((n) => n.value !== void 0).map((n) => n.value);
|
|
26638
|
+
const hasRamp = nodeValues.length > 0;
|
|
26639
|
+
const allNonNegative = hasRamp && nodeValues.every((v) => v >= 0);
|
|
26640
|
+
const rampMin = allNonNegative ? 0 : Math.min(...nodeValues);
|
|
26641
|
+
const rampMax = Math.max(...nodeValues);
|
|
26642
|
+
const rampHue = resolveColor(parsed.boxMetricColor ?? "", palette) ?? palette.primary;
|
|
26643
|
+
const rampBase = isDark ? mix(palette.surface, palette.text, 28) : palette.bg;
|
|
26644
|
+
const fillForValue = (v) => {
|
|
26645
|
+
const t = rampMax > rampMin ? (v - rampMin) / (rampMax - rampMin) : 1;
|
|
26646
|
+
const pct = RAMP_FLOOR + Math.max(0, Math.min(1, t)) * (100 - RAMP_FLOOR);
|
|
26647
|
+
return mix(rampHue, rampBase, pct);
|
|
26648
|
+
};
|
|
26649
|
+
const VALUE_NAME = hasRamp ? parsed.boxMetric?.trim() || "Value" : null;
|
|
26650
|
+
const matchColorGroup = (v) => {
|
|
26651
|
+
const lv = v.trim().toLowerCase();
|
|
26652
|
+
if (lv === "" || lv === "none") return null;
|
|
26653
|
+
const tg = parsed.tagGroups.find((g) => g.name.toLowerCase() === lv);
|
|
26654
|
+
if (tg) return tg.name;
|
|
26655
|
+
if (lv === VALUE_NAME?.toLowerCase()) return VALUE_NAME;
|
|
26656
|
+
return v;
|
|
26657
|
+
};
|
|
26658
|
+
const override = activeTagGroup;
|
|
26659
|
+
let activeGroup;
|
|
26660
|
+
if (override !== void 0) {
|
|
26661
|
+
activeGroup = override === null ? null : matchColorGroup(override);
|
|
26662
|
+
} else if (parsed.options["active-tag"] !== void 0) {
|
|
26663
|
+
activeGroup = matchColorGroup(parsed.options["active-tag"]);
|
|
26664
|
+
} else {
|
|
26665
|
+
activeGroup = VALUE_NAME ?? (parsed.tagGroups.length > 0 ? parsed.tagGroups[0].name : null);
|
|
26666
|
+
}
|
|
26667
|
+
const activeIsValue = VALUE_NAME !== null && activeGroup === VALUE_NAME;
|
|
26668
|
+
const valueGroup = VALUE_NAME !== null ? {
|
|
26669
|
+
name: VALUE_NAME,
|
|
26670
|
+
entries: [],
|
|
26671
|
+
gradient: {
|
|
26672
|
+
min: rampMin,
|
|
26673
|
+
max: rampMax,
|
|
26674
|
+
hue: rampHue,
|
|
26675
|
+
base: rampBase
|
|
26676
|
+
}
|
|
26677
|
+
} : null;
|
|
26678
|
+
const legendGroups = [
|
|
26679
|
+
...valueGroup ? [valueGroup] : [],
|
|
26680
|
+
...parsed.tagGroups
|
|
26681
|
+
];
|
|
26599
26682
|
const reserveHasDescriptions = parsed.nodes.some(
|
|
26600
26683
|
(n) => n.description && n.description.length > 0
|
|
26601
26684
|
);
|
|
26602
|
-
const willRenderLegend =
|
|
26685
|
+
const willRenderLegend = legendGroups.length > 0 || reserveHasDescriptions && controlsHost !== "app";
|
|
26603
26686
|
const sLegendHeight = willRenderLegend ? sctx.structural(
|
|
26604
26687
|
getMaxLegendReservedHeight(
|
|
26605
26688
|
{
|
|
26606
|
-
groups:
|
|
26689
|
+
groups: legendGroups,
|
|
26607
26690
|
position: { placement: "top-center", titleRelation: "below-title" },
|
|
26608
26691
|
mode: exportMode ? "export" : "preview"
|
|
26609
26692
|
},
|
|
26610
26693
|
width
|
|
26611
26694
|
)
|
|
26612
26695
|
) : 0;
|
|
26613
|
-
const activeGroup = resolveActiveTagGroup(
|
|
26614
|
-
parsed.tagGroups,
|
|
26615
|
-
parsed.options["active-tag"],
|
|
26616
|
-
activeTagGroup
|
|
26617
|
-
);
|
|
26618
26696
|
const hidden = hiddenTagValues ?? parsed.initialHiddenTagValues;
|
|
26619
26697
|
const nodeMap = /* @__PURE__ */ new Map();
|
|
26620
26698
|
for (const node of parsed.nodes) nodeMap.set(node.label, node);
|
|
@@ -26625,7 +26703,7 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26625
26703
|
const hasAnyDescriptions = parsed.nodes.some(
|
|
26626
26704
|
(n) => n.description && n.description.length > 0
|
|
26627
26705
|
);
|
|
26628
|
-
const needsLegend =
|
|
26706
|
+
const needsLegend = legendGroups.length > 0 || hasAnyDescriptions && onToggleDescriptions;
|
|
26629
26707
|
const legendH = needsLegend ? sLegendHeight + 8 : 0;
|
|
26630
26708
|
const groupLabelsSet = new Set(layout.groups.map((g) => g.label));
|
|
26631
26709
|
let labelZoneExtension = 0;
|
|
@@ -26831,12 +26909,16 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26831
26909
|
activeGroup,
|
|
26832
26910
|
palette,
|
|
26833
26911
|
isDark,
|
|
26912
|
+
{ active: activeIsValue, hue: rampHue, fillForValue },
|
|
26834
26913
|
parsed.options["solid-fill"] === "on"
|
|
26835
26914
|
);
|
|
26836
26915
|
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);
|
|
26837
26916
|
for (const [key, val] of Object.entries(node.metadata)) {
|
|
26838
26917
|
nodeG.attr(`data-tag-${key.toLowerCase()}`, val.toLowerCase());
|
|
26839
26918
|
}
|
|
26919
|
+
if (node.value !== void 0) {
|
|
26920
|
+
nodeG.attr("data-value", node.value);
|
|
26921
|
+
}
|
|
26840
26922
|
if (onClickItem) {
|
|
26841
26923
|
nodeG.on("click", (event) => {
|
|
26842
26924
|
const target = event.target;
|
|
@@ -26908,6 +26990,22 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26908
26990
|
const tooltipText = fullText.length > 200 ? fullText.slice(0, 199) + "\u2026" : fullText;
|
|
26909
26991
|
nodeG.append("title").text(tooltipText);
|
|
26910
26992
|
}
|
|
26993
|
+
} else if (parsed.showValues && node.value !== void 0) {
|
|
26994
|
+
const valueLabel = parsed.boxMetric ? `${parsed.boxMetric}: ${node.value}` : String(node.value);
|
|
26995
|
+
const headerH = ln.height / 2;
|
|
26996
|
+
const sepY = -ln.height / 2 + headerH;
|
|
26997
|
+
const fitted = fitLabelToHeader(node.label, ln.width, 2);
|
|
26998
|
+
const labelLineH = fitted.fontSize * 1.3;
|
|
26999
|
+
const labelTotalH = fitted.lines.length * labelLineH;
|
|
27000
|
+
const headerCenterY = -ln.height / 2 + headerH / 2;
|
|
27001
|
+
for (let li = 0; li < fitted.lines.length; li++) {
|
|
27002
|
+
nodeG.append("text").attr("x", 0).attr(
|
|
27003
|
+
"y",
|
|
27004
|
+
headerCenterY - labelTotalH / 2 + labelLineH / 2 + li * labelLineH
|
|
27005
|
+
).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]);
|
|
27006
|
+
}
|
|
27007
|
+
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);
|
|
27008
|
+
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);
|
|
26911
27009
|
} else {
|
|
26912
27010
|
const maxLabelLines = Math.max(
|
|
26913
27011
|
2,
|
|
@@ -26920,11 +27018,22 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26920
27018
|
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]);
|
|
26921
27019
|
}
|
|
26922
27020
|
}
|
|
27021
|
+
if (parsed.showValues && node.value !== void 0 && desc && desc.length > 0 && !hideDescriptions) {
|
|
27022
|
+
const valueText = String(node.value);
|
|
27023
|
+
const padX = 6;
|
|
27024
|
+
const padY = 5;
|
|
27025
|
+
const bw = valueText.length * VALUE_FONT_SIZE * CHAR_WIDTH_RATIO2 + 8;
|
|
27026
|
+
const bh = VALUE_FONT_SIZE + 4;
|
|
27027
|
+
const bx = Math.max(-ln.width / 2 + 4, ln.width / 2 - bw - 4);
|
|
27028
|
+
const by = -ln.height / 2 + 4;
|
|
27029
|
+
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);
|
|
27030
|
+
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);
|
|
27031
|
+
}
|
|
26923
27032
|
}
|
|
26924
27033
|
const hasDescriptions = parsed.nodes.some(
|
|
26925
27034
|
(n) => n.description && n.description.length > 0
|
|
26926
27035
|
);
|
|
26927
|
-
const hasLegend =
|
|
27036
|
+
const hasLegend = legendGroups.length > 0 || hasDescriptions && controlsHost !== "app";
|
|
26928
27037
|
if (hasLegend) {
|
|
26929
27038
|
let controlsGroup;
|
|
26930
27039
|
if (hasDescriptions && (onToggleDescriptions || controlsHost === "app")) {
|
|
@@ -26942,7 +27051,7 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26942
27051
|
};
|
|
26943
27052
|
}
|
|
26944
27053
|
const legendConfig = {
|
|
26945
|
-
groups:
|
|
27054
|
+
groups: legendGroups,
|
|
26946
27055
|
position: { placement: "top-center", titleRelation: "below-title" },
|
|
26947
27056
|
mode: exportMode ? "export" : "preview",
|
|
26948
27057
|
// Keep inactive sibling tag groups visible as collapsed pills so the user
|
|
@@ -26997,7 +27106,7 @@ function renderBoxesAndLinesForExport(container, parsed, layout, palette, isDark
|
|
|
26997
27106
|
}
|
|
26998
27107
|
});
|
|
26999
27108
|
}
|
|
27000
|
-
var 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;
|
|
27109
|
+
var 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;
|
|
27001
27110
|
var init_renderer6 = __esm({
|
|
27002
27111
|
"src/boxes-and-lines/renderer.ts"() {
|
|
27003
27112
|
"use strict";
|
|
@@ -27006,12 +27115,13 @@ var init_renderer6 = __esm({
|
|
|
27006
27115
|
init_legend_layout();
|
|
27007
27116
|
init_title_constants();
|
|
27008
27117
|
init_color_utils();
|
|
27118
|
+
init_colors();
|
|
27009
27119
|
init_tag_groups();
|
|
27010
27120
|
init_inline_markdown();
|
|
27011
27121
|
init_wrapped_desc();
|
|
27012
27122
|
init_scaling();
|
|
27013
27123
|
DIAGRAM_PADDING6 = 20;
|
|
27014
|
-
NODE_FONT_SIZE =
|
|
27124
|
+
NODE_FONT_SIZE = 11;
|
|
27015
27125
|
MIN_NODE_FONT_SIZE = 9;
|
|
27016
27126
|
EDGE_LABEL_FONT_SIZE4 = 11;
|
|
27017
27127
|
EDGE_STROKE_WIDTH5 = 1.5;
|
|
@@ -27028,6 +27138,8 @@ var init_renderer6 = __esm({
|
|
|
27028
27138
|
GROUP_RX = 8;
|
|
27029
27139
|
GROUP_LABEL_FONT_SIZE = 14;
|
|
27030
27140
|
GROUP_LABEL_ZONE = 32;
|
|
27141
|
+
RAMP_FLOOR = 15;
|
|
27142
|
+
VALUE_FONT_SIZE = 11;
|
|
27031
27143
|
lineGeneratorLR = d3Shape4.line().x((d) => d.x).y((d) => d.y).curve(d3Shape4.curveBasis);
|
|
27032
27144
|
lineGeneratorTB = d3Shape4.line().x((d) => d.x).y((d) => d.y).curve(d3Shape4.curveBasis);
|
|
27033
27145
|
}
|
|
@@ -46969,7 +47081,11 @@ function resolveMap(parsed, data) {
|
|
|
46969
47081
|
if (bb && !isWholeSphere(bb)) containerBoxes.push(bb);
|
|
46970
47082
|
}
|
|
46971
47083
|
const containerUnion = unionExtent(containerBoxes, points);
|
|
46972
|
-
if (containerUnion)
|
|
47084
|
+
if (containerUnion)
|
|
47085
|
+
extent2 = pad(
|
|
47086
|
+
clampContainerToCluster(containerUnion, points),
|
|
47087
|
+
PAD_FRACTION
|
|
47088
|
+
);
|
|
46973
47089
|
}
|
|
46974
47090
|
if (isPoiOnly) {
|
|
46975
47091
|
const cx = (extent2[0][0] + extent2[1][0]) / 2;
|
|
@@ -47050,6 +47166,22 @@ function mostCommonCountry(regions, poiCountries) {
|
|
|
47050
47166
|
}
|
|
47051
47167
|
return best;
|
|
47052
47168
|
}
|
|
47169
|
+
function clampContainerToCluster(container, points) {
|
|
47170
|
+
const poi = unionExtent([], points);
|
|
47171
|
+
if (!poi) return container;
|
|
47172
|
+
let [[west, south], [east, north]] = container;
|
|
47173
|
+
const [[pWest, pSouth], [pEast, pNorth]] = poi;
|
|
47174
|
+
south = Math.max(south, pSouth - CONTAINER_OVERSHOOT_DEG);
|
|
47175
|
+
north = Math.min(north, pNorth + CONTAINER_OVERSHOOT_DEG);
|
|
47176
|
+
if (east <= 180 && pEast <= 180) {
|
|
47177
|
+
west = Math.max(west, pWest - CONTAINER_OVERSHOOT_DEG);
|
|
47178
|
+
east = Math.min(east, pEast + CONTAINER_OVERSHOOT_DEG);
|
|
47179
|
+
}
|
|
47180
|
+
return [
|
|
47181
|
+
[west, south],
|
|
47182
|
+
[east, north]
|
|
47183
|
+
];
|
|
47184
|
+
}
|
|
47053
47185
|
function pad(e, frac) {
|
|
47054
47186
|
const dLon = (e[1][0] - e[0][0]) * frac || 1;
|
|
47055
47187
|
const dLat = (e[1][1] - e[0][1]) * frac || 1;
|
|
@@ -47062,7 +47194,7 @@ function firstError(diags) {
|
|
|
47062
47194
|
const e = diags.find((d) => d.severity === "error");
|
|
47063
47195
|
return e ? formatDgmoError(e) : null;
|
|
47064
47196
|
}
|
|
47065
|
-
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;
|
|
47197
|
+
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;
|
|
47066
47198
|
var init_resolver2 = __esm({
|
|
47067
47199
|
"src/map/resolver.ts"() {
|
|
47068
47200
|
"use strict";
|
|
@@ -47075,6 +47207,7 @@ var init_resolver2 = __esm({
|
|
|
47075
47207
|
WORLD_LAT_SOUTH = -58;
|
|
47076
47208
|
WORLD_LAT_NORTH = 78;
|
|
47077
47209
|
POI_ZOOM_FLOOR_DEG = 7;
|
|
47210
|
+
CONTAINER_OVERSHOOT_DEG = 8;
|
|
47078
47211
|
US_NATIONAL_LON_SPAN = 48;
|
|
47079
47212
|
REGION_ALIASES = {
|
|
47080
47213
|
// Common everyday names → the Natural-Earth display name actually shipped.
|
|
@@ -47153,6 +47286,55 @@ var init_resolver2 = __esm({
|
|
|
47153
47286
|
}
|
|
47154
47287
|
});
|
|
47155
47288
|
|
|
47289
|
+
// src/map/legend-band.ts
|
|
47290
|
+
function mapLegendGroups(legend) {
|
|
47291
|
+
const ramp = legend.ramp;
|
|
47292
|
+
const scoreGroup = ramp ? {
|
|
47293
|
+
name: ramp.metric?.trim() || "Value",
|
|
47294
|
+
entries: [],
|
|
47295
|
+
gradient: {
|
|
47296
|
+
min: ramp.min,
|
|
47297
|
+
max: ramp.max,
|
|
47298
|
+
hue: ramp.hue,
|
|
47299
|
+
base: ramp.base
|
|
47300
|
+
}
|
|
47301
|
+
} : null;
|
|
47302
|
+
const tagGroups = legend.tagGroups.filter((g) => g.entries.length > 0).map((g) => ({ name: g.name, entries: [...g.entries] }));
|
|
47303
|
+
return [...scoreGroup ? [scoreGroup] : [], ...tagGroups];
|
|
47304
|
+
}
|
|
47305
|
+
function mapLegendConfig(groups, mode) {
|
|
47306
|
+
return {
|
|
47307
|
+
groups,
|
|
47308
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
47309
|
+
mode,
|
|
47310
|
+
showEmptyGroups: false,
|
|
47311
|
+
showInactivePills: true
|
|
47312
|
+
};
|
|
47313
|
+
}
|
|
47314
|
+
function mapLegendTop(hasTitle, hasSubtitle) {
|
|
47315
|
+
return (hasTitle ? TITLE_Y + TITLE_FONT_SIZE : 0) + (hasSubtitle ? TITLE_FONT_SIZE : 0) + LEGEND_TOP_GAP2;
|
|
47316
|
+
}
|
|
47317
|
+
function mapLegendBand(legend, opts) {
|
|
47318
|
+
if (!legend) return 0;
|
|
47319
|
+
const groups = mapLegendGroups(legend);
|
|
47320
|
+
if (groups.length === 0) return 0;
|
|
47321
|
+
const config = mapLegendConfig(groups, opts.mode);
|
|
47322
|
+
const state = { activeGroup: legend.activeGroup };
|
|
47323
|
+
const { height } = computeLegendLayout(config, state, opts.width);
|
|
47324
|
+
if (height <= 0) return 0;
|
|
47325
|
+
return mapLegendTop(opts.hasTitle, opts.hasSubtitle) + height + LEGEND_BOTTOM_GAP2;
|
|
47326
|
+
}
|
|
47327
|
+
var LEGEND_TOP_GAP2, LEGEND_BOTTOM_GAP2;
|
|
47328
|
+
var init_legend_band = __esm({
|
|
47329
|
+
"src/map/legend-band.ts"() {
|
|
47330
|
+
"use strict";
|
|
47331
|
+
init_legend_layout();
|
|
47332
|
+
init_title_constants();
|
|
47333
|
+
LEGEND_TOP_GAP2 = 8;
|
|
47334
|
+
LEGEND_BOTTOM_GAP2 = 10;
|
|
47335
|
+
}
|
|
47336
|
+
});
|
|
47337
|
+
|
|
47156
47338
|
// src/map/colorize.ts
|
|
47157
47339
|
function assignColors(isos, adjacency) {
|
|
47158
47340
|
const sorted = [...isos].sort();
|
|
@@ -47593,6 +47775,38 @@ function parsePathRings(d) {
|
|
|
47593
47775
|
if (cur.length) rings.push(cur);
|
|
47594
47776
|
return rings;
|
|
47595
47777
|
}
|
|
47778
|
+
function dropAntimeridianWrapSlivers(d, width, height) {
|
|
47779
|
+
const rings = parsePathRings(d);
|
|
47780
|
+
if (rings.length <= 1) return d;
|
|
47781
|
+
const eps = 0.75;
|
|
47782
|
+
const minArea = 3e-3 * width * height;
|
|
47783
|
+
const ringArea = (r) => {
|
|
47784
|
+
let s = 0;
|
|
47785
|
+
for (let i = 0; i < r.length; i++) {
|
|
47786
|
+
const a = r[i];
|
|
47787
|
+
const b = r[(i + 1) % r.length];
|
|
47788
|
+
s += a[0] * b[1] - b[0] * a[1];
|
|
47789
|
+
}
|
|
47790
|
+
return Math.abs(s) / 2;
|
|
47791
|
+
};
|
|
47792
|
+
const areas = rings.map(ringArea);
|
|
47793
|
+
const maxArea = Math.max(...areas);
|
|
47794
|
+
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;
|
|
47795
|
+
let dropped = false;
|
|
47796
|
+
const kept = rings.filter((r, idx) => {
|
|
47797
|
+
if (areas[idx] >= maxArea || areas[idx] >= minArea) return true;
|
|
47798
|
+
const touches = r.some((p, i) => onVEdge(p, r[(i + 1) % r.length]));
|
|
47799
|
+
if (touches) {
|
|
47800
|
+
dropped = true;
|
|
47801
|
+
return false;
|
|
47802
|
+
}
|
|
47803
|
+
return true;
|
|
47804
|
+
});
|
|
47805
|
+
if (!dropped) return d;
|
|
47806
|
+
return kept.map(
|
|
47807
|
+
(r) => r.map((p, i) => (i ? "L" : "M") + p[0] + "," + p[1]).join("") + "Z"
|
|
47808
|
+
).join("");
|
|
47809
|
+
}
|
|
47596
47810
|
function layoutMap(resolved, data, size, opts) {
|
|
47597
47811
|
const { palette, isDark } = opts;
|
|
47598
47812
|
const { width, height } = size;
|
|
@@ -47676,7 +47890,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47676
47890
|
const rampBase = isDark ? mix(palette.surface, palette.text, 28) : palette.bg;
|
|
47677
47891
|
const fillForValue = (s) => {
|
|
47678
47892
|
const t = rampMax > rampMin ? (s - rampMin) / (rampMax - rampMin) : 1;
|
|
47679
|
-
const pct =
|
|
47893
|
+
const pct = RAMP_FLOOR2 + Math.max(0, Math.min(1, t)) * (100 - RAMP_FLOOR2);
|
|
47680
47894
|
return mix(rampHue, rampBase, pct);
|
|
47681
47895
|
};
|
|
47682
47896
|
const tagFill = (tags, groupName) => {
|
|
@@ -47712,12 +47926,43 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47712
47926
|
return tagFill(r.tags, activeGroup) ?? neutralFill;
|
|
47713
47927
|
};
|
|
47714
47928
|
const regionById = new Map(resolved.regions.map((r) => [r.iso, r]));
|
|
47929
|
+
let legend = null;
|
|
47930
|
+
if (!resolved.directives.noLegend) {
|
|
47931
|
+
const legendTagGroups = resolved.tagGroups.map((g) => ({
|
|
47932
|
+
name: g.name,
|
|
47933
|
+
entries: g.entries.map((e) => ({ value: e.value, color: e.color }))
|
|
47934
|
+
}));
|
|
47935
|
+
if (legendTagGroups.length > 0 || hasRamp) {
|
|
47936
|
+
legend = {
|
|
47937
|
+
tagGroups: legendTagGroups,
|
|
47938
|
+
activeGroup,
|
|
47939
|
+
...hasRamp && {
|
|
47940
|
+
ramp: {
|
|
47941
|
+
...resolved.directives.regionMetric !== void 0 && {
|
|
47942
|
+
metric: resolved.directives.regionMetric
|
|
47943
|
+
},
|
|
47944
|
+
min: rampMin,
|
|
47945
|
+
max: rampMax,
|
|
47946
|
+
hue: rampHue,
|
|
47947
|
+
base: rampBase
|
|
47948
|
+
}
|
|
47949
|
+
}
|
|
47950
|
+
};
|
|
47951
|
+
}
|
|
47952
|
+
}
|
|
47715
47953
|
const TITLE_GAP2 = 16;
|
|
47716
47954
|
let topPad = FIT_PAD;
|
|
47717
47955
|
if (resolved.title && resolved.pois.length > 0) {
|
|
47718
47956
|
const bannerBottom = (resolved.subtitle ? TITLE_Y + TITLE_FONT_SIZE : TITLE_Y) + TITLE_FONT_SIZE / 2;
|
|
47719
47957
|
topPad = Math.max(FIT_PAD, bannerBottom + TITLE_GAP2);
|
|
47720
47958
|
}
|
|
47959
|
+
const legendBand = mapLegendBand(legend, {
|
|
47960
|
+
width,
|
|
47961
|
+
mode: opts.legendMode ?? "preview",
|
|
47962
|
+
hasTitle: Boolean(resolved.title),
|
|
47963
|
+
hasSubtitle: Boolean(resolved.subtitle)
|
|
47964
|
+
});
|
|
47965
|
+
if (legendBand > topPad) topPad = legendBand;
|
|
47721
47966
|
const fitBox = [
|
|
47722
47967
|
[FIT_PAD, topPad],
|
|
47723
47968
|
[
|
|
@@ -47735,10 +47980,11 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47735
47980
|
const by0 = cb[0][1];
|
|
47736
47981
|
const cw = cb[1][0] - bx0;
|
|
47737
47982
|
const ch = cb[1][1] - by0;
|
|
47738
|
-
const
|
|
47739
|
-
const
|
|
47740
|
-
const
|
|
47741
|
-
const
|
|
47983
|
+
const topReserve = resolved.title && resolved.pois.length > 0 || legendBand > 0 ? topPad : 0;
|
|
47984
|
+
const ox = 0;
|
|
47985
|
+
const oy = topReserve;
|
|
47986
|
+
const sx = cw > 0 ? width / cw : 1;
|
|
47987
|
+
const sy = ch > 0 ? (height - topReserve) / ch : 1;
|
|
47742
47988
|
stretchParams = { sx, sy, ox, oy, bx0, by0 };
|
|
47743
47989
|
const stretch = (x, y) => [
|
|
47744
47990
|
ox + (x - bx0) * sx,
|
|
@@ -48011,7 +48257,8 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
48011
48257
|
const r = regionById.get(iso);
|
|
48012
48258
|
const viewF = shouldCull ? cullFeatureToView(f) : dropFrameFillers(f);
|
|
48013
48259
|
if (!viewF) continue;
|
|
48014
|
-
const
|
|
48260
|
+
const raw = path(viewF) ?? "";
|
|
48261
|
+
const d = fitIsGlobal ? dropAntimeridianWrapSlivers(raw, width, height) : raw;
|
|
48015
48262
|
if (!d) continue;
|
|
48016
48263
|
const isThisLayer = r?.layer === layerKind;
|
|
48017
48264
|
const isForeign = layerKind === "country" && usContext && iso !== "US";
|
|
@@ -48028,6 +48275,9 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
48028
48275
|
} else {
|
|
48029
48276
|
label = f.properties?.name;
|
|
48030
48277
|
}
|
|
48278
|
+
const labelAnchor = WORLD_LABEL_ANCHORS[iso];
|
|
48279
|
+
const c = labelAnchor ? project(labelAnchor[0], labelAnchor[1]) : path.centroid(viewF);
|
|
48280
|
+
const hasCentroid = c != null && Number.isFinite(c[0]) && Number.isFinite(c[1]);
|
|
48031
48281
|
regions.push({
|
|
48032
48282
|
id: iso,
|
|
48033
48283
|
d,
|
|
@@ -48036,6 +48286,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
48036
48286
|
lineNumber,
|
|
48037
48287
|
layer,
|
|
48038
48288
|
...label !== void 0 && { label },
|
|
48289
|
+
...hasCentroid && { labelX: c[0], labelY: c[1] },
|
|
48039
48290
|
...isThisLayer && r.value !== void 0 && { value: r.value },
|
|
48040
48291
|
...isThisLayer && Object.keys(r.tags).length > 0 && { tags: r.tags }
|
|
48041
48292
|
});
|
|
@@ -48476,10 +48727,6 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
48476
48727
|
lineNumber
|
|
48477
48728
|
});
|
|
48478
48729
|
};
|
|
48479
|
-
const WORLD_LABEL_ANCHORS = {
|
|
48480
|
-
US: [-98.5, 39.5]
|
|
48481
|
-
// CONUS geographic centre (near Lebanon, Kansas)
|
|
48482
|
-
};
|
|
48483
48730
|
const REGION_LABEL_GAP = 2;
|
|
48484
48731
|
const regionLabelRect = (cx, cy, text) => {
|
|
48485
48732
|
const w = measureLegendText(text, FONT2) + 2 * REGION_LABEL_GAP;
|
|
@@ -48797,30 +49044,6 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
48797
49044
|
});
|
|
48798
49045
|
labels.push(...contextLabels);
|
|
48799
49046
|
}
|
|
48800
|
-
let legend = null;
|
|
48801
|
-
if (!resolved.directives.noLegend) {
|
|
48802
|
-
const tagGroups = resolved.tagGroups.map((g) => ({
|
|
48803
|
-
name: g.name,
|
|
48804
|
-
entries: g.entries.map((e) => ({ value: e.value, color: e.color }))
|
|
48805
|
-
}));
|
|
48806
|
-
if (tagGroups.length > 0 || hasRamp) {
|
|
48807
|
-
legend = {
|
|
48808
|
-
tagGroups,
|
|
48809
|
-
activeGroup,
|
|
48810
|
-
...hasRamp && {
|
|
48811
|
-
ramp: {
|
|
48812
|
-
...resolved.directives.regionMetric !== void 0 && {
|
|
48813
|
-
metric: resolved.directives.regionMetric
|
|
48814
|
-
},
|
|
48815
|
-
min: rampMin,
|
|
48816
|
-
max: rampMax,
|
|
48817
|
-
hue: rampHue,
|
|
48818
|
-
base: rampBase
|
|
48819
|
-
}
|
|
48820
|
-
}
|
|
48821
|
-
};
|
|
48822
|
-
}
|
|
48823
|
-
}
|
|
48824
49047
|
return {
|
|
48825
49048
|
width,
|
|
48826
49049
|
height,
|
|
@@ -48845,7 +49068,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
48845
49068
|
diagnostics: []
|
|
48846
49069
|
};
|
|
48847
49070
|
}
|
|
48848
|
-
var FIT_PAD,
|
|
49071
|
+
var 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;
|
|
48849
49072
|
var init_layout15 = __esm({
|
|
48850
49073
|
"src/map/layout.ts"() {
|
|
48851
49074
|
"use strict";
|
|
@@ -48856,15 +49079,20 @@ var init_layout15 = __esm({
|
|
|
48856
49079
|
init_label_layout();
|
|
48857
49080
|
init_legend_constants();
|
|
48858
49081
|
init_title_constants();
|
|
49082
|
+
init_legend_band();
|
|
48859
49083
|
init_context_labels();
|
|
48860
49084
|
FIT_PAD = 24;
|
|
48861
|
-
|
|
49085
|
+
RAMP_FLOOR2 = 15;
|
|
48862
49086
|
R_DEFAULT = 6;
|
|
48863
49087
|
R_MIN = 4;
|
|
48864
49088
|
R_MAX = 22;
|
|
48865
49089
|
W_MIN = 1.25;
|
|
48866
49090
|
W_MAX = 8;
|
|
48867
49091
|
FONT2 = 11;
|
|
49092
|
+
WORLD_LABEL_ANCHORS = {
|
|
49093
|
+
US: [-98.5, 39.5]
|
|
49094
|
+
// CONUS geographic centre (near Lebanon, Kansas)
|
|
49095
|
+
};
|
|
48868
49096
|
MAX_CLUSTER_EXTENT_FACTOR = 0.18;
|
|
48869
49097
|
MAX_COLUMN_ROWS = 7;
|
|
48870
49098
|
REGION_LABEL_HALO_RATIO = 4.5;
|
|
@@ -48878,9 +49106,9 @@ var init_layout15 = __esm({
|
|
|
48878
49106
|
COMPACT_WIDTH_PX = 480;
|
|
48879
49107
|
RELIEF_MIN_AREA = 12;
|
|
48880
49108
|
RELIEF_MIN_DIM = 2;
|
|
48881
|
-
RELIEF_HATCH_SPACING =
|
|
48882
|
-
RELIEF_HATCH_WIDTH = 0.
|
|
48883
|
-
RELIEF_HATCH_STRENGTH =
|
|
49109
|
+
RELIEF_HATCH_SPACING = 1.5;
|
|
49110
|
+
RELIEF_HATCH_WIDTH = 0.2;
|
|
49111
|
+
RELIEF_HATCH_STRENGTH = 26;
|
|
48884
49112
|
COASTLINE_RING_COUNT = 5;
|
|
48885
49113
|
COASTLINE_D0 = 16e-4;
|
|
48886
49114
|
COASTLINE_STEP = 28e-4;
|
|
@@ -48959,7 +49187,47 @@ function ringToPath(ring) {
|
|
|
48959
49187
|
d += (i ? "L" : "M") + ring[i][0] + "," + ring[i][1];
|
|
48960
49188
|
return d + "Z";
|
|
48961
49189
|
}
|
|
48962
|
-
function
|
|
49190
|
+
function polylineToPath(pts) {
|
|
49191
|
+
let d = "";
|
|
49192
|
+
for (let i = 0; i < pts.length; i++)
|
|
49193
|
+
d += (i ? "L" : "M") + pts[i][0] + "," + pts[i][1];
|
|
49194
|
+
return d;
|
|
49195
|
+
}
|
|
49196
|
+
function ringToCoastPaths(ring, frame) {
|
|
49197
|
+
if (!frame) return [ringToPath(ring)];
|
|
49198
|
+
const n = ring.length;
|
|
49199
|
+
const eps = 0.75;
|
|
49200
|
+
const onL = (x) => Math.abs(x) <= eps;
|
|
49201
|
+
const onR = (x) => Math.abs(x - frame.w) <= eps;
|
|
49202
|
+
const onT = (y) => Math.abs(y) <= eps;
|
|
49203
|
+
const onB = (y) => Math.abs(y - frame.h) <= eps;
|
|
49204
|
+
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]);
|
|
49205
|
+
let firstBreak = -1;
|
|
49206
|
+
for (let i = 0; i < n; i++)
|
|
49207
|
+
if (isFrameEdge(ring[i], ring[(i + 1) % n])) {
|
|
49208
|
+
firstBreak = i;
|
|
49209
|
+
break;
|
|
49210
|
+
}
|
|
49211
|
+
if (firstBreak === -1) return [ringToPath(ring)];
|
|
49212
|
+
const paths = [];
|
|
49213
|
+
let cur = [];
|
|
49214
|
+
const start = (firstBreak + 1) % n;
|
|
49215
|
+
for (let k = 0; k < n; k++) {
|
|
49216
|
+
const i = (start + k) % n;
|
|
49217
|
+
const a = ring[i];
|
|
49218
|
+
const b = ring[(i + 1) % n];
|
|
49219
|
+
if (isFrameEdge(a, b)) {
|
|
49220
|
+
if (cur.length >= 2) paths.push(polylineToPath(cur));
|
|
49221
|
+
cur = [];
|
|
49222
|
+
continue;
|
|
49223
|
+
}
|
|
49224
|
+
if (cur.length === 0) cur.push(a);
|
|
49225
|
+
cur.push(b);
|
|
49226
|
+
}
|
|
49227
|
+
if (cur.length >= 2) paths.push(polylineToPath(cur));
|
|
49228
|
+
return paths;
|
|
49229
|
+
}
|
|
49230
|
+
function coastlineOuterRings(regions, minExtent, frame) {
|
|
48963
49231
|
const paths = [];
|
|
48964
49232
|
for (const r of regions) {
|
|
48965
49233
|
const rings = parsePathRings(r.d);
|
|
@@ -48982,7 +49250,7 @@ function coastlineOuterRings(regions, minExtent) {
|
|
|
48982
49250
|
for (let j = 0; j < rings.length; j++)
|
|
48983
49251
|
if (j !== i && pointInRing2(fx, fy, rings[j])) depth++;
|
|
48984
49252
|
if (depth % 2 === 1) continue;
|
|
48985
|
-
paths.push(
|
|
49253
|
+
paths.push(...ringToCoastPaths(ring, frame));
|
|
48986
49254
|
}
|
|
48987
49255
|
}
|
|
48988
49256
|
return paths;
|
|
@@ -49012,6 +49280,9 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
49012
49280
|
// stretch-distorting. The in-app preview pane passes no exportDims → unset →
|
|
49013
49281
|
// keeps the global stretch-fill.
|
|
49014
49282
|
preferContain: exportDims?.preferContain ?? false,
|
|
49283
|
+
// Reserve the legend band for the mode actually drawn below (export shows
|
|
49284
|
+
// only the active group; preview keeps the inactive pills).
|
|
49285
|
+
legendMode: exportDims ? "export" : "preview",
|
|
49015
49286
|
...activeGroupOverride !== void 0 && {
|
|
49016
49287
|
activeGroup: activeGroupOverride
|
|
49017
49288
|
}
|
|
@@ -49026,6 +49297,10 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
49026
49297
|
const drawRegion = (g, r, strokeWidth) => {
|
|
49027
49298
|
const p = g.append("path").attr("d", r.d).attr("fill", r.fill).attr("stroke", r.stroke).attr("stroke-width", strokeWidth);
|
|
49028
49299
|
if (r.label) p.attr("data-region-name", r.label);
|
|
49300
|
+
if (r.id && r.id !== "lake") p.attr("data-iso", r.id);
|
|
49301
|
+
if (r.labelX !== void 0 && r.labelY !== void 0) {
|
|
49302
|
+
p.attr("data-label-x", r.labelX).attr("data-label-y", r.labelY);
|
|
49303
|
+
}
|
|
49029
49304
|
if (r.layer !== "base") {
|
|
49030
49305
|
p.classed("dgmo-map-region", true).attr("data-region", r.id);
|
|
49031
49306
|
if (r.value !== void 0) p.attr("data-value", r.value);
|
|
@@ -49055,7 +49330,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
49055
49330
|
const landClip = defs.append("clipPath").attr("id", landClipId);
|
|
49056
49331
|
for (const r of layout.regions)
|
|
49057
49332
|
if (r.id !== "lake") landClip.append("path").attr("d", r.d);
|
|
49058
|
-
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");
|
|
49333
|
+
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");
|
|
49059
49334
|
for (let y = h.spacing; y < height; y += h.spacing) {
|
|
49060
49335
|
gRelief.append("line").attr("x1", 0).attr("y1", y).attr("x2", width).attr("y2", y);
|
|
49061
49336
|
}
|
|
@@ -49076,10 +49351,16 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
49076
49351
|
mask.append("path").attr("d", d).attr("fill", "black").attr("stroke", "black").attr("stroke-width", 2 * reach).attr("stroke-linejoin", "round");
|
|
49077
49352
|
}
|
|
49078
49353
|
}
|
|
49079
|
-
const gWater = svg.append("g").attr("class", "dgmo-map-water-lines").attr("fill", "none").attr("mask", `url(#${maskId})`);
|
|
49354
|
+
const gWater = svg.append("g").attr("class", "dgmo-map-water-lines").attr("fill", "none").style("pointer-events", "none").attr("mask", `url(#${maskId})`);
|
|
49080
49355
|
appendWaterLines(
|
|
49081
49356
|
gWater,
|
|
49082
|
-
|
|
49357
|
+
// Pass the canvas frame so edges collinear with it (the antimeridian on a
|
|
49358
|
+
// world map, regional clipExtent cuts) don't get ringed as fake coast —
|
|
49359
|
+
// land runs cleanly to the render-area edge.
|
|
49360
|
+
coastlineOuterRings(layout.regions, cs.minExtent, {
|
|
49361
|
+
w: width,
|
|
49362
|
+
h: height
|
|
49363
|
+
}),
|
|
49083
49364
|
cs,
|
|
49084
49365
|
layout.background
|
|
49085
49366
|
);
|
|
@@ -49093,7 +49374,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
49093
49374
|
gWater.append("path").attr("d", ds.join(" ")).attr("stroke", stroke2).attr("stroke-width", 0.5).attr("stroke-linejoin", "round");
|
|
49094
49375
|
}
|
|
49095
49376
|
if (layout.rivers.length) {
|
|
49096
|
-
const gRivers = svg.append("g").attr("class", "dgmo-map-rivers").attr("fill", "none");
|
|
49377
|
+
const gRivers = svg.append("g").attr("class", "dgmo-map-rivers").attr("fill", "none").style("pointer-events", "none");
|
|
49097
49378
|
for (const r of layout.rivers) {
|
|
49098
49379
|
gRivers.append("path").attr("d", r.d).attr("stroke", r.color).attr("stroke-width", r.width).attr("stroke-linecap", "round").attr("stroke-linejoin", "round");
|
|
49099
49380
|
}
|
|
@@ -49134,7 +49415,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
49134
49415
|
const d = box.points.map((p, i) => `${i ? "L" : "M"}${p[0]},${p[1]}`).join("") + "Z";
|
|
49135
49416
|
clip.append("path").attr("d", d);
|
|
49136
49417
|
}
|
|
49137
|
-
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})`);
|
|
49418
|
+
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})`);
|
|
49138
49419
|
appendWaterLines(
|
|
49139
49420
|
gInsetWater,
|
|
49140
49421
|
coastlineOuterRings(layout.insetRegions, cs.minExtent),
|
|
@@ -49293,30 +49574,12 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
49293
49574
|
if (layout.legend) {
|
|
49294
49575
|
const legendY = (layout.title ? TITLE_Y + TITLE_FONT_SIZE : 0) + (layout.subtitle ? TITLE_FONT_SIZE : 0) + 8;
|
|
49295
49576
|
const legendG = svg.append("g").attr("class", "dgmo-map-legend").attr("transform", `translate(0, ${legendY})`);
|
|
49296
|
-
const
|
|
49297
|
-
const scoreGroup = ramp ? {
|
|
49298
|
-
name: ramp.metric?.trim() || "Value",
|
|
49299
|
-
entries: [],
|
|
49300
|
-
gradient: {
|
|
49301
|
-
min: ramp.min,
|
|
49302
|
-
max: ramp.max,
|
|
49303
|
-
hue: ramp.hue,
|
|
49304
|
-
base: ramp.base
|
|
49305
|
-
}
|
|
49306
|
-
} : null;
|
|
49307
|
-
const tagGroups = layout.legend.tagGroups.filter((g) => g.entries.length > 0).map((g) => ({ name: g.name, entries: [...g.entries] }));
|
|
49308
|
-
const groups = [...scoreGroup ? [scoreGroup] : [], ...tagGroups];
|
|
49577
|
+
const groups = mapLegendGroups(layout.legend);
|
|
49309
49578
|
if (groups.length > 0) {
|
|
49310
|
-
const config =
|
|
49579
|
+
const config = mapLegendConfig(
|
|
49311
49580
|
groups,
|
|
49312
|
-
|
|
49313
|
-
|
|
49314
|
-
showEmptyGroups: false,
|
|
49315
|
-
// Keep inactive siblings visible as pills so the user can click to flip
|
|
49316
|
-
// the active colouring dimension (preview only — export shows just the
|
|
49317
|
-
// active group).
|
|
49318
|
-
showInactivePills: true
|
|
49319
|
-
};
|
|
49581
|
+
exportDims ? "export" : "preview"
|
|
49582
|
+
);
|
|
49320
49583
|
const state = { activeGroup: layout.legend.activeGroup };
|
|
49321
49584
|
renderLegendD3(legendG, config, state, palette, isDark, void 0, width);
|
|
49322
49585
|
}
|
|
@@ -49360,6 +49623,7 @@ var init_renderer16 = __esm({
|
|
|
49360
49623
|
init_title_constants();
|
|
49361
49624
|
init_color_utils();
|
|
49362
49625
|
init_legend_d3();
|
|
49626
|
+
init_legend_band();
|
|
49363
49627
|
init_layout15();
|
|
49364
49628
|
LABEL_FONT = 11;
|
|
49365
49629
|
}
|
|
@@ -49381,9 +49645,10 @@ function mapContentAspect(resolved, data, ref = REF) {
|
|
|
49381
49645
|
const aspect = w / h;
|
|
49382
49646
|
return Number.isFinite(aspect) && aspect > 0 ? aspect : FALLBACK_ASPECT;
|
|
49383
49647
|
}
|
|
49384
|
-
function mapExportDimensions(resolved, data, baseWidth = 1200) {
|
|
49385
|
-
const
|
|
49386
|
-
const
|
|
49648
|
+
function mapExportDimensions(resolved, data, baseWidth = 1200, aspectOverride) {
|
|
49649
|
+
const useOverride = aspectOverride !== void 0 && Number.isFinite(aspectOverride) && aspectOverride > 0;
|
|
49650
|
+
const raw = useOverride ? aspectOverride : mapContentAspect(resolved, data);
|
|
49651
|
+
const clamped = useOverride ? raw : Math.max(ASPECT_MIN, Math.min(ASPECT_MAX, raw));
|
|
49387
49652
|
const width = baseWidth;
|
|
49388
49653
|
let height = Math.round(width / clamped);
|
|
49389
49654
|
let chromeReserve = 0;
|
|
@@ -49396,7 +49661,7 @@ function mapExportDimensions(resolved, data, baseWidth = 1200) {
|
|
|
49396
49661
|
height = Math.round(chromeReserve + MIN_MAP_BAND);
|
|
49397
49662
|
floored = true;
|
|
49398
49663
|
}
|
|
49399
|
-
const preferContain = clamped !== raw || floored;
|
|
49664
|
+
const preferContain = useOverride ? floored : clamped !== raw || floored;
|
|
49400
49665
|
return { width, height, preferContain };
|
|
49401
49666
|
}
|
|
49402
49667
|
var FIT_PAD2, TITLE_GAP, ASPECT_MAX, ASPECT_MIN, MIN_MAP_BAND, FALLBACK_ASPECT, REF;
|
|
@@ -55106,7 +55371,6 @@ function renderTimelineTagLegendOverlay(container, parsed, palette, isDark, setu
|
|
|
55106
55371
|
function renderTimelineHorizontalTimeSort(container, parsed, palette, isDark, setup, hovers, onClickItem, _exportDims, _swimlaneTagGroup, _activeTagGroup, _onTagStateChange, _viewMode) {
|
|
55107
55372
|
const {
|
|
55108
55373
|
width,
|
|
55109
|
-
height,
|
|
55110
55374
|
tooltip,
|
|
55111
55375
|
solid,
|
|
55112
55376
|
textColor,
|
|
@@ -55155,10 +55419,11 @@ function renderTimelineHorizontalTimeSort(container, parsed, palette, isDark, se
|
|
|
55155
55419
|
const markerLabelY = markerReserve ? -(topScaleH + MARKER_ROW_H / 2) : 0;
|
|
55156
55420
|
const eraLabelY = eraReserve ? -(topScaleH + markerReserve + ERA_ROW_H / 2) : 0;
|
|
55157
55421
|
const innerWidth = width - margin.left - margin.right;
|
|
55158
|
-
const
|
|
55159
|
-
const
|
|
55422
|
+
const rowH = ctx.structural(28);
|
|
55423
|
+
const innerHeight = rowH * sorted.length;
|
|
55424
|
+
const usedHeight = margin.top + innerHeight + margin.bottom;
|
|
55160
55425
|
const xScale = d3Scale2.scaleLinear().domain([minDate - datePadding, maxDate + datePadding]).range([0, innerWidth]);
|
|
55161
|
-
const svg = d3Selection23.select(container).append("svg").attr("width", width).attr("height",
|
|
55426
|
+
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);
|
|
55162
55427
|
if (ctx.isBelowFloor) {
|
|
55163
55428
|
svg.attr("width", "100%");
|
|
55164
55429
|
}
|
|
@@ -57735,7 +58000,12 @@ async function renderForExport(content, theme, palette, viewState, options) {
|
|
|
57735
58000
|
}
|
|
57736
58001
|
}
|
|
57737
58002
|
const mapResolved = resolveMap2(mapParsed, mapData);
|
|
57738
|
-
const dims2 = mapExportDimensions2(
|
|
58003
|
+
const dims2 = mapExportDimensions2(
|
|
58004
|
+
mapResolved,
|
|
58005
|
+
mapData,
|
|
58006
|
+
EXPORT_WIDTH,
|
|
58007
|
+
options?.mapAspect
|
|
58008
|
+
);
|
|
57739
58009
|
const container2 = createExportContainer(dims2.width, dims2.height);
|
|
57740
58010
|
renderMapForExport2(
|
|
57741
58011
|
container2,
|
|
@@ -60244,7 +60514,9 @@ var COMPLETION_REGISTRY = /* @__PURE__ */ new Map([
|
|
|
60244
60514
|
withGlobals({
|
|
60245
60515
|
direction: { description: "Layout direction", values: ["LR", "TB"] },
|
|
60246
60516
|
"active-tag": { description: "Active tag group name" },
|
|
60247
|
-
hide: { description: "Hide tag:value pairs" }
|
|
60517
|
+
hide: { description: "Hide tag:value pairs" },
|
|
60518
|
+
"box-metric": { description: "Metric label for the value ramp" },
|
|
60519
|
+
"show-values": { description: "Print box values as text" }
|
|
60248
60520
|
})
|
|
60249
60521
|
],
|
|
60250
60522
|
[
|
|
@@ -60472,13 +60744,10 @@ var PIPE_METADATA = /* @__PURE__ */ new Map([
|
|
|
60472
60744
|
"boxes-and-lines",
|
|
60473
60745
|
{
|
|
60474
60746
|
node: {
|
|
60475
|
-
description: { description: "Node description text" }
|
|
60747
|
+
description: { description: "Node description text" },
|
|
60748
|
+
value: { description: "Numeric value for the metric ramp" }
|
|
60476
60749
|
},
|
|
60477
|
-
edge: {
|
|
60478
|
-
width: { description: "Edge stroke width in pixels" },
|
|
60479
|
-
split: { description: "Traffic split percentage" },
|
|
60480
|
-
fanout: { description: "Fanout multiplier (integer >= 1)" }
|
|
60481
|
-
}
|
|
60750
|
+
edge: {}
|
|
60482
60751
|
}
|
|
60483
60752
|
],
|
|
60484
60753
|
[
|