@diagrammo/dgmo 0.20.3 → 0.21.1

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.
Files changed (48) hide show
  1. package/dist/advanced.cjs +867 -286
  2. package/dist/advanced.js +866 -286
  3. package/dist/auto.cjs +635 -284
  4. package/dist/auto.js +113 -113
  5. package/dist/auto.mjs +635 -284
  6. package/dist/cli.cjs +156 -156
  7. package/dist/editor.cjs +6 -2
  8. package/dist/editor.js +6 -2
  9. package/dist/highlight.cjs +6 -2
  10. package/dist/highlight.js +6 -2
  11. package/dist/index.cjs +628 -281
  12. package/dist/index.js +628 -281
  13. package/dist/internal.cjs +867 -286
  14. package/dist/internal.js +866 -286
  15. package/dist/map-data/PROVENANCE.json +1 -1
  16. package/dist/map-data/mountain-ranges.json +1 -0
  17. package/docs/language-reference.md +27 -25
  18. package/gallery/fixtures/map-choropleth.dgmo +7 -7
  19. package/gallery/fixtures/map-direct-color.dgmo +10 -0
  20. package/gallery/fixtures/map-pois.dgmo +4 -4
  21. package/gallery/fixtures/map-region-scope.dgmo +8 -8
  22. package/gallery/fixtures/map-route.dgmo +5 -6
  23. package/package.json +1 -1
  24. package/src/advanced.ts +14 -0
  25. package/src/completion.ts +10 -4
  26. package/src/d3.ts +15 -9
  27. package/src/editor/keywords.ts +6 -2
  28. package/src/map/data/PROVENANCE.json +1 -1
  29. package/src/map/data/mountain-ranges.json +1 -0
  30. package/src/map/geo-query.ts +277 -0
  31. package/src/map/geo.ts +258 -1
  32. package/src/map/invert.ts +111 -0
  33. package/src/map/layout.ts +333 -139
  34. package/src/map/load-data.ts +7 -1
  35. package/src/map/parser.ts +142 -33
  36. package/src/map/renderer.ts +57 -6
  37. package/src/map/resolved-types.ts +21 -2
  38. package/src/map/resolver.ts +219 -53
  39. package/src/map/types.ts +57 -14
  40. package/src/utils/reserved-key-registry.ts +7 -7
  41. package/dist/advanced.d.cts +0 -5290
  42. package/dist/advanced.d.ts +0 -5290
  43. package/dist/auto.d.cts +0 -39
  44. package/dist/auto.d.ts +0 -39
  45. package/dist/index.d.cts +0 -336
  46. package/dist/index.d.ts +0 -336
  47. package/dist/internal.d.cts +0 -5290
  48. package/dist/internal.d.ts +0 -5290
package/dist/auto.cjs CHANGED
@@ -760,13 +760,9 @@ var init_reserved_key_registry = __esm({
760
760
  "icon"
761
761
  ]);
762
762
  MAP_REGISTRY = staticRegistry([
763
- "score",
763
+ "value",
764
764
  "label",
765
- "size",
766
- "description",
767
- "weight",
768
- "style",
769
- "date"
765
+ "style"
770
766
  ]);
771
767
  ORG_REGISTRY = staticRegistry([
772
768
  "color",
@@ -15779,7 +15775,8 @@ function parseMap(content) {
15779
15775
  continue;
15780
15776
  }
15781
15777
  if (open.route && indent > open.route.indent) {
15782
- open.route.route.stops.push(parseStop(trimmed, lineNumber));
15778
+ const leg = parseLeg(trimmed, lineNumber, open.route.route.style);
15779
+ open.route.route.legs.push(leg);
15783
15780
  continue;
15784
15781
  }
15785
15782
  if (open.poi && indent > open.poi.indent) {
@@ -15810,6 +15807,10 @@ function parseMap(content) {
15810
15807
  handleTag(trimmed, lineNumber);
15811
15808
  continue;
15812
15809
  }
15810
+ if ((firstWord === "muted" || firstWord === "natural") && trimmed === firstWord) {
15811
+ handleDirective(firstWord, "", lineNumber);
15812
+ continue;
15813
+ }
15813
15814
  if (DIRECTIVE_SET.has(firstWord) && !trimmed.slice(firstWord.length).trimStart().startsWith(":")) {
15814
15815
  handleDirective(
15815
15816
  firstWord,
@@ -15874,13 +15875,20 @@ function parseMap(content) {
15874
15875
  );
15875
15876
  d.projection = value;
15876
15877
  break;
15877
- case "metric":
15878
- dup(d.metric);
15879
- d.metric = value;
15878
+ case "region-metric": {
15879
+ dup(d.regionMetric);
15880
+ const { label: rmLabel, colorName: rmColor } = peelTrailingColorName(value);
15881
+ d.regionMetric = rmLabel;
15882
+ if (rmColor) d.regionMetricColor = rmColor;
15883
+ break;
15884
+ }
15885
+ case "poi-metric":
15886
+ dup(d.poiMetric);
15887
+ d.poiMetric = value;
15880
15888
  break;
15881
- case "size-metric":
15882
- dup(d.sizeMetric);
15883
- d.sizeMetric = value;
15889
+ case "flow-metric":
15890
+ dup(d.flowMetric);
15891
+ d.flowMetric = value;
15884
15892
  break;
15885
15893
  case "scale":
15886
15894
  dup(d.scale);
@@ -15922,6 +15930,21 @@ function parseMap(content) {
15922
15930
  case "no-legend":
15923
15931
  d.noLegend = true;
15924
15932
  break;
15933
+ case "no-insets":
15934
+ d.noInsets = true;
15935
+ break;
15936
+ case "relief":
15937
+ d.relief = true;
15938
+ break;
15939
+ case "muted":
15940
+ case "natural":
15941
+ if (d.basemapStyle !== void 0 && d.basemapStyle !== key)
15942
+ pushWarning(
15943
+ line12,
15944
+ `Conflicting basemap dress \u2014 "${d.basemapStyle}" then "${key}"; last wins.`
15945
+ );
15946
+ d.basemapStyle = key;
15947
+ break;
15925
15948
  case "subtitle":
15926
15949
  dup(d.subtitle);
15927
15950
  d.subtitle = value;
@@ -15999,14 +16022,14 @@ function parseMap(content) {
15999
16022
  line12
16000
16023
  );
16001
16024
  const { tags, meta } = partitionMeta(split.meta, tagGroupNames());
16002
- let scoreNum;
16003
- const score = meta["score"];
16004
- if (score !== void 0) {
16005
- delete meta["score"];
16006
- scoreNum = Number(score);
16007
- if (!Number.isFinite(scoreNum)) {
16008
- pushError(line12, `score must be a number (got "${score}").`);
16009
- scoreNum = void 0;
16025
+ let valueNum;
16026
+ const value = meta["value"];
16027
+ if (value !== void 0) {
16028
+ delete meta["value"];
16029
+ valueNum = Number(value);
16030
+ if (!Number.isFinite(valueNum)) {
16031
+ pushError(line12, `value must be a number (got "${value}").`);
16032
+ valueNum = void 0;
16010
16033
  }
16011
16034
  }
16012
16035
  let regionName = split.name;
@@ -16024,7 +16047,8 @@ function parseMap(content) {
16024
16047
  lineNumber: line12
16025
16048
  };
16026
16049
  if (regionScope !== void 0) region.scope = regionScope;
16027
- if (scoreNum !== void 0) region.score = scoreNum;
16050
+ if (valueNum !== void 0) region.value = valueNum;
16051
+ if (split.color) region.color = split.color;
16028
16052
  regions.push(region);
16029
16053
  }
16030
16054
  function handlePoi(rest, line12, indent) {
@@ -16049,28 +16073,81 @@ function parseMap(content) {
16049
16073
  const poi = { pos, tags, meta, lineNumber: line12 };
16050
16074
  if (split.alias) poi.alias = split.alias;
16051
16075
  if (label !== void 0) poi.label = label;
16076
+ if (split.color) poi.color = split.color;
16052
16077
  pois.push(poi);
16053
16078
  open.poi = { poi, indent };
16054
16079
  }
16055
16080
  function handleRoute(rest, line12, indent) {
16056
- const meta = rest ? splitNameAndMeta(rest, registry(), aliasMap).meta : {};
16057
- const route = { stops: [], meta, lineNumber: line12 };
16081
+ const split = rest ? splitNameAndMeta(
16082
+ rest,
16083
+ registry(),
16084
+ aliasMap,
16085
+ void 0,
16086
+ diagnostics,
16087
+ line12
16088
+ ) : { name: "", meta: {}, alias: void 0 };
16089
+ const pos = parsePos(split.name, line12);
16090
+ if (!pos || pos.kind === "name" && !pos.name) {
16091
+ pushError(
16092
+ line12,
16093
+ "route requires an origin: `route <origin> [style: arc]`."
16094
+ );
16095
+ return;
16096
+ }
16097
+ const { tags, meta } = partitionMeta(split.meta, tagGroupNames());
16098
+ const originLabel = meta["label"];
16099
+ const originValue = meta["value"];
16100
+ const style = meta["style"] === "arc" ? "arc" : "straight";
16101
+ const route = {
16102
+ origin: pos,
16103
+ ...split.alias !== void 0 && { originAlias: split.alias },
16104
+ ...originLabel !== void 0 && { originLabel },
16105
+ ...originValue !== void 0 && { originValue },
16106
+ originTags: tags,
16107
+ style,
16108
+ legs: [],
16109
+ lineNumber: line12
16110
+ };
16058
16111
  routes.push(route);
16059
16112
  open.route = { route, indent };
16060
16113
  }
16061
- function parseStop(trimmed, line12) {
16062
- const split = splitNameAndMeta(trimmed, registry(), aliasMap);
16063
- const ref = parsePos(split.name, line12) ?? {
16114
+ function parseLeg(trimmed, line12, headerStyle) {
16115
+ let arrowStyle = "straight";
16116
+ let label;
16117
+ let rest = trimmed;
16118
+ const m = trimmed.match(LEG_ARROW_RE);
16119
+ if (m) {
16120
+ const arr = classifyArrow(m[1], line12);
16121
+ arrowStyle = arr.style;
16122
+ label = arr.label;
16123
+ rest = m[2];
16124
+ }
16125
+ const split = splitNameAndMeta(
16126
+ rest,
16127
+ registry(),
16128
+ aliasMap,
16129
+ void 0,
16130
+ diagnostics,
16131
+ line12
16132
+ );
16133
+ const pos = parsePos(split.name, line12) ?? {
16064
16134
  kind: "name",
16065
16135
  name: split.name
16066
16136
  };
16067
- const stop = {
16068
- ref,
16069
- meta: split.meta,
16137
+ const { tags, meta } = partitionMeta(split.meta, tagGroupNames());
16138
+ const value = meta["value"];
16139
+ const destLabel = meta["label"];
16140
+ const style = arrowStyle === "arc" || headerStyle === "arc" ? "arc" : "straight";
16141
+ return {
16142
+ ...label !== void 0 && { label },
16143
+ style,
16144
+ ...value !== void 0 && { value },
16145
+ dest: pos,
16146
+ ...split.alias !== void 0 && { destAlias: split.alias },
16147
+ ...destLabel !== void 0 && { destLabel },
16148
+ destTags: tags,
16070
16149
  lineNumber: line12
16071
16150
  };
16072
- if (split.alias) stop.alias = split.alias;
16073
- return stop;
16074
16151
  }
16075
16152
  function handleEdges(trimmed, line12) {
16076
16153
  const parts = trimmed.split(ARROW_SPLIT);
@@ -16172,7 +16249,7 @@ function partitionMeta(meta, tagGroupNames) {
16172
16249
  function poiName(pos) {
16173
16250
  return pos.kind === "name" ? pos.name : void 0;
16174
16251
  }
16175
- var COORD_RE, NUMERIC_LEAD_RE, SCOPE_RE, ARROW_SPLIT, HUB_RE, AT_RE, DIRECTIVE_SET;
16252
+ var COORD_RE, NUMERIC_LEAD_RE, SCOPE_RE, ARROW_SPLIT, HUB_RE, LEG_ARROW_RE, AT_RE, DIRECTIVE_SET;
16176
16253
  var init_parser12 = __esm({
16177
16254
  "src/map/parser.ts"() {
16178
16255
  "use strict";
@@ -16186,12 +16263,14 @@ var init_parser12 = __esm({
16186
16263
  SCOPE_RE = /^[A-Z]{2}(?:-[A-Z0-9]{1,3})?$/;
16187
16264
  ARROW_SPLIT = /\s+(-[^>]*?->|->|~[^>]*?~>|~>|--)\s+/;
16188
16265
  HUB_RE = /^(->|~>)\s+(.+)$/;
16266
+ LEG_ARROW_RE = /^(-[^>]*?->|->|~[^>]*?~>|~>|--)\s+(.+)$/;
16189
16267
  AT_RE = /(^|[\s,])at\s*:/i;
16190
16268
  DIRECTIVE_SET = /* @__PURE__ */ new Set([
16191
16269
  "region",
16192
16270
  "projection",
16193
- "metric",
16194
- "size-metric",
16271
+ "region-metric",
16272
+ "poi-metric",
16273
+ "flow-metric",
16195
16274
  "scale",
16196
16275
  "region-labels",
16197
16276
  "poi-labels",
@@ -16199,6 +16278,8 @@ var init_parser12 = __esm({
16199
16278
  "default-state",
16200
16279
  "active-tag",
16201
16280
  "no-legend",
16281
+ "no-insets",
16282
+ "relief",
16202
16283
  "subtitle",
16203
16284
  "caption"
16204
16285
  ]);
@@ -45423,6 +45504,74 @@ function featureBbox(topo, geomId) {
45423
45504
  [b[1][0], b[1][1]]
45424
45505
  ];
45425
45506
  }
45507
+ function explodePolygons(gj) {
45508
+ const g = gj.geometry ?? gj;
45509
+ const t = g.type;
45510
+ const coords = g.coordinates;
45511
+ if (t === "Polygon") {
45512
+ return [
45513
+ { type: "Feature", geometry: { type: "Polygon", coordinates: coords } }
45514
+ ];
45515
+ }
45516
+ if (t === "MultiPolygon") {
45517
+ return coords.map((rings) => ({
45518
+ type: "Feature",
45519
+ geometry: { type: "Polygon", coordinates: rings }
45520
+ }));
45521
+ }
45522
+ return [];
45523
+ }
45524
+ function bboxGap(a, b) {
45525
+ const lonGap = Math.max(0, a[0][0] - b[1][0], b[0][0] - a[1][0]);
45526
+ const latGap = Math.max(0, a[0][1] - b[1][1], b[0][1] - a[1][1]);
45527
+ return Math.max(lonGap, latGap);
45528
+ }
45529
+ function featureBboxPrimary(topo, geomId) {
45530
+ const geom = geomObject(topo).geometries.find((g) => g.id === geomId);
45531
+ if (!geom) return null;
45532
+ const gj = (0, import_topojson_client.feature)(topo, geom);
45533
+ const parts = explodePolygons(gj);
45534
+ if (parts.length <= 1) return featureBbox(topo, geomId);
45535
+ const polys = parts.map((p) => {
45536
+ const b = (0, import_d3_geo.geoBounds)(p);
45537
+ if (!b || !Number.isFinite(b[0][0])) return null;
45538
+ const wraps = b[1][0] < b[0][0];
45539
+ const bbox = [
45540
+ [b[0][0], b[0][1]],
45541
+ [b[1][0], b[1][1]]
45542
+ ];
45543
+ return { bbox, area: (0, import_d3_geo.geoArea)(p), wraps };
45544
+ }).filter(
45545
+ (p) => p !== null
45546
+ );
45547
+ if (polys.length <= 1 || polys.some((p) => p.wraps))
45548
+ return featureBbox(topo, geomId);
45549
+ const maxArea = Math.max(...polys.map((p) => p.area));
45550
+ const anchor = polys.find((p) => p.area === maxArea);
45551
+ const cluster = [
45552
+ [anchor.bbox[0][0], anchor.bbox[0][1]],
45553
+ [anchor.bbox[1][0], anchor.bbox[1][1]]
45554
+ ];
45555
+ const remaining = polys.filter((p) => p !== anchor);
45556
+ let added = true;
45557
+ while (added) {
45558
+ added = false;
45559
+ for (let i = remaining.length - 1; i >= 0; i--) {
45560
+ const p = remaining[i];
45561
+ const near = bboxGap(p.bbox, cluster) <= DETACH_GAP_DEG;
45562
+ const large = p.area >= DETACH_AREA_FRAC * maxArea;
45563
+ if (near || large) {
45564
+ cluster[0][0] = Math.min(cluster[0][0], p.bbox[0][0]);
45565
+ cluster[0][1] = Math.min(cluster[0][1], p.bbox[0][1]);
45566
+ cluster[1][0] = Math.max(cluster[1][0], p.bbox[1][0]);
45567
+ cluster[1][1] = Math.max(cluster[1][1], p.bbox[1][1]);
45568
+ remaining.splice(i, 1);
45569
+ added = true;
45570
+ }
45571
+ }
45572
+ }
45573
+ return cluster;
45574
+ }
45426
45575
  function unionExtent(boxes, points) {
45427
45576
  const lats = [];
45428
45577
  const lons = [];
@@ -45461,13 +45610,15 @@ function unionLongitudes(lons) {
45461
45610
  }
45462
45611
  return { west: pts[gapIdx], east: pts[gapIdx - 1] + 360 };
45463
45612
  }
45464
- var import_topojson_client, import_d3_geo, fold;
45613
+ var import_topojson_client, import_d3_geo, fold, DETACH_GAP_DEG, DETACH_AREA_FRAC;
45465
45614
  var init_geo = __esm({
45466
45615
  "src/map/geo.ts"() {
45467
45616
  "use strict";
45468
45617
  import_topojson_client = require("topojson-client");
45469
45618
  import_d3_geo = require("d3-geo");
45470
45619
  fold = (s) => s.normalize("NFD").replace(/\p{Diacritic}/gu, "").toLowerCase().trim();
45620
+ DETACH_GAP_DEG = 10;
45621
+ DETACH_AREA_FRAC = 0.25;
45471
45622
  }
45472
45623
  });
45473
45624
 
@@ -45476,6 +45627,11 @@ var resolver_exports = {};
45476
45627
  __export(resolver_exports, {
45477
45628
  resolveMap: () => resolveMap
45478
45629
  });
45630
+ function usStateFromBareScope(scope) {
45631
+ if (!scope) return null;
45632
+ const up = scope.toUpperCase();
45633
+ return US_STATE_POSTAL.has(up) ? `US-${up}` : null;
45634
+ }
45479
45635
  function looksUS(lat, lon) {
45480
45636
  if (lat < 15 || lat > 72) return false;
45481
45637
  return lon >= -180 && lon <= -64 || lon >= 172;
@@ -45525,9 +45681,9 @@ function resolveMap(parsed, data) {
45525
45681
  const f = fold(r.name);
45526
45682
  return usStateIndex.has(f) && !countryIndex.has(f);
45527
45683
  }) || parsed.regions.some(
45528
- (r) => r.scope === "US" || r.scope?.startsWith("US-")
45684
+ (r) => r.scope === "US" || r.scope?.startsWith("US-") || usStateFromBareScope(r.scope) !== null
45529
45685
  ) || parsed.pois.some(
45530
- (p) => p.pos.kind === "name" && p.pos.scope?.startsWith("US-")
45686
+ (p) => p.pos.kind === "name" && (p.pos.scope?.startsWith("US-") || usStateFromBareScope(p.pos.scope) !== null)
45531
45687
  );
45532
45688
  const regions = [];
45533
45689
  const seenRegion = /* @__PURE__ */ new Map();
@@ -45566,12 +45722,12 @@ function resolveMap(parsed, data) {
45566
45722
  chosen = { ...inState, layer: "us-state" };
45567
45723
  } else {
45568
45724
  chosen = { ...inCountry, layer: "country" };
45725
+ warn2(
45726
+ r.lineNumber,
45727
+ `"${r.name}" is both a country and a US state \u2014 resolved as ${chosen.layer} (${chosen.id}). Pin it with an ISO code (${inState.id} / ${inCountry.id}) or name + scope ("${r.name} US" / "${r.name} ${inCountry.id}").`,
45728
+ "W_MAP_REGION_AMBIGUOUS"
45729
+ );
45569
45730
  }
45570
- warn2(
45571
- r.lineNumber,
45572
- `"${r.name}" is both a country and a US state \u2014 resolved as ${chosen.layer} (${chosen.id}). Pin it with an ISO code (${inState.id} / ${inCountry.id}) or name + scope ("${r.name} US" / "${r.name} ${inCountry.id}").`,
45573
- "W_MAP_REGION_AMBIGUOUS"
45574
- );
45575
45731
  } else if (inState) {
45576
45732
  chosen = { ...inState, layer: "us-state" };
45577
45733
  } else if (inCountry) {
@@ -45594,7 +45750,8 @@ function resolveMap(parsed, data) {
45594
45750
  iso: chosen.id,
45595
45751
  name: chosen.name,
45596
45752
  layer: chosen.layer,
45597
- ...r.score !== void 0 && { score: r.score },
45753
+ ...r.value !== void 0 && { value: r.value },
45754
+ ...r.color !== void 0 && { color: r.color },
45598
45755
  tags: r.tags,
45599
45756
  meta: r.meta,
45600
45757
  lineNumber: r.lineNumber
@@ -45652,9 +45809,10 @@ function resolveMap(parsed, data) {
45652
45809
  let cands = idxs.map((i) => data.gazetteer.cities[i]);
45653
45810
  const scopeUse = scope ?? scopeHint;
45654
45811
  if (scopeUse) {
45655
- const isSub = /^[A-Za-z]{2}-/.test(scopeUse);
45812
+ const bareState = usStateFromBareScope(scopeUse);
45813
+ const subScope = /^[A-Za-z]{2}-/.test(scopeUse) ? scopeUse : bareState;
45656
45814
  const filtered = cands.filter(
45657
- (c2) => isSub ? c2[5] === scopeUse : c2[2] === scopeUse
45815
+ (c2) => subScope ? c2[5] === subScope : c2[2] === scopeUse
45658
45816
  );
45659
45817
  if (filtered.length) cands = filtered;
45660
45818
  else if (scope) {
@@ -45735,6 +45893,7 @@ function resolveMap(parsed, data) {
45735
45893
  lat,
45736
45894
  lon,
45737
45895
  ...p.label !== void 0 && { label: p.label },
45896
+ ...p.color !== void 0 && { color: p.color },
45738
45897
  tags: p.tags,
45739
45898
  meta: p.meta,
45740
45899
  lineNumber: p.lineNumber
@@ -45783,33 +45942,89 @@ function resolveMap(parsed, data) {
45783
45942
  lineNumber: e.lineNumber
45784
45943
  });
45785
45944
  }
45786
- const routes = [];
45787
- for (const rt of parsed.routes) {
45788
- const stopIds = [];
45789
- for (const stop of rt.stops) {
45790
- let id;
45791
- if (stop.ref.kind === "coords") {
45792
- id = stop.alias ? fold(stop.alias) : `@${stop.ref.lat},${stop.ref.lon}`;
45793
- if (!looksUS(stop.ref.lat, stop.ref.lon)) anyNonUsPoi = true;
45794
- if (!registry.has(id)) {
45795
- const poi = {
45945
+ const resolveStop = (pos, alias, label, tags, sizeValue, line12) => {
45946
+ const meta = sizeValue !== void 0 ? { value: sizeValue } : {};
45947
+ if (pos.kind === "coords") {
45948
+ const id = alias ? fold(alias) : `@${pos.lat},${pos.lon}`;
45949
+ if (!looksUS(pos.lat, pos.lon)) anyNonUsPoi = true;
45950
+ if (!registry.has(id)) {
45951
+ registerPoi(
45952
+ id,
45953
+ {
45796
45954
  id,
45797
- ...stop.alias !== void 0 && { name: stop.alias },
45798
- lat: stop.ref.lat,
45799
- lon: stop.ref.lon,
45800
- tags: {},
45801
- meta: stop.meta,
45802
- lineNumber: stop.lineNumber,
45803
- implicit: true
45804
- };
45805
- registerPoi(id, poi, stop.lineNumber);
45806
- }
45807
- } else {
45808
- id = stop.alias && registry.has(fold(stop.alias)) ? fold(stop.alias) : resolveEndpoint2(stop.ref.name, stop.lineNumber);
45955
+ ...alias !== void 0 && { name: alias },
45956
+ lat: pos.lat,
45957
+ lon: pos.lon,
45958
+ ...label !== void 0 && { label },
45959
+ tags,
45960
+ meta,
45961
+ lineNumber: line12
45962
+ },
45963
+ line12
45964
+ );
45809
45965
  }
45810
- if (id) stopIds.push(id);
45966
+ return id;
45811
45967
  }
45812
- routes.push({ stopIds, meta: rt.meta, lineNumber: rt.lineNumber });
45968
+ const f = fold(pos.name);
45969
+ if (registry.has(f)) return f;
45970
+ const aliased = declaredByName.get(f);
45971
+ if (aliased) return aliased;
45972
+ const got = lookupName(pos.name, pos.scope, line12, inferredCountry, true);
45973
+ if (got.kind !== "ok") return null;
45974
+ noteCountry(got.iso);
45975
+ registerPoi(
45976
+ f,
45977
+ {
45978
+ id: f,
45979
+ name: pos.name,
45980
+ lat: got.lat,
45981
+ lon: got.lon,
45982
+ ...label !== void 0 && { label },
45983
+ tags,
45984
+ meta,
45985
+ lineNumber: line12
45986
+ },
45987
+ line12
45988
+ );
45989
+ return f;
45990
+ };
45991
+ const routes = [];
45992
+ for (const rt of parsed.routes) {
45993
+ const originId = resolveStop(
45994
+ rt.origin,
45995
+ rt.originAlias,
45996
+ rt.originLabel,
45997
+ rt.originTags,
45998
+ rt.originValue,
45999
+ rt.lineNumber
46000
+ );
46001
+ if (!originId) continue;
46002
+ const stopIds = [originId];
46003
+ const legs = [];
46004
+ let prevId = originId;
46005
+ for (const leg of rt.legs) {
46006
+ const destId = resolveStop(
46007
+ leg.dest,
46008
+ leg.destAlias,
46009
+ leg.destLabel,
46010
+ leg.destTags,
46011
+ void 0,
46012
+ // a leg's `value:` is leg thickness, not the dest's size
46013
+ leg.lineNumber
46014
+ );
46015
+ if (!destId) continue;
46016
+ legs.push({
46017
+ fromId: prevId,
46018
+ toId: destId,
46019
+ ...leg.label !== void 0 && { label: leg.label },
46020
+ style: leg.style,
46021
+ ...leg.value !== void 0 && { value: leg.value },
46022
+ lineNumber: leg.lineNumber
46023
+ });
46024
+ if (!stopIds.includes(destId)) stopIds.push(destId);
46025
+ prevId = destId;
46026
+ }
46027
+ routes.push({ stopIds, legs, lineNumber: rt.lineNumber });
45813
46028
  }
45814
46029
  const subdivisions = [];
45815
46030
  if (usSubdivisionReferenced || parsed.directives.region === "us-states")
@@ -45821,7 +46036,7 @@ function resolveMap(parsed, data) {
45821
46036
  }
45822
46037
  for (const r of regions) {
45823
46038
  if (r.layer === "country") {
45824
- const bb = featureBbox(data.worldCoarse, r.iso);
46039
+ const bb = featureBboxPrimary(data.worldCoarse, r.iso);
45825
46040
  if (bb) regionBoxes.push(bb);
45826
46041
  }
45827
46042
  }
@@ -45835,6 +46050,7 @@ function resolveMap(parsed, data) {
45835
46050
  const lonSpan = extent2[1][0] - extent2[0][0];
45836
46051
  const latSpan = extent2[1][1] - extent2[0][1];
45837
46052
  const span = Math.max(lonSpan, latSpan);
46053
+ const maxAbsLat = Math.max(Math.abs(extent2[0][1]), Math.abs(extent2[1][1]));
45838
46054
  const usDominant = (subdivisions.includes("us-states") || regions.some((r) => r.layer === "us-state")) && !regions.some((r) => r.layer === "country" && r.iso !== "US") && !anyNonUsPoi;
45839
46055
  let projection;
45840
46056
  const override = parsed.directives.projection;
@@ -45842,12 +46058,10 @@ function resolveMap(parsed, data) {
45842
46058
  projection = override;
45843
46059
  } else if (usDominant) {
45844
46060
  projection = "albers-usa";
45845
- } else if (span > WORLD_SPAN) {
46061
+ } else if (span > WORLD_SPAN || maxAbsLat > MERCATOR_MAX_LAT) {
45846
46062
  projection = "equirectangular";
45847
- } else if (span < MERCATOR_MAX_SPAN) {
45848
- projection = "mercator";
45849
46063
  } else {
45850
- projection = "equirectangular";
46064
+ projection = "mercator";
45851
46065
  }
45852
46066
  if (lonSpan >= 180) {
45853
46067
  extent2 = [
@@ -45901,14 +46115,14 @@ function firstError(diags) {
45901
46115
  const e = diags.find((d) => d.severity === "error");
45902
46116
  return e ? formatDgmoError(e) : null;
45903
46117
  }
45904
- var WORLD_SPAN, MERCATOR_MAX_SPAN, PAD_FRACTION, WORLD_LAT_SOUTH, WORLD_LAT_NORTH, REGION_ALIASES;
46118
+ var WORLD_SPAN, MERCATOR_MAX_LAT, PAD_FRACTION, WORLD_LAT_SOUTH, WORLD_LAT_NORTH, REGION_ALIASES, US_STATE_POSTAL;
45905
46119
  var init_resolver2 = __esm({
45906
46120
  "src/map/resolver.ts"() {
45907
46121
  "use strict";
45908
46122
  init_diagnostics();
45909
46123
  init_geo();
45910
46124
  WORLD_SPAN = 90;
45911
- MERCATOR_MAX_SPAN = 25;
46125
+ MERCATOR_MAX_LAT = 80;
45912
46126
  PAD_FRACTION = 0.05;
45913
46127
  WORLD_LAT_SOUTH = -58;
45914
46128
  WORLD_LAT_NORTH = 78;
@@ -45933,115 +46147,59 @@ var init_resolver2 = __esm({
45933
46147
  "north macedonia": "macedonia",
45934
46148
  "czech republic": "czechia"
45935
46149
  };
45936
- }
45937
- });
45938
-
45939
- // src/map/load-data.ts
45940
- var load_data_exports = {};
45941
- __export(load_data_exports, {
45942
- loadMapData: () => loadMapData
45943
- });
45944
- async function loadNodeBuiltins() {
45945
- const [{ readFile }, { fileURLToPath }, { dirname, resolve }] = await Promise.all([
45946
- import("fs/promises"),
45947
- import("url"),
45948
- import("path")
45949
- ]);
45950
- return { readFile, fileURLToPath, dirname, resolve };
45951
- }
45952
- async function readJson(nb, dir, name) {
45953
- return JSON.parse(await nb.readFile(nb.resolve(dir, name), "utf8"));
45954
- }
45955
- async function firstExistingDir(nb, baseDir) {
45956
- for (const rel of CANDIDATE_DIRS) {
45957
- const dir = nb.resolve(baseDir, rel);
45958
- try {
45959
- await nb.readFile(nb.resolve(dir, FILES.gazetteer), "utf8");
45960
- return dir;
45961
- } catch {
45962
- }
45963
- }
45964
- throw new Error(
45965
- `map data assets not found near ${baseDir} (looked in ${CANDIDATE_DIRS.join(", ")}). Run \`pnpm build:map-data\` and \`pnpm build\`.`
45966
- );
45967
- }
45968
- function validate(data) {
45969
- const topoOk = (t) => !!t && t.type === "Topology" && !!t.objects;
45970
- if (!topoOk(data.worldCoarse) || !topoOk(data.worldDetail) || !topoOk(data.usStates) || !data.gazetteer || !Array.isArray(data.gazetteer.cities) || !data.gazetteer.byName) {
45971
- throw new Error("map data assets are malformed (failed shape validation)");
45972
- }
45973
- return data;
45974
- }
45975
- function moduleBaseDir(nb) {
45976
- try {
45977
- const url = import_meta.url;
45978
- if (url) return nb.dirname(nb.fileURLToPath(url));
45979
- } catch {
45980
- }
45981
- if (typeof __dirname !== "undefined") return __dirname;
45982
- return process.cwd();
45983
- }
45984
- function loadMapData() {
45985
- cache ??= (async () => {
45986
- const nb = await loadNodeBuiltins();
45987
- const dir = await firstExistingDir(nb, moduleBaseDir(nb));
45988
- const [
45989
- worldCoarse,
45990
- worldDetail,
45991
- usStates,
45992
- lakes,
45993
- rivers,
45994
- naLand,
45995
- naLakes,
45996
- gazetteer
45997
- ] = await Promise.all([
45998
- readJson(nb, dir, FILES.worldCoarse),
45999
- readJson(nb, dir, FILES.worldDetail),
46000
- readJson(nb, dir, FILES.usStates),
46001
- // Lakes/rivers/NA assets are optional — older bundles may predate them.
46002
- readJson(nb, dir, FILES.lakes).catch(() => void 0),
46003
- readJson(nb, dir, FILES.rivers).catch(() => void 0),
46004
- readJson(nb, dir, FILES.naLand).catch(() => void 0),
46005
- readJson(nb, dir, FILES.naLakes).catch(() => void 0),
46006
- readJson(nb, dir, FILES.gazetteer)
46150
+ US_STATE_POSTAL = /* @__PURE__ */ new Set([
46151
+ "AL",
46152
+ "AK",
46153
+ "AZ",
46154
+ "AR",
46155
+ "CA",
46156
+ "CO",
46157
+ "CT",
46158
+ "DE",
46159
+ "FL",
46160
+ "GA",
46161
+ "HI",
46162
+ "ID",
46163
+ "IL",
46164
+ "IN",
46165
+ "IA",
46166
+ "KS",
46167
+ "KY",
46168
+ "LA",
46169
+ "ME",
46170
+ "MD",
46171
+ "MA",
46172
+ "MI",
46173
+ "MN",
46174
+ "MS",
46175
+ "MO",
46176
+ "MT",
46177
+ "NE",
46178
+ "NV",
46179
+ "NH",
46180
+ "NJ",
46181
+ "NM",
46182
+ "NY",
46183
+ "NC",
46184
+ "ND",
46185
+ "OH",
46186
+ "OK",
46187
+ "OR",
46188
+ "PA",
46189
+ "RI",
46190
+ "SC",
46191
+ "SD",
46192
+ "TN",
46193
+ "TX",
46194
+ "UT",
46195
+ "VT",
46196
+ "VA",
46197
+ "WA",
46198
+ "WV",
46199
+ "WI",
46200
+ "WY",
46201
+ "DC"
46007
46202
  ]);
46008
- return validate({
46009
- worldCoarse,
46010
- worldDetail,
46011
- usStates,
46012
- gazetteer,
46013
- ...lakes && { lakes },
46014
- ...rivers && { rivers },
46015
- ...naLand && { naLand },
46016
- ...naLakes && { naLakes }
46017
- });
46018
- })().catch((e) => {
46019
- cache = void 0;
46020
- throw e;
46021
- });
46022
- return cache;
46023
- }
46024
- var import_meta, FILES, CANDIDATE_DIRS, cache;
46025
- var init_load_data = __esm({
46026
- "src/map/load-data.ts"() {
46027
- "use strict";
46028
- import_meta = {};
46029
- FILES = {
46030
- worldCoarse: "world-coarse.json",
46031
- worldDetail: "world-detail.json",
46032
- usStates: "us-states.json",
46033
- lakes: "lakes.json",
46034
- rivers: "rivers.json",
46035
- naLand: "na-land.json",
46036
- naLakes: "na-lakes.json",
46037
- gazetteer: "gazetteer.json"
46038
- };
46039
- CANDIDATE_DIRS = [
46040
- "./data",
46041
- "./map-data",
46042
- "../map-data",
46043
- "../src/map/data"
46044
- ];
46045
46203
  }
46046
46204
  });
46047
46205
 
@@ -46071,8 +46229,19 @@ function projectionFor(family) {
46071
46229
  return (0, import_d3_geo2.geoEquirectangular)();
46072
46230
  }
46073
46231
  }
46074
- function mapBackgroundColor(palette) {
46075
- return mix(palette.colors.blue, palette.bg, WATER_TINT);
46232
+ function mapBackgroundColor(palette, isDark = false, _dataActive = false) {
46233
+ return mix(
46234
+ palette.colors.blue,
46235
+ palette.bg,
46236
+ isDark ? WATER_TINT_DARK : WATER_TINT_LIGHT
46237
+ );
46238
+ }
46239
+ function mapNeutralLandColor(palette, isDark, _dataActive = false) {
46240
+ return mix(
46241
+ palette.colors.green,
46242
+ palette.bg,
46243
+ isDark ? LAND_TINT_DARK : LAND_TINT_LIGHT
46244
+ );
46076
46245
  }
46077
46246
  function layoutMap(resolved, data, size, opts) {
46078
46247
  const { palette, isDark } = opts;
@@ -46093,28 +46262,19 @@ function layoutMap(resolved, data, size, opts) {
46093
46262
  }
46094
46263
  }
46095
46264
  const usLayer = wantsUsStates ? decodeLayer(data.usStates) : null;
46096
- const landTint = isDark ? LAND_TINT_DARK : LAND_TINT_LIGHT;
46097
- const neutralFill = mix(palette.colors.green, palette.bg, landTint);
46098
- const water = mapBackgroundColor(palette);
46099
46265
  const usContext = usLayer !== null;
46100
- const foreignFill = mix(
46101
- palette.colors.gray,
46102
- palette.bg,
46103
- isDark ? FOREIGN_TINT_DARK : FOREIGN_TINT_LIGHT
46104
- );
46105
46266
  const regionStroke = isDark ? mix(palette.bg, palette.text, 78) : mix(palette.text, palette.bg, 78);
46106
- const scores = resolved.regions.filter((r) => r.score !== void 0).map((r) => r.score);
46267
+ const values = resolved.regions.filter((r) => r.value !== void 0).map((r) => r.value);
46107
46268
  const scaleOverride = resolved.directives.scale;
46108
- const rampMin = scaleOverride ? scaleOverride.min : Math.min(...scores);
46109
- const rampMax = scaleOverride ? scaleOverride.max : Math.max(...scores);
46110
- const rampHue = palette.colors.red;
46111
- const hasRamp = scores.length > 0;
46112
- const SCORE_NAME = hasRamp ? resolved.directives.metric?.trim() || "Score" : null;
46269
+ const rampMin = scaleOverride ? scaleOverride.min : Math.min(...values);
46270
+ const rampMax = scaleOverride ? scaleOverride.max : Math.max(...values);
46271
+ const rampHue = resolveColor(resolved.directives.regionMetricColor ?? "", palette) ?? palette.colors.red;
46272
+ const hasRamp = values.length > 0;
46273
+ const VALUE_NAME = hasRamp ? resolved.directives.regionMetric?.trim() || "Value" : null;
46113
46274
  const matchColorGroup = (v) => {
46114
46275
  const lv = v.trim().toLowerCase();
46115
46276
  if (lv === "none") return null;
46116
- if (SCORE_NAME && (lv === "score" || lv === SCORE_NAME.toLowerCase()))
46117
- return SCORE_NAME;
46277
+ if (lv === VALUE_NAME?.toLowerCase()) return VALUE_NAME;
46118
46278
  const tg = resolved.tagGroups.find((g) => g.name.toLowerCase() === lv);
46119
46279
  return tg ? tg.name : v;
46120
46280
  };
@@ -46125,11 +46285,20 @@ function layoutMap(resolved, data, size, opts) {
46125
46285
  } else if (resolved.directives.activeTag !== void 0) {
46126
46286
  activeGroup = matchColorGroup(resolved.directives.activeTag);
46127
46287
  } else {
46128
- activeGroup = SCORE_NAME ?? (resolved.tagGroups.length > 0 ? resolved.tagGroups[0].name : null);
46288
+ activeGroup = VALUE_NAME ?? (resolved.tagGroups.length > 0 ? resolved.tagGroups[0].name : null);
46129
46289
  }
46130
- const activeIsScore = SCORE_NAME !== null && activeGroup === SCORE_NAME;
46290
+ const activeIsScore = VALUE_NAME !== null && activeGroup === VALUE_NAME;
46291
+ const mutedBasemap = resolved.directives.basemapStyle === "muted" ? true : resolved.directives.basemapStyle === "natural" ? false : activeGroup !== null;
46292
+ const neutralFill = mapNeutralLandColor(palette, isDark, mutedBasemap);
46293
+ const water = mapBackgroundColor(palette, isDark, mutedBasemap);
46294
+ const lakeStroke = mix(regionStroke, water, 45);
46295
+ const foreignFill = mix(
46296
+ palette.colors.gray,
46297
+ palette.bg,
46298
+ mutedBasemap ? isDark ? MUTED_FOREIGN_DARK : MUTED_FOREIGN_LIGHT : isDark ? FOREIGN_TINT_DARK : FOREIGN_TINT_LIGHT
46299
+ );
46131
46300
  const rampBase = isDark ? mix(palette.surface, palette.text, 28) : palette.bg;
46132
- const fillForScore = (s) => {
46301
+ const fillForValue = (s) => {
46133
46302
  const t = rampMax > rampMin ? (s - rampMin) / (rampMax - rampMin) : 1;
46134
46303
  const pct = RAMP_FLOOR + Math.max(0, Math.min(1, t)) * (100 - RAMP_FLOOR);
46135
46304
  return mix(rampHue, rampBase, pct);
@@ -46152,9 +46321,16 @@ function layoutMap(resolved, data, size, opts) {
46152
46321
  isDark ? TAG_TINT_DARK : TAG_TINT_LIGHT
46153
46322
  );
46154
46323
  };
46324
+ const directFill = (name) => {
46325
+ const hex = name ? resolveColor(name, palette) : null;
46326
+ if (!hex) return null;
46327
+ return mix(hex, palette.bg, isDark ? TAG_TINT_DARK : TAG_TINT_LIGHT);
46328
+ };
46155
46329
  const regionFill = (r) => {
46330
+ const direct = directFill(r.color);
46331
+ if (direct) return direct;
46156
46332
  if (activeIsScore) {
46157
- return r.score !== void 0 ? fillForScore(r.score) : neutralFill;
46333
+ return r.value !== void 0 ? fillForValue(r.value) : neutralFill;
46158
46334
  }
46159
46335
  return tagFill(r.tags, activeGroup) ?? neutralFill;
46160
46336
  };
@@ -46206,6 +46382,7 @@ function layoutMap(resolved, data, size, opts) {
46206
46382
  const fitIsGlobal = fitGB[1][0] - fitGB[0][0] >= 270 || fitGB[1][1] - fitGB[0][1] >= 130;
46207
46383
  let path;
46208
46384
  let project;
46385
+ let stretchParams = null;
46209
46386
  if (fitIsGlobal) {
46210
46387
  const cb = (0, import_d3_geo2.geoPath)(projection).bounds(fitTarget);
46211
46388
  const bx0 = cb[0][0];
@@ -46216,6 +46393,7 @@ function layoutMap(resolved, data, size, opts) {
46216
46393
  const oy = fitBox[0][1];
46217
46394
  const sx = cw > 0 ? (fitBox[1][0] - ox) / cw : 1;
46218
46395
  const sy = ch > 0 ? (fitBox[1][1] - oy) / ch : 1;
46396
+ stretchParams = { sx, sy, ox, oy, bx0, by0 };
46219
46397
  const stretch = (x, y) => [
46220
46398
  ox + (x - bx0) * sx,
46221
46399
  oy + (y - by0) * sy
@@ -46247,7 +46425,7 @@ function layoutMap(resolved, data, size, opts) {
46247
46425
  const insets = [];
46248
46426
  const insetRegions = [];
46249
46427
  const insetLabelSeeds = [];
46250
- if (resolved.projection === "albers-usa" && usLayer) {
46428
+ if (resolved.projection === "albers-usa" && usLayer && !resolved.directives.noInsets) {
46251
46429
  const PAD = 8;
46252
46430
  const GAP = 12;
46253
46431
  const yB = height - FIT_PAD;
@@ -46278,38 +46456,14 @@ function layoutMap(resolved, data, size, opts) {
46278
46456
  }
46279
46457
  return y;
46280
46458
  };
46281
- const coastTop = (x0, xr) => {
46459
+ const coastFloor = (x0, xr) => {
46282
46460
  const n = 24;
46283
- const pts = [];
46284
46461
  let maxY = -Infinity;
46285
46462
  for (let i = 0; i <= n; i++) {
46286
- const x = x0 + (xr - x0) * i / n;
46287
- const y = at(x);
46288
- if (y > -Infinity) {
46289
- pts.push([x, y]);
46290
- if (y > maxY) maxY = y;
46291
- }
46292
- }
46293
- if (pts.length === 0) return () => yB - height * 0.42;
46294
- let m = 0;
46295
- if (pts.length >= 2) {
46296
- let sx = 0, sy = 0, sxx = 0, sxy = 0;
46297
- for (const [x, y] of pts) {
46298
- sx += x;
46299
- sy += y;
46300
- sxx += x * x;
46301
- sxy += x * y;
46302
- }
46303
- const den = pts.length * sxx - sx * sx;
46304
- if (den !== 0) m = (pts.length * sxy - sx * sy) / den;
46305
- }
46306
- m = Math.max(-0.35, Math.min(0.35, m));
46307
- let c = -Infinity;
46308
- for (const [x, y] of pts) {
46309
- const need = y - m * x + GAP;
46310
- if (need > c) c = need;
46311
- }
46312
- return (x) => m * x + c;
46463
+ const y = at(x0 + (xr - x0) * i / n);
46464
+ if (y > maxY) maxY = y;
46465
+ }
46466
+ return maxY;
46313
46467
  };
46314
46468
  const placeInset = (iso, proj, boxX, iwReq) => {
46315
46469
  const f = usLayer.get(iso);
@@ -46318,19 +46472,15 @@ function layoutMap(resolved, data, size, opts) {
46318
46472
  const iw = Math.min(iwReq, width - FIT_PAD - x0 - 2 * PAD);
46319
46473
  if (iw < 24) return boxX;
46320
46474
  const xr = x0 + iw + 2 * PAD;
46321
- const top = coastTop(x0, xr);
46322
- const yL = top(x0);
46323
- const yR = top(xr);
46475
+ const floor = coastFloor(x0, xr);
46476
+ const topGuess = floor > -Infinity ? floor + GAP : yB - height * 0.42;
46324
46477
  proj.fitWidth(iw, f);
46325
46478
  const bb = (0, import_d3_geo2.geoPath)(proj).bounds(f);
46326
46479
  const sh = Number.isFinite(bb[0][0]) ? bb[1][1] - bb[0][1] : iw;
46327
46480
  const needH = sh + 2 * PAD;
46328
- let topFit = Math.max(yL, yR);
46481
+ let topFit = topGuess;
46329
46482
  const bottom = Math.min(topFit + needH, yB);
46330
46483
  if (bottom - topFit < needH) topFit = bottom - needH;
46331
- const lift = topFit - Math.max(yL, yR);
46332
- const topL = yL + lift;
46333
- const topR = yR + lift;
46334
46484
  proj.fitExtent(
46335
46485
  [
46336
46486
  [x0 + PAD, topFit + PAD],
@@ -46349,15 +46499,18 @@ function layoutMap(resolved, data, size, opts) {
46349
46499
  }
46350
46500
  insets.push({
46351
46501
  x: x0,
46352
- y: Math.min(topL, topR),
46502
+ y: topFit,
46353
46503
  w: xr - x0,
46354
- h: bottom - Math.min(topL, topR),
46504
+ h: bottom - topFit,
46355
46505
  points: [
46356
- [x0, topL],
46357
- [xr, topR],
46506
+ [x0, topFit],
46507
+ [xr, topFit],
46358
46508
  [xr, bottom],
46359
46509
  [x0, bottom]
46360
- ]
46510
+ ],
46511
+ // The FITTED inset projection (just fit to this box) — captured so the
46512
+ // geo-query can invert pixels inside the frame back to AK/HI coords.
46513
+ projection: proj
46361
46514
  });
46362
46515
  insetRegions.push({
46363
46516
  id: iso,
@@ -46366,7 +46519,7 @@ function layoutMap(resolved, data, size, opts) {
46366
46519
  stroke: regionStroke,
46367
46520
  lineNumber,
46368
46521
  layer: "us-state",
46369
- ...r?.score !== void 0 && { score: r.score },
46522
+ ...r?.value !== void 0 && { value: r.value },
46370
46523
  ...r && Object.keys(r.tags).length > 0 && { tags: r.tags }
46371
46524
  });
46372
46525
  const ctr = (0, import_d3_geo2.geoPath)(proj).centroid(f);
@@ -46509,7 +46662,7 @@ function layoutMap(resolved, data, size, opts) {
46509
46662
  lineNumber,
46510
46663
  layer,
46511
46664
  ...label !== void 0 && { label },
46512
- ...isThisLayer && r.score !== void 0 && { score: r.score },
46665
+ ...isThisLayer && r.value !== void 0 && { value: r.value },
46513
46666
  ...isThisLayer && Object.keys(r.tags).length > 0 && { tags: r.tags }
46514
46667
  });
46515
46668
  }
@@ -46527,13 +46680,40 @@ function layoutMap(resolved, data, size, opts) {
46527
46680
  id: "lake",
46528
46681
  d,
46529
46682
  fill: water,
46530
- stroke: "none",
46683
+ stroke: lakeStroke,
46531
46684
  lineNumber: -1,
46532
46685
  layer: "base"
46533
46686
  });
46534
46687
  }
46535
46688
  }
46536
- const riverColor = water;
46689
+ const relief = [];
46690
+ let reliefHatch = null;
46691
+ if (resolved.directives.relief === true && data.mountainRanges) {
46692
+ for (const [, f] of decodeLayer(data.mountainRanges)) {
46693
+ const viewF = isGlobalView ? dropFrameFillers(f) : cullFeatureToView(f);
46694
+ if (!viewF) continue;
46695
+ const area2 = path.area(viewF);
46696
+ if (!Number.isFinite(area2) || area2 < RELIEF_MIN_AREA) continue;
46697
+ const box = path.bounds(viewF);
46698
+ if (box[1][0] - box[0][0] < RELIEF_MIN_DIM || box[1][1] - box[0][1] < RELIEF_MIN_DIM)
46699
+ continue;
46700
+ const d = path(viewF) ?? "";
46701
+ if (!d) continue;
46702
+ relief.push({ d });
46703
+ }
46704
+ if (relief.length) {
46705
+ const darkTone = isDark ? palette.bg : palette.text;
46706
+ const lightTone = isDark ? palette.text : palette.bg;
46707
+ const landLum = relativeLuminance(neutralFill);
46708
+ const tone = Math.abs(landLum - relativeLuminance(darkTone)) > 0.04 ? darkTone : lightTone;
46709
+ reliefHatch = {
46710
+ color: mix(tone, neutralFill, RELIEF_HATCH_STRENGTH),
46711
+ spacing: RELIEF_HATCH_SPACING,
46712
+ width: RELIEF_HATCH_WIDTH
46713
+ };
46714
+ }
46715
+ }
46716
+ const riverColor = mix(water, regionStroke, 16);
46537
46717
  const rivers = [];
46538
46718
  if (data.rivers) {
46539
46719
  for (const [, f] of decodeLayer(data.rivers)) {
@@ -46544,16 +46724,19 @@ function layoutMap(resolved, data, size, opts) {
46544
46724
  rivers.push({ d, color: riverColor, width: RIVER_WIDTH });
46545
46725
  }
46546
46726
  }
46547
- const sizeVals = resolved.pois.map((p) => Number(p.meta["size"])).filter((n) => Number.isFinite(n) && n > 0);
46727
+ const sizeVals = resolved.pois.map((p) => Number(p.meta["value"])).filter((n) => Number.isFinite(n) && n > 0);
46548
46728
  const sizeMin = sizeVals.length ? Math.min(...sizeVals) : 0;
46549
46729
  const sizeMax = sizeVals.length ? Math.max(...sizeVals) : 0;
46550
46730
  const radiusFor = (p) => {
46551
- const v = Number(p.meta["size"]);
46731
+ const v = Number(p.meta["value"]);
46552
46732
  if (!Number.isFinite(v) || v <= 0 || sizeMax <= 0) return R_DEFAULT;
46553
46733
  const t = sizeMax > sizeMin ? (Math.sqrt(v) - Math.sqrt(sizeMin)) / (Math.sqrt(sizeMax) - Math.sqrt(sizeMin)) : 1;
46554
46734
  return R_MIN + Math.max(0, Math.min(1, t)) * (R_MAX - R_MIN);
46555
46735
  };
46556
46736
  const poiFill = (p) => {
46737
+ const directHex = p.color ? resolveColor(p.color, palette) : null;
46738
+ if (directHex)
46739
+ return { fill: directHex, stroke: mix(directHex, palette.text, 18) };
46557
46740
  for (const group of resolved.tagGroups) {
46558
46741
  const val = p.tags[group.name.toLowerCase()];
46559
46742
  if (!val) continue;
@@ -46615,7 +46798,8 @@ function layoutMap(resolved, data, size, opts) {
46615
46798
  lineNumber: e.p.lineNumber,
46616
46799
  implicit: !!e.p.implicit,
46617
46800
  isOrigin: originIds.has(e.p.id),
46618
- ...num !== void 0 && { routeNumber: num }
46801
+ ...num !== void 0 && { routeNumber: num },
46802
+ ...Object.keys(e.p.tags).length > 0 && { tags: e.p.tags }
46619
46803
  });
46620
46804
  });
46621
46805
  }
@@ -46651,26 +46835,40 @@ function layoutMap(resolved, data, size, opts) {
46651
46835
  const by = b.cy - (b.cy - py) / tb * trimB;
46652
46836
  return `M${ax},${ay}Q${px},${py} ${bx},${by}`;
46653
46837
  };
46838
+ const routeLegVals = resolved.routes.flatMap((rt) => rt.legs).map((l) => Number(l.value)).filter((n) => Number.isFinite(n) && n > 0);
46839
+ const rlMin = routeLegVals.length ? Math.min(...routeLegVals) : 0;
46840
+ const rlMax = routeLegVals.length ? Math.max(...routeLegVals) : 0;
46841
+ const routeWidthFor = (v) => {
46842
+ if (!Number.isFinite(v) || v <= 0 || rlMax <= 0) return W_MIN;
46843
+ const t = rlMax > rlMin ? (v - rlMin) / (rlMax - rlMin) : 1;
46844
+ return W_MIN + t * (W_MAX - W_MIN);
46845
+ };
46654
46846
  for (const rt of resolved.routes) {
46655
- const curved = rt.meta["style"] === "arc";
46656
- for (let i = 1; i < rt.stopIds.length; i++) {
46657
- const a = poiScreen.get(rt.stopIds[i - 1]);
46658
- const b = poiScreen.get(rt.stopIds[i]);
46847
+ for (const leg of rt.legs) {
46848
+ const a = poiScreen.get(leg.fromId);
46849
+ const b = poiScreen.get(leg.toId);
46659
46850
  if (!a || !b) continue;
46851
+ const mx = (a.cx + b.cx) / 2;
46852
+ const my = (a.cy + b.cy) / 2;
46660
46853
  legs.push({
46661
- d: legPath(a, b, curved, 0),
46662
- width: W_MIN,
46854
+ d: legPath(a, b, leg.style === "arc", 0),
46855
+ width: routeWidthFor(Number(leg.value)),
46663
46856
  color: mix(palette.text, palette.bg, 72),
46664
46857
  arrow: true,
46665
- lineNumber: rt.lineNumber
46858
+ lineNumber: leg.lineNumber,
46859
+ ...leg.label !== void 0 && {
46860
+ label: leg.label,
46861
+ labelX: mx,
46862
+ labelY: my - 4
46863
+ }
46666
46864
  });
46667
46865
  }
46668
46866
  }
46669
- const weightVals = resolved.edges.map((e) => Number(e.meta["weight"])).filter((n) => Number.isFinite(n) && n > 0);
46867
+ const weightVals = resolved.edges.map((e) => Number(e.meta["value"])).filter((n) => Number.isFinite(n) && n > 0);
46670
46868
  const wMin = weightVals.length ? Math.min(...weightVals) : 0;
46671
46869
  const wMax = weightVals.length ? Math.max(...weightVals) : 0;
46672
46870
  const widthFor = (e) => {
46673
- const v = Number(e.meta["weight"]);
46871
+ const v = Number(e.meta["value"]);
46674
46872
  if (!Number.isFinite(v) || v <= 0 || wMax <= 0) return W_MIN;
46675
46873
  const t = wMax > wMin ? (v - wMin) / (wMax - wMin) : 1;
46676
46874
  return W_MIN + t * (W_MAX - W_MIN);
@@ -46933,8 +47131,8 @@ function layoutMap(resolved, data, size, opts) {
46933
47131
  activeGroup,
46934
47132
  ...hasRamp && {
46935
47133
  ramp: {
46936
- ...resolved.directives.metric !== void 0 && {
46937
- metric: resolved.directives.metric
47134
+ ...resolved.directives.regionMetric !== void 0 && {
47135
+ metric: resolved.directives.regionMetric
46938
47136
  },
46939
47137
  min: rampMin,
46940
47138
  max: rampMax,
@@ -46954,21 +47152,26 @@ function layoutMap(resolved, data, size, opts) {
46954
47152
  ...resolved.caption !== void 0 && { caption: resolved.caption },
46955
47153
  regions,
46956
47154
  rivers,
47155
+ relief,
47156
+ reliefHatch,
46957
47157
  legs,
46958
47158
  pois,
46959
47159
  labels,
46960
47160
  legend,
46961
47161
  insets,
46962
- insetRegions
47162
+ insetRegions,
47163
+ projection,
47164
+ stretch: stretchParams
46963
47165
  };
46964
47166
  }
46965
- var import_d3_geo2, import_topojson_client2, FIT_PAD, RAMP_FLOOR, R_DEFAULT, R_MIN, R_MAX, W_MIN, W_MAX, FONT, COLO_EPS, LAND_TINT_LIGHT, LAND_TINT_DARK, TAG_TINT_LIGHT, TAG_TINT_DARK, WATER_TINT, RIVER_WIDTH, FOREIGN_TINT_LIGHT, FOREIGN_TINT_DARK, COLO_R, GOLDEN_ANGLE, FAN_STEP, ARC_CURVE_FRAC, usConusProjection, alaskaProjection, hawaiiProjection, INSET_STATES, US_NON_CONUS;
47167
+ var import_d3_geo2, import_topojson_client2, FIT_PAD, RAMP_FLOOR, R_DEFAULT, R_MIN, R_MAX, W_MIN, W_MAX, FONT, COLO_EPS, LAND_TINT_LIGHT, LAND_TINT_DARK, TAG_TINT_LIGHT, TAG_TINT_DARK, WATER_TINT_LIGHT, WATER_TINT_DARK, RIVER_WIDTH, RELIEF_MIN_AREA, RELIEF_MIN_DIM, RELIEF_HATCH_SPACING, RELIEF_HATCH_WIDTH, RELIEF_HATCH_STRENGTH, FOREIGN_TINT_LIGHT, FOREIGN_TINT_DARK, MUTED_FOREIGN_LIGHT, MUTED_FOREIGN_DARK, COLO_R, GOLDEN_ANGLE, FAN_STEP, ARC_CURVE_FRAC, usConusProjection, alaskaProjection, hawaiiProjection, INSET_STATES, US_NON_CONUS;
46966
47168
  var init_layout15 = __esm({
46967
47169
  "src/map/layout.ts"() {
46968
47170
  "use strict";
46969
47171
  import_d3_geo2 = require("d3-geo");
46970
47172
  import_topojson_client2 = require("topojson-client");
46971
47173
  init_color_utils();
47174
+ init_colors();
46972
47175
  init_label_layout();
46973
47176
  init_legend_constants();
46974
47177
  init_title_constants();
@@ -46981,14 +47184,22 @@ var init_layout15 = __esm({
46981
47184
  W_MAX = 8;
46982
47185
  FONT = 11;
46983
47186
  COLO_EPS = 1.5;
46984
- LAND_TINT_LIGHT = 58;
46985
- LAND_TINT_DARK = 75;
47187
+ LAND_TINT_LIGHT = 12;
47188
+ LAND_TINT_DARK = 24;
46986
47189
  TAG_TINT_LIGHT = 60;
46987
47190
  TAG_TINT_DARK = 68;
46988
- WATER_TINT = 55;
47191
+ WATER_TINT_LIGHT = 13;
47192
+ WATER_TINT_DARK = 14;
46989
47193
  RIVER_WIDTH = 1.3;
47194
+ RELIEF_MIN_AREA = 12;
47195
+ RELIEF_MIN_DIM = 2;
47196
+ RELIEF_HATCH_SPACING = 3;
47197
+ RELIEF_HATCH_WIDTH = 0.25;
47198
+ RELIEF_HATCH_STRENGTH = 32;
46990
47199
  FOREIGN_TINT_LIGHT = 30;
46991
47200
  FOREIGN_TINT_DARK = 62;
47201
+ MUTED_FOREIGN_LIGHT = 28;
47202
+ MUTED_FOREIGN_DARK = 16;
46992
47203
  COLO_R = 9;
46993
47204
  GOLDEN_ANGLE = 2.399963229728653;
46994
47205
  FAN_STEP = 16;
@@ -47042,7 +47253,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
47042
47253
  const p = g.append("path").attr("d", r.d).attr("fill", r.fill).attr("stroke", r.stroke).attr("stroke-width", strokeWidth);
47043
47254
  if (r.layer !== "base") {
47044
47255
  p.classed("dgmo-map-region", true).attr("data-region", r.id);
47045
- if (r.score !== void 0) p.attr("data-score", r.score);
47256
+ if (r.value !== void 0) p.attr("data-value", r.value);
47046
47257
  if (r.tags) {
47047
47258
  for (const [group, value] of Object.entries(r.tags)) {
47048
47259
  p.attr(`data-tag-${group.toLowerCase()}`, value.toLowerCase());
@@ -47060,6 +47271,20 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
47060
47271
  }
47061
47272
  };
47062
47273
  for (const r of layout.regions) drawRegion(gRegions, r, 0.5);
47274
+ if (layout.relief.length && layout.reliefHatch) {
47275
+ const h = layout.reliefHatch;
47276
+ const rangeClipId = "dgmo-relief-clip";
47277
+ const landClipId = "dgmo-relief-land";
47278
+ const rangeClip = defs.append("clipPath").attr("id", rangeClipId);
47279
+ for (const s of layout.relief) rangeClip.append("path").attr("d", s.d);
47280
+ const landClip = defs.append("clipPath").attr("id", landClipId);
47281
+ for (const r of layout.regions)
47282
+ if (r.id !== "lake") landClip.append("path").attr("d", r.d);
47283
+ const gRelief = svg.append("g").attr("clip-path", `url(#${landClipId})`).append("g").attr("class", "dgmo-map-relief").attr("clip-path", `url(#${rangeClipId})`).attr("stroke", h.color).attr("stroke-width", h.width).attr("vector-effect", "non-scaling-stroke");
47284
+ for (let y = h.spacing; y < height; y += h.spacing) {
47285
+ gRelief.append("line").attr("x1", 0).attr("y1", y).attr("x2", width).attr("y2", y);
47286
+ }
47287
+ }
47063
47288
  if (layout.rivers.length) {
47064
47289
  const gRivers = svg.append("g").attr("class", "dgmo-map-rivers").attr("fill", "none");
47065
47290
  for (const r of layout.rivers) {
@@ -47103,6 +47328,11 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
47103
47328
  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);
47104
47329
  }
47105
47330
  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);
47331
+ if (poi.tags) {
47332
+ for (const [group, value] of Object.entries(poi.tags)) {
47333
+ c.attr(`data-tag-${group.toLowerCase()}`, value.toLowerCase());
47334
+ }
47335
+ }
47106
47336
  if (onClickItem) {
47107
47337
  c.style("cursor", "pointer").on(
47108
47338
  "click",
@@ -47152,7 +47382,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
47152
47382
  const legendG = svg.append("g").attr("class", "dgmo-map-legend").attr("transform", `translate(0, ${legendY})`);
47153
47383
  const ramp = layout.legend.ramp;
47154
47384
  const scoreGroup = ramp ? {
47155
- name: ramp.metric?.trim() || "Score",
47385
+ name: ramp.metric?.trim() || "Value",
47156
47386
  entries: [],
47157
47387
  gradient: {
47158
47388
  min: ramp.min,
@@ -47179,7 +47409,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
47179
47409
  }
47180
47410
  }
47181
47411
  if (layout.title) {
47182
- svg.append("text").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);
47412
+ 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);
47183
47413
  }
47184
47414
  if (layout.subtitle) {
47185
47415
  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);
@@ -47212,6 +47442,121 @@ var init_renderer16 = __esm({
47212
47442
  }
47213
47443
  });
47214
47444
 
47445
+ // src/map/load-data.ts
47446
+ var load_data_exports = {};
47447
+ __export(load_data_exports, {
47448
+ loadMapData: () => loadMapData
47449
+ });
47450
+ async function loadNodeBuiltins() {
47451
+ const [{ readFile }, { fileURLToPath }, { dirname, resolve }] = await Promise.all([
47452
+ import("fs/promises"),
47453
+ import("url"),
47454
+ import("path")
47455
+ ]);
47456
+ return { readFile, fileURLToPath, dirname, resolve };
47457
+ }
47458
+ async function readJson(nb, dir, name) {
47459
+ return JSON.parse(await nb.readFile(nb.resolve(dir, name), "utf8"));
47460
+ }
47461
+ async function firstExistingDir(nb, baseDir) {
47462
+ for (const rel of CANDIDATE_DIRS) {
47463
+ const dir = nb.resolve(baseDir, rel);
47464
+ try {
47465
+ await nb.readFile(nb.resolve(dir, FILES.gazetteer), "utf8");
47466
+ return dir;
47467
+ } catch {
47468
+ }
47469
+ }
47470
+ throw new Error(
47471
+ `map data assets not found near ${baseDir} (looked in ${CANDIDATE_DIRS.join(", ")}). Run \`pnpm build:map-data\` and \`pnpm build\`.`
47472
+ );
47473
+ }
47474
+ function validate(data) {
47475
+ const topoOk = (t) => !!t && t.type === "Topology" && !!t.objects;
47476
+ if (!topoOk(data.worldCoarse) || !topoOk(data.worldDetail) || !topoOk(data.usStates) || !data.gazetteer || !Array.isArray(data.gazetteer.cities) || !data.gazetteer.byName) {
47477
+ throw new Error("map data assets are malformed (failed shape validation)");
47478
+ }
47479
+ return data;
47480
+ }
47481
+ function moduleBaseDir(nb) {
47482
+ try {
47483
+ const url = import_meta.url;
47484
+ if (url) return nb.dirname(nb.fileURLToPath(url));
47485
+ } catch {
47486
+ }
47487
+ if (typeof __dirname !== "undefined") return __dirname;
47488
+ return process.cwd();
47489
+ }
47490
+ function loadMapData() {
47491
+ cache ??= (async () => {
47492
+ const nb = await loadNodeBuiltins();
47493
+ const dir = await firstExistingDir(nb, moduleBaseDir(nb));
47494
+ const [
47495
+ worldCoarse,
47496
+ worldDetail,
47497
+ usStates,
47498
+ lakes,
47499
+ rivers,
47500
+ mountainRanges,
47501
+ naLand,
47502
+ naLakes,
47503
+ gazetteer
47504
+ ] = await Promise.all([
47505
+ readJson(nb, dir, FILES.worldCoarse),
47506
+ readJson(nb, dir, FILES.worldDetail),
47507
+ readJson(nb, dir, FILES.usStates),
47508
+ // Lakes/rivers/mountain/NA assets are optional — older bundles may predate them.
47509
+ readJson(nb, dir, FILES.lakes).catch(() => void 0),
47510
+ readJson(nb, dir, FILES.rivers).catch(() => void 0),
47511
+ readJson(nb, dir, FILES.mountainRanges).catch(
47512
+ () => void 0
47513
+ ),
47514
+ readJson(nb, dir, FILES.naLand).catch(() => void 0),
47515
+ readJson(nb, dir, FILES.naLakes).catch(() => void 0),
47516
+ readJson(nb, dir, FILES.gazetteer)
47517
+ ]);
47518
+ return validate({
47519
+ worldCoarse,
47520
+ worldDetail,
47521
+ usStates,
47522
+ gazetteer,
47523
+ ...lakes && { lakes },
47524
+ ...rivers && { rivers },
47525
+ ...mountainRanges && { mountainRanges },
47526
+ ...naLand && { naLand },
47527
+ ...naLakes && { naLakes }
47528
+ });
47529
+ })().catch((e) => {
47530
+ cache = void 0;
47531
+ throw e;
47532
+ });
47533
+ return cache;
47534
+ }
47535
+ var import_meta, FILES, CANDIDATE_DIRS, cache;
47536
+ var init_load_data = __esm({
47537
+ "src/map/load-data.ts"() {
47538
+ "use strict";
47539
+ import_meta = {};
47540
+ FILES = {
47541
+ worldCoarse: "world-coarse.json",
47542
+ worldDetail: "world-detail.json",
47543
+ usStates: "us-states.json",
47544
+ lakes: "lakes.json",
47545
+ rivers: "rivers.json",
47546
+ mountainRanges: "mountain-ranges.json",
47547
+ naLand: "na-land.json",
47548
+ naLakes: "na-lakes.json",
47549
+ gazetteer: "gazetteer.json"
47550
+ };
47551
+ CANDIDATE_DIRS = [
47552
+ "./data",
47553
+ "./map-data",
47554
+ "../map-data",
47555
+ "../src/map/data"
47556
+ ];
47557
+ }
47558
+ });
47559
+
47215
47560
  // src/pyramid/renderer.ts
47216
47561
  var renderer_exports17 = {};
47217
47562
  __export(renderer_exports17, {
@@ -55335,15 +55680,17 @@ async function renderForExport(content, theme, palette, viewState, options) {
55335
55680
  if (detectedType === "map") {
55336
55681
  const { parseMap: parseMap2 } = await Promise.resolve().then(() => (init_parser12(), parser_exports11));
55337
55682
  const { resolveMap: resolveMap2 } = await Promise.resolve().then(() => (init_resolver2(), resolver_exports));
55338
- const { loadMapData: loadMapData2 } = await Promise.resolve().then(() => (init_load_data(), load_data_exports));
55339
55683
  const { renderMapForExport: renderMapForExport2 } = await Promise.resolve().then(() => (init_renderer16(), renderer_exports16));
55340
55684
  const effectivePalette2 = await resolveExportPalette(theme, palette);
55341
55685
  const mapParsed = parseMap2(content);
55342
- let mapData;
55343
- try {
55344
- mapData = await loadMapData2();
55345
- } catch {
55346
- return "";
55686
+ let mapData = options?.mapData;
55687
+ if (!mapData) {
55688
+ const { loadMapData: loadMapData2 } = await Promise.resolve().then(() => (init_load_data(), load_data_exports));
55689
+ try {
55690
+ mapData = await loadMapData2();
55691
+ } catch {
55692
+ return "";
55693
+ }
55347
55694
  }
55348
55695
  const mapResolved = resolveMap2(mapParsed, mapData);
55349
55696
  const container2 = createExportContainer(EXPORT_WIDTH, EXPORT_HEIGHT);
@@ -56396,13 +56743,17 @@ var DIRECTIVE_KEYWORDS = /* @__PURE__ */ new Set([
56396
56743
  // Map (§24B) directives
56397
56744
  "region",
56398
56745
  "projection",
56399
- "metric",
56400
- "size-metric",
56746
+ "region-metric",
56747
+ "poi-metric",
56748
+ "flow-metric",
56401
56749
  "region-labels",
56402
56750
  "poi-labels",
56403
56751
  "default-country",
56404
56752
  "default-state",
56405
56753
  "no-legend",
56754
+ "no-insets",
56755
+ "muted",
56756
+ "natural",
56406
56757
  "subtitle",
56407
56758
  "caption",
56408
56759
  "poi",
@@ -57070,7 +57421,7 @@ pre.dgmo, code.language-dgmo, pre > code.language-dgmo,
57070
57421
 
57071
57422
  // src/auto/index.ts
57072
57423
  init_safe_href();
57073
- var VERSION = "0.20.3";
57424
+ var VERSION = "0.21.1";
57074
57425
  var DEFAULTS = {
57075
57426
  theme: "auto",
57076
57427
  palette: "nord",