@diagrammo/dgmo 0.22.0 → 0.23.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 +238 -48
- package/dist/advanced.d.cts +17 -0
- package/dist/advanced.d.ts +17 -0
- package/dist/advanced.js +238 -48
- package/dist/auto.cjs +236 -42
- package/dist/auto.js +115 -115
- package/dist/auto.mjs +236 -42
- package/dist/cli.cjs +153 -153
- 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 +232 -41
- package/dist/index.js +232 -41
- package/dist/internal.cjs +238 -48
- package/dist/internal.d.cts +17 -0
- package/dist/internal.d.ts +17 -0
- package/dist/internal.js +238 -48
- 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 +35 -0
- 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 +171 -13
- package/src/boxes-and-lines/types.ts +9 -0
- package/src/completion.ts +4 -5
- package/src/d3.ts +12 -4
- package/src/editor/keywords.ts +3 -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/layout.ts +111 -18
- package/src/map/renderer.ts +95 -4
- package/src/utils/reserved-key-registry.ts +5 -3
package/dist/index.js
CHANGED
|
@@ -893,9 +893,7 @@ var init_reserved_key_registry = __esm({
|
|
|
893
893
|
BOXES_AND_LINES_REGISTRY = staticRegistry([
|
|
894
894
|
"color",
|
|
895
895
|
"description",
|
|
896
|
-
"
|
|
897
|
-
"split",
|
|
898
|
-
"fanout"
|
|
896
|
+
"value"
|
|
899
897
|
]);
|
|
900
898
|
TIMELINE_REGISTRY = staticRegistry([
|
|
901
899
|
"color",
|
|
@@ -16915,6 +16913,21 @@ function parseBoxesAndLines(content) {
|
|
|
16915
16913
|
}
|
|
16916
16914
|
continue;
|
|
16917
16915
|
}
|
|
16916
|
+
if (!contentStarted) {
|
|
16917
|
+
const metricMatch = trimmed.match(/^box-metric\s+(.+)$/i);
|
|
16918
|
+
if (metricMatch) {
|
|
16919
|
+
const { label, colorName } = peelTrailingColorName(
|
|
16920
|
+
metricMatch[1].trim()
|
|
16921
|
+
);
|
|
16922
|
+
result.boxMetric = label;
|
|
16923
|
+
if (colorName !== void 0) result.boxMetricColor = colorName;
|
|
16924
|
+
continue;
|
|
16925
|
+
}
|
|
16926
|
+
if (/^show-values$/i.test(trimmed)) {
|
|
16927
|
+
result.showValues = true;
|
|
16928
|
+
continue;
|
|
16929
|
+
}
|
|
16930
|
+
}
|
|
16918
16931
|
if (!contentStarted) {
|
|
16919
16932
|
const optMatch = trimmed.match(OPTION_NOCOLON_RE);
|
|
16920
16933
|
if (optMatch) {
|
|
@@ -17293,6 +17306,19 @@ function parseNodeLine(trimmed, lineNum, metaAliasMap, diagnostics, nameAliasMap
|
|
|
17293
17306
|
description = [metadata["description"]];
|
|
17294
17307
|
delete metadata["description"];
|
|
17295
17308
|
}
|
|
17309
|
+
let value;
|
|
17310
|
+
if (metadata["value"] !== void 0) {
|
|
17311
|
+
const raw = metadata["value"];
|
|
17312
|
+
const num = Number(raw);
|
|
17313
|
+
if (Number.isFinite(num)) {
|
|
17314
|
+
value = num;
|
|
17315
|
+
} else {
|
|
17316
|
+
diagnostics.push(
|
|
17317
|
+
makeDgmoError(lineNum, `value must be a number (got "${raw}")`, "error")
|
|
17318
|
+
);
|
|
17319
|
+
}
|
|
17320
|
+
delete metadata["value"];
|
|
17321
|
+
}
|
|
17296
17322
|
if (split.alias) {
|
|
17297
17323
|
nameAliasMap?.set(normalizeName(split.alias), label);
|
|
17298
17324
|
}
|
|
@@ -17301,7 +17327,8 @@ function parseNodeLine(trimmed, lineNum, metaAliasMap, diagnostics, nameAliasMap
|
|
|
17301
17327
|
label,
|
|
17302
17328
|
lineNumber: lineNum,
|
|
17303
17329
|
metadata,
|
|
17304
|
-
...description !== void 0 && { description }
|
|
17330
|
+
...description !== void 0 && { description },
|
|
17331
|
+
...value !== void 0 && { value }
|
|
17305
17332
|
};
|
|
17306
17333
|
}
|
|
17307
17334
|
function splitTargetAndMeta(rest, metaAliasMap) {
|
|
@@ -26423,7 +26450,18 @@ function fitLabelToHeader(label, nodeWidth, maxLines) {
|
|
|
26423
26450
|
const truncated = label.length > maxChars ? label.slice(0, maxChars - 1) + "\u2026" : label;
|
|
26424
26451
|
return { lines: [truncated], fontSize: MIN_NODE_FONT_SIZE };
|
|
26425
26452
|
}
|
|
26426
|
-
function nodeColors(node, tagGroups, activeGroupName, palette, isDark, solid) {
|
|
26453
|
+
function nodeColors(node, tagGroups, activeGroupName, palette, isDark, value, solid) {
|
|
26454
|
+
const neutralFill = mix(palette.bg, palette.text, isDark ? 90 : 95);
|
|
26455
|
+
if (value.active) {
|
|
26456
|
+
const fill3 = node.value !== void 0 ? value.fillForValue(node.value) : neutralFill;
|
|
26457
|
+
const stroke3 = value.hue;
|
|
26458
|
+
const text2 = contrastText(
|
|
26459
|
+
fill3,
|
|
26460
|
+
palette.textOnFillLight,
|
|
26461
|
+
palette.textOnFillDark
|
|
26462
|
+
);
|
|
26463
|
+
return { fill: fill3, stroke: stroke3, text: text2 };
|
|
26464
|
+
}
|
|
26427
26465
|
const tagColor = resolveTagColor(
|
|
26428
26466
|
node.metadata,
|
|
26429
26467
|
[...tagGroups],
|
|
@@ -26532,25 +26570,65 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26532
26570
|
const sGroupLabelZone = sctx.structural(GROUP_LABEL_ZONE);
|
|
26533
26571
|
const sTitleFontSize = sctx.text(TITLE_FONT_SIZE);
|
|
26534
26572
|
const sTitleY = sctx.structural(TITLE_Y);
|
|
26573
|
+
const nodeValues = parsed.nodes.filter((n) => n.value !== void 0).map((n) => n.value);
|
|
26574
|
+
const hasRamp = nodeValues.length > 0;
|
|
26575
|
+
const allNonNegative = hasRamp && nodeValues.every((v) => v >= 0);
|
|
26576
|
+
const rampMin = allNonNegative ? 0 : Math.min(...nodeValues);
|
|
26577
|
+
const rampMax = Math.max(...nodeValues);
|
|
26578
|
+
const rampHue = resolveColor(parsed.boxMetricColor ?? "", palette) ?? palette.primary;
|
|
26579
|
+
const rampBase = isDark ? mix(palette.surface, palette.text, 28) : palette.bg;
|
|
26580
|
+
const fillForValue = (v) => {
|
|
26581
|
+
const t = rampMax > rampMin ? (v - rampMin) / (rampMax - rampMin) : 1;
|
|
26582
|
+
const pct = RAMP_FLOOR + Math.max(0, Math.min(1, t)) * (100 - RAMP_FLOOR);
|
|
26583
|
+
return mix(rampHue, rampBase, pct);
|
|
26584
|
+
};
|
|
26585
|
+
const VALUE_NAME = hasRamp ? parsed.boxMetric?.trim() || "Value" : null;
|
|
26586
|
+
const matchColorGroup = (v) => {
|
|
26587
|
+
const lv = v.trim().toLowerCase();
|
|
26588
|
+
if (lv === "none") return null;
|
|
26589
|
+
const tg = parsed.tagGroups.find((g) => g.name.toLowerCase() === lv);
|
|
26590
|
+
if (tg) return tg.name;
|
|
26591
|
+
if (lv === VALUE_NAME?.toLowerCase()) return VALUE_NAME;
|
|
26592
|
+
return v;
|
|
26593
|
+
};
|
|
26594
|
+
const override = activeTagGroup;
|
|
26595
|
+
let activeGroup;
|
|
26596
|
+
if (override !== void 0) {
|
|
26597
|
+
activeGroup = override === null ? null : matchColorGroup(override);
|
|
26598
|
+
} else if (parsed.options["active-tag"] !== void 0) {
|
|
26599
|
+
activeGroup = matchColorGroup(parsed.options["active-tag"]);
|
|
26600
|
+
} else {
|
|
26601
|
+
activeGroup = VALUE_NAME ?? (parsed.tagGroups.length > 0 ? parsed.tagGroups[0].name : null);
|
|
26602
|
+
}
|
|
26603
|
+
const activeIsValue = VALUE_NAME !== null && activeGroup === VALUE_NAME;
|
|
26604
|
+
const valueGroup = VALUE_NAME !== null ? {
|
|
26605
|
+
name: VALUE_NAME,
|
|
26606
|
+
entries: [],
|
|
26607
|
+
gradient: {
|
|
26608
|
+
min: rampMin,
|
|
26609
|
+
max: rampMax,
|
|
26610
|
+
hue: rampHue,
|
|
26611
|
+
base: rampBase
|
|
26612
|
+
}
|
|
26613
|
+
} : null;
|
|
26614
|
+
const legendGroups = [
|
|
26615
|
+
...valueGroup ? [valueGroup] : [],
|
|
26616
|
+
...parsed.tagGroups
|
|
26617
|
+
];
|
|
26535
26618
|
const reserveHasDescriptions = parsed.nodes.some(
|
|
26536
26619
|
(n) => n.description && n.description.length > 0
|
|
26537
26620
|
);
|
|
26538
|
-
const willRenderLegend =
|
|
26621
|
+
const willRenderLegend = legendGroups.length > 0 || reserveHasDescriptions && controlsHost !== "app";
|
|
26539
26622
|
const sLegendHeight = willRenderLegend ? sctx.structural(
|
|
26540
26623
|
getMaxLegendReservedHeight(
|
|
26541
26624
|
{
|
|
26542
|
-
groups:
|
|
26625
|
+
groups: legendGroups,
|
|
26543
26626
|
position: { placement: "top-center", titleRelation: "below-title" },
|
|
26544
26627
|
mode: exportMode ? "export" : "preview"
|
|
26545
26628
|
},
|
|
26546
26629
|
width
|
|
26547
26630
|
)
|
|
26548
26631
|
) : 0;
|
|
26549
|
-
const activeGroup = resolveActiveTagGroup(
|
|
26550
|
-
parsed.tagGroups,
|
|
26551
|
-
parsed.options["active-tag"],
|
|
26552
|
-
activeTagGroup
|
|
26553
|
-
);
|
|
26554
26632
|
const hidden = hiddenTagValues ?? parsed.initialHiddenTagValues;
|
|
26555
26633
|
const nodeMap = /* @__PURE__ */ new Map();
|
|
26556
26634
|
for (const node of parsed.nodes) nodeMap.set(node.label, node);
|
|
@@ -26561,7 +26639,7 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26561
26639
|
const hasAnyDescriptions = parsed.nodes.some(
|
|
26562
26640
|
(n) => n.description && n.description.length > 0
|
|
26563
26641
|
);
|
|
26564
|
-
const needsLegend =
|
|
26642
|
+
const needsLegend = legendGroups.length > 0 || hasAnyDescriptions && onToggleDescriptions;
|
|
26565
26643
|
const legendH = needsLegend ? sLegendHeight + 8 : 0;
|
|
26566
26644
|
const groupLabelsSet = new Set(layout.groups.map((g) => g.label));
|
|
26567
26645
|
let labelZoneExtension = 0;
|
|
@@ -26767,12 +26845,16 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26767
26845
|
activeGroup,
|
|
26768
26846
|
palette,
|
|
26769
26847
|
isDark,
|
|
26848
|
+
{ active: activeIsValue, hue: rampHue, fillForValue },
|
|
26770
26849
|
parsed.options["solid-fill"] === "on"
|
|
26771
26850
|
);
|
|
26772
26851
|
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);
|
|
26773
26852
|
for (const [key, val] of Object.entries(node.metadata)) {
|
|
26774
26853
|
nodeG.attr(`data-tag-${key.toLowerCase()}`, val.toLowerCase());
|
|
26775
26854
|
}
|
|
26855
|
+
if (node.value !== void 0) {
|
|
26856
|
+
nodeG.attr("data-value", node.value);
|
|
26857
|
+
}
|
|
26776
26858
|
if (onClickItem) {
|
|
26777
26859
|
nodeG.on("click", (event) => {
|
|
26778
26860
|
const target = event.target;
|
|
@@ -26856,11 +26938,27 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26856
26938
|
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]);
|
|
26857
26939
|
}
|
|
26858
26940
|
}
|
|
26941
|
+
if (parsed.showValues && node.value !== void 0) {
|
|
26942
|
+
const valueText = String(node.value);
|
|
26943
|
+
const descShown = !!(desc && desc.length > 0 && !hideDescriptions);
|
|
26944
|
+
if (descShown) {
|
|
26945
|
+
const padX = 6;
|
|
26946
|
+
const padY = 5;
|
|
26947
|
+
const bw = valueText.length * VALUE_FONT_SIZE * CHAR_WIDTH_RATIO2 + 8;
|
|
26948
|
+
const bh = VALUE_FONT_SIZE + 4;
|
|
26949
|
+
const bx = ln.width / 2 - bw - 4;
|
|
26950
|
+
const by = -ln.height / 2 + 4;
|
|
26951
|
+
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);
|
|
26952
|
+
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);
|
|
26953
|
+
} else {
|
|
26954
|
+
nodeG.append("text").attr("class", "bl-node-value").attr("x", 0).attr("y", ln.height / 2 - VALUE_FONT_SIZE).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-size", VALUE_FONT_SIZE).attr("font-weight", "600").attr("fill", colors.text).attr("opacity", 0.8).text(valueText);
|
|
26955
|
+
}
|
|
26956
|
+
}
|
|
26859
26957
|
}
|
|
26860
26958
|
const hasDescriptions = parsed.nodes.some(
|
|
26861
26959
|
(n) => n.description && n.description.length > 0
|
|
26862
26960
|
);
|
|
26863
|
-
const hasLegend =
|
|
26961
|
+
const hasLegend = legendGroups.length > 0 || hasDescriptions && controlsHost !== "app";
|
|
26864
26962
|
if (hasLegend) {
|
|
26865
26963
|
let controlsGroup;
|
|
26866
26964
|
if (hasDescriptions && (onToggleDescriptions || controlsHost === "app")) {
|
|
@@ -26878,7 +26976,7 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26878
26976
|
};
|
|
26879
26977
|
}
|
|
26880
26978
|
const legendConfig = {
|
|
26881
|
-
groups:
|
|
26979
|
+
groups: legendGroups,
|
|
26882
26980
|
position: { placement: "top-center", titleRelation: "below-title" },
|
|
26883
26981
|
mode: exportMode ? "export" : "preview",
|
|
26884
26982
|
// Keep inactive sibling tag groups visible as collapsed pills so the user
|
|
@@ -26933,7 +27031,7 @@ function renderBoxesAndLinesForExport(container, parsed, layout, palette, isDark
|
|
|
26933
27031
|
}
|
|
26934
27032
|
});
|
|
26935
27033
|
}
|
|
26936
|
-
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;
|
|
27034
|
+
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;
|
|
26937
27035
|
var init_renderer6 = __esm({
|
|
26938
27036
|
"src/boxes-and-lines/renderer.ts"() {
|
|
26939
27037
|
"use strict";
|
|
@@ -26942,6 +27040,7 @@ var init_renderer6 = __esm({
|
|
|
26942
27040
|
init_legend_layout();
|
|
26943
27041
|
init_title_constants();
|
|
26944
27042
|
init_color_utils();
|
|
27043
|
+
init_colors();
|
|
26945
27044
|
init_tag_groups();
|
|
26946
27045
|
init_inline_markdown();
|
|
26947
27046
|
init_wrapped_desc();
|
|
@@ -26964,6 +27063,8 @@ var init_renderer6 = __esm({
|
|
|
26964
27063
|
GROUP_RX = 8;
|
|
26965
27064
|
GROUP_LABEL_FONT_SIZE = 14;
|
|
26966
27065
|
GROUP_LABEL_ZONE = 32;
|
|
27066
|
+
RAMP_FLOOR = 15;
|
|
27067
|
+
VALUE_FONT_SIZE = 11;
|
|
26967
27068
|
lineGeneratorLR = d3Shape4.line().x((d) => d.x).y((d) => d.y).curve(d3Shape4.curveBasis);
|
|
26968
27069
|
lineGeneratorTB = d3Shape4.line().x((d) => d.x).y((d) => d.y).curve(d3Shape4.curveBasis);
|
|
26969
27070
|
}
|
|
@@ -47306,6 +47407,38 @@ function parsePathRings(d) {
|
|
|
47306
47407
|
if (cur.length) rings.push(cur);
|
|
47307
47408
|
return rings;
|
|
47308
47409
|
}
|
|
47410
|
+
function dropAntimeridianWrapSlivers(d, width, height) {
|
|
47411
|
+
const rings = parsePathRings(d);
|
|
47412
|
+
if (rings.length <= 1) return d;
|
|
47413
|
+
const eps = 0.75;
|
|
47414
|
+
const minArea = 3e-3 * width * height;
|
|
47415
|
+
const ringArea = (r) => {
|
|
47416
|
+
let s = 0;
|
|
47417
|
+
for (let i = 0; i < r.length; i++) {
|
|
47418
|
+
const a = r[i];
|
|
47419
|
+
const b = r[(i + 1) % r.length];
|
|
47420
|
+
s += a[0] * b[1] - b[0] * a[1];
|
|
47421
|
+
}
|
|
47422
|
+
return Math.abs(s) / 2;
|
|
47423
|
+
};
|
|
47424
|
+
const areas = rings.map(ringArea);
|
|
47425
|
+
const maxArea = Math.max(...areas);
|
|
47426
|
+
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;
|
|
47427
|
+
let dropped = false;
|
|
47428
|
+
const kept = rings.filter((r, idx) => {
|
|
47429
|
+
if (areas[idx] >= maxArea || areas[idx] >= minArea) return true;
|
|
47430
|
+
const touches = r.some((p, i) => onVEdge(p, r[(i + 1) % r.length]));
|
|
47431
|
+
if (touches) {
|
|
47432
|
+
dropped = true;
|
|
47433
|
+
return false;
|
|
47434
|
+
}
|
|
47435
|
+
return true;
|
|
47436
|
+
});
|
|
47437
|
+
if (!dropped) return d;
|
|
47438
|
+
return kept.map(
|
|
47439
|
+
(r) => r.map((p, i) => (i ? "L" : "M") + p[0] + "," + p[1]).join("") + "Z"
|
|
47440
|
+
).join("");
|
|
47441
|
+
}
|
|
47309
47442
|
function layoutMap(resolved, data, size, opts) {
|
|
47310
47443
|
const { palette, isDark } = opts;
|
|
47311
47444
|
const { width, height } = size;
|
|
@@ -47389,7 +47522,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47389
47522
|
const rampBase = isDark ? mix(palette.surface, palette.text, 28) : palette.bg;
|
|
47390
47523
|
const fillForValue = (s) => {
|
|
47391
47524
|
const t = rampMax > rampMin ? (s - rampMin) / (rampMax - rampMin) : 1;
|
|
47392
|
-
const pct =
|
|
47525
|
+
const pct = RAMP_FLOOR2 + Math.max(0, Math.min(1, t)) * (100 - RAMP_FLOOR2);
|
|
47393
47526
|
return mix(rampHue, rampBase, pct);
|
|
47394
47527
|
};
|
|
47395
47528
|
const tagFill = (tags, groupName) => {
|
|
@@ -47448,10 +47581,11 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47448
47581
|
const by0 = cb[0][1];
|
|
47449
47582
|
const cw = cb[1][0] - bx0;
|
|
47450
47583
|
const ch = cb[1][1] - by0;
|
|
47451
|
-
const
|
|
47452
|
-
const
|
|
47453
|
-
const
|
|
47454
|
-
const
|
|
47584
|
+
const topReserve = resolved.title && resolved.pois.length > 0 ? topPad : 0;
|
|
47585
|
+
const ox = 0;
|
|
47586
|
+
const oy = topReserve;
|
|
47587
|
+
const sx = cw > 0 ? width / cw : 1;
|
|
47588
|
+
const sy = ch > 0 ? (height - topReserve) / ch : 1;
|
|
47455
47589
|
stretchParams = { sx, sy, ox, oy, bx0, by0 };
|
|
47456
47590
|
const stretch = (x, y) => [
|
|
47457
47591
|
ox + (x - bx0) * sx,
|
|
@@ -47724,7 +47858,8 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47724
47858
|
const r = regionById.get(iso);
|
|
47725
47859
|
const viewF = shouldCull ? cullFeatureToView(f) : dropFrameFillers(f);
|
|
47726
47860
|
if (!viewF) continue;
|
|
47727
|
-
const
|
|
47861
|
+
const raw = path(viewF) ?? "";
|
|
47862
|
+
const d = fitIsGlobal ? dropAntimeridianWrapSlivers(raw, width, height) : raw;
|
|
47728
47863
|
if (!d) continue;
|
|
47729
47864
|
const isThisLayer = r?.layer === layerKind;
|
|
47730
47865
|
const isForeign = layerKind === "country" && usContext && iso !== "US";
|
|
@@ -47741,6 +47876,9 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47741
47876
|
} else {
|
|
47742
47877
|
label = f.properties?.name;
|
|
47743
47878
|
}
|
|
47879
|
+
const labelAnchor = WORLD_LABEL_ANCHORS[iso];
|
|
47880
|
+
const c = labelAnchor ? project(labelAnchor[0], labelAnchor[1]) : path.centroid(viewF);
|
|
47881
|
+
const hasCentroid = c != null && Number.isFinite(c[0]) && Number.isFinite(c[1]);
|
|
47744
47882
|
regions.push({
|
|
47745
47883
|
id: iso,
|
|
47746
47884
|
d,
|
|
@@ -47749,6 +47887,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47749
47887
|
lineNumber,
|
|
47750
47888
|
layer,
|
|
47751
47889
|
...label !== void 0 && { label },
|
|
47890
|
+
...hasCentroid && { labelX: c[0], labelY: c[1] },
|
|
47752
47891
|
...isThisLayer && r.value !== void 0 && { value: r.value },
|
|
47753
47892
|
...isThisLayer && Object.keys(r.tags).length > 0 && { tags: r.tags }
|
|
47754
47893
|
});
|
|
@@ -48189,10 +48328,6 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
48189
48328
|
lineNumber
|
|
48190
48329
|
});
|
|
48191
48330
|
};
|
|
48192
|
-
const WORLD_LABEL_ANCHORS = {
|
|
48193
|
-
US: [-98.5, 39.5]
|
|
48194
|
-
// CONUS geographic centre (near Lebanon, Kansas)
|
|
48195
|
-
};
|
|
48196
48331
|
const REGION_LABEL_GAP = 2;
|
|
48197
48332
|
const regionLabelRect = (cx, cy, text) => {
|
|
48198
48333
|
const w = measureLegendText(text, FONT2) + 2 * REGION_LABEL_GAP;
|
|
@@ -48558,7 +48693,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
48558
48693
|
diagnostics: []
|
|
48559
48694
|
};
|
|
48560
48695
|
}
|
|
48561
|
-
var FIT_PAD,
|
|
48696
|
+
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;
|
|
48562
48697
|
var init_layout15 = __esm({
|
|
48563
48698
|
"src/map/layout.ts"() {
|
|
48564
48699
|
"use strict";
|
|
@@ -48571,13 +48706,17 @@ var init_layout15 = __esm({
|
|
|
48571
48706
|
init_title_constants();
|
|
48572
48707
|
init_context_labels();
|
|
48573
48708
|
FIT_PAD = 24;
|
|
48574
|
-
|
|
48709
|
+
RAMP_FLOOR2 = 15;
|
|
48575
48710
|
R_DEFAULT = 6;
|
|
48576
48711
|
R_MIN = 4;
|
|
48577
48712
|
R_MAX = 22;
|
|
48578
48713
|
W_MIN = 1.25;
|
|
48579
48714
|
W_MAX = 8;
|
|
48580
48715
|
FONT2 = 11;
|
|
48716
|
+
WORLD_LABEL_ANCHORS = {
|
|
48717
|
+
US: [-98.5, 39.5]
|
|
48718
|
+
// CONUS geographic centre (near Lebanon, Kansas)
|
|
48719
|
+
};
|
|
48581
48720
|
MAX_CLUSTER_EXTENT_FACTOR = 0.18;
|
|
48582
48721
|
MAX_COLUMN_ROWS = 7;
|
|
48583
48722
|
REGION_LABEL_HALO_RATIO = 4.5;
|
|
@@ -48591,9 +48730,9 @@ var init_layout15 = __esm({
|
|
|
48591
48730
|
COMPACT_WIDTH_PX = 480;
|
|
48592
48731
|
RELIEF_MIN_AREA = 12;
|
|
48593
48732
|
RELIEF_MIN_DIM = 2;
|
|
48594
|
-
RELIEF_HATCH_SPACING =
|
|
48595
|
-
RELIEF_HATCH_WIDTH = 0.
|
|
48596
|
-
RELIEF_HATCH_STRENGTH =
|
|
48733
|
+
RELIEF_HATCH_SPACING = 1.5;
|
|
48734
|
+
RELIEF_HATCH_WIDTH = 0.2;
|
|
48735
|
+
RELIEF_HATCH_STRENGTH = 26;
|
|
48597
48736
|
COASTLINE_RING_COUNT = 5;
|
|
48598
48737
|
COASTLINE_D0 = 16e-4;
|
|
48599
48738
|
COASTLINE_STEP = 28e-4;
|
|
@@ -48672,7 +48811,47 @@ function ringToPath(ring) {
|
|
|
48672
48811
|
d += (i ? "L" : "M") + ring[i][0] + "," + ring[i][1];
|
|
48673
48812
|
return d + "Z";
|
|
48674
48813
|
}
|
|
48675
|
-
function
|
|
48814
|
+
function polylineToPath(pts) {
|
|
48815
|
+
let d = "";
|
|
48816
|
+
for (let i = 0; i < pts.length; i++)
|
|
48817
|
+
d += (i ? "L" : "M") + pts[i][0] + "," + pts[i][1];
|
|
48818
|
+
return d;
|
|
48819
|
+
}
|
|
48820
|
+
function ringToCoastPaths(ring, frame) {
|
|
48821
|
+
if (!frame) return [ringToPath(ring)];
|
|
48822
|
+
const n = ring.length;
|
|
48823
|
+
const eps = 0.75;
|
|
48824
|
+
const onL = (x) => Math.abs(x) <= eps;
|
|
48825
|
+
const onR = (x) => Math.abs(x - frame.w) <= eps;
|
|
48826
|
+
const onT = (y) => Math.abs(y) <= eps;
|
|
48827
|
+
const onB = (y) => Math.abs(y - frame.h) <= eps;
|
|
48828
|
+
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]);
|
|
48829
|
+
let firstBreak = -1;
|
|
48830
|
+
for (let i = 0; i < n; i++)
|
|
48831
|
+
if (isFrameEdge(ring[i], ring[(i + 1) % n])) {
|
|
48832
|
+
firstBreak = i;
|
|
48833
|
+
break;
|
|
48834
|
+
}
|
|
48835
|
+
if (firstBreak === -1) return [ringToPath(ring)];
|
|
48836
|
+
const paths = [];
|
|
48837
|
+
let cur = [];
|
|
48838
|
+
const start = (firstBreak + 1) % n;
|
|
48839
|
+
for (let k = 0; k < n; k++) {
|
|
48840
|
+
const i = (start + k) % n;
|
|
48841
|
+
const a = ring[i];
|
|
48842
|
+
const b = ring[(i + 1) % n];
|
|
48843
|
+
if (isFrameEdge(a, b)) {
|
|
48844
|
+
if (cur.length >= 2) paths.push(polylineToPath(cur));
|
|
48845
|
+
cur = [];
|
|
48846
|
+
continue;
|
|
48847
|
+
}
|
|
48848
|
+
if (cur.length === 0) cur.push(a);
|
|
48849
|
+
cur.push(b);
|
|
48850
|
+
}
|
|
48851
|
+
if (cur.length >= 2) paths.push(polylineToPath(cur));
|
|
48852
|
+
return paths;
|
|
48853
|
+
}
|
|
48854
|
+
function coastlineOuterRings(regions, minExtent, frame) {
|
|
48676
48855
|
const paths = [];
|
|
48677
48856
|
for (const r of regions) {
|
|
48678
48857
|
const rings = parsePathRings(r.d);
|
|
@@ -48695,7 +48874,7 @@ function coastlineOuterRings(regions, minExtent) {
|
|
|
48695
48874
|
for (let j = 0; j < rings.length; j++)
|
|
48696
48875
|
if (j !== i && pointInRing2(fx, fy, rings[j])) depth++;
|
|
48697
48876
|
if (depth % 2 === 1) continue;
|
|
48698
|
-
paths.push(
|
|
48877
|
+
paths.push(...ringToCoastPaths(ring, frame));
|
|
48699
48878
|
}
|
|
48700
48879
|
}
|
|
48701
48880
|
return paths;
|
|
@@ -48739,6 +48918,10 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
48739
48918
|
const drawRegion = (g, r, strokeWidth) => {
|
|
48740
48919
|
const p = g.append("path").attr("d", r.d).attr("fill", r.fill).attr("stroke", r.stroke).attr("stroke-width", strokeWidth);
|
|
48741
48920
|
if (r.label) p.attr("data-region-name", r.label);
|
|
48921
|
+
if (r.id && r.id !== "lake") p.attr("data-iso", r.id);
|
|
48922
|
+
if (r.labelX !== void 0 && r.labelY !== void 0) {
|
|
48923
|
+
p.attr("data-label-x", r.labelX).attr("data-label-y", r.labelY);
|
|
48924
|
+
}
|
|
48742
48925
|
if (r.layer !== "base") {
|
|
48743
48926
|
p.classed("dgmo-map-region", true).attr("data-region", r.id);
|
|
48744
48927
|
if (r.value !== void 0) p.attr("data-value", r.value);
|
|
@@ -48768,7 +48951,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
48768
48951
|
const landClip = defs.append("clipPath").attr("id", landClipId);
|
|
48769
48952
|
for (const r of layout.regions)
|
|
48770
48953
|
if (r.id !== "lake") landClip.append("path").attr("d", r.d);
|
|
48771
|
-
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");
|
|
48954
|
+
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");
|
|
48772
48955
|
for (let y = h.spacing; y < height; y += h.spacing) {
|
|
48773
48956
|
gRelief.append("line").attr("x1", 0).attr("y1", y).attr("x2", width).attr("y2", y);
|
|
48774
48957
|
}
|
|
@@ -48789,10 +48972,16 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
48789
48972
|
mask.append("path").attr("d", d).attr("fill", "black").attr("stroke", "black").attr("stroke-width", 2 * reach).attr("stroke-linejoin", "round");
|
|
48790
48973
|
}
|
|
48791
48974
|
}
|
|
48792
|
-
const gWater = svg.append("g").attr("class", "dgmo-map-water-lines").attr("fill", "none").attr("mask", `url(#${maskId})`);
|
|
48975
|
+
const gWater = svg.append("g").attr("class", "dgmo-map-water-lines").attr("fill", "none").style("pointer-events", "none").attr("mask", `url(#${maskId})`);
|
|
48793
48976
|
appendWaterLines(
|
|
48794
48977
|
gWater,
|
|
48795
|
-
|
|
48978
|
+
// Pass the canvas frame so edges collinear with it (the antimeridian on a
|
|
48979
|
+
// world map, regional clipExtent cuts) don't get ringed as fake coast —
|
|
48980
|
+
// land runs cleanly to the render-area edge.
|
|
48981
|
+
coastlineOuterRings(layout.regions, cs.minExtent, {
|
|
48982
|
+
w: width,
|
|
48983
|
+
h: height
|
|
48984
|
+
}),
|
|
48796
48985
|
cs,
|
|
48797
48986
|
layout.background
|
|
48798
48987
|
);
|
|
@@ -48806,7 +48995,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
48806
48995
|
gWater.append("path").attr("d", ds.join(" ")).attr("stroke", stroke2).attr("stroke-width", 0.5).attr("stroke-linejoin", "round");
|
|
48807
48996
|
}
|
|
48808
48997
|
if (layout.rivers.length) {
|
|
48809
|
-
const gRivers = svg.append("g").attr("class", "dgmo-map-rivers").attr("fill", "none");
|
|
48998
|
+
const gRivers = svg.append("g").attr("class", "dgmo-map-rivers").attr("fill", "none").style("pointer-events", "none");
|
|
48810
48999
|
for (const r of layout.rivers) {
|
|
48811
49000
|
gRivers.append("path").attr("d", r.d).attr("stroke", r.color).attr("stroke-width", r.width).attr("stroke-linecap", "round").attr("stroke-linejoin", "round");
|
|
48812
49001
|
}
|
|
@@ -48847,7 +49036,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
48847
49036
|
const d = box.points.map((p, i) => `${i ? "L" : "M"}${p[0]},${p[1]}`).join("") + "Z";
|
|
48848
49037
|
clip.append("path").attr("d", d);
|
|
48849
49038
|
}
|
|
48850
|
-
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})`);
|
|
49039
|
+
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})`);
|
|
48851
49040
|
appendWaterLines(
|
|
48852
49041
|
gInsetWater,
|
|
48853
49042
|
coastlineOuterRings(layout.insetRegions, cs.minExtent),
|
|
@@ -54868,10 +55057,12 @@ function renderTimelineHorizontalTimeSort(container, parsed, palette, isDark, se
|
|
|
54868
55057
|
const markerLabelY = markerReserve ? -(topScaleH + MARKER_ROW_H / 2) : 0;
|
|
54869
55058
|
const eraLabelY = eraReserve ? -(topScaleH + markerReserve + ERA_ROW_H / 2) : 0;
|
|
54870
55059
|
const innerWidth = width - margin.left - margin.right;
|
|
54871
|
-
const
|
|
54872
|
-
const rowH = Math.min(ctx.structural(28),
|
|
55060
|
+
const availInnerHeight = height - margin.top - margin.bottom;
|
|
55061
|
+
const rowH = Math.min(ctx.structural(28), availInnerHeight / sorted.length);
|
|
55062
|
+
const innerHeight = rowH * sorted.length;
|
|
55063
|
+
const usedHeight = margin.top + innerHeight + margin.bottom;
|
|
54873
55064
|
const xScale = d3Scale2.scaleLinear().domain([minDate - datePadding, maxDate + datePadding]).range([0, innerWidth]);
|
|
54874
|
-
const svg = d3Selection23.select(container).append("svg").attr("width", width).attr("height",
|
|
55065
|
+
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);
|
|
54875
55066
|
if (ctx.isBelowFloor) {
|
|
54876
55067
|
svg.attr("width", "100%");
|
|
54877
55068
|
}
|