@diagrammo/dgmo 0.21.1 → 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/README.md +16 -6
- package/dist/advanced.cjs +2230 -503
- package/dist/advanced.d.cts +5731 -0
- package/dist/advanced.d.ts +5731 -0
- package/dist/advanced.js +2226 -503
- package/dist/auto.cjs +2272 -479
- package/dist/auto.d.cts +39 -0
- package/dist/auto.d.ts +39 -0
- package/dist/auto.js +124 -124
- package/dist/auto.mjs +2274 -480
- package/dist/cli.cjs +170 -170
- package/dist/editor.cjs +16 -16
- package/dist/editor.js +16 -16
- package/dist/highlight.cjs +18 -13
- package/dist/highlight.js +18 -13
- package/dist/index.cjs +2253 -465
- package/dist/index.d.cts +339 -0
- package/dist/index.d.ts +339 -0
- package/dist/index.js +2255 -466
- package/dist/internal.cjs +2230 -503
- package/dist/internal.d.cts +5731 -0
- package/dist/internal.d.ts +5731 -0
- package/dist/internal.js +2226 -503
- 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 -0
- package/dist/map-data/world-coarse.json +1 -1
- package/dist/map-data/world-detail.json +1 -1
- package/docs/language-reference.md +55 -9
- package/gallery/fixtures/boxes-and-lines.dgmo +6 -4
- package/gallery/fixtures/map-categorical-world.dgmo +16 -0
- package/gallery/fixtures/map-categorical.dgmo +0 -1
- package/gallery/fixtures/map-choropleth.dgmo +0 -1
- package/gallery/fixtures/map-coastline.dgmo +7 -0
- package/gallery/fixtures/map-colorize.dgmo +11 -0
- package/gallery/fixtures/map-direct-color.dgmo +0 -1
- package/gallery/fixtures/map-reference-world.dgmo +11 -0
- package/gallery/fixtures/map-region-scope.dgmo +0 -3
- package/gallery/fixtures/map-route.dgmo +0 -1
- package/package.json +1 -1
- package/src/advanced.ts +12 -1
- package/src/boxes-and-lines/parser.ts +39 -0
- package/src/boxes-and-lines/renderer.ts +205 -20
- package/src/boxes-and-lines/types.ts +9 -0
- package/src/cli.ts +1 -1
- package/src/completion.ts +36 -30
- package/src/cycle/renderer.ts +14 -1
- package/src/d3.ts +20 -6
- package/src/editor/highlight-api.ts +4 -0
- package/src/editor/keywords.ts +16 -16
- package/src/infra/renderer.ts +35 -7
- package/src/map/colorize.ts +54 -0
- package/src/map/context-labels.ts +429 -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/types.ts +34 -0
- package/src/map/data/water-bodies.json +1 -0
- package/src/map/data/world-coarse.json +1 -1
- package/src/map/data/world-detail.json +1 -1
- package/src/map/dimensions.ts +117 -0
- package/src/map/geo-query.ts +21 -3
- package/src/map/geo.ts +47 -1
- package/src/map/layout.ts +1408 -266
- package/src/map/load-data.ts +10 -2
- package/src/map/parser.ts +42 -116
- package/src/map/renderer.ts +604 -14
- package/src/map/resolved-types.ts +16 -2
- package/src/map/resolver.ts +208 -59
- package/src/map/types.ts +30 -32
- package/src/mindmap/renderer.ts +10 -1
- package/src/palettes/atlas.ts +77 -0
- package/src/palettes/blueprint.ts +73 -0
- package/src/palettes/color-utils.ts +58 -1
- package/src/palettes/index.ts +12 -3
- package/src/palettes/slate.ts +73 -0
- package/src/palettes/tidewater.ts +73 -0
- package/src/render.ts +8 -1
- package/src/tech-radar/renderer.ts +3 -0
- package/src/tech-radar/types.ts +3 -0
- package/src/utils/d3-types.ts +5 -0
- package/src/utils/legend-layout.ts +21 -4
- package/src/utils/legend-types.ts +7 -0
- package/src/utils/reserved-key-registry.ts +8 -3
- package/src/palettes/bold.ts +0 -67
package/dist/advanced.cjs
CHANGED
|
@@ -373,18 +373,18 @@ function computeQuadrantPointLabels(points, chartBounds, obstacles, pointRadius,
|
|
|
373
373
|
const results = [];
|
|
374
374
|
for (let i = 0; i < points.length; i++) {
|
|
375
375
|
const pt = points[i];
|
|
376
|
-
const
|
|
376
|
+
const labelWidth2 = pt.label.length * fontSize * CHAR_WIDTH_RATIO + 8;
|
|
377
377
|
let best = null;
|
|
378
378
|
const directions = [
|
|
379
379
|
{
|
|
380
380
|
// Above
|
|
381
381
|
gen: (offset) => {
|
|
382
|
-
const lx = pt.cx -
|
|
382
|
+
const lx = pt.cx - labelWidth2 / 2;
|
|
383
383
|
const ly = pt.cy - offset - labelHeight;
|
|
384
|
-
if (ly < chartBounds.top || lx < chartBounds.left || lx +
|
|
384
|
+
if (ly < chartBounds.top || lx < chartBounds.left || lx + labelWidth2 > chartBounds.right)
|
|
385
385
|
return null;
|
|
386
386
|
return {
|
|
387
|
-
rect: { x: lx, y: ly, w:
|
|
387
|
+
rect: { x: lx, y: ly, w: labelWidth2, h: labelHeight },
|
|
388
388
|
textX: pt.cx,
|
|
389
389
|
textY: ly + labelHeight / 2,
|
|
390
390
|
anchor: "middle"
|
|
@@ -394,12 +394,12 @@ function computeQuadrantPointLabels(points, chartBounds, obstacles, pointRadius,
|
|
|
394
394
|
{
|
|
395
395
|
// Below
|
|
396
396
|
gen: (offset) => {
|
|
397
|
-
const lx = pt.cx -
|
|
397
|
+
const lx = pt.cx - labelWidth2 / 2;
|
|
398
398
|
const ly = pt.cy + offset;
|
|
399
|
-
if (ly + labelHeight > chartBounds.bottom || lx < chartBounds.left || lx +
|
|
399
|
+
if (ly + labelHeight > chartBounds.bottom || lx < chartBounds.left || lx + labelWidth2 > chartBounds.right)
|
|
400
400
|
return null;
|
|
401
401
|
return {
|
|
402
|
-
rect: { x: lx, y: ly, w:
|
|
402
|
+
rect: { x: lx, y: ly, w: labelWidth2, h: labelHeight },
|
|
403
403
|
textX: pt.cx,
|
|
404
404
|
textY: ly + labelHeight / 2,
|
|
405
405
|
anchor: "middle"
|
|
@@ -411,10 +411,10 @@ function computeQuadrantPointLabels(points, chartBounds, obstacles, pointRadius,
|
|
|
411
411
|
gen: (offset) => {
|
|
412
412
|
const lx = pt.cx + offset;
|
|
413
413
|
const ly = pt.cy - labelHeight / 2;
|
|
414
|
-
if (lx +
|
|
414
|
+
if (lx + labelWidth2 > chartBounds.right || ly < chartBounds.top || ly + labelHeight > chartBounds.bottom)
|
|
415
415
|
return null;
|
|
416
416
|
return {
|
|
417
|
-
rect: { x: lx, y: ly, w:
|
|
417
|
+
rect: { x: lx, y: ly, w: labelWidth2, h: labelHeight },
|
|
418
418
|
textX: lx,
|
|
419
419
|
textY: pt.cy,
|
|
420
420
|
anchor: "start"
|
|
@@ -424,13 +424,13 @@ function computeQuadrantPointLabels(points, chartBounds, obstacles, pointRadius,
|
|
|
424
424
|
{
|
|
425
425
|
// Left
|
|
426
426
|
gen: (offset) => {
|
|
427
|
-
const lx = pt.cx - offset -
|
|
427
|
+
const lx = pt.cx - offset - labelWidth2;
|
|
428
428
|
const ly = pt.cy - labelHeight / 2;
|
|
429
429
|
if (lx < chartBounds.left || ly < chartBounds.top || ly + labelHeight > chartBounds.bottom)
|
|
430
430
|
return null;
|
|
431
431
|
return {
|
|
432
|
-
rect: { x: lx, y: ly, w:
|
|
433
|
-
textX: lx +
|
|
432
|
+
rect: { x: lx, y: ly, w: labelWidth2, h: labelHeight },
|
|
433
|
+
textX: lx + labelWidth2,
|
|
434
434
|
textY: pt.cy,
|
|
435
435
|
anchor: "end"
|
|
436
436
|
};
|
|
@@ -480,10 +480,10 @@ function computeQuadrantPointLabels(points, chartBounds, obstacles, pointRadius,
|
|
|
480
480
|
}
|
|
481
481
|
}
|
|
482
482
|
if (!best) {
|
|
483
|
-
const lx = pt.cx -
|
|
483
|
+
const lx = pt.cx - labelWidth2 / 2;
|
|
484
484
|
const ly = pt.cy - minGap - labelHeight;
|
|
485
485
|
best = {
|
|
486
|
-
rect: { x: lx, y: ly, w:
|
|
486
|
+
rect: { x: lx, y: ly, w: labelWidth2, h: labelHeight },
|
|
487
487
|
textX: pt.cx,
|
|
488
488
|
textY: ly + labelHeight / 2,
|
|
489
489
|
anchor: "middle",
|
|
@@ -860,6 +860,9 @@ var init_reserved_key_registry = __esm({
|
|
|
860
860
|
"value",
|
|
861
861
|
"label",
|
|
862
862
|
"style"
|
|
863
|
+
// `surface:` was removed in the 2026-06-02 defaults-on review — it is no longer
|
|
864
|
+
// a recognized metadata key (the route/edge surface feature was cut; §24B.7).
|
|
865
|
+
// A stray `surface: water` is no longer captured as a reserved key.
|
|
863
866
|
]);
|
|
864
867
|
ORG_REGISTRY = staticRegistry([
|
|
865
868
|
"color",
|
|
@@ -914,9 +917,7 @@ var init_reserved_key_registry = __esm({
|
|
|
914
917
|
BOXES_AND_LINES_REGISTRY = staticRegistry([
|
|
915
918
|
"color",
|
|
916
919
|
"description",
|
|
917
|
-
"
|
|
918
|
-
"split",
|
|
919
|
-
"fanout"
|
|
920
|
+
"value"
|
|
920
921
|
]);
|
|
921
922
|
TIMELINE_REGISTRY = staticRegistry([
|
|
922
923
|
"color",
|
|
@@ -1922,77 +1923,266 @@ function getSegmentColors(palette, count) {
|
|
|
1922
1923
|
(_, i) => hslToHex(Math.round((startHue + i * step) % 360), avgS, avgL)
|
|
1923
1924
|
);
|
|
1924
1925
|
}
|
|
1926
|
+
function politicalTints(palette, count, isDark) {
|
|
1927
|
+
if (count <= 0) return [];
|
|
1928
|
+
const base = isDark ? palette.surface : palette.bg;
|
|
1929
|
+
const c = palette.colors;
|
|
1930
|
+
const swatches = [
|
|
1931
|
+
.../* @__PURE__ */ new Set([
|
|
1932
|
+
c.green,
|
|
1933
|
+
c.yellow,
|
|
1934
|
+
c.orange,
|
|
1935
|
+
c.purple,
|
|
1936
|
+
c.red,
|
|
1937
|
+
c.teal,
|
|
1938
|
+
c.cyan,
|
|
1939
|
+
c.blue
|
|
1940
|
+
])
|
|
1941
|
+
];
|
|
1942
|
+
const bands = isDark ? POLITICAL_TINT_BANDS.dark : POLITICAL_TINT_BANDS.light;
|
|
1943
|
+
const out = [];
|
|
1944
|
+
for (const pct of bands) {
|
|
1945
|
+
if (out.length >= count) break;
|
|
1946
|
+
for (const s of swatches) out.push(mix(s, base, pct));
|
|
1947
|
+
}
|
|
1948
|
+
return out.slice(0, count);
|
|
1949
|
+
}
|
|
1950
|
+
var POLITICAL_TINT_BANDS;
|
|
1925
1951
|
var init_color_utils = __esm({
|
|
1926
1952
|
"src/palettes/color-utils.ts"() {
|
|
1927
1953
|
"use strict";
|
|
1954
|
+
POLITICAL_TINT_BANDS = {
|
|
1955
|
+
light: [32, 48, 64, 80],
|
|
1956
|
+
dark: [44, 58, 72, 86]
|
|
1957
|
+
};
|
|
1928
1958
|
}
|
|
1929
1959
|
});
|
|
1930
1960
|
|
|
1931
|
-
// src/palettes/
|
|
1932
|
-
var
|
|
1933
|
-
var
|
|
1934
|
-
"src/palettes/
|
|
1961
|
+
// src/palettes/atlas.ts
|
|
1962
|
+
var atlasPalette;
|
|
1963
|
+
var init_atlas = __esm({
|
|
1964
|
+
"src/palettes/atlas.ts"() {
|
|
1935
1965
|
"use strict";
|
|
1936
1966
|
init_registry();
|
|
1937
|
-
|
|
1938
|
-
id: "
|
|
1939
|
-
name: "
|
|
1967
|
+
atlasPalette = {
|
|
1968
|
+
id: "atlas",
|
|
1969
|
+
name: "Atlas",
|
|
1940
1970
|
light: {
|
|
1941
|
-
bg: "#
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1971
|
+
bg: "#f3ead3",
|
|
1972
|
+
// warm manila / parchment
|
|
1973
|
+
surface: "#ece0c0",
|
|
1974
|
+
// deeper paper (cards, panels)
|
|
1975
|
+
overlay: "#e8dab8",
|
|
1976
|
+
// popovers, dropdowns
|
|
1977
|
+
border: "#bcaa86",
|
|
1978
|
+
// muted sepia rule line
|
|
1979
|
+
text: "#463a26",
|
|
1980
|
+
// aged sepia-brown ink
|
|
1981
|
+
textMuted: "#7a6a4f",
|
|
1982
|
+
// faded annotation ink
|
|
1983
|
+
textOnFillLight: "#f7f1de",
|
|
1984
|
+
// parchment (light text on dark fills)
|
|
1985
|
+
textOnFillDark: "#3a2e1c",
|
|
1986
|
+
// deep ink (dark text on light fills)
|
|
1987
|
+
primary: "#5b7a99",
|
|
1988
|
+
// pull-down map ocean (steel-blue)
|
|
1989
|
+
secondary: "#7e9a6f",
|
|
1990
|
+
// lowland sage / celadon
|
|
1991
|
+
accent: "#b07f7c",
|
|
1992
|
+
// dusty rose
|
|
1993
|
+
destructive: "#b25a45",
|
|
1994
|
+
// brick / terracotta
|
|
1953
1995
|
colors: {
|
|
1954
|
-
red: "#
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1996
|
+
red: "#bf6a52",
|
|
1997
|
+
// terracotta brick
|
|
1998
|
+
orange: "#cf9a5c",
|
|
1999
|
+
// map tan / ochre
|
|
2000
|
+
yellow: "#cdb35e",
|
|
2001
|
+
// straw / muted lemon
|
|
2002
|
+
green: "#7e9a6f",
|
|
2003
|
+
// sage / celadon lowland
|
|
2004
|
+
blue: "#5b7a99",
|
|
2005
|
+
// steel-blue ocean
|
|
2006
|
+
purple: "#9a7fa6",
|
|
2007
|
+
// dusty lilac / mauve
|
|
2008
|
+
teal: "#6fa094",
|
|
2009
|
+
// muted seafoam
|
|
2010
|
+
cyan: "#79a7b5",
|
|
2011
|
+
// shallow-water blue
|
|
2012
|
+
gray: "#8a7d68",
|
|
2013
|
+
// warm taupe
|
|
2014
|
+
black: "#463a26",
|
|
2015
|
+
// ink
|
|
2016
|
+
white: "#ece0c0"
|
|
2017
|
+
// paper
|
|
1965
2018
|
}
|
|
1966
2019
|
},
|
|
1967
2020
|
dark: {
|
|
1968
|
-
bg: "#
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
2021
|
+
bg: "#1e2a33",
|
|
2022
|
+
// deep map ocean (night globe)
|
|
2023
|
+
surface: "#27353f",
|
|
2024
|
+
// raised ocean
|
|
2025
|
+
overlay: "#2e3d48",
|
|
2026
|
+
// popovers, dropdowns
|
|
2027
|
+
border: "#3d4f5c",
|
|
2028
|
+
// depth-contour line
|
|
2029
|
+
text: "#e8dcc0",
|
|
2030
|
+
// parchment ink, inverted
|
|
2031
|
+
textMuted: "#a89a7d",
|
|
2032
|
+
// faded label
|
|
2033
|
+
textOnFillLight: "#f7f1de",
|
|
2034
|
+
// parchment
|
|
2035
|
+
textOnFillDark: "#1a242c",
|
|
2036
|
+
// deep ocean ink
|
|
2037
|
+
primary: "#7ba0bf",
|
|
2038
|
+
// brighter ocean
|
|
2039
|
+
secondary: "#9bb588",
|
|
2040
|
+
// sage, lifted
|
|
2041
|
+
accent: "#cf9a96",
|
|
2042
|
+
// dusty rose, lifted
|
|
2043
|
+
destructive: "#c9745c",
|
|
2044
|
+
// brick, lifted
|
|
2045
|
+
colors: {
|
|
2046
|
+
red: "#cf7a60",
|
|
2047
|
+
// terracotta
|
|
2048
|
+
orange: "#d9a96a",
|
|
2049
|
+
// tan / ochre
|
|
2050
|
+
yellow: "#d8c074",
|
|
2051
|
+
// straw
|
|
2052
|
+
green: "#9bb588",
|
|
2053
|
+
// sage lowland
|
|
2054
|
+
blue: "#7ba0bf",
|
|
2055
|
+
// ocean
|
|
2056
|
+
purple: "#b59ac0",
|
|
2057
|
+
// lilac / mauve
|
|
2058
|
+
teal: "#85b3a6",
|
|
2059
|
+
// seafoam
|
|
2060
|
+
cyan: "#92bccb",
|
|
2061
|
+
// shallow-water blue
|
|
2062
|
+
gray: "#9a8d76",
|
|
2063
|
+
// warm taupe
|
|
2064
|
+
black: "#27353f",
|
|
2065
|
+
// raised ocean
|
|
2066
|
+
white: "#e8dcc0"
|
|
2067
|
+
// parchment
|
|
2068
|
+
}
|
|
2069
|
+
}
|
|
2070
|
+
};
|
|
2071
|
+
registerPalette(atlasPalette);
|
|
2072
|
+
}
|
|
2073
|
+
});
|
|
2074
|
+
|
|
2075
|
+
// src/palettes/blueprint.ts
|
|
2076
|
+
var blueprintPalette;
|
|
2077
|
+
var init_blueprint = __esm({
|
|
2078
|
+
"src/palettes/blueprint.ts"() {
|
|
2079
|
+
"use strict";
|
|
2080
|
+
init_registry();
|
|
2081
|
+
blueprintPalette = {
|
|
2082
|
+
id: "blueprint",
|
|
2083
|
+
name: "Blueprint",
|
|
2084
|
+
light: {
|
|
2085
|
+
bg: "#f4f8fb",
|
|
2086
|
+
// pale drafting white (faint cyan)
|
|
2087
|
+
surface: "#e6eef4",
|
|
2088
|
+
// drafting panel
|
|
2089
|
+
overlay: "#dde9f1",
|
|
2090
|
+
// popovers, dropdowns
|
|
2091
|
+
border: "#aac3d6",
|
|
2092
|
+
// pale blue grid line
|
|
2093
|
+
text: "#123a5e",
|
|
2094
|
+
// blueprint navy ink
|
|
2095
|
+
textMuted: "#4f7390",
|
|
2096
|
+
// faint draft note
|
|
2097
|
+
textOnFillLight: "#f4f8fb",
|
|
2098
|
+
// drafting white
|
|
2099
|
+
textOnFillDark: "#0c2f4d",
|
|
2100
|
+
// deep blueprint navy
|
|
2101
|
+
primary: "#1f5e8c",
|
|
2102
|
+
// blueprint blue
|
|
2103
|
+
secondary: "#5b7d96",
|
|
2104
|
+
// steel
|
|
2105
|
+
accent: "#b08a3e",
|
|
2106
|
+
// draftsman's ochre highlight
|
|
2107
|
+
destructive: "#c0504d",
|
|
2108
|
+
// correction red
|
|
2109
|
+
colors: {
|
|
2110
|
+
red: "#c25a4e",
|
|
2111
|
+
// correction red
|
|
2112
|
+
orange: "#c2823e",
|
|
2113
|
+
// ochre
|
|
2114
|
+
yellow: "#c2a843",
|
|
2115
|
+
// pencil gold
|
|
2116
|
+
green: "#4f8a6b",
|
|
2117
|
+
// drafting green
|
|
2118
|
+
blue: "#1f5e8c",
|
|
2119
|
+
// blueprint blue
|
|
2120
|
+
purple: "#6f5e96",
|
|
2121
|
+
// indigo pencil
|
|
2122
|
+
teal: "#3a8a8a",
|
|
2123
|
+
// teal
|
|
2124
|
+
cyan: "#3f8fb5",
|
|
2125
|
+
// cyan
|
|
2126
|
+
gray: "#7e8e98",
|
|
2127
|
+
// graphite
|
|
2128
|
+
black: "#123a5e",
|
|
2129
|
+
// navy ink
|
|
2130
|
+
white: "#e6eef4"
|
|
2131
|
+
// panel
|
|
2132
|
+
}
|
|
2133
|
+
},
|
|
2134
|
+
dark: {
|
|
2135
|
+
bg: "#103a5e",
|
|
2136
|
+
// deep blueprint blue (cyanotype ground)
|
|
2137
|
+
surface: "#16466e",
|
|
2138
|
+
// raised sheet
|
|
2139
|
+
overlay: "#1c5180",
|
|
2140
|
+
// popovers, dropdowns
|
|
2141
|
+
border: "#3a6f96",
|
|
2142
|
+
// grid line
|
|
2143
|
+
text: "#eaf2f8",
|
|
2144
|
+
// chalk white
|
|
2145
|
+
textMuted: "#9fc0d6",
|
|
2146
|
+
// faint chalk note
|
|
2147
|
+
textOnFillLight: "#eaf2f8",
|
|
2148
|
+
// chalk white
|
|
2149
|
+
textOnFillDark: "#0c2f4d",
|
|
2150
|
+
// deep blueprint navy
|
|
2151
|
+
primary: "#7fb8d8",
|
|
2152
|
+
// chalk cyan
|
|
2153
|
+
secondary: "#9fb8c8",
|
|
2154
|
+
// pale steel
|
|
2155
|
+
accent: "#d8c27a",
|
|
2156
|
+
// chalk amber
|
|
2157
|
+
destructive: "#e08a7a",
|
|
2158
|
+
// chalk correction red
|
|
1980
2159
|
colors: {
|
|
1981
|
-
red: "#
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
2160
|
+
red: "#e0907e",
|
|
2161
|
+
// chalk red
|
|
2162
|
+
orange: "#e0ab78",
|
|
2163
|
+
// chalk amber
|
|
2164
|
+
yellow: "#e3d089",
|
|
2165
|
+
// chalk gold
|
|
2166
|
+
green: "#93c79e",
|
|
2167
|
+
// chalk green
|
|
2168
|
+
blue: "#8ec3e0",
|
|
2169
|
+
// chalk cyan-blue
|
|
2170
|
+
purple: "#b6a6d8",
|
|
2171
|
+
// chalk indigo
|
|
2172
|
+
teal: "#84c7c2",
|
|
2173
|
+
// chalk teal
|
|
2174
|
+
cyan: "#9fd6e0",
|
|
2175
|
+
// chalk cyan
|
|
2176
|
+
gray: "#aebecb",
|
|
2177
|
+
// chalk graphite
|
|
2178
|
+
black: "#16466e",
|
|
2179
|
+
// raised sheet
|
|
2180
|
+
white: "#eaf2f8"
|
|
2181
|
+
// chalk white
|
|
1992
2182
|
}
|
|
1993
2183
|
}
|
|
1994
2184
|
};
|
|
1995
|
-
registerPalette(
|
|
2185
|
+
registerPalette(blueprintPalette);
|
|
1996
2186
|
}
|
|
1997
2187
|
});
|
|
1998
2188
|
|
|
@@ -2489,6 +2679,120 @@ var init_rose_pine = __esm({
|
|
|
2489
2679
|
}
|
|
2490
2680
|
});
|
|
2491
2681
|
|
|
2682
|
+
// src/palettes/slate.ts
|
|
2683
|
+
var slatePalette;
|
|
2684
|
+
var init_slate = __esm({
|
|
2685
|
+
"src/palettes/slate.ts"() {
|
|
2686
|
+
"use strict";
|
|
2687
|
+
init_registry();
|
|
2688
|
+
slatePalette = {
|
|
2689
|
+
id: "slate",
|
|
2690
|
+
name: "Slate",
|
|
2691
|
+
light: {
|
|
2692
|
+
bg: "#ffffff",
|
|
2693
|
+
// clean slide white
|
|
2694
|
+
surface: "#f3f5f8",
|
|
2695
|
+
// light cool-gray panel
|
|
2696
|
+
overlay: "#eaeef3",
|
|
2697
|
+
// popovers, dropdowns
|
|
2698
|
+
border: "#d4dae1",
|
|
2699
|
+
// hairline rule
|
|
2700
|
+
text: "#1f2933",
|
|
2701
|
+
// near-black slate (softer than pure black)
|
|
2702
|
+
textMuted: "#5b6672",
|
|
2703
|
+
// secondary label
|
|
2704
|
+
textOnFillLight: "#ffffff",
|
|
2705
|
+
// light text on dark fills
|
|
2706
|
+
textOnFillDark: "#1f2933",
|
|
2707
|
+
// dark text on light fills
|
|
2708
|
+
primary: "#3b6ea5",
|
|
2709
|
+
// confident corporate blue
|
|
2710
|
+
secondary: "#5b6672",
|
|
2711
|
+
// slate gray
|
|
2712
|
+
accent: "#3a9188",
|
|
2713
|
+
// muted teal accent
|
|
2714
|
+
destructive: "#c0504d",
|
|
2715
|
+
// brick red
|
|
2716
|
+
colors: {
|
|
2717
|
+
red: "#c0504d",
|
|
2718
|
+
// brick
|
|
2719
|
+
orange: "#cc7a33",
|
|
2720
|
+
// muted amber
|
|
2721
|
+
yellow: "#c9a227",
|
|
2722
|
+
// gold (not neon)
|
|
2723
|
+
green: "#5b9357",
|
|
2724
|
+
// forest / sage
|
|
2725
|
+
blue: "#3b6ea5",
|
|
2726
|
+
// corporate blue
|
|
2727
|
+
purple: "#7d5ba6",
|
|
2728
|
+
// muted violet
|
|
2729
|
+
teal: "#3a9188",
|
|
2730
|
+
// teal
|
|
2731
|
+
cyan: "#4f96c4",
|
|
2732
|
+
// steel cyan
|
|
2733
|
+
gray: "#7e8a97",
|
|
2734
|
+
// cool gray
|
|
2735
|
+
black: "#1f2933",
|
|
2736
|
+
// slate ink
|
|
2737
|
+
white: "#f3f5f8"
|
|
2738
|
+
// panel
|
|
2739
|
+
}
|
|
2740
|
+
},
|
|
2741
|
+
dark: {
|
|
2742
|
+
bg: "#161b22",
|
|
2743
|
+
// deep slate (keynote dark)
|
|
2744
|
+
surface: "#202833",
|
|
2745
|
+
// raised panel
|
|
2746
|
+
overlay: "#29323e",
|
|
2747
|
+
// popovers, dropdowns
|
|
2748
|
+
border: "#38424f",
|
|
2749
|
+
// divider
|
|
2750
|
+
text: "#e6eaef",
|
|
2751
|
+
// off-white
|
|
2752
|
+
textMuted: "#9aa5b1",
|
|
2753
|
+
// secondary label
|
|
2754
|
+
textOnFillLight: "#ffffff",
|
|
2755
|
+
// light text on dark fills
|
|
2756
|
+
textOnFillDark: "#161b22",
|
|
2757
|
+
// dark text on light fills
|
|
2758
|
+
primary: "#5b9bd5",
|
|
2759
|
+
// lifted corporate blue
|
|
2760
|
+
secondary: "#8593a3",
|
|
2761
|
+
// slate gray, lifted
|
|
2762
|
+
accent: "#45b3a3",
|
|
2763
|
+
// teal, lifted
|
|
2764
|
+
destructive: "#e07b6e",
|
|
2765
|
+
// brick, lifted
|
|
2766
|
+
colors: {
|
|
2767
|
+
red: "#e07b6e",
|
|
2768
|
+
// brick
|
|
2769
|
+
orange: "#e0975a",
|
|
2770
|
+
// amber
|
|
2771
|
+
yellow: "#d9bd5a",
|
|
2772
|
+
// gold
|
|
2773
|
+
green: "#74b56e",
|
|
2774
|
+
// forest / sage
|
|
2775
|
+
blue: "#5b9bd5",
|
|
2776
|
+
// corporate blue
|
|
2777
|
+
purple: "#a585c9",
|
|
2778
|
+
// violet
|
|
2779
|
+
teal: "#45b3a3",
|
|
2780
|
+
// teal
|
|
2781
|
+
cyan: "#62b0d9",
|
|
2782
|
+
// steel cyan
|
|
2783
|
+
gray: "#95a1ae",
|
|
2784
|
+
// cool gray
|
|
2785
|
+
black: "#202833",
|
|
2786
|
+
// raised panel
|
|
2787
|
+
white: "#e6eaef"
|
|
2788
|
+
// off-white
|
|
2789
|
+
}
|
|
2790
|
+
}
|
|
2791
|
+
};
|
|
2792
|
+
registerPalette(slatePalette);
|
|
2793
|
+
}
|
|
2794
|
+
});
|
|
2795
|
+
|
|
2492
2796
|
// src/palettes/solarized.ts
|
|
2493
2797
|
var solarizedPalette;
|
|
2494
2798
|
var init_solarized = __esm({
|
|
@@ -2584,6 +2888,120 @@ var init_solarized = __esm({
|
|
|
2584
2888
|
}
|
|
2585
2889
|
});
|
|
2586
2890
|
|
|
2891
|
+
// src/palettes/tidewater.ts
|
|
2892
|
+
var tidewaterPalette;
|
|
2893
|
+
var init_tidewater = __esm({
|
|
2894
|
+
"src/palettes/tidewater.ts"() {
|
|
2895
|
+
"use strict";
|
|
2896
|
+
init_registry();
|
|
2897
|
+
tidewaterPalette = {
|
|
2898
|
+
id: "tidewater",
|
|
2899
|
+
name: "Tidewater",
|
|
2900
|
+
light: {
|
|
2901
|
+
bg: "#eceff0",
|
|
2902
|
+
// weathered sea-mist paper
|
|
2903
|
+
surface: "#e0e4e3",
|
|
2904
|
+
// worn deck panel
|
|
2905
|
+
overlay: "#dadfdf",
|
|
2906
|
+
// popovers, dropdowns
|
|
2907
|
+
border: "#a9b2b3",
|
|
2908
|
+
// muted slate rule
|
|
2909
|
+
text: "#18313f",
|
|
2910
|
+
// ship's-log navy ink
|
|
2911
|
+
textMuted: "#51636b",
|
|
2912
|
+
// faded log entry
|
|
2913
|
+
textOnFillLight: "#f3f5f3",
|
|
2914
|
+
// weathered white
|
|
2915
|
+
textOnFillDark: "#162c38",
|
|
2916
|
+
// deep navy
|
|
2917
|
+
primary: "#1f4e6b",
|
|
2918
|
+
// deep-sea navy
|
|
2919
|
+
secondary: "#b08a4f",
|
|
2920
|
+
// rope / manila tan
|
|
2921
|
+
accent: "#c69a3e",
|
|
2922
|
+
// brass
|
|
2923
|
+
destructive: "#c1433a",
|
|
2924
|
+
// signal-flag red
|
|
2925
|
+
colors: {
|
|
2926
|
+
red: "#c1433a",
|
|
2927
|
+
// signal-flag red
|
|
2928
|
+
orange: "#cc7a38",
|
|
2929
|
+
// weathered amber
|
|
2930
|
+
yellow: "#d6bf5a",
|
|
2931
|
+
// brass gold
|
|
2932
|
+
green: "#4f8a6b",
|
|
2933
|
+
// sea-glass green
|
|
2934
|
+
blue: "#1f4e6b",
|
|
2935
|
+
// deep-sea navy
|
|
2936
|
+
purple: "#6a5a8c",
|
|
2937
|
+
// twilight harbor
|
|
2938
|
+
teal: "#3d8c8c",
|
|
2939
|
+
// sea-glass teal
|
|
2940
|
+
cyan: "#4f9bb5",
|
|
2941
|
+
// shallow water
|
|
2942
|
+
gray: "#8a8d86",
|
|
2943
|
+
// driftwood gray
|
|
2944
|
+
black: "#18313f",
|
|
2945
|
+
// navy ink
|
|
2946
|
+
white: "#e0e4e3"
|
|
2947
|
+
// deck panel
|
|
2948
|
+
}
|
|
2949
|
+
},
|
|
2950
|
+
dark: {
|
|
2951
|
+
bg: "#0f2230",
|
|
2952
|
+
// night-harbor deep sea
|
|
2953
|
+
surface: "#16303f",
|
|
2954
|
+
// raised hull
|
|
2955
|
+
overlay: "#1d3a4a",
|
|
2956
|
+
// popovers, dropdowns
|
|
2957
|
+
border: "#2c4856",
|
|
2958
|
+
// rigging line
|
|
2959
|
+
text: "#e6ebe8",
|
|
2960
|
+
// weathered white
|
|
2961
|
+
textMuted: "#9aaab0",
|
|
2962
|
+
// faded label
|
|
2963
|
+
textOnFillLight: "#f3f5f3",
|
|
2964
|
+
// weathered white
|
|
2965
|
+
textOnFillDark: "#0f2230",
|
|
2966
|
+
// deep sea
|
|
2967
|
+
primary: "#4f9bc4",
|
|
2968
|
+
// lifted sea blue
|
|
2969
|
+
secondary: "#c9a46a",
|
|
2970
|
+
// rope tan, lifted
|
|
2971
|
+
accent: "#d9b25a",
|
|
2972
|
+
// brass, lifted
|
|
2973
|
+
destructive: "#e06a5e",
|
|
2974
|
+
// signal red, lifted
|
|
2975
|
+
colors: {
|
|
2976
|
+
red: "#e06a5e",
|
|
2977
|
+
// signal-flag red
|
|
2978
|
+
orange: "#df9a52",
|
|
2979
|
+
// amber
|
|
2980
|
+
yellow: "#e0c662",
|
|
2981
|
+
// brass gold
|
|
2982
|
+
green: "#6fb58c",
|
|
2983
|
+
// sea-glass green
|
|
2984
|
+
blue: "#4f9bc4",
|
|
2985
|
+
// sea blue
|
|
2986
|
+
purple: "#9486bf",
|
|
2987
|
+
// twilight harbor
|
|
2988
|
+
teal: "#5cb0ac",
|
|
2989
|
+
// sea-glass teal
|
|
2990
|
+
cyan: "#62b4cf",
|
|
2991
|
+
// shallow water
|
|
2992
|
+
gray: "#9aa39c",
|
|
2993
|
+
// driftwood gray
|
|
2994
|
+
black: "#16303f",
|
|
2995
|
+
// raised hull
|
|
2996
|
+
white: "#e6ebe8"
|
|
2997
|
+
// weathered white
|
|
2998
|
+
}
|
|
2999
|
+
}
|
|
3000
|
+
};
|
|
3001
|
+
registerPalette(tidewaterPalette);
|
|
3002
|
+
}
|
|
3003
|
+
});
|
|
3004
|
+
|
|
2587
3005
|
// src/palettes/tokyo-night.ts
|
|
2588
3006
|
var tokyoNightPalette;
|
|
2589
3007
|
var init_tokyo_night = __esm({
|
|
@@ -2859,7 +3277,8 @@ var init_monokai = __esm({
|
|
|
2859
3277
|
// src/palettes/index.ts
|
|
2860
3278
|
var palettes_exports = {};
|
|
2861
3279
|
__export(palettes_exports, {
|
|
2862
|
-
|
|
3280
|
+
atlasPalette: () => atlasPalette,
|
|
3281
|
+
blueprintPalette: () => blueprintPalette,
|
|
2863
3282
|
catppuccinPalette: () => catppuccinPalette,
|
|
2864
3283
|
contrastText: () => contrastText,
|
|
2865
3284
|
draculaPalette: () => draculaPalette,
|
|
@@ -2880,7 +3299,9 @@ __export(palettes_exports, {
|
|
|
2880
3299
|
rosePinePalette: () => rosePinePalette,
|
|
2881
3300
|
shade: () => shade,
|
|
2882
3301
|
shapeFill: () => shapeFill,
|
|
3302
|
+
slatePalette: () => slatePalette,
|
|
2883
3303
|
solarizedPalette: () => solarizedPalette,
|
|
3304
|
+
tidewaterPalette: () => tidewaterPalette,
|
|
2884
3305
|
tint: () => tint,
|
|
2885
3306
|
tokyoNightPalette: () => tokyoNightPalette
|
|
2886
3307
|
});
|
|
@@ -2890,17 +3311,21 @@ var init_palettes = __esm({
|
|
|
2890
3311
|
"use strict";
|
|
2891
3312
|
init_registry();
|
|
2892
3313
|
init_color_utils();
|
|
2893
|
-
|
|
3314
|
+
init_atlas();
|
|
3315
|
+
init_blueprint();
|
|
2894
3316
|
init_catppuccin();
|
|
2895
3317
|
init_gruvbox();
|
|
2896
3318
|
init_nord();
|
|
2897
3319
|
init_one_dark();
|
|
2898
3320
|
init_rose_pine();
|
|
3321
|
+
init_slate();
|
|
2899
3322
|
init_solarized();
|
|
3323
|
+
init_tidewater();
|
|
2900
3324
|
init_tokyo_night();
|
|
2901
3325
|
init_dracula();
|
|
2902
3326
|
init_monokai();
|
|
2903
|
-
|
|
3327
|
+
init_atlas();
|
|
3328
|
+
init_blueprint();
|
|
2904
3329
|
init_catppuccin();
|
|
2905
3330
|
init_dracula();
|
|
2906
3331
|
init_gruvbox();
|
|
@@ -2908,9 +3333,15 @@ var init_palettes = __esm({
|
|
|
2908
3333
|
init_nord();
|
|
2909
3334
|
init_one_dark();
|
|
2910
3335
|
init_rose_pine();
|
|
3336
|
+
init_slate();
|
|
2911
3337
|
init_solarized();
|
|
3338
|
+
init_tidewater();
|
|
2912
3339
|
init_tokyo_night();
|
|
2913
3340
|
palettes = {
|
|
3341
|
+
atlas: atlasPalette,
|
|
3342
|
+
blueprint: blueprintPalette,
|
|
3343
|
+
slate: slatePalette,
|
|
3344
|
+
tidewater: tidewaterPalette,
|
|
2914
3345
|
nord: nordPalette,
|
|
2915
3346
|
catppuccin: catppuccinPalette,
|
|
2916
3347
|
solarized: solarizedPalette,
|
|
@@ -2919,8 +3350,7 @@ var init_palettes = __esm({
|
|
|
2919
3350
|
oneDark: oneDarkPalette,
|
|
2920
3351
|
rosePine: rosePinePalette,
|
|
2921
3352
|
dracula: draculaPalette,
|
|
2922
|
-
monokai: monokaiPalette
|
|
2923
|
-
bold: boldPalette
|
|
3353
|
+
monokai: monokaiPalette
|
|
2924
3354
|
};
|
|
2925
3355
|
}
|
|
2926
3356
|
});
|
|
@@ -3430,6 +3860,9 @@ function controlsGroupCapsuleWidth(toggles) {
|
|
|
3430
3860
|
}
|
|
3431
3861
|
return w;
|
|
3432
3862
|
}
|
|
3863
|
+
function isAppHostedControls(config, isExport) {
|
|
3864
|
+
return !isExport && config.controlsHost === "app" && !!config.controlsGroup && config.controlsGroup.toggles.length > 0;
|
|
3865
|
+
}
|
|
3433
3866
|
function buildControlsGroupLayout(config, state) {
|
|
3434
3867
|
const cg = config.controlsGroup;
|
|
3435
3868
|
if (!cg || cg.toggles.length === 0) return void 0;
|
|
@@ -3483,6 +3916,7 @@ function buildControlsGroupLayout(config, state) {
|
|
|
3483
3916
|
function computeLegendLayout(config, state, containerWidth) {
|
|
3484
3917
|
const { groups, controls: configControls, mode } = config;
|
|
3485
3918
|
const isExport = mode === "export";
|
|
3919
|
+
const gated = isAppHostedControls(config, isExport);
|
|
3486
3920
|
const activeGroupName = state.activeGroup?.toLowerCase() ?? null;
|
|
3487
3921
|
if (isExport && !activeGroupName) {
|
|
3488
3922
|
return {
|
|
@@ -3493,7 +3927,7 @@ function computeLegendLayout(config, state, containerWidth) {
|
|
|
3493
3927
|
pills: []
|
|
3494
3928
|
};
|
|
3495
3929
|
}
|
|
3496
|
-
const controlsGroupLayout = isExport ? void 0 : buildControlsGroupLayout(config, state);
|
|
3930
|
+
const controlsGroupLayout = isExport || gated ? void 0 : buildControlsGroupLayout(config, state);
|
|
3497
3931
|
const visibleGroups = config.showEmptyGroups ? groups : groups.filter((g) => g.entries.length > 0 || !!g.gradient);
|
|
3498
3932
|
if (visibleGroups.length === 0 && (!configControls || configControls.length === 0) && !controlsGroupLayout) {
|
|
3499
3933
|
return {
|
|
@@ -8325,8 +8759,8 @@ function computeScatterLabelGraphics(points, chartBounds, fontSize, symbolSize,
|
|
|
8325
8759
|
const pt = points[i];
|
|
8326
8760
|
const ptSize = pt.size ?? symbolSize;
|
|
8327
8761
|
const minGap = ptSize / 2 + 4;
|
|
8328
|
-
const
|
|
8329
|
-
const labelX = pt.px -
|
|
8762
|
+
const labelWidth2 = pt.name.length * fontSize * 0.6 + 8;
|
|
8763
|
+
const labelX = pt.px - labelWidth2 / 2;
|
|
8330
8764
|
let bestLabelY = 0;
|
|
8331
8765
|
let bestOffset = Infinity;
|
|
8332
8766
|
let placed = false;
|
|
@@ -8338,7 +8772,7 @@ function computeScatterLabelGraphics(points, chartBounds, fontSize, symbolSize,
|
|
|
8338
8772
|
const candidate = {
|
|
8339
8773
|
x: labelX,
|
|
8340
8774
|
y: labelY,
|
|
8341
|
-
w:
|
|
8775
|
+
w: labelWidth2,
|
|
8342
8776
|
h: labelHeight
|
|
8343
8777
|
};
|
|
8344
8778
|
let collision = false;
|
|
@@ -8380,7 +8814,7 @@ function computeScatterLabelGraphics(points, chartBounds, fontSize, symbolSize,
|
|
|
8380
8814
|
const labelRect = {
|
|
8381
8815
|
x: labelX,
|
|
8382
8816
|
y: bestLabelY,
|
|
8383
|
-
w:
|
|
8817
|
+
w: labelWidth2,
|
|
8384
8818
|
h: labelHeight
|
|
8385
8819
|
};
|
|
8386
8820
|
placedLabels.push(labelRect);
|
|
@@ -8416,7 +8850,7 @@ function computeScatterLabelGraphics(points, chartBounds, fontSize, symbolSize,
|
|
|
8416
8850
|
shape: {
|
|
8417
8851
|
x: labelX - bgPad,
|
|
8418
8852
|
y: bestLabelY - bgPad,
|
|
8419
|
-
width:
|
|
8853
|
+
width: labelWidth2 + bgPad * 2,
|
|
8420
8854
|
height: labelHeight + bgPad * 2
|
|
8421
8855
|
},
|
|
8422
8856
|
style: { fill: bg },
|
|
@@ -15856,10 +16290,6 @@ function parseMap(content) {
|
|
|
15856
16290
|
handleTag(trimmed, lineNumber);
|
|
15857
16291
|
continue;
|
|
15858
16292
|
}
|
|
15859
|
-
if ((firstWord === "muted" || firstWord === "natural") && trimmed === firstWord) {
|
|
15860
|
-
handleDirective(firstWord, "", lineNumber);
|
|
15861
|
-
continue;
|
|
15862
|
-
}
|
|
15863
16293
|
if (DIRECTIVE_SET.has(firstWord) && !trimmed.slice(firstWord.length).trimStart().startsWith(":")) {
|
|
15864
16294
|
handleDirective(
|
|
15865
16295
|
firstWord,
|
|
@@ -15906,24 +16336,6 @@ function parseMap(content) {
|
|
|
15906
16336
|
pushWarning(line12, `Duplicate directive "${key}" \u2014 last value wins.`);
|
|
15907
16337
|
};
|
|
15908
16338
|
switch (key) {
|
|
15909
|
-
case "region":
|
|
15910
|
-
dup(d.region);
|
|
15911
|
-
d.region = value;
|
|
15912
|
-
break;
|
|
15913
|
-
case "projection":
|
|
15914
|
-
dup(d.projection);
|
|
15915
|
-
if (value && ![
|
|
15916
|
-
"equirectangular",
|
|
15917
|
-
"natural-earth",
|
|
15918
|
-
"albers-usa",
|
|
15919
|
-
"mercator"
|
|
15920
|
-
].includes(value))
|
|
15921
|
-
pushWarning(
|
|
15922
|
-
line12,
|
|
15923
|
-
`Unknown projection "${value}" (expected equirectangular | natural-earth | albers-usa | mercator).`
|
|
15924
|
-
);
|
|
15925
|
-
d.projection = value;
|
|
15926
|
-
break;
|
|
15927
16339
|
case "region-metric": {
|
|
15928
16340
|
dup(d.regionMetric);
|
|
15929
16341
|
const { label: rmLabel, colorName: rmColor } = peelTrailingColorName(value);
|
|
@@ -15939,91 +16351,43 @@ function parseMap(content) {
|
|
|
15939
16351
|
dup(d.flowMetric);
|
|
15940
16352
|
d.flowMetric = value;
|
|
15941
16353
|
break;
|
|
15942
|
-
case "
|
|
15943
|
-
dup(d.
|
|
15944
|
-
|
|
15945
|
-
const s = parseScale(value, line12);
|
|
15946
|
-
if (s) d.scale = s;
|
|
15947
|
-
}
|
|
15948
|
-
break;
|
|
15949
|
-
case "region-labels":
|
|
15950
|
-
dup(d.regionLabels);
|
|
15951
|
-
if (value && !["full", "abbrev", "off"].includes(value))
|
|
15952
|
-
pushWarning(
|
|
15953
|
-
line12,
|
|
15954
|
-
`Unknown region-labels "${value}" (expected full | abbrev | off).`
|
|
15955
|
-
);
|
|
15956
|
-
d.regionLabels = value;
|
|
15957
|
-
break;
|
|
15958
|
-
case "poi-labels":
|
|
15959
|
-
dup(d.poiLabels);
|
|
15960
|
-
if (value && !["off", "auto", "all"].includes(value))
|
|
15961
|
-
pushWarning(
|
|
15962
|
-
line12,
|
|
15963
|
-
`Unknown poi-labels "${value}" (expected off | auto | all).`
|
|
15964
|
-
);
|
|
15965
|
-
d.poiLabels = value;
|
|
15966
|
-
break;
|
|
15967
|
-
case "default-country":
|
|
15968
|
-
dup(d.defaultCountry);
|
|
15969
|
-
d.defaultCountry = value;
|
|
15970
|
-
break;
|
|
15971
|
-
case "default-state":
|
|
15972
|
-
dup(d.defaultState);
|
|
15973
|
-
d.defaultState = value;
|
|
16354
|
+
case "locale":
|
|
16355
|
+
dup(d.locale);
|
|
16356
|
+
d.locale = value;
|
|
15974
16357
|
break;
|
|
15975
16358
|
case "active-tag":
|
|
15976
16359
|
dup(d.activeTag);
|
|
15977
16360
|
d.activeTag = value;
|
|
15978
16361
|
break;
|
|
16362
|
+
case "caption":
|
|
16363
|
+
dup(d.caption);
|
|
16364
|
+
d.caption = value;
|
|
16365
|
+
break;
|
|
16366
|
+
// ── Cosmetic `no-*` opt-outs: bare flags, idempotent (mirror `no-legend`,
|
|
16367
|
+
// no dup warning); each defaults the feature ON when absent. ──
|
|
15979
16368
|
case "no-legend":
|
|
15980
16369
|
d.noLegend = true;
|
|
15981
16370
|
break;
|
|
15982
|
-
case "no-
|
|
15983
|
-
d.
|
|
16371
|
+
case "no-coastline":
|
|
16372
|
+
d.noCoastline = true;
|
|
15984
16373
|
break;
|
|
15985
|
-
case "relief":
|
|
15986
|
-
d.
|
|
16374
|
+
case "no-relief":
|
|
16375
|
+
d.noRelief = true;
|
|
15987
16376
|
break;
|
|
15988
|
-
case "
|
|
15989
|
-
|
|
15990
|
-
if (d.basemapStyle !== void 0 && d.basemapStyle !== key)
|
|
15991
|
-
pushWarning(
|
|
15992
|
-
line12,
|
|
15993
|
-
`Conflicting basemap dress \u2014 "${d.basemapStyle}" then "${key}"; last wins.`
|
|
15994
|
-
);
|
|
15995
|
-
d.basemapStyle = key;
|
|
16377
|
+
case "no-context-labels":
|
|
16378
|
+
d.noContextLabels = true;
|
|
15996
16379
|
break;
|
|
15997
|
-
case "
|
|
15998
|
-
|
|
15999
|
-
d.subtitle = value;
|
|
16380
|
+
case "no-region-labels":
|
|
16381
|
+
d.noRegionLabels = true;
|
|
16000
16382
|
break;
|
|
16001
|
-
case "
|
|
16002
|
-
|
|
16003
|
-
|
|
16383
|
+
case "no-poi-labels":
|
|
16384
|
+
d.noPoiLabels = true;
|
|
16385
|
+
break;
|
|
16386
|
+
case "no-colorize":
|
|
16387
|
+
d.noColorize = true;
|
|
16004
16388
|
break;
|
|
16005
16389
|
}
|
|
16006
16390
|
}
|
|
16007
|
-
function parseScale(value, line12) {
|
|
16008
|
-
const toks = value.split(/\s+/).filter(Boolean);
|
|
16009
|
-
const min = Number(toks[0]);
|
|
16010
|
-
const max = Number(toks[1]);
|
|
16011
|
-
if (!Number.isFinite(min) || !Number.isFinite(max)) {
|
|
16012
|
-
pushError(line12, `scale requires numeric <min> <max> (got "${value}").`);
|
|
16013
|
-
return null;
|
|
16014
|
-
}
|
|
16015
|
-
const scale = { min, max };
|
|
16016
|
-
if (toks[2] === "center") {
|
|
16017
|
-
const c = Number(toks[3]);
|
|
16018
|
-
if (Number.isFinite(c)) scale.center = c;
|
|
16019
|
-
else
|
|
16020
|
-
pushError(
|
|
16021
|
-
line12,
|
|
16022
|
-
`scale center requires a number (got "${toks[3] ?? ""}").`
|
|
16023
|
-
);
|
|
16024
|
-
}
|
|
16025
|
-
return scale;
|
|
16026
|
-
}
|
|
16027
16391
|
function handleTag(trimmed, line12) {
|
|
16028
16392
|
const m = matchTagBlockHeading(trimmed);
|
|
16029
16393
|
if (!m) {
|
|
@@ -16223,13 +16587,15 @@ function parseMap(content) {
|
|
|
16223
16587
|
pushError(line12, `Edge has an empty endpoint: "${trimmed}".`);
|
|
16224
16588
|
continue;
|
|
16225
16589
|
}
|
|
16226
|
-
const
|
|
16590
|
+
const isLast = k === links.length - 1;
|
|
16591
|
+
const meta = isLast ? lastSplit.meta : {};
|
|
16592
|
+
const style = links[k].style === "arc" ? "arc" : "straight";
|
|
16227
16593
|
edges.push({
|
|
16228
16594
|
from,
|
|
16229
16595
|
to,
|
|
16230
16596
|
...links[k].label !== void 0 && { label: links[k].label },
|
|
16231
16597
|
directed: links[k].directed,
|
|
16232
|
-
style
|
|
16598
|
+
style,
|
|
16233
16599
|
meta,
|
|
16234
16600
|
lineNumber: line12
|
|
16235
16601
|
});
|
|
@@ -16315,22 +16681,19 @@ var init_parser12 = __esm({
|
|
|
16315
16681
|
LEG_ARROW_RE = /^(-[^>]*?->|->|~[^>]*?~>|~>|--)\s+(.+)$/;
|
|
16316
16682
|
AT_RE = /(^|[\s,])at\s*:/i;
|
|
16317
16683
|
DIRECTIVE_SET = /* @__PURE__ */ new Set([
|
|
16318
|
-
"region",
|
|
16319
|
-
"projection",
|
|
16320
16684
|
"region-metric",
|
|
16321
16685
|
"poi-metric",
|
|
16322
16686
|
"flow-metric",
|
|
16323
|
-
"
|
|
16324
|
-
"region-labels",
|
|
16325
|
-
"poi-labels",
|
|
16326
|
-
"default-country",
|
|
16327
|
-
"default-state",
|
|
16687
|
+
"locale",
|
|
16328
16688
|
"active-tag",
|
|
16689
|
+
"caption",
|
|
16329
16690
|
"no-legend",
|
|
16330
|
-
"no-
|
|
16331
|
-
"relief",
|
|
16332
|
-
"
|
|
16333
|
-
"
|
|
16691
|
+
"no-coastline",
|
|
16692
|
+
"no-relief",
|
|
16693
|
+
"no-context-labels",
|
|
16694
|
+
"no-region-labels",
|
|
16695
|
+
"no-poi-labels",
|
|
16696
|
+
"no-colorize"
|
|
16334
16697
|
]);
|
|
16335
16698
|
}
|
|
16336
16699
|
});
|
|
@@ -16508,6 +16871,21 @@ function parseBoxesAndLines(content) {
|
|
|
16508
16871
|
}
|
|
16509
16872
|
continue;
|
|
16510
16873
|
}
|
|
16874
|
+
if (!contentStarted) {
|
|
16875
|
+
const metricMatch = trimmed.match(/^box-metric\s+(.+)$/i);
|
|
16876
|
+
if (metricMatch) {
|
|
16877
|
+
const { label, colorName } = peelTrailingColorName(
|
|
16878
|
+
metricMatch[1].trim()
|
|
16879
|
+
);
|
|
16880
|
+
result.boxMetric = label;
|
|
16881
|
+
if (colorName !== void 0) result.boxMetricColor = colorName;
|
|
16882
|
+
continue;
|
|
16883
|
+
}
|
|
16884
|
+
if (/^show-values$/i.test(trimmed)) {
|
|
16885
|
+
result.showValues = true;
|
|
16886
|
+
continue;
|
|
16887
|
+
}
|
|
16888
|
+
}
|
|
16511
16889
|
if (!contentStarted) {
|
|
16512
16890
|
const optMatch = trimmed.match(OPTION_NOCOLON_RE);
|
|
16513
16891
|
if (optMatch) {
|
|
@@ -16886,6 +17264,19 @@ function parseNodeLine(trimmed, lineNum, metaAliasMap, diagnostics, nameAliasMap
|
|
|
16886
17264
|
description = [metadata["description"]];
|
|
16887
17265
|
delete metadata["description"];
|
|
16888
17266
|
}
|
|
17267
|
+
let value;
|
|
17268
|
+
if (metadata["value"] !== void 0) {
|
|
17269
|
+
const raw = metadata["value"];
|
|
17270
|
+
const num = Number(raw);
|
|
17271
|
+
if (Number.isFinite(num)) {
|
|
17272
|
+
value = num;
|
|
17273
|
+
} else {
|
|
17274
|
+
diagnostics.push(
|
|
17275
|
+
makeDgmoError(lineNum, `value must be a number (got "${raw}")`, "error")
|
|
17276
|
+
);
|
|
17277
|
+
}
|
|
17278
|
+
delete metadata["value"];
|
|
17279
|
+
}
|
|
16889
17280
|
if (split.alias) {
|
|
16890
17281
|
nameAliasMap?.set(normalizeName(split.alias), label);
|
|
16891
17282
|
}
|
|
@@ -16894,7 +17285,8 @@ function parseNodeLine(trimmed, lineNum, metaAliasMap, diagnostics, nameAliasMap
|
|
|
16894
17285
|
label,
|
|
16895
17286
|
lineNumber: lineNum,
|
|
16896
17287
|
metadata,
|
|
16897
|
-
...description !== void 0 && { description }
|
|
17288
|
+
...description !== void 0 && { description },
|
|
17289
|
+
...value !== void 0 && { value }
|
|
16898
17290
|
};
|
|
16899
17291
|
}
|
|
16900
17292
|
function splitTargetAndMeta(rest, metaAliasMap) {
|
|
@@ -24341,8 +24733,8 @@ function renderKanban(container, parsed, palette, isDark, options) {
|
|
|
24341
24733
|
let metaY = separatorY + sCardSeparatorGap + sCardMetaFontSize;
|
|
24342
24734
|
for (const meta of tagMeta) {
|
|
24343
24735
|
cg.append("text").attr("x", cx + sCardPaddingX).attr("y", metaY).attr("font-size", sCardMetaFontSize).attr("fill", onCardText).text(`${meta.label}: `);
|
|
24344
|
-
const
|
|
24345
|
-
cg.append("text").attr("x", cx + sCardPaddingX +
|
|
24736
|
+
const labelWidth2 = (meta.label.length + 2) * sCardMetaFontSize * 0.6;
|
|
24737
|
+
cg.append("text").attr("x", cx + sCardPaddingX + labelWidth2).attr("y", metaY).attr("font-size", sCardMetaFontSize).attr("fill", onCardText).text(meta.value);
|
|
24346
24738
|
metaY += sCardMetaLineHeight;
|
|
24347
24739
|
}
|
|
24348
24740
|
for (const detail of card.details) {
|
|
@@ -24686,8 +25078,8 @@ function renderSwimlaneCard(parent, cardLayout, tagGroups, activeTagGroup, palet
|
|
|
24686
25078
|
let metaY = separatorY + sCardSeparatorGap + sCardMetaFontSize;
|
|
24687
25079
|
for (const meta of tagMeta) {
|
|
24688
25080
|
cg.append("text").attr("x", cx + sCardPaddingX).attr("y", metaY).attr("font-size", sCardMetaFontSize).attr("fill", palette.textMuted).text(`${meta.label}: `);
|
|
24689
|
-
const
|
|
24690
|
-
cg.append("text").attr("x", cx + sCardPaddingX +
|
|
25081
|
+
const labelWidth2 = (meta.label.length + 2) * sCardMetaFontSize * 0.6;
|
|
25082
|
+
cg.append("text").attr("x", cx + sCardPaddingX + labelWidth2).attr("y", metaY).attr("font-size", sCardMetaFontSize).attr("fill", onCardText).text(meta.value);
|
|
24691
25083
|
metaY += sCardMetaLineHeight;
|
|
24692
25084
|
}
|
|
24693
25085
|
for (const detail of card.details) {
|
|
@@ -25522,8 +25914,8 @@ function classifyEREntities(tables, relationships) {
|
|
|
25522
25914
|
}
|
|
25523
25915
|
}
|
|
25524
25916
|
const mmParticipants = /* @__PURE__ */ new Set();
|
|
25525
|
-
for (const [id,
|
|
25526
|
-
if (
|
|
25917
|
+
for (const [id, neighbors2] of tableStarNeighbors) {
|
|
25918
|
+
if (neighbors2.size >= 2) mmParticipants.add(id);
|
|
25527
25919
|
}
|
|
25528
25920
|
const indegreeValues = Object.values(indegreeMap);
|
|
25529
25921
|
const mean = indegreeValues.reduce((a, b) => a + b, 0) / indegreeValues.length;
|
|
@@ -26104,7 +26496,18 @@ function fitLabelToHeader(label, nodeWidth, maxLines) {
|
|
|
26104
26496
|
const truncated = label.length > maxChars ? label.slice(0, maxChars - 1) + "\u2026" : label;
|
|
26105
26497
|
return { lines: [truncated], fontSize: MIN_NODE_FONT_SIZE };
|
|
26106
26498
|
}
|
|
26107
|
-
function nodeColors(node, tagGroups, activeGroupName, palette, isDark, solid) {
|
|
26499
|
+
function nodeColors(node, tagGroups, activeGroupName, palette, isDark, value, solid) {
|
|
26500
|
+
const neutralFill = mix(palette.bg, palette.text, isDark ? 90 : 95);
|
|
26501
|
+
if (value.active) {
|
|
26502
|
+
const fill3 = node.value !== void 0 ? value.fillForValue(node.value) : neutralFill;
|
|
26503
|
+
const stroke3 = value.hue;
|
|
26504
|
+
const text2 = contrastText(
|
|
26505
|
+
fill3,
|
|
26506
|
+
palette.textOnFillLight,
|
|
26507
|
+
palette.textOnFillDark
|
|
26508
|
+
);
|
|
26509
|
+
return { fill: fill3, stroke: stroke3, text: text2 };
|
|
26510
|
+
}
|
|
26108
26511
|
const tagColor = resolveTagColor(
|
|
26109
26512
|
node.metadata,
|
|
26110
26513
|
[...tagGroups],
|
|
@@ -26194,7 +26597,8 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26194
26597
|
controlsExpanded,
|
|
26195
26598
|
onToggleDescriptions,
|
|
26196
26599
|
onToggleControlsExpand,
|
|
26197
|
-
exportMode = false
|
|
26600
|
+
exportMode = false,
|
|
26601
|
+
controlsHost
|
|
26198
26602
|
} = options ?? {};
|
|
26199
26603
|
d3Selection6.select(container).selectAll(":not([data-d3-tooltip])").remove();
|
|
26200
26604
|
const width = exportDims?.width ?? container.clientWidth;
|
|
@@ -26212,21 +26616,65 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26212
26616
|
const sGroupLabelZone = sctx.structural(GROUP_LABEL_ZONE);
|
|
26213
26617
|
const sTitleFontSize = sctx.text(TITLE_FONT_SIZE);
|
|
26214
26618
|
const sTitleY = sctx.structural(TITLE_Y);
|
|
26215
|
-
const
|
|
26619
|
+
const nodeValues = parsed.nodes.filter((n) => n.value !== void 0).map((n) => n.value);
|
|
26620
|
+
const hasRamp = nodeValues.length > 0;
|
|
26621
|
+
const allNonNegative = hasRamp && nodeValues.every((v) => v >= 0);
|
|
26622
|
+
const rampMin = allNonNegative ? 0 : Math.min(...nodeValues);
|
|
26623
|
+
const rampMax = Math.max(...nodeValues);
|
|
26624
|
+
const rampHue = resolveColor(parsed.boxMetricColor ?? "", palette) ?? palette.primary;
|
|
26625
|
+
const rampBase = isDark ? mix(palette.surface, palette.text, 28) : palette.bg;
|
|
26626
|
+
const fillForValue = (v) => {
|
|
26627
|
+
const t = rampMax > rampMin ? (v - rampMin) / (rampMax - rampMin) : 1;
|
|
26628
|
+
const pct = RAMP_FLOOR + Math.max(0, Math.min(1, t)) * (100 - RAMP_FLOOR);
|
|
26629
|
+
return mix(rampHue, rampBase, pct);
|
|
26630
|
+
};
|
|
26631
|
+
const VALUE_NAME = hasRamp ? parsed.boxMetric?.trim() || "Value" : null;
|
|
26632
|
+
const matchColorGroup = (v) => {
|
|
26633
|
+
const lv = v.trim().toLowerCase();
|
|
26634
|
+
if (lv === "none") return null;
|
|
26635
|
+
const tg = parsed.tagGroups.find((g) => g.name.toLowerCase() === lv);
|
|
26636
|
+
if (tg) return tg.name;
|
|
26637
|
+
if (lv === VALUE_NAME?.toLowerCase()) return VALUE_NAME;
|
|
26638
|
+
return v;
|
|
26639
|
+
};
|
|
26640
|
+
const override = activeTagGroup;
|
|
26641
|
+
let activeGroup;
|
|
26642
|
+
if (override !== void 0) {
|
|
26643
|
+
activeGroup = override === null ? null : matchColorGroup(override);
|
|
26644
|
+
} else if (parsed.options["active-tag"] !== void 0) {
|
|
26645
|
+
activeGroup = matchColorGroup(parsed.options["active-tag"]);
|
|
26646
|
+
} else {
|
|
26647
|
+
activeGroup = VALUE_NAME ?? (parsed.tagGroups.length > 0 ? parsed.tagGroups[0].name : null);
|
|
26648
|
+
}
|
|
26649
|
+
const activeIsValue = VALUE_NAME !== null && activeGroup === VALUE_NAME;
|
|
26650
|
+
const valueGroup = VALUE_NAME !== null ? {
|
|
26651
|
+
name: VALUE_NAME,
|
|
26652
|
+
entries: [],
|
|
26653
|
+
gradient: {
|
|
26654
|
+
min: rampMin,
|
|
26655
|
+
max: rampMax,
|
|
26656
|
+
hue: rampHue,
|
|
26657
|
+
base: rampBase
|
|
26658
|
+
}
|
|
26659
|
+
} : null;
|
|
26660
|
+
const legendGroups = [
|
|
26661
|
+
...valueGroup ? [valueGroup] : [],
|
|
26662
|
+
...parsed.tagGroups
|
|
26663
|
+
];
|
|
26664
|
+
const reserveHasDescriptions = parsed.nodes.some(
|
|
26665
|
+
(n) => n.description && n.description.length > 0
|
|
26666
|
+
);
|
|
26667
|
+
const willRenderLegend = legendGroups.length > 0 || reserveHasDescriptions && controlsHost !== "app";
|
|
26668
|
+
const sLegendHeight = willRenderLegend ? sctx.structural(
|
|
26216
26669
|
getMaxLegendReservedHeight(
|
|
26217
26670
|
{
|
|
26218
|
-
groups:
|
|
26671
|
+
groups: legendGroups,
|
|
26219
26672
|
position: { placement: "top-center", titleRelation: "below-title" },
|
|
26220
26673
|
mode: exportMode ? "export" : "preview"
|
|
26221
26674
|
},
|
|
26222
26675
|
width
|
|
26223
26676
|
)
|
|
26224
|
-
);
|
|
26225
|
-
const activeGroup = resolveActiveTagGroup(
|
|
26226
|
-
parsed.tagGroups,
|
|
26227
|
-
parsed.options["active-tag"],
|
|
26228
|
-
activeTagGroup
|
|
26229
|
-
);
|
|
26677
|
+
) : 0;
|
|
26230
26678
|
const hidden = hiddenTagValues ?? parsed.initialHiddenTagValues;
|
|
26231
26679
|
const nodeMap = /* @__PURE__ */ new Map();
|
|
26232
26680
|
for (const node of parsed.nodes) nodeMap.set(node.label, node);
|
|
@@ -26237,7 +26685,7 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26237
26685
|
const hasAnyDescriptions = parsed.nodes.some(
|
|
26238
26686
|
(n) => n.description && n.description.length > 0
|
|
26239
26687
|
);
|
|
26240
|
-
const needsLegend =
|
|
26688
|
+
const needsLegend = legendGroups.length > 0 || hasAnyDescriptions && onToggleDescriptions;
|
|
26241
26689
|
const legendH = needsLegend ? sLegendHeight + 8 : 0;
|
|
26242
26690
|
const groupLabelsSet = new Set(layout.groups.map((g) => g.label));
|
|
26243
26691
|
let labelZoneExtension = 0;
|
|
@@ -26443,12 +26891,16 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26443
26891
|
activeGroup,
|
|
26444
26892
|
palette,
|
|
26445
26893
|
isDark,
|
|
26894
|
+
{ active: activeIsValue, hue: rampHue, fillForValue },
|
|
26446
26895
|
parsed.options["solid-fill"] === "on"
|
|
26447
26896
|
);
|
|
26448
26897
|
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);
|
|
26449
26898
|
for (const [key, val] of Object.entries(node.metadata)) {
|
|
26450
26899
|
nodeG.attr(`data-tag-${key.toLowerCase()}`, val.toLowerCase());
|
|
26451
26900
|
}
|
|
26901
|
+
if (node.value !== void 0) {
|
|
26902
|
+
nodeG.attr("data-value", node.value);
|
|
26903
|
+
}
|
|
26452
26904
|
if (onClickItem) {
|
|
26453
26905
|
nodeG.on("click", (event) => {
|
|
26454
26906
|
const target = event.target;
|
|
@@ -26532,14 +26984,30 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26532
26984
|
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]);
|
|
26533
26985
|
}
|
|
26534
26986
|
}
|
|
26987
|
+
if (parsed.showValues && node.value !== void 0) {
|
|
26988
|
+
const valueText = String(node.value);
|
|
26989
|
+
const descShown = !!(desc && desc.length > 0 && !hideDescriptions);
|
|
26990
|
+
if (descShown) {
|
|
26991
|
+
const padX = 6;
|
|
26992
|
+
const padY = 5;
|
|
26993
|
+
const bw = valueText.length * VALUE_FONT_SIZE * CHAR_WIDTH_RATIO2 + 8;
|
|
26994
|
+
const bh = VALUE_FONT_SIZE + 4;
|
|
26995
|
+
const bx = ln.width / 2 - bw - 4;
|
|
26996
|
+
const by = -ln.height / 2 + 4;
|
|
26997
|
+
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);
|
|
26998
|
+
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);
|
|
26999
|
+
} else {
|
|
27000
|
+
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);
|
|
27001
|
+
}
|
|
27002
|
+
}
|
|
26535
27003
|
}
|
|
26536
27004
|
const hasDescriptions = parsed.nodes.some(
|
|
26537
27005
|
(n) => n.description && n.description.length > 0
|
|
26538
27006
|
);
|
|
26539
|
-
const hasLegend =
|
|
27007
|
+
const hasLegend = legendGroups.length > 0 || hasDescriptions && controlsHost !== "app";
|
|
26540
27008
|
if (hasLegend) {
|
|
26541
27009
|
let controlsGroup;
|
|
26542
|
-
if (hasDescriptions && onToggleDescriptions) {
|
|
27010
|
+
if (hasDescriptions && (onToggleDescriptions || controlsHost === "app")) {
|
|
26543
27011
|
controlsGroup = {
|
|
26544
27012
|
toggles: [
|
|
26545
27013
|
{
|
|
@@ -26554,10 +27022,17 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26554
27022
|
};
|
|
26555
27023
|
}
|
|
26556
27024
|
const legendConfig = {
|
|
26557
|
-
groups:
|
|
27025
|
+
groups: legendGroups,
|
|
26558
27026
|
position: { placement: "top-center", titleRelation: "below-title" },
|
|
26559
27027
|
mode: exportMode ? "export" : "preview",
|
|
26560
|
-
|
|
27028
|
+
// Keep inactive sibling tag groups visible as collapsed pills so the user
|
|
27029
|
+
// can click one to flip the active colouring dimension (preview only —
|
|
27030
|
+
// export shows just the active group). Without this, declaring a second
|
|
27031
|
+
// tag group (e.g. Team) leaves it invisible whenever another group is
|
|
27032
|
+
// active. The app's BoxesAndLinesPreview already wires pill clicks.
|
|
27033
|
+
showInactivePills: true,
|
|
27034
|
+
...controlsGroup !== void 0 && { controlsGroup },
|
|
27035
|
+
...controlsHost !== void 0 && { controlsHost }
|
|
26561
27036
|
};
|
|
26562
27037
|
const legendState = {
|
|
26563
27038
|
activeGroup,
|
|
@@ -26602,7 +27077,7 @@ function renderBoxesAndLinesForExport(container, parsed, layout, palette, isDark
|
|
|
26602
27077
|
}
|
|
26603
27078
|
});
|
|
26604
27079
|
}
|
|
26605
|
-
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;
|
|
27080
|
+
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;
|
|
26606
27081
|
var init_renderer6 = __esm({
|
|
26607
27082
|
"src/boxes-and-lines/renderer.ts"() {
|
|
26608
27083
|
"use strict";
|
|
@@ -26613,6 +27088,7 @@ var init_renderer6 = __esm({
|
|
|
26613
27088
|
init_legend_layout();
|
|
26614
27089
|
init_title_constants();
|
|
26615
27090
|
init_color_utils();
|
|
27091
|
+
init_colors();
|
|
26616
27092
|
init_tag_groups();
|
|
26617
27093
|
init_inline_markdown();
|
|
26618
27094
|
init_wrapped_desc();
|
|
@@ -26635,6 +27111,8 @@ var init_renderer6 = __esm({
|
|
|
26635
27111
|
GROUP_RX = 8;
|
|
26636
27112
|
GROUP_LABEL_FONT_SIZE = 14;
|
|
26637
27113
|
GROUP_LABEL_ZONE = 32;
|
|
27114
|
+
RAMP_FLOOR = 15;
|
|
27115
|
+
VALUE_FONT_SIZE = 11;
|
|
26638
27116
|
lineGeneratorLR = d3Shape4.line().x((d) => d.x).y((d) => d.y).curve(d3Shape4.curveBasis);
|
|
26639
27117
|
lineGeneratorTB = d3Shape4.line().x((d) => d.x).y((d) => d.y).curve(d3Shape4.curveBasis);
|
|
26640
27118
|
}
|
|
@@ -27805,8 +28283,9 @@ function renderMindmap(container, parsed, layout, palette, isDark, onClickItem,
|
|
|
27805
28283
|
const containerHeight = exportDims?.height ?? (container.getBoundingClientRect().height || 600);
|
|
27806
28284
|
d3Selection7.select(container).selectAll("*").remove();
|
|
27807
28285
|
const svg = d3Selection7.select(container).append("svg").attr("width", containerWidth).attr("height", containerHeight).attr("viewBox", `0 0 ${containerWidth} ${containerHeight}`).attr("preserveAspectRatio", "xMidYMin meet").style("font-family", FONT_FAMILY);
|
|
28286
|
+
const appHosted = options?.controlsHost === "app";
|
|
27808
28287
|
const hasControls = !!options?.onToggleColorByDepth || !!options?.onToggleDescriptions;
|
|
27809
|
-
const hasLegend = parsed.tagGroups.length > 0 || hasControls;
|
|
28288
|
+
const hasLegend = parsed.tagGroups.length > 0 || hasControls && !appHosted;
|
|
27810
28289
|
const fixedLegend = !isExport && hasLegend;
|
|
27811
28290
|
const legendReserve = fixedLegend ? getMaxLegendReservedHeight(
|
|
27812
28291
|
{
|
|
@@ -27900,7 +28379,10 @@ function renderMindmap(container, parsed, layout, palette, isDark, onClickItem,
|
|
|
27900
28379
|
}),
|
|
27901
28380
|
position: { placement: "top-center", titleRelation: "below-title" },
|
|
27902
28381
|
mode: options?.exportMode ? "export" : "preview",
|
|
27903
|
-
...controlsToggles !== void 0 && { controlsGroup: controlsToggles }
|
|
28382
|
+
...controlsToggles !== void 0 && { controlsGroup: controlsToggles },
|
|
28383
|
+
...options?.controlsHost !== void 0 && {
|
|
28384
|
+
controlsHost: options.controlsHost
|
|
28385
|
+
}
|
|
27904
28386
|
};
|
|
27905
28387
|
const legendState = {
|
|
27906
28388
|
activeGroup: options?.colorByDepth ? null : activeTagGroup !== void 0 ? activeTagGroup : parsed.options["active-tag"] ?? null,
|
|
@@ -28344,8 +28826,8 @@ function computeFieldAlignX(children) {
|
|
|
28344
28826
|
for (const child of children) {
|
|
28345
28827
|
if (child.metadata["_labelField"] === "true" && child.children.length >= 2) {
|
|
28346
28828
|
const labelEl = child.children[0];
|
|
28347
|
-
const
|
|
28348
|
-
maxLabelWidth = Math.max(maxLabelWidth,
|
|
28829
|
+
const labelWidth2 = labelEl.label.length * CHAR_WIDTH5;
|
|
28830
|
+
maxLabelWidth = Math.max(maxLabelWidth, labelWidth2);
|
|
28349
28831
|
labelFieldCount++;
|
|
28350
28832
|
}
|
|
28351
28833
|
}
|
|
@@ -33309,7 +33791,7 @@ function hasRoles(node) {
|
|
|
33309
33791
|
function computeNodeWidth2(node, expanded, options) {
|
|
33310
33792
|
const badgeVal = node.computedConcurrentInvocations === 0 && node.computedInstances > 1 ? node.computedInstances : 0;
|
|
33311
33793
|
const badgeLen = badgeVal > 0 ? `${badgeVal}x`.length + 2 : 0;
|
|
33312
|
-
const
|
|
33794
|
+
const labelWidth2 = (node.label.length + badgeLen) * CHAR_WIDTH7 + PADDING_X3;
|
|
33313
33795
|
const allKeys = [];
|
|
33314
33796
|
if (node.computedRps > 0) allKeys.push("RPS");
|
|
33315
33797
|
if (expanded) {
|
|
@@ -33353,7 +33835,7 @@ function computeNodeWidth2(node, expanded, options) {
|
|
|
33353
33835
|
allKeys.push("overflow");
|
|
33354
33836
|
}
|
|
33355
33837
|
}
|
|
33356
|
-
if (allKeys.length === 0) return Math.max(MIN_NODE_WIDTH2,
|
|
33838
|
+
if (allKeys.length === 0) return Math.max(MIN_NODE_WIDTH2, labelWidth2);
|
|
33357
33839
|
const maxKeyLen = Math.max(...allKeys.map((k) => k.length));
|
|
33358
33840
|
let maxRowWidth = 0;
|
|
33359
33841
|
if (node.computedRps > 0) {
|
|
@@ -33441,7 +33923,7 @@ function computeNodeWidth2(node, expanded, options) {
|
|
|
33441
33923
|
truncated.length * META_CHAR_WIDTH3 + PADDING_X3
|
|
33442
33924
|
);
|
|
33443
33925
|
}
|
|
33444
|
-
return Math.max(MIN_NODE_WIDTH2,
|
|
33926
|
+
return Math.max(MIN_NODE_WIDTH2, labelWidth2, maxRowWidth + 20, descWidth);
|
|
33445
33927
|
}
|
|
33446
33928
|
function computeNodeHeight2(node, expanded, options) {
|
|
33447
33929
|
const propCount = countDisplayProps(node, expanded, options);
|
|
@@ -34990,8 +35472,9 @@ function computeInfraLegendGroups(nodes, tagGroups, palette, edges) {
|
|
|
34990
35472
|
}
|
|
34991
35473
|
return groups;
|
|
34992
35474
|
}
|
|
34993
|
-
function renderLegend3(rootSvg, legendGroups, totalWidth, legendY, palette, isDark, activeGroup, playback, exportMode = false) {
|
|
35475
|
+
function renderLegend3(rootSvg, legendGroups, totalWidth, legendY, palette, isDark, activeGroup, playback, exportMode = false, controlsHost) {
|
|
34994
35476
|
if (legendGroups.length === 0 && !playback) return;
|
|
35477
|
+
const appHostedPlayback = controlsHost === "app" && !!playback;
|
|
34995
35478
|
const legendG = rootSvg.append("g").attr("transform", `translate(0, ${legendY})`);
|
|
34996
35479
|
if (activeGroup) {
|
|
34997
35480
|
legendG.attr("data-legend-active", activeGroup.toLowerCase());
|
|
@@ -35000,14 +35483,29 @@ function renderLegend3(rootSvg, legendGroups, totalWidth, legendY, palette, isDa
|
|
|
35000
35483
|
name: g.name,
|
|
35001
35484
|
entries: g.entries.map((e) => ({ value: e.value, color: e.color }))
|
|
35002
35485
|
}));
|
|
35003
|
-
if (playback) {
|
|
35486
|
+
if (playback && !appHostedPlayback) {
|
|
35004
35487
|
allGroups.push({ name: "Playback", entries: [] });
|
|
35005
35488
|
}
|
|
35006
35489
|
const legendConfig = {
|
|
35007
35490
|
groups: allGroups,
|
|
35008
35491
|
position: { placement: "top-center", titleRelation: "below-title" },
|
|
35009
35492
|
mode: exportMode ? "export" : "preview",
|
|
35010
|
-
showEmptyGroups: true
|
|
35493
|
+
showEmptyGroups: true,
|
|
35494
|
+
...appHostedPlayback && {
|
|
35495
|
+
controlsHost: "app",
|
|
35496
|
+
controlsGroup: {
|
|
35497
|
+
toggles: [
|
|
35498
|
+
{
|
|
35499
|
+
id: "playback",
|
|
35500
|
+
type: "toggle",
|
|
35501
|
+
label: "Playback",
|
|
35502
|
+
active: true,
|
|
35503
|
+
onToggle: () => {
|
|
35504
|
+
}
|
|
35505
|
+
}
|
|
35506
|
+
]
|
|
35507
|
+
}
|
|
35508
|
+
}
|
|
35011
35509
|
};
|
|
35012
35510
|
const legendState = { activeGroup };
|
|
35013
35511
|
renderLegendD3(
|
|
@@ -35058,8 +35556,9 @@ function renderLegend3(rootSvg, legendGroups, totalWidth, legendY, palette, isDa
|
|
|
35058
35556
|
}
|
|
35059
35557
|
}
|
|
35060
35558
|
}
|
|
35061
|
-
function renderInfra(container, layout, palette, isDark, title, titleLineNumber, tagGroups, activeGroup, animate, playback, expandedNodeIds, exportMode, collapsedNodes) {
|
|
35559
|
+
function renderInfra(container, layout, palette, isDark, title, titleLineNumber, tagGroups, activeGroup, animate, playback, expandedNodeIds, exportMode, collapsedNodes, controlsHost) {
|
|
35062
35560
|
d3Selection11.select(container).selectAll(":not([data-d3-tooltip])").remove();
|
|
35561
|
+
const appHostedPlayback = controlsHost === "app" && !!playback;
|
|
35063
35562
|
const ctx = ScaleContext.identity();
|
|
35064
35563
|
const sc = buildScaledConstants(ctx);
|
|
35065
35564
|
const legendGroups = computeInfraLegendGroups(
|
|
@@ -35068,7 +35567,7 @@ function renderInfra(container, layout, palette, isDark, title, titleLineNumber,
|
|
|
35068
35567
|
palette,
|
|
35069
35568
|
layout.edges
|
|
35070
35569
|
);
|
|
35071
|
-
const hasLegend = legendGroups.length > 0 || !!playback;
|
|
35570
|
+
const hasLegend = legendGroups.length > 0 || !!playback && !appHostedPlayback;
|
|
35072
35571
|
const fixedLegend = !exportMode && hasLegend;
|
|
35073
35572
|
const legendDynamicH = hasLegend ? getMaxLegendReservedHeight(
|
|
35074
35573
|
{
|
|
@@ -35212,7 +35711,8 @@ function renderInfra(container, layout, palette, isDark, title, titleLineNumber,
|
|
|
35212
35711
|
isDark,
|
|
35213
35712
|
activeGroup ?? null,
|
|
35214
35713
|
playback ?? void 0,
|
|
35215
|
-
exportMode
|
|
35714
|
+
exportMode,
|
|
35715
|
+
controlsHost
|
|
35216
35716
|
);
|
|
35217
35717
|
legendSvg.selectAll(".infra-legend-group").style("pointer-events", "auto");
|
|
35218
35718
|
} else {
|
|
@@ -35225,7 +35725,8 @@ function renderInfra(container, layout, palette, isDark, title, titleLineNumber,
|
|
|
35225
35725
|
isDark,
|
|
35226
35726
|
activeGroup ?? null,
|
|
35227
35727
|
playback ?? void 0,
|
|
35228
|
-
exportMode
|
|
35728
|
+
exportMode,
|
|
35729
|
+
controlsHost
|
|
35229
35730
|
);
|
|
35230
35731
|
}
|
|
35231
35732
|
}
|
|
@@ -43083,6 +43584,9 @@ function renderTechRadar(container, parsed, palette, isDark, onClickItem, export
|
|
|
43083
43584
|
onToggle: (active) => options.onToggleListing(active)
|
|
43084
43585
|
}
|
|
43085
43586
|
]
|
|
43587
|
+
},
|
|
43588
|
+
...options.controlsHost !== void 0 && {
|
|
43589
|
+
controlsHost: options.controlsHost
|
|
43086
43590
|
}
|
|
43087
43591
|
};
|
|
43088
43592
|
const legendState = {
|
|
@@ -44906,7 +45410,7 @@ function computeCycleLayout(parsed, options) {
|
|
|
44906
45410
|
const circleNodes = parsed.options["circle-nodes"] === "true";
|
|
44907
45411
|
const nodeDims = parsed.nodes.map((node) => {
|
|
44908
45412
|
const hasDesc = !hideDescriptions && node.description.length > 0;
|
|
44909
|
-
const
|
|
45413
|
+
const labelWidth2 = Math.max(
|
|
44910
45414
|
MIN_NODE_WIDTH4,
|
|
44911
45415
|
node.label.length * LABEL_CHAR_W + NODE_PAD_X * 2
|
|
44912
45416
|
);
|
|
@@ -44915,12 +45419,12 @@ function computeCycleLayout(parsed, options) {
|
|
|
44915
45419
|
}
|
|
44916
45420
|
if (!hasDesc) {
|
|
44917
45421
|
return {
|
|
44918
|
-
width: Math.min(MAX_NODE_WIDTH3,
|
|
45422
|
+
width: Math.min(MAX_NODE_WIDTH3, labelWidth2),
|
|
44919
45423
|
height: PLAIN_NODE_HEIGHT,
|
|
44920
45424
|
wrappedDesc: []
|
|
44921
45425
|
};
|
|
44922
45426
|
}
|
|
44923
|
-
return chooseDescribedRectDims(node.description,
|
|
45427
|
+
return chooseDescribedRectDims(node.description, labelWidth2);
|
|
44924
45428
|
});
|
|
44925
45429
|
if (circleNodes) {
|
|
44926
45430
|
const maxDiam = Math.max(...nodeDims.map((d) => d.width));
|
|
@@ -45116,10 +45620,10 @@ function computeCycleLayout(parsed, options) {
|
|
|
45116
45620
|
scale
|
|
45117
45621
|
};
|
|
45118
45622
|
}
|
|
45119
|
-
function chooseDescribedRectDims(description,
|
|
45623
|
+
function chooseDescribedRectDims(description, labelWidth2) {
|
|
45120
45624
|
const minW = Math.min(
|
|
45121
45625
|
MAX_NODE_WIDTH3,
|
|
45122
|
-
Math.max(MIN_NODE_WIDTH4,
|
|
45626
|
+
Math.max(MIN_NODE_WIDTH4, labelWidth2, DESC_MIN_WIDTH)
|
|
45123
45627
|
);
|
|
45124
45628
|
let best = null;
|
|
45125
45629
|
let bestScore = Infinity;
|
|
@@ -45547,7 +46051,8 @@ function renderCycle(container, parsed, palette, isDark, onClickItem, exportDims
|
|
|
45547
46051
|
const hideDescriptions = (renderOptions?.hideDescriptions ?? false) || parsed.options["no-descriptions"] === "true" || viewState?.hd === true;
|
|
45548
46052
|
const showDescriptions = !hideDescriptions;
|
|
45549
46053
|
const hasDescriptions = parsed.nodes.some((n) => n.description.length > 0) || parsed.edges.some((e) => e.description.length > 0);
|
|
45550
|
-
const
|
|
46054
|
+
const appHostedControls = renderOptions?.controlsHost === "app";
|
|
46055
|
+
const hasLegend = !appHostedControls && hasDescriptions && !!renderOptions?.onToggleDescriptions;
|
|
45551
46056
|
const showTitle = !!parsed.title && parsed.options["no-title"] !== "on";
|
|
45552
46057
|
const legendOffset = hasLegend ? sLegendHeight : 0;
|
|
45553
46058
|
const layoutHeight = height - (showTitle ? sTitleAreaHeight : 0) - legendOffset;
|
|
@@ -45584,7 +46089,10 @@ function renderCycle(container, parsed, palette, isDark, onClickItem, exportDims
|
|
|
45584
46089
|
groups: [],
|
|
45585
46090
|
position: { placement: "top-center", titleRelation: "below-title" },
|
|
45586
46091
|
mode: renderOptions?.exportMode ? "export" : "preview",
|
|
45587
|
-
controlsGroup
|
|
46092
|
+
controlsGroup,
|
|
46093
|
+
...renderOptions?.controlsHost !== void 0 && {
|
|
46094
|
+
controlsHost: renderOptions.controlsHost
|
|
46095
|
+
}
|
|
45588
46096
|
};
|
|
45589
46097
|
const legendState = {
|
|
45590
46098
|
activeGroup: null,
|
|
@@ -45855,6 +46363,29 @@ function featureIndex(topo) {
|
|
|
45855
46363
|
}
|
|
45856
46364
|
return idx;
|
|
45857
46365
|
}
|
|
46366
|
+
function buildAdjacency(topo) {
|
|
46367
|
+
const cached = adjacencyCache.get(topo);
|
|
46368
|
+
if (cached) return cached;
|
|
46369
|
+
const geometries = geomObject(topo).geometries;
|
|
46370
|
+
const nb = (0, import_topojson_client.neighbors)(geometries);
|
|
46371
|
+
const sets = /* @__PURE__ */ new Map();
|
|
46372
|
+
geometries.forEach((g, i) => {
|
|
46373
|
+
if (!g.type || g.type === "null") return;
|
|
46374
|
+
let set = sets.get(g.id);
|
|
46375
|
+
if (!set) {
|
|
46376
|
+
set = /* @__PURE__ */ new Set();
|
|
46377
|
+
sets.set(g.id, set);
|
|
46378
|
+
}
|
|
46379
|
+
for (const j of nb[i] ?? []) {
|
|
46380
|
+
const nid = geometries[j]?.id;
|
|
46381
|
+
if (nid && nid !== g.id) set.add(nid);
|
|
46382
|
+
}
|
|
46383
|
+
});
|
|
46384
|
+
const out = /* @__PURE__ */ new Map();
|
|
46385
|
+
for (const [iso, set] of sets) out.set(iso, [...set].sort());
|
|
46386
|
+
adjacencyCache.set(topo, out);
|
|
46387
|
+
return out;
|
|
46388
|
+
}
|
|
45858
46389
|
function decodeFeatures(topo) {
|
|
45859
46390
|
return geomObject(topo).geometries.map((g) => {
|
|
45860
46391
|
const f = (0, import_topojson_client.feature)(topo, g);
|
|
@@ -46050,13 +46581,14 @@ function unionLongitudes(lons) {
|
|
|
46050
46581
|
}
|
|
46051
46582
|
return { west: pts[gapIdx], east: pts[gapIdx - 1] + 360 };
|
|
46052
46583
|
}
|
|
46053
|
-
var import_topojson_client, import_d3_geo, fold, EDGE_EPS, DETACH_GAP_DEG, DETACH_AREA_FRAC;
|
|
46584
|
+
var import_topojson_client, import_d3_geo, fold, adjacencyCache, EDGE_EPS, DETACH_GAP_DEG, DETACH_AREA_FRAC;
|
|
46054
46585
|
var init_geo = __esm({
|
|
46055
46586
|
"src/map/geo.ts"() {
|
|
46056
46587
|
"use strict";
|
|
46057
46588
|
import_topojson_client = require("topojson-client");
|
|
46058
46589
|
import_d3_geo = require("d3-geo");
|
|
46059
46590
|
fold = (s) => s.normalize("NFD").replace(/\p{Diacritic}/gu, "").toLowerCase().trim();
|
|
46591
|
+
adjacencyCache = /* @__PURE__ */ new WeakMap();
|
|
46060
46592
|
EDGE_EPS = 1e-9;
|
|
46061
46593
|
DETACH_GAP_DEG = 10;
|
|
46062
46594
|
DETACH_AREA_FRAC = 0.25;
|
|
@@ -46077,6 +46609,12 @@ function looksUS(lat, lon) {
|
|
|
46077
46609
|
if (lat < 15 || lat > 72) return false;
|
|
46078
46610
|
return lon >= -180 && lon <= -64 || lon >= 172;
|
|
46079
46611
|
}
|
|
46612
|
+
function looksNorthAmericaNeighbor(lat, lon) {
|
|
46613
|
+
return lat >= 14 && lat <= 72 && lon >= -141 && lon <= -52;
|
|
46614
|
+
}
|
|
46615
|
+
function isWholeSphere(bb) {
|
|
46616
|
+
return bb[0][0] <= -179 && bb[1][0] >= 179 && bb[0][1] <= -89 && bb[1][1] >= 89;
|
|
46617
|
+
}
|
|
46080
46618
|
function resolveMap(parsed, data) {
|
|
46081
46619
|
const diagnostics = [...parsed.diagnostics];
|
|
46082
46620
|
const err = (line12, message, code) => {
|
|
@@ -46087,9 +46625,6 @@ function resolveMap(parsed, data) {
|
|
|
46087
46625
|
};
|
|
46088
46626
|
const result = {
|
|
46089
46627
|
title: parsed.title,
|
|
46090
|
-
...parsed.directives.subtitle !== void 0 && {
|
|
46091
|
-
subtitle: parsed.directives.subtitle
|
|
46092
|
-
},
|
|
46093
46628
|
...parsed.directives.caption !== void 0 && {
|
|
46094
46629
|
caption: parsed.directives.caption
|
|
46095
46630
|
},
|
|
@@ -46099,7 +46634,7 @@ function resolveMap(parsed, data) {
|
|
|
46099
46634
|
// renderer's job (step 4) — the resolver only carries `tags` + `tagGroups`
|
|
46100
46635
|
// through; it never resolves a tag value to a palette color (#10).
|
|
46101
46636
|
directives: { ...parsed.directives },
|
|
46102
|
-
basemaps: { world: "
|
|
46637
|
+
basemaps: { world: "detail", subdivisions: [] },
|
|
46103
46638
|
regions: [],
|
|
46104
46639
|
pois: [],
|
|
46105
46640
|
edges: [],
|
|
@@ -46108,7 +46643,8 @@ function resolveMap(parsed, data) {
|
|
|
46108
46643
|
[-180, -85],
|
|
46109
46644
|
[180, 85]
|
|
46110
46645
|
],
|
|
46111
|
-
projection: "
|
|
46646
|
+
projection: "equirectangular",
|
|
46647
|
+
poiFrameContainers: [],
|
|
46112
46648
|
diagnostics,
|
|
46113
46649
|
error: parsed.error
|
|
46114
46650
|
};
|
|
@@ -46118,7 +46654,10 @@ function resolveMap(parsed, data) {
|
|
|
46118
46654
|
...[...countryIndex.values()].map((v) => v.name),
|
|
46119
46655
|
...[...usStateIndex.values()].map((v) => v.name)
|
|
46120
46656
|
];
|
|
46121
|
-
const
|
|
46657
|
+
const localeRaw = parsed.directives.locale?.toUpperCase();
|
|
46658
|
+
const localeCountry = localeRaw ? localeRaw.split("-")[0] : void 0;
|
|
46659
|
+
const localeSubdivision = localeRaw && /^[A-Z]{2}-/.test(localeRaw) ? localeRaw : void 0;
|
|
46660
|
+
const usScoped = localeCountry === "US" || parsed.regions.some((r) => {
|
|
46122
46661
|
const f = fold(r.name);
|
|
46123
46662
|
return usStateIndex.has(f) && !countryIndex.has(f);
|
|
46124
46663
|
}) || parsed.regions.some(
|
|
@@ -46269,7 +46808,7 @@ function resolveMap(parsed, data) {
|
|
|
46269
46808
|
if (!scope)
|
|
46270
46809
|
warn(
|
|
46271
46810
|
line12,
|
|
46272
|
-
`"${name}" is ambiguous \u2014 resolved to the most-populous match.`,
|
|
46811
|
+
`"${name}" is ambiguous \u2014 resolved to the most-populous match. Set a default with \`locale <ISO>\` (e.g. \`locale US\` / \`locale US-GA\`) to steer it.`,
|
|
46273
46812
|
"W_MAP_AMBIGUOUS_NAME"
|
|
46274
46813
|
);
|
|
46275
46814
|
}
|
|
@@ -46282,17 +46821,21 @@ function resolveMap(parsed, data) {
|
|
|
46282
46821
|
return fold(pos.name);
|
|
46283
46822
|
};
|
|
46284
46823
|
const poiCountries = [];
|
|
46285
|
-
let
|
|
46824
|
+
let anyUsPoi = false;
|
|
46825
|
+
let anyNonNaPoi = false;
|
|
46286
46826
|
const noteCountry = (iso) => {
|
|
46287
46827
|
if (iso) {
|
|
46288
46828
|
poiCountries.push(iso);
|
|
46289
|
-
if (iso
|
|
46829
|
+
if (iso === "US") anyUsPoi = true;
|
|
46830
|
+
if (iso !== "US" && iso !== "CA" && iso !== "MX") anyNonNaPoi = true;
|
|
46290
46831
|
}
|
|
46291
46832
|
};
|
|
46292
46833
|
const deferred = [];
|
|
46293
46834
|
for (const p of parsed.pois) {
|
|
46294
46835
|
if (p.pos.kind === "coords") {
|
|
46295
|
-
if (
|
|
46836
|
+
if (looksUS(p.pos.lat, p.pos.lon)) anyUsPoi = true;
|
|
46837
|
+
else if (!looksNorthAmericaNeighbor(p.pos.lat, p.pos.lon))
|
|
46838
|
+
anyNonNaPoi = true;
|
|
46296
46839
|
addResolvedPoi(p.pos.lat, p.pos.lon, p);
|
|
46297
46840
|
continue;
|
|
46298
46841
|
}
|
|
@@ -46310,14 +46853,15 @@ function resolveMap(parsed, data) {
|
|
|
46310
46853
|
deferred.push(p);
|
|
46311
46854
|
}
|
|
46312
46855
|
}
|
|
46313
|
-
const inferredCountry =
|
|
46856
|
+
const inferredCountry = localeCountry ?? mostCommonCountry(regions, poiCountries) ?? void 0;
|
|
46857
|
+
const inferredScope = localeSubdivision ?? inferredCountry;
|
|
46314
46858
|
for (const p of deferred) {
|
|
46315
46859
|
if (p.pos.kind !== "name") continue;
|
|
46316
46860
|
const got = lookupName(
|
|
46317
46861
|
p.pos.name,
|
|
46318
46862
|
p.pos.scope,
|
|
46319
46863
|
p.lineNumber,
|
|
46320
|
-
|
|
46864
|
+
inferredScope,
|
|
46321
46865
|
true
|
|
46322
46866
|
);
|
|
46323
46867
|
if (got.kind === "ok") {
|
|
@@ -46387,7 +46931,8 @@ function resolveMap(parsed, data) {
|
|
|
46387
46931
|
const meta = sizeValue !== void 0 ? { value: sizeValue } : {};
|
|
46388
46932
|
if (pos.kind === "coords") {
|
|
46389
46933
|
const id = alias ? fold(alias) : `@${pos.lat},${pos.lon}`;
|
|
46390
|
-
if (
|
|
46934
|
+
if (looksUS(pos.lat, pos.lon)) anyUsPoi = true;
|
|
46935
|
+
else if (!looksNorthAmericaNeighbor(pos.lat, pos.lon)) anyNonNaPoi = true;
|
|
46391
46936
|
if (!registry.has(id)) {
|
|
46392
46937
|
registerPoi(
|
|
46393
46938
|
id,
|
|
@@ -46410,7 +46955,7 @@ function resolveMap(parsed, data) {
|
|
|
46410
46955
|
if (registry.has(f)) return f;
|
|
46411
46956
|
const aliased = declaredByName.get(f);
|
|
46412
46957
|
if (aliased) return aliased;
|
|
46413
|
-
const got = lookupName(pos.name, pos.scope, line12,
|
|
46958
|
+
const got = lookupName(pos.name, pos.scope, line12, inferredScope, true);
|
|
46414
46959
|
if (got.kind !== "ok") return null;
|
|
46415
46960
|
noteCountry(got.iso);
|
|
46416
46961
|
registerPoi(
|
|
@@ -46467,9 +47012,12 @@ function resolveMap(parsed, data) {
|
|
|
46467
47012
|
}
|
|
46468
47013
|
routes.push({ stopIds, legs, lineNumber: rt.lineNumber });
|
|
46469
47014
|
}
|
|
47015
|
+
const hasUsContent = usSubdivisionReferenced || anyUsPoi || localeCountry === "US";
|
|
47016
|
+
const usOriented = !anyNonNaPoi && !regions.some(
|
|
47017
|
+
(r) => r.layer === "country" && !["US", "CA", "MX"].includes(r.iso)
|
|
47018
|
+
) && hasUsContent;
|
|
46470
47019
|
const subdivisions = [];
|
|
46471
|
-
if (usSubdivisionReferenced ||
|
|
46472
|
-
subdivisions.push("us-states");
|
|
47020
|
+
if (usSubdivisionReferenced || usOriented) subdivisions.push("us-states");
|
|
46473
47021
|
const regionBoxes = [];
|
|
46474
47022
|
for (const ref of referencedRegionIds) {
|
|
46475
47023
|
const bb = featureBbox(data.usStates, ref.id);
|
|
@@ -46487,17 +47035,51 @@ function resolveMap(parsed, data) {
|
|
|
46487
47035
|
[-180, -85],
|
|
46488
47036
|
[180, 85]
|
|
46489
47037
|
];
|
|
46490
|
-
|
|
47038
|
+
const basePad = regions.length > 0 ? REGION_PAD_FRACTION : PAD_FRACTION;
|
|
47039
|
+
let extent2 = unioned ? pad(unioned, basePad) : DEFAULT_EXTENT;
|
|
47040
|
+
const isPoiOnly = pois.length > 0 && regions.length === 0;
|
|
47041
|
+
const containerRegionIds = [];
|
|
47042
|
+
if (isPoiOnly) {
|
|
47043
|
+
const countries = decodeFeatures(data.worldDetail);
|
|
47044
|
+
const states = decodeFeatures(data.usStates);
|
|
47045
|
+
const seen = /* @__PURE__ */ new Set();
|
|
47046
|
+
const containerBoxes = [];
|
|
47047
|
+
for (const p of pois) {
|
|
47048
|
+
const { country, state } = regionAt([p.lon, p.lat], countries, states);
|
|
47049
|
+
const id = state?.iso ?? country?.iso;
|
|
47050
|
+
if (!id || seen.has(id)) continue;
|
|
47051
|
+
seen.add(id);
|
|
47052
|
+
containerRegionIds.push(id);
|
|
47053
|
+
const bb = state ? featureBbox(data.usStates, id) : featureBboxPrimary(data.worldCoarse, id);
|
|
47054
|
+
if (bb && !isWholeSphere(bb)) containerBoxes.push(bb);
|
|
47055
|
+
}
|
|
47056
|
+
const containerUnion = unionExtent(containerBoxes, points);
|
|
47057
|
+
if (containerUnion) extent2 = pad(containerUnion, PAD_FRACTION);
|
|
47058
|
+
}
|
|
47059
|
+
if (isPoiOnly) {
|
|
47060
|
+
const cx = (extent2[0][0] + extent2[1][0]) / 2;
|
|
47061
|
+
const cy = (extent2[0][1] + extent2[1][1]) / 2;
|
|
47062
|
+
const lon = extent2[1][0] - extent2[0][0];
|
|
47063
|
+
const lat = extent2[1][1] - extent2[0][1];
|
|
47064
|
+
const longer = Math.max(lon, lat);
|
|
47065
|
+
if (longer > 0 && longer < POI_ZOOM_FLOOR_DEG) {
|
|
47066
|
+
const k = POI_ZOOM_FLOOR_DEG / longer;
|
|
47067
|
+
const halfLon = lon * k / 2;
|
|
47068
|
+
const halfLat = lat * k / 2;
|
|
47069
|
+
extent2 = [
|
|
47070
|
+
[cx - halfLon, cy - halfLat],
|
|
47071
|
+
[cx + halfLon, cy + halfLat]
|
|
47072
|
+
];
|
|
47073
|
+
}
|
|
47074
|
+
}
|
|
46491
47075
|
const lonSpan = extent2[1][0] - extent2[0][0];
|
|
46492
47076
|
const latSpan = extent2[1][1] - extent2[0][1];
|
|
46493
47077
|
const span = Math.max(lonSpan, latSpan);
|
|
46494
47078
|
const maxAbsLat = Math.max(Math.abs(extent2[0][1]), Math.abs(extent2[1][1]));
|
|
46495
|
-
const usDominant = (subdivisions.includes("us-states") || regions.some((r) => r.layer === "us-state")) && !regions.some((r) => r.layer === "country" && r.iso !== "US") && !anyNonUsPoi;
|
|
46496
47079
|
let projection;
|
|
46497
|
-
|
|
46498
|
-
|
|
46499
|
-
|
|
46500
|
-
} else if (usDominant) {
|
|
47080
|
+
if (isPoiOnly && usOriented && lonSpan < US_NATIONAL_LON_SPAN) {
|
|
47081
|
+
projection = "mercator";
|
|
47082
|
+
} else if (usOriented) {
|
|
46501
47083
|
projection = "albers-usa";
|
|
46502
47084
|
} else if (span > WORLD_SPAN || maxAbsLat > MERCATOR_MAX_LAT) {
|
|
46503
47085
|
projection = "equirectangular";
|
|
@@ -46515,11 +47097,20 @@ function resolveMap(parsed, data) {
|
|
|
46515
47097
|
result.edges = edges;
|
|
46516
47098
|
result.routes = routes;
|
|
46517
47099
|
result.basemaps = {
|
|
46518
|
-
|
|
47100
|
+
// Tier is intentionally pinned to detail (50m) at ALL scales. Diagrammo maps
|
|
47101
|
+
// are presentational (palette tints, relief hachures, POI hubs), not
|
|
47102
|
+
// survey-grade — recognizability > generalization: 110m coarse drops the
|
|
47103
|
+
// Italian boot to a stump at world scale. `WORLD_SPAN` lives on only for the
|
|
47104
|
+
// projection decision (the `usOriented`/`span > WORLD_SPAN` chain above); it
|
|
47105
|
+
// no longer gates basemap resolution.
|
|
47106
|
+
// `worldCoarse` is still loaded — it's the authoritative name/bbox index
|
|
47107
|
+
// (featureIndex, featureBboxPrimary), not dead code.
|
|
47108
|
+
world: "detail",
|
|
46519
47109
|
subdivisions
|
|
46520
47110
|
};
|
|
46521
47111
|
result.extent = extent2;
|
|
46522
47112
|
result.projection = projection;
|
|
47113
|
+
result.poiFrameContainers = containerRegionIds;
|
|
46523
47114
|
result.error = parsed.error ?? firstError(diagnostics);
|
|
46524
47115
|
return result;
|
|
46525
47116
|
}
|
|
@@ -46556,7 +47147,7 @@ function firstError(diags) {
|
|
|
46556
47147
|
const e = diags.find((d) => d.severity === "error");
|
|
46557
47148
|
return e ? formatDgmoError(e) : null;
|
|
46558
47149
|
}
|
|
46559
|
-
var WORLD_SPAN, MERCATOR_MAX_LAT, PAD_FRACTION, WORLD_LAT_SOUTH, WORLD_LAT_NORTH, REGION_ALIASES, US_STATE_POSTAL;
|
|
47150
|
+
var WORLD_SPAN, MERCATOR_MAX_LAT, PAD_FRACTION, REGION_PAD_FRACTION, WORLD_LAT_SOUTH, WORLD_LAT_NORTH, POI_ZOOM_FLOOR_DEG, US_NATIONAL_LON_SPAN, REGION_ALIASES, US_STATE_POSTAL;
|
|
46560
47151
|
var init_resolver2 = __esm({
|
|
46561
47152
|
"src/map/resolver.ts"() {
|
|
46562
47153
|
"use strict";
|
|
@@ -46565,8 +47156,11 @@ var init_resolver2 = __esm({
|
|
|
46565
47156
|
WORLD_SPAN = 90;
|
|
46566
47157
|
MERCATOR_MAX_LAT = 80;
|
|
46567
47158
|
PAD_FRACTION = 0.05;
|
|
47159
|
+
REGION_PAD_FRACTION = 0.12;
|
|
46568
47160
|
WORLD_LAT_SOUTH = -58;
|
|
46569
47161
|
WORLD_LAT_NORTH = 78;
|
|
47162
|
+
POI_ZOOM_FLOOR_DEG = 7;
|
|
47163
|
+
US_NATIONAL_LON_SPAN = 48;
|
|
46570
47164
|
REGION_ALIASES = {
|
|
46571
47165
|
// Common everyday names → the Natural-Earth display name actually shipped.
|
|
46572
47166
|
"united states": "united states of america",
|
|
@@ -46644,17 +47238,305 @@ var init_resolver2 = __esm({
|
|
|
46644
47238
|
}
|
|
46645
47239
|
});
|
|
46646
47240
|
|
|
47241
|
+
// src/map/colorize.ts
|
|
47242
|
+
function assignColors(isos, adjacency) {
|
|
47243
|
+
const sorted = [...isos].sort();
|
|
47244
|
+
const byIso = /* @__PURE__ */ new Map();
|
|
47245
|
+
let maxIndex = -1;
|
|
47246
|
+
for (const iso of sorted) {
|
|
47247
|
+
const taken = /* @__PURE__ */ new Set();
|
|
47248
|
+
for (const n of adjacency.get(iso) ?? []) {
|
|
47249
|
+
const c = byIso.get(n);
|
|
47250
|
+
if (c !== void 0) taken.add(c);
|
|
47251
|
+
}
|
|
47252
|
+
let h = 0;
|
|
47253
|
+
while (taken.has(h)) h++;
|
|
47254
|
+
byIso.set(iso, h);
|
|
47255
|
+
if (h > maxIndex) maxIndex = h;
|
|
47256
|
+
}
|
|
47257
|
+
return { byIso, huesNeeded: maxIndex + 1 };
|
|
47258
|
+
}
|
|
47259
|
+
var init_colorize = __esm({
|
|
47260
|
+
"src/map/colorize.ts"() {
|
|
47261
|
+
"use strict";
|
|
47262
|
+
}
|
|
47263
|
+
});
|
|
47264
|
+
|
|
47265
|
+
// src/map/context-labels.ts
|
|
47266
|
+
function tierBand(maxSpanDeg) {
|
|
47267
|
+
if (maxSpanDeg >= 90) return "world";
|
|
47268
|
+
if (maxSpanDeg >= 20) return "continental";
|
|
47269
|
+
if (maxSpanDeg >= 5) return "regional";
|
|
47270
|
+
return "local";
|
|
47271
|
+
}
|
|
47272
|
+
function labelBudget(width, height, band) {
|
|
47273
|
+
const bandCap = {
|
|
47274
|
+
world: 6,
|
|
47275
|
+
continental: 5,
|
|
47276
|
+
regional: 4,
|
|
47277
|
+
local: 3
|
|
47278
|
+
};
|
|
47279
|
+
const area2 = Math.floor(Math.sqrt(Math.max(0, width * height)) / 150);
|
|
47280
|
+
return Math.max(0, Math.min(area2, bandCap[band]));
|
|
47281
|
+
}
|
|
47282
|
+
function waterEligible(tier, kind, band) {
|
|
47283
|
+
switch (band) {
|
|
47284
|
+
case "world":
|
|
47285
|
+
return tier <= 1 && (kind === "ocean" || kind === "sea");
|
|
47286
|
+
case "continental":
|
|
47287
|
+
return tier <= 2;
|
|
47288
|
+
case "regional":
|
|
47289
|
+
return tier <= 3;
|
|
47290
|
+
case "local":
|
|
47291
|
+
return tier <= 4;
|
|
47292
|
+
}
|
|
47293
|
+
}
|
|
47294
|
+
function insideViewport(p, width, height) {
|
|
47295
|
+
return !!p && Number.isFinite(p[0]) && Number.isFinite(p[1]) && p[0] >= 0 && p[0] <= width && p[1] >= 0 && p[1] <= height;
|
|
47296
|
+
}
|
|
47297
|
+
function labelWidth(text, letterSpacing) {
|
|
47298
|
+
const spacing = letterSpacing > 0 ? Math.max(0, text.length - 1) * letterSpacing : 0;
|
|
47299
|
+
return measureLegendText(text, FONT) + spacing + 2 * PADX;
|
|
47300
|
+
}
|
|
47301
|
+
function wrapLabel2(text, letterSpacing) {
|
|
47302
|
+
const words = text.split(/\s+/).filter(Boolean);
|
|
47303
|
+
if (words.length <= 1) return [text];
|
|
47304
|
+
const maxLines = words.length >= 4 ? 3 : 2;
|
|
47305
|
+
const n = words.length;
|
|
47306
|
+
let best = null;
|
|
47307
|
+
for (let mask = 0; mask < 1 << n - 1; mask++) {
|
|
47308
|
+
const lines = [];
|
|
47309
|
+
let cur = [words[0]];
|
|
47310
|
+
for (let i = 1; i < n; i++) {
|
|
47311
|
+
if (mask & 1 << i - 1) {
|
|
47312
|
+
lines.push(cur.join(" "));
|
|
47313
|
+
cur = [words[i]];
|
|
47314
|
+
} else cur.push(words[i]);
|
|
47315
|
+
}
|
|
47316
|
+
lines.push(cur.join(" "));
|
|
47317
|
+
if (lines.length > maxLines) continue;
|
|
47318
|
+
const cost = Math.round(
|
|
47319
|
+
Math.max(...lines.map((l) => labelWidth(l, letterSpacing)))
|
|
47320
|
+
);
|
|
47321
|
+
const head = labelWidth(lines[0], letterSpacing);
|
|
47322
|
+
if (!best || cost < best.cost || cost === best.cost && lines.length < best.lines.length || cost === best.cost && lines.length === best.lines.length && head > best.head)
|
|
47323
|
+
best = { lines, cost, head };
|
|
47324
|
+
}
|
|
47325
|
+
return best?.lines ?? [text];
|
|
47326
|
+
}
|
|
47327
|
+
function rectAround(cx, cy, lines, letterSpacing) {
|
|
47328
|
+
const w = Math.max(...lines.map((l) => labelWidth(l, letterSpacing)));
|
|
47329
|
+
const h = (lines.length - 1) * LINE_HEIGHT + FONT + 2 * PADY;
|
|
47330
|
+
return { x: cx - w / 2, y: cy - h / 2, w, h };
|
|
47331
|
+
}
|
|
47332
|
+
function rectFits(r, width, height) {
|
|
47333
|
+
return r.x >= 0 && r.y >= 0 && r.x + r.w <= width && r.y + r.h <= height;
|
|
47334
|
+
}
|
|
47335
|
+
function overlapsPadded(a, b, pad2) {
|
|
47336
|
+
return a.x - pad2 < b.x + b.w && a.x + a.w + pad2 > b.x && a.y - pad2 < b.y + b.h && a.y + a.h + pad2 > b.y;
|
|
47337
|
+
}
|
|
47338
|
+
function placeContextLabels(args) {
|
|
47339
|
+
const {
|
|
47340
|
+
projection,
|
|
47341
|
+
dLonSpan,
|
|
47342
|
+
dLatSpan,
|
|
47343
|
+
width,
|
|
47344
|
+
height,
|
|
47345
|
+
waterBodies,
|
|
47346
|
+
countries,
|
|
47347
|
+
palette,
|
|
47348
|
+
project,
|
|
47349
|
+
collides,
|
|
47350
|
+
overLand
|
|
47351
|
+
} = args;
|
|
47352
|
+
void projection;
|
|
47353
|
+
const band = tierBand(Math.max(dLonSpan, dLatSpan));
|
|
47354
|
+
const budget = labelBudget(width, height, band);
|
|
47355
|
+
if (budget <= 0) return [];
|
|
47356
|
+
const waterColor = mix(palette.colors.blue, palette.textMuted, 50);
|
|
47357
|
+
const countryColor = palette.textMuted;
|
|
47358
|
+
const haloColor = palette.bg;
|
|
47359
|
+
const candidates = [];
|
|
47360
|
+
const center = [width / 2, height / 2];
|
|
47361
|
+
for (const e of waterBodies?.entries ?? []) {
|
|
47362
|
+
const [lat, lon, name, tier, kind, alt] = e;
|
|
47363
|
+
if (!waterEligible(tier, kind, band)) continue;
|
|
47364
|
+
const wlines = wrapLabel2(name, WATER_LETTER_SPACING);
|
|
47365
|
+
const anchorsLngLat = [[lon, lat]];
|
|
47366
|
+
for (const a of alt ?? []) anchorsLngLat.push([a[1], a[0]]);
|
|
47367
|
+
let best = null;
|
|
47368
|
+
let bestD = Infinity;
|
|
47369
|
+
let nearestProj = null;
|
|
47370
|
+
let nearestProjD = Infinity;
|
|
47371
|
+
for (const [aLon, aLat] of anchorsLngLat) {
|
|
47372
|
+
const p = project(aLon, aLat);
|
|
47373
|
+
if (!p || !Number.isFinite(p[0]) || !Number.isFinite(p[1])) continue;
|
|
47374
|
+
const d = (p[0] - center[0]) ** 2 + (p[1] - center[1]) ** 2;
|
|
47375
|
+
if (d < nearestProjD) {
|
|
47376
|
+
nearestProjD = d;
|
|
47377
|
+
nearestProj = p;
|
|
47378
|
+
}
|
|
47379
|
+
if (!insideViewport(p, width, height)) continue;
|
|
47380
|
+
if (d < bestD) {
|
|
47381
|
+
bestD = d;
|
|
47382
|
+
best = p;
|
|
47383
|
+
}
|
|
47384
|
+
}
|
|
47385
|
+
if (!best && tier === 0 && nearestProj) {
|
|
47386
|
+
const overX = Math.max(0, -nearestProj[0], nearestProj[0] - width);
|
|
47387
|
+
const overY = Math.max(0, -nearestProj[1], nearestProj[1] - height);
|
|
47388
|
+
if (overX <= width * EDGE_CLAMP_OVERSHOOT && overY <= height * EDGE_CLAMP_OVERSHOOT) {
|
|
47389
|
+
const halfW = Math.max(...wlines.map((l) => labelWidth(l, WATER_LETTER_SPACING))) / 2;
|
|
47390
|
+
const halfH = ((wlines.length - 1) * LINE_HEIGHT + FONT + 2 * PADY) / 2;
|
|
47391
|
+
const m = EDGE_CLAMP_MARGIN;
|
|
47392
|
+
best = [
|
|
47393
|
+
Math.min(Math.max(nearestProj[0], halfW + m), width - halfW - m),
|
|
47394
|
+
Math.min(Math.max(nearestProj[1], halfH + m), height - halfH - m)
|
|
47395
|
+
];
|
|
47396
|
+
}
|
|
47397
|
+
}
|
|
47398
|
+
if (!best) continue;
|
|
47399
|
+
candidates.push({
|
|
47400
|
+
text: name,
|
|
47401
|
+
lines: wlines,
|
|
47402
|
+
cx: best[0],
|
|
47403
|
+
cy: best[1],
|
|
47404
|
+
italic: true,
|
|
47405
|
+
letterSpacing: WATER_LETTER_SPACING,
|
|
47406
|
+
color: waterColor,
|
|
47407
|
+
// Water before any country (×1000), then by tier, then kind, then name.
|
|
47408
|
+
sort: tier * 10 + KIND_ORDER[kind]
|
|
47409
|
+
});
|
|
47410
|
+
}
|
|
47411
|
+
const ranked = countries.map((c) => {
|
|
47412
|
+
const [x0, y0, x1, y1] = c.bbox;
|
|
47413
|
+
const w = x1 - x0;
|
|
47414
|
+
const h = y1 - y0;
|
|
47415
|
+
return { c, w, h, area: w * h };
|
|
47416
|
+
}).filter((r) => Number.isFinite(r.area) && r.area > 0).sort((a, b) => b.area - a.area);
|
|
47417
|
+
let ci = 0;
|
|
47418
|
+
for (const r of ranked) {
|
|
47419
|
+
const { c, w, h } = r;
|
|
47420
|
+
if (w > width * 0.66 || h > height * 0.66) continue;
|
|
47421
|
+
if (!insideViewport(c.anchor, width, height)) continue;
|
|
47422
|
+
const text = c.name;
|
|
47423
|
+
const tw = labelWidth(text, 0);
|
|
47424
|
+
if (tw > w || FONT + 2 * PADY > h) continue;
|
|
47425
|
+
candidates.push({
|
|
47426
|
+
text,
|
|
47427
|
+
lines: [text],
|
|
47428
|
+
cx: c.anchor[0],
|
|
47429
|
+
cy: c.anchor[1],
|
|
47430
|
+
italic: false,
|
|
47431
|
+
letterSpacing: 0,
|
|
47432
|
+
color: countryColor,
|
|
47433
|
+
// Always after every water body (+1e6); larger area = earlier.
|
|
47434
|
+
sort: 1e6 + ci++
|
|
47435
|
+
});
|
|
47436
|
+
}
|
|
47437
|
+
candidates.sort((a, b) => a.sort - b.sort);
|
|
47438
|
+
const placed = [];
|
|
47439
|
+
const placedRects = [];
|
|
47440
|
+
for (const cand of candidates) {
|
|
47441
|
+
if (placed.length >= budget) break;
|
|
47442
|
+
const rect = rectAround(cand.cx, cand.cy, cand.lines, cand.letterSpacing);
|
|
47443
|
+
if (!rectFits(rect, width, height)) continue;
|
|
47444
|
+
if (cand.italic && overLand) {
|
|
47445
|
+
const inset = 2;
|
|
47446
|
+
const top = cand.cy - (cand.lines.length - 1) / 2 * LINE_HEIGHT;
|
|
47447
|
+
const touchesLand = cand.lines.some((line12, li) => {
|
|
47448
|
+
const lw = labelWidth(line12, cand.letterSpacing);
|
|
47449
|
+
const x0 = cand.cx - lw / 2 + inset;
|
|
47450
|
+
const x1 = cand.cx + lw / 2 - inset;
|
|
47451
|
+
const xs = [x0, (x0 + cand.cx) / 2, cand.cx, (cand.cx + x1) / 2, x1];
|
|
47452
|
+
const base = top + li * LINE_HEIGHT;
|
|
47453
|
+
return [base, base - FONT * 0.4, base - FONT * 0.8].some(
|
|
47454
|
+
(y) => xs.some((x) => overLand(x, y))
|
|
47455
|
+
);
|
|
47456
|
+
});
|
|
47457
|
+
if (touchesLand) continue;
|
|
47458
|
+
}
|
|
47459
|
+
if (collides(rect)) continue;
|
|
47460
|
+
if (placedRects.some((r) => overlapsPadded(rect, r, CONTEXT_PAD))) continue;
|
|
47461
|
+
placedRects.push(rect);
|
|
47462
|
+
placed.push({
|
|
47463
|
+
x: cand.cx,
|
|
47464
|
+
y: cand.cy,
|
|
47465
|
+
text: cand.text,
|
|
47466
|
+
anchor: "middle",
|
|
47467
|
+
color: cand.color,
|
|
47468
|
+
// No halo: the bg-coloured outline reads as a ghost box behind the text
|
|
47469
|
+
// over the tinted water/land. Context labels are muted enough to sit
|
|
47470
|
+
// cleanly on the basemap without one.
|
|
47471
|
+
halo: false,
|
|
47472
|
+
haloColor,
|
|
47473
|
+
italic: cand.italic,
|
|
47474
|
+
letterSpacing: cand.letterSpacing,
|
|
47475
|
+
...cand.lines.length > 1 ? { lines: cand.lines } : {},
|
|
47476
|
+
lineNumber: 0
|
|
47477
|
+
});
|
|
47478
|
+
}
|
|
47479
|
+
return placed;
|
|
47480
|
+
}
|
|
47481
|
+
var FONT, LINE_HEIGHT, PADX, PADY, WATER_LETTER_SPACING, CONTEXT_PAD, EDGE_CLAMP_MARGIN, EDGE_CLAMP_OVERSHOOT, KIND_ORDER;
|
|
47482
|
+
var init_context_labels = __esm({
|
|
47483
|
+
"src/map/context-labels.ts"() {
|
|
47484
|
+
"use strict";
|
|
47485
|
+
init_color_utils();
|
|
47486
|
+
init_legend_constants();
|
|
47487
|
+
FONT = 11;
|
|
47488
|
+
LINE_HEIGHT = FONT + 2;
|
|
47489
|
+
PADX = 4;
|
|
47490
|
+
PADY = 3;
|
|
47491
|
+
WATER_LETTER_SPACING = 1.5;
|
|
47492
|
+
CONTEXT_PAD = 4;
|
|
47493
|
+
EDGE_CLAMP_MARGIN = 8;
|
|
47494
|
+
EDGE_CLAMP_OVERSHOOT = 0.35;
|
|
47495
|
+
KIND_ORDER = {
|
|
47496
|
+
ocean: 0,
|
|
47497
|
+
sea: 1,
|
|
47498
|
+
gulf: 2,
|
|
47499
|
+
bay: 3,
|
|
47500
|
+
strait: 4,
|
|
47501
|
+
channel: 5,
|
|
47502
|
+
sound: 6
|
|
47503
|
+
};
|
|
47504
|
+
}
|
|
47505
|
+
});
|
|
47506
|
+
|
|
46647
47507
|
// src/map/layout.ts
|
|
46648
47508
|
function geomObject2(topo) {
|
|
46649
47509
|
const key = Object.keys(topo.objects)[0];
|
|
46650
47510
|
return topo.objects[key];
|
|
46651
47511
|
}
|
|
47512
|
+
function mergeFeatures(a, b) {
|
|
47513
|
+
const polysOf = (f) => {
|
|
47514
|
+
const g = f.geometry;
|
|
47515
|
+
if (!g) return null;
|
|
47516
|
+
if (g.type === "Polygon") return [g.coordinates];
|
|
47517
|
+
if (g.type === "MultiPolygon") return g.coordinates;
|
|
47518
|
+
return null;
|
|
47519
|
+
};
|
|
47520
|
+
const pa = polysOf(a);
|
|
47521
|
+
const pb = polysOf(b);
|
|
47522
|
+
if (!pa || !pb) return a;
|
|
47523
|
+
return {
|
|
47524
|
+
...a,
|
|
47525
|
+
geometry: { type: "MultiPolygon", coordinates: [...pa, ...pb] }
|
|
47526
|
+
};
|
|
47527
|
+
}
|
|
46652
47528
|
function decodeLayer(topo) {
|
|
47529
|
+
const cached = decodeCache.get(topo);
|
|
47530
|
+
if (cached) return cached;
|
|
46653
47531
|
const out = /* @__PURE__ */ new Map();
|
|
46654
47532
|
for (const g of geomObject2(topo).geometries) {
|
|
46655
47533
|
const f = (0, import_topojson_client2.feature)(topo, g);
|
|
46656
|
-
|
|
47534
|
+
if (!f.geometry) continue;
|
|
47535
|
+
const tagged = { ...f, id: g.id };
|
|
47536
|
+
const existing = out.get(g.id);
|
|
47537
|
+
out.set(g.id, existing ? mergeFeatures(existing, tagged) : tagged);
|
|
46657
47538
|
}
|
|
47539
|
+
decodeCache.set(topo, out);
|
|
46658
47540
|
return out;
|
|
46659
47541
|
}
|
|
46660
47542
|
function projectionFor(family) {
|
|
@@ -46663,9 +47545,12 @@ function projectionFor(family) {
|
|
|
46663
47545
|
return usConusProjection();
|
|
46664
47546
|
case "mercator":
|
|
46665
47547
|
return (0, import_d3_geo2.geoMercator)();
|
|
47548
|
+
case "equal-earth":
|
|
47549
|
+
return (0, import_d3_geo2.geoEqualEarth)();
|
|
47550
|
+
case "equirectangular":
|
|
47551
|
+
return (0, import_d3_geo2.geoEquirectangular)();
|
|
46666
47552
|
case "natural-earth":
|
|
46667
47553
|
return (0, import_d3_geo2.geoNaturalEarth1)();
|
|
46668
|
-
case "equirectangular":
|
|
46669
47554
|
default:
|
|
46670
47555
|
return (0, import_d3_geo2.geoEquirectangular)();
|
|
46671
47556
|
}
|
|
@@ -46684,13 +47569,11 @@ function mapNeutralLandColor(palette, isDark, _dataActive = false) {
|
|
|
46684
47569
|
isDark ? LAND_TINT_DARK : LAND_TINT_LIGHT
|
|
46685
47570
|
);
|
|
46686
47571
|
}
|
|
46687
|
-
function
|
|
46688
|
-
const { palette, isDark } = opts;
|
|
46689
|
-
const { width, height } = size;
|
|
47572
|
+
function buildMapProjection(resolved, data) {
|
|
46690
47573
|
const wantsUsStates = resolved.basemaps.subdivisions.includes("us-states");
|
|
46691
|
-
const usCrisp = resolved.projection === "albers-usa" && wantsUsStates && !!data.naLand;
|
|
47574
|
+
const usCrisp = (resolved.projection === "albers-usa" || resolved.projection === "mercator") && wantsUsStates && !!data.naLand;
|
|
46692
47575
|
const worldTopo = usCrisp ? data.worldDetail : resolved.basemaps.world === "detail" ? data.worldDetail : data.worldCoarse;
|
|
46693
|
-
const worldLayer = decodeLayer(worldTopo);
|
|
47576
|
+
const worldLayer = new Map(decodeLayer(worldTopo));
|
|
46694
47577
|
if (usCrisp && data.naLand) {
|
|
46695
47578
|
const [nbW, nbS, nbE, nbN] = [-140, 10, -52, 66];
|
|
46696
47579
|
const crisp = decodeLayer(data.naLand);
|
|
@@ -46699,16 +47582,141 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46699
47582
|
if (!base) continue;
|
|
46700
47583
|
const [[bw, bs], [be, bn]] = (0, import_d3_geo2.geoBounds)(base);
|
|
46701
47584
|
if (bw >= nbW && be <= nbE && bs >= nbS && bn <= nbN)
|
|
46702
|
-
worldLayer.set(iso, cf);
|
|
47585
|
+
worldLayer.set(iso, { ...cf, properties: base.properties });
|
|
46703
47586
|
}
|
|
46704
47587
|
}
|
|
46705
47588
|
const usLayer = wantsUsStates ? decodeLayer(data.usStates) : null;
|
|
47589
|
+
const extentOutline = () => {
|
|
47590
|
+
const [[w, s], [e, n]] = resolved.extent;
|
|
47591
|
+
const N = 16;
|
|
47592
|
+
const coords = [];
|
|
47593
|
+
for (let i = 0; i <= N; i++) {
|
|
47594
|
+
const t = i / N;
|
|
47595
|
+
const lon = w + (e - w) * t;
|
|
47596
|
+
const lat = s + (n - s) * t;
|
|
47597
|
+
coords.push([lon, s], [lon, n], [w, lat], [e, lat]);
|
|
47598
|
+
}
|
|
47599
|
+
return {
|
|
47600
|
+
type: "Feature",
|
|
47601
|
+
properties: {},
|
|
47602
|
+
geometry: { type: "MultiPoint", coordinates: coords }
|
|
47603
|
+
};
|
|
47604
|
+
};
|
|
47605
|
+
let fitFeatures;
|
|
47606
|
+
if (resolved.projection === "albers-usa" && usLayer) {
|
|
47607
|
+
fitFeatures = [...usLayer.entries()].filter(([iso]) => !US_NON_CONUS.has(iso)).map(([, f]) => f);
|
|
47608
|
+
const neighborPoints = resolved.pois.filter((p) => !inAlaska(p.lon, p.lat) && !inHawaii(p.lon, p.lat)).map((p) => [p.lon, p.lat]);
|
|
47609
|
+
if (neighborPoints.length > 0) {
|
|
47610
|
+
fitFeatures.push({
|
|
47611
|
+
type: "Feature",
|
|
47612
|
+
properties: {},
|
|
47613
|
+
geometry: { type: "MultiPoint", coordinates: neighborPoints }
|
|
47614
|
+
});
|
|
47615
|
+
}
|
|
47616
|
+
for (const r of resolved.regions) {
|
|
47617
|
+
if (r.layer === "country" && (r.iso === "CA" || r.iso === "MX")) {
|
|
47618
|
+
const cf = worldLayer.get(r.iso);
|
|
47619
|
+
if (cf) fitFeatures.push(cf);
|
|
47620
|
+
}
|
|
47621
|
+
}
|
|
47622
|
+
} else {
|
|
47623
|
+
fitFeatures = [extentOutline()];
|
|
47624
|
+
}
|
|
47625
|
+
const fitTarget = { type: "FeatureCollection", features: fitFeatures };
|
|
47626
|
+
const projection = projectionFor(resolved.projection);
|
|
47627
|
+
if (resolved.projection !== "albers-usa") {
|
|
47628
|
+
let centerLon = (resolved.extent[0][0] + resolved.extent[1][0]) / 2;
|
|
47629
|
+
if (centerLon > 180) centerLon -= 360;
|
|
47630
|
+
projection.rotate([-centerLon, 0]);
|
|
47631
|
+
}
|
|
47632
|
+
const fitGB = (0, import_d3_geo2.geoBounds)(fitTarget);
|
|
47633
|
+
const fitIsGlobal = fitGB[1][0] - fitGB[0][0] >= 270 || fitGB[1][1] - fitGB[0][1] >= 130;
|
|
47634
|
+
return {
|
|
47635
|
+
projection,
|
|
47636
|
+
fitTarget,
|
|
47637
|
+
fitIsGlobal,
|
|
47638
|
+
worldLayer,
|
|
47639
|
+
usLayer,
|
|
47640
|
+
usCrisp,
|
|
47641
|
+
wantsUsStates,
|
|
47642
|
+
worldTopo
|
|
47643
|
+
};
|
|
47644
|
+
}
|
|
47645
|
+
function parsePathRings(d) {
|
|
47646
|
+
const rings = [];
|
|
47647
|
+
let cur = [];
|
|
47648
|
+
const re = /([MLZ])([^MLZ]*)/g;
|
|
47649
|
+
let m;
|
|
47650
|
+
while (m = re.exec(d)) {
|
|
47651
|
+
if (m[1] === "Z") {
|
|
47652
|
+
if (cur.length) rings.push(cur);
|
|
47653
|
+
cur = [];
|
|
47654
|
+
continue;
|
|
47655
|
+
}
|
|
47656
|
+
if (m[1] === "M" && cur.length) {
|
|
47657
|
+
rings.push(cur);
|
|
47658
|
+
cur = [];
|
|
47659
|
+
}
|
|
47660
|
+
const nums = m[2].split(/[ ,]+/).map(Number);
|
|
47661
|
+
for (let i = 0; i + 1 < nums.length; i += 2) {
|
|
47662
|
+
const x = nums[i];
|
|
47663
|
+
const y = nums[i + 1];
|
|
47664
|
+
if (Number.isFinite(x) && Number.isFinite(y)) cur.push([x, y]);
|
|
47665
|
+
}
|
|
47666
|
+
}
|
|
47667
|
+
if (cur.length) rings.push(cur);
|
|
47668
|
+
return rings;
|
|
47669
|
+
}
|
|
47670
|
+
function dropAntimeridianWrapSlivers(d, width, height) {
|
|
47671
|
+
const rings = parsePathRings(d);
|
|
47672
|
+
if (rings.length <= 1) return d;
|
|
47673
|
+
const eps = 0.75;
|
|
47674
|
+
const minArea = 3e-3 * width * height;
|
|
47675
|
+
const ringArea = (r) => {
|
|
47676
|
+
let s = 0;
|
|
47677
|
+
for (let i = 0; i < r.length; i++) {
|
|
47678
|
+
const a = r[i];
|
|
47679
|
+
const b = r[(i + 1) % r.length];
|
|
47680
|
+
s += a[0] * b[1] - b[0] * a[1];
|
|
47681
|
+
}
|
|
47682
|
+
return Math.abs(s) / 2;
|
|
47683
|
+
};
|
|
47684
|
+
const areas = rings.map(ringArea);
|
|
47685
|
+
const maxArea = Math.max(...areas);
|
|
47686
|
+
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;
|
|
47687
|
+
let dropped = false;
|
|
47688
|
+
const kept = rings.filter((r, idx) => {
|
|
47689
|
+
if (areas[idx] >= maxArea || areas[idx] >= minArea) return true;
|
|
47690
|
+
const touches = r.some((p, i) => onVEdge(p, r[(i + 1) % r.length]));
|
|
47691
|
+
if (touches) {
|
|
47692
|
+
dropped = true;
|
|
47693
|
+
return false;
|
|
47694
|
+
}
|
|
47695
|
+
return true;
|
|
47696
|
+
});
|
|
47697
|
+
if (!dropped) return d;
|
|
47698
|
+
return kept.map(
|
|
47699
|
+
(r) => r.map((p, i) => (i ? "L" : "M") + p[0] + "," + p[1]).join("") + "Z"
|
|
47700
|
+
).join("");
|
|
47701
|
+
}
|
|
47702
|
+
function layoutMap(resolved, data, size, opts) {
|
|
47703
|
+
const { palette, isDark } = opts;
|
|
47704
|
+
const { width, height } = size;
|
|
47705
|
+
const {
|
|
47706
|
+
projection,
|
|
47707
|
+
fitTarget,
|
|
47708
|
+
fitIsGlobal,
|
|
47709
|
+
worldLayer,
|
|
47710
|
+
usLayer,
|
|
47711
|
+
usCrisp,
|
|
47712
|
+
worldTopo
|
|
47713
|
+
} = buildMapProjection(resolved, data);
|
|
46706
47714
|
const usContext = usLayer !== null;
|
|
46707
47715
|
const regionStroke = isDark ? mix(palette.bg, palette.text, 78) : mix(palette.text, palette.bg, 78);
|
|
46708
47716
|
const values = resolved.regions.filter((r) => r.value !== void 0).map((r) => r.value);
|
|
46709
|
-
const
|
|
46710
|
-
const rampMin =
|
|
46711
|
-
const rampMax =
|
|
47717
|
+
const allNonNegative = values.length > 0 && values.every((v) => v >= 0);
|
|
47718
|
+
const rampMin = allNonNegative ? 0 : Math.min(...values);
|
|
47719
|
+
const rampMax = Math.max(...values);
|
|
46712
47720
|
const rampHue = resolveColor(resolved.directives.regionMetricColor ?? "", palette) ?? palette.colors.red;
|
|
46713
47721
|
const hasRamp = values.length > 0;
|
|
46714
47722
|
const VALUE_NAME = hasRamp ? resolved.directives.regionMetric?.trim() || "Value" : null;
|
|
@@ -46729,7 +47737,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46729
47737
|
activeGroup = VALUE_NAME ?? (resolved.tagGroups.length > 0 ? resolved.tagGroups[0].name : null);
|
|
46730
47738
|
}
|
|
46731
47739
|
const activeIsScore = VALUE_NAME !== null && activeGroup === VALUE_NAME;
|
|
46732
|
-
const mutedBasemap =
|
|
47740
|
+
const mutedBasemap = activeGroup !== null;
|
|
46733
47741
|
const neutralFill = mapNeutralLandColor(palette, isDark, mutedBasemap);
|
|
46734
47742
|
const water = mapBackgroundColor(palette, isDark, mutedBasemap);
|
|
46735
47743
|
const lakeStroke = mix(regionStroke, water, 45);
|
|
@@ -46738,10 +47746,43 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46738
47746
|
palette.bg,
|
|
46739
47747
|
mutedBasemap ? isDark ? MUTED_FOREIGN_DARK : MUTED_FOREIGN_LIGHT : isDark ? FOREIGN_TINT_DARK : FOREIGN_TINT_LIGHT
|
|
46740
47748
|
);
|
|
47749
|
+
const colorizeActive = resolved.directives.noColorize !== true && !hasRamp && resolved.tagGroups.length === 0;
|
|
47750
|
+
const colorByIso = /* @__PURE__ */ new Map();
|
|
47751
|
+
if (colorizeActive) {
|
|
47752
|
+
const adjacency = /* @__PURE__ */ new Map();
|
|
47753
|
+
const addEdges = (src) => {
|
|
47754
|
+
for (const [iso, ns] of src) {
|
|
47755
|
+
const cur = adjacency.get(iso);
|
|
47756
|
+
if (cur) cur.push(...ns);
|
|
47757
|
+
else adjacency.set(iso, [...ns]);
|
|
47758
|
+
}
|
|
47759
|
+
};
|
|
47760
|
+
addEdges(buildAdjacency(worldTopo));
|
|
47761
|
+
if (usLayer) {
|
|
47762
|
+
addEdges(buildAdjacency(data.usStates));
|
|
47763
|
+
for (const [country, states] of Object.entries(FOREIGN_BORDER)) {
|
|
47764
|
+
const cn = adjacency.get(country);
|
|
47765
|
+
if (!cn) continue;
|
|
47766
|
+
for (const st of states) {
|
|
47767
|
+
const sn = adjacency.get(st);
|
|
47768
|
+
if (!sn) continue;
|
|
47769
|
+
cn.push(st);
|
|
47770
|
+
sn.push(country);
|
|
47771
|
+
}
|
|
47772
|
+
}
|
|
47773
|
+
}
|
|
47774
|
+
const { byIso, huesNeeded } = assignColors(
|
|
47775
|
+
[...adjacency.keys()],
|
|
47776
|
+
adjacency
|
|
47777
|
+
);
|
|
47778
|
+
const tints = politicalTints(palette, huesNeeded, isDark);
|
|
47779
|
+
for (const [iso, idx] of byIso) colorByIso.set(iso, tints[idx]);
|
|
47780
|
+
}
|
|
47781
|
+
const colorizeStroke = (fill2) => mix(fill2, palette.text, 35);
|
|
46741
47782
|
const rampBase = isDark ? mix(palette.surface, palette.text, 28) : palette.bg;
|
|
46742
47783
|
const fillForValue = (s) => {
|
|
46743
47784
|
const t = rampMax > rampMin ? (s - rampMin) / (rampMax - rampMin) : 1;
|
|
46744
|
-
const pct =
|
|
47785
|
+
const pct = RAMP_FLOOR2 + Math.max(0, Math.min(1, t)) * (100 - RAMP_FLOOR2);
|
|
46745
47786
|
return mix(rampHue, rampBase, pct);
|
|
46746
47787
|
};
|
|
46747
47788
|
const tagFill = (tags, groupName) => {
|
|
@@ -46773,43 +47814,15 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46773
47814
|
if (activeIsScore) {
|
|
46774
47815
|
return r.value !== void 0 ? fillForValue(r.value) : neutralFill;
|
|
46775
47816
|
}
|
|
47817
|
+
if (colorizeActive) return (r.iso && colorByIso.get(r.iso)) ?? neutralFill;
|
|
46776
47818
|
return tagFill(r.tags, activeGroup) ?? neutralFill;
|
|
46777
47819
|
};
|
|
46778
47820
|
const regionById = new Map(resolved.regions.map((r) => [r.iso, r]));
|
|
46779
|
-
const
|
|
46780
|
-
const [[w, s], [e, n]] = resolved.extent;
|
|
46781
|
-
const N = 16;
|
|
46782
|
-
const coords = [];
|
|
46783
|
-
for (let i = 0; i <= N; i++) {
|
|
46784
|
-
const t = i / N;
|
|
46785
|
-
const lon = w + (e - w) * t;
|
|
46786
|
-
const lat = s + (n - s) * t;
|
|
46787
|
-
coords.push([lon, s], [lon, n], [w, lat], [e, lat]);
|
|
46788
|
-
}
|
|
46789
|
-
return {
|
|
46790
|
-
type: "Feature",
|
|
46791
|
-
properties: {},
|
|
46792
|
-
geometry: { type: "MultiPoint", coordinates: coords }
|
|
46793
|
-
};
|
|
46794
|
-
};
|
|
46795
|
-
let fitFeatures;
|
|
46796
|
-
if (resolved.projection === "albers-usa" && usLayer) {
|
|
46797
|
-
fitFeatures = [...usLayer.entries()].filter(([iso]) => !US_NON_CONUS.has(iso)).map(([, f]) => f);
|
|
46798
|
-
} else {
|
|
46799
|
-
fitFeatures = [extentOutline()];
|
|
46800
|
-
}
|
|
46801
|
-
const fitTarget = { type: "FeatureCollection", features: fitFeatures };
|
|
46802
|
-
const projection = projectionFor(resolved.projection);
|
|
46803
|
-
if (resolved.projection !== "albers-usa") {
|
|
46804
|
-
let centerLon = (resolved.extent[0][0] + resolved.extent[1][0]) / 2;
|
|
46805
|
-
if (centerLon > 180) centerLon -= 360;
|
|
46806
|
-
projection.rotate([-centerLon, 0]);
|
|
46807
|
-
}
|
|
46808
|
-
const TITLE_GAP = 16;
|
|
47821
|
+
const TITLE_GAP2 = 16;
|
|
46809
47822
|
let topPad = FIT_PAD;
|
|
46810
47823
|
if (resolved.title && resolved.pois.length > 0) {
|
|
46811
47824
|
const bannerBottom = (resolved.subtitle ? TITLE_Y + TITLE_FONT_SIZE : TITLE_Y) + TITLE_FONT_SIZE / 2;
|
|
46812
|
-
topPad = Math.max(FIT_PAD, bannerBottom +
|
|
47825
|
+
topPad = Math.max(FIT_PAD, bannerBottom + TITLE_GAP2);
|
|
46813
47826
|
}
|
|
46814
47827
|
const fitBox = [
|
|
46815
47828
|
[FIT_PAD, topPad],
|
|
@@ -46819,21 +47832,20 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46819
47832
|
]
|
|
46820
47833
|
];
|
|
46821
47834
|
projection.fitExtent(fitBox, fitTarget);
|
|
46822
|
-
const fitGB = (0, import_d3_geo2.geoBounds)(fitTarget);
|
|
46823
|
-
const fitIsGlobal = fitGB[1][0] - fitGB[0][0] >= 270 || fitGB[1][1] - fitGB[0][1] >= 130;
|
|
46824
47835
|
let path;
|
|
46825
47836
|
let project;
|
|
46826
47837
|
let stretchParams = null;
|
|
46827
|
-
if (fitIsGlobal) {
|
|
47838
|
+
if (fitIsGlobal && !opts.preferContain) {
|
|
46828
47839
|
const cb = (0, import_d3_geo2.geoPath)(projection).bounds(fitTarget);
|
|
46829
47840
|
const bx0 = cb[0][0];
|
|
46830
47841
|
const by0 = cb[0][1];
|
|
46831
47842
|
const cw = cb[1][0] - bx0;
|
|
46832
47843
|
const ch = cb[1][1] - by0;
|
|
46833
|
-
const
|
|
46834
|
-
const
|
|
46835
|
-
const
|
|
46836
|
-
const
|
|
47844
|
+
const topReserve = resolved.title && resolved.pois.length > 0 ? topPad : 0;
|
|
47845
|
+
const ox = 0;
|
|
47846
|
+
const oy = topReserve;
|
|
47847
|
+
const sx = cw > 0 ? width / cw : 1;
|
|
47848
|
+
const sy = ch > 0 ? (height - topReserve) / ch : 1;
|
|
46837
47849
|
stretchParams = { sx, sy, ox, oy, bx0, by0 };
|
|
46838
47850
|
const stretch = (x, y) => [
|
|
46839
47851
|
ox + (x - bx0) * sx,
|
|
@@ -46866,7 +47878,9 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46866
47878
|
const insets = [];
|
|
46867
47879
|
const insetRegions = [];
|
|
46868
47880
|
const insetLabelSeeds = [];
|
|
46869
|
-
|
|
47881
|
+
const akRef = resolved.regions.some((r) => r.iso === "US-AK") || resolved.pois.some((p) => inAlaska(p.lon, p.lat));
|
|
47882
|
+
const hiRef = resolved.regions.some((r) => r.iso === "US-HI") || resolved.pois.some((p) => inHawaii(p.lon, p.lat));
|
|
47883
|
+
if (resolved.projection === "albers-usa" && usLayer && (akRef || hiRef)) {
|
|
46870
47884
|
const PAD = 8;
|
|
46871
47885
|
const GAP = 12;
|
|
46872
47886
|
const yB = height - FIT_PAD;
|
|
@@ -46931,8 +47945,18 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46931
47945
|
);
|
|
46932
47946
|
const d = (0, import_d3_geo2.geoPath)(proj)(f) ?? "";
|
|
46933
47947
|
if (!d) return xr;
|
|
47948
|
+
let contextLand;
|
|
47949
|
+
if (iso === "US-AK") {
|
|
47950
|
+
const can = worldLayer.get("CA");
|
|
47951
|
+
const cd = can ? (0, import_d3_geo2.geoPath)(proj)(can) ?? "" : "";
|
|
47952
|
+
if (cd)
|
|
47953
|
+
contextLand = {
|
|
47954
|
+
d: cd,
|
|
47955
|
+
fill: colorizeActive ? colorByIso.get("CA") ?? foreignFill : foreignFill
|
|
47956
|
+
};
|
|
47957
|
+
}
|
|
46934
47958
|
const r = regionById.get(iso);
|
|
46935
|
-
let fill2 = neutralFill;
|
|
47959
|
+
let fill2 = colorizeActive ? colorByIso.get(iso) ?? neutralFill : neutralFill;
|
|
46936
47960
|
let lineNumber = -1;
|
|
46937
47961
|
if (r?.layer === "us-state") {
|
|
46938
47962
|
fill2 = regionFill(r);
|
|
@@ -46951,13 +47975,14 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46951
47975
|
],
|
|
46952
47976
|
// The FITTED inset projection (just fit to this box) — captured so the
|
|
46953
47977
|
// geo-query can invert pixels inside the frame back to AK/HI coords.
|
|
46954
|
-
projection: proj
|
|
47978
|
+
projection: proj,
|
|
47979
|
+
...contextLand && { contextLand }
|
|
46955
47980
|
});
|
|
46956
47981
|
insetRegions.push({
|
|
46957
47982
|
id: iso,
|
|
46958
47983
|
d,
|
|
46959
47984
|
fill: fill2,
|
|
46960
|
-
stroke: regionStroke,
|
|
47985
|
+
stroke: colorizeActive ? colorizeStroke(fill2) : regionStroke,
|
|
46961
47986
|
lineNumber,
|
|
46962
47987
|
layer: "us-state",
|
|
46963
47988
|
...r?.value !== void 0 && { value: r.value },
|
|
@@ -46970,13 +47995,16 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46970
47995
|
}
|
|
46971
47996
|
return xr;
|
|
46972
47997
|
};
|
|
46973
|
-
|
|
46974
|
-
|
|
46975
|
-
alaskaProjection(),
|
|
46976
|
-
|
|
46977
|
-
|
|
46978
|
-
|
|
46979
|
-
|
|
47998
|
+
let akRight = FIT_PAD;
|
|
47999
|
+
if (akRef)
|
|
48000
|
+
akRight = placeInset("US-AK", alaskaProjection(), FIT_PAD, width * 0.15);
|
|
48001
|
+
if (hiRef)
|
|
48002
|
+
placeInset(
|
|
48003
|
+
"US-HI",
|
|
48004
|
+
hawaiiProjection(),
|
|
48005
|
+
akRef ? akRight + 24 : FIT_PAD,
|
|
48006
|
+
width * 0.1
|
|
48007
|
+
);
|
|
46980
48008
|
}
|
|
46981
48009
|
const conusFit = resolved.projection === "albers-usa" && !!usLayer;
|
|
46982
48010
|
const classifyExtent = conusFit ? (0, import_d3_geo2.geoBounds)(fitTarget) : resolved.extent;
|
|
@@ -46992,15 +48020,24 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46992
48020
|
};
|
|
46993
48021
|
const ringOverlapsView = (ring) => {
|
|
46994
48022
|
let loMin = Infinity, loMax = -Infinity, rawMin = Infinity, rawMax = -Infinity;
|
|
48023
|
+
const lons = [];
|
|
46995
48024
|
for (const [rawLon] of ring) {
|
|
46996
48025
|
const lon = normLon(rawLon);
|
|
48026
|
+
lons.push(lon);
|
|
46997
48027
|
if (lon < loMin) loMin = lon;
|
|
46998
48028
|
if (lon > loMax) loMax = lon;
|
|
46999
48029
|
if (rawLon < rawMin) rawMin = rawLon;
|
|
47000
48030
|
if (rawLon > rawMax) rawMax = rawLon;
|
|
47001
48031
|
}
|
|
47002
|
-
|
|
47003
|
-
|
|
48032
|
+
lons.sort((a, b) => a - b);
|
|
48033
|
+
let maxGap = 0;
|
|
48034
|
+
for (let i = 1; i < lons.length; i++)
|
|
48035
|
+
maxGap = Math.max(maxGap, lons[i] - lons[i - 1]);
|
|
48036
|
+
if (lons.length > 1)
|
|
48037
|
+
maxGap = Math.max(maxGap, lons[0] + 360 - lons[lons.length - 1]);
|
|
48038
|
+
const occupiedArc = 360 - maxGap;
|
|
48039
|
+
if (occupiedArc > 270) return false;
|
|
48040
|
+
if (rawMax - rawMin > 180 && occupiedArc < 90) return false;
|
|
47004
48041
|
let px0 = Infinity, py0 = Infinity, px1 = -Infinity, py1 = -Infinity, anyFinite = false;
|
|
47005
48042
|
for (const [lon, lat] of ring) {
|
|
47006
48043
|
const p = project(lon, lat);
|
|
@@ -47073,7 +48110,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47073
48110
|
const regions = [];
|
|
47074
48111
|
const pushRegionLayer = (layerFeatures, layerKind, shouldCull) => {
|
|
47075
48112
|
for (const [iso, f] of layerFeatures) {
|
|
47076
|
-
if (layerKind === "us-state" && usContext && INSET_STATES.has(iso))
|
|
48113
|
+
if (layerKind === "us-state" && usContext && resolved.projection === "albers-usa" && INSET_STATES.has(iso))
|
|
47077
48114
|
continue;
|
|
47078
48115
|
if (layerKind === "country" && usContext && iso === "US") continue;
|
|
47079
48116
|
if (layerKind === "country" && iso === "AQ" && !regionById.has("AQ"))
|
|
@@ -47081,11 +48118,13 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47081
48118
|
const r = regionById.get(iso);
|
|
47082
48119
|
const viewF = shouldCull ? cullFeatureToView(f) : dropFrameFillers(f);
|
|
47083
48120
|
if (!viewF) continue;
|
|
47084
|
-
const
|
|
48121
|
+
const raw = path(viewF) ?? "";
|
|
48122
|
+
const d = fitIsGlobal ? dropAntimeridianWrapSlivers(raw, width, height) : raw;
|
|
47085
48123
|
if (!d) continue;
|
|
47086
48124
|
const isThisLayer = r?.layer === layerKind;
|
|
47087
48125
|
const isForeign = layerKind === "country" && usContext && iso !== "US";
|
|
47088
|
-
|
|
48126
|
+
const baseFill = isForeign ? foreignFill : neutralFill;
|
|
48127
|
+
let fill2 = colorizeActive ? colorByIso.get(iso) ?? baseFill : baseFill;
|
|
47089
48128
|
let label;
|
|
47090
48129
|
let lineNumber = -1;
|
|
47091
48130
|
let layer = "base";
|
|
@@ -47094,15 +48133,21 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47094
48133
|
lineNumber = r.lineNumber;
|
|
47095
48134
|
layer = layerKind;
|
|
47096
48135
|
label = r.name;
|
|
48136
|
+
} else {
|
|
48137
|
+
label = f.properties?.name;
|
|
47097
48138
|
}
|
|
48139
|
+
const labelAnchor = WORLD_LABEL_ANCHORS[iso];
|
|
48140
|
+
const c = labelAnchor ? project(labelAnchor[0], labelAnchor[1]) : path.centroid(viewF);
|
|
48141
|
+
const hasCentroid = c != null && Number.isFinite(c[0]) && Number.isFinite(c[1]);
|
|
47098
48142
|
regions.push({
|
|
47099
48143
|
id: iso,
|
|
47100
48144
|
d,
|
|
47101
48145
|
fill: fill2,
|
|
47102
|
-
stroke: regionStroke,
|
|
48146
|
+
stroke: colorizeActive ? colorizeStroke(fill2) : regionStroke,
|
|
47103
48147
|
lineNumber,
|
|
47104
48148
|
layer,
|
|
47105
48149
|
...label !== void 0 && { label },
|
|
48150
|
+
...hasCentroid && { labelX: c[0], labelY: c[1] },
|
|
47106
48151
|
...isThisLayer && r.value !== void 0 && { value: r.value },
|
|
47107
48152
|
...isThisLayer && Object.keys(r.tags).length > 0 && { tags: r.tags }
|
|
47108
48153
|
});
|
|
@@ -47127,9 +48172,41 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47127
48172
|
});
|
|
47128
48173
|
}
|
|
47129
48174
|
}
|
|
48175
|
+
const pointInRings = (px, py, rings) => {
|
|
48176
|
+
let inside = false;
|
|
48177
|
+
for (const ring of rings) {
|
|
48178
|
+
for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {
|
|
48179
|
+
const [xi, yi] = ring[i];
|
|
48180
|
+
const [xj, yj] = ring[j];
|
|
48181
|
+
if (yi > py !== yj > py && px < (xj - xi) * (py - yi) / (yj - yi) + xi)
|
|
48182
|
+
inside = !inside;
|
|
48183
|
+
}
|
|
48184
|
+
}
|
|
48185
|
+
return inside;
|
|
48186
|
+
};
|
|
48187
|
+
const fillHitTargets = [...regions, ...insetRegions].map((r) => ({
|
|
48188
|
+
fill: r.fill,
|
|
48189
|
+
rings: parsePathRings(r.d)
|
|
48190
|
+
}));
|
|
48191
|
+
const fillAt = (x, y) => {
|
|
48192
|
+
let hit = water;
|
|
48193
|
+
for (const t of fillHitTargets)
|
|
48194
|
+
if (pointInRings(x, y, t.rings)) hit = t.fill;
|
|
48195
|
+
return hit;
|
|
48196
|
+
};
|
|
48197
|
+
const labelOnFill = (fill2) => {
|
|
48198
|
+
const color = contrastRatio(fill2, palette.textOnFillDark) >= contrastRatio(fill2, palette.textOnFillLight) ? palette.textOnFillDark : palette.textOnFillLight;
|
|
48199
|
+
const haloColor = color === palette.textOnFillLight ? palette.textOnFillDark : palette.textOnFillLight;
|
|
48200
|
+
return {
|
|
48201
|
+
color,
|
|
48202
|
+
halo: contrastRatio(fill2, color) < REGION_LABEL_HALO_RATIO,
|
|
48203
|
+
haloColor
|
|
48204
|
+
};
|
|
48205
|
+
};
|
|
48206
|
+
const reliefAllowed = resolved.directives.noRelief !== true;
|
|
47130
48207
|
const relief = [];
|
|
47131
48208
|
let reliefHatch = null;
|
|
47132
|
-
if (
|
|
48209
|
+
if (reliefAllowed && data.mountainRanges) {
|
|
47133
48210
|
for (const [, f] of decodeLayer(data.mountainRanges)) {
|
|
47134
48211
|
const viewF = isGlobalView ? dropFrameFillers(f) : cullFeatureToView(f);
|
|
47135
48212
|
if (!viewF) continue;
|
|
@@ -47145,16 +48222,32 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47145
48222
|
if (relief.length) {
|
|
47146
48223
|
const darkTone = isDark ? palette.bg : palette.text;
|
|
47147
48224
|
const lightTone = isDark ? palette.text : palette.bg;
|
|
47148
|
-
const
|
|
48225
|
+
const reliefLandRef = colorizeActive ? isDark ? palette.surface : palette.bg : neutralFill;
|
|
48226
|
+
const landLum = relativeLuminance(reliefLandRef);
|
|
47149
48227
|
const tone = Math.abs(landLum - relativeLuminance(darkTone)) > 0.04 ? darkTone : lightTone;
|
|
47150
48228
|
reliefHatch = {
|
|
47151
|
-
color: mix(tone,
|
|
48229
|
+
color: mix(tone, reliefLandRef, RELIEF_HATCH_STRENGTH),
|
|
47152
48230
|
spacing: RELIEF_HATCH_SPACING,
|
|
47153
48231
|
width: RELIEF_HATCH_WIDTH
|
|
47154
48232
|
};
|
|
47155
48233
|
}
|
|
47156
48234
|
}
|
|
47157
|
-
|
|
48235
|
+
let coastlineStyle = null;
|
|
48236
|
+
if (resolved.directives.noCoastline !== true) {
|
|
48237
|
+
const minDim = Math.min(width, height);
|
|
48238
|
+
coastlineStyle = {
|
|
48239
|
+
color: mix(regionStroke, water, COASTLINE_STROKE_MIX),
|
|
48240
|
+
// N equal-width rings: distance steps outward by COASTLINE_STEP; opacity
|
|
48241
|
+
// fades linearly from NEAR (innermost) to FAR (outermost).
|
|
48242
|
+
lines: Array.from({ length: COASTLINE_RING_COUNT }, (_, k) => ({
|
|
48243
|
+
d: (COASTLINE_D0 + k * COASTLINE_STEP) * minDim,
|
|
48244
|
+
thickness: COASTLINE_THICKNESS * minDim,
|
|
48245
|
+
opacity: COASTLINE_OPACITY_NEAR + (COASTLINE_OPACITY_FAR - COASTLINE_OPACITY_NEAR) * k / (COASTLINE_RING_COUNT - 1)
|
|
48246
|
+
})),
|
|
48247
|
+
minExtent: (isGlobalView ? COASTLINE_MIN_EXTENT_GLOBAL : COASTLINE_MIN_EXTENT) * minDim
|
|
48248
|
+
};
|
|
48249
|
+
}
|
|
48250
|
+
const riverColor = mix(palette.colors.blue, water, 32);
|
|
47158
48251
|
const rivers = [];
|
|
47159
48252
|
if (data.rivers) {
|
|
47160
48253
|
for (const [, f] of decodeLayer(data.rivers)) {
|
|
@@ -47210,38 +48303,108 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47210
48303
|
const xy = project(p.lon, p.lat);
|
|
47211
48304
|
if (xy) projected.push({ p, xy });
|
|
47212
48305
|
}
|
|
47213
|
-
const
|
|
48306
|
+
const placePoi = (e, cx, cy, clusterId) => {
|
|
48307
|
+
const { fill: fill2, stroke: stroke2 } = poiFill(e.p);
|
|
48308
|
+
poiScreen.set(e.p.id, { cx, cy, r: radiusFor(e.p) });
|
|
48309
|
+
const num = routeNumberById.get(e.p.id);
|
|
48310
|
+
pois.push({
|
|
48311
|
+
id: e.p.id,
|
|
48312
|
+
cx,
|
|
48313
|
+
cy,
|
|
48314
|
+
r: radiusFor(e.p),
|
|
48315
|
+
fill: fill2,
|
|
48316
|
+
stroke: stroke2,
|
|
48317
|
+
lineNumber: e.p.lineNumber,
|
|
48318
|
+
implicit: !!e.p.implicit,
|
|
48319
|
+
isOrigin: originIds.has(e.p.id),
|
|
48320
|
+
...num !== void 0 && { routeNumber: num },
|
|
48321
|
+
...Object.keys(e.p.tags).length > 0 && { tags: e.p.tags },
|
|
48322
|
+
...clusterId !== void 0 && { clusterId }
|
|
48323
|
+
});
|
|
48324
|
+
};
|
|
48325
|
+
const clusters = [];
|
|
48326
|
+
const connected = /* @__PURE__ */ new Set();
|
|
48327
|
+
for (const e of resolved.edges) {
|
|
48328
|
+
connected.add(e.fromId);
|
|
48329
|
+
connected.add(e.toId);
|
|
48330
|
+
}
|
|
48331
|
+
for (const rt of resolved.routes) {
|
|
48332
|
+
rt.stopIds.forEach((id) => connected.add(id));
|
|
48333
|
+
}
|
|
48334
|
+
const radiusOf = (e) => radiusFor(e.p);
|
|
47214
48335
|
for (const e of projected) {
|
|
47215
|
-
|
|
47216
|
-
|
|
47217
|
-
|
|
47218
|
-
|
|
47219
|
-
|
|
47220
|
-
|
|
47221
|
-
|
|
47222
|
-
|
|
47223
|
-
|
|
47224
|
-
|
|
47225
|
-
|
|
47226
|
-
|
|
47227
|
-
|
|
47228
|
-
|
|
47229
|
-
|
|
47230
|
-
|
|
47231
|
-
|
|
47232
|
-
|
|
47233
|
-
|
|
47234
|
-
|
|
47235
|
-
|
|
47236
|
-
|
|
47237
|
-
|
|
47238
|
-
|
|
47239
|
-
|
|
47240
|
-
|
|
47241
|
-
|
|
47242
|
-
|
|
47243
|
-
|
|
47244
|
-
|
|
48336
|
+
if (connected.has(e.p.id)) placePoi(e, e.xy[0], e.xy[1]);
|
|
48337
|
+
}
|
|
48338
|
+
const groups = [];
|
|
48339
|
+
for (const e of projected) {
|
|
48340
|
+
if (connected.has(e.p.id)) continue;
|
|
48341
|
+
const r = radiusOf(e);
|
|
48342
|
+
const near = groups.find(
|
|
48343
|
+
(g) => g.some(
|
|
48344
|
+
(q) => Math.hypot(q.xy[0] - e.xy[0], q.xy[1] - e.xy[1]) < (r + radiusOf(q)) * STACK_OVERLAP
|
|
48345
|
+
)
|
|
48346
|
+
);
|
|
48347
|
+
if (near) near.push(e);
|
|
48348
|
+
else groups.push([e]);
|
|
48349
|
+
}
|
|
48350
|
+
for (const g of groups) {
|
|
48351
|
+
if (g.length === 1) {
|
|
48352
|
+
placePoi(g[0], g[0].xy[0], g[0].xy[1]);
|
|
48353
|
+
continue;
|
|
48354
|
+
}
|
|
48355
|
+
const clusterId = g[0].p.id;
|
|
48356
|
+
const cx0 = g.reduce((s, e) => s + e.xy[0], 0) / g.length;
|
|
48357
|
+
const cy0 = g.reduce((s, e) => s + e.xy[1], 0) / g.length;
|
|
48358
|
+
const maxR = Math.max(...g.map(radiusOf));
|
|
48359
|
+
const sep = 2 * maxR + STACK_RING_GAP;
|
|
48360
|
+
const ringR = Math.max(
|
|
48361
|
+
COLO_R,
|
|
48362
|
+
sep / (2 * Math.sin(Math.PI / Math.max(g.length, 2)))
|
|
48363
|
+
);
|
|
48364
|
+
const positions = g.map((e, i) => {
|
|
48365
|
+
if (g.length <= STACK_RING_MAX) {
|
|
48366
|
+
const ang2 = -Math.PI / 2 + i * 2 * Math.PI / g.length;
|
|
48367
|
+
return {
|
|
48368
|
+
e,
|
|
48369
|
+
mx: cx0 + Math.cos(ang2) * ringR,
|
|
48370
|
+
my: cy0 + Math.sin(ang2) * ringR
|
|
48371
|
+
};
|
|
48372
|
+
}
|
|
48373
|
+
const ang = i * GOLDEN_ANGLE;
|
|
48374
|
+
const rr = ringR * Math.sqrt((i + 1) / g.length);
|
|
48375
|
+
return { e, mx: cx0 + Math.cos(ang) * rr, my: cy0 + Math.sin(ang) * rr };
|
|
48376
|
+
});
|
|
48377
|
+
let minX = cx0 - maxR;
|
|
48378
|
+
let maxX = cx0 + maxR;
|
|
48379
|
+
let minY = cy0 - maxR;
|
|
48380
|
+
let maxY = cy0 + maxR;
|
|
48381
|
+
for (const { mx, my, e } of positions) {
|
|
48382
|
+
const r = radiusOf(e);
|
|
48383
|
+
minX = Math.min(minX, mx - r);
|
|
48384
|
+
maxX = Math.max(maxX, mx + r);
|
|
48385
|
+
minY = Math.min(minY, my - r);
|
|
48386
|
+
maxY = Math.max(maxY, my + r);
|
|
48387
|
+
}
|
|
48388
|
+
let dx = 0;
|
|
48389
|
+
let dy = 0;
|
|
48390
|
+
if (minX + dx < 2) dx = 2 - minX;
|
|
48391
|
+
if (maxX + dx > width - 2) dx = width - 2 - maxX;
|
|
48392
|
+
if (minY + dy < 2) dy = 2 - minY;
|
|
48393
|
+
if (maxY + dy > height - 2) dy = height - 2 - maxY;
|
|
48394
|
+
const legsOut = [];
|
|
48395
|
+
for (const { e, mx, my } of positions) {
|
|
48396
|
+
const fx = mx + dx;
|
|
48397
|
+
const fy = my + dy;
|
|
48398
|
+
placePoi(e, fx, fy, clusterId);
|
|
48399
|
+
legsOut.push({ x2: fx, y2: fy, color: poiFill(e.p).fill });
|
|
48400
|
+
}
|
|
48401
|
+
clusters.push({
|
|
48402
|
+
id: clusterId,
|
|
48403
|
+
cx: cx0 + dx,
|
|
48404
|
+
cy: cy0 + dy,
|
|
48405
|
+
count: g.length,
|
|
48406
|
+
hitR: ringR + maxR + 6,
|
|
48407
|
+
legs: legsOut
|
|
47245
48408
|
});
|
|
47246
48409
|
}
|
|
47247
48410
|
const legs = [];
|
|
@@ -47291,16 +48454,26 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47291
48454
|
if (!a || !b) continue;
|
|
47292
48455
|
const mx = (a.cx + b.cx) / 2;
|
|
47293
48456
|
const my = (a.cy + b.cy) / 2;
|
|
48457
|
+
const bow = {
|
|
48458
|
+
curved: leg.style === "arc",
|
|
48459
|
+
offset: 0,
|
|
48460
|
+
labelX: mx,
|
|
48461
|
+
labelY: my - 4
|
|
48462
|
+
};
|
|
48463
|
+
const routeLabelStyle = leg.label !== void 0 ? labelOnFill(fillAt(bow.labelX, bow.labelY)) : void 0;
|
|
47294
48464
|
legs.push({
|
|
47295
|
-
d: legPath(a, b,
|
|
48465
|
+
d: legPath(a, b, bow.curved, bow.offset),
|
|
47296
48466
|
width: routeWidthFor(Number(leg.value)),
|
|
47297
48467
|
color: mix(palette.text, palette.bg, 72),
|
|
47298
48468
|
arrow: true,
|
|
47299
48469
|
lineNumber: leg.lineNumber,
|
|
47300
48470
|
...leg.label !== void 0 && {
|
|
47301
48471
|
label: leg.label,
|
|
47302
|
-
labelX:
|
|
47303
|
-
labelY:
|
|
48472
|
+
labelX: bow.labelX,
|
|
48473
|
+
labelY: bow.labelY,
|
|
48474
|
+
labelColor: routeLabelStyle.color,
|
|
48475
|
+
labelHalo: routeLabelStyle.halo,
|
|
48476
|
+
labelHaloColor: routeLabelStyle.haloColor
|
|
47304
48477
|
}
|
|
47305
48478
|
});
|
|
47306
48479
|
}
|
|
@@ -47328,20 +48501,29 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47328
48501
|
const a = poiScreen.get(e.fromId);
|
|
47329
48502
|
const b = poiScreen.get(e.toId);
|
|
47330
48503
|
if (!a || !b) return;
|
|
47331
|
-
const
|
|
47332
|
-
const offset = n > 1 ? (i - (n - 1) / 2) * FAN_STEP : 0;
|
|
48504
|
+
const fanOffset = n > 1 ? (i - (n - 1) / 2) * FAN_STEP : 0;
|
|
47333
48505
|
const mx = (a.cx + b.cx) / 2;
|
|
47334
48506
|
const my = (a.cy + b.cy) / 2;
|
|
48507
|
+
const bow = {
|
|
48508
|
+
curved: e.style === "arc" || n > 1,
|
|
48509
|
+
offset: fanOffset,
|
|
48510
|
+
labelX: mx,
|
|
48511
|
+
labelY: my - 4
|
|
48512
|
+
};
|
|
48513
|
+
const edgeLabelStyle = e.label !== void 0 ? labelOnFill(fillAt(bow.labelX, bow.labelY)) : void 0;
|
|
47335
48514
|
legs.push({
|
|
47336
|
-
d: legPath(a, b, curved, offset),
|
|
48515
|
+
d: legPath(a, b, bow.curved, bow.offset),
|
|
47337
48516
|
width: widthFor(e),
|
|
47338
48517
|
color: mix(palette.text, palette.bg, 66),
|
|
47339
48518
|
arrow: e.directed,
|
|
47340
48519
|
lineNumber: e.lineNumber,
|
|
47341
48520
|
...e.label !== void 0 && {
|
|
47342
48521
|
label: e.label,
|
|
47343
|
-
labelX:
|
|
47344
|
-
labelY:
|
|
48522
|
+
labelX: bow.labelX,
|
|
48523
|
+
labelY: bow.labelY,
|
|
48524
|
+
labelColor: edgeLabelStyle.color,
|
|
48525
|
+
labelHalo: edgeLabelStyle.halo,
|
|
48526
|
+
labelHaloColor: edgeLabelStyle.haloColor
|
|
47345
48527
|
}
|
|
47346
48528
|
});
|
|
47347
48529
|
});
|
|
@@ -47383,48 +48565,73 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47383
48565
|
}
|
|
47384
48566
|
}
|
|
47385
48567
|
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));
|
|
47386
|
-
const
|
|
48568
|
+
const showRegionLabels = resolved.directives.noRegionLabels !== true;
|
|
48569
|
+
const isCompact = width < COMPACT_WIDTH_PX;
|
|
47387
48570
|
const LABEL_PADX = 6;
|
|
47388
48571
|
const LABEL_PADY = 3;
|
|
47389
|
-
const labelW = (text) => measureLegendText(text,
|
|
47390
|
-
const labelH =
|
|
48572
|
+
const labelW = (text) => measureLegendText(text, FONT2) + 2 * LABEL_PADX;
|
|
48573
|
+
const labelH = FONT2 + 2 * LABEL_PADY;
|
|
47391
48574
|
const pushRegionLabel = (x, y, text, fill2, lineNumber) => {
|
|
47392
|
-
const color =
|
|
47393
|
-
|
|
47394
|
-
|
|
47395
|
-
|
|
48575
|
+
const { color, haloColor } = labelOnFill(fill2);
|
|
48576
|
+
const halfW = measureLegendText(text, FONT2) / 2;
|
|
48577
|
+
const overflows = [y - FONT2 * 0.55, y - FONT2 * 0.1].some(
|
|
48578
|
+
(sy) => fillAt(x - halfW, sy) !== fill2 || fillAt(x + halfW, sy) !== fill2
|
|
47396
48579
|
);
|
|
47397
|
-
const haloColor = color === palette.textOnFillLight ? palette.textOnFillDark : palette.textOnFillLight;
|
|
47398
48580
|
labels.push({
|
|
47399
48581
|
x,
|
|
47400
48582
|
y,
|
|
47401
48583
|
text,
|
|
47402
48584
|
anchor: "middle",
|
|
47403
48585
|
color,
|
|
47404
|
-
halo:
|
|
48586
|
+
halo: overflows,
|
|
47405
48587
|
haloColor,
|
|
47406
48588
|
lineNumber
|
|
47407
48589
|
});
|
|
47408
48590
|
};
|
|
47409
|
-
const
|
|
47410
|
-
|
|
47411
|
-
|
|
48591
|
+
const REGION_LABEL_GAP = 2;
|
|
48592
|
+
const regionLabelRect = (cx, cy, text) => {
|
|
48593
|
+
const w = measureLegendText(text, FONT2) + 2 * REGION_LABEL_GAP;
|
|
48594
|
+
return { x: cx - w / 2, y: cy - FONT2 / 2, w, h: FONT2 };
|
|
47412
48595
|
};
|
|
47413
|
-
if (
|
|
47414
|
-
|
|
47415
|
-
|
|
47416
|
-
const
|
|
47417
|
-
if (!
|
|
48596
|
+
if (showRegionLabels) {
|
|
48597
|
+
const frameContainers = new Set(resolved.poiFrameContainers);
|
|
48598
|
+
const entries = regions.map((r) => {
|
|
48599
|
+
const isContainer = frameContainers.has(r.id);
|
|
48600
|
+
if (r.layer === "base" && !isContainer || r.label === void 0)
|
|
48601
|
+
return null;
|
|
48602
|
+
const isUsState = r.layer === "us-state" || r.id.startsWith("US-");
|
|
48603
|
+
const f = isUsState ? usLayer?.get(r.id) : worldLayer.get(r.id);
|
|
48604
|
+
if (!f) return null;
|
|
47418
48605
|
const [[x0, y0], [x1, y1]] = path.bounds(f);
|
|
47419
|
-
const
|
|
47420
|
-
|
|
47421
|
-
const
|
|
48606
|
+
const boxW = x1 - x0;
|
|
48607
|
+
const boxH = y1 - y0;
|
|
48608
|
+
const abbrev = isUsState ? r.id.replace(/^US-/, "") : void 0;
|
|
48609
|
+
const candidates = abbrev !== void 0 ? isCompact ? [abbrev, r.label] : [r.label, abbrev] : [r.label];
|
|
48610
|
+
const anchor = !isUsState ? WORLD_LABEL_ANCHORS[r.id] : void 0;
|
|
47422
48611
|
const c = anchor ? project(anchor[0], anchor[1]) : path.centroid(f);
|
|
47423
|
-
if (!c || !Number.isFinite(c[0]))
|
|
48612
|
+
if (!c || !Number.isFinite(c[0])) return null;
|
|
48613
|
+
return { r, c, boxW, boxH, area: boxW * boxH, candidates };
|
|
48614
|
+
}).filter((e) => e !== null).sort((a, b) => b.area - a.area || a.r.lineNumber - b.r.lineNumber);
|
|
48615
|
+
const placedRegionRects = [];
|
|
48616
|
+
const POI_LABEL_PAD = 14;
|
|
48617
|
+
const poiObstacles = pois.map((p) => ({
|
|
48618
|
+
x: p.cx - p.r - POI_LABEL_PAD,
|
|
48619
|
+
y: p.cy - p.r - POI_LABEL_PAD,
|
|
48620
|
+
w: 2 * (p.r + POI_LABEL_PAD),
|
|
48621
|
+
h: 2 * (p.r + POI_LABEL_PAD)
|
|
48622
|
+
}));
|
|
48623
|
+
for (const { r, c, boxW, boxH, candidates } of entries) {
|
|
48624
|
+
const text = candidates.find((t) => {
|
|
48625
|
+
if (labelW(t) > boxW || labelH > boxH) return false;
|
|
48626
|
+
const rect = regionLabelRect(c[0], c[1], t);
|
|
48627
|
+
return !placedRegionRects.some((p) => rectsOverlap(rect, p)) && !poiObstacles.some((o) => rectsOverlap(rect, o));
|
|
48628
|
+
});
|
|
48629
|
+
if (text === void 0) continue;
|
|
48630
|
+
placedRegionRects.push(regionLabelRect(c[0], c[1], text));
|
|
47424
48631
|
pushRegionLabel(c[0], c[1], text, r.fill, r.lineNumber);
|
|
47425
48632
|
}
|
|
47426
48633
|
for (const seed of insetLabelSeeds) {
|
|
47427
|
-
const text =
|
|
48634
|
+
const text = isCompact ? seed.iso.replace(/^US-/, "") : seed.name;
|
|
47428
48635
|
const src = regionById.get(seed.iso);
|
|
47429
48636
|
pushRegionLabel(
|
|
47430
48637
|
seed.x,
|
|
@@ -47435,22 +48642,26 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47435
48642
|
);
|
|
47436
48643
|
}
|
|
47437
48644
|
}
|
|
47438
|
-
|
|
47439
|
-
|
|
47440
|
-
const ordered = [...pois].sort(
|
|
47441
|
-
(a, b) => a.lineNumber - b.lineNumber || (a.id < b.id ? -1 : 1)
|
|
47442
|
-
);
|
|
48645
|
+
if (resolved.directives.noPoiLabels !== true) {
|
|
48646
|
+
const ordered = [...pois].filter((p) => p.clusterId === void 0).sort((a, b) => a.lineNumber - b.lineNumber || (a.id < b.id ? -1 : 1));
|
|
47443
48647
|
const poiById = new Map(resolved.pois.map((q) => [q.id, q]));
|
|
47444
48648
|
const labelText = (p) => {
|
|
47445
48649
|
const src = poiById.get(p.id);
|
|
47446
48650
|
return src?.label ?? src?.name ?? p.id;
|
|
47447
48651
|
};
|
|
47448
|
-
const poiLabH =
|
|
48652
|
+
const poiLabH = FONT2 * 1.25;
|
|
47449
48653
|
const labelInfo = (p) => {
|
|
47450
48654
|
const text = labelText(p);
|
|
47451
|
-
return { text, w: measureLegendText(text,
|
|
48655
|
+
return { text, w: measureLegendText(text, FONT2) };
|
|
47452
48656
|
};
|
|
47453
48657
|
const GAP = 3;
|
|
48658
|
+
const clusterMembersById = /* @__PURE__ */ new Map();
|
|
48659
|
+
for (const p of pois) {
|
|
48660
|
+
if (p.clusterId === void 0) continue;
|
|
48661
|
+
const arr = clusterMembersById.get(p.clusterId);
|
|
48662
|
+
if (arr) arr.push(p);
|
|
48663
|
+
else clusterMembersById.set(p.clusterId, [p]);
|
|
48664
|
+
}
|
|
47454
48665
|
const inlineRect = (p, w, side) => {
|
|
47455
48666
|
switch (side) {
|
|
47456
48667
|
case "right":
|
|
@@ -47480,11 +48691,11 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47480
48691
|
const x = side === "right" ? rect.x : side === "left" ? rect.x + w : p.cx;
|
|
47481
48692
|
labels.push({
|
|
47482
48693
|
x,
|
|
47483
|
-
y: rect.y + poiLabH / 2 +
|
|
48694
|
+
y: rect.y + poiLabH / 2 + FONT2 / 3,
|
|
47484
48695
|
text,
|
|
47485
48696
|
anchor,
|
|
47486
48697
|
color: palette.text,
|
|
47487
|
-
halo:
|
|
48698
|
+
halo: false,
|
|
47488
48699
|
haloColor: palette.bg,
|
|
47489
48700
|
poiId: p.id,
|
|
47490
48701
|
lineNumber: p.lineNumber
|
|
@@ -47495,43 +48706,60 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47495
48706
|
return rect.x >= 0 && rect.x + rect.w <= width && rect.y >= 0 && rect.y + rect.h <= height && !collides(rect);
|
|
47496
48707
|
};
|
|
47497
48708
|
const GROUP_R = 30;
|
|
47498
|
-
const
|
|
48709
|
+
const groups2 = [];
|
|
47499
48710
|
for (const p of ordered) {
|
|
47500
|
-
const near =
|
|
48711
|
+
const near = groups2.find(
|
|
47501
48712
|
(g) => g.some((q) => Math.hypot(q.cx - p.cx, q.cy - p.cy) < GROUP_R)
|
|
47502
48713
|
);
|
|
47503
48714
|
if (near) near.push(p);
|
|
47504
|
-
else
|
|
48715
|
+
else groups2.push([p]);
|
|
47505
48716
|
}
|
|
47506
48717
|
const ROW_GAP2 = 3;
|
|
47507
48718
|
const step = poiLabH + ROW_GAP2;
|
|
47508
48719
|
const COL_GAP = 16;
|
|
47509
|
-
const
|
|
47510
|
-
|
|
48720
|
+
const makeItems = (group) => group.map((p) => ({ p, ...labelInfo(p) })).sort((a, b) => a.p.cy - b.p.cy || (a.text < b.text ? -1 : 1));
|
|
48721
|
+
const columnRows = (items, side) => {
|
|
47511
48722
|
const left = Math.min(...items.map((o) => o.p.cx - o.p.r));
|
|
47512
48723
|
const right = Math.max(...items.map((o) => o.p.cx + o.p.r));
|
|
47513
|
-
const cyMid = (Math.min(...items.map((o) => o.p.cy)) + Math.max(...items.map((o) => o.p.cy))) / 2;
|
|
47514
48724
|
const maxW = Math.max(...items.map((o) => o.w));
|
|
47515
|
-
const
|
|
47516
|
-
const colX = side === "right" ? right + COL_GAP : left - COL_GAP;
|
|
48725
|
+
const cyMid = (Math.min(...items.map((o) => o.p.cy)) + Math.max(...items.map((o) => o.p.cy))) / 2;
|
|
48726
|
+
const colX = side === "right" ? Math.min(right + COL_GAP, width - 2 - maxW) : Math.max(left - COL_GAP, 2 + maxW);
|
|
47517
48727
|
const totalH = items.length * step;
|
|
47518
48728
|
let startY = cyMid - totalH / 2;
|
|
47519
48729
|
startY = Math.max(2, Math.min(startY, height - totalH - 2));
|
|
47520
|
-
items.
|
|
48730
|
+
return items.map((o, i) => {
|
|
47521
48731
|
const rowCy = startY + i * step + step / 2;
|
|
47522
|
-
|
|
47523
|
-
|
|
47524
|
-
|
|
47525
|
-
|
|
47526
|
-
|
|
47527
|
-
|
|
48732
|
+
return {
|
|
48733
|
+
o,
|
|
48734
|
+
colX,
|
|
48735
|
+
rowCy,
|
|
48736
|
+
rect: {
|
|
48737
|
+
x: side === "right" ? colX : colX - o.w,
|
|
48738
|
+
y: rowCy - poiLabH / 2,
|
|
48739
|
+
w: o.w,
|
|
48740
|
+
h: poiLabH
|
|
48741
|
+
}
|
|
48742
|
+
};
|
|
48743
|
+
});
|
|
48744
|
+
};
|
|
48745
|
+
const wouldColumnBeClean = (items, side) => columnRows(items, side).every(
|
|
48746
|
+
({ rect }) => rect.x >= 0 && rect.x + rect.w <= width && rect.y >= 0 && rect.y + rect.h <= height && !collides(rect)
|
|
48747
|
+
);
|
|
48748
|
+
const defaultColumnSide = (items) => {
|
|
48749
|
+
const right = Math.max(...items.map((o) => o.p.cx + o.p.r));
|
|
48750
|
+
const maxW = Math.max(...items.map((o) => o.w));
|
|
48751
|
+
return right + COL_GAP + maxW <= width - 2 ? "right" : "left";
|
|
48752
|
+
};
|
|
48753
|
+
const commitColumn = (items, side, clusterId) => {
|
|
48754
|
+
for (const { o, colX, rowCy, rect } of columnRows(items, side)) {
|
|
48755
|
+
obstacles.push(rect);
|
|
47528
48756
|
labels.push({
|
|
47529
48757
|
x: colX,
|
|
47530
|
-
y: rowCy +
|
|
48758
|
+
y: rowCy + FONT2 / 3,
|
|
47531
48759
|
text: o.text,
|
|
47532
48760
|
anchor: side === "right" ? "start" : "end",
|
|
47533
48761
|
color: palette.text,
|
|
47534
|
-
halo:
|
|
48762
|
+
halo: false,
|
|
47535
48763
|
haloColor: palette.bg,
|
|
47536
48764
|
leader: {
|
|
47537
48765
|
x1: o.p.cx,
|
|
@@ -47541,24 +48769,141 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47541
48769
|
},
|
|
47542
48770
|
leaderColor: o.p.fill,
|
|
47543
48771
|
poiId: o.p.id,
|
|
47544
|
-
lineNumber: o.p.lineNumber
|
|
48772
|
+
lineNumber: o.p.lineNumber,
|
|
48773
|
+
...clusterId !== void 0 && { clusterMember: clusterId }
|
|
47545
48774
|
});
|
|
48775
|
+
}
|
|
48776
|
+
};
|
|
48777
|
+
const pushHidden = (p) => {
|
|
48778
|
+
const { text, w } = labelInfo(p);
|
|
48779
|
+
let x = p.cx + p.r + GAP;
|
|
48780
|
+
let anchor = "start";
|
|
48781
|
+
if (x + w > width) {
|
|
48782
|
+
x = p.cx - p.r - GAP - w;
|
|
48783
|
+
anchor = "end";
|
|
48784
|
+
}
|
|
48785
|
+
const y = Math.max(0, Math.min(p.cy - poiLabH / 2, height - poiLabH));
|
|
48786
|
+
labels.push({
|
|
48787
|
+
x: anchor === "start" ? x : x + w,
|
|
48788
|
+
y: y + poiLabH / 2 + FONT2 / 3,
|
|
48789
|
+
text,
|
|
48790
|
+
anchor,
|
|
48791
|
+
color: palette.text,
|
|
48792
|
+
halo: false,
|
|
48793
|
+
haloColor: palette.bg,
|
|
48794
|
+
poiId: p.id,
|
|
48795
|
+
hidden: true,
|
|
48796
|
+
lineNumber: p.lineNumber
|
|
47546
48797
|
});
|
|
47547
48798
|
};
|
|
47548
|
-
for (const
|
|
48799
|
+
for (const [clusterId, members] of clusterMembersById) {
|
|
48800
|
+
if (members.length === 0) continue;
|
|
48801
|
+
const items = makeItems(members);
|
|
48802
|
+
const side = wouldColumnBeClean(items, "right") ? "right" : wouldColumnBeClean(items, "left") ? "left" : defaultColumnSide(items);
|
|
48803
|
+
commitColumn(items, side, clusterId);
|
|
48804
|
+
}
|
|
48805
|
+
const maxExtent = MAX_CLUSTER_EXTENT_FACTOR * Math.min(width, height);
|
|
48806
|
+
const clusterPending = [];
|
|
48807
|
+
for (const g of groups2) {
|
|
48808
|
+
const items = makeItems(g);
|
|
47549
48809
|
if (g.length === 1) {
|
|
47550
|
-
const p =
|
|
47551
|
-
const { text, w } = labelInfo(p);
|
|
48810
|
+
const { p, text, w } = items[0];
|
|
47552
48811
|
const side = ["right", "left", "above", "below"].find(
|
|
47553
48812
|
(s) => inlineFits(p, w, s)
|
|
47554
48813
|
);
|
|
47555
|
-
if (side)
|
|
47556
|
-
|
|
47557
|
-
|
|
48814
|
+
if (side) pushInline(p, text, w, side);
|
|
48815
|
+
else commitColumn(items, defaultColumnSide(items));
|
|
48816
|
+
continue;
|
|
48817
|
+
}
|
|
48818
|
+
const left = Math.min(...items.map((o) => o.p.cx - o.p.r));
|
|
48819
|
+
const right = Math.max(...items.map((o) => o.p.cx + o.p.r));
|
|
48820
|
+
const minCy = Math.min(...items.map((o) => o.p.cy));
|
|
48821
|
+
const maxCy = Math.max(...items.map((o) => o.p.cy));
|
|
48822
|
+
const diag = Math.hypot(right - left, maxCy - minCy);
|
|
48823
|
+
if (diag > maxExtent || items.length > MAX_COLUMN_ROWS) {
|
|
48824
|
+
items.forEach((o) => pushHidden(o.p));
|
|
48825
|
+
} else {
|
|
48826
|
+
clusterPending.push(items);
|
|
48827
|
+
}
|
|
48828
|
+
}
|
|
48829
|
+
for (const items of clusterPending) {
|
|
48830
|
+
const side = ["right", "left"].find(
|
|
48831
|
+
(s) => wouldColumnBeClean(items, s)
|
|
48832
|
+
);
|
|
48833
|
+
if (side) commitColumn(items, side);
|
|
48834
|
+
else items.forEach((o) => pushHidden(o.p));
|
|
48835
|
+
}
|
|
48836
|
+
}
|
|
48837
|
+
if (resolved.directives.noContextLabels !== true) {
|
|
48838
|
+
for (const l of labels) {
|
|
48839
|
+
if (l.hidden) continue;
|
|
48840
|
+
const w = labelW(l.text);
|
|
48841
|
+
const x = l.anchor === "start" ? l.x : l.anchor === "end" ? l.x - w : l.x - w / 2;
|
|
48842
|
+
obstacles.push({ x, y: l.y - labelH / 2, w, h: labelH });
|
|
48843
|
+
}
|
|
48844
|
+
for (const box of insets)
|
|
48845
|
+
obstacles.push({ x: box.x, y: box.y, w: box.w, h: box.h });
|
|
48846
|
+
const countryCandidates = [];
|
|
48847
|
+
for (const f of worldLayer.values()) {
|
|
48848
|
+
const iso = typeof f.id === "string" ? f.id : String(f.id ?? "");
|
|
48849
|
+
if (!iso || regionById.has(iso)) continue;
|
|
48850
|
+
let hasReferencedSub = false;
|
|
48851
|
+
for (const k of regionById.keys())
|
|
48852
|
+
if (k.startsWith(iso + "-")) {
|
|
48853
|
+
hasReferencedSub = true;
|
|
48854
|
+
break;
|
|
47558
48855
|
}
|
|
48856
|
+
if (hasReferencedSub) continue;
|
|
48857
|
+
const b = path.bounds(f);
|
|
48858
|
+
const [x0, y0] = b[0];
|
|
48859
|
+
const [x1, y1] = b[1];
|
|
48860
|
+
if (!Number.isFinite(x0) || !Number.isFinite(x1)) continue;
|
|
48861
|
+
const anchorLngLat = WORLD_LABEL_ANCHORS[iso];
|
|
48862
|
+
const a = anchorLngLat ? project(anchorLngLat[0], anchorLngLat[1]) : path.centroid(f);
|
|
48863
|
+
countryCandidates.push({
|
|
48864
|
+
name: f.properties?.name ?? iso,
|
|
48865
|
+
bbox: [x0, y0, x1, y1],
|
|
48866
|
+
anchor: a && Number.isFinite(a[0]) ? [a[0], a[1]] : null
|
|
48867
|
+
});
|
|
48868
|
+
}
|
|
48869
|
+
const framedStateContainers = (resolved.poiFrameContainers ?? []).some(
|
|
48870
|
+
(id) => id.startsWith("US-")
|
|
48871
|
+
);
|
|
48872
|
+
if (usLayer && framedStateContainers) {
|
|
48873
|
+
const containerSet = new Set(resolved.poiFrameContainers);
|
|
48874
|
+
for (const [iso, f] of usLayer) {
|
|
48875
|
+
if (containerSet.has(iso) || regionById.has(iso)) continue;
|
|
48876
|
+
const viewF = cullFeatureToView(f);
|
|
48877
|
+
if (!viewF) continue;
|
|
48878
|
+
const b = path.bounds(viewF);
|
|
48879
|
+
const [x0, y0] = b[0];
|
|
48880
|
+
const [x1, y1] = b[1];
|
|
48881
|
+
if (!Number.isFinite(x0) || !Number.isFinite(x1)) continue;
|
|
48882
|
+
const a = path.centroid(viewF);
|
|
48883
|
+
countryCandidates.push({
|
|
48884
|
+
name: f.properties?.name ?? iso,
|
|
48885
|
+
bbox: [x0, y0, x1, y1],
|
|
48886
|
+
anchor: a && Number.isFinite(a[0]) ? [a[0], a[1]] : null
|
|
48887
|
+
});
|
|
47559
48888
|
}
|
|
47560
|
-
placeColumn(g);
|
|
47561
48889
|
}
|
|
48890
|
+
const contextLabels = placeContextLabels({
|
|
48891
|
+
projection: resolved.projection,
|
|
48892
|
+
dLonSpan,
|
|
48893
|
+
dLatSpan,
|
|
48894
|
+
width,
|
|
48895
|
+
height,
|
|
48896
|
+
waterBodies: data.waterBodies,
|
|
48897
|
+
countries: countryCandidates,
|
|
48898
|
+
palette,
|
|
48899
|
+
project,
|
|
48900
|
+
collides,
|
|
48901
|
+
// Water labels must stay over open water — `fillAt` returns the ocean
|
|
48902
|
+
// backdrop colour off-land and a region fill on-land (lakes/states count
|
|
48903
|
+
// as land here, which is the safe side for an ocean name).
|
|
48904
|
+
overLand: (x, y) => fillAt(x, y) !== water
|
|
48905
|
+
});
|
|
48906
|
+
labels.push(...contextLabels);
|
|
47562
48907
|
}
|
|
47563
48908
|
let legend = null;
|
|
47564
48909
|
if (!resolved.directives.noLegend) {
|
|
@@ -47595,60 +48940,104 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47595
48940
|
rivers,
|
|
47596
48941
|
relief,
|
|
47597
48942
|
reliefHatch,
|
|
48943
|
+
coastlineStyle,
|
|
47598
48944
|
legs,
|
|
47599
48945
|
pois,
|
|
48946
|
+
clusters,
|
|
47600
48947
|
labels,
|
|
47601
48948
|
legend,
|
|
47602
48949
|
insets,
|
|
47603
48950
|
insetRegions,
|
|
47604
48951
|
projection,
|
|
47605
|
-
stretch: stretchParams
|
|
48952
|
+
stretch: stretchParams,
|
|
48953
|
+
diagnostics: []
|
|
47606
48954
|
};
|
|
47607
48955
|
}
|
|
47608
|
-
var import_d3_geo2, import_topojson_client2, FIT_PAD,
|
|
48956
|
+
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;
|
|
47609
48957
|
var init_layout15 = __esm({
|
|
47610
48958
|
"src/map/layout.ts"() {
|
|
47611
48959
|
"use strict";
|
|
47612
48960
|
import_d3_geo2 = require("d3-geo");
|
|
47613
48961
|
import_topojson_client2 = require("topojson-client");
|
|
47614
48962
|
init_color_utils();
|
|
48963
|
+
init_geo();
|
|
48964
|
+
init_colorize();
|
|
47615
48965
|
init_colors();
|
|
47616
48966
|
init_label_layout();
|
|
47617
48967
|
init_legend_constants();
|
|
47618
48968
|
init_title_constants();
|
|
48969
|
+
init_context_labels();
|
|
47619
48970
|
FIT_PAD = 24;
|
|
47620
|
-
|
|
48971
|
+
RAMP_FLOOR2 = 15;
|
|
47621
48972
|
R_DEFAULT = 6;
|
|
47622
48973
|
R_MIN = 4;
|
|
47623
48974
|
R_MAX = 22;
|
|
47624
48975
|
W_MIN = 1.25;
|
|
47625
48976
|
W_MAX = 8;
|
|
47626
|
-
|
|
47627
|
-
|
|
48977
|
+
FONT2 = 11;
|
|
48978
|
+
WORLD_LABEL_ANCHORS = {
|
|
48979
|
+
US: [-98.5, 39.5]
|
|
48980
|
+
// CONUS geographic centre (near Lebanon, Kansas)
|
|
48981
|
+
};
|
|
48982
|
+
MAX_CLUSTER_EXTENT_FACTOR = 0.18;
|
|
48983
|
+
MAX_COLUMN_ROWS = 7;
|
|
48984
|
+
REGION_LABEL_HALO_RATIO = 4.5;
|
|
47628
48985
|
LAND_TINT_LIGHT = 12;
|
|
47629
48986
|
LAND_TINT_DARK = 24;
|
|
47630
48987
|
TAG_TINT_LIGHT = 60;
|
|
47631
48988
|
TAG_TINT_DARK = 68;
|
|
47632
|
-
WATER_TINT_LIGHT =
|
|
47633
|
-
WATER_TINT_DARK =
|
|
48989
|
+
WATER_TINT_LIGHT = 24;
|
|
48990
|
+
WATER_TINT_DARK = 24;
|
|
47634
48991
|
RIVER_WIDTH = 1.3;
|
|
48992
|
+
COMPACT_WIDTH_PX = 480;
|
|
47635
48993
|
RELIEF_MIN_AREA = 12;
|
|
47636
48994
|
RELIEF_MIN_DIM = 2;
|
|
47637
|
-
RELIEF_HATCH_SPACING =
|
|
47638
|
-
RELIEF_HATCH_WIDTH = 0.
|
|
47639
|
-
RELIEF_HATCH_STRENGTH =
|
|
48995
|
+
RELIEF_HATCH_SPACING = 1.5;
|
|
48996
|
+
RELIEF_HATCH_WIDTH = 0.2;
|
|
48997
|
+
RELIEF_HATCH_STRENGTH = 26;
|
|
48998
|
+
COASTLINE_RING_COUNT = 5;
|
|
48999
|
+
COASTLINE_D0 = 16e-4;
|
|
49000
|
+
COASTLINE_STEP = 28e-4;
|
|
49001
|
+
COASTLINE_THICKNESS = 14e-4;
|
|
49002
|
+
COASTLINE_OPACITY_NEAR = 0.5;
|
|
49003
|
+
COASTLINE_OPACITY_FAR = 0.1;
|
|
49004
|
+
COASTLINE_MIN_EXTENT = 6e-4;
|
|
49005
|
+
COASTLINE_MIN_EXTENT_GLOBAL = 6e-4;
|
|
49006
|
+
COASTLINE_STROKE_MIX = 32;
|
|
47640
49007
|
FOREIGN_TINT_LIGHT = 30;
|
|
47641
49008
|
FOREIGN_TINT_DARK = 62;
|
|
47642
49009
|
MUTED_FOREIGN_LIGHT = 28;
|
|
47643
49010
|
MUTED_FOREIGN_DARK = 16;
|
|
47644
49011
|
COLO_R = 9;
|
|
47645
49012
|
GOLDEN_ANGLE = 2.399963229728653;
|
|
49013
|
+
STACK_OVERLAP = 1;
|
|
49014
|
+
STACK_RING_MAX = 8;
|
|
49015
|
+
STACK_RING_GAP = 4;
|
|
47646
49016
|
FAN_STEP = 16;
|
|
47647
49017
|
ARC_CURVE_FRAC = 0.18;
|
|
49018
|
+
decodeCache = /* @__PURE__ */ new WeakMap();
|
|
47648
49019
|
usConusProjection = () => (0, import_d3_geo2.geoConicEqualArea)().parallels([29.5, 45.5]).rotate([96, 0]);
|
|
47649
49020
|
alaskaProjection = () => (0, import_d3_geo2.geoConicEqualArea)().rotate([154, 0]).center([-2, 58.5]).parallels([55, 65]);
|
|
47650
49021
|
hawaiiProjection = () => (0, import_d3_geo2.geoMercator)();
|
|
47651
49022
|
INSET_STATES = /* @__PURE__ */ new Set(["US-AK", "US-HI"]);
|
|
49023
|
+
inAlaska = (lon, lat) => lat >= 51 && (lon <= -129 || lon >= 172);
|
|
49024
|
+
inHawaii = (lon, lat) => lat >= 18 && lat <= 23 && lon >= -161 && lon <= -154;
|
|
49025
|
+
FOREIGN_BORDER = {
|
|
49026
|
+
CA: [
|
|
49027
|
+
"US-AK",
|
|
49028
|
+
"US-WA",
|
|
49029
|
+
"US-ID",
|
|
49030
|
+
"US-MT",
|
|
49031
|
+
"US-ND",
|
|
49032
|
+
"US-MN",
|
|
49033
|
+
"US-MI",
|
|
49034
|
+
"US-NY",
|
|
49035
|
+
"US-VT",
|
|
49036
|
+
"US-NH",
|
|
49037
|
+
"US-ME"
|
|
49038
|
+
],
|
|
49039
|
+
MX: ["US-CA", "US-AZ", "US-NM", "US-TX"]
|
|
49040
|
+
};
|
|
47652
49041
|
US_NON_CONUS = /* @__PURE__ */ new Set([
|
|
47653
49042
|
"US-AK",
|
|
47654
49043
|
"US-HI",
|
|
@@ -47667,6 +49056,98 @@ __export(renderer_exports16, {
|
|
|
47667
49056
|
renderMap: () => renderMap,
|
|
47668
49057
|
renderMapForExport: () => renderMapForExport
|
|
47669
49058
|
});
|
|
49059
|
+
function pointInRing2(px, py, ring) {
|
|
49060
|
+
let inside = false;
|
|
49061
|
+
for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {
|
|
49062
|
+
const [xi, yi] = ring[i];
|
|
49063
|
+
const [xj, yj] = ring[j];
|
|
49064
|
+
if (yi > py !== yj > py && px < (xj - xi) * (py - yi) / (yj - yi) + xi)
|
|
49065
|
+
inside = !inside;
|
|
49066
|
+
}
|
|
49067
|
+
return inside;
|
|
49068
|
+
}
|
|
49069
|
+
function ringToPath(ring) {
|
|
49070
|
+
let d = "";
|
|
49071
|
+
for (let i = 0; i < ring.length; i++)
|
|
49072
|
+
d += (i ? "L" : "M") + ring[i][0] + "," + ring[i][1];
|
|
49073
|
+
return d + "Z";
|
|
49074
|
+
}
|
|
49075
|
+
function polylineToPath(pts) {
|
|
49076
|
+
let d = "";
|
|
49077
|
+
for (let i = 0; i < pts.length; i++)
|
|
49078
|
+
d += (i ? "L" : "M") + pts[i][0] + "," + pts[i][1];
|
|
49079
|
+
return d;
|
|
49080
|
+
}
|
|
49081
|
+
function ringToCoastPaths(ring, frame) {
|
|
49082
|
+
if (!frame) return [ringToPath(ring)];
|
|
49083
|
+
const n = ring.length;
|
|
49084
|
+
const eps = 0.75;
|
|
49085
|
+
const onL = (x) => Math.abs(x) <= eps;
|
|
49086
|
+
const onR = (x) => Math.abs(x - frame.w) <= eps;
|
|
49087
|
+
const onT = (y) => Math.abs(y) <= eps;
|
|
49088
|
+
const onB = (y) => Math.abs(y - frame.h) <= eps;
|
|
49089
|
+
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]);
|
|
49090
|
+
let firstBreak = -1;
|
|
49091
|
+
for (let i = 0; i < n; i++)
|
|
49092
|
+
if (isFrameEdge(ring[i], ring[(i + 1) % n])) {
|
|
49093
|
+
firstBreak = i;
|
|
49094
|
+
break;
|
|
49095
|
+
}
|
|
49096
|
+
if (firstBreak === -1) return [ringToPath(ring)];
|
|
49097
|
+
const paths = [];
|
|
49098
|
+
let cur = [];
|
|
49099
|
+
const start = (firstBreak + 1) % n;
|
|
49100
|
+
for (let k = 0; k < n; k++) {
|
|
49101
|
+
const i = (start + k) % n;
|
|
49102
|
+
const a = ring[i];
|
|
49103
|
+
const b = ring[(i + 1) % n];
|
|
49104
|
+
if (isFrameEdge(a, b)) {
|
|
49105
|
+
if (cur.length >= 2) paths.push(polylineToPath(cur));
|
|
49106
|
+
cur = [];
|
|
49107
|
+
continue;
|
|
49108
|
+
}
|
|
49109
|
+
if (cur.length === 0) cur.push(a);
|
|
49110
|
+
cur.push(b);
|
|
49111
|
+
}
|
|
49112
|
+
if (cur.length >= 2) paths.push(polylineToPath(cur));
|
|
49113
|
+
return paths;
|
|
49114
|
+
}
|
|
49115
|
+
function coastlineOuterRings(regions, minExtent, frame) {
|
|
49116
|
+
const paths = [];
|
|
49117
|
+
for (const r of regions) {
|
|
49118
|
+
const rings = parsePathRings(r.d);
|
|
49119
|
+
for (let i = 0; i < rings.length; i++) {
|
|
49120
|
+
const ring = rings[i];
|
|
49121
|
+
if (ring.length < 3) continue;
|
|
49122
|
+
let minX = Infinity;
|
|
49123
|
+
let minY = Infinity;
|
|
49124
|
+
let maxX = -Infinity;
|
|
49125
|
+
let maxY = -Infinity;
|
|
49126
|
+
for (const [x, y] of ring) {
|
|
49127
|
+
if (x < minX) minX = x;
|
|
49128
|
+
if (x > maxX) maxX = x;
|
|
49129
|
+
if (y < minY) minY = y;
|
|
49130
|
+
if (y > maxY) maxY = y;
|
|
49131
|
+
}
|
|
49132
|
+
if (Math.max(maxX - minX, maxY - minY) < minExtent) continue;
|
|
49133
|
+
const [fx, fy] = ring[0];
|
|
49134
|
+
let depth = 0;
|
|
49135
|
+
for (let j = 0; j < rings.length; j++)
|
|
49136
|
+
if (j !== i && pointInRing2(fx, fy, rings[j])) depth++;
|
|
49137
|
+
if (depth % 2 === 1) continue;
|
|
49138
|
+
paths.push(...ringToCoastPaths(ring, frame));
|
|
49139
|
+
}
|
|
49140
|
+
}
|
|
49141
|
+
return paths;
|
|
49142
|
+
}
|
|
49143
|
+
function appendWaterLines(g, outerRings, style, flatWater) {
|
|
49144
|
+
const d = outerRings.join(" ");
|
|
49145
|
+
const linesOuterFirst = [...style.lines].sort((a, b) => b.d - a.d);
|
|
49146
|
+
for (const line12 of linesOuterFirst) {
|
|
49147
|
+
g.append("path").attr("d", d).attr("stroke", style.color).attr("stroke-width", 2 * (line12.d + line12.thickness)).attr("stroke-opacity", line12.opacity).attr("stroke-linejoin", "round").attr("stroke-linecap", "round");
|
|
49148
|
+
g.append("path").attr("d", d).attr("stroke", flatWater).attr("stroke-width", 2 * line12.d).attr("stroke-linejoin", "round").attr("stroke-linecap", "round");
|
|
49149
|
+
}
|
|
49150
|
+
}
|
|
47670
49151
|
function renderMap(container, resolved, data, palette, isDark, onClickItem, exportDims, activeGroupOverride) {
|
|
47671
49152
|
d3Selection18.select(container).selectAll(":not([data-d3-tooltip])").remove();
|
|
47672
49153
|
const width = exportDims?.width ?? container.clientWidth;
|
|
@@ -47679,6 +49160,11 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
47679
49160
|
{
|
|
47680
49161
|
palette,
|
|
47681
49162
|
isDark,
|
|
49163
|
+
// Export-only: forward the contain-fit request from mapExportDimensions so a
|
|
49164
|
+
// clamped/floored (off-aspect) export canvas letterboxes instead of
|
|
49165
|
+
// stretch-distorting. The in-app preview pane passes no exportDims → unset →
|
|
49166
|
+
// keeps the global stretch-fill.
|
|
49167
|
+
preferContain: exportDims?.preferContain ?? false,
|
|
47682
49168
|
...activeGroupOverride !== void 0 && {
|
|
47683
49169
|
activeGroup: activeGroupOverride
|
|
47684
49170
|
}
|
|
@@ -47692,6 +49178,11 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
47692
49178
|
const gRegions = svg.append("g").attr("class", "dgmo-map-regions");
|
|
47693
49179
|
const drawRegion = (g, r, strokeWidth) => {
|
|
47694
49180
|
const p = g.append("path").attr("d", r.d).attr("fill", r.fill).attr("stroke", r.stroke).attr("stroke-width", strokeWidth);
|
|
49181
|
+
if (r.label) p.attr("data-region-name", r.label);
|
|
49182
|
+
if (r.id && r.id !== "lake") p.attr("data-iso", r.id);
|
|
49183
|
+
if (r.labelX !== void 0 && r.labelY !== void 0) {
|
|
49184
|
+
p.attr("data-label-x", r.labelX).attr("data-label-y", r.labelY);
|
|
49185
|
+
}
|
|
47695
49186
|
if (r.layer !== "base") {
|
|
47696
49187
|
p.classed("dgmo-map-region", true).attr("data-region", r.id);
|
|
47697
49188
|
if (r.value !== void 0) p.attr("data-value", r.value);
|
|
@@ -47721,28 +49212,112 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
47721
49212
|
const landClip = defs.append("clipPath").attr("id", landClipId);
|
|
47722
49213
|
for (const r of layout.regions)
|
|
47723
49214
|
if (r.id !== "lake") landClip.append("path").attr("d", r.d);
|
|
47724
|
-
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");
|
|
49215
|
+
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");
|
|
47725
49216
|
for (let y = h.spacing; y < height; y += h.spacing) {
|
|
47726
49217
|
gRelief.append("line").attr("x1", 0).attr("y1", y).attr("x2", width).attr("y2", y);
|
|
47727
49218
|
}
|
|
47728
49219
|
}
|
|
49220
|
+
if (layout.coastlineStyle) {
|
|
49221
|
+
const cs = layout.coastlineStyle;
|
|
49222
|
+
const maskId = "dgmo-map-water-mask";
|
|
49223
|
+
const mask = defs.append("mask").attr("id", maskId).attr("maskUnits", "userSpaceOnUse").attr("x", 0).attr("y", 0).attr("width", width).attr("height", height);
|
|
49224
|
+
mask.append("rect").attr("x", 0).attr("y", 0).attr("width", width).attr("height", height).attr("fill", "white");
|
|
49225
|
+
const landD = layout.regions.filter((r) => r.id !== "lake").map((r) => r.d).join(" ");
|
|
49226
|
+
const lakeD = layout.regions.filter((r) => r.id === "lake").map((r) => r.d).join(" ");
|
|
49227
|
+
if (landD) mask.append("path").attr("d", landD).attr("fill", "black");
|
|
49228
|
+
if (lakeD) mask.append("path").attr("d", lakeD).attr("fill", "white");
|
|
49229
|
+
if (layout.insets.length) {
|
|
49230
|
+
const reach = Math.max(0, ...cs.lines.map((l) => l.d + l.thickness));
|
|
49231
|
+
for (const box of layout.insets) {
|
|
49232
|
+
const d = box.points.map((p, i) => `${i ? "L" : "M"}${p[0]},${p[1]}`).join("") + "Z";
|
|
49233
|
+
mask.append("path").attr("d", d).attr("fill", "black").attr("stroke", "black").attr("stroke-width", 2 * reach).attr("stroke-linejoin", "round");
|
|
49234
|
+
}
|
|
49235
|
+
}
|
|
49236
|
+
const gWater = svg.append("g").attr("class", "dgmo-map-water-lines").attr("fill", "none").style("pointer-events", "none").attr("mask", `url(#${maskId})`);
|
|
49237
|
+
appendWaterLines(
|
|
49238
|
+
gWater,
|
|
49239
|
+
// Pass the canvas frame so edges collinear with it (the antimeridian on a
|
|
49240
|
+
// world map, regional clipExtent cuts) don't get ringed as fake coast —
|
|
49241
|
+
// land runs cleanly to the render-area edge.
|
|
49242
|
+
coastlineOuterRings(layout.regions, cs.minExtent, {
|
|
49243
|
+
w: width,
|
|
49244
|
+
h: height
|
|
49245
|
+
}),
|
|
49246
|
+
cs,
|
|
49247
|
+
layout.background
|
|
49248
|
+
);
|
|
49249
|
+
const byStroke = /* @__PURE__ */ new Map();
|
|
49250
|
+
for (const r of layout.regions) {
|
|
49251
|
+
const arr = byStroke.get(r.stroke);
|
|
49252
|
+
if (arr) arr.push(r.d);
|
|
49253
|
+
else byStroke.set(r.stroke, [r.d]);
|
|
49254
|
+
}
|
|
49255
|
+
for (const [stroke2, ds] of byStroke)
|
|
49256
|
+
gWater.append("path").attr("d", ds.join(" ")).attr("stroke", stroke2).attr("stroke-width", 0.5).attr("stroke-linejoin", "round");
|
|
49257
|
+
}
|
|
47729
49258
|
if (layout.rivers.length) {
|
|
47730
|
-
const gRivers = svg.append("g").attr("class", "dgmo-map-rivers").attr("fill", "none");
|
|
49259
|
+
const gRivers = svg.append("g").attr("class", "dgmo-map-rivers").attr("fill", "none").style("pointer-events", "none");
|
|
47731
49260
|
for (const r of layout.rivers) {
|
|
47732
49261
|
gRivers.append("path").attr("d", r.d).attr("stroke", r.color).attr("stroke-width", r.width).attr("stroke-linecap", "round").attr("stroke-linejoin", "round");
|
|
47733
49262
|
}
|
|
47734
49263
|
}
|
|
47735
49264
|
if (layout.insets.length) {
|
|
47736
49265
|
const insetG = svg.append("g").attr("class", "dgmo-map-insets");
|
|
47737
|
-
|
|
49266
|
+
layout.insets.forEach((box, bi) => {
|
|
47738
49267
|
const d = box.points.map((p, i) => `${i ? "L" : "M"}${p[0]},${p[1]}`).join("") + "Z";
|
|
47739
49268
|
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");
|
|
47740
|
-
|
|
49269
|
+
if (box.contextLand) {
|
|
49270
|
+
const clipId = `dgmo-map-inset-clip-${bi}`;
|
|
49271
|
+
defs.append("clipPath").attr("id", clipId).append("path").attr("d", d);
|
|
49272
|
+
insetG.append("path").attr("d", box.contextLand.d).attr("fill", box.contextLand.fill).attr("clip-path", `url(#${clipId})`);
|
|
49273
|
+
}
|
|
49274
|
+
});
|
|
47741
49275
|
for (const r of layout.insetRegions) drawRegion(insetG, r, 0.5);
|
|
47742
|
-
|
|
49276
|
+
if (layout.coastlineStyle) {
|
|
49277
|
+
const cs = layout.coastlineStyle;
|
|
49278
|
+
const maskId = "dgmo-map-inset-water-mask";
|
|
49279
|
+
const mask = defs.append("mask").attr("id", maskId).attr("maskUnits", "userSpaceOnUse").attr("x", 0).attr("y", 0).attr("width", width).attr("height", height);
|
|
49280
|
+
for (const box of layout.insets) {
|
|
49281
|
+
const d = box.points.map((p, i) => `${i ? "L" : "M"}${p[0]},${p[1]}`).join("") + "Z";
|
|
49282
|
+
mask.append("path").attr("d", d).attr("fill", "white");
|
|
49283
|
+
}
|
|
49284
|
+
layout.insets.forEach((box, bi) => {
|
|
49285
|
+
if (box.contextLand)
|
|
49286
|
+
mask.append("path").attr("d", box.contextLand.d).attr("fill", "black").attr("clip-path", `url(#dgmo-map-inset-clip-${bi})`);
|
|
49287
|
+
});
|
|
49288
|
+
for (const r of layout.insetRegions)
|
|
49289
|
+
if (r.id !== "lake")
|
|
49290
|
+
mask.append("path").attr("d", r.d).attr("fill", "black");
|
|
49291
|
+
for (const r of layout.insetRegions)
|
|
49292
|
+
if (r.id === "lake")
|
|
49293
|
+
mask.append("path").attr("d", r.d).attr("fill", "white");
|
|
49294
|
+
const clipId = "dgmo-map-inset-water-clip";
|
|
49295
|
+
const clip = defs.append("clipPath").attr("id", clipId);
|
|
49296
|
+
for (const box of layout.insets) {
|
|
49297
|
+
const d = box.points.map((p, i) => `${i ? "L" : "M"}${p[0]},${p[1]}`).join("") + "Z";
|
|
49298
|
+
clip.append("path").attr("d", d);
|
|
49299
|
+
}
|
|
49300
|
+
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})`);
|
|
49301
|
+
appendWaterLines(
|
|
49302
|
+
gInsetWater,
|
|
49303
|
+
coastlineOuterRings(layout.insetRegions, cs.minExtent),
|
|
49304
|
+
cs,
|
|
49305
|
+
layout.background
|
|
49306
|
+
);
|
|
49307
|
+
for (const r of layout.insetRegions)
|
|
49308
|
+
gInsetWater.append("path").attr("d", r.d).attr("stroke", r.stroke).attr("stroke-width", 0.5).attr("stroke-linejoin", "round");
|
|
49309
|
+
}
|
|
49310
|
+
}
|
|
49311
|
+
const wireSync = (sel, lineNumber) => {
|
|
49312
|
+
if (lineNumber < 1) return;
|
|
49313
|
+
sel.attr("data-line-number", lineNumber);
|
|
49314
|
+
if (onClickItem)
|
|
49315
|
+
sel.style("cursor", "pointer").on("click", () => onClickItem(lineNumber));
|
|
49316
|
+
};
|
|
47743
49317
|
const gLegs = svg.append("g").attr("class", "dgmo-map-legs").attr("fill", "none");
|
|
47744
49318
|
layout.legs.forEach((leg, i) => {
|
|
47745
49319
|
const p = gLegs.append("path").attr("d", leg.d).attr("stroke", leg.color).attr("stroke-width", leg.width).attr("stroke-linecap", "round");
|
|
49320
|
+
wireSync(p, leg.lineNumber);
|
|
47746
49321
|
if (leg.arrow) {
|
|
47747
49322
|
const id = `dgmo-map-arrow-${i}`;
|
|
47748
49323
|
const s = arrowSize(leg.width);
|
|
@@ -47750,25 +49325,38 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
47750
49325
|
p.attr("marker-end", `url(#${id})`);
|
|
47751
49326
|
}
|
|
47752
49327
|
if (leg.label !== void 0 && leg.labelX !== void 0) {
|
|
47753
|
-
emitText(
|
|
49328
|
+
const lt = emitText(
|
|
47754
49329
|
gLegs,
|
|
47755
49330
|
leg.labelX,
|
|
47756
49331
|
leg.labelY ?? 0,
|
|
47757
49332
|
leg.label,
|
|
47758
49333
|
"middle",
|
|
47759
|
-
palette.textMuted,
|
|
47760
|
-
haloColor,
|
|
47761
|
-
true,
|
|
49334
|
+
leg.labelColor ?? palette.textMuted,
|
|
49335
|
+
leg.labelHaloColor ?? haloColor,
|
|
49336
|
+
leg.labelHalo ?? true,
|
|
47762
49337
|
LABEL_FONT - 1
|
|
47763
49338
|
);
|
|
49339
|
+
wireSync(lt, leg.lineNumber);
|
|
47764
49340
|
}
|
|
47765
49341
|
});
|
|
49342
|
+
const gSpider = svg.append("g").attr("class", "dgmo-map-spider");
|
|
49343
|
+
for (const cl of layout.clusters) {
|
|
49344
|
+
if (!exportDims) {
|
|
49345
|
+
gSpider.append("circle").attr("cx", cl.cx).attr("cy", cl.cy).attr("r", cl.hitR).attr("fill", "transparent").attr("data-cluster-hit", cl.id).style("cursor", "pointer");
|
|
49346
|
+
}
|
|
49347
|
+
for (const leg of cl.legs) {
|
|
49348
|
+
gSpider.append("line").attr("x1", cl.cx).attr("y1", cl.cy).attr("x2", leg.x2).attr("y2", leg.y2).attr("stroke", leg.color).attr("stroke-width", 1).attr("data-cluster-deco", cl.id).style("pointer-events", "none");
|
|
49349
|
+
}
|
|
49350
|
+
gSpider.append("circle").attr("cx", cl.cx).attr("cy", cl.cy).attr("r", 2).attr("fill", mix(palette.textMuted, palette.bg, 40)).attr("data-cluster-deco", cl.id).style("pointer-events", "none");
|
|
49351
|
+
}
|
|
47766
49352
|
const gPois = svg.append("g").attr("class", "dgmo-map-pois");
|
|
47767
49353
|
for (const poi of layout.pois) {
|
|
47768
49354
|
if (poi.isOrigin) {
|
|
47769
49355
|
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);
|
|
47770
49356
|
}
|
|
47771
49357
|
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);
|
|
49358
|
+
if (poi.clusterId !== void 0)
|
|
49359
|
+
c.attr("data-cluster-member", poi.clusterId);
|
|
47772
49360
|
if (poi.tags) {
|
|
47773
49361
|
for (const [group, value] of Object.entries(poi.tags)) {
|
|
47774
49362
|
c.attr(`data-tag-${group.toLowerCase()}`, value.toLowerCase());
|
|
@@ -47796,12 +49384,32 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
47796
49384
|
}
|
|
47797
49385
|
const gLabels = svg.append("g").attr("class", "dgmo-map-labels");
|
|
47798
49386
|
for (const lab of layout.labels) {
|
|
49387
|
+
if (lab.hidden) {
|
|
49388
|
+
if (exportDims) continue;
|
|
49389
|
+
emitText(
|
|
49390
|
+
gLabels,
|
|
49391
|
+
lab.x,
|
|
49392
|
+
lab.y,
|
|
49393
|
+
lab.text,
|
|
49394
|
+
lab.anchor,
|
|
49395
|
+
lab.color,
|
|
49396
|
+
lab.haloColor,
|
|
49397
|
+
lab.halo,
|
|
49398
|
+
LABEL_FONT,
|
|
49399
|
+
lab.italic,
|
|
49400
|
+
lab.letterSpacing
|
|
49401
|
+
).attr("data-poi", lab.poiId ?? null).attr("data-poi-hidden", "").style("opacity", 0).style("pointer-events", "none");
|
|
49402
|
+
continue;
|
|
49403
|
+
}
|
|
47799
49404
|
if (lab.leader) {
|
|
47800
49405
|
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(
|
|
47801
49406
|
"stroke",
|
|
47802
49407
|
lab.leaderColor ?? mix(palette.textMuted, palette.bg, 60)
|
|
47803
49408
|
).attr("stroke-width", lab.leaderColor ? 1 : 0.75);
|
|
47804
49409
|
if (lab.poiId !== void 0) line12.attr("data-poi", lab.poiId);
|
|
49410
|
+
if (lab.clusterMember !== void 0)
|
|
49411
|
+
line12.attr("data-cluster-member", lab.clusterMember);
|
|
49412
|
+
wireSync(line12, lab.lineNumber);
|
|
47805
49413
|
}
|
|
47806
49414
|
const t = emitText(
|
|
47807
49415
|
gLabels,
|
|
@@ -47812,11 +49420,38 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
47812
49420
|
lab.color,
|
|
47813
49421
|
lab.haloColor,
|
|
47814
49422
|
lab.halo,
|
|
47815
|
-
LABEL_FONT
|
|
49423
|
+
LABEL_FONT,
|
|
49424
|
+
lab.italic,
|
|
49425
|
+
lab.letterSpacing,
|
|
49426
|
+
lab.lines
|
|
47816
49427
|
);
|
|
47817
49428
|
if (lab.poiId !== void 0) {
|
|
47818
49429
|
t.attr("data-poi", lab.poiId).style("cursor", "default");
|
|
47819
49430
|
}
|
|
49431
|
+
if (lab.clusterMember !== void 0) {
|
|
49432
|
+
t.attr("data-cluster-member", lab.clusterMember);
|
|
49433
|
+
}
|
|
49434
|
+
wireSync(t, lab.lineNumber);
|
|
49435
|
+
}
|
|
49436
|
+
if (!exportDims && layout.clusters.length) {
|
|
49437
|
+
const gBadge = svg.append("g").attr("class", "dgmo-map-cluster-badges");
|
|
49438
|
+
for (const cl of layout.clusters) {
|
|
49439
|
+
const g = gBadge.append("g").attr("data-cluster", cl.id).style("opacity", 0).style("pointer-events", "none");
|
|
49440
|
+
const R = 9;
|
|
49441
|
+
g.append("circle").attr("cx", cl.cx).attr("cy", cl.cy).attr("r", R).attr("fill", mix(palette.textMuted, palette.bg, 35)).attr("stroke", palette.textMuted).attr("stroke-width", 1);
|
|
49442
|
+
g.append("circle").attr("cx", cl.cx).attr("cy", cl.cy).attr("r", R + 2.5).attr("fill", "none").attr("stroke", palette.textMuted).attr("stroke-width", 1);
|
|
49443
|
+
emitText(
|
|
49444
|
+
g,
|
|
49445
|
+
cl.cx,
|
|
49446
|
+
cl.cy + 3,
|
|
49447
|
+
String(cl.count),
|
|
49448
|
+
"middle",
|
|
49449
|
+
palette.text,
|
|
49450
|
+
palette.bg,
|
|
49451
|
+
false,
|
|
49452
|
+
LABEL_FONT
|
|
49453
|
+
);
|
|
49454
|
+
}
|
|
47820
49455
|
}
|
|
47821
49456
|
if (layout.legend) {
|
|
47822
49457
|
const legendY = (layout.title ? TITLE_Y + TITLE_FONT_SIZE : 0) + (layout.subtitle ? TITLE_FONT_SIZE : 0) + 8;
|
|
@@ -47853,7 +49488,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
47853
49488
|
svg.append("text").attr("class", "dgmo-map-title").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);
|
|
47854
49489
|
}
|
|
47855
49490
|
if (layout.subtitle) {
|
|
47856
|
-
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);
|
|
49491
|
+
svg.append("text").attr("class", "dgmo-map-subtitle").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);
|
|
47857
49492
|
}
|
|
47858
49493
|
if (layout.caption) {
|
|
47859
49494
|
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);
|
|
@@ -47862,10 +49497,21 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
47862
49497
|
function renderMapForExport(container, resolved, data, palette, isDark, exportDims) {
|
|
47863
49498
|
renderMap(container, resolved, data, palette, isDark, void 0, exportDims);
|
|
47864
49499
|
}
|
|
47865
|
-
function emitText(g, x, y, text, anchor, color, halo, withHalo, fontSize) {
|
|
47866
|
-
const t = g.append("text").attr("x", x).attr("y", y).attr("text-anchor", anchor).attr("font-size", fontSize).attr("fill", color)
|
|
49500
|
+
function emitText(g, x, y, text, anchor, color, halo, withHalo, fontSize, italic, letterSpacing, lines) {
|
|
49501
|
+
const t = g.append("text").attr("x", x).attr("y", y).attr("text-anchor", anchor).attr("font-size", fontSize).attr("fill", color);
|
|
49502
|
+
if (lines && lines.length > 1) {
|
|
49503
|
+
const lineHeight = fontSize + 2;
|
|
49504
|
+
const startDy = -((lines.length - 1) / 2) * lineHeight;
|
|
49505
|
+
lines.forEach((ln, i) => {
|
|
49506
|
+
t.append("tspan").attr("x", x).attr("dy", i === 0 ? startDy : lineHeight).text(ln);
|
|
49507
|
+
});
|
|
49508
|
+
} else {
|
|
49509
|
+
t.text(text);
|
|
49510
|
+
}
|
|
49511
|
+
if (italic) t.attr("font-style", "italic");
|
|
49512
|
+
if (letterSpacing) t.attr("letter-spacing", letterSpacing);
|
|
47867
49513
|
if (withHalo) {
|
|
47868
|
-
t.attr("paint-order", "stroke fill").attr("stroke", halo).attr("stroke-width",
|
|
49514
|
+
t.attr("paint-order", "stroke fill").attr("stroke", halo).attr("stroke-width", 2).attr("stroke-linejoin", "round").attr("stroke-linecap", "round").attr("stroke-opacity", 0.55);
|
|
47869
49515
|
}
|
|
47870
49516
|
return t;
|
|
47871
49517
|
}
|
|
@@ -47883,6 +49529,56 @@ var init_renderer16 = __esm({
|
|
|
47883
49529
|
}
|
|
47884
49530
|
});
|
|
47885
49531
|
|
|
49532
|
+
// src/map/dimensions.ts
|
|
49533
|
+
var dimensions_exports = {};
|
|
49534
|
+
__export(dimensions_exports, {
|
|
49535
|
+
mapContentAspect: () => mapContentAspect,
|
|
49536
|
+
mapExportDimensions: () => mapExportDimensions
|
|
49537
|
+
});
|
|
49538
|
+
function mapContentAspect(resolved, data, ref = REF) {
|
|
49539
|
+
const { projection, fitTarget } = buildMapProjection(resolved, data);
|
|
49540
|
+
projection.fitSize([ref, ref], fitTarget);
|
|
49541
|
+
const b = (0, import_d3_geo3.geoPath)(projection).bounds(fitTarget);
|
|
49542
|
+
const w = b[1][0] - b[0][0];
|
|
49543
|
+
const h = b[1][1] - b[0][1];
|
|
49544
|
+
const aspect = w / h;
|
|
49545
|
+
return Number.isFinite(aspect) && aspect > 0 ? aspect : FALLBACK_ASPECT;
|
|
49546
|
+
}
|
|
49547
|
+
function mapExportDimensions(resolved, data, baseWidth = 1200) {
|
|
49548
|
+
const raw = mapContentAspect(resolved, data);
|
|
49549
|
+
const clamped = Math.max(ASPECT_MIN, Math.min(ASPECT_MAX, raw));
|
|
49550
|
+
const width = baseWidth;
|
|
49551
|
+
let height = Math.round(width / clamped);
|
|
49552
|
+
let chromeReserve = 0;
|
|
49553
|
+
if (resolved.title && resolved.pois.length > 0) {
|
|
49554
|
+
const bannerBottom = (resolved.subtitle ? TITLE_Y + TITLE_FONT_SIZE : TITLE_Y) + TITLE_FONT_SIZE / 2;
|
|
49555
|
+
chromeReserve += Math.max(FIT_PAD2, bannerBottom + TITLE_GAP) - FIT_PAD2;
|
|
49556
|
+
}
|
|
49557
|
+
let floored = false;
|
|
49558
|
+
if (height - chromeReserve < MIN_MAP_BAND) {
|
|
49559
|
+
height = Math.round(chromeReserve + MIN_MAP_BAND);
|
|
49560
|
+
floored = true;
|
|
49561
|
+
}
|
|
49562
|
+
const preferContain = clamped !== raw || floored;
|
|
49563
|
+
return { width, height, preferContain };
|
|
49564
|
+
}
|
|
49565
|
+
var import_d3_geo3, FIT_PAD2, TITLE_GAP, ASPECT_MAX, ASPECT_MIN, MIN_MAP_BAND, FALLBACK_ASPECT, REF;
|
|
49566
|
+
var init_dimensions = __esm({
|
|
49567
|
+
"src/map/dimensions.ts"() {
|
|
49568
|
+
"use strict";
|
|
49569
|
+
import_d3_geo3 = require("d3-geo");
|
|
49570
|
+
init_title_constants();
|
|
49571
|
+
init_layout15();
|
|
49572
|
+
FIT_PAD2 = 24;
|
|
49573
|
+
TITLE_GAP = 16;
|
|
49574
|
+
ASPECT_MAX = 3;
|
|
49575
|
+
ASPECT_MIN = 0.9;
|
|
49576
|
+
MIN_MAP_BAND = 200;
|
|
49577
|
+
FALLBACK_ASPECT = 1.5;
|
|
49578
|
+
REF = 1e3;
|
|
49579
|
+
}
|
|
49580
|
+
});
|
|
49581
|
+
|
|
47886
49582
|
// src/map/load-data.ts
|
|
47887
49583
|
var load_data_exports = {};
|
|
47888
49584
|
__export(load_data_exports, {
|
|
@@ -47941,12 +49637,17 @@ function loadMapData() {
|
|
|
47941
49637
|
mountainRanges,
|
|
47942
49638
|
naLand,
|
|
47943
49639
|
naLakes,
|
|
49640
|
+
waterBodies,
|
|
47944
49641
|
gazetteer
|
|
47945
49642
|
] = await Promise.all([
|
|
49643
|
+
// worldCoarse (110m) is LOAD-BEARING but NOT a render source: the world
|
|
49644
|
+
// basemap renders from worldDetail (50m) at all scales (resolver pins
|
|
49645
|
+
// basemaps.world = 'detail'). Coarse stays as the authoritative region
|
|
49646
|
+
// name index + dominant-landmass bbox source in resolver.ts. Do not drop it.
|
|
47946
49647
|
readJson(nb, dir, FILES.worldCoarse),
|
|
47947
49648
|
readJson(nb, dir, FILES.worldDetail),
|
|
47948
49649
|
readJson(nb, dir, FILES.usStates),
|
|
47949
|
-
// Lakes/rivers/mountain/NA assets are optional — older bundles may predate them.
|
|
49650
|
+
// Lakes/rivers/mountain/NA/water assets are optional — older bundles may predate them.
|
|
47950
49651
|
readJson(nb, dir, FILES.lakes).catch(() => void 0),
|
|
47951
49652
|
readJson(nb, dir, FILES.rivers).catch(() => void 0),
|
|
47952
49653
|
readJson(nb, dir, FILES.mountainRanges).catch(
|
|
@@ -47954,6 +49655,7 @@ function loadMapData() {
|
|
|
47954
49655
|
),
|
|
47955
49656
|
readJson(nb, dir, FILES.naLand).catch(() => void 0),
|
|
47956
49657
|
readJson(nb, dir, FILES.naLakes).catch(() => void 0),
|
|
49658
|
+
readJson(nb, dir, FILES.waterBodies).catch(() => void 0),
|
|
47957
49659
|
readJson(nb, dir, FILES.gazetteer)
|
|
47958
49660
|
]);
|
|
47959
49661
|
return validate({
|
|
@@ -47965,7 +49667,8 @@ function loadMapData() {
|
|
|
47965
49667
|
...rivers && { rivers },
|
|
47966
49668
|
...mountainRanges && { mountainRanges },
|
|
47967
49669
|
...naLand && { naLand },
|
|
47968
|
-
...naLakes && { naLakes }
|
|
49670
|
+
...naLakes && { naLakes },
|
|
49671
|
+
...waterBodies && { waterBodies }
|
|
47969
49672
|
});
|
|
47970
49673
|
})().catch((e) => {
|
|
47971
49674
|
cache = void 0;
|
|
@@ -47987,6 +49690,7 @@ var init_load_data = __esm({
|
|
|
47987
49690
|
mountainRanges: "mountain-ranges.json",
|
|
47988
49691
|
naLand: "na-land.json",
|
|
47989
49692
|
naLakes: "na-lakes.json",
|
|
49693
|
+
waterBodies: "water-bodies.json",
|
|
47990
49694
|
gazetteer: "gazetteer.json"
|
|
47991
49695
|
};
|
|
47992
49696
|
CANDIDATE_DIRS = [
|
|
@@ -49999,8 +51703,8 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
|
|
|
49999
51703
|
const lines = splitParticipantLabel(p.label, LABEL_MAX_CHARS);
|
|
50000
51704
|
if (lines.length === 0) continue;
|
|
50001
51705
|
const widest = Math.max(...lines.map((l) => l.length));
|
|
50002
|
-
const
|
|
50003
|
-
uniformBoxWidth = Math.max(uniformBoxWidth,
|
|
51706
|
+
const labelWidth2 = widest * LABEL_CHAR_WIDTH + 10;
|
|
51707
|
+
uniformBoxWidth = Math.max(uniformBoxWidth, labelWidth2);
|
|
50004
51708
|
}
|
|
50005
51709
|
uniformBoxWidth = Math.min(MAX_BOX_WIDTH, uniformBoxWidth);
|
|
50006
51710
|
const effectiveGap = Math.max(PARTICIPANT_GAP, uniformBoxWidth + 30);
|
|
@@ -52695,15 +54399,15 @@ function renderArcDiagram(container, parsed, palette, _isDark, onClickItem, expo
|
|
|
52695
54399
|
textColor,
|
|
52696
54400
|
onClickItem
|
|
52697
54401
|
);
|
|
52698
|
-
const
|
|
52699
|
-
for (const node of nodes)
|
|
54402
|
+
const neighbors2 = /* @__PURE__ */ new Map();
|
|
54403
|
+
for (const node of nodes) neighbors2.set(node, /* @__PURE__ */ new Set());
|
|
52700
54404
|
for (const link of links) {
|
|
52701
|
-
|
|
52702
|
-
|
|
54405
|
+
neighbors2.get(link.source).add(link.target);
|
|
54406
|
+
neighbors2.get(link.target).add(link.source);
|
|
52703
54407
|
}
|
|
52704
54408
|
const FADE_OPACITY3 = 0.1;
|
|
52705
54409
|
function handleMouseEnter(hovered) {
|
|
52706
|
-
const connected =
|
|
54410
|
+
const connected = neighbors2.get(hovered);
|
|
52707
54411
|
g.selectAll(".arc-link").each(function() {
|
|
52708
54412
|
const el = d3Selection23.select(this);
|
|
52709
54413
|
const src = el.attr("data-source");
|
|
@@ -53611,10 +55315,12 @@ function renderTimelineHorizontalTimeSort(container, parsed, palette, isDark, se
|
|
|
53611
55315
|
const markerLabelY = markerReserve ? -(topScaleH + MARKER_ROW_H / 2) : 0;
|
|
53612
55316
|
const eraLabelY = eraReserve ? -(topScaleH + markerReserve + ERA_ROW_H / 2) : 0;
|
|
53613
55317
|
const innerWidth = width - margin.left - margin.right;
|
|
53614
|
-
const
|
|
53615
|
-
const rowH = Math.min(ctx.structural(28),
|
|
55318
|
+
const availInnerHeight = height - margin.top - margin.bottom;
|
|
55319
|
+
const rowH = Math.min(ctx.structural(28), availInnerHeight / sorted.length);
|
|
55320
|
+
const innerHeight = rowH * sorted.length;
|
|
55321
|
+
const usedHeight = margin.top + innerHeight + margin.bottom;
|
|
53616
55322
|
const xScale = d3Scale2.scaleLinear().domain([minDate - datePadding, maxDate + datePadding]).range([0, innerWidth]);
|
|
53617
|
-
const svg = d3Selection23.select(container).append("svg").attr("width", width).attr("height",
|
|
55323
|
+
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);
|
|
53618
55324
|
if (ctx.isBelowFloor) {
|
|
53619
55325
|
svg.attr("width", "100%");
|
|
53620
55326
|
}
|
|
@@ -54694,7 +56400,7 @@ function renderVenn(container, parsed, palette, _isDark, onClickItem, exportDims
|
|
|
54694
56400
|
8,
|
|
54695
56401
|
Math.floor(OVERLAP_WRAP_TARGET_W / OVERLAP_CH_W)
|
|
54696
56402
|
);
|
|
54697
|
-
function
|
|
56403
|
+
function wrapLabel3(text, maxChars) {
|
|
54698
56404
|
const words = text.split(/\s+/).filter(Boolean);
|
|
54699
56405
|
const lines = [];
|
|
54700
56406
|
let cur = "";
|
|
@@ -54740,7 +56446,7 @@ function renderVenn(container, parsed, palette, _isDark, onClickItem, exportDims
|
|
|
54740
56446
|
if (!ov.label) continue;
|
|
54741
56447
|
const idxs = ov.sets.map((s) => vennSets.findIndex((vs) => vs.name === s));
|
|
54742
56448
|
if (idxs.some((idx) => idx < 0)) continue;
|
|
54743
|
-
const lines =
|
|
56449
|
+
const lines = wrapLabel3(ov.label, MAX_WRAP_CHARS);
|
|
54744
56450
|
wrappedOverlapLabels.set(ov, lines);
|
|
54745
56451
|
const dir = predictOverlapDirRaw(idxs);
|
|
54746
56452
|
const longest = lines.reduce((m, l) => Math.max(m, l.length), 0);
|
|
@@ -56178,6 +57884,7 @@ async function renderForExport(content, theme, palette, viewState, options) {
|
|
|
56178
57884
|
const { parseMap: parseMap2 } = await Promise.resolve().then(() => (init_parser12(), parser_exports11));
|
|
56179
57885
|
const { resolveMap: resolveMap2 } = await Promise.resolve().then(() => (init_resolver2(), resolver_exports));
|
|
56180
57886
|
const { renderMapForExport: renderMapForExport2 } = await Promise.resolve().then(() => (init_renderer16(), renderer_exports16));
|
|
57887
|
+
const { mapExportDimensions: mapExportDimensions2 } = await Promise.resolve().then(() => (init_dimensions(), dimensions_exports));
|
|
56181
57888
|
const effectivePalette2 = await resolveExportPalette(theme, palette);
|
|
56182
57889
|
const mapParsed = parseMap2(content);
|
|
56183
57890
|
let mapData = options?.mapData;
|
|
@@ -56190,14 +57897,15 @@ async function renderForExport(content, theme, palette, viewState, options) {
|
|
|
56190
57897
|
}
|
|
56191
57898
|
}
|
|
56192
57899
|
const mapResolved = resolveMap2(mapParsed, mapData);
|
|
56193
|
-
const
|
|
57900
|
+
const dims2 = mapExportDimensions2(mapResolved, mapData, EXPORT_WIDTH);
|
|
57901
|
+
const container2 = createExportContainer(dims2.width, dims2.height);
|
|
56194
57902
|
renderMapForExport2(
|
|
56195
57903
|
container2,
|
|
56196
57904
|
mapResolved,
|
|
56197
57905
|
mapData,
|
|
56198
57906
|
effectivePalette2,
|
|
56199
57907
|
theme === "dark",
|
|
56200
|
-
|
|
57908
|
+
dims2
|
|
56201
57909
|
);
|
|
56202
57910
|
return finalizeSvgExport(container2, theme, effectivePalette2);
|
|
56203
57911
|
}
|
|
@@ -57004,7 +58712,8 @@ __export(advanced_exports, {
|
|
|
57004
58712
|
applyCollapseProjection: () => applyCollapseProjection,
|
|
57005
58713
|
applyGroupOrdering: () => applyGroupOrdering,
|
|
57006
58714
|
applyPositionOverrides: () => applyPositionOverrides,
|
|
57007
|
-
|
|
58715
|
+
atlasPalette: () => atlasPalette,
|
|
58716
|
+
blueprintPalette: () => blueprintPalette,
|
|
57008
58717
|
buildExtendedChartOption: () => buildExtendedChartOption,
|
|
57009
58718
|
buildNoteMessageMap: () => buildNoteMessageMap,
|
|
57010
58719
|
buildRenderSequence: () => buildRenderSequence,
|
|
@@ -57107,6 +58816,8 @@ __export(advanced_exports, {
|
|
|
57107
58816
|
looksLikeState: () => looksLikeState,
|
|
57108
58817
|
makeDgmoError: () => makeDgmoError,
|
|
57109
58818
|
mapBackgroundColor: () => mapBackgroundColor,
|
|
58819
|
+
mapContentAspect: () => mapContentAspect,
|
|
58820
|
+
mapExportDimensions: () => mapExportDimensions,
|
|
57110
58821
|
mapNeutralLandColor: () => mapNeutralLandColor,
|
|
57111
58822
|
matchesContiguously: () => matchesContiguously,
|
|
57112
58823
|
measurePertAnalysisBlock: () => measurePertAnalysisBlock,
|
|
@@ -57242,9 +58953,11 @@ __export(advanced_exports, {
|
|
|
57242
58953
|
shapeFill: () => shapeFill,
|
|
57243
58954
|
simulateCanonical: () => simulateCanonical,
|
|
57244
58955
|
simulateFast: () => simulateFast,
|
|
58956
|
+
slatePalette: () => slatePalette,
|
|
57245
58957
|
solarizedPalette: () => solarizedPalette,
|
|
57246
58958
|
suggestChartTypes: () => suggestChartTypes,
|
|
57247
58959
|
themes: () => themes,
|
|
58960
|
+
tidewaterPalette: () => tidewaterPalette,
|
|
57248
58961
|
tint: () => tint,
|
|
57249
58962
|
tokyoNightPalette: () => tokyoNightPalette,
|
|
57250
58963
|
transformLine: () => transformLine,
|
|
@@ -57328,7 +59041,8 @@ async function render(content, options) {
|
|
|
57328
59041
|
...options?.c4Container !== void 0 && {
|
|
57329
59042
|
c4Container: options.c4Container
|
|
57330
59043
|
},
|
|
57331
|
-
...options?.tagGroup !== void 0 && { tagGroup: options.tagGroup }
|
|
59044
|
+
...options?.tagGroup !== void 0 && { tagGroup: options.tagGroup },
|
|
59045
|
+
...options?.mapData !== void 0 && { mapData: options.mapData }
|
|
57332
59046
|
});
|
|
57333
59047
|
if (chartType === "map") {
|
|
57334
59048
|
try {
|
|
@@ -57339,7 +59053,7 @@ async function render(content, options) {
|
|
|
57339
59053
|
Promise.resolve().then(() => (init_load_data(), load_data_exports))
|
|
57340
59054
|
]
|
|
57341
59055
|
);
|
|
57342
|
-
const data = await loadMapData2();
|
|
59056
|
+
const data = options?.mapData ?? await loadMapData2();
|
|
57343
59057
|
diagnostics = [...resolveMap2(parseMap2(content), data).diagnostics];
|
|
57344
59058
|
} catch {
|
|
57345
59059
|
}
|
|
@@ -57578,8 +59292,8 @@ function detectCycles(parsed) {
|
|
|
57578
59292
|
const parent = /* @__PURE__ */ new Map();
|
|
57579
59293
|
function dfs(nodeId3) {
|
|
57580
59294
|
color.set(nodeId3, 1);
|
|
57581
|
-
const
|
|
57582
|
-
for (const next of
|
|
59295
|
+
const neighbors2 = adj.get(nodeId3) ?? [];
|
|
59296
|
+
for (const next of neighbors2) {
|
|
57583
59297
|
const c = color.get(next) ?? 0;
|
|
57584
59298
|
if (c === 1) {
|
|
57585
59299
|
const lineKey = `${nodeId3}->${next}`;
|
|
@@ -57764,6 +59478,7 @@ init_resolver2();
|
|
|
57764
59478
|
init_load_data();
|
|
57765
59479
|
init_layout15();
|
|
57766
59480
|
init_renderer16();
|
|
59481
|
+
init_dimensions();
|
|
57767
59482
|
|
|
57768
59483
|
// src/map/geo-query.ts
|
|
57769
59484
|
init_parser12();
|
|
@@ -57837,7 +59552,9 @@ function nearestCity(lonLat, gazetteer) {
|
|
|
57837
59552
|
name: c[4],
|
|
57838
59553
|
iso: c[2],
|
|
57839
59554
|
...c[5] !== void 0 && { sub: c[5] },
|
|
57840
|
-
distanceKm: best.dist
|
|
59555
|
+
distanceKm: best.dist,
|
|
59556
|
+
lat: c[0],
|
|
59557
|
+
lon: c[1]
|
|
57841
59558
|
};
|
|
57842
59559
|
}
|
|
57843
59560
|
function roundCoord(n) {
|
|
@@ -57916,7 +59633,7 @@ function createMapGeoQuery(opts) {
|
|
|
57916
59633
|
}
|
|
57917
59634
|
return out;
|
|
57918
59635
|
};
|
|
57919
|
-
return { invert, project, locate, cities };
|
|
59636
|
+
return { invert, project, locate, cities, diagnostics: layout.diagnostics };
|
|
57920
59637
|
}
|
|
57921
59638
|
|
|
57922
59639
|
// src/map/completion.ts
|
|
@@ -58642,9 +60359,12 @@ var GLOBAL_DIRECTIVES = {
|
|
|
58642
60359
|
"gruvbox",
|
|
58643
60360
|
"tokyo-night",
|
|
58644
60361
|
"one-dark",
|
|
58645
|
-
"bold",
|
|
58646
60362
|
"dracula",
|
|
58647
|
-
"monokai"
|
|
60363
|
+
"monokai",
|
|
60364
|
+
"atlas",
|
|
60365
|
+
"blueprint",
|
|
60366
|
+
"slate",
|
|
60367
|
+
"tidewater"
|
|
58648
60368
|
]
|
|
58649
60369
|
},
|
|
58650
60370
|
theme: {
|
|
@@ -58975,7 +60695,9 @@ var COMPLETION_REGISTRY = /* @__PURE__ */ new Map([
|
|
|
58975
60695
|
withGlobals({
|
|
58976
60696
|
direction: { description: "Layout direction", values: ["LR", "TB"] },
|
|
58977
60697
|
"active-tag": { description: "Active tag group name" },
|
|
58978
|
-
hide: { description: "Hide tag:value pairs" }
|
|
60698
|
+
hide: { description: "Hide tag:value pairs" },
|
|
60699
|
+
"box-metric": { description: "Metric label for the value ramp" },
|
|
60700
|
+
"show-values": { description: "Print box values as text" }
|
|
58979
60701
|
})
|
|
58980
60702
|
],
|
|
58981
60703
|
[
|
|
@@ -59040,18 +60762,12 @@ var COMPLETION_REGISTRY = /* @__PURE__ */ new Map([
|
|
|
59040
60762
|
],
|
|
59041
60763
|
[
|
|
59042
60764
|
"map",
|
|
59043
|
-
// Geographic map directives (§24B.2/.7).
|
|
59044
|
-
//
|
|
59045
|
-
//
|
|
60765
|
+
// Geographic map directives (§24B.2/.7). Cosmetics are ON by default — the
|
|
60766
|
+
// only switches are bare `no-*` opt-outs, surfaced proactively so a
|
|
60767
|
+
// zero-config map still hints at what can be turned off. `poi`/`route` are
|
|
60768
|
+
// content keywords, not directives; metadata keys (value/label/style) live
|
|
60769
|
+
// in the reserved-key registry.
|
|
59046
60770
|
withGlobals({
|
|
59047
|
-
region: {
|
|
59048
|
-
description: "Basemap: us-states (force US state mesh + scoping) | world (inert \u2014 already the default)",
|
|
59049
|
-
values: ["us-states", "world"]
|
|
59050
|
-
},
|
|
59051
|
-
projection: {
|
|
59052
|
-
description: "Override the auto projection",
|
|
59053
|
-
values: ["equirectangular", "natural-earth", "albers-usa", "mercator"]
|
|
59054
|
-
},
|
|
59055
60771
|
"region-metric": { description: "Label for the region value ramp" },
|
|
59056
60772
|
"poi-metric": {
|
|
59057
60773
|
description: "Label for the POI value (marker size) channel"
|
|
@@ -59059,21 +60775,30 @@ var COMPLETION_REGISTRY = /* @__PURE__ */ new Map([
|
|
|
59059
60775
|
"flow-metric": {
|
|
59060
60776
|
description: "Label for the edge/leg value (thickness) channel"
|
|
59061
60777
|
},
|
|
59062
|
-
|
|
59063
|
-
|
|
59064
|
-
description: "Subdivision name labels",
|
|
59065
|
-
values: ["full", "abbrev", "off"]
|
|
60778
|
+
locale: {
|
|
60779
|
+
description: "Default country/state for bare place names, e.g. locale US-GA"
|
|
59066
60780
|
},
|
|
59067
|
-
"
|
|
59068
|
-
description: "
|
|
59069
|
-
values: ["off", "auto", "all"]
|
|
60781
|
+
"active-tag": {
|
|
60782
|
+
description: "Which tag group leads when several are present"
|
|
59070
60783
|
},
|
|
59071
|
-
|
|
59072
|
-
"default-state": { description: "ISO subdivision scope" },
|
|
60784
|
+
caption: { description: "Caption line (data-source attribution)" },
|
|
59073
60785
|
"no-legend": { description: "Suppress the legend" },
|
|
59074
|
-
|
|
59075
|
-
|
|
59076
|
-
|
|
60786
|
+
"no-coastline": {
|
|
60787
|
+
description: "Turn off coastal water-lines (on by default)"
|
|
60788
|
+
},
|
|
60789
|
+
"no-relief": {
|
|
60790
|
+
description: "Turn off mountain-range relief shading (on by default)"
|
|
60791
|
+
},
|
|
60792
|
+
"no-context-labels": {
|
|
60793
|
+
description: "Turn off orientation labels for water + nearby countries"
|
|
60794
|
+
},
|
|
60795
|
+
"no-region-labels": {
|
|
60796
|
+
description: "Turn off subdivision name labels (on by default)"
|
|
60797
|
+
},
|
|
60798
|
+
"no-poi-labels": { description: "Turn off POI labels (on by default)" },
|
|
60799
|
+
"no-colorize": {
|
|
60800
|
+
description: "Force plain green-land reference dress (regions are auto-coloured by default)"
|
|
60801
|
+
}
|
|
59077
60802
|
})
|
|
59078
60803
|
]
|
|
59079
60804
|
]);
|
|
@@ -59200,13 +60925,10 @@ var PIPE_METADATA = /* @__PURE__ */ new Map([
|
|
|
59200
60925
|
"boxes-and-lines",
|
|
59201
60926
|
{
|
|
59202
60927
|
node: {
|
|
59203
|
-
description: { description: "Node description text" }
|
|
60928
|
+
description: { description: "Node description text" },
|
|
60929
|
+
value: { description: "Numeric value for the metric ramp" }
|
|
59204
60930
|
},
|
|
59205
|
-
edge: {
|
|
59206
|
-
width: { description: "Edge stroke width in pixels" },
|
|
59207
|
-
split: { description: "Traffic split percentage" },
|
|
59208
|
-
fanout: { description: "Fanout multiplier (integer >= 1)" }
|
|
59209
|
-
}
|
|
60931
|
+
edge: {}
|
|
59210
60932
|
}
|
|
59211
60933
|
],
|
|
59212
60934
|
[
|
|
@@ -60543,7 +62265,8 @@ function formatLineDiff(path, original, migrated) {
|
|
|
60543
62265
|
applyCollapseProjection,
|
|
60544
62266
|
applyGroupOrdering,
|
|
60545
62267
|
applyPositionOverrides,
|
|
60546
|
-
|
|
62268
|
+
atlasPalette,
|
|
62269
|
+
blueprintPalette,
|
|
60547
62270
|
buildExtendedChartOption,
|
|
60548
62271
|
buildNoteMessageMap,
|
|
60549
62272
|
buildRenderSequence,
|
|
@@ -60646,6 +62369,8 @@ function formatLineDiff(path, original, migrated) {
|
|
|
60646
62369
|
looksLikeState,
|
|
60647
62370
|
makeDgmoError,
|
|
60648
62371
|
mapBackgroundColor,
|
|
62372
|
+
mapContentAspect,
|
|
62373
|
+
mapExportDimensions,
|
|
60649
62374
|
mapNeutralLandColor,
|
|
60650
62375
|
matchesContiguously,
|
|
60651
62376
|
measurePertAnalysisBlock,
|
|
@@ -60781,9 +62506,11 @@ function formatLineDiff(path, original, migrated) {
|
|
|
60781
62506
|
shapeFill,
|
|
60782
62507
|
simulateCanonical,
|
|
60783
62508
|
simulateFast,
|
|
62509
|
+
slatePalette,
|
|
60784
62510
|
solarizedPalette,
|
|
60785
62511
|
suggestChartTypes,
|
|
60786
62512
|
themes,
|
|
62513
|
+
tidewaterPalette,
|
|
60787
62514
|
tint,
|
|
60788
62515
|
tokyoNightPalette,
|
|
60789
62516
|
transformLine,
|