@diagrammo/dgmo 0.21.1 → 0.22.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 +2003 -466
- package/dist/advanced.d.cts +5714 -0
- package/dist/advanced.d.ts +5714 -0
- package/dist/advanced.js +1999 -466
- package/dist/auto.cjs +2048 -449
- package/dist/auto.d.cts +39 -0
- package/dist/auto.d.ts +39 -0
- package/dist/auto.js +121 -121
- package/dist/auto.mjs +2050 -450
- package/dist/cli.cjs +170 -170
- package/dist/editor.cjs +13 -16
- package/dist/editor.js +13 -16
- package/dist/highlight.cjs +15 -13
- package/dist/highlight.js +15 -13
- package/dist/index.cjs +2032 -435
- package/dist/index.d.cts +339 -0
- package/dist/index.d.ts +339 -0
- package/dist/index.js +2034 -436
- package/dist/internal.cjs +2003 -466
- package/dist/internal.d.cts +5714 -0
- package/dist/internal.d.ts +5714 -0
- package/dist/internal.js +1999 -466
- package/dist/map-data/water-bodies.json +1 -0
- package/docs/language-reference.md +20 -9
- 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/renderer.ts +39 -12
- package/src/cli.ts +1 -1
- package/src/completion.ts +32 -25
- package/src/cycle/renderer.ts +14 -1
- package/src/d3.ts +8 -2
- package/src/editor/highlight-api.ts +4 -0
- package/src/editor/keywords.ts +13 -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/types.ts +34 -0
- package/src/map/data/water-bodies.json +1 -0
- 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 +1300 -251
- package/src/map/load-data.ts +10 -2
- package/src/map/parser.ts +42 -116
- package/src/map/renderer.ts +512 -13
- 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 +3 -0
- package/src/palettes/bold.ts +0 -67
package/dist/advanced.js
CHANGED
|
@@ -371,18 +371,18 @@ function computeQuadrantPointLabels(points, chartBounds, obstacles, pointRadius,
|
|
|
371
371
|
const results = [];
|
|
372
372
|
for (let i = 0; i < points.length; i++) {
|
|
373
373
|
const pt = points[i];
|
|
374
|
-
const
|
|
374
|
+
const labelWidth2 = pt.label.length * fontSize * CHAR_WIDTH_RATIO + 8;
|
|
375
375
|
let best = null;
|
|
376
376
|
const directions = [
|
|
377
377
|
{
|
|
378
378
|
// Above
|
|
379
379
|
gen: (offset) => {
|
|
380
|
-
const lx = pt.cx -
|
|
380
|
+
const lx = pt.cx - labelWidth2 / 2;
|
|
381
381
|
const ly = pt.cy - offset - labelHeight;
|
|
382
|
-
if (ly < chartBounds.top || lx < chartBounds.left || lx +
|
|
382
|
+
if (ly < chartBounds.top || lx < chartBounds.left || lx + labelWidth2 > chartBounds.right)
|
|
383
383
|
return null;
|
|
384
384
|
return {
|
|
385
|
-
rect: { x: lx, y: ly, w:
|
|
385
|
+
rect: { x: lx, y: ly, w: labelWidth2, h: labelHeight },
|
|
386
386
|
textX: pt.cx,
|
|
387
387
|
textY: ly + labelHeight / 2,
|
|
388
388
|
anchor: "middle"
|
|
@@ -392,12 +392,12 @@ function computeQuadrantPointLabels(points, chartBounds, obstacles, pointRadius,
|
|
|
392
392
|
{
|
|
393
393
|
// Below
|
|
394
394
|
gen: (offset) => {
|
|
395
|
-
const lx = pt.cx -
|
|
395
|
+
const lx = pt.cx - labelWidth2 / 2;
|
|
396
396
|
const ly = pt.cy + offset;
|
|
397
|
-
if (ly + labelHeight > chartBounds.bottom || lx < chartBounds.left || lx +
|
|
397
|
+
if (ly + labelHeight > chartBounds.bottom || lx < chartBounds.left || lx + labelWidth2 > chartBounds.right)
|
|
398
398
|
return null;
|
|
399
399
|
return {
|
|
400
|
-
rect: { x: lx, y: ly, w:
|
|
400
|
+
rect: { x: lx, y: ly, w: labelWidth2, h: labelHeight },
|
|
401
401
|
textX: pt.cx,
|
|
402
402
|
textY: ly + labelHeight / 2,
|
|
403
403
|
anchor: "middle"
|
|
@@ -409,10 +409,10 @@ function computeQuadrantPointLabels(points, chartBounds, obstacles, pointRadius,
|
|
|
409
409
|
gen: (offset) => {
|
|
410
410
|
const lx = pt.cx + offset;
|
|
411
411
|
const ly = pt.cy - labelHeight / 2;
|
|
412
|
-
if (lx +
|
|
412
|
+
if (lx + labelWidth2 > chartBounds.right || ly < chartBounds.top || ly + labelHeight > chartBounds.bottom)
|
|
413
413
|
return null;
|
|
414
414
|
return {
|
|
415
|
-
rect: { x: lx, y: ly, w:
|
|
415
|
+
rect: { x: lx, y: ly, w: labelWidth2, h: labelHeight },
|
|
416
416
|
textX: lx,
|
|
417
417
|
textY: pt.cy,
|
|
418
418
|
anchor: "start"
|
|
@@ -422,13 +422,13 @@ function computeQuadrantPointLabels(points, chartBounds, obstacles, pointRadius,
|
|
|
422
422
|
{
|
|
423
423
|
// Left
|
|
424
424
|
gen: (offset) => {
|
|
425
|
-
const lx = pt.cx - offset -
|
|
425
|
+
const lx = pt.cx - offset - labelWidth2;
|
|
426
426
|
const ly = pt.cy - labelHeight / 2;
|
|
427
427
|
if (lx < chartBounds.left || ly < chartBounds.top || ly + labelHeight > chartBounds.bottom)
|
|
428
428
|
return null;
|
|
429
429
|
return {
|
|
430
|
-
rect: { x: lx, y: ly, w:
|
|
431
|
-
textX: lx +
|
|
430
|
+
rect: { x: lx, y: ly, w: labelWidth2, h: labelHeight },
|
|
431
|
+
textX: lx + labelWidth2,
|
|
432
432
|
textY: pt.cy,
|
|
433
433
|
anchor: "end"
|
|
434
434
|
};
|
|
@@ -478,10 +478,10 @@ function computeQuadrantPointLabels(points, chartBounds, obstacles, pointRadius,
|
|
|
478
478
|
}
|
|
479
479
|
}
|
|
480
480
|
if (!best) {
|
|
481
|
-
const lx = pt.cx -
|
|
481
|
+
const lx = pt.cx - labelWidth2 / 2;
|
|
482
482
|
const ly = pt.cy - minGap - labelHeight;
|
|
483
483
|
best = {
|
|
484
|
-
rect: { x: lx, y: ly, w:
|
|
484
|
+
rect: { x: lx, y: ly, w: labelWidth2, h: labelHeight },
|
|
485
485
|
textX: pt.cx,
|
|
486
486
|
textY: ly + labelHeight / 2,
|
|
487
487
|
anchor: "middle",
|
|
@@ -858,6 +858,9 @@ var init_reserved_key_registry = __esm({
|
|
|
858
858
|
"value",
|
|
859
859
|
"label",
|
|
860
860
|
"style"
|
|
861
|
+
// `surface:` was removed in the 2026-06-02 defaults-on review — it is no longer
|
|
862
|
+
// a recognized metadata key (the route/edge surface feature was cut; §24B.7).
|
|
863
|
+
// A stray `surface: water` is no longer captured as a reserved key.
|
|
861
864
|
]);
|
|
862
865
|
ORG_REGISTRY = staticRegistry([
|
|
863
866
|
"color",
|
|
@@ -1920,77 +1923,266 @@ function getSegmentColors(palette, count) {
|
|
|
1920
1923
|
(_, i) => hslToHex(Math.round((startHue + i * step) % 360), avgS, avgL)
|
|
1921
1924
|
);
|
|
1922
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;
|
|
1923
1951
|
var init_color_utils = __esm({
|
|
1924
1952
|
"src/palettes/color-utils.ts"() {
|
|
1925
1953
|
"use strict";
|
|
1954
|
+
POLITICAL_TINT_BANDS = {
|
|
1955
|
+
light: [32, 48, 64, 80],
|
|
1956
|
+
dark: [44, 58, 72, 86]
|
|
1957
|
+
};
|
|
1926
1958
|
}
|
|
1927
1959
|
});
|
|
1928
1960
|
|
|
1929
|
-
// src/palettes/
|
|
1930
|
-
var
|
|
1931
|
-
var
|
|
1932
|
-
"src/palettes/
|
|
1961
|
+
// src/palettes/atlas.ts
|
|
1962
|
+
var atlasPalette;
|
|
1963
|
+
var init_atlas = __esm({
|
|
1964
|
+
"src/palettes/atlas.ts"() {
|
|
1933
1965
|
"use strict";
|
|
1934
1966
|
init_registry();
|
|
1935
|
-
|
|
1936
|
-
id: "
|
|
1937
|
-
name: "
|
|
1967
|
+
atlasPalette = {
|
|
1968
|
+
id: "atlas",
|
|
1969
|
+
name: "Atlas",
|
|
1938
1970
|
light: {
|
|
1939
|
-
bg: "#
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
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
|
|
1951
1995
|
colors: {
|
|
1952
|
-
red: "#
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
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
|
|
1963
2018
|
}
|
|
1964
2019
|
},
|
|
1965
2020
|
dark: {
|
|
1966
|
-
bg: "#
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
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
|
|
1978
2109
|
colors: {
|
|
1979
|
-
red: "#
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
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
|
|
2159
|
+
colors: {
|
|
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
|
|
1990
2182
|
}
|
|
1991
2183
|
}
|
|
1992
2184
|
};
|
|
1993
|
-
registerPalette(
|
|
2185
|
+
registerPalette(blueprintPalette);
|
|
1994
2186
|
}
|
|
1995
2187
|
});
|
|
1996
2188
|
|
|
@@ -2487,6 +2679,120 @@ var init_rose_pine = __esm({
|
|
|
2487
2679
|
}
|
|
2488
2680
|
});
|
|
2489
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
|
+
|
|
2490
2796
|
// src/palettes/solarized.ts
|
|
2491
2797
|
var solarizedPalette;
|
|
2492
2798
|
var init_solarized = __esm({
|
|
@@ -2582,6 +2888,120 @@ var init_solarized = __esm({
|
|
|
2582
2888
|
}
|
|
2583
2889
|
});
|
|
2584
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
|
+
|
|
2585
3005
|
// src/palettes/tokyo-night.ts
|
|
2586
3006
|
var tokyoNightPalette;
|
|
2587
3007
|
var init_tokyo_night = __esm({
|
|
@@ -2857,7 +3277,8 @@ var init_monokai = __esm({
|
|
|
2857
3277
|
// src/palettes/index.ts
|
|
2858
3278
|
var palettes_exports = {};
|
|
2859
3279
|
__export(palettes_exports, {
|
|
2860
|
-
|
|
3280
|
+
atlasPalette: () => atlasPalette,
|
|
3281
|
+
blueprintPalette: () => blueprintPalette,
|
|
2861
3282
|
catppuccinPalette: () => catppuccinPalette,
|
|
2862
3283
|
contrastText: () => contrastText,
|
|
2863
3284
|
draculaPalette: () => draculaPalette,
|
|
@@ -2878,7 +3299,9 @@ __export(palettes_exports, {
|
|
|
2878
3299
|
rosePinePalette: () => rosePinePalette,
|
|
2879
3300
|
shade: () => shade,
|
|
2880
3301
|
shapeFill: () => shapeFill,
|
|
3302
|
+
slatePalette: () => slatePalette,
|
|
2881
3303
|
solarizedPalette: () => solarizedPalette,
|
|
3304
|
+
tidewaterPalette: () => tidewaterPalette,
|
|
2882
3305
|
tint: () => tint,
|
|
2883
3306
|
tokyoNightPalette: () => tokyoNightPalette
|
|
2884
3307
|
});
|
|
@@ -2888,17 +3311,21 @@ var init_palettes = __esm({
|
|
|
2888
3311
|
"use strict";
|
|
2889
3312
|
init_registry();
|
|
2890
3313
|
init_color_utils();
|
|
2891
|
-
|
|
3314
|
+
init_atlas();
|
|
3315
|
+
init_blueprint();
|
|
2892
3316
|
init_catppuccin();
|
|
2893
3317
|
init_gruvbox();
|
|
2894
3318
|
init_nord();
|
|
2895
3319
|
init_one_dark();
|
|
2896
3320
|
init_rose_pine();
|
|
3321
|
+
init_slate();
|
|
2897
3322
|
init_solarized();
|
|
3323
|
+
init_tidewater();
|
|
2898
3324
|
init_tokyo_night();
|
|
2899
3325
|
init_dracula();
|
|
2900
3326
|
init_monokai();
|
|
2901
|
-
|
|
3327
|
+
init_atlas();
|
|
3328
|
+
init_blueprint();
|
|
2902
3329
|
init_catppuccin();
|
|
2903
3330
|
init_dracula();
|
|
2904
3331
|
init_gruvbox();
|
|
@@ -2906,9 +3333,15 @@ var init_palettes = __esm({
|
|
|
2906
3333
|
init_nord();
|
|
2907
3334
|
init_one_dark();
|
|
2908
3335
|
init_rose_pine();
|
|
3336
|
+
init_slate();
|
|
2909
3337
|
init_solarized();
|
|
3338
|
+
init_tidewater();
|
|
2910
3339
|
init_tokyo_night();
|
|
2911
3340
|
palettes = {
|
|
3341
|
+
atlas: atlasPalette,
|
|
3342
|
+
blueprint: blueprintPalette,
|
|
3343
|
+
slate: slatePalette,
|
|
3344
|
+
tidewater: tidewaterPalette,
|
|
2912
3345
|
nord: nordPalette,
|
|
2913
3346
|
catppuccin: catppuccinPalette,
|
|
2914
3347
|
solarized: solarizedPalette,
|
|
@@ -2917,8 +3350,7 @@ var init_palettes = __esm({
|
|
|
2917
3350
|
oneDark: oneDarkPalette,
|
|
2918
3351
|
rosePine: rosePinePalette,
|
|
2919
3352
|
dracula: draculaPalette,
|
|
2920
|
-
monokai: monokaiPalette
|
|
2921
|
-
bold: boldPalette
|
|
3353
|
+
monokai: monokaiPalette
|
|
2922
3354
|
};
|
|
2923
3355
|
}
|
|
2924
3356
|
});
|
|
@@ -3428,6 +3860,9 @@ function controlsGroupCapsuleWidth(toggles) {
|
|
|
3428
3860
|
}
|
|
3429
3861
|
return w;
|
|
3430
3862
|
}
|
|
3863
|
+
function isAppHostedControls(config, isExport) {
|
|
3864
|
+
return !isExport && config.controlsHost === "app" && !!config.controlsGroup && config.controlsGroup.toggles.length > 0;
|
|
3865
|
+
}
|
|
3431
3866
|
function buildControlsGroupLayout(config, state) {
|
|
3432
3867
|
const cg = config.controlsGroup;
|
|
3433
3868
|
if (!cg || cg.toggles.length === 0) return void 0;
|
|
@@ -3481,6 +3916,7 @@ function buildControlsGroupLayout(config, state) {
|
|
|
3481
3916
|
function computeLegendLayout(config, state, containerWidth) {
|
|
3482
3917
|
const { groups, controls: configControls, mode } = config;
|
|
3483
3918
|
const isExport = mode === "export";
|
|
3919
|
+
const gated = isAppHostedControls(config, isExport);
|
|
3484
3920
|
const activeGroupName = state.activeGroup?.toLowerCase() ?? null;
|
|
3485
3921
|
if (isExport && !activeGroupName) {
|
|
3486
3922
|
return {
|
|
@@ -3491,7 +3927,7 @@ function computeLegendLayout(config, state, containerWidth) {
|
|
|
3491
3927
|
pills: []
|
|
3492
3928
|
};
|
|
3493
3929
|
}
|
|
3494
|
-
const controlsGroupLayout = isExport ? void 0 : buildControlsGroupLayout(config, state);
|
|
3930
|
+
const controlsGroupLayout = isExport || gated ? void 0 : buildControlsGroupLayout(config, state);
|
|
3495
3931
|
const visibleGroups = config.showEmptyGroups ? groups : groups.filter((g) => g.entries.length > 0 || !!g.gradient);
|
|
3496
3932
|
if (visibleGroups.length === 0 && (!configControls || configControls.length === 0) && !controlsGroupLayout) {
|
|
3497
3933
|
return {
|
|
@@ -8345,8 +8781,8 @@ function computeScatterLabelGraphics(points, chartBounds, fontSize, symbolSize,
|
|
|
8345
8781
|
const pt = points[i];
|
|
8346
8782
|
const ptSize = pt.size ?? symbolSize;
|
|
8347
8783
|
const minGap = ptSize / 2 + 4;
|
|
8348
|
-
const
|
|
8349
|
-
const labelX = pt.px -
|
|
8784
|
+
const labelWidth2 = pt.name.length * fontSize * 0.6 + 8;
|
|
8785
|
+
const labelX = pt.px - labelWidth2 / 2;
|
|
8350
8786
|
let bestLabelY = 0;
|
|
8351
8787
|
let bestOffset = Infinity;
|
|
8352
8788
|
let placed = false;
|
|
@@ -8358,7 +8794,7 @@ function computeScatterLabelGraphics(points, chartBounds, fontSize, symbolSize,
|
|
|
8358
8794
|
const candidate = {
|
|
8359
8795
|
x: labelX,
|
|
8360
8796
|
y: labelY,
|
|
8361
|
-
w:
|
|
8797
|
+
w: labelWidth2,
|
|
8362
8798
|
h: labelHeight
|
|
8363
8799
|
};
|
|
8364
8800
|
let collision = false;
|
|
@@ -8400,7 +8836,7 @@ function computeScatterLabelGraphics(points, chartBounds, fontSize, symbolSize,
|
|
|
8400
8836
|
const labelRect = {
|
|
8401
8837
|
x: labelX,
|
|
8402
8838
|
y: bestLabelY,
|
|
8403
|
-
w:
|
|
8839
|
+
w: labelWidth2,
|
|
8404
8840
|
h: labelHeight
|
|
8405
8841
|
};
|
|
8406
8842
|
placedLabels.push(labelRect);
|
|
@@ -8436,7 +8872,7 @@ function computeScatterLabelGraphics(points, chartBounds, fontSize, symbolSize,
|
|
|
8436
8872
|
shape: {
|
|
8437
8873
|
x: labelX - bgPad,
|
|
8438
8874
|
y: bestLabelY - bgPad,
|
|
8439
|
-
width:
|
|
8875
|
+
width: labelWidth2 + bgPad * 2,
|
|
8440
8876
|
height: labelHeight + bgPad * 2
|
|
8441
8877
|
},
|
|
8442
8878
|
style: { fill: bg },
|
|
@@ -15872,10 +16308,6 @@ function parseMap(content) {
|
|
|
15872
16308
|
handleTag(trimmed, lineNumber);
|
|
15873
16309
|
continue;
|
|
15874
16310
|
}
|
|
15875
|
-
if ((firstWord === "muted" || firstWord === "natural") && trimmed === firstWord) {
|
|
15876
|
-
handleDirective(firstWord, "", lineNumber);
|
|
15877
|
-
continue;
|
|
15878
|
-
}
|
|
15879
16311
|
if (DIRECTIVE_SET.has(firstWord) && !trimmed.slice(firstWord.length).trimStart().startsWith(":")) {
|
|
15880
16312
|
handleDirective(
|
|
15881
16313
|
firstWord,
|
|
@@ -15922,24 +16354,6 @@ function parseMap(content) {
|
|
|
15922
16354
|
pushWarning(line12, `Duplicate directive "${key}" \u2014 last value wins.`);
|
|
15923
16355
|
};
|
|
15924
16356
|
switch (key) {
|
|
15925
|
-
case "region":
|
|
15926
|
-
dup(d.region);
|
|
15927
|
-
d.region = value;
|
|
15928
|
-
break;
|
|
15929
|
-
case "projection":
|
|
15930
|
-
dup(d.projection);
|
|
15931
|
-
if (value && ![
|
|
15932
|
-
"equirectangular",
|
|
15933
|
-
"natural-earth",
|
|
15934
|
-
"albers-usa",
|
|
15935
|
-
"mercator"
|
|
15936
|
-
].includes(value))
|
|
15937
|
-
pushWarning(
|
|
15938
|
-
line12,
|
|
15939
|
-
`Unknown projection "${value}" (expected equirectangular | natural-earth | albers-usa | mercator).`
|
|
15940
|
-
);
|
|
15941
|
-
d.projection = value;
|
|
15942
|
-
break;
|
|
15943
16357
|
case "region-metric": {
|
|
15944
16358
|
dup(d.regionMetric);
|
|
15945
16359
|
const { label: rmLabel, colorName: rmColor } = peelTrailingColorName(value);
|
|
@@ -15955,91 +16369,43 @@ function parseMap(content) {
|
|
|
15955
16369
|
dup(d.flowMetric);
|
|
15956
16370
|
d.flowMetric = value;
|
|
15957
16371
|
break;
|
|
15958
|
-
case "
|
|
15959
|
-
dup(d.
|
|
15960
|
-
|
|
15961
|
-
const s = parseScale(value, line12);
|
|
15962
|
-
if (s) d.scale = s;
|
|
15963
|
-
}
|
|
15964
|
-
break;
|
|
15965
|
-
case "region-labels":
|
|
15966
|
-
dup(d.regionLabels);
|
|
15967
|
-
if (value && !["full", "abbrev", "off"].includes(value))
|
|
15968
|
-
pushWarning(
|
|
15969
|
-
line12,
|
|
15970
|
-
`Unknown region-labels "${value}" (expected full | abbrev | off).`
|
|
15971
|
-
);
|
|
15972
|
-
d.regionLabels = value;
|
|
15973
|
-
break;
|
|
15974
|
-
case "poi-labels":
|
|
15975
|
-
dup(d.poiLabels);
|
|
15976
|
-
if (value && !["off", "auto", "all"].includes(value))
|
|
15977
|
-
pushWarning(
|
|
15978
|
-
line12,
|
|
15979
|
-
`Unknown poi-labels "${value}" (expected off | auto | all).`
|
|
15980
|
-
);
|
|
15981
|
-
d.poiLabels = value;
|
|
15982
|
-
break;
|
|
15983
|
-
case "default-country":
|
|
15984
|
-
dup(d.defaultCountry);
|
|
15985
|
-
d.defaultCountry = value;
|
|
15986
|
-
break;
|
|
15987
|
-
case "default-state":
|
|
15988
|
-
dup(d.defaultState);
|
|
15989
|
-
d.defaultState = value;
|
|
16372
|
+
case "locale":
|
|
16373
|
+
dup(d.locale);
|
|
16374
|
+
d.locale = value;
|
|
15990
16375
|
break;
|
|
15991
16376
|
case "active-tag":
|
|
15992
16377
|
dup(d.activeTag);
|
|
15993
16378
|
d.activeTag = value;
|
|
15994
16379
|
break;
|
|
16380
|
+
case "caption":
|
|
16381
|
+
dup(d.caption);
|
|
16382
|
+
d.caption = value;
|
|
16383
|
+
break;
|
|
16384
|
+
// ── Cosmetic `no-*` opt-outs: bare flags, idempotent (mirror `no-legend`,
|
|
16385
|
+
// no dup warning); each defaults the feature ON when absent. ──
|
|
15995
16386
|
case "no-legend":
|
|
15996
16387
|
d.noLegend = true;
|
|
15997
16388
|
break;
|
|
15998
|
-
case "no-
|
|
15999
|
-
d.
|
|
16389
|
+
case "no-coastline":
|
|
16390
|
+
d.noCoastline = true;
|
|
16000
16391
|
break;
|
|
16001
|
-
case "relief":
|
|
16002
|
-
d.
|
|
16392
|
+
case "no-relief":
|
|
16393
|
+
d.noRelief = true;
|
|
16003
16394
|
break;
|
|
16004
|
-
case "
|
|
16005
|
-
|
|
16006
|
-
if (d.basemapStyle !== void 0 && d.basemapStyle !== key)
|
|
16007
|
-
pushWarning(
|
|
16008
|
-
line12,
|
|
16009
|
-
`Conflicting basemap dress \u2014 "${d.basemapStyle}" then "${key}"; last wins.`
|
|
16010
|
-
);
|
|
16011
|
-
d.basemapStyle = key;
|
|
16395
|
+
case "no-context-labels":
|
|
16396
|
+
d.noContextLabels = true;
|
|
16012
16397
|
break;
|
|
16013
|
-
case "
|
|
16014
|
-
|
|
16015
|
-
d.subtitle = value;
|
|
16398
|
+
case "no-region-labels":
|
|
16399
|
+
d.noRegionLabels = true;
|
|
16016
16400
|
break;
|
|
16017
|
-
case "
|
|
16018
|
-
|
|
16019
|
-
|
|
16401
|
+
case "no-poi-labels":
|
|
16402
|
+
d.noPoiLabels = true;
|
|
16403
|
+
break;
|
|
16404
|
+
case "no-colorize":
|
|
16405
|
+
d.noColorize = true;
|
|
16020
16406
|
break;
|
|
16021
16407
|
}
|
|
16022
16408
|
}
|
|
16023
|
-
function parseScale(value, line12) {
|
|
16024
|
-
const toks = value.split(/\s+/).filter(Boolean);
|
|
16025
|
-
const min = Number(toks[0]);
|
|
16026
|
-
const max = Number(toks[1]);
|
|
16027
|
-
if (!Number.isFinite(min) || !Number.isFinite(max)) {
|
|
16028
|
-
pushError(line12, `scale requires numeric <min> <max> (got "${value}").`);
|
|
16029
|
-
return null;
|
|
16030
|
-
}
|
|
16031
|
-
const scale = { min, max };
|
|
16032
|
-
if (toks[2] === "center") {
|
|
16033
|
-
const c = Number(toks[3]);
|
|
16034
|
-
if (Number.isFinite(c)) scale.center = c;
|
|
16035
|
-
else
|
|
16036
|
-
pushError(
|
|
16037
|
-
line12,
|
|
16038
|
-
`scale center requires a number (got "${toks[3] ?? ""}").`
|
|
16039
|
-
);
|
|
16040
|
-
}
|
|
16041
|
-
return scale;
|
|
16042
|
-
}
|
|
16043
16409
|
function handleTag(trimmed, line12) {
|
|
16044
16410
|
const m = matchTagBlockHeading(trimmed);
|
|
16045
16411
|
if (!m) {
|
|
@@ -16239,13 +16605,15 @@ function parseMap(content) {
|
|
|
16239
16605
|
pushError(line12, `Edge has an empty endpoint: "${trimmed}".`);
|
|
16240
16606
|
continue;
|
|
16241
16607
|
}
|
|
16242
|
-
const
|
|
16608
|
+
const isLast = k === links.length - 1;
|
|
16609
|
+
const meta = isLast ? lastSplit.meta : {};
|
|
16610
|
+
const style = links[k].style === "arc" ? "arc" : "straight";
|
|
16243
16611
|
edges.push({
|
|
16244
16612
|
from,
|
|
16245
16613
|
to,
|
|
16246
16614
|
...links[k].label !== void 0 && { label: links[k].label },
|
|
16247
16615
|
directed: links[k].directed,
|
|
16248
|
-
style
|
|
16616
|
+
style,
|
|
16249
16617
|
meta,
|
|
16250
16618
|
lineNumber: line12
|
|
16251
16619
|
});
|
|
@@ -16331,22 +16699,19 @@ var init_parser12 = __esm({
|
|
|
16331
16699
|
LEG_ARROW_RE = /^(-[^>]*?->|->|~[^>]*?~>|~>|--)\s+(.+)$/;
|
|
16332
16700
|
AT_RE = /(^|[\s,])at\s*:/i;
|
|
16333
16701
|
DIRECTIVE_SET = /* @__PURE__ */ new Set([
|
|
16334
|
-
"region",
|
|
16335
|
-
"projection",
|
|
16336
16702
|
"region-metric",
|
|
16337
16703
|
"poi-metric",
|
|
16338
16704
|
"flow-metric",
|
|
16339
|
-
"
|
|
16340
|
-
"region-labels",
|
|
16341
|
-
"poi-labels",
|
|
16342
|
-
"default-country",
|
|
16343
|
-
"default-state",
|
|
16705
|
+
"locale",
|
|
16344
16706
|
"active-tag",
|
|
16707
|
+
"caption",
|
|
16345
16708
|
"no-legend",
|
|
16346
|
-
"no-
|
|
16347
|
-
"relief",
|
|
16348
|
-
"
|
|
16349
|
-
"
|
|
16709
|
+
"no-coastline",
|
|
16710
|
+
"no-relief",
|
|
16711
|
+
"no-context-labels",
|
|
16712
|
+
"no-region-labels",
|
|
16713
|
+
"no-poi-labels",
|
|
16714
|
+
"no-colorize"
|
|
16350
16715
|
]);
|
|
16351
16716
|
}
|
|
16352
16717
|
});
|
|
@@ -24358,8 +24723,8 @@ function renderKanban(container, parsed, palette, isDark, options) {
|
|
|
24358
24723
|
let metaY = separatorY + sCardSeparatorGap + sCardMetaFontSize;
|
|
24359
24724
|
for (const meta of tagMeta) {
|
|
24360
24725
|
cg.append("text").attr("x", cx + sCardPaddingX).attr("y", metaY).attr("font-size", sCardMetaFontSize).attr("fill", onCardText).text(`${meta.label}: `);
|
|
24361
|
-
const
|
|
24362
|
-
cg.append("text").attr("x", cx + sCardPaddingX +
|
|
24726
|
+
const labelWidth2 = (meta.label.length + 2) * sCardMetaFontSize * 0.6;
|
|
24727
|
+
cg.append("text").attr("x", cx + sCardPaddingX + labelWidth2).attr("y", metaY).attr("font-size", sCardMetaFontSize).attr("fill", onCardText).text(meta.value);
|
|
24363
24728
|
metaY += sCardMetaLineHeight;
|
|
24364
24729
|
}
|
|
24365
24730
|
for (const detail of card.details) {
|
|
@@ -24703,8 +25068,8 @@ function renderSwimlaneCard(parent, cardLayout, tagGroups, activeTagGroup, palet
|
|
|
24703
25068
|
let metaY = separatorY + sCardSeparatorGap + sCardMetaFontSize;
|
|
24704
25069
|
for (const meta of tagMeta) {
|
|
24705
25070
|
cg.append("text").attr("x", cx + sCardPaddingX).attr("y", metaY).attr("font-size", sCardMetaFontSize).attr("fill", palette.textMuted).text(`${meta.label}: `);
|
|
24706
|
-
const
|
|
24707
|
-
cg.append("text").attr("x", cx + sCardPaddingX +
|
|
25071
|
+
const labelWidth2 = (meta.label.length + 2) * sCardMetaFontSize * 0.6;
|
|
25072
|
+
cg.append("text").attr("x", cx + sCardPaddingX + labelWidth2).attr("y", metaY).attr("font-size", sCardMetaFontSize).attr("fill", onCardText).text(meta.value);
|
|
24708
25073
|
metaY += sCardMetaLineHeight;
|
|
24709
25074
|
}
|
|
24710
25075
|
for (const detail of card.details) {
|
|
@@ -25538,8 +25903,8 @@ function classifyEREntities(tables, relationships) {
|
|
|
25538
25903
|
}
|
|
25539
25904
|
}
|
|
25540
25905
|
const mmParticipants = /* @__PURE__ */ new Set();
|
|
25541
|
-
for (const [id,
|
|
25542
|
-
if (
|
|
25906
|
+
for (const [id, neighbors2] of tableStarNeighbors) {
|
|
25907
|
+
if (neighbors2.size >= 2) mmParticipants.add(id);
|
|
25543
25908
|
}
|
|
25544
25909
|
const indegreeValues = Object.values(indegreeMap);
|
|
25545
25910
|
const mean = indegreeValues.reduce((a, b) => a + b, 0) / indegreeValues.length;
|
|
@@ -26212,7 +26577,8 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26212
26577
|
controlsExpanded,
|
|
26213
26578
|
onToggleDescriptions,
|
|
26214
26579
|
onToggleControlsExpand,
|
|
26215
|
-
exportMode = false
|
|
26580
|
+
exportMode = false,
|
|
26581
|
+
controlsHost
|
|
26216
26582
|
} = options ?? {};
|
|
26217
26583
|
d3Selection6.select(container).selectAll(":not([data-d3-tooltip])").remove();
|
|
26218
26584
|
const width = exportDims?.width ?? container.clientWidth;
|
|
@@ -26230,7 +26596,11 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26230
26596
|
const sGroupLabelZone = sctx.structural(GROUP_LABEL_ZONE);
|
|
26231
26597
|
const sTitleFontSize = sctx.text(TITLE_FONT_SIZE);
|
|
26232
26598
|
const sTitleY = sctx.structural(TITLE_Y);
|
|
26233
|
-
const
|
|
26599
|
+
const reserveHasDescriptions = parsed.nodes.some(
|
|
26600
|
+
(n) => n.description && n.description.length > 0
|
|
26601
|
+
);
|
|
26602
|
+
const willRenderLegend = parsed.tagGroups.length > 0 || reserveHasDescriptions && controlsHost !== "app";
|
|
26603
|
+
const sLegendHeight = willRenderLegend ? sctx.structural(
|
|
26234
26604
|
getMaxLegendReservedHeight(
|
|
26235
26605
|
{
|
|
26236
26606
|
groups: parsed.tagGroups,
|
|
@@ -26239,7 +26609,7 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26239
26609
|
},
|
|
26240
26610
|
width
|
|
26241
26611
|
)
|
|
26242
|
-
);
|
|
26612
|
+
) : 0;
|
|
26243
26613
|
const activeGroup = resolveActiveTagGroup(
|
|
26244
26614
|
parsed.tagGroups,
|
|
26245
26615
|
parsed.options["active-tag"],
|
|
@@ -26554,10 +26924,10 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26554
26924
|
const hasDescriptions = parsed.nodes.some(
|
|
26555
26925
|
(n) => n.description && n.description.length > 0
|
|
26556
26926
|
);
|
|
26557
|
-
const hasLegend = parsed.tagGroups.length > 0 || hasDescriptions;
|
|
26927
|
+
const hasLegend = parsed.tagGroups.length > 0 || hasDescriptions && controlsHost !== "app";
|
|
26558
26928
|
if (hasLegend) {
|
|
26559
26929
|
let controlsGroup;
|
|
26560
|
-
if (hasDescriptions && onToggleDescriptions) {
|
|
26930
|
+
if (hasDescriptions && (onToggleDescriptions || controlsHost === "app")) {
|
|
26561
26931
|
controlsGroup = {
|
|
26562
26932
|
toggles: [
|
|
26563
26933
|
{
|
|
@@ -26575,7 +26945,14 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26575
26945
|
groups: parsed.tagGroups,
|
|
26576
26946
|
position: { placement: "top-center", titleRelation: "below-title" },
|
|
26577
26947
|
mode: exportMode ? "export" : "preview",
|
|
26578
|
-
|
|
26948
|
+
// Keep inactive sibling tag groups visible as collapsed pills so the user
|
|
26949
|
+
// can click one to flip the active colouring dimension (preview only —
|
|
26950
|
+
// export shows just the active group). Without this, declaring a second
|
|
26951
|
+
// tag group (e.g. Team) leaves it invisible whenever another group is
|
|
26952
|
+
// active. The app's BoxesAndLinesPreview already wires pill clicks.
|
|
26953
|
+
showInactivePills: true,
|
|
26954
|
+
...controlsGroup !== void 0 && { controlsGroup },
|
|
26955
|
+
...controlsHost !== void 0 && { controlsHost }
|
|
26579
26956
|
};
|
|
26580
26957
|
const legendState = {
|
|
26581
26958
|
activeGroup,
|
|
@@ -27822,8 +28199,9 @@ function renderMindmap(container, parsed, layout, palette, isDark, onClickItem,
|
|
|
27822
28199
|
const containerHeight = exportDims?.height ?? (container.getBoundingClientRect().height || 600);
|
|
27823
28200
|
d3Selection7.select(container).selectAll("*").remove();
|
|
27824
28201
|
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);
|
|
28202
|
+
const appHosted = options?.controlsHost === "app";
|
|
27825
28203
|
const hasControls = !!options?.onToggleColorByDepth || !!options?.onToggleDescriptions;
|
|
27826
|
-
const hasLegend = parsed.tagGroups.length > 0 || hasControls;
|
|
28204
|
+
const hasLegend = parsed.tagGroups.length > 0 || hasControls && !appHosted;
|
|
27827
28205
|
const fixedLegend = !isExport && hasLegend;
|
|
27828
28206
|
const legendReserve = fixedLegend ? getMaxLegendReservedHeight(
|
|
27829
28207
|
{
|
|
@@ -27917,7 +28295,10 @@ function renderMindmap(container, parsed, layout, palette, isDark, onClickItem,
|
|
|
27917
28295
|
}),
|
|
27918
28296
|
position: { placement: "top-center", titleRelation: "below-title" },
|
|
27919
28297
|
mode: options?.exportMode ? "export" : "preview",
|
|
27920
|
-
...controlsToggles !== void 0 && { controlsGroup: controlsToggles }
|
|
28298
|
+
...controlsToggles !== void 0 && { controlsGroup: controlsToggles },
|
|
28299
|
+
...options?.controlsHost !== void 0 && {
|
|
28300
|
+
controlsHost: options.controlsHost
|
|
28301
|
+
}
|
|
27921
28302
|
};
|
|
27922
28303
|
const legendState = {
|
|
27923
28304
|
activeGroup: options?.colorByDepth ? null : activeTagGroup !== void 0 ? activeTagGroup : parsed.options["active-tag"] ?? null,
|
|
@@ -28360,8 +28741,8 @@ function computeFieldAlignX(children) {
|
|
|
28360
28741
|
for (const child of children) {
|
|
28361
28742
|
if (child.metadata["_labelField"] === "true" && child.children.length >= 2) {
|
|
28362
28743
|
const labelEl = child.children[0];
|
|
28363
|
-
const
|
|
28364
|
-
maxLabelWidth = Math.max(maxLabelWidth,
|
|
28744
|
+
const labelWidth2 = labelEl.label.length * CHAR_WIDTH5;
|
|
28745
|
+
maxLabelWidth = Math.max(maxLabelWidth, labelWidth2);
|
|
28365
28746
|
labelFieldCount++;
|
|
28366
28747
|
}
|
|
28367
28748
|
}
|
|
@@ -33326,7 +33707,7 @@ function hasRoles(node) {
|
|
|
33326
33707
|
function computeNodeWidth2(node, expanded, options) {
|
|
33327
33708
|
const badgeVal = node.computedConcurrentInvocations === 0 && node.computedInstances > 1 ? node.computedInstances : 0;
|
|
33328
33709
|
const badgeLen = badgeVal > 0 ? `${badgeVal}x`.length + 2 : 0;
|
|
33329
|
-
const
|
|
33710
|
+
const labelWidth2 = (node.label.length + badgeLen) * CHAR_WIDTH7 + PADDING_X3;
|
|
33330
33711
|
const allKeys = [];
|
|
33331
33712
|
if (node.computedRps > 0) allKeys.push("RPS");
|
|
33332
33713
|
if (expanded) {
|
|
@@ -33370,7 +33751,7 @@ function computeNodeWidth2(node, expanded, options) {
|
|
|
33370
33751
|
allKeys.push("overflow");
|
|
33371
33752
|
}
|
|
33372
33753
|
}
|
|
33373
|
-
if (allKeys.length === 0) return Math.max(MIN_NODE_WIDTH2,
|
|
33754
|
+
if (allKeys.length === 0) return Math.max(MIN_NODE_WIDTH2, labelWidth2);
|
|
33374
33755
|
const maxKeyLen = Math.max(...allKeys.map((k) => k.length));
|
|
33375
33756
|
let maxRowWidth = 0;
|
|
33376
33757
|
if (node.computedRps > 0) {
|
|
@@ -33458,7 +33839,7 @@ function computeNodeWidth2(node, expanded, options) {
|
|
|
33458
33839
|
truncated.length * META_CHAR_WIDTH3 + PADDING_X3
|
|
33459
33840
|
);
|
|
33460
33841
|
}
|
|
33461
|
-
return Math.max(MIN_NODE_WIDTH2,
|
|
33842
|
+
return Math.max(MIN_NODE_WIDTH2, labelWidth2, maxRowWidth + 20, descWidth);
|
|
33462
33843
|
}
|
|
33463
33844
|
function computeNodeHeight2(node, expanded, options) {
|
|
33464
33845
|
const propCount = countDisplayProps(node, expanded, options);
|
|
@@ -35008,8 +35389,9 @@ function computeInfraLegendGroups(nodes, tagGroups, palette, edges) {
|
|
|
35008
35389
|
}
|
|
35009
35390
|
return groups;
|
|
35010
35391
|
}
|
|
35011
|
-
function renderLegend3(rootSvg, legendGroups, totalWidth, legendY, palette, isDark, activeGroup, playback, exportMode = false) {
|
|
35392
|
+
function renderLegend3(rootSvg, legendGroups, totalWidth, legendY, palette, isDark, activeGroup, playback, exportMode = false, controlsHost) {
|
|
35012
35393
|
if (legendGroups.length === 0 && !playback) return;
|
|
35394
|
+
const appHostedPlayback = controlsHost === "app" && !!playback;
|
|
35013
35395
|
const legendG = rootSvg.append("g").attr("transform", `translate(0, ${legendY})`);
|
|
35014
35396
|
if (activeGroup) {
|
|
35015
35397
|
legendG.attr("data-legend-active", activeGroup.toLowerCase());
|
|
@@ -35018,14 +35400,29 @@ function renderLegend3(rootSvg, legendGroups, totalWidth, legendY, palette, isDa
|
|
|
35018
35400
|
name: g.name,
|
|
35019
35401
|
entries: g.entries.map((e) => ({ value: e.value, color: e.color }))
|
|
35020
35402
|
}));
|
|
35021
|
-
if (playback) {
|
|
35403
|
+
if (playback && !appHostedPlayback) {
|
|
35022
35404
|
allGroups.push({ name: "Playback", entries: [] });
|
|
35023
35405
|
}
|
|
35024
35406
|
const legendConfig = {
|
|
35025
35407
|
groups: allGroups,
|
|
35026
35408
|
position: { placement: "top-center", titleRelation: "below-title" },
|
|
35027
35409
|
mode: exportMode ? "export" : "preview",
|
|
35028
|
-
showEmptyGroups: true
|
|
35410
|
+
showEmptyGroups: true,
|
|
35411
|
+
...appHostedPlayback && {
|
|
35412
|
+
controlsHost: "app",
|
|
35413
|
+
controlsGroup: {
|
|
35414
|
+
toggles: [
|
|
35415
|
+
{
|
|
35416
|
+
id: "playback",
|
|
35417
|
+
type: "toggle",
|
|
35418
|
+
label: "Playback",
|
|
35419
|
+
active: true,
|
|
35420
|
+
onToggle: () => {
|
|
35421
|
+
}
|
|
35422
|
+
}
|
|
35423
|
+
]
|
|
35424
|
+
}
|
|
35425
|
+
}
|
|
35029
35426
|
};
|
|
35030
35427
|
const legendState = { activeGroup };
|
|
35031
35428
|
renderLegendD3(
|
|
@@ -35076,8 +35473,9 @@ function renderLegend3(rootSvg, legendGroups, totalWidth, legendY, palette, isDa
|
|
|
35076
35473
|
}
|
|
35077
35474
|
}
|
|
35078
35475
|
}
|
|
35079
|
-
function renderInfra(container, layout, palette, isDark, title, titleLineNumber, tagGroups, activeGroup, animate, playback, expandedNodeIds, exportMode, collapsedNodes) {
|
|
35476
|
+
function renderInfra(container, layout, palette, isDark, title, titleLineNumber, tagGroups, activeGroup, animate, playback, expandedNodeIds, exportMode, collapsedNodes, controlsHost) {
|
|
35080
35477
|
d3Selection11.select(container).selectAll(":not([data-d3-tooltip])").remove();
|
|
35478
|
+
const appHostedPlayback = controlsHost === "app" && !!playback;
|
|
35081
35479
|
const ctx = ScaleContext.identity();
|
|
35082
35480
|
const sc = buildScaledConstants(ctx);
|
|
35083
35481
|
const legendGroups = computeInfraLegendGroups(
|
|
@@ -35086,7 +35484,7 @@ function renderInfra(container, layout, palette, isDark, title, titleLineNumber,
|
|
|
35086
35484
|
palette,
|
|
35087
35485
|
layout.edges
|
|
35088
35486
|
);
|
|
35089
|
-
const hasLegend = legendGroups.length > 0 || !!playback;
|
|
35487
|
+
const hasLegend = legendGroups.length > 0 || !!playback && !appHostedPlayback;
|
|
35090
35488
|
const fixedLegend = !exportMode && hasLegend;
|
|
35091
35489
|
const legendDynamicH = hasLegend ? getMaxLegendReservedHeight(
|
|
35092
35490
|
{
|
|
@@ -35230,7 +35628,8 @@ function renderInfra(container, layout, palette, isDark, title, titleLineNumber,
|
|
|
35230
35628
|
isDark,
|
|
35231
35629
|
activeGroup ?? null,
|
|
35232
35630
|
playback ?? void 0,
|
|
35233
|
-
exportMode
|
|
35631
|
+
exportMode,
|
|
35632
|
+
controlsHost
|
|
35234
35633
|
);
|
|
35235
35634
|
legendSvg.selectAll(".infra-legend-group").style("pointer-events", "auto");
|
|
35236
35635
|
} else {
|
|
@@ -35243,7 +35642,8 @@ function renderInfra(container, layout, palette, isDark, title, titleLineNumber,
|
|
|
35243
35642
|
isDark,
|
|
35244
35643
|
activeGroup ?? null,
|
|
35245
35644
|
playback ?? void 0,
|
|
35246
|
-
exportMode
|
|
35645
|
+
exportMode,
|
|
35646
|
+
controlsHost
|
|
35247
35647
|
);
|
|
35248
35648
|
}
|
|
35249
35649
|
}
|
|
@@ -43100,6 +43500,9 @@ function renderTechRadar(container, parsed, palette, isDark, onClickItem, export
|
|
|
43100
43500
|
onToggle: (active) => options.onToggleListing(active)
|
|
43101
43501
|
}
|
|
43102
43502
|
]
|
|
43503
|
+
},
|
|
43504
|
+
...options.controlsHost !== void 0 && {
|
|
43505
|
+
controlsHost: options.controlsHost
|
|
43103
43506
|
}
|
|
43104
43507
|
};
|
|
43105
43508
|
const legendState = {
|
|
@@ -44922,7 +45325,7 @@ function computeCycleLayout(parsed, options) {
|
|
|
44922
45325
|
const circleNodes = parsed.options["circle-nodes"] === "true";
|
|
44923
45326
|
const nodeDims = parsed.nodes.map((node) => {
|
|
44924
45327
|
const hasDesc = !hideDescriptions && node.description.length > 0;
|
|
44925
|
-
const
|
|
45328
|
+
const labelWidth2 = Math.max(
|
|
44926
45329
|
MIN_NODE_WIDTH4,
|
|
44927
45330
|
node.label.length * LABEL_CHAR_W + NODE_PAD_X * 2
|
|
44928
45331
|
);
|
|
@@ -44931,12 +45334,12 @@ function computeCycleLayout(parsed, options) {
|
|
|
44931
45334
|
}
|
|
44932
45335
|
if (!hasDesc) {
|
|
44933
45336
|
return {
|
|
44934
|
-
width: Math.min(MAX_NODE_WIDTH3,
|
|
45337
|
+
width: Math.min(MAX_NODE_WIDTH3, labelWidth2),
|
|
44935
45338
|
height: PLAIN_NODE_HEIGHT,
|
|
44936
45339
|
wrappedDesc: []
|
|
44937
45340
|
};
|
|
44938
45341
|
}
|
|
44939
|
-
return chooseDescribedRectDims(node.description,
|
|
45342
|
+
return chooseDescribedRectDims(node.description, labelWidth2);
|
|
44940
45343
|
});
|
|
44941
45344
|
if (circleNodes) {
|
|
44942
45345
|
const maxDiam = Math.max(...nodeDims.map((d) => d.width));
|
|
@@ -45132,10 +45535,10 @@ function computeCycleLayout(parsed, options) {
|
|
|
45132
45535
|
scale
|
|
45133
45536
|
};
|
|
45134
45537
|
}
|
|
45135
|
-
function chooseDescribedRectDims(description,
|
|
45538
|
+
function chooseDescribedRectDims(description, labelWidth2) {
|
|
45136
45539
|
const minW = Math.min(
|
|
45137
45540
|
MAX_NODE_WIDTH3,
|
|
45138
|
-
Math.max(MIN_NODE_WIDTH4,
|
|
45541
|
+
Math.max(MIN_NODE_WIDTH4, labelWidth2, DESC_MIN_WIDTH)
|
|
45139
45542
|
);
|
|
45140
45543
|
let best = null;
|
|
45141
45544
|
let bestScore = Infinity;
|
|
@@ -45564,7 +45967,8 @@ function renderCycle(container, parsed, palette, isDark, onClickItem, exportDims
|
|
|
45564
45967
|
const hideDescriptions = (renderOptions?.hideDescriptions ?? false) || parsed.options["no-descriptions"] === "true" || viewState?.hd === true;
|
|
45565
45968
|
const showDescriptions = !hideDescriptions;
|
|
45566
45969
|
const hasDescriptions = parsed.nodes.some((n) => n.description.length > 0) || parsed.edges.some((e) => e.description.length > 0);
|
|
45567
|
-
const
|
|
45970
|
+
const appHostedControls = renderOptions?.controlsHost === "app";
|
|
45971
|
+
const hasLegend = !appHostedControls && hasDescriptions && !!renderOptions?.onToggleDescriptions;
|
|
45568
45972
|
const showTitle = !!parsed.title && parsed.options["no-title"] !== "on";
|
|
45569
45973
|
const legendOffset = hasLegend ? sLegendHeight : 0;
|
|
45570
45974
|
const layoutHeight = height - (showTitle ? sTitleAreaHeight : 0) - legendOffset;
|
|
@@ -45601,7 +46005,10 @@ function renderCycle(container, parsed, palette, isDark, onClickItem, exportDims
|
|
|
45601
46005
|
groups: [],
|
|
45602
46006
|
position: { placement: "top-center", titleRelation: "below-title" },
|
|
45603
46007
|
mode: renderOptions?.exportMode ? "export" : "preview",
|
|
45604
|
-
controlsGroup
|
|
46008
|
+
controlsGroup,
|
|
46009
|
+
...renderOptions?.controlsHost !== void 0 && {
|
|
46010
|
+
controlsHost: renderOptions.controlsHost
|
|
46011
|
+
}
|
|
45605
46012
|
};
|
|
45606
46013
|
const legendState = {
|
|
45607
46014
|
activeGroup: null,
|
|
@@ -45855,7 +46262,7 @@ var init_renderer15 = __esm({
|
|
|
45855
46262
|
});
|
|
45856
46263
|
|
|
45857
46264
|
// src/map/geo.ts
|
|
45858
|
-
import { feature } from "topojson-client";
|
|
46265
|
+
import { feature, neighbors } from "topojson-client";
|
|
45859
46266
|
import { geoBounds, geoArea } from "d3-geo";
|
|
45860
46267
|
function geomObject(topo) {
|
|
45861
46268
|
const key = Object.keys(topo.objects)[0];
|
|
@@ -45873,6 +46280,29 @@ function featureIndex(topo) {
|
|
|
45873
46280
|
}
|
|
45874
46281
|
return idx;
|
|
45875
46282
|
}
|
|
46283
|
+
function buildAdjacency(topo) {
|
|
46284
|
+
const cached = adjacencyCache.get(topo);
|
|
46285
|
+
if (cached) return cached;
|
|
46286
|
+
const geometries = geomObject(topo).geometries;
|
|
46287
|
+
const nb = neighbors(geometries);
|
|
46288
|
+
const sets = /* @__PURE__ */ new Map();
|
|
46289
|
+
geometries.forEach((g, i) => {
|
|
46290
|
+
if (!g.type || g.type === "null") return;
|
|
46291
|
+
let set = sets.get(g.id);
|
|
46292
|
+
if (!set) {
|
|
46293
|
+
set = /* @__PURE__ */ new Set();
|
|
46294
|
+
sets.set(g.id, set);
|
|
46295
|
+
}
|
|
46296
|
+
for (const j of nb[i] ?? []) {
|
|
46297
|
+
const nid = geometries[j]?.id;
|
|
46298
|
+
if (nid && nid !== g.id) set.add(nid);
|
|
46299
|
+
}
|
|
46300
|
+
});
|
|
46301
|
+
const out = /* @__PURE__ */ new Map();
|
|
46302
|
+
for (const [iso, set] of sets) out.set(iso, [...set].sort());
|
|
46303
|
+
adjacencyCache.set(topo, out);
|
|
46304
|
+
return out;
|
|
46305
|
+
}
|
|
45876
46306
|
function decodeFeatures(topo) {
|
|
45877
46307
|
return geomObject(topo).geometries.map((g) => {
|
|
45878
46308
|
const f = feature(topo, g);
|
|
@@ -46068,11 +46498,12 @@ function unionLongitudes(lons) {
|
|
|
46068
46498
|
}
|
|
46069
46499
|
return { west: pts[gapIdx], east: pts[gapIdx - 1] + 360 };
|
|
46070
46500
|
}
|
|
46071
|
-
var fold, EDGE_EPS, DETACH_GAP_DEG, DETACH_AREA_FRAC;
|
|
46501
|
+
var fold, adjacencyCache, EDGE_EPS, DETACH_GAP_DEG, DETACH_AREA_FRAC;
|
|
46072
46502
|
var init_geo = __esm({
|
|
46073
46503
|
"src/map/geo.ts"() {
|
|
46074
46504
|
"use strict";
|
|
46075
46505
|
fold = (s) => s.normalize("NFD").replace(/\p{Diacritic}/gu, "").toLowerCase().trim();
|
|
46506
|
+
adjacencyCache = /* @__PURE__ */ new WeakMap();
|
|
46076
46507
|
EDGE_EPS = 1e-9;
|
|
46077
46508
|
DETACH_GAP_DEG = 10;
|
|
46078
46509
|
DETACH_AREA_FRAC = 0.25;
|
|
@@ -46093,6 +46524,12 @@ function looksUS(lat, lon) {
|
|
|
46093
46524
|
if (lat < 15 || lat > 72) return false;
|
|
46094
46525
|
return lon >= -180 && lon <= -64 || lon >= 172;
|
|
46095
46526
|
}
|
|
46527
|
+
function looksNorthAmericaNeighbor(lat, lon) {
|
|
46528
|
+
return lat >= 14 && lat <= 72 && lon >= -141 && lon <= -52;
|
|
46529
|
+
}
|
|
46530
|
+
function isWholeSphere(bb) {
|
|
46531
|
+
return bb[0][0] <= -179 && bb[1][0] >= 179 && bb[0][1] <= -89 && bb[1][1] >= 89;
|
|
46532
|
+
}
|
|
46096
46533
|
function resolveMap(parsed, data) {
|
|
46097
46534
|
const diagnostics = [...parsed.diagnostics];
|
|
46098
46535
|
const err = (line12, message, code) => {
|
|
@@ -46103,9 +46540,6 @@ function resolveMap(parsed, data) {
|
|
|
46103
46540
|
};
|
|
46104
46541
|
const result = {
|
|
46105
46542
|
title: parsed.title,
|
|
46106
|
-
...parsed.directives.subtitle !== void 0 && {
|
|
46107
|
-
subtitle: parsed.directives.subtitle
|
|
46108
|
-
},
|
|
46109
46543
|
...parsed.directives.caption !== void 0 && {
|
|
46110
46544
|
caption: parsed.directives.caption
|
|
46111
46545
|
},
|
|
@@ -46115,7 +46549,7 @@ function resolveMap(parsed, data) {
|
|
|
46115
46549
|
// renderer's job (step 4) — the resolver only carries `tags` + `tagGroups`
|
|
46116
46550
|
// through; it never resolves a tag value to a palette color (#10).
|
|
46117
46551
|
directives: { ...parsed.directives },
|
|
46118
|
-
basemaps: { world: "
|
|
46552
|
+
basemaps: { world: "detail", subdivisions: [] },
|
|
46119
46553
|
regions: [],
|
|
46120
46554
|
pois: [],
|
|
46121
46555
|
edges: [],
|
|
@@ -46124,7 +46558,8 @@ function resolveMap(parsed, data) {
|
|
|
46124
46558
|
[-180, -85],
|
|
46125
46559
|
[180, 85]
|
|
46126
46560
|
],
|
|
46127
|
-
projection: "
|
|
46561
|
+
projection: "equirectangular",
|
|
46562
|
+
poiFrameContainers: [],
|
|
46128
46563
|
diagnostics,
|
|
46129
46564
|
error: parsed.error
|
|
46130
46565
|
};
|
|
@@ -46134,7 +46569,10 @@ function resolveMap(parsed, data) {
|
|
|
46134
46569
|
...[...countryIndex.values()].map((v) => v.name),
|
|
46135
46570
|
...[...usStateIndex.values()].map((v) => v.name)
|
|
46136
46571
|
];
|
|
46137
|
-
const
|
|
46572
|
+
const localeRaw = parsed.directives.locale?.toUpperCase();
|
|
46573
|
+
const localeCountry = localeRaw ? localeRaw.split("-")[0] : void 0;
|
|
46574
|
+
const localeSubdivision = localeRaw && /^[A-Z]{2}-/.test(localeRaw) ? localeRaw : void 0;
|
|
46575
|
+
const usScoped = localeCountry === "US" || parsed.regions.some((r) => {
|
|
46138
46576
|
const f = fold(r.name);
|
|
46139
46577
|
return usStateIndex.has(f) && !countryIndex.has(f);
|
|
46140
46578
|
}) || parsed.regions.some(
|
|
@@ -46285,7 +46723,7 @@ function resolveMap(parsed, data) {
|
|
|
46285
46723
|
if (!scope)
|
|
46286
46724
|
warn(
|
|
46287
46725
|
line12,
|
|
46288
|
-
`"${name}" is ambiguous \u2014 resolved to the most-populous match.`,
|
|
46726
|
+
`"${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.`,
|
|
46289
46727
|
"W_MAP_AMBIGUOUS_NAME"
|
|
46290
46728
|
);
|
|
46291
46729
|
}
|
|
@@ -46298,17 +46736,21 @@ function resolveMap(parsed, data) {
|
|
|
46298
46736
|
return fold(pos.name);
|
|
46299
46737
|
};
|
|
46300
46738
|
const poiCountries = [];
|
|
46301
|
-
let
|
|
46739
|
+
let anyUsPoi = false;
|
|
46740
|
+
let anyNonNaPoi = false;
|
|
46302
46741
|
const noteCountry = (iso) => {
|
|
46303
46742
|
if (iso) {
|
|
46304
46743
|
poiCountries.push(iso);
|
|
46305
|
-
if (iso
|
|
46744
|
+
if (iso === "US") anyUsPoi = true;
|
|
46745
|
+
if (iso !== "US" && iso !== "CA" && iso !== "MX") anyNonNaPoi = true;
|
|
46306
46746
|
}
|
|
46307
46747
|
};
|
|
46308
46748
|
const deferred = [];
|
|
46309
46749
|
for (const p of parsed.pois) {
|
|
46310
46750
|
if (p.pos.kind === "coords") {
|
|
46311
|
-
if (
|
|
46751
|
+
if (looksUS(p.pos.lat, p.pos.lon)) anyUsPoi = true;
|
|
46752
|
+
else if (!looksNorthAmericaNeighbor(p.pos.lat, p.pos.lon))
|
|
46753
|
+
anyNonNaPoi = true;
|
|
46312
46754
|
addResolvedPoi(p.pos.lat, p.pos.lon, p);
|
|
46313
46755
|
continue;
|
|
46314
46756
|
}
|
|
@@ -46326,14 +46768,15 @@ function resolveMap(parsed, data) {
|
|
|
46326
46768
|
deferred.push(p);
|
|
46327
46769
|
}
|
|
46328
46770
|
}
|
|
46329
|
-
const inferredCountry =
|
|
46771
|
+
const inferredCountry = localeCountry ?? mostCommonCountry(regions, poiCountries) ?? void 0;
|
|
46772
|
+
const inferredScope = localeSubdivision ?? inferredCountry;
|
|
46330
46773
|
for (const p of deferred) {
|
|
46331
46774
|
if (p.pos.kind !== "name") continue;
|
|
46332
46775
|
const got = lookupName(
|
|
46333
46776
|
p.pos.name,
|
|
46334
46777
|
p.pos.scope,
|
|
46335
46778
|
p.lineNumber,
|
|
46336
|
-
|
|
46779
|
+
inferredScope,
|
|
46337
46780
|
true
|
|
46338
46781
|
);
|
|
46339
46782
|
if (got.kind === "ok") {
|
|
@@ -46403,7 +46846,8 @@ function resolveMap(parsed, data) {
|
|
|
46403
46846
|
const meta = sizeValue !== void 0 ? { value: sizeValue } : {};
|
|
46404
46847
|
if (pos.kind === "coords") {
|
|
46405
46848
|
const id = alias ? fold(alias) : `@${pos.lat},${pos.lon}`;
|
|
46406
|
-
if (
|
|
46849
|
+
if (looksUS(pos.lat, pos.lon)) anyUsPoi = true;
|
|
46850
|
+
else if (!looksNorthAmericaNeighbor(pos.lat, pos.lon)) anyNonNaPoi = true;
|
|
46407
46851
|
if (!registry.has(id)) {
|
|
46408
46852
|
registerPoi(
|
|
46409
46853
|
id,
|
|
@@ -46426,7 +46870,7 @@ function resolveMap(parsed, data) {
|
|
|
46426
46870
|
if (registry.has(f)) return f;
|
|
46427
46871
|
const aliased = declaredByName.get(f);
|
|
46428
46872
|
if (aliased) return aliased;
|
|
46429
|
-
const got = lookupName(pos.name, pos.scope, line12,
|
|
46873
|
+
const got = lookupName(pos.name, pos.scope, line12, inferredScope, true);
|
|
46430
46874
|
if (got.kind !== "ok") return null;
|
|
46431
46875
|
noteCountry(got.iso);
|
|
46432
46876
|
registerPoi(
|
|
@@ -46483,9 +46927,12 @@ function resolveMap(parsed, data) {
|
|
|
46483
46927
|
}
|
|
46484
46928
|
routes.push({ stopIds, legs, lineNumber: rt.lineNumber });
|
|
46485
46929
|
}
|
|
46930
|
+
const hasUsContent = usSubdivisionReferenced || anyUsPoi || localeCountry === "US";
|
|
46931
|
+
const usOriented = !anyNonNaPoi && !regions.some(
|
|
46932
|
+
(r) => r.layer === "country" && !["US", "CA", "MX"].includes(r.iso)
|
|
46933
|
+
) && hasUsContent;
|
|
46486
46934
|
const subdivisions = [];
|
|
46487
|
-
if (usSubdivisionReferenced ||
|
|
46488
|
-
subdivisions.push("us-states");
|
|
46935
|
+
if (usSubdivisionReferenced || usOriented) subdivisions.push("us-states");
|
|
46489
46936
|
const regionBoxes = [];
|
|
46490
46937
|
for (const ref of referencedRegionIds) {
|
|
46491
46938
|
const bb = featureBbox(data.usStates, ref.id);
|
|
@@ -46503,17 +46950,51 @@ function resolveMap(parsed, data) {
|
|
|
46503
46950
|
[-180, -85],
|
|
46504
46951
|
[180, 85]
|
|
46505
46952
|
];
|
|
46506
|
-
|
|
46953
|
+
const basePad = regions.length > 0 ? REGION_PAD_FRACTION : PAD_FRACTION;
|
|
46954
|
+
let extent2 = unioned ? pad(unioned, basePad) : DEFAULT_EXTENT;
|
|
46955
|
+
const isPoiOnly = pois.length > 0 && regions.length === 0;
|
|
46956
|
+
const containerRegionIds = [];
|
|
46957
|
+
if (isPoiOnly) {
|
|
46958
|
+
const countries = decodeFeatures(data.worldDetail);
|
|
46959
|
+
const states = decodeFeatures(data.usStates);
|
|
46960
|
+
const seen = /* @__PURE__ */ new Set();
|
|
46961
|
+
const containerBoxes = [];
|
|
46962
|
+
for (const p of pois) {
|
|
46963
|
+
const { country, state } = regionAt([p.lon, p.lat], countries, states);
|
|
46964
|
+
const id = state?.iso ?? country?.iso;
|
|
46965
|
+
if (!id || seen.has(id)) continue;
|
|
46966
|
+
seen.add(id);
|
|
46967
|
+
containerRegionIds.push(id);
|
|
46968
|
+
const bb = state ? featureBbox(data.usStates, id) : featureBboxPrimary(data.worldCoarse, id);
|
|
46969
|
+
if (bb && !isWholeSphere(bb)) containerBoxes.push(bb);
|
|
46970
|
+
}
|
|
46971
|
+
const containerUnion = unionExtent(containerBoxes, points);
|
|
46972
|
+
if (containerUnion) extent2 = pad(containerUnion, PAD_FRACTION);
|
|
46973
|
+
}
|
|
46974
|
+
if (isPoiOnly) {
|
|
46975
|
+
const cx = (extent2[0][0] + extent2[1][0]) / 2;
|
|
46976
|
+
const cy = (extent2[0][1] + extent2[1][1]) / 2;
|
|
46977
|
+
const lon = extent2[1][0] - extent2[0][0];
|
|
46978
|
+
const lat = extent2[1][1] - extent2[0][1];
|
|
46979
|
+
const longer = Math.max(lon, lat);
|
|
46980
|
+
if (longer > 0 && longer < POI_ZOOM_FLOOR_DEG) {
|
|
46981
|
+
const k = POI_ZOOM_FLOOR_DEG / longer;
|
|
46982
|
+
const halfLon = lon * k / 2;
|
|
46983
|
+
const halfLat = lat * k / 2;
|
|
46984
|
+
extent2 = [
|
|
46985
|
+
[cx - halfLon, cy - halfLat],
|
|
46986
|
+
[cx + halfLon, cy + halfLat]
|
|
46987
|
+
];
|
|
46988
|
+
}
|
|
46989
|
+
}
|
|
46507
46990
|
const lonSpan = extent2[1][0] - extent2[0][0];
|
|
46508
46991
|
const latSpan = extent2[1][1] - extent2[0][1];
|
|
46509
46992
|
const span = Math.max(lonSpan, latSpan);
|
|
46510
46993
|
const maxAbsLat = Math.max(Math.abs(extent2[0][1]), Math.abs(extent2[1][1]));
|
|
46511
|
-
const usDominant = (subdivisions.includes("us-states") || regions.some((r) => r.layer === "us-state")) && !regions.some((r) => r.layer === "country" && r.iso !== "US") && !anyNonUsPoi;
|
|
46512
46994
|
let projection;
|
|
46513
|
-
|
|
46514
|
-
|
|
46515
|
-
|
|
46516
|
-
} else if (usDominant) {
|
|
46995
|
+
if (isPoiOnly && usOriented && lonSpan < US_NATIONAL_LON_SPAN) {
|
|
46996
|
+
projection = "mercator";
|
|
46997
|
+
} else if (usOriented) {
|
|
46517
46998
|
projection = "albers-usa";
|
|
46518
46999
|
} else if (span > WORLD_SPAN || maxAbsLat > MERCATOR_MAX_LAT) {
|
|
46519
47000
|
projection = "equirectangular";
|
|
@@ -46531,11 +47012,20 @@ function resolveMap(parsed, data) {
|
|
|
46531
47012
|
result.edges = edges;
|
|
46532
47013
|
result.routes = routes;
|
|
46533
47014
|
result.basemaps = {
|
|
46534
|
-
|
|
47015
|
+
// Tier is intentionally pinned to detail (50m) at ALL scales. Diagrammo maps
|
|
47016
|
+
// are presentational (palette tints, relief hachures, POI hubs), not
|
|
47017
|
+
// survey-grade — recognizability > generalization: 110m coarse drops the
|
|
47018
|
+
// Italian boot to a stump at world scale. `WORLD_SPAN` lives on only for the
|
|
47019
|
+
// projection decision (the `usOriented`/`span > WORLD_SPAN` chain above); it
|
|
47020
|
+
// no longer gates basemap resolution.
|
|
47021
|
+
// `worldCoarse` is still loaded — it's the authoritative name/bbox index
|
|
47022
|
+
// (featureIndex, featureBboxPrimary), not dead code.
|
|
47023
|
+
world: "detail",
|
|
46535
47024
|
subdivisions
|
|
46536
47025
|
};
|
|
46537
47026
|
result.extent = extent2;
|
|
46538
47027
|
result.projection = projection;
|
|
47028
|
+
result.poiFrameContainers = containerRegionIds;
|
|
46539
47029
|
result.error = parsed.error ?? firstError(diagnostics);
|
|
46540
47030
|
return result;
|
|
46541
47031
|
}
|
|
@@ -46572,7 +47062,7 @@ function firstError(diags) {
|
|
|
46572
47062
|
const e = diags.find((d) => d.severity === "error");
|
|
46573
47063
|
return e ? formatDgmoError(e) : null;
|
|
46574
47064
|
}
|
|
46575
|
-
var WORLD_SPAN, MERCATOR_MAX_LAT, PAD_FRACTION, WORLD_LAT_SOUTH, WORLD_LAT_NORTH, REGION_ALIASES, US_STATE_POSTAL;
|
|
47065
|
+
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;
|
|
46576
47066
|
var init_resolver2 = __esm({
|
|
46577
47067
|
"src/map/resolver.ts"() {
|
|
46578
47068
|
"use strict";
|
|
@@ -46581,8 +47071,11 @@ var init_resolver2 = __esm({
|
|
|
46581
47071
|
WORLD_SPAN = 90;
|
|
46582
47072
|
MERCATOR_MAX_LAT = 80;
|
|
46583
47073
|
PAD_FRACTION = 0.05;
|
|
47074
|
+
REGION_PAD_FRACTION = 0.12;
|
|
46584
47075
|
WORLD_LAT_SOUTH = -58;
|
|
46585
47076
|
WORLD_LAT_NORTH = 78;
|
|
47077
|
+
POI_ZOOM_FLOOR_DEG = 7;
|
|
47078
|
+
US_NATIONAL_LON_SPAN = 48;
|
|
46586
47079
|
REGION_ALIASES = {
|
|
46587
47080
|
// Common everyday names → the Natural-Earth display name actually shipped.
|
|
46588
47081
|
"united states": "united states of america",
|
|
@@ -46660,10 +47153,277 @@ var init_resolver2 = __esm({
|
|
|
46660
47153
|
}
|
|
46661
47154
|
});
|
|
46662
47155
|
|
|
47156
|
+
// src/map/colorize.ts
|
|
47157
|
+
function assignColors(isos, adjacency) {
|
|
47158
|
+
const sorted = [...isos].sort();
|
|
47159
|
+
const byIso = /* @__PURE__ */ new Map();
|
|
47160
|
+
let maxIndex = -1;
|
|
47161
|
+
for (const iso of sorted) {
|
|
47162
|
+
const taken = /* @__PURE__ */ new Set();
|
|
47163
|
+
for (const n of adjacency.get(iso) ?? []) {
|
|
47164
|
+
const c = byIso.get(n);
|
|
47165
|
+
if (c !== void 0) taken.add(c);
|
|
47166
|
+
}
|
|
47167
|
+
let h = 0;
|
|
47168
|
+
while (taken.has(h)) h++;
|
|
47169
|
+
byIso.set(iso, h);
|
|
47170
|
+
if (h > maxIndex) maxIndex = h;
|
|
47171
|
+
}
|
|
47172
|
+
return { byIso, huesNeeded: maxIndex + 1 };
|
|
47173
|
+
}
|
|
47174
|
+
var init_colorize = __esm({
|
|
47175
|
+
"src/map/colorize.ts"() {
|
|
47176
|
+
"use strict";
|
|
47177
|
+
}
|
|
47178
|
+
});
|
|
47179
|
+
|
|
47180
|
+
// src/map/context-labels.ts
|
|
47181
|
+
function tierBand(maxSpanDeg) {
|
|
47182
|
+
if (maxSpanDeg >= 90) return "world";
|
|
47183
|
+
if (maxSpanDeg >= 20) return "continental";
|
|
47184
|
+
if (maxSpanDeg >= 5) return "regional";
|
|
47185
|
+
return "local";
|
|
47186
|
+
}
|
|
47187
|
+
function labelBudget(width, height, band) {
|
|
47188
|
+
const bandCap = {
|
|
47189
|
+
world: 6,
|
|
47190
|
+
continental: 5,
|
|
47191
|
+
regional: 4,
|
|
47192
|
+
local: 3
|
|
47193
|
+
};
|
|
47194
|
+
const area2 = Math.floor(Math.sqrt(Math.max(0, width * height)) / 150);
|
|
47195
|
+
return Math.max(0, Math.min(area2, bandCap[band]));
|
|
47196
|
+
}
|
|
47197
|
+
function waterEligible(tier, kind, band) {
|
|
47198
|
+
switch (band) {
|
|
47199
|
+
case "world":
|
|
47200
|
+
return tier <= 1 && (kind === "ocean" || kind === "sea");
|
|
47201
|
+
case "continental":
|
|
47202
|
+
return tier <= 2;
|
|
47203
|
+
case "regional":
|
|
47204
|
+
return tier <= 3;
|
|
47205
|
+
case "local":
|
|
47206
|
+
return tier <= 4;
|
|
47207
|
+
}
|
|
47208
|
+
}
|
|
47209
|
+
function insideViewport(p, width, height) {
|
|
47210
|
+
return !!p && Number.isFinite(p[0]) && Number.isFinite(p[1]) && p[0] >= 0 && p[0] <= width && p[1] >= 0 && p[1] <= height;
|
|
47211
|
+
}
|
|
47212
|
+
function labelWidth(text, letterSpacing) {
|
|
47213
|
+
const spacing = letterSpacing > 0 ? Math.max(0, text.length - 1) * letterSpacing : 0;
|
|
47214
|
+
return measureLegendText(text, FONT) + spacing + 2 * PADX;
|
|
47215
|
+
}
|
|
47216
|
+
function wrapLabel2(text, letterSpacing) {
|
|
47217
|
+
const words = text.split(/\s+/).filter(Boolean);
|
|
47218
|
+
if (words.length <= 1) return [text];
|
|
47219
|
+
const maxLines = words.length >= 4 ? 3 : 2;
|
|
47220
|
+
const n = words.length;
|
|
47221
|
+
let best = null;
|
|
47222
|
+
for (let mask = 0; mask < 1 << n - 1; mask++) {
|
|
47223
|
+
const lines = [];
|
|
47224
|
+
let cur = [words[0]];
|
|
47225
|
+
for (let i = 1; i < n; i++) {
|
|
47226
|
+
if (mask & 1 << i - 1) {
|
|
47227
|
+
lines.push(cur.join(" "));
|
|
47228
|
+
cur = [words[i]];
|
|
47229
|
+
} else cur.push(words[i]);
|
|
47230
|
+
}
|
|
47231
|
+
lines.push(cur.join(" "));
|
|
47232
|
+
if (lines.length > maxLines) continue;
|
|
47233
|
+
const cost = Math.round(
|
|
47234
|
+
Math.max(...lines.map((l) => labelWidth(l, letterSpacing)))
|
|
47235
|
+
);
|
|
47236
|
+
const head = labelWidth(lines[0], letterSpacing);
|
|
47237
|
+
if (!best || cost < best.cost || cost === best.cost && lines.length < best.lines.length || cost === best.cost && lines.length === best.lines.length && head > best.head)
|
|
47238
|
+
best = { lines, cost, head };
|
|
47239
|
+
}
|
|
47240
|
+
return best?.lines ?? [text];
|
|
47241
|
+
}
|
|
47242
|
+
function rectAround(cx, cy, lines, letterSpacing) {
|
|
47243
|
+
const w = Math.max(...lines.map((l) => labelWidth(l, letterSpacing)));
|
|
47244
|
+
const h = (lines.length - 1) * LINE_HEIGHT + FONT + 2 * PADY;
|
|
47245
|
+
return { x: cx - w / 2, y: cy - h / 2, w, h };
|
|
47246
|
+
}
|
|
47247
|
+
function rectFits(r, width, height) {
|
|
47248
|
+
return r.x >= 0 && r.y >= 0 && r.x + r.w <= width && r.y + r.h <= height;
|
|
47249
|
+
}
|
|
47250
|
+
function overlapsPadded(a, b, pad2) {
|
|
47251
|
+
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;
|
|
47252
|
+
}
|
|
47253
|
+
function placeContextLabels(args) {
|
|
47254
|
+
const {
|
|
47255
|
+
projection,
|
|
47256
|
+
dLonSpan,
|
|
47257
|
+
dLatSpan,
|
|
47258
|
+
width,
|
|
47259
|
+
height,
|
|
47260
|
+
waterBodies,
|
|
47261
|
+
countries,
|
|
47262
|
+
palette,
|
|
47263
|
+
project,
|
|
47264
|
+
collides,
|
|
47265
|
+
overLand
|
|
47266
|
+
} = args;
|
|
47267
|
+
void projection;
|
|
47268
|
+
const band = tierBand(Math.max(dLonSpan, dLatSpan));
|
|
47269
|
+
const budget = labelBudget(width, height, band);
|
|
47270
|
+
if (budget <= 0) return [];
|
|
47271
|
+
const waterColor = mix(palette.colors.blue, palette.textMuted, 50);
|
|
47272
|
+
const countryColor = palette.textMuted;
|
|
47273
|
+
const haloColor = palette.bg;
|
|
47274
|
+
const candidates = [];
|
|
47275
|
+
const center = [width / 2, height / 2];
|
|
47276
|
+
for (const e of waterBodies?.entries ?? []) {
|
|
47277
|
+
const [lat, lon, name, tier, kind, alt] = e;
|
|
47278
|
+
if (!waterEligible(tier, kind, band)) continue;
|
|
47279
|
+
const wlines = wrapLabel2(name, WATER_LETTER_SPACING);
|
|
47280
|
+
const anchorsLngLat = [[lon, lat]];
|
|
47281
|
+
for (const a of alt ?? []) anchorsLngLat.push([a[1], a[0]]);
|
|
47282
|
+
let best = null;
|
|
47283
|
+
let bestD = Infinity;
|
|
47284
|
+
let nearestProj = null;
|
|
47285
|
+
let nearestProjD = Infinity;
|
|
47286
|
+
for (const [aLon, aLat] of anchorsLngLat) {
|
|
47287
|
+
const p = project(aLon, aLat);
|
|
47288
|
+
if (!p || !Number.isFinite(p[0]) || !Number.isFinite(p[1])) continue;
|
|
47289
|
+
const d = (p[0] - center[0]) ** 2 + (p[1] - center[1]) ** 2;
|
|
47290
|
+
if (d < nearestProjD) {
|
|
47291
|
+
nearestProjD = d;
|
|
47292
|
+
nearestProj = p;
|
|
47293
|
+
}
|
|
47294
|
+
if (!insideViewport(p, width, height)) continue;
|
|
47295
|
+
if (d < bestD) {
|
|
47296
|
+
bestD = d;
|
|
47297
|
+
best = p;
|
|
47298
|
+
}
|
|
47299
|
+
}
|
|
47300
|
+
if (!best && tier === 0 && nearestProj) {
|
|
47301
|
+
const overX = Math.max(0, -nearestProj[0], nearestProj[0] - width);
|
|
47302
|
+
const overY = Math.max(0, -nearestProj[1], nearestProj[1] - height);
|
|
47303
|
+
if (overX <= width * EDGE_CLAMP_OVERSHOOT && overY <= height * EDGE_CLAMP_OVERSHOOT) {
|
|
47304
|
+
const halfW = Math.max(...wlines.map((l) => labelWidth(l, WATER_LETTER_SPACING))) / 2;
|
|
47305
|
+
const halfH = ((wlines.length - 1) * LINE_HEIGHT + FONT + 2 * PADY) / 2;
|
|
47306
|
+
const m = EDGE_CLAMP_MARGIN;
|
|
47307
|
+
best = [
|
|
47308
|
+
Math.min(Math.max(nearestProj[0], halfW + m), width - halfW - m),
|
|
47309
|
+
Math.min(Math.max(nearestProj[1], halfH + m), height - halfH - m)
|
|
47310
|
+
];
|
|
47311
|
+
}
|
|
47312
|
+
}
|
|
47313
|
+
if (!best) continue;
|
|
47314
|
+
candidates.push({
|
|
47315
|
+
text: name,
|
|
47316
|
+
lines: wlines,
|
|
47317
|
+
cx: best[0],
|
|
47318
|
+
cy: best[1],
|
|
47319
|
+
italic: true,
|
|
47320
|
+
letterSpacing: WATER_LETTER_SPACING,
|
|
47321
|
+
color: waterColor,
|
|
47322
|
+
// Water before any country (×1000), then by tier, then kind, then name.
|
|
47323
|
+
sort: tier * 10 + KIND_ORDER[kind]
|
|
47324
|
+
});
|
|
47325
|
+
}
|
|
47326
|
+
const ranked = countries.map((c) => {
|
|
47327
|
+
const [x0, y0, x1, y1] = c.bbox;
|
|
47328
|
+
const w = x1 - x0;
|
|
47329
|
+
const h = y1 - y0;
|
|
47330
|
+
return { c, w, h, area: w * h };
|
|
47331
|
+
}).filter((r) => Number.isFinite(r.area) && r.area > 0).sort((a, b) => b.area - a.area);
|
|
47332
|
+
let ci = 0;
|
|
47333
|
+
for (const r of ranked) {
|
|
47334
|
+
const { c, w, h } = r;
|
|
47335
|
+
if (w > width * 0.66 || h > height * 0.66) continue;
|
|
47336
|
+
if (!insideViewport(c.anchor, width, height)) continue;
|
|
47337
|
+
const text = c.name;
|
|
47338
|
+
const tw = labelWidth(text, 0);
|
|
47339
|
+
if (tw > w || FONT + 2 * PADY > h) continue;
|
|
47340
|
+
candidates.push({
|
|
47341
|
+
text,
|
|
47342
|
+
lines: [text],
|
|
47343
|
+
cx: c.anchor[0],
|
|
47344
|
+
cy: c.anchor[1],
|
|
47345
|
+
italic: false,
|
|
47346
|
+
letterSpacing: 0,
|
|
47347
|
+
color: countryColor,
|
|
47348
|
+
// Always after every water body (+1e6); larger area = earlier.
|
|
47349
|
+
sort: 1e6 + ci++
|
|
47350
|
+
});
|
|
47351
|
+
}
|
|
47352
|
+
candidates.sort((a, b) => a.sort - b.sort);
|
|
47353
|
+
const placed = [];
|
|
47354
|
+
const placedRects = [];
|
|
47355
|
+
for (const cand of candidates) {
|
|
47356
|
+
if (placed.length >= budget) break;
|
|
47357
|
+
const rect = rectAround(cand.cx, cand.cy, cand.lines, cand.letterSpacing);
|
|
47358
|
+
if (!rectFits(rect, width, height)) continue;
|
|
47359
|
+
if (cand.italic && overLand) {
|
|
47360
|
+
const inset = 2;
|
|
47361
|
+
const top = cand.cy - (cand.lines.length - 1) / 2 * LINE_HEIGHT;
|
|
47362
|
+
const touchesLand = cand.lines.some((line12, li) => {
|
|
47363
|
+
const lw = labelWidth(line12, cand.letterSpacing);
|
|
47364
|
+
const x0 = cand.cx - lw / 2 + inset;
|
|
47365
|
+
const x1 = cand.cx + lw / 2 - inset;
|
|
47366
|
+
const xs = [x0, (x0 + cand.cx) / 2, cand.cx, (cand.cx + x1) / 2, x1];
|
|
47367
|
+
const base = top + li * LINE_HEIGHT;
|
|
47368
|
+
return [base, base - FONT * 0.4, base - FONT * 0.8].some(
|
|
47369
|
+
(y) => xs.some((x) => overLand(x, y))
|
|
47370
|
+
);
|
|
47371
|
+
});
|
|
47372
|
+
if (touchesLand) continue;
|
|
47373
|
+
}
|
|
47374
|
+
if (collides(rect)) continue;
|
|
47375
|
+
if (placedRects.some((r) => overlapsPadded(rect, r, CONTEXT_PAD))) continue;
|
|
47376
|
+
placedRects.push(rect);
|
|
47377
|
+
placed.push({
|
|
47378
|
+
x: cand.cx,
|
|
47379
|
+
y: cand.cy,
|
|
47380
|
+
text: cand.text,
|
|
47381
|
+
anchor: "middle",
|
|
47382
|
+
color: cand.color,
|
|
47383
|
+
// No halo: the bg-coloured outline reads as a ghost box behind the text
|
|
47384
|
+
// over the tinted water/land. Context labels are muted enough to sit
|
|
47385
|
+
// cleanly on the basemap without one.
|
|
47386
|
+
halo: false,
|
|
47387
|
+
haloColor,
|
|
47388
|
+
italic: cand.italic,
|
|
47389
|
+
letterSpacing: cand.letterSpacing,
|
|
47390
|
+
...cand.lines.length > 1 ? { lines: cand.lines } : {},
|
|
47391
|
+
lineNumber: 0
|
|
47392
|
+
});
|
|
47393
|
+
}
|
|
47394
|
+
return placed;
|
|
47395
|
+
}
|
|
47396
|
+
var FONT, LINE_HEIGHT, PADX, PADY, WATER_LETTER_SPACING, CONTEXT_PAD, EDGE_CLAMP_MARGIN, EDGE_CLAMP_OVERSHOOT, KIND_ORDER;
|
|
47397
|
+
var init_context_labels = __esm({
|
|
47398
|
+
"src/map/context-labels.ts"() {
|
|
47399
|
+
"use strict";
|
|
47400
|
+
init_color_utils();
|
|
47401
|
+
init_legend_constants();
|
|
47402
|
+
FONT = 11;
|
|
47403
|
+
LINE_HEIGHT = FONT + 2;
|
|
47404
|
+
PADX = 4;
|
|
47405
|
+
PADY = 3;
|
|
47406
|
+
WATER_LETTER_SPACING = 1.5;
|
|
47407
|
+
CONTEXT_PAD = 4;
|
|
47408
|
+
EDGE_CLAMP_MARGIN = 8;
|
|
47409
|
+
EDGE_CLAMP_OVERSHOOT = 0.35;
|
|
47410
|
+
KIND_ORDER = {
|
|
47411
|
+
ocean: 0,
|
|
47412
|
+
sea: 1,
|
|
47413
|
+
gulf: 2,
|
|
47414
|
+
bay: 3,
|
|
47415
|
+
strait: 4,
|
|
47416
|
+
channel: 5,
|
|
47417
|
+
sound: 6
|
|
47418
|
+
};
|
|
47419
|
+
}
|
|
47420
|
+
});
|
|
47421
|
+
|
|
46663
47422
|
// src/map/layout.ts
|
|
46664
47423
|
import {
|
|
46665
47424
|
geoPath,
|
|
46666
47425
|
geoNaturalEarth1,
|
|
47426
|
+
geoEqualEarth,
|
|
46667
47427
|
geoEquirectangular,
|
|
46668
47428
|
geoConicEqualArea,
|
|
46669
47429
|
geoMercator,
|
|
@@ -46675,12 +47435,34 @@ function geomObject2(topo) {
|
|
|
46675
47435
|
const key = Object.keys(topo.objects)[0];
|
|
46676
47436
|
return topo.objects[key];
|
|
46677
47437
|
}
|
|
47438
|
+
function mergeFeatures(a, b) {
|
|
47439
|
+
const polysOf = (f) => {
|
|
47440
|
+
const g = f.geometry;
|
|
47441
|
+
if (!g) return null;
|
|
47442
|
+
if (g.type === "Polygon") return [g.coordinates];
|
|
47443
|
+
if (g.type === "MultiPolygon") return g.coordinates;
|
|
47444
|
+
return null;
|
|
47445
|
+
};
|
|
47446
|
+
const pa = polysOf(a);
|
|
47447
|
+
const pb = polysOf(b);
|
|
47448
|
+
if (!pa || !pb) return a;
|
|
47449
|
+
return {
|
|
47450
|
+
...a,
|
|
47451
|
+
geometry: { type: "MultiPolygon", coordinates: [...pa, ...pb] }
|
|
47452
|
+
};
|
|
47453
|
+
}
|
|
46678
47454
|
function decodeLayer(topo) {
|
|
47455
|
+
const cached = decodeCache.get(topo);
|
|
47456
|
+
if (cached) return cached;
|
|
46679
47457
|
const out = /* @__PURE__ */ new Map();
|
|
46680
47458
|
for (const g of geomObject2(topo).geometries) {
|
|
46681
47459
|
const f = feature2(topo, g);
|
|
46682
|
-
|
|
47460
|
+
if (!f.geometry) continue;
|
|
47461
|
+
const tagged = { ...f, id: g.id };
|
|
47462
|
+
const existing = out.get(g.id);
|
|
47463
|
+
out.set(g.id, existing ? mergeFeatures(existing, tagged) : tagged);
|
|
46683
47464
|
}
|
|
47465
|
+
decodeCache.set(topo, out);
|
|
46684
47466
|
return out;
|
|
46685
47467
|
}
|
|
46686
47468
|
function projectionFor(family) {
|
|
@@ -46689,9 +47471,12 @@ function projectionFor(family) {
|
|
|
46689
47471
|
return usConusProjection();
|
|
46690
47472
|
case "mercator":
|
|
46691
47473
|
return geoMercator();
|
|
47474
|
+
case "equal-earth":
|
|
47475
|
+
return geoEqualEarth();
|
|
47476
|
+
case "equirectangular":
|
|
47477
|
+
return geoEquirectangular();
|
|
46692
47478
|
case "natural-earth":
|
|
46693
47479
|
return geoNaturalEarth1();
|
|
46694
|
-
case "equirectangular":
|
|
46695
47480
|
default:
|
|
46696
47481
|
return geoEquirectangular();
|
|
46697
47482
|
}
|
|
@@ -46710,13 +47495,11 @@ function mapNeutralLandColor(palette, isDark, _dataActive = false) {
|
|
|
46710
47495
|
isDark ? LAND_TINT_DARK : LAND_TINT_LIGHT
|
|
46711
47496
|
);
|
|
46712
47497
|
}
|
|
46713
|
-
function
|
|
46714
|
-
const { palette, isDark } = opts;
|
|
46715
|
-
const { width, height } = size;
|
|
47498
|
+
function buildMapProjection(resolved, data) {
|
|
46716
47499
|
const wantsUsStates = resolved.basemaps.subdivisions.includes("us-states");
|
|
46717
|
-
const usCrisp = resolved.projection === "albers-usa" && wantsUsStates && !!data.naLand;
|
|
47500
|
+
const usCrisp = (resolved.projection === "albers-usa" || resolved.projection === "mercator") && wantsUsStates && !!data.naLand;
|
|
46718
47501
|
const worldTopo = usCrisp ? data.worldDetail : resolved.basemaps.world === "detail" ? data.worldDetail : data.worldCoarse;
|
|
46719
|
-
const worldLayer = decodeLayer(worldTopo);
|
|
47502
|
+
const worldLayer = new Map(decodeLayer(worldTopo));
|
|
46720
47503
|
if (usCrisp && data.naLand) {
|
|
46721
47504
|
const [nbW, nbS, nbE, nbN] = [-140, 10, -52, 66];
|
|
46722
47505
|
const crisp = decodeLayer(data.naLand);
|
|
@@ -46725,16 +47508,109 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46725
47508
|
if (!base) continue;
|
|
46726
47509
|
const [[bw, bs], [be, bn]] = geoBounds2(base);
|
|
46727
47510
|
if (bw >= nbW && be <= nbE && bs >= nbS && bn <= nbN)
|
|
46728
|
-
worldLayer.set(iso, cf);
|
|
47511
|
+
worldLayer.set(iso, { ...cf, properties: base.properties });
|
|
46729
47512
|
}
|
|
46730
47513
|
}
|
|
46731
47514
|
const usLayer = wantsUsStates ? decodeLayer(data.usStates) : null;
|
|
47515
|
+
const extentOutline = () => {
|
|
47516
|
+
const [[w, s], [e, n]] = resolved.extent;
|
|
47517
|
+
const N = 16;
|
|
47518
|
+
const coords = [];
|
|
47519
|
+
for (let i = 0; i <= N; i++) {
|
|
47520
|
+
const t = i / N;
|
|
47521
|
+
const lon = w + (e - w) * t;
|
|
47522
|
+
const lat = s + (n - s) * t;
|
|
47523
|
+
coords.push([lon, s], [lon, n], [w, lat], [e, lat]);
|
|
47524
|
+
}
|
|
47525
|
+
return {
|
|
47526
|
+
type: "Feature",
|
|
47527
|
+
properties: {},
|
|
47528
|
+
geometry: { type: "MultiPoint", coordinates: coords }
|
|
47529
|
+
};
|
|
47530
|
+
};
|
|
47531
|
+
let fitFeatures;
|
|
47532
|
+
if (resolved.projection === "albers-usa" && usLayer) {
|
|
47533
|
+
fitFeatures = [...usLayer.entries()].filter(([iso]) => !US_NON_CONUS.has(iso)).map(([, f]) => f);
|
|
47534
|
+
const neighborPoints = resolved.pois.filter((p) => !inAlaska(p.lon, p.lat) && !inHawaii(p.lon, p.lat)).map((p) => [p.lon, p.lat]);
|
|
47535
|
+
if (neighborPoints.length > 0) {
|
|
47536
|
+
fitFeatures.push({
|
|
47537
|
+
type: "Feature",
|
|
47538
|
+
properties: {},
|
|
47539
|
+
geometry: { type: "MultiPoint", coordinates: neighborPoints }
|
|
47540
|
+
});
|
|
47541
|
+
}
|
|
47542
|
+
for (const r of resolved.regions) {
|
|
47543
|
+
if (r.layer === "country" && (r.iso === "CA" || r.iso === "MX")) {
|
|
47544
|
+
const cf = worldLayer.get(r.iso);
|
|
47545
|
+
if (cf) fitFeatures.push(cf);
|
|
47546
|
+
}
|
|
47547
|
+
}
|
|
47548
|
+
} else {
|
|
47549
|
+
fitFeatures = [extentOutline()];
|
|
47550
|
+
}
|
|
47551
|
+
const fitTarget = { type: "FeatureCollection", features: fitFeatures };
|
|
47552
|
+
const projection = projectionFor(resolved.projection);
|
|
47553
|
+
if (resolved.projection !== "albers-usa") {
|
|
47554
|
+
let centerLon = (resolved.extent[0][0] + resolved.extent[1][0]) / 2;
|
|
47555
|
+
if (centerLon > 180) centerLon -= 360;
|
|
47556
|
+
projection.rotate([-centerLon, 0]);
|
|
47557
|
+
}
|
|
47558
|
+
const fitGB = geoBounds2(fitTarget);
|
|
47559
|
+
const fitIsGlobal = fitGB[1][0] - fitGB[0][0] >= 270 || fitGB[1][1] - fitGB[0][1] >= 130;
|
|
47560
|
+
return {
|
|
47561
|
+
projection,
|
|
47562
|
+
fitTarget,
|
|
47563
|
+
fitIsGlobal,
|
|
47564
|
+
worldLayer,
|
|
47565
|
+
usLayer,
|
|
47566
|
+
usCrisp,
|
|
47567
|
+
wantsUsStates,
|
|
47568
|
+
worldTopo
|
|
47569
|
+
};
|
|
47570
|
+
}
|
|
47571
|
+
function parsePathRings(d) {
|
|
47572
|
+
const rings = [];
|
|
47573
|
+
let cur = [];
|
|
47574
|
+
const re = /([MLZ])([^MLZ]*)/g;
|
|
47575
|
+
let m;
|
|
47576
|
+
while (m = re.exec(d)) {
|
|
47577
|
+
if (m[1] === "Z") {
|
|
47578
|
+
if (cur.length) rings.push(cur);
|
|
47579
|
+
cur = [];
|
|
47580
|
+
continue;
|
|
47581
|
+
}
|
|
47582
|
+
if (m[1] === "M" && cur.length) {
|
|
47583
|
+
rings.push(cur);
|
|
47584
|
+
cur = [];
|
|
47585
|
+
}
|
|
47586
|
+
const nums = m[2].split(/[ ,]+/).map(Number);
|
|
47587
|
+
for (let i = 0; i + 1 < nums.length; i += 2) {
|
|
47588
|
+
const x = nums[i];
|
|
47589
|
+
const y = nums[i + 1];
|
|
47590
|
+
if (Number.isFinite(x) && Number.isFinite(y)) cur.push([x, y]);
|
|
47591
|
+
}
|
|
47592
|
+
}
|
|
47593
|
+
if (cur.length) rings.push(cur);
|
|
47594
|
+
return rings;
|
|
47595
|
+
}
|
|
47596
|
+
function layoutMap(resolved, data, size, opts) {
|
|
47597
|
+
const { palette, isDark } = opts;
|
|
47598
|
+
const { width, height } = size;
|
|
47599
|
+
const {
|
|
47600
|
+
projection,
|
|
47601
|
+
fitTarget,
|
|
47602
|
+
fitIsGlobal,
|
|
47603
|
+
worldLayer,
|
|
47604
|
+
usLayer,
|
|
47605
|
+
usCrisp,
|
|
47606
|
+
worldTopo
|
|
47607
|
+
} = buildMapProjection(resolved, data);
|
|
46732
47608
|
const usContext = usLayer !== null;
|
|
46733
47609
|
const regionStroke = isDark ? mix(palette.bg, palette.text, 78) : mix(palette.text, palette.bg, 78);
|
|
46734
47610
|
const values = resolved.regions.filter((r) => r.value !== void 0).map((r) => r.value);
|
|
46735
|
-
const
|
|
46736
|
-
const rampMin =
|
|
46737
|
-
const rampMax =
|
|
47611
|
+
const allNonNegative = values.length > 0 && values.every((v) => v >= 0);
|
|
47612
|
+
const rampMin = allNonNegative ? 0 : Math.min(...values);
|
|
47613
|
+
const rampMax = Math.max(...values);
|
|
46738
47614
|
const rampHue = resolveColor(resolved.directives.regionMetricColor ?? "", palette) ?? palette.colors.red;
|
|
46739
47615
|
const hasRamp = values.length > 0;
|
|
46740
47616
|
const VALUE_NAME = hasRamp ? resolved.directives.regionMetric?.trim() || "Value" : null;
|
|
@@ -46755,7 +47631,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46755
47631
|
activeGroup = VALUE_NAME ?? (resolved.tagGroups.length > 0 ? resolved.tagGroups[0].name : null);
|
|
46756
47632
|
}
|
|
46757
47633
|
const activeIsScore = VALUE_NAME !== null && activeGroup === VALUE_NAME;
|
|
46758
|
-
const mutedBasemap =
|
|
47634
|
+
const mutedBasemap = activeGroup !== null;
|
|
46759
47635
|
const neutralFill = mapNeutralLandColor(palette, isDark, mutedBasemap);
|
|
46760
47636
|
const water = mapBackgroundColor(palette, isDark, mutedBasemap);
|
|
46761
47637
|
const lakeStroke = mix(regionStroke, water, 45);
|
|
@@ -46764,6 +47640,39 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46764
47640
|
palette.bg,
|
|
46765
47641
|
mutedBasemap ? isDark ? MUTED_FOREIGN_DARK : MUTED_FOREIGN_LIGHT : isDark ? FOREIGN_TINT_DARK : FOREIGN_TINT_LIGHT
|
|
46766
47642
|
);
|
|
47643
|
+
const colorizeActive = resolved.directives.noColorize !== true && !hasRamp && resolved.tagGroups.length === 0;
|
|
47644
|
+
const colorByIso = /* @__PURE__ */ new Map();
|
|
47645
|
+
if (colorizeActive) {
|
|
47646
|
+
const adjacency = /* @__PURE__ */ new Map();
|
|
47647
|
+
const addEdges = (src) => {
|
|
47648
|
+
for (const [iso, ns] of src) {
|
|
47649
|
+
const cur = adjacency.get(iso);
|
|
47650
|
+
if (cur) cur.push(...ns);
|
|
47651
|
+
else adjacency.set(iso, [...ns]);
|
|
47652
|
+
}
|
|
47653
|
+
};
|
|
47654
|
+
addEdges(buildAdjacency(worldTopo));
|
|
47655
|
+
if (usLayer) {
|
|
47656
|
+
addEdges(buildAdjacency(data.usStates));
|
|
47657
|
+
for (const [country, states] of Object.entries(FOREIGN_BORDER)) {
|
|
47658
|
+
const cn = adjacency.get(country);
|
|
47659
|
+
if (!cn) continue;
|
|
47660
|
+
for (const st of states) {
|
|
47661
|
+
const sn = adjacency.get(st);
|
|
47662
|
+
if (!sn) continue;
|
|
47663
|
+
cn.push(st);
|
|
47664
|
+
sn.push(country);
|
|
47665
|
+
}
|
|
47666
|
+
}
|
|
47667
|
+
}
|
|
47668
|
+
const { byIso, huesNeeded } = assignColors(
|
|
47669
|
+
[...adjacency.keys()],
|
|
47670
|
+
adjacency
|
|
47671
|
+
);
|
|
47672
|
+
const tints = politicalTints(palette, huesNeeded, isDark);
|
|
47673
|
+
for (const [iso, idx] of byIso) colorByIso.set(iso, tints[idx]);
|
|
47674
|
+
}
|
|
47675
|
+
const colorizeStroke = (fill2) => mix(fill2, palette.text, 35);
|
|
46767
47676
|
const rampBase = isDark ? mix(palette.surface, palette.text, 28) : palette.bg;
|
|
46768
47677
|
const fillForValue = (s) => {
|
|
46769
47678
|
const t = rampMax > rampMin ? (s - rampMin) / (rampMax - rampMin) : 1;
|
|
@@ -46799,43 +47708,15 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46799
47708
|
if (activeIsScore) {
|
|
46800
47709
|
return r.value !== void 0 ? fillForValue(r.value) : neutralFill;
|
|
46801
47710
|
}
|
|
47711
|
+
if (colorizeActive) return (r.iso && colorByIso.get(r.iso)) ?? neutralFill;
|
|
46802
47712
|
return tagFill(r.tags, activeGroup) ?? neutralFill;
|
|
46803
47713
|
};
|
|
46804
47714
|
const regionById = new Map(resolved.regions.map((r) => [r.iso, r]));
|
|
46805
|
-
const
|
|
46806
|
-
const [[w, s], [e, n]] = resolved.extent;
|
|
46807
|
-
const N = 16;
|
|
46808
|
-
const coords = [];
|
|
46809
|
-
for (let i = 0; i <= N; i++) {
|
|
46810
|
-
const t = i / N;
|
|
46811
|
-
const lon = w + (e - w) * t;
|
|
46812
|
-
const lat = s + (n - s) * t;
|
|
46813
|
-
coords.push([lon, s], [lon, n], [w, lat], [e, lat]);
|
|
46814
|
-
}
|
|
46815
|
-
return {
|
|
46816
|
-
type: "Feature",
|
|
46817
|
-
properties: {},
|
|
46818
|
-
geometry: { type: "MultiPoint", coordinates: coords }
|
|
46819
|
-
};
|
|
46820
|
-
};
|
|
46821
|
-
let fitFeatures;
|
|
46822
|
-
if (resolved.projection === "albers-usa" && usLayer) {
|
|
46823
|
-
fitFeatures = [...usLayer.entries()].filter(([iso]) => !US_NON_CONUS.has(iso)).map(([, f]) => f);
|
|
46824
|
-
} else {
|
|
46825
|
-
fitFeatures = [extentOutline()];
|
|
46826
|
-
}
|
|
46827
|
-
const fitTarget = { type: "FeatureCollection", features: fitFeatures };
|
|
46828
|
-
const projection = projectionFor(resolved.projection);
|
|
46829
|
-
if (resolved.projection !== "albers-usa") {
|
|
46830
|
-
let centerLon = (resolved.extent[0][0] + resolved.extent[1][0]) / 2;
|
|
46831
|
-
if (centerLon > 180) centerLon -= 360;
|
|
46832
|
-
projection.rotate([-centerLon, 0]);
|
|
46833
|
-
}
|
|
46834
|
-
const TITLE_GAP = 16;
|
|
47715
|
+
const TITLE_GAP2 = 16;
|
|
46835
47716
|
let topPad = FIT_PAD;
|
|
46836
47717
|
if (resolved.title && resolved.pois.length > 0) {
|
|
46837
47718
|
const bannerBottom = (resolved.subtitle ? TITLE_Y + TITLE_FONT_SIZE : TITLE_Y) + TITLE_FONT_SIZE / 2;
|
|
46838
|
-
topPad = Math.max(FIT_PAD, bannerBottom +
|
|
47719
|
+
topPad = Math.max(FIT_PAD, bannerBottom + TITLE_GAP2);
|
|
46839
47720
|
}
|
|
46840
47721
|
const fitBox = [
|
|
46841
47722
|
[FIT_PAD, topPad],
|
|
@@ -46845,12 +47726,10 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46845
47726
|
]
|
|
46846
47727
|
];
|
|
46847
47728
|
projection.fitExtent(fitBox, fitTarget);
|
|
46848
|
-
const fitGB = geoBounds2(fitTarget);
|
|
46849
|
-
const fitIsGlobal = fitGB[1][0] - fitGB[0][0] >= 270 || fitGB[1][1] - fitGB[0][1] >= 130;
|
|
46850
47729
|
let path;
|
|
46851
47730
|
let project;
|
|
46852
47731
|
let stretchParams = null;
|
|
46853
|
-
if (fitIsGlobal) {
|
|
47732
|
+
if (fitIsGlobal && !opts.preferContain) {
|
|
46854
47733
|
const cb = geoPath(projection).bounds(fitTarget);
|
|
46855
47734
|
const bx0 = cb[0][0];
|
|
46856
47735
|
const by0 = cb[0][1];
|
|
@@ -46892,7 +47771,9 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46892
47771
|
const insets = [];
|
|
46893
47772
|
const insetRegions = [];
|
|
46894
47773
|
const insetLabelSeeds = [];
|
|
46895
|
-
|
|
47774
|
+
const akRef = resolved.regions.some((r) => r.iso === "US-AK") || resolved.pois.some((p) => inAlaska(p.lon, p.lat));
|
|
47775
|
+
const hiRef = resolved.regions.some((r) => r.iso === "US-HI") || resolved.pois.some((p) => inHawaii(p.lon, p.lat));
|
|
47776
|
+
if (resolved.projection === "albers-usa" && usLayer && (akRef || hiRef)) {
|
|
46896
47777
|
const PAD = 8;
|
|
46897
47778
|
const GAP = 12;
|
|
46898
47779
|
const yB = height - FIT_PAD;
|
|
@@ -46957,8 +47838,18 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46957
47838
|
);
|
|
46958
47839
|
const d = geoPath(proj)(f) ?? "";
|
|
46959
47840
|
if (!d) return xr;
|
|
47841
|
+
let contextLand;
|
|
47842
|
+
if (iso === "US-AK") {
|
|
47843
|
+
const can = worldLayer.get("CA");
|
|
47844
|
+
const cd = can ? geoPath(proj)(can) ?? "" : "";
|
|
47845
|
+
if (cd)
|
|
47846
|
+
contextLand = {
|
|
47847
|
+
d: cd,
|
|
47848
|
+
fill: colorizeActive ? colorByIso.get("CA") ?? foreignFill : foreignFill
|
|
47849
|
+
};
|
|
47850
|
+
}
|
|
46960
47851
|
const r = regionById.get(iso);
|
|
46961
|
-
let fill2 = neutralFill;
|
|
47852
|
+
let fill2 = colorizeActive ? colorByIso.get(iso) ?? neutralFill : neutralFill;
|
|
46962
47853
|
let lineNumber = -1;
|
|
46963
47854
|
if (r?.layer === "us-state") {
|
|
46964
47855
|
fill2 = regionFill(r);
|
|
@@ -46977,13 +47868,14 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46977
47868
|
],
|
|
46978
47869
|
// The FITTED inset projection (just fit to this box) — captured so the
|
|
46979
47870
|
// geo-query can invert pixels inside the frame back to AK/HI coords.
|
|
46980
|
-
projection: proj
|
|
47871
|
+
projection: proj,
|
|
47872
|
+
...contextLand && { contextLand }
|
|
46981
47873
|
});
|
|
46982
47874
|
insetRegions.push({
|
|
46983
47875
|
id: iso,
|
|
46984
47876
|
d,
|
|
46985
47877
|
fill: fill2,
|
|
46986
|
-
stroke: regionStroke,
|
|
47878
|
+
stroke: colorizeActive ? colorizeStroke(fill2) : regionStroke,
|
|
46987
47879
|
lineNumber,
|
|
46988
47880
|
layer: "us-state",
|
|
46989
47881
|
...r?.value !== void 0 && { value: r.value },
|
|
@@ -46996,13 +47888,16 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46996
47888
|
}
|
|
46997
47889
|
return xr;
|
|
46998
47890
|
};
|
|
46999
|
-
|
|
47000
|
-
|
|
47001
|
-
alaskaProjection(),
|
|
47002
|
-
|
|
47003
|
-
|
|
47004
|
-
|
|
47005
|
-
|
|
47891
|
+
let akRight = FIT_PAD;
|
|
47892
|
+
if (akRef)
|
|
47893
|
+
akRight = placeInset("US-AK", alaskaProjection(), FIT_PAD, width * 0.15);
|
|
47894
|
+
if (hiRef)
|
|
47895
|
+
placeInset(
|
|
47896
|
+
"US-HI",
|
|
47897
|
+
hawaiiProjection(),
|
|
47898
|
+
akRef ? akRight + 24 : FIT_PAD,
|
|
47899
|
+
width * 0.1
|
|
47900
|
+
);
|
|
47006
47901
|
}
|
|
47007
47902
|
const conusFit = resolved.projection === "albers-usa" && !!usLayer;
|
|
47008
47903
|
const classifyExtent = conusFit ? geoBounds2(fitTarget) : resolved.extent;
|
|
@@ -47018,15 +47913,24 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47018
47913
|
};
|
|
47019
47914
|
const ringOverlapsView = (ring) => {
|
|
47020
47915
|
let loMin = Infinity, loMax = -Infinity, rawMin = Infinity, rawMax = -Infinity;
|
|
47916
|
+
const lons = [];
|
|
47021
47917
|
for (const [rawLon] of ring) {
|
|
47022
47918
|
const lon = normLon(rawLon);
|
|
47919
|
+
lons.push(lon);
|
|
47023
47920
|
if (lon < loMin) loMin = lon;
|
|
47024
47921
|
if (lon > loMax) loMax = lon;
|
|
47025
47922
|
if (rawLon < rawMin) rawMin = rawLon;
|
|
47026
47923
|
if (rawLon > rawMax) rawMax = rawLon;
|
|
47027
47924
|
}
|
|
47028
|
-
|
|
47029
|
-
|
|
47925
|
+
lons.sort((a, b) => a - b);
|
|
47926
|
+
let maxGap = 0;
|
|
47927
|
+
for (let i = 1; i < lons.length; i++)
|
|
47928
|
+
maxGap = Math.max(maxGap, lons[i] - lons[i - 1]);
|
|
47929
|
+
if (lons.length > 1)
|
|
47930
|
+
maxGap = Math.max(maxGap, lons[0] + 360 - lons[lons.length - 1]);
|
|
47931
|
+
const occupiedArc = 360 - maxGap;
|
|
47932
|
+
if (occupiedArc > 270) return false;
|
|
47933
|
+
if (rawMax - rawMin > 180 && occupiedArc < 90) return false;
|
|
47030
47934
|
let px0 = Infinity, py0 = Infinity, px1 = -Infinity, py1 = -Infinity, anyFinite = false;
|
|
47031
47935
|
for (const [lon, lat] of ring) {
|
|
47032
47936
|
const p = project(lon, lat);
|
|
@@ -47099,7 +48003,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47099
48003
|
const regions = [];
|
|
47100
48004
|
const pushRegionLayer = (layerFeatures, layerKind, shouldCull) => {
|
|
47101
48005
|
for (const [iso, f] of layerFeatures) {
|
|
47102
|
-
if (layerKind === "us-state" && usContext && INSET_STATES.has(iso))
|
|
48006
|
+
if (layerKind === "us-state" && usContext && resolved.projection === "albers-usa" && INSET_STATES.has(iso))
|
|
47103
48007
|
continue;
|
|
47104
48008
|
if (layerKind === "country" && usContext && iso === "US") continue;
|
|
47105
48009
|
if (layerKind === "country" && iso === "AQ" && !regionById.has("AQ"))
|
|
@@ -47111,7 +48015,8 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47111
48015
|
if (!d) continue;
|
|
47112
48016
|
const isThisLayer = r?.layer === layerKind;
|
|
47113
48017
|
const isForeign = layerKind === "country" && usContext && iso !== "US";
|
|
47114
|
-
|
|
48018
|
+
const baseFill = isForeign ? foreignFill : neutralFill;
|
|
48019
|
+
let fill2 = colorizeActive ? colorByIso.get(iso) ?? baseFill : baseFill;
|
|
47115
48020
|
let label;
|
|
47116
48021
|
let lineNumber = -1;
|
|
47117
48022
|
let layer = "base";
|
|
@@ -47120,12 +48025,14 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47120
48025
|
lineNumber = r.lineNumber;
|
|
47121
48026
|
layer = layerKind;
|
|
47122
48027
|
label = r.name;
|
|
48028
|
+
} else {
|
|
48029
|
+
label = f.properties?.name;
|
|
47123
48030
|
}
|
|
47124
48031
|
regions.push({
|
|
47125
48032
|
id: iso,
|
|
47126
48033
|
d,
|
|
47127
48034
|
fill: fill2,
|
|
47128
|
-
stroke: regionStroke,
|
|
48035
|
+
stroke: colorizeActive ? colorizeStroke(fill2) : regionStroke,
|
|
47129
48036
|
lineNumber,
|
|
47130
48037
|
layer,
|
|
47131
48038
|
...label !== void 0 && { label },
|
|
@@ -47153,9 +48060,41 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47153
48060
|
});
|
|
47154
48061
|
}
|
|
47155
48062
|
}
|
|
48063
|
+
const pointInRings = (px, py, rings) => {
|
|
48064
|
+
let inside = false;
|
|
48065
|
+
for (const ring of rings) {
|
|
48066
|
+
for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {
|
|
48067
|
+
const [xi, yi] = ring[i];
|
|
48068
|
+
const [xj, yj] = ring[j];
|
|
48069
|
+
if (yi > py !== yj > py && px < (xj - xi) * (py - yi) / (yj - yi) + xi)
|
|
48070
|
+
inside = !inside;
|
|
48071
|
+
}
|
|
48072
|
+
}
|
|
48073
|
+
return inside;
|
|
48074
|
+
};
|
|
48075
|
+
const fillHitTargets = [...regions, ...insetRegions].map((r) => ({
|
|
48076
|
+
fill: r.fill,
|
|
48077
|
+
rings: parsePathRings(r.d)
|
|
48078
|
+
}));
|
|
48079
|
+
const fillAt = (x, y) => {
|
|
48080
|
+
let hit = water;
|
|
48081
|
+
for (const t of fillHitTargets)
|
|
48082
|
+
if (pointInRings(x, y, t.rings)) hit = t.fill;
|
|
48083
|
+
return hit;
|
|
48084
|
+
};
|
|
48085
|
+
const labelOnFill = (fill2) => {
|
|
48086
|
+
const color = contrastRatio(fill2, palette.textOnFillDark) >= contrastRatio(fill2, palette.textOnFillLight) ? palette.textOnFillDark : palette.textOnFillLight;
|
|
48087
|
+
const haloColor = color === palette.textOnFillLight ? palette.textOnFillDark : palette.textOnFillLight;
|
|
48088
|
+
return {
|
|
48089
|
+
color,
|
|
48090
|
+
halo: contrastRatio(fill2, color) < REGION_LABEL_HALO_RATIO,
|
|
48091
|
+
haloColor
|
|
48092
|
+
};
|
|
48093
|
+
};
|
|
48094
|
+
const reliefAllowed = resolved.directives.noRelief !== true;
|
|
47156
48095
|
const relief = [];
|
|
47157
48096
|
let reliefHatch = null;
|
|
47158
|
-
if (
|
|
48097
|
+
if (reliefAllowed && data.mountainRanges) {
|
|
47159
48098
|
for (const [, f] of decodeLayer(data.mountainRanges)) {
|
|
47160
48099
|
const viewF = isGlobalView ? dropFrameFillers(f) : cullFeatureToView(f);
|
|
47161
48100
|
if (!viewF) continue;
|
|
@@ -47171,16 +48110,32 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47171
48110
|
if (relief.length) {
|
|
47172
48111
|
const darkTone = isDark ? palette.bg : palette.text;
|
|
47173
48112
|
const lightTone = isDark ? palette.text : palette.bg;
|
|
47174
|
-
const
|
|
48113
|
+
const reliefLandRef = colorizeActive ? isDark ? palette.surface : palette.bg : neutralFill;
|
|
48114
|
+
const landLum = relativeLuminance(reliefLandRef);
|
|
47175
48115
|
const tone = Math.abs(landLum - relativeLuminance(darkTone)) > 0.04 ? darkTone : lightTone;
|
|
47176
48116
|
reliefHatch = {
|
|
47177
|
-
color: mix(tone,
|
|
48117
|
+
color: mix(tone, reliefLandRef, RELIEF_HATCH_STRENGTH),
|
|
47178
48118
|
spacing: RELIEF_HATCH_SPACING,
|
|
47179
48119
|
width: RELIEF_HATCH_WIDTH
|
|
47180
48120
|
};
|
|
47181
48121
|
}
|
|
47182
48122
|
}
|
|
47183
|
-
|
|
48123
|
+
let coastlineStyle = null;
|
|
48124
|
+
if (resolved.directives.noCoastline !== true) {
|
|
48125
|
+
const minDim = Math.min(width, height);
|
|
48126
|
+
coastlineStyle = {
|
|
48127
|
+
color: mix(regionStroke, water, COASTLINE_STROKE_MIX),
|
|
48128
|
+
// N equal-width rings: distance steps outward by COASTLINE_STEP; opacity
|
|
48129
|
+
// fades linearly from NEAR (innermost) to FAR (outermost).
|
|
48130
|
+
lines: Array.from({ length: COASTLINE_RING_COUNT }, (_, k) => ({
|
|
48131
|
+
d: (COASTLINE_D0 + k * COASTLINE_STEP) * minDim,
|
|
48132
|
+
thickness: COASTLINE_THICKNESS * minDim,
|
|
48133
|
+
opacity: COASTLINE_OPACITY_NEAR + (COASTLINE_OPACITY_FAR - COASTLINE_OPACITY_NEAR) * k / (COASTLINE_RING_COUNT - 1)
|
|
48134
|
+
})),
|
|
48135
|
+
minExtent: (isGlobalView ? COASTLINE_MIN_EXTENT_GLOBAL : COASTLINE_MIN_EXTENT) * minDim
|
|
48136
|
+
};
|
|
48137
|
+
}
|
|
48138
|
+
const riverColor = mix(palette.colors.blue, water, 32);
|
|
47184
48139
|
const rivers = [];
|
|
47185
48140
|
if (data.rivers) {
|
|
47186
48141
|
for (const [, f] of decodeLayer(data.rivers)) {
|
|
@@ -47236,38 +48191,108 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47236
48191
|
const xy = project(p.lon, p.lat);
|
|
47237
48192
|
if (xy) projected.push({ p, xy });
|
|
47238
48193
|
}
|
|
47239
|
-
const
|
|
48194
|
+
const placePoi = (e, cx, cy, clusterId) => {
|
|
48195
|
+
const { fill: fill2, stroke: stroke2 } = poiFill(e.p);
|
|
48196
|
+
poiScreen.set(e.p.id, { cx, cy, r: radiusFor(e.p) });
|
|
48197
|
+
const num = routeNumberById.get(e.p.id);
|
|
48198
|
+
pois.push({
|
|
48199
|
+
id: e.p.id,
|
|
48200
|
+
cx,
|
|
48201
|
+
cy,
|
|
48202
|
+
r: radiusFor(e.p),
|
|
48203
|
+
fill: fill2,
|
|
48204
|
+
stroke: stroke2,
|
|
48205
|
+
lineNumber: e.p.lineNumber,
|
|
48206
|
+
implicit: !!e.p.implicit,
|
|
48207
|
+
isOrigin: originIds.has(e.p.id),
|
|
48208
|
+
...num !== void 0 && { routeNumber: num },
|
|
48209
|
+
...Object.keys(e.p.tags).length > 0 && { tags: e.p.tags },
|
|
48210
|
+
...clusterId !== void 0 && { clusterId }
|
|
48211
|
+
});
|
|
48212
|
+
};
|
|
48213
|
+
const clusters = [];
|
|
48214
|
+
const connected = /* @__PURE__ */ new Set();
|
|
48215
|
+
for (const e of resolved.edges) {
|
|
48216
|
+
connected.add(e.fromId);
|
|
48217
|
+
connected.add(e.toId);
|
|
48218
|
+
}
|
|
48219
|
+
for (const rt of resolved.routes) {
|
|
48220
|
+
rt.stopIds.forEach((id) => connected.add(id));
|
|
48221
|
+
}
|
|
48222
|
+
const radiusOf = (e) => radiusFor(e.p);
|
|
47240
48223
|
for (const e of projected) {
|
|
47241
|
-
|
|
47242
|
-
|
|
47243
|
-
|
|
47244
|
-
|
|
47245
|
-
|
|
47246
|
-
|
|
47247
|
-
|
|
47248
|
-
|
|
47249
|
-
|
|
47250
|
-
|
|
47251
|
-
|
|
47252
|
-
|
|
47253
|
-
|
|
47254
|
-
|
|
47255
|
-
|
|
47256
|
-
|
|
47257
|
-
|
|
47258
|
-
|
|
47259
|
-
|
|
47260
|
-
|
|
47261
|
-
|
|
47262
|
-
|
|
47263
|
-
|
|
47264
|
-
|
|
47265
|
-
|
|
47266
|
-
|
|
47267
|
-
|
|
47268
|
-
|
|
47269
|
-
|
|
47270
|
-
|
|
48224
|
+
if (connected.has(e.p.id)) placePoi(e, e.xy[0], e.xy[1]);
|
|
48225
|
+
}
|
|
48226
|
+
const groups = [];
|
|
48227
|
+
for (const e of projected) {
|
|
48228
|
+
if (connected.has(e.p.id)) continue;
|
|
48229
|
+
const r = radiusOf(e);
|
|
48230
|
+
const near = groups.find(
|
|
48231
|
+
(g) => g.some(
|
|
48232
|
+
(q) => Math.hypot(q.xy[0] - e.xy[0], q.xy[1] - e.xy[1]) < (r + radiusOf(q)) * STACK_OVERLAP
|
|
48233
|
+
)
|
|
48234
|
+
);
|
|
48235
|
+
if (near) near.push(e);
|
|
48236
|
+
else groups.push([e]);
|
|
48237
|
+
}
|
|
48238
|
+
for (const g of groups) {
|
|
48239
|
+
if (g.length === 1) {
|
|
48240
|
+
placePoi(g[0], g[0].xy[0], g[0].xy[1]);
|
|
48241
|
+
continue;
|
|
48242
|
+
}
|
|
48243
|
+
const clusterId = g[0].p.id;
|
|
48244
|
+
const cx0 = g.reduce((s, e) => s + e.xy[0], 0) / g.length;
|
|
48245
|
+
const cy0 = g.reduce((s, e) => s + e.xy[1], 0) / g.length;
|
|
48246
|
+
const maxR = Math.max(...g.map(radiusOf));
|
|
48247
|
+
const sep = 2 * maxR + STACK_RING_GAP;
|
|
48248
|
+
const ringR = Math.max(
|
|
48249
|
+
COLO_R,
|
|
48250
|
+
sep / (2 * Math.sin(Math.PI / Math.max(g.length, 2)))
|
|
48251
|
+
);
|
|
48252
|
+
const positions = g.map((e, i) => {
|
|
48253
|
+
if (g.length <= STACK_RING_MAX) {
|
|
48254
|
+
const ang2 = -Math.PI / 2 + i * 2 * Math.PI / g.length;
|
|
48255
|
+
return {
|
|
48256
|
+
e,
|
|
48257
|
+
mx: cx0 + Math.cos(ang2) * ringR,
|
|
48258
|
+
my: cy0 + Math.sin(ang2) * ringR
|
|
48259
|
+
};
|
|
48260
|
+
}
|
|
48261
|
+
const ang = i * GOLDEN_ANGLE;
|
|
48262
|
+
const rr = ringR * Math.sqrt((i + 1) / g.length);
|
|
48263
|
+
return { e, mx: cx0 + Math.cos(ang) * rr, my: cy0 + Math.sin(ang) * rr };
|
|
48264
|
+
});
|
|
48265
|
+
let minX = cx0 - maxR;
|
|
48266
|
+
let maxX = cx0 + maxR;
|
|
48267
|
+
let minY = cy0 - maxR;
|
|
48268
|
+
let maxY = cy0 + maxR;
|
|
48269
|
+
for (const { mx, my, e } of positions) {
|
|
48270
|
+
const r = radiusOf(e);
|
|
48271
|
+
minX = Math.min(minX, mx - r);
|
|
48272
|
+
maxX = Math.max(maxX, mx + r);
|
|
48273
|
+
minY = Math.min(minY, my - r);
|
|
48274
|
+
maxY = Math.max(maxY, my + r);
|
|
48275
|
+
}
|
|
48276
|
+
let dx = 0;
|
|
48277
|
+
let dy = 0;
|
|
48278
|
+
if (minX + dx < 2) dx = 2 - minX;
|
|
48279
|
+
if (maxX + dx > width - 2) dx = width - 2 - maxX;
|
|
48280
|
+
if (minY + dy < 2) dy = 2 - minY;
|
|
48281
|
+
if (maxY + dy > height - 2) dy = height - 2 - maxY;
|
|
48282
|
+
const legsOut = [];
|
|
48283
|
+
for (const { e, mx, my } of positions) {
|
|
48284
|
+
const fx = mx + dx;
|
|
48285
|
+
const fy = my + dy;
|
|
48286
|
+
placePoi(e, fx, fy, clusterId);
|
|
48287
|
+
legsOut.push({ x2: fx, y2: fy, color: poiFill(e.p).fill });
|
|
48288
|
+
}
|
|
48289
|
+
clusters.push({
|
|
48290
|
+
id: clusterId,
|
|
48291
|
+
cx: cx0 + dx,
|
|
48292
|
+
cy: cy0 + dy,
|
|
48293
|
+
count: g.length,
|
|
48294
|
+
hitR: ringR + maxR + 6,
|
|
48295
|
+
legs: legsOut
|
|
47271
48296
|
});
|
|
47272
48297
|
}
|
|
47273
48298
|
const legs = [];
|
|
@@ -47317,16 +48342,26 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47317
48342
|
if (!a || !b) continue;
|
|
47318
48343
|
const mx = (a.cx + b.cx) / 2;
|
|
47319
48344
|
const my = (a.cy + b.cy) / 2;
|
|
48345
|
+
const bow = {
|
|
48346
|
+
curved: leg.style === "arc",
|
|
48347
|
+
offset: 0,
|
|
48348
|
+
labelX: mx,
|
|
48349
|
+
labelY: my - 4
|
|
48350
|
+
};
|
|
48351
|
+
const routeLabelStyle = leg.label !== void 0 ? labelOnFill(fillAt(bow.labelX, bow.labelY)) : void 0;
|
|
47320
48352
|
legs.push({
|
|
47321
|
-
d: legPath(a, b,
|
|
48353
|
+
d: legPath(a, b, bow.curved, bow.offset),
|
|
47322
48354
|
width: routeWidthFor(Number(leg.value)),
|
|
47323
48355
|
color: mix(palette.text, palette.bg, 72),
|
|
47324
48356
|
arrow: true,
|
|
47325
48357
|
lineNumber: leg.lineNumber,
|
|
47326
48358
|
...leg.label !== void 0 && {
|
|
47327
48359
|
label: leg.label,
|
|
47328
|
-
labelX:
|
|
47329
|
-
labelY:
|
|
48360
|
+
labelX: bow.labelX,
|
|
48361
|
+
labelY: bow.labelY,
|
|
48362
|
+
labelColor: routeLabelStyle.color,
|
|
48363
|
+
labelHalo: routeLabelStyle.halo,
|
|
48364
|
+
labelHaloColor: routeLabelStyle.haloColor
|
|
47330
48365
|
}
|
|
47331
48366
|
});
|
|
47332
48367
|
}
|
|
@@ -47354,20 +48389,29 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47354
48389
|
const a = poiScreen.get(e.fromId);
|
|
47355
48390
|
const b = poiScreen.get(e.toId);
|
|
47356
48391
|
if (!a || !b) return;
|
|
47357
|
-
const
|
|
47358
|
-
const offset = n > 1 ? (i - (n - 1) / 2) * FAN_STEP : 0;
|
|
48392
|
+
const fanOffset = n > 1 ? (i - (n - 1) / 2) * FAN_STEP : 0;
|
|
47359
48393
|
const mx = (a.cx + b.cx) / 2;
|
|
47360
48394
|
const my = (a.cy + b.cy) / 2;
|
|
48395
|
+
const bow = {
|
|
48396
|
+
curved: e.style === "arc" || n > 1,
|
|
48397
|
+
offset: fanOffset,
|
|
48398
|
+
labelX: mx,
|
|
48399
|
+
labelY: my - 4
|
|
48400
|
+
};
|
|
48401
|
+
const edgeLabelStyle = e.label !== void 0 ? labelOnFill(fillAt(bow.labelX, bow.labelY)) : void 0;
|
|
47361
48402
|
legs.push({
|
|
47362
|
-
d: legPath(a, b, curved, offset),
|
|
48403
|
+
d: legPath(a, b, bow.curved, bow.offset),
|
|
47363
48404
|
width: widthFor(e),
|
|
47364
48405
|
color: mix(palette.text, palette.bg, 66),
|
|
47365
48406
|
arrow: e.directed,
|
|
47366
48407
|
lineNumber: e.lineNumber,
|
|
47367
48408
|
...e.label !== void 0 && {
|
|
47368
48409
|
label: e.label,
|
|
47369
|
-
labelX:
|
|
47370
|
-
labelY:
|
|
48410
|
+
labelX: bow.labelX,
|
|
48411
|
+
labelY: bow.labelY,
|
|
48412
|
+
labelColor: edgeLabelStyle.color,
|
|
48413
|
+
labelHalo: edgeLabelStyle.halo,
|
|
48414
|
+
labelHaloColor: edgeLabelStyle.haloColor
|
|
47371
48415
|
}
|
|
47372
48416
|
});
|
|
47373
48417
|
});
|
|
@@ -47409,25 +48453,25 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47409
48453
|
}
|
|
47410
48454
|
}
|
|
47411
48455
|
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));
|
|
47412
|
-
const
|
|
48456
|
+
const showRegionLabels = resolved.directives.noRegionLabels !== true;
|
|
48457
|
+
const isCompact = width < COMPACT_WIDTH_PX;
|
|
47413
48458
|
const LABEL_PADX = 6;
|
|
47414
48459
|
const LABEL_PADY = 3;
|
|
47415
|
-
const labelW = (text) => measureLegendText(text,
|
|
47416
|
-
const labelH =
|
|
48460
|
+
const labelW = (text) => measureLegendText(text, FONT2) + 2 * LABEL_PADX;
|
|
48461
|
+
const labelH = FONT2 + 2 * LABEL_PADY;
|
|
47417
48462
|
const pushRegionLabel = (x, y, text, fill2, lineNumber) => {
|
|
47418
|
-
const color =
|
|
47419
|
-
|
|
47420
|
-
|
|
47421
|
-
|
|
48463
|
+
const { color, haloColor } = labelOnFill(fill2);
|
|
48464
|
+
const halfW = measureLegendText(text, FONT2) / 2;
|
|
48465
|
+
const overflows = [y - FONT2 * 0.55, y - FONT2 * 0.1].some(
|
|
48466
|
+
(sy) => fillAt(x - halfW, sy) !== fill2 || fillAt(x + halfW, sy) !== fill2
|
|
47422
48467
|
);
|
|
47423
|
-
const haloColor = color === palette.textOnFillLight ? palette.textOnFillDark : palette.textOnFillLight;
|
|
47424
48468
|
labels.push({
|
|
47425
48469
|
x,
|
|
47426
48470
|
y,
|
|
47427
48471
|
text,
|
|
47428
48472
|
anchor: "middle",
|
|
47429
48473
|
color,
|
|
47430
|
-
halo:
|
|
48474
|
+
halo: overflows,
|
|
47431
48475
|
haloColor,
|
|
47432
48476
|
lineNumber
|
|
47433
48477
|
});
|
|
@@ -47436,21 +48480,50 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47436
48480
|
US: [-98.5, 39.5]
|
|
47437
48481
|
// CONUS geographic centre (near Lebanon, Kansas)
|
|
47438
48482
|
};
|
|
47439
|
-
|
|
47440
|
-
|
|
47441
|
-
|
|
47442
|
-
|
|
47443
|
-
|
|
48483
|
+
const REGION_LABEL_GAP = 2;
|
|
48484
|
+
const regionLabelRect = (cx, cy, text) => {
|
|
48485
|
+
const w = measureLegendText(text, FONT2) + 2 * REGION_LABEL_GAP;
|
|
48486
|
+
return { x: cx - w / 2, y: cy - FONT2 / 2, w, h: FONT2 };
|
|
48487
|
+
};
|
|
48488
|
+
if (showRegionLabels) {
|
|
48489
|
+
const frameContainers = new Set(resolved.poiFrameContainers);
|
|
48490
|
+
const entries = regions.map((r) => {
|
|
48491
|
+
const isContainer = frameContainers.has(r.id);
|
|
48492
|
+
if (r.layer === "base" && !isContainer || r.label === void 0)
|
|
48493
|
+
return null;
|
|
48494
|
+
const isUsState = r.layer === "us-state" || r.id.startsWith("US-");
|
|
48495
|
+
const f = isUsState ? usLayer?.get(r.id) : worldLayer.get(r.id);
|
|
48496
|
+
if (!f) return null;
|
|
47444
48497
|
const [[x0, y0], [x1, y1]] = path.bounds(f);
|
|
47445
|
-
const
|
|
47446
|
-
|
|
47447
|
-
const
|
|
48498
|
+
const boxW = x1 - x0;
|
|
48499
|
+
const boxH = y1 - y0;
|
|
48500
|
+
const abbrev = isUsState ? r.id.replace(/^US-/, "") : void 0;
|
|
48501
|
+
const candidates = abbrev !== void 0 ? isCompact ? [abbrev, r.label] : [r.label, abbrev] : [r.label];
|
|
48502
|
+
const anchor = !isUsState ? WORLD_LABEL_ANCHORS[r.id] : void 0;
|
|
47448
48503
|
const c = anchor ? project(anchor[0], anchor[1]) : path.centroid(f);
|
|
47449
|
-
if (!c || !Number.isFinite(c[0]))
|
|
48504
|
+
if (!c || !Number.isFinite(c[0])) return null;
|
|
48505
|
+
return { r, c, boxW, boxH, area: boxW * boxH, candidates };
|
|
48506
|
+
}).filter((e) => e !== null).sort((a, b) => b.area - a.area || a.r.lineNumber - b.r.lineNumber);
|
|
48507
|
+
const placedRegionRects = [];
|
|
48508
|
+
const POI_LABEL_PAD = 14;
|
|
48509
|
+
const poiObstacles = pois.map((p) => ({
|
|
48510
|
+
x: p.cx - p.r - POI_LABEL_PAD,
|
|
48511
|
+
y: p.cy - p.r - POI_LABEL_PAD,
|
|
48512
|
+
w: 2 * (p.r + POI_LABEL_PAD),
|
|
48513
|
+
h: 2 * (p.r + POI_LABEL_PAD)
|
|
48514
|
+
}));
|
|
48515
|
+
for (const { r, c, boxW, boxH, candidates } of entries) {
|
|
48516
|
+
const text = candidates.find((t) => {
|
|
48517
|
+
if (labelW(t) > boxW || labelH > boxH) return false;
|
|
48518
|
+
const rect = regionLabelRect(c[0], c[1], t);
|
|
48519
|
+
return !placedRegionRects.some((p) => rectsOverlap(rect, p)) && !poiObstacles.some((o) => rectsOverlap(rect, o));
|
|
48520
|
+
});
|
|
48521
|
+
if (text === void 0) continue;
|
|
48522
|
+
placedRegionRects.push(regionLabelRect(c[0], c[1], text));
|
|
47450
48523
|
pushRegionLabel(c[0], c[1], text, r.fill, r.lineNumber);
|
|
47451
48524
|
}
|
|
47452
48525
|
for (const seed of insetLabelSeeds) {
|
|
47453
|
-
const text =
|
|
48526
|
+
const text = isCompact ? seed.iso.replace(/^US-/, "") : seed.name;
|
|
47454
48527
|
const src = regionById.get(seed.iso);
|
|
47455
48528
|
pushRegionLabel(
|
|
47456
48529
|
seed.x,
|
|
@@ -47461,22 +48534,26 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47461
48534
|
);
|
|
47462
48535
|
}
|
|
47463
48536
|
}
|
|
47464
|
-
|
|
47465
|
-
|
|
47466
|
-
const ordered = [...pois].sort(
|
|
47467
|
-
(a, b) => a.lineNumber - b.lineNumber || (a.id < b.id ? -1 : 1)
|
|
47468
|
-
);
|
|
48537
|
+
if (resolved.directives.noPoiLabels !== true) {
|
|
48538
|
+
const ordered = [...pois].filter((p) => p.clusterId === void 0).sort((a, b) => a.lineNumber - b.lineNumber || (a.id < b.id ? -1 : 1));
|
|
47469
48539
|
const poiById = new Map(resolved.pois.map((q) => [q.id, q]));
|
|
47470
48540
|
const labelText = (p) => {
|
|
47471
48541
|
const src = poiById.get(p.id);
|
|
47472
48542
|
return src?.label ?? src?.name ?? p.id;
|
|
47473
48543
|
};
|
|
47474
|
-
const poiLabH =
|
|
48544
|
+
const poiLabH = FONT2 * 1.25;
|
|
47475
48545
|
const labelInfo = (p) => {
|
|
47476
48546
|
const text = labelText(p);
|
|
47477
|
-
return { text, w: measureLegendText(text,
|
|
48547
|
+
return { text, w: measureLegendText(text, FONT2) };
|
|
47478
48548
|
};
|
|
47479
48549
|
const GAP = 3;
|
|
48550
|
+
const clusterMembersById = /* @__PURE__ */ new Map();
|
|
48551
|
+
for (const p of pois) {
|
|
48552
|
+
if (p.clusterId === void 0) continue;
|
|
48553
|
+
const arr = clusterMembersById.get(p.clusterId);
|
|
48554
|
+
if (arr) arr.push(p);
|
|
48555
|
+
else clusterMembersById.set(p.clusterId, [p]);
|
|
48556
|
+
}
|
|
47480
48557
|
const inlineRect = (p, w, side) => {
|
|
47481
48558
|
switch (side) {
|
|
47482
48559
|
case "right":
|
|
@@ -47506,11 +48583,11 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47506
48583
|
const x = side === "right" ? rect.x : side === "left" ? rect.x + w : p.cx;
|
|
47507
48584
|
labels.push({
|
|
47508
48585
|
x,
|
|
47509
|
-
y: rect.y + poiLabH / 2 +
|
|
48586
|
+
y: rect.y + poiLabH / 2 + FONT2 / 3,
|
|
47510
48587
|
text,
|
|
47511
48588
|
anchor,
|
|
47512
48589
|
color: palette.text,
|
|
47513
|
-
halo:
|
|
48590
|
+
halo: false,
|
|
47514
48591
|
haloColor: palette.bg,
|
|
47515
48592
|
poiId: p.id,
|
|
47516
48593
|
lineNumber: p.lineNumber
|
|
@@ -47521,43 +48598,60 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47521
48598
|
return rect.x >= 0 && rect.x + rect.w <= width && rect.y >= 0 && rect.y + rect.h <= height && !collides(rect);
|
|
47522
48599
|
};
|
|
47523
48600
|
const GROUP_R = 30;
|
|
47524
|
-
const
|
|
48601
|
+
const groups2 = [];
|
|
47525
48602
|
for (const p of ordered) {
|
|
47526
|
-
const near =
|
|
48603
|
+
const near = groups2.find(
|
|
47527
48604
|
(g) => g.some((q) => Math.hypot(q.cx - p.cx, q.cy - p.cy) < GROUP_R)
|
|
47528
48605
|
);
|
|
47529
48606
|
if (near) near.push(p);
|
|
47530
|
-
else
|
|
48607
|
+
else groups2.push([p]);
|
|
47531
48608
|
}
|
|
47532
48609
|
const ROW_GAP2 = 3;
|
|
47533
48610
|
const step = poiLabH + ROW_GAP2;
|
|
47534
48611
|
const COL_GAP = 16;
|
|
47535
|
-
const
|
|
47536
|
-
|
|
48612
|
+
const makeItems = (group) => group.map((p) => ({ p, ...labelInfo(p) })).sort((a, b) => a.p.cy - b.p.cy || (a.text < b.text ? -1 : 1));
|
|
48613
|
+
const columnRows = (items, side) => {
|
|
47537
48614
|
const left = Math.min(...items.map((o) => o.p.cx - o.p.r));
|
|
47538
48615
|
const right = Math.max(...items.map((o) => o.p.cx + o.p.r));
|
|
47539
|
-
const cyMid = (Math.min(...items.map((o) => o.p.cy)) + Math.max(...items.map((o) => o.p.cy))) / 2;
|
|
47540
48616
|
const maxW = Math.max(...items.map((o) => o.w));
|
|
47541
|
-
const
|
|
47542
|
-
const colX = side === "right" ? right + COL_GAP : left - COL_GAP;
|
|
48617
|
+
const cyMid = (Math.min(...items.map((o) => o.p.cy)) + Math.max(...items.map((o) => o.p.cy))) / 2;
|
|
48618
|
+
const colX = side === "right" ? Math.min(right + COL_GAP, width - 2 - maxW) : Math.max(left - COL_GAP, 2 + maxW);
|
|
47543
48619
|
const totalH = items.length * step;
|
|
47544
48620
|
let startY = cyMid - totalH / 2;
|
|
47545
48621
|
startY = Math.max(2, Math.min(startY, height - totalH - 2));
|
|
47546
|
-
items.
|
|
48622
|
+
return items.map((o, i) => {
|
|
47547
48623
|
const rowCy = startY + i * step + step / 2;
|
|
47548
|
-
|
|
47549
|
-
|
|
47550
|
-
|
|
47551
|
-
|
|
47552
|
-
|
|
47553
|
-
|
|
48624
|
+
return {
|
|
48625
|
+
o,
|
|
48626
|
+
colX,
|
|
48627
|
+
rowCy,
|
|
48628
|
+
rect: {
|
|
48629
|
+
x: side === "right" ? colX : colX - o.w,
|
|
48630
|
+
y: rowCy - poiLabH / 2,
|
|
48631
|
+
w: o.w,
|
|
48632
|
+
h: poiLabH
|
|
48633
|
+
}
|
|
48634
|
+
};
|
|
48635
|
+
});
|
|
48636
|
+
};
|
|
48637
|
+
const wouldColumnBeClean = (items, side) => columnRows(items, side).every(
|
|
48638
|
+
({ rect }) => rect.x >= 0 && rect.x + rect.w <= width && rect.y >= 0 && rect.y + rect.h <= height && !collides(rect)
|
|
48639
|
+
);
|
|
48640
|
+
const defaultColumnSide = (items) => {
|
|
48641
|
+
const right = Math.max(...items.map((o) => o.p.cx + o.p.r));
|
|
48642
|
+
const maxW = Math.max(...items.map((o) => o.w));
|
|
48643
|
+
return right + COL_GAP + maxW <= width - 2 ? "right" : "left";
|
|
48644
|
+
};
|
|
48645
|
+
const commitColumn = (items, side, clusterId) => {
|
|
48646
|
+
for (const { o, colX, rowCy, rect } of columnRows(items, side)) {
|
|
48647
|
+
obstacles.push(rect);
|
|
47554
48648
|
labels.push({
|
|
47555
48649
|
x: colX,
|
|
47556
|
-
y: rowCy +
|
|
48650
|
+
y: rowCy + FONT2 / 3,
|
|
47557
48651
|
text: o.text,
|
|
47558
48652
|
anchor: side === "right" ? "start" : "end",
|
|
47559
48653
|
color: palette.text,
|
|
47560
|
-
halo:
|
|
48654
|
+
halo: false,
|
|
47561
48655
|
haloColor: palette.bg,
|
|
47562
48656
|
leader: {
|
|
47563
48657
|
x1: o.p.cx,
|
|
@@ -47567,24 +48661,141 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47567
48661
|
},
|
|
47568
48662
|
leaderColor: o.p.fill,
|
|
47569
48663
|
poiId: o.p.id,
|
|
47570
|
-
lineNumber: o.p.lineNumber
|
|
48664
|
+
lineNumber: o.p.lineNumber,
|
|
48665
|
+
...clusterId !== void 0 && { clusterMember: clusterId }
|
|
47571
48666
|
});
|
|
48667
|
+
}
|
|
48668
|
+
};
|
|
48669
|
+
const pushHidden = (p) => {
|
|
48670
|
+
const { text, w } = labelInfo(p);
|
|
48671
|
+
let x = p.cx + p.r + GAP;
|
|
48672
|
+
let anchor = "start";
|
|
48673
|
+
if (x + w > width) {
|
|
48674
|
+
x = p.cx - p.r - GAP - w;
|
|
48675
|
+
anchor = "end";
|
|
48676
|
+
}
|
|
48677
|
+
const y = Math.max(0, Math.min(p.cy - poiLabH / 2, height - poiLabH));
|
|
48678
|
+
labels.push({
|
|
48679
|
+
x: anchor === "start" ? x : x + w,
|
|
48680
|
+
y: y + poiLabH / 2 + FONT2 / 3,
|
|
48681
|
+
text,
|
|
48682
|
+
anchor,
|
|
48683
|
+
color: palette.text,
|
|
48684
|
+
halo: false,
|
|
48685
|
+
haloColor: palette.bg,
|
|
48686
|
+
poiId: p.id,
|
|
48687
|
+
hidden: true,
|
|
48688
|
+
lineNumber: p.lineNumber
|
|
47572
48689
|
});
|
|
47573
48690
|
};
|
|
47574
|
-
for (const
|
|
48691
|
+
for (const [clusterId, members] of clusterMembersById) {
|
|
48692
|
+
if (members.length === 0) continue;
|
|
48693
|
+
const items = makeItems(members);
|
|
48694
|
+
const side = wouldColumnBeClean(items, "right") ? "right" : wouldColumnBeClean(items, "left") ? "left" : defaultColumnSide(items);
|
|
48695
|
+
commitColumn(items, side, clusterId);
|
|
48696
|
+
}
|
|
48697
|
+
const maxExtent = MAX_CLUSTER_EXTENT_FACTOR * Math.min(width, height);
|
|
48698
|
+
const clusterPending = [];
|
|
48699
|
+
for (const g of groups2) {
|
|
48700
|
+
const items = makeItems(g);
|
|
47575
48701
|
if (g.length === 1) {
|
|
47576
|
-
const p =
|
|
47577
|
-
const { text, w } = labelInfo(p);
|
|
48702
|
+
const { p, text, w } = items[0];
|
|
47578
48703
|
const side = ["right", "left", "above", "below"].find(
|
|
47579
48704
|
(s) => inlineFits(p, w, s)
|
|
47580
48705
|
);
|
|
47581
|
-
if (side)
|
|
47582
|
-
|
|
47583
|
-
|
|
48706
|
+
if (side) pushInline(p, text, w, side);
|
|
48707
|
+
else commitColumn(items, defaultColumnSide(items));
|
|
48708
|
+
continue;
|
|
48709
|
+
}
|
|
48710
|
+
const left = Math.min(...items.map((o) => o.p.cx - o.p.r));
|
|
48711
|
+
const right = Math.max(...items.map((o) => o.p.cx + o.p.r));
|
|
48712
|
+
const minCy = Math.min(...items.map((o) => o.p.cy));
|
|
48713
|
+
const maxCy = Math.max(...items.map((o) => o.p.cy));
|
|
48714
|
+
const diag = Math.hypot(right - left, maxCy - minCy);
|
|
48715
|
+
if (diag > maxExtent || items.length > MAX_COLUMN_ROWS) {
|
|
48716
|
+
items.forEach((o) => pushHidden(o.p));
|
|
48717
|
+
} else {
|
|
48718
|
+
clusterPending.push(items);
|
|
48719
|
+
}
|
|
48720
|
+
}
|
|
48721
|
+
for (const items of clusterPending) {
|
|
48722
|
+
const side = ["right", "left"].find(
|
|
48723
|
+
(s) => wouldColumnBeClean(items, s)
|
|
48724
|
+
);
|
|
48725
|
+
if (side) commitColumn(items, side);
|
|
48726
|
+
else items.forEach((o) => pushHidden(o.p));
|
|
48727
|
+
}
|
|
48728
|
+
}
|
|
48729
|
+
if (resolved.directives.noContextLabels !== true) {
|
|
48730
|
+
for (const l of labels) {
|
|
48731
|
+
if (l.hidden) continue;
|
|
48732
|
+
const w = labelW(l.text);
|
|
48733
|
+
const x = l.anchor === "start" ? l.x : l.anchor === "end" ? l.x - w : l.x - w / 2;
|
|
48734
|
+
obstacles.push({ x, y: l.y - labelH / 2, w, h: labelH });
|
|
48735
|
+
}
|
|
48736
|
+
for (const box of insets)
|
|
48737
|
+
obstacles.push({ x: box.x, y: box.y, w: box.w, h: box.h });
|
|
48738
|
+
const countryCandidates = [];
|
|
48739
|
+
for (const f of worldLayer.values()) {
|
|
48740
|
+
const iso = typeof f.id === "string" ? f.id : String(f.id ?? "");
|
|
48741
|
+
if (!iso || regionById.has(iso)) continue;
|
|
48742
|
+
let hasReferencedSub = false;
|
|
48743
|
+
for (const k of regionById.keys())
|
|
48744
|
+
if (k.startsWith(iso + "-")) {
|
|
48745
|
+
hasReferencedSub = true;
|
|
48746
|
+
break;
|
|
47584
48747
|
}
|
|
48748
|
+
if (hasReferencedSub) continue;
|
|
48749
|
+
const b = path.bounds(f);
|
|
48750
|
+
const [x0, y0] = b[0];
|
|
48751
|
+
const [x1, y1] = b[1];
|
|
48752
|
+
if (!Number.isFinite(x0) || !Number.isFinite(x1)) continue;
|
|
48753
|
+
const anchorLngLat = WORLD_LABEL_ANCHORS[iso];
|
|
48754
|
+
const a = anchorLngLat ? project(anchorLngLat[0], anchorLngLat[1]) : path.centroid(f);
|
|
48755
|
+
countryCandidates.push({
|
|
48756
|
+
name: f.properties?.name ?? iso,
|
|
48757
|
+
bbox: [x0, y0, x1, y1],
|
|
48758
|
+
anchor: a && Number.isFinite(a[0]) ? [a[0], a[1]] : null
|
|
48759
|
+
});
|
|
48760
|
+
}
|
|
48761
|
+
const framedStateContainers = (resolved.poiFrameContainers ?? []).some(
|
|
48762
|
+
(id) => id.startsWith("US-")
|
|
48763
|
+
);
|
|
48764
|
+
if (usLayer && framedStateContainers) {
|
|
48765
|
+
const containerSet = new Set(resolved.poiFrameContainers);
|
|
48766
|
+
for (const [iso, f] of usLayer) {
|
|
48767
|
+
if (containerSet.has(iso) || regionById.has(iso)) continue;
|
|
48768
|
+
const viewF = cullFeatureToView(f);
|
|
48769
|
+
if (!viewF) continue;
|
|
48770
|
+
const b = path.bounds(viewF);
|
|
48771
|
+
const [x0, y0] = b[0];
|
|
48772
|
+
const [x1, y1] = b[1];
|
|
48773
|
+
if (!Number.isFinite(x0) || !Number.isFinite(x1)) continue;
|
|
48774
|
+
const a = path.centroid(viewF);
|
|
48775
|
+
countryCandidates.push({
|
|
48776
|
+
name: f.properties?.name ?? iso,
|
|
48777
|
+
bbox: [x0, y0, x1, y1],
|
|
48778
|
+
anchor: a && Number.isFinite(a[0]) ? [a[0], a[1]] : null
|
|
48779
|
+
});
|
|
47585
48780
|
}
|
|
47586
|
-
placeColumn(g);
|
|
47587
48781
|
}
|
|
48782
|
+
const contextLabels = placeContextLabels({
|
|
48783
|
+
projection: resolved.projection,
|
|
48784
|
+
dLonSpan,
|
|
48785
|
+
dLatSpan,
|
|
48786
|
+
width,
|
|
48787
|
+
height,
|
|
48788
|
+
waterBodies: data.waterBodies,
|
|
48789
|
+
countries: countryCandidates,
|
|
48790
|
+
palette,
|
|
48791
|
+
project,
|
|
48792
|
+
collides,
|
|
48793
|
+
// Water labels must stay over open water — `fillAt` returns the ocean
|
|
48794
|
+
// backdrop colour off-land and a region fill on-land (lakes/states count
|
|
48795
|
+
// as land here, which is the safe side for an ocean name).
|
|
48796
|
+
overLand: (x, y) => fillAt(x, y) !== water
|
|
48797
|
+
});
|
|
48798
|
+
labels.push(...contextLabels);
|
|
47588
48799
|
}
|
|
47589
48800
|
let legend = null;
|
|
47590
48801
|
if (!resolved.directives.noLegend) {
|
|
@@ -47621,25 +48832,31 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47621
48832
|
rivers,
|
|
47622
48833
|
relief,
|
|
47623
48834
|
reliefHatch,
|
|
48835
|
+
coastlineStyle,
|
|
47624
48836
|
legs,
|
|
47625
48837
|
pois,
|
|
48838
|
+
clusters,
|
|
47626
48839
|
labels,
|
|
47627
48840
|
legend,
|
|
47628
48841
|
insets,
|
|
47629
48842
|
insetRegions,
|
|
47630
48843
|
projection,
|
|
47631
|
-
stretch: stretchParams
|
|
48844
|
+
stretch: stretchParams,
|
|
48845
|
+
diagnostics: []
|
|
47632
48846
|
};
|
|
47633
48847
|
}
|
|
47634
|
-
var FIT_PAD, RAMP_FLOOR, R_DEFAULT, R_MIN, R_MAX, W_MIN, W_MAX,
|
|
48848
|
+
var FIT_PAD, RAMP_FLOOR, R_DEFAULT, R_MIN, R_MAX, W_MIN, W_MAX, FONT2, 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;
|
|
47635
48849
|
var init_layout15 = __esm({
|
|
47636
48850
|
"src/map/layout.ts"() {
|
|
47637
48851
|
"use strict";
|
|
47638
48852
|
init_color_utils();
|
|
48853
|
+
init_geo();
|
|
48854
|
+
init_colorize();
|
|
47639
48855
|
init_colors();
|
|
47640
48856
|
init_label_layout();
|
|
47641
48857
|
init_legend_constants();
|
|
47642
48858
|
init_title_constants();
|
|
48859
|
+
init_context_labels();
|
|
47643
48860
|
FIT_PAD = 24;
|
|
47644
48861
|
RAMP_FLOOR = 15;
|
|
47645
48862
|
R_DEFAULT = 6;
|
|
@@ -47647,32 +48864,66 @@ var init_layout15 = __esm({
|
|
|
47647
48864
|
R_MAX = 22;
|
|
47648
48865
|
W_MIN = 1.25;
|
|
47649
48866
|
W_MAX = 8;
|
|
47650
|
-
|
|
47651
|
-
|
|
48867
|
+
FONT2 = 11;
|
|
48868
|
+
MAX_CLUSTER_EXTENT_FACTOR = 0.18;
|
|
48869
|
+
MAX_COLUMN_ROWS = 7;
|
|
48870
|
+
REGION_LABEL_HALO_RATIO = 4.5;
|
|
47652
48871
|
LAND_TINT_LIGHT = 12;
|
|
47653
48872
|
LAND_TINT_DARK = 24;
|
|
47654
48873
|
TAG_TINT_LIGHT = 60;
|
|
47655
48874
|
TAG_TINT_DARK = 68;
|
|
47656
|
-
WATER_TINT_LIGHT =
|
|
47657
|
-
WATER_TINT_DARK =
|
|
48875
|
+
WATER_TINT_LIGHT = 24;
|
|
48876
|
+
WATER_TINT_DARK = 24;
|
|
47658
48877
|
RIVER_WIDTH = 1.3;
|
|
48878
|
+
COMPACT_WIDTH_PX = 480;
|
|
47659
48879
|
RELIEF_MIN_AREA = 12;
|
|
47660
48880
|
RELIEF_MIN_DIM = 2;
|
|
47661
|
-
RELIEF_HATCH_SPACING =
|
|
47662
|
-
RELIEF_HATCH_WIDTH = 0.
|
|
48881
|
+
RELIEF_HATCH_SPACING = 2;
|
|
48882
|
+
RELIEF_HATCH_WIDTH = 0.15;
|
|
47663
48883
|
RELIEF_HATCH_STRENGTH = 32;
|
|
48884
|
+
COASTLINE_RING_COUNT = 5;
|
|
48885
|
+
COASTLINE_D0 = 16e-4;
|
|
48886
|
+
COASTLINE_STEP = 28e-4;
|
|
48887
|
+
COASTLINE_THICKNESS = 14e-4;
|
|
48888
|
+
COASTLINE_OPACITY_NEAR = 0.5;
|
|
48889
|
+
COASTLINE_OPACITY_FAR = 0.1;
|
|
48890
|
+
COASTLINE_MIN_EXTENT = 6e-4;
|
|
48891
|
+
COASTLINE_MIN_EXTENT_GLOBAL = 6e-4;
|
|
48892
|
+
COASTLINE_STROKE_MIX = 32;
|
|
47664
48893
|
FOREIGN_TINT_LIGHT = 30;
|
|
47665
48894
|
FOREIGN_TINT_DARK = 62;
|
|
47666
48895
|
MUTED_FOREIGN_LIGHT = 28;
|
|
47667
48896
|
MUTED_FOREIGN_DARK = 16;
|
|
47668
48897
|
COLO_R = 9;
|
|
47669
48898
|
GOLDEN_ANGLE = 2.399963229728653;
|
|
48899
|
+
STACK_OVERLAP = 1;
|
|
48900
|
+
STACK_RING_MAX = 8;
|
|
48901
|
+
STACK_RING_GAP = 4;
|
|
47670
48902
|
FAN_STEP = 16;
|
|
47671
48903
|
ARC_CURVE_FRAC = 0.18;
|
|
48904
|
+
decodeCache = /* @__PURE__ */ new WeakMap();
|
|
47672
48905
|
usConusProjection = () => geoConicEqualArea().parallels([29.5, 45.5]).rotate([96, 0]);
|
|
47673
48906
|
alaskaProjection = () => geoConicEqualArea().rotate([154, 0]).center([-2, 58.5]).parallels([55, 65]);
|
|
47674
48907
|
hawaiiProjection = () => geoMercator();
|
|
47675
48908
|
INSET_STATES = /* @__PURE__ */ new Set(["US-AK", "US-HI"]);
|
|
48909
|
+
inAlaska = (lon, lat) => lat >= 51 && (lon <= -129 || lon >= 172);
|
|
48910
|
+
inHawaii = (lon, lat) => lat >= 18 && lat <= 23 && lon >= -161 && lon <= -154;
|
|
48911
|
+
FOREIGN_BORDER = {
|
|
48912
|
+
CA: [
|
|
48913
|
+
"US-AK",
|
|
48914
|
+
"US-WA",
|
|
48915
|
+
"US-ID",
|
|
48916
|
+
"US-MT",
|
|
48917
|
+
"US-ND",
|
|
48918
|
+
"US-MN",
|
|
48919
|
+
"US-MI",
|
|
48920
|
+
"US-NY",
|
|
48921
|
+
"US-VT",
|
|
48922
|
+
"US-NH",
|
|
48923
|
+
"US-ME"
|
|
48924
|
+
],
|
|
48925
|
+
MX: ["US-CA", "US-AZ", "US-NM", "US-TX"]
|
|
48926
|
+
};
|
|
47676
48927
|
US_NON_CONUS = /* @__PURE__ */ new Set([
|
|
47677
48928
|
"US-AK",
|
|
47678
48929
|
"US-HI",
|
|
@@ -47692,6 +48943,58 @@ __export(renderer_exports16, {
|
|
|
47692
48943
|
renderMapForExport: () => renderMapForExport
|
|
47693
48944
|
});
|
|
47694
48945
|
import * as d3Selection18 from "d3-selection";
|
|
48946
|
+
function pointInRing2(px, py, ring) {
|
|
48947
|
+
let inside = false;
|
|
48948
|
+
for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {
|
|
48949
|
+
const [xi, yi] = ring[i];
|
|
48950
|
+
const [xj, yj] = ring[j];
|
|
48951
|
+
if (yi > py !== yj > py && px < (xj - xi) * (py - yi) / (yj - yi) + xi)
|
|
48952
|
+
inside = !inside;
|
|
48953
|
+
}
|
|
48954
|
+
return inside;
|
|
48955
|
+
}
|
|
48956
|
+
function ringToPath(ring) {
|
|
48957
|
+
let d = "";
|
|
48958
|
+
for (let i = 0; i < ring.length; i++)
|
|
48959
|
+
d += (i ? "L" : "M") + ring[i][0] + "," + ring[i][1];
|
|
48960
|
+
return d + "Z";
|
|
48961
|
+
}
|
|
48962
|
+
function coastlineOuterRings(regions, minExtent) {
|
|
48963
|
+
const paths = [];
|
|
48964
|
+
for (const r of regions) {
|
|
48965
|
+
const rings = parsePathRings(r.d);
|
|
48966
|
+
for (let i = 0; i < rings.length; i++) {
|
|
48967
|
+
const ring = rings[i];
|
|
48968
|
+
if (ring.length < 3) continue;
|
|
48969
|
+
let minX = Infinity;
|
|
48970
|
+
let minY = Infinity;
|
|
48971
|
+
let maxX = -Infinity;
|
|
48972
|
+
let maxY = -Infinity;
|
|
48973
|
+
for (const [x, y] of ring) {
|
|
48974
|
+
if (x < minX) minX = x;
|
|
48975
|
+
if (x > maxX) maxX = x;
|
|
48976
|
+
if (y < minY) minY = y;
|
|
48977
|
+
if (y > maxY) maxY = y;
|
|
48978
|
+
}
|
|
48979
|
+
if (Math.max(maxX - minX, maxY - minY) < minExtent) continue;
|
|
48980
|
+
const [fx, fy] = ring[0];
|
|
48981
|
+
let depth = 0;
|
|
48982
|
+
for (let j = 0; j < rings.length; j++)
|
|
48983
|
+
if (j !== i && pointInRing2(fx, fy, rings[j])) depth++;
|
|
48984
|
+
if (depth % 2 === 1) continue;
|
|
48985
|
+
paths.push(ringToPath(ring));
|
|
48986
|
+
}
|
|
48987
|
+
}
|
|
48988
|
+
return paths;
|
|
48989
|
+
}
|
|
48990
|
+
function appendWaterLines(g, outerRings, style, flatWater) {
|
|
48991
|
+
const d = outerRings.join(" ");
|
|
48992
|
+
const linesOuterFirst = [...style.lines].sort((a, b) => b.d - a.d);
|
|
48993
|
+
for (const line12 of linesOuterFirst) {
|
|
48994
|
+
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");
|
|
48995
|
+
g.append("path").attr("d", d).attr("stroke", flatWater).attr("stroke-width", 2 * line12.d).attr("stroke-linejoin", "round").attr("stroke-linecap", "round");
|
|
48996
|
+
}
|
|
48997
|
+
}
|
|
47695
48998
|
function renderMap(container, resolved, data, palette, isDark, onClickItem, exportDims, activeGroupOverride) {
|
|
47696
48999
|
d3Selection18.select(container).selectAll(":not([data-d3-tooltip])").remove();
|
|
47697
49000
|
const width = exportDims?.width ?? container.clientWidth;
|
|
@@ -47704,6 +49007,11 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
47704
49007
|
{
|
|
47705
49008
|
palette,
|
|
47706
49009
|
isDark,
|
|
49010
|
+
// Export-only: forward the contain-fit request from mapExportDimensions so a
|
|
49011
|
+
// clamped/floored (off-aspect) export canvas letterboxes instead of
|
|
49012
|
+
// stretch-distorting. The in-app preview pane passes no exportDims → unset →
|
|
49013
|
+
// keeps the global stretch-fill.
|
|
49014
|
+
preferContain: exportDims?.preferContain ?? false,
|
|
47707
49015
|
...activeGroupOverride !== void 0 && {
|
|
47708
49016
|
activeGroup: activeGroupOverride
|
|
47709
49017
|
}
|
|
@@ -47717,6 +49025,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
47717
49025
|
const gRegions = svg.append("g").attr("class", "dgmo-map-regions");
|
|
47718
49026
|
const drawRegion = (g, r, strokeWidth) => {
|
|
47719
49027
|
const p = g.append("path").attr("d", r.d).attr("fill", r.fill).attr("stroke", r.stroke).attr("stroke-width", strokeWidth);
|
|
49028
|
+
if (r.label) p.attr("data-region-name", r.label);
|
|
47720
49029
|
if (r.layer !== "base") {
|
|
47721
49030
|
p.classed("dgmo-map-region", true).attr("data-region", r.id);
|
|
47722
49031
|
if (r.value !== void 0) p.attr("data-value", r.value);
|
|
@@ -47751,6 +49060,38 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
47751
49060
|
gRelief.append("line").attr("x1", 0).attr("y1", y).attr("x2", width).attr("y2", y);
|
|
47752
49061
|
}
|
|
47753
49062
|
}
|
|
49063
|
+
if (layout.coastlineStyle) {
|
|
49064
|
+
const cs = layout.coastlineStyle;
|
|
49065
|
+
const maskId = "dgmo-map-water-mask";
|
|
49066
|
+
const mask = defs.append("mask").attr("id", maskId).attr("maskUnits", "userSpaceOnUse").attr("x", 0).attr("y", 0).attr("width", width).attr("height", height);
|
|
49067
|
+
mask.append("rect").attr("x", 0).attr("y", 0).attr("width", width).attr("height", height).attr("fill", "white");
|
|
49068
|
+
const landD = layout.regions.filter((r) => r.id !== "lake").map((r) => r.d).join(" ");
|
|
49069
|
+
const lakeD = layout.regions.filter((r) => r.id === "lake").map((r) => r.d).join(" ");
|
|
49070
|
+
if (landD) mask.append("path").attr("d", landD).attr("fill", "black");
|
|
49071
|
+
if (lakeD) mask.append("path").attr("d", lakeD).attr("fill", "white");
|
|
49072
|
+
if (layout.insets.length) {
|
|
49073
|
+
const reach = Math.max(0, ...cs.lines.map((l) => l.d + l.thickness));
|
|
49074
|
+
for (const box of layout.insets) {
|
|
49075
|
+
const d = box.points.map((p, i) => `${i ? "L" : "M"}${p[0]},${p[1]}`).join("") + "Z";
|
|
49076
|
+
mask.append("path").attr("d", d).attr("fill", "black").attr("stroke", "black").attr("stroke-width", 2 * reach).attr("stroke-linejoin", "round");
|
|
49077
|
+
}
|
|
49078
|
+
}
|
|
49079
|
+
const gWater = svg.append("g").attr("class", "dgmo-map-water-lines").attr("fill", "none").attr("mask", `url(#${maskId})`);
|
|
49080
|
+
appendWaterLines(
|
|
49081
|
+
gWater,
|
|
49082
|
+
coastlineOuterRings(layout.regions, cs.minExtent),
|
|
49083
|
+
cs,
|
|
49084
|
+
layout.background
|
|
49085
|
+
);
|
|
49086
|
+
const byStroke = /* @__PURE__ */ new Map();
|
|
49087
|
+
for (const r of layout.regions) {
|
|
49088
|
+
const arr = byStroke.get(r.stroke);
|
|
49089
|
+
if (arr) arr.push(r.d);
|
|
49090
|
+
else byStroke.set(r.stroke, [r.d]);
|
|
49091
|
+
}
|
|
49092
|
+
for (const [stroke2, ds] of byStroke)
|
|
49093
|
+
gWater.append("path").attr("d", ds.join(" ")).attr("stroke", stroke2).attr("stroke-width", 0.5).attr("stroke-linejoin", "round");
|
|
49094
|
+
}
|
|
47754
49095
|
if (layout.rivers.length) {
|
|
47755
49096
|
const gRivers = svg.append("g").attr("class", "dgmo-map-rivers").attr("fill", "none");
|
|
47756
49097
|
for (const r of layout.rivers) {
|
|
@@ -47759,15 +49100,61 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
47759
49100
|
}
|
|
47760
49101
|
if (layout.insets.length) {
|
|
47761
49102
|
const insetG = svg.append("g").attr("class", "dgmo-map-insets");
|
|
47762
|
-
|
|
49103
|
+
layout.insets.forEach((box, bi) => {
|
|
47763
49104
|
const d = box.points.map((p, i) => `${i ? "L" : "M"}${p[0]},${p[1]}`).join("") + "Z";
|
|
47764
49105
|
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");
|
|
47765
|
-
|
|
49106
|
+
if (box.contextLand) {
|
|
49107
|
+
const clipId = `dgmo-map-inset-clip-${bi}`;
|
|
49108
|
+
defs.append("clipPath").attr("id", clipId).append("path").attr("d", d);
|
|
49109
|
+
insetG.append("path").attr("d", box.contextLand.d).attr("fill", box.contextLand.fill).attr("clip-path", `url(#${clipId})`);
|
|
49110
|
+
}
|
|
49111
|
+
});
|
|
47766
49112
|
for (const r of layout.insetRegions) drawRegion(insetG, r, 0.5);
|
|
47767
|
-
|
|
49113
|
+
if (layout.coastlineStyle) {
|
|
49114
|
+
const cs = layout.coastlineStyle;
|
|
49115
|
+
const maskId = "dgmo-map-inset-water-mask";
|
|
49116
|
+
const mask = defs.append("mask").attr("id", maskId).attr("maskUnits", "userSpaceOnUse").attr("x", 0).attr("y", 0).attr("width", width).attr("height", height);
|
|
49117
|
+
for (const box of layout.insets) {
|
|
49118
|
+
const d = box.points.map((p, i) => `${i ? "L" : "M"}${p[0]},${p[1]}`).join("") + "Z";
|
|
49119
|
+
mask.append("path").attr("d", d).attr("fill", "white");
|
|
49120
|
+
}
|
|
49121
|
+
layout.insets.forEach((box, bi) => {
|
|
49122
|
+
if (box.contextLand)
|
|
49123
|
+
mask.append("path").attr("d", box.contextLand.d).attr("fill", "black").attr("clip-path", `url(#dgmo-map-inset-clip-${bi})`);
|
|
49124
|
+
});
|
|
49125
|
+
for (const r of layout.insetRegions)
|
|
49126
|
+
if (r.id !== "lake")
|
|
49127
|
+
mask.append("path").attr("d", r.d).attr("fill", "black");
|
|
49128
|
+
for (const r of layout.insetRegions)
|
|
49129
|
+
if (r.id === "lake")
|
|
49130
|
+
mask.append("path").attr("d", r.d).attr("fill", "white");
|
|
49131
|
+
const clipId = "dgmo-map-inset-water-clip";
|
|
49132
|
+
const clip = defs.append("clipPath").attr("id", clipId);
|
|
49133
|
+
for (const box of layout.insets) {
|
|
49134
|
+
const d = box.points.map((p, i) => `${i ? "L" : "M"}${p[0]},${p[1]}`).join("") + "Z";
|
|
49135
|
+
clip.append("path").attr("d", d);
|
|
49136
|
+
}
|
|
49137
|
+
const gInsetWater = insetG.append("g").attr("clip-path", `url(#${clipId})`).append("g").attr("class", "dgmo-map-inset-water-lines").attr("fill", "none").attr("mask", `url(#${maskId})`);
|
|
49138
|
+
appendWaterLines(
|
|
49139
|
+
gInsetWater,
|
|
49140
|
+
coastlineOuterRings(layout.insetRegions, cs.minExtent),
|
|
49141
|
+
cs,
|
|
49142
|
+
layout.background
|
|
49143
|
+
);
|
|
49144
|
+
for (const r of layout.insetRegions)
|
|
49145
|
+
gInsetWater.append("path").attr("d", r.d).attr("stroke", r.stroke).attr("stroke-width", 0.5).attr("stroke-linejoin", "round");
|
|
49146
|
+
}
|
|
49147
|
+
}
|
|
49148
|
+
const wireSync = (sel, lineNumber) => {
|
|
49149
|
+
if (lineNumber < 1) return;
|
|
49150
|
+
sel.attr("data-line-number", lineNumber);
|
|
49151
|
+
if (onClickItem)
|
|
49152
|
+
sel.style("cursor", "pointer").on("click", () => onClickItem(lineNumber));
|
|
49153
|
+
};
|
|
47768
49154
|
const gLegs = svg.append("g").attr("class", "dgmo-map-legs").attr("fill", "none");
|
|
47769
49155
|
layout.legs.forEach((leg, i) => {
|
|
47770
49156
|
const p = gLegs.append("path").attr("d", leg.d).attr("stroke", leg.color).attr("stroke-width", leg.width).attr("stroke-linecap", "round");
|
|
49157
|
+
wireSync(p, leg.lineNumber);
|
|
47771
49158
|
if (leg.arrow) {
|
|
47772
49159
|
const id = `dgmo-map-arrow-${i}`;
|
|
47773
49160
|
const s = arrowSize(leg.width);
|
|
@@ -47775,25 +49162,38 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
47775
49162
|
p.attr("marker-end", `url(#${id})`);
|
|
47776
49163
|
}
|
|
47777
49164
|
if (leg.label !== void 0 && leg.labelX !== void 0) {
|
|
47778
|
-
emitText(
|
|
49165
|
+
const lt = emitText(
|
|
47779
49166
|
gLegs,
|
|
47780
49167
|
leg.labelX,
|
|
47781
49168
|
leg.labelY ?? 0,
|
|
47782
49169
|
leg.label,
|
|
47783
49170
|
"middle",
|
|
47784
|
-
palette.textMuted,
|
|
47785
|
-
haloColor,
|
|
47786
|
-
true,
|
|
49171
|
+
leg.labelColor ?? palette.textMuted,
|
|
49172
|
+
leg.labelHaloColor ?? haloColor,
|
|
49173
|
+
leg.labelHalo ?? true,
|
|
47787
49174
|
LABEL_FONT - 1
|
|
47788
49175
|
);
|
|
49176
|
+
wireSync(lt, leg.lineNumber);
|
|
47789
49177
|
}
|
|
47790
49178
|
});
|
|
49179
|
+
const gSpider = svg.append("g").attr("class", "dgmo-map-spider");
|
|
49180
|
+
for (const cl of layout.clusters) {
|
|
49181
|
+
if (!exportDims) {
|
|
49182
|
+
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");
|
|
49183
|
+
}
|
|
49184
|
+
for (const leg of cl.legs) {
|
|
49185
|
+
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");
|
|
49186
|
+
}
|
|
49187
|
+
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");
|
|
49188
|
+
}
|
|
47791
49189
|
const gPois = svg.append("g").attr("class", "dgmo-map-pois");
|
|
47792
49190
|
for (const poi of layout.pois) {
|
|
47793
49191
|
if (poi.isOrigin) {
|
|
47794
49192
|
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);
|
|
47795
49193
|
}
|
|
47796
49194
|
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);
|
|
49195
|
+
if (poi.clusterId !== void 0)
|
|
49196
|
+
c.attr("data-cluster-member", poi.clusterId);
|
|
47797
49197
|
if (poi.tags) {
|
|
47798
49198
|
for (const [group, value] of Object.entries(poi.tags)) {
|
|
47799
49199
|
c.attr(`data-tag-${group.toLowerCase()}`, value.toLowerCase());
|
|
@@ -47821,12 +49221,32 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
47821
49221
|
}
|
|
47822
49222
|
const gLabels = svg.append("g").attr("class", "dgmo-map-labels");
|
|
47823
49223
|
for (const lab of layout.labels) {
|
|
49224
|
+
if (lab.hidden) {
|
|
49225
|
+
if (exportDims) continue;
|
|
49226
|
+
emitText(
|
|
49227
|
+
gLabels,
|
|
49228
|
+
lab.x,
|
|
49229
|
+
lab.y,
|
|
49230
|
+
lab.text,
|
|
49231
|
+
lab.anchor,
|
|
49232
|
+
lab.color,
|
|
49233
|
+
lab.haloColor,
|
|
49234
|
+
lab.halo,
|
|
49235
|
+
LABEL_FONT,
|
|
49236
|
+
lab.italic,
|
|
49237
|
+
lab.letterSpacing
|
|
49238
|
+
).attr("data-poi", lab.poiId ?? null).attr("data-poi-hidden", "").style("opacity", 0).style("pointer-events", "none");
|
|
49239
|
+
continue;
|
|
49240
|
+
}
|
|
47824
49241
|
if (lab.leader) {
|
|
47825
49242
|
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(
|
|
47826
49243
|
"stroke",
|
|
47827
49244
|
lab.leaderColor ?? mix(palette.textMuted, palette.bg, 60)
|
|
47828
49245
|
).attr("stroke-width", lab.leaderColor ? 1 : 0.75);
|
|
47829
49246
|
if (lab.poiId !== void 0) line12.attr("data-poi", lab.poiId);
|
|
49247
|
+
if (lab.clusterMember !== void 0)
|
|
49248
|
+
line12.attr("data-cluster-member", lab.clusterMember);
|
|
49249
|
+
wireSync(line12, lab.lineNumber);
|
|
47830
49250
|
}
|
|
47831
49251
|
const t = emitText(
|
|
47832
49252
|
gLabels,
|
|
@@ -47837,11 +49257,38 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
47837
49257
|
lab.color,
|
|
47838
49258
|
lab.haloColor,
|
|
47839
49259
|
lab.halo,
|
|
47840
|
-
LABEL_FONT
|
|
49260
|
+
LABEL_FONT,
|
|
49261
|
+
lab.italic,
|
|
49262
|
+
lab.letterSpacing,
|
|
49263
|
+
lab.lines
|
|
47841
49264
|
);
|
|
47842
49265
|
if (lab.poiId !== void 0) {
|
|
47843
49266
|
t.attr("data-poi", lab.poiId).style("cursor", "default");
|
|
47844
49267
|
}
|
|
49268
|
+
if (lab.clusterMember !== void 0) {
|
|
49269
|
+
t.attr("data-cluster-member", lab.clusterMember);
|
|
49270
|
+
}
|
|
49271
|
+
wireSync(t, lab.lineNumber);
|
|
49272
|
+
}
|
|
49273
|
+
if (!exportDims && layout.clusters.length) {
|
|
49274
|
+
const gBadge = svg.append("g").attr("class", "dgmo-map-cluster-badges");
|
|
49275
|
+
for (const cl of layout.clusters) {
|
|
49276
|
+
const g = gBadge.append("g").attr("data-cluster", cl.id).style("opacity", 0).style("pointer-events", "none");
|
|
49277
|
+
const R = 9;
|
|
49278
|
+
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);
|
|
49279
|
+
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);
|
|
49280
|
+
emitText(
|
|
49281
|
+
g,
|
|
49282
|
+
cl.cx,
|
|
49283
|
+
cl.cy + 3,
|
|
49284
|
+
String(cl.count),
|
|
49285
|
+
"middle",
|
|
49286
|
+
palette.text,
|
|
49287
|
+
palette.bg,
|
|
49288
|
+
false,
|
|
49289
|
+
LABEL_FONT
|
|
49290
|
+
);
|
|
49291
|
+
}
|
|
47845
49292
|
}
|
|
47846
49293
|
if (layout.legend) {
|
|
47847
49294
|
const legendY = (layout.title ? TITLE_Y + TITLE_FONT_SIZE : 0) + (layout.subtitle ? TITLE_FONT_SIZE : 0) + 8;
|
|
@@ -47878,7 +49325,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
47878
49325
|
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);
|
|
47879
49326
|
}
|
|
47880
49327
|
if (layout.subtitle) {
|
|
47881
|
-
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);
|
|
49328
|
+
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);
|
|
47882
49329
|
}
|
|
47883
49330
|
if (layout.caption) {
|
|
47884
49331
|
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);
|
|
@@ -47887,10 +49334,21 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
47887
49334
|
function renderMapForExport(container, resolved, data, palette, isDark, exportDims) {
|
|
47888
49335
|
renderMap(container, resolved, data, palette, isDark, void 0, exportDims);
|
|
47889
49336
|
}
|
|
47890
|
-
function emitText(g, x, y, text, anchor, color, halo, withHalo, fontSize) {
|
|
47891
|
-
const t = g.append("text").attr("x", x).attr("y", y).attr("text-anchor", anchor).attr("font-size", fontSize).attr("fill", color)
|
|
49337
|
+
function emitText(g, x, y, text, anchor, color, halo, withHalo, fontSize, italic, letterSpacing, lines) {
|
|
49338
|
+
const t = g.append("text").attr("x", x).attr("y", y).attr("text-anchor", anchor).attr("font-size", fontSize).attr("fill", color);
|
|
49339
|
+
if (lines && lines.length > 1) {
|
|
49340
|
+
const lineHeight = fontSize + 2;
|
|
49341
|
+
const startDy = -((lines.length - 1) / 2) * lineHeight;
|
|
49342
|
+
lines.forEach((ln, i) => {
|
|
49343
|
+
t.append("tspan").attr("x", x).attr("dy", i === 0 ? startDy : lineHeight).text(ln);
|
|
49344
|
+
});
|
|
49345
|
+
} else {
|
|
49346
|
+
t.text(text);
|
|
49347
|
+
}
|
|
49348
|
+
if (italic) t.attr("font-style", "italic");
|
|
49349
|
+
if (letterSpacing) t.attr("letter-spacing", letterSpacing);
|
|
47892
49350
|
if (withHalo) {
|
|
47893
|
-
t.attr("paint-order", "stroke fill").attr("stroke", halo).attr("stroke-width",
|
|
49351
|
+
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);
|
|
47894
49352
|
}
|
|
47895
49353
|
return t;
|
|
47896
49354
|
}
|
|
@@ -47907,6 +49365,56 @@ var init_renderer16 = __esm({
|
|
|
47907
49365
|
}
|
|
47908
49366
|
});
|
|
47909
49367
|
|
|
49368
|
+
// src/map/dimensions.ts
|
|
49369
|
+
var dimensions_exports = {};
|
|
49370
|
+
__export(dimensions_exports, {
|
|
49371
|
+
mapContentAspect: () => mapContentAspect,
|
|
49372
|
+
mapExportDimensions: () => mapExportDimensions
|
|
49373
|
+
});
|
|
49374
|
+
import { geoPath as geoPath2 } from "d3-geo";
|
|
49375
|
+
function mapContentAspect(resolved, data, ref = REF) {
|
|
49376
|
+
const { projection, fitTarget } = buildMapProjection(resolved, data);
|
|
49377
|
+
projection.fitSize([ref, ref], fitTarget);
|
|
49378
|
+
const b = geoPath2(projection).bounds(fitTarget);
|
|
49379
|
+
const w = b[1][0] - b[0][0];
|
|
49380
|
+
const h = b[1][1] - b[0][1];
|
|
49381
|
+
const aspect = w / h;
|
|
49382
|
+
return Number.isFinite(aspect) && aspect > 0 ? aspect : FALLBACK_ASPECT;
|
|
49383
|
+
}
|
|
49384
|
+
function mapExportDimensions(resolved, data, baseWidth = 1200) {
|
|
49385
|
+
const raw = mapContentAspect(resolved, data);
|
|
49386
|
+
const clamped = Math.max(ASPECT_MIN, Math.min(ASPECT_MAX, raw));
|
|
49387
|
+
const width = baseWidth;
|
|
49388
|
+
let height = Math.round(width / clamped);
|
|
49389
|
+
let chromeReserve = 0;
|
|
49390
|
+
if (resolved.title && resolved.pois.length > 0) {
|
|
49391
|
+
const bannerBottom = (resolved.subtitle ? TITLE_Y + TITLE_FONT_SIZE : TITLE_Y) + TITLE_FONT_SIZE / 2;
|
|
49392
|
+
chromeReserve += Math.max(FIT_PAD2, bannerBottom + TITLE_GAP) - FIT_PAD2;
|
|
49393
|
+
}
|
|
49394
|
+
let floored = false;
|
|
49395
|
+
if (height - chromeReserve < MIN_MAP_BAND) {
|
|
49396
|
+
height = Math.round(chromeReserve + MIN_MAP_BAND);
|
|
49397
|
+
floored = true;
|
|
49398
|
+
}
|
|
49399
|
+
const preferContain = clamped !== raw || floored;
|
|
49400
|
+
return { width, height, preferContain };
|
|
49401
|
+
}
|
|
49402
|
+
var FIT_PAD2, TITLE_GAP, ASPECT_MAX, ASPECT_MIN, MIN_MAP_BAND, FALLBACK_ASPECT, REF;
|
|
49403
|
+
var init_dimensions = __esm({
|
|
49404
|
+
"src/map/dimensions.ts"() {
|
|
49405
|
+
"use strict";
|
|
49406
|
+
init_title_constants();
|
|
49407
|
+
init_layout15();
|
|
49408
|
+
FIT_PAD2 = 24;
|
|
49409
|
+
TITLE_GAP = 16;
|
|
49410
|
+
ASPECT_MAX = 3;
|
|
49411
|
+
ASPECT_MIN = 0.9;
|
|
49412
|
+
MIN_MAP_BAND = 200;
|
|
49413
|
+
FALLBACK_ASPECT = 1.5;
|
|
49414
|
+
REF = 1e3;
|
|
49415
|
+
}
|
|
49416
|
+
});
|
|
49417
|
+
|
|
47910
49418
|
// src/map/load-data.ts
|
|
47911
49419
|
var load_data_exports = {};
|
|
47912
49420
|
__export(load_data_exports, {
|
|
@@ -47965,12 +49473,17 @@ function loadMapData() {
|
|
|
47965
49473
|
mountainRanges,
|
|
47966
49474
|
naLand,
|
|
47967
49475
|
naLakes,
|
|
49476
|
+
waterBodies,
|
|
47968
49477
|
gazetteer
|
|
47969
49478
|
] = await Promise.all([
|
|
49479
|
+
// worldCoarse (110m) is LOAD-BEARING but NOT a render source: the world
|
|
49480
|
+
// basemap renders from worldDetail (50m) at all scales (resolver pins
|
|
49481
|
+
// basemaps.world = 'detail'). Coarse stays as the authoritative region
|
|
49482
|
+
// name index + dominant-landmass bbox source in resolver.ts. Do not drop it.
|
|
47970
49483
|
readJson(nb, dir, FILES.worldCoarse),
|
|
47971
49484
|
readJson(nb, dir, FILES.worldDetail),
|
|
47972
49485
|
readJson(nb, dir, FILES.usStates),
|
|
47973
|
-
// Lakes/rivers/mountain/NA assets are optional — older bundles may predate them.
|
|
49486
|
+
// Lakes/rivers/mountain/NA/water assets are optional — older bundles may predate them.
|
|
47974
49487
|
readJson(nb, dir, FILES.lakes).catch(() => void 0),
|
|
47975
49488
|
readJson(nb, dir, FILES.rivers).catch(() => void 0),
|
|
47976
49489
|
readJson(nb, dir, FILES.mountainRanges).catch(
|
|
@@ -47978,6 +49491,7 @@ function loadMapData() {
|
|
|
47978
49491
|
),
|
|
47979
49492
|
readJson(nb, dir, FILES.naLand).catch(() => void 0),
|
|
47980
49493
|
readJson(nb, dir, FILES.naLakes).catch(() => void 0),
|
|
49494
|
+
readJson(nb, dir, FILES.waterBodies).catch(() => void 0),
|
|
47981
49495
|
readJson(nb, dir, FILES.gazetteer)
|
|
47982
49496
|
]);
|
|
47983
49497
|
return validate({
|
|
@@ -47989,7 +49503,8 @@ function loadMapData() {
|
|
|
47989
49503
|
...rivers && { rivers },
|
|
47990
49504
|
...mountainRanges && { mountainRanges },
|
|
47991
49505
|
...naLand && { naLand },
|
|
47992
|
-
...naLakes && { naLakes }
|
|
49506
|
+
...naLakes && { naLakes },
|
|
49507
|
+
...waterBodies && { waterBodies }
|
|
47993
49508
|
});
|
|
47994
49509
|
})().catch((e) => {
|
|
47995
49510
|
cache = void 0;
|
|
@@ -48010,6 +49525,7 @@ var init_load_data = __esm({
|
|
|
48010
49525
|
mountainRanges: "mountain-ranges.json",
|
|
48011
49526
|
naLand: "na-land.json",
|
|
48012
49527
|
naLakes: "na-lakes.json",
|
|
49528
|
+
waterBodies: "water-bodies.json",
|
|
48013
49529
|
gazetteer: "gazetteer.json"
|
|
48014
49530
|
};
|
|
48015
49531
|
CANDIDATE_DIRS = [
|
|
@@ -50023,8 +51539,8 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
|
|
|
50023
51539
|
const lines = splitParticipantLabel(p.label, LABEL_MAX_CHARS);
|
|
50024
51540
|
if (lines.length === 0) continue;
|
|
50025
51541
|
const widest = Math.max(...lines.map((l) => l.length));
|
|
50026
|
-
const
|
|
50027
|
-
uniformBoxWidth = Math.max(uniformBoxWidth,
|
|
51542
|
+
const labelWidth2 = widest * LABEL_CHAR_WIDTH + 10;
|
|
51543
|
+
uniformBoxWidth = Math.max(uniformBoxWidth, labelWidth2);
|
|
50028
51544
|
}
|
|
50029
51545
|
uniformBoxWidth = Math.min(MAX_BOX_WIDTH, uniformBoxWidth);
|
|
50030
51546
|
const effectiveGap = Math.max(PARTICIPANT_GAP, uniformBoxWidth + 30);
|
|
@@ -52723,15 +54239,15 @@ function renderArcDiagram(container, parsed, palette, _isDark, onClickItem, expo
|
|
|
52723
54239
|
textColor,
|
|
52724
54240
|
onClickItem
|
|
52725
54241
|
);
|
|
52726
|
-
const
|
|
52727
|
-
for (const node of nodes)
|
|
54242
|
+
const neighbors2 = /* @__PURE__ */ new Map();
|
|
54243
|
+
for (const node of nodes) neighbors2.set(node, /* @__PURE__ */ new Set());
|
|
52728
54244
|
for (const link of links) {
|
|
52729
|
-
|
|
52730
|
-
|
|
54245
|
+
neighbors2.get(link.source).add(link.target);
|
|
54246
|
+
neighbors2.get(link.target).add(link.source);
|
|
52731
54247
|
}
|
|
52732
54248
|
const FADE_OPACITY3 = 0.1;
|
|
52733
54249
|
function handleMouseEnter(hovered) {
|
|
52734
|
-
const connected =
|
|
54250
|
+
const connected = neighbors2.get(hovered);
|
|
52735
54251
|
g.selectAll(".arc-link").each(function() {
|
|
52736
54252
|
const el = d3Selection23.select(this);
|
|
52737
54253
|
const src = el.attr("data-source");
|
|
@@ -54722,7 +56238,7 @@ function renderVenn(container, parsed, palette, _isDark, onClickItem, exportDims
|
|
|
54722
56238
|
8,
|
|
54723
56239
|
Math.floor(OVERLAP_WRAP_TARGET_W / OVERLAP_CH_W)
|
|
54724
56240
|
);
|
|
54725
|
-
function
|
|
56241
|
+
function wrapLabel3(text, maxChars) {
|
|
54726
56242
|
const words = text.split(/\s+/).filter(Boolean);
|
|
54727
56243
|
const lines = [];
|
|
54728
56244
|
let cur = "";
|
|
@@ -54768,7 +56284,7 @@ function renderVenn(container, parsed, palette, _isDark, onClickItem, exportDims
|
|
|
54768
56284
|
if (!ov.label) continue;
|
|
54769
56285
|
const idxs = ov.sets.map((s) => vennSets.findIndex((vs) => vs.name === s));
|
|
54770
56286
|
if (idxs.some((idx) => idx < 0)) continue;
|
|
54771
|
-
const lines =
|
|
56287
|
+
const lines = wrapLabel3(ov.label, MAX_WRAP_CHARS);
|
|
54772
56288
|
wrappedOverlapLabels.set(ov, lines);
|
|
54773
56289
|
const dir = predictOverlapDirRaw(idxs);
|
|
54774
56290
|
const longest = lines.reduce((m, l) => Math.max(m, l.length), 0);
|
|
@@ -56206,6 +57722,7 @@ async function renderForExport(content, theme, palette, viewState, options) {
|
|
|
56206
57722
|
const { parseMap: parseMap2 } = await Promise.resolve().then(() => (init_parser12(), parser_exports11));
|
|
56207
57723
|
const { resolveMap: resolveMap2 } = await Promise.resolve().then(() => (init_resolver2(), resolver_exports));
|
|
56208
57724
|
const { renderMapForExport: renderMapForExport2 } = await Promise.resolve().then(() => (init_renderer16(), renderer_exports16));
|
|
57725
|
+
const { mapExportDimensions: mapExportDimensions2 } = await Promise.resolve().then(() => (init_dimensions(), dimensions_exports));
|
|
56209
57726
|
const effectivePalette2 = await resolveExportPalette(theme, palette);
|
|
56210
57727
|
const mapParsed = parseMap2(content);
|
|
56211
57728
|
let mapData = options?.mapData;
|
|
@@ -56218,14 +57735,15 @@ async function renderForExport(content, theme, palette, viewState, options) {
|
|
|
56218
57735
|
}
|
|
56219
57736
|
}
|
|
56220
57737
|
const mapResolved = resolveMap2(mapParsed, mapData);
|
|
56221
|
-
const
|
|
57738
|
+
const dims2 = mapExportDimensions2(mapResolved, mapData, EXPORT_WIDTH);
|
|
57739
|
+
const container2 = createExportContainer(dims2.width, dims2.height);
|
|
56222
57740
|
renderMapForExport2(
|
|
56223
57741
|
container2,
|
|
56224
57742
|
mapResolved,
|
|
56225
57743
|
mapData,
|
|
56226
57744
|
effectivePalette2,
|
|
56227
57745
|
theme === "dark",
|
|
56228
|
-
|
|
57746
|
+
dims2
|
|
56229
57747
|
);
|
|
56230
57748
|
return finalizeSvgExport(container2, theme, effectivePalette2);
|
|
56231
57749
|
}
|
|
@@ -57072,7 +58590,8 @@ async function render(content, options) {
|
|
|
57072
58590
|
...options?.c4Container !== void 0 && {
|
|
57073
58591
|
c4Container: options.c4Container
|
|
57074
58592
|
},
|
|
57075
|
-
...options?.tagGroup !== void 0 && { tagGroup: options.tagGroup }
|
|
58593
|
+
...options?.tagGroup !== void 0 && { tagGroup: options.tagGroup },
|
|
58594
|
+
...options?.mapData !== void 0 && { mapData: options.mapData }
|
|
57076
58595
|
});
|
|
57077
58596
|
if (chartType === "map") {
|
|
57078
58597
|
try {
|
|
@@ -57083,7 +58602,7 @@ async function render(content, options) {
|
|
|
57083
58602
|
Promise.resolve().then(() => (init_load_data(), load_data_exports))
|
|
57084
58603
|
]
|
|
57085
58604
|
);
|
|
57086
|
-
const data = await loadMapData2();
|
|
58605
|
+
const data = options?.mapData ?? await loadMapData2();
|
|
57087
58606
|
diagnostics = [...resolveMap2(parseMap2(content), data).diagnostics];
|
|
57088
58607
|
} catch {
|
|
57089
58608
|
}
|
|
@@ -57322,8 +58841,8 @@ function detectCycles(parsed) {
|
|
|
57322
58841
|
const parent = /* @__PURE__ */ new Map();
|
|
57323
58842
|
function dfs(nodeId3) {
|
|
57324
58843
|
color.set(nodeId3, 1);
|
|
57325
|
-
const
|
|
57326
|
-
for (const next of
|
|
58844
|
+
const neighbors2 = adj.get(nodeId3) ?? [];
|
|
58845
|
+
for (const next of neighbors2) {
|
|
57327
58846
|
const c = color.get(next) ?? 0;
|
|
57328
58847
|
if (c === 1) {
|
|
57329
58848
|
const lineKey = `${nodeId3}->${next}`;
|
|
@@ -57508,6 +59027,7 @@ init_resolver2();
|
|
|
57508
59027
|
init_load_data();
|
|
57509
59028
|
init_layout15();
|
|
57510
59029
|
init_renderer16();
|
|
59030
|
+
init_dimensions();
|
|
57511
59031
|
|
|
57512
59032
|
// src/map/geo-query.ts
|
|
57513
59033
|
init_parser12();
|
|
@@ -57581,7 +59101,9 @@ function nearestCity(lonLat, gazetteer) {
|
|
|
57581
59101
|
name: c[4],
|
|
57582
59102
|
iso: c[2],
|
|
57583
59103
|
...c[5] !== void 0 && { sub: c[5] },
|
|
57584
|
-
distanceKm: best.dist
|
|
59104
|
+
distanceKm: best.dist,
|
|
59105
|
+
lat: c[0],
|
|
59106
|
+
lon: c[1]
|
|
57585
59107
|
};
|
|
57586
59108
|
}
|
|
57587
59109
|
function roundCoord(n) {
|
|
@@ -57660,7 +59182,7 @@ function createMapGeoQuery(opts) {
|
|
|
57660
59182
|
}
|
|
57661
59183
|
return out;
|
|
57662
59184
|
};
|
|
57663
|
-
return { invert, project, locate, cities };
|
|
59185
|
+
return { invert, project, locate, cities, diagnostics: layout.diagnostics };
|
|
57664
59186
|
}
|
|
57665
59187
|
|
|
57666
59188
|
// src/map/completion.ts
|
|
@@ -58386,9 +59908,12 @@ var GLOBAL_DIRECTIVES = {
|
|
|
58386
59908
|
"gruvbox",
|
|
58387
59909
|
"tokyo-night",
|
|
58388
59910
|
"one-dark",
|
|
58389
|
-
"bold",
|
|
58390
59911
|
"dracula",
|
|
58391
|
-
"monokai"
|
|
59912
|
+
"monokai",
|
|
59913
|
+
"atlas",
|
|
59914
|
+
"blueprint",
|
|
59915
|
+
"slate",
|
|
59916
|
+
"tidewater"
|
|
58392
59917
|
]
|
|
58393
59918
|
},
|
|
58394
59919
|
theme: {
|
|
@@ -58784,18 +60309,12 @@ var COMPLETION_REGISTRY = /* @__PURE__ */ new Map([
|
|
|
58784
60309
|
],
|
|
58785
60310
|
[
|
|
58786
60311
|
"map",
|
|
58787
|
-
// Geographic map directives (§24B.2/.7).
|
|
58788
|
-
//
|
|
58789
|
-
//
|
|
60312
|
+
// Geographic map directives (§24B.2/.7). Cosmetics are ON by default — the
|
|
60313
|
+
// only switches are bare `no-*` opt-outs, surfaced proactively so a
|
|
60314
|
+
// zero-config map still hints at what can be turned off. `poi`/`route` are
|
|
60315
|
+
// content keywords, not directives; metadata keys (value/label/style) live
|
|
60316
|
+
// in the reserved-key registry.
|
|
58790
60317
|
withGlobals({
|
|
58791
|
-
region: {
|
|
58792
|
-
description: "Basemap: us-states (force US state mesh + scoping) | world (inert \u2014 already the default)",
|
|
58793
|
-
values: ["us-states", "world"]
|
|
58794
|
-
},
|
|
58795
|
-
projection: {
|
|
58796
|
-
description: "Override the auto projection",
|
|
58797
|
-
values: ["equirectangular", "natural-earth", "albers-usa", "mercator"]
|
|
58798
|
-
},
|
|
58799
60318
|
"region-metric": { description: "Label for the region value ramp" },
|
|
58800
60319
|
"poi-metric": {
|
|
58801
60320
|
description: "Label for the POI value (marker size) channel"
|
|
@@ -58803,21 +60322,30 @@ var COMPLETION_REGISTRY = /* @__PURE__ */ new Map([
|
|
|
58803
60322
|
"flow-metric": {
|
|
58804
60323
|
description: "Label for the edge/leg value (thickness) channel"
|
|
58805
60324
|
},
|
|
58806
|
-
|
|
58807
|
-
|
|
58808
|
-
description: "Subdivision name labels",
|
|
58809
|
-
values: ["full", "abbrev", "off"]
|
|
60325
|
+
locale: {
|
|
60326
|
+
description: "Default country/state for bare place names, e.g. locale US-GA"
|
|
58810
60327
|
},
|
|
58811
|
-
"
|
|
58812
|
-
description: "
|
|
58813
|
-
values: ["off", "auto", "all"]
|
|
60328
|
+
"active-tag": {
|
|
60329
|
+
description: "Which tag group leads when several are present"
|
|
58814
60330
|
},
|
|
58815
|
-
|
|
58816
|
-
"default-state": { description: "ISO subdivision scope" },
|
|
60331
|
+
caption: { description: "Caption line (data-source attribution)" },
|
|
58817
60332
|
"no-legend": { description: "Suppress the legend" },
|
|
58818
|
-
|
|
58819
|
-
|
|
58820
|
-
|
|
60333
|
+
"no-coastline": {
|
|
60334
|
+
description: "Turn off coastal water-lines (on by default)"
|
|
60335
|
+
},
|
|
60336
|
+
"no-relief": {
|
|
60337
|
+
description: "Turn off mountain-range relief shading (on by default)"
|
|
60338
|
+
},
|
|
60339
|
+
"no-context-labels": {
|
|
60340
|
+
description: "Turn off orientation labels for water + nearby countries"
|
|
60341
|
+
},
|
|
60342
|
+
"no-region-labels": {
|
|
60343
|
+
description: "Turn off subdivision name labels (on by default)"
|
|
60344
|
+
},
|
|
60345
|
+
"no-poi-labels": { description: "Turn off POI labels (on by default)" },
|
|
60346
|
+
"no-colorize": {
|
|
60347
|
+
description: "Force plain green-land reference dress (regions are auto-coloured by default)"
|
|
60348
|
+
}
|
|
58821
60349
|
})
|
|
58822
60350
|
]
|
|
58823
60351
|
]);
|
|
@@ -60292,7 +61820,8 @@ export {
|
|
|
60292
61820
|
applyCollapseProjection,
|
|
60293
61821
|
applyGroupOrdering,
|
|
60294
61822
|
applyPositionOverrides,
|
|
60295
|
-
|
|
61823
|
+
atlasPalette,
|
|
61824
|
+
blueprintPalette,
|
|
60296
61825
|
buildExtendedChartOption,
|
|
60297
61826
|
buildNoteMessageMap,
|
|
60298
61827
|
buildRenderSequence,
|
|
@@ -60395,6 +61924,8 @@ export {
|
|
|
60395
61924
|
looksLikeState,
|
|
60396
61925
|
makeDgmoError,
|
|
60397
61926
|
mapBackgroundColor,
|
|
61927
|
+
mapContentAspect,
|
|
61928
|
+
mapExportDimensions,
|
|
60398
61929
|
mapNeutralLandColor,
|
|
60399
61930
|
matchesContiguously,
|
|
60400
61931
|
measurePertAnalysisBlock,
|
|
@@ -60530,9 +62061,11 @@ export {
|
|
|
60530
62061
|
shapeFill,
|
|
60531
62062
|
simulateCanonical,
|
|
60532
62063
|
simulateFast,
|
|
62064
|
+
slatePalette,
|
|
60533
62065
|
solarizedPalette,
|
|
60534
62066
|
suggestChartTypes,
|
|
60535
62067
|
themes,
|
|
62068
|
+
tidewaterPalette,
|
|
60536
62069
|
tint,
|
|
60537
62070
|
tokyoNightPalette,
|
|
60538
62071
|
transformLine,
|