@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.cjs
CHANGED
|
@@ -373,18 +373,18 @@ function computeQuadrantPointLabels(points, chartBounds, obstacles, pointRadius,
|
|
|
373
373
|
const results = [];
|
|
374
374
|
for (let i = 0; i < points.length; i++) {
|
|
375
375
|
const pt = points[i];
|
|
376
|
-
const
|
|
376
|
+
const labelWidth2 = pt.label.length * fontSize * CHAR_WIDTH_RATIO + 8;
|
|
377
377
|
let best = null;
|
|
378
378
|
const directions = [
|
|
379
379
|
{
|
|
380
380
|
// Above
|
|
381
381
|
gen: (offset) => {
|
|
382
|
-
const lx = pt.cx -
|
|
382
|
+
const lx = pt.cx - labelWidth2 / 2;
|
|
383
383
|
const ly = pt.cy - offset - labelHeight;
|
|
384
|
-
if (ly < chartBounds.top || lx < chartBounds.left || lx +
|
|
384
|
+
if (ly < chartBounds.top || lx < chartBounds.left || lx + labelWidth2 > chartBounds.right)
|
|
385
385
|
return null;
|
|
386
386
|
return {
|
|
387
|
-
rect: { x: lx, y: ly, w:
|
|
387
|
+
rect: { x: lx, y: ly, w: labelWidth2, h: labelHeight },
|
|
388
388
|
textX: pt.cx,
|
|
389
389
|
textY: ly + labelHeight / 2,
|
|
390
390
|
anchor: "middle"
|
|
@@ -394,12 +394,12 @@ function computeQuadrantPointLabels(points, chartBounds, obstacles, pointRadius,
|
|
|
394
394
|
{
|
|
395
395
|
// Below
|
|
396
396
|
gen: (offset) => {
|
|
397
|
-
const lx = pt.cx -
|
|
397
|
+
const lx = pt.cx - labelWidth2 / 2;
|
|
398
398
|
const ly = pt.cy + offset;
|
|
399
|
-
if (ly + labelHeight > chartBounds.bottom || lx < chartBounds.left || lx +
|
|
399
|
+
if (ly + labelHeight > chartBounds.bottom || lx < chartBounds.left || lx + labelWidth2 > chartBounds.right)
|
|
400
400
|
return null;
|
|
401
401
|
return {
|
|
402
|
-
rect: { x: lx, y: ly, w:
|
|
402
|
+
rect: { x: lx, y: ly, w: labelWidth2, h: labelHeight },
|
|
403
403
|
textX: pt.cx,
|
|
404
404
|
textY: ly + labelHeight / 2,
|
|
405
405
|
anchor: "middle"
|
|
@@ -411,10 +411,10 @@ function computeQuadrantPointLabels(points, chartBounds, obstacles, pointRadius,
|
|
|
411
411
|
gen: (offset) => {
|
|
412
412
|
const lx = pt.cx + offset;
|
|
413
413
|
const ly = pt.cy - labelHeight / 2;
|
|
414
|
-
if (lx +
|
|
414
|
+
if (lx + labelWidth2 > chartBounds.right || ly < chartBounds.top || ly + labelHeight > chartBounds.bottom)
|
|
415
415
|
return null;
|
|
416
416
|
return {
|
|
417
|
-
rect: { x: lx, y: ly, w:
|
|
417
|
+
rect: { x: lx, y: ly, w: labelWidth2, h: labelHeight },
|
|
418
418
|
textX: lx,
|
|
419
419
|
textY: pt.cy,
|
|
420
420
|
anchor: "start"
|
|
@@ -424,13 +424,13 @@ function computeQuadrantPointLabels(points, chartBounds, obstacles, pointRadius,
|
|
|
424
424
|
{
|
|
425
425
|
// Left
|
|
426
426
|
gen: (offset) => {
|
|
427
|
-
const lx = pt.cx - offset -
|
|
427
|
+
const lx = pt.cx - offset - labelWidth2;
|
|
428
428
|
const ly = pt.cy - labelHeight / 2;
|
|
429
429
|
if (lx < chartBounds.left || ly < chartBounds.top || ly + labelHeight > chartBounds.bottom)
|
|
430
430
|
return null;
|
|
431
431
|
return {
|
|
432
|
-
rect: { x: lx, y: ly, w:
|
|
433
|
-
textX: lx +
|
|
432
|
+
rect: { x: lx, y: ly, w: labelWidth2, h: labelHeight },
|
|
433
|
+
textX: lx + labelWidth2,
|
|
434
434
|
textY: pt.cy,
|
|
435
435
|
anchor: "end"
|
|
436
436
|
};
|
|
@@ -480,10 +480,10 @@ function computeQuadrantPointLabels(points, chartBounds, obstacles, pointRadius,
|
|
|
480
480
|
}
|
|
481
481
|
}
|
|
482
482
|
if (!best) {
|
|
483
|
-
const lx = pt.cx -
|
|
483
|
+
const lx = pt.cx - labelWidth2 / 2;
|
|
484
484
|
const ly = pt.cy - minGap - labelHeight;
|
|
485
485
|
best = {
|
|
486
|
-
rect: { x: lx, y: ly, w:
|
|
486
|
+
rect: { x: lx, y: ly, w: labelWidth2, h: labelHeight },
|
|
487
487
|
textX: pt.cx,
|
|
488
488
|
textY: ly + labelHeight / 2,
|
|
489
489
|
anchor: "middle",
|
|
@@ -860,6 +860,9 @@ var init_reserved_key_registry = __esm({
|
|
|
860
860
|
"value",
|
|
861
861
|
"label",
|
|
862
862
|
"style"
|
|
863
|
+
// `surface:` was removed in the 2026-06-02 defaults-on review — it is no longer
|
|
864
|
+
// a recognized metadata key (the route/edge surface feature was cut; §24B.7).
|
|
865
|
+
// A stray `surface: water` is no longer captured as a reserved key.
|
|
863
866
|
]);
|
|
864
867
|
ORG_REGISTRY = staticRegistry([
|
|
865
868
|
"color",
|
|
@@ -1922,77 +1925,266 @@ function getSegmentColors(palette, count) {
|
|
|
1922
1925
|
(_, i) => hslToHex(Math.round((startHue + i * step) % 360), avgS, avgL)
|
|
1923
1926
|
);
|
|
1924
1927
|
}
|
|
1928
|
+
function politicalTints(palette, count, isDark) {
|
|
1929
|
+
if (count <= 0) return [];
|
|
1930
|
+
const base = isDark ? palette.surface : palette.bg;
|
|
1931
|
+
const c = palette.colors;
|
|
1932
|
+
const swatches = [
|
|
1933
|
+
.../* @__PURE__ */ new Set([
|
|
1934
|
+
c.green,
|
|
1935
|
+
c.yellow,
|
|
1936
|
+
c.orange,
|
|
1937
|
+
c.purple,
|
|
1938
|
+
c.red,
|
|
1939
|
+
c.teal,
|
|
1940
|
+
c.cyan,
|
|
1941
|
+
c.blue
|
|
1942
|
+
])
|
|
1943
|
+
];
|
|
1944
|
+
const bands = isDark ? POLITICAL_TINT_BANDS.dark : POLITICAL_TINT_BANDS.light;
|
|
1945
|
+
const out = [];
|
|
1946
|
+
for (const pct of bands) {
|
|
1947
|
+
if (out.length >= count) break;
|
|
1948
|
+
for (const s of swatches) out.push(mix(s, base, pct));
|
|
1949
|
+
}
|
|
1950
|
+
return out.slice(0, count);
|
|
1951
|
+
}
|
|
1952
|
+
var POLITICAL_TINT_BANDS;
|
|
1925
1953
|
var init_color_utils = __esm({
|
|
1926
1954
|
"src/palettes/color-utils.ts"() {
|
|
1927
1955
|
"use strict";
|
|
1956
|
+
POLITICAL_TINT_BANDS = {
|
|
1957
|
+
light: [32, 48, 64, 80],
|
|
1958
|
+
dark: [44, 58, 72, 86]
|
|
1959
|
+
};
|
|
1928
1960
|
}
|
|
1929
1961
|
});
|
|
1930
1962
|
|
|
1931
|
-
// src/palettes/
|
|
1932
|
-
var
|
|
1933
|
-
var
|
|
1934
|
-
"src/palettes/
|
|
1963
|
+
// src/palettes/atlas.ts
|
|
1964
|
+
var atlasPalette;
|
|
1965
|
+
var init_atlas = __esm({
|
|
1966
|
+
"src/palettes/atlas.ts"() {
|
|
1935
1967
|
"use strict";
|
|
1936
1968
|
init_registry();
|
|
1937
|
-
|
|
1938
|
-
id: "
|
|
1939
|
-
name: "
|
|
1969
|
+
atlasPalette = {
|
|
1970
|
+
id: "atlas",
|
|
1971
|
+
name: "Atlas",
|
|
1940
1972
|
light: {
|
|
1941
|
-
bg: "#
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1973
|
+
bg: "#f3ead3",
|
|
1974
|
+
// warm manila / parchment
|
|
1975
|
+
surface: "#ece0c0",
|
|
1976
|
+
// deeper paper (cards, panels)
|
|
1977
|
+
overlay: "#e8dab8",
|
|
1978
|
+
// popovers, dropdowns
|
|
1979
|
+
border: "#bcaa86",
|
|
1980
|
+
// muted sepia rule line
|
|
1981
|
+
text: "#463a26",
|
|
1982
|
+
// aged sepia-brown ink
|
|
1983
|
+
textMuted: "#7a6a4f",
|
|
1984
|
+
// faded annotation ink
|
|
1985
|
+
textOnFillLight: "#f7f1de",
|
|
1986
|
+
// parchment (light text on dark fills)
|
|
1987
|
+
textOnFillDark: "#3a2e1c",
|
|
1988
|
+
// deep ink (dark text on light fills)
|
|
1989
|
+
primary: "#5b7a99",
|
|
1990
|
+
// pull-down map ocean (steel-blue)
|
|
1991
|
+
secondary: "#7e9a6f",
|
|
1992
|
+
// lowland sage / celadon
|
|
1993
|
+
accent: "#b07f7c",
|
|
1994
|
+
// dusty rose
|
|
1995
|
+
destructive: "#b25a45",
|
|
1996
|
+
// brick / terracotta
|
|
1953
1997
|
colors: {
|
|
1954
|
-
red: "#
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1998
|
+
red: "#bf6a52",
|
|
1999
|
+
// terracotta brick
|
|
2000
|
+
orange: "#cf9a5c",
|
|
2001
|
+
// map tan / ochre
|
|
2002
|
+
yellow: "#cdb35e",
|
|
2003
|
+
// straw / muted lemon
|
|
2004
|
+
green: "#7e9a6f",
|
|
2005
|
+
// sage / celadon lowland
|
|
2006
|
+
blue: "#5b7a99",
|
|
2007
|
+
// steel-blue ocean
|
|
2008
|
+
purple: "#9a7fa6",
|
|
2009
|
+
// dusty lilac / mauve
|
|
2010
|
+
teal: "#6fa094",
|
|
2011
|
+
// muted seafoam
|
|
2012
|
+
cyan: "#79a7b5",
|
|
2013
|
+
// shallow-water blue
|
|
2014
|
+
gray: "#8a7d68",
|
|
2015
|
+
// warm taupe
|
|
2016
|
+
black: "#463a26",
|
|
2017
|
+
// ink
|
|
2018
|
+
white: "#ece0c0"
|
|
2019
|
+
// paper
|
|
1965
2020
|
}
|
|
1966
2021
|
},
|
|
1967
2022
|
dark: {
|
|
1968
|
-
bg: "#
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
2023
|
+
bg: "#1e2a33",
|
|
2024
|
+
// deep map ocean (night globe)
|
|
2025
|
+
surface: "#27353f",
|
|
2026
|
+
// raised ocean
|
|
2027
|
+
overlay: "#2e3d48",
|
|
2028
|
+
// popovers, dropdowns
|
|
2029
|
+
border: "#3d4f5c",
|
|
2030
|
+
// depth-contour line
|
|
2031
|
+
text: "#e8dcc0",
|
|
2032
|
+
// parchment ink, inverted
|
|
2033
|
+
textMuted: "#a89a7d",
|
|
2034
|
+
// faded label
|
|
2035
|
+
textOnFillLight: "#f7f1de",
|
|
2036
|
+
// parchment
|
|
2037
|
+
textOnFillDark: "#1a242c",
|
|
2038
|
+
// deep ocean ink
|
|
2039
|
+
primary: "#7ba0bf",
|
|
2040
|
+
// brighter ocean
|
|
2041
|
+
secondary: "#9bb588",
|
|
2042
|
+
// sage, lifted
|
|
2043
|
+
accent: "#cf9a96",
|
|
2044
|
+
// dusty rose, lifted
|
|
2045
|
+
destructive: "#c9745c",
|
|
2046
|
+
// brick, lifted
|
|
2047
|
+
colors: {
|
|
2048
|
+
red: "#cf7a60",
|
|
2049
|
+
// terracotta
|
|
2050
|
+
orange: "#d9a96a",
|
|
2051
|
+
// tan / ochre
|
|
2052
|
+
yellow: "#d8c074",
|
|
2053
|
+
// straw
|
|
2054
|
+
green: "#9bb588",
|
|
2055
|
+
// sage lowland
|
|
2056
|
+
blue: "#7ba0bf",
|
|
2057
|
+
// ocean
|
|
2058
|
+
purple: "#b59ac0",
|
|
2059
|
+
// lilac / mauve
|
|
2060
|
+
teal: "#85b3a6",
|
|
2061
|
+
// seafoam
|
|
2062
|
+
cyan: "#92bccb",
|
|
2063
|
+
// shallow-water blue
|
|
2064
|
+
gray: "#9a8d76",
|
|
2065
|
+
// warm taupe
|
|
2066
|
+
black: "#27353f",
|
|
2067
|
+
// raised ocean
|
|
2068
|
+
white: "#e8dcc0"
|
|
2069
|
+
// parchment
|
|
2070
|
+
}
|
|
2071
|
+
}
|
|
2072
|
+
};
|
|
2073
|
+
registerPalette(atlasPalette);
|
|
2074
|
+
}
|
|
2075
|
+
});
|
|
2076
|
+
|
|
2077
|
+
// src/palettes/blueprint.ts
|
|
2078
|
+
var blueprintPalette;
|
|
2079
|
+
var init_blueprint = __esm({
|
|
2080
|
+
"src/palettes/blueprint.ts"() {
|
|
2081
|
+
"use strict";
|
|
2082
|
+
init_registry();
|
|
2083
|
+
blueprintPalette = {
|
|
2084
|
+
id: "blueprint",
|
|
2085
|
+
name: "Blueprint",
|
|
2086
|
+
light: {
|
|
2087
|
+
bg: "#f4f8fb",
|
|
2088
|
+
// pale drafting white (faint cyan)
|
|
2089
|
+
surface: "#e6eef4",
|
|
2090
|
+
// drafting panel
|
|
2091
|
+
overlay: "#dde9f1",
|
|
2092
|
+
// popovers, dropdowns
|
|
2093
|
+
border: "#aac3d6",
|
|
2094
|
+
// pale blue grid line
|
|
2095
|
+
text: "#123a5e",
|
|
2096
|
+
// blueprint navy ink
|
|
2097
|
+
textMuted: "#4f7390",
|
|
2098
|
+
// faint draft note
|
|
2099
|
+
textOnFillLight: "#f4f8fb",
|
|
2100
|
+
// drafting white
|
|
2101
|
+
textOnFillDark: "#0c2f4d",
|
|
2102
|
+
// deep blueprint navy
|
|
2103
|
+
primary: "#1f5e8c",
|
|
2104
|
+
// blueprint blue
|
|
2105
|
+
secondary: "#5b7d96",
|
|
2106
|
+
// steel
|
|
2107
|
+
accent: "#b08a3e",
|
|
2108
|
+
// draftsman's ochre highlight
|
|
2109
|
+
destructive: "#c0504d",
|
|
2110
|
+
// correction red
|
|
1980
2111
|
colors: {
|
|
1981
|
-
red: "#
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
2112
|
+
red: "#c25a4e",
|
|
2113
|
+
// correction red
|
|
2114
|
+
orange: "#c2823e",
|
|
2115
|
+
// ochre
|
|
2116
|
+
yellow: "#c2a843",
|
|
2117
|
+
// pencil gold
|
|
2118
|
+
green: "#4f8a6b",
|
|
2119
|
+
// drafting green
|
|
2120
|
+
blue: "#1f5e8c",
|
|
2121
|
+
// blueprint blue
|
|
2122
|
+
purple: "#6f5e96",
|
|
2123
|
+
// indigo pencil
|
|
2124
|
+
teal: "#3a8a8a",
|
|
2125
|
+
// teal
|
|
2126
|
+
cyan: "#3f8fb5",
|
|
2127
|
+
// cyan
|
|
2128
|
+
gray: "#7e8e98",
|
|
2129
|
+
// graphite
|
|
2130
|
+
black: "#123a5e",
|
|
2131
|
+
// navy ink
|
|
2132
|
+
white: "#e6eef4"
|
|
2133
|
+
// panel
|
|
2134
|
+
}
|
|
2135
|
+
},
|
|
2136
|
+
dark: {
|
|
2137
|
+
bg: "#103a5e",
|
|
2138
|
+
// deep blueprint blue (cyanotype ground)
|
|
2139
|
+
surface: "#16466e",
|
|
2140
|
+
// raised sheet
|
|
2141
|
+
overlay: "#1c5180",
|
|
2142
|
+
// popovers, dropdowns
|
|
2143
|
+
border: "#3a6f96",
|
|
2144
|
+
// grid line
|
|
2145
|
+
text: "#eaf2f8",
|
|
2146
|
+
// chalk white
|
|
2147
|
+
textMuted: "#9fc0d6",
|
|
2148
|
+
// faint chalk note
|
|
2149
|
+
textOnFillLight: "#eaf2f8",
|
|
2150
|
+
// chalk white
|
|
2151
|
+
textOnFillDark: "#0c2f4d",
|
|
2152
|
+
// deep blueprint navy
|
|
2153
|
+
primary: "#7fb8d8",
|
|
2154
|
+
// chalk cyan
|
|
2155
|
+
secondary: "#9fb8c8",
|
|
2156
|
+
// pale steel
|
|
2157
|
+
accent: "#d8c27a",
|
|
2158
|
+
// chalk amber
|
|
2159
|
+
destructive: "#e08a7a",
|
|
2160
|
+
// chalk correction red
|
|
2161
|
+
colors: {
|
|
2162
|
+
red: "#e0907e",
|
|
2163
|
+
// chalk red
|
|
2164
|
+
orange: "#e0ab78",
|
|
2165
|
+
// chalk amber
|
|
2166
|
+
yellow: "#e3d089",
|
|
2167
|
+
// chalk gold
|
|
2168
|
+
green: "#93c79e",
|
|
2169
|
+
// chalk green
|
|
2170
|
+
blue: "#8ec3e0",
|
|
2171
|
+
// chalk cyan-blue
|
|
2172
|
+
purple: "#b6a6d8",
|
|
2173
|
+
// chalk indigo
|
|
2174
|
+
teal: "#84c7c2",
|
|
2175
|
+
// chalk teal
|
|
2176
|
+
cyan: "#9fd6e0",
|
|
2177
|
+
// chalk cyan
|
|
2178
|
+
gray: "#aebecb",
|
|
2179
|
+
// chalk graphite
|
|
2180
|
+
black: "#16466e",
|
|
2181
|
+
// raised sheet
|
|
2182
|
+
white: "#eaf2f8"
|
|
2183
|
+
// chalk white
|
|
1992
2184
|
}
|
|
1993
2185
|
}
|
|
1994
2186
|
};
|
|
1995
|
-
registerPalette(
|
|
2187
|
+
registerPalette(blueprintPalette);
|
|
1996
2188
|
}
|
|
1997
2189
|
});
|
|
1998
2190
|
|
|
@@ -2489,6 +2681,120 @@ var init_rose_pine = __esm({
|
|
|
2489
2681
|
}
|
|
2490
2682
|
});
|
|
2491
2683
|
|
|
2684
|
+
// src/palettes/slate.ts
|
|
2685
|
+
var slatePalette;
|
|
2686
|
+
var init_slate = __esm({
|
|
2687
|
+
"src/palettes/slate.ts"() {
|
|
2688
|
+
"use strict";
|
|
2689
|
+
init_registry();
|
|
2690
|
+
slatePalette = {
|
|
2691
|
+
id: "slate",
|
|
2692
|
+
name: "Slate",
|
|
2693
|
+
light: {
|
|
2694
|
+
bg: "#ffffff",
|
|
2695
|
+
// clean slide white
|
|
2696
|
+
surface: "#f3f5f8",
|
|
2697
|
+
// light cool-gray panel
|
|
2698
|
+
overlay: "#eaeef3",
|
|
2699
|
+
// popovers, dropdowns
|
|
2700
|
+
border: "#d4dae1",
|
|
2701
|
+
// hairline rule
|
|
2702
|
+
text: "#1f2933",
|
|
2703
|
+
// near-black slate (softer than pure black)
|
|
2704
|
+
textMuted: "#5b6672",
|
|
2705
|
+
// secondary label
|
|
2706
|
+
textOnFillLight: "#ffffff",
|
|
2707
|
+
// light text on dark fills
|
|
2708
|
+
textOnFillDark: "#1f2933",
|
|
2709
|
+
// dark text on light fills
|
|
2710
|
+
primary: "#3b6ea5",
|
|
2711
|
+
// confident corporate blue
|
|
2712
|
+
secondary: "#5b6672",
|
|
2713
|
+
// slate gray
|
|
2714
|
+
accent: "#3a9188",
|
|
2715
|
+
// muted teal accent
|
|
2716
|
+
destructive: "#c0504d",
|
|
2717
|
+
// brick red
|
|
2718
|
+
colors: {
|
|
2719
|
+
red: "#c0504d",
|
|
2720
|
+
// brick
|
|
2721
|
+
orange: "#cc7a33",
|
|
2722
|
+
// muted amber
|
|
2723
|
+
yellow: "#c9a227",
|
|
2724
|
+
// gold (not neon)
|
|
2725
|
+
green: "#5b9357",
|
|
2726
|
+
// forest / sage
|
|
2727
|
+
blue: "#3b6ea5",
|
|
2728
|
+
// corporate blue
|
|
2729
|
+
purple: "#7d5ba6",
|
|
2730
|
+
// muted violet
|
|
2731
|
+
teal: "#3a9188",
|
|
2732
|
+
// teal
|
|
2733
|
+
cyan: "#4f96c4",
|
|
2734
|
+
// steel cyan
|
|
2735
|
+
gray: "#7e8a97",
|
|
2736
|
+
// cool gray
|
|
2737
|
+
black: "#1f2933",
|
|
2738
|
+
// slate ink
|
|
2739
|
+
white: "#f3f5f8"
|
|
2740
|
+
// panel
|
|
2741
|
+
}
|
|
2742
|
+
},
|
|
2743
|
+
dark: {
|
|
2744
|
+
bg: "#161b22",
|
|
2745
|
+
// deep slate (keynote dark)
|
|
2746
|
+
surface: "#202833",
|
|
2747
|
+
// raised panel
|
|
2748
|
+
overlay: "#29323e",
|
|
2749
|
+
// popovers, dropdowns
|
|
2750
|
+
border: "#38424f",
|
|
2751
|
+
// divider
|
|
2752
|
+
text: "#e6eaef",
|
|
2753
|
+
// off-white
|
|
2754
|
+
textMuted: "#9aa5b1",
|
|
2755
|
+
// secondary label
|
|
2756
|
+
textOnFillLight: "#ffffff",
|
|
2757
|
+
// light text on dark fills
|
|
2758
|
+
textOnFillDark: "#161b22",
|
|
2759
|
+
// dark text on light fills
|
|
2760
|
+
primary: "#5b9bd5",
|
|
2761
|
+
// lifted corporate blue
|
|
2762
|
+
secondary: "#8593a3",
|
|
2763
|
+
// slate gray, lifted
|
|
2764
|
+
accent: "#45b3a3",
|
|
2765
|
+
// teal, lifted
|
|
2766
|
+
destructive: "#e07b6e",
|
|
2767
|
+
// brick, lifted
|
|
2768
|
+
colors: {
|
|
2769
|
+
red: "#e07b6e",
|
|
2770
|
+
// brick
|
|
2771
|
+
orange: "#e0975a",
|
|
2772
|
+
// amber
|
|
2773
|
+
yellow: "#d9bd5a",
|
|
2774
|
+
// gold
|
|
2775
|
+
green: "#74b56e",
|
|
2776
|
+
// forest / sage
|
|
2777
|
+
blue: "#5b9bd5",
|
|
2778
|
+
// corporate blue
|
|
2779
|
+
purple: "#a585c9",
|
|
2780
|
+
// violet
|
|
2781
|
+
teal: "#45b3a3",
|
|
2782
|
+
// teal
|
|
2783
|
+
cyan: "#62b0d9",
|
|
2784
|
+
// steel cyan
|
|
2785
|
+
gray: "#95a1ae",
|
|
2786
|
+
// cool gray
|
|
2787
|
+
black: "#202833",
|
|
2788
|
+
// raised panel
|
|
2789
|
+
white: "#e6eaef"
|
|
2790
|
+
// off-white
|
|
2791
|
+
}
|
|
2792
|
+
}
|
|
2793
|
+
};
|
|
2794
|
+
registerPalette(slatePalette);
|
|
2795
|
+
}
|
|
2796
|
+
});
|
|
2797
|
+
|
|
2492
2798
|
// src/palettes/solarized.ts
|
|
2493
2799
|
var solarizedPalette;
|
|
2494
2800
|
var init_solarized = __esm({
|
|
@@ -2584,6 +2890,120 @@ var init_solarized = __esm({
|
|
|
2584
2890
|
}
|
|
2585
2891
|
});
|
|
2586
2892
|
|
|
2893
|
+
// src/palettes/tidewater.ts
|
|
2894
|
+
var tidewaterPalette;
|
|
2895
|
+
var init_tidewater = __esm({
|
|
2896
|
+
"src/palettes/tidewater.ts"() {
|
|
2897
|
+
"use strict";
|
|
2898
|
+
init_registry();
|
|
2899
|
+
tidewaterPalette = {
|
|
2900
|
+
id: "tidewater",
|
|
2901
|
+
name: "Tidewater",
|
|
2902
|
+
light: {
|
|
2903
|
+
bg: "#eceff0",
|
|
2904
|
+
// weathered sea-mist paper
|
|
2905
|
+
surface: "#e0e4e3",
|
|
2906
|
+
// worn deck panel
|
|
2907
|
+
overlay: "#dadfdf",
|
|
2908
|
+
// popovers, dropdowns
|
|
2909
|
+
border: "#a9b2b3",
|
|
2910
|
+
// muted slate rule
|
|
2911
|
+
text: "#18313f",
|
|
2912
|
+
// ship's-log navy ink
|
|
2913
|
+
textMuted: "#51636b",
|
|
2914
|
+
// faded log entry
|
|
2915
|
+
textOnFillLight: "#f3f5f3",
|
|
2916
|
+
// weathered white
|
|
2917
|
+
textOnFillDark: "#162c38",
|
|
2918
|
+
// deep navy
|
|
2919
|
+
primary: "#1f4e6b",
|
|
2920
|
+
// deep-sea navy
|
|
2921
|
+
secondary: "#b08a4f",
|
|
2922
|
+
// rope / manila tan
|
|
2923
|
+
accent: "#c69a3e",
|
|
2924
|
+
// brass
|
|
2925
|
+
destructive: "#c1433a",
|
|
2926
|
+
// signal-flag red
|
|
2927
|
+
colors: {
|
|
2928
|
+
red: "#c1433a",
|
|
2929
|
+
// signal-flag red
|
|
2930
|
+
orange: "#cc7a38",
|
|
2931
|
+
// weathered amber
|
|
2932
|
+
yellow: "#d6bf5a",
|
|
2933
|
+
// brass gold
|
|
2934
|
+
green: "#4f8a6b",
|
|
2935
|
+
// sea-glass green
|
|
2936
|
+
blue: "#1f4e6b",
|
|
2937
|
+
// deep-sea navy
|
|
2938
|
+
purple: "#6a5a8c",
|
|
2939
|
+
// twilight harbor
|
|
2940
|
+
teal: "#3d8c8c",
|
|
2941
|
+
// sea-glass teal
|
|
2942
|
+
cyan: "#4f9bb5",
|
|
2943
|
+
// shallow water
|
|
2944
|
+
gray: "#8a8d86",
|
|
2945
|
+
// driftwood gray
|
|
2946
|
+
black: "#18313f",
|
|
2947
|
+
// navy ink
|
|
2948
|
+
white: "#e0e4e3"
|
|
2949
|
+
// deck panel
|
|
2950
|
+
}
|
|
2951
|
+
},
|
|
2952
|
+
dark: {
|
|
2953
|
+
bg: "#0f2230",
|
|
2954
|
+
// night-harbor deep sea
|
|
2955
|
+
surface: "#16303f",
|
|
2956
|
+
// raised hull
|
|
2957
|
+
overlay: "#1d3a4a",
|
|
2958
|
+
// popovers, dropdowns
|
|
2959
|
+
border: "#2c4856",
|
|
2960
|
+
// rigging line
|
|
2961
|
+
text: "#e6ebe8",
|
|
2962
|
+
// weathered white
|
|
2963
|
+
textMuted: "#9aaab0",
|
|
2964
|
+
// faded label
|
|
2965
|
+
textOnFillLight: "#f3f5f3",
|
|
2966
|
+
// weathered white
|
|
2967
|
+
textOnFillDark: "#0f2230",
|
|
2968
|
+
// deep sea
|
|
2969
|
+
primary: "#4f9bc4",
|
|
2970
|
+
// lifted sea blue
|
|
2971
|
+
secondary: "#c9a46a",
|
|
2972
|
+
// rope tan, lifted
|
|
2973
|
+
accent: "#d9b25a",
|
|
2974
|
+
// brass, lifted
|
|
2975
|
+
destructive: "#e06a5e",
|
|
2976
|
+
// signal red, lifted
|
|
2977
|
+
colors: {
|
|
2978
|
+
red: "#e06a5e",
|
|
2979
|
+
// signal-flag red
|
|
2980
|
+
orange: "#df9a52",
|
|
2981
|
+
// amber
|
|
2982
|
+
yellow: "#e0c662",
|
|
2983
|
+
// brass gold
|
|
2984
|
+
green: "#6fb58c",
|
|
2985
|
+
// sea-glass green
|
|
2986
|
+
blue: "#4f9bc4",
|
|
2987
|
+
// sea blue
|
|
2988
|
+
purple: "#9486bf",
|
|
2989
|
+
// twilight harbor
|
|
2990
|
+
teal: "#5cb0ac",
|
|
2991
|
+
// sea-glass teal
|
|
2992
|
+
cyan: "#62b4cf",
|
|
2993
|
+
// shallow water
|
|
2994
|
+
gray: "#9aa39c",
|
|
2995
|
+
// driftwood gray
|
|
2996
|
+
black: "#16303f",
|
|
2997
|
+
// raised hull
|
|
2998
|
+
white: "#e6ebe8"
|
|
2999
|
+
// weathered white
|
|
3000
|
+
}
|
|
3001
|
+
}
|
|
3002
|
+
};
|
|
3003
|
+
registerPalette(tidewaterPalette);
|
|
3004
|
+
}
|
|
3005
|
+
});
|
|
3006
|
+
|
|
2587
3007
|
// src/palettes/tokyo-night.ts
|
|
2588
3008
|
var tokyoNightPalette;
|
|
2589
3009
|
var init_tokyo_night = __esm({
|
|
@@ -2859,7 +3279,8 @@ var init_monokai = __esm({
|
|
|
2859
3279
|
// src/palettes/index.ts
|
|
2860
3280
|
var palettes_exports = {};
|
|
2861
3281
|
__export(palettes_exports, {
|
|
2862
|
-
|
|
3282
|
+
atlasPalette: () => atlasPalette,
|
|
3283
|
+
blueprintPalette: () => blueprintPalette,
|
|
2863
3284
|
catppuccinPalette: () => catppuccinPalette,
|
|
2864
3285
|
contrastText: () => contrastText,
|
|
2865
3286
|
draculaPalette: () => draculaPalette,
|
|
@@ -2880,7 +3301,9 @@ __export(palettes_exports, {
|
|
|
2880
3301
|
rosePinePalette: () => rosePinePalette,
|
|
2881
3302
|
shade: () => shade,
|
|
2882
3303
|
shapeFill: () => shapeFill,
|
|
3304
|
+
slatePalette: () => slatePalette,
|
|
2883
3305
|
solarizedPalette: () => solarizedPalette,
|
|
3306
|
+
tidewaterPalette: () => tidewaterPalette,
|
|
2884
3307
|
tint: () => tint,
|
|
2885
3308
|
tokyoNightPalette: () => tokyoNightPalette
|
|
2886
3309
|
});
|
|
@@ -2890,17 +3313,21 @@ var init_palettes = __esm({
|
|
|
2890
3313
|
"use strict";
|
|
2891
3314
|
init_registry();
|
|
2892
3315
|
init_color_utils();
|
|
2893
|
-
|
|
3316
|
+
init_atlas();
|
|
3317
|
+
init_blueprint();
|
|
2894
3318
|
init_catppuccin();
|
|
2895
3319
|
init_gruvbox();
|
|
2896
3320
|
init_nord();
|
|
2897
3321
|
init_one_dark();
|
|
2898
3322
|
init_rose_pine();
|
|
3323
|
+
init_slate();
|
|
2899
3324
|
init_solarized();
|
|
3325
|
+
init_tidewater();
|
|
2900
3326
|
init_tokyo_night();
|
|
2901
3327
|
init_dracula();
|
|
2902
3328
|
init_monokai();
|
|
2903
|
-
|
|
3329
|
+
init_atlas();
|
|
3330
|
+
init_blueprint();
|
|
2904
3331
|
init_catppuccin();
|
|
2905
3332
|
init_dracula();
|
|
2906
3333
|
init_gruvbox();
|
|
@@ -2908,9 +3335,15 @@ var init_palettes = __esm({
|
|
|
2908
3335
|
init_nord();
|
|
2909
3336
|
init_one_dark();
|
|
2910
3337
|
init_rose_pine();
|
|
3338
|
+
init_slate();
|
|
2911
3339
|
init_solarized();
|
|
3340
|
+
init_tidewater();
|
|
2912
3341
|
init_tokyo_night();
|
|
2913
3342
|
palettes = {
|
|
3343
|
+
atlas: atlasPalette,
|
|
3344
|
+
blueprint: blueprintPalette,
|
|
3345
|
+
slate: slatePalette,
|
|
3346
|
+
tidewater: tidewaterPalette,
|
|
2914
3347
|
nord: nordPalette,
|
|
2915
3348
|
catppuccin: catppuccinPalette,
|
|
2916
3349
|
solarized: solarizedPalette,
|
|
@@ -2919,8 +3352,7 @@ var init_palettes = __esm({
|
|
|
2919
3352
|
oneDark: oneDarkPalette,
|
|
2920
3353
|
rosePine: rosePinePalette,
|
|
2921
3354
|
dracula: draculaPalette,
|
|
2922
|
-
monokai: monokaiPalette
|
|
2923
|
-
bold: boldPalette
|
|
3355
|
+
monokai: monokaiPalette
|
|
2924
3356
|
};
|
|
2925
3357
|
}
|
|
2926
3358
|
});
|
|
@@ -3430,6 +3862,9 @@ function controlsGroupCapsuleWidth(toggles) {
|
|
|
3430
3862
|
}
|
|
3431
3863
|
return w;
|
|
3432
3864
|
}
|
|
3865
|
+
function isAppHostedControls(config, isExport) {
|
|
3866
|
+
return !isExport && config.controlsHost === "app" && !!config.controlsGroup && config.controlsGroup.toggles.length > 0;
|
|
3867
|
+
}
|
|
3433
3868
|
function buildControlsGroupLayout(config, state) {
|
|
3434
3869
|
const cg = config.controlsGroup;
|
|
3435
3870
|
if (!cg || cg.toggles.length === 0) return void 0;
|
|
@@ -3483,6 +3918,7 @@ function buildControlsGroupLayout(config, state) {
|
|
|
3483
3918
|
function computeLegendLayout(config, state, containerWidth) {
|
|
3484
3919
|
const { groups, controls: configControls, mode } = config;
|
|
3485
3920
|
const isExport = mode === "export";
|
|
3921
|
+
const gated = isAppHostedControls(config, isExport);
|
|
3486
3922
|
const activeGroupName = state.activeGroup?.toLowerCase() ?? null;
|
|
3487
3923
|
if (isExport && !activeGroupName) {
|
|
3488
3924
|
return {
|
|
@@ -3493,7 +3929,7 @@ function computeLegendLayout(config, state, containerWidth) {
|
|
|
3493
3929
|
pills: []
|
|
3494
3930
|
};
|
|
3495
3931
|
}
|
|
3496
|
-
const controlsGroupLayout = isExport ? void 0 : buildControlsGroupLayout(config, state);
|
|
3932
|
+
const controlsGroupLayout = isExport || gated ? void 0 : buildControlsGroupLayout(config, state);
|
|
3497
3933
|
const visibleGroups = config.showEmptyGroups ? groups : groups.filter((g) => g.entries.length > 0 || !!g.gradient);
|
|
3498
3934
|
if (visibleGroups.length === 0 && (!configControls || configControls.length === 0) && !controlsGroupLayout) {
|
|
3499
3935
|
return {
|
|
@@ -8325,8 +8761,8 @@ function computeScatterLabelGraphics(points, chartBounds, fontSize, symbolSize,
|
|
|
8325
8761
|
const pt = points[i];
|
|
8326
8762
|
const ptSize = pt.size ?? symbolSize;
|
|
8327
8763
|
const minGap = ptSize / 2 + 4;
|
|
8328
|
-
const
|
|
8329
|
-
const labelX = pt.px -
|
|
8764
|
+
const labelWidth2 = pt.name.length * fontSize * 0.6 + 8;
|
|
8765
|
+
const labelX = pt.px - labelWidth2 / 2;
|
|
8330
8766
|
let bestLabelY = 0;
|
|
8331
8767
|
let bestOffset = Infinity;
|
|
8332
8768
|
let placed = false;
|
|
@@ -8338,7 +8774,7 @@ function computeScatterLabelGraphics(points, chartBounds, fontSize, symbolSize,
|
|
|
8338
8774
|
const candidate = {
|
|
8339
8775
|
x: labelX,
|
|
8340
8776
|
y: labelY,
|
|
8341
|
-
w:
|
|
8777
|
+
w: labelWidth2,
|
|
8342
8778
|
h: labelHeight
|
|
8343
8779
|
};
|
|
8344
8780
|
let collision = false;
|
|
@@ -8380,7 +8816,7 @@ function computeScatterLabelGraphics(points, chartBounds, fontSize, symbolSize,
|
|
|
8380
8816
|
const labelRect = {
|
|
8381
8817
|
x: labelX,
|
|
8382
8818
|
y: bestLabelY,
|
|
8383
|
-
w:
|
|
8819
|
+
w: labelWidth2,
|
|
8384
8820
|
h: labelHeight
|
|
8385
8821
|
};
|
|
8386
8822
|
placedLabels.push(labelRect);
|
|
@@ -8416,7 +8852,7 @@ function computeScatterLabelGraphics(points, chartBounds, fontSize, symbolSize,
|
|
|
8416
8852
|
shape: {
|
|
8417
8853
|
x: labelX - bgPad,
|
|
8418
8854
|
y: bestLabelY - bgPad,
|
|
8419
|
-
width:
|
|
8855
|
+
width: labelWidth2 + bgPad * 2,
|
|
8420
8856
|
height: labelHeight + bgPad * 2
|
|
8421
8857
|
},
|
|
8422
8858
|
style: { fill: bg },
|
|
@@ -15856,10 +16292,6 @@ function parseMap(content) {
|
|
|
15856
16292
|
handleTag(trimmed, lineNumber);
|
|
15857
16293
|
continue;
|
|
15858
16294
|
}
|
|
15859
|
-
if ((firstWord === "muted" || firstWord === "natural") && trimmed === firstWord) {
|
|
15860
|
-
handleDirective(firstWord, "", lineNumber);
|
|
15861
|
-
continue;
|
|
15862
|
-
}
|
|
15863
16295
|
if (DIRECTIVE_SET.has(firstWord) && !trimmed.slice(firstWord.length).trimStart().startsWith(":")) {
|
|
15864
16296
|
handleDirective(
|
|
15865
16297
|
firstWord,
|
|
@@ -15906,24 +16338,6 @@ function parseMap(content) {
|
|
|
15906
16338
|
pushWarning(line12, `Duplicate directive "${key}" \u2014 last value wins.`);
|
|
15907
16339
|
};
|
|
15908
16340
|
switch (key) {
|
|
15909
|
-
case "region":
|
|
15910
|
-
dup(d.region);
|
|
15911
|
-
d.region = value;
|
|
15912
|
-
break;
|
|
15913
|
-
case "projection":
|
|
15914
|
-
dup(d.projection);
|
|
15915
|
-
if (value && ![
|
|
15916
|
-
"equirectangular",
|
|
15917
|
-
"natural-earth",
|
|
15918
|
-
"albers-usa",
|
|
15919
|
-
"mercator"
|
|
15920
|
-
].includes(value))
|
|
15921
|
-
pushWarning(
|
|
15922
|
-
line12,
|
|
15923
|
-
`Unknown projection "${value}" (expected equirectangular | natural-earth | albers-usa | mercator).`
|
|
15924
|
-
);
|
|
15925
|
-
d.projection = value;
|
|
15926
|
-
break;
|
|
15927
16341
|
case "region-metric": {
|
|
15928
16342
|
dup(d.regionMetric);
|
|
15929
16343
|
const { label: rmLabel, colorName: rmColor } = peelTrailingColorName(value);
|
|
@@ -15939,91 +16353,43 @@ function parseMap(content) {
|
|
|
15939
16353
|
dup(d.flowMetric);
|
|
15940
16354
|
d.flowMetric = value;
|
|
15941
16355
|
break;
|
|
15942
|
-
case "
|
|
15943
|
-
dup(d.
|
|
15944
|
-
|
|
15945
|
-
const s = parseScale(value, line12);
|
|
15946
|
-
if (s) d.scale = s;
|
|
15947
|
-
}
|
|
15948
|
-
break;
|
|
15949
|
-
case "region-labels":
|
|
15950
|
-
dup(d.regionLabels);
|
|
15951
|
-
if (value && !["full", "abbrev", "off"].includes(value))
|
|
15952
|
-
pushWarning(
|
|
15953
|
-
line12,
|
|
15954
|
-
`Unknown region-labels "${value}" (expected full | abbrev | off).`
|
|
15955
|
-
);
|
|
15956
|
-
d.regionLabels = value;
|
|
15957
|
-
break;
|
|
15958
|
-
case "poi-labels":
|
|
15959
|
-
dup(d.poiLabels);
|
|
15960
|
-
if (value && !["off", "auto", "all"].includes(value))
|
|
15961
|
-
pushWarning(
|
|
15962
|
-
line12,
|
|
15963
|
-
`Unknown poi-labels "${value}" (expected off | auto | all).`
|
|
15964
|
-
);
|
|
15965
|
-
d.poiLabels = value;
|
|
15966
|
-
break;
|
|
15967
|
-
case "default-country":
|
|
15968
|
-
dup(d.defaultCountry);
|
|
15969
|
-
d.defaultCountry = value;
|
|
15970
|
-
break;
|
|
15971
|
-
case "default-state":
|
|
15972
|
-
dup(d.defaultState);
|
|
15973
|
-
d.defaultState = value;
|
|
16356
|
+
case "locale":
|
|
16357
|
+
dup(d.locale);
|
|
16358
|
+
d.locale = value;
|
|
15974
16359
|
break;
|
|
15975
16360
|
case "active-tag":
|
|
15976
16361
|
dup(d.activeTag);
|
|
15977
16362
|
d.activeTag = value;
|
|
15978
16363
|
break;
|
|
16364
|
+
case "caption":
|
|
16365
|
+
dup(d.caption);
|
|
16366
|
+
d.caption = value;
|
|
16367
|
+
break;
|
|
16368
|
+
// ── Cosmetic `no-*` opt-outs: bare flags, idempotent (mirror `no-legend`,
|
|
16369
|
+
// no dup warning); each defaults the feature ON when absent. ──
|
|
15979
16370
|
case "no-legend":
|
|
15980
16371
|
d.noLegend = true;
|
|
15981
16372
|
break;
|
|
15982
|
-
case "no-
|
|
15983
|
-
d.
|
|
16373
|
+
case "no-coastline":
|
|
16374
|
+
d.noCoastline = true;
|
|
15984
16375
|
break;
|
|
15985
|
-
case "relief":
|
|
15986
|
-
d.
|
|
16376
|
+
case "no-relief":
|
|
16377
|
+
d.noRelief = true;
|
|
15987
16378
|
break;
|
|
15988
|
-
case "
|
|
15989
|
-
|
|
15990
|
-
if (d.basemapStyle !== void 0 && d.basemapStyle !== key)
|
|
15991
|
-
pushWarning(
|
|
15992
|
-
line12,
|
|
15993
|
-
`Conflicting basemap dress \u2014 "${d.basemapStyle}" then "${key}"; last wins.`
|
|
15994
|
-
);
|
|
15995
|
-
d.basemapStyle = key;
|
|
16379
|
+
case "no-context-labels":
|
|
16380
|
+
d.noContextLabels = true;
|
|
15996
16381
|
break;
|
|
15997
|
-
case "
|
|
15998
|
-
|
|
15999
|
-
d.subtitle = value;
|
|
16382
|
+
case "no-region-labels":
|
|
16383
|
+
d.noRegionLabels = true;
|
|
16000
16384
|
break;
|
|
16001
|
-
case "
|
|
16002
|
-
|
|
16003
|
-
|
|
16385
|
+
case "no-poi-labels":
|
|
16386
|
+
d.noPoiLabels = true;
|
|
16387
|
+
break;
|
|
16388
|
+
case "no-colorize":
|
|
16389
|
+
d.noColorize = true;
|
|
16004
16390
|
break;
|
|
16005
16391
|
}
|
|
16006
16392
|
}
|
|
16007
|
-
function parseScale(value, line12) {
|
|
16008
|
-
const toks = value.split(/\s+/).filter(Boolean);
|
|
16009
|
-
const min = Number(toks[0]);
|
|
16010
|
-
const max = Number(toks[1]);
|
|
16011
|
-
if (!Number.isFinite(min) || !Number.isFinite(max)) {
|
|
16012
|
-
pushError(line12, `scale requires numeric <min> <max> (got "${value}").`);
|
|
16013
|
-
return null;
|
|
16014
|
-
}
|
|
16015
|
-
const scale = { min, max };
|
|
16016
|
-
if (toks[2] === "center") {
|
|
16017
|
-
const c = Number(toks[3]);
|
|
16018
|
-
if (Number.isFinite(c)) scale.center = c;
|
|
16019
|
-
else
|
|
16020
|
-
pushError(
|
|
16021
|
-
line12,
|
|
16022
|
-
`scale center requires a number (got "${toks[3] ?? ""}").`
|
|
16023
|
-
);
|
|
16024
|
-
}
|
|
16025
|
-
return scale;
|
|
16026
|
-
}
|
|
16027
16393
|
function handleTag(trimmed, line12) {
|
|
16028
16394
|
const m = matchTagBlockHeading(trimmed);
|
|
16029
16395
|
if (!m) {
|
|
@@ -16223,13 +16589,15 @@ function parseMap(content) {
|
|
|
16223
16589
|
pushError(line12, `Edge has an empty endpoint: "${trimmed}".`);
|
|
16224
16590
|
continue;
|
|
16225
16591
|
}
|
|
16226
|
-
const
|
|
16592
|
+
const isLast = k === links.length - 1;
|
|
16593
|
+
const meta = isLast ? lastSplit.meta : {};
|
|
16594
|
+
const style = links[k].style === "arc" ? "arc" : "straight";
|
|
16227
16595
|
edges.push({
|
|
16228
16596
|
from,
|
|
16229
16597
|
to,
|
|
16230
16598
|
...links[k].label !== void 0 && { label: links[k].label },
|
|
16231
16599
|
directed: links[k].directed,
|
|
16232
|
-
style
|
|
16600
|
+
style,
|
|
16233
16601
|
meta,
|
|
16234
16602
|
lineNumber: line12
|
|
16235
16603
|
});
|
|
@@ -16315,22 +16683,19 @@ var init_parser12 = __esm({
|
|
|
16315
16683
|
LEG_ARROW_RE = /^(-[^>]*?->|->|~[^>]*?~>|~>|--)\s+(.+)$/;
|
|
16316
16684
|
AT_RE = /(^|[\s,])at\s*:/i;
|
|
16317
16685
|
DIRECTIVE_SET = /* @__PURE__ */ new Set([
|
|
16318
|
-
"region",
|
|
16319
|
-
"projection",
|
|
16320
16686
|
"region-metric",
|
|
16321
16687
|
"poi-metric",
|
|
16322
16688
|
"flow-metric",
|
|
16323
|
-
"
|
|
16324
|
-
"region-labels",
|
|
16325
|
-
"poi-labels",
|
|
16326
|
-
"default-country",
|
|
16327
|
-
"default-state",
|
|
16689
|
+
"locale",
|
|
16328
16690
|
"active-tag",
|
|
16691
|
+
"caption",
|
|
16329
16692
|
"no-legend",
|
|
16330
|
-
"no-
|
|
16331
|
-
"relief",
|
|
16332
|
-
"
|
|
16333
|
-
"
|
|
16693
|
+
"no-coastline",
|
|
16694
|
+
"no-relief",
|
|
16695
|
+
"no-context-labels",
|
|
16696
|
+
"no-region-labels",
|
|
16697
|
+
"no-poi-labels",
|
|
16698
|
+
"no-colorize"
|
|
16334
16699
|
]);
|
|
16335
16700
|
}
|
|
16336
16701
|
});
|
|
@@ -24341,8 +24706,8 @@ function renderKanban(container, parsed, palette, isDark, options) {
|
|
|
24341
24706
|
let metaY = separatorY + sCardSeparatorGap + sCardMetaFontSize;
|
|
24342
24707
|
for (const meta of tagMeta) {
|
|
24343
24708
|
cg.append("text").attr("x", cx + sCardPaddingX).attr("y", metaY).attr("font-size", sCardMetaFontSize).attr("fill", onCardText).text(`${meta.label}: `);
|
|
24344
|
-
const
|
|
24345
|
-
cg.append("text").attr("x", cx + sCardPaddingX +
|
|
24709
|
+
const labelWidth2 = (meta.label.length + 2) * sCardMetaFontSize * 0.6;
|
|
24710
|
+
cg.append("text").attr("x", cx + sCardPaddingX + labelWidth2).attr("y", metaY).attr("font-size", sCardMetaFontSize).attr("fill", onCardText).text(meta.value);
|
|
24346
24711
|
metaY += sCardMetaLineHeight;
|
|
24347
24712
|
}
|
|
24348
24713
|
for (const detail of card.details) {
|
|
@@ -24686,8 +25051,8 @@ function renderSwimlaneCard(parent, cardLayout, tagGroups, activeTagGroup, palet
|
|
|
24686
25051
|
let metaY = separatorY + sCardSeparatorGap + sCardMetaFontSize;
|
|
24687
25052
|
for (const meta of tagMeta) {
|
|
24688
25053
|
cg.append("text").attr("x", cx + sCardPaddingX).attr("y", metaY).attr("font-size", sCardMetaFontSize).attr("fill", palette.textMuted).text(`${meta.label}: `);
|
|
24689
|
-
const
|
|
24690
|
-
cg.append("text").attr("x", cx + sCardPaddingX +
|
|
25054
|
+
const labelWidth2 = (meta.label.length + 2) * sCardMetaFontSize * 0.6;
|
|
25055
|
+
cg.append("text").attr("x", cx + sCardPaddingX + labelWidth2).attr("y", metaY).attr("font-size", sCardMetaFontSize).attr("fill", onCardText).text(meta.value);
|
|
24691
25056
|
metaY += sCardMetaLineHeight;
|
|
24692
25057
|
}
|
|
24693
25058
|
for (const detail of card.details) {
|
|
@@ -25522,8 +25887,8 @@ function classifyEREntities(tables, relationships) {
|
|
|
25522
25887
|
}
|
|
25523
25888
|
}
|
|
25524
25889
|
const mmParticipants = /* @__PURE__ */ new Set();
|
|
25525
|
-
for (const [id,
|
|
25526
|
-
if (
|
|
25890
|
+
for (const [id, neighbors2] of tableStarNeighbors) {
|
|
25891
|
+
if (neighbors2.size >= 2) mmParticipants.add(id);
|
|
25527
25892
|
}
|
|
25528
25893
|
const indegreeValues = Object.values(indegreeMap);
|
|
25529
25894
|
const mean = indegreeValues.reduce((a, b) => a + b, 0) / indegreeValues.length;
|
|
@@ -26194,7 +26559,8 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26194
26559
|
controlsExpanded,
|
|
26195
26560
|
onToggleDescriptions,
|
|
26196
26561
|
onToggleControlsExpand,
|
|
26197
|
-
exportMode = false
|
|
26562
|
+
exportMode = false,
|
|
26563
|
+
controlsHost
|
|
26198
26564
|
} = options ?? {};
|
|
26199
26565
|
d3Selection6.select(container).selectAll(":not([data-d3-tooltip])").remove();
|
|
26200
26566
|
const width = exportDims?.width ?? container.clientWidth;
|
|
@@ -26212,7 +26578,11 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26212
26578
|
const sGroupLabelZone = sctx.structural(GROUP_LABEL_ZONE);
|
|
26213
26579
|
const sTitleFontSize = sctx.text(TITLE_FONT_SIZE);
|
|
26214
26580
|
const sTitleY = sctx.structural(TITLE_Y);
|
|
26215
|
-
const
|
|
26581
|
+
const reserveHasDescriptions = parsed.nodes.some(
|
|
26582
|
+
(n) => n.description && n.description.length > 0
|
|
26583
|
+
);
|
|
26584
|
+
const willRenderLegend = parsed.tagGroups.length > 0 || reserveHasDescriptions && controlsHost !== "app";
|
|
26585
|
+
const sLegendHeight = willRenderLegend ? sctx.structural(
|
|
26216
26586
|
getMaxLegendReservedHeight(
|
|
26217
26587
|
{
|
|
26218
26588
|
groups: parsed.tagGroups,
|
|
@@ -26221,7 +26591,7 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26221
26591
|
},
|
|
26222
26592
|
width
|
|
26223
26593
|
)
|
|
26224
|
-
);
|
|
26594
|
+
) : 0;
|
|
26225
26595
|
const activeGroup = resolveActiveTagGroup(
|
|
26226
26596
|
parsed.tagGroups,
|
|
26227
26597
|
parsed.options["active-tag"],
|
|
@@ -26536,10 +26906,10 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26536
26906
|
const hasDescriptions = parsed.nodes.some(
|
|
26537
26907
|
(n) => n.description && n.description.length > 0
|
|
26538
26908
|
);
|
|
26539
|
-
const hasLegend = parsed.tagGroups.length > 0 || hasDescriptions;
|
|
26909
|
+
const hasLegend = parsed.tagGroups.length > 0 || hasDescriptions && controlsHost !== "app";
|
|
26540
26910
|
if (hasLegend) {
|
|
26541
26911
|
let controlsGroup;
|
|
26542
|
-
if (hasDescriptions && onToggleDescriptions) {
|
|
26912
|
+
if (hasDescriptions && (onToggleDescriptions || controlsHost === "app")) {
|
|
26543
26913
|
controlsGroup = {
|
|
26544
26914
|
toggles: [
|
|
26545
26915
|
{
|
|
@@ -26557,7 +26927,14 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
|
|
|
26557
26927
|
groups: parsed.tagGroups,
|
|
26558
26928
|
position: { placement: "top-center", titleRelation: "below-title" },
|
|
26559
26929
|
mode: exportMode ? "export" : "preview",
|
|
26560
|
-
|
|
26930
|
+
// Keep inactive sibling tag groups visible as collapsed pills so the user
|
|
26931
|
+
// can click one to flip the active colouring dimension (preview only —
|
|
26932
|
+
// export shows just the active group). Without this, declaring a second
|
|
26933
|
+
// tag group (e.g. Team) leaves it invisible whenever another group is
|
|
26934
|
+
// active. The app's BoxesAndLinesPreview already wires pill clicks.
|
|
26935
|
+
showInactivePills: true,
|
|
26936
|
+
...controlsGroup !== void 0 && { controlsGroup },
|
|
26937
|
+
...controlsHost !== void 0 && { controlsHost }
|
|
26561
26938
|
};
|
|
26562
26939
|
const legendState = {
|
|
26563
26940
|
activeGroup,
|
|
@@ -27805,8 +28182,9 @@ function renderMindmap(container, parsed, layout, palette, isDark, onClickItem,
|
|
|
27805
28182
|
const containerHeight = exportDims?.height ?? (container.getBoundingClientRect().height || 600);
|
|
27806
28183
|
d3Selection7.select(container).selectAll("*").remove();
|
|
27807
28184
|
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);
|
|
28185
|
+
const appHosted = options?.controlsHost === "app";
|
|
27808
28186
|
const hasControls = !!options?.onToggleColorByDepth || !!options?.onToggleDescriptions;
|
|
27809
|
-
const hasLegend = parsed.tagGroups.length > 0 || hasControls;
|
|
28187
|
+
const hasLegend = parsed.tagGroups.length > 0 || hasControls && !appHosted;
|
|
27810
28188
|
const fixedLegend = !isExport && hasLegend;
|
|
27811
28189
|
const legendReserve = fixedLegend ? getMaxLegendReservedHeight(
|
|
27812
28190
|
{
|
|
@@ -27900,7 +28278,10 @@ function renderMindmap(container, parsed, layout, palette, isDark, onClickItem,
|
|
|
27900
28278
|
}),
|
|
27901
28279
|
position: { placement: "top-center", titleRelation: "below-title" },
|
|
27902
28280
|
mode: options?.exportMode ? "export" : "preview",
|
|
27903
|
-
...controlsToggles !== void 0 && { controlsGroup: controlsToggles }
|
|
28281
|
+
...controlsToggles !== void 0 && { controlsGroup: controlsToggles },
|
|
28282
|
+
...options?.controlsHost !== void 0 && {
|
|
28283
|
+
controlsHost: options.controlsHost
|
|
28284
|
+
}
|
|
27904
28285
|
};
|
|
27905
28286
|
const legendState = {
|
|
27906
28287
|
activeGroup: options?.colorByDepth ? null : activeTagGroup !== void 0 ? activeTagGroup : parsed.options["active-tag"] ?? null,
|
|
@@ -28344,8 +28725,8 @@ function computeFieldAlignX(children) {
|
|
|
28344
28725
|
for (const child of children) {
|
|
28345
28726
|
if (child.metadata["_labelField"] === "true" && child.children.length >= 2) {
|
|
28346
28727
|
const labelEl = child.children[0];
|
|
28347
|
-
const
|
|
28348
|
-
maxLabelWidth = Math.max(maxLabelWidth,
|
|
28728
|
+
const labelWidth2 = labelEl.label.length * CHAR_WIDTH5;
|
|
28729
|
+
maxLabelWidth = Math.max(maxLabelWidth, labelWidth2);
|
|
28349
28730
|
labelFieldCount++;
|
|
28350
28731
|
}
|
|
28351
28732
|
}
|
|
@@ -33309,7 +33690,7 @@ function hasRoles(node) {
|
|
|
33309
33690
|
function computeNodeWidth2(node, expanded, options) {
|
|
33310
33691
|
const badgeVal = node.computedConcurrentInvocations === 0 && node.computedInstances > 1 ? node.computedInstances : 0;
|
|
33311
33692
|
const badgeLen = badgeVal > 0 ? `${badgeVal}x`.length + 2 : 0;
|
|
33312
|
-
const
|
|
33693
|
+
const labelWidth2 = (node.label.length + badgeLen) * CHAR_WIDTH7 + PADDING_X3;
|
|
33313
33694
|
const allKeys = [];
|
|
33314
33695
|
if (node.computedRps > 0) allKeys.push("RPS");
|
|
33315
33696
|
if (expanded) {
|
|
@@ -33353,7 +33734,7 @@ function computeNodeWidth2(node, expanded, options) {
|
|
|
33353
33734
|
allKeys.push("overflow");
|
|
33354
33735
|
}
|
|
33355
33736
|
}
|
|
33356
|
-
if (allKeys.length === 0) return Math.max(MIN_NODE_WIDTH2,
|
|
33737
|
+
if (allKeys.length === 0) return Math.max(MIN_NODE_WIDTH2, labelWidth2);
|
|
33357
33738
|
const maxKeyLen = Math.max(...allKeys.map((k) => k.length));
|
|
33358
33739
|
let maxRowWidth = 0;
|
|
33359
33740
|
if (node.computedRps > 0) {
|
|
@@ -33441,7 +33822,7 @@ function computeNodeWidth2(node, expanded, options) {
|
|
|
33441
33822
|
truncated.length * META_CHAR_WIDTH3 + PADDING_X3
|
|
33442
33823
|
);
|
|
33443
33824
|
}
|
|
33444
|
-
return Math.max(MIN_NODE_WIDTH2,
|
|
33825
|
+
return Math.max(MIN_NODE_WIDTH2, labelWidth2, maxRowWidth + 20, descWidth);
|
|
33445
33826
|
}
|
|
33446
33827
|
function computeNodeHeight2(node, expanded, options) {
|
|
33447
33828
|
const propCount = countDisplayProps(node, expanded, options);
|
|
@@ -34990,8 +35371,9 @@ function computeInfraLegendGroups(nodes, tagGroups, palette, edges) {
|
|
|
34990
35371
|
}
|
|
34991
35372
|
return groups;
|
|
34992
35373
|
}
|
|
34993
|
-
function renderLegend3(rootSvg, legendGroups, totalWidth, legendY, palette, isDark, activeGroup, playback, exportMode = false) {
|
|
35374
|
+
function renderLegend3(rootSvg, legendGroups, totalWidth, legendY, palette, isDark, activeGroup, playback, exportMode = false, controlsHost) {
|
|
34994
35375
|
if (legendGroups.length === 0 && !playback) return;
|
|
35376
|
+
const appHostedPlayback = controlsHost === "app" && !!playback;
|
|
34995
35377
|
const legendG = rootSvg.append("g").attr("transform", `translate(0, ${legendY})`);
|
|
34996
35378
|
if (activeGroup) {
|
|
34997
35379
|
legendG.attr("data-legend-active", activeGroup.toLowerCase());
|
|
@@ -35000,14 +35382,29 @@ function renderLegend3(rootSvg, legendGroups, totalWidth, legendY, palette, isDa
|
|
|
35000
35382
|
name: g.name,
|
|
35001
35383
|
entries: g.entries.map((e) => ({ value: e.value, color: e.color }))
|
|
35002
35384
|
}));
|
|
35003
|
-
if (playback) {
|
|
35385
|
+
if (playback && !appHostedPlayback) {
|
|
35004
35386
|
allGroups.push({ name: "Playback", entries: [] });
|
|
35005
35387
|
}
|
|
35006
35388
|
const legendConfig = {
|
|
35007
35389
|
groups: allGroups,
|
|
35008
35390
|
position: { placement: "top-center", titleRelation: "below-title" },
|
|
35009
35391
|
mode: exportMode ? "export" : "preview",
|
|
35010
|
-
showEmptyGroups: true
|
|
35392
|
+
showEmptyGroups: true,
|
|
35393
|
+
...appHostedPlayback && {
|
|
35394
|
+
controlsHost: "app",
|
|
35395
|
+
controlsGroup: {
|
|
35396
|
+
toggles: [
|
|
35397
|
+
{
|
|
35398
|
+
id: "playback",
|
|
35399
|
+
type: "toggle",
|
|
35400
|
+
label: "Playback",
|
|
35401
|
+
active: true,
|
|
35402
|
+
onToggle: () => {
|
|
35403
|
+
}
|
|
35404
|
+
}
|
|
35405
|
+
]
|
|
35406
|
+
}
|
|
35407
|
+
}
|
|
35011
35408
|
};
|
|
35012
35409
|
const legendState = { activeGroup };
|
|
35013
35410
|
renderLegendD3(
|
|
@@ -35058,8 +35455,9 @@ function renderLegend3(rootSvg, legendGroups, totalWidth, legendY, palette, isDa
|
|
|
35058
35455
|
}
|
|
35059
35456
|
}
|
|
35060
35457
|
}
|
|
35061
|
-
function renderInfra(container, layout, palette, isDark, title, titleLineNumber, tagGroups, activeGroup, animate, playback, expandedNodeIds, exportMode, collapsedNodes) {
|
|
35458
|
+
function renderInfra(container, layout, palette, isDark, title, titleLineNumber, tagGroups, activeGroup, animate, playback, expandedNodeIds, exportMode, collapsedNodes, controlsHost) {
|
|
35062
35459
|
d3Selection11.select(container).selectAll(":not([data-d3-tooltip])").remove();
|
|
35460
|
+
const appHostedPlayback = controlsHost === "app" && !!playback;
|
|
35063
35461
|
const ctx = ScaleContext.identity();
|
|
35064
35462
|
const sc = buildScaledConstants(ctx);
|
|
35065
35463
|
const legendGroups = computeInfraLegendGroups(
|
|
@@ -35068,7 +35466,7 @@ function renderInfra(container, layout, palette, isDark, title, titleLineNumber,
|
|
|
35068
35466
|
palette,
|
|
35069
35467
|
layout.edges
|
|
35070
35468
|
);
|
|
35071
|
-
const hasLegend = legendGroups.length > 0 || !!playback;
|
|
35469
|
+
const hasLegend = legendGroups.length > 0 || !!playback && !appHostedPlayback;
|
|
35072
35470
|
const fixedLegend = !exportMode && hasLegend;
|
|
35073
35471
|
const legendDynamicH = hasLegend ? getMaxLegendReservedHeight(
|
|
35074
35472
|
{
|
|
@@ -35212,7 +35610,8 @@ function renderInfra(container, layout, palette, isDark, title, titleLineNumber,
|
|
|
35212
35610
|
isDark,
|
|
35213
35611
|
activeGroup ?? null,
|
|
35214
35612
|
playback ?? void 0,
|
|
35215
|
-
exportMode
|
|
35613
|
+
exportMode,
|
|
35614
|
+
controlsHost
|
|
35216
35615
|
);
|
|
35217
35616
|
legendSvg.selectAll(".infra-legend-group").style("pointer-events", "auto");
|
|
35218
35617
|
} else {
|
|
@@ -35225,7 +35624,8 @@ function renderInfra(container, layout, palette, isDark, title, titleLineNumber,
|
|
|
35225
35624
|
isDark,
|
|
35226
35625
|
activeGroup ?? null,
|
|
35227
35626
|
playback ?? void 0,
|
|
35228
|
-
exportMode
|
|
35627
|
+
exportMode,
|
|
35628
|
+
controlsHost
|
|
35229
35629
|
);
|
|
35230
35630
|
}
|
|
35231
35631
|
}
|
|
@@ -43083,6 +43483,9 @@ function renderTechRadar(container, parsed, palette, isDark, onClickItem, export
|
|
|
43083
43483
|
onToggle: (active) => options.onToggleListing(active)
|
|
43084
43484
|
}
|
|
43085
43485
|
]
|
|
43486
|
+
},
|
|
43487
|
+
...options.controlsHost !== void 0 && {
|
|
43488
|
+
controlsHost: options.controlsHost
|
|
43086
43489
|
}
|
|
43087
43490
|
};
|
|
43088
43491
|
const legendState = {
|
|
@@ -44906,7 +45309,7 @@ function computeCycleLayout(parsed, options) {
|
|
|
44906
45309
|
const circleNodes = parsed.options["circle-nodes"] === "true";
|
|
44907
45310
|
const nodeDims = parsed.nodes.map((node) => {
|
|
44908
45311
|
const hasDesc = !hideDescriptions && node.description.length > 0;
|
|
44909
|
-
const
|
|
45312
|
+
const labelWidth2 = Math.max(
|
|
44910
45313
|
MIN_NODE_WIDTH4,
|
|
44911
45314
|
node.label.length * LABEL_CHAR_W + NODE_PAD_X * 2
|
|
44912
45315
|
);
|
|
@@ -44915,12 +45318,12 @@ function computeCycleLayout(parsed, options) {
|
|
|
44915
45318
|
}
|
|
44916
45319
|
if (!hasDesc) {
|
|
44917
45320
|
return {
|
|
44918
|
-
width: Math.min(MAX_NODE_WIDTH3,
|
|
45321
|
+
width: Math.min(MAX_NODE_WIDTH3, labelWidth2),
|
|
44919
45322
|
height: PLAIN_NODE_HEIGHT,
|
|
44920
45323
|
wrappedDesc: []
|
|
44921
45324
|
};
|
|
44922
45325
|
}
|
|
44923
|
-
return chooseDescribedRectDims(node.description,
|
|
45326
|
+
return chooseDescribedRectDims(node.description, labelWidth2);
|
|
44924
45327
|
});
|
|
44925
45328
|
if (circleNodes) {
|
|
44926
45329
|
const maxDiam = Math.max(...nodeDims.map((d) => d.width));
|
|
@@ -45116,10 +45519,10 @@ function computeCycleLayout(parsed, options) {
|
|
|
45116
45519
|
scale
|
|
45117
45520
|
};
|
|
45118
45521
|
}
|
|
45119
|
-
function chooseDescribedRectDims(description,
|
|
45522
|
+
function chooseDescribedRectDims(description, labelWidth2) {
|
|
45120
45523
|
const minW = Math.min(
|
|
45121
45524
|
MAX_NODE_WIDTH3,
|
|
45122
|
-
Math.max(MIN_NODE_WIDTH4,
|
|
45525
|
+
Math.max(MIN_NODE_WIDTH4, labelWidth2, DESC_MIN_WIDTH)
|
|
45123
45526
|
);
|
|
45124
45527
|
let best = null;
|
|
45125
45528
|
let bestScore = Infinity;
|
|
@@ -45547,7 +45950,8 @@ function renderCycle(container, parsed, palette, isDark, onClickItem, exportDims
|
|
|
45547
45950
|
const hideDescriptions = (renderOptions?.hideDescriptions ?? false) || parsed.options["no-descriptions"] === "true" || viewState?.hd === true;
|
|
45548
45951
|
const showDescriptions = !hideDescriptions;
|
|
45549
45952
|
const hasDescriptions = parsed.nodes.some((n) => n.description.length > 0) || parsed.edges.some((e) => e.description.length > 0);
|
|
45550
|
-
const
|
|
45953
|
+
const appHostedControls = renderOptions?.controlsHost === "app";
|
|
45954
|
+
const hasLegend = !appHostedControls && hasDescriptions && !!renderOptions?.onToggleDescriptions;
|
|
45551
45955
|
const showTitle = !!parsed.title && parsed.options["no-title"] !== "on";
|
|
45552
45956
|
const legendOffset = hasLegend ? sLegendHeight : 0;
|
|
45553
45957
|
const layoutHeight = height - (showTitle ? sTitleAreaHeight : 0) - legendOffset;
|
|
@@ -45584,7 +45988,10 @@ function renderCycle(container, parsed, palette, isDark, onClickItem, exportDims
|
|
|
45584
45988
|
groups: [],
|
|
45585
45989
|
position: { placement: "top-center", titleRelation: "below-title" },
|
|
45586
45990
|
mode: renderOptions?.exportMode ? "export" : "preview",
|
|
45587
|
-
controlsGroup
|
|
45991
|
+
controlsGroup,
|
|
45992
|
+
...renderOptions?.controlsHost !== void 0 && {
|
|
45993
|
+
controlsHost: renderOptions.controlsHost
|
|
45994
|
+
}
|
|
45588
45995
|
};
|
|
45589
45996
|
const legendState = {
|
|
45590
45997
|
activeGroup: null,
|
|
@@ -45855,6 +46262,29 @@ function featureIndex(topo) {
|
|
|
45855
46262
|
}
|
|
45856
46263
|
return idx;
|
|
45857
46264
|
}
|
|
46265
|
+
function buildAdjacency(topo) {
|
|
46266
|
+
const cached = adjacencyCache.get(topo);
|
|
46267
|
+
if (cached) return cached;
|
|
46268
|
+
const geometries = geomObject(topo).geometries;
|
|
46269
|
+
const nb = (0, import_topojson_client.neighbors)(geometries);
|
|
46270
|
+
const sets = /* @__PURE__ */ new Map();
|
|
46271
|
+
geometries.forEach((g, i) => {
|
|
46272
|
+
if (!g.type || g.type === "null") return;
|
|
46273
|
+
let set = sets.get(g.id);
|
|
46274
|
+
if (!set) {
|
|
46275
|
+
set = /* @__PURE__ */ new Set();
|
|
46276
|
+
sets.set(g.id, set);
|
|
46277
|
+
}
|
|
46278
|
+
for (const j of nb[i] ?? []) {
|
|
46279
|
+
const nid = geometries[j]?.id;
|
|
46280
|
+
if (nid && nid !== g.id) set.add(nid);
|
|
46281
|
+
}
|
|
46282
|
+
});
|
|
46283
|
+
const out = /* @__PURE__ */ new Map();
|
|
46284
|
+
for (const [iso, set] of sets) out.set(iso, [...set].sort());
|
|
46285
|
+
adjacencyCache.set(topo, out);
|
|
46286
|
+
return out;
|
|
46287
|
+
}
|
|
45858
46288
|
function decodeFeatures(topo) {
|
|
45859
46289
|
return geomObject(topo).geometries.map((g) => {
|
|
45860
46290
|
const f = (0, import_topojson_client.feature)(topo, g);
|
|
@@ -46050,13 +46480,14 @@ function unionLongitudes(lons) {
|
|
|
46050
46480
|
}
|
|
46051
46481
|
return { west: pts[gapIdx], east: pts[gapIdx - 1] + 360 };
|
|
46052
46482
|
}
|
|
46053
|
-
var import_topojson_client, import_d3_geo, fold, EDGE_EPS, DETACH_GAP_DEG, DETACH_AREA_FRAC;
|
|
46483
|
+
var import_topojson_client, import_d3_geo, fold, adjacencyCache, EDGE_EPS, DETACH_GAP_DEG, DETACH_AREA_FRAC;
|
|
46054
46484
|
var init_geo = __esm({
|
|
46055
46485
|
"src/map/geo.ts"() {
|
|
46056
46486
|
"use strict";
|
|
46057
46487
|
import_topojson_client = require("topojson-client");
|
|
46058
46488
|
import_d3_geo = require("d3-geo");
|
|
46059
46489
|
fold = (s) => s.normalize("NFD").replace(/\p{Diacritic}/gu, "").toLowerCase().trim();
|
|
46490
|
+
adjacencyCache = /* @__PURE__ */ new WeakMap();
|
|
46060
46491
|
EDGE_EPS = 1e-9;
|
|
46061
46492
|
DETACH_GAP_DEG = 10;
|
|
46062
46493
|
DETACH_AREA_FRAC = 0.25;
|
|
@@ -46077,6 +46508,12 @@ function looksUS(lat, lon) {
|
|
|
46077
46508
|
if (lat < 15 || lat > 72) return false;
|
|
46078
46509
|
return lon >= -180 && lon <= -64 || lon >= 172;
|
|
46079
46510
|
}
|
|
46511
|
+
function looksNorthAmericaNeighbor(lat, lon) {
|
|
46512
|
+
return lat >= 14 && lat <= 72 && lon >= -141 && lon <= -52;
|
|
46513
|
+
}
|
|
46514
|
+
function isWholeSphere(bb) {
|
|
46515
|
+
return bb[0][0] <= -179 && bb[1][0] >= 179 && bb[0][1] <= -89 && bb[1][1] >= 89;
|
|
46516
|
+
}
|
|
46080
46517
|
function resolveMap(parsed, data) {
|
|
46081
46518
|
const diagnostics = [...parsed.diagnostics];
|
|
46082
46519
|
const err = (line12, message, code) => {
|
|
@@ -46087,9 +46524,6 @@ function resolveMap(parsed, data) {
|
|
|
46087
46524
|
};
|
|
46088
46525
|
const result = {
|
|
46089
46526
|
title: parsed.title,
|
|
46090
|
-
...parsed.directives.subtitle !== void 0 && {
|
|
46091
|
-
subtitle: parsed.directives.subtitle
|
|
46092
|
-
},
|
|
46093
46527
|
...parsed.directives.caption !== void 0 && {
|
|
46094
46528
|
caption: parsed.directives.caption
|
|
46095
46529
|
},
|
|
@@ -46099,7 +46533,7 @@ function resolveMap(parsed, data) {
|
|
|
46099
46533
|
// renderer's job (step 4) — the resolver only carries `tags` + `tagGroups`
|
|
46100
46534
|
// through; it never resolves a tag value to a palette color (#10).
|
|
46101
46535
|
directives: { ...parsed.directives },
|
|
46102
|
-
basemaps: { world: "
|
|
46536
|
+
basemaps: { world: "detail", subdivisions: [] },
|
|
46103
46537
|
regions: [],
|
|
46104
46538
|
pois: [],
|
|
46105
46539
|
edges: [],
|
|
@@ -46108,7 +46542,8 @@ function resolveMap(parsed, data) {
|
|
|
46108
46542
|
[-180, -85],
|
|
46109
46543
|
[180, 85]
|
|
46110
46544
|
],
|
|
46111
|
-
projection: "
|
|
46545
|
+
projection: "equirectangular",
|
|
46546
|
+
poiFrameContainers: [],
|
|
46112
46547
|
diagnostics,
|
|
46113
46548
|
error: parsed.error
|
|
46114
46549
|
};
|
|
@@ -46118,7 +46553,10 @@ function resolveMap(parsed, data) {
|
|
|
46118
46553
|
...[...countryIndex.values()].map((v) => v.name),
|
|
46119
46554
|
...[...usStateIndex.values()].map((v) => v.name)
|
|
46120
46555
|
];
|
|
46121
|
-
const
|
|
46556
|
+
const localeRaw = parsed.directives.locale?.toUpperCase();
|
|
46557
|
+
const localeCountry = localeRaw ? localeRaw.split("-")[0] : void 0;
|
|
46558
|
+
const localeSubdivision = localeRaw && /^[A-Z]{2}-/.test(localeRaw) ? localeRaw : void 0;
|
|
46559
|
+
const usScoped = localeCountry === "US" || parsed.regions.some((r) => {
|
|
46122
46560
|
const f = fold(r.name);
|
|
46123
46561
|
return usStateIndex.has(f) && !countryIndex.has(f);
|
|
46124
46562
|
}) || parsed.regions.some(
|
|
@@ -46269,7 +46707,7 @@ function resolveMap(parsed, data) {
|
|
|
46269
46707
|
if (!scope)
|
|
46270
46708
|
warn(
|
|
46271
46709
|
line12,
|
|
46272
|
-
`"${name}" is ambiguous \u2014 resolved to the most-populous match.`,
|
|
46710
|
+
`"${name}" is ambiguous \u2014 resolved to the most-populous match. Set a default with \`locale <ISO>\` (e.g. \`locale US\` / \`locale US-GA\`) to steer it.`,
|
|
46273
46711
|
"W_MAP_AMBIGUOUS_NAME"
|
|
46274
46712
|
);
|
|
46275
46713
|
}
|
|
@@ -46282,17 +46720,21 @@ function resolveMap(parsed, data) {
|
|
|
46282
46720
|
return fold(pos.name);
|
|
46283
46721
|
};
|
|
46284
46722
|
const poiCountries = [];
|
|
46285
|
-
let
|
|
46723
|
+
let anyUsPoi = false;
|
|
46724
|
+
let anyNonNaPoi = false;
|
|
46286
46725
|
const noteCountry = (iso) => {
|
|
46287
46726
|
if (iso) {
|
|
46288
46727
|
poiCountries.push(iso);
|
|
46289
|
-
if (iso
|
|
46728
|
+
if (iso === "US") anyUsPoi = true;
|
|
46729
|
+
if (iso !== "US" && iso !== "CA" && iso !== "MX") anyNonNaPoi = true;
|
|
46290
46730
|
}
|
|
46291
46731
|
};
|
|
46292
46732
|
const deferred = [];
|
|
46293
46733
|
for (const p of parsed.pois) {
|
|
46294
46734
|
if (p.pos.kind === "coords") {
|
|
46295
|
-
if (
|
|
46735
|
+
if (looksUS(p.pos.lat, p.pos.lon)) anyUsPoi = true;
|
|
46736
|
+
else if (!looksNorthAmericaNeighbor(p.pos.lat, p.pos.lon))
|
|
46737
|
+
anyNonNaPoi = true;
|
|
46296
46738
|
addResolvedPoi(p.pos.lat, p.pos.lon, p);
|
|
46297
46739
|
continue;
|
|
46298
46740
|
}
|
|
@@ -46310,14 +46752,15 @@ function resolveMap(parsed, data) {
|
|
|
46310
46752
|
deferred.push(p);
|
|
46311
46753
|
}
|
|
46312
46754
|
}
|
|
46313
|
-
const inferredCountry =
|
|
46755
|
+
const inferredCountry = localeCountry ?? mostCommonCountry(regions, poiCountries) ?? void 0;
|
|
46756
|
+
const inferredScope = localeSubdivision ?? inferredCountry;
|
|
46314
46757
|
for (const p of deferred) {
|
|
46315
46758
|
if (p.pos.kind !== "name") continue;
|
|
46316
46759
|
const got = lookupName(
|
|
46317
46760
|
p.pos.name,
|
|
46318
46761
|
p.pos.scope,
|
|
46319
46762
|
p.lineNumber,
|
|
46320
|
-
|
|
46763
|
+
inferredScope,
|
|
46321
46764
|
true
|
|
46322
46765
|
);
|
|
46323
46766
|
if (got.kind === "ok") {
|
|
@@ -46387,7 +46830,8 @@ function resolveMap(parsed, data) {
|
|
|
46387
46830
|
const meta = sizeValue !== void 0 ? { value: sizeValue } : {};
|
|
46388
46831
|
if (pos.kind === "coords") {
|
|
46389
46832
|
const id = alias ? fold(alias) : `@${pos.lat},${pos.lon}`;
|
|
46390
|
-
if (
|
|
46833
|
+
if (looksUS(pos.lat, pos.lon)) anyUsPoi = true;
|
|
46834
|
+
else if (!looksNorthAmericaNeighbor(pos.lat, pos.lon)) anyNonNaPoi = true;
|
|
46391
46835
|
if (!registry.has(id)) {
|
|
46392
46836
|
registerPoi(
|
|
46393
46837
|
id,
|
|
@@ -46410,7 +46854,7 @@ function resolveMap(parsed, data) {
|
|
|
46410
46854
|
if (registry.has(f)) return f;
|
|
46411
46855
|
const aliased = declaredByName.get(f);
|
|
46412
46856
|
if (aliased) return aliased;
|
|
46413
|
-
const got = lookupName(pos.name, pos.scope, line12,
|
|
46857
|
+
const got = lookupName(pos.name, pos.scope, line12, inferredScope, true);
|
|
46414
46858
|
if (got.kind !== "ok") return null;
|
|
46415
46859
|
noteCountry(got.iso);
|
|
46416
46860
|
registerPoi(
|
|
@@ -46467,9 +46911,12 @@ function resolveMap(parsed, data) {
|
|
|
46467
46911
|
}
|
|
46468
46912
|
routes.push({ stopIds, legs, lineNumber: rt.lineNumber });
|
|
46469
46913
|
}
|
|
46914
|
+
const hasUsContent = usSubdivisionReferenced || anyUsPoi || localeCountry === "US";
|
|
46915
|
+
const usOriented = !anyNonNaPoi && !regions.some(
|
|
46916
|
+
(r) => r.layer === "country" && !["US", "CA", "MX"].includes(r.iso)
|
|
46917
|
+
) && hasUsContent;
|
|
46470
46918
|
const subdivisions = [];
|
|
46471
|
-
if (usSubdivisionReferenced ||
|
|
46472
|
-
subdivisions.push("us-states");
|
|
46919
|
+
if (usSubdivisionReferenced || usOriented) subdivisions.push("us-states");
|
|
46473
46920
|
const regionBoxes = [];
|
|
46474
46921
|
for (const ref of referencedRegionIds) {
|
|
46475
46922
|
const bb = featureBbox(data.usStates, ref.id);
|
|
@@ -46487,17 +46934,51 @@ function resolveMap(parsed, data) {
|
|
|
46487
46934
|
[-180, -85],
|
|
46488
46935
|
[180, 85]
|
|
46489
46936
|
];
|
|
46490
|
-
|
|
46937
|
+
const basePad = regions.length > 0 ? REGION_PAD_FRACTION : PAD_FRACTION;
|
|
46938
|
+
let extent2 = unioned ? pad(unioned, basePad) : DEFAULT_EXTENT;
|
|
46939
|
+
const isPoiOnly = pois.length > 0 && regions.length === 0;
|
|
46940
|
+
const containerRegionIds = [];
|
|
46941
|
+
if (isPoiOnly) {
|
|
46942
|
+
const countries = decodeFeatures(data.worldDetail);
|
|
46943
|
+
const states = decodeFeatures(data.usStates);
|
|
46944
|
+
const seen = /* @__PURE__ */ new Set();
|
|
46945
|
+
const containerBoxes = [];
|
|
46946
|
+
for (const p of pois) {
|
|
46947
|
+
const { country, state } = regionAt([p.lon, p.lat], countries, states);
|
|
46948
|
+
const id = state?.iso ?? country?.iso;
|
|
46949
|
+
if (!id || seen.has(id)) continue;
|
|
46950
|
+
seen.add(id);
|
|
46951
|
+
containerRegionIds.push(id);
|
|
46952
|
+
const bb = state ? featureBbox(data.usStates, id) : featureBboxPrimary(data.worldCoarse, id);
|
|
46953
|
+
if (bb && !isWholeSphere(bb)) containerBoxes.push(bb);
|
|
46954
|
+
}
|
|
46955
|
+
const containerUnion = unionExtent(containerBoxes, points);
|
|
46956
|
+
if (containerUnion) extent2 = pad(containerUnion, PAD_FRACTION);
|
|
46957
|
+
}
|
|
46958
|
+
if (isPoiOnly) {
|
|
46959
|
+
const cx = (extent2[0][0] + extent2[1][0]) / 2;
|
|
46960
|
+
const cy = (extent2[0][1] + extent2[1][1]) / 2;
|
|
46961
|
+
const lon = extent2[1][0] - extent2[0][0];
|
|
46962
|
+
const lat = extent2[1][1] - extent2[0][1];
|
|
46963
|
+
const longer = Math.max(lon, lat);
|
|
46964
|
+
if (longer > 0 && longer < POI_ZOOM_FLOOR_DEG) {
|
|
46965
|
+
const k = POI_ZOOM_FLOOR_DEG / longer;
|
|
46966
|
+
const halfLon = lon * k / 2;
|
|
46967
|
+
const halfLat = lat * k / 2;
|
|
46968
|
+
extent2 = [
|
|
46969
|
+
[cx - halfLon, cy - halfLat],
|
|
46970
|
+
[cx + halfLon, cy + halfLat]
|
|
46971
|
+
];
|
|
46972
|
+
}
|
|
46973
|
+
}
|
|
46491
46974
|
const lonSpan = extent2[1][0] - extent2[0][0];
|
|
46492
46975
|
const latSpan = extent2[1][1] - extent2[0][1];
|
|
46493
46976
|
const span = Math.max(lonSpan, latSpan);
|
|
46494
46977
|
const maxAbsLat = Math.max(Math.abs(extent2[0][1]), Math.abs(extent2[1][1]));
|
|
46495
|
-
const usDominant = (subdivisions.includes("us-states") || regions.some((r) => r.layer === "us-state")) && !regions.some((r) => r.layer === "country" && r.iso !== "US") && !anyNonUsPoi;
|
|
46496
46978
|
let projection;
|
|
46497
|
-
|
|
46498
|
-
|
|
46499
|
-
|
|
46500
|
-
} else if (usDominant) {
|
|
46979
|
+
if (isPoiOnly && usOriented && lonSpan < US_NATIONAL_LON_SPAN) {
|
|
46980
|
+
projection = "mercator";
|
|
46981
|
+
} else if (usOriented) {
|
|
46501
46982
|
projection = "albers-usa";
|
|
46502
46983
|
} else if (span > WORLD_SPAN || maxAbsLat > MERCATOR_MAX_LAT) {
|
|
46503
46984
|
projection = "equirectangular";
|
|
@@ -46515,11 +46996,20 @@ function resolveMap(parsed, data) {
|
|
|
46515
46996
|
result.edges = edges;
|
|
46516
46997
|
result.routes = routes;
|
|
46517
46998
|
result.basemaps = {
|
|
46518
|
-
|
|
46999
|
+
// Tier is intentionally pinned to detail (50m) at ALL scales. Diagrammo maps
|
|
47000
|
+
// are presentational (palette tints, relief hachures, POI hubs), not
|
|
47001
|
+
// survey-grade — recognizability > generalization: 110m coarse drops the
|
|
47002
|
+
// Italian boot to a stump at world scale. `WORLD_SPAN` lives on only for the
|
|
47003
|
+
// projection decision (the `usOriented`/`span > WORLD_SPAN` chain above); it
|
|
47004
|
+
// no longer gates basemap resolution.
|
|
47005
|
+
// `worldCoarse` is still loaded — it's the authoritative name/bbox index
|
|
47006
|
+
// (featureIndex, featureBboxPrimary), not dead code.
|
|
47007
|
+
world: "detail",
|
|
46519
47008
|
subdivisions
|
|
46520
47009
|
};
|
|
46521
47010
|
result.extent = extent2;
|
|
46522
47011
|
result.projection = projection;
|
|
47012
|
+
result.poiFrameContainers = containerRegionIds;
|
|
46523
47013
|
result.error = parsed.error ?? firstError(diagnostics);
|
|
46524
47014
|
return result;
|
|
46525
47015
|
}
|
|
@@ -46556,7 +47046,7 @@ function firstError(diags) {
|
|
|
46556
47046
|
const e = diags.find((d) => d.severity === "error");
|
|
46557
47047
|
return e ? formatDgmoError(e) : null;
|
|
46558
47048
|
}
|
|
46559
|
-
var WORLD_SPAN, MERCATOR_MAX_LAT, PAD_FRACTION, WORLD_LAT_SOUTH, WORLD_LAT_NORTH, REGION_ALIASES, US_STATE_POSTAL;
|
|
47049
|
+
var WORLD_SPAN, MERCATOR_MAX_LAT, PAD_FRACTION, REGION_PAD_FRACTION, WORLD_LAT_SOUTH, WORLD_LAT_NORTH, POI_ZOOM_FLOOR_DEG, US_NATIONAL_LON_SPAN, REGION_ALIASES, US_STATE_POSTAL;
|
|
46560
47050
|
var init_resolver2 = __esm({
|
|
46561
47051
|
"src/map/resolver.ts"() {
|
|
46562
47052
|
"use strict";
|
|
@@ -46565,8 +47055,11 @@ var init_resolver2 = __esm({
|
|
|
46565
47055
|
WORLD_SPAN = 90;
|
|
46566
47056
|
MERCATOR_MAX_LAT = 80;
|
|
46567
47057
|
PAD_FRACTION = 0.05;
|
|
47058
|
+
REGION_PAD_FRACTION = 0.12;
|
|
46568
47059
|
WORLD_LAT_SOUTH = -58;
|
|
46569
47060
|
WORLD_LAT_NORTH = 78;
|
|
47061
|
+
POI_ZOOM_FLOOR_DEG = 7;
|
|
47062
|
+
US_NATIONAL_LON_SPAN = 48;
|
|
46570
47063
|
REGION_ALIASES = {
|
|
46571
47064
|
// Common everyday names → the Natural-Earth display name actually shipped.
|
|
46572
47065
|
"united states": "united states of america",
|
|
@@ -46644,17 +47137,305 @@ var init_resolver2 = __esm({
|
|
|
46644
47137
|
}
|
|
46645
47138
|
});
|
|
46646
47139
|
|
|
47140
|
+
// src/map/colorize.ts
|
|
47141
|
+
function assignColors(isos, adjacency) {
|
|
47142
|
+
const sorted = [...isos].sort();
|
|
47143
|
+
const byIso = /* @__PURE__ */ new Map();
|
|
47144
|
+
let maxIndex = -1;
|
|
47145
|
+
for (const iso of sorted) {
|
|
47146
|
+
const taken = /* @__PURE__ */ new Set();
|
|
47147
|
+
for (const n of adjacency.get(iso) ?? []) {
|
|
47148
|
+
const c = byIso.get(n);
|
|
47149
|
+
if (c !== void 0) taken.add(c);
|
|
47150
|
+
}
|
|
47151
|
+
let h = 0;
|
|
47152
|
+
while (taken.has(h)) h++;
|
|
47153
|
+
byIso.set(iso, h);
|
|
47154
|
+
if (h > maxIndex) maxIndex = h;
|
|
47155
|
+
}
|
|
47156
|
+
return { byIso, huesNeeded: maxIndex + 1 };
|
|
47157
|
+
}
|
|
47158
|
+
var init_colorize = __esm({
|
|
47159
|
+
"src/map/colorize.ts"() {
|
|
47160
|
+
"use strict";
|
|
47161
|
+
}
|
|
47162
|
+
});
|
|
47163
|
+
|
|
47164
|
+
// src/map/context-labels.ts
|
|
47165
|
+
function tierBand(maxSpanDeg) {
|
|
47166
|
+
if (maxSpanDeg >= 90) return "world";
|
|
47167
|
+
if (maxSpanDeg >= 20) return "continental";
|
|
47168
|
+
if (maxSpanDeg >= 5) return "regional";
|
|
47169
|
+
return "local";
|
|
47170
|
+
}
|
|
47171
|
+
function labelBudget(width, height, band) {
|
|
47172
|
+
const bandCap = {
|
|
47173
|
+
world: 6,
|
|
47174
|
+
continental: 5,
|
|
47175
|
+
regional: 4,
|
|
47176
|
+
local: 3
|
|
47177
|
+
};
|
|
47178
|
+
const area2 = Math.floor(Math.sqrt(Math.max(0, width * height)) / 150);
|
|
47179
|
+
return Math.max(0, Math.min(area2, bandCap[band]));
|
|
47180
|
+
}
|
|
47181
|
+
function waterEligible(tier, kind, band) {
|
|
47182
|
+
switch (band) {
|
|
47183
|
+
case "world":
|
|
47184
|
+
return tier <= 1 && (kind === "ocean" || kind === "sea");
|
|
47185
|
+
case "continental":
|
|
47186
|
+
return tier <= 2;
|
|
47187
|
+
case "regional":
|
|
47188
|
+
return tier <= 3;
|
|
47189
|
+
case "local":
|
|
47190
|
+
return tier <= 4;
|
|
47191
|
+
}
|
|
47192
|
+
}
|
|
47193
|
+
function insideViewport(p, width, height) {
|
|
47194
|
+
return !!p && Number.isFinite(p[0]) && Number.isFinite(p[1]) && p[0] >= 0 && p[0] <= width && p[1] >= 0 && p[1] <= height;
|
|
47195
|
+
}
|
|
47196
|
+
function labelWidth(text, letterSpacing) {
|
|
47197
|
+
const spacing = letterSpacing > 0 ? Math.max(0, text.length - 1) * letterSpacing : 0;
|
|
47198
|
+
return measureLegendText(text, FONT) + spacing + 2 * PADX;
|
|
47199
|
+
}
|
|
47200
|
+
function wrapLabel2(text, letterSpacing) {
|
|
47201
|
+
const words = text.split(/\s+/).filter(Boolean);
|
|
47202
|
+
if (words.length <= 1) return [text];
|
|
47203
|
+
const maxLines = words.length >= 4 ? 3 : 2;
|
|
47204
|
+
const n = words.length;
|
|
47205
|
+
let best = null;
|
|
47206
|
+
for (let mask = 0; mask < 1 << n - 1; mask++) {
|
|
47207
|
+
const lines = [];
|
|
47208
|
+
let cur = [words[0]];
|
|
47209
|
+
for (let i = 1; i < n; i++) {
|
|
47210
|
+
if (mask & 1 << i - 1) {
|
|
47211
|
+
lines.push(cur.join(" "));
|
|
47212
|
+
cur = [words[i]];
|
|
47213
|
+
} else cur.push(words[i]);
|
|
47214
|
+
}
|
|
47215
|
+
lines.push(cur.join(" "));
|
|
47216
|
+
if (lines.length > maxLines) continue;
|
|
47217
|
+
const cost = Math.round(
|
|
47218
|
+
Math.max(...lines.map((l) => labelWidth(l, letterSpacing)))
|
|
47219
|
+
);
|
|
47220
|
+
const head = labelWidth(lines[0], letterSpacing);
|
|
47221
|
+
if (!best || cost < best.cost || cost === best.cost && lines.length < best.lines.length || cost === best.cost && lines.length === best.lines.length && head > best.head)
|
|
47222
|
+
best = { lines, cost, head };
|
|
47223
|
+
}
|
|
47224
|
+
return best?.lines ?? [text];
|
|
47225
|
+
}
|
|
47226
|
+
function rectAround(cx, cy, lines, letterSpacing) {
|
|
47227
|
+
const w = Math.max(...lines.map((l) => labelWidth(l, letterSpacing)));
|
|
47228
|
+
const h = (lines.length - 1) * LINE_HEIGHT + FONT + 2 * PADY;
|
|
47229
|
+
return { x: cx - w / 2, y: cy - h / 2, w, h };
|
|
47230
|
+
}
|
|
47231
|
+
function rectFits(r, width, height) {
|
|
47232
|
+
return r.x >= 0 && r.y >= 0 && r.x + r.w <= width && r.y + r.h <= height;
|
|
47233
|
+
}
|
|
47234
|
+
function overlapsPadded(a, b, pad2) {
|
|
47235
|
+
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;
|
|
47236
|
+
}
|
|
47237
|
+
function placeContextLabels(args) {
|
|
47238
|
+
const {
|
|
47239
|
+
projection,
|
|
47240
|
+
dLonSpan,
|
|
47241
|
+
dLatSpan,
|
|
47242
|
+
width,
|
|
47243
|
+
height,
|
|
47244
|
+
waterBodies,
|
|
47245
|
+
countries,
|
|
47246
|
+
palette,
|
|
47247
|
+
project,
|
|
47248
|
+
collides,
|
|
47249
|
+
overLand
|
|
47250
|
+
} = args;
|
|
47251
|
+
void projection;
|
|
47252
|
+
const band = tierBand(Math.max(dLonSpan, dLatSpan));
|
|
47253
|
+
const budget = labelBudget(width, height, band);
|
|
47254
|
+
if (budget <= 0) return [];
|
|
47255
|
+
const waterColor = mix(palette.colors.blue, palette.textMuted, 50);
|
|
47256
|
+
const countryColor = palette.textMuted;
|
|
47257
|
+
const haloColor = palette.bg;
|
|
47258
|
+
const candidates = [];
|
|
47259
|
+
const center = [width / 2, height / 2];
|
|
47260
|
+
for (const e of waterBodies?.entries ?? []) {
|
|
47261
|
+
const [lat, lon, name, tier, kind, alt] = e;
|
|
47262
|
+
if (!waterEligible(tier, kind, band)) continue;
|
|
47263
|
+
const wlines = wrapLabel2(name, WATER_LETTER_SPACING);
|
|
47264
|
+
const anchorsLngLat = [[lon, lat]];
|
|
47265
|
+
for (const a of alt ?? []) anchorsLngLat.push([a[1], a[0]]);
|
|
47266
|
+
let best = null;
|
|
47267
|
+
let bestD = Infinity;
|
|
47268
|
+
let nearestProj = null;
|
|
47269
|
+
let nearestProjD = Infinity;
|
|
47270
|
+
for (const [aLon, aLat] of anchorsLngLat) {
|
|
47271
|
+
const p = project(aLon, aLat);
|
|
47272
|
+
if (!p || !Number.isFinite(p[0]) || !Number.isFinite(p[1])) continue;
|
|
47273
|
+
const d = (p[0] - center[0]) ** 2 + (p[1] - center[1]) ** 2;
|
|
47274
|
+
if (d < nearestProjD) {
|
|
47275
|
+
nearestProjD = d;
|
|
47276
|
+
nearestProj = p;
|
|
47277
|
+
}
|
|
47278
|
+
if (!insideViewport(p, width, height)) continue;
|
|
47279
|
+
if (d < bestD) {
|
|
47280
|
+
bestD = d;
|
|
47281
|
+
best = p;
|
|
47282
|
+
}
|
|
47283
|
+
}
|
|
47284
|
+
if (!best && tier === 0 && nearestProj) {
|
|
47285
|
+
const overX = Math.max(0, -nearestProj[0], nearestProj[0] - width);
|
|
47286
|
+
const overY = Math.max(0, -nearestProj[1], nearestProj[1] - height);
|
|
47287
|
+
if (overX <= width * EDGE_CLAMP_OVERSHOOT && overY <= height * EDGE_CLAMP_OVERSHOOT) {
|
|
47288
|
+
const halfW = Math.max(...wlines.map((l) => labelWidth(l, WATER_LETTER_SPACING))) / 2;
|
|
47289
|
+
const halfH = ((wlines.length - 1) * LINE_HEIGHT + FONT + 2 * PADY) / 2;
|
|
47290
|
+
const m = EDGE_CLAMP_MARGIN;
|
|
47291
|
+
best = [
|
|
47292
|
+
Math.min(Math.max(nearestProj[0], halfW + m), width - halfW - m),
|
|
47293
|
+
Math.min(Math.max(nearestProj[1], halfH + m), height - halfH - m)
|
|
47294
|
+
];
|
|
47295
|
+
}
|
|
47296
|
+
}
|
|
47297
|
+
if (!best) continue;
|
|
47298
|
+
candidates.push({
|
|
47299
|
+
text: name,
|
|
47300
|
+
lines: wlines,
|
|
47301
|
+
cx: best[0],
|
|
47302
|
+
cy: best[1],
|
|
47303
|
+
italic: true,
|
|
47304
|
+
letterSpacing: WATER_LETTER_SPACING,
|
|
47305
|
+
color: waterColor,
|
|
47306
|
+
// Water before any country (×1000), then by tier, then kind, then name.
|
|
47307
|
+
sort: tier * 10 + KIND_ORDER[kind]
|
|
47308
|
+
});
|
|
47309
|
+
}
|
|
47310
|
+
const ranked = countries.map((c) => {
|
|
47311
|
+
const [x0, y0, x1, y1] = c.bbox;
|
|
47312
|
+
const w = x1 - x0;
|
|
47313
|
+
const h = y1 - y0;
|
|
47314
|
+
return { c, w, h, area: w * h };
|
|
47315
|
+
}).filter((r) => Number.isFinite(r.area) && r.area > 0).sort((a, b) => b.area - a.area);
|
|
47316
|
+
let ci = 0;
|
|
47317
|
+
for (const r of ranked) {
|
|
47318
|
+
const { c, w, h } = r;
|
|
47319
|
+
if (w > width * 0.66 || h > height * 0.66) continue;
|
|
47320
|
+
if (!insideViewport(c.anchor, width, height)) continue;
|
|
47321
|
+
const text = c.name;
|
|
47322
|
+
const tw = labelWidth(text, 0);
|
|
47323
|
+
if (tw > w || FONT + 2 * PADY > h) continue;
|
|
47324
|
+
candidates.push({
|
|
47325
|
+
text,
|
|
47326
|
+
lines: [text],
|
|
47327
|
+
cx: c.anchor[0],
|
|
47328
|
+
cy: c.anchor[1],
|
|
47329
|
+
italic: false,
|
|
47330
|
+
letterSpacing: 0,
|
|
47331
|
+
color: countryColor,
|
|
47332
|
+
// Always after every water body (+1e6); larger area = earlier.
|
|
47333
|
+
sort: 1e6 + ci++
|
|
47334
|
+
});
|
|
47335
|
+
}
|
|
47336
|
+
candidates.sort((a, b) => a.sort - b.sort);
|
|
47337
|
+
const placed = [];
|
|
47338
|
+
const placedRects = [];
|
|
47339
|
+
for (const cand of candidates) {
|
|
47340
|
+
if (placed.length >= budget) break;
|
|
47341
|
+
const rect = rectAround(cand.cx, cand.cy, cand.lines, cand.letterSpacing);
|
|
47342
|
+
if (!rectFits(rect, width, height)) continue;
|
|
47343
|
+
if (cand.italic && overLand) {
|
|
47344
|
+
const inset = 2;
|
|
47345
|
+
const top = cand.cy - (cand.lines.length - 1) / 2 * LINE_HEIGHT;
|
|
47346
|
+
const touchesLand = cand.lines.some((line12, li) => {
|
|
47347
|
+
const lw = labelWidth(line12, cand.letterSpacing);
|
|
47348
|
+
const x0 = cand.cx - lw / 2 + inset;
|
|
47349
|
+
const x1 = cand.cx + lw / 2 - inset;
|
|
47350
|
+
const xs = [x0, (x0 + cand.cx) / 2, cand.cx, (cand.cx + x1) / 2, x1];
|
|
47351
|
+
const base = top + li * LINE_HEIGHT;
|
|
47352
|
+
return [base, base - FONT * 0.4, base - FONT * 0.8].some(
|
|
47353
|
+
(y) => xs.some((x) => overLand(x, y))
|
|
47354
|
+
);
|
|
47355
|
+
});
|
|
47356
|
+
if (touchesLand) continue;
|
|
47357
|
+
}
|
|
47358
|
+
if (collides(rect)) continue;
|
|
47359
|
+
if (placedRects.some((r) => overlapsPadded(rect, r, CONTEXT_PAD))) continue;
|
|
47360
|
+
placedRects.push(rect);
|
|
47361
|
+
placed.push({
|
|
47362
|
+
x: cand.cx,
|
|
47363
|
+
y: cand.cy,
|
|
47364
|
+
text: cand.text,
|
|
47365
|
+
anchor: "middle",
|
|
47366
|
+
color: cand.color,
|
|
47367
|
+
// No halo: the bg-coloured outline reads as a ghost box behind the text
|
|
47368
|
+
// over the tinted water/land. Context labels are muted enough to sit
|
|
47369
|
+
// cleanly on the basemap without one.
|
|
47370
|
+
halo: false,
|
|
47371
|
+
haloColor,
|
|
47372
|
+
italic: cand.italic,
|
|
47373
|
+
letterSpacing: cand.letterSpacing,
|
|
47374
|
+
...cand.lines.length > 1 ? { lines: cand.lines } : {},
|
|
47375
|
+
lineNumber: 0
|
|
47376
|
+
});
|
|
47377
|
+
}
|
|
47378
|
+
return placed;
|
|
47379
|
+
}
|
|
47380
|
+
var FONT, LINE_HEIGHT, PADX, PADY, WATER_LETTER_SPACING, CONTEXT_PAD, EDGE_CLAMP_MARGIN, EDGE_CLAMP_OVERSHOOT, KIND_ORDER;
|
|
47381
|
+
var init_context_labels = __esm({
|
|
47382
|
+
"src/map/context-labels.ts"() {
|
|
47383
|
+
"use strict";
|
|
47384
|
+
init_color_utils();
|
|
47385
|
+
init_legend_constants();
|
|
47386
|
+
FONT = 11;
|
|
47387
|
+
LINE_HEIGHT = FONT + 2;
|
|
47388
|
+
PADX = 4;
|
|
47389
|
+
PADY = 3;
|
|
47390
|
+
WATER_LETTER_SPACING = 1.5;
|
|
47391
|
+
CONTEXT_PAD = 4;
|
|
47392
|
+
EDGE_CLAMP_MARGIN = 8;
|
|
47393
|
+
EDGE_CLAMP_OVERSHOOT = 0.35;
|
|
47394
|
+
KIND_ORDER = {
|
|
47395
|
+
ocean: 0,
|
|
47396
|
+
sea: 1,
|
|
47397
|
+
gulf: 2,
|
|
47398
|
+
bay: 3,
|
|
47399
|
+
strait: 4,
|
|
47400
|
+
channel: 5,
|
|
47401
|
+
sound: 6
|
|
47402
|
+
};
|
|
47403
|
+
}
|
|
47404
|
+
});
|
|
47405
|
+
|
|
46647
47406
|
// src/map/layout.ts
|
|
46648
47407
|
function geomObject2(topo) {
|
|
46649
47408
|
const key = Object.keys(topo.objects)[0];
|
|
46650
47409
|
return topo.objects[key];
|
|
46651
47410
|
}
|
|
47411
|
+
function mergeFeatures(a, b) {
|
|
47412
|
+
const polysOf = (f) => {
|
|
47413
|
+
const g = f.geometry;
|
|
47414
|
+
if (!g) return null;
|
|
47415
|
+
if (g.type === "Polygon") return [g.coordinates];
|
|
47416
|
+
if (g.type === "MultiPolygon") return g.coordinates;
|
|
47417
|
+
return null;
|
|
47418
|
+
};
|
|
47419
|
+
const pa = polysOf(a);
|
|
47420
|
+
const pb = polysOf(b);
|
|
47421
|
+
if (!pa || !pb) return a;
|
|
47422
|
+
return {
|
|
47423
|
+
...a,
|
|
47424
|
+
geometry: { type: "MultiPolygon", coordinates: [...pa, ...pb] }
|
|
47425
|
+
};
|
|
47426
|
+
}
|
|
46652
47427
|
function decodeLayer(topo) {
|
|
47428
|
+
const cached = decodeCache.get(topo);
|
|
47429
|
+
if (cached) return cached;
|
|
46653
47430
|
const out = /* @__PURE__ */ new Map();
|
|
46654
47431
|
for (const g of geomObject2(topo).geometries) {
|
|
46655
47432
|
const f = (0, import_topojson_client2.feature)(topo, g);
|
|
46656
|
-
|
|
47433
|
+
if (!f.geometry) continue;
|
|
47434
|
+
const tagged = { ...f, id: g.id };
|
|
47435
|
+
const existing = out.get(g.id);
|
|
47436
|
+
out.set(g.id, existing ? mergeFeatures(existing, tagged) : tagged);
|
|
46657
47437
|
}
|
|
47438
|
+
decodeCache.set(topo, out);
|
|
46658
47439
|
return out;
|
|
46659
47440
|
}
|
|
46660
47441
|
function projectionFor(family) {
|
|
@@ -46663,9 +47444,12 @@ function projectionFor(family) {
|
|
|
46663
47444
|
return usConusProjection();
|
|
46664
47445
|
case "mercator":
|
|
46665
47446
|
return (0, import_d3_geo2.geoMercator)();
|
|
47447
|
+
case "equal-earth":
|
|
47448
|
+
return (0, import_d3_geo2.geoEqualEarth)();
|
|
47449
|
+
case "equirectangular":
|
|
47450
|
+
return (0, import_d3_geo2.geoEquirectangular)();
|
|
46666
47451
|
case "natural-earth":
|
|
46667
47452
|
return (0, import_d3_geo2.geoNaturalEarth1)();
|
|
46668
|
-
case "equirectangular":
|
|
46669
47453
|
default:
|
|
46670
47454
|
return (0, import_d3_geo2.geoEquirectangular)();
|
|
46671
47455
|
}
|
|
@@ -46684,13 +47468,11 @@ function mapNeutralLandColor(palette, isDark, _dataActive = false) {
|
|
|
46684
47468
|
isDark ? LAND_TINT_DARK : LAND_TINT_LIGHT
|
|
46685
47469
|
);
|
|
46686
47470
|
}
|
|
46687
|
-
function
|
|
46688
|
-
const { palette, isDark } = opts;
|
|
46689
|
-
const { width, height } = size;
|
|
47471
|
+
function buildMapProjection(resolved, data) {
|
|
46690
47472
|
const wantsUsStates = resolved.basemaps.subdivisions.includes("us-states");
|
|
46691
|
-
const usCrisp = resolved.projection === "albers-usa" && wantsUsStates && !!data.naLand;
|
|
47473
|
+
const usCrisp = (resolved.projection === "albers-usa" || resolved.projection === "mercator") && wantsUsStates && !!data.naLand;
|
|
46692
47474
|
const worldTopo = usCrisp ? data.worldDetail : resolved.basemaps.world === "detail" ? data.worldDetail : data.worldCoarse;
|
|
46693
|
-
const worldLayer = decodeLayer(worldTopo);
|
|
47475
|
+
const worldLayer = new Map(decodeLayer(worldTopo));
|
|
46694
47476
|
if (usCrisp && data.naLand) {
|
|
46695
47477
|
const [nbW, nbS, nbE, nbN] = [-140, 10, -52, 66];
|
|
46696
47478
|
const crisp = decodeLayer(data.naLand);
|
|
@@ -46699,16 +47481,109 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46699
47481
|
if (!base) continue;
|
|
46700
47482
|
const [[bw, bs], [be, bn]] = (0, import_d3_geo2.geoBounds)(base);
|
|
46701
47483
|
if (bw >= nbW && be <= nbE && bs >= nbS && bn <= nbN)
|
|
46702
|
-
worldLayer.set(iso, cf);
|
|
47484
|
+
worldLayer.set(iso, { ...cf, properties: base.properties });
|
|
46703
47485
|
}
|
|
46704
47486
|
}
|
|
46705
47487
|
const usLayer = wantsUsStates ? decodeLayer(data.usStates) : null;
|
|
47488
|
+
const extentOutline = () => {
|
|
47489
|
+
const [[w, s], [e, n]] = resolved.extent;
|
|
47490
|
+
const N = 16;
|
|
47491
|
+
const coords = [];
|
|
47492
|
+
for (let i = 0; i <= N; i++) {
|
|
47493
|
+
const t = i / N;
|
|
47494
|
+
const lon = w + (e - w) * t;
|
|
47495
|
+
const lat = s + (n - s) * t;
|
|
47496
|
+
coords.push([lon, s], [lon, n], [w, lat], [e, lat]);
|
|
47497
|
+
}
|
|
47498
|
+
return {
|
|
47499
|
+
type: "Feature",
|
|
47500
|
+
properties: {},
|
|
47501
|
+
geometry: { type: "MultiPoint", coordinates: coords }
|
|
47502
|
+
};
|
|
47503
|
+
};
|
|
47504
|
+
let fitFeatures;
|
|
47505
|
+
if (resolved.projection === "albers-usa" && usLayer) {
|
|
47506
|
+
fitFeatures = [...usLayer.entries()].filter(([iso]) => !US_NON_CONUS.has(iso)).map(([, f]) => f);
|
|
47507
|
+
const neighborPoints = resolved.pois.filter((p) => !inAlaska(p.lon, p.lat) && !inHawaii(p.lon, p.lat)).map((p) => [p.lon, p.lat]);
|
|
47508
|
+
if (neighborPoints.length > 0) {
|
|
47509
|
+
fitFeatures.push({
|
|
47510
|
+
type: "Feature",
|
|
47511
|
+
properties: {},
|
|
47512
|
+
geometry: { type: "MultiPoint", coordinates: neighborPoints }
|
|
47513
|
+
});
|
|
47514
|
+
}
|
|
47515
|
+
for (const r of resolved.regions) {
|
|
47516
|
+
if (r.layer === "country" && (r.iso === "CA" || r.iso === "MX")) {
|
|
47517
|
+
const cf = worldLayer.get(r.iso);
|
|
47518
|
+
if (cf) fitFeatures.push(cf);
|
|
47519
|
+
}
|
|
47520
|
+
}
|
|
47521
|
+
} else {
|
|
47522
|
+
fitFeatures = [extentOutline()];
|
|
47523
|
+
}
|
|
47524
|
+
const fitTarget = { type: "FeatureCollection", features: fitFeatures };
|
|
47525
|
+
const projection = projectionFor(resolved.projection);
|
|
47526
|
+
if (resolved.projection !== "albers-usa") {
|
|
47527
|
+
let centerLon = (resolved.extent[0][0] + resolved.extent[1][0]) / 2;
|
|
47528
|
+
if (centerLon > 180) centerLon -= 360;
|
|
47529
|
+
projection.rotate([-centerLon, 0]);
|
|
47530
|
+
}
|
|
47531
|
+
const fitGB = (0, import_d3_geo2.geoBounds)(fitTarget);
|
|
47532
|
+
const fitIsGlobal = fitGB[1][0] - fitGB[0][0] >= 270 || fitGB[1][1] - fitGB[0][1] >= 130;
|
|
47533
|
+
return {
|
|
47534
|
+
projection,
|
|
47535
|
+
fitTarget,
|
|
47536
|
+
fitIsGlobal,
|
|
47537
|
+
worldLayer,
|
|
47538
|
+
usLayer,
|
|
47539
|
+
usCrisp,
|
|
47540
|
+
wantsUsStates,
|
|
47541
|
+
worldTopo
|
|
47542
|
+
};
|
|
47543
|
+
}
|
|
47544
|
+
function parsePathRings(d) {
|
|
47545
|
+
const rings = [];
|
|
47546
|
+
let cur = [];
|
|
47547
|
+
const re = /([MLZ])([^MLZ]*)/g;
|
|
47548
|
+
let m;
|
|
47549
|
+
while (m = re.exec(d)) {
|
|
47550
|
+
if (m[1] === "Z") {
|
|
47551
|
+
if (cur.length) rings.push(cur);
|
|
47552
|
+
cur = [];
|
|
47553
|
+
continue;
|
|
47554
|
+
}
|
|
47555
|
+
if (m[1] === "M" && cur.length) {
|
|
47556
|
+
rings.push(cur);
|
|
47557
|
+
cur = [];
|
|
47558
|
+
}
|
|
47559
|
+
const nums = m[2].split(/[ ,]+/).map(Number);
|
|
47560
|
+
for (let i = 0; i + 1 < nums.length; i += 2) {
|
|
47561
|
+
const x = nums[i];
|
|
47562
|
+
const y = nums[i + 1];
|
|
47563
|
+
if (Number.isFinite(x) && Number.isFinite(y)) cur.push([x, y]);
|
|
47564
|
+
}
|
|
47565
|
+
}
|
|
47566
|
+
if (cur.length) rings.push(cur);
|
|
47567
|
+
return rings;
|
|
47568
|
+
}
|
|
47569
|
+
function layoutMap(resolved, data, size, opts) {
|
|
47570
|
+
const { palette, isDark } = opts;
|
|
47571
|
+
const { width, height } = size;
|
|
47572
|
+
const {
|
|
47573
|
+
projection,
|
|
47574
|
+
fitTarget,
|
|
47575
|
+
fitIsGlobal,
|
|
47576
|
+
worldLayer,
|
|
47577
|
+
usLayer,
|
|
47578
|
+
usCrisp,
|
|
47579
|
+
worldTopo
|
|
47580
|
+
} = buildMapProjection(resolved, data);
|
|
46706
47581
|
const usContext = usLayer !== null;
|
|
46707
47582
|
const regionStroke = isDark ? mix(palette.bg, palette.text, 78) : mix(palette.text, palette.bg, 78);
|
|
46708
47583
|
const values = resolved.regions.filter((r) => r.value !== void 0).map((r) => r.value);
|
|
46709
|
-
const
|
|
46710
|
-
const rampMin =
|
|
46711
|
-
const rampMax =
|
|
47584
|
+
const allNonNegative = values.length > 0 && values.every((v) => v >= 0);
|
|
47585
|
+
const rampMin = allNonNegative ? 0 : Math.min(...values);
|
|
47586
|
+
const rampMax = Math.max(...values);
|
|
46712
47587
|
const rampHue = resolveColor(resolved.directives.regionMetricColor ?? "", palette) ?? palette.colors.red;
|
|
46713
47588
|
const hasRamp = values.length > 0;
|
|
46714
47589
|
const VALUE_NAME = hasRamp ? resolved.directives.regionMetric?.trim() || "Value" : null;
|
|
@@ -46729,7 +47604,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46729
47604
|
activeGroup = VALUE_NAME ?? (resolved.tagGroups.length > 0 ? resolved.tagGroups[0].name : null);
|
|
46730
47605
|
}
|
|
46731
47606
|
const activeIsScore = VALUE_NAME !== null && activeGroup === VALUE_NAME;
|
|
46732
|
-
const mutedBasemap =
|
|
47607
|
+
const mutedBasemap = activeGroup !== null;
|
|
46733
47608
|
const neutralFill = mapNeutralLandColor(palette, isDark, mutedBasemap);
|
|
46734
47609
|
const water = mapBackgroundColor(palette, isDark, mutedBasemap);
|
|
46735
47610
|
const lakeStroke = mix(regionStroke, water, 45);
|
|
@@ -46738,6 +47613,39 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46738
47613
|
palette.bg,
|
|
46739
47614
|
mutedBasemap ? isDark ? MUTED_FOREIGN_DARK : MUTED_FOREIGN_LIGHT : isDark ? FOREIGN_TINT_DARK : FOREIGN_TINT_LIGHT
|
|
46740
47615
|
);
|
|
47616
|
+
const colorizeActive = resolved.directives.noColorize !== true && !hasRamp && resolved.tagGroups.length === 0;
|
|
47617
|
+
const colorByIso = /* @__PURE__ */ new Map();
|
|
47618
|
+
if (colorizeActive) {
|
|
47619
|
+
const adjacency = /* @__PURE__ */ new Map();
|
|
47620
|
+
const addEdges = (src) => {
|
|
47621
|
+
for (const [iso, ns] of src) {
|
|
47622
|
+
const cur = adjacency.get(iso);
|
|
47623
|
+
if (cur) cur.push(...ns);
|
|
47624
|
+
else adjacency.set(iso, [...ns]);
|
|
47625
|
+
}
|
|
47626
|
+
};
|
|
47627
|
+
addEdges(buildAdjacency(worldTopo));
|
|
47628
|
+
if (usLayer) {
|
|
47629
|
+
addEdges(buildAdjacency(data.usStates));
|
|
47630
|
+
for (const [country, states] of Object.entries(FOREIGN_BORDER)) {
|
|
47631
|
+
const cn = adjacency.get(country);
|
|
47632
|
+
if (!cn) continue;
|
|
47633
|
+
for (const st of states) {
|
|
47634
|
+
const sn = adjacency.get(st);
|
|
47635
|
+
if (!sn) continue;
|
|
47636
|
+
cn.push(st);
|
|
47637
|
+
sn.push(country);
|
|
47638
|
+
}
|
|
47639
|
+
}
|
|
47640
|
+
}
|
|
47641
|
+
const { byIso, huesNeeded } = assignColors(
|
|
47642
|
+
[...adjacency.keys()],
|
|
47643
|
+
adjacency
|
|
47644
|
+
);
|
|
47645
|
+
const tints = politicalTints(palette, huesNeeded, isDark);
|
|
47646
|
+
for (const [iso, idx] of byIso) colorByIso.set(iso, tints[idx]);
|
|
47647
|
+
}
|
|
47648
|
+
const colorizeStroke = (fill2) => mix(fill2, palette.text, 35);
|
|
46741
47649
|
const rampBase = isDark ? mix(palette.surface, palette.text, 28) : palette.bg;
|
|
46742
47650
|
const fillForValue = (s) => {
|
|
46743
47651
|
const t = rampMax > rampMin ? (s - rampMin) / (rampMax - rampMin) : 1;
|
|
@@ -46773,43 +47681,15 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46773
47681
|
if (activeIsScore) {
|
|
46774
47682
|
return r.value !== void 0 ? fillForValue(r.value) : neutralFill;
|
|
46775
47683
|
}
|
|
47684
|
+
if (colorizeActive) return (r.iso && colorByIso.get(r.iso)) ?? neutralFill;
|
|
46776
47685
|
return tagFill(r.tags, activeGroup) ?? neutralFill;
|
|
46777
47686
|
};
|
|
46778
47687
|
const regionById = new Map(resolved.regions.map((r) => [r.iso, r]));
|
|
46779
|
-
const
|
|
46780
|
-
const [[w, s], [e, n]] = resolved.extent;
|
|
46781
|
-
const N = 16;
|
|
46782
|
-
const coords = [];
|
|
46783
|
-
for (let i = 0; i <= N; i++) {
|
|
46784
|
-
const t = i / N;
|
|
46785
|
-
const lon = w + (e - w) * t;
|
|
46786
|
-
const lat = s + (n - s) * t;
|
|
46787
|
-
coords.push([lon, s], [lon, n], [w, lat], [e, lat]);
|
|
46788
|
-
}
|
|
46789
|
-
return {
|
|
46790
|
-
type: "Feature",
|
|
46791
|
-
properties: {},
|
|
46792
|
-
geometry: { type: "MultiPoint", coordinates: coords }
|
|
46793
|
-
};
|
|
46794
|
-
};
|
|
46795
|
-
let fitFeatures;
|
|
46796
|
-
if (resolved.projection === "albers-usa" && usLayer) {
|
|
46797
|
-
fitFeatures = [...usLayer.entries()].filter(([iso]) => !US_NON_CONUS.has(iso)).map(([, f]) => f);
|
|
46798
|
-
} else {
|
|
46799
|
-
fitFeatures = [extentOutline()];
|
|
46800
|
-
}
|
|
46801
|
-
const fitTarget = { type: "FeatureCollection", features: fitFeatures };
|
|
46802
|
-
const projection = projectionFor(resolved.projection);
|
|
46803
|
-
if (resolved.projection !== "albers-usa") {
|
|
46804
|
-
let centerLon = (resolved.extent[0][0] + resolved.extent[1][0]) / 2;
|
|
46805
|
-
if (centerLon > 180) centerLon -= 360;
|
|
46806
|
-
projection.rotate([-centerLon, 0]);
|
|
46807
|
-
}
|
|
46808
|
-
const TITLE_GAP = 16;
|
|
47688
|
+
const TITLE_GAP2 = 16;
|
|
46809
47689
|
let topPad = FIT_PAD;
|
|
46810
47690
|
if (resolved.title && resolved.pois.length > 0) {
|
|
46811
47691
|
const bannerBottom = (resolved.subtitle ? TITLE_Y + TITLE_FONT_SIZE : TITLE_Y) + TITLE_FONT_SIZE / 2;
|
|
46812
|
-
topPad = Math.max(FIT_PAD, bannerBottom +
|
|
47692
|
+
topPad = Math.max(FIT_PAD, bannerBottom + TITLE_GAP2);
|
|
46813
47693
|
}
|
|
46814
47694
|
const fitBox = [
|
|
46815
47695
|
[FIT_PAD, topPad],
|
|
@@ -46819,12 +47699,10 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46819
47699
|
]
|
|
46820
47700
|
];
|
|
46821
47701
|
projection.fitExtent(fitBox, fitTarget);
|
|
46822
|
-
const fitGB = (0, import_d3_geo2.geoBounds)(fitTarget);
|
|
46823
|
-
const fitIsGlobal = fitGB[1][0] - fitGB[0][0] >= 270 || fitGB[1][1] - fitGB[0][1] >= 130;
|
|
46824
47702
|
let path;
|
|
46825
47703
|
let project;
|
|
46826
47704
|
let stretchParams = null;
|
|
46827
|
-
if (fitIsGlobal) {
|
|
47705
|
+
if (fitIsGlobal && !opts.preferContain) {
|
|
46828
47706
|
const cb = (0, import_d3_geo2.geoPath)(projection).bounds(fitTarget);
|
|
46829
47707
|
const bx0 = cb[0][0];
|
|
46830
47708
|
const by0 = cb[0][1];
|
|
@@ -46866,7 +47744,9 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46866
47744
|
const insets = [];
|
|
46867
47745
|
const insetRegions = [];
|
|
46868
47746
|
const insetLabelSeeds = [];
|
|
46869
|
-
|
|
47747
|
+
const akRef = resolved.regions.some((r) => r.iso === "US-AK") || resolved.pois.some((p) => inAlaska(p.lon, p.lat));
|
|
47748
|
+
const hiRef = resolved.regions.some((r) => r.iso === "US-HI") || resolved.pois.some((p) => inHawaii(p.lon, p.lat));
|
|
47749
|
+
if (resolved.projection === "albers-usa" && usLayer && (akRef || hiRef)) {
|
|
46870
47750
|
const PAD = 8;
|
|
46871
47751
|
const GAP = 12;
|
|
46872
47752
|
const yB = height - FIT_PAD;
|
|
@@ -46931,8 +47811,18 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46931
47811
|
);
|
|
46932
47812
|
const d = (0, import_d3_geo2.geoPath)(proj)(f) ?? "";
|
|
46933
47813
|
if (!d) return xr;
|
|
47814
|
+
let contextLand;
|
|
47815
|
+
if (iso === "US-AK") {
|
|
47816
|
+
const can = worldLayer.get("CA");
|
|
47817
|
+
const cd = can ? (0, import_d3_geo2.geoPath)(proj)(can) ?? "" : "";
|
|
47818
|
+
if (cd)
|
|
47819
|
+
contextLand = {
|
|
47820
|
+
d: cd,
|
|
47821
|
+
fill: colorizeActive ? colorByIso.get("CA") ?? foreignFill : foreignFill
|
|
47822
|
+
};
|
|
47823
|
+
}
|
|
46934
47824
|
const r = regionById.get(iso);
|
|
46935
|
-
let fill2 = neutralFill;
|
|
47825
|
+
let fill2 = colorizeActive ? colorByIso.get(iso) ?? neutralFill : neutralFill;
|
|
46936
47826
|
let lineNumber = -1;
|
|
46937
47827
|
if (r?.layer === "us-state") {
|
|
46938
47828
|
fill2 = regionFill(r);
|
|
@@ -46951,13 +47841,14 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46951
47841
|
],
|
|
46952
47842
|
// The FITTED inset projection (just fit to this box) — captured so the
|
|
46953
47843
|
// geo-query can invert pixels inside the frame back to AK/HI coords.
|
|
46954
|
-
projection: proj
|
|
47844
|
+
projection: proj,
|
|
47845
|
+
...contextLand && { contextLand }
|
|
46955
47846
|
});
|
|
46956
47847
|
insetRegions.push({
|
|
46957
47848
|
id: iso,
|
|
46958
47849
|
d,
|
|
46959
47850
|
fill: fill2,
|
|
46960
|
-
stroke: regionStroke,
|
|
47851
|
+
stroke: colorizeActive ? colorizeStroke(fill2) : regionStroke,
|
|
46961
47852
|
lineNumber,
|
|
46962
47853
|
layer: "us-state",
|
|
46963
47854
|
...r?.value !== void 0 && { value: r.value },
|
|
@@ -46970,13 +47861,16 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46970
47861
|
}
|
|
46971
47862
|
return xr;
|
|
46972
47863
|
};
|
|
46973
|
-
|
|
46974
|
-
|
|
46975
|
-
alaskaProjection(),
|
|
46976
|
-
|
|
46977
|
-
|
|
46978
|
-
|
|
46979
|
-
|
|
47864
|
+
let akRight = FIT_PAD;
|
|
47865
|
+
if (akRef)
|
|
47866
|
+
akRight = placeInset("US-AK", alaskaProjection(), FIT_PAD, width * 0.15);
|
|
47867
|
+
if (hiRef)
|
|
47868
|
+
placeInset(
|
|
47869
|
+
"US-HI",
|
|
47870
|
+
hawaiiProjection(),
|
|
47871
|
+
akRef ? akRight + 24 : FIT_PAD,
|
|
47872
|
+
width * 0.1
|
|
47873
|
+
);
|
|
46980
47874
|
}
|
|
46981
47875
|
const conusFit = resolved.projection === "albers-usa" && !!usLayer;
|
|
46982
47876
|
const classifyExtent = conusFit ? (0, import_d3_geo2.geoBounds)(fitTarget) : resolved.extent;
|
|
@@ -46992,15 +47886,24 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46992
47886
|
};
|
|
46993
47887
|
const ringOverlapsView = (ring) => {
|
|
46994
47888
|
let loMin = Infinity, loMax = -Infinity, rawMin = Infinity, rawMax = -Infinity;
|
|
47889
|
+
const lons = [];
|
|
46995
47890
|
for (const [rawLon] of ring) {
|
|
46996
47891
|
const lon = normLon(rawLon);
|
|
47892
|
+
lons.push(lon);
|
|
46997
47893
|
if (lon < loMin) loMin = lon;
|
|
46998
47894
|
if (lon > loMax) loMax = lon;
|
|
46999
47895
|
if (rawLon < rawMin) rawMin = rawLon;
|
|
47000
47896
|
if (rawLon > rawMax) rawMax = rawLon;
|
|
47001
47897
|
}
|
|
47002
|
-
|
|
47003
|
-
|
|
47898
|
+
lons.sort((a, b) => a - b);
|
|
47899
|
+
let maxGap = 0;
|
|
47900
|
+
for (let i = 1; i < lons.length; i++)
|
|
47901
|
+
maxGap = Math.max(maxGap, lons[i] - lons[i - 1]);
|
|
47902
|
+
if (lons.length > 1)
|
|
47903
|
+
maxGap = Math.max(maxGap, lons[0] + 360 - lons[lons.length - 1]);
|
|
47904
|
+
const occupiedArc = 360 - maxGap;
|
|
47905
|
+
if (occupiedArc > 270) return false;
|
|
47906
|
+
if (rawMax - rawMin > 180 && occupiedArc < 90) return false;
|
|
47004
47907
|
let px0 = Infinity, py0 = Infinity, px1 = -Infinity, py1 = -Infinity, anyFinite = false;
|
|
47005
47908
|
for (const [lon, lat] of ring) {
|
|
47006
47909
|
const p = project(lon, lat);
|
|
@@ -47073,7 +47976,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47073
47976
|
const regions = [];
|
|
47074
47977
|
const pushRegionLayer = (layerFeatures, layerKind, shouldCull) => {
|
|
47075
47978
|
for (const [iso, f] of layerFeatures) {
|
|
47076
|
-
if (layerKind === "us-state" && usContext && INSET_STATES.has(iso))
|
|
47979
|
+
if (layerKind === "us-state" && usContext && resolved.projection === "albers-usa" && INSET_STATES.has(iso))
|
|
47077
47980
|
continue;
|
|
47078
47981
|
if (layerKind === "country" && usContext && iso === "US") continue;
|
|
47079
47982
|
if (layerKind === "country" && iso === "AQ" && !regionById.has("AQ"))
|
|
@@ -47085,7 +47988,8 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47085
47988
|
if (!d) continue;
|
|
47086
47989
|
const isThisLayer = r?.layer === layerKind;
|
|
47087
47990
|
const isForeign = layerKind === "country" && usContext && iso !== "US";
|
|
47088
|
-
|
|
47991
|
+
const baseFill = isForeign ? foreignFill : neutralFill;
|
|
47992
|
+
let fill2 = colorizeActive ? colorByIso.get(iso) ?? baseFill : baseFill;
|
|
47089
47993
|
let label;
|
|
47090
47994
|
let lineNumber = -1;
|
|
47091
47995
|
let layer = "base";
|
|
@@ -47094,12 +47998,14 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47094
47998
|
lineNumber = r.lineNumber;
|
|
47095
47999
|
layer = layerKind;
|
|
47096
48000
|
label = r.name;
|
|
48001
|
+
} else {
|
|
48002
|
+
label = f.properties?.name;
|
|
47097
48003
|
}
|
|
47098
48004
|
regions.push({
|
|
47099
48005
|
id: iso,
|
|
47100
48006
|
d,
|
|
47101
48007
|
fill: fill2,
|
|
47102
|
-
stroke: regionStroke,
|
|
48008
|
+
stroke: colorizeActive ? colorizeStroke(fill2) : regionStroke,
|
|
47103
48009
|
lineNumber,
|
|
47104
48010
|
layer,
|
|
47105
48011
|
...label !== void 0 && { label },
|
|
@@ -47127,9 +48033,41 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47127
48033
|
});
|
|
47128
48034
|
}
|
|
47129
48035
|
}
|
|
48036
|
+
const pointInRings = (px, py, rings) => {
|
|
48037
|
+
let inside = false;
|
|
48038
|
+
for (const ring of rings) {
|
|
48039
|
+
for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {
|
|
48040
|
+
const [xi, yi] = ring[i];
|
|
48041
|
+
const [xj, yj] = ring[j];
|
|
48042
|
+
if (yi > py !== yj > py && px < (xj - xi) * (py - yi) / (yj - yi) + xi)
|
|
48043
|
+
inside = !inside;
|
|
48044
|
+
}
|
|
48045
|
+
}
|
|
48046
|
+
return inside;
|
|
48047
|
+
};
|
|
48048
|
+
const fillHitTargets = [...regions, ...insetRegions].map((r) => ({
|
|
48049
|
+
fill: r.fill,
|
|
48050
|
+
rings: parsePathRings(r.d)
|
|
48051
|
+
}));
|
|
48052
|
+
const fillAt = (x, y) => {
|
|
48053
|
+
let hit = water;
|
|
48054
|
+
for (const t of fillHitTargets)
|
|
48055
|
+
if (pointInRings(x, y, t.rings)) hit = t.fill;
|
|
48056
|
+
return hit;
|
|
48057
|
+
};
|
|
48058
|
+
const labelOnFill = (fill2) => {
|
|
48059
|
+
const color = contrastRatio(fill2, palette.textOnFillDark) >= contrastRatio(fill2, palette.textOnFillLight) ? palette.textOnFillDark : palette.textOnFillLight;
|
|
48060
|
+
const haloColor = color === palette.textOnFillLight ? palette.textOnFillDark : palette.textOnFillLight;
|
|
48061
|
+
return {
|
|
48062
|
+
color,
|
|
48063
|
+
halo: contrastRatio(fill2, color) < REGION_LABEL_HALO_RATIO,
|
|
48064
|
+
haloColor
|
|
48065
|
+
};
|
|
48066
|
+
};
|
|
48067
|
+
const reliefAllowed = resolved.directives.noRelief !== true;
|
|
47130
48068
|
const relief = [];
|
|
47131
48069
|
let reliefHatch = null;
|
|
47132
|
-
if (
|
|
48070
|
+
if (reliefAllowed && data.mountainRanges) {
|
|
47133
48071
|
for (const [, f] of decodeLayer(data.mountainRanges)) {
|
|
47134
48072
|
const viewF = isGlobalView ? dropFrameFillers(f) : cullFeatureToView(f);
|
|
47135
48073
|
if (!viewF) continue;
|
|
@@ -47145,16 +48083,32 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47145
48083
|
if (relief.length) {
|
|
47146
48084
|
const darkTone = isDark ? palette.bg : palette.text;
|
|
47147
48085
|
const lightTone = isDark ? palette.text : palette.bg;
|
|
47148
|
-
const
|
|
48086
|
+
const reliefLandRef = colorizeActive ? isDark ? palette.surface : palette.bg : neutralFill;
|
|
48087
|
+
const landLum = relativeLuminance(reliefLandRef);
|
|
47149
48088
|
const tone = Math.abs(landLum - relativeLuminance(darkTone)) > 0.04 ? darkTone : lightTone;
|
|
47150
48089
|
reliefHatch = {
|
|
47151
|
-
color: mix(tone,
|
|
48090
|
+
color: mix(tone, reliefLandRef, RELIEF_HATCH_STRENGTH),
|
|
47152
48091
|
spacing: RELIEF_HATCH_SPACING,
|
|
47153
48092
|
width: RELIEF_HATCH_WIDTH
|
|
47154
48093
|
};
|
|
47155
48094
|
}
|
|
47156
48095
|
}
|
|
47157
|
-
|
|
48096
|
+
let coastlineStyle = null;
|
|
48097
|
+
if (resolved.directives.noCoastline !== true) {
|
|
48098
|
+
const minDim = Math.min(width, height);
|
|
48099
|
+
coastlineStyle = {
|
|
48100
|
+
color: mix(regionStroke, water, COASTLINE_STROKE_MIX),
|
|
48101
|
+
// N equal-width rings: distance steps outward by COASTLINE_STEP; opacity
|
|
48102
|
+
// fades linearly from NEAR (innermost) to FAR (outermost).
|
|
48103
|
+
lines: Array.from({ length: COASTLINE_RING_COUNT }, (_, k) => ({
|
|
48104
|
+
d: (COASTLINE_D0 + k * COASTLINE_STEP) * minDim,
|
|
48105
|
+
thickness: COASTLINE_THICKNESS * minDim,
|
|
48106
|
+
opacity: COASTLINE_OPACITY_NEAR + (COASTLINE_OPACITY_FAR - COASTLINE_OPACITY_NEAR) * k / (COASTLINE_RING_COUNT - 1)
|
|
48107
|
+
})),
|
|
48108
|
+
minExtent: (isGlobalView ? COASTLINE_MIN_EXTENT_GLOBAL : COASTLINE_MIN_EXTENT) * minDim
|
|
48109
|
+
};
|
|
48110
|
+
}
|
|
48111
|
+
const riverColor = mix(palette.colors.blue, water, 32);
|
|
47158
48112
|
const rivers = [];
|
|
47159
48113
|
if (data.rivers) {
|
|
47160
48114
|
for (const [, f] of decodeLayer(data.rivers)) {
|
|
@@ -47210,38 +48164,108 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47210
48164
|
const xy = project(p.lon, p.lat);
|
|
47211
48165
|
if (xy) projected.push({ p, xy });
|
|
47212
48166
|
}
|
|
47213
|
-
const
|
|
48167
|
+
const placePoi = (e, cx, cy, clusterId) => {
|
|
48168
|
+
const { fill: fill2, stroke: stroke2 } = poiFill(e.p);
|
|
48169
|
+
poiScreen.set(e.p.id, { cx, cy, r: radiusFor(e.p) });
|
|
48170
|
+
const num = routeNumberById.get(e.p.id);
|
|
48171
|
+
pois.push({
|
|
48172
|
+
id: e.p.id,
|
|
48173
|
+
cx,
|
|
48174
|
+
cy,
|
|
48175
|
+
r: radiusFor(e.p),
|
|
48176
|
+
fill: fill2,
|
|
48177
|
+
stroke: stroke2,
|
|
48178
|
+
lineNumber: e.p.lineNumber,
|
|
48179
|
+
implicit: !!e.p.implicit,
|
|
48180
|
+
isOrigin: originIds.has(e.p.id),
|
|
48181
|
+
...num !== void 0 && { routeNumber: num },
|
|
48182
|
+
...Object.keys(e.p.tags).length > 0 && { tags: e.p.tags },
|
|
48183
|
+
...clusterId !== void 0 && { clusterId }
|
|
48184
|
+
});
|
|
48185
|
+
};
|
|
48186
|
+
const clusters = [];
|
|
48187
|
+
const connected = /* @__PURE__ */ new Set();
|
|
48188
|
+
for (const e of resolved.edges) {
|
|
48189
|
+
connected.add(e.fromId);
|
|
48190
|
+
connected.add(e.toId);
|
|
48191
|
+
}
|
|
48192
|
+
for (const rt of resolved.routes) {
|
|
48193
|
+
rt.stopIds.forEach((id) => connected.add(id));
|
|
48194
|
+
}
|
|
48195
|
+
const radiusOf = (e) => radiusFor(e.p);
|
|
47214
48196
|
for (const e of projected) {
|
|
47215
|
-
|
|
47216
|
-
|
|
47217
|
-
|
|
47218
|
-
|
|
47219
|
-
|
|
47220
|
-
|
|
47221
|
-
|
|
47222
|
-
|
|
47223
|
-
|
|
47224
|
-
|
|
47225
|
-
|
|
47226
|
-
|
|
47227
|
-
|
|
47228
|
-
|
|
47229
|
-
|
|
47230
|
-
|
|
47231
|
-
|
|
47232
|
-
|
|
47233
|
-
|
|
47234
|
-
|
|
47235
|
-
|
|
47236
|
-
|
|
47237
|
-
|
|
47238
|
-
|
|
47239
|
-
|
|
47240
|
-
|
|
47241
|
-
|
|
47242
|
-
|
|
47243
|
-
|
|
47244
|
-
|
|
48197
|
+
if (connected.has(e.p.id)) placePoi(e, e.xy[0], e.xy[1]);
|
|
48198
|
+
}
|
|
48199
|
+
const groups = [];
|
|
48200
|
+
for (const e of projected) {
|
|
48201
|
+
if (connected.has(e.p.id)) continue;
|
|
48202
|
+
const r = radiusOf(e);
|
|
48203
|
+
const near = groups.find(
|
|
48204
|
+
(g) => g.some(
|
|
48205
|
+
(q) => Math.hypot(q.xy[0] - e.xy[0], q.xy[1] - e.xy[1]) < (r + radiusOf(q)) * STACK_OVERLAP
|
|
48206
|
+
)
|
|
48207
|
+
);
|
|
48208
|
+
if (near) near.push(e);
|
|
48209
|
+
else groups.push([e]);
|
|
48210
|
+
}
|
|
48211
|
+
for (const g of groups) {
|
|
48212
|
+
if (g.length === 1) {
|
|
48213
|
+
placePoi(g[0], g[0].xy[0], g[0].xy[1]);
|
|
48214
|
+
continue;
|
|
48215
|
+
}
|
|
48216
|
+
const clusterId = g[0].p.id;
|
|
48217
|
+
const cx0 = g.reduce((s, e) => s + e.xy[0], 0) / g.length;
|
|
48218
|
+
const cy0 = g.reduce((s, e) => s + e.xy[1], 0) / g.length;
|
|
48219
|
+
const maxR = Math.max(...g.map(radiusOf));
|
|
48220
|
+
const sep = 2 * maxR + STACK_RING_GAP;
|
|
48221
|
+
const ringR = Math.max(
|
|
48222
|
+
COLO_R,
|
|
48223
|
+
sep / (2 * Math.sin(Math.PI / Math.max(g.length, 2)))
|
|
48224
|
+
);
|
|
48225
|
+
const positions = g.map((e, i) => {
|
|
48226
|
+
if (g.length <= STACK_RING_MAX) {
|
|
48227
|
+
const ang2 = -Math.PI / 2 + i * 2 * Math.PI / g.length;
|
|
48228
|
+
return {
|
|
48229
|
+
e,
|
|
48230
|
+
mx: cx0 + Math.cos(ang2) * ringR,
|
|
48231
|
+
my: cy0 + Math.sin(ang2) * ringR
|
|
48232
|
+
};
|
|
48233
|
+
}
|
|
48234
|
+
const ang = i * GOLDEN_ANGLE;
|
|
48235
|
+
const rr = ringR * Math.sqrt((i + 1) / g.length);
|
|
48236
|
+
return { e, mx: cx0 + Math.cos(ang) * rr, my: cy0 + Math.sin(ang) * rr };
|
|
48237
|
+
});
|
|
48238
|
+
let minX = cx0 - maxR;
|
|
48239
|
+
let maxX = cx0 + maxR;
|
|
48240
|
+
let minY = cy0 - maxR;
|
|
48241
|
+
let maxY = cy0 + maxR;
|
|
48242
|
+
for (const { mx, my, e } of positions) {
|
|
48243
|
+
const r = radiusOf(e);
|
|
48244
|
+
minX = Math.min(minX, mx - r);
|
|
48245
|
+
maxX = Math.max(maxX, mx + r);
|
|
48246
|
+
minY = Math.min(minY, my - r);
|
|
48247
|
+
maxY = Math.max(maxY, my + r);
|
|
48248
|
+
}
|
|
48249
|
+
let dx = 0;
|
|
48250
|
+
let dy = 0;
|
|
48251
|
+
if (minX + dx < 2) dx = 2 - minX;
|
|
48252
|
+
if (maxX + dx > width - 2) dx = width - 2 - maxX;
|
|
48253
|
+
if (minY + dy < 2) dy = 2 - minY;
|
|
48254
|
+
if (maxY + dy > height - 2) dy = height - 2 - maxY;
|
|
48255
|
+
const legsOut = [];
|
|
48256
|
+
for (const { e, mx, my } of positions) {
|
|
48257
|
+
const fx = mx + dx;
|
|
48258
|
+
const fy = my + dy;
|
|
48259
|
+
placePoi(e, fx, fy, clusterId);
|
|
48260
|
+
legsOut.push({ x2: fx, y2: fy, color: poiFill(e.p).fill });
|
|
48261
|
+
}
|
|
48262
|
+
clusters.push({
|
|
48263
|
+
id: clusterId,
|
|
48264
|
+
cx: cx0 + dx,
|
|
48265
|
+
cy: cy0 + dy,
|
|
48266
|
+
count: g.length,
|
|
48267
|
+
hitR: ringR + maxR + 6,
|
|
48268
|
+
legs: legsOut
|
|
47245
48269
|
});
|
|
47246
48270
|
}
|
|
47247
48271
|
const legs = [];
|
|
@@ -47291,16 +48315,26 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47291
48315
|
if (!a || !b) continue;
|
|
47292
48316
|
const mx = (a.cx + b.cx) / 2;
|
|
47293
48317
|
const my = (a.cy + b.cy) / 2;
|
|
48318
|
+
const bow = {
|
|
48319
|
+
curved: leg.style === "arc",
|
|
48320
|
+
offset: 0,
|
|
48321
|
+
labelX: mx,
|
|
48322
|
+
labelY: my - 4
|
|
48323
|
+
};
|
|
48324
|
+
const routeLabelStyle = leg.label !== void 0 ? labelOnFill(fillAt(bow.labelX, bow.labelY)) : void 0;
|
|
47294
48325
|
legs.push({
|
|
47295
|
-
d: legPath(a, b,
|
|
48326
|
+
d: legPath(a, b, bow.curved, bow.offset),
|
|
47296
48327
|
width: routeWidthFor(Number(leg.value)),
|
|
47297
48328
|
color: mix(palette.text, palette.bg, 72),
|
|
47298
48329
|
arrow: true,
|
|
47299
48330
|
lineNumber: leg.lineNumber,
|
|
47300
48331
|
...leg.label !== void 0 && {
|
|
47301
48332
|
label: leg.label,
|
|
47302
|
-
labelX:
|
|
47303
|
-
labelY:
|
|
48333
|
+
labelX: bow.labelX,
|
|
48334
|
+
labelY: bow.labelY,
|
|
48335
|
+
labelColor: routeLabelStyle.color,
|
|
48336
|
+
labelHalo: routeLabelStyle.halo,
|
|
48337
|
+
labelHaloColor: routeLabelStyle.haloColor
|
|
47304
48338
|
}
|
|
47305
48339
|
});
|
|
47306
48340
|
}
|
|
@@ -47328,20 +48362,29 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47328
48362
|
const a = poiScreen.get(e.fromId);
|
|
47329
48363
|
const b = poiScreen.get(e.toId);
|
|
47330
48364
|
if (!a || !b) return;
|
|
47331
|
-
const
|
|
47332
|
-
const offset = n > 1 ? (i - (n - 1) / 2) * FAN_STEP : 0;
|
|
48365
|
+
const fanOffset = n > 1 ? (i - (n - 1) / 2) * FAN_STEP : 0;
|
|
47333
48366
|
const mx = (a.cx + b.cx) / 2;
|
|
47334
48367
|
const my = (a.cy + b.cy) / 2;
|
|
48368
|
+
const bow = {
|
|
48369
|
+
curved: e.style === "arc" || n > 1,
|
|
48370
|
+
offset: fanOffset,
|
|
48371
|
+
labelX: mx,
|
|
48372
|
+
labelY: my - 4
|
|
48373
|
+
};
|
|
48374
|
+
const edgeLabelStyle = e.label !== void 0 ? labelOnFill(fillAt(bow.labelX, bow.labelY)) : void 0;
|
|
47335
48375
|
legs.push({
|
|
47336
|
-
d: legPath(a, b, curved, offset),
|
|
48376
|
+
d: legPath(a, b, bow.curved, bow.offset),
|
|
47337
48377
|
width: widthFor(e),
|
|
47338
48378
|
color: mix(palette.text, palette.bg, 66),
|
|
47339
48379
|
arrow: e.directed,
|
|
47340
48380
|
lineNumber: e.lineNumber,
|
|
47341
48381
|
...e.label !== void 0 && {
|
|
47342
48382
|
label: e.label,
|
|
47343
|
-
labelX:
|
|
47344
|
-
labelY:
|
|
48383
|
+
labelX: bow.labelX,
|
|
48384
|
+
labelY: bow.labelY,
|
|
48385
|
+
labelColor: edgeLabelStyle.color,
|
|
48386
|
+
labelHalo: edgeLabelStyle.halo,
|
|
48387
|
+
labelHaloColor: edgeLabelStyle.haloColor
|
|
47345
48388
|
}
|
|
47346
48389
|
});
|
|
47347
48390
|
});
|
|
@@ -47383,25 +48426,25 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47383
48426
|
}
|
|
47384
48427
|
}
|
|
47385
48428
|
const collides = (rect) => markers.some((m) => rectCircleOverlap(rect, m)) || obstacles.some((o) => rectsOverlap(rect, o)) || legSegments.some((s) => segmentRectOverlap(s[0], s[1], s[2], s[3], rect));
|
|
47386
|
-
const
|
|
48429
|
+
const showRegionLabels = resolved.directives.noRegionLabels !== true;
|
|
48430
|
+
const isCompact = width < COMPACT_WIDTH_PX;
|
|
47387
48431
|
const LABEL_PADX = 6;
|
|
47388
48432
|
const LABEL_PADY = 3;
|
|
47389
|
-
const labelW = (text) => measureLegendText(text,
|
|
47390
|
-
const labelH =
|
|
48433
|
+
const labelW = (text) => measureLegendText(text, FONT2) + 2 * LABEL_PADX;
|
|
48434
|
+
const labelH = FONT2 + 2 * LABEL_PADY;
|
|
47391
48435
|
const pushRegionLabel = (x, y, text, fill2, lineNumber) => {
|
|
47392
|
-
const color =
|
|
47393
|
-
|
|
47394
|
-
|
|
47395
|
-
|
|
48436
|
+
const { color, haloColor } = labelOnFill(fill2);
|
|
48437
|
+
const halfW = measureLegendText(text, FONT2) / 2;
|
|
48438
|
+
const overflows = [y - FONT2 * 0.55, y - FONT2 * 0.1].some(
|
|
48439
|
+
(sy) => fillAt(x - halfW, sy) !== fill2 || fillAt(x + halfW, sy) !== fill2
|
|
47396
48440
|
);
|
|
47397
|
-
const haloColor = color === palette.textOnFillLight ? palette.textOnFillDark : palette.textOnFillLight;
|
|
47398
48441
|
labels.push({
|
|
47399
48442
|
x,
|
|
47400
48443
|
y,
|
|
47401
48444
|
text,
|
|
47402
48445
|
anchor: "middle",
|
|
47403
48446
|
color,
|
|
47404
|
-
halo:
|
|
48447
|
+
halo: overflows,
|
|
47405
48448
|
haloColor,
|
|
47406
48449
|
lineNumber
|
|
47407
48450
|
});
|
|
@@ -47410,21 +48453,50 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47410
48453
|
US: [-98.5, 39.5]
|
|
47411
48454
|
// CONUS geographic centre (near Lebanon, Kansas)
|
|
47412
48455
|
};
|
|
47413
|
-
|
|
47414
|
-
|
|
47415
|
-
|
|
47416
|
-
|
|
47417
|
-
|
|
48456
|
+
const REGION_LABEL_GAP = 2;
|
|
48457
|
+
const regionLabelRect = (cx, cy, text) => {
|
|
48458
|
+
const w = measureLegendText(text, FONT2) + 2 * REGION_LABEL_GAP;
|
|
48459
|
+
return { x: cx - w / 2, y: cy - FONT2 / 2, w, h: FONT2 };
|
|
48460
|
+
};
|
|
48461
|
+
if (showRegionLabels) {
|
|
48462
|
+
const frameContainers = new Set(resolved.poiFrameContainers);
|
|
48463
|
+
const entries = regions.map((r) => {
|
|
48464
|
+
const isContainer = frameContainers.has(r.id);
|
|
48465
|
+
if (r.layer === "base" && !isContainer || r.label === void 0)
|
|
48466
|
+
return null;
|
|
48467
|
+
const isUsState = r.layer === "us-state" || r.id.startsWith("US-");
|
|
48468
|
+
const f = isUsState ? usLayer?.get(r.id) : worldLayer.get(r.id);
|
|
48469
|
+
if (!f) return null;
|
|
47418
48470
|
const [[x0, y0], [x1, y1]] = path.bounds(f);
|
|
47419
|
-
const
|
|
47420
|
-
|
|
47421
|
-
const
|
|
48471
|
+
const boxW = x1 - x0;
|
|
48472
|
+
const boxH = y1 - y0;
|
|
48473
|
+
const abbrev = isUsState ? r.id.replace(/^US-/, "") : void 0;
|
|
48474
|
+
const candidates = abbrev !== void 0 ? isCompact ? [abbrev, r.label] : [r.label, abbrev] : [r.label];
|
|
48475
|
+
const anchor = !isUsState ? WORLD_LABEL_ANCHORS[r.id] : void 0;
|
|
47422
48476
|
const c = anchor ? project(anchor[0], anchor[1]) : path.centroid(f);
|
|
47423
|
-
if (!c || !Number.isFinite(c[0]))
|
|
48477
|
+
if (!c || !Number.isFinite(c[0])) return null;
|
|
48478
|
+
return { r, c, boxW, boxH, area: boxW * boxH, candidates };
|
|
48479
|
+
}).filter((e) => e !== null).sort((a, b) => b.area - a.area || a.r.lineNumber - b.r.lineNumber);
|
|
48480
|
+
const placedRegionRects = [];
|
|
48481
|
+
const POI_LABEL_PAD = 14;
|
|
48482
|
+
const poiObstacles = pois.map((p) => ({
|
|
48483
|
+
x: p.cx - p.r - POI_LABEL_PAD,
|
|
48484
|
+
y: p.cy - p.r - POI_LABEL_PAD,
|
|
48485
|
+
w: 2 * (p.r + POI_LABEL_PAD),
|
|
48486
|
+
h: 2 * (p.r + POI_LABEL_PAD)
|
|
48487
|
+
}));
|
|
48488
|
+
for (const { r, c, boxW, boxH, candidates } of entries) {
|
|
48489
|
+
const text = candidates.find((t) => {
|
|
48490
|
+
if (labelW(t) > boxW || labelH > boxH) return false;
|
|
48491
|
+
const rect = regionLabelRect(c[0], c[1], t);
|
|
48492
|
+
return !placedRegionRects.some((p) => rectsOverlap(rect, p)) && !poiObstacles.some((o) => rectsOverlap(rect, o));
|
|
48493
|
+
});
|
|
48494
|
+
if (text === void 0) continue;
|
|
48495
|
+
placedRegionRects.push(regionLabelRect(c[0], c[1], text));
|
|
47424
48496
|
pushRegionLabel(c[0], c[1], text, r.fill, r.lineNumber);
|
|
47425
48497
|
}
|
|
47426
48498
|
for (const seed of insetLabelSeeds) {
|
|
47427
|
-
const text =
|
|
48499
|
+
const text = isCompact ? seed.iso.replace(/^US-/, "") : seed.name;
|
|
47428
48500
|
const src = regionById.get(seed.iso);
|
|
47429
48501
|
pushRegionLabel(
|
|
47430
48502
|
seed.x,
|
|
@@ -47435,22 +48507,26 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47435
48507
|
);
|
|
47436
48508
|
}
|
|
47437
48509
|
}
|
|
47438
|
-
|
|
47439
|
-
|
|
47440
|
-
const ordered = [...pois].sort(
|
|
47441
|
-
(a, b) => a.lineNumber - b.lineNumber || (a.id < b.id ? -1 : 1)
|
|
47442
|
-
);
|
|
48510
|
+
if (resolved.directives.noPoiLabels !== true) {
|
|
48511
|
+
const ordered = [...pois].filter((p) => p.clusterId === void 0).sort((a, b) => a.lineNumber - b.lineNumber || (a.id < b.id ? -1 : 1));
|
|
47443
48512
|
const poiById = new Map(resolved.pois.map((q) => [q.id, q]));
|
|
47444
48513
|
const labelText = (p) => {
|
|
47445
48514
|
const src = poiById.get(p.id);
|
|
47446
48515
|
return src?.label ?? src?.name ?? p.id;
|
|
47447
48516
|
};
|
|
47448
|
-
const poiLabH =
|
|
48517
|
+
const poiLabH = FONT2 * 1.25;
|
|
47449
48518
|
const labelInfo = (p) => {
|
|
47450
48519
|
const text = labelText(p);
|
|
47451
|
-
return { text, w: measureLegendText(text,
|
|
48520
|
+
return { text, w: measureLegendText(text, FONT2) };
|
|
47452
48521
|
};
|
|
47453
48522
|
const GAP = 3;
|
|
48523
|
+
const clusterMembersById = /* @__PURE__ */ new Map();
|
|
48524
|
+
for (const p of pois) {
|
|
48525
|
+
if (p.clusterId === void 0) continue;
|
|
48526
|
+
const arr = clusterMembersById.get(p.clusterId);
|
|
48527
|
+
if (arr) arr.push(p);
|
|
48528
|
+
else clusterMembersById.set(p.clusterId, [p]);
|
|
48529
|
+
}
|
|
47454
48530
|
const inlineRect = (p, w, side) => {
|
|
47455
48531
|
switch (side) {
|
|
47456
48532
|
case "right":
|
|
@@ -47480,11 +48556,11 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47480
48556
|
const x = side === "right" ? rect.x : side === "left" ? rect.x + w : p.cx;
|
|
47481
48557
|
labels.push({
|
|
47482
48558
|
x,
|
|
47483
|
-
y: rect.y + poiLabH / 2 +
|
|
48559
|
+
y: rect.y + poiLabH / 2 + FONT2 / 3,
|
|
47484
48560
|
text,
|
|
47485
48561
|
anchor,
|
|
47486
48562
|
color: palette.text,
|
|
47487
|
-
halo:
|
|
48563
|
+
halo: false,
|
|
47488
48564
|
haloColor: palette.bg,
|
|
47489
48565
|
poiId: p.id,
|
|
47490
48566
|
lineNumber: p.lineNumber
|
|
@@ -47495,43 +48571,60 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47495
48571
|
return rect.x >= 0 && rect.x + rect.w <= width && rect.y >= 0 && rect.y + rect.h <= height && !collides(rect);
|
|
47496
48572
|
};
|
|
47497
48573
|
const GROUP_R = 30;
|
|
47498
|
-
const
|
|
48574
|
+
const groups2 = [];
|
|
47499
48575
|
for (const p of ordered) {
|
|
47500
|
-
const near =
|
|
48576
|
+
const near = groups2.find(
|
|
47501
48577
|
(g) => g.some((q) => Math.hypot(q.cx - p.cx, q.cy - p.cy) < GROUP_R)
|
|
47502
48578
|
);
|
|
47503
48579
|
if (near) near.push(p);
|
|
47504
|
-
else
|
|
48580
|
+
else groups2.push([p]);
|
|
47505
48581
|
}
|
|
47506
48582
|
const ROW_GAP2 = 3;
|
|
47507
48583
|
const step = poiLabH + ROW_GAP2;
|
|
47508
48584
|
const COL_GAP = 16;
|
|
47509
|
-
const
|
|
47510
|
-
|
|
48585
|
+
const makeItems = (group) => group.map((p) => ({ p, ...labelInfo(p) })).sort((a, b) => a.p.cy - b.p.cy || (a.text < b.text ? -1 : 1));
|
|
48586
|
+
const columnRows = (items, side) => {
|
|
47511
48587
|
const left = Math.min(...items.map((o) => o.p.cx - o.p.r));
|
|
47512
48588
|
const right = Math.max(...items.map((o) => o.p.cx + o.p.r));
|
|
47513
|
-
const cyMid = (Math.min(...items.map((o) => o.p.cy)) + Math.max(...items.map((o) => o.p.cy))) / 2;
|
|
47514
48589
|
const maxW = Math.max(...items.map((o) => o.w));
|
|
47515
|
-
const
|
|
47516
|
-
const colX = side === "right" ? right + COL_GAP : left - COL_GAP;
|
|
48590
|
+
const cyMid = (Math.min(...items.map((o) => o.p.cy)) + Math.max(...items.map((o) => o.p.cy))) / 2;
|
|
48591
|
+
const colX = side === "right" ? Math.min(right + COL_GAP, width - 2 - maxW) : Math.max(left - COL_GAP, 2 + maxW);
|
|
47517
48592
|
const totalH = items.length * step;
|
|
47518
48593
|
let startY = cyMid - totalH / 2;
|
|
47519
48594
|
startY = Math.max(2, Math.min(startY, height - totalH - 2));
|
|
47520
|
-
items.
|
|
48595
|
+
return items.map((o, i) => {
|
|
47521
48596
|
const rowCy = startY + i * step + step / 2;
|
|
47522
|
-
|
|
47523
|
-
|
|
47524
|
-
|
|
47525
|
-
|
|
47526
|
-
|
|
47527
|
-
|
|
48597
|
+
return {
|
|
48598
|
+
o,
|
|
48599
|
+
colX,
|
|
48600
|
+
rowCy,
|
|
48601
|
+
rect: {
|
|
48602
|
+
x: side === "right" ? colX : colX - o.w,
|
|
48603
|
+
y: rowCy - poiLabH / 2,
|
|
48604
|
+
w: o.w,
|
|
48605
|
+
h: poiLabH
|
|
48606
|
+
}
|
|
48607
|
+
};
|
|
48608
|
+
});
|
|
48609
|
+
};
|
|
48610
|
+
const wouldColumnBeClean = (items, side) => columnRows(items, side).every(
|
|
48611
|
+
({ rect }) => rect.x >= 0 && rect.x + rect.w <= width && rect.y >= 0 && rect.y + rect.h <= height && !collides(rect)
|
|
48612
|
+
);
|
|
48613
|
+
const defaultColumnSide = (items) => {
|
|
48614
|
+
const right = Math.max(...items.map((o) => o.p.cx + o.p.r));
|
|
48615
|
+
const maxW = Math.max(...items.map((o) => o.w));
|
|
48616
|
+
return right + COL_GAP + maxW <= width - 2 ? "right" : "left";
|
|
48617
|
+
};
|
|
48618
|
+
const commitColumn = (items, side, clusterId) => {
|
|
48619
|
+
for (const { o, colX, rowCy, rect } of columnRows(items, side)) {
|
|
48620
|
+
obstacles.push(rect);
|
|
47528
48621
|
labels.push({
|
|
47529
48622
|
x: colX,
|
|
47530
|
-
y: rowCy +
|
|
48623
|
+
y: rowCy + FONT2 / 3,
|
|
47531
48624
|
text: o.text,
|
|
47532
48625
|
anchor: side === "right" ? "start" : "end",
|
|
47533
48626
|
color: palette.text,
|
|
47534
|
-
halo:
|
|
48627
|
+
halo: false,
|
|
47535
48628
|
haloColor: palette.bg,
|
|
47536
48629
|
leader: {
|
|
47537
48630
|
x1: o.p.cx,
|
|
@@ -47541,24 +48634,141 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47541
48634
|
},
|
|
47542
48635
|
leaderColor: o.p.fill,
|
|
47543
48636
|
poiId: o.p.id,
|
|
47544
|
-
lineNumber: o.p.lineNumber
|
|
48637
|
+
lineNumber: o.p.lineNumber,
|
|
48638
|
+
...clusterId !== void 0 && { clusterMember: clusterId }
|
|
47545
48639
|
});
|
|
48640
|
+
}
|
|
48641
|
+
};
|
|
48642
|
+
const pushHidden = (p) => {
|
|
48643
|
+
const { text, w } = labelInfo(p);
|
|
48644
|
+
let x = p.cx + p.r + GAP;
|
|
48645
|
+
let anchor = "start";
|
|
48646
|
+
if (x + w > width) {
|
|
48647
|
+
x = p.cx - p.r - GAP - w;
|
|
48648
|
+
anchor = "end";
|
|
48649
|
+
}
|
|
48650
|
+
const y = Math.max(0, Math.min(p.cy - poiLabH / 2, height - poiLabH));
|
|
48651
|
+
labels.push({
|
|
48652
|
+
x: anchor === "start" ? x : x + w,
|
|
48653
|
+
y: y + poiLabH / 2 + FONT2 / 3,
|
|
48654
|
+
text,
|
|
48655
|
+
anchor,
|
|
48656
|
+
color: palette.text,
|
|
48657
|
+
halo: false,
|
|
48658
|
+
haloColor: palette.bg,
|
|
48659
|
+
poiId: p.id,
|
|
48660
|
+
hidden: true,
|
|
48661
|
+
lineNumber: p.lineNumber
|
|
47546
48662
|
});
|
|
47547
48663
|
};
|
|
47548
|
-
for (const
|
|
48664
|
+
for (const [clusterId, members] of clusterMembersById) {
|
|
48665
|
+
if (members.length === 0) continue;
|
|
48666
|
+
const items = makeItems(members);
|
|
48667
|
+
const side = wouldColumnBeClean(items, "right") ? "right" : wouldColumnBeClean(items, "left") ? "left" : defaultColumnSide(items);
|
|
48668
|
+
commitColumn(items, side, clusterId);
|
|
48669
|
+
}
|
|
48670
|
+
const maxExtent = MAX_CLUSTER_EXTENT_FACTOR * Math.min(width, height);
|
|
48671
|
+
const clusterPending = [];
|
|
48672
|
+
for (const g of groups2) {
|
|
48673
|
+
const items = makeItems(g);
|
|
47549
48674
|
if (g.length === 1) {
|
|
47550
|
-
const p =
|
|
47551
|
-
const { text, w } = labelInfo(p);
|
|
48675
|
+
const { p, text, w } = items[0];
|
|
47552
48676
|
const side = ["right", "left", "above", "below"].find(
|
|
47553
48677
|
(s) => inlineFits(p, w, s)
|
|
47554
48678
|
);
|
|
47555
|
-
if (side)
|
|
47556
|
-
|
|
47557
|
-
|
|
48679
|
+
if (side) pushInline(p, text, w, side);
|
|
48680
|
+
else commitColumn(items, defaultColumnSide(items));
|
|
48681
|
+
continue;
|
|
48682
|
+
}
|
|
48683
|
+
const left = Math.min(...items.map((o) => o.p.cx - o.p.r));
|
|
48684
|
+
const right = Math.max(...items.map((o) => o.p.cx + o.p.r));
|
|
48685
|
+
const minCy = Math.min(...items.map((o) => o.p.cy));
|
|
48686
|
+
const maxCy = Math.max(...items.map((o) => o.p.cy));
|
|
48687
|
+
const diag = Math.hypot(right - left, maxCy - minCy);
|
|
48688
|
+
if (diag > maxExtent || items.length > MAX_COLUMN_ROWS) {
|
|
48689
|
+
items.forEach((o) => pushHidden(o.p));
|
|
48690
|
+
} else {
|
|
48691
|
+
clusterPending.push(items);
|
|
48692
|
+
}
|
|
48693
|
+
}
|
|
48694
|
+
for (const items of clusterPending) {
|
|
48695
|
+
const side = ["right", "left"].find(
|
|
48696
|
+
(s) => wouldColumnBeClean(items, s)
|
|
48697
|
+
);
|
|
48698
|
+
if (side) commitColumn(items, side);
|
|
48699
|
+
else items.forEach((o) => pushHidden(o.p));
|
|
48700
|
+
}
|
|
48701
|
+
}
|
|
48702
|
+
if (resolved.directives.noContextLabels !== true) {
|
|
48703
|
+
for (const l of labels) {
|
|
48704
|
+
if (l.hidden) continue;
|
|
48705
|
+
const w = labelW(l.text);
|
|
48706
|
+
const x = l.anchor === "start" ? l.x : l.anchor === "end" ? l.x - w : l.x - w / 2;
|
|
48707
|
+
obstacles.push({ x, y: l.y - labelH / 2, w, h: labelH });
|
|
48708
|
+
}
|
|
48709
|
+
for (const box of insets)
|
|
48710
|
+
obstacles.push({ x: box.x, y: box.y, w: box.w, h: box.h });
|
|
48711
|
+
const countryCandidates = [];
|
|
48712
|
+
for (const f of worldLayer.values()) {
|
|
48713
|
+
const iso = typeof f.id === "string" ? f.id : String(f.id ?? "");
|
|
48714
|
+
if (!iso || regionById.has(iso)) continue;
|
|
48715
|
+
let hasReferencedSub = false;
|
|
48716
|
+
for (const k of regionById.keys())
|
|
48717
|
+
if (k.startsWith(iso + "-")) {
|
|
48718
|
+
hasReferencedSub = true;
|
|
48719
|
+
break;
|
|
47558
48720
|
}
|
|
48721
|
+
if (hasReferencedSub) continue;
|
|
48722
|
+
const b = path.bounds(f);
|
|
48723
|
+
const [x0, y0] = b[0];
|
|
48724
|
+
const [x1, y1] = b[1];
|
|
48725
|
+
if (!Number.isFinite(x0) || !Number.isFinite(x1)) continue;
|
|
48726
|
+
const anchorLngLat = WORLD_LABEL_ANCHORS[iso];
|
|
48727
|
+
const a = anchorLngLat ? project(anchorLngLat[0], anchorLngLat[1]) : path.centroid(f);
|
|
48728
|
+
countryCandidates.push({
|
|
48729
|
+
name: f.properties?.name ?? iso,
|
|
48730
|
+
bbox: [x0, y0, x1, y1],
|
|
48731
|
+
anchor: a && Number.isFinite(a[0]) ? [a[0], a[1]] : null
|
|
48732
|
+
});
|
|
48733
|
+
}
|
|
48734
|
+
const framedStateContainers = (resolved.poiFrameContainers ?? []).some(
|
|
48735
|
+
(id) => id.startsWith("US-")
|
|
48736
|
+
);
|
|
48737
|
+
if (usLayer && framedStateContainers) {
|
|
48738
|
+
const containerSet = new Set(resolved.poiFrameContainers);
|
|
48739
|
+
for (const [iso, f] of usLayer) {
|
|
48740
|
+
if (containerSet.has(iso) || regionById.has(iso)) continue;
|
|
48741
|
+
const viewF = cullFeatureToView(f);
|
|
48742
|
+
if (!viewF) continue;
|
|
48743
|
+
const b = path.bounds(viewF);
|
|
48744
|
+
const [x0, y0] = b[0];
|
|
48745
|
+
const [x1, y1] = b[1];
|
|
48746
|
+
if (!Number.isFinite(x0) || !Number.isFinite(x1)) continue;
|
|
48747
|
+
const a = path.centroid(viewF);
|
|
48748
|
+
countryCandidates.push({
|
|
48749
|
+
name: f.properties?.name ?? iso,
|
|
48750
|
+
bbox: [x0, y0, x1, y1],
|
|
48751
|
+
anchor: a && Number.isFinite(a[0]) ? [a[0], a[1]] : null
|
|
48752
|
+
});
|
|
47559
48753
|
}
|
|
47560
|
-
placeColumn(g);
|
|
47561
48754
|
}
|
|
48755
|
+
const contextLabels = placeContextLabels({
|
|
48756
|
+
projection: resolved.projection,
|
|
48757
|
+
dLonSpan,
|
|
48758
|
+
dLatSpan,
|
|
48759
|
+
width,
|
|
48760
|
+
height,
|
|
48761
|
+
waterBodies: data.waterBodies,
|
|
48762
|
+
countries: countryCandidates,
|
|
48763
|
+
palette,
|
|
48764
|
+
project,
|
|
48765
|
+
collides,
|
|
48766
|
+
// Water labels must stay over open water — `fillAt` returns the ocean
|
|
48767
|
+
// backdrop colour off-land and a region fill on-land (lakes/states count
|
|
48768
|
+
// as land here, which is the safe side for an ocean name).
|
|
48769
|
+
overLand: (x, y) => fillAt(x, y) !== water
|
|
48770
|
+
});
|
|
48771
|
+
labels.push(...contextLabels);
|
|
47562
48772
|
}
|
|
47563
48773
|
let legend = null;
|
|
47564
48774
|
if (!resolved.directives.noLegend) {
|
|
@@ -47595,27 +48805,33 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47595
48805
|
rivers,
|
|
47596
48806
|
relief,
|
|
47597
48807
|
reliefHatch,
|
|
48808
|
+
coastlineStyle,
|
|
47598
48809
|
legs,
|
|
47599
48810
|
pois,
|
|
48811
|
+
clusters,
|
|
47600
48812
|
labels,
|
|
47601
48813
|
legend,
|
|
47602
48814
|
insets,
|
|
47603
48815
|
insetRegions,
|
|
47604
48816
|
projection,
|
|
47605
|
-
stretch: stretchParams
|
|
48817
|
+
stretch: stretchParams,
|
|
48818
|
+
diagnostics: []
|
|
47606
48819
|
};
|
|
47607
48820
|
}
|
|
47608
|
-
var import_d3_geo2, import_topojson_client2, FIT_PAD, RAMP_FLOOR, R_DEFAULT, R_MIN, R_MAX, W_MIN, W_MAX,
|
|
48821
|
+
var import_d3_geo2, import_topojson_client2, 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;
|
|
47609
48822
|
var init_layout15 = __esm({
|
|
47610
48823
|
"src/map/layout.ts"() {
|
|
47611
48824
|
"use strict";
|
|
47612
48825
|
import_d3_geo2 = require("d3-geo");
|
|
47613
48826
|
import_topojson_client2 = require("topojson-client");
|
|
47614
48827
|
init_color_utils();
|
|
48828
|
+
init_geo();
|
|
48829
|
+
init_colorize();
|
|
47615
48830
|
init_colors();
|
|
47616
48831
|
init_label_layout();
|
|
47617
48832
|
init_legend_constants();
|
|
47618
48833
|
init_title_constants();
|
|
48834
|
+
init_context_labels();
|
|
47619
48835
|
FIT_PAD = 24;
|
|
47620
48836
|
RAMP_FLOOR = 15;
|
|
47621
48837
|
R_DEFAULT = 6;
|
|
@@ -47623,32 +48839,66 @@ var init_layout15 = __esm({
|
|
|
47623
48839
|
R_MAX = 22;
|
|
47624
48840
|
W_MIN = 1.25;
|
|
47625
48841
|
W_MAX = 8;
|
|
47626
|
-
|
|
47627
|
-
|
|
48842
|
+
FONT2 = 11;
|
|
48843
|
+
MAX_CLUSTER_EXTENT_FACTOR = 0.18;
|
|
48844
|
+
MAX_COLUMN_ROWS = 7;
|
|
48845
|
+
REGION_LABEL_HALO_RATIO = 4.5;
|
|
47628
48846
|
LAND_TINT_LIGHT = 12;
|
|
47629
48847
|
LAND_TINT_DARK = 24;
|
|
47630
48848
|
TAG_TINT_LIGHT = 60;
|
|
47631
48849
|
TAG_TINT_DARK = 68;
|
|
47632
|
-
WATER_TINT_LIGHT =
|
|
47633
|
-
WATER_TINT_DARK =
|
|
48850
|
+
WATER_TINT_LIGHT = 24;
|
|
48851
|
+
WATER_TINT_DARK = 24;
|
|
47634
48852
|
RIVER_WIDTH = 1.3;
|
|
48853
|
+
COMPACT_WIDTH_PX = 480;
|
|
47635
48854
|
RELIEF_MIN_AREA = 12;
|
|
47636
48855
|
RELIEF_MIN_DIM = 2;
|
|
47637
|
-
RELIEF_HATCH_SPACING =
|
|
47638
|
-
RELIEF_HATCH_WIDTH = 0.
|
|
48856
|
+
RELIEF_HATCH_SPACING = 2;
|
|
48857
|
+
RELIEF_HATCH_WIDTH = 0.15;
|
|
47639
48858
|
RELIEF_HATCH_STRENGTH = 32;
|
|
48859
|
+
COASTLINE_RING_COUNT = 5;
|
|
48860
|
+
COASTLINE_D0 = 16e-4;
|
|
48861
|
+
COASTLINE_STEP = 28e-4;
|
|
48862
|
+
COASTLINE_THICKNESS = 14e-4;
|
|
48863
|
+
COASTLINE_OPACITY_NEAR = 0.5;
|
|
48864
|
+
COASTLINE_OPACITY_FAR = 0.1;
|
|
48865
|
+
COASTLINE_MIN_EXTENT = 6e-4;
|
|
48866
|
+
COASTLINE_MIN_EXTENT_GLOBAL = 6e-4;
|
|
48867
|
+
COASTLINE_STROKE_MIX = 32;
|
|
47640
48868
|
FOREIGN_TINT_LIGHT = 30;
|
|
47641
48869
|
FOREIGN_TINT_DARK = 62;
|
|
47642
48870
|
MUTED_FOREIGN_LIGHT = 28;
|
|
47643
48871
|
MUTED_FOREIGN_DARK = 16;
|
|
47644
48872
|
COLO_R = 9;
|
|
47645
48873
|
GOLDEN_ANGLE = 2.399963229728653;
|
|
48874
|
+
STACK_OVERLAP = 1;
|
|
48875
|
+
STACK_RING_MAX = 8;
|
|
48876
|
+
STACK_RING_GAP = 4;
|
|
47646
48877
|
FAN_STEP = 16;
|
|
47647
48878
|
ARC_CURVE_FRAC = 0.18;
|
|
48879
|
+
decodeCache = /* @__PURE__ */ new WeakMap();
|
|
47648
48880
|
usConusProjection = () => (0, import_d3_geo2.geoConicEqualArea)().parallels([29.5, 45.5]).rotate([96, 0]);
|
|
47649
48881
|
alaskaProjection = () => (0, import_d3_geo2.geoConicEqualArea)().rotate([154, 0]).center([-2, 58.5]).parallels([55, 65]);
|
|
47650
48882
|
hawaiiProjection = () => (0, import_d3_geo2.geoMercator)();
|
|
47651
48883
|
INSET_STATES = /* @__PURE__ */ new Set(["US-AK", "US-HI"]);
|
|
48884
|
+
inAlaska = (lon, lat) => lat >= 51 && (lon <= -129 || lon >= 172);
|
|
48885
|
+
inHawaii = (lon, lat) => lat >= 18 && lat <= 23 && lon >= -161 && lon <= -154;
|
|
48886
|
+
FOREIGN_BORDER = {
|
|
48887
|
+
CA: [
|
|
48888
|
+
"US-AK",
|
|
48889
|
+
"US-WA",
|
|
48890
|
+
"US-ID",
|
|
48891
|
+
"US-MT",
|
|
48892
|
+
"US-ND",
|
|
48893
|
+
"US-MN",
|
|
48894
|
+
"US-MI",
|
|
48895
|
+
"US-NY",
|
|
48896
|
+
"US-VT",
|
|
48897
|
+
"US-NH",
|
|
48898
|
+
"US-ME"
|
|
48899
|
+
],
|
|
48900
|
+
MX: ["US-CA", "US-AZ", "US-NM", "US-TX"]
|
|
48901
|
+
};
|
|
47652
48902
|
US_NON_CONUS = /* @__PURE__ */ new Set([
|
|
47653
48903
|
"US-AK",
|
|
47654
48904
|
"US-HI",
|
|
@@ -47667,6 +48917,58 @@ __export(renderer_exports16, {
|
|
|
47667
48917
|
renderMap: () => renderMap,
|
|
47668
48918
|
renderMapForExport: () => renderMapForExport
|
|
47669
48919
|
});
|
|
48920
|
+
function pointInRing2(px, py, ring) {
|
|
48921
|
+
let inside = false;
|
|
48922
|
+
for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {
|
|
48923
|
+
const [xi, yi] = ring[i];
|
|
48924
|
+
const [xj, yj] = ring[j];
|
|
48925
|
+
if (yi > py !== yj > py && px < (xj - xi) * (py - yi) / (yj - yi) + xi)
|
|
48926
|
+
inside = !inside;
|
|
48927
|
+
}
|
|
48928
|
+
return inside;
|
|
48929
|
+
}
|
|
48930
|
+
function ringToPath(ring) {
|
|
48931
|
+
let d = "";
|
|
48932
|
+
for (let i = 0; i < ring.length; i++)
|
|
48933
|
+
d += (i ? "L" : "M") + ring[i][0] + "," + ring[i][1];
|
|
48934
|
+
return d + "Z";
|
|
48935
|
+
}
|
|
48936
|
+
function coastlineOuterRings(regions, minExtent) {
|
|
48937
|
+
const paths = [];
|
|
48938
|
+
for (const r of regions) {
|
|
48939
|
+
const rings = parsePathRings(r.d);
|
|
48940
|
+
for (let i = 0; i < rings.length; i++) {
|
|
48941
|
+
const ring = rings[i];
|
|
48942
|
+
if (ring.length < 3) continue;
|
|
48943
|
+
let minX = Infinity;
|
|
48944
|
+
let minY = Infinity;
|
|
48945
|
+
let maxX = -Infinity;
|
|
48946
|
+
let maxY = -Infinity;
|
|
48947
|
+
for (const [x, y] of ring) {
|
|
48948
|
+
if (x < minX) minX = x;
|
|
48949
|
+
if (x > maxX) maxX = x;
|
|
48950
|
+
if (y < minY) minY = y;
|
|
48951
|
+
if (y > maxY) maxY = y;
|
|
48952
|
+
}
|
|
48953
|
+
if (Math.max(maxX - minX, maxY - minY) < minExtent) continue;
|
|
48954
|
+
const [fx, fy] = ring[0];
|
|
48955
|
+
let depth = 0;
|
|
48956
|
+
for (let j = 0; j < rings.length; j++)
|
|
48957
|
+
if (j !== i && pointInRing2(fx, fy, rings[j])) depth++;
|
|
48958
|
+
if (depth % 2 === 1) continue;
|
|
48959
|
+
paths.push(ringToPath(ring));
|
|
48960
|
+
}
|
|
48961
|
+
}
|
|
48962
|
+
return paths;
|
|
48963
|
+
}
|
|
48964
|
+
function appendWaterLines(g, outerRings, style, flatWater) {
|
|
48965
|
+
const d = outerRings.join(" ");
|
|
48966
|
+
const linesOuterFirst = [...style.lines].sort((a, b) => b.d - a.d);
|
|
48967
|
+
for (const line12 of linesOuterFirst) {
|
|
48968
|
+
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");
|
|
48969
|
+
g.append("path").attr("d", d).attr("stroke", flatWater).attr("stroke-width", 2 * line12.d).attr("stroke-linejoin", "round").attr("stroke-linecap", "round");
|
|
48970
|
+
}
|
|
48971
|
+
}
|
|
47670
48972
|
function renderMap(container, resolved, data, palette, isDark, onClickItem, exportDims, activeGroupOverride) {
|
|
47671
48973
|
d3Selection18.select(container).selectAll(":not([data-d3-tooltip])").remove();
|
|
47672
48974
|
const width = exportDims?.width ?? container.clientWidth;
|
|
@@ -47679,6 +48981,11 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
47679
48981
|
{
|
|
47680
48982
|
palette,
|
|
47681
48983
|
isDark,
|
|
48984
|
+
// Export-only: forward the contain-fit request from mapExportDimensions so a
|
|
48985
|
+
// clamped/floored (off-aspect) export canvas letterboxes instead of
|
|
48986
|
+
// stretch-distorting. The in-app preview pane passes no exportDims → unset →
|
|
48987
|
+
// keeps the global stretch-fill.
|
|
48988
|
+
preferContain: exportDims?.preferContain ?? false,
|
|
47682
48989
|
...activeGroupOverride !== void 0 && {
|
|
47683
48990
|
activeGroup: activeGroupOverride
|
|
47684
48991
|
}
|
|
@@ -47692,6 +48999,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
47692
48999
|
const gRegions = svg.append("g").attr("class", "dgmo-map-regions");
|
|
47693
49000
|
const drawRegion = (g, r, strokeWidth) => {
|
|
47694
49001
|
const p = g.append("path").attr("d", r.d).attr("fill", r.fill).attr("stroke", r.stroke).attr("stroke-width", strokeWidth);
|
|
49002
|
+
if (r.label) p.attr("data-region-name", r.label);
|
|
47695
49003
|
if (r.layer !== "base") {
|
|
47696
49004
|
p.classed("dgmo-map-region", true).attr("data-region", r.id);
|
|
47697
49005
|
if (r.value !== void 0) p.attr("data-value", r.value);
|
|
@@ -47726,6 +49034,38 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
47726
49034
|
gRelief.append("line").attr("x1", 0).attr("y1", y).attr("x2", width).attr("y2", y);
|
|
47727
49035
|
}
|
|
47728
49036
|
}
|
|
49037
|
+
if (layout.coastlineStyle) {
|
|
49038
|
+
const cs = layout.coastlineStyle;
|
|
49039
|
+
const maskId = "dgmo-map-water-mask";
|
|
49040
|
+
const mask = defs.append("mask").attr("id", maskId).attr("maskUnits", "userSpaceOnUse").attr("x", 0).attr("y", 0).attr("width", width).attr("height", height);
|
|
49041
|
+
mask.append("rect").attr("x", 0).attr("y", 0).attr("width", width).attr("height", height).attr("fill", "white");
|
|
49042
|
+
const landD = layout.regions.filter((r) => r.id !== "lake").map((r) => r.d).join(" ");
|
|
49043
|
+
const lakeD = layout.regions.filter((r) => r.id === "lake").map((r) => r.d).join(" ");
|
|
49044
|
+
if (landD) mask.append("path").attr("d", landD).attr("fill", "black");
|
|
49045
|
+
if (lakeD) mask.append("path").attr("d", lakeD).attr("fill", "white");
|
|
49046
|
+
if (layout.insets.length) {
|
|
49047
|
+
const reach = Math.max(0, ...cs.lines.map((l) => l.d + l.thickness));
|
|
49048
|
+
for (const box of layout.insets) {
|
|
49049
|
+
const d = box.points.map((p, i) => `${i ? "L" : "M"}${p[0]},${p[1]}`).join("") + "Z";
|
|
49050
|
+
mask.append("path").attr("d", d).attr("fill", "black").attr("stroke", "black").attr("stroke-width", 2 * reach).attr("stroke-linejoin", "round");
|
|
49051
|
+
}
|
|
49052
|
+
}
|
|
49053
|
+
const gWater = svg.append("g").attr("class", "dgmo-map-water-lines").attr("fill", "none").attr("mask", `url(#${maskId})`);
|
|
49054
|
+
appendWaterLines(
|
|
49055
|
+
gWater,
|
|
49056
|
+
coastlineOuterRings(layout.regions, cs.minExtent),
|
|
49057
|
+
cs,
|
|
49058
|
+
layout.background
|
|
49059
|
+
);
|
|
49060
|
+
const byStroke = /* @__PURE__ */ new Map();
|
|
49061
|
+
for (const r of layout.regions) {
|
|
49062
|
+
const arr = byStroke.get(r.stroke);
|
|
49063
|
+
if (arr) arr.push(r.d);
|
|
49064
|
+
else byStroke.set(r.stroke, [r.d]);
|
|
49065
|
+
}
|
|
49066
|
+
for (const [stroke2, ds] of byStroke)
|
|
49067
|
+
gWater.append("path").attr("d", ds.join(" ")).attr("stroke", stroke2).attr("stroke-width", 0.5).attr("stroke-linejoin", "round");
|
|
49068
|
+
}
|
|
47729
49069
|
if (layout.rivers.length) {
|
|
47730
49070
|
const gRivers = svg.append("g").attr("class", "dgmo-map-rivers").attr("fill", "none");
|
|
47731
49071
|
for (const r of layout.rivers) {
|
|
@@ -47734,15 +49074,61 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
47734
49074
|
}
|
|
47735
49075
|
if (layout.insets.length) {
|
|
47736
49076
|
const insetG = svg.append("g").attr("class", "dgmo-map-insets");
|
|
47737
|
-
|
|
49077
|
+
layout.insets.forEach((box, bi) => {
|
|
47738
49078
|
const d = box.points.map((p, i) => `${i ? "L" : "M"}${p[0]},${p[1]}`).join("") + "Z";
|
|
47739
49079
|
insetG.append("path").attr("d", d).attr("fill", layout.background).attr("stroke", mix(palette.text, palette.bg, 55)).attr("stroke-width", 1).attr("stroke-linejoin", "round");
|
|
47740
|
-
|
|
49080
|
+
if (box.contextLand) {
|
|
49081
|
+
const clipId = `dgmo-map-inset-clip-${bi}`;
|
|
49082
|
+
defs.append("clipPath").attr("id", clipId).append("path").attr("d", d);
|
|
49083
|
+
insetG.append("path").attr("d", box.contextLand.d).attr("fill", box.contextLand.fill).attr("clip-path", `url(#${clipId})`);
|
|
49084
|
+
}
|
|
49085
|
+
});
|
|
47741
49086
|
for (const r of layout.insetRegions) drawRegion(insetG, r, 0.5);
|
|
47742
|
-
|
|
49087
|
+
if (layout.coastlineStyle) {
|
|
49088
|
+
const cs = layout.coastlineStyle;
|
|
49089
|
+
const maskId = "dgmo-map-inset-water-mask";
|
|
49090
|
+
const mask = defs.append("mask").attr("id", maskId).attr("maskUnits", "userSpaceOnUse").attr("x", 0).attr("y", 0).attr("width", width).attr("height", height);
|
|
49091
|
+
for (const box of layout.insets) {
|
|
49092
|
+
const d = box.points.map((p, i) => `${i ? "L" : "M"}${p[0]},${p[1]}`).join("") + "Z";
|
|
49093
|
+
mask.append("path").attr("d", d).attr("fill", "white");
|
|
49094
|
+
}
|
|
49095
|
+
layout.insets.forEach((box, bi) => {
|
|
49096
|
+
if (box.contextLand)
|
|
49097
|
+
mask.append("path").attr("d", box.contextLand.d).attr("fill", "black").attr("clip-path", `url(#dgmo-map-inset-clip-${bi})`);
|
|
49098
|
+
});
|
|
49099
|
+
for (const r of layout.insetRegions)
|
|
49100
|
+
if (r.id !== "lake")
|
|
49101
|
+
mask.append("path").attr("d", r.d).attr("fill", "black");
|
|
49102
|
+
for (const r of layout.insetRegions)
|
|
49103
|
+
if (r.id === "lake")
|
|
49104
|
+
mask.append("path").attr("d", r.d).attr("fill", "white");
|
|
49105
|
+
const clipId = "dgmo-map-inset-water-clip";
|
|
49106
|
+
const clip = defs.append("clipPath").attr("id", clipId);
|
|
49107
|
+
for (const box of layout.insets) {
|
|
49108
|
+
const d = box.points.map((p, i) => `${i ? "L" : "M"}${p[0]},${p[1]}`).join("") + "Z";
|
|
49109
|
+
clip.append("path").attr("d", d);
|
|
49110
|
+
}
|
|
49111
|
+
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})`);
|
|
49112
|
+
appendWaterLines(
|
|
49113
|
+
gInsetWater,
|
|
49114
|
+
coastlineOuterRings(layout.insetRegions, cs.minExtent),
|
|
49115
|
+
cs,
|
|
49116
|
+
layout.background
|
|
49117
|
+
);
|
|
49118
|
+
for (const r of layout.insetRegions)
|
|
49119
|
+
gInsetWater.append("path").attr("d", r.d).attr("stroke", r.stroke).attr("stroke-width", 0.5).attr("stroke-linejoin", "round");
|
|
49120
|
+
}
|
|
49121
|
+
}
|
|
49122
|
+
const wireSync = (sel, lineNumber) => {
|
|
49123
|
+
if (lineNumber < 1) return;
|
|
49124
|
+
sel.attr("data-line-number", lineNumber);
|
|
49125
|
+
if (onClickItem)
|
|
49126
|
+
sel.style("cursor", "pointer").on("click", () => onClickItem(lineNumber));
|
|
49127
|
+
};
|
|
47743
49128
|
const gLegs = svg.append("g").attr("class", "dgmo-map-legs").attr("fill", "none");
|
|
47744
49129
|
layout.legs.forEach((leg, i) => {
|
|
47745
49130
|
const p = gLegs.append("path").attr("d", leg.d).attr("stroke", leg.color).attr("stroke-width", leg.width).attr("stroke-linecap", "round");
|
|
49131
|
+
wireSync(p, leg.lineNumber);
|
|
47746
49132
|
if (leg.arrow) {
|
|
47747
49133
|
const id = `dgmo-map-arrow-${i}`;
|
|
47748
49134
|
const s = arrowSize(leg.width);
|
|
@@ -47750,25 +49136,38 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
47750
49136
|
p.attr("marker-end", `url(#${id})`);
|
|
47751
49137
|
}
|
|
47752
49138
|
if (leg.label !== void 0 && leg.labelX !== void 0) {
|
|
47753
|
-
emitText(
|
|
49139
|
+
const lt = emitText(
|
|
47754
49140
|
gLegs,
|
|
47755
49141
|
leg.labelX,
|
|
47756
49142
|
leg.labelY ?? 0,
|
|
47757
49143
|
leg.label,
|
|
47758
49144
|
"middle",
|
|
47759
|
-
palette.textMuted,
|
|
47760
|
-
haloColor,
|
|
47761
|
-
true,
|
|
49145
|
+
leg.labelColor ?? palette.textMuted,
|
|
49146
|
+
leg.labelHaloColor ?? haloColor,
|
|
49147
|
+
leg.labelHalo ?? true,
|
|
47762
49148
|
LABEL_FONT - 1
|
|
47763
49149
|
);
|
|
49150
|
+
wireSync(lt, leg.lineNumber);
|
|
47764
49151
|
}
|
|
47765
49152
|
});
|
|
49153
|
+
const gSpider = svg.append("g").attr("class", "dgmo-map-spider");
|
|
49154
|
+
for (const cl of layout.clusters) {
|
|
49155
|
+
if (!exportDims) {
|
|
49156
|
+
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");
|
|
49157
|
+
}
|
|
49158
|
+
for (const leg of cl.legs) {
|
|
49159
|
+
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");
|
|
49160
|
+
}
|
|
49161
|
+
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");
|
|
49162
|
+
}
|
|
47766
49163
|
const gPois = svg.append("g").attr("class", "dgmo-map-pois");
|
|
47767
49164
|
for (const poi of layout.pois) {
|
|
47768
49165
|
if (poi.isOrigin) {
|
|
47769
49166
|
gPois.append("circle").attr("cx", poi.cx).attr("cy", poi.cy).attr("r", poi.r + 3).attr("fill", "none").attr("stroke", poi.stroke).attr("stroke-width", 1.5);
|
|
47770
49167
|
}
|
|
47771
49168
|
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);
|
|
49169
|
+
if (poi.clusterId !== void 0)
|
|
49170
|
+
c.attr("data-cluster-member", poi.clusterId);
|
|
47772
49171
|
if (poi.tags) {
|
|
47773
49172
|
for (const [group, value] of Object.entries(poi.tags)) {
|
|
47774
49173
|
c.attr(`data-tag-${group.toLowerCase()}`, value.toLowerCase());
|
|
@@ -47796,12 +49195,32 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
47796
49195
|
}
|
|
47797
49196
|
const gLabels = svg.append("g").attr("class", "dgmo-map-labels");
|
|
47798
49197
|
for (const lab of layout.labels) {
|
|
49198
|
+
if (lab.hidden) {
|
|
49199
|
+
if (exportDims) continue;
|
|
49200
|
+
emitText(
|
|
49201
|
+
gLabels,
|
|
49202
|
+
lab.x,
|
|
49203
|
+
lab.y,
|
|
49204
|
+
lab.text,
|
|
49205
|
+
lab.anchor,
|
|
49206
|
+
lab.color,
|
|
49207
|
+
lab.haloColor,
|
|
49208
|
+
lab.halo,
|
|
49209
|
+
LABEL_FONT,
|
|
49210
|
+
lab.italic,
|
|
49211
|
+
lab.letterSpacing
|
|
49212
|
+
).attr("data-poi", lab.poiId ?? null).attr("data-poi-hidden", "").style("opacity", 0).style("pointer-events", "none");
|
|
49213
|
+
continue;
|
|
49214
|
+
}
|
|
47799
49215
|
if (lab.leader) {
|
|
47800
49216
|
const line12 = gLabels.append("line").attr("x1", lab.leader.x1).attr("y1", lab.leader.y1).attr("x2", lab.leader.x2).attr("y2", lab.leader.y2).attr(
|
|
47801
49217
|
"stroke",
|
|
47802
49218
|
lab.leaderColor ?? mix(palette.textMuted, palette.bg, 60)
|
|
47803
49219
|
).attr("stroke-width", lab.leaderColor ? 1 : 0.75);
|
|
47804
49220
|
if (lab.poiId !== void 0) line12.attr("data-poi", lab.poiId);
|
|
49221
|
+
if (lab.clusterMember !== void 0)
|
|
49222
|
+
line12.attr("data-cluster-member", lab.clusterMember);
|
|
49223
|
+
wireSync(line12, lab.lineNumber);
|
|
47805
49224
|
}
|
|
47806
49225
|
const t = emitText(
|
|
47807
49226
|
gLabels,
|
|
@@ -47812,11 +49231,38 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
47812
49231
|
lab.color,
|
|
47813
49232
|
lab.haloColor,
|
|
47814
49233
|
lab.halo,
|
|
47815
|
-
LABEL_FONT
|
|
49234
|
+
LABEL_FONT,
|
|
49235
|
+
lab.italic,
|
|
49236
|
+
lab.letterSpacing,
|
|
49237
|
+
lab.lines
|
|
47816
49238
|
);
|
|
47817
49239
|
if (lab.poiId !== void 0) {
|
|
47818
49240
|
t.attr("data-poi", lab.poiId).style("cursor", "default");
|
|
47819
49241
|
}
|
|
49242
|
+
if (lab.clusterMember !== void 0) {
|
|
49243
|
+
t.attr("data-cluster-member", lab.clusterMember);
|
|
49244
|
+
}
|
|
49245
|
+
wireSync(t, lab.lineNumber);
|
|
49246
|
+
}
|
|
49247
|
+
if (!exportDims && layout.clusters.length) {
|
|
49248
|
+
const gBadge = svg.append("g").attr("class", "dgmo-map-cluster-badges");
|
|
49249
|
+
for (const cl of layout.clusters) {
|
|
49250
|
+
const g = gBadge.append("g").attr("data-cluster", cl.id).style("opacity", 0).style("pointer-events", "none");
|
|
49251
|
+
const R = 9;
|
|
49252
|
+
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);
|
|
49253
|
+
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);
|
|
49254
|
+
emitText(
|
|
49255
|
+
g,
|
|
49256
|
+
cl.cx,
|
|
49257
|
+
cl.cy + 3,
|
|
49258
|
+
String(cl.count),
|
|
49259
|
+
"middle",
|
|
49260
|
+
palette.text,
|
|
49261
|
+
palette.bg,
|
|
49262
|
+
false,
|
|
49263
|
+
LABEL_FONT
|
|
49264
|
+
);
|
|
49265
|
+
}
|
|
47820
49266
|
}
|
|
47821
49267
|
if (layout.legend) {
|
|
47822
49268
|
const legendY = (layout.title ? TITLE_Y + TITLE_FONT_SIZE : 0) + (layout.subtitle ? TITLE_FONT_SIZE : 0) + 8;
|
|
@@ -47853,7 +49299,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
47853
49299
|
svg.append("text").attr("class", "dgmo-map-title").attr("x", width / 2).attr("y", TITLE_Y).attr("text-anchor", "middle").attr("font-size", TITLE_FONT_SIZE).attr("font-weight", TITLE_FONT_WEIGHT).attr("fill", palette.text).attr("paint-order", "stroke fill").attr("stroke", palette.bg).attr("stroke-width", 4).attr("stroke-linejoin", "round").attr("stroke-opacity", 0.7).text(layout.title);
|
|
47854
49300
|
}
|
|
47855
49301
|
if (layout.subtitle) {
|
|
47856
|
-
svg.append("text").attr("x", width / 2).attr("y", TITLE_Y + TITLE_FONT_SIZE).attr("text-anchor", "middle").attr("font-size", LABEL_FONT + 1).attr("fill", palette.textMuted).attr("paint-order", "stroke fill").attr("stroke", palette.bg).attr("stroke-width", 3).attr("stroke-linejoin", "round").attr("stroke-opacity", 0.7).text(layout.subtitle);
|
|
49302
|
+
svg.append("text").attr("class", "dgmo-map-subtitle").attr("x", width / 2).attr("y", TITLE_Y + TITLE_FONT_SIZE).attr("text-anchor", "middle").attr("font-size", LABEL_FONT + 1).attr("fill", palette.textMuted).attr("paint-order", "stroke fill").attr("stroke", palette.bg).attr("stroke-width", 3).attr("stroke-linejoin", "round").attr("stroke-opacity", 0.7).text(layout.subtitle);
|
|
47857
49303
|
}
|
|
47858
49304
|
if (layout.caption) {
|
|
47859
49305
|
svg.append("text").attr("x", width / 2).attr("y", height - 8).attr("text-anchor", "middle").attr("font-size", LABEL_FONT).attr("fill", palette.textMuted).attr("paint-order", "stroke fill").attr("stroke", palette.bg).attr("stroke-width", 3).attr("stroke-linejoin", "round").attr("stroke-opacity", 0.7).text(layout.caption);
|
|
@@ -47862,10 +49308,21 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
47862
49308
|
function renderMapForExport(container, resolved, data, palette, isDark, exportDims) {
|
|
47863
49309
|
renderMap(container, resolved, data, palette, isDark, void 0, exportDims);
|
|
47864
49310
|
}
|
|
47865
|
-
function emitText(g, x, y, text, anchor, color, halo, withHalo, fontSize) {
|
|
47866
|
-
const t = g.append("text").attr("x", x).attr("y", y).attr("text-anchor", anchor).attr("font-size", fontSize).attr("fill", color)
|
|
49311
|
+
function emitText(g, x, y, text, anchor, color, halo, withHalo, fontSize, italic, letterSpacing, lines) {
|
|
49312
|
+
const t = g.append("text").attr("x", x).attr("y", y).attr("text-anchor", anchor).attr("font-size", fontSize).attr("fill", color);
|
|
49313
|
+
if (lines && lines.length > 1) {
|
|
49314
|
+
const lineHeight = fontSize + 2;
|
|
49315
|
+
const startDy = -((lines.length - 1) / 2) * lineHeight;
|
|
49316
|
+
lines.forEach((ln, i) => {
|
|
49317
|
+
t.append("tspan").attr("x", x).attr("dy", i === 0 ? startDy : lineHeight).text(ln);
|
|
49318
|
+
});
|
|
49319
|
+
} else {
|
|
49320
|
+
t.text(text);
|
|
49321
|
+
}
|
|
49322
|
+
if (italic) t.attr("font-style", "italic");
|
|
49323
|
+
if (letterSpacing) t.attr("letter-spacing", letterSpacing);
|
|
47867
49324
|
if (withHalo) {
|
|
47868
|
-
t.attr("paint-order", "stroke fill").attr("stroke", halo).attr("stroke-width",
|
|
49325
|
+
t.attr("paint-order", "stroke fill").attr("stroke", halo).attr("stroke-width", 2).attr("stroke-linejoin", "round").attr("stroke-linecap", "round").attr("stroke-opacity", 0.55);
|
|
47869
49326
|
}
|
|
47870
49327
|
return t;
|
|
47871
49328
|
}
|
|
@@ -47883,6 +49340,56 @@ var init_renderer16 = __esm({
|
|
|
47883
49340
|
}
|
|
47884
49341
|
});
|
|
47885
49342
|
|
|
49343
|
+
// src/map/dimensions.ts
|
|
49344
|
+
var dimensions_exports = {};
|
|
49345
|
+
__export(dimensions_exports, {
|
|
49346
|
+
mapContentAspect: () => mapContentAspect,
|
|
49347
|
+
mapExportDimensions: () => mapExportDimensions
|
|
49348
|
+
});
|
|
49349
|
+
function mapContentAspect(resolved, data, ref = REF) {
|
|
49350
|
+
const { projection, fitTarget } = buildMapProjection(resolved, data);
|
|
49351
|
+
projection.fitSize([ref, ref], fitTarget);
|
|
49352
|
+
const b = (0, import_d3_geo3.geoPath)(projection).bounds(fitTarget);
|
|
49353
|
+
const w = b[1][0] - b[0][0];
|
|
49354
|
+
const h = b[1][1] - b[0][1];
|
|
49355
|
+
const aspect = w / h;
|
|
49356
|
+
return Number.isFinite(aspect) && aspect > 0 ? aspect : FALLBACK_ASPECT;
|
|
49357
|
+
}
|
|
49358
|
+
function mapExportDimensions(resolved, data, baseWidth = 1200) {
|
|
49359
|
+
const raw = mapContentAspect(resolved, data);
|
|
49360
|
+
const clamped = Math.max(ASPECT_MIN, Math.min(ASPECT_MAX, raw));
|
|
49361
|
+
const width = baseWidth;
|
|
49362
|
+
let height = Math.round(width / clamped);
|
|
49363
|
+
let chromeReserve = 0;
|
|
49364
|
+
if (resolved.title && resolved.pois.length > 0) {
|
|
49365
|
+
const bannerBottom = (resolved.subtitle ? TITLE_Y + TITLE_FONT_SIZE : TITLE_Y) + TITLE_FONT_SIZE / 2;
|
|
49366
|
+
chromeReserve += Math.max(FIT_PAD2, bannerBottom + TITLE_GAP) - FIT_PAD2;
|
|
49367
|
+
}
|
|
49368
|
+
let floored = false;
|
|
49369
|
+
if (height - chromeReserve < MIN_MAP_BAND) {
|
|
49370
|
+
height = Math.round(chromeReserve + MIN_MAP_BAND);
|
|
49371
|
+
floored = true;
|
|
49372
|
+
}
|
|
49373
|
+
const preferContain = clamped !== raw || floored;
|
|
49374
|
+
return { width, height, preferContain };
|
|
49375
|
+
}
|
|
49376
|
+
var import_d3_geo3, FIT_PAD2, TITLE_GAP, ASPECT_MAX, ASPECT_MIN, MIN_MAP_BAND, FALLBACK_ASPECT, REF;
|
|
49377
|
+
var init_dimensions = __esm({
|
|
49378
|
+
"src/map/dimensions.ts"() {
|
|
49379
|
+
"use strict";
|
|
49380
|
+
import_d3_geo3 = require("d3-geo");
|
|
49381
|
+
init_title_constants();
|
|
49382
|
+
init_layout15();
|
|
49383
|
+
FIT_PAD2 = 24;
|
|
49384
|
+
TITLE_GAP = 16;
|
|
49385
|
+
ASPECT_MAX = 3;
|
|
49386
|
+
ASPECT_MIN = 0.9;
|
|
49387
|
+
MIN_MAP_BAND = 200;
|
|
49388
|
+
FALLBACK_ASPECT = 1.5;
|
|
49389
|
+
REF = 1e3;
|
|
49390
|
+
}
|
|
49391
|
+
});
|
|
49392
|
+
|
|
47886
49393
|
// src/map/load-data.ts
|
|
47887
49394
|
var load_data_exports = {};
|
|
47888
49395
|
__export(load_data_exports, {
|
|
@@ -47941,12 +49448,17 @@ function loadMapData() {
|
|
|
47941
49448
|
mountainRanges,
|
|
47942
49449
|
naLand,
|
|
47943
49450
|
naLakes,
|
|
49451
|
+
waterBodies,
|
|
47944
49452
|
gazetteer
|
|
47945
49453
|
] = await Promise.all([
|
|
49454
|
+
// worldCoarse (110m) is LOAD-BEARING but NOT a render source: the world
|
|
49455
|
+
// basemap renders from worldDetail (50m) at all scales (resolver pins
|
|
49456
|
+
// basemaps.world = 'detail'). Coarse stays as the authoritative region
|
|
49457
|
+
// name index + dominant-landmass bbox source in resolver.ts. Do not drop it.
|
|
47946
49458
|
readJson(nb, dir, FILES.worldCoarse),
|
|
47947
49459
|
readJson(nb, dir, FILES.worldDetail),
|
|
47948
49460
|
readJson(nb, dir, FILES.usStates),
|
|
47949
|
-
// Lakes/rivers/mountain/NA assets are optional — older bundles may predate them.
|
|
49461
|
+
// Lakes/rivers/mountain/NA/water assets are optional — older bundles may predate them.
|
|
47950
49462
|
readJson(nb, dir, FILES.lakes).catch(() => void 0),
|
|
47951
49463
|
readJson(nb, dir, FILES.rivers).catch(() => void 0),
|
|
47952
49464
|
readJson(nb, dir, FILES.mountainRanges).catch(
|
|
@@ -47954,6 +49466,7 @@ function loadMapData() {
|
|
|
47954
49466
|
),
|
|
47955
49467
|
readJson(nb, dir, FILES.naLand).catch(() => void 0),
|
|
47956
49468
|
readJson(nb, dir, FILES.naLakes).catch(() => void 0),
|
|
49469
|
+
readJson(nb, dir, FILES.waterBodies).catch(() => void 0),
|
|
47957
49470
|
readJson(nb, dir, FILES.gazetteer)
|
|
47958
49471
|
]);
|
|
47959
49472
|
return validate({
|
|
@@ -47965,7 +49478,8 @@ function loadMapData() {
|
|
|
47965
49478
|
...rivers && { rivers },
|
|
47966
49479
|
...mountainRanges && { mountainRanges },
|
|
47967
49480
|
...naLand && { naLand },
|
|
47968
|
-
...naLakes && { naLakes }
|
|
49481
|
+
...naLakes && { naLakes },
|
|
49482
|
+
...waterBodies && { waterBodies }
|
|
47969
49483
|
});
|
|
47970
49484
|
})().catch((e) => {
|
|
47971
49485
|
cache = void 0;
|
|
@@ -47987,6 +49501,7 @@ var init_load_data = __esm({
|
|
|
47987
49501
|
mountainRanges: "mountain-ranges.json",
|
|
47988
49502
|
naLand: "na-land.json",
|
|
47989
49503
|
naLakes: "na-lakes.json",
|
|
49504
|
+
waterBodies: "water-bodies.json",
|
|
47990
49505
|
gazetteer: "gazetteer.json"
|
|
47991
49506
|
};
|
|
47992
49507
|
CANDIDATE_DIRS = [
|
|
@@ -49999,8 +51514,8 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
|
|
|
49999
51514
|
const lines = splitParticipantLabel(p.label, LABEL_MAX_CHARS);
|
|
50000
51515
|
if (lines.length === 0) continue;
|
|
50001
51516
|
const widest = Math.max(...lines.map((l) => l.length));
|
|
50002
|
-
const
|
|
50003
|
-
uniformBoxWidth = Math.max(uniformBoxWidth,
|
|
51517
|
+
const labelWidth2 = widest * LABEL_CHAR_WIDTH + 10;
|
|
51518
|
+
uniformBoxWidth = Math.max(uniformBoxWidth, labelWidth2);
|
|
50004
51519
|
}
|
|
50005
51520
|
uniformBoxWidth = Math.min(MAX_BOX_WIDTH, uniformBoxWidth);
|
|
50006
51521
|
const effectiveGap = Math.max(PARTICIPANT_GAP, uniformBoxWidth + 30);
|
|
@@ -52695,15 +54210,15 @@ function renderArcDiagram(container, parsed, palette, _isDark, onClickItem, expo
|
|
|
52695
54210
|
textColor,
|
|
52696
54211
|
onClickItem
|
|
52697
54212
|
);
|
|
52698
|
-
const
|
|
52699
|
-
for (const node of nodes)
|
|
54213
|
+
const neighbors2 = /* @__PURE__ */ new Map();
|
|
54214
|
+
for (const node of nodes) neighbors2.set(node, /* @__PURE__ */ new Set());
|
|
52700
54215
|
for (const link of links) {
|
|
52701
|
-
|
|
52702
|
-
|
|
54216
|
+
neighbors2.get(link.source).add(link.target);
|
|
54217
|
+
neighbors2.get(link.target).add(link.source);
|
|
52703
54218
|
}
|
|
52704
54219
|
const FADE_OPACITY3 = 0.1;
|
|
52705
54220
|
function handleMouseEnter(hovered) {
|
|
52706
|
-
const connected =
|
|
54221
|
+
const connected = neighbors2.get(hovered);
|
|
52707
54222
|
g.selectAll(".arc-link").each(function() {
|
|
52708
54223
|
const el = d3Selection23.select(this);
|
|
52709
54224
|
const src = el.attr("data-source");
|
|
@@ -54694,7 +56209,7 @@ function renderVenn(container, parsed, palette, _isDark, onClickItem, exportDims
|
|
|
54694
56209
|
8,
|
|
54695
56210
|
Math.floor(OVERLAP_WRAP_TARGET_W / OVERLAP_CH_W)
|
|
54696
56211
|
);
|
|
54697
|
-
function
|
|
56212
|
+
function wrapLabel3(text, maxChars) {
|
|
54698
56213
|
const words = text.split(/\s+/).filter(Boolean);
|
|
54699
56214
|
const lines = [];
|
|
54700
56215
|
let cur = "";
|
|
@@ -54740,7 +56255,7 @@ function renderVenn(container, parsed, palette, _isDark, onClickItem, exportDims
|
|
|
54740
56255
|
if (!ov.label) continue;
|
|
54741
56256
|
const idxs = ov.sets.map((s) => vennSets.findIndex((vs) => vs.name === s));
|
|
54742
56257
|
if (idxs.some((idx) => idx < 0)) continue;
|
|
54743
|
-
const lines =
|
|
56258
|
+
const lines = wrapLabel3(ov.label, MAX_WRAP_CHARS);
|
|
54744
56259
|
wrappedOverlapLabels.set(ov, lines);
|
|
54745
56260
|
const dir = predictOverlapDirRaw(idxs);
|
|
54746
56261
|
const longest = lines.reduce((m, l) => Math.max(m, l.length), 0);
|
|
@@ -56178,6 +57693,7 @@ async function renderForExport(content, theme, palette, viewState, options) {
|
|
|
56178
57693
|
const { parseMap: parseMap2 } = await Promise.resolve().then(() => (init_parser12(), parser_exports11));
|
|
56179
57694
|
const { resolveMap: resolveMap2 } = await Promise.resolve().then(() => (init_resolver2(), resolver_exports));
|
|
56180
57695
|
const { renderMapForExport: renderMapForExport2 } = await Promise.resolve().then(() => (init_renderer16(), renderer_exports16));
|
|
57696
|
+
const { mapExportDimensions: mapExportDimensions2 } = await Promise.resolve().then(() => (init_dimensions(), dimensions_exports));
|
|
56181
57697
|
const effectivePalette2 = await resolveExportPalette(theme, palette);
|
|
56182
57698
|
const mapParsed = parseMap2(content);
|
|
56183
57699
|
let mapData = options?.mapData;
|
|
@@ -56190,14 +57706,15 @@ async function renderForExport(content, theme, palette, viewState, options) {
|
|
|
56190
57706
|
}
|
|
56191
57707
|
}
|
|
56192
57708
|
const mapResolved = resolveMap2(mapParsed, mapData);
|
|
56193
|
-
const
|
|
57709
|
+
const dims2 = mapExportDimensions2(mapResolved, mapData, EXPORT_WIDTH);
|
|
57710
|
+
const container2 = createExportContainer(dims2.width, dims2.height);
|
|
56194
57711
|
renderMapForExport2(
|
|
56195
57712
|
container2,
|
|
56196
57713
|
mapResolved,
|
|
56197
57714
|
mapData,
|
|
56198
57715
|
effectivePalette2,
|
|
56199
57716
|
theme === "dark",
|
|
56200
|
-
|
|
57717
|
+
dims2
|
|
56201
57718
|
);
|
|
56202
57719
|
return finalizeSvgExport(container2, theme, effectivePalette2);
|
|
56203
57720
|
}
|
|
@@ -57004,7 +58521,8 @@ __export(advanced_exports, {
|
|
|
57004
58521
|
applyCollapseProjection: () => applyCollapseProjection,
|
|
57005
58522
|
applyGroupOrdering: () => applyGroupOrdering,
|
|
57006
58523
|
applyPositionOverrides: () => applyPositionOverrides,
|
|
57007
|
-
|
|
58524
|
+
atlasPalette: () => atlasPalette,
|
|
58525
|
+
blueprintPalette: () => blueprintPalette,
|
|
57008
58526
|
buildExtendedChartOption: () => buildExtendedChartOption,
|
|
57009
58527
|
buildNoteMessageMap: () => buildNoteMessageMap,
|
|
57010
58528
|
buildRenderSequence: () => buildRenderSequence,
|
|
@@ -57107,6 +58625,8 @@ __export(advanced_exports, {
|
|
|
57107
58625
|
looksLikeState: () => looksLikeState,
|
|
57108
58626
|
makeDgmoError: () => makeDgmoError,
|
|
57109
58627
|
mapBackgroundColor: () => mapBackgroundColor,
|
|
58628
|
+
mapContentAspect: () => mapContentAspect,
|
|
58629
|
+
mapExportDimensions: () => mapExportDimensions,
|
|
57110
58630
|
mapNeutralLandColor: () => mapNeutralLandColor,
|
|
57111
58631
|
matchesContiguously: () => matchesContiguously,
|
|
57112
58632
|
measurePertAnalysisBlock: () => measurePertAnalysisBlock,
|
|
@@ -57242,9 +58762,11 @@ __export(advanced_exports, {
|
|
|
57242
58762
|
shapeFill: () => shapeFill,
|
|
57243
58763
|
simulateCanonical: () => simulateCanonical,
|
|
57244
58764
|
simulateFast: () => simulateFast,
|
|
58765
|
+
slatePalette: () => slatePalette,
|
|
57245
58766
|
solarizedPalette: () => solarizedPalette,
|
|
57246
58767
|
suggestChartTypes: () => suggestChartTypes,
|
|
57247
58768
|
themes: () => themes,
|
|
58769
|
+
tidewaterPalette: () => tidewaterPalette,
|
|
57248
58770
|
tint: () => tint,
|
|
57249
58771
|
tokyoNightPalette: () => tokyoNightPalette,
|
|
57250
58772
|
transformLine: () => transformLine,
|
|
@@ -57328,7 +58850,8 @@ async function render(content, options) {
|
|
|
57328
58850
|
...options?.c4Container !== void 0 && {
|
|
57329
58851
|
c4Container: options.c4Container
|
|
57330
58852
|
},
|
|
57331
|
-
...options?.tagGroup !== void 0 && { tagGroup: options.tagGroup }
|
|
58853
|
+
...options?.tagGroup !== void 0 && { tagGroup: options.tagGroup },
|
|
58854
|
+
...options?.mapData !== void 0 && { mapData: options.mapData }
|
|
57332
58855
|
});
|
|
57333
58856
|
if (chartType === "map") {
|
|
57334
58857
|
try {
|
|
@@ -57339,7 +58862,7 @@ async function render(content, options) {
|
|
|
57339
58862
|
Promise.resolve().then(() => (init_load_data(), load_data_exports))
|
|
57340
58863
|
]
|
|
57341
58864
|
);
|
|
57342
|
-
const data = await loadMapData2();
|
|
58865
|
+
const data = options?.mapData ?? await loadMapData2();
|
|
57343
58866
|
diagnostics = [...resolveMap2(parseMap2(content), data).diagnostics];
|
|
57344
58867
|
} catch {
|
|
57345
58868
|
}
|
|
@@ -57578,8 +59101,8 @@ function detectCycles(parsed) {
|
|
|
57578
59101
|
const parent = /* @__PURE__ */ new Map();
|
|
57579
59102
|
function dfs(nodeId3) {
|
|
57580
59103
|
color.set(nodeId3, 1);
|
|
57581
|
-
const
|
|
57582
|
-
for (const next of
|
|
59104
|
+
const neighbors2 = adj.get(nodeId3) ?? [];
|
|
59105
|
+
for (const next of neighbors2) {
|
|
57583
59106
|
const c = color.get(next) ?? 0;
|
|
57584
59107
|
if (c === 1) {
|
|
57585
59108
|
const lineKey = `${nodeId3}->${next}`;
|
|
@@ -57764,6 +59287,7 @@ init_resolver2();
|
|
|
57764
59287
|
init_load_data();
|
|
57765
59288
|
init_layout15();
|
|
57766
59289
|
init_renderer16();
|
|
59290
|
+
init_dimensions();
|
|
57767
59291
|
|
|
57768
59292
|
// src/map/geo-query.ts
|
|
57769
59293
|
init_parser12();
|
|
@@ -57837,7 +59361,9 @@ function nearestCity(lonLat, gazetteer) {
|
|
|
57837
59361
|
name: c[4],
|
|
57838
59362
|
iso: c[2],
|
|
57839
59363
|
...c[5] !== void 0 && { sub: c[5] },
|
|
57840
|
-
distanceKm: best.dist
|
|
59364
|
+
distanceKm: best.dist,
|
|
59365
|
+
lat: c[0],
|
|
59366
|
+
lon: c[1]
|
|
57841
59367
|
};
|
|
57842
59368
|
}
|
|
57843
59369
|
function roundCoord(n) {
|
|
@@ -57916,7 +59442,7 @@ function createMapGeoQuery(opts) {
|
|
|
57916
59442
|
}
|
|
57917
59443
|
return out;
|
|
57918
59444
|
};
|
|
57919
|
-
return { invert, project, locate, cities };
|
|
59445
|
+
return { invert, project, locate, cities, diagnostics: layout.diagnostics };
|
|
57920
59446
|
}
|
|
57921
59447
|
|
|
57922
59448
|
// src/map/completion.ts
|
|
@@ -58642,9 +60168,12 @@ var GLOBAL_DIRECTIVES = {
|
|
|
58642
60168
|
"gruvbox",
|
|
58643
60169
|
"tokyo-night",
|
|
58644
60170
|
"one-dark",
|
|
58645
|
-
"bold",
|
|
58646
60171
|
"dracula",
|
|
58647
|
-
"monokai"
|
|
60172
|
+
"monokai",
|
|
60173
|
+
"atlas",
|
|
60174
|
+
"blueprint",
|
|
60175
|
+
"slate",
|
|
60176
|
+
"tidewater"
|
|
58648
60177
|
]
|
|
58649
60178
|
},
|
|
58650
60179
|
theme: {
|
|
@@ -59040,18 +60569,12 @@ var COMPLETION_REGISTRY = /* @__PURE__ */ new Map([
|
|
|
59040
60569
|
],
|
|
59041
60570
|
[
|
|
59042
60571
|
"map",
|
|
59043
|
-
// Geographic map directives (§24B.2/.7).
|
|
59044
|
-
//
|
|
59045
|
-
//
|
|
60572
|
+
// Geographic map directives (§24B.2/.7). Cosmetics are ON by default — the
|
|
60573
|
+
// only switches are bare `no-*` opt-outs, surfaced proactively so a
|
|
60574
|
+
// zero-config map still hints at what can be turned off. `poi`/`route` are
|
|
60575
|
+
// content keywords, not directives; metadata keys (value/label/style) live
|
|
60576
|
+
// in the reserved-key registry.
|
|
59046
60577
|
withGlobals({
|
|
59047
|
-
region: {
|
|
59048
|
-
description: "Basemap: us-states (force US state mesh + scoping) | world (inert \u2014 already the default)",
|
|
59049
|
-
values: ["us-states", "world"]
|
|
59050
|
-
},
|
|
59051
|
-
projection: {
|
|
59052
|
-
description: "Override the auto projection",
|
|
59053
|
-
values: ["equirectangular", "natural-earth", "albers-usa", "mercator"]
|
|
59054
|
-
},
|
|
59055
60578
|
"region-metric": { description: "Label for the region value ramp" },
|
|
59056
60579
|
"poi-metric": {
|
|
59057
60580
|
description: "Label for the POI value (marker size) channel"
|
|
@@ -59059,21 +60582,30 @@ var COMPLETION_REGISTRY = /* @__PURE__ */ new Map([
|
|
|
59059
60582
|
"flow-metric": {
|
|
59060
60583
|
description: "Label for the edge/leg value (thickness) channel"
|
|
59061
60584
|
},
|
|
59062
|
-
|
|
59063
|
-
|
|
59064
|
-
description: "Subdivision name labels",
|
|
59065
|
-
values: ["full", "abbrev", "off"]
|
|
60585
|
+
locale: {
|
|
60586
|
+
description: "Default country/state for bare place names, e.g. locale US-GA"
|
|
59066
60587
|
},
|
|
59067
|
-
"
|
|
59068
|
-
description: "
|
|
59069
|
-
values: ["off", "auto", "all"]
|
|
60588
|
+
"active-tag": {
|
|
60589
|
+
description: "Which tag group leads when several are present"
|
|
59070
60590
|
},
|
|
59071
|
-
|
|
59072
|
-
"default-state": { description: "ISO subdivision scope" },
|
|
60591
|
+
caption: { description: "Caption line (data-source attribution)" },
|
|
59073
60592
|
"no-legend": { description: "Suppress the legend" },
|
|
59074
|
-
|
|
59075
|
-
|
|
59076
|
-
|
|
60593
|
+
"no-coastline": {
|
|
60594
|
+
description: "Turn off coastal water-lines (on by default)"
|
|
60595
|
+
},
|
|
60596
|
+
"no-relief": {
|
|
60597
|
+
description: "Turn off mountain-range relief shading (on by default)"
|
|
60598
|
+
},
|
|
60599
|
+
"no-context-labels": {
|
|
60600
|
+
description: "Turn off orientation labels for water + nearby countries"
|
|
60601
|
+
},
|
|
60602
|
+
"no-region-labels": {
|
|
60603
|
+
description: "Turn off subdivision name labels (on by default)"
|
|
60604
|
+
},
|
|
60605
|
+
"no-poi-labels": { description: "Turn off POI labels (on by default)" },
|
|
60606
|
+
"no-colorize": {
|
|
60607
|
+
description: "Force plain green-land reference dress (regions are auto-coloured by default)"
|
|
60608
|
+
}
|
|
59077
60609
|
})
|
|
59078
60610
|
]
|
|
59079
60611
|
]);
|
|
@@ -60543,7 +62075,8 @@ function formatLineDiff(path, original, migrated) {
|
|
|
60543
62075
|
applyCollapseProjection,
|
|
60544
62076
|
applyGroupOrdering,
|
|
60545
62077
|
applyPositionOverrides,
|
|
60546
|
-
|
|
62078
|
+
atlasPalette,
|
|
62079
|
+
blueprintPalette,
|
|
60547
62080
|
buildExtendedChartOption,
|
|
60548
62081
|
buildNoteMessageMap,
|
|
60549
62082
|
buildRenderSequence,
|
|
@@ -60646,6 +62179,8 @@ function formatLineDiff(path, original, migrated) {
|
|
|
60646
62179
|
looksLikeState,
|
|
60647
62180
|
makeDgmoError,
|
|
60648
62181
|
mapBackgroundColor,
|
|
62182
|
+
mapContentAspect,
|
|
62183
|
+
mapExportDimensions,
|
|
60649
62184
|
mapNeutralLandColor,
|
|
60650
62185
|
matchesContiguously,
|
|
60651
62186
|
measurePertAnalysisBlock,
|
|
@@ -60781,9 +62316,11 @@ function formatLineDiff(path, original, migrated) {
|
|
|
60781
62316
|
shapeFill,
|
|
60782
62317
|
simulateCanonical,
|
|
60783
62318
|
simulateFast,
|
|
62319
|
+
slatePalette,
|
|
60784
62320
|
solarizedPalette,
|
|
60785
62321
|
suggestChartTypes,
|
|
60786
62322
|
themes,
|
|
62323
|
+
tidewaterPalette,
|
|
60787
62324
|
tint,
|
|
60788
62325
|
tokyoNightPalette,
|
|
60789
62326
|
transformLine,
|