@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/auto.cjs
CHANGED
|
@@ -820,9 +820,7 @@ var init_reserved_key_registry = __esm({
|
|
|
820
820
|
BOXES_AND_LINES_REGISTRY = staticRegistry([
|
|
821
821
|
"color",
|
|
822
822
|
"description",
|
|
823
|
-
"
|
|
824
|
-
"split",
|
|
825
|
-
"fanout"
|
|
823
|
+
"value"
|
|
826
824
|
]);
|
|
827
825
|
TIMELINE_REGISTRY = staticRegistry([
|
|
828
826
|
"color",
|
|
@@ -16824,6 +16822,21 @@ function parseBoxesAndLines(content) {
|
|
|
16824
16822
|
}
|
|
16825
16823
|
continue;
|
|
16826
16824
|
}
|
|
16825
|
+
if (!contentStarted) {
|
|
16826
|
+
const metricMatch = trimmed.match(/^box-metric\s+(.+)$/i);
|
|
16827
|
+
if (metricMatch) {
|
|
16828
|
+
const { label, colorName } = peelTrailingColorName(
|
|
16829
|
+
metricMatch[1].trim()
|
|
16830
|
+
);
|
|
16831
|
+
result.boxMetric = label;
|
|
16832
|
+
if (colorName !== void 0) result.boxMetricColor = colorName;
|
|
16833
|
+
continue;
|
|
16834
|
+
}
|
|
16835
|
+
if (/^show-values$/i.test(trimmed)) {
|
|
16836
|
+
result.showValues = true;
|
|
16837
|
+
continue;
|
|
16838
|
+
}
|
|
16839
|
+
}
|
|
16827
16840
|
if (!contentStarted) {
|
|
16828
16841
|
const optMatch = trimmed.match(OPTION_NOCOLON_RE);
|
|
16829
16842
|
if (optMatch) {
|
|
@@ -17202,6 +17215,19 @@ function parseNodeLine(trimmed, lineNum, metaAliasMap, diagnostics, nameAliasMap
|
|
|
17202
17215
|
description = [metadata["description"]];
|
|
17203
17216
|
delete metadata["description"];
|
|
17204
17217
|
}
|
|
17218
|
+
let value;
|
|
17219
|
+
if (metadata["value"] !== void 0) {
|
|
17220
|
+
const raw = metadata["value"];
|
|
17221
|
+
const num = Number(raw);
|
|
17222
|
+
if (Number.isFinite(num)) {
|
|
17223
|
+
value = num;
|
|
17224
|
+
} else {
|
|
17225
|
+
diagnostics.push(
|
|
17226
|
+
makeDgmoError(lineNum, `value must be a number (got "${raw}")`, "error")
|
|
17227
|
+
);
|
|
17228
|
+
}
|
|
17229
|
+
delete metadata["value"];
|
|
17230
|
+
}
|
|
17205
17231
|
if (split.alias) {
|
|
17206
17232
|
nameAliasMap?.set(normalizeName(split.alias), label);
|
|
17207
17233
|
}
|
|
@@ -17210,7 +17236,8 @@ function parseNodeLine(trimmed, lineNum, metaAliasMap, diagnostics, nameAliasMap
|
|
|
17210
17236
|
label,
|
|
17211
17237
|
lineNumber: lineNum,
|
|
17212
17238
|
metadata,
|
|
17213
|
-
...description !== void 0 && { description }
|
|
17239
|
+
...description !== void 0 && { description },
|
|
17240
|
+
...value !== void 0 && { value }
|
|
17214
17241
|
};
|
|
17215
17242
|
}
|
|
17216
17243
|
function splitTargetAndMeta(rest, metaAliasMap) {
|
|
@@ -26330,7 +26357,18 @@ function fitLabelToHeader(label, nodeWidth, maxLines) {
|
|
|
26330
26357
|
const truncated = label.length > maxChars ? label.slice(0, maxChars - 1) + "\u2026" : label;
|
|
26331
26358
|
return { lines: [truncated], fontSize: MIN_NODE_FONT_SIZE };
|
|
26332
26359
|
}
|
|
26333
|
-
function nodeColors(node, tagGroups, activeGroupName, palette, isDark, solid) {
|
|
26360
|
+
function nodeColors(node, tagGroups, activeGroupName, palette, isDark, value, solid) {
|
|
26361
|
+
const neutralFill = mix(palette.bg, palette.text, isDark ? 90 : 95);
|
|
26362
|
+
if (value.active) {
|
|
26363
|
+
const fill3 = node.value !== void 0 ? value.fillForValue(node.value) : neutralFill;
|
|
26364
|
+
const stroke3 = value.hue;
|
|
26365
|
+
const text2 = contrastText(
|
|
26366
|
+
fill3,
|
|
26367
|
+
palette.textOnFillLight,
|
|
26368
|
+
palette.textOnFillDark
|
|
26369
|
+
);
|
|
26370
|
+
return { fill: fill3, stroke: stroke3, text: text2 };
|
|
26371
|
+
}
|
|
26334
26372
|
const tagColor = resolveTagColor(
|
|
26335
26373
|
node.metadata,
|
|
26336
26374
|
[...tagGroups],
|
|
@@ -26439,25 +26477,65 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26439
26477
|
const sGroupLabelZone = sctx.structural(GROUP_LABEL_ZONE);
|
|
26440
26478
|
const sTitleFontSize = sctx.text(TITLE_FONT_SIZE);
|
|
26441
26479
|
const sTitleY = sctx.structural(TITLE_Y);
|
|
26480
|
+
const nodeValues = parsed.nodes.filter((n) => n.value !== void 0).map((n) => n.value);
|
|
26481
|
+
const hasRamp = nodeValues.length > 0;
|
|
26482
|
+
const allNonNegative = hasRamp && nodeValues.every((v) => v >= 0);
|
|
26483
|
+
const rampMin = allNonNegative ? 0 : Math.min(...nodeValues);
|
|
26484
|
+
const rampMax = Math.max(...nodeValues);
|
|
26485
|
+
const rampHue = resolveColor(parsed.boxMetricColor ?? "", palette) ?? palette.primary;
|
|
26486
|
+
const rampBase = isDark ? mix(palette.surface, palette.text, 28) : palette.bg;
|
|
26487
|
+
const fillForValue = (v) => {
|
|
26488
|
+
const t = rampMax > rampMin ? (v - rampMin) / (rampMax - rampMin) : 1;
|
|
26489
|
+
const pct = RAMP_FLOOR + Math.max(0, Math.min(1, t)) * (100 - RAMP_FLOOR);
|
|
26490
|
+
return mix(rampHue, rampBase, pct);
|
|
26491
|
+
};
|
|
26492
|
+
const VALUE_NAME = hasRamp ? parsed.boxMetric?.trim() || "Value" : null;
|
|
26493
|
+
const matchColorGroup = (v) => {
|
|
26494
|
+
const lv = v.trim().toLowerCase();
|
|
26495
|
+
if (lv === "" || lv === "none") return null;
|
|
26496
|
+
const tg = parsed.tagGroups.find((g) => g.name.toLowerCase() === lv);
|
|
26497
|
+
if (tg) return tg.name;
|
|
26498
|
+
if (lv === VALUE_NAME?.toLowerCase()) return VALUE_NAME;
|
|
26499
|
+
return v;
|
|
26500
|
+
};
|
|
26501
|
+
const override = activeTagGroup;
|
|
26502
|
+
let activeGroup;
|
|
26503
|
+
if (override !== void 0) {
|
|
26504
|
+
activeGroup = override === null ? null : matchColorGroup(override);
|
|
26505
|
+
} else if (parsed.options["active-tag"] !== void 0) {
|
|
26506
|
+
activeGroup = matchColorGroup(parsed.options["active-tag"]);
|
|
26507
|
+
} else {
|
|
26508
|
+
activeGroup = VALUE_NAME ?? (parsed.tagGroups.length > 0 ? parsed.tagGroups[0].name : null);
|
|
26509
|
+
}
|
|
26510
|
+
const activeIsValue = VALUE_NAME !== null && activeGroup === VALUE_NAME;
|
|
26511
|
+
const valueGroup = VALUE_NAME !== null ? {
|
|
26512
|
+
name: VALUE_NAME,
|
|
26513
|
+
entries: [],
|
|
26514
|
+
gradient: {
|
|
26515
|
+
min: rampMin,
|
|
26516
|
+
max: rampMax,
|
|
26517
|
+
hue: rampHue,
|
|
26518
|
+
base: rampBase
|
|
26519
|
+
}
|
|
26520
|
+
} : null;
|
|
26521
|
+
const legendGroups = [
|
|
26522
|
+
...valueGroup ? [valueGroup] : [],
|
|
26523
|
+
...parsed.tagGroups
|
|
26524
|
+
];
|
|
26442
26525
|
const reserveHasDescriptions = parsed.nodes.some(
|
|
26443
26526
|
(n) => n.description && n.description.length > 0
|
|
26444
26527
|
);
|
|
26445
|
-
const willRenderLegend =
|
|
26528
|
+
const willRenderLegend = legendGroups.length > 0 || reserveHasDescriptions && controlsHost !== "app";
|
|
26446
26529
|
const sLegendHeight = willRenderLegend ? sctx.structural(
|
|
26447
26530
|
getMaxLegendReservedHeight(
|
|
26448
26531
|
{
|
|
26449
|
-
groups:
|
|
26532
|
+
groups: legendGroups,
|
|
26450
26533
|
position: { placement: "top-center", titleRelation: "below-title" },
|
|
26451
26534
|
mode: exportMode ? "export" : "preview"
|
|
26452
26535
|
},
|
|
26453
26536
|
width
|
|
26454
26537
|
)
|
|
26455
26538
|
) : 0;
|
|
26456
|
-
const activeGroup = resolveActiveTagGroup(
|
|
26457
|
-
parsed.tagGroups,
|
|
26458
|
-
parsed.options["active-tag"],
|
|
26459
|
-
activeTagGroup
|
|
26460
|
-
);
|
|
26461
26539
|
const hidden = hiddenTagValues ?? parsed.initialHiddenTagValues;
|
|
26462
26540
|
const nodeMap = /* @__PURE__ */ new Map();
|
|
26463
26541
|
for (const node of parsed.nodes) nodeMap.set(node.label, node);
|
|
@@ -26468,7 +26546,7 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26468
26546
|
const hasAnyDescriptions = parsed.nodes.some(
|
|
26469
26547
|
(n) => n.description && n.description.length > 0
|
|
26470
26548
|
);
|
|
26471
|
-
const needsLegend =
|
|
26549
|
+
const needsLegend = legendGroups.length > 0 || hasAnyDescriptions && onToggleDescriptions;
|
|
26472
26550
|
const legendH = needsLegend ? sLegendHeight + 8 : 0;
|
|
26473
26551
|
const groupLabelsSet = new Set(layout.groups.map((g) => g.label));
|
|
26474
26552
|
let labelZoneExtension = 0;
|
|
@@ -26674,12 +26752,16 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26674
26752
|
activeGroup,
|
|
26675
26753
|
palette,
|
|
26676
26754
|
isDark,
|
|
26755
|
+
{ active: activeIsValue, hue: rampHue, fillForValue },
|
|
26677
26756
|
parsed.options["solid-fill"] === "on"
|
|
26678
26757
|
);
|
|
26679
26758
|
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);
|
|
26680
26759
|
for (const [key, val] of Object.entries(node.metadata)) {
|
|
26681
26760
|
nodeG.attr(`data-tag-${key.toLowerCase()}`, val.toLowerCase());
|
|
26682
26761
|
}
|
|
26762
|
+
if (node.value !== void 0) {
|
|
26763
|
+
nodeG.attr("data-value", node.value);
|
|
26764
|
+
}
|
|
26683
26765
|
if (onClickItem) {
|
|
26684
26766
|
nodeG.on("click", (event) => {
|
|
26685
26767
|
const target = event.target;
|
|
@@ -26751,6 +26833,22 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26751
26833
|
const tooltipText = fullText.length > 200 ? fullText.slice(0, 199) + "\u2026" : fullText;
|
|
26752
26834
|
nodeG.append("title").text(tooltipText);
|
|
26753
26835
|
}
|
|
26836
|
+
} else if (parsed.showValues && node.value !== void 0) {
|
|
26837
|
+
const valueLabel = parsed.boxMetric ? `${parsed.boxMetric}: ${node.value}` : String(node.value);
|
|
26838
|
+
const headerH = ln.height / 2;
|
|
26839
|
+
const sepY = -ln.height / 2 + headerH;
|
|
26840
|
+
const fitted = fitLabelToHeader(node.label, ln.width, 2);
|
|
26841
|
+
const labelLineH = fitted.fontSize * 1.3;
|
|
26842
|
+
const labelTotalH = fitted.lines.length * labelLineH;
|
|
26843
|
+
const headerCenterY = -ln.height / 2 + headerH / 2;
|
|
26844
|
+
for (let li = 0; li < fitted.lines.length; li++) {
|
|
26845
|
+
nodeG.append("text").attr("x", 0).attr(
|
|
26846
|
+
"y",
|
|
26847
|
+
headerCenterY - labelTotalH / 2 + labelLineH / 2 + li * labelLineH
|
|
26848
|
+
).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]);
|
|
26849
|
+
}
|
|
26850
|
+
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);
|
|
26851
|
+
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);
|
|
26754
26852
|
} else {
|
|
26755
26853
|
const maxLabelLines = Math.max(
|
|
26756
26854
|
2,
|
|
@@ -26763,11 +26861,22 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26763
26861
|
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]);
|
|
26764
26862
|
}
|
|
26765
26863
|
}
|
|
26864
|
+
if (parsed.showValues && node.value !== void 0 && desc && desc.length > 0 && !hideDescriptions) {
|
|
26865
|
+
const valueText = String(node.value);
|
|
26866
|
+
const padX = 6;
|
|
26867
|
+
const padY = 5;
|
|
26868
|
+
const bw = valueText.length * VALUE_FONT_SIZE * CHAR_WIDTH_RATIO2 + 8;
|
|
26869
|
+
const bh = VALUE_FONT_SIZE + 4;
|
|
26870
|
+
const bx = Math.max(-ln.width / 2 + 4, ln.width / 2 - bw - 4);
|
|
26871
|
+
const by = -ln.height / 2 + 4;
|
|
26872
|
+
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);
|
|
26873
|
+
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);
|
|
26874
|
+
}
|
|
26766
26875
|
}
|
|
26767
26876
|
const hasDescriptions = parsed.nodes.some(
|
|
26768
26877
|
(n) => n.description && n.description.length > 0
|
|
26769
26878
|
);
|
|
26770
|
-
const hasLegend =
|
|
26879
|
+
const hasLegend = legendGroups.length > 0 || hasDescriptions && controlsHost !== "app";
|
|
26771
26880
|
if (hasLegend) {
|
|
26772
26881
|
let controlsGroup;
|
|
26773
26882
|
if (hasDescriptions && (onToggleDescriptions || controlsHost === "app")) {
|
|
@@ -26785,7 +26894,7 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26785
26894
|
};
|
|
26786
26895
|
}
|
|
26787
26896
|
const legendConfig = {
|
|
26788
|
-
groups:
|
|
26897
|
+
groups: legendGroups,
|
|
26789
26898
|
position: { placement: "top-center", titleRelation: "below-title" },
|
|
26790
26899
|
mode: exportMode ? "export" : "preview",
|
|
26791
26900
|
// Keep inactive sibling tag groups visible as collapsed pills so the user
|
|
@@ -26840,7 +26949,7 @@ function renderBoxesAndLinesForExport(container, parsed, layout, palette, isDark
|
|
|
26840
26949
|
}
|
|
26841
26950
|
});
|
|
26842
26951
|
}
|
|
26843
|
-
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;
|
|
26952
|
+
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;
|
|
26844
26953
|
var init_renderer6 = __esm({
|
|
26845
26954
|
"src/boxes-and-lines/renderer.ts"() {
|
|
26846
26955
|
"use strict";
|
|
@@ -26851,12 +26960,13 @@ var init_renderer6 = __esm({
|
|
|
26851
26960
|
init_legend_layout();
|
|
26852
26961
|
init_title_constants();
|
|
26853
26962
|
init_color_utils();
|
|
26963
|
+
init_colors();
|
|
26854
26964
|
init_tag_groups();
|
|
26855
26965
|
init_inline_markdown();
|
|
26856
26966
|
init_wrapped_desc();
|
|
26857
26967
|
init_scaling();
|
|
26858
26968
|
DIAGRAM_PADDING6 = 20;
|
|
26859
|
-
NODE_FONT_SIZE =
|
|
26969
|
+
NODE_FONT_SIZE = 11;
|
|
26860
26970
|
MIN_NODE_FONT_SIZE = 9;
|
|
26861
26971
|
EDGE_LABEL_FONT_SIZE4 = 11;
|
|
26862
26972
|
EDGE_STROKE_WIDTH5 = 1.5;
|
|
@@ -26873,6 +26983,8 @@ var init_renderer6 = __esm({
|
|
|
26873
26983
|
GROUP_RX = 8;
|
|
26874
26984
|
GROUP_LABEL_FONT_SIZE = 14;
|
|
26875
26985
|
GROUP_LABEL_ZONE = 32;
|
|
26986
|
+
RAMP_FLOOR = 15;
|
|
26987
|
+
VALUE_FONT_SIZE = 11;
|
|
26876
26988
|
lineGeneratorLR = d3Shape4.line().x((d) => d.x).y((d) => d.y).curve(d3Shape4.curveBasis);
|
|
26877
26989
|
lineGeneratorTB = d3Shape4.line().x((d) => d.x).y((d) => d.y).curve(d3Shape4.curveBasis);
|
|
26878
26990
|
}
|
|
@@ -46591,7 +46703,11 @@ function resolveMap(parsed, data) {
|
|
|
46591
46703
|
if (bb && !isWholeSphere(bb)) containerBoxes.push(bb);
|
|
46592
46704
|
}
|
|
46593
46705
|
const containerUnion = unionExtent(containerBoxes, points);
|
|
46594
|
-
if (containerUnion)
|
|
46706
|
+
if (containerUnion)
|
|
46707
|
+
extent2 = pad(
|
|
46708
|
+
clampContainerToCluster(containerUnion, points),
|
|
46709
|
+
PAD_FRACTION
|
|
46710
|
+
);
|
|
46595
46711
|
}
|
|
46596
46712
|
if (isPoiOnly) {
|
|
46597
46713
|
const cx = (extent2[0][0] + extent2[1][0]) / 2;
|
|
@@ -46672,6 +46788,22 @@ function mostCommonCountry(regions, poiCountries) {
|
|
|
46672
46788
|
}
|
|
46673
46789
|
return best;
|
|
46674
46790
|
}
|
|
46791
|
+
function clampContainerToCluster(container, points) {
|
|
46792
|
+
const poi = unionExtent([], points);
|
|
46793
|
+
if (!poi) return container;
|
|
46794
|
+
let [[west, south], [east, north]] = container;
|
|
46795
|
+
const [[pWest, pSouth], [pEast, pNorth]] = poi;
|
|
46796
|
+
south = Math.max(south, pSouth - CONTAINER_OVERSHOOT_DEG);
|
|
46797
|
+
north = Math.min(north, pNorth + CONTAINER_OVERSHOOT_DEG);
|
|
46798
|
+
if (east <= 180 && pEast <= 180) {
|
|
46799
|
+
west = Math.max(west, pWest - CONTAINER_OVERSHOOT_DEG);
|
|
46800
|
+
east = Math.min(east, pEast + CONTAINER_OVERSHOOT_DEG);
|
|
46801
|
+
}
|
|
46802
|
+
return [
|
|
46803
|
+
[west, south],
|
|
46804
|
+
[east, north]
|
|
46805
|
+
];
|
|
46806
|
+
}
|
|
46675
46807
|
function pad(e, frac) {
|
|
46676
46808
|
const dLon = (e[1][0] - e[0][0]) * frac || 1;
|
|
46677
46809
|
const dLat = (e[1][1] - e[0][1]) * frac || 1;
|
|
@@ -46684,7 +46816,7 @@ function firstError(diags) {
|
|
|
46684
46816
|
const e = diags.find((d) => d.severity === "error");
|
|
46685
46817
|
return e ? formatDgmoError(e) : null;
|
|
46686
46818
|
}
|
|
46687
|
-
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;
|
|
46819
|
+
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;
|
|
46688
46820
|
var init_resolver2 = __esm({
|
|
46689
46821
|
"src/map/resolver.ts"() {
|
|
46690
46822
|
"use strict";
|
|
@@ -46697,6 +46829,7 @@ var init_resolver2 = __esm({
|
|
|
46697
46829
|
WORLD_LAT_SOUTH = -58;
|
|
46698
46830
|
WORLD_LAT_NORTH = 78;
|
|
46699
46831
|
POI_ZOOM_FLOOR_DEG = 7;
|
|
46832
|
+
CONTAINER_OVERSHOOT_DEG = 8;
|
|
46700
46833
|
US_NATIONAL_LON_SPAN = 48;
|
|
46701
46834
|
REGION_ALIASES = {
|
|
46702
46835
|
// Common everyday names → the Natural-Earth display name actually shipped.
|
|
@@ -46775,6 +46908,55 @@ var init_resolver2 = __esm({
|
|
|
46775
46908
|
}
|
|
46776
46909
|
});
|
|
46777
46910
|
|
|
46911
|
+
// src/map/legend-band.ts
|
|
46912
|
+
function mapLegendGroups(legend) {
|
|
46913
|
+
const ramp = legend.ramp;
|
|
46914
|
+
const scoreGroup = ramp ? {
|
|
46915
|
+
name: ramp.metric?.trim() || "Value",
|
|
46916
|
+
entries: [],
|
|
46917
|
+
gradient: {
|
|
46918
|
+
min: ramp.min,
|
|
46919
|
+
max: ramp.max,
|
|
46920
|
+
hue: ramp.hue,
|
|
46921
|
+
base: ramp.base
|
|
46922
|
+
}
|
|
46923
|
+
} : null;
|
|
46924
|
+
const tagGroups = legend.tagGroups.filter((g) => g.entries.length > 0).map((g) => ({ name: g.name, entries: [...g.entries] }));
|
|
46925
|
+
return [...scoreGroup ? [scoreGroup] : [], ...tagGroups];
|
|
46926
|
+
}
|
|
46927
|
+
function mapLegendConfig(groups, mode) {
|
|
46928
|
+
return {
|
|
46929
|
+
groups,
|
|
46930
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
46931
|
+
mode,
|
|
46932
|
+
showEmptyGroups: false,
|
|
46933
|
+
showInactivePills: true
|
|
46934
|
+
};
|
|
46935
|
+
}
|
|
46936
|
+
function mapLegendTop(hasTitle, hasSubtitle) {
|
|
46937
|
+
return (hasTitle ? TITLE_Y + TITLE_FONT_SIZE : 0) + (hasSubtitle ? TITLE_FONT_SIZE : 0) + LEGEND_TOP_GAP2;
|
|
46938
|
+
}
|
|
46939
|
+
function mapLegendBand(legend, opts) {
|
|
46940
|
+
if (!legend) return 0;
|
|
46941
|
+
const groups = mapLegendGroups(legend);
|
|
46942
|
+
if (groups.length === 0) return 0;
|
|
46943
|
+
const config = mapLegendConfig(groups, opts.mode);
|
|
46944
|
+
const state = { activeGroup: legend.activeGroup };
|
|
46945
|
+
const { height } = computeLegendLayout(config, state, opts.width);
|
|
46946
|
+
if (height <= 0) return 0;
|
|
46947
|
+
return mapLegendTop(opts.hasTitle, opts.hasSubtitle) + height + LEGEND_BOTTOM_GAP2;
|
|
46948
|
+
}
|
|
46949
|
+
var LEGEND_TOP_GAP2, LEGEND_BOTTOM_GAP2;
|
|
46950
|
+
var init_legend_band = __esm({
|
|
46951
|
+
"src/map/legend-band.ts"() {
|
|
46952
|
+
"use strict";
|
|
46953
|
+
init_legend_layout();
|
|
46954
|
+
init_title_constants();
|
|
46955
|
+
LEGEND_TOP_GAP2 = 8;
|
|
46956
|
+
LEGEND_BOTTOM_GAP2 = 10;
|
|
46957
|
+
}
|
|
46958
|
+
});
|
|
46959
|
+
|
|
46778
46960
|
// src/map/colorize.ts
|
|
46779
46961
|
function assignColors(isos, adjacency) {
|
|
46780
46962
|
const sorted = [...isos].sort();
|
|
@@ -47204,6 +47386,38 @@ function parsePathRings(d) {
|
|
|
47204
47386
|
if (cur.length) rings.push(cur);
|
|
47205
47387
|
return rings;
|
|
47206
47388
|
}
|
|
47389
|
+
function dropAntimeridianWrapSlivers(d, width, height) {
|
|
47390
|
+
const rings = parsePathRings(d);
|
|
47391
|
+
if (rings.length <= 1) return d;
|
|
47392
|
+
const eps = 0.75;
|
|
47393
|
+
const minArea = 3e-3 * width * height;
|
|
47394
|
+
const ringArea = (r) => {
|
|
47395
|
+
let s = 0;
|
|
47396
|
+
for (let i = 0; i < r.length; i++) {
|
|
47397
|
+
const a = r[i];
|
|
47398
|
+
const b = r[(i + 1) % r.length];
|
|
47399
|
+
s += a[0] * b[1] - b[0] * a[1];
|
|
47400
|
+
}
|
|
47401
|
+
return Math.abs(s) / 2;
|
|
47402
|
+
};
|
|
47403
|
+
const areas = rings.map(ringArea);
|
|
47404
|
+
const maxArea = Math.max(...areas);
|
|
47405
|
+
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;
|
|
47406
|
+
let dropped = false;
|
|
47407
|
+
const kept = rings.filter((r, idx) => {
|
|
47408
|
+
if (areas[idx] >= maxArea || areas[idx] >= minArea) return true;
|
|
47409
|
+
const touches = r.some((p, i) => onVEdge(p, r[(i + 1) % r.length]));
|
|
47410
|
+
if (touches) {
|
|
47411
|
+
dropped = true;
|
|
47412
|
+
return false;
|
|
47413
|
+
}
|
|
47414
|
+
return true;
|
|
47415
|
+
});
|
|
47416
|
+
if (!dropped) return d;
|
|
47417
|
+
return kept.map(
|
|
47418
|
+
(r) => r.map((p, i) => (i ? "L" : "M") + p[0] + "," + p[1]).join("") + "Z"
|
|
47419
|
+
).join("");
|
|
47420
|
+
}
|
|
47207
47421
|
function layoutMap(resolved, data, size, opts) {
|
|
47208
47422
|
const { palette, isDark } = opts;
|
|
47209
47423
|
const { width, height } = size;
|
|
@@ -47287,7 +47501,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47287
47501
|
const rampBase = isDark ? mix(palette.surface, palette.text, 28) : palette.bg;
|
|
47288
47502
|
const fillForValue = (s) => {
|
|
47289
47503
|
const t = rampMax > rampMin ? (s - rampMin) / (rampMax - rampMin) : 1;
|
|
47290
|
-
const pct =
|
|
47504
|
+
const pct = RAMP_FLOOR2 + Math.max(0, Math.min(1, t)) * (100 - RAMP_FLOOR2);
|
|
47291
47505
|
return mix(rampHue, rampBase, pct);
|
|
47292
47506
|
};
|
|
47293
47507
|
const tagFill = (tags, groupName) => {
|
|
@@ -47323,12 +47537,43 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47323
47537
|
return tagFill(r.tags, activeGroup) ?? neutralFill;
|
|
47324
47538
|
};
|
|
47325
47539
|
const regionById = new Map(resolved.regions.map((r) => [r.iso, r]));
|
|
47540
|
+
let legend = null;
|
|
47541
|
+
if (!resolved.directives.noLegend) {
|
|
47542
|
+
const legendTagGroups = resolved.tagGroups.map((g) => ({
|
|
47543
|
+
name: g.name,
|
|
47544
|
+
entries: g.entries.map((e) => ({ value: e.value, color: e.color }))
|
|
47545
|
+
}));
|
|
47546
|
+
if (legendTagGroups.length > 0 || hasRamp) {
|
|
47547
|
+
legend = {
|
|
47548
|
+
tagGroups: legendTagGroups,
|
|
47549
|
+
activeGroup,
|
|
47550
|
+
...hasRamp && {
|
|
47551
|
+
ramp: {
|
|
47552
|
+
...resolved.directives.regionMetric !== void 0 && {
|
|
47553
|
+
metric: resolved.directives.regionMetric
|
|
47554
|
+
},
|
|
47555
|
+
min: rampMin,
|
|
47556
|
+
max: rampMax,
|
|
47557
|
+
hue: rampHue,
|
|
47558
|
+
base: rampBase
|
|
47559
|
+
}
|
|
47560
|
+
}
|
|
47561
|
+
};
|
|
47562
|
+
}
|
|
47563
|
+
}
|
|
47326
47564
|
const TITLE_GAP2 = 16;
|
|
47327
47565
|
let topPad = FIT_PAD;
|
|
47328
47566
|
if (resolved.title && resolved.pois.length > 0) {
|
|
47329
47567
|
const bannerBottom = (resolved.subtitle ? TITLE_Y + TITLE_FONT_SIZE : TITLE_Y) + TITLE_FONT_SIZE / 2;
|
|
47330
47568
|
topPad = Math.max(FIT_PAD, bannerBottom + TITLE_GAP2);
|
|
47331
47569
|
}
|
|
47570
|
+
const legendBand = mapLegendBand(legend, {
|
|
47571
|
+
width,
|
|
47572
|
+
mode: opts.legendMode ?? "preview",
|
|
47573
|
+
hasTitle: Boolean(resolved.title),
|
|
47574
|
+
hasSubtitle: Boolean(resolved.subtitle)
|
|
47575
|
+
});
|
|
47576
|
+
if (legendBand > topPad) topPad = legendBand;
|
|
47332
47577
|
const fitBox = [
|
|
47333
47578
|
[FIT_PAD, topPad],
|
|
47334
47579
|
[
|
|
@@ -47346,10 +47591,11 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47346
47591
|
const by0 = cb[0][1];
|
|
47347
47592
|
const cw = cb[1][0] - bx0;
|
|
47348
47593
|
const ch = cb[1][1] - by0;
|
|
47349
|
-
const
|
|
47350
|
-
const
|
|
47351
|
-
const
|
|
47352
|
-
const
|
|
47594
|
+
const topReserve = resolved.title && resolved.pois.length > 0 || legendBand > 0 ? topPad : 0;
|
|
47595
|
+
const ox = 0;
|
|
47596
|
+
const oy = topReserve;
|
|
47597
|
+
const sx = cw > 0 ? width / cw : 1;
|
|
47598
|
+
const sy = ch > 0 ? (height - topReserve) / ch : 1;
|
|
47353
47599
|
stretchParams = { sx, sy, ox, oy, bx0, by0 };
|
|
47354
47600
|
const stretch = (x, y) => [
|
|
47355
47601
|
ox + (x - bx0) * sx,
|
|
@@ -47622,7 +47868,8 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47622
47868
|
const r = regionById.get(iso);
|
|
47623
47869
|
const viewF = shouldCull ? cullFeatureToView(f) : dropFrameFillers(f);
|
|
47624
47870
|
if (!viewF) continue;
|
|
47625
|
-
const
|
|
47871
|
+
const raw = path(viewF) ?? "";
|
|
47872
|
+
const d = fitIsGlobal ? dropAntimeridianWrapSlivers(raw, width, height) : raw;
|
|
47626
47873
|
if (!d) continue;
|
|
47627
47874
|
const isThisLayer = r?.layer === layerKind;
|
|
47628
47875
|
const isForeign = layerKind === "country" && usContext && iso !== "US";
|
|
@@ -47639,6 +47886,9 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47639
47886
|
} else {
|
|
47640
47887
|
label = f.properties?.name;
|
|
47641
47888
|
}
|
|
47889
|
+
const labelAnchor = WORLD_LABEL_ANCHORS[iso];
|
|
47890
|
+
const c = labelAnchor ? project(labelAnchor[0], labelAnchor[1]) : path.centroid(viewF);
|
|
47891
|
+
const hasCentroid = c != null && Number.isFinite(c[0]) && Number.isFinite(c[1]);
|
|
47642
47892
|
regions.push({
|
|
47643
47893
|
id: iso,
|
|
47644
47894
|
d,
|
|
@@ -47647,6 +47897,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47647
47897
|
lineNumber,
|
|
47648
47898
|
layer,
|
|
47649
47899
|
...label !== void 0 && { label },
|
|
47900
|
+
...hasCentroid && { labelX: c[0], labelY: c[1] },
|
|
47650
47901
|
...isThisLayer && r.value !== void 0 && { value: r.value },
|
|
47651
47902
|
...isThisLayer && Object.keys(r.tags).length > 0 && { tags: r.tags }
|
|
47652
47903
|
});
|
|
@@ -48087,10 +48338,6 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
48087
48338
|
lineNumber
|
|
48088
48339
|
});
|
|
48089
48340
|
};
|
|
48090
|
-
const WORLD_LABEL_ANCHORS = {
|
|
48091
|
-
US: [-98.5, 39.5]
|
|
48092
|
-
// CONUS geographic centre (near Lebanon, Kansas)
|
|
48093
|
-
};
|
|
48094
48341
|
const REGION_LABEL_GAP = 2;
|
|
48095
48342
|
const regionLabelRect = (cx, cy, text) => {
|
|
48096
48343
|
const w = measureLegendText(text, FONT2) + 2 * REGION_LABEL_GAP;
|
|
@@ -48408,30 +48655,6 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
48408
48655
|
});
|
|
48409
48656
|
labels.push(...contextLabels);
|
|
48410
48657
|
}
|
|
48411
|
-
let legend = null;
|
|
48412
|
-
if (!resolved.directives.noLegend) {
|
|
48413
|
-
const tagGroups = resolved.tagGroups.map((g) => ({
|
|
48414
|
-
name: g.name,
|
|
48415
|
-
entries: g.entries.map((e) => ({ value: e.value, color: e.color }))
|
|
48416
|
-
}));
|
|
48417
|
-
if (tagGroups.length > 0 || hasRamp) {
|
|
48418
|
-
legend = {
|
|
48419
|
-
tagGroups,
|
|
48420
|
-
activeGroup,
|
|
48421
|
-
...hasRamp && {
|
|
48422
|
-
ramp: {
|
|
48423
|
-
...resolved.directives.regionMetric !== void 0 && {
|
|
48424
|
-
metric: resolved.directives.regionMetric
|
|
48425
|
-
},
|
|
48426
|
-
min: rampMin,
|
|
48427
|
-
max: rampMax,
|
|
48428
|
-
hue: rampHue,
|
|
48429
|
-
base: rampBase
|
|
48430
|
-
}
|
|
48431
|
-
}
|
|
48432
|
-
};
|
|
48433
|
-
}
|
|
48434
|
-
}
|
|
48435
48658
|
return {
|
|
48436
48659
|
width,
|
|
48437
48660
|
height,
|
|
@@ -48456,7 +48679,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
48456
48679
|
diagnostics: []
|
|
48457
48680
|
};
|
|
48458
48681
|
}
|
|
48459
|
-
var import_d3_geo2, import_topojson_client2, FIT_PAD,
|
|
48682
|
+
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;
|
|
48460
48683
|
var init_layout15 = __esm({
|
|
48461
48684
|
"src/map/layout.ts"() {
|
|
48462
48685
|
"use strict";
|
|
@@ -48469,15 +48692,20 @@ var init_layout15 = __esm({
|
|
|
48469
48692
|
init_label_layout();
|
|
48470
48693
|
init_legend_constants();
|
|
48471
48694
|
init_title_constants();
|
|
48695
|
+
init_legend_band();
|
|
48472
48696
|
init_context_labels();
|
|
48473
48697
|
FIT_PAD = 24;
|
|
48474
|
-
|
|
48698
|
+
RAMP_FLOOR2 = 15;
|
|
48475
48699
|
R_DEFAULT = 6;
|
|
48476
48700
|
R_MIN = 4;
|
|
48477
48701
|
R_MAX = 22;
|
|
48478
48702
|
W_MIN = 1.25;
|
|
48479
48703
|
W_MAX = 8;
|
|
48480
48704
|
FONT2 = 11;
|
|
48705
|
+
WORLD_LABEL_ANCHORS = {
|
|
48706
|
+
US: [-98.5, 39.5]
|
|
48707
|
+
// CONUS geographic centre (near Lebanon, Kansas)
|
|
48708
|
+
};
|
|
48481
48709
|
MAX_CLUSTER_EXTENT_FACTOR = 0.18;
|
|
48482
48710
|
MAX_COLUMN_ROWS = 7;
|
|
48483
48711
|
REGION_LABEL_HALO_RATIO = 4.5;
|
|
@@ -48491,9 +48719,9 @@ var init_layout15 = __esm({
|
|
|
48491
48719
|
COMPACT_WIDTH_PX = 480;
|
|
48492
48720
|
RELIEF_MIN_AREA = 12;
|
|
48493
48721
|
RELIEF_MIN_DIM = 2;
|
|
48494
|
-
RELIEF_HATCH_SPACING =
|
|
48495
|
-
RELIEF_HATCH_WIDTH = 0.
|
|
48496
|
-
RELIEF_HATCH_STRENGTH =
|
|
48722
|
+
RELIEF_HATCH_SPACING = 1.5;
|
|
48723
|
+
RELIEF_HATCH_WIDTH = 0.2;
|
|
48724
|
+
RELIEF_HATCH_STRENGTH = 26;
|
|
48497
48725
|
COASTLINE_RING_COUNT = 5;
|
|
48498
48726
|
COASTLINE_D0 = 16e-4;
|
|
48499
48727
|
COASTLINE_STEP = 28e-4;
|
|
@@ -48571,7 +48799,47 @@ function ringToPath(ring) {
|
|
|
48571
48799
|
d += (i ? "L" : "M") + ring[i][0] + "," + ring[i][1];
|
|
48572
48800
|
return d + "Z";
|
|
48573
48801
|
}
|
|
48574
|
-
function
|
|
48802
|
+
function polylineToPath(pts) {
|
|
48803
|
+
let d = "";
|
|
48804
|
+
for (let i = 0; i < pts.length; i++)
|
|
48805
|
+
d += (i ? "L" : "M") + pts[i][0] + "," + pts[i][1];
|
|
48806
|
+
return d;
|
|
48807
|
+
}
|
|
48808
|
+
function ringToCoastPaths(ring, frame) {
|
|
48809
|
+
if (!frame) return [ringToPath(ring)];
|
|
48810
|
+
const n = ring.length;
|
|
48811
|
+
const eps = 0.75;
|
|
48812
|
+
const onL = (x) => Math.abs(x) <= eps;
|
|
48813
|
+
const onR = (x) => Math.abs(x - frame.w) <= eps;
|
|
48814
|
+
const onT = (y) => Math.abs(y) <= eps;
|
|
48815
|
+
const onB = (y) => Math.abs(y - frame.h) <= eps;
|
|
48816
|
+
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]);
|
|
48817
|
+
let firstBreak = -1;
|
|
48818
|
+
for (let i = 0; i < n; i++)
|
|
48819
|
+
if (isFrameEdge(ring[i], ring[(i + 1) % n])) {
|
|
48820
|
+
firstBreak = i;
|
|
48821
|
+
break;
|
|
48822
|
+
}
|
|
48823
|
+
if (firstBreak === -1) return [ringToPath(ring)];
|
|
48824
|
+
const paths = [];
|
|
48825
|
+
let cur = [];
|
|
48826
|
+
const start = (firstBreak + 1) % n;
|
|
48827
|
+
for (let k = 0; k < n; k++) {
|
|
48828
|
+
const i = (start + k) % n;
|
|
48829
|
+
const a = ring[i];
|
|
48830
|
+
const b = ring[(i + 1) % n];
|
|
48831
|
+
if (isFrameEdge(a, b)) {
|
|
48832
|
+
if (cur.length >= 2) paths.push(polylineToPath(cur));
|
|
48833
|
+
cur = [];
|
|
48834
|
+
continue;
|
|
48835
|
+
}
|
|
48836
|
+
if (cur.length === 0) cur.push(a);
|
|
48837
|
+
cur.push(b);
|
|
48838
|
+
}
|
|
48839
|
+
if (cur.length >= 2) paths.push(polylineToPath(cur));
|
|
48840
|
+
return paths;
|
|
48841
|
+
}
|
|
48842
|
+
function coastlineOuterRings(regions, minExtent, frame) {
|
|
48575
48843
|
const paths = [];
|
|
48576
48844
|
for (const r of regions) {
|
|
48577
48845
|
const rings = parsePathRings(r.d);
|
|
@@ -48594,7 +48862,7 @@ function coastlineOuterRings(regions, minExtent) {
|
|
|
48594
48862
|
for (let j = 0; j < rings.length; j++)
|
|
48595
48863
|
if (j !== i && pointInRing2(fx, fy, rings[j])) depth++;
|
|
48596
48864
|
if (depth % 2 === 1) continue;
|
|
48597
|
-
paths.push(
|
|
48865
|
+
paths.push(...ringToCoastPaths(ring, frame));
|
|
48598
48866
|
}
|
|
48599
48867
|
}
|
|
48600
48868
|
return paths;
|
|
@@ -48624,6 +48892,9 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
48624
48892
|
// stretch-distorting. The in-app preview pane passes no exportDims → unset →
|
|
48625
48893
|
// keeps the global stretch-fill.
|
|
48626
48894
|
preferContain: exportDims?.preferContain ?? false,
|
|
48895
|
+
// Reserve the legend band for the mode actually drawn below (export shows
|
|
48896
|
+
// only the active group; preview keeps the inactive pills).
|
|
48897
|
+
legendMode: exportDims ? "export" : "preview",
|
|
48627
48898
|
...activeGroupOverride !== void 0 && {
|
|
48628
48899
|
activeGroup: activeGroupOverride
|
|
48629
48900
|
}
|
|
@@ -48638,6 +48909,10 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
48638
48909
|
const drawRegion = (g, r, strokeWidth) => {
|
|
48639
48910
|
const p = g.append("path").attr("d", r.d).attr("fill", r.fill).attr("stroke", r.stroke).attr("stroke-width", strokeWidth);
|
|
48640
48911
|
if (r.label) p.attr("data-region-name", r.label);
|
|
48912
|
+
if (r.id && r.id !== "lake") p.attr("data-iso", r.id);
|
|
48913
|
+
if (r.labelX !== void 0 && r.labelY !== void 0) {
|
|
48914
|
+
p.attr("data-label-x", r.labelX).attr("data-label-y", r.labelY);
|
|
48915
|
+
}
|
|
48641
48916
|
if (r.layer !== "base") {
|
|
48642
48917
|
p.classed("dgmo-map-region", true).attr("data-region", r.id);
|
|
48643
48918
|
if (r.value !== void 0) p.attr("data-value", r.value);
|
|
@@ -48667,7 +48942,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
48667
48942
|
const landClip = defs.append("clipPath").attr("id", landClipId);
|
|
48668
48943
|
for (const r of layout.regions)
|
|
48669
48944
|
if (r.id !== "lake") landClip.append("path").attr("d", r.d);
|
|
48670
|
-
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");
|
|
48945
|
+
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");
|
|
48671
48946
|
for (let y = h.spacing; y < height; y += h.spacing) {
|
|
48672
48947
|
gRelief.append("line").attr("x1", 0).attr("y1", y).attr("x2", width).attr("y2", y);
|
|
48673
48948
|
}
|
|
@@ -48688,10 +48963,16 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
48688
48963
|
mask.append("path").attr("d", d).attr("fill", "black").attr("stroke", "black").attr("stroke-width", 2 * reach).attr("stroke-linejoin", "round");
|
|
48689
48964
|
}
|
|
48690
48965
|
}
|
|
48691
|
-
const gWater = svg.append("g").attr("class", "dgmo-map-water-lines").attr("fill", "none").attr("mask", `url(#${maskId})`);
|
|
48966
|
+
const gWater = svg.append("g").attr("class", "dgmo-map-water-lines").attr("fill", "none").style("pointer-events", "none").attr("mask", `url(#${maskId})`);
|
|
48692
48967
|
appendWaterLines(
|
|
48693
48968
|
gWater,
|
|
48694
|
-
|
|
48969
|
+
// Pass the canvas frame so edges collinear with it (the antimeridian on a
|
|
48970
|
+
// world map, regional clipExtent cuts) don't get ringed as fake coast —
|
|
48971
|
+
// land runs cleanly to the render-area edge.
|
|
48972
|
+
coastlineOuterRings(layout.regions, cs.minExtent, {
|
|
48973
|
+
w: width,
|
|
48974
|
+
h: height
|
|
48975
|
+
}),
|
|
48695
48976
|
cs,
|
|
48696
48977
|
layout.background
|
|
48697
48978
|
);
|
|
@@ -48705,7 +48986,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
48705
48986
|
gWater.append("path").attr("d", ds.join(" ")).attr("stroke", stroke2).attr("stroke-width", 0.5).attr("stroke-linejoin", "round");
|
|
48706
48987
|
}
|
|
48707
48988
|
if (layout.rivers.length) {
|
|
48708
|
-
const gRivers = svg.append("g").attr("class", "dgmo-map-rivers").attr("fill", "none");
|
|
48989
|
+
const gRivers = svg.append("g").attr("class", "dgmo-map-rivers").attr("fill", "none").style("pointer-events", "none");
|
|
48709
48990
|
for (const r of layout.rivers) {
|
|
48710
48991
|
gRivers.append("path").attr("d", r.d).attr("stroke", r.color).attr("stroke-width", r.width).attr("stroke-linecap", "round").attr("stroke-linejoin", "round");
|
|
48711
48992
|
}
|
|
@@ -48746,7 +49027,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
48746
49027
|
const d = box.points.map((p, i) => `${i ? "L" : "M"}${p[0]},${p[1]}`).join("") + "Z";
|
|
48747
49028
|
clip.append("path").attr("d", d);
|
|
48748
49029
|
}
|
|
48749
|
-
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})`);
|
|
49030
|
+
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})`);
|
|
48750
49031
|
appendWaterLines(
|
|
48751
49032
|
gInsetWater,
|
|
48752
49033
|
coastlineOuterRings(layout.insetRegions, cs.minExtent),
|
|
@@ -48905,30 +49186,12 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
48905
49186
|
if (layout.legend) {
|
|
48906
49187
|
const legendY = (layout.title ? TITLE_Y + TITLE_FONT_SIZE : 0) + (layout.subtitle ? TITLE_FONT_SIZE : 0) + 8;
|
|
48907
49188
|
const legendG = svg.append("g").attr("class", "dgmo-map-legend").attr("transform", `translate(0, ${legendY})`);
|
|
48908
|
-
const
|
|
48909
|
-
const scoreGroup = ramp ? {
|
|
48910
|
-
name: ramp.metric?.trim() || "Value",
|
|
48911
|
-
entries: [],
|
|
48912
|
-
gradient: {
|
|
48913
|
-
min: ramp.min,
|
|
48914
|
-
max: ramp.max,
|
|
48915
|
-
hue: ramp.hue,
|
|
48916
|
-
base: ramp.base
|
|
48917
|
-
}
|
|
48918
|
-
} : null;
|
|
48919
|
-
const tagGroups = layout.legend.tagGroups.filter((g) => g.entries.length > 0).map((g) => ({ name: g.name, entries: [...g.entries] }));
|
|
48920
|
-
const groups = [...scoreGroup ? [scoreGroup] : [], ...tagGroups];
|
|
49189
|
+
const groups = mapLegendGroups(layout.legend);
|
|
48921
49190
|
if (groups.length > 0) {
|
|
48922
|
-
const config =
|
|
49191
|
+
const config = mapLegendConfig(
|
|
48923
49192
|
groups,
|
|
48924
|
-
|
|
48925
|
-
|
|
48926
|
-
showEmptyGroups: false,
|
|
48927
|
-
// Keep inactive siblings visible as pills so the user can click to flip
|
|
48928
|
-
// the active colouring dimension (preview only — export shows just the
|
|
48929
|
-
// active group).
|
|
48930
|
-
showInactivePills: true
|
|
48931
|
-
};
|
|
49193
|
+
exportDims ? "export" : "preview"
|
|
49194
|
+
);
|
|
48932
49195
|
const state = { activeGroup: layout.legend.activeGroup };
|
|
48933
49196
|
renderLegendD3(legendG, config, state, palette, isDark, void 0, width);
|
|
48934
49197
|
}
|
|
@@ -48973,6 +49236,7 @@ var init_renderer16 = __esm({
|
|
|
48973
49236
|
init_title_constants();
|
|
48974
49237
|
init_color_utils();
|
|
48975
49238
|
init_legend_d3();
|
|
49239
|
+
init_legend_band();
|
|
48976
49240
|
init_layout15();
|
|
48977
49241
|
LABEL_FONT = 11;
|
|
48978
49242
|
}
|
|
@@ -48993,9 +49257,10 @@ function mapContentAspect(resolved, data, ref = REF) {
|
|
|
48993
49257
|
const aspect = w / h;
|
|
48994
49258
|
return Number.isFinite(aspect) && aspect > 0 ? aspect : FALLBACK_ASPECT;
|
|
48995
49259
|
}
|
|
48996
|
-
function mapExportDimensions(resolved, data, baseWidth = 1200) {
|
|
48997
|
-
const
|
|
48998
|
-
const
|
|
49260
|
+
function mapExportDimensions(resolved, data, baseWidth = 1200, aspectOverride) {
|
|
49261
|
+
const useOverride = aspectOverride !== void 0 && Number.isFinite(aspectOverride) && aspectOverride > 0;
|
|
49262
|
+
const raw = useOverride ? aspectOverride : mapContentAspect(resolved, data);
|
|
49263
|
+
const clamped = useOverride ? raw : Math.max(ASPECT_MIN, Math.min(ASPECT_MAX, raw));
|
|
48999
49264
|
const width = baseWidth;
|
|
49000
49265
|
let height = Math.round(width / clamped);
|
|
49001
49266
|
let chromeReserve = 0;
|
|
@@ -49008,7 +49273,7 @@ function mapExportDimensions(resolved, data, baseWidth = 1200) {
|
|
|
49008
49273
|
height = Math.round(chromeReserve + MIN_MAP_BAND);
|
|
49009
49274
|
floored = true;
|
|
49010
49275
|
}
|
|
49011
|
-
const preferContain = clamped !== raw || floored;
|
|
49276
|
+
const preferContain = useOverride ? floored : clamped !== raw || floored;
|
|
49012
49277
|
return { width, height, preferContain };
|
|
49013
49278
|
}
|
|
49014
49279
|
var import_d3_geo3, FIT_PAD2, TITLE_GAP, ASPECT_MAX, ASPECT_MIN, MIN_MAP_BAND, FALLBACK_ASPECT, REF;
|
|
@@ -54715,7 +54980,6 @@ function renderTimelineTagLegendOverlay(container, parsed, palette, isDark, setu
|
|
|
54715
54980
|
function renderTimelineHorizontalTimeSort(container, parsed, palette, isDark, setup, hovers, onClickItem, _exportDims, _swimlaneTagGroup, _activeTagGroup, _onTagStateChange, _viewMode) {
|
|
54716
54981
|
const {
|
|
54717
54982
|
width,
|
|
54718
|
-
height,
|
|
54719
54983
|
tooltip,
|
|
54720
54984
|
solid,
|
|
54721
54985
|
textColor,
|
|
@@ -54764,10 +55028,11 @@ function renderTimelineHorizontalTimeSort(container, parsed, palette, isDark, se
|
|
|
54764
55028
|
const markerLabelY = markerReserve ? -(topScaleH + MARKER_ROW_H / 2) : 0;
|
|
54765
55029
|
const eraLabelY = eraReserve ? -(topScaleH + markerReserve + ERA_ROW_H / 2) : 0;
|
|
54766
55030
|
const innerWidth = width - margin.left - margin.right;
|
|
54767
|
-
const
|
|
54768
|
-
const
|
|
55031
|
+
const rowH = ctx.structural(28);
|
|
55032
|
+
const innerHeight = rowH * sorted.length;
|
|
55033
|
+
const usedHeight = margin.top + innerHeight + margin.bottom;
|
|
54769
55034
|
const xScale = d3Scale2.scaleLinear().domain([minDate - datePadding, maxDate + datePadding]).range([0, innerWidth]);
|
|
54770
|
-
const svg = d3Selection23.select(container).append("svg").attr("width", width).attr("height",
|
|
55035
|
+
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);
|
|
54771
55036
|
if (ctx.isBelowFloor) {
|
|
54772
55037
|
svg.attr("width", "100%");
|
|
54773
55038
|
}
|
|
@@ -57288,7 +57553,12 @@ async function renderForExport(content, theme, palette, viewState, options) {
|
|
|
57288
57553
|
}
|
|
57289
57554
|
}
|
|
57290
57555
|
const mapResolved = resolveMap2(mapParsed, mapData);
|
|
57291
|
-
const dims2 = mapExportDimensions2(
|
|
57556
|
+
const dims2 = mapExportDimensions2(
|
|
57557
|
+
mapResolved,
|
|
57558
|
+
mapData,
|
|
57559
|
+
EXPORT_WIDTH,
|
|
57560
|
+
options?.mapAspect
|
|
57561
|
+
);
|
|
57292
57562
|
const container2 = createExportContainer(dims2.width, dims2.height);
|
|
57293
57563
|
renderMapForExport2(
|
|
57294
57564
|
container2,
|
|
@@ -58298,6 +58568,9 @@ var DIRECTIVE_KEYWORDS = /* @__PURE__ */ new Set([
|
|
|
58298
58568
|
"hide",
|
|
58299
58569
|
"mode",
|
|
58300
58570
|
"direction",
|
|
58571
|
+
// Boxes-and-lines
|
|
58572
|
+
"box-metric",
|
|
58573
|
+
"show-values",
|
|
58301
58574
|
// ER
|
|
58302
58575
|
"notation",
|
|
58303
58576
|
// Class
|
|
@@ -59020,7 +59293,7 @@ pre.dgmo, code.language-dgmo, pre > code.language-dgmo,
|
|
|
59020
59293
|
|
|
59021
59294
|
// src/auto/index.ts
|
|
59022
59295
|
init_safe_href();
|
|
59023
|
-
var VERSION = "0.
|
|
59296
|
+
var VERSION = "0.24.0";
|
|
59024
59297
|
var DEFAULTS = {
|
|
59025
59298
|
theme: "auto",
|
|
59026
59299
|
palette: "nord",
|