@diagrammo/dgmo 0.20.3 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/advanced.cjs CHANGED
@@ -857,13 +857,9 @@ var init_reserved_key_registry = __esm({
857
857
  "icon"
858
858
  ]);
859
859
  MAP_REGISTRY = staticRegistry([
860
- "score",
860
+ "value",
861
861
  "label",
862
- "size",
863
- "description",
864
- "weight",
865
- "style",
866
- "date"
862
+ "style"
867
863
  ]);
868
864
  ORG_REGISTRY = staticRegistry([
869
865
  "color",
@@ -15828,7 +15824,8 @@ function parseMap(content) {
15828
15824
  continue;
15829
15825
  }
15830
15826
  if (open.route && indent > open.route.indent) {
15831
- open.route.route.stops.push(parseStop(trimmed, lineNumber));
15827
+ const leg = parseLeg(trimmed, lineNumber, open.route.route.style);
15828
+ open.route.route.legs.push(leg);
15832
15829
  continue;
15833
15830
  }
15834
15831
  if (open.poi && indent > open.poi.indent) {
@@ -15859,6 +15856,10 @@ function parseMap(content) {
15859
15856
  handleTag(trimmed, lineNumber);
15860
15857
  continue;
15861
15858
  }
15859
+ if ((firstWord === "muted" || firstWord === "natural") && trimmed === firstWord) {
15860
+ handleDirective(firstWord, "", lineNumber);
15861
+ continue;
15862
+ }
15862
15863
  if (DIRECTIVE_SET.has(firstWord) && !trimmed.slice(firstWord.length).trimStart().startsWith(":")) {
15863
15864
  handleDirective(
15864
15865
  firstWord,
@@ -15923,13 +15924,17 @@ function parseMap(content) {
15923
15924
  );
15924
15925
  d.projection = value;
15925
15926
  break;
15926
- case "metric":
15927
- dup(d.metric);
15928
- d.metric = value;
15927
+ case "region-metric":
15928
+ dup(d.regionMetric);
15929
+ d.regionMetric = value;
15930
+ break;
15931
+ case "poi-metric":
15932
+ dup(d.poiMetric);
15933
+ d.poiMetric = value;
15929
15934
  break;
15930
- case "size-metric":
15931
- dup(d.sizeMetric);
15932
- d.sizeMetric = value;
15935
+ case "flow-metric":
15936
+ dup(d.flowMetric);
15937
+ d.flowMetric = value;
15933
15938
  break;
15934
15939
  case "scale":
15935
15940
  dup(d.scale);
@@ -15971,6 +15976,15 @@ function parseMap(content) {
15971
15976
  case "no-legend":
15972
15977
  d.noLegend = true;
15973
15978
  break;
15979
+ case "muted":
15980
+ case "natural":
15981
+ if (d.basemapStyle !== void 0 && d.basemapStyle !== key)
15982
+ pushWarning(
15983
+ line12,
15984
+ `Conflicting basemap dress \u2014 "${d.basemapStyle}" then "${key}"; last wins.`
15985
+ );
15986
+ d.basemapStyle = key;
15987
+ break;
15974
15988
  case "subtitle":
15975
15989
  dup(d.subtitle);
15976
15990
  d.subtitle = value;
@@ -16048,14 +16062,14 @@ function parseMap(content) {
16048
16062
  line12
16049
16063
  );
16050
16064
  const { tags, meta } = partitionMeta(split.meta, tagGroupNames());
16051
- let scoreNum;
16052
- const score = meta["score"];
16053
- if (score !== void 0) {
16054
- delete meta["score"];
16055
- scoreNum = Number(score);
16056
- if (!Number.isFinite(scoreNum)) {
16057
- pushError(line12, `score must be a number (got "${score}").`);
16058
- scoreNum = void 0;
16065
+ let valueNum;
16066
+ const value = meta["value"];
16067
+ if (value !== void 0) {
16068
+ delete meta["value"];
16069
+ valueNum = Number(value);
16070
+ if (!Number.isFinite(valueNum)) {
16071
+ pushError(line12, `value must be a number (got "${value}").`);
16072
+ valueNum = void 0;
16059
16073
  }
16060
16074
  }
16061
16075
  let regionName = split.name;
@@ -16073,7 +16087,7 @@ function parseMap(content) {
16073
16087
  lineNumber: line12
16074
16088
  };
16075
16089
  if (regionScope !== void 0) region.scope = regionScope;
16076
- if (scoreNum !== void 0) region.score = scoreNum;
16090
+ if (valueNum !== void 0) region.value = valueNum;
16077
16091
  regions.push(region);
16078
16092
  }
16079
16093
  function handlePoi(rest, line12, indent) {
@@ -16102,24 +16116,76 @@ function parseMap(content) {
16102
16116
  open.poi = { poi, indent };
16103
16117
  }
16104
16118
  function handleRoute(rest, line12, indent) {
16105
- const meta = rest ? splitNameAndMeta(rest, registry(), aliasMap).meta : {};
16106
- const route = { stops: [], meta, lineNumber: line12 };
16119
+ const split = rest ? splitNameAndMeta(
16120
+ rest,
16121
+ registry(),
16122
+ aliasMap,
16123
+ void 0,
16124
+ diagnostics,
16125
+ line12
16126
+ ) : { name: "", meta: {}, alias: void 0 };
16127
+ const pos = parsePos(split.name, line12);
16128
+ if (!pos || pos.kind === "name" && !pos.name) {
16129
+ pushError(
16130
+ line12,
16131
+ "route requires an origin: `route <origin> [style: arc]`."
16132
+ );
16133
+ return;
16134
+ }
16135
+ const { tags, meta } = partitionMeta(split.meta, tagGroupNames());
16136
+ const originLabel = meta["label"];
16137
+ const originValue = meta["value"];
16138
+ const style = meta["style"] === "arc" ? "arc" : "straight";
16139
+ const route = {
16140
+ origin: pos,
16141
+ ...split.alias !== void 0 && { originAlias: split.alias },
16142
+ ...originLabel !== void 0 && { originLabel },
16143
+ ...originValue !== void 0 && { originValue },
16144
+ originTags: tags,
16145
+ style,
16146
+ legs: [],
16147
+ lineNumber: line12
16148
+ };
16107
16149
  routes.push(route);
16108
16150
  open.route = { route, indent };
16109
16151
  }
16110
- function parseStop(trimmed, line12) {
16111
- const split = splitNameAndMeta(trimmed, registry(), aliasMap);
16112
- const ref = parsePos(split.name, line12) ?? {
16152
+ function parseLeg(trimmed, line12, headerStyle) {
16153
+ let arrowStyle = "straight";
16154
+ let label;
16155
+ let rest = trimmed;
16156
+ const m = trimmed.match(LEG_ARROW_RE);
16157
+ if (m) {
16158
+ const arr = classifyArrow(m[1], line12);
16159
+ arrowStyle = arr.style;
16160
+ label = arr.label;
16161
+ rest = m[2];
16162
+ }
16163
+ const split = splitNameAndMeta(
16164
+ rest,
16165
+ registry(),
16166
+ aliasMap,
16167
+ void 0,
16168
+ diagnostics,
16169
+ line12
16170
+ );
16171
+ const pos = parsePos(split.name, line12) ?? {
16113
16172
  kind: "name",
16114
16173
  name: split.name
16115
16174
  };
16116
- const stop = {
16117
- ref,
16118
- meta: split.meta,
16175
+ const { tags, meta } = partitionMeta(split.meta, tagGroupNames());
16176
+ const value = meta["value"];
16177
+ const destLabel = meta["label"];
16178
+ const style = arrowStyle === "arc" || headerStyle === "arc" ? "arc" : "straight";
16179
+ return {
16180
+ ...label !== void 0 && { label },
16181
+ style,
16182
+ ...value !== void 0 && { value },
16183
+ dest: pos,
16184
+ ...split.alias !== void 0 && { destAlias: split.alias },
16185
+ ...destLabel !== void 0 && { destLabel },
16186
+ destTags: tags,
16119
16187
  lineNumber: line12
16120
16188
  };
16121
- if (split.alias) stop.alias = split.alias;
16122
- return stop;
16123
16189
  }
16124
16190
  function handleEdges(trimmed, line12) {
16125
16191
  const parts = trimmed.split(ARROW_SPLIT);
@@ -16221,7 +16287,7 @@ function partitionMeta(meta, tagGroupNames) {
16221
16287
  function poiName(pos) {
16222
16288
  return pos.kind === "name" ? pos.name : void 0;
16223
16289
  }
16224
- var COORD_RE, NUMERIC_LEAD_RE, SCOPE_RE, ARROW_SPLIT, HUB_RE, AT_RE, DIRECTIVE_SET;
16290
+ var COORD_RE, NUMERIC_LEAD_RE, SCOPE_RE, ARROW_SPLIT, HUB_RE, LEG_ARROW_RE, AT_RE, DIRECTIVE_SET;
16225
16291
  var init_parser12 = __esm({
16226
16292
  "src/map/parser.ts"() {
16227
16293
  "use strict";
@@ -16235,12 +16301,14 @@ var init_parser12 = __esm({
16235
16301
  SCOPE_RE = /^[A-Z]{2}(?:-[A-Z0-9]{1,3})?$/;
16236
16302
  ARROW_SPLIT = /\s+(-[^>]*?->|->|~[^>]*?~>|~>|--)\s+/;
16237
16303
  HUB_RE = /^(->|~>)\s+(.+)$/;
16304
+ LEG_ARROW_RE = /^(-[^>]*?->|->|~[^>]*?~>|~>|--)\s+(.+)$/;
16238
16305
  AT_RE = /(^|[\s,])at\s*:/i;
16239
16306
  DIRECTIVE_SET = /* @__PURE__ */ new Set([
16240
16307
  "region",
16241
16308
  "projection",
16242
- "metric",
16243
- "size-metric",
16309
+ "region-metric",
16310
+ "poi-metric",
16311
+ "flow-metric",
16244
16312
  "scale",
16245
16313
  "region-labels",
16246
16314
  "poi-labels",
@@ -45838,6 +45906,11 @@ var resolver_exports = {};
45838
45906
  __export(resolver_exports, {
45839
45907
  resolveMap: () => resolveMap
45840
45908
  });
45909
+ function usStateFromBareScope(scope) {
45910
+ if (!scope) return null;
45911
+ const up = scope.toUpperCase();
45912
+ return US_STATE_POSTAL.has(up) ? `US-${up}` : null;
45913
+ }
45841
45914
  function looksUS(lat, lon) {
45842
45915
  if (lat < 15 || lat > 72) return false;
45843
45916
  return lon >= -180 && lon <= -64 || lon >= 172;
@@ -45887,9 +45960,9 @@ function resolveMap(parsed, data) {
45887
45960
  const f = fold(r.name);
45888
45961
  return usStateIndex.has(f) && !countryIndex.has(f);
45889
45962
  }) || parsed.regions.some(
45890
- (r) => r.scope === "US" || r.scope?.startsWith("US-")
45963
+ (r) => r.scope === "US" || r.scope?.startsWith("US-") || usStateFromBareScope(r.scope) !== null
45891
45964
  ) || parsed.pois.some(
45892
- (p) => p.pos.kind === "name" && p.pos.scope?.startsWith("US-")
45965
+ (p) => p.pos.kind === "name" && (p.pos.scope?.startsWith("US-") || usStateFromBareScope(p.pos.scope) !== null)
45893
45966
  );
45894
45967
  const regions = [];
45895
45968
  const seenRegion = /* @__PURE__ */ new Map();
@@ -45956,7 +46029,7 @@ function resolveMap(parsed, data) {
45956
46029
  iso: chosen.id,
45957
46030
  name: chosen.name,
45958
46031
  layer: chosen.layer,
45959
- ...r.score !== void 0 && { score: r.score },
46032
+ ...r.value !== void 0 && { value: r.value },
45960
46033
  tags: r.tags,
45961
46034
  meta: r.meta,
45962
46035
  lineNumber: r.lineNumber
@@ -46014,9 +46087,10 @@ function resolveMap(parsed, data) {
46014
46087
  let cands = idxs.map((i) => data.gazetteer.cities[i]);
46015
46088
  const scopeUse = scope ?? scopeHint;
46016
46089
  if (scopeUse) {
46017
- const isSub = /^[A-Za-z]{2}-/.test(scopeUse);
46090
+ const bareState = usStateFromBareScope(scopeUse);
46091
+ const subScope = /^[A-Za-z]{2}-/.test(scopeUse) ? scopeUse : bareState;
46018
46092
  const filtered = cands.filter(
46019
- (c2) => isSub ? c2[5] === scopeUse : c2[2] === scopeUse
46093
+ (c2) => subScope ? c2[5] === subScope : c2[2] === scopeUse
46020
46094
  );
46021
46095
  if (filtered.length) cands = filtered;
46022
46096
  else if (scope) {
@@ -46145,33 +46219,89 @@ function resolveMap(parsed, data) {
46145
46219
  lineNumber: e.lineNumber
46146
46220
  });
46147
46221
  }
46148
- const routes = [];
46149
- for (const rt of parsed.routes) {
46150
- const stopIds = [];
46151
- for (const stop of rt.stops) {
46152
- let id;
46153
- if (stop.ref.kind === "coords") {
46154
- id = stop.alias ? fold(stop.alias) : `@${stop.ref.lat},${stop.ref.lon}`;
46155
- if (!looksUS(stop.ref.lat, stop.ref.lon)) anyNonUsPoi = true;
46156
- if (!registry.has(id)) {
46157
- const poi = {
46222
+ const resolveStop = (pos, alias, label, tags, sizeValue, line12) => {
46223
+ const meta = sizeValue !== void 0 ? { value: sizeValue } : {};
46224
+ if (pos.kind === "coords") {
46225
+ const id = alias ? fold(alias) : `@${pos.lat},${pos.lon}`;
46226
+ if (!looksUS(pos.lat, pos.lon)) anyNonUsPoi = true;
46227
+ if (!registry.has(id)) {
46228
+ registerPoi(
46229
+ id,
46230
+ {
46158
46231
  id,
46159
- ...stop.alias !== void 0 && { name: stop.alias },
46160
- lat: stop.ref.lat,
46161
- lon: stop.ref.lon,
46162
- tags: {},
46163
- meta: stop.meta,
46164
- lineNumber: stop.lineNumber,
46165
- implicit: true
46166
- };
46167
- registerPoi(id, poi, stop.lineNumber);
46168
- }
46169
- } else {
46170
- id = stop.alias && registry.has(fold(stop.alias)) ? fold(stop.alias) : resolveEndpoint2(stop.ref.name, stop.lineNumber);
46232
+ ...alias !== void 0 && { name: alias },
46233
+ lat: pos.lat,
46234
+ lon: pos.lon,
46235
+ ...label !== void 0 && { label },
46236
+ tags,
46237
+ meta,
46238
+ lineNumber: line12
46239
+ },
46240
+ line12
46241
+ );
46171
46242
  }
46172
- if (id) stopIds.push(id);
46243
+ return id;
46244
+ }
46245
+ const f = fold(pos.name);
46246
+ if (registry.has(f)) return f;
46247
+ const aliased = declaredByName.get(f);
46248
+ if (aliased) return aliased;
46249
+ const got = lookupName(pos.name, pos.scope, line12, inferredCountry, true);
46250
+ if (got.kind !== "ok") return null;
46251
+ noteCountry(got.iso);
46252
+ registerPoi(
46253
+ f,
46254
+ {
46255
+ id: f,
46256
+ name: pos.name,
46257
+ lat: got.lat,
46258
+ lon: got.lon,
46259
+ ...label !== void 0 && { label },
46260
+ tags,
46261
+ meta,
46262
+ lineNumber: line12
46263
+ },
46264
+ line12
46265
+ );
46266
+ return f;
46267
+ };
46268
+ const routes = [];
46269
+ for (const rt of parsed.routes) {
46270
+ const originId = resolveStop(
46271
+ rt.origin,
46272
+ rt.originAlias,
46273
+ rt.originLabel,
46274
+ rt.originTags,
46275
+ rt.originValue,
46276
+ rt.lineNumber
46277
+ );
46278
+ if (!originId) continue;
46279
+ const stopIds = [originId];
46280
+ const legs = [];
46281
+ let prevId = originId;
46282
+ for (const leg of rt.legs) {
46283
+ const destId = resolveStop(
46284
+ leg.dest,
46285
+ leg.destAlias,
46286
+ leg.destLabel,
46287
+ leg.destTags,
46288
+ void 0,
46289
+ // a leg's `value:` is leg thickness, not the dest's size
46290
+ leg.lineNumber
46291
+ );
46292
+ if (!destId) continue;
46293
+ legs.push({
46294
+ fromId: prevId,
46295
+ toId: destId,
46296
+ ...leg.label !== void 0 && { label: leg.label },
46297
+ style: leg.style,
46298
+ ...leg.value !== void 0 && { value: leg.value },
46299
+ lineNumber: leg.lineNumber
46300
+ });
46301
+ if (!stopIds.includes(destId)) stopIds.push(destId);
46302
+ prevId = destId;
46173
46303
  }
46174
- routes.push({ stopIds, meta: rt.meta, lineNumber: rt.lineNumber });
46304
+ routes.push({ stopIds, legs, lineNumber: rt.lineNumber });
46175
46305
  }
46176
46306
  const subdivisions = [];
46177
46307
  if (usSubdivisionReferenced || parsed.directives.region === "us-states")
@@ -46263,7 +46393,7 @@ function firstError(diags) {
46263
46393
  const e = diags.find((d) => d.severity === "error");
46264
46394
  return e ? formatDgmoError(e) : null;
46265
46395
  }
46266
- var WORLD_SPAN, MERCATOR_MAX_SPAN, PAD_FRACTION, WORLD_LAT_SOUTH, WORLD_LAT_NORTH, REGION_ALIASES;
46396
+ var WORLD_SPAN, MERCATOR_MAX_SPAN, PAD_FRACTION, WORLD_LAT_SOUTH, WORLD_LAT_NORTH, REGION_ALIASES, US_STATE_POSTAL;
46267
46397
  var init_resolver2 = __esm({
46268
46398
  "src/map/resolver.ts"() {
46269
46399
  "use strict";
@@ -46295,6 +46425,59 @@ var init_resolver2 = __esm({
46295
46425
  "north macedonia": "macedonia",
46296
46426
  "czech republic": "czechia"
46297
46427
  };
46428
+ US_STATE_POSTAL = /* @__PURE__ */ new Set([
46429
+ "AL",
46430
+ "AK",
46431
+ "AZ",
46432
+ "AR",
46433
+ "CA",
46434
+ "CO",
46435
+ "CT",
46436
+ "DE",
46437
+ "FL",
46438
+ "GA",
46439
+ "HI",
46440
+ "ID",
46441
+ "IL",
46442
+ "IN",
46443
+ "IA",
46444
+ "KS",
46445
+ "KY",
46446
+ "LA",
46447
+ "ME",
46448
+ "MD",
46449
+ "MA",
46450
+ "MI",
46451
+ "MN",
46452
+ "MS",
46453
+ "MO",
46454
+ "MT",
46455
+ "NE",
46456
+ "NV",
46457
+ "NH",
46458
+ "NJ",
46459
+ "NM",
46460
+ "NY",
46461
+ "NC",
46462
+ "ND",
46463
+ "OH",
46464
+ "OK",
46465
+ "OR",
46466
+ "PA",
46467
+ "RI",
46468
+ "SC",
46469
+ "SD",
46470
+ "TN",
46471
+ "TX",
46472
+ "UT",
46473
+ "VT",
46474
+ "VA",
46475
+ "WA",
46476
+ "WV",
46477
+ "WI",
46478
+ "WY",
46479
+ "DC"
46480
+ ]);
46298
46481
  }
46299
46482
  });
46300
46483
 
@@ -46433,10 +46616,18 @@ function projectionFor(family) {
46433
46616
  return (0, import_d3_geo2.geoEquirectangular)();
46434
46617
  }
46435
46618
  }
46436
- function mapBackgroundColor(palette) {
46619
+ function mapBackgroundColor(palette, isDark = false, dataActive = false) {
46620
+ if (dataActive)
46621
+ return mix(
46622
+ palette.colors.gray,
46623
+ palette.bg,
46624
+ isDark ? MUTED_WATER_DARK : MUTED_WATER_LIGHT
46625
+ );
46437
46626
  return mix(palette.colors.blue, palette.bg, WATER_TINT);
46438
46627
  }
46439
- function mapNeutralLandColor(palette, isDark) {
46628
+ function mapNeutralLandColor(palette, isDark, dataActive = false) {
46629
+ if (dataActive)
46630
+ return isDark ? mix(palette.colors.gray, palette.bg, MUTED_LAND_DARK) : palette.bg;
46440
46631
  return mix(
46441
46632
  palette.colors.green,
46442
46633
  palette.bg,
@@ -46462,28 +46653,19 @@ function layoutMap(resolved, data, size, opts) {
46462
46653
  }
46463
46654
  }
46464
46655
  const usLayer = wantsUsStates ? decodeLayer(data.usStates) : null;
46465
- const landTint = isDark ? LAND_TINT_DARK : LAND_TINT_LIGHT;
46466
- const neutralFill = mix(palette.colors.green, palette.bg, landTint);
46467
- const water = mapBackgroundColor(palette);
46468
46656
  const usContext = usLayer !== null;
46469
- const foreignFill = mix(
46470
- palette.colors.gray,
46471
- palette.bg,
46472
- isDark ? FOREIGN_TINT_DARK : FOREIGN_TINT_LIGHT
46473
- );
46474
46657
  const regionStroke = isDark ? mix(palette.bg, palette.text, 78) : mix(palette.text, palette.bg, 78);
46475
- const scores = resolved.regions.filter((r) => r.score !== void 0).map((r) => r.score);
46658
+ const values = resolved.regions.filter((r) => r.value !== void 0).map((r) => r.value);
46476
46659
  const scaleOverride = resolved.directives.scale;
46477
- const rampMin = scaleOverride ? scaleOverride.min : Math.min(...scores);
46478
- const rampMax = scaleOverride ? scaleOverride.max : Math.max(...scores);
46660
+ const rampMin = scaleOverride ? scaleOverride.min : Math.min(...values);
46661
+ const rampMax = scaleOverride ? scaleOverride.max : Math.max(...values);
46479
46662
  const rampHue = palette.colors.red;
46480
- const hasRamp = scores.length > 0;
46481
- const SCORE_NAME = hasRamp ? resolved.directives.metric?.trim() || "Score" : null;
46663
+ const hasRamp = values.length > 0;
46664
+ const VALUE_NAME = hasRamp ? resolved.directives.regionMetric?.trim() || "Value" : null;
46482
46665
  const matchColorGroup = (v) => {
46483
46666
  const lv = v.trim().toLowerCase();
46484
46667
  if (lv === "none") return null;
46485
- if (SCORE_NAME && (lv === "score" || lv === SCORE_NAME.toLowerCase()))
46486
- return SCORE_NAME;
46668
+ if (lv === VALUE_NAME?.toLowerCase()) return VALUE_NAME;
46487
46669
  const tg = resolved.tagGroups.find((g) => g.name.toLowerCase() === lv);
46488
46670
  return tg ? tg.name : v;
46489
46671
  };
@@ -46494,11 +46676,19 @@ function layoutMap(resolved, data, size, opts) {
46494
46676
  } else if (resolved.directives.activeTag !== void 0) {
46495
46677
  activeGroup = matchColorGroup(resolved.directives.activeTag);
46496
46678
  } else {
46497
- activeGroup = SCORE_NAME ?? (resolved.tagGroups.length > 0 ? resolved.tagGroups[0].name : null);
46679
+ activeGroup = VALUE_NAME ?? (resolved.tagGroups.length > 0 ? resolved.tagGroups[0].name : null);
46498
46680
  }
46499
- const activeIsScore = SCORE_NAME !== null && activeGroup === SCORE_NAME;
46681
+ const activeIsScore = VALUE_NAME !== null && activeGroup === VALUE_NAME;
46682
+ const mutedBasemap = resolved.directives.basemapStyle === "muted" ? true : resolved.directives.basemapStyle === "natural" ? false : activeGroup !== null;
46683
+ const neutralFill = mapNeutralLandColor(palette, isDark, mutedBasemap);
46684
+ const water = mapBackgroundColor(palette, isDark, mutedBasemap);
46685
+ const foreignFill = mix(
46686
+ palette.colors.gray,
46687
+ palette.bg,
46688
+ mutedBasemap ? isDark ? MUTED_FOREIGN_DARK : MUTED_FOREIGN_LIGHT : isDark ? FOREIGN_TINT_DARK : FOREIGN_TINT_LIGHT
46689
+ );
46500
46690
  const rampBase = isDark ? mix(palette.surface, palette.text, 28) : palette.bg;
46501
- const fillForScore = (s) => {
46691
+ const fillForValue = (s) => {
46502
46692
  const t = rampMax > rampMin ? (s - rampMin) / (rampMax - rampMin) : 1;
46503
46693
  const pct = RAMP_FLOOR + Math.max(0, Math.min(1, t)) * (100 - RAMP_FLOOR);
46504
46694
  return mix(rampHue, rampBase, pct);
@@ -46523,7 +46713,7 @@ function layoutMap(resolved, data, size, opts) {
46523
46713
  };
46524
46714
  const regionFill = (r) => {
46525
46715
  if (activeIsScore) {
46526
- return r.score !== void 0 ? fillForScore(r.score) : neutralFill;
46716
+ return r.value !== void 0 ? fillForValue(r.value) : neutralFill;
46527
46717
  }
46528
46718
  return tagFill(r.tags, activeGroup) ?? neutralFill;
46529
46719
  };
@@ -46735,7 +46925,7 @@ function layoutMap(resolved, data, size, opts) {
46735
46925
  stroke: regionStroke,
46736
46926
  lineNumber,
46737
46927
  layer: "us-state",
46738
- ...r?.score !== void 0 && { score: r.score },
46928
+ ...r?.value !== void 0 && { value: r.value },
46739
46929
  ...r && Object.keys(r.tags).length > 0 && { tags: r.tags }
46740
46930
  });
46741
46931
  const ctr = (0, import_d3_geo2.geoPath)(proj).centroid(f);
@@ -46878,7 +47068,7 @@ function layoutMap(resolved, data, size, opts) {
46878
47068
  lineNumber,
46879
47069
  layer,
46880
47070
  ...label !== void 0 && { label },
46881
- ...isThisLayer && r.score !== void 0 && { score: r.score },
47071
+ ...isThisLayer && r.value !== void 0 && { value: r.value },
46882
47072
  ...isThisLayer && Object.keys(r.tags).length > 0 && { tags: r.tags }
46883
47073
  });
46884
47074
  }
@@ -46913,11 +47103,11 @@ function layoutMap(resolved, data, size, opts) {
46913
47103
  rivers.push({ d, color: riverColor, width: RIVER_WIDTH });
46914
47104
  }
46915
47105
  }
46916
- const sizeVals = resolved.pois.map((p) => Number(p.meta["size"])).filter((n) => Number.isFinite(n) && n > 0);
47106
+ const sizeVals = resolved.pois.map((p) => Number(p.meta["value"])).filter((n) => Number.isFinite(n) && n > 0);
46917
47107
  const sizeMin = sizeVals.length ? Math.min(...sizeVals) : 0;
46918
47108
  const sizeMax = sizeVals.length ? Math.max(...sizeVals) : 0;
46919
47109
  const radiusFor = (p) => {
46920
- const v = Number(p.meta["size"]);
47110
+ const v = Number(p.meta["value"]);
46921
47111
  if (!Number.isFinite(v) || v <= 0 || sizeMax <= 0) return R_DEFAULT;
46922
47112
  const t = sizeMax > sizeMin ? (Math.sqrt(v) - Math.sqrt(sizeMin)) / (Math.sqrt(sizeMax) - Math.sqrt(sizeMin)) : 1;
46923
47113
  return R_MIN + Math.max(0, Math.min(1, t)) * (R_MAX - R_MIN);
@@ -46984,7 +47174,8 @@ function layoutMap(resolved, data, size, opts) {
46984
47174
  lineNumber: e.p.lineNumber,
46985
47175
  implicit: !!e.p.implicit,
46986
47176
  isOrigin: originIds.has(e.p.id),
46987
- ...num !== void 0 && { routeNumber: num }
47177
+ ...num !== void 0 && { routeNumber: num },
47178
+ ...Object.keys(e.p.tags).length > 0 && { tags: e.p.tags }
46988
47179
  });
46989
47180
  });
46990
47181
  }
@@ -47020,26 +47211,40 @@ function layoutMap(resolved, data, size, opts) {
47020
47211
  const by = b.cy - (b.cy - py) / tb * trimB;
47021
47212
  return `M${ax},${ay}Q${px},${py} ${bx},${by}`;
47022
47213
  };
47214
+ const routeLegVals = resolved.routes.flatMap((rt) => rt.legs).map((l) => Number(l.value)).filter((n) => Number.isFinite(n) && n > 0);
47215
+ const rlMin = routeLegVals.length ? Math.min(...routeLegVals) : 0;
47216
+ const rlMax = routeLegVals.length ? Math.max(...routeLegVals) : 0;
47217
+ const routeWidthFor = (v) => {
47218
+ if (!Number.isFinite(v) || v <= 0 || rlMax <= 0) return W_MIN;
47219
+ const t = rlMax > rlMin ? (v - rlMin) / (rlMax - rlMin) : 1;
47220
+ return W_MIN + t * (W_MAX - W_MIN);
47221
+ };
47023
47222
  for (const rt of resolved.routes) {
47024
- const curved = rt.meta["style"] === "arc";
47025
- for (let i = 1; i < rt.stopIds.length; i++) {
47026
- const a = poiScreen.get(rt.stopIds[i - 1]);
47027
- const b = poiScreen.get(rt.stopIds[i]);
47223
+ for (const leg of rt.legs) {
47224
+ const a = poiScreen.get(leg.fromId);
47225
+ const b = poiScreen.get(leg.toId);
47028
47226
  if (!a || !b) continue;
47227
+ const mx = (a.cx + b.cx) / 2;
47228
+ const my = (a.cy + b.cy) / 2;
47029
47229
  legs.push({
47030
- d: legPath(a, b, curved, 0),
47031
- width: W_MIN,
47230
+ d: legPath(a, b, leg.style === "arc", 0),
47231
+ width: routeWidthFor(Number(leg.value)),
47032
47232
  color: mix(palette.text, palette.bg, 72),
47033
47233
  arrow: true,
47034
- lineNumber: rt.lineNumber
47234
+ lineNumber: leg.lineNumber,
47235
+ ...leg.label !== void 0 && {
47236
+ label: leg.label,
47237
+ labelX: mx,
47238
+ labelY: my - 4
47239
+ }
47035
47240
  });
47036
47241
  }
47037
47242
  }
47038
- const weightVals = resolved.edges.map((e) => Number(e.meta["weight"])).filter((n) => Number.isFinite(n) && n > 0);
47243
+ const weightVals = resolved.edges.map((e) => Number(e.meta["value"])).filter((n) => Number.isFinite(n) && n > 0);
47039
47244
  const wMin = weightVals.length ? Math.min(...weightVals) : 0;
47040
47245
  const wMax = weightVals.length ? Math.max(...weightVals) : 0;
47041
47246
  const widthFor = (e) => {
47042
- const v = Number(e.meta["weight"]);
47247
+ const v = Number(e.meta["value"]);
47043
47248
  if (!Number.isFinite(v) || v <= 0 || wMax <= 0) return W_MIN;
47044
47249
  const t = wMax > wMin ? (v - wMin) / (wMax - wMin) : 1;
47045
47250
  return W_MIN + t * (W_MAX - W_MIN);
@@ -47302,8 +47507,8 @@ function layoutMap(resolved, data, size, opts) {
47302
47507
  activeGroup,
47303
47508
  ...hasRamp && {
47304
47509
  ramp: {
47305
- ...resolved.directives.metric !== void 0 && {
47306
- metric: resolved.directives.metric
47510
+ ...resolved.directives.regionMetric !== void 0 && {
47511
+ metric: resolved.directives.regionMetric
47307
47512
  },
47308
47513
  min: rampMin,
47309
47514
  max: rampMax,
@@ -47331,7 +47536,7 @@ function layoutMap(resolved, data, size, opts) {
47331
47536
  insetRegions
47332
47537
  };
47333
47538
  }
47334
- 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;
47539
+ 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, MUTED_WATER_LIGHT, MUTED_WATER_DARK, MUTED_FOREIGN_LIGHT, MUTED_FOREIGN_DARK, MUTED_LAND_DARK, COLO_R, GOLDEN_ANGLE, FAN_STEP, ARC_CURVE_FRAC, usConusProjection, alaskaProjection, hawaiiProjection, INSET_STATES, US_NON_CONUS;
47335
47540
  var init_layout15 = __esm({
47336
47541
  "src/map/layout.ts"() {
47337
47542
  "use strict";
@@ -47358,6 +47563,11 @@ var init_layout15 = __esm({
47358
47563
  RIVER_WIDTH = 1.3;
47359
47564
  FOREIGN_TINT_LIGHT = 30;
47360
47565
  FOREIGN_TINT_DARK = 62;
47566
+ MUTED_WATER_LIGHT = 14;
47567
+ MUTED_WATER_DARK = 10;
47568
+ MUTED_FOREIGN_LIGHT = 28;
47569
+ MUTED_FOREIGN_DARK = 16;
47570
+ MUTED_LAND_DARK = 24;
47361
47571
  COLO_R = 9;
47362
47572
  GOLDEN_ANGLE = 2.399963229728653;
47363
47573
  FAN_STEP = 16;
@@ -47411,7 +47621,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
47411
47621
  const p = g.append("path").attr("d", r.d).attr("fill", r.fill).attr("stroke", r.stroke).attr("stroke-width", strokeWidth);
47412
47622
  if (r.layer !== "base") {
47413
47623
  p.classed("dgmo-map-region", true).attr("data-region", r.id);
47414
- if (r.score !== void 0) p.attr("data-score", r.score);
47624
+ if (r.value !== void 0) p.attr("data-value", r.value);
47415
47625
  if (r.tags) {
47416
47626
  for (const [group, value] of Object.entries(r.tags)) {
47417
47627
  p.attr(`data-tag-${group.toLowerCase()}`, value.toLowerCase());
@@ -47472,6 +47682,11 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
47472
47682
  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);
47473
47683
  }
47474
47684
  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);
47685
+ if (poi.tags) {
47686
+ for (const [group, value] of Object.entries(poi.tags)) {
47687
+ c.attr(`data-tag-${group.toLowerCase()}`, value.toLowerCase());
47688
+ }
47689
+ }
47475
47690
  if (onClickItem) {
47476
47691
  c.style("cursor", "pointer").on(
47477
47692
  "click",
@@ -47521,7 +47736,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
47521
47736
  const legendG = svg.append("g").attr("class", "dgmo-map-legend").attr("transform", `translate(0, ${legendY})`);
47522
47737
  const ramp = layout.legend.ramp;
47523
47738
  const scoreGroup = ramp ? {
47524
- name: ramp.metric?.trim() || "Score",
47739
+ name: ramp.metric?.trim() || "Value",
47525
47740
  entries: [],
47526
47741
  gradient: {
47527
47742
  min: ramp.min,
@@ -58467,7 +58682,7 @@ var COMPLETION_REGISTRY = /* @__PURE__ */ new Map([
58467
58682
  [
58468
58683
  "map",
58469
58684
  // Geographic map directives (§24B.2/.7). `poi`/`route` are content
58470
- // keywords, not directives; metadata keys (score/size/label) live in the
58685
+ // keywords, not directives; metadata keys (value/label/style) live in the
58471
58686
  // reserved-key registry.
58472
58687
  withGlobals({
58473
58688
  region: {
@@ -58478,9 +58693,14 @@ var COMPLETION_REGISTRY = /* @__PURE__ */ new Map([
58478
58693
  description: "Override the auto projection",
58479
58694
  values: ["equirectangular", "natural-earth", "albers-usa", "mercator"]
58480
58695
  },
58481
- metric: { description: "Label for the region score ramp" },
58482
- "size-metric": { description: "Label for the POI size channel" },
58483
- scale: { description: "Override score ramp anchors: scale <min> <max>" },
58696
+ "region-metric": { description: "Label for the region value ramp" },
58697
+ "poi-metric": {
58698
+ description: "Label for the POI value (marker size) channel"
58699
+ },
58700
+ "flow-metric": {
58701
+ description: "Label for the edge/leg value (thickness) channel"
58702
+ },
58703
+ scale: { description: "Override value ramp anchors: scale <min> <max>" },
58484
58704
  "region-labels": {
58485
58705
  description: "Subdivision name labels",
58486
58706
  values: ["full", "abbrev", "off"]