@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/advanced.cjs CHANGED
@@ -46197,7 +46197,7 @@ function resolveMap(parsed, data) {
46197
46197
  const lonSpan = extent2[1][0] - extent2[0][0];
46198
46198
  const latSpan = extent2[1][1] - extent2[0][1];
46199
46199
  const span = Math.max(lonSpan, latSpan);
46200
- const usDominant = (inferredCountry === "US" || subdivisions.includes("us-states")) && !regions.some((r) => r.layer === "country" && r.iso !== "US") && !anyNonUsPoi;
46200
+ const usDominant = (subdivisions.includes("us-states") || regions.some((r) => r.layer === "us-state")) && !regions.some((r) => r.layer === "country" && r.iso !== "US") && !anyNonUsPoi;
46201
46201
  let projection;
46202
46202
  const override = parsed.directives.projection;
46203
46203
  if (override === "equirectangular" || override === "natural-earth" || override === "albers-usa" || override === "mercator") {
@@ -46303,14 +46303,22 @@ var load_data_exports = {};
46303
46303
  __export(load_data_exports, {
46304
46304
  loadMapData: () => loadMapData
46305
46305
  });
46306
- async function readJson(dir, name) {
46307
- return JSON.parse(await (0, import_promises.readFile)((0, import_node_path.resolve)(dir, name), "utf8"));
46306
+ async function loadNodeBuiltins() {
46307
+ const [{ readFile }, { fileURLToPath }, { dirname: dirname2, resolve }] = await Promise.all([
46308
+ import("fs/promises"),
46309
+ import("url"),
46310
+ import("path")
46311
+ ]);
46312
+ return { readFile, fileURLToPath, dirname: dirname2, resolve };
46313
+ }
46314
+ async function readJson(nb, dir, name) {
46315
+ return JSON.parse(await nb.readFile(nb.resolve(dir, name), "utf8"));
46308
46316
  }
46309
- async function firstExistingDir(baseDir) {
46317
+ async function firstExistingDir(nb, baseDir) {
46310
46318
  for (const rel of CANDIDATE_DIRS) {
46311
- const dir = (0, import_node_path.resolve)(baseDir, rel);
46319
+ const dir = nb.resolve(baseDir, rel);
46312
46320
  try {
46313
- await (0, import_promises.readFile)((0, import_node_path.resolve)(dir, FILES.gazetteer), "utf8");
46321
+ await nb.readFile(nb.resolve(dir, FILES.gazetteer), "utf8");
46314
46322
  return dir;
46315
46323
  } catch {
46316
46324
  }
@@ -46326,10 +46334,10 @@ function validate(data) {
46326
46334
  }
46327
46335
  return data;
46328
46336
  }
46329
- function moduleBaseDir() {
46337
+ function moduleBaseDir(nb) {
46330
46338
  try {
46331
46339
  const url = import_meta.url;
46332
- if (url) return (0, import_node_path.dirname)((0, import_node_url.fileURLToPath)(url));
46340
+ if (url) return nb.dirname(nb.fileURLToPath(url));
46333
46341
  } catch {
46334
46342
  }
46335
46343
  if (typeof __dirname !== "undefined") return __dirname;
@@ -46337,7 +46345,8 @@ function moduleBaseDir() {
46337
46345
  }
46338
46346
  function loadMapData() {
46339
46347
  cache ??= (async () => {
46340
- const dir = await firstExistingDir(moduleBaseDir());
46348
+ const nb = await loadNodeBuiltins();
46349
+ const dir = await firstExistingDir(nb, moduleBaseDir(nb));
46341
46350
  const [
46342
46351
  worldCoarse,
46343
46352
  worldDetail,
@@ -46348,15 +46357,15 @@ function loadMapData() {
46348
46357
  naLakes,
46349
46358
  gazetteer
46350
46359
  ] = await Promise.all([
46351
- readJson(dir, FILES.worldCoarse),
46352
- readJson(dir, FILES.worldDetail),
46353
- readJson(dir, FILES.usStates),
46360
+ readJson(nb, dir, FILES.worldCoarse),
46361
+ readJson(nb, dir, FILES.worldDetail),
46362
+ readJson(nb, dir, FILES.usStates),
46354
46363
  // Lakes/rivers/NA assets are optional — older bundles may predate them.
46355
- readJson(dir, FILES.lakes).catch(() => void 0),
46356
- readJson(dir, FILES.rivers).catch(() => void 0),
46357
- readJson(dir, FILES.naLand).catch(() => void 0),
46358
- readJson(dir, FILES.naLakes).catch(() => void 0),
46359
- readJson(dir, FILES.gazetteer)
46364
+ readJson(nb, dir, FILES.lakes).catch(() => void 0),
46365
+ readJson(nb, dir, FILES.rivers).catch(() => void 0),
46366
+ readJson(nb, dir, FILES.naLand).catch(() => void 0),
46367
+ readJson(nb, dir, FILES.naLakes).catch(() => void 0),
46368
+ readJson(nb, dir, FILES.gazetteer)
46360
46369
  ]);
46361
46370
  return validate({
46362
46371
  worldCoarse,
@@ -46374,13 +46383,10 @@ function loadMapData() {
46374
46383
  });
46375
46384
  return cache;
46376
46385
  }
46377
- var import_promises, import_node_url, import_node_path, import_meta, FILES, CANDIDATE_DIRS, cache;
46386
+ var import_meta, FILES, CANDIDATE_DIRS, cache;
46378
46387
  var init_load_data = __esm({
46379
46388
  "src/map/load-data.ts"() {
46380
46389
  "use strict";
46381
- import_promises = require("fs/promises");
46382
- import_node_url = require("url");
46383
- import_node_path = require("path");
46384
46390
  import_meta = {};
46385
46391
  FILES = {
46386
46392
  worldCoarse: "world-coarse.json",
@@ -46442,8 +46448,19 @@ function layoutMap(resolved, data, size, opts) {
46442
46448
  const { width, height } = size;
46443
46449
  const wantsUsStates = resolved.basemaps.subdivisions.includes("us-states");
46444
46450
  const usCrisp = resolved.projection === "albers-usa" && wantsUsStates && !!data.naLand;
46445
- const worldTopo = usCrisp ? data.naLand : resolved.basemaps.world === "detail" ? data.worldDetail : data.worldCoarse;
46451
+ const worldTopo = usCrisp ? data.worldDetail : resolved.basemaps.world === "detail" ? data.worldDetail : data.worldCoarse;
46446
46452
  const worldLayer = decodeLayer(worldTopo);
46453
+ if (usCrisp && data.naLand) {
46454
+ const [nbW, nbS, nbE, nbN] = [-140, 10, -52, 66];
46455
+ const crisp = decodeLayer(data.naLand);
46456
+ for (const [iso, cf] of crisp) {
46457
+ const base = worldLayer.get(iso);
46458
+ if (!base) continue;
46459
+ const [[bw, bs], [be, bn]] = (0, import_d3_geo2.geoBounds)(base);
46460
+ if (bw >= nbW && be <= nbE && bs >= nbS && bn <= nbN)
46461
+ worldLayer.set(iso, cf);
46462
+ }
46463
+ }
46447
46464
  const usLayer = wantsUsStates ? decodeLayer(data.usStates) : null;
46448
46465
  const landTint = isDark ? LAND_TINT_DARK : LAND_TINT_LIGHT;
46449
46466
  const neutralFill = mix(palette.colors.green, palette.bg, landTint);
@@ -46589,6 +46606,10 @@ function layoutMap(resolved, data, size, opts) {
46589
46606
  return p ? stretch(p[0], p[1]) : null;
46590
46607
  };
46591
46608
  } else {
46609
+ projection.clipExtent([
46610
+ [0, 0],
46611
+ [width, height]
46612
+ ]);
46592
46613
  path = (0, import_d3_geo2.geoPath)(projection);
46593
46614
  project = (lon, lat) => projection([lon, lat]) ?? null;
46594
46615
  }
@@ -46733,18 +46754,11 @@ function layoutMap(resolved, data, size, opts) {
46733
46754
  placeInset("US-HI", hawaiiProjection(), akRight + 24, width * 0.1);
46734
46755
  }
46735
46756
  const conusFit = resolved.projection === "albers-usa" && !!usLayer;
46736
- const cullExtent = conusFit ? (0, import_d3_geo2.geoBounds)(fitTarget) : resolved.extent;
46737
- const [[exW, exS], [exE, exN]] = cullExtent;
46738
- const lonSpan = exE - exW;
46739
- const latSpan = exN - exS;
46740
- const isGlobalView = lonSpan >= 270 || latSpan >= 130;
46741
- const padLon = Math.max(8, lonSpan * 0.35);
46742
- const padLat = Math.max(8, latSpan * 0.35);
46743
- const vW = exW - padLon;
46744
- const vE = exE + padLon;
46745
- const vS = exS - padLat;
46746
- const vN = exN + padLat;
46747
- const vLonCenter = (exW + exE) / 2;
46757
+ const classifyExtent = conusFit ? (0, import_d3_geo2.geoBounds)(fitTarget) : resolved.extent;
46758
+ const dLonSpan = classifyExtent[1][0] - classifyExtent[0][0];
46759
+ const dLatSpan = classifyExtent[1][1] - classifyExtent[0][1];
46760
+ const isGlobalView = dLonSpan >= 270 || dLatSpan >= 130;
46761
+ const vLonCenter = (classifyExtent[0][0] + classifyExtent[1][0]) / 2;
46748
46762
  const normLon = (lon) => {
46749
46763
  let L = lon;
46750
46764
  while (L < vLonCenter - 180) L += 360;
@@ -46752,23 +46766,28 @@ function layoutMap(resolved, data, size, opts) {
46752
46766
  return L;
46753
46767
  };
46754
46768
  const ringOverlapsView = (ring) => {
46755
- let anyIn = false;
46756
- let loMin = Infinity, loMax = -Infinity, laMin = Infinity, laMax = -Infinity, rawMin = Infinity, rawMax = -Infinity;
46757
- for (const [rawLon, lat] of ring) {
46769
+ let loMin = Infinity, loMax = -Infinity, rawMin = Infinity, rawMax = -Infinity;
46770
+ for (const [rawLon] of ring) {
46758
46771
  const lon = normLon(rawLon);
46759
- if (lon >= vW && lon <= vE && lat >= vS && lat <= vN) anyIn = true;
46760
46772
  if (lon < loMin) loMin = lon;
46761
46773
  if (lon > loMax) loMax = lon;
46762
46774
  if (rawLon < rawMin) rawMin = rawLon;
46763
46775
  if (rawLon > rawMax) rawMax = rawLon;
46764
- if (lat < laMin) laMin = lat;
46765
- if (lat > laMax) laMax = lat;
46766
46776
  }
46767
46777
  if (loMax - loMin > 270) return false;
46768
46778
  if (rawMax - rawMin > 180 && loMax - loMin < 90) return false;
46769
- if (anyIn) return true;
46770
- if (loMax - loMin > 180) return false;
46771
- return !(loMax < vW || loMin > vE || laMax < vS || laMin > vN);
46779
+ let px0 = Infinity, py0 = Infinity, px1 = -Infinity, py1 = -Infinity, anyFinite = false;
46780
+ for (const [lon, lat] of ring) {
46781
+ const p = project(lon, lat);
46782
+ if (!p || !Number.isFinite(p[0]) || !Number.isFinite(p[1])) continue;
46783
+ anyFinite = true;
46784
+ if (p[0] < px0) px0 = p[0];
46785
+ if (p[0] > px1) px1 = p[0];
46786
+ if (p[1] < py0) py0 = p[1];
46787
+ if (p[1] > py1) py1 = p[1];
46788
+ }
46789
+ if (!anyFinite) return false;
46790
+ return !(px1 < 0 || px0 > width || py1 < 0 || py0 > height);
46772
46791
  };
46773
46792
  const cullFeatureToView = (f) => {
46774
46793
  if (isGlobalView) return f;
@@ -47159,19 +47178,39 @@ function layoutMap(resolved, data, size, opts) {
47159
47178
  const text = labelText(p);
47160
47179
  return { text, w: measureLegendText(text, FONT) };
47161
47180
  };
47181
+ const GAP = 3;
47182
+ const inlineRect = (p, w, side) => {
47183
+ switch (side) {
47184
+ case "right":
47185
+ return { x: p.cx + p.r + GAP, y: p.cy - poiLabH / 2, w, h: poiLabH };
47186
+ case "left":
47187
+ return {
47188
+ x: p.cx - p.r - GAP - w,
47189
+ y: p.cy - poiLabH / 2,
47190
+ w,
47191
+ h: poiLabH
47192
+ };
47193
+ case "above":
47194
+ return {
47195
+ x: p.cx - w / 2,
47196
+ y: p.cy - p.r - GAP - poiLabH,
47197
+ w,
47198
+ h: poiLabH
47199
+ };
47200
+ case "below":
47201
+ return { x: p.cx - w / 2, y: p.cy + p.r + GAP, w, h: poiLabH };
47202
+ }
47203
+ };
47162
47204
  const pushInline = (p, text, w, side) => {
47163
- const tx = side === "right" ? p.cx + p.r + 3 : p.cx - p.r - 3;
47164
- obstacles.push({
47165
- x: side === "right" ? tx : tx - w,
47166
- y: p.cy - poiLabH / 2,
47167
- w,
47168
- h: poiLabH
47169
- });
47205
+ const rect = inlineRect(p, w, side);
47206
+ obstacles.push(rect);
47207
+ const anchor = side === "right" ? "start" : side === "left" ? "end" : "middle";
47208
+ const x = side === "right" ? rect.x : side === "left" ? rect.x + w : p.cx;
47170
47209
  labels.push({
47171
- x: tx,
47172
- y: p.cy + FONT / 3,
47210
+ x,
47211
+ y: rect.y + poiLabH / 2 + FONT / 3,
47173
47212
  text,
47174
- anchor: side === "right" ? "start" : "end",
47213
+ anchor,
47175
47214
  color: palette.text,
47176
47215
  halo: true,
47177
47216
  haloColor: palette.bg,
@@ -47180,14 +47219,8 @@ function layoutMap(resolved, data, size, opts) {
47180
47219
  });
47181
47220
  };
47182
47221
  const inlineFits = (p, w, side) => {
47183
- const tx = side === "right" ? p.cx + p.r + 3 : p.cx - p.r - 3;
47184
- const rect = {
47185
- x: side === "right" ? tx : tx - w,
47186
- y: p.cy - poiLabH / 2,
47187
- w,
47188
- h: poiLabH
47189
- };
47190
- return rect.x >= 0 && rect.x + rect.w <= width && !collides(rect);
47222
+ const rect = inlineRect(p, w, side);
47223
+ return rect.x >= 0 && rect.x + rect.w <= width && rect.y >= 0 && rect.y + rect.h <= height && !collides(rect);
47191
47224
  };
47192
47225
  const GROUP_R = 30;
47193
47226
  const groups = [];
@@ -47244,12 +47277,11 @@ function layoutMap(resolved, data, size, opts) {
47244
47277
  if (g.length === 1) {
47245
47278
  const p = g[0];
47246
47279
  const { text, w } = labelInfo(p);
47247
- if (inlineFits(p, w, "right")) {
47248
- pushInline(p, text, w, "right");
47249
- continue;
47250
- }
47251
- if (inlineFits(p, w, "left")) {
47252
- pushInline(p, text, w, "left");
47280
+ const side = ["right", "left", "above", "below"].find(
47281
+ (s) => inlineFits(p, w, s)
47282
+ );
47283
+ if (side) {
47284
+ pushInline(p, text, w, side);
47253
47285
  continue;
47254
47286
  }
47255
47287
  }
@@ -54055,18 +54087,18 @@ function renderWordCloud(container, parsed, palette, _isDark, onClickItem, expor
54055
54087
  }).start();
54056
54088
  }
54057
54089
  function renderWordCloudAsync(container, parsed, palette, _isDark, exportDims) {
54058
- return new Promise((resolve2) => {
54090
+ return new Promise((resolve) => {
54059
54091
  d3Selection23.select(container).selectAll(":not([data-d3-tooltip])").remove();
54060
54092
  const { words, cloudOptions } = parsed;
54061
54093
  const title = parsed.noTitle ? null : parsed.title;
54062
54094
  if (words.length === 0) {
54063
- resolve2();
54095
+ resolve();
54064
54096
  return;
54065
54097
  }
54066
54098
  const width = exportDims?.width ?? container.clientWidth;
54067
54099
  const height = exportDims?.height ?? container.clientHeight;
54068
54100
  if (width <= 0 || height <= 0) {
54069
- resolve2();
54101
+ resolve();
54070
54102
  return;
54071
54103
  }
54072
54104
  const titleHeight = title ? 40 : 0;
@@ -54095,7 +54127,7 @@ function renderWordCloudAsync(container, parsed, palette, _isDark, exportDims) {
54095
54127
  "transform",
54096
54128
  (d) => `translate(${d.x},${d.y}) rotate(${d.rotate})`
54097
54129
  ).text((d) => d.text);
54098
- resolve2();
54130
+ resolve();
54099
54131
  }).start();
54100
54132
  });
54101
54133
  }
@@ -57528,12 +57560,12 @@ var KNOWN_HEADER_OPTIONS = /* @__PURE__ */ new Set([
57528
57560
  "solid-fill",
57529
57561
  "active-tag"
57530
57562
  ]);
57531
- function dirname2(filePath) {
57563
+ function dirname(filePath) {
57532
57564
  const last = filePath.lastIndexOf("/");
57533
57565
  return last > 0 ? filePath.substring(0, last) : "/";
57534
57566
  }
57535
57567
  function resolvePath(base, relative) {
57536
- const parts = dirname2(base).split("/");
57568
+ const parts = dirname(base).split("/");
57537
57569
  for (const seg of relative.split("/")) {
57538
57570
  if (seg === "..") {
57539
57571
  if (parts.length > 1) parts.pop();
@@ -59660,7 +59692,7 @@ init_dgmo_router();
59660
59692
 
59661
59693
  // src/migrate/index.ts
59662
59694
  var import_node_fs = require("fs");
59663
- var import_node_path2 = require("path");
59695
+ var import_node_path = require("path");
59664
59696
  init_dgmo_router();
59665
59697
 
59666
59698
  // src/migrate/line-classifier.ts
package/dist/advanced.js CHANGED
@@ -46213,7 +46213,7 @@ function resolveMap(parsed, data) {
46213
46213
  const lonSpan = extent2[1][0] - extent2[0][0];
46214
46214
  const latSpan = extent2[1][1] - extent2[0][1];
46215
46215
  const span = Math.max(lonSpan, latSpan);
46216
- const usDominant = (inferredCountry === "US" || subdivisions.includes("us-states")) && !regions.some((r) => r.layer === "country" && r.iso !== "US") && !anyNonUsPoi;
46216
+ const usDominant = (subdivisions.includes("us-states") || regions.some((r) => r.layer === "us-state")) && !regions.some((r) => r.layer === "country" && r.iso !== "US") && !anyNonUsPoi;
46217
46217
  let projection;
46218
46218
  const override = parsed.directives.projection;
46219
46219
  if (override === "equirectangular" || override === "natural-earth" || override === "albers-usa" || override === "mercator") {
@@ -46319,17 +46319,22 @@ var load_data_exports = {};
46319
46319
  __export(load_data_exports, {
46320
46320
  loadMapData: () => loadMapData
46321
46321
  });
46322
- import { readFile } from "fs/promises";
46323
- import { fileURLToPath } from "url";
46324
- import { dirname, resolve } from "path";
46325
- async function readJson(dir, name) {
46326
- return JSON.parse(await readFile(resolve(dir, name), "utf8"));
46322
+ async function loadNodeBuiltins() {
46323
+ const [{ readFile }, { fileURLToPath }, { dirname: dirname2, resolve }] = await Promise.all([
46324
+ import("fs/promises"),
46325
+ import("url"),
46326
+ import("path")
46327
+ ]);
46328
+ return { readFile, fileURLToPath, dirname: dirname2, resolve };
46329
+ }
46330
+ async function readJson(nb, dir, name) {
46331
+ return JSON.parse(await nb.readFile(nb.resolve(dir, name), "utf8"));
46327
46332
  }
46328
- async function firstExistingDir(baseDir) {
46333
+ async function firstExistingDir(nb, baseDir) {
46329
46334
  for (const rel of CANDIDATE_DIRS) {
46330
- const dir = resolve(baseDir, rel);
46335
+ const dir = nb.resolve(baseDir, rel);
46331
46336
  try {
46332
- await readFile(resolve(dir, FILES.gazetteer), "utf8");
46337
+ await nb.readFile(nb.resolve(dir, FILES.gazetteer), "utf8");
46333
46338
  return dir;
46334
46339
  } catch {
46335
46340
  }
@@ -46345,10 +46350,10 @@ function validate(data) {
46345
46350
  }
46346
46351
  return data;
46347
46352
  }
46348
- function moduleBaseDir() {
46353
+ function moduleBaseDir(nb) {
46349
46354
  try {
46350
46355
  const url = import.meta.url;
46351
- if (url) return dirname(fileURLToPath(url));
46356
+ if (url) return nb.dirname(nb.fileURLToPath(url));
46352
46357
  } catch {
46353
46358
  }
46354
46359
  if (typeof __dirname !== "undefined") return __dirname;
@@ -46356,7 +46361,8 @@ function moduleBaseDir() {
46356
46361
  }
46357
46362
  function loadMapData() {
46358
46363
  cache ??= (async () => {
46359
- const dir = await firstExistingDir(moduleBaseDir());
46364
+ const nb = await loadNodeBuiltins();
46365
+ const dir = await firstExistingDir(nb, moduleBaseDir(nb));
46360
46366
  const [
46361
46367
  worldCoarse,
46362
46368
  worldDetail,
@@ -46367,15 +46373,15 @@ function loadMapData() {
46367
46373
  naLakes,
46368
46374
  gazetteer
46369
46375
  ] = await Promise.all([
46370
- readJson(dir, FILES.worldCoarse),
46371
- readJson(dir, FILES.worldDetail),
46372
- readJson(dir, FILES.usStates),
46376
+ readJson(nb, dir, FILES.worldCoarse),
46377
+ readJson(nb, dir, FILES.worldDetail),
46378
+ readJson(nb, dir, FILES.usStates),
46373
46379
  // Lakes/rivers/NA assets are optional — older bundles may predate them.
46374
- readJson(dir, FILES.lakes).catch(() => void 0),
46375
- readJson(dir, FILES.rivers).catch(() => void 0),
46376
- readJson(dir, FILES.naLand).catch(() => void 0),
46377
- readJson(dir, FILES.naLakes).catch(() => void 0),
46378
- readJson(dir, FILES.gazetteer)
46380
+ readJson(nb, dir, FILES.lakes).catch(() => void 0),
46381
+ readJson(nb, dir, FILES.rivers).catch(() => void 0),
46382
+ readJson(nb, dir, FILES.naLand).catch(() => void 0),
46383
+ readJson(nb, dir, FILES.naLakes).catch(() => void 0),
46384
+ readJson(nb, dir, FILES.gazetteer)
46379
46385
  ]);
46380
46386
  return validate({
46381
46387
  worldCoarse,
@@ -46467,8 +46473,19 @@ function layoutMap(resolved, data, size, opts) {
46467
46473
  const { width, height } = size;
46468
46474
  const wantsUsStates = resolved.basemaps.subdivisions.includes("us-states");
46469
46475
  const usCrisp = resolved.projection === "albers-usa" && wantsUsStates && !!data.naLand;
46470
- const worldTopo = usCrisp ? data.naLand : resolved.basemaps.world === "detail" ? data.worldDetail : data.worldCoarse;
46476
+ const worldTopo = usCrisp ? data.worldDetail : resolved.basemaps.world === "detail" ? data.worldDetail : data.worldCoarse;
46471
46477
  const worldLayer = decodeLayer(worldTopo);
46478
+ if (usCrisp && data.naLand) {
46479
+ const [nbW, nbS, nbE, nbN] = [-140, 10, -52, 66];
46480
+ const crisp = decodeLayer(data.naLand);
46481
+ for (const [iso, cf] of crisp) {
46482
+ const base = worldLayer.get(iso);
46483
+ if (!base) continue;
46484
+ const [[bw, bs], [be, bn]] = geoBounds2(base);
46485
+ if (bw >= nbW && be <= nbE && bs >= nbS && bn <= nbN)
46486
+ worldLayer.set(iso, cf);
46487
+ }
46488
+ }
46472
46489
  const usLayer = wantsUsStates ? decodeLayer(data.usStates) : null;
46473
46490
  const landTint = isDark ? LAND_TINT_DARK : LAND_TINT_LIGHT;
46474
46491
  const neutralFill = mix(palette.colors.green, palette.bg, landTint);
@@ -46614,6 +46631,10 @@ function layoutMap(resolved, data, size, opts) {
46614
46631
  return p ? stretch(p[0], p[1]) : null;
46615
46632
  };
46616
46633
  } else {
46634
+ projection.clipExtent([
46635
+ [0, 0],
46636
+ [width, height]
46637
+ ]);
46617
46638
  path = geoPath(projection);
46618
46639
  project = (lon, lat) => projection([lon, lat]) ?? null;
46619
46640
  }
@@ -46758,18 +46779,11 @@ function layoutMap(resolved, data, size, opts) {
46758
46779
  placeInset("US-HI", hawaiiProjection(), akRight + 24, width * 0.1);
46759
46780
  }
46760
46781
  const conusFit = resolved.projection === "albers-usa" && !!usLayer;
46761
- const cullExtent = conusFit ? geoBounds2(fitTarget) : resolved.extent;
46762
- const [[exW, exS], [exE, exN]] = cullExtent;
46763
- const lonSpan = exE - exW;
46764
- const latSpan = exN - exS;
46765
- const isGlobalView = lonSpan >= 270 || latSpan >= 130;
46766
- const padLon = Math.max(8, lonSpan * 0.35);
46767
- const padLat = Math.max(8, latSpan * 0.35);
46768
- const vW = exW - padLon;
46769
- const vE = exE + padLon;
46770
- const vS = exS - padLat;
46771
- const vN = exN + padLat;
46772
- const vLonCenter = (exW + exE) / 2;
46782
+ const classifyExtent = conusFit ? geoBounds2(fitTarget) : resolved.extent;
46783
+ const dLonSpan = classifyExtent[1][0] - classifyExtent[0][0];
46784
+ const dLatSpan = classifyExtent[1][1] - classifyExtent[0][1];
46785
+ const isGlobalView = dLonSpan >= 270 || dLatSpan >= 130;
46786
+ const vLonCenter = (classifyExtent[0][0] + classifyExtent[1][0]) / 2;
46773
46787
  const normLon = (lon) => {
46774
46788
  let L = lon;
46775
46789
  while (L < vLonCenter - 180) L += 360;
@@ -46777,23 +46791,28 @@ function layoutMap(resolved, data, size, opts) {
46777
46791
  return L;
46778
46792
  };
46779
46793
  const ringOverlapsView = (ring) => {
46780
- let anyIn = false;
46781
- let loMin = Infinity, loMax = -Infinity, laMin = Infinity, laMax = -Infinity, rawMin = Infinity, rawMax = -Infinity;
46782
- for (const [rawLon, lat] of ring) {
46794
+ let loMin = Infinity, loMax = -Infinity, rawMin = Infinity, rawMax = -Infinity;
46795
+ for (const [rawLon] of ring) {
46783
46796
  const lon = normLon(rawLon);
46784
- if (lon >= vW && lon <= vE && lat >= vS && lat <= vN) anyIn = true;
46785
46797
  if (lon < loMin) loMin = lon;
46786
46798
  if (lon > loMax) loMax = lon;
46787
46799
  if (rawLon < rawMin) rawMin = rawLon;
46788
46800
  if (rawLon > rawMax) rawMax = rawLon;
46789
- if (lat < laMin) laMin = lat;
46790
- if (lat > laMax) laMax = lat;
46791
46801
  }
46792
46802
  if (loMax - loMin > 270) return false;
46793
46803
  if (rawMax - rawMin > 180 && loMax - loMin < 90) return false;
46794
- if (anyIn) return true;
46795
- if (loMax - loMin > 180) return false;
46796
- return !(loMax < vW || loMin > vE || laMax < vS || laMin > vN);
46804
+ let px0 = Infinity, py0 = Infinity, px1 = -Infinity, py1 = -Infinity, anyFinite = false;
46805
+ for (const [lon, lat] of ring) {
46806
+ const p = project(lon, lat);
46807
+ if (!p || !Number.isFinite(p[0]) || !Number.isFinite(p[1])) continue;
46808
+ anyFinite = true;
46809
+ if (p[0] < px0) px0 = p[0];
46810
+ if (p[0] > px1) px1 = p[0];
46811
+ if (p[1] < py0) py0 = p[1];
46812
+ if (p[1] > py1) py1 = p[1];
46813
+ }
46814
+ if (!anyFinite) return false;
46815
+ return !(px1 < 0 || px0 > width || py1 < 0 || py0 > height);
46797
46816
  };
46798
46817
  const cullFeatureToView = (f) => {
46799
46818
  if (isGlobalView) return f;
@@ -47184,19 +47203,39 @@ function layoutMap(resolved, data, size, opts) {
47184
47203
  const text = labelText(p);
47185
47204
  return { text, w: measureLegendText(text, FONT) };
47186
47205
  };
47206
+ const GAP = 3;
47207
+ const inlineRect = (p, w, side) => {
47208
+ switch (side) {
47209
+ case "right":
47210
+ return { x: p.cx + p.r + GAP, y: p.cy - poiLabH / 2, w, h: poiLabH };
47211
+ case "left":
47212
+ return {
47213
+ x: p.cx - p.r - GAP - w,
47214
+ y: p.cy - poiLabH / 2,
47215
+ w,
47216
+ h: poiLabH
47217
+ };
47218
+ case "above":
47219
+ return {
47220
+ x: p.cx - w / 2,
47221
+ y: p.cy - p.r - GAP - poiLabH,
47222
+ w,
47223
+ h: poiLabH
47224
+ };
47225
+ case "below":
47226
+ return { x: p.cx - w / 2, y: p.cy + p.r + GAP, w, h: poiLabH };
47227
+ }
47228
+ };
47187
47229
  const pushInline = (p, text, w, side) => {
47188
- const tx = side === "right" ? p.cx + p.r + 3 : p.cx - p.r - 3;
47189
- obstacles.push({
47190
- x: side === "right" ? tx : tx - w,
47191
- y: p.cy - poiLabH / 2,
47192
- w,
47193
- h: poiLabH
47194
- });
47230
+ const rect = inlineRect(p, w, side);
47231
+ obstacles.push(rect);
47232
+ const anchor = side === "right" ? "start" : side === "left" ? "end" : "middle";
47233
+ const x = side === "right" ? rect.x : side === "left" ? rect.x + w : p.cx;
47195
47234
  labels.push({
47196
- x: tx,
47197
- y: p.cy + FONT / 3,
47235
+ x,
47236
+ y: rect.y + poiLabH / 2 + FONT / 3,
47198
47237
  text,
47199
- anchor: side === "right" ? "start" : "end",
47238
+ anchor,
47200
47239
  color: palette.text,
47201
47240
  halo: true,
47202
47241
  haloColor: palette.bg,
@@ -47205,14 +47244,8 @@ function layoutMap(resolved, data, size, opts) {
47205
47244
  });
47206
47245
  };
47207
47246
  const inlineFits = (p, w, side) => {
47208
- const tx = side === "right" ? p.cx + p.r + 3 : p.cx - p.r - 3;
47209
- const rect = {
47210
- x: side === "right" ? tx : tx - w,
47211
- y: p.cy - poiLabH / 2,
47212
- w,
47213
- h: poiLabH
47214
- };
47215
- return rect.x >= 0 && rect.x + rect.w <= width && !collides(rect);
47247
+ const rect = inlineRect(p, w, side);
47248
+ return rect.x >= 0 && rect.x + rect.w <= width && rect.y >= 0 && rect.y + rect.h <= height && !collides(rect);
47216
47249
  };
47217
47250
  const GROUP_R = 30;
47218
47251
  const groups = [];
@@ -47269,12 +47302,11 @@ function layoutMap(resolved, data, size, opts) {
47269
47302
  if (g.length === 1) {
47270
47303
  const p = g[0];
47271
47304
  const { text, w } = labelInfo(p);
47272
- if (inlineFits(p, w, "right")) {
47273
- pushInline(p, text, w, "right");
47274
- continue;
47275
- }
47276
- if (inlineFits(p, w, "left")) {
47277
- pushInline(p, text, w, "left");
47305
+ const side = ["right", "left", "above", "below"].find(
47306
+ (s) => inlineFits(p, w, s)
47307
+ );
47308
+ if (side) {
47309
+ pushInline(p, text, w, side);
47278
47310
  continue;
47279
47311
  }
47280
47312
  }
@@ -54083,18 +54115,18 @@ function renderWordCloud(container, parsed, palette, _isDark, onClickItem, expor
54083
54115
  }).start();
54084
54116
  }
54085
54117
  function renderWordCloudAsync(container, parsed, palette, _isDark, exportDims) {
54086
- return new Promise((resolve2) => {
54118
+ return new Promise((resolve) => {
54087
54119
  d3Selection23.select(container).selectAll(":not([data-d3-tooltip])").remove();
54088
54120
  const { words, cloudOptions } = parsed;
54089
54121
  const title = parsed.noTitle ? null : parsed.title;
54090
54122
  if (words.length === 0) {
54091
- resolve2();
54123
+ resolve();
54092
54124
  return;
54093
54125
  }
54094
54126
  const width = exportDims?.width ?? container.clientWidth;
54095
54127
  const height = exportDims?.height ?? container.clientHeight;
54096
54128
  if (width <= 0 || height <= 0) {
54097
- resolve2();
54129
+ resolve();
54098
54130
  return;
54099
54131
  }
54100
54132
  const titleHeight = title ? 40 : 0;
@@ -54123,7 +54155,7 @@ function renderWordCloudAsync(container, parsed, palette, _isDark, exportDims) {
54123
54155
  "transform",
54124
54156
  (d) => `translate(${d.x},${d.y}) rotate(${d.rotate})`
54125
54157
  ).text((d) => d.text);
54126
- resolve2();
54158
+ resolve();
54127
54159
  }).start();
54128
54160
  });
54129
54161
  }
@@ -57273,12 +57305,12 @@ var KNOWN_HEADER_OPTIONS = /* @__PURE__ */ new Set([
57273
57305
  "solid-fill",
57274
57306
  "active-tag"
57275
57307
  ]);
57276
- function dirname2(filePath) {
57308
+ function dirname(filePath) {
57277
57309
  const last = filePath.lastIndexOf("/");
57278
57310
  return last > 0 ? filePath.substring(0, last) : "/";
57279
57311
  }
57280
57312
  function resolvePath(base, relative) {
57281
- const parts = dirname2(base).split("/");
57313
+ const parts = dirname(base).split("/");
57282
57314
  for (const seg of relative.split("/")) {
57283
57315
  if (seg === "..") {
57284
57316
  if (parts.length > 1) parts.pop();