@diagrammo/dgmo 0.19.0 → 0.20.1
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 +948 -321
- package/dist/advanced.d.cts +148 -54
- package/dist/advanced.d.ts +148 -54
- package/dist/advanced.js +949 -321
- package/dist/auto.cjs +930 -317
- package/dist/auto.js +117 -117
- package/dist/auto.mjs +934 -318
- package/dist/cli.cjs +160 -160
- package/dist/index.cjs +929 -316
- package/dist/index.js +933 -317
- package/dist/internal.cjs +948 -321
- package/dist/internal.d.cts +148 -54
- package/dist/internal.d.ts +148 -54
- package/dist/internal.js +949 -321
- package/dist/map-data/PROVENANCE.json +1 -1
- package/dist/map-data/lakes.json +1 -0
- package/dist/map-data/na-lakes.json +1 -0
- package/dist/map-data/na-land.json +1 -0
- package/dist/map-data/rivers.json +1 -0
- package/docs/language-reference.md +12 -7
- package/gallery/fixtures/map-region-scope.dgmo +15 -0
- package/package.json +4 -4
- package/src/advanced.ts +7 -6
- package/src/c4/parser.ts +6 -6
- package/src/completion.ts +6 -2
- package/src/echarts.ts +1 -1
- package/src/infra/parser.ts +10 -10
- package/src/journey-map/parser.ts +1 -1
- package/src/label-layout.ts +36 -0
- package/src/map/data/PROVENANCE.json +1 -1
- package/src/map/data/README.md +2 -0
- package/src/map/data/lakes.json +1 -0
- package/src/map/data/na-lakes.json +1 -0
- package/src/map/data/na-land.json +1 -0
- package/src/map/data/rivers.json +1 -0
- package/src/map/layout.ts +1022 -205
- package/src/map/load-data.ts +73 -17
- package/src/map/parser.ts +22 -13
- package/src/map/renderer.ts +200 -219
- package/src/map/resolved-types.ts +18 -1
- package/src/map/resolver.ts +79 -7
- package/src/map/types.ts +4 -0
- package/src/mindmap/parser.ts +1 -1
- package/src/sitemap/parser.ts +1 -1
- package/src/utils/legend-d3.ts +42 -0
- package/src/utils/legend-layout.ts +83 -3
- package/src/utils/legend-svg.ts +1 -8
- package/src/utils/legend-types.ts +44 -1
package/dist/auto.cjs
CHANGED
|
@@ -53,6 +53,33 @@ function rectCircleOverlap(rect, circle) {
|
|
|
53
53
|
const dy = nearestY - circle.cy;
|
|
54
54
|
return dx * dx + dy * dy < circle.r * circle.r;
|
|
55
55
|
}
|
|
56
|
+
function segmentRectOverlap(x0, y0, x1, y1, rect) {
|
|
57
|
+
const dx = x1 - x0;
|
|
58
|
+
const dy = y1 - y0;
|
|
59
|
+
let t0 = 0;
|
|
60
|
+
let t1 = 1;
|
|
61
|
+
const edges = [
|
|
62
|
+
[-dx, x0 - rect.x],
|
|
63
|
+
[dx, rect.x + rect.w - x0],
|
|
64
|
+
[-dy, y0 - rect.y],
|
|
65
|
+
[dy, rect.y + rect.h - y0]
|
|
66
|
+
];
|
|
67
|
+
for (const [p, q] of edges) {
|
|
68
|
+
if (p === 0) {
|
|
69
|
+
if (q < 0) return false;
|
|
70
|
+
} else {
|
|
71
|
+
const t = q / p;
|
|
72
|
+
if (p < 0) {
|
|
73
|
+
if (t > t1) return false;
|
|
74
|
+
if (t > t0) t0 = t;
|
|
75
|
+
} else {
|
|
76
|
+
if (t < t0) return false;
|
|
77
|
+
if (t < t1) t1 = t;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
56
83
|
function computeQuadrantPointLabels(points, chartBounds, obstacles, pointRadius, fontSize) {
|
|
57
84
|
const labelHeight = fontSize + 4;
|
|
58
85
|
const stepSize = labelHeight + 2;
|
|
@@ -3181,6 +3208,57 @@ var init_legend_constants = __esm({
|
|
|
3181
3208
|
});
|
|
3182
3209
|
|
|
3183
3210
|
// src/utils/legend-layout.ts
|
|
3211
|
+
function fmtRamp(n) {
|
|
3212
|
+
return Number.isInteger(n) ? String(n) : String(Math.round(n * 10) / 10);
|
|
3213
|
+
}
|
|
3214
|
+
function gradientCapsuleWidth(name, gradient) {
|
|
3215
|
+
const pw = pillWidth(name);
|
|
3216
|
+
const minW = measureLegendText(fmtRamp(gradient.min), LEGEND_ENTRY_FONT_SIZE);
|
|
3217
|
+
const maxW = measureLegendText(fmtRamp(gradient.max), LEGEND_ENTRY_FONT_SIZE);
|
|
3218
|
+
return LEGEND_CAPSULE_PAD + pw + 4 + minW + RAMP_LABEL_GAP + RAMP_LEGEND_W + RAMP_LABEL_GAP + maxW + LEGEND_CAPSULE_PAD;
|
|
3219
|
+
}
|
|
3220
|
+
function buildGradientCapsuleLayout(group, gradient) {
|
|
3221
|
+
const pw = pillWidth(group.name);
|
|
3222
|
+
const minText = fmtRamp(gradient.min);
|
|
3223
|
+
const maxText = fmtRamp(gradient.max);
|
|
3224
|
+
const minW = measureLegendText(minText, LEGEND_ENTRY_FONT_SIZE);
|
|
3225
|
+
const gx = LEGEND_CAPSULE_PAD + pw + 4;
|
|
3226
|
+
const minX = gx;
|
|
3227
|
+
const rampX = gx + minW + RAMP_LABEL_GAP;
|
|
3228
|
+
const maxX = rampX + RAMP_LEGEND_W + RAMP_LABEL_GAP;
|
|
3229
|
+
const width = gradientCapsuleWidth(group.name, gradient);
|
|
3230
|
+
return {
|
|
3231
|
+
groupName: group.name,
|
|
3232
|
+
x: 0,
|
|
3233
|
+
y: 0,
|
|
3234
|
+
width,
|
|
3235
|
+
height: LEGEND_HEIGHT,
|
|
3236
|
+
pill: {
|
|
3237
|
+
groupName: group.name,
|
|
3238
|
+
x: LEGEND_CAPSULE_PAD,
|
|
3239
|
+
y: LEGEND_CAPSULE_PAD,
|
|
3240
|
+
width: pw,
|
|
3241
|
+
height: LEGEND_HEIGHT - LEGEND_CAPSULE_PAD * 2,
|
|
3242
|
+
isActive: true
|
|
3243
|
+
},
|
|
3244
|
+
entries: [],
|
|
3245
|
+
gradient: {
|
|
3246
|
+
rampX,
|
|
3247
|
+
rampY: (LEGEND_HEIGHT - RAMP_LEGEND_H) / 2,
|
|
3248
|
+
rampW: RAMP_LEGEND_W,
|
|
3249
|
+
rampH: RAMP_LEGEND_H,
|
|
3250
|
+
min: gradient.min,
|
|
3251
|
+
max: gradient.max,
|
|
3252
|
+
minText,
|
|
3253
|
+
minX,
|
|
3254
|
+
maxText,
|
|
3255
|
+
maxX,
|
|
3256
|
+
textY: LEGEND_HEIGHT / 2,
|
|
3257
|
+
hue: gradient.hue,
|
|
3258
|
+
base: gradient.base
|
|
3259
|
+
}
|
|
3260
|
+
};
|
|
3261
|
+
}
|
|
3184
3262
|
function pillWidth(name) {
|
|
3185
3263
|
return measureLegendText(name, LEGEND_PILL_FONT_SIZE) + LEGEND_PILL_PAD;
|
|
3186
3264
|
}
|
|
@@ -3323,7 +3401,7 @@ function computeLegendLayout(config, state, containerWidth) {
|
|
|
3323
3401
|
};
|
|
3324
3402
|
}
|
|
3325
3403
|
const controlsGroupLayout = isExport ? void 0 : buildControlsGroupLayout(config, state);
|
|
3326
|
-
const visibleGroups = config.showEmptyGroups ? groups : groups.filter((g) => g.entries.length > 0);
|
|
3404
|
+
const visibleGroups = config.showEmptyGroups ? groups : groups.filter((g) => g.entries.length > 0 || !!g.gradient);
|
|
3327
3405
|
if (visibleGroups.length === 0 && (!configControls || configControls.length === 0) && !controlsGroupLayout) {
|
|
3328
3406
|
return {
|
|
3329
3407
|
height: 0,
|
|
@@ -3402,7 +3480,7 @@ function computeLegendLayout(config, state, containerWidth) {
|
|
|
3402
3480
|
groupAvailW,
|
|
3403
3481
|
config.capsulePillAddonWidth ?? 0
|
|
3404
3482
|
);
|
|
3405
|
-
} else if (!activeGroupName) {
|
|
3483
|
+
} else if (!activeGroupName || config.showInactivePills) {
|
|
3406
3484
|
const pw = pillWidth(g.name);
|
|
3407
3485
|
pills.push({
|
|
3408
3486
|
groupName: g.name,
|
|
@@ -3440,6 +3518,7 @@ function computeLegendLayout(config, state, containerWidth) {
|
|
|
3440
3518
|
};
|
|
3441
3519
|
}
|
|
3442
3520
|
function buildCapsuleLayout(group, containerWidth, addonWidth = 0) {
|
|
3521
|
+
if (group.gradient) return buildGradientCapsuleLayout(group, group.gradient);
|
|
3443
3522
|
const pw = pillWidth(group.name);
|
|
3444
3523
|
const info = capsuleWidth(
|
|
3445
3524
|
group.name,
|
|
@@ -3610,7 +3689,7 @@ function getMaxLegendReservedHeight(config, containerWidth) {
|
|
|
3610
3689
|
}
|
|
3611
3690
|
return max;
|
|
3612
3691
|
}
|
|
3613
|
-
var CONTROL_PILL_PAD, CONTROL_FONT_SIZE, CONTROL_ICON_GAP, CONTROL_GAP;
|
|
3692
|
+
var CONTROL_PILL_PAD, CONTROL_FONT_SIZE, CONTROL_ICON_GAP, CONTROL_GAP, RAMP_LEGEND_W, RAMP_LEGEND_H, RAMP_LABEL_GAP;
|
|
3614
3693
|
var init_legend_layout = __esm({
|
|
3615
3694
|
"src/utils/legend-layout.ts"() {
|
|
3616
3695
|
"use strict";
|
|
@@ -3619,6 +3698,9 @@ var init_legend_layout = __esm({
|
|
|
3619
3698
|
CONTROL_FONT_SIZE = 11;
|
|
3620
3699
|
CONTROL_ICON_GAP = 4;
|
|
3621
3700
|
CONTROL_GAP = 8;
|
|
3701
|
+
RAMP_LEGEND_W = 80;
|
|
3702
|
+
RAMP_LEGEND_H = 8;
|
|
3703
|
+
RAMP_LABEL_GAP = 6;
|
|
3622
3704
|
}
|
|
3623
3705
|
});
|
|
3624
3706
|
|
|
@@ -3706,6 +3788,16 @@ function renderCapsule(parent, capsule, palette, groupBg, pillBorder, _isDark, c
|
|
|
3706
3788
|
g.append("rect").attr("x", pill.x).attr("y", pill.y).attr("width", pill.width).attr("height", pill.height).attr("rx", pill.height / 2).attr("fill", palette.bg);
|
|
3707
3789
|
g.append("rect").attr("x", pill.x).attr("y", pill.y).attr("width", pill.width).attr("height", pill.height).attr("rx", pill.height / 2).attr("fill", "none").attr("stroke", pillBorder).attr("stroke-width", 0.75);
|
|
3708
3790
|
g.append("text").attr("x", pill.x + pill.width / 2).attr("y", LEGEND_HEIGHT / 2).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-size", LEGEND_PILL_FONT_SIZE).attr("font-weight", 500).attr("fill", palette.text).attr("pointer-events", "none").attr("font-family", FONT_FAMILY).text(capsule.groupName);
|
|
3791
|
+
if (capsule.gradient) {
|
|
3792
|
+
const gr = capsule.gradient;
|
|
3793
|
+
const gradId = `dgmo-legend-ramp-${capsule.groupName.toLowerCase().replace(/[^a-z0-9]+/g, "-")}`;
|
|
3794
|
+
const def = g.append("defs").append("linearGradient").attr("id", gradId);
|
|
3795
|
+
def.append("stop").attr("offset", "0%").attr("stop-color", mix(gr.hue, gr.base, 15));
|
|
3796
|
+
def.append("stop").attr("offset", "100%").attr("stop-color", gr.hue);
|
|
3797
|
+
g.append("text").attr("x", gr.minX).attr("y", gr.textY).attr("dominant-baseline", "central").attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("fill", palette.textMuted).attr("pointer-events", "none").attr("font-family", FONT_FAMILY).text(gr.minText);
|
|
3798
|
+
g.append("rect").attr("class", "dgmo-legend-gradient-ramp").attr("data-ramp-min", gr.min).attr("data-ramp-max", gr.max).attr("x", gr.rampX).attr("y", gr.rampY).attr("width", gr.rampW).attr("height", gr.rampH).attr("rx", 2).attr("fill", `url(#${gradId})`);
|
|
3799
|
+
g.append("text").attr("x", gr.maxX).attr("y", gr.textY).attr("dominant-baseline", "central").attr("font-size", LEGEND_ENTRY_FONT_SIZE).attr("fill", palette.textMuted).attr("pointer-events", "none").attr("font-family", FONT_FAMILY).text(gr.maxText);
|
|
3800
|
+
}
|
|
3709
3801
|
for (const entry of capsule.entries) {
|
|
3710
3802
|
const entryG = g.append("g").attr("data-legend-entry", entry.value.toLowerCase()).attr("data-series-name", entry.value).style("cursor", "pointer");
|
|
3711
3803
|
entryG.append("circle").attr("cx", entry.dotCx).attr("cy", entry.dotCy).attr("r", LEGEND_DOT_R).attr("fill", entry.color);
|
|
@@ -11179,23 +11271,22 @@ function parseC4(content, palette) {
|
|
|
11179
11271
|
}
|
|
11180
11272
|
}
|
|
11181
11273
|
const parent = findParentElement(indent, stack);
|
|
11182
|
-
|
|
11183
|
-
|
|
11274
|
+
const descResult = tryStripDescriptionKeyword(trimmed);
|
|
11275
|
+
if (parent && descResult.isKeyword) {
|
|
11184
11276
|
if (descResult.needsColon) {
|
|
11185
11277
|
pushError(
|
|
11186
11278
|
lineNumber,
|
|
11187
|
-
`Use "description: ${descResult.text}" \u2014
|
|
11279
|
+
`Use "description: ${descResult.text}" \u2014 bare "description" is deprecated.`,
|
|
11188
11280
|
"warning"
|
|
11189
11281
|
);
|
|
11190
11282
|
}
|
|
11191
|
-
const descText = descResult.isKeyword ? descResult.text : trimmed;
|
|
11192
11283
|
let desc = elementDescription.get(parent.element);
|
|
11193
11284
|
if (!desc) {
|
|
11194
11285
|
desc = [];
|
|
11195
11286
|
elementDescription.set(parent.element, desc);
|
|
11196
11287
|
parent.element.description = desc;
|
|
11197
11288
|
}
|
|
11198
|
-
desc.push(
|
|
11289
|
+
desc.push(descResult.text);
|
|
11199
11290
|
} else {
|
|
11200
11291
|
pushError(lineNumber, `Unexpected content: "${trimmed}"`);
|
|
11201
11292
|
}
|
|
@@ -11662,7 +11753,7 @@ function parseSitemap(content, palette) {
|
|
|
11662
11753
|
if (descResult.needsColon) {
|
|
11663
11754
|
pushWarning(
|
|
11664
11755
|
lineNumber,
|
|
11665
|
-
`Use "description: ${descResult.text}" \u2014
|
|
11756
|
+
`Use "description: ${descResult.text}" \u2014 bare "description" is deprecated.`
|
|
11666
11757
|
);
|
|
11667
11758
|
}
|
|
11668
11759
|
const parent = findParentNode(indent, indentStack);
|
|
@@ -12490,23 +12581,22 @@ function parseInfra(content) {
|
|
|
12490
12581
|
}
|
|
12491
12582
|
}
|
|
12492
12583
|
const descResult = tryStripDescriptionKeyword(trimmed);
|
|
12493
|
-
if (descResult.isKeyword
|
|
12494
|
-
|
|
12495
|
-
|
|
12496
|
-
|
|
12584
|
+
if (descResult.isKeyword) {
|
|
12585
|
+
if (currentNode.isEdge) {
|
|
12586
|
+
continue;
|
|
12587
|
+
}
|
|
12497
12588
|
if (descResult.needsColon) {
|
|
12498
12589
|
warn2(
|
|
12499
12590
|
lineNumber,
|
|
12500
|
-
`Use "description: ${descResult.text}" \u2014
|
|
12591
|
+
`Use "description: ${descResult.text}" \u2014 bare "description" is deprecated.`
|
|
12501
12592
|
);
|
|
12502
12593
|
}
|
|
12503
|
-
|
|
12504
|
-
pushDescription(currentNode, descText);
|
|
12594
|
+
pushDescription(currentNode, descResult.text);
|
|
12505
12595
|
continue;
|
|
12506
12596
|
}
|
|
12507
12597
|
warn2(
|
|
12508
12598
|
lineNumber,
|
|
12509
|
-
`Unexpected line inside component '${currentNode.label}'. Expected a property (key: value), connection (-> Target), or description text.`
|
|
12599
|
+
`Unexpected line inside component '${currentNode.label}'. Expected a property (key: value), connection (-> Target), or a description (description: text).`
|
|
12510
12600
|
);
|
|
12511
12601
|
continue;
|
|
12512
12602
|
}
|
|
@@ -15643,9 +15733,6 @@ function parseMap(content) {
|
|
|
15643
15733
|
const pushWarning = (line12, message) => {
|
|
15644
15734
|
diagnostics.push(makeDgmoError(line12, message, "warning"));
|
|
15645
15735
|
};
|
|
15646
|
-
const pushInfo = (line12, message) => {
|
|
15647
|
-
diagnostics.push(makeDgmoError(line12, message, "warning"));
|
|
15648
|
-
};
|
|
15649
15736
|
const lines = content.split("\n");
|
|
15650
15737
|
let firstIdx = 0;
|
|
15651
15738
|
while (firstIdx < lines.length) {
|
|
@@ -15775,10 +15862,15 @@ function parseMap(content) {
|
|
|
15775
15862
|
break;
|
|
15776
15863
|
case "projection":
|
|
15777
15864
|
dup(d.projection);
|
|
15778
|
-
if (value && ![
|
|
15865
|
+
if (value && ![
|
|
15866
|
+
"equirectangular",
|
|
15867
|
+
"natural-earth",
|
|
15868
|
+
"albers-usa",
|
|
15869
|
+
"mercator"
|
|
15870
|
+
].includes(value))
|
|
15779
15871
|
pushWarning(
|
|
15780
15872
|
line12,
|
|
15781
|
-
`Unknown projection "${value}" (expected natural-earth | albers-usa | mercator).`
|
|
15873
|
+
`Unknown projection "${value}" (expected equirectangular | natural-earth | albers-usa | mercator).`
|
|
15782
15874
|
);
|
|
15783
15875
|
d.projection = value;
|
|
15784
15876
|
break;
|
|
@@ -15917,17 +16009,21 @@ function parseMap(content) {
|
|
|
15917
16009
|
scoreNum = void 0;
|
|
15918
16010
|
}
|
|
15919
16011
|
}
|
|
15920
|
-
|
|
15921
|
-
|
|
15922
|
-
|
|
15923
|
-
|
|
15924
|
-
|
|
16012
|
+
let regionName = split.name;
|
|
16013
|
+
let regionScope;
|
|
16014
|
+
const rToks = regionName.split(/\s+/);
|
|
16015
|
+
const rLast = rToks[rToks.length - 1];
|
|
16016
|
+
if (rToks.length > 1 && SCOPE_RE.test(rLast)) {
|
|
16017
|
+
regionName = rToks.slice(0, -1).join(" ");
|
|
16018
|
+
regionScope = rLast;
|
|
16019
|
+
}
|
|
15925
16020
|
const region = {
|
|
15926
|
-
name:
|
|
16021
|
+
name: regionName,
|
|
15927
16022
|
tags,
|
|
15928
16023
|
meta,
|
|
15929
16024
|
lineNumber: line12
|
|
15930
16025
|
};
|
|
16026
|
+
if (regionScope !== void 0) region.scope = regionScope;
|
|
15931
16027
|
if (scoreNum !== void 0) region.score = scoreNum;
|
|
15932
16028
|
regions.push(region);
|
|
15933
16029
|
}
|
|
@@ -17051,7 +17147,7 @@ function parseMindmap(content, palette) {
|
|
|
17051
17147
|
if (descResult.needsColon) {
|
|
17052
17148
|
pushWarning(
|
|
17053
17149
|
lineNumber,
|
|
17054
|
-
`Use "description: ${descResult.text}" \u2014
|
|
17150
|
+
`Use "description: ${descResult.text}" \u2014 bare "description" is deprecated.`
|
|
17055
17151
|
);
|
|
17056
17152
|
}
|
|
17057
17153
|
const parent = findMetadataParent2(indent, indentStack);
|
|
@@ -18839,7 +18935,7 @@ function parseJourneyMap(content, palette) {
|
|
|
18839
18935
|
if (descResult.needsColon) {
|
|
18840
18936
|
warn2(
|
|
18841
18937
|
lineNumber,
|
|
18842
|
-
`Use "description: ${descResult.text}" \u2014
|
|
18938
|
+
`Use "description: ${descResult.text}" \u2014 bare "description" is deprecated.`
|
|
18843
18939
|
);
|
|
18844
18940
|
}
|
|
18845
18941
|
currentStep.description = descResult.text;
|
|
@@ -45428,7 +45524,9 @@ function resolveMap(parsed, data) {
|
|
|
45428
45524
|
const usScoped = parsed.directives.region === "us-states" || parsed.directives.defaultCountry?.toUpperCase() === "US" || parsed.regions.some((r) => {
|
|
45429
45525
|
const f = fold(r.name);
|
|
45430
45526
|
return usStateIndex.has(f) && !countryIndex.has(f);
|
|
45431
|
-
}) || parsed.
|
|
45527
|
+
}) || parsed.regions.some(
|
|
45528
|
+
(r) => r.scope === "US" || r.scope?.startsWith("US-")
|
|
45529
|
+
) || parsed.pois.some(
|
|
45432
45530
|
(p) => p.pos.kind === "name" && p.pos.scope?.startsWith("US-")
|
|
45433
45531
|
);
|
|
45434
45532
|
const regions = [];
|
|
@@ -45440,7 +45538,30 @@ function resolveMap(parsed, data) {
|
|
|
45440
45538
|
const inCountry = countryIndex.get(f) ?? (REGION_ALIASES[f] ? countryIndex.get(REGION_ALIASES[f]) : void 0);
|
|
45441
45539
|
const inState = usStateIndex.get(f);
|
|
45442
45540
|
let chosen = null;
|
|
45443
|
-
|
|
45541
|
+
const scope = r.scope;
|
|
45542
|
+
if (scope) {
|
|
45543
|
+
const wantsState = scope === "US" || scope.startsWith("US-");
|
|
45544
|
+
if (wantsState && inState) {
|
|
45545
|
+
if (scope.startsWith("US-") && inState.id !== scope) {
|
|
45546
|
+
err(
|
|
45547
|
+
r.lineNumber,
|
|
45548
|
+
`No subdivision "${r.name}" in scope ${scope} (it is ${inState.id}).`,
|
|
45549
|
+
"E_MAP_SCOPE_MISS"
|
|
45550
|
+
);
|
|
45551
|
+
continue;
|
|
45552
|
+
}
|
|
45553
|
+
chosen = { ...inState, layer: "us-state" };
|
|
45554
|
+
} else if (!wantsState && inCountry) {
|
|
45555
|
+
chosen = { ...inCountry, layer: "country" };
|
|
45556
|
+
} else {
|
|
45557
|
+
err(
|
|
45558
|
+
r.lineNumber,
|
|
45559
|
+
`No region "${r.name}" found in scope ${scope}.`,
|
|
45560
|
+
"E_MAP_SCOPE_MISS"
|
|
45561
|
+
);
|
|
45562
|
+
continue;
|
|
45563
|
+
}
|
|
45564
|
+
} else if (inCountry && inState) {
|
|
45444
45565
|
if (usScoped) {
|
|
45445
45566
|
chosen = { ...inState, layer: "us-state" };
|
|
45446
45567
|
} else {
|
|
@@ -45448,7 +45569,7 @@ function resolveMap(parsed, data) {
|
|
|
45448
45569
|
}
|
|
45449
45570
|
warn2(
|
|
45450
45571
|
r.lineNumber,
|
|
45451
|
-
`"${r.name}" is both a country and a US state \u2014 resolved as ${chosen.layer} (${chosen.id}).`,
|
|
45572
|
+
`"${r.name}" is both a country and a US state \u2014 resolved as ${chosen.layer} (${chosen.id}). Pin it with an ISO code (${inState.id} / ${inCountry.id}) or name + scope ("${r.name} US" / "${r.name} ${inCountry.id}").`,
|
|
45452
45573
|
"W_MAP_REGION_AMBIGUOUS"
|
|
45453
45574
|
);
|
|
45454
45575
|
} else if (inState) {
|
|
@@ -45620,9 +45741,17 @@ function resolveMap(parsed, data) {
|
|
|
45620
45741
|
};
|
|
45621
45742
|
registerPoi(id, poi, p.lineNumber);
|
|
45622
45743
|
}
|
|
45744
|
+
const declaredByName = /* @__PURE__ */ new Map();
|
|
45745
|
+
for (const p of pois) {
|
|
45746
|
+
const fn = p.name ? fold(p.name) : void 0;
|
|
45747
|
+
if (fn && fn !== p.id && !declaredByName.has(fn))
|
|
45748
|
+
declaredByName.set(fn, p.id);
|
|
45749
|
+
}
|
|
45623
45750
|
const resolveEndpoint2 = (ref, line12) => {
|
|
45624
45751
|
const f = fold(ref);
|
|
45625
45752
|
if (registry.has(f)) return f;
|
|
45753
|
+
const aliased = declaredByName.get(f);
|
|
45754
|
+
if (aliased) return aliased;
|
|
45626
45755
|
const got = lookupName(ref, void 0, line12, inferredCountry, true);
|
|
45627
45756
|
if (got.kind !== "ok") return null;
|
|
45628
45757
|
noteCountry(got.iso);
|
|
@@ -45702,23 +45831,29 @@ function resolveMap(parsed, data) {
|
|
|
45702
45831
|
[-180, -85],
|
|
45703
45832
|
[180, 85]
|
|
45704
45833
|
];
|
|
45705
|
-
|
|
45834
|
+
let extent2 = unioned ? pad(unioned, PAD_FRACTION) : DEFAULT_EXTENT;
|
|
45706
45835
|
const lonSpan = extent2[1][0] - extent2[0][0];
|
|
45707
45836
|
const latSpan = extent2[1][1] - extent2[0][1];
|
|
45708
45837
|
const span = Math.max(lonSpan, latSpan);
|
|
45709
45838
|
const usDominant = (inferredCountry === "US" || subdivisions.includes("us-states")) && !regions.some((r) => r.layer === "country" && r.iso !== "US") && !anyNonUsPoi;
|
|
45710
45839
|
let projection;
|
|
45711
45840
|
const override = parsed.directives.projection;
|
|
45712
|
-
if (override === "natural-earth" || override === "albers-usa" || override === "mercator") {
|
|
45841
|
+
if (override === "equirectangular" || override === "natural-earth" || override === "albers-usa" || override === "mercator") {
|
|
45713
45842
|
projection = override;
|
|
45714
45843
|
} else if (usDominant) {
|
|
45715
45844
|
projection = "albers-usa";
|
|
45716
45845
|
} else if (span > WORLD_SPAN) {
|
|
45717
|
-
projection = "
|
|
45846
|
+
projection = "equirectangular";
|
|
45718
45847
|
} else if (span < MERCATOR_MAX_SPAN) {
|
|
45719
45848
|
projection = "mercator";
|
|
45720
45849
|
} else {
|
|
45721
|
-
projection = "
|
|
45850
|
+
projection = "equirectangular";
|
|
45851
|
+
}
|
|
45852
|
+
if (lonSpan >= 180) {
|
|
45853
|
+
extent2 = [
|
|
45854
|
+
[-180, Math.min(extent2[0][1], WORLD_LAT_SOUTH)],
|
|
45855
|
+
[180, Math.max(extent2[1][1], WORLD_LAT_NORTH)]
|
|
45856
|
+
];
|
|
45722
45857
|
}
|
|
45723
45858
|
result.regions = regions;
|
|
45724
45859
|
result.pois = pois;
|
|
@@ -45766,7 +45901,7 @@ function firstError(diags) {
|
|
|
45766
45901
|
const e = diags.find((d) => d.severity === "error");
|
|
45767
45902
|
return e ? formatDgmoError(e) : null;
|
|
45768
45903
|
}
|
|
45769
|
-
var WORLD_SPAN, MERCATOR_MAX_SPAN, PAD_FRACTION, REGION_ALIASES;
|
|
45904
|
+
var WORLD_SPAN, MERCATOR_MAX_SPAN, PAD_FRACTION, WORLD_LAT_SOUTH, WORLD_LAT_NORTH, REGION_ALIASES;
|
|
45770
45905
|
var init_resolver2 = __esm({
|
|
45771
45906
|
"src/map/resolver.ts"() {
|
|
45772
45907
|
"use strict";
|
|
@@ -45775,6 +45910,8 @@ var init_resolver2 = __esm({
|
|
|
45775
45910
|
WORLD_SPAN = 90;
|
|
45776
45911
|
MERCATOR_MAX_SPAN = 25;
|
|
45777
45912
|
PAD_FRACTION = 0.05;
|
|
45913
|
+
WORLD_LAT_SOUTH = -58;
|
|
45914
|
+
WORLD_LAT_NORTH = 78;
|
|
45778
45915
|
REGION_ALIASES = {
|
|
45779
45916
|
// Common everyday names → the Natural-Earth display name actually shipped.
|
|
45780
45917
|
"united states": "united states of america",
|
|
@@ -45804,14 +45941,22 @@ var load_data_exports = {};
|
|
|
45804
45941
|
__export(load_data_exports, {
|
|
45805
45942
|
loadMapData: () => loadMapData
|
|
45806
45943
|
});
|
|
45807
|
-
async function
|
|
45808
|
-
|
|
45944
|
+
async function loadNodeBuiltins() {
|
|
45945
|
+
const [{ readFile }, { fileURLToPath }, { dirname, resolve }] = await Promise.all([
|
|
45946
|
+
import("fs/promises"),
|
|
45947
|
+
import("url"),
|
|
45948
|
+
import("path")
|
|
45949
|
+
]);
|
|
45950
|
+
return { readFile, fileURLToPath, dirname, resolve };
|
|
45951
|
+
}
|
|
45952
|
+
async function readJson(nb, dir, name) {
|
|
45953
|
+
return JSON.parse(await nb.readFile(nb.resolve(dir, name), "utf8"));
|
|
45809
45954
|
}
|
|
45810
|
-
async function firstExistingDir(baseDir) {
|
|
45955
|
+
async function firstExistingDir(nb, baseDir) {
|
|
45811
45956
|
for (const rel of CANDIDATE_DIRS) {
|
|
45812
|
-
const dir =
|
|
45957
|
+
const dir = nb.resolve(baseDir, rel);
|
|
45813
45958
|
try {
|
|
45814
|
-
await
|
|
45959
|
+
await nb.readFile(nb.resolve(dir, FILES.gazetteer), "utf8");
|
|
45815
45960
|
return dir;
|
|
45816
45961
|
} catch {
|
|
45817
45962
|
}
|
|
@@ -45827,10 +45972,10 @@ function validate(data) {
|
|
|
45827
45972
|
}
|
|
45828
45973
|
return data;
|
|
45829
45974
|
}
|
|
45830
|
-
function moduleBaseDir() {
|
|
45975
|
+
function moduleBaseDir(nb) {
|
|
45831
45976
|
try {
|
|
45832
45977
|
const url = import_meta.url;
|
|
45833
|
-
if (url) return
|
|
45978
|
+
if (url) return nb.dirname(nb.fileURLToPath(url));
|
|
45834
45979
|
} catch {
|
|
45835
45980
|
}
|
|
45836
45981
|
if (typeof __dirname !== "undefined") return __dirname;
|
|
@@ -45838,32 +45983,57 @@ function moduleBaseDir() {
|
|
|
45838
45983
|
}
|
|
45839
45984
|
function loadMapData() {
|
|
45840
45985
|
cache ??= (async () => {
|
|
45841
|
-
const
|
|
45842
|
-
const
|
|
45843
|
-
|
|
45844
|
-
|
|
45845
|
-
|
|
45846
|
-
|
|
45986
|
+
const nb = await loadNodeBuiltins();
|
|
45987
|
+
const dir = await firstExistingDir(nb, moduleBaseDir(nb));
|
|
45988
|
+
const [
|
|
45989
|
+
worldCoarse,
|
|
45990
|
+
worldDetail,
|
|
45991
|
+
usStates,
|
|
45992
|
+
lakes,
|
|
45993
|
+
rivers,
|
|
45994
|
+
naLand,
|
|
45995
|
+
naLakes,
|
|
45996
|
+
gazetteer
|
|
45997
|
+
] = await Promise.all([
|
|
45998
|
+
readJson(nb, dir, FILES.worldCoarse),
|
|
45999
|
+
readJson(nb, dir, FILES.worldDetail),
|
|
46000
|
+
readJson(nb, dir, FILES.usStates),
|
|
46001
|
+
// Lakes/rivers/NA assets are optional — older bundles may predate them.
|
|
46002
|
+
readJson(nb, dir, FILES.lakes).catch(() => void 0),
|
|
46003
|
+
readJson(nb, dir, FILES.rivers).catch(() => void 0),
|
|
46004
|
+
readJson(nb, dir, FILES.naLand).catch(() => void 0),
|
|
46005
|
+
readJson(nb, dir, FILES.naLakes).catch(() => void 0),
|
|
46006
|
+
readJson(nb, dir, FILES.gazetteer)
|
|
45847
46007
|
]);
|
|
45848
|
-
return validate({
|
|
46008
|
+
return validate({
|
|
46009
|
+
worldCoarse,
|
|
46010
|
+
worldDetail,
|
|
46011
|
+
usStates,
|
|
46012
|
+
gazetteer,
|
|
46013
|
+
...lakes && { lakes },
|
|
46014
|
+
...rivers && { rivers },
|
|
46015
|
+
...naLand && { naLand },
|
|
46016
|
+
...naLakes && { naLakes }
|
|
46017
|
+
});
|
|
45849
46018
|
})().catch((e) => {
|
|
45850
46019
|
cache = void 0;
|
|
45851
46020
|
throw e;
|
|
45852
46021
|
});
|
|
45853
46022
|
return cache;
|
|
45854
46023
|
}
|
|
45855
|
-
var
|
|
46024
|
+
var import_meta, FILES, CANDIDATE_DIRS, cache;
|
|
45856
46025
|
var init_load_data = __esm({
|
|
45857
46026
|
"src/map/load-data.ts"() {
|
|
45858
46027
|
"use strict";
|
|
45859
|
-
import_promises = require("fs/promises");
|
|
45860
|
-
import_node_url = require("url");
|
|
45861
|
-
import_node_path = require("path");
|
|
45862
46028
|
import_meta = {};
|
|
45863
46029
|
FILES = {
|
|
45864
46030
|
worldCoarse: "world-coarse.json",
|
|
45865
46031
|
worldDetail: "world-detail.json",
|
|
45866
46032
|
usStates: "us-states.json",
|
|
46033
|
+
lakes: "lakes.json",
|
|
46034
|
+
rivers: "rivers.json",
|
|
46035
|
+
naLand: "na-land.json",
|
|
46036
|
+
naLakes: "na-lakes.json",
|
|
45867
46037
|
gazetteer: "gazetteer.json"
|
|
45868
46038
|
};
|
|
45869
46039
|
CANDIDATE_DIRS = [
|
|
@@ -45891,36 +46061,67 @@ function decodeLayer(topo) {
|
|
|
45891
46061
|
function projectionFor(family) {
|
|
45892
46062
|
switch (family) {
|
|
45893
46063
|
case "albers-usa":
|
|
45894
|
-
return (
|
|
46064
|
+
return usConusProjection();
|
|
45895
46065
|
case "mercator":
|
|
45896
46066
|
return (0, import_d3_geo2.geoMercator)();
|
|
45897
46067
|
case "natural-earth":
|
|
45898
|
-
default:
|
|
45899
46068
|
return (0, import_d3_geo2.geoNaturalEarth1)();
|
|
46069
|
+
case "equirectangular":
|
|
46070
|
+
default:
|
|
46071
|
+
return (0, import_d3_geo2.geoEquirectangular)();
|
|
45900
46072
|
}
|
|
45901
46073
|
}
|
|
46074
|
+
function mapBackgroundColor(palette) {
|
|
46075
|
+
return mix(palette.colors.blue, palette.bg, WATER_TINT);
|
|
46076
|
+
}
|
|
45902
46077
|
function layoutMap(resolved, data, size, opts) {
|
|
45903
46078
|
const { palette, isDark } = opts;
|
|
45904
46079
|
const { width, height } = size;
|
|
45905
|
-
const
|
|
46080
|
+
const wantsUsStates = resolved.basemaps.subdivisions.includes("us-states");
|
|
46081
|
+
const usCrisp = resolved.projection === "albers-usa" && wantsUsStates && !!data.naLand;
|
|
46082
|
+
const worldTopo = usCrisp ? data.naLand : resolved.basemaps.world === "detail" ? data.worldDetail : data.worldCoarse;
|
|
45906
46083
|
const worldLayer = decodeLayer(worldTopo);
|
|
45907
|
-
const usLayer =
|
|
45908
|
-
const
|
|
45909
|
-
const
|
|
46084
|
+
const usLayer = wantsUsStates ? decodeLayer(data.usStates) : null;
|
|
46085
|
+
const landTint = isDark ? LAND_TINT_DARK : LAND_TINT_LIGHT;
|
|
46086
|
+
const neutralFill = mix(palette.colors.green, palette.bg, landTint);
|
|
46087
|
+
const water = mapBackgroundColor(palette);
|
|
46088
|
+
const usContext = usLayer !== null;
|
|
46089
|
+
const foreignFill = mix(
|
|
46090
|
+
palette.colors.gray,
|
|
46091
|
+
palette.bg,
|
|
46092
|
+
isDark ? FOREIGN_TINT_DARK : FOREIGN_TINT_LIGHT
|
|
46093
|
+
);
|
|
46094
|
+
const regionStroke = isDark ? mix(palette.bg, palette.text, 78) : mix(palette.text, palette.bg, 78);
|
|
45910
46095
|
const scores = resolved.regions.filter((r) => r.score !== void 0).map((r) => r.score);
|
|
45911
46096
|
const scaleOverride = resolved.directives.scale;
|
|
45912
46097
|
const rampMin = scaleOverride ? scaleOverride.min : Math.min(...scores);
|
|
45913
46098
|
const rampMax = scaleOverride ? scaleOverride.max : Math.max(...scores);
|
|
45914
|
-
const rampHue = palette.
|
|
46099
|
+
const rampHue = palette.colors.red;
|
|
45915
46100
|
const hasRamp = scores.length > 0;
|
|
45916
|
-
const
|
|
45917
|
-
|
|
45918
|
-
|
|
45919
|
-
|
|
46101
|
+
const SCORE_NAME = hasRamp ? resolved.directives.metric?.trim() || "Score" : null;
|
|
46102
|
+
const matchColorGroup = (v) => {
|
|
46103
|
+
const lv = v.trim().toLowerCase();
|
|
46104
|
+
if (lv === "none") return null;
|
|
46105
|
+
if (SCORE_NAME && (lv === "score" || lv === SCORE_NAME.toLowerCase()))
|
|
46106
|
+
return SCORE_NAME;
|
|
46107
|
+
const tg = resolved.tagGroups.find((g) => g.name.toLowerCase() === lv);
|
|
46108
|
+
return tg ? tg.name : v;
|
|
46109
|
+
};
|
|
46110
|
+
const override = opts.activeGroup;
|
|
46111
|
+
let activeGroup;
|
|
46112
|
+
if (override !== void 0) {
|
|
46113
|
+
activeGroup = override === null ? null : matchColorGroup(override);
|
|
46114
|
+
} else if (resolved.directives.activeTag !== void 0) {
|
|
46115
|
+
activeGroup = matchColorGroup(resolved.directives.activeTag);
|
|
46116
|
+
} else {
|
|
46117
|
+
activeGroup = SCORE_NAME ?? (resolved.tagGroups.length > 0 ? resolved.tagGroups[0].name : null);
|
|
46118
|
+
}
|
|
46119
|
+
const activeIsScore = SCORE_NAME !== null && activeGroup === SCORE_NAME;
|
|
46120
|
+
const rampBase = isDark ? mix(palette.surface, palette.text, 28) : palette.bg;
|
|
45920
46121
|
const fillForScore = (s) => {
|
|
45921
46122
|
const t = rampMax > rampMin ? (s - rampMin) / (rampMax - rampMin) : 1;
|
|
45922
46123
|
const pct = RAMP_FLOOR + Math.max(0, Math.min(1, t)) * (100 - RAMP_FLOOR);
|
|
45923
|
-
return mix(rampHue,
|
|
46124
|
+
return mix(rampHue, rampBase, pct);
|
|
45924
46125
|
};
|
|
45925
46126
|
const tagFill = (tags, groupName) => {
|
|
45926
46127
|
if (!groupName) return null;
|
|
@@ -45934,40 +46135,40 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
45934
46135
|
(e) => e.value.toLowerCase() === val.toLowerCase()
|
|
45935
46136
|
);
|
|
45936
46137
|
if (!entry?.color) return null;
|
|
45937
|
-
return
|
|
46138
|
+
return mix(
|
|
46139
|
+
entry.color,
|
|
46140
|
+
palette.bg,
|
|
46141
|
+
isDark ? TAG_TINT_DARK : TAG_TINT_LIGHT
|
|
46142
|
+
);
|
|
46143
|
+
};
|
|
46144
|
+
const regionFill = (r) => {
|
|
46145
|
+
if (activeIsScore) {
|
|
46146
|
+
return r.score !== void 0 ? fillForScore(r.score) : neutralFill;
|
|
46147
|
+
}
|
|
46148
|
+
return tagFill(r.tags, activeGroup) ?? neutralFill;
|
|
45938
46149
|
};
|
|
45939
46150
|
const regionById = new Map(resolved.regions.map((r) => [r.iso, r]));
|
|
45940
|
-
const
|
|
45941
|
-
for (const r of resolved.regions) {
|
|
45942
|
-
const f = r.layer === "us-state" ? usLayer?.get(r.iso) : worldLayer.get(r.iso);
|
|
45943
|
-
if (f) regionFeatures.push(f);
|
|
45944
|
-
}
|
|
45945
|
-
const extentCorners = () => {
|
|
46151
|
+
const extentOutline = () => {
|
|
45946
46152
|
const [[w, s], [e, n]] = resolved.extent;
|
|
46153
|
+
const N = 16;
|
|
46154
|
+
const coords = [];
|
|
46155
|
+
for (let i = 0; i <= N; i++) {
|
|
46156
|
+
const t = i / N;
|
|
46157
|
+
const lon = w + (e - w) * t;
|
|
46158
|
+
const lat = s + (n - s) * t;
|
|
46159
|
+
coords.push([lon, s], [lon, n], [w, lat], [e, lat]);
|
|
46160
|
+
}
|
|
45947
46161
|
return {
|
|
45948
46162
|
type: "Feature",
|
|
45949
46163
|
properties: {},
|
|
45950
|
-
geometry: {
|
|
45951
|
-
type: "MultiPoint",
|
|
45952
|
-
coordinates: [
|
|
45953
|
-
[w, s],
|
|
45954
|
-
[e, s],
|
|
45955
|
-
[e, n],
|
|
45956
|
-
[w, n]
|
|
45957
|
-
]
|
|
45958
|
-
}
|
|
46164
|
+
geometry: { type: "MultiPoint", coordinates: coords }
|
|
45959
46165
|
};
|
|
45960
46166
|
};
|
|
45961
46167
|
let fitFeatures;
|
|
45962
|
-
if (resolved.projection === "albers-usa") {
|
|
45963
|
-
|
|
45964
|
-
else if (usLayer) fitFeatures = [...usLayer.values()];
|
|
45965
|
-
else {
|
|
45966
|
-
const us = worldLayer.get("US");
|
|
45967
|
-
fitFeatures = us ? [us] : [...worldLayer.values()];
|
|
45968
|
-
}
|
|
46168
|
+
if (resolved.projection === "albers-usa" && usLayer) {
|
|
46169
|
+
fitFeatures = [...usLayer.entries()].filter(([iso]) => !US_NON_CONUS.has(iso)).map(([, f]) => f);
|
|
45969
46170
|
} else {
|
|
45970
|
-
fitFeatures = [
|
|
46171
|
+
fitFeatures = [extentOutline()];
|
|
45971
46172
|
}
|
|
45972
46173
|
const fitTarget = { type: "FeatureCollection", features: fitFeatures };
|
|
45973
46174
|
const projection = projectionFor(resolved.projection);
|
|
@@ -45976,32 +46177,311 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
45976
46177
|
if (centerLon > 180) centerLon -= 360;
|
|
45977
46178
|
projection.rotate([-centerLon, 0]);
|
|
45978
46179
|
}
|
|
45979
|
-
|
|
46180
|
+
const TITLE_GAP = 16;
|
|
46181
|
+
let topPad = FIT_PAD;
|
|
46182
|
+
if (resolved.title && resolved.pois.length > 0) {
|
|
46183
|
+
const bannerBottom = (resolved.subtitle ? TITLE_Y + TITLE_FONT_SIZE : TITLE_Y) + TITLE_FONT_SIZE / 2;
|
|
46184
|
+
topPad = Math.max(FIT_PAD, bannerBottom + TITLE_GAP);
|
|
46185
|
+
}
|
|
46186
|
+
const fitBox = [
|
|
46187
|
+
[FIT_PAD, topPad],
|
|
45980
46188
|
[
|
|
45981
|
-
|
|
45982
|
-
|
|
45983
|
-
|
|
45984
|
-
|
|
45985
|
-
|
|
45986
|
-
|
|
45987
|
-
|
|
45988
|
-
|
|
45989
|
-
|
|
45990
|
-
|
|
46189
|
+
Math.max(FIT_PAD + 1, width - FIT_PAD),
|
|
46190
|
+
Math.max(topPad + 1, height - FIT_PAD)
|
|
46191
|
+
]
|
|
46192
|
+
];
|
|
46193
|
+
projection.fitExtent(fitBox, fitTarget);
|
|
46194
|
+
const fitGB = (0, import_d3_geo2.geoBounds)(fitTarget);
|
|
46195
|
+
const fitIsGlobal = fitGB[1][0] - fitGB[0][0] >= 270 || fitGB[1][1] - fitGB[0][1] >= 130;
|
|
46196
|
+
let path;
|
|
46197
|
+
let project;
|
|
46198
|
+
if (fitIsGlobal) {
|
|
46199
|
+
const cb = (0, import_d3_geo2.geoPath)(projection).bounds(fitTarget);
|
|
46200
|
+
const bx0 = cb[0][0];
|
|
46201
|
+
const by0 = cb[0][1];
|
|
46202
|
+
const cw = cb[1][0] - bx0;
|
|
46203
|
+
const ch = cb[1][1] - by0;
|
|
46204
|
+
const ox = fitBox[0][0];
|
|
46205
|
+
const oy = fitBox[0][1];
|
|
46206
|
+
const sx = cw > 0 ? (fitBox[1][0] - ox) / cw : 1;
|
|
46207
|
+
const sy = ch > 0 ? (fitBox[1][1] - oy) / ch : 1;
|
|
46208
|
+
const stretch = (x, y) => [
|
|
46209
|
+
ox + (x - bx0) * sx,
|
|
46210
|
+
oy + (y - by0) * sy
|
|
46211
|
+
];
|
|
46212
|
+
const baseProjection = projection;
|
|
46213
|
+
const tx = (0, import_d3_geo2.geoTransform)({
|
|
46214
|
+
point(x, y) {
|
|
46215
|
+
const [px, py] = stretch(x, y);
|
|
46216
|
+
this.stream.point(px, py);
|
|
46217
|
+
}
|
|
46218
|
+
});
|
|
46219
|
+
path = (0, import_d3_geo2.geoPath)({
|
|
46220
|
+
stream: (s) => baseProjection.stream(
|
|
46221
|
+
tx.stream(s)
|
|
46222
|
+
)
|
|
46223
|
+
});
|
|
46224
|
+
project = (lon, lat) => {
|
|
46225
|
+
const p = baseProjection([lon, lat]);
|
|
46226
|
+
return p ? stretch(p[0], p[1]) : null;
|
|
46227
|
+
};
|
|
46228
|
+
} else {
|
|
46229
|
+
path = (0, import_d3_geo2.geoPath)(projection);
|
|
46230
|
+
project = (lon, lat) => projection([lon, lat]) ?? null;
|
|
46231
|
+
}
|
|
46232
|
+
const insets = [];
|
|
46233
|
+
const insetRegions = [];
|
|
46234
|
+
const insetLabelSeeds = [];
|
|
46235
|
+
if (resolved.projection === "albers-usa" && usLayer) {
|
|
46236
|
+
const PAD = 8;
|
|
46237
|
+
const GAP = 12;
|
|
46238
|
+
const yB = height - FIT_PAD;
|
|
46239
|
+
const BW = 8;
|
|
46240
|
+
const coast = /* @__PURE__ */ new Map();
|
|
46241
|
+
const addPt = (lon, lat) => {
|
|
46242
|
+
const p = projection([lon, lat]);
|
|
46243
|
+
if (!p) return;
|
|
46244
|
+
const bi = Math.floor(p[0] / BW);
|
|
46245
|
+
const cur = coast.get(bi);
|
|
46246
|
+
if (cur === void 0 || p[1] > cur) coast.set(bi, p[1]);
|
|
46247
|
+
};
|
|
46248
|
+
const walk = (co) => {
|
|
46249
|
+
if (Array.isArray(co) && typeof co[0] === "number")
|
|
46250
|
+
addPt(co[0], co[1]);
|
|
46251
|
+
else if (Array.isArray(co)) for (const c of co) walk(c);
|
|
46252
|
+
};
|
|
46253
|
+
for (const [iso, f] of usLayer) {
|
|
46254
|
+
if (US_NON_CONUS.has(iso)) continue;
|
|
46255
|
+
walk(f.geometry.coordinates);
|
|
46256
|
+
}
|
|
46257
|
+
const at = (x) => {
|
|
46258
|
+
const bi = Math.floor(x / BW);
|
|
46259
|
+
let y = -Infinity;
|
|
46260
|
+
for (let k = bi - 1; k <= bi + 1; k++) {
|
|
46261
|
+
const v = coast.get(k);
|
|
46262
|
+
if (v !== void 0 && v > y) y = v;
|
|
46263
|
+
}
|
|
46264
|
+
return y;
|
|
46265
|
+
};
|
|
46266
|
+
const coastTop = (x0, xr) => {
|
|
46267
|
+
const n = 24;
|
|
46268
|
+
const pts = [];
|
|
46269
|
+
let maxY = -Infinity;
|
|
46270
|
+
for (let i = 0; i <= n; i++) {
|
|
46271
|
+
const x = x0 + (xr - x0) * i / n;
|
|
46272
|
+
const y = at(x);
|
|
46273
|
+
if (y > -Infinity) {
|
|
46274
|
+
pts.push([x, y]);
|
|
46275
|
+
if (y > maxY) maxY = y;
|
|
46276
|
+
}
|
|
46277
|
+
}
|
|
46278
|
+
if (pts.length === 0) return () => yB - height * 0.42;
|
|
46279
|
+
let m = 0;
|
|
46280
|
+
if (pts.length >= 2) {
|
|
46281
|
+
let sx = 0, sy = 0, sxx = 0, sxy = 0;
|
|
46282
|
+
for (const [x, y] of pts) {
|
|
46283
|
+
sx += x;
|
|
46284
|
+
sy += y;
|
|
46285
|
+
sxx += x * x;
|
|
46286
|
+
sxy += x * y;
|
|
46287
|
+
}
|
|
46288
|
+
const den = pts.length * sxx - sx * sx;
|
|
46289
|
+
if (den !== 0) m = (pts.length * sxy - sx * sy) / den;
|
|
46290
|
+
}
|
|
46291
|
+
m = Math.max(-0.35, Math.min(0.35, m));
|
|
46292
|
+
let c = -Infinity;
|
|
46293
|
+
for (const [x, y] of pts) {
|
|
46294
|
+
const need = y - m * x + GAP;
|
|
46295
|
+
if (need > c) c = need;
|
|
46296
|
+
}
|
|
46297
|
+
return (x) => m * x + c;
|
|
46298
|
+
};
|
|
46299
|
+
const placeInset = (iso, proj, boxX, iwReq) => {
|
|
46300
|
+
const f = usLayer.get(iso);
|
|
46301
|
+
if (!f) return boxX;
|
|
46302
|
+
const x0 = boxX;
|
|
46303
|
+
const iw = Math.min(iwReq, width - FIT_PAD - x0 - 2 * PAD);
|
|
46304
|
+
if (iw < 24) return boxX;
|
|
46305
|
+
const xr = x0 + iw + 2 * PAD;
|
|
46306
|
+
const top = coastTop(x0, xr);
|
|
46307
|
+
const yL = top(x0);
|
|
46308
|
+
const yR = top(xr);
|
|
46309
|
+
proj.fitWidth(iw, f);
|
|
46310
|
+
const bb = (0, import_d3_geo2.geoPath)(proj).bounds(f);
|
|
46311
|
+
const sh = Number.isFinite(bb[0][0]) ? bb[1][1] - bb[0][1] : iw;
|
|
46312
|
+
const needH = sh + 2 * PAD;
|
|
46313
|
+
let topFit = Math.max(yL, yR);
|
|
46314
|
+
const bottom = Math.min(topFit + needH, yB);
|
|
46315
|
+
if (bottom - topFit < needH) topFit = bottom - needH;
|
|
46316
|
+
const lift = topFit - Math.max(yL, yR);
|
|
46317
|
+
const topL = yL + lift;
|
|
46318
|
+
const topR = yR + lift;
|
|
46319
|
+
proj.fitExtent(
|
|
46320
|
+
[
|
|
46321
|
+
[x0 + PAD, topFit + PAD],
|
|
46322
|
+
[xr - PAD, bottom - PAD]
|
|
46323
|
+
],
|
|
46324
|
+
f
|
|
46325
|
+
);
|
|
46326
|
+
const d = (0, import_d3_geo2.geoPath)(proj)(f) ?? "";
|
|
46327
|
+
if (!d) return xr;
|
|
46328
|
+
const r = regionById.get(iso);
|
|
46329
|
+
let fill2 = neutralFill;
|
|
46330
|
+
let lineNumber = -1;
|
|
46331
|
+
if (r?.layer === "us-state") {
|
|
46332
|
+
fill2 = regionFill(r);
|
|
46333
|
+
lineNumber = r.lineNumber;
|
|
46334
|
+
}
|
|
46335
|
+
insets.push({
|
|
46336
|
+
x: x0,
|
|
46337
|
+
y: Math.min(topL, topR),
|
|
46338
|
+
w: xr - x0,
|
|
46339
|
+
h: bottom - Math.min(topL, topR),
|
|
46340
|
+
points: [
|
|
46341
|
+
[x0, topL],
|
|
46342
|
+
[xr, topR],
|
|
46343
|
+
[xr, bottom],
|
|
46344
|
+
[x0, bottom]
|
|
46345
|
+
]
|
|
46346
|
+
});
|
|
46347
|
+
insetRegions.push({
|
|
46348
|
+
id: iso,
|
|
46349
|
+
d,
|
|
46350
|
+
fill: fill2,
|
|
46351
|
+
stroke: regionStroke,
|
|
46352
|
+
lineNumber,
|
|
46353
|
+
layer: "us-state",
|
|
46354
|
+
...r?.score !== void 0 && { score: r.score },
|
|
46355
|
+
...r && Object.keys(r.tags).length > 0 && { tags: r.tags }
|
|
46356
|
+
});
|
|
46357
|
+
const ctr = (0, import_d3_geo2.geoPath)(proj).centroid(f);
|
|
46358
|
+
if (Number.isFinite(ctr[0])) {
|
|
46359
|
+
const name = f.properties?.name ?? iso;
|
|
46360
|
+
insetLabelSeeds.push({ x: ctr[0], y: ctr[1], iso, name, lineNumber });
|
|
46361
|
+
}
|
|
46362
|
+
return xr;
|
|
46363
|
+
};
|
|
46364
|
+
const akRight = placeInset(
|
|
46365
|
+
"US-AK",
|
|
46366
|
+
alaskaProjection(),
|
|
46367
|
+
FIT_PAD,
|
|
46368
|
+
width * 0.15
|
|
46369
|
+
);
|
|
46370
|
+
placeInset("US-HI", hawaiiProjection(), akRight + 24, width * 0.1);
|
|
46371
|
+
}
|
|
46372
|
+
const conusFit = resolved.projection === "albers-usa" && !!usLayer;
|
|
46373
|
+
const cullExtent = conusFit ? (0, import_d3_geo2.geoBounds)(fitTarget) : resolved.extent;
|
|
46374
|
+
const [[exW, exS], [exE, exN]] = cullExtent;
|
|
46375
|
+
const lonSpan = exE - exW;
|
|
46376
|
+
const latSpan = exN - exS;
|
|
46377
|
+
const isGlobalView = lonSpan >= 270 || latSpan >= 130;
|
|
46378
|
+
const padLon = Math.max(8, lonSpan * 0.35);
|
|
46379
|
+
const padLat = Math.max(8, latSpan * 0.35);
|
|
46380
|
+
const vW = exW - padLon;
|
|
46381
|
+
const vE = exE + padLon;
|
|
46382
|
+
const vS = exS - padLat;
|
|
46383
|
+
const vN = exN + padLat;
|
|
46384
|
+
const vLonCenter = (exW + exE) / 2;
|
|
46385
|
+
const normLon = (lon) => {
|
|
46386
|
+
let L = lon;
|
|
46387
|
+
while (L < vLonCenter - 180) L += 360;
|
|
46388
|
+
while (L > vLonCenter + 180) L -= 360;
|
|
46389
|
+
return L;
|
|
46390
|
+
};
|
|
46391
|
+
const ringOverlapsView = (ring) => {
|
|
46392
|
+
let anyIn = false;
|
|
46393
|
+
let loMin = Infinity, loMax = -Infinity, laMin = Infinity, laMax = -Infinity, rawMin = Infinity, rawMax = -Infinity;
|
|
46394
|
+
for (const [rawLon, lat] of ring) {
|
|
46395
|
+
const lon = normLon(rawLon);
|
|
46396
|
+
if (lon >= vW && lon <= vE && lat >= vS && lat <= vN) anyIn = true;
|
|
46397
|
+
if (lon < loMin) loMin = lon;
|
|
46398
|
+
if (lon > loMax) loMax = lon;
|
|
46399
|
+
if (rawLon < rawMin) rawMin = rawLon;
|
|
46400
|
+
if (rawLon > rawMax) rawMax = rawLon;
|
|
46401
|
+
if (lat < laMin) laMin = lat;
|
|
46402
|
+
if (lat > laMax) laMax = lat;
|
|
46403
|
+
}
|
|
46404
|
+
if (loMax - loMin > 270) return false;
|
|
46405
|
+
if (rawMax - rawMin > 180 && loMax - loMin < 90) return false;
|
|
46406
|
+
if (anyIn) return true;
|
|
46407
|
+
if (loMax - loMin > 180) return false;
|
|
46408
|
+
return !(loMax < vW || loMin > vE || laMax < vS || laMin > vN);
|
|
46409
|
+
};
|
|
46410
|
+
const cullFeatureToView = (f) => {
|
|
46411
|
+
if (isGlobalView) return f;
|
|
46412
|
+
const g = f.geometry;
|
|
46413
|
+
if (!g) return f;
|
|
46414
|
+
if (g.type === "Polygon") {
|
|
46415
|
+
const ring = g.coordinates[0];
|
|
46416
|
+
return ringOverlapsView(ring) ? f : null;
|
|
46417
|
+
}
|
|
46418
|
+
if (g.type === "MultiPolygon") {
|
|
46419
|
+
const polys = g.coordinates;
|
|
46420
|
+
const keep = polys.filter(
|
|
46421
|
+
(p) => ringOverlapsView(p[0])
|
|
46422
|
+
);
|
|
46423
|
+
if (!keep.length) return null;
|
|
46424
|
+
if (keep.length === polys.length) return f;
|
|
46425
|
+
return { ...f, geometry: { ...g, coordinates: keep } };
|
|
46426
|
+
}
|
|
46427
|
+
return f;
|
|
46428
|
+
};
|
|
46429
|
+
const SEAM_SLIVER_MAX_SPAN = 100;
|
|
46430
|
+
const ringIsFrameFiller = (ring) => {
|
|
46431
|
+
const lons = ring.map(([lon]) => lon).sort((a, b) => a - b);
|
|
46432
|
+
if (lons.length < 2) return false;
|
|
46433
|
+
let maxGap = -1;
|
|
46434
|
+
let gapIdx = 0;
|
|
46435
|
+
for (let i = 1; i < lons.length; i++) {
|
|
46436
|
+
const g = lons[i] - lons[i - 1];
|
|
46437
|
+
if (g > maxGap) {
|
|
46438
|
+
maxGap = g;
|
|
46439
|
+
gapIdx = i;
|
|
46440
|
+
}
|
|
46441
|
+
}
|
|
46442
|
+
const wrapGap = lons[0] + 360 - lons[lons.length - 1];
|
|
46443
|
+
if (wrapGap >= maxGap) return false;
|
|
46444
|
+
const span = 360 - maxGap;
|
|
46445
|
+
const east = lons[gapIdx - 1] + 360;
|
|
46446
|
+
return east > 180 && span < SEAM_SLIVER_MAX_SPAN;
|
|
46447
|
+
};
|
|
46448
|
+
const dropFrameFillers = (f) => {
|
|
46449
|
+
const g = f.geometry;
|
|
46450
|
+
if (!g) return f;
|
|
46451
|
+
if (g.type === "Polygon") {
|
|
46452
|
+
const ring = g.coordinates[0];
|
|
46453
|
+
return ringIsFrameFiller(ring) ? null : f;
|
|
46454
|
+
}
|
|
46455
|
+
if (g.type === "MultiPolygon") {
|
|
46456
|
+
const polys = g.coordinates;
|
|
46457
|
+
const keep = polys.filter(
|
|
46458
|
+
(p) => !ringIsFrameFiller(p[0])
|
|
46459
|
+
);
|
|
46460
|
+
if (!keep.length) return null;
|
|
46461
|
+
if (keep.length === polys.length) return f;
|
|
46462
|
+
return { ...f, geometry: { ...g, coordinates: keep } };
|
|
46463
|
+
}
|
|
46464
|
+
return f;
|
|
46465
|
+
};
|
|
45991
46466
|
const regions = [];
|
|
45992
|
-
const pushRegionLayer = (layerFeatures, layerKind) => {
|
|
46467
|
+
const pushRegionLayer = (layerFeatures, layerKind, shouldCull) => {
|
|
45993
46468
|
for (const [iso, f] of layerFeatures) {
|
|
45994
|
-
|
|
45995
|
-
|
|
46469
|
+
if (layerKind === "us-state" && usContext && INSET_STATES.has(iso))
|
|
46470
|
+
continue;
|
|
46471
|
+
if (layerKind === "country" && usContext && iso === "US") continue;
|
|
45996
46472
|
const r = regionById.get(iso);
|
|
46473
|
+
const viewF = shouldCull ? cullFeatureToView(f) : dropFrameFillers(f);
|
|
46474
|
+
if (!viewF) continue;
|
|
46475
|
+
const d = path(viewF) ?? "";
|
|
46476
|
+
if (!d) continue;
|
|
45997
46477
|
const isThisLayer = r?.layer === layerKind;
|
|
45998
|
-
|
|
46478
|
+
const isForeign = layerKind === "country" && usContext && iso !== "US";
|
|
46479
|
+
let fill2 = isForeign ? foreignFill : neutralFill;
|
|
45999
46480
|
let label;
|
|
46000
46481
|
let lineNumber = -1;
|
|
46001
46482
|
let layer = "base";
|
|
46002
46483
|
if (isThisLayer) {
|
|
46003
|
-
|
|
46004
|
-
else fill2 = tagFill(r.tags, activeGroup) ?? neutralFill;
|
|
46484
|
+
fill2 = regionFill(r);
|
|
46005
46485
|
lineNumber = r.lineNumber;
|
|
46006
46486
|
layer = layerKind;
|
|
46007
46487
|
label = r.name;
|
|
@@ -46013,12 +46493,42 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46013
46493
|
stroke: regionStroke,
|
|
46014
46494
|
lineNumber,
|
|
46015
46495
|
layer,
|
|
46016
|
-
...label !== void 0 && { label }
|
|
46496
|
+
...label !== void 0 && { label },
|
|
46497
|
+
...isThisLayer && r.score !== void 0 && { score: r.score },
|
|
46498
|
+
...isThisLayer && Object.keys(r.tags).length > 0 && { tags: r.tags }
|
|
46017
46499
|
});
|
|
46018
46500
|
}
|
|
46019
46501
|
};
|
|
46020
|
-
pushRegionLayer(worldLayer, "country");
|
|
46021
|
-
if (usLayer) pushRegionLayer(usLayer, "us-state");
|
|
46502
|
+
pushRegionLayer(worldLayer, "country", !isGlobalView);
|
|
46503
|
+
if (usLayer) pushRegionLayer(usLayer, "us-state", !conusFit && !isGlobalView);
|
|
46504
|
+
const lakesTopo = usCrisp && data.naLakes ? data.naLakes : data.lakes;
|
|
46505
|
+
if (lakesTopo) {
|
|
46506
|
+
for (const [, f] of decodeLayer(lakesTopo)) {
|
|
46507
|
+
const viewF = isGlobalView ? dropFrameFillers(f) : cullFeatureToView(f);
|
|
46508
|
+
if (!viewF) continue;
|
|
46509
|
+
const d = path(viewF) ?? "";
|
|
46510
|
+
if (!d) continue;
|
|
46511
|
+
regions.push({
|
|
46512
|
+
id: "lake",
|
|
46513
|
+
d,
|
|
46514
|
+
fill: water,
|
|
46515
|
+
stroke: "none",
|
|
46516
|
+
lineNumber: -1,
|
|
46517
|
+
layer: "base"
|
|
46518
|
+
});
|
|
46519
|
+
}
|
|
46520
|
+
}
|
|
46521
|
+
const riverColor = water;
|
|
46522
|
+
const rivers = [];
|
|
46523
|
+
if (data.rivers) {
|
|
46524
|
+
for (const [, f] of decodeLayer(data.rivers)) {
|
|
46525
|
+
const viewF = isGlobalView ? dropFrameFillers(f) : cullFeatureToView(f);
|
|
46526
|
+
if (!viewF) continue;
|
|
46527
|
+
const d = path(viewF) ?? "";
|
|
46528
|
+
if (!d) continue;
|
|
46529
|
+
rivers.push({ d, color: riverColor, width: RIVER_WIDTH });
|
|
46530
|
+
}
|
|
46531
|
+
}
|
|
46022
46532
|
const sizeVals = resolved.pois.map((p) => Number(p.meta["size"])).filter((n) => Number.isFinite(n) && n > 0);
|
|
46023
46533
|
const sizeMin = sizeVals.length ? Math.min(...sizeVals) : 0;
|
|
46024
46534
|
const sizeMax = sizeVals.length ? Math.max(...sizeVals) : 0;
|
|
@@ -46039,8 +46549,8 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46039
46549
|
if (hex) return { fill: hex, stroke: mix(hex, palette.text, 18) };
|
|
46040
46550
|
}
|
|
46041
46551
|
return {
|
|
46042
|
-
fill: palette.
|
|
46043
|
-
stroke: mix(palette.
|
|
46552
|
+
fill: palette.colors.orange,
|
|
46553
|
+
stroke: mix(palette.colors.orange, palette.text, 18)
|
|
46044
46554
|
};
|
|
46045
46555
|
};
|
|
46046
46556
|
const routeNumberById = /* @__PURE__ */ new Map();
|
|
@@ -46078,7 +46588,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46078
46588
|
cy += Math.sin(ang) * COLO_R;
|
|
46079
46589
|
}
|
|
46080
46590
|
const { fill: fill2, stroke: stroke2 } = poiFill(e.p);
|
|
46081
|
-
poiScreen.set(e.p.id, { cx, cy });
|
|
46591
|
+
poiScreen.set(e.p.id, { cx, cy, r: radiusFor(e.p) });
|
|
46082
46592
|
const num = routeNumberById.get(e.p.id);
|
|
46083
46593
|
pois.push({
|
|
46084
46594
|
id: e.p.id,
|
|
@@ -46095,17 +46605,36 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46095
46605
|
});
|
|
46096
46606
|
}
|
|
46097
46607
|
const legs = [];
|
|
46608
|
+
const RIM_GAP = 1.5;
|
|
46098
46609
|
const legPath = (a, b, curved, offset) => {
|
|
46099
|
-
if (!curved && offset === 0) return `M${a.cx},${a.cy}L${b.cx},${b.cy}`;
|
|
46100
46610
|
const mx = (a.cx + b.cx) / 2;
|
|
46101
46611
|
const my = (a.cy + b.cy) / 2;
|
|
46102
46612
|
const dx = b.cx - a.cx;
|
|
46103
46613
|
const dy = b.cy - a.cy;
|
|
46104
46614
|
const len = Math.hypot(dx, dy) || 1;
|
|
46615
|
+
const trimA = Math.min(a.r + RIM_GAP, len * 0.45);
|
|
46616
|
+
const trimB = Math.min(b.r + RIM_GAP, len * 0.45);
|
|
46617
|
+
if (!curved && offset === 0) {
|
|
46618
|
+
const ux = dx / len;
|
|
46619
|
+
const uy = dy / len;
|
|
46620
|
+
const ax2 = a.cx + ux * trimA;
|
|
46621
|
+
const ay2 = a.cy + uy * trimA;
|
|
46622
|
+
const bx2 = b.cx - ux * trimB;
|
|
46623
|
+
const by2 = b.cy - uy * trimB;
|
|
46624
|
+
return `M${ax2},${ay2}L${bx2},${by2}`;
|
|
46625
|
+
}
|
|
46105
46626
|
const nx = -dy / len;
|
|
46106
46627
|
const ny = dx / len;
|
|
46107
46628
|
const bow = offset !== 0 ? offset : len * ARC_CURVE_FRAC;
|
|
46108
|
-
|
|
46629
|
+
const px = mx + nx * bow;
|
|
46630
|
+
const py = my + ny * bow;
|
|
46631
|
+
const ta = Math.hypot(px - a.cx, py - a.cy) || 1;
|
|
46632
|
+
const tb = Math.hypot(b.cx - px, b.cy - py) || 1;
|
|
46633
|
+
const ax = a.cx + (px - a.cx) / ta * trimA;
|
|
46634
|
+
const ay = a.cy + (py - a.cy) / ta * trimA;
|
|
46635
|
+
const bx = b.cx - (b.cx - px) / tb * trimB;
|
|
46636
|
+
const by = b.cy - (b.cy - py) / tb * trimB;
|
|
46637
|
+
return `M${ax},${ay}Q${px},${py} ${bx},${by}`;
|
|
46109
46638
|
};
|
|
46110
46639
|
for (const rt of resolved.routes) {
|
|
46111
46640
|
const curved = rt.meta["style"] === "arc";
|
|
@@ -46116,7 +46645,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46116
46645
|
legs.push({
|
|
46117
46646
|
d: legPath(a, b, curved, 0),
|
|
46118
46647
|
width: W_MIN,
|
|
46119
|
-
color: mix(palette.text, palette.bg,
|
|
46648
|
+
color: mix(palette.text, palette.bg, 72),
|
|
46120
46649
|
arrow: true,
|
|
46121
46650
|
lineNumber: rt.lineNumber
|
|
46122
46651
|
});
|
|
@@ -46152,7 +46681,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46152
46681
|
legs.push({
|
|
46153
46682
|
d: legPath(a, b, curved, offset),
|
|
46154
46683
|
width: widthFor(e),
|
|
46155
|
-
color: mix(palette.text, palette.bg,
|
|
46684
|
+
color: mix(palette.text, palette.bg, 66),
|
|
46156
46685
|
arrow: e.directed,
|
|
46157
46686
|
lineNumber: e.lineNumber,
|
|
46158
46687
|
...e.label !== void 0 && {
|
|
@@ -46164,38 +46693,92 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46164
46693
|
});
|
|
46165
46694
|
}
|
|
46166
46695
|
const labels = [];
|
|
46167
|
-
const pinList = [];
|
|
46168
46696
|
const obstacles = [];
|
|
46169
46697
|
const markers = pois.map((p) => ({
|
|
46170
46698
|
cx: p.cx,
|
|
46171
46699
|
cy: p.cy,
|
|
46172
46700
|
r: p.r
|
|
46173
46701
|
}));
|
|
46174
|
-
const
|
|
46702
|
+
const legSegments = [];
|
|
46703
|
+
for (const leg of legs) {
|
|
46704
|
+
const m = /^M(-?[\d.]+),(-?[\d.]+)(?:L(-?[\d.]+),(-?[\d.]+)|Q(-?[\d.]+),(-?[\d.]+) (-?[\d.]+),(-?[\d.]+))$/.exec(
|
|
46705
|
+
leg.d
|
|
46706
|
+
);
|
|
46707
|
+
if (!m) continue;
|
|
46708
|
+
const x0 = +m[1];
|
|
46709
|
+
const y0 = +m[2];
|
|
46710
|
+
if (m[3] !== void 0) {
|
|
46711
|
+
legSegments.push([x0, y0, +m[3], +m[4]]);
|
|
46712
|
+
} else {
|
|
46713
|
+
const cx = +m[5];
|
|
46714
|
+
const cy = +m[6];
|
|
46715
|
+
const ex = +m[7];
|
|
46716
|
+
const ey = +m[8];
|
|
46717
|
+
const N = 8;
|
|
46718
|
+
let px = x0;
|
|
46719
|
+
let py = y0;
|
|
46720
|
+
for (let i = 1; i <= N; i++) {
|
|
46721
|
+
const t = i / N;
|
|
46722
|
+
const u = 1 - t;
|
|
46723
|
+
const qx = u * u * x0 + 2 * u * t * cx + t * t * ex;
|
|
46724
|
+
const qy = u * u * y0 + 2 * u * t * cy + t * t * ey;
|
|
46725
|
+
legSegments.push([px, py, qx, qy]);
|
|
46726
|
+
px = qx;
|
|
46727
|
+
py = qy;
|
|
46728
|
+
}
|
|
46729
|
+
}
|
|
46730
|
+
}
|
|
46731
|
+
const collides = (rect) => markers.some((m) => rectCircleOverlap(rect, m)) || obstacles.some((o) => rectsOverlap(rect, o)) || legSegments.some((s) => segmentRectOverlap(s[0], s[1], s[2], s[3], rect));
|
|
46175
46732
|
const regionLabelMode = resolved.directives.regionLabels ?? "off";
|
|
46733
|
+
const LABEL_PADX = 6;
|
|
46734
|
+
const LABEL_PADY = 3;
|
|
46735
|
+
const labelW = (text) => measureLegendText(text, FONT) + 2 * LABEL_PADX;
|
|
46736
|
+
const labelH = FONT + 2 * LABEL_PADY;
|
|
46737
|
+
const pushRegionLabel = (x, y, text, fill2, lineNumber) => {
|
|
46738
|
+
const color = contrastText(
|
|
46739
|
+
fill2,
|
|
46740
|
+
palette.textOnFillLight,
|
|
46741
|
+
palette.textOnFillDark
|
|
46742
|
+
);
|
|
46743
|
+
const haloColor = color === palette.textOnFillLight ? palette.textOnFillDark : palette.textOnFillLight;
|
|
46744
|
+
labels.push({
|
|
46745
|
+
x,
|
|
46746
|
+
y,
|
|
46747
|
+
text,
|
|
46748
|
+
anchor: "middle",
|
|
46749
|
+
color,
|
|
46750
|
+
halo: true,
|
|
46751
|
+
haloColor,
|
|
46752
|
+
lineNumber
|
|
46753
|
+
});
|
|
46754
|
+
};
|
|
46755
|
+
const WORLD_LABEL_ANCHORS = {
|
|
46756
|
+
US: [-98.5, 39.5]
|
|
46757
|
+
// CONUS geographic centre (near Lebanon, Kansas)
|
|
46758
|
+
};
|
|
46176
46759
|
if (regionLabelMode === "full" || regionLabelMode === "abbrev") {
|
|
46177
46760
|
for (const r of regions) {
|
|
46178
46761
|
if (r.layer === "base" || r.label === void 0) continue;
|
|
46179
46762
|
const f = r.layer === "us-state" ? usLayer?.get(r.id) : worldLayer.get(r.id);
|
|
46180
46763
|
if (!f) continue;
|
|
46181
46764
|
const [[x0, y0], [x1, y1]] = path.bounds(f);
|
|
46182
|
-
if ((x1 - x0) * (y1 - y0) < TINY_REGION_AREA) continue;
|
|
46183
|
-
const c = path.centroid(f);
|
|
46184
|
-
if (!Number.isFinite(c[0])) continue;
|
|
46185
46765
|
const text = regionLabelMode === "abbrev" ? r.id.replace(/^US-/, "") : r.label;
|
|
46186
|
-
|
|
46187
|
-
|
|
46188
|
-
|
|
46766
|
+
if (labelW(text) > x1 - x0 || labelH > y1 - y0) continue;
|
|
46767
|
+
const anchor = r.layer !== "us-state" ? WORLD_LABEL_ANCHORS[r.id] : void 0;
|
|
46768
|
+
const c = anchor ? project(anchor[0], anchor[1]) : path.centroid(f);
|
|
46769
|
+
if (!c || !Number.isFinite(c[0])) continue;
|
|
46770
|
+
pushRegionLabel(c[0], c[1], text, r.fill, r.lineNumber);
|
|
46771
|
+
}
|
|
46772
|
+
for (const seed of insetLabelSeeds) {
|
|
46773
|
+
const text = regionLabelMode === "abbrev" ? seed.iso.replace(/^US-/, "") : seed.name;
|
|
46774
|
+
const src = regionById.get(seed.iso);
|
|
46775
|
+
pushRegionLabel(
|
|
46776
|
+
seed.x,
|
|
46777
|
+
seed.y,
|
|
46189
46778
|
text,
|
|
46190
|
-
|
|
46191
|
-
|
|
46192
|
-
|
|
46193
|
-
palette.textOnFillLight,
|
|
46194
|
-
palette.textOnFillDark
|
|
46195
|
-
),
|
|
46196
|
-
halo: true,
|
|
46197
|
-
lineNumber: r.lineNumber
|
|
46198
|
-
});
|
|
46779
|
+
src ? regionFill(src) : neutralFill,
|
|
46780
|
+
seed.lineNumber
|
|
46781
|
+
);
|
|
46199
46782
|
}
|
|
46200
46783
|
}
|
|
46201
46784
|
const poiLabelMode = resolved.directives.poiLabels ?? "auto";
|
|
@@ -46208,68 +46791,106 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46208
46791
|
const src = poiById.get(p.id);
|
|
46209
46792
|
return src?.label ?? src?.name ?? p.id;
|
|
46210
46793
|
};
|
|
46211
|
-
|
|
46212
|
-
|
|
46794
|
+
const poiLabH = FONT * 1.25;
|
|
46795
|
+
const labelInfo = (p) => {
|
|
46213
46796
|
const text = labelText(p);
|
|
46214
|
-
|
|
46215
|
-
|
|
46216
|
-
|
|
46217
|
-
|
|
46218
|
-
|
|
46797
|
+
return { text, w: measureLegendText(text, FONT) };
|
|
46798
|
+
};
|
|
46799
|
+
const pushInline = (p, text, w, side) => {
|
|
46800
|
+
const tx = side === "right" ? p.cx + p.r + 3 : p.cx - p.r - 3;
|
|
46801
|
+
obstacles.push({
|
|
46802
|
+
x: side === "right" ? tx : tx - w,
|
|
46803
|
+
y: p.cy - poiLabH / 2,
|
|
46804
|
+
w,
|
|
46805
|
+
h: poiLabH
|
|
46806
|
+
});
|
|
46807
|
+
labels.push({
|
|
46808
|
+
x: tx,
|
|
46809
|
+
y: p.cy + FONT / 3,
|
|
46810
|
+
text,
|
|
46811
|
+
anchor: side === "right" ? "start" : "end",
|
|
46812
|
+
color: palette.text,
|
|
46813
|
+
halo: true,
|
|
46814
|
+
haloColor: palette.bg,
|
|
46815
|
+
poiId: p.id,
|
|
46816
|
+
lineNumber: p.lineNumber
|
|
46817
|
+
});
|
|
46818
|
+
};
|
|
46819
|
+
const inlineFits = (p, w, side) => {
|
|
46820
|
+
const tx = side === "right" ? p.cx + p.r + 3 : p.cx - p.r - 3;
|
|
46821
|
+
const rect = {
|
|
46822
|
+
x: side === "right" ? tx : tx - w,
|
|
46823
|
+
y: p.cy - poiLabH / 2,
|
|
46824
|
+
w,
|
|
46825
|
+
h: poiLabH
|
|
46826
|
+
};
|
|
46827
|
+
return rect.x >= 0 && rect.x + rect.w <= width && !collides(rect);
|
|
46828
|
+
};
|
|
46829
|
+
const GROUP_R = 30;
|
|
46830
|
+
const groups = [];
|
|
46831
|
+
for (const p of ordered) {
|
|
46832
|
+
const near = groups.find(
|
|
46833
|
+
(g) => g.some((q) => Math.hypot(q.cx - p.cx, q.cy - p.cy) < GROUP_R)
|
|
46834
|
+
);
|
|
46835
|
+
if (near) near.push(p);
|
|
46836
|
+
else groups.push([p]);
|
|
46837
|
+
}
|
|
46838
|
+
const ROW_GAP2 = 3;
|
|
46839
|
+
const step = poiLabH + ROW_GAP2;
|
|
46840
|
+
const COL_GAP = 16;
|
|
46841
|
+
const placeColumn = (group) => {
|
|
46842
|
+
const items = group.map((p) => ({ p, ...labelInfo(p) })).sort((a, b) => a.p.cy - b.p.cy || (a.text < b.text ? -1 : 1));
|
|
46843
|
+
const left = Math.min(...items.map((o) => o.p.cx - o.p.r));
|
|
46844
|
+
const right = Math.max(...items.map((o) => o.p.cx + o.p.r));
|
|
46845
|
+
const cyMid = (Math.min(...items.map((o) => o.p.cy)) + Math.max(...items.map((o) => o.p.cy))) / 2;
|
|
46846
|
+
const maxW = Math.max(...items.map((o) => o.w));
|
|
46847
|
+
const side = right + COL_GAP + maxW <= width - 2 ? "right" : "left";
|
|
46848
|
+
const colX = side === "right" ? right + COL_GAP : left - COL_GAP;
|
|
46849
|
+
const totalH = items.length * step;
|
|
46850
|
+
let startY = cyMid - totalH / 2;
|
|
46851
|
+
startY = Math.max(2, Math.min(startY, height - totalH - 2));
|
|
46852
|
+
items.forEach((o, i) => {
|
|
46853
|
+
const rowCy = startY + i * step + step / 2;
|
|
46854
|
+
obstacles.push({
|
|
46855
|
+
x: side === "right" ? colX : colX - o.w,
|
|
46856
|
+
y: rowCy - poiLabH / 2,
|
|
46857
|
+
w: o.w,
|
|
46858
|
+
h: poiLabH
|
|
46859
|
+
});
|
|
46219
46860
|
labels.push({
|
|
46220
|
-
x:
|
|
46221
|
-
y:
|
|
46222
|
-
text,
|
|
46223
|
-
anchor: "start",
|
|
46861
|
+
x: colX,
|
|
46862
|
+
y: rowCy + FONT / 3,
|
|
46863
|
+
text: o.text,
|
|
46864
|
+
anchor: side === "right" ? "start" : "end",
|
|
46224
46865
|
color: palette.text,
|
|
46225
46866
|
halo: true,
|
|
46226
|
-
|
|
46867
|
+
haloColor: palette.bg,
|
|
46868
|
+
leader: {
|
|
46869
|
+
x1: o.p.cx,
|
|
46870
|
+
y1: o.p.cy,
|
|
46871
|
+
x2: side === "right" ? colX - 2 : colX + 2,
|
|
46872
|
+
y2: rowCy
|
|
46873
|
+
},
|
|
46874
|
+
leaderColor: o.p.fill,
|
|
46875
|
+
poiId: o.p.id,
|
|
46876
|
+
lineNumber: o.p.lineNumber
|
|
46227
46877
|
});
|
|
46228
|
-
|
|
46229
|
-
|
|
46230
|
-
|
|
46231
|
-
|
|
46232
|
-
|
|
46233
|
-
|
|
46234
|
-
|
|
46235
|
-
|
|
46236
|
-
|
|
46237
|
-
|
|
46238
|
-
|
|
46239
|
-
|
|
46240
|
-
|
|
46241
|
-
if (rect.x < 0 || rect.x + rect.w > width || rect.y < 0 || rect.y + rect.h > height) {
|
|
46242
|
-
continue;
|
|
46243
|
-
}
|
|
46244
|
-
if (collides(rect)) continue;
|
|
46245
|
-
obstacles.push(rect);
|
|
46246
|
-
labels.push({
|
|
46247
|
-
x: cx,
|
|
46248
|
-
y: cy + FONT / 3,
|
|
46249
|
-
text,
|
|
46250
|
-
anchor: dx >= 0 ? "start" : "end",
|
|
46251
|
-
color: palette.text,
|
|
46252
|
-
halo: true,
|
|
46253
|
-
leader: { x1: p.cx, y1: p.cy, x2: cx, y2: cy },
|
|
46254
|
-
lineNumber: p.lineNumber
|
|
46255
|
-
});
|
|
46256
|
-
placed = true;
|
|
46257
|
-
break;
|
|
46878
|
+
});
|
|
46879
|
+
};
|
|
46880
|
+
for (const g of groups) {
|
|
46881
|
+
if (g.length === 1) {
|
|
46882
|
+
const p = g[0];
|
|
46883
|
+
const { text, w } = labelInfo(p);
|
|
46884
|
+
if (inlineFits(p, w, "right")) {
|
|
46885
|
+
pushInline(p, text, w, "right");
|
|
46886
|
+
continue;
|
|
46887
|
+
}
|
|
46888
|
+
if (inlineFits(p, w, "left")) {
|
|
46889
|
+
pushInline(p, text, w, "left");
|
|
46890
|
+
continue;
|
|
46258
46891
|
}
|
|
46259
46892
|
}
|
|
46260
|
-
|
|
46261
|
-
pinCounter += 1;
|
|
46262
|
-
pinList.push({ pin: pinCounter, label: text });
|
|
46263
|
-
labels.push({
|
|
46264
|
-
x: p.cx + p.r + 2,
|
|
46265
|
-
y: p.cy - p.r,
|
|
46266
|
-
text: String(pinCounter),
|
|
46267
|
-
anchor: "start",
|
|
46268
|
-
color: palette.text,
|
|
46269
|
-
halo: true,
|
|
46270
|
-
pin: pinCounter,
|
|
46271
|
-
lineNumber: p.lineNumber
|
|
46272
|
-
});
|
|
46893
|
+
placeColumn(g);
|
|
46273
46894
|
}
|
|
46274
46895
|
}
|
|
46275
46896
|
let legend = null;
|
|
@@ -46278,8 +46899,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46278
46899
|
name: g.name,
|
|
46279
46900
|
entries: g.entries.map((e) => ({ value: e.value, color: e.color }))
|
|
46280
46901
|
}));
|
|
46281
|
-
|
|
46282
|
-
if (hasAnything) {
|
|
46902
|
+
if (tagGroups.length > 0 || hasRamp) {
|
|
46283
46903
|
legend = {
|
|
46284
46904
|
tagGroups,
|
|
46285
46905
|
activeGroup,
|
|
@@ -46290,20 +46910,9 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46290
46910
|
},
|
|
46291
46911
|
min: rampMin,
|
|
46292
46912
|
max: rampMax,
|
|
46293
|
-
hue: rampHue
|
|
46294
|
-
|
|
46295
|
-
},
|
|
46296
|
-
...sizeVals.length > 0 && {
|
|
46297
|
-
size: {
|
|
46298
|
-
...resolved.directives.sizeMetric !== void 0 && {
|
|
46299
|
-
metric: resolved.directives.sizeMetric
|
|
46300
|
-
},
|
|
46301
|
-
min: sizeMin,
|
|
46302
|
-
max: sizeMax
|
|
46913
|
+
hue: rampHue,
|
|
46914
|
+
base: rampBase
|
|
46303
46915
|
}
|
|
46304
|
-
},
|
|
46305
|
-
...weightVals.length > 0 && {
|
|
46306
|
-
weight: { min: wMin, max: wMax }
|
|
46307
46916
|
}
|
|
46308
46917
|
};
|
|
46309
46918
|
}
|
|
@@ -46311,28 +46920,30 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46311
46920
|
return {
|
|
46312
46921
|
width,
|
|
46313
46922
|
height,
|
|
46314
|
-
background:
|
|
46923
|
+
background: water,
|
|
46315
46924
|
title: resolved.title,
|
|
46316
46925
|
...resolved.subtitle !== void 0 && { subtitle: resolved.subtitle },
|
|
46317
46926
|
...resolved.caption !== void 0 && { caption: resolved.caption },
|
|
46318
46927
|
regions,
|
|
46928
|
+
rivers,
|
|
46319
46929
|
legs,
|
|
46320
46930
|
pois,
|
|
46321
46931
|
labels,
|
|
46322
|
-
|
|
46323
|
-
|
|
46932
|
+
legend,
|
|
46933
|
+
insets,
|
|
46934
|
+
insetRegions
|
|
46324
46935
|
};
|
|
46325
46936
|
}
|
|
46326
|
-
var import_d3_geo2, import_topojson_client2, FIT_PAD, RAMP_FLOOR, R_DEFAULT, R_MIN, R_MAX, W_MIN, W_MAX, FONT,
|
|
46937
|
+
var import_d3_geo2, import_topojson_client2, FIT_PAD, RAMP_FLOOR, R_DEFAULT, R_MIN, R_MAX, W_MIN, W_MAX, FONT, COLO_EPS, LAND_TINT_LIGHT, LAND_TINT_DARK, TAG_TINT_LIGHT, TAG_TINT_DARK, WATER_TINT, RIVER_WIDTH, FOREIGN_TINT_LIGHT, FOREIGN_TINT_DARK, COLO_R, GOLDEN_ANGLE, FAN_STEP, ARC_CURVE_FRAC, usConusProjection, alaskaProjection, hawaiiProjection, INSET_STATES, US_NON_CONUS;
|
|
46327
46938
|
var init_layout15 = __esm({
|
|
46328
46939
|
"src/map/layout.ts"() {
|
|
46329
46940
|
"use strict";
|
|
46330
46941
|
import_d3_geo2 = require("d3-geo");
|
|
46331
46942
|
import_topojson_client2 = require("topojson-client");
|
|
46332
46943
|
init_color_utils();
|
|
46333
|
-
init_tag_groups();
|
|
46334
46944
|
init_label_layout();
|
|
46335
46945
|
init_legend_constants();
|
|
46946
|
+
init_title_constants();
|
|
46336
46947
|
FIT_PAD = 24;
|
|
46337
46948
|
RAMP_FLOOR = 15;
|
|
46338
46949
|
R_DEFAULT = 6;
|
|
@@ -46341,23 +46952,32 @@ var init_layout15 = __esm({
|
|
|
46341
46952
|
W_MIN = 1.25;
|
|
46342
46953
|
W_MAX = 8;
|
|
46343
46954
|
FONT = 11;
|
|
46344
|
-
LEADER_STEP = 14;
|
|
46345
46955
|
COLO_EPS = 1.5;
|
|
46956
|
+
LAND_TINT_LIGHT = 58;
|
|
46957
|
+
LAND_TINT_DARK = 75;
|
|
46958
|
+
TAG_TINT_LIGHT = 60;
|
|
46959
|
+
TAG_TINT_DARK = 68;
|
|
46960
|
+
WATER_TINT = 55;
|
|
46961
|
+
RIVER_WIDTH = 1.3;
|
|
46962
|
+
FOREIGN_TINT_LIGHT = 30;
|
|
46963
|
+
FOREIGN_TINT_DARK = 62;
|
|
46346
46964
|
COLO_R = 9;
|
|
46347
46965
|
GOLDEN_ANGLE = 2.399963229728653;
|
|
46348
46966
|
FAN_STEP = 16;
|
|
46349
|
-
TINY_REGION_AREA = 600;
|
|
46350
46967
|
ARC_CURVE_FRAC = 0.18;
|
|
46351
|
-
|
|
46352
|
-
|
|
46353
|
-
|
|
46354
|
-
|
|
46355
|
-
|
|
46356
|
-
|
|
46357
|
-
|
|
46358
|
-
|
|
46359
|
-
|
|
46360
|
-
|
|
46968
|
+
usConusProjection = () => (0, import_d3_geo2.geoConicEqualArea)().parallels([29.5, 45.5]).rotate([96, 0]);
|
|
46969
|
+
alaskaProjection = () => (0, import_d3_geo2.geoConicEqualArea)().rotate([154, 0]).center([-2, 58.5]).parallels([55, 65]);
|
|
46970
|
+
hawaiiProjection = () => (0, import_d3_geo2.geoMercator)();
|
|
46971
|
+
INSET_STATES = /* @__PURE__ */ new Set(["US-AK", "US-HI"]);
|
|
46972
|
+
US_NON_CONUS = /* @__PURE__ */ new Set([
|
|
46973
|
+
"US-AK",
|
|
46974
|
+
"US-HI",
|
|
46975
|
+
"US-AS",
|
|
46976
|
+
"US-GU",
|
|
46977
|
+
"US-MP",
|
|
46978
|
+
"US-PR",
|
|
46979
|
+
"US-VI"
|
|
46980
|
+
]);
|
|
46361
46981
|
}
|
|
46362
46982
|
});
|
|
46363
46983
|
|
|
@@ -46367,7 +46987,7 @@ __export(renderer_exports16, {
|
|
|
46367
46987
|
renderMap: () => renderMap,
|
|
46368
46988
|
renderMapForExport: () => renderMapForExport
|
|
46369
46989
|
});
|
|
46370
|
-
function renderMap(container, resolved, data, palette, isDark, onClickItem, exportDims) {
|
|
46990
|
+
function renderMap(container, resolved, data, palette, isDark, onClickItem, exportDims, activeGroupOverride) {
|
|
46371
46991
|
d3Selection18.select(container).selectAll(":not([data-d3-tooltip])").remove();
|
|
46372
46992
|
const width = exportDims?.width ?? container.clientWidth;
|
|
46373
46993
|
const height = exportDims?.height ?? container.clientHeight;
|
|
@@ -46378,27 +46998,29 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
46378
46998
|
{ width, height },
|
|
46379
46999
|
{
|
|
46380
47000
|
palette,
|
|
46381
|
-
isDark
|
|
47001
|
+
isDark,
|
|
47002
|
+
...activeGroupOverride !== void 0 && {
|
|
47003
|
+
activeGroup: activeGroupOverride
|
|
47004
|
+
}
|
|
46382
47005
|
}
|
|
46383
47006
|
);
|
|
46384
|
-
const svg = d3Selection18.select(container).append("svg").attr("width", width).attr("height", height).attr("viewBox", `0 0 ${width} ${height}`).attr("preserveAspectRatio", "xMidYMin meet").attr("xmlns", "http://www.w3.org/2000/svg").style("font-family", FONT_FAMILY);
|
|
47007
|
+
const svg = d3Selection18.select(container).append("svg").attr("width", width).attr("height", height).attr("viewBox", `0 0 ${width} ${height}`).attr("preserveAspectRatio", "xMidYMin meet").attr("xmlns", "http://www.w3.org/2000/svg").style("font-family", FONT_FAMILY).style("background", layout.background);
|
|
46385
47008
|
svg.append("rect").attr("width", width).attr("height", height).attr("fill", layout.background);
|
|
46386
|
-
const arrowColor = mix(palette.text, palette.bg, 50);
|
|
46387
47009
|
const defs = svg.append("defs");
|
|
46388
|
-
|
|
46389
|
-
const haloColor =
|
|
46390
|
-
if (layout.title) {
|
|
46391
|
-
svg.append("text").attr("x", width / 2).attr("y", TITLE_Y).attr("text-anchor", "middle").attr("font-size", TITLE_FONT_SIZE).attr("font-weight", TITLE_FONT_WEIGHT).attr("fill", palette.text).text(layout.title);
|
|
46392
|
-
}
|
|
46393
|
-
if (layout.subtitle) {
|
|
46394
|
-
svg.append("text").attr("x", width / 2).attr("y", TITLE_Y + TITLE_FONT_SIZE).attr("text-anchor", "middle").attr("font-size", LABEL_FONT + 1).attr("fill", palette.textMuted).text(layout.subtitle);
|
|
46395
|
-
}
|
|
46396
|
-
if (layout.caption) {
|
|
46397
|
-
svg.append("text").attr("x", width / 2).attr("y", height - 8).attr("text-anchor", "middle").attr("font-size", LABEL_FONT).attr("fill", palette.textMuted).text(layout.caption);
|
|
46398
|
-
}
|
|
47010
|
+
const arrowSize = (w) => Math.min(15, 7 + w * 0.95);
|
|
47011
|
+
const haloColor = palette.bg;
|
|
46399
47012
|
const gRegions = svg.append("g").attr("class", "dgmo-map-regions");
|
|
46400
|
-
|
|
46401
|
-
const p =
|
|
47013
|
+
const drawRegion = (g, r, strokeWidth) => {
|
|
47014
|
+
const p = g.append("path").attr("d", r.d).attr("fill", r.fill).attr("stroke", r.stroke).attr("stroke-width", strokeWidth);
|
|
47015
|
+
if (r.layer !== "base") {
|
|
47016
|
+
p.classed("dgmo-map-region", true).attr("data-region", r.id);
|
|
47017
|
+
if (r.score !== void 0) p.attr("data-score", r.score);
|
|
47018
|
+
if (r.tags) {
|
|
47019
|
+
for (const [group, value] of Object.entries(r.tags)) {
|
|
47020
|
+
p.attr(`data-tag-${group.toLowerCase()}`, value.toLowerCase());
|
|
47021
|
+
}
|
|
47022
|
+
}
|
|
47023
|
+
}
|
|
46402
47024
|
if (r.lineNumber >= 0) {
|
|
46403
47025
|
p.attr("data-line-number", r.lineNumber);
|
|
46404
47026
|
if (onClickItem) {
|
|
@@ -46408,11 +47030,31 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
46408
47030
|
);
|
|
46409
47031
|
}
|
|
46410
47032
|
}
|
|
47033
|
+
};
|
|
47034
|
+
for (const r of layout.regions) drawRegion(gRegions, r, 0.5);
|
|
47035
|
+
if (layout.rivers.length) {
|
|
47036
|
+
const gRivers = svg.append("g").attr("class", "dgmo-map-rivers").attr("fill", "none");
|
|
47037
|
+
for (const r of layout.rivers) {
|
|
47038
|
+
gRivers.append("path").attr("d", r.d).attr("stroke", r.color).attr("stroke-width", r.width).attr("stroke-linecap", "round").attr("stroke-linejoin", "round");
|
|
47039
|
+
}
|
|
47040
|
+
}
|
|
47041
|
+
if (layout.insets.length) {
|
|
47042
|
+
const insetG = svg.append("g").attr("class", "dgmo-map-insets");
|
|
47043
|
+
for (const box of layout.insets) {
|
|
47044
|
+
const d = box.points.map((p, i) => `${i ? "L" : "M"}${p[0]},${p[1]}`).join("") + "Z";
|
|
47045
|
+
insetG.append("path").attr("d", d).attr("fill", layout.background).attr("stroke", mix(palette.text, palette.bg, 55)).attr("stroke-width", 1).attr("stroke-linejoin", "round");
|
|
47046
|
+
}
|
|
47047
|
+
for (const r of layout.insetRegions) drawRegion(insetG, r, 0.5);
|
|
46411
47048
|
}
|
|
46412
47049
|
const gLegs = svg.append("g").attr("class", "dgmo-map-legs").attr("fill", "none");
|
|
46413
|
-
|
|
47050
|
+
layout.legs.forEach((leg, i) => {
|
|
46414
47051
|
const p = gLegs.append("path").attr("d", leg.d).attr("stroke", leg.color).attr("stroke-width", leg.width).attr("stroke-linecap", "round");
|
|
46415
|
-
if (leg.arrow)
|
|
47052
|
+
if (leg.arrow) {
|
|
47053
|
+
const id = `dgmo-map-arrow-${i}`;
|
|
47054
|
+
const s = arrowSize(leg.width);
|
|
47055
|
+
defs.append("marker").attr("id", id).attr("viewBox", "0 0 10 10").attr("refX", 10).attr("refY", 5).attr("markerUnits", "userSpaceOnUse").attr("markerWidth", s).attr("markerHeight", s).attr("orient", "auto-start-reverse").append("path").attr("d", "M0,0L10,5L0,10z").attr("fill", leg.color);
|
|
47056
|
+
p.attr("marker-end", `url(#${id})`);
|
|
47057
|
+
}
|
|
46416
47058
|
if (leg.label !== void 0 && leg.labelX !== void 0) {
|
|
46417
47059
|
emitText(
|
|
46418
47060
|
gLegs,
|
|
@@ -46426,13 +47068,13 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
46426
47068
|
LABEL_FONT - 1
|
|
46427
47069
|
);
|
|
46428
47070
|
}
|
|
46429
|
-
}
|
|
47071
|
+
});
|
|
46430
47072
|
const gPois = svg.append("g").attr("class", "dgmo-map-pois");
|
|
46431
47073
|
for (const poi of layout.pois) {
|
|
46432
47074
|
if (poi.isOrigin) {
|
|
46433
47075
|
gPois.append("circle").attr("cx", poi.cx).attr("cy", poi.cy).attr("r", poi.r + 3).attr("fill", "none").attr("stroke", poi.stroke).attr("stroke-width", 1.5);
|
|
46434
47076
|
}
|
|
46435
|
-
const c = gPois.append("circle").attr("cx", poi.cx).attr("cy", poi.cy).attr("r", poi.r).attr("fill", poi.fill).attr("stroke", poi.stroke).attr("stroke-width", 1).attr("data-line-number", poi.lineNumber);
|
|
47077
|
+
const c = gPois.append("circle").attr("cx", poi.cx).attr("cy", poi.cy).attr("r", poi.r).attr("fill", poi.fill).attr("stroke", poi.stroke).attr("stroke-width", 1).attr("data-line-number", poi.lineNumber).attr("data-poi", poi.id);
|
|
46436
47078
|
if (onClickItem) {
|
|
46437
47079
|
c.style("cursor", "pointer").on(
|
|
46438
47080
|
"click",
|
|
@@ -46456,48 +47098,66 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
46456
47098
|
const gLabels = svg.append("g").attr("class", "dgmo-map-labels");
|
|
46457
47099
|
for (const lab of layout.labels) {
|
|
46458
47100
|
if (lab.leader) {
|
|
46459
|
-
gLabels.append("line").attr("x1", lab.leader.x1).attr("y1", lab.leader.y1).attr("x2", lab.leader.x2).attr("y2", lab.leader.y2).attr(
|
|
47101
|
+
const line12 = gLabels.append("line").attr("x1", lab.leader.x1).attr("y1", lab.leader.y1).attr("x2", lab.leader.x2).attr("y2", lab.leader.y2).attr(
|
|
47102
|
+
"stroke",
|
|
47103
|
+
lab.leaderColor ?? mix(palette.textMuted, palette.bg, 60)
|
|
47104
|
+
).attr("stroke-width", lab.leaderColor ? 1 : 0.75);
|
|
47105
|
+
if (lab.poiId !== void 0) line12.attr("data-poi", lab.poiId);
|
|
46460
47106
|
}
|
|
46461
|
-
|
|
46462
|
-
gLabels.append("rect").attr("x", lab.x - 1).attr("y", lab.y - LABEL_FONT).attr("width", LABEL_FONT * 1.3).attr("height", LABEL_FONT * 1.3).attr("rx", 2).attr("fill", palette.surface).attr("stroke", palette.border);
|
|
46463
|
-
}
|
|
46464
|
-
emitText(
|
|
47107
|
+
const t = emitText(
|
|
46465
47108
|
gLabels,
|
|
46466
47109
|
lab.x,
|
|
46467
47110
|
lab.y,
|
|
46468
47111
|
lab.text,
|
|
46469
47112
|
lab.anchor,
|
|
46470
47113
|
lab.color,
|
|
46471
|
-
haloColor,
|
|
47114
|
+
lab.haloColor,
|
|
46472
47115
|
lab.halo,
|
|
46473
47116
|
LABEL_FONT
|
|
46474
47117
|
);
|
|
46475
|
-
|
|
46476
|
-
|
|
46477
|
-
|
|
46478
|
-
"transform",
|
|
46479
|
-
`translate(12, ${height - layout.pinList.length * 14 - 8})`
|
|
46480
|
-
);
|
|
46481
|
-
layout.pinList.forEach((entry, i) => {
|
|
46482
|
-
gPins.append("text").attr("x", 0).attr("y", i * 14).attr("font-size", LABEL_FONT - 1).attr("fill", palette.textMuted).text(`${entry.pin} \u2014 ${entry.label}`);
|
|
46483
|
-
});
|
|
47118
|
+
if (lab.poiId !== void 0) {
|
|
47119
|
+
t.attr("data-poi", lab.poiId).style("cursor", "default");
|
|
47120
|
+
}
|
|
46484
47121
|
}
|
|
46485
47122
|
if (layout.legend) {
|
|
46486
47123
|
const legendY = (layout.title ? TITLE_Y + TITLE_FONT_SIZE : 0) + (layout.subtitle ? TITLE_FONT_SIZE : 0) + 8;
|
|
46487
47124
|
const legendG = svg.append("g").attr("class", "dgmo-map-legend").attr("transform", `translate(0, ${legendY})`);
|
|
46488
|
-
const
|
|
47125
|
+
const ramp = layout.legend.ramp;
|
|
47126
|
+
const scoreGroup = ramp ? {
|
|
47127
|
+
name: ramp.metric?.trim() || "Score",
|
|
47128
|
+
entries: [],
|
|
47129
|
+
gradient: {
|
|
47130
|
+
min: ramp.min,
|
|
47131
|
+
max: ramp.max,
|
|
47132
|
+
hue: ramp.hue,
|
|
47133
|
+
base: ramp.base
|
|
47134
|
+
}
|
|
47135
|
+
} : null;
|
|
47136
|
+
const tagGroups = layout.legend.tagGroups.filter((g) => g.entries.length > 0).map((g) => ({ name: g.name, entries: [...g.entries] }));
|
|
47137
|
+
const groups = [...scoreGroup ? [scoreGroup] : [], ...tagGroups];
|
|
46489
47138
|
if (groups.length > 0) {
|
|
46490
47139
|
const config = {
|
|
46491
|
-
groups
|
|
47140
|
+
groups,
|
|
46492
47141
|
position: { placement: "top-center", titleRelation: "below-title" },
|
|
46493
47142
|
mode: exportDims ? "export" : "preview",
|
|
46494
|
-
showEmptyGroups: false
|
|
47143
|
+
showEmptyGroups: false,
|
|
47144
|
+
// Keep inactive siblings visible as pills so the user can click to flip
|
|
47145
|
+
// the active colouring dimension (preview only — export shows just the
|
|
47146
|
+
// active group).
|
|
47147
|
+
showInactivePills: true
|
|
46495
47148
|
};
|
|
46496
47149
|
const state = { activeGroup: layout.legend.activeGroup };
|
|
46497
47150
|
renderLegendD3(legendG, config, state, palette, isDark, void 0, width);
|
|
46498
47151
|
}
|
|
46499
|
-
|
|
46500
|
-
|
|
47152
|
+
}
|
|
47153
|
+
if (layout.title) {
|
|
47154
|
+
svg.append("text").attr("x", width / 2).attr("y", TITLE_Y).attr("text-anchor", "middle").attr("font-size", TITLE_FONT_SIZE).attr("font-weight", TITLE_FONT_WEIGHT).attr("fill", palette.text).attr("paint-order", "stroke fill").attr("stroke", palette.bg).attr("stroke-width", 4).attr("stroke-linejoin", "round").attr("stroke-opacity", 0.7).text(layout.title);
|
|
47155
|
+
}
|
|
47156
|
+
if (layout.subtitle) {
|
|
47157
|
+
svg.append("text").attr("x", width / 2).attr("y", TITLE_Y + TITLE_FONT_SIZE).attr("text-anchor", "middle").attr("font-size", LABEL_FONT + 1).attr("fill", palette.textMuted).attr("paint-order", "stroke fill").attr("stroke", palette.bg).attr("stroke-width", 3).attr("stroke-linejoin", "round").attr("stroke-opacity", 0.7).text(layout.subtitle);
|
|
47158
|
+
}
|
|
47159
|
+
if (layout.caption) {
|
|
47160
|
+
svg.append("text").attr("x", width / 2).attr("y", height - 8).attr("text-anchor", "middle").attr("font-size", LABEL_FONT).attr("fill", palette.textMuted).attr("paint-order", "stroke fill").attr("stroke", palette.bg).attr("stroke-width", 3).attr("stroke-linejoin", "round").attr("stroke-opacity", 0.7).text(layout.caption);
|
|
46501
47161
|
}
|
|
46502
47162
|
}
|
|
46503
47163
|
function renderMapForExport(container, resolved, data, palette, isDark, exportDims) {
|
|
@@ -46508,54 +47168,7 @@ function emitText(g, x, y, text, anchor, color, halo, withHalo, fontSize) {
|
|
|
46508
47168
|
if (withHalo) {
|
|
46509
47169
|
t.attr("paint-order", "stroke fill").attr("stroke", halo).attr("stroke-width", 3).attr("stroke-linejoin", "round").attr("stroke-opacity", 0.7);
|
|
46510
47170
|
}
|
|
46511
|
-
|
|
46512
|
-
function emitExtraLegend(svg, layout, palette, height, bottomGap) {
|
|
46513
|
-
const { legend } = layout;
|
|
46514
|
-
if (!legend) return;
|
|
46515
|
-
if (!legend.ramp && !legend.size && !legend.weight) return;
|
|
46516
|
-
const blocks = [];
|
|
46517
|
-
const g = svg.append("g").attr("class", "dgmo-map-legend-keys").attr("transform", `translate(12, ${height - 56 - bottomGap})`);
|
|
46518
|
-
let xCursor = 0;
|
|
46519
|
-
if (legend.ramp) {
|
|
46520
|
-
const ramp = legend.ramp;
|
|
46521
|
-
blocks.push(() => {
|
|
46522
|
-
const block = g.append("g").attr("transform", `translate(${xCursor},0)`);
|
|
46523
|
-
const gradId = "dgmo-map-ramp";
|
|
46524
|
-
const grad = block.append("defs").append("linearGradient").attr("id", gradId).attr("x1", "0%").attr("x2", "100%");
|
|
46525
|
-
grad.append("stop").attr("offset", "0%").attr("stop-color", mix(ramp.hue, palette.bg, 15));
|
|
46526
|
-
grad.append("stop").attr("offset", "100%").attr("stop-color", ramp.hue);
|
|
46527
|
-
block.append("rect").attr("width", 80).attr("height", 8).attr("fill", `url(#${gradId})`);
|
|
46528
|
-
block.append("text").attr("x", 0).attr("y", 22).attr("font-size", 9).attr("fill", palette.textMuted).text(String(ramp.min));
|
|
46529
|
-
block.append("text").attr("x", 80).attr("y", 22).attr("text-anchor", "end").attr("font-size", 9).attr("fill", palette.textMuted).text(String(ramp.max));
|
|
46530
|
-
if (ramp.metric) {
|
|
46531
|
-
block.append("text").attr("x", 0).attr("y", -4).attr("font-size", 9).attr("fill", palette.textMuted).text(ramp.metric);
|
|
46532
|
-
}
|
|
46533
|
-
xCursor += 110;
|
|
46534
|
-
});
|
|
46535
|
-
}
|
|
46536
|
-
if (legend.size) {
|
|
46537
|
-
const sz = legend.size;
|
|
46538
|
-
blocks.push(() => {
|
|
46539
|
-
const block = g.append("g").attr("transform", `translate(${xCursor},0)`);
|
|
46540
|
-
[3, 6, 10].forEach((r, i) => {
|
|
46541
|
-
block.append("circle").attr("cx", i * 26 + r).attr("cy", 8).attr("r", r).attr("fill", "none").attr("stroke", palette.textMuted);
|
|
46542
|
-
});
|
|
46543
|
-
block.append("text").attr("x", 0).attr("y", -4).attr("font-size", 9).attr("fill", palette.textMuted).text(sz.metric ?? "size");
|
|
46544
|
-
xCursor += 110;
|
|
46545
|
-
});
|
|
46546
|
-
}
|
|
46547
|
-
if (legend.weight) {
|
|
46548
|
-
const wt = legend.weight;
|
|
46549
|
-
blocks.push(() => {
|
|
46550
|
-
const block = g.append("g").attr("transform", `translate(${xCursor},0)`);
|
|
46551
|
-
[1, 3, 6].forEach((w, i) => {
|
|
46552
|
-
block.append("line").attr("x1", i * 26).attr("y1", 8).attr("x2", i * 26 + 20).attr("y2", 8).attr("stroke", palette.textMuted).attr("stroke-width", w);
|
|
46553
|
-
});
|
|
46554
|
-
block.append("text").attr("x", 0).attr("y", -4).attr("font-size", 9).attr("fill", palette.textMuted).text(wt.metric ?? "weight");
|
|
46555
|
-
xCursor += 110;
|
|
46556
|
-
});
|
|
46557
|
-
}
|
|
46558
|
-
for (const draw of blocks) draw();
|
|
47171
|
+
return t;
|
|
46559
47172
|
}
|
|
46560
47173
|
var d3Selection18, LABEL_FONT;
|
|
46561
47174
|
var init_renderer16 = __esm({
|
|
@@ -53023,18 +53636,18 @@ function getRotateFn(mode) {
|
|
|
53023
53636
|
return () => 0;
|
|
53024
53637
|
}
|
|
53025
53638
|
function renderWordCloudAsync(container, parsed, palette, _isDark, exportDims) {
|
|
53026
|
-
return new Promise((
|
|
53639
|
+
return new Promise((resolve) => {
|
|
53027
53640
|
d3Selection23.select(container).selectAll(":not([data-d3-tooltip])").remove();
|
|
53028
53641
|
const { words, cloudOptions } = parsed;
|
|
53029
53642
|
const title = parsed.noTitle ? null : parsed.title;
|
|
53030
53643
|
if (words.length === 0) {
|
|
53031
|
-
|
|
53644
|
+
resolve();
|
|
53032
53645
|
return;
|
|
53033
53646
|
}
|
|
53034
53647
|
const width = exportDims?.width ?? container.clientWidth;
|
|
53035
53648
|
const height = exportDims?.height ?? container.clientHeight;
|
|
53036
53649
|
if (width <= 0 || height <= 0) {
|
|
53037
|
-
|
|
53650
|
+
resolve();
|
|
53038
53651
|
return;
|
|
53039
53652
|
}
|
|
53040
53653
|
const titleHeight = title ? 40 : 0;
|
|
@@ -53063,7 +53676,7 @@ function renderWordCloudAsync(container, parsed, palette, _isDark, exportDims) {
|
|
|
53063
53676
|
"transform",
|
|
53064
53677
|
(d) => `translate(${d.x},${d.y}) rotate(${d.rotate})`
|
|
53065
53678
|
).text((d) => d.text);
|
|
53066
|
-
|
|
53679
|
+
resolve();
|
|
53067
53680
|
}).start();
|
|
53068
53681
|
});
|
|
53069
53682
|
}
|
|
@@ -56429,7 +57042,7 @@ pre.dgmo, code.language-dgmo, pre > code.language-dgmo,
|
|
|
56429
57042
|
|
|
56430
57043
|
// src/auto/index.ts
|
|
56431
57044
|
init_safe_href();
|
|
56432
|
-
var VERSION = "0.
|
|
57045
|
+
var VERSION = "0.20.1";
|
|
56433
57046
|
var DEFAULTS = {
|
|
56434
57047
|
theme: "auto",
|
|
56435
57048
|
palette: "nord",
|