@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/editor.cjs
CHANGED
package/dist/editor.js
CHANGED
package/dist/highlight.cjs
CHANGED
package/dist/highlight.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -895,9 +895,7 @@ var init_reserved_key_registry = __esm({
|
|
|
895
895
|
BOXES_AND_LINES_REGISTRY = staticRegistry([
|
|
896
896
|
"color",
|
|
897
897
|
"description",
|
|
898
|
-
"
|
|
899
|
-
"split",
|
|
900
|
-
"fanout"
|
|
898
|
+
"value"
|
|
901
899
|
]);
|
|
902
900
|
TIMELINE_REGISTRY = staticRegistry([
|
|
903
901
|
"color",
|
|
@@ -16899,6 +16897,21 @@ function parseBoxesAndLines(content) {
|
|
|
16899
16897
|
}
|
|
16900
16898
|
continue;
|
|
16901
16899
|
}
|
|
16900
|
+
if (!contentStarted) {
|
|
16901
|
+
const metricMatch = trimmed.match(/^box-metric\s+(.+)$/i);
|
|
16902
|
+
if (metricMatch) {
|
|
16903
|
+
const { label, colorName } = peelTrailingColorName(
|
|
16904
|
+
metricMatch[1].trim()
|
|
16905
|
+
);
|
|
16906
|
+
result.boxMetric = label;
|
|
16907
|
+
if (colorName !== void 0) result.boxMetricColor = colorName;
|
|
16908
|
+
continue;
|
|
16909
|
+
}
|
|
16910
|
+
if (/^show-values$/i.test(trimmed)) {
|
|
16911
|
+
result.showValues = true;
|
|
16912
|
+
continue;
|
|
16913
|
+
}
|
|
16914
|
+
}
|
|
16902
16915
|
if (!contentStarted) {
|
|
16903
16916
|
const optMatch = trimmed.match(OPTION_NOCOLON_RE);
|
|
16904
16917
|
if (optMatch) {
|
|
@@ -17277,6 +17290,19 @@ function parseNodeLine(trimmed, lineNum, metaAliasMap, diagnostics, nameAliasMap
|
|
|
17277
17290
|
description = [metadata["description"]];
|
|
17278
17291
|
delete metadata["description"];
|
|
17279
17292
|
}
|
|
17293
|
+
let value;
|
|
17294
|
+
if (metadata["value"] !== void 0) {
|
|
17295
|
+
const raw = metadata["value"];
|
|
17296
|
+
const num = Number(raw);
|
|
17297
|
+
if (Number.isFinite(num)) {
|
|
17298
|
+
value = num;
|
|
17299
|
+
} else {
|
|
17300
|
+
diagnostics.push(
|
|
17301
|
+
makeDgmoError(lineNum, `value must be a number (got "${raw}")`, "error")
|
|
17302
|
+
);
|
|
17303
|
+
}
|
|
17304
|
+
delete metadata["value"];
|
|
17305
|
+
}
|
|
17280
17306
|
if (split.alias) {
|
|
17281
17307
|
nameAliasMap?.set(normalizeName(split.alias), label);
|
|
17282
17308
|
}
|
|
@@ -17285,7 +17311,8 @@ function parseNodeLine(trimmed, lineNum, metaAliasMap, diagnostics, nameAliasMap
|
|
|
17285
17311
|
label,
|
|
17286
17312
|
lineNumber: lineNum,
|
|
17287
17313
|
metadata,
|
|
17288
|
-
...description !== void 0 && { description }
|
|
17314
|
+
...description !== void 0 && { description },
|
|
17315
|
+
...value !== void 0 && { value }
|
|
17289
17316
|
};
|
|
17290
17317
|
}
|
|
17291
17318
|
function splitTargetAndMeta(rest, metaAliasMap) {
|
|
@@ -26405,7 +26432,18 @@ function fitLabelToHeader(label, nodeWidth, maxLines) {
|
|
|
26405
26432
|
const truncated = label.length > maxChars ? label.slice(0, maxChars - 1) + "\u2026" : label;
|
|
26406
26433
|
return { lines: [truncated], fontSize: MIN_NODE_FONT_SIZE };
|
|
26407
26434
|
}
|
|
26408
|
-
function nodeColors(node, tagGroups, activeGroupName, palette, isDark, solid) {
|
|
26435
|
+
function nodeColors(node, tagGroups, activeGroupName, palette, isDark, value, solid) {
|
|
26436
|
+
const neutralFill = mix(palette.bg, palette.text, isDark ? 90 : 95);
|
|
26437
|
+
if (value.active) {
|
|
26438
|
+
const fill3 = node.value !== void 0 ? value.fillForValue(node.value) : neutralFill;
|
|
26439
|
+
const stroke3 = value.hue;
|
|
26440
|
+
const text2 = contrastText(
|
|
26441
|
+
fill3,
|
|
26442
|
+
palette.textOnFillLight,
|
|
26443
|
+
palette.textOnFillDark
|
|
26444
|
+
);
|
|
26445
|
+
return { fill: fill3, stroke: stroke3, text: text2 };
|
|
26446
|
+
}
|
|
26409
26447
|
const tagColor = resolveTagColor(
|
|
26410
26448
|
node.metadata,
|
|
26411
26449
|
[...tagGroups],
|
|
@@ -26514,25 +26552,65 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26514
26552
|
const sGroupLabelZone = sctx.structural(GROUP_LABEL_ZONE);
|
|
26515
26553
|
const sTitleFontSize = sctx.text(TITLE_FONT_SIZE);
|
|
26516
26554
|
const sTitleY = sctx.structural(TITLE_Y);
|
|
26555
|
+
const nodeValues = parsed.nodes.filter((n) => n.value !== void 0).map((n) => n.value);
|
|
26556
|
+
const hasRamp = nodeValues.length > 0;
|
|
26557
|
+
const allNonNegative = hasRamp && nodeValues.every((v) => v >= 0);
|
|
26558
|
+
const rampMin = allNonNegative ? 0 : Math.min(...nodeValues);
|
|
26559
|
+
const rampMax = Math.max(...nodeValues);
|
|
26560
|
+
const rampHue = resolveColor(parsed.boxMetricColor ?? "", palette) ?? palette.primary;
|
|
26561
|
+
const rampBase = isDark ? mix(palette.surface, palette.text, 28) : palette.bg;
|
|
26562
|
+
const fillForValue = (v) => {
|
|
26563
|
+
const t = rampMax > rampMin ? (v - rampMin) / (rampMax - rampMin) : 1;
|
|
26564
|
+
const pct = RAMP_FLOOR + Math.max(0, Math.min(1, t)) * (100 - RAMP_FLOOR);
|
|
26565
|
+
return mix(rampHue, rampBase, pct);
|
|
26566
|
+
};
|
|
26567
|
+
const VALUE_NAME = hasRamp ? parsed.boxMetric?.trim() || "Value" : null;
|
|
26568
|
+
const matchColorGroup = (v) => {
|
|
26569
|
+
const lv = v.trim().toLowerCase();
|
|
26570
|
+
if (lv === "none") return null;
|
|
26571
|
+
const tg = parsed.tagGroups.find((g) => g.name.toLowerCase() === lv);
|
|
26572
|
+
if (tg) return tg.name;
|
|
26573
|
+
if (lv === VALUE_NAME?.toLowerCase()) return VALUE_NAME;
|
|
26574
|
+
return v;
|
|
26575
|
+
};
|
|
26576
|
+
const override = activeTagGroup;
|
|
26577
|
+
let activeGroup;
|
|
26578
|
+
if (override !== void 0) {
|
|
26579
|
+
activeGroup = override === null ? null : matchColorGroup(override);
|
|
26580
|
+
} else if (parsed.options["active-tag"] !== void 0) {
|
|
26581
|
+
activeGroup = matchColorGroup(parsed.options["active-tag"]);
|
|
26582
|
+
} else {
|
|
26583
|
+
activeGroup = VALUE_NAME ?? (parsed.tagGroups.length > 0 ? parsed.tagGroups[0].name : null);
|
|
26584
|
+
}
|
|
26585
|
+
const activeIsValue = VALUE_NAME !== null && activeGroup === VALUE_NAME;
|
|
26586
|
+
const valueGroup = VALUE_NAME !== null ? {
|
|
26587
|
+
name: VALUE_NAME,
|
|
26588
|
+
entries: [],
|
|
26589
|
+
gradient: {
|
|
26590
|
+
min: rampMin,
|
|
26591
|
+
max: rampMax,
|
|
26592
|
+
hue: rampHue,
|
|
26593
|
+
base: rampBase
|
|
26594
|
+
}
|
|
26595
|
+
} : null;
|
|
26596
|
+
const legendGroups = [
|
|
26597
|
+
...valueGroup ? [valueGroup] : [],
|
|
26598
|
+
...parsed.tagGroups
|
|
26599
|
+
];
|
|
26517
26600
|
const reserveHasDescriptions = parsed.nodes.some(
|
|
26518
26601
|
(n) => n.description && n.description.length > 0
|
|
26519
26602
|
);
|
|
26520
|
-
const willRenderLegend =
|
|
26603
|
+
const willRenderLegend = legendGroups.length > 0 || reserveHasDescriptions && controlsHost !== "app";
|
|
26521
26604
|
const sLegendHeight = willRenderLegend ? sctx.structural(
|
|
26522
26605
|
getMaxLegendReservedHeight(
|
|
26523
26606
|
{
|
|
26524
|
-
groups:
|
|
26607
|
+
groups: legendGroups,
|
|
26525
26608
|
position: { placement: "top-center", titleRelation: "below-title" },
|
|
26526
26609
|
mode: exportMode ? "export" : "preview"
|
|
26527
26610
|
},
|
|
26528
26611
|
width
|
|
26529
26612
|
)
|
|
26530
26613
|
) : 0;
|
|
26531
|
-
const activeGroup = resolveActiveTagGroup(
|
|
26532
|
-
parsed.tagGroups,
|
|
26533
|
-
parsed.options["active-tag"],
|
|
26534
|
-
activeTagGroup
|
|
26535
|
-
);
|
|
26536
26614
|
const hidden = hiddenTagValues ?? parsed.initialHiddenTagValues;
|
|
26537
26615
|
const nodeMap = /* @__PURE__ */ new Map();
|
|
26538
26616
|
for (const node of parsed.nodes) nodeMap.set(node.label, node);
|
|
@@ -26543,7 +26621,7 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26543
26621
|
const hasAnyDescriptions = parsed.nodes.some(
|
|
26544
26622
|
(n) => n.description && n.description.length > 0
|
|
26545
26623
|
);
|
|
26546
|
-
const needsLegend =
|
|
26624
|
+
const needsLegend = legendGroups.length > 0 || hasAnyDescriptions && onToggleDescriptions;
|
|
26547
26625
|
const legendH = needsLegend ? sLegendHeight + 8 : 0;
|
|
26548
26626
|
const groupLabelsSet = new Set(layout.groups.map((g) => g.label));
|
|
26549
26627
|
let labelZoneExtension = 0;
|
|
@@ -26749,12 +26827,16 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26749
26827
|
activeGroup,
|
|
26750
26828
|
palette,
|
|
26751
26829
|
isDark,
|
|
26830
|
+
{ active: activeIsValue, hue: rampHue, fillForValue },
|
|
26752
26831
|
parsed.options["solid-fill"] === "on"
|
|
26753
26832
|
);
|
|
26754
26833
|
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);
|
|
26755
26834
|
for (const [key, val] of Object.entries(node.metadata)) {
|
|
26756
26835
|
nodeG.attr(`data-tag-${key.toLowerCase()}`, val.toLowerCase());
|
|
26757
26836
|
}
|
|
26837
|
+
if (node.value !== void 0) {
|
|
26838
|
+
nodeG.attr("data-value", node.value);
|
|
26839
|
+
}
|
|
26758
26840
|
if (onClickItem) {
|
|
26759
26841
|
nodeG.on("click", (event) => {
|
|
26760
26842
|
const target = event.target;
|
|
@@ -26838,11 +26920,27 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26838
26920
|
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]);
|
|
26839
26921
|
}
|
|
26840
26922
|
}
|
|
26923
|
+
if (parsed.showValues && node.value !== void 0) {
|
|
26924
|
+
const valueText = String(node.value);
|
|
26925
|
+
const descShown = !!(desc && desc.length > 0 && !hideDescriptions);
|
|
26926
|
+
if (descShown) {
|
|
26927
|
+
const padX = 6;
|
|
26928
|
+
const padY = 5;
|
|
26929
|
+
const bw = valueText.length * VALUE_FONT_SIZE * CHAR_WIDTH_RATIO2 + 8;
|
|
26930
|
+
const bh = VALUE_FONT_SIZE + 4;
|
|
26931
|
+
const bx = ln.width / 2 - bw - 4;
|
|
26932
|
+
const by = -ln.height / 2 + 4;
|
|
26933
|
+
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);
|
|
26934
|
+
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);
|
|
26935
|
+
} else {
|
|
26936
|
+
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);
|
|
26937
|
+
}
|
|
26938
|
+
}
|
|
26841
26939
|
}
|
|
26842
26940
|
const hasDescriptions = parsed.nodes.some(
|
|
26843
26941
|
(n) => n.description && n.description.length > 0
|
|
26844
26942
|
);
|
|
26845
|
-
const hasLegend =
|
|
26943
|
+
const hasLegend = legendGroups.length > 0 || hasDescriptions && controlsHost !== "app";
|
|
26846
26944
|
if (hasLegend) {
|
|
26847
26945
|
let controlsGroup;
|
|
26848
26946
|
if (hasDescriptions && (onToggleDescriptions || controlsHost === "app")) {
|
|
@@ -26860,7 +26958,7 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26860
26958
|
};
|
|
26861
26959
|
}
|
|
26862
26960
|
const legendConfig = {
|
|
26863
|
-
groups:
|
|
26961
|
+
groups: legendGroups,
|
|
26864
26962
|
position: { placement: "top-center", titleRelation: "below-title" },
|
|
26865
26963
|
mode: exportMode ? "export" : "preview",
|
|
26866
26964
|
// Keep inactive sibling tag groups visible as collapsed pills so the user
|
|
@@ -26915,7 +27013,7 @@ function renderBoxesAndLinesForExport(container, parsed, layout, palette, isDark
|
|
|
26915
27013
|
}
|
|
26916
27014
|
});
|
|
26917
27015
|
}
|
|
26918
|
-
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;
|
|
27016
|
+
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;
|
|
26919
27017
|
var init_renderer6 = __esm({
|
|
26920
27018
|
"src/boxes-and-lines/renderer.ts"() {
|
|
26921
27019
|
"use strict";
|
|
@@ -26926,6 +27024,7 @@ var init_renderer6 = __esm({
|
|
|
26926
27024
|
init_legend_layout();
|
|
26927
27025
|
init_title_constants();
|
|
26928
27026
|
init_color_utils();
|
|
27027
|
+
init_colors();
|
|
26929
27028
|
init_tag_groups();
|
|
26930
27029
|
init_inline_markdown();
|
|
26931
27030
|
init_wrapped_desc();
|
|
@@ -26948,6 +27047,8 @@ var init_renderer6 = __esm({
|
|
|
26948
27047
|
GROUP_RX = 8;
|
|
26949
27048
|
GROUP_LABEL_FONT_SIZE = 14;
|
|
26950
27049
|
GROUP_LABEL_ZONE = 32;
|
|
27050
|
+
RAMP_FLOOR = 15;
|
|
27051
|
+
VALUE_FONT_SIZE = 11;
|
|
26951
27052
|
lineGeneratorLR = d3Shape4.line().x((d) => d.x).y((d) => d.y).curve(d3Shape4.curveBasis);
|
|
26952
27053
|
lineGeneratorTB = d3Shape4.line().x((d) => d.x).y((d) => d.y).curve(d3Shape4.curveBasis);
|
|
26953
27054
|
}
|
|
@@ -47279,6 +47380,38 @@ function parsePathRings(d) {
|
|
|
47279
47380
|
if (cur.length) rings.push(cur);
|
|
47280
47381
|
return rings;
|
|
47281
47382
|
}
|
|
47383
|
+
function dropAntimeridianWrapSlivers(d, width, height) {
|
|
47384
|
+
const rings = parsePathRings(d);
|
|
47385
|
+
if (rings.length <= 1) return d;
|
|
47386
|
+
const eps = 0.75;
|
|
47387
|
+
const minArea = 3e-3 * width * height;
|
|
47388
|
+
const ringArea = (r) => {
|
|
47389
|
+
let s = 0;
|
|
47390
|
+
for (let i = 0; i < r.length; i++) {
|
|
47391
|
+
const a = r[i];
|
|
47392
|
+
const b = r[(i + 1) % r.length];
|
|
47393
|
+
s += a[0] * b[1] - b[0] * a[1];
|
|
47394
|
+
}
|
|
47395
|
+
return Math.abs(s) / 2;
|
|
47396
|
+
};
|
|
47397
|
+
const areas = rings.map(ringArea);
|
|
47398
|
+
const maxArea = Math.max(...areas);
|
|
47399
|
+
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;
|
|
47400
|
+
let dropped = false;
|
|
47401
|
+
const kept = rings.filter((r, idx) => {
|
|
47402
|
+
if (areas[idx] >= maxArea || areas[idx] >= minArea) return true;
|
|
47403
|
+
const touches = r.some((p, i) => onVEdge(p, r[(i + 1) % r.length]));
|
|
47404
|
+
if (touches) {
|
|
47405
|
+
dropped = true;
|
|
47406
|
+
return false;
|
|
47407
|
+
}
|
|
47408
|
+
return true;
|
|
47409
|
+
});
|
|
47410
|
+
if (!dropped) return d;
|
|
47411
|
+
return kept.map(
|
|
47412
|
+
(r) => r.map((p, i) => (i ? "L" : "M") + p[0] + "," + p[1]).join("") + "Z"
|
|
47413
|
+
).join("");
|
|
47414
|
+
}
|
|
47282
47415
|
function layoutMap(resolved, data, size, opts) {
|
|
47283
47416
|
const { palette, isDark } = opts;
|
|
47284
47417
|
const { width, height } = size;
|
|
@@ -47362,7 +47495,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47362
47495
|
const rampBase = isDark ? mix(palette.surface, palette.text, 28) : palette.bg;
|
|
47363
47496
|
const fillForValue = (s) => {
|
|
47364
47497
|
const t = rampMax > rampMin ? (s - rampMin) / (rampMax - rampMin) : 1;
|
|
47365
|
-
const pct =
|
|
47498
|
+
const pct = RAMP_FLOOR2 + Math.max(0, Math.min(1, t)) * (100 - RAMP_FLOOR2);
|
|
47366
47499
|
return mix(rampHue, rampBase, pct);
|
|
47367
47500
|
};
|
|
47368
47501
|
const tagFill = (tags, groupName) => {
|
|
@@ -47421,10 +47554,11 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47421
47554
|
const by0 = cb[0][1];
|
|
47422
47555
|
const cw = cb[1][0] - bx0;
|
|
47423
47556
|
const ch = cb[1][1] - by0;
|
|
47424
|
-
const
|
|
47425
|
-
const
|
|
47426
|
-
const
|
|
47427
|
-
const
|
|
47557
|
+
const topReserve = resolved.title && resolved.pois.length > 0 ? topPad : 0;
|
|
47558
|
+
const ox = 0;
|
|
47559
|
+
const oy = topReserve;
|
|
47560
|
+
const sx = cw > 0 ? width / cw : 1;
|
|
47561
|
+
const sy = ch > 0 ? (height - topReserve) / ch : 1;
|
|
47428
47562
|
stretchParams = { sx, sy, ox, oy, bx0, by0 };
|
|
47429
47563
|
const stretch = (x, y) => [
|
|
47430
47564
|
ox + (x - bx0) * sx,
|
|
@@ -47697,7 +47831,8 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47697
47831
|
const r = regionById.get(iso);
|
|
47698
47832
|
const viewF = shouldCull ? cullFeatureToView(f) : dropFrameFillers(f);
|
|
47699
47833
|
if (!viewF) continue;
|
|
47700
|
-
const
|
|
47834
|
+
const raw = path(viewF) ?? "";
|
|
47835
|
+
const d = fitIsGlobal ? dropAntimeridianWrapSlivers(raw, width, height) : raw;
|
|
47701
47836
|
if (!d) continue;
|
|
47702
47837
|
const isThisLayer = r?.layer === layerKind;
|
|
47703
47838
|
const isForeign = layerKind === "country" && usContext && iso !== "US";
|
|
@@ -47714,6 +47849,9 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47714
47849
|
} else {
|
|
47715
47850
|
label = f.properties?.name;
|
|
47716
47851
|
}
|
|
47852
|
+
const labelAnchor = WORLD_LABEL_ANCHORS[iso];
|
|
47853
|
+
const c = labelAnchor ? project(labelAnchor[0], labelAnchor[1]) : path.centroid(viewF);
|
|
47854
|
+
const hasCentroid = c != null && Number.isFinite(c[0]) && Number.isFinite(c[1]);
|
|
47717
47855
|
regions.push({
|
|
47718
47856
|
id: iso,
|
|
47719
47857
|
d,
|
|
@@ -47722,6 +47860,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47722
47860
|
lineNumber,
|
|
47723
47861
|
layer,
|
|
47724
47862
|
...label !== void 0 && { label },
|
|
47863
|
+
...hasCentroid && { labelX: c[0], labelY: c[1] },
|
|
47725
47864
|
...isThisLayer && r.value !== void 0 && { value: r.value },
|
|
47726
47865
|
...isThisLayer && Object.keys(r.tags).length > 0 && { tags: r.tags }
|
|
47727
47866
|
});
|
|
@@ -48162,10 +48301,6 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
48162
48301
|
lineNumber
|
|
48163
48302
|
});
|
|
48164
48303
|
};
|
|
48165
|
-
const WORLD_LABEL_ANCHORS = {
|
|
48166
|
-
US: [-98.5, 39.5]
|
|
48167
|
-
// CONUS geographic centre (near Lebanon, Kansas)
|
|
48168
|
-
};
|
|
48169
48304
|
const REGION_LABEL_GAP = 2;
|
|
48170
48305
|
const regionLabelRect = (cx, cy, text) => {
|
|
48171
48306
|
const w = measureLegendText(text, FONT2) + 2 * REGION_LABEL_GAP;
|
|
@@ -48531,7 +48666,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
48531
48666
|
diagnostics: []
|
|
48532
48667
|
};
|
|
48533
48668
|
}
|
|
48534
|
-
var import_d3_geo2, import_topojson_client2, FIT_PAD,
|
|
48669
|
+
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;
|
|
48535
48670
|
var init_layout15 = __esm({
|
|
48536
48671
|
"src/map/layout.ts"() {
|
|
48537
48672
|
"use strict";
|
|
@@ -48546,13 +48681,17 @@ var init_layout15 = __esm({
|
|
|
48546
48681
|
init_title_constants();
|
|
48547
48682
|
init_context_labels();
|
|
48548
48683
|
FIT_PAD = 24;
|
|
48549
|
-
|
|
48684
|
+
RAMP_FLOOR2 = 15;
|
|
48550
48685
|
R_DEFAULT = 6;
|
|
48551
48686
|
R_MIN = 4;
|
|
48552
48687
|
R_MAX = 22;
|
|
48553
48688
|
W_MIN = 1.25;
|
|
48554
48689
|
W_MAX = 8;
|
|
48555
48690
|
FONT2 = 11;
|
|
48691
|
+
WORLD_LABEL_ANCHORS = {
|
|
48692
|
+
US: [-98.5, 39.5]
|
|
48693
|
+
// CONUS geographic centre (near Lebanon, Kansas)
|
|
48694
|
+
};
|
|
48556
48695
|
MAX_CLUSTER_EXTENT_FACTOR = 0.18;
|
|
48557
48696
|
MAX_COLUMN_ROWS = 7;
|
|
48558
48697
|
REGION_LABEL_HALO_RATIO = 4.5;
|
|
@@ -48566,9 +48705,9 @@ var init_layout15 = __esm({
|
|
|
48566
48705
|
COMPACT_WIDTH_PX = 480;
|
|
48567
48706
|
RELIEF_MIN_AREA = 12;
|
|
48568
48707
|
RELIEF_MIN_DIM = 2;
|
|
48569
|
-
RELIEF_HATCH_SPACING =
|
|
48570
|
-
RELIEF_HATCH_WIDTH = 0.
|
|
48571
|
-
RELIEF_HATCH_STRENGTH =
|
|
48708
|
+
RELIEF_HATCH_SPACING = 1.5;
|
|
48709
|
+
RELIEF_HATCH_WIDTH = 0.2;
|
|
48710
|
+
RELIEF_HATCH_STRENGTH = 26;
|
|
48572
48711
|
COASTLINE_RING_COUNT = 5;
|
|
48573
48712
|
COASTLINE_D0 = 16e-4;
|
|
48574
48713
|
COASTLINE_STEP = 28e-4;
|
|
@@ -48646,7 +48785,47 @@ function ringToPath(ring) {
|
|
|
48646
48785
|
d += (i ? "L" : "M") + ring[i][0] + "," + ring[i][1];
|
|
48647
48786
|
return d + "Z";
|
|
48648
48787
|
}
|
|
48649
|
-
function
|
|
48788
|
+
function polylineToPath(pts) {
|
|
48789
|
+
let d = "";
|
|
48790
|
+
for (let i = 0; i < pts.length; i++)
|
|
48791
|
+
d += (i ? "L" : "M") + pts[i][0] + "," + pts[i][1];
|
|
48792
|
+
return d;
|
|
48793
|
+
}
|
|
48794
|
+
function ringToCoastPaths(ring, frame) {
|
|
48795
|
+
if (!frame) return [ringToPath(ring)];
|
|
48796
|
+
const n = ring.length;
|
|
48797
|
+
const eps = 0.75;
|
|
48798
|
+
const onL = (x) => Math.abs(x) <= eps;
|
|
48799
|
+
const onR = (x) => Math.abs(x - frame.w) <= eps;
|
|
48800
|
+
const onT = (y) => Math.abs(y) <= eps;
|
|
48801
|
+
const onB = (y) => Math.abs(y - frame.h) <= eps;
|
|
48802
|
+
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]);
|
|
48803
|
+
let firstBreak = -1;
|
|
48804
|
+
for (let i = 0; i < n; i++)
|
|
48805
|
+
if (isFrameEdge(ring[i], ring[(i + 1) % n])) {
|
|
48806
|
+
firstBreak = i;
|
|
48807
|
+
break;
|
|
48808
|
+
}
|
|
48809
|
+
if (firstBreak === -1) return [ringToPath(ring)];
|
|
48810
|
+
const paths = [];
|
|
48811
|
+
let cur = [];
|
|
48812
|
+
const start = (firstBreak + 1) % n;
|
|
48813
|
+
for (let k = 0; k < n; k++) {
|
|
48814
|
+
const i = (start + k) % n;
|
|
48815
|
+
const a = ring[i];
|
|
48816
|
+
const b = ring[(i + 1) % n];
|
|
48817
|
+
if (isFrameEdge(a, b)) {
|
|
48818
|
+
if (cur.length >= 2) paths.push(polylineToPath(cur));
|
|
48819
|
+
cur = [];
|
|
48820
|
+
continue;
|
|
48821
|
+
}
|
|
48822
|
+
if (cur.length === 0) cur.push(a);
|
|
48823
|
+
cur.push(b);
|
|
48824
|
+
}
|
|
48825
|
+
if (cur.length >= 2) paths.push(polylineToPath(cur));
|
|
48826
|
+
return paths;
|
|
48827
|
+
}
|
|
48828
|
+
function coastlineOuterRings(regions, minExtent, frame) {
|
|
48650
48829
|
const paths = [];
|
|
48651
48830
|
for (const r of regions) {
|
|
48652
48831
|
const rings = parsePathRings(r.d);
|
|
@@ -48669,7 +48848,7 @@ function coastlineOuterRings(regions, minExtent) {
|
|
|
48669
48848
|
for (let j = 0; j < rings.length; j++)
|
|
48670
48849
|
if (j !== i && pointInRing2(fx, fy, rings[j])) depth++;
|
|
48671
48850
|
if (depth % 2 === 1) continue;
|
|
48672
|
-
paths.push(
|
|
48851
|
+
paths.push(...ringToCoastPaths(ring, frame));
|
|
48673
48852
|
}
|
|
48674
48853
|
}
|
|
48675
48854
|
return paths;
|
|
@@ -48713,6 +48892,10 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
48713
48892
|
const drawRegion = (g, r, strokeWidth) => {
|
|
48714
48893
|
const p = g.append("path").attr("d", r.d).attr("fill", r.fill).attr("stroke", r.stroke).attr("stroke-width", strokeWidth);
|
|
48715
48894
|
if (r.label) p.attr("data-region-name", r.label);
|
|
48895
|
+
if (r.id && r.id !== "lake") p.attr("data-iso", r.id);
|
|
48896
|
+
if (r.labelX !== void 0 && r.labelY !== void 0) {
|
|
48897
|
+
p.attr("data-label-x", r.labelX).attr("data-label-y", r.labelY);
|
|
48898
|
+
}
|
|
48716
48899
|
if (r.layer !== "base") {
|
|
48717
48900
|
p.classed("dgmo-map-region", true).attr("data-region", r.id);
|
|
48718
48901
|
if (r.value !== void 0) p.attr("data-value", r.value);
|
|
@@ -48742,7 +48925,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
48742
48925
|
const landClip = defs.append("clipPath").attr("id", landClipId);
|
|
48743
48926
|
for (const r of layout.regions)
|
|
48744
48927
|
if (r.id !== "lake") landClip.append("path").attr("d", r.d);
|
|
48745
|
-
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");
|
|
48928
|
+
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");
|
|
48746
48929
|
for (let y = h.spacing; y < height; y += h.spacing) {
|
|
48747
48930
|
gRelief.append("line").attr("x1", 0).attr("y1", y).attr("x2", width).attr("y2", y);
|
|
48748
48931
|
}
|
|
@@ -48763,10 +48946,16 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
48763
48946
|
mask.append("path").attr("d", d).attr("fill", "black").attr("stroke", "black").attr("stroke-width", 2 * reach).attr("stroke-linejoin", "round");
|
|
48764
48947
|
}
|
|
48765
48948
|
}
|
|
48766
|
-
const gWater = svg.append("g").attr("class", "dgmo-map-water-lines").attr("fill", "none").attr("mask", `url(#${maskId})`);
|
|
48949
|
+
const gWater = svg.append("g").attr("class", "dgmo-map-water-lines").attr("fill", "none").style("pointer-events", "none").attr("mask", `url(#${maskId})`);
|
|
48767
48950
|
appendWaterLines(
|
|
48768
48951
|
gWater,
|
|
48769
|
-
|
|
48952
|
+
// Pass the canvas frame so edges collinear with it (the antimeridian on a
|
|
48953
|
+
// world map, regional clipExtent cuts) don't get ringed as fake coast —
|
|
48954
|
+
// land runs cleanly to the render-area edge.
|
|
48955
|
+
coastlineOuterRings(layout.regions, cs.minExtent, {
|
|
48956
|
+
w: width,
|
|
48957
|
+
h: height
|
|
48958
|
+
}),
|
|
48770
48959
|
cs,
|
|
48771
48960
|
layout.background
|
|
48772
48961
|
);
|
|
@@ -48780,7 +48969,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
48780
48969
|
gWater.append("path").attr("d", ds.join(" ")).attr("stroke", stroke2).attr("stroke-width", 0.5).attr("stroke-linejoin", "round");
|
|
48781
48970
|
}
|
|
48782
48971
|
if (layout.rivers.length) {
|
|
48783
|
-
const gRivers = svg.append("g").attr("class", "dgmo-map-rivers").attr("fill", "none");
|
|
48972
|
+
const gRivers = svg.append("g").attr("class", "dgmo-map-rivers").attr("fill", "none").style("pointer-events", "none");
|
|
48784
48973
|
for (const r of layout.rivers) {
|
|
48785
48974
|
gRivers.append("path").attr("d", r.d).attr("stroke", r.color).attr("stroke-width", r.width).attr("stroke-linecap", "round").attr("stroke-linejoin", "round");
|
|
48786
48975
|
}
|
|
@@ -48821,7 +49010,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
48821
49010
|
const d = box.points.map((p, i) => `${i ? "L" : "M"}${p[0]},${p[1]}`).join("") + "Z";
|
|
48822
49011
|
clip.append("path").attr("d", d);
|
|
48823
49012
|
}
|
|
48824
|
-
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})`);
|
|
49013
|
+
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})`);
|
|
48825
49014
|
appendWaterLines(
|
|
48826
49015
|
gInsetWater,
|
|
48827
49016
|
coastlineOuterRings(layout.insetRegions, cs.minExtent),
|
|
@@ -54839,10 +55028,12 @@ function renderTimelineHorizontalTimeSort(container, parsed, palette, isDark, se
|
|
|
54839
55028
|
const markerLabelY = markerReserve ? -(topScaleH + MARKER_ROW_H / 2) : 0;
|
|
54840
55029
|
const eraLabelY = eraReserve ? -(topScaleH + markerReserve + ERA_ROW_H / 2) : 0;
|
|
54841
55030
|
const innerWidth = width - margin.left - margin.right;
|
|
54842
|
-
const
|
|
54843
|
-
const rowH = Math.min(ctx.structural(28),
|
|
55031
|
+
const availInnerHeight = height - margin.top - margin.bottom;
|
|
55032
|
+
const rowH = Math.min(ctx.structural(28), availInnerHeight / sorted.length);
|
|
55033
|
+
const innerHeight = rowH * sorted.length;
|
|
55034
|
+
const usedHeight = margin.top + innerHeight + margin.bottom;
|
|
54844
55035
|
const xScale = d3Scale2.scaleLinear().domain([minDate - datePadding, maxDate + datePadding]).range([0, innerWidth]);
|
|
54845
|
-
const svg = d3Selection23.select(container).append("svg").attr("width", width).attr("height",
|
|
55036
|
+
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);
|
|
54846
55037
|
if (ctx.isBelowFloor) {
|
|
54847
55038
|
svg.attr("width", "100%");
|
|
54848
55039
|
}
|