@diagrammo/dgmo 0.20.0 → 0.20.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -45910,7 +45910,7 @@ function resolveMap(parsed, data) {
45910
45910
  const lonSpan = extent2[1][0] - extent2[0][0];
45911
45911
  const latSpan = extent2[1][1] - extent2[0][1];
45912
45912
  const span = Math.max(lonSpan, latSpan);
45913
- const usDominant = (inferredCountry === "US" || subdivisions.includes("us-states")) && !regions.some((r) => r.layer === "country" && r.iso !== "US") && !anyNonUsPoi;
45913
+ const usDominant = (subdivisions.includes("us-states") || regions.some((r) => r.layer === "us-state")) && !regions.some((r) => r.layer === "country" && r.iso !== "US") && !anyNonUsPoi;
45914
45914
  let projection;
45915
45915
  const override = parsed.directives.projection;
45916
45916
  if (override === "equirectangular" || override === "natural-earth" || override === "albers-usa" || override === "mercator") {
@@ -46016,14 +46016,22 @@ var load_data_exports = {};
46016
46016
  __export(load_data_exports, {
46017
46017
  loadMapData: () => loadMapData
46018
46018
  });
46019
- async function readJson(dir, name) {
46020
- return JSON.parse(await (0, import_promises.readFile)((0, import_node_path.resolve)(dir, name), "utf8"));
46019
+ async function loadNodeBuiltins() {
46020
+ const [{ readFile }, { fileURLToPath }, { dirname, resolve }] = await Promise.all([
46021
+ import("fs/promises"),
46022
+ import("url"),
46023
+ import("path")
46024
+ ]);
46025
+ return { readFile, fileURLToPath, dirname, resolve };
46026
+ }
46027
+ async function readJson(nb, dir, name) {
46028
+ return JSON.parse(await nb.readFile(nb.resolve(dir, name), "utf8"));
46021
46029
  }
46022
- async function firstExistingDir(baseDir) {
46030
+ async function firstExistingDir(nb, baseDir) {
46023
46031
  for (const rel of CANDIDATE_DIRS) {
46024
- const dir = (0, import_node_path.resolve)(baseDir, rel);
46032
+ const dir = nb.resolve(baseDir, rel);
46025
46033
  try {
46026
- await (0, import_promises.readFile)((0, import_node_path.resolve)(dir, FILES.gazetteer), "utf8");
46034
+ await nb.readFile(nb.resolve(dir, FILES.gazetteer), "utf8");
46027
46035
  return dir;
46028
46036
  } catch {
46029
46037
  }
@@ -46039,10 +46047,10 @@ function validate(data) {
46039
46047
  }
46040
46048
  return data;
46041
46049
  }
46042
- function moduleBaseDir() {
46050
+ function moduleBaseDir(nb) {
46043
46051
  try {
46044
46052
  const url = import_meta.url;
46045
- if (url) return (0, import_node_path.dirname)((0, import_node_url.fileURLToPath)(url));
46053
+ if (url) return nb.dirname(nb.fileURLToPath(url));
46046
46054
  } catch {
46047
46055
  }
46048
46056
  if (typeof __dirname !== "undefined") return __dirname;
@@ -46050,7 +46058,8 @@ function moduleBaseDir() {
46050
46058
  }
46051
46059
  function loadMapData() {
46052
46060
  cache ??= (async () => {
46053
- const dir = await firstExistingDir(moduleBaseDir());
46061
+ const nb = await loadNodeBuiltins();
46062
+ const dir = await firstExistingDir(nb, moduleBaseDir(nb));
46054
46063
  const [
46055
46064
  worldCoarse,
46056
46065
  worldDetail,
@@ -46061,15 +46070,15 @@ function loadMapData() {
46061
46070
  naLakes,
46062
46071
  gazetteer
46063
46072
  ] = await Promise.all([
46064
- readJson(dir, FILES.worldCoarse),
46065
- readJson(dir, FILES.worldDetail),
46066
- readJson(dir, FILES.usStates),
46073
+ readJson(nb, dir, FILES.worldCoarse),
46074
+ readJson(nb, dir, FILES.worldDetail),
46075
+ readJson(nb, dir, FILES.usStates),
46067
46076
  // Lakes/rivers/NA assets are optional — older bundles may predate them.
46068
- readJson(dir, FILES.lakes).catch(() => void 0),
46069
- readJson(dir, FILES.rivers).catch(() => void 0),
46070
- readJson(dir, FILES.naLand).catch(() => void 0),
46071
- readJson(dir, FILES.naLakes).catch(() => void 0),
46072
- readJson(dir, FILES.gazetteer)
46077
+ readJson(nb, dir, FILES.lakes).catch(() => void 0),
46078
+ readJson(nb, dir, FILES.rivers).catch(() => void 0),
46079
+ readJson(nb, dir, FILES.naLand).catch(() => void 0),
46080
+ readJson(nb, dir, FILES.naLakes).catch(() => void 0),
46081
+ readJson(nb, dir, FILES.gazetteer)
46073
46082
  ]);
46074
46083
  return validate({
46075
46084
  worldCoarse,
@@ -46087,13 +46096,10 @@ function loadMapData() {
46087
46096
  });
46088
46097
  return cache;
46089
46098
  }
46090
- var import_promises, import_node_url, import_node_path, import_meta, FILES, CANDIDATE_DIRS, cache;
46099
+ var import_meta, FILES, CANDIDATE_DIRS, cache;
46091
46100
  var init_load_data = __esm({
46092
46101
  "src/map/load-data.ts"() {
46093
46102
  "use strict";
46094
- import_promises = require("fs/promises");
46095
- import_node_url = require("url");
46096
- import_node_path = require("path");
46097
46103
  import_meta = {};
46098
46104
  FILES = {
46099
46105
  worldCoarse: "world-coarse.json",
@@ -46148,8 +46154,19 @@ function layoutMap(resolved, data, size, opts) {
46148
46154
  const { width, height } = size;
46149
46155
  const wantsUsStates = resolved.basemaps.subdivisions.includes("us-states");
46150
46156
  const usCrisp = resolved.projection === "albers-usa" && wantsUsStates && !!data.naLand;
46151
- const worldTopo = usCrisp ? data.naLand : resolved.basemaps.world === "detail" ? data.worldDetail : data.worldCoarse;
46157
+ const worldTopo = usCrisp ? data.worldDetail : resolved.basemaps.world === "detail" ? data.worldDetail : data.worldCoarse;
46152
46158
  const worldLayer = decodeLayer(worldTopo);
46159
+ if (usCrisp && data.naLand) {
46160
+ const [nbW, nbS, nbE, nbN] = [-140, 10, -52, 66];
46161
+ const crisp = decodeLayer(data.naLand);
46162
+ for (const [iso, cf] of crisp) {
46163
+ const base = worldLayer.get(iso);
46164
+ if (!base) continue;
46165
+ const [[bw, bs], [be, bn]] = (0, import_d3_geo2.geoBounds)(base);
46166
+ if (bw >= nbW && be <= nbE && bs >= nbS && bn <= nbN)
46167
+ worldLayer.set(iso, cf);
46168
+ }
46169
+ }
46153
46170
  const usLayer = wantsUsStates ? decodeLayer(data.usStates) : null;
46154
46171
  const landTint = isDark ? LAND_TINT_DARK : LAND_TINT_LIGHT;
46155
46172
  const neutralFill = mix(palette.colors.green, palette.bg, landTint);
@@ -46295,6 +46312,10 @@ function layoutMap(resolved, data, size, opts) {
46295
46312
  return p ? stretch(p[0], p[1]) : null;
46296
46313
  };
46297
46314
  } else {
46315
+ projection.clipExtent([
46316
+ [0, 0],
46317
+ [width, height]
46318
+ ]);
46298
46319
  path = (0, import_d3_geo2.geoPath)(projection);
46299
46320
  project = (lon, lat) => projection([lon, lat]) ?? null;
46300
46321
  }
@@ -46439,18 +46460,11 @@ function layoutMap(resolved, data, size, opts) {
46439
46460
  placeInset("US-HI", hawaiiProjection(), akRight + 24, width * 0.1);
46440
46461
  }
46441
46462
  const conusFit = resolved.projection === "albers-usa" && !!usLayer;
46442
- const cullExtent = conusFit ? (0, import_d3_geo2.geoBounds)(fitTarget) : resolved.extent;
46443
- const [[exW, exS], [exE, exN]] = cullExtent;
46444
- const lonSpan = exE - exW;
46445
- const latSpan = exN - exS;
46446
- const isGlobalView = lonSpan >= 270 || latSpan >= 130;
46447
- const padLon = Math.max(8, lonSpan * 0.35);
46448
- const padLat = Math.max(8, latSpan * 0.35);
46449
- const vW = exW - padLon;
46450
- const vE = exE + padLon;
46451
- const vS = exS - padLat;
46452
- const vN = exN + padLat;
46453
- const vLonCenter = (exW + exE) / 2;
46463
+ const classifyExtent = conusFit ? (0, import_d3_geo2.geoBounds)(fitTarget) : resolved.extent;
46464
+ const dLonSpan = classifyExtent[1][0] - classifyExtent[0][0];
46465
+ const dLatSpan = classifyExtent[1][1] - classifyExtent[0][1];
46466
+ const isGlobalView = dLonSpan >= 270 || dLatSpan >= 130;
46467
+ const vLonCenter = (classifyExtent[0][0] + classifyExtent[1][0]) / 2;
46454
46468
  const normLon = (lon) => {
46455
46469
  let L = lon;
46456
46470
  while (L < vLonCenter - 180) L += 360;
@@ -46458,23 +46472,28 @@ function layoutMap(resolved, data, size, opts) {
46458
46472
  return L;
46459
46473
  };
46460
46474
  const ringOverlapsView = (ring) => {
46461
- let anyIn = false;
46462
- let loMin = Infinity, loMax = -Infinity, laMin = Infinity, laMax = -Infinity, rawMin = Infinity, rawMax = -Infinity;
46463
- for (const [rawLon, lat] of ring) {
46475
+ let loMin = Infinity, loMax = -Infinity, rawMin = Infinity, rawMax = -Infinity;
46476
+ for (const [rawLon] of ring) {
46464
46477
  const lon = normLon(rawLon);
46465
- if (lon >= vW && lon <= vE && lat >= vS && lat <= vN) anyIn = true;
46466
46478
  if (lon < loMin) loMin = lon;
46467
46479
  if (lon > loMax) loMax = lon;
46468
46480
  if (rawLon < rawMin) rawMin = rawLon;
46469
46481
  if (rawLon > rawMax) rawMax = rawLon;
46470
- if (lat < laMin) laMin = lat;
46471
- if (lat > laMax) laMax = lat;
46472
46482
  }
46473
46483
  if (loMax - loMin > 270) return false;
46474
46484
  if (rawMax - rawMin > 180 && loMax - loMin < 90) return false;
46475
- if (anyIn) return true;
46476
- if (loMax - loMin > 180) return false;
46477
- return !(loMax < vW || loMin > vE || laMax < vS || laMin > vN);
46485
+ let px0 = Infinity, py0 = Infinity, px1 = -Infinity, py1 = -Infinity, anyFinite = false;
46486
+ for (const [lon, lat] of ring) {
46487
+ const p = project(lon, lat);
46488
+ if (!p || !Number.isFinite(p[0]) || !Number.isFinite(p[1])) continue;
46489
+ anyFinite = true;
46490
+ if (p[0] < px0) px0 = p[0];
46491
+ if (p[0] > px1) px1 = p[0];
46492
+ if (p[1] < py0) py0 = p[1];
46493
+ if (p[1] > py1) py1 = p[1];
46494
+ }
46495
+ if (!anyFinite) return false;
46496
+ return !(px1 < 0 || px0 > width || py1 < 0 || py0 > height);
46478
46497
  };
46479
46498
  const cullFeatureToView = (f) => {
46480
46499
  if (isGlobalView) return f;
@@ -46865,19 +46884,39 @@ function layoutMap(resolved, data, size, opts) {
46865
46884
  const text = labelText(p);
46866
46885
  return { text, w: measureLegendText(text, FONT) };
46867
46886
  };
46887
+ const GAP = 3;
46888
+ const inlineRect = (p, w, side) => {
46889
+ switch (side) {
46890
+ case "right":
46891
+ return { x: p.cx + p.r + GAP, y: p.cy - poiLabH / 2, w, h: poiLabH };
46892
+ case "left":
46893
+ return {
46894
+ x: p.cx - p.r - GAP - w,
46895
+ y: p.cy - poiLabH / 2,
46896
+ w,
46897
+ h: poiLabH
46898
+ };
46899
+ case "above":
46900
+ return {
46901
+ x: p.cx - w / 2,
46902
+ y: p.cy - p.r - GAP - poiLabH,
46903
+ w,
46904
+ h: poiLabH
46905
+ };
46906
+ case "below":
46907
+ return { x: p.cx - w / 2, y: p.cy + p.r + GAP, w, h: poiLabH };
46908
+ }
46909
+ };
46868
46910
  const pushInline = (p, text, w, side) => {
46869
- const tx = side === "right" ? p.cx + p.r + 3 : p.cx - p.r - 3;
46870
- obstacles.push({
46871
- x: side === "right" ? tx : tx - w,
46872
- y: p.cy - poiLabH / 2,
46873
- w,
46874
- h: poiLabH
46875
- });
46911
+ const rect = inlineRect(p, w, side);
46912
+ obstacles.push(rect);
46913
+ const anchor = side === "right" ? "start" : side === "left" ? "end" : "middle";
46914
+ const x = side === "right" ? rect.x : side === "left" ? rect.x + w : p.cx;
46876
46915
  labels.push({
46877
- x: tx,
46878
- y: p.cy + FONT / 3,
46916
+ x,
46917
+ y: rect.y + poiLabH / 2 + FONT / 3,
46879
46918
  text,
46880
- anchor: side === "right" ? "start" : "end",
46919
+ anchor,
46881
46920
  color: palette.text,
46882
46921
  halo: true,
46883
46922
  haloColor: palette.bg,
@@ -46886,14 +46925,8 @@ function layoutMap(resolved, data, size, opts) {
46886
46925
  });
46887
46926
  };
46888
46927
  const inlineFits = (p, w, side) => {
46889
- const tx = side === "right" ? p.cx + p.r + 3 : p.cx - p.r - 3;
46890
- const rect = {
46891
- x: side === "right" ? tx : tx - w,
46892
- y: p.cy - poiLabH / 2,
46893
- w,
46894
- h: poiLabH
46895
- };
46896
- return rect.x >= 0 && rect.x + rect.w <= width && !collides(rect);
46928
+ const rect = inlineRect(p, w, side);
46929
+ return rect.x >= 0 && rect.x + rect.w <= width && rect.y >= 0 && rect.y + rect.h <= height && !collides(rect);
46897
46930
  };
46898
46931
  const GROUP_R = 30;
46899
46932
  const groups = [];
@@ -46950,12 +46983,11 @@ function layoutMap(resolved, data, size, opts) {
46950
46983
  if (g.length === 1) {
46951
46984
  const p = g[0];
46952
46985
  const { text, w } = labelInfo(p);
46953
- if (inlineFits(p, w, "right")) {
46954
- pushInline(p, text, w, "right");
46955
- continue;
46956
- }
46957
- if (inlineFits(p, w, "left")) {
46958
- pushInline(p, text, w, "left");
46986
+ const side = ["right", "left", "above", "below"].find(
46987
+ (s) => inlineFits(p, w, s)
46988
+ );
46989
+ if (side) {
46990
+ pushInline(p, text, w, side);
46959
46991
  continue;
46960
46992
  }
46961
46993
  }
@@ -53705,18 +53737,18 @@ function getRotateFn(mode) {
53705
53737
  return () => 0;
53706
53738
  }
53707
53739
  function renderWordCloudAsync(container, parsed, palette, _isDark, exportDims) {
53708
- return new Promise((resolve2) => {
53740
+ return new Promise((resolve) => {
53709
53741
  d3Selection23.select(container).selectAll(":not([data-d3-tooltip])").remove();
53710
53742
  const { words, cloudOptions } = parsed;
53711
53743
  const title = parsed.noTitle ? null : parsed.title;
53712
53744
  if (words.length === 0) {
53713
- resolve2();
53745
+ resolve();
53714
53746
  return;
53715
53747
  }
53716
53748
  const width = exportDims?.width ?? container.clientWidth;
53717
53749
  const height = exportDims?.height ?? container.clientHeight;
53718
53750
  if (width <= 0 || height <= 0) {
53719
- resolve2();
53751
+ resolve();
53720
53752
  return;
53721
53753
  }
53722
53754
  const titleHeight = title ? 40 : 0;
@@ -53745,7 +53777,7 @@ function renderWordCloudAsync(container, parsed, palette, _isDark, exportDims) {
53745
53777
  "transform",
53746
53778
  (d) => `translate(${d.x},${d.y}) rotate(${d.rotate})`
53747
53779
  ).text((d) => d.text);
53748
- resolve2();
53780
+ resolve();
53749
53781
  }).start();
53750
53782
  });
53751
53783
  }
package/dist/index.js CHANGED
@@ -45926,7 +45926,7 @@ function resolveMap(parsed, data) {
45926
45926
  const lonSpan = extent2[1][0] - extent2[0][0];
45927
45927
  const latSpan = extent2[1][1] - extent2[0][1];
45928
45928
  const span = Math.max(lonSpan, latSpan);
45929
- const usDominant = (inferredCountry === "US" || subdivisions.includes("us-states")) && !regions.some((r) => r.layer === "country" && r.iso !== "US") && !anyNonUsPoi;
45929
+ const usDominant = (subdivisions.includes("us-states") || regions.some((r) => r.layer === "us-state")) && !regions.some((r) => r.layer === "country" && r.iso !== "US") && !anyNonUsPoi;
45930
45930
  let projection;
45931
45931
  const override = parsed.directives.projection;
45932
45932
  if (override === "equirectangular" || override === "natural-earth" || override === "albers-usa" || override === "mercator") {
@@ -46032,17 +46032,22 @@ var load_data_exports = {};
46032
46032
  __export(load_data_exports, {
46033
46033
  loadMapData: () => loadMapData
46034
46034
  });
46035
- import { readFile } from "fs/promises";
46036
- import { fileURLToPath } from "url";
46037
- import { dirname, resolve } from "path";
46038
- async function readJson(dir, name) {
46039
- return JSON.parse(await readFile(resolve(dir, name), "utf8"));
46035
+ async function loadNodeBuiltins() {
46036
+ const [{ readFile }, { fileURLToPath }, { dirname, resolve }] = await Promise.all([
46037
+ import("fs/promises"),
46038
+ import("url"),
46039
+ import("path")
46040
+ ]);
46041
+ return { readFile, fileURLToPath, dirname, resolve };
46042
+ }
46043
+ async function readJson(nb, dir, name) {
46044
+ return JSON.parse(await nb.readFile(nb.resolve(dir, name), "utf8"));
46040
46045
  }
46041
- async function firstExistingDir(baseDir) {
46046
+ async function firstExistingDir(nb, baseDir) {
46042
46047
  for (const rel of CANDIDATE_DIRS) {
46043
- const dir = resolve(baseDir, rel);
46048
+ const dir = nb.resolve(baseDir, rel);
46044
46049
  try {
46045
- await readFile(resolve(dir, FILES.gazetteer), "utf8");
46050
+ await nb.readFile(nb.resolve(dir, FILES.gazetteer), "utf8");
46046
46051
  return dir;
46047
46052
  } catch {
46048
46053
  }
@@ -46058,10 +46063,10 @@ function validate(data) {
46058
46063
  }
46059
46064
  return data;
46060
46065
  }
46061
- function moduleBaseDir() {
46066
+ function moduleBaseDir(nb) {
46062
46067
  try {
46063
46068
  const url = import.meta.url;
46064
- if (url) return dirname(fileURLToPath(url));
46069
+ if (url) return nb.dirname(nb.fileURLToPath(url));
46065
46070
  } catch {
46066
46071
  }
46067
46072
  if (typeof __dirname !== "undefined") return __dirname;
@@ -46069,7 +46074,8 @@ function moduleBaseDir() {
46069
46074
  }
46070
46075
  function loadMapData() {
46071
46076
  cache ??= (async () => {
46072
- const dir = await firstExistingDir(moduleBaseDir());
46077
+ const nb = await loadNodeBuiltins();
46078
+ const dir = await firstExistingDir(nb, moduleBaseDir(nb));
46073
46079
  const [
46074
46080
  worldCoarse,
46075
46081
  worldDetail,
@@ -46080,15 +46086,15 @@ function loadMapData() {
46080
46086
  naLakes,
46081
46087
  gazetteer
46082
46088
  ] = await Promise.all([
46083
- readJson(dir, FILES.worldCoarse),
46084
- readJson(dir, FILES.worldDetail),
46085
- readJson(dir, FILES.usStates),
46089
+ readJson(nb, dir, FILES.worldCoarse),
46090
+ readJson(nb, dir, FILES.worldDetail),
46091
+ readJson(nb, dir, FILES.usStates),
46086
46092
  // Lakes/rivers/NA assets are optional — older bundles may predate them.
46087
- readJson(dir, FILES.lakes).catch(() => void 0),
46088
- readJson(dir, FILES.rivers).catch(() => void 0),
46089
- readJson(dir, FILES.naLand).catch(() => void 0),
46090
- readJson(dir, FILES.naLakes).catch(() => void 0),
46091
- readJson(dir, FILES.gazetteer)
46093
+ readJson(nb, dir, FILES.lakes).catch(() => void 0),
46094
+ readJson(nb, dir, FILES.rivers).catch(() => void 0),
46095
+ readJson(nb, dir, FILES.naLand).catch(() => void 0),
46096
+ readJson(nb, dir, FILES.naLakes).catch(() => void 0),
46097
+ readJson(nb, dir, FILES.gazetteer)
46092
46098
  ]);
46093
46099
  return validate({
46094
46100
  worldCoarse,
@@ -46173,8 +46179,19 @@ function layoutMap(resolved, data, size, opts) {
46173
46179
  const { width, height } = size;
46174
46180
  const wantsUsStates = resolved.basemaps.subdivisions.includes("us-states");
46175
46181
  const usCrisp = resolved.projection === "albers-usa" && wantsUsStates && !!data.naLand;
46176
- const worldTopo = usCrisp ? data.naLand : resolved.basemaps.world === "detail" ? data.worldDetail : data.worldCoarse;
46182
+ const worldTopo = usCrisp ? data.worldDetail : resolved.basemaps.world === "detail" ? data.worldDetail : data.worldCoarse;
46177
46183
  const worldLayer = decodeLayer(worldTopo);
46184
+ if (usCrisp && data.naLand) {
46185
+ const [nbW, nbS, nbE, nbN] = [-140, 10, -52, 66];
46186
+ const crisp = decodeLayer(data.naLand);
46187
+ for (const [iso, cf] of crisp) {
46188
+ const base = worldLayer.get(iso);
46189
+ if (!base) continue;
46190
+ const [[bw, bs], [be, bn]] = geoBounds2(base);
46191
+ if (bw >= nbW && be <= nbE && bs >= nbS && bn <= nbN)
46192
+ worldLayer.set(iso, cf);
46193
+ }
46194
+ }
46178
46195
  const usLayer = wantsUsStates ? decodeLayer(data.usStates) : null;
46179
46196
  const landTint = isDark ? LAND_TINT_DARK : LAND_TINT_LIGHT;
46180
46197
  const neutralFill = mix(palette.colors.green, palette.bg, landTint);
@@ -46320,6 +46337,10 @@ function layoutMap(resolved, data, size, opts) {
46320
46337
  return p ? stretch(p[0], p[1]) : null;
46321
46338
  };
46322
46339
  } else {
46340
+ projection.clipExtent([
46341
+ [0, 0],
46342
+ [width, height]
46343
+ ]);
46323
46344
  path = geoPath(projection);
46324
46345
  project = (lon, lat) => projection([lon, lat]) ?? null;
46325
46346
  }
@@ -46464,18 +46485,11 @@ function layoutMap(resolved, data, size, opts) {
46464
46485
  placeInset("US-HI", hawaiiProjection(), akRight + 24, width * 0.1);
46465
46486
  }
46466
46487
  const conusFit = resolved.projection === "albers-usa" && !!usLayer;
46467
- const cullExtent = conusFit ? geoBounds2(fitTarget) : resolved.extent;
46468
- const [[exW, exS], [exE, exN]] = cullExtent;
46469
- const lonSpan = exE - exW;
46470
- const latSpan = exN - exS;
46471
- const isGlobalView = lonSpan >= 270 || latSpan >= 130;
46472
- const padLon = Math.max(8, lonSpan * 0.35);
46473
- const padLat = Math.max(8, latSpan * 0.35);
46474
- const vW = exW - padLon;
46475
- const vE = exE + padLon;
46476
- const vS = exS - padLat;
46477
- const vN = exN + padLat;
46478
- const vLonCenter = (exW + exE) / 2;
46488
+ const classifyExtent = conusFit ? geoBounds2(fitTarget) : resolved.extent;
46489
+ const dLonSpan = classifyExtent[1][0] - classifyExtent[0][0];
46490
+ const dLatSpan = classifyExtent[1][1] - classifyExtent[0][1];
46491
+ const isGlobalView = dLonSpan >= 270 || dLatSpan >= 130;
46492
+ const vLonCenter = (classifyExtent[0][0] + classifyExtent[1][0]) / 2;
46479
46493
  const normLon = (lon) => {
46480
46494
  let L = lon;
46481
46495
  while (L < vLonCenter - 180) L += 360;
@@ -46483,23 +46497,28 @@ function layoutMap(resolved, data, size, opts) {
46483
46497
  return L;
46484
46498
  };
46485
46499
  const ringOverlapsView = (ring) => {
46486
- let anyIn = false;
46487
- let loMin = Infinity, loMax = -Infinity, laMin = Infinity, laMax = -Infinity, rawMin = Infinity, rawMax = -Infinity;
46488
- for (const [rawLon, lat] of ring) {
46500
+ let loMin = Infinity, loMax = -Infinity, rawMin = Infinity, rawMax = -Infinity;
46501
+ for (const [rawLon] of ring) {
46489
46502
  const lon = normLon(rawLon);
46490
- if (lon >= vW && lon <= vE && lat >= vS && lat <= vN) anyIn = true;
46491
46503
  if (lon < loMin) loMin = lon;
46492
46504
  if (lon > loMax) loMax = lon;
46493
46505
  if (rawLon < rawMin) rawMin = rawLon;
46494
46506
  if (rawLon > rawMax) rawMax = rawLon;
46495
- if (lat < laMin) laMin = lat;
46496
- if (lat > laMax) laMax = lat;
46497
46507
  }
46498
46508
  if (loMax - loMin > 270) return false;
46499
46509
  if (rawMax - rawMin > 180 && loMax - loMin < 90) return false;
46500
- if (anyIn) return true;
46501
- if (loMax - loMin > 180) return false;
46502
- return !(loMax < vW || loMin > vE || laMax < vS || laMin > vN);
46510
+ let px0 = Infinity, py0 = Infinity, px1 = -Infinity, py1 = -Infinity, anyFinite = false;
46511
+ for (const [lon, lat] of ring) {
46512
+ const p = project(lon, lat);
46513
+ if (!p || !Number.isFinite(p[0]) || !Number.isFinite(p[1])) continue;
46514
+ anyFinite = true;
46515
+ if (p[0] < px0) px0 = p[0];
46516
+ if (p[0] > px1) px1 = p[0];
46517
+ if (p[1] < py0) py0 = p[1];
46518
+ if (p[1] > py1) py1 = p[1];
46519
+ }
46520
+ if (!anyFinite) return false;
46521
+ return !(px1 < 0 || px0 > width || py1 < 0 || py0 > height);
46503
46522
  };
46504
46523
  const cullFeatureToView = (f) => {
46505
46524
  if (isGlobalView) return f;
@@ -46890,19 +46909,39 @@ function layoutMap(resolved, data, size, opts) {
46890
46909
  const text = labelText(p);
46891
46910
  return { text, w: measureLegendText(text, FONT) };
46892
46911
  };
46912
+ const GAP = 3;
46913
+ const inlineRect = (p, w, side) => {
46914
+ switch (side) {
46915
+ case "right":
46916
+ return { x: p.cx + p.r + GAP, y: p.cy - poiLabH / 2, w, h: poiLabH };
46917
+ case "left":
46918
+ return {
46919
+ x: p.cx - p.r - GAP - w,
46920
+ y: p.cy - poiLabH / 2,
46921
+ w,
46922
+ h: poiLabH
46923
+ };
46924
+ case "above":
46925
+ return {
46926
+ x: p.cx - w / 2,
46927
+ y: p.cy - p.r - GAP - poiLabH,
46928
+ w,
46929
+ h: poiLabH
46930
+ };
46931
+ case "below":
46932
+ return { x: p.cx - w / 2, y: p.cy + p.r + GAP, w, h: poiLabH };
46933
+ }
46934
+ };
46893
46935
  const pushInline = (p, text, w, side) => {
46894
- const tx = side === "right" ? p.cx + p.r + 3 : p.cx - p.r - 3;
46895
- obstacles.push({
46896
- x: side === "right" ? tx : tx - w,
46897
- y: p.cy - poiLabH / 2,
46898
- w,
46899
- h: poiLabH
46900
- });
46936
+ const rect = inlineRect(p, w, side);
46937
+ obstacles.push(rect);
46938
+ const anchor = side === "right" ? "start" : side === "left" ? "end" : "middle";
46939
+ const x = side === "right" ? rect.x : side === "left" ? rect.x + w : p.cx;
46901
46940
  labels.push({
46902
- x: tx,
46903
- y: p.cy + FONT / 3,
46941
+ x,
46942
+ y: rect.y + poiLabH / 2 + FONT / 3,
46904
46943
  text,
46905
- anchor: side === "right" ? "start" : "end",
46944
+ anchor,
46906
46945
  color: palette.text,
46907
46946
  halo: true,
46908
46947
  haloColor: palette.bg,
@@ -46911,14 +46950,8 @@ function layoutMap(resolved, data, size, opts) {
46911
46950
  });
46912
46951
  };
46913
46952
  const inlineFits = (p, w, side) => {
46914
- const tx = side === "right" ? p.cx + p.r + 3 : p.cx - p.r - 3;
46915
- const rect = {
46916
- x: side === "right" ? tx : tx - w,
46917
- y: p.cy - poiLabH / 2,
46918
- w,
46919
- h: poiLabH
46920
- };
46921
- return rect.x >= 0 && rect.x + rect.w <= width && !collides(rect);
46953
+ const rect = inlineRect(p, w, side);
46954
+ return rect.x >= 0 && rect.x + rect.w <= width && rect.y >= 0 && rect.y + rect.h <= height && !collides(rect);
46922
46955
  };
46923
46956
  const GROUP_R = 30;
46924
46957
  const groups = [];
@@ -46975,12 +47008,11 @@ function layoutMap(resolved, data, size, opts) {
46975
47008
  if (g.length === 1) {
46976
47009
  const p = g[0];
46977
47010
  const { text, w } = labelInfo(p);
46978
- if (inlineFits(p, w, "right")) {
46979
- pushInline(p, text, w, "right");
46980
- continue;
46981
- }
46982
- if (inlineFits(p, w, "left")) {
46983
- pushInline(p, text, w, "left");
47011
+ const side = ["right", "left", "above", "below"].find(
47012
+ (s) => inlineFits(p, w, s)
47013
+ );
47014
+ if (side) {
47015
+ pushInline(p, text, w, side);
46984
47016
  continue;
46985
47017
  }
46986
47018
  }
@@ -53733,18 +53765,18 @@ function getRotateFn(mode) {
53733
53765
  return () => 0;
53734
53766
  }
53735
53767
  function renderWordCloudAsync(container, parsed, palette, _isDark, exportDims) {
53736
- return new Promise((resolve2) => {
53768
+ return new Promise((resolve) => {
53737
53769
  d3Selection23.select(container).selectAll(":not([data-d3-tooltip])").remove();
53738
53770
  const { words, cloudOptions } = parsed;
53739
53771
  const title = parsed.noTitle ? null : parsed.title;
53740
53772
  if (words.length === 0) {
53741
- resolve2();
53773
+ resolve();
53742
53774
  return;
53743
53775
  }
53744
53776
  const width = exportDims?.width ?? container.clientWidth;
53745
53777
  const height = exportDims?.height ?? container.clientHeight;
53746
53778
  if (width <= 0 || height <= 0) {
53747
- resolve2();
53779
+ resolve();
53748
53780
  return;
53749
53781
  }
53750
53782
  const titleHeight = title ? 40 : 0;
@@ -53773,7 +53805,7 @@ function renderWordCloudAsync(container, parsed, palette, _isDark, exportDims) {
53773
53805
  "transform",
53774
53806
  (d) => `translate(${d.x},${d.y}) rotate(${d.rotate})`
53775
53807
  ).text((d) => d.text);
53776
- resolve2();
53808
+ resolve();
53777
53809
  }).start();
53778
53810
  });
53779
53811
  }