@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.mjs
CHANGED
|
@@ -818,9 +818,7 @@ var init_reserved_key_registry = __esm({
|
|
|
818
818
|
BOXES_AND_LINES_REGISTRY = staticRegistry([
|
|
819
819
|
"color",
|
|
820
820
|
"description",
|
|
821
|
-
"
|
|
822
|
-
"split",
|
|
823
|
-
"fanout"
|
|
821
|
+
"value"
|
|
824
822
|
]);
|
|
825
823
|
TIMELINE_REGISTRY = staticRegistry([
|
|
826
824
|
"color",
|
|
@@ -16840,6 +16838,21 @@ function parseBoxesAndLines(content) {
|
|
|
16840
16838
|
}
|
|
16841
16839
|
continue;
|
|
16842
16840
|
}
|
|
16841
|
+
if (!contentStarted) {
|
|
16842
|
+
const metricMatch = trimmed.match(/^box-metric\s+(.+)$/i);
|
|
16843
|
+
if (metricMatch) {
|
|
16844
|
+
const { label, colorName } = peelTrailingColorName(
|
|
16845
|
+
metricMatch[1].trim()
|
|
16846
|
+
);
|
|
16847
|
+
result.boxMetric = label;
|
|
16848
|
+
if (colorName !== void 0) result.boxMetricColor = colorName;
|
|
16849
|
+
continue;
|
|
16850
|
+
}
|
|
16851
|
+
if (/^show-values$/i.test(trimmed)) {
|
|
16852
|
+
result.showValues = true;
|
|
16853
|
+
continue;
|
|
16854
|
+
}
|
|
16855
|
+
}
|
|
16843
16856
|
if (!contentStarted) {
|
|
16844
16857
|
const optMatch = trimmed.match(OPTION_NOCOLON_RE);
|
|
16845
16858
|
if (optMatch) {
|
|
@@ -17218,6 +17231,19 @@ function parseNodeLine(trimmed, lineNum, metaAliasMap, diagnostics, nameAliasMap
|
|
|
17218
17231
|
description = [metadata["description"]];
|
|
17219
17232
|
delete metadata["description"];
|
|
17220
17233
|
}
|
|
17234
|
+
let value;
|
|
17235
|
+
if (metadata["value"] !== void 0) {
|
|
17236
|
+
const raw = metadata["value"];
|
|
17237
|
+
const num = Number(raw);
|
|
17238
|
+
if (Number.isFinite(num)) {
|
|
17239
|
+
value = num;
|
|
17240
|
+
} else {
|
|
17241
|
+
diagnostics.push(
|
|
17242
|
+
makeDgmoError(lineNum, `value must be a number (got "${raw}")`, "error")
|
|
17243
|
+
);
|
|
17244
|
+
}
|
|
17245
|
+
delete metadata["value"];
|
|
17246
|
+
}
|
|
17221
17247
|
if (split.alias) {
|
|
17222
17248
|
nameAliasMap?.set(normalizeName(split.alias), label);
|
|
17223
17249
|
}
|
|
@@ -17226,7 +17252,8 @@ function parseNodeLine(trimmed, lineNum, metaAliasMap, diagnostics, nameAliasMap
|
|
|
17226
17252
|
label,
|
|
17227
17253
|
lineNumber: lineNum,
|
|
17228
17254
|
metadata,
|
|
17229
|
-
...description !== void 0 && { description }
|
|
17255
|
+
...description !== void 0 && { description },
|
|
17256
|
+
...value !== void 0 && { value }
|
|
17230
17257
|
};
|
|
17231
17258
|
}
|
|
17232
17259
|
function splitTargetAndMeta(rest, metaAliasMap) {
|
|
@@ -26348,7 +26375,18 @@ function fitLabelToHeader(label, nodeWidth, maxLines) {
|
|
|
26348
26375
|
const truncated = label.length > maxChars ? label.slice(0, maxChars - 1) + "\u2026" : label;
|
|
26349
26376
|
return { lines: [truncated], fontSize: MIN_NODE_FONT_SIZE };
|
|
26350
26377
|
}
|
|
26351
|
-
function nodeColors(node, tagGroups, activeGroupName, palette, isDark, solid) {
|
|
26378
|
+
function nodeColors(node, tagGroups, activeGroupName, palette, isDark, value, solid) {
|
|
26379
|
+
const neutralFill = mix(palette.bg, palette.text, isDark ? 90 : 95);
|
|
26380
|
+
if (value.active) {
|
|
26381
|
+
const fill3 = node.value !== void 0 ? value.fillForValue(node.value) : neutralFill;
|
|
26382
|
+
const stroke3 = value.hue;
|
|
26383
|
+
const text2 = contrastText(
|
|
26384
|
+
fill3,
|
|
26385
|
+
palette.textOnFillLight,
|
|
26386
|
+
palette.textOnFillDark
|
|
26387
|
+
);
|
|
26388
|
+
return { fill: fill3, stroke: stroke3, text: text2 };
|
|
26389
|
+
}
|
|
26352
26390
|
const tagColor = resolveTagColor(
|
|
26353
26391
|
node.metadata,
|
|
26354
26392
|
[...tagGroups],
|
|
@@ -26457,25 +26495,65 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26457
26495
|
const sGroupLabelZone = sctx.structural(GROUP_LABEL_ZONE);
|
|
26458
26496
|
const sTitleFontSize = sctx.text(TITLE_FONT_SIZE);
|
|
26459
26497
|
const sTitleY = sctx.structural(TITLE_Y);
|
|
26498
|
+
const nodeValues = parsed.nodes.filter((n) => n.value !== void 0).map((n) => n.value);
|
|
26499
|
+
const hasRamp = nodeValues.length > 0;
|
|
26500
|
+
const allNonNegative = hasRamp && nodeValues.every((v) => v >= 0);
|
|
26501
|
+
const rampMin = allNonNegative ? 0 : Math.min(...nodeValues);
|
|
26502
|
+
const rampMax = Math.max(...nodeValues);
|
|
26503
|
+
const rampHue = resolveColor(parsed.boxMetricColor ?? "", palette) ?? palette.primary;
|
|
26504
|
+
const rampBase = isDark ? mix(palette.surface, palette.text, 28) : palette.bg;
|
|
26505
|
+
const fillForValue = (v) => {
|
|
26506
|
+
const t = rampMax > rampMin ? (v - rampMin) / (rampMax - rampMin) : 1;
|
|
26507
|
+
const pct = RAMP_FLOOR + Math.max(0, Math.min(1, t)) * (100 - RAMP_FLOOR);
|
|
26508
|
+
return mix(rampHue, rampBase, pct);
|
|
26509
|
+
};
|
|
26510
|
+
const VALUE_NAME = hasRamp ? parsed.boxMetric?.trim() || "Value" : null;
|
|
26511
|
+
const matchColorGroup = (v) => {
|
|
26512
|
+
const lv = v.trim().toLowerCase();
|
|
26513
|
+
if (lv === "" || lv === "none") return null;
|
|
26514
|
+
const tg = parsed.tagGroups.find((g) => g.name.toLowerCase() === lv);
|
|
26515
|
+
if (tg) return tg.name;
|
|
26516
|
+
if (lv === VALUE_NAME?.toLowerCase()) return VALUE_NAME;
|
|
26517
|
+
return v;
|
|
26518
|
+
};
|
|
26519
|
+
const override = activeTagGroup;
|
|
26520
|
+
let activeGroup;
|
|
26521
|
+
if (override !== void 0) {
|
|
26522
|
+
activeGroup = override === null ? null : matchColorGroup(override);
|
|
26523
|
+
} else if (parsed.options["active-tag"] !== void 0) {
|
|
26524
|
+
activeGroup = matchColorGroup(parsed.options["active-tag"]);
|
|
26525
|
+
} else {
|
|
26526
|
+
activeGroup = VALUE_NAME ?? (parsed.tagGroups.length > 0 ? parsed.tagGroups[0].name : null);
|
|
26527
|
+
}
|
|
26528
|
+
const activeIsValue = VALUE_NAME !== null && activeGroup === VALUE_NAME;
|
|
26529
|
+
const valueGroup = VALUE_NAME !== null ? {
|
|
26530
|
+
name: VALUE_NAME,
|
|
26531
|
+
entries: [],
|
|
26532
|
+
gradient: {
|
|
26533
|
+
min: rampMin,
|
|
26534
|
+
max: rampMax,
|
|
26535
|
+
hue: rampHue,
|
|
26536
|
+
base: rampBase
|
|
26537
|
+
}
|
|
26538
|
+
} : null;
|
|
26539
|
+
const legendGroups = [
|
|
26540
|
+
...valueGroup ? [valueGroup] : [],
|
|
26541
|
+
...parsed.tagGroups
|
|
26542
|
+
];
|
|
26460
26543
|
const reserveHasDescriptions = parsed.nodes.some(
|
|
26461
26544
|
(n) => n.description && n.description.length > 0
|
|
26462
26545
|
);
|
|
26463
|
-
const willRenderLegend =
|
|
26546
|
+
const willRenderLegend = legendGroups.length > 0 || reserveHasDescriptions && controlsHost !== "app";
|
|
26464
26547
|
const sLegendHeight = willRenderLegend ? sctx.structural(
|
|
26465
26548
|
getMaxLegendReservedHeight(
|
|
26466
26549
|
{
|
|
26467
|
-
groups:
|
|
26550
|
+
groups: legendGroups,
|
|
26468
26551
|
position: { placement: "top-center", titleRelation: "below-title" },
|
|
26469
26552
|
mode: exportMode ? "export" : "preview"
|
|
26470
26553
|
},
|
|
26471
26554
|
width
|
|
26472
26555
|
)
|
|
26473
26556
|
) : 0;
|
|
26474
|
-
const activeGroup = resolveActiveTagGroup(
|
|
26475
|
-
parsed.tagGroups,
|
|
26476
|
-
parsed.options["active-tag"],
|
|
26477
|
-
activeTagGroup
|
|
26478
|
-
);
|
|
26479
26557
|
const hidden = hiddenTagValues ?? parsed.initialHiddenTagValues;
|
|
26480
26558
|
const nodeMap = /* @__PURE__ */ new Map();
|
|
26481
26559
|
for (const node of parsed.nodes) nodeMap.set(node.label, node);
|
|
@@ -26486,7 +26564,7 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26486
26564
|
const hasAnyDescriptions = parsed.nodes.some(
|
|
26487
26565
|
(n) => n.description && n.description.length > 0
|
|
26488
26566
|
);
|
|
26489
|
-
const needsLegend =
|
|
26567
|
+
const needsLegend = legendGroups.length > 0 || hasAnyDescriptions && onToggleDescriptions;
|
|
26490
26568
|
const legendH = needsLegend ? sLegendHeight + 8 : 0;
|
|
26491
26569
|
const groupLabelsSet = new Set(layout.groups.map((g) => g.label));
|
|
26492
26570
|
let labelZoneExtension = 0;
|
|
@@ -26692,12 +26770,16 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26692
26770
|
activeGroup,
|
|
26693
26771
|
palette,
|
|
26694
26772
|
isDark,
|
|
26773
|
+
{ active: activeIsValue, hue: rampHue, fillForValue },
|
|
26695
26774
|
parsed.options["solid-fill"] === "on"
|
|
26696
26775
|
);
|
|
26697
26776
|
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);
|
|
26698
26777
|
for (const [key, val] of Object.entries(node.metadata)) {
|
|
26699
26778
|
nodeG.attr(`data-tag-${key.toLowerCase()}`, val.toLowerCase());
|
|
26700
26779
|
}
|
|
26780
|
+
if (node.value !== void 0) {
|
|
26781
|
+
nodeG.attr("data-value", node.value);
|
|
26782
|
+
}
|
|
26701
26783
|
if (onClickItem) {
|
|
26702
26784
|
nodeG.on("click", (event) => {
|
|
26703
26785
|
const target = event.target;
|
|
@@ -26769,6 +26851,22 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26769
26851
|
const tooltipText = fullText.length > 200 ? fullText.slice(0, 199) + "\u2026" : fullText;
|
|
26770
26852
|
nodeG.append("title").text(tooltipText);
|
|
26771
26853
|
}
|
|
26854
|
+
} else if (parsed.showValues && node.value !== void 0) {
|
|
26855
|
+
const valueLabel = parsed.boxMetric ? `${parsed.boxMetric}: ${node.value}` : String(node.value);
|
|
26856
|
+
const headerH = ln.height / 2;
|
|
26857
|
+
const sepY = -ln.height / 2 + headerH;
|
|
26858
|
+
const fitted = fitLabelToHeader(node.label, ln.width, 2);
|
|
26859
|
+
const labelLineH = fitted.fontSize * 1.3;
|
|
26860
|
+
const labelTotalH = fitted.lines.length * labelLineH;
|
|
26861
|
+
const headerCenterY = -ln.height / 2 + headerH / 2;
|
|
26862
|
+
for (let li = 0; li < fitted.lines.length; li++) {
|
|
26863
|
+
nodeG.append("text").attr("x", 0).attr(
|
|
26864
|
+
"y",
|
|
26865
|
+
headerCenterY - labelTotalH / 2 + labelLineH / 2 + li * labelLineH
|
|
26866
|
+
).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]);
|
|
26867
|
+
}
|
|
26868
|
+
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);
|
|
26869
|
+
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);
|
|
26772
26870
|
} else {
|
|
26773
26871
|
const maxLabelLines = Math.max(
|
|
26774
26872
|
2,
|
|
@@ -26781,11 +26879,22 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26781
26879
|
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]);
|
|
26782
26880
|
}
|
|
26783
26881
|
}
|
|
26882
|
+
if (parsed.showValues && node.value !== void 0 && desc && desc.length > 0 && !hideDescriptions) {
|
|
26883
|
+
const valueText = String(node.value);
|
|
26884
|
+
const padX = 6;
|
|
26885
|
+
const padY = 5;
|
|
26886
|
+
const bw = valueText.length * VALUE_FONT_SIZE * CHAR_WIDTH_RATIO2 + 8;
|
|
26887
|
+
const bh = VALUE_FONT_SIZE + 4;
|
|
26888
|
+
const bx = Math.max(-ln.width / 2 + 4, ln.width / 2 - bw - 4);
|
|
26889
|
+
const by = -ln.height / 2 + 4;
|
|
26890
|
+
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);
|
|
26891
|
+
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);
|
|
26892
|
+
}
|
|
26784
26893
|
}
|
|
26785
26894
|
const hasDescriptions = parsed.nodes.some(
|
|
26786
26895
|
(n) => n.description && n.description.length > 0
|
|
26787
26896
|
);
|
|
26788
|
-
const hasLegend =
|
|
26897
|
+
const hasLegend = legendGroups.length > 0 || hasDescriptions && controlsHost !== "app";
|
|
26789
26898
|
if (hasLegend) {
|
|
26790
26899
|
let controlsGroup;
|
|
26791
26900
|
if (hasDescriptions && (onToggleDescriptions || controlsHost === "app")) {
|
|
@@ -26803,7 +26912,7 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26803
26912
|
};
|
|
26804
26913
|
}
|
|
26805
26914
|
const legendConfig = {
|
|
26806
|
-
groups:
|
|
26915
|
+
groups: legendGroups,
|
|
26807
26916
|
position: { placement: "top-center", titleRelation: "below-title" },
|
|
26808
26917
|
mode: exportMode ? "export" : "preview",
|
|
26809
26918
|
// Keep inactive sibling tag groups visible as collapsed pills so the user
|
|
@@ -26858,7 +26967,7 @@ function renderBoxesAndLinesForExport(container, parsed, layout, palette, isDark
|
|
|
26858
26967
|
}
|
|
26859
26968
|
});
|
|
26860
26969
|
}
|
|
26861
|
-
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;
|
|
26970
|
+
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;
|
|
26862
26971
|
var init_renderer6 = __esm({
|
|
26863
26972
|
"src/boxes-and-lines/renderer.ts"() {
|
|
26864
26973
|
"use strict";
|
|
@@ -26867,12 +26976,13 @@ var init_renderer6 = __esm({
|
|
|
26867
26976
|
init_legend_layout();
|
|
26868
26977
|
init_title_constants();
|
|
26869
26978
|
init_color_utils();
|
|
26979
|
+
init_colors();
|
|
26870
26980
|
init_tag_groups();
|
|
26871
26981
|
init_inline_markdown();
|
|
26872
26982
|
init_wrapped_desc();
|
|
26873
26983
|
init_scaling();
|
|
26874
26984
|
DIAGRAM_PADDING6 = 20;
|
|
26875
|
-
NODE_FONT_SIZE =
|
|
26985
|
+
NODE_FONT_SIZE = 11;
|
|
26876
26986
|
MIN_NODE_FONT_SIZE = 9;
|
|
26877
26987
|
EDGE_LABEL_FONT_SIZE4 = 11;
|
|
26878
26988
|
EDGE_STROKE_WIDTH5 = 1.5;
|
|
@@ -26889,6 +26999,8 @@ var init_renderer6 = __esm({
|
|
|
26889
26999
|
GROUP_RX = 8;
|
|
26890
27000
|
GROUP_LABEL_FONT_SIZE = 14;
|
|
26891
27001
|
GROUP_LABEL_ZONE = 32;
|
|
27002
|
+
RAMP_FLOOR = 15;
|
|
27003
|
+
VALUE_FONT_SIZE = 11;
|
|
26892
27004
|
lineGeneratorLR = d3Shape4.line().x((d) => d.x).y((d) => d.y).curve(d3Shape4.curveBasis);
|
|
26893
27005
|
lineGeneratorTB = d3Shape4.line().x((d) => d.x).y((d) => d.y).curve(d3Shape4.curveBasis);
|
|
26894
27006
|
}
|
|
@@ -46607,7 +46719,11 @@ function resolveMap(parsed, data) {
|
|
|
46607
46719
|
if (bb && !isWholeSphere(bb)) containerBoxes.push(bb);
|
|
46608
46720
|
}
|
|
46609
46721
|
const containerUnion = unionExtent(containerBoxes, points);
|
|
46610
|
-
if (containerUnion)
|
|
46722
|
+
if (containerUnion)
|
|
46723
|
+
extent2 = pad(
|
|
46724
|
+
clampContainerToCluster(containerUnion, points),
|
|
46725
|
+
PAD_FRACTION
|
|
46726
|
+
);
|
|
46611
46727
|
}
|
|
46612
46728
|
if (isPoiOnly) {
|
|
46613
46729
|
const cx = (extent2[0][0] + extent2[1][0]) / 2;
|
|
@@ -46688,6 +46804,22 @@ function mostCommonCountry(regions, poiCountries) {
|
|
|
46688
46804
|
}
|
|
46689
46805
|
return best;
|
|
46690
46806
|
}
|
|
46807
|
+
function clampContainerToCluster(container, points) {
|
|
46808
|
+
const poi = unionExtent([], points);
|
|
46809
|
+
if (!poi) return container;
|
|
46810
|
+
let [[west, south], [east, north]] = container;
|
|
46811
|
+
const [[pWest, pSouth], [pEast, pNorth]] = poi;
|
|
46812
|
+
south = Math.max(south, pSouth - CONTAINER_OVERSHOOT_DEG);
|
|
46813
|
+
north = Math.min(north, pNorth + CONTAINER_OVERSHOOT_DEG);
|
|
46814
|
+
if (east <= 180 && pEast <= 180) {
|
|
46815
|
+
west = Math.max(west, pWest - CONTAINER_OVERSHOOT_DEG);
|
|
46816
|
+
east = Math.min(east, pEast + CONTAINER_OVERSHOOT_DEG);
|
|
46817
|
+
}
|
|
46818
|
+
return [
|
|
46819
|
+
[west, south],
|
|
46820
|
+
[east, north]
|
|
46821
|
+
];
|
|
46822
|
+
}
|
|
46691
46823
|
function pad(e, frac) {
|
|
46692
46824
|
const dLon = (e[1][0] - e[0][0]) * frac || 1;
|
|
46693
46825
|
const dLat = (e[1][1] - e[0][1]) * frac || 1;
|
|
@@ -46700,7 +46832,7 @@ function firstError(diags) {
|
|
|
46700
46832
|
const e = diags.find((d) => d.severity === "error");
|
|
46701
46833
|
return e ? formatDgmoError(e) : null;
|
|
46702
46834
|
}
|
|
46703
|
-
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;
|
|
46835
|
+
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;
|
|
46704
46836
|
var init_resolver2 = __esm({
|
|
46705
46837
|
"src/map/resolver.ts"() {
|
|
46706
46838
|
"use strict";
|
|
@@ -46713,6 +46845,7 @@ var init_resolver2 = __esm({
|
|
|
46713
46845
|
WORLD_LAT_SOUTH = -58;
|
|
46714
46846
|
WORLD_LAT_NORTH = 78;
|
|
46715
46847
|
POI_ZOOM_FLOOR_DEG = 7;
|
|
46848
|
+
CONTAINER_OVERSHOOT_DEG = 8;
|
|
46716
46849
|
US_NATIONAL_LON_SPAN = 48;
|
|
46717
46850
|
REGION_ALIASES = {
|
|
46718
46851
|
// Common everyday names → the Natural-Earth display name actually shipped.
|
|
@@ -46791,6 +46924,55 @@ var init_resolver2 = __esm({
|
|
|
46791
46924
|
}
|
|
46792
46925
|
});
|
|
46793
46926
|
|
|
46927
|
+
// src/map/legend-band.ts
|
|
46928
|
+
function mapLegendGroups(legend) {
|
|
46929
|
+
const ramp = legend.ramp;
|
|
46930
|
+
const scoreGroup = ramp ? {
|
|
46931
|
+
name: ramp.metric?.trim() || "Value",
|
|
46932
|
+
entries: [],
|
|
46933
|
+
gradient: {
|
|
46934
|
+
min: ramp.min,
|
|
46935
|
+
max: ramp.max,
|
|
46936
|
+
hue: ramp.hue,
|
|
46937
|
+
base: ramp.base
|
|
46938
|
+
}
|
|
46939
|
+
} : null;
|
|
46940
|
+
const tagGroups = legend.tagGroups.filter((g) => g.entries.length > 0).map((g) => ({ name: g.name, entries: [...g.entries] }));
|
|
46941
|
+
return [...scoreGroup ? [scoreGroup] : [], ...tagGroups];
|
|
46942
|
+
}
|
|
46943
|
+
function mapLegendConfig(groups, mode) {
|
|
46944
|
+
return {
|
|
46945
|
+
groups,
|
|
46946
|
+
position: { placement: "top-center", titleRelation: "below-title" },
|
|
46947
|
+
mode,
|
|
46948
|
+
showEmptyGroups: false,
|
|
46949
|
+
showInactivePills: true
|
|
46950
|
+
};
|
|
46951
|
+
}
|
|
46952
|
+
function mapLegendTop(hasTitle, hasSubtitle) {
|
|
46953
|
+
return (hasTitle ? TITLE_Y + TITLE_FONT_SIZE : 0) + (hasSubtitle ? TITLE_FONT_SIZE : 0) + LEGEND_TOP_GAP2;
|
|
46954
|
+
}
|
|
46955
|
+
function mapLegendBand(legend, opts) {
|
|
46956
|
+
if (!legend) return 0;
|
|
46957
|
+
const groups = mapLegendGroups(legend);
|
|
46958
|
+
if (groups.length === 0) return 0;
|
|
46959
|
+
const config = mapLegendConfig(groups, opts.mode);
|
|
46960
|
+
const state = { activeGroup: legend.activeGroup };
|
|
46961
|
+
const { height } = computeLegendLayout(config, state, opts.width);
|
|
46962
|
+
if (height <= 0) return 0;
|
|
46963
|
+
return mapLegendTop(opts.hasTitle, opts.hasSubtitle) + height + LEGEND_BOTTOM_GAP2;
|
|
46964
|
+
}
|
|
46965
|
+
var LEGEND_TOP_GAP2, LEGEND_BOTTOM_GAP2;
|
|
46966
|
+
var init_legend_band = __esm({
|
|
46967
|
+
"src/map/legend-band.ts"() {
|
|
46968
|
+
"use strict";
|
|
46969
|
+
init_legend_layout();
|
|
46970
|
+
init_title_constants();
|
|
46971
|
+
LEGEND_TOP_GAP2 = 8;
|
|
46972
|
+
LEGEND_BOTTOM_GAP2 = 10;
|
|
46973
|
+
}
|
|
46974
|
+
});
|
|
46975
|
+
|
|
46794
46976
|
// src/map/colorize.ts
|
|
46795
46977
|
function assignColors(isos, adjacency) {
|
|
46796
46978
|
const sorted = [...isos].sort();
|
|
@@ -47231,6 +47413,38 @@ function parsePathRings(d) {
|
|
|
47231
47413
|
if (cur.length) rings.push(cur);
|
|
47232
47414
|
return rings;
|
|
47233
47415
|
}
|
|
47416
|
+
function dropAntimeridianWrapSlivers(d, width, height) {
|
|
47417
|
+
const rings = parsePathRings(d);
|
|
47418
|
+
if (rings.length <= 1) return d;
|
|
47419
|
+
const eps = 0.75;
|
|
47420
|
+
const minArea = 3e-3 * width * height;
|
|
47421
|
+
const ringArea = (r) => {
|
|
47422
|
+
let s = 0;
|
|
47423
|
+
for (let i = 0; i < r.length; i++) {
|
|
47424
|
+
const a = r[i];
|
|
47425
|
+
const b = r[(i + 1) % r.length];
|
|
47426
|
+
s += a[0] * b[1] - b[0] * a[1];
|
|
47427
|
+
}
|
|
47428
|
+
return Math.abs(s) / 2;
|
|
47429
|
+
};
|
|
47430
|
+
const areas = rings.map(ringArea);
|
|
47431
|
+
const maxArea = Math.max(...areas);
|
|
47432
|
+
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;
|
|
47433
|
+
let dropped = false;
|
|
47434
|
+
const kept = rings.filter((r, idx) => {
|
|
47435
|
+
if (areas[idx] >= maxArea || areas[idx] >= minArea) return true;
|
|
47436
|
+
const touches = r.some((p, i) => onVEdge(p, r[(i + 1) % r.length]));
|
|
47437
|
+
if (touches) {
|
|
47438
|
+
dropped = true;
|
|
47439
|
+
return false;
|
|
47440
|
+
}
|
|
47441
|
+
return true;
|
|
47442
|
+
});
|
|
47443
|
+
if (!dropped) return d;
|
|
47444
|
+
return kept.map(
|
|
47445
|
+
(r) => r.map((p, i) => (i ? "L" : "M") + p[0] + "," + p[1]).join("") + "Z"
|
|
47446
|
+
).join("");
|
|
47447
|
+
}
|
|
47234
47448
|
function layoutMap(resolved, data, size, opts) {
|
|
47235
47449
|
const { palette, isDark } = opts;
|
|
47236
47450
|
const { width, height } = size;
|
|
@@ -47314,7 +47528,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47314
47528
|
const rampBase = isDark ? mix(palette.surface, palette.text, 28) : palette.bg;
|
|
47315
47529
|
const fillForValue = (s) => {
|
|
47316
47530
|
const t = rampMax > rampMin ? (s - rampMin) / (rampMax - rampMin) : 1;
|
|
47317
|
-
const pct =
|
|
47531
|
+
const pct = RAMP_FLOOR2 + Math.max(0, Math.min(1, t)) * (100 - RAMP_FLOOR2);
|
|
47318
47532
|
return mix(rampHue, rampBase, pct);
|
|
47319
47533
|
};
|
|
47320
47534
|
const tagFill = (tags, groupName) => {
|
|
@@ -47350,12 +47564,43 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47350
47564
|
return tagFill(r.tags, activeGroup) ?? neutralFill;
|
|
47351
47565
|
};
|
|
47352
47566
|
const regionById = new Map(resolved.regions.map((r) => [r.iso, r]));
|
|
47567
|
+
let legend = null;
|
|
47568
|
+
if (!resolved.directives.noLegend) {
|
|
47569
|
+
const legendTagGroups = resolved.tagGroups.map((g) => ({
|
|
47570
|
+
name: g.name,
|
|
47571
|
+
entries: g.entries.map((e) => ({ value: e.value, color: e.color }))
|
|
47572
|
+
}));
|
|
47573
|
+
if (legendTagGroups.length > 0 || hasRamp) {
|
|
47574
|
+
legend = {
|
|
47575
|
+
tagGroups: legendTagGroups,
|
|
47576
|
+
activeGroup,
|
|
47577
|
+
...hasRamp && {
|
|
47578
|
+
ramp: {
|
|
47579
|
+
...resolved.directives.regionMetric !== void 0 && {
|
|
47580
|
+
metric: resolved.directives.regionMetric
|
|
47581
|
+
},
|
|
47582
|
+
min: rampMin,
|
|
47583
|
+
max: rampMax,
|
|
47584
|
+
hue: rampHue,
|
|
47585
|
+
base: rampBase
|
|
47586
|
+
}
|
|
47587
|
+
}
|
|
47588
|
+
};
|
|
47589
|
+
}
|
|
47590
|
+
}
|
|
47353
47591
|
const TITLE_GAP2 = 16;
|
|
47354
47592
|
let topPad = FIT_PAD;
|
|
47355
47593
|
if (resolved.title && resolved.pois.length > 0) {
|
|
47356
47594
|
const bannerBottom = (resolved.subtitle ? TITLE_Y + TITLE_FONT_SIZE : TITLE_Y) + TITLE_FONT_SIZE / 2;
|
|
47357
47595
|
topPad = Math.max(FIT_PAD, bannerBottom + TITLE_GAP2);
|
|
47358
47596
|
}
|
|
47597
|
+
const legendBand = mapLegendBand(legend, {
|
|
47598
|
+
width,
|
|
47599
|
+
mode: opts.legendMode ?? "preview",
|
|
47600
|
+
hasTitle: Boolean(resolved.title),
|
|
47601
|
+
hasSubtitle: Boolean(resolved.subtitle)
|
|
47602
|
+
});
|
|
47603
|
+
if (legendBand > topPad) topPad = legendBand;
|
|
47359
47604
|
const fitBox = [
|
|
47360
47605
|
[FIT_PAD, topPad],
|
|
47361
47606
|
[
|
|
@@ -47373,10 +47618,11 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47373
47618
|
const by0 = cb[0][1];
|
|
47374
47619
|
const cw = cb[1][0] - bx0;
|
|
47375
47620
|
const ch = cb[1][1] - by0;
|
|
47376
|
-
const
|
|
47377
|
-
const
|
|
47378
|
-
const
|
|
47379
|
-
const
|
|
47621
|
+
const topReserve = resolved.title && resolved.pois.length > 0 || legendBand > 0 ? topPad : 0;
|
|
47622
|
+
const ox = 0;
|
|
47623
|
+
const oy = topReserve;
|
|
47624
|
+
const sx = cw > 0 ? width / cw : 1;
|
|
47625
|
+
const sy = ch > 0 ? (height - topReserve) / ch : 1;
|
|
47380
47626
|
stretchParams = { sx, sy, ox, oy, bx0, by0 };
|
|
47381
47627
|
const stretch = (x, y) => [
|
|
47382
47628
|
ox + (x - bx0) * sx,
|
|
@@ -47649,7 +47895,8 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47649
47895
|
const r = regionById.get(iso);
|
|
47650
47896
|
const viewF = shouldCull ? cullFeatureToView(f) : dropFrameFillers(f);
|
|
47651
47897
|
if (!viewF) continue;
|
|
47652
|
-
const
|
|
47898
|
+
const raw = path(viewF) ?? "";
|
|
47899
|
+
const d = fitIsGlobal ? dropAntimeridianWrapSlivers(raw, width, height) : raw;
|
|
47653
47900
|
if (!d) continue;
|
|
47654
47901
|
const isThisLayer = r?.layer === layerKind;
|
|
47655
47902
|
const isForeign = layerKind === "country" && usContext && iso !== "US";
|
|
@@ -47666,6 +47913,9 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47666
47913
|
} else {
|
|
47667
47914
|
label = f.properties?.name;
|
|
47668
47915
|
}
|
|
47916
|
+
const labelAnchor = WORLD_LABEL_ANCHORS[iso];
|
|
47917
|
+
const c = labelAnchor ? project(labelAnchor[0], labelAnchor[1]) : path.centroid(viewF);
|
|
47918
|
+
const hasCentroid = c != null && Number.isFinite(c[0]) && Number.isFinite(c[1]);
|
|
47669
47919
|
regions.push({
|
|
47670
47920
|
id: iso,
|
|
47671
47921
|
d,
|
|
@@ -47674,6 +47924,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47674
47924
|
lineNumber,
|
|
47675
47925
|
layer,
|
|
47676
47926
|
...label !== void 0 && { label },
|
|
47927
|
+
...hasCentroid && { labelX: c[0], labelY: c[1] },
|
|
47677
47928
|
...isThisLayer && r.value !== void 0 && { value: r.value },
|
|
47678
47929
|
...isThisLayer && Object.keys(r.tags).length > 0 && { tags: r.tags }
|
|
47679
47930
|
});
|
|
@@ -48114,10 +48365,6 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
48114
48365
|
lineNumber
|
|
48115
48366
|
});
|
|
48116
48367
|
};
|
|
48117
|
-
const WORLD_LABEL_ANCHORS = {
|
|
48118
|
-
US: [-98.5, 39.5]
|
|
48119
|
-
// CONUS geographic centre (near Lebanon, Kansas)
|
|
48120
|
-
};
|
|
48121
48368
|
const REGION_LABEL_GAP = 2;
|
|
48122
48369
|
const regionLabelRect = (cx, cy, text) => {
|
|
48123
48370
|
const w = measureLegendText(text, FONT2) + 2 * REGION_LABEL_GAP;
|
|
@@ -48435,30 +48682,6 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
48435
48682
|
});
|
|
48436
48683
|
labels.push(...contextLabels);
|
|
48437
48684
|
}
|
|
48438
|
-
let legend = null;
|
|
48439
|
-
if (!resolved.directives.noLegend) {
|
|
48440
|
-
const tagGroups = resolved.tagGroups.map((g) => ({
|
|
48441
|
-
name: g.name,
|
|
48442
|
-
entries: g.entries.map((e) => ({ value: e.value, color: e.color }))
|
|
48443
|
-
}));
|
|
48444
|
-
if (tagGroups.length > 0 || hasRamp) {
|
|
48445
|
-
legend = {
|
|
48446
|
-
tagGroups,
|
|
48447
|
-
activeGroup,
|
|
48448
|
-
...hasRamp && {
|
|
48449
|
-
ramp: {
|
|
48450
|
-
...resolved.directives.regionMetric !== void 0 && {
|
|
48451
|
-
metric: resolved.directives.regionMetric
|
|
48452
|
-
},
|
|
48453
|
-
min: rampMin,
|
|
48454
|
-
max: rampMax,
|
|
48455
|
-
hue: rampHue,
|
|
48456
|
-
base: rampBase
|
|
48457
|
-
}
|
|
48458
|
-
}
|
|
48459
|
-
};
|
|
48460
|
-
}
|
|
48461
|
-
}
|
|
48462
48685
|
return {
|
|
48463
48686
|
width,
|
|
48464
48687
|
height,
|
|
@@ -48483,7 +48706,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
48483
48706
|
diagnostics: []
|
|
48484
48707
|
};
|
|
48485
48708
|
}
|
|
48486
|
-
var FIT_PAD,
|
|
48709
|
+
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;
|
|
48487
48710
|
var init_layout15 = __esm({
|
|
48488
48711
|
"src/map/layout.ts"() {
|
|
48489
48712
|
"use strict";
|
|
@@ -48494,15 +48717,20 @@ var init_layout15 = __esm({
|
|
|
48494
48717
|
init_label_layout();
|
|
48495
48718
|
init_legend_constants();
|
|
48496
48719
|
init_title_constants();
|
|
48720
|
+
init_legend_band();
|
|
48497
48721
|
init_context_labels();
|
|
48498
48722
|
FIT_PAD = 24;
|
|
48499
|
-
|
|
48723
|
+
RAMP_FLOOR2 = 15;
|
|
48500
48724
|
R_DEFAULT = 6;
|
|
48501
48725
|
R_MIN = 4;
|
|
48502
48726
|
R_MAX = 22;
|
|
48503
48727
|
W_MIN = 1.25;
|
|
48504
48728
|
W_MAX = 8;
|
|
48505
48729
|
FONT2 = 11;
|
|
48730
|
+
WORLD_LABEL_ANCHORS = {
|
|
48731
|
+
US: [-98.5, 39.5]
|
|
48732
|
+
// CONUS geographic centre (near Lebanon, Kansas)
|
|
48733
|
+
};
|
|
48506
48734
|
MAX_CLUSTER_EXTENT_FACTOR = 0.18;
|
|
48507
48735
|
MAX_COLUMN_ROWS = 7;
|
|
48508
48736
|
REGION_LABEL_HALO_RATIO = 4.5;
|
|
@@ -48516,9 +48744,9 @@ var init_layout15 = __esm({
|
|
|
48516
48744
|
COMPACT_WIDTH_PX = 480;
|
|
48517
48745
|
RELIEF_MIN_AREA = 12;
|
|
48518
48746
|
RELIEF_MIN_DIM = 2;
|
|
48519
|
-
RELIEF_HATCH_SPACING =
|
|
48520
|
-
RELIEF_HATCH_WIDTH = 0.
|
|
48521
|
-
RELIEF_HATCH_STRENGTH =
|
|
48747
|
+
RELIEF_HATCH_SPACING = 1.5;
|
|
48748
|
+
RELIEF_HATCH_WIDTH = 0.2;
|
|
48749
|
+
RELIEF_HATCH_STRENGTH = 26;
|
|
48522
48750
|
COASTLINE_RING_COUNT = 5;
|
|
48523
48751
|
COASTLINE_D0 = 16e-4;
|
|
48524
48752
|
COASTLINE_STEP = 28e-4;
|
|
@@ -48597,7 +48825,47 @@ function ringToPath(ring) {
|
|
|
48597
48825
|
d += (i ? "L" : "M") + ring[i][0] + "," + ring[i][1];
|
|
48598
48826
|
return d + "Z";
|
|
48599
48827
|
}
|
|
48600
|
-
function
|
|
48828
|
+
function polylineToPath(pts) {
|
|
48829
|
+
let d = "";
|
|
48830
|
+
for (let i = 0; i < pts.length; i++)
|
|
48831
|
+
d += (i ? "L" : "M") + pts[i][0] + "," + pts[i][1];
|
|
48832
|
+
return d;
|
|
48833
|
+
}
|
|
48834
|
+
function ringToCoastPaths(ring, frame) {
|
|
48835
|
+
if (!frame) return [ringToPath(ring)];
|
|
48836
|
+
const n = ring.length;
|
|
48837
|
+
const eps = 0.75;
|
|
48838
|
+
const onL = (x) => Math.abs(x) <= eps;
|
|
48839
|
+
const onR = (x) => Math.abs(x - frame.w) <= eps;
|
|
48840
|
+
const onT = (y) => Math.abs(y) <= eps;
|
|
48841
|
+
const onB = (y) => Math.abs(y - frame.h) <= eps;
|
|
48842
|
+
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]);
|
|
48843
|
+
let firstBreak = -1;
|
|
48844
|
+
for (let i = 0; i < n; i++)
|
|
48845
|
+
if (isFrameEdge(ring[i], ring[(i + 1) % n])) {
|
|
48846
|
+
firstBreak = i;
|
|
48847
|
+
break;
|
|
48848
|
+
}
|
|
48849
|
+
if (firstBreak === -1) return [ringToPath(ring)];
|
|
48850
|
+
const paths = [];
|
|
48851
|
+
let cur = [];
|
|
48852
|
+
const start = (firstBreak + 1) % n;
|
|
48853
|
+
for (let k = 0; k < n; k++) {
|
|
48854
|
+
const i = (start + k) % n;
|
|
48855
|
+
const a = ring[i];
|
|
48856
|
+
const b = ring[(i + 1) % n];
|
|
48857
|
+
if (isFrameEdge(a, b)) {
|
|
48858
|
+
if (cur.length >= 2) paths.push(polylineToPath(cur));
|
|
48859
|
+
cur = [];
|
|
48860
|
+
continue;
|
|
48861
|
+
}
|
|
48862
|
+
if (cur.length === 0) cur.push(a);
|
|
48863
|
+
cur.push(b);
|
|
48864
|
+
}
|
|
48865
|
+
if (cur.length >= 2) paths.push(polylineToPath(cur));
|
|
48866
|
+
return paths;
|
|
48867
|
+
}
|
|
48868
|
+
function coastlineOuterRings(regions, minExtent, frame) {
|
|
48601
48869
|
const paths = [];
|
|
48602
48870
|
for (const r of regions) {
|
|
48603
48871
|
const rings = parsePathRings(r.d);
|
|
@@ -48620,7 +48888,7 @@ function coastlineOuterRings(regions, minExtent) {
|
|
|
48620
48888
|
for (let j = 0; j < rings.length; j++)
|
|
48621
48889
|
if (j !== i && pointInRing2(fx, fy, rings[j])) depth++;
|
|
48622
48890
|
if (depth % 2 === 1) continue;
|
|
48623
|
-
paths.push(
|
|
48891
|
+
paths.push(...ringToCoastPaths(ring, frame));
|
|
48624
48892
|
}
|
|
48625
48893
|
}
|
|
48626
48894
|
return paths;
|
|
@@ -48650,6 +48918,9 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
48650
48918
|
// stretch-distorting. The in-app preview pane passes no exportDims → unset →
|
|
48651
48919
|
// keeps the global stretch-fill.
|
|
48652
48920
|
preferContain: exportDims?.preferContain ?? false,
|
|
48921
|
+
// Reserve the legend band for the mode actually drawn below (export shows
|
|
48922
|
+
// only the active group; preview keeps the inactive pills).
|
|
48923
|
+
legendMode: exportDims ? "export" : "preview",
|
|
48653
48924
|
...activeGroupOverride !== void 0 && {
|
|
48654
48925
|
activeGroup: activeGroupOverride
|
|
48655
48926
|
}
|
|
@@ -48664,6 +48935,10 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
48664
48935
|
const drawRegion = (g, r, strokeWidth) => {
|
|
48665
48936
|
const p = g.append("path").attr("d", r.d).attr("fill", r.fill).attr("stroke", r.stroke).attr("stroke-width", strokeWidth);
|
|
48666
48937
|
if (r.label) p.attr("data-region-name", r.label);
|
|
48938
|
+
if (r.id && r.id !== "lake") p.attr("data-iso", r.id);
|
|
48939
|
+
if (r.labelX !== void 0 && r.labelY !== void 0) {
|
|
48940
|
+
p.attr("data-label-x", r.labelX).attr("data-label-y", r.labelY);
|
|
48941
|
+
}
|
|
48667
48942
|
if (r.layer !== "base") {
|
|
48668
48943
|
p.classed("dgmo-map-region", true).attr("data-region", r.id);
|
|
48669
48944
|
if (r.value !== void 0) p.attr("data-value", r.value);
|
|
@@ -48693,7 +48968,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
48693
48968
|
const landClip = defs.append("clipPath").attr("id", landClipId);
|
|
48694
48969
|
for (const r of layout.regions)
|
|
48695
48970
|
if (r.id !== "lake") landClip.append("path").attr("d", r.d);
|
|
48696
|
-
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");
|
|
48971
|
+
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");
|
|
48697
48972
|
for (let y = h.spacing; y < height; y += h.spacing) {
|
|
48698
48973
|
gRelief.append("line").attr("x1", 0).attr("y1", y).attr("x2", width).attr("y2", y);
|
|
48699
48974
|
}
|
|
@@ -48714,10 +48989,16 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
48714
48989
|
mask.append("path").attr("d", d).attr("fill", "black").attr("stroke", "black").attr("stroke-width", 2 * reach).attr("stroke-linejoin", "round");
|
|
48715
48990
|
}
|
|
48716
48991
|
}
|
|
48717
|
-
const gWater = svg.append("g").attr("class", "dgmo-map-water-lines").attr("fill", "none").attr("mask", `url(#${maskId})`);
|
|
48992
|
+
const gWater = svg.append("g").attr("class", "dgmo-map-water-lines").attr("fill", "none").style("pointer-events", "none").attr("mask", `url(#${maskId})`);
|
|
48718
48993
|
appendWaterLines(
|
|
48719
48994
|
gWater,
|
|
48720
|
-
|
|
48995
|
+
// Pass the canvas frame so edges collinear with it (the antimeridian on a
|
|
48996
|
+
// world map, regional clipExtent cuts) don't get ringed as fake coast —
|
|
48997
|
+
// land runs cleanly to the render-area edge.
|
|
48998
|
+
coastlineOuterRings(layout.regions, cs.minExtent, {
|
|
48999
|
+
w: width,
|
|
49000
|
+
h: height
|
|
49001
|
+
}),
|
|
48721
49002
|
cs,
|
|
48722
49003
|
layout.background
|
|
48723
49004
|
);
|
|
@@ -48731,7 +49012,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
48731
49012
|
gWater.append("path").attr("d", ds.join(" ")).attr("stroke", stroke2).attr("stroke-width", 0.5).attr("stroke-linejoin", "round");
|
|
48732
49013
|
}
|
|
48733
49014
|
if (layout.rivers.length) {
|
|
48734
|
-
const gRivers = svg.append("g").attr("class", "dgmo-map-rivers").attr("fill", "none");
|
|
49015
|
+
const gRivers = svg.append("g").attr("class", "dgmo-map-rivers").attr("fill", "none").style("pointer-events", "none");
|
|
48735
49016
|
for (const r of layout.rivers) {
|
|
48736
49017
|
gRivers.append("path").attr("d", r.d).attr("stroke", r.color).attr("stroke-width", r.width).attr("stroke-linecap", "round").attr("stroke-linejoin", "round");
|
|
48737
49018
|
}
|
|
@@ -48772,7 +49053,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
48772
49053
|
const d = box.points.map((p, i) => `${i ? "L" : "M"}${p[0]},${p[1]}`).join("") + "Z";
|
|
48773
49054
|
clip.append("path").attr("d", d);
|
|
48774
49055
|
}
|
|
48775
|
-
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})`);
|
|
49056
|
+
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})`);
|
|
48776
49057
|
appendWaterLines(
|
|
48777
49058
|
gInsetWater,
|
|
48778
49059
|
coastlineOuterRings(layout.insetRegions, cs.minExtent),
|
|
@@ -48931,30 +49212,12 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
48931
49212
|
if (layout.legend) {
|
|
48932
49213
|
const legendY = (layout.title ? TITLE_Y + TITLE_FONT_SIZE : 0) + (layout.subtitle ? TITLE_FONT_SIZE : 0) + 8;
|
|
48933
49214
|
const legendG = svg.append("g").attr("class", "dgmo-map-legend").attr("transform", `translate(0, ${legendY})`);
|
|
48934
|
-
const
|
|
48935
|
-
const scoreGroup = ramp ? {
|
|
48936
|
-
name: ramp.metric?.trim() || "Value",
|
|
48937
|
-
entries: [],
|
|
48938
|
-
gradient: {
|
|
48939
|
-
min: ramp.min,
|
|
48940
|
-
max: ramp.max,
|
|
48941
|
-
hue: ramp.hue,
|
|
48942
|
-
base: ramp.base
|
|
48943
|
-
}
|
|
48944
|
-
} : null;
|
|
48945
|
-
const tagGroups = layout.legend.tagGroups.filter((g) => g.entries.length > 0).map((g) => ({ name: g.name, entries: [...g.entries] }));
|
|
48946
|
-
const groups = [...scoreGroup ? [scoreGroup] : [], ...tagGroups];
|
|
49215
|
+
const groups = mapLegendGroups(layout.legend);
|
|
48947
49216
|
if (groups.length > 0) {
|
|
48948
|
-
const config =
|
|
49217
|
+
const config = mapLegendConfig(
|
|
48949
49218
|
groups,
|
|
48950
|
-
|
|
48951
|
-
|
|
48952
|
-
showEmptyGroups: false,
|
|
48953
|
-
// Keep inactive siblings visible as pills so the user can click to flip
|
|
48954
|
-
// the active colouring dimension (preview only — export shows just the
|
|
48955
|
-
// active group).
|
|
48956
|
-
showInactivePills: true
|
|
48957
|
-
};
|
|
49219
|
+
exportDims ? "export" : "preview"
|
|
49220
|
+
);
|
|
48958
49221
|
const state = { activeGroup: layout.legend.activeGroup };
|
|
48959
49222
|
renderLegendD3(legendG, config, state, palette, isDark, void 0, width);
|
|
48960
49223
|
}
|
|
@@ -48998,6 +49261,7 @@ var init_renderer16 = __esm({
|
|
|
48998
49261
|
init_title_constants();
|
|
48999
49262
|
init_color_utils();
|
|
49000
49263
|
init_legend_d3();
|
|
49264
|
+
init_legend_band();
|
|
49001
49265
|
init_layout15();
|
|
49002
49266
|
LABEL_FONT = 11;
|
|
49003
49267
|
}
|
|
@@ -49019,9 +49283,10 @@ function mapContentAspect(resolved, data, ref = REF) {
|
|
|
49019
49283
|
const aspect = w / h;
|
|
49020
49284
|
return Number.isFinite(aspect) && aspect > 0 ? aspect : FALLBACK_ASPECT;
|
|
49021
49285
|
}
|
|
49022
|
-
function mapExportDimensions(resolved, data, baseWidth = 1200) {
|
|
49023
|
-
const
|
|
49024
|
-
const
|
|
49286
|
+
function mapExportDimensions(resolved, data, baseWidth = 1200, aspectOverride) {
|
|
49287
|
+
const useOverride = aspectOverride !== void 0 && Number.isFinite(aspectOverride) && aspectOverride > 0;
|
|
49288
|
+
const raw = useOverride ? aspectOverride : mapContentAspect(resolved, data);
|
|
49289
|
+
const clamped = useOverride ? raw : Math.max(ASPECT_MIN, Math.min(ASPECT_MAX, raw));
|
|
49025
49290
|
const width = baseWidth;
|
|
49026
49291
|
let height = Math.round(width / clamped);
|
|
49027
49292
|
let chromeReserve = 0;
|
|
@@ -49034,7 +49299,7 @@ function mapExportDimensions(resolved, data, baseWidth = 1200) {
|
|
|
49034
49299
|
height = Math.round(chromeReserve + MIN_MAP_BAND);
|
|
49035
49300
|
floored = true;
|
|
49036
49301
|
}
|
|
49037
|
-
const preferContain = clamped !== raw || floored;
|
|
49302
|
+
const preferContain = useOverride ? floored : clamped !== raw || floored;
|
|
49038
49303
|
return { width, height, preferContain };
|
|
49039
49304
|
}
|
|
49040
49305
|
var FIT_PAD2, TITLE_GAP, ASPECT_MAX, ASPECT_MIN, MIN_MAP_BAND, FALLBACK_ASPECT, REF;
|
|
@@ -54744,7 +55009,6 @@ function renderTimelineTagLegendOverlay(container, parsed, palette, isDark, setu
|
|
|
54744
55009
|
function renderTimelineHorizontalTimeSort(container, parsed, palette, isDark, setup, hovers, onClickItem, _exportDims, _swimlaneTagGroup, _activeTagGroup, _onTagStateChange, _viewMode) {
|
|
54745
55010
|
const {
|
|
54746
55011
|
width,
|
|
54747
|
-
height,
|
|
54748
55012
|
tooltip,
|
|
54749
55013
|
solid,
|
|
54750
55014
|
textColor,
|
|
@@ -54793,10 +55057,11 @@ function renderTimelineHorizontalTimeSort(container, parsed, palette, isDark, se
|
|
|
54793
55057
|
const markerLabelY = markerReserve ? -(topScaleH + MARKER_ROW_H / 2) : 0;
|
|
54794
55058
|
const eraLabelY = eraReserve ? -(topScaleH + markerReserve + ERA_ROW_H / 2) : 0;
|
|
54795
55059
|
const innerWidth = width - margin.left - margin.right;
|
|
54796
|
-
const
|
|
54797
|
-
const
|
|
55060
|
+
const rowH = ctx.structural(28);
|
|
55061
|
+
const innerHeight = rowH * sorted.length;
|
|
55062
|
+
const usedHeight = margin.top + innerHeight + margin.bottom;
|
|
54798
55063
|
const xScale = d3Scale2.scaleLinear().domain([minDate - datePadding, maxDate + datePadding]).range([0, innerWidth]);
|
|
54799
|
-
const svg = d3Selection23.select(container).append("svg").attr("width", width).attr("height",
|
|
55064
|
+
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);
|
|
54800
55065
|
if (ctx.isBelowFloor) {
|
|
54801
55066
|
svg.attr("width", "100%");
|
|
54802
55067
|
}
|
|
@@ -57317,7 +57582,12 @@ async function renderForExport(content, theme, palette, viewState, options) {
|
|
|
57317
57582
|
}
|
|
57318
57583
|
}
|
|
57319
57584
|
const mapResolved = resolveMap2(mapParsed, mapData);
|
|
57320
|
-
const dims2 = mapExportDimensions2(
|
|
57585
|
+
const dims2 = mapExportDimensions2(
|
|
57586
|
+
mapResolved,
|
|
57587
|
+
mapData,
|
|
57588
|
+
EXPORT_WIDTH,
|
|
57589
|
+
options?.mapAspect
|
|
57590
|
+
);
|
|
57321
57591
|
const container2 = createExportContainer(dims2.width, dims2.height);
|
|
57322
57592
|
renderMapForExport2(
|
|
57323
57593
|
container2,
|
|
@@ -58308,6 +58578,9 @@ var DIRECTIVE_KEYWORDS = /* @__PURE__ */ new Set([
|
|
|
58308
58578
|
"hide",
|
|
58309
58579
|
"mode",
|
|
58310
58580
|
"direction",
|
|
58581
|
+
// Boxes-and-lines
|
|
58582
|
+
"box-metric",
|
|
58583
|
+
"show-values",
|
|
58311
58584
|
// ER
|
|
58312
58585
|
"notation",
|
|
58313
58586
|
// Class
|
|
@@ -59030,7 +59303,7 @@ pre.dgmo, code.language-dgmo, pre > code.language-dgmo,
|
|
|
59030
59303
|
|
|
59031
59304
|
// src/auto/index.ts
|
|
59032
59305
|
init_safe_href();
|
|
59033
|
-
var VERSION = "0.
|
|
59306
|
+
var VERSION = "0.24.0";
|
|
59034
59307
|
var DEFAULTS = {
|
|
59035
59308
|
theme: "auto",
|
|
59036
59309
|
palette: "nord",
|