@motionscript/geography 0.1.0-alpha.7 → 0.1.0-alpha.8

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 (59) hide show
  1. package/CHANGELOG.md +102 -1
  2. package/NOTICE +15 -14
  3. package/README.md +78 -14
  4. package/dist/border/format.d.ts +73 -0
  5. package/dist/border/format.d.ts.map +1 -0
  6. package/dist/border/format.js +68 -0
  7. package/dist/border/format.js.map +1 -0
  8. package/dist/border/geo-border.d.ts +103 -0
  9. package/dist/border/geo-border.d.ts.map +1 -0
  10. package/dist/border/geo-border.js +203 -0
  11. package/dist/border/geo-border.js.map +1 -0
  12. package/dist/border/geometry.d.ts +40 -0
  13. package/dist/border/geometry.d.ts.map +1 -0
  14. package/dist/border/geometry.js +382 -0
  15. package/dist/border/geometry.js.map +1 -0
  16. package/dist/border/index.d.ts +15 -0
  17. package/dist/border/index.d.ts.map +1 -0
  18. package/dist/border/index.js +15 -0
  19. package/dist/border/index.js.map +1 -0
  20. package/dist/border/loader.d.ts +31 -0
  21. package/dist/border/loader.d.ts.map +1 -0
  22. package/dist/border/loader.js +87 -0
  23. package/dist/border/loader.js.map +1 -0
  24. package/dist/border/registry.d.ts +64 -0
  25. package/dist/border/registry.d.ts.map +1 -0
  26. package/dist/border/registry.js +163 -0
  27. package/dist/border/registry.js.map +1 -0
  28. package/dist/border/selection.d.ts +21 -0
  29. package/dist/border/selection.d.ts.map +1 -0
  30. package/dist/border/selection.js +86 -0
  31. package/dist/border/selection.js.map +1 -0
  32. package/dist/border/simplify.d.ts +12 -0
  33. package/dist/border/simplify.d.ts.map +1 -0
  34. package/dist/border/simplify.js +116 -0
  35. package/dist/border/simplify.js.map +1 -0
  36. package/dist/browser/THIRD_PARTY_LICENSES.txt +58 -0
  37. package/dist/browser/index.js +2 -0
  38. package/dist/browser/index.js.map +7 -0
  39. package/dist/browser/manifest.json +23 -0
  40. package/dist/index.d.ts +3 -0
  41. package/dist/index.d.ts.map +1 -0
  42. package/dist/index.js +3 -0
  43. package/dist/index.js.map +1 -0
  44. package/dist/nodes.d.ts +15 -0
  45. package/dist/nodes.d.ts.map +1 -0
  46. package/dist/nodes.js +16 -0
  47. package/dist/nodes.js.map +1 -0
  48. package/package.json +46 -8
  49. package/registry.json +16 -0
  50. package/src/border/format.ts +147 -0
  51. package/src/border/geo-border.ts +268 -0
  52. package/src/border/geometry.ts +463 -0
  53. package/src/border/index.ts +14 -0
  54. package/src/border/loader.ts +97 -0
  55. package/src/border/registry.ts +201 -0
  56. package/src/border/selection.ts +95 -0
  57. package/src/border/simplify.ts +110 -0
  58. package/src/index.ts +2 -0
  59. package/src/nodes.ts +16 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"geometry.js","sourceRoot":"","sources":["../../src/border/geometry.ts"],"names":[],"mappings":"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","sourcesContent":["import {\r\n geoArea,\r\n geoBounds,\r\n geoConicEqualArea,\r\n geoEquirectangular,\r\n geoMercator,\r\n geoOrthographic,\r\n geoPath,\r\n geoStream,\r\n type GeoPermissibleObjects,\r\n type GeoProjection,\r\n} from \"d3-geo\"\r\n\r\nimport { ringCoordinates, type GeoArc, type GeoFeature, type GeoPolygon, type GeoRingRef } from \"./format\"\r\nimport type { GeoFrame } from \"./selection\"\r\n\r\nexport type GeoProjectionKind = \"conic\" | \"mercator\" | \"equirectangular\" | \"orthographic\"\r\nexport type GeoBorders = \"all\" | \"outline\"\r\n\r\nexport interface GeoContour {\r\n /** Interleaved x/y in unit space: the longer side spans 1, centred on the origin, y up. */\r\n points: Float32Array\r\n closed: boolean\r\n length: number\r\n}\r\n\r\nexport interface GeoGeometry {\r\n /** The drawing's extent in unit space; the longer of the two is 1. */\r\n width: number\r\n height: number\r\n fills: GeoContour[]\r\n lines: GeoContour[]\r\n fillLength: number\r\n lineLength: number\r\n bytes: number\r\n}\r\n\r\ninterface Part {\r\n polygon: GeoPolygon\r\n largest: boolean\r\n}\r\n\r\ninterface Frame {\r\n projection: GeoProjection\r\n centerX: number\r\n centerY: number\r\n size: number\r\n width: number\r\n height: number\r\n}\r\n\r\nconst FIT = 1024\r\n\r\n// `detail` maps onto a weight threshold that is a fraction of the selection's\r\n// own area, on a log scale — which is what makes a value look equally stylised\r\n// on Monaco and on Russia. 0 keeps points worth 1% of the area; just below 1,\r\n// points worth a billionth of it.\r\nconst POINT_BASE = 2\r\nconst POINT_RANGE = 7\r\nconst POLYGON_BASE = 1.5\r\nconst POLYGON_RANGE = 6\r\n\r\nconst clamp01 = (value: number) => (value > 1 ? 1 : value > 0 ? value : 0)\r\n\r\n/** The highest weight bucket a point may carry and still be drawn. */\r\nexport function pointBucketLimit(detail: number, area: number): number {\r\n if (detail >= 1 || !(area > 0)) return 255\r\n const minWeight = area * 10 ** -(POINT_BASE + POINT_RANGE * clamp01(detail))\r\n return Math.floor(-2 * Math.log2(minWeight))\r\n}\r\n\r\n/** Rings smaller than this (steradians) are dropped, bar each region's largest. */\r\nexport function polygonAreaLimit(detail: number, area: number): number {\r\n if (detail >= 1) return 0\r\n return area * 10 ** -(POLYGON_BASE + POLYGON_RANGE * clamp01(detail))\r\n}\r\n\r\nfunction partsOf(features: readonly GeoFeature[], frame: GeoFrame): Part[] {\r\n const parts: Part[] = []\r\n for (const feature of features) {\r\n const mainland = frame === \"mainland\" ? feature.polygons.filter((p) => p.mainland) : []\r\n const polygons = mainland.length > 0 ? mainland : feature.polygons\r\n let largest: GeoPolygon | null = null\r\n for (const polygon of polygons) if (!largest || polygon.area > largest.area) largest = polygon\r\n for (const polygon of polygons) parts.push({ polygon, largest: polygon === largest })\r\n }\r\n return parts\r\n}\r\n\r\nfunction centerLongitude(west: number, east: number): number {\r\n if (west <= east) return (west + east) / 2\r\n const mid = (west + east + 360) / 2\r\n return mid > 180 ? mid - 360 : mid\r\n}\r\n\r\nfunction makeProjection(kind: GeoProjectionKind, west: number, south: number, east: number, north: number): GeoProjection {\r\n const lon = centerLongitude(west, east)\r\n const lat = (south + north) / 2\r\n switch (kind) {\r\n case \"mercator\":\r\n return geoMercator().rotate([-lon, 0])\r\n case \"equirectangular\":\r\n return geoEquirectangular().rotate([-lon, 0])\r\n case \"orthographic\":\r\n return geoOrthographic().rotate([-lon, -lat])\r\n case \"conic\": {\r\n const span = north - south\r\n return geoConicEqualArea()\r\n .rotate([-lon, 0])\r\n .center([0, lat])\r\n .parallels([south + span / 6, north - span / 6])\r\n }\r\n }\r\n}\r\n\r\nfunction fitFrame(kind: GeoProjectionKind, parts: readonly Part[]): Frame | null {\r\n if (parts.length === 0) return null\r\n const shape = {\r\n type: \"MultiPolygon\",\r\n coordinates: parts.map(({ polygon }) => [ringCoordinates(polygon.rings[0])]),\r\n } as GeoPermissibleObjects\r\n const [[west, south], [east, north]] = geoBounds(shape)\r\n\r\n for (const candidate of [kind, \"equirectangular\"] as const) {\r\n const projection = makeProjection(candidate, west, south, east, north).fitSize([FIT, FIT], shape)\r\n const [[x0, y0], [x1, y1]] = geoPath(projection).bounds(shape)\r\n const size = Math.max(x1 - x0, y1 - y0)\r\n if (!Number.isFinite(size) || size <= 0) continue\r\n return {\r\n projection,\r\n centerX: (x0 + x1) / 2,\r\n centerY: (y0 + y1) / 2,\r\n size,\r\n width: (x1 - x0) / size,\r\n height: (y1 - y0) / size,\r\n }\r\n }\r\n return null\r\n}\r\n\r\nfunction project(frame: Frame, object: GeoPermissibleObjects, closed: boolean): GeoContour[] {\r\n const contours: GeoContour[] = []\r\n let current: number[] | null = null\r\n const { centerX, centerY, size } = frame\r\n const sink = {\r\n point(x: number, y: number) {\r\n current?.push((x - centerX) / size, -(y - centerY) / size)\r\n },\r\n lineStart() {\r\n current = []\r\n },\r\n lineEnd() {\r\n const flat = current\r\n current = null\r\n if (!flat || flat.length < 4) return\r\n let isClosed = closed\r\n if (!closed) {\r\n const n = flat.length\r\n if (flat[0] === flat[n - 2] && flat[1] === flat[n - 1] && n >= 8) {\r\n flat.length = n - 2\r\n isClosed = true\r\n }\r\n }\r\n const points = Float32Array.from(flat)\r\n contours.push({ points, closed: isClosed, length: contourLength(points, isClosed) })\r\n },\r\n polygonStart() {},\r\n polygonEnd() {},\r\n sphere() {},\r\n }\r\n geoStream(object, frame.projection.stream(sink))\r\n return contours\r\n}\r\n\r\nfunction contourLength(points: Float32Array, closed: boolean): number {\r\n let length = 0\r\n const n = points.length / 2\r\n for (let i = 1; i < n; i++) {\r\n length += Math.hypot(points[i * 2] - points[i * 2 - 2], points[i * 2 + 1] - points[i * 2 - 1])\r\n }\r\n if (closed && n > 1) length += Math.hypot(points[0] - points[n * 2 - 2], points[1] - points[n * 2 - 1])\r\n return length\r\n}\r\n\r\n// Longest edge, in degrees, that simplification may leave. d3 takes an edge as\r\n// the short way round the sphere, so an edge across more than half the planet\r\n// (Kaliningrad to Chukotka, once the coast between is dropped) turns inside out.\r\nconst MAX_EDGE_DEGREES = 20\r\n\r\ntype MaskFor = (arc: GeoArc) => Uint8Array\r\n\r\n/** Which of an arc's points survive `limit`, the same whichever way the arc is walked. */\r\nfunction keepMask(arc: GeoArc, limit: number): Uint8Array {\r\n const n = arc.buckets.length\r\n const mask = new Uint8Array(n)\r\n let lastLon = arc.points[0]\r\n let lastLat = arc.points[1]\r\n for (let i = 0; i < n; i++) {\r\n const lon = arc.points[i * 2]\r\n const lat = arc.points[i * 2 + 1]\r\n let far = false\r\n if (arc.buckets[i] > limit) {\r\n let dLon = Math.abs(lon - lastLon)\r\n if (dLon > 180) dLon = 360 - dLon\r\n far = Math.abs(lat - lastLat) > MAX_EDGE_DEGREES || dLon * Math.cos((lat * Math.PI) / 180) > MAX_EDGE_DEGREES\r\n }\r\n if (arc.buckets[i] <= limit || far) {\r\n mask[i] = 1\r\n lastLon = lon\r\n lastLat = lat\r\n }\r\n }\r\n return mask\r\n}\r\n\r\nfunction filteredPoints(refs: readonly GeoRingRef[], maskFor: MaskFor): [number, number][] {\r\n const out: [number, number][] = []\r\n for (const { arc, reversed } of refs) {\r\n const n = arc.buckets.length\r\n const mask = maskFor(arc)\r\n for (let j = out.length === 0 ? 0 : 1; j < n; j++) {\r\n const i = reversed ? n - 1 - j : j\r\n if (mask[i]) out.push([arc.points[i * 2], arc.points[i * 2 + 1]])\r\n }\r\n }\r\n return out\r\n}\r\n\r\n/** A ring keeps at least three vertices, raising its arcs' limits if the global one would collapse it. */\r\nfunction ringLimit(ring: readonly GeoRingRef[], limit: number): number {\r\n let kept = 0\r\n for (const { arc } of ring) {\r\n for (let i = 0; i < arc.buckets.length - 1; i++) if (arc.buckets[i] <= limit) kept++\r\n }\r\n if (kept >= 3) return limit\r\n const buckets: number[] = []\r\n for (const { arc } of ring) for (let i = 0; i < arc.buckets.length - 1; i++) buckets.push(arc.buckets[i])\r\n buckets.sort((a, b) => a - b)\r\n return Math.max(limit, buckets[Math.min(2, buckets.length - 1)] ?? limit)\r\n}\r\n\r\n/**\r\n * Whether a simplified ring still winds the way its original did. Dropping\r\n * points can fold a small ring over itself, and d3 reads an exterior wound the\r\n * wrong way as the rest of the planet — one such island fills the whole frame.\r\n */\r\nfunction windsAsOriginal(ring: [number, number][], exterior: boolean): boolean {\r\n if (ring.length < 4) return true\r\n const inverted = geoArea({ type: \"Polygon\", coordinates: [ring] }) > 2 * Math.PI\r\n return inverted !== exterior\r\n}\r\n\r\ninterface Chain {\r\n refs: GeoRingRef[]\r\n closed: boolean\r\n}\r\n\r\nconst endKey = (arc: GeoArc, last: boolean) => {\r\n const i = last ? arc.buckets.length - 1 : 0\r\n return `${arc.points[i * 2]},${arc.points[i * 2 + 1]}`\r\n}\r\n\r\n/** Joins arcs that meet end to end with nothing else at the joint, so a border draws as one line with real joins. */\r\nfunction chainArcs(arcs: readonly GeoArc[]): Chain[] {\r\n const atNode = new Map<string, GeoArc[]>()\r\n for (const arc of arcs) {\r\n for (const key of [endKey(arc, false), endKey(arc, true)]) {\r\n const list = atNode.get(key)\r\n if (list) list.push(arc)\r\n else atNode.set(key, [arc])\r\n }\r\n }\r\n const visited = new Set<GeoArc>()\r\n const chains: Chain[] = []\r\n const refStart = ({ arc, reversed }: GeoRingRef) => endKey(arc, reversed)\r\n const refEnd = ({ arc, reversed }: GeoRingRef) => endKey(arc, !reversed)\r\n const nextAt = (node: string): GeoArc | null => {\r\n const list = atNode.get(node)!\r\n if (list.length !== 2) return null\r\n return list.find((arc) => !visited.has(arc)) ?? null\r\n }\r\n\r\n for (const arc of arcs) {\r\n if (visited.has(arc)) continue\r\n visited.add(arc)\r\n const refs: GeoRingRef[] = [{ arc, reversed: false }]\r\n for (let next = nextAt(refEnd(refs[refs.length - 1])); next; next = nextAt(refEnd(refs[refs.length - 1]))) {\r\n visited.add(next)\r\n refs.push({ arc: next, reversed: endKey(next, false) !== refEnd(refs[refs.length - 1]) })\r\n }\r\n for (let prev = nextAt(refStart(refs[0])); prev; prev = nextAt(refStart(refs[0]))) {\r\n visited.add(prev)\r\n refs.unshift({ arc: prev, reversed: endKey(prev, true) !== refStart(refs[0]) })\r\n }\r\n chains.push({ refs, closed: refStart(refs[0]) === refEnd(refs[refs.length - 1]) })\r\n }\r\n return chains\r\n}\r\n\r\nfunction buildGeometry(\r\n features: readonly GeoFeature[],\r\n frame: GeoFrame,\r\n fitted: Frame,\r\n borders: GeoBorders,\r\n detail: number\r\n): GeoGeometry {\r\n const parts = partsOf(features, frame)\r\n const area = parts.reduce((sum, { polygon }) => sum + polygon.area, 0)\r\n const pointLimit = pointBucketLimit(detail, area)\r\n const polygonLimit = polygonAreaLimit(detail, area)\r\n\r\n const kept: GeoRingRef[][][] = []\r\n for (const { polygon, largest } of parts) {\r\n if (!largest && polygon.area < polygonLimit) continue\r\n kept.push(polygon.rings.filter((_, i) => i === 0 || polygon.ringAreas[i] >= polygonLimit))\r\n }\r\n\r\n const limits = new Map<GeoArc[\"key\"], number>()\r\n const usage = new Map<GeoArc[\"key\"], { arc: GeoArc; count: number }>()\r\n for (const rings of kept) {\r\n for (const ring of rings) {\r\n const limit = ringLimit(ring, pointLimit)\r\n for (const { arc } of ring) {\r\n limits.set(arc.key, Math.max(limits.get(arc.key) ?? 0, limit))\r\n const use = usage.get(arc.key)\r\n if (use) use.count++\r\n else usage.set(arc.key, { arc, count: 1 })\r\n }\r\n }\r\n }\r\n\r\n const masks = new Map<GeoArc[\"key\"], Uint8Array>()\r\n const maskFor: MaskFor = (arc) => {\r\n let mask = masks.get(arc.key)\r\n if (!mask) {\r\n mask = keepMask(arc, limits.get(arc.key) ?? 255)\r\n masks.set(arc.key, mask)\r\n }\r\n return mask\r\n }\r\n\r\n if (pointLimit < 255) {\r\n for (const rings of kept) {\r\n rings.forEach((ring, index) => {\r\n let limit = Math.min(...ring.map(({ arc }) => limits.get(arc.key) ?? pointLimit))\r\n while (limit < 255 && !windsAsOriginal(filteredPoints(ring, maskFor), index === 0)) {\r\n limit = Math.min(255, limit + 2)\r\n for (const { arc } of ring) {\r\n limits.set(arc.key, Math.max(limits.get(arc.key) ?? 0, limit))\r\n masks.delete(arc.key)\r\n }\r\n }\r\n })\r\n }\r\n }\r\n\r\n const fills = project(\r\n fitted,\r\n {\r\n type: \"MultiPolygon\",\r\n coordinates: kept.flatMap((rings) => {\r\n const [exterior, ...holes] = rings.map((ring) => filteredPoints(ring, maskFor))\r\n return exterior.length < 4 ? [] : [[exterior, ...holes.filter((hole) => hole.length >= 4)]]\r\n }),\r\n } as GeoPermissibleObjects,\r\n true\r\n )\r\n\r\n const lineArcs = [...usage.values()].filter(({ count }) => borders === \"all\" || count === 1).map(({ arc }) => arc)\r\n const lines: GeoContour[] = []\r\n for (const chain of chainArcs(lineArcs)) {\r\n lines.push(\r\n ...project(fitted, { type: \"LineString\", coordinates: filteredPoints(chain.refs, maskFor) } as GeoPermissibleObjects, false)\r\n )\r\n }\r\n\r\n const sum = (contours: GeoContour[]) => contours.reduce((total, c) => total + c.length, 0)\r\n const bytes = [...fills, ...lines].reduce((total, c) => total + c.points.byteLength + 32, 0)\r\n return {\r\n width: fitted.width,\r\n height: fitted.height,\r\n fills,\r\n lines,\r\n fillLength: sum(fills),\r\n lineLength: sum(lines),\r\n bytes,\r\n }\r\n}\r\n\r\nclass ByteCache<V extends { bytes: number }> {\r\n private _entries = new Map<string, V>()\r\n private _bytes = 0\r\n\r\n constructor(private readonly _budget: number) {}\r\n\r\n get(key: string): V | undefined {\r\n const value = this._entries.get(key)\r\n if (value) {\r\n this._entries.delete(key)\r\n this._entries.set(key, value)\r\n }\r\n return value\r\n }\r\n\r\n set(key: string, value: V): void {\r\n const previous = this._entries.get(key)\r\n if (previous) this._bytes -= previous.bytes\r\n this._entries.delete(key)\r\n this._entries.set(key, value)\r\n this._bytes += value.bytes\r\n for (const [oldest, entry] of this._entries) {\r\n if (this._bytes <= this._budget || this._entries.size <= 1) break\r\n this._entries.delete(oldest)\r\n this._bytes -= entry.bytes\r\n }\r\n }\r\n\r\n clear(): void {\r\n this._entries.clear()\r\n this._bytes = 0\r\n }\r\n}\r\n\r\nconst frames = new ByteCache<Frame & { bytes: number }>(64)\r\nconst geometries = new ByteCache<GeoGeometry>(64 * 1024 * 1024)\r\n\r\nexport interface GeoGeometryRequest {\r\n /** Identifies `features` and `frame`: equal keys must mean equal selections. */\r\n selectionKey: string\r\n features: readonly GeoFeature[]\r\n frame: GeoFrame\r\n projection: GeoProjectionKind\r\n borders: GeoBorders\r\n detail: number\r\n}\r\n\r\n/**\r\n * The drawing for a selection, cached. The projection is fitted to the\r\n * selection at full detail, so a `detail` tween never moves or rescales it.\r\n */\r\nexport function geoGeometry(request: GeoGeometryRequest): GeoGeometry | null {\r\n const detail = Math.round(clamp01(request.detail) * 100) / 100\r\n const frameKey = `${request.selectionKey}|${request.projection}`\r\n const key = `${frameKey}|${request.borders}|${detail}`\r\n const cached = geometries.get(key)\r\n if (cached) return cached\r\n\r\n let fitted: Frame | undefined = frames.get(frameKey)\r\n if (!fitted) {\r\n const made = fitFrame(request.projection, partsOf(request.features, request.frame))\r\n if (!made) return null\r\n fitted = made\r\n frames.set(frameKey, { ...made, bytes: 1 })\r\n }\r\n const geometry = buildGeometry(request.features, request.frame, fitted, request.borders, detail)\r\n geometries.set(key, geometry)\r\n return geometry\r\n}\r\n\r\nexport function clearGeoGeometry(): void {\r\n frames.clear()\r\n geometries.clear()\r\n}\r\n"]}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * GeoBorder: country and subdivision outlines by ISO 3166 code.
3
+ *
4
+ * `ms add geo-border` copies only `geo-border.ts`. Everything it imports from
5
+ * here — the source registry, the file cache, the geometry — stays behind the
6
+ * package, so a forked node shares the host's registered sources instead of
7
+ * owning an empty registry of its own.
8
+ */
9
+ export * from "./format.js";
10
+ export * from "./geo-border.js";
11
+ export * from "./geometry.js";
12
+ export * from "./loader.js";
13
+ export * from "./registry.js";
14
+ export * from "./selection.js";
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/border/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,cAAc,UAAU,CAAA;AACxB,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA;AAC1B,cAAc,UAAU,CAAA;AACxB,cAAc,YAAY,CAAA;AAC1B,cAAc,aAAa,CAAA"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * GeoBorder: country and subdivision outlines by ISO 3166 code.
3
+ *
4
+ * `ms add geo-border` copies only `geo-border.ts`. Everything it imports from
5
+ * here — the source registry, the file cache, the geometry — stays behind the
6
+ * package, so a forked node shares the host's registered sources instead of
7
+ * owning an empty registry of its own.
8
+ */
9
+ export * from "./format.js";
10
+ export * from "./geo-border.js";
11
+ export * from "./geometry.js";
12
+ export * from "./loader.js";
13
+ export * from "./registry.js";
14
+ export * from "./selection.js";
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/border/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,cAAc,UAAU,CAAA;AACxB,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA;AAC1B,cAAc,UAAU,CAAA;AACxB,cAAc,YAAY,CAAA;AAC1B,cAAc,aAAa,CAAA","sourcesContent":["/**\r\n * GeoBorder: country and subdivision outlines by ISO 3166 code.\r\n *\r\n * `ms add geo-border` copies only `geo-border.ts`. Everything it imports from\r\n * here — the source registry, the file cache, the geometry — stays behind the\r\n * package, so a forked node shares the host's registered sources instead of\r\n * owning an empty registry of its own.\r\n */\r\nexport * from \"./format\"\r\nexport * from \"./geo-border\"\r\nexport * from \"./geometry\"\r\nexport * from \"./loader\"\r\nexport * from \"./registry\"\r\nexport * from \"./selection\"\r\n"]}
@@ -0,0 +1,31 @@
1
+ import type { LoaderFn } from "@motionscript/sdk";
2
+ import { type DecodedGeoFile } from "./format.js";
3
+ export type GeoFileEntry = {
4
+ status: "ready";
5
+ file: DecodedGeoFile;
6
+ } | {
7
+ status: "missing";
8
+ } | {
9
+ status: "failed";
10
+ error: unknown;
11
+ };
12
+ export declare function countryFileKey(code: string): string;
13
+ export declare function statesFileKey(country: string): string;
14
+ /** Bumps whenever a file lands, so derived geometry keyed on it rebuilds. */
15
+ export declare function geoDataVersion(): number;
16
+ export declare function geoFileEntry(key: string): GeoFileEntry | undefined;
17
+ /**
18
+ * Loads one data file into the shared cache. Never rejects: a rejected loader
19
+ * is retried on every tick and fails an export outright, where a recorded
20
+ * failure draws nothing and is tried again by the next call.
21
+ */
22
+ export declare function loadGeoFile(key: string): Promise<GeoFileEntry>;
23
+ /**
24
+ * The loader an `AssetScope` declares for a file: one function per key, so
25
+ * every node that needs the file declares the same one. Nothing is disposed —
26
+ * decoded data is shared by every engine in the process.
27
+ */
28
+ export declare function geoLoader(key: string): LoaderFn;
29
+ /** Forgets every loaded file — for tests. */
30
+ export declare function clearGeoFiles(): void;
31
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/border/loader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAEjD,OAAO,EAAiB,KAAK,cAAc,EAAoB,MAAM,UAAU,CAAA;AAG/E,MAAM,MAAM,YAAY,GAClB;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,cAAc,CAAA;CAAE,GACzC;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,GACrB;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAA;AAQ1C,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,6EAA6E;AAC7E,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAElE;AAeD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAqB9D;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAS/C;AAED,6CAA6C;AAC7C,wBAAgB,aAAa,IAAI,IAAI,CAKpC"}
@@ -0,0 +1,87 @@
1
+ import { decodeGeoFile } from "./format.js";
2
+ import { GEO_DATA_VERSION, geoRegistry } from "./registry.js";
3
+ const entries = new Map();
4
+ const inflight = new Map();
5
+ const loaders = new Map();
6
+ const warned = new Set();
7
+ let version = 0;
8
+ export function countryFileKey(code) {
9
+ return `${GEO_DATA_VERSION}/countries/${code}`;
10
+ }
11
+ export function statesFileKey(country) {
12
+ return `${GEO_DATA_VERSION}/states/${country}`;
13
+ }
14
+ /** Bumps whenever a file lands, so derived geometry keyed on it rebuilds. */
15
+ export function geoDataVersion() {
16
+ return version;
17
+ }
18
+ export function geoFileEntry(key) {
19
+ return entries.get(key);
20
+ }
21
+ async function fetchEntry(key) {
22
+ try {
23
+ let data = (await geoRegistry.resolve(key));
24
+ // A country with no subdivisions has no states file; its outline stands in.
25
+ if (data === null && key.includes("/states/")) {
26
+ data = (await geoRegistry.resolve(key.replace("/states/", "/countries/")));
27
+ }
28
+ return data === null ? { status: "missing" } : { status: "ready", file: decodeGeoFile(data) };
29
+ }
30
+ catch (error) {
31
+ return { status: "failed", error };
32
+ }
33
+ }
34
+ /**
35
+ * Loads one data file into the shared cache. Never rejects: a rejected loader
36
+ * is retried on every tick and fails an export outright, where a recorded
37
+ * failure draws nothing and is tried again by the next call.
38
+ */
39
+ export function loadGeoFile(key) {
40
+ const current = entries.get(key);
41
+ if (current?.status === "ready")
42
+ return Promise.resolve(current);
43
+ let job = inflight.get(key);
44
+ if (!job) {
45
+ job = fetchEntry(key).then((entry) => {
46
+ inflight.delete(key);
47
+ entries.set(key, entry);
48
+ version++;
49
+ if (entry.status === "ready") {
50
+ warned.delete(key);
51
+ }
52
+ else if (!warned.has(key)) {
53
+ warned.add(key);
54
+ if (entry.status === "failed")
55
+ console.warn(`[GeoBorder] could not load ${key}:`, entry.error);
56
+ else
57
+ console.warn(`[GeoBorder] no geo source has ${key}`);
58
+ }
59
+ return entry;
60
+ });
61
+ inflight.set(key, job);
62
+ }
63
+ return job;
64
+ }
65
+ /**
66
+ * The loader an `AssetScope` declares for a file: one function per key, so
67
+ * every node that needs the file declares the same one. Nothing is disposed —
68
+ * decoded data is shared by every engine in the process.
69
+ */
70
+ export function geoLoader(key) {
71
+ let load = loaders.get(key);
72
+ if (!load) {
73
+ load = async () => {
74
+ await loadGeoFile(key);
75
+ };
76
+ loaders.set(key, load);
77
+ }
78
+ return load;
79
+ }
80
+ /** Forgets every loaded file — for tests. */
81
+ export function clearGeoFiles() {
82
+ entries.clear();
83
+ inflight.clear();
84
+ warned.clear();
85
+ version++;
86
+ }
87
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/border/loader.ts"],"names":[],"mappings":"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","sourcesContent":["import type { LoaderFn } from \"@motionscript/sdk\"\r\n\r\nimport { decodeGeoFile, type DecodedGeoFile, type GeoFileData } from \"./format\"\r\nimport { GEO_DATA_VERSION, geoRegistry } from \"./registry\"\r\n\r\nexport type GeoFileEntry =\r\n | { status: \"ready\"; file: DecodedGeoFile }\r\n | { status: \"missing\" }\r\n | { status: \"failed\"; error: unknown }\r\n\r\nconst entries = new Map<string, GeoFileEntry>()\r\nconst inflight = new Map<string, Promise<GeoFileEntry>>()\r\nconst loaders = new Map<string, LoaderFn>()\r\nconst warned = new Set<string>()\r\nlet version = 0\r\n\r\nexport function countryFileKey(code: string): string {\r\n return `${GEO_DATA_VERSION}/countries/${code}`\r\n}\r\n\r\nexport function statesFileKey(country: string): string {\r\n return `${GEO_DATA_VERSION}/states/${country}`\r\n}\r\n\r\n/** Bumps whenever a file lands, so derived geometry keyed on it rebuilds. */\r\nexport function geoDataVersion(): number {\r\n return version\r\n}\r\n\r\nexport function geoFileEntry(key: string): GeoFileEntry | undefined {\r\n return entries.get(key)\r\n}\r\n\r\nasync function fetchEntry(key: string): Promise<GeoFileEntry> {\r\n try {\r\n let data = (await geoRegistry.resolve(key)) as GeoFileData | null\r\n // A country with no subdivisions has no states file; its outline stands in.\r\n if (data === null && key.includes(\"/states/\")) {\r\n data = (await geoRegistry.resolve(key.replace(\"/states/\", \"/countries/\"))) as GeoFileData | null\r\n }\r\n return data === null ? { status: \"missing\" } : { status: \"ready\", file: decodeGeoFile(data) }\r\n } catch (error) {\r\n return { status: \"failed\", error }\r\n }\r\n}\r\n\r\n/**\r\n * Loads one data file into the shared cache. Never rejects: a rejected loader\r\n * is retried on every tick and fails an export outright, where a recorded\r\n * failure draws nothing and is tried again by the next call.\r\n */\r\nexport function loadGeoFile(key: string): Promise<GeoFileEntry> {\r\n const current = entries.get(key)\r\n if (current?.status === \"ready\") return Promise.resolve(current)\r\n let job = inflight.get(key)\r\n if (!job) {\r\n job = fetchEntry(key).then((entry) => {\r\n inflight.delete(key)\r\n entries.set(key, entry)\r\n version++\r\n if (entry.status === \"ready\") {\r\n warned.delete(key)\r\n } else if (!warned.has(key)) {\r\n warned.add(key)\r\n if (entry.status === \"failed\") console.warn(`[GeoBorder] could not load ${key}:`, entry.error)\r\n else console.warn(`[GeoBorder] no geo source has ${key}`)\r\n }\r\n return entry\r\n })\r\n inflight.set(key, job)\r\n }\r\n return job\r\n}\r\n\r\n/**\r\n * The loader an `AssetScope` declares for a file: one function per key, so\r\n * every node that needs the file declares the same one. Nothing is disposed —\r\n * decoded data is shared by every engine in the process.\r\n */\r\nexport function geoLoader(key: string): LoaderFn {\r\n let load = loaders.get(key)\r\n if (!load) {\r\n load = async () => {\r\n await loadGeoFile(key)\r\n }\r\n loaders.set(key, load)\r\n }\r\n return load\r\n}\r\n\r\n/** Forgets every loaded file — for tests. */\r\nexport function clearGeoFiles(): void {\r\n entries.clear()\r\n inflight.clear()\r\n warned.clear()\r\n version++\r\n}\r\n"]}
@@ -0,0 +1,64 @@
1
+ import { type GeoFeature, type GeoFileData, type GeoIndex } from "./format.js";
2
+ /** Prefix every data key carries; bumped with the file format. */
3
+ export declare const GEO_DATA_VERSION = "v1";
4
+ /**
5
+ * Answers a data key — `v1/countries/FR`, `v1/states/US`, `v1/index` — with the
6
+ * parsed file, or `null` when this source does not have it. A throw means "could
7
+ * not tell" (offline, a 500) and is retried on the next load.
8
+ */
9
+ export type GeoSource = (key: string) => Promise<unknown>;
10
+ type Position = readonly [number, number] | readonly number[];
11
+ type GeoPolygonShape = {
12
+ type: "Polygon";
13
+ coordinates: readonly (readonly Position[])[];
14
+ } | {
15
+ type: "MultiPolygon";
16
+ coordinates: readonly (readonly (readonly Position[])[])[];
17
+ };
18
+ /** GeoJSON in lon/lat: a Polygon, a MultiPolygon, or a Feature holding one. */
19
+ export type GeoShape = GeoPolygonShape | {
20
+ type: "Feature";
21
+ geometry: GeoPolygonShape;
22
+ properties?: {
23
+ name?: string;
24
+ } | null;
25
+ };
26
+ export interface GeoDefinition {
27
+ shape: GeoShape;
28
+ name?: string;
29
+ /** The country a subdivision code expands under, when it has one. */
30
+ parent?: string;
31
+ }
32
+ /** Fetches `<base>/<key>.json`; `base` may instead map a key to its URL. */
33
+ export declare function geoUrlSource(base: string | ((key: string) => string), init?: RequestInit): GeoSource;
34
+ /** Wraps a function returning the file as text, bytes or parsed JSON (e.g. `fs.readFile`). */
35
+ export declare function geoLoaderSource(load: (key: string) => Promise<string | ArrayBuffer | Uint8Array | object | null | undefined>): GeoSource;
36
+ declare class GeoRegistry {
37
+ private _sources;
38
+ private _defined;
39
+ private _generation;
40
+ private _serial;
41
+ /** Bumps whenever a source or a definition is added or removed. */
42
+ get generation(): number;
43
+ get hasSources(): boolean;
44
+ /** Adds a source after every source already registered. Returns its removal. */
45
+ use(source: GeoSource): () => void;
46
+ /**
47
+ * Shapes (GeoJSON, lon/lat) under codes of your choosing, checked before any
48
+ * source. A definition replaces generated data for the same code.
49
+ */
50
+ define(shapes: Record<string, GeoShape | GeoDefinition>): () => void;
51
+ defined(code: string): GeoFeature | undefined;
52
+ /** Removes every source and definition — for tests. */
53
+ reset(): void;
54
+ /**
55
+ * Asks each source in registration order; the first non-null answer wins.
56
+ * Resolves `null` only when every source answered that it has no such file.
57
+ */
58
+ resolve(key: string): Promise<GeoFileData | GeoIndex | null>;
59
+ /** Every listed region's code, names and parent, for a picker. */
60
+ index(): Promise<GeoIndex | null>;
61
+ }
62
+ export declare const geoRegistry: GeoRegistry;
63
+ export {};
64
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/border/registry.ts"],"names":[],"mappings":"AAEA,OAAO,EAEH,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,QAAQ,EAGhB,MAAM,UAAU,CAAA;AAGjB,kEAAkE;AAClE,eAAO,MAAM,gBAAgB,OAAwB,CAAA;AAErD;;;;GAIG;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;AAEzD,KAAK,QAAQ,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,MAAM,EAAE,CAAA;AAC7D,KAAK,eAAe,GACd;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,WAAW,EAAE,SAAS,CAAC,SAAS,QAAQ,EAAE,CAAC,EAAE,CAAA;CAAE,GAClE;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,WAAW,EAAE,SAAS,CAAC,SAAS,CAAC,SAAS,QAAQ,EAAE,CAAC,EAAE,CAAC,EAAE,CAAA;CAAE,CAAA;AAC1F,+EAA+E;AAC/E,MAAM,MAAM,QAAQ,GAAG,eAAe,GAAG;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,eAAe,CAAC;IAAC,UAAU,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;CAAE,CAAA;AAE9H,MAAM,WAAW,aAAa;IAC1B,KAAK,EAAE,QAAQ,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,4EAA4E;AAC5E,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,SAAS,CASpG;AAED,8FAA8F;AAC9F,wBAAgB,eAAe,CAC3B,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,WAAW,GAAG,UAAU,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,GAC9F,SAAS,CAUX;AAqDD,cAAM,WAAW;IACb,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,QAAQ,CAA6D;IAC7E,OAAO,CAAC,WAAW,CAAI;IACvB,OAAO,CAAC,OAAO,CAAI;IAEnB,mEAAmE;IACnE,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,IAAI,UAAU,IAAI,OAAO,CAExB;IAED,gFAAgF;IAChF,GAAG,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,IAAI;IAWlC;;;OAGG;IACH,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,GAAG,aAAa,CAAC,GAAG,MAAM,IAAI;IAiBpE,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS;IAI7C,uDAAuD;IACvD,KAAK,IAAI,IAAI;IAMb;;;OAGG;IACG,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,QAAQ,GAAG,IAAI,CAAC;IAiBlE,kEAAkE;IAC5D,KAAK,IAAI,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;CAG1C;AAED,eAAO,MAAM,WAAW,aAAoB,CAAA"}
@@ -0,0 +1,163 @@
1
+ import { geoArea } from "d3-geo";
2
+ import { GEO_DATA_FORMAT, } from "./format.js";
3
+ import { ringBuckets } from "./simplify.js";
4
+ /** Prefix every data key carries; bumped with the file format. */
5
+ export const GEO_DATA_VERSION = `v${GEO_DATA_FORMAT}`;
6
+ /** Fetches `<base>/<key>.json`; `base` may instead map a key to its URL. */
7
+ export function geoUrlSource(base, init) {
8
+ return async (key) => {
9
+ const url = typeof base === "function" ? base(key) : `${base.replace(/\/+$/, "")}/${key}.json`;
10
+ const response = await fetch(url, init);
11
+ // Some object stores answer a missing key with 400, not 404.
12
+ if (response.status === 404 || response.status === 400)
13
+ return null;
14
+ if (!response.ok)
15
+ throw new Error(`${url} → HTTP ${response.status}`);
16
+ return response.json();
17
+ };
18
+ }
19
+ /** Wraps a function returning the file as text, bytes or parsed JSON (e.g. `fs.readFile`). */
20
+ export function geoLoaderSource(load) {
21
+ return async (key) => {
22
+ const value = await load(key);
23
+ if (value == null)
24
+ return null;
25
+ if (typeof value === "string")
26
+ return JSON.parse(value);
27
+ if (value instanceof ArrayBuffer || value instanceof Uint8Array) {
28
+ return JSON.parse(new TextDecoder().decode(value));
29
+ }
30
+ return value;
31
+ };
32
+ }
33
+ function definedFeature(code, definition, serial) {
34
+ const shape = definition.shape.type === "Feature" ? definition.shape.geometry : definition.shape;
35
+ const feature = definition.shape.type === "Feature" ? definition.shape : null;
36
+ const polygons = shape.type === "Polygon" ? [shape.coordinates] : shape.coordinates;
37
+ let arcIndex = 0;
38
+ /**
39
+ * One ring, wound the way d3 reads it. d3 takes the *inside* of a ring to be
40
+ * the side its points go clockwise around, so an exterior must be small
41
+ * (`geoArea` under a hemisphere) and a hole its complement. GeoJSON (RFC 7946)
42
+ * writes the opposite way round, counter-clockwise exteriors, and a ring
43
+ * taken as written would fill the rest of the sphere; so a ring that reads
44
+ * the wrong way for its place is reversed.
45
+ */
46
+ const toRing = (ring, exterior) => {
47
+ const closed = ring.length > 0 && ring[0][0] === ring[ring.length - 1][0] && ring[0][1] === ring[ring.length - 1][1];
48
+ let coordinates = closed ? ring : [...ring, ring[0]];
49
+ const encloses = geoArea({ type: "Polygon", coordinates: [coordinates] }) <= 2 * Math.PI;
50
+ if (encloses !== exterior)
51
+ coordinates = [...coordinates].reverse();
52
+ const points = new Float64Array(coordinates.length * 2);
53
+ coordinates.forEach(([lon, lat], i) => {
54
+ points[i * 2] = lon;
55
+ points[i * 2 + 1] = lat;
56
+ });
57
+ return { arc: { key: `define:${serial}:${code}:${arcIndex++}`, points, buckets: ringBuckets(points) }, reversed: false };
58
+ };
59
+ const measured = polygons.map((rings) => {
60
+ const resolved = rings.map((ring, i) => [toRing(ring, i === 0)]);
61
+ const ringAreas = rings.map((ring) => {
62
+ const area = geoArea({ type: "Polygon", coordinates: [ring] });
63
+ return area > 2 * Math.PI ? 4 * Math.PI - area : area;
64
+ });
65
+ const area = Math.max(0, ringAreas[0] - ringAreas.slice(1).reduce((a, b) => a + b, 0));
66
+ return { rings: resolved, ringAreas, area, mainland: true };
67
+ });
68
+ const name = definition.name ?? feature?.properties?.name ?? code;
69
+ return {
70
+ code,
71
+ name,
72
+ nameNl: name,
73
+ parent: definition.parent ?? (code.includes("-") ? code.slice(0, 2) : null),
74
+ first: true,
75
+ listed: false,
76
+ remote: false,
77
+ polygons: measured,
78
+ };
79
+ }
80
+ class GeoRegistry {
81
+ _sources = [];
82
+ _defined = new Map();
83
+ _generation = 0;
84
+ _serial = 0;
85
+ /** Bumps whenever a source or a definition is added or removed. */
86
+ get generation() {
87
+ return this._generation;
88
+ }
89
+ get hasSources() {
90
+ return this._sources.length > 0;
91
+ }
92
+ /** Adds a source after every source already registered. Returns its removal. */
93
+ use(source) {
94
+ this._sources.push(source);
95
+ this._generation++;
96
+ return () => {
97
+ const i = this._sources.indexOf(source);
98
+ if (i < 0)
99
+ return;
100
+ this._sources.splice(i, 1);
101
+ this._generation++;
102
+ };
103
+ }
104
+ /**
105
+ * Shapes (GeoJSON, lon/lat) under codes of your choosing, checked before any
106
+ * source. A definition replaces generated data for the same code.
107
+ */
108
+ define(shapes) {
109
+ const serial = ++this._serial;
110
+ const codes = Object.entries(shapes).map(([rawCode, value]) => {
111
+ const code = rawCode.trim().toUpperCase();
112
+ const definition = "shape" in value ? value : { shape: value };
113
+ this._defined.set(code, { serial, feature: definedFeature(code, definition, serial) });
114
+ return code;
115
+ });
116
+ this._generation++;
117
+ return () => {
118
+ for (const code of codes) {
119
+ if (this._defined.get(code)?.serial === serial)
120
+ this._defined.delete(code);
121
+ }
122
+ this._generation++;
123
+ };
124
+ }
125
+ defined(code) {
126
+ return this._defined.get(code)?.feature;
127
+ }
128
+ /** Removes every source and definition — for tests. */
129
+ reset() {
130
+ this._sources = [];
131
+ this._defined.clear();
132
+ this._generation++;
133
+ }
134
+ /**
135
+ * Asks each source in registration order; the first non-null answer wins.
136
+ * Resolves `null` only when every source answered that it has no such file.
137
+ */
138
+ async resolve(key) {
139
+ if (this._sources.length === 0) {
140
+ throw new Error("No geo source registered — call geoRegistry.use(geoUrlSource(…)) before rendering GeoBorder");
141
+ }
142
+ let failure = null;
143
+ for (const source of [...this._sources]) {
144
+ try {
145
+ const value = await source(key);
146
+ if (value != null)
147
+ return value;
148
+ }
149
+ catch (error) {
150
+ failure ??= error;
151
+ }
152
+ }
153
+ if (failure)
154
+ throw failure;
155
+ return null;
156
+ }
157
+ /** Every listed region's code, names and parent, for a picker. */
158
+ async index() {
159
+ return (await this.resolve(`${GEO_DATA_VERSION}/index`));
160
+ }
161
+ }
162
+ export const geoRegistry = new GeoRegistry();
163
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/border/registry.ts"],"names":[],"mappings":"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","sourcesContent":["import { geoArea } from \"d3-geo\"\r\n\r\nimport {\r\n GEO_DATA_FORMAT,\r\n type GeoFeature,\r\n type GeoFileData,\r\n type GeoIndex,\r\n type GeoPolygon,\r\n type GeoRingRef,\r\n} from \"./format\"\r\nimport { ringBuckets } from \"./simplify\"\r\n\r\n/** Prefix every data key carries; bumped with the file format. */\r\nexport const GEO_DATA_VERSION = `v${GEO_DATA_FORMAT}`\r\n\r\n/**\r\n * Answers a data key — `v1/countries/FR`, `v1/states/US`, `v1/index` — with the\r\n * parsed file, or `null` when this source does not have it. A throw means \"could\r\n * not tell\" (offline, a 500) and is retried on the next load.\r\n */\r\nexport type GeoSource = (key: string) => Promise<unknown>\r\n\r\ntype Position = readonly [number, number] | readonly number[]\r\ntype GeoPolygonShape =\r\n | { type: \"Polygon\"; coordinates: readonly (readonly Position[])[] }\r\n | { type: \"MultiPolygon\"; coordinates: readonly (readonly (readonly Position[])[])[] }\r\n/** GeoJSON in lon/lat: a Polygon, a MultiPolygon, or a Feature holding one. */\r\nexport type GeoShape = GeoPolygonShape | { type: \"Feature\"; geometry: GeoPolygonShape; properties?: { name?: string } | null }\r\n\r\nexport interface GeoDefinition {\r\n shape: GeoShape\r\n name?: string\r\n /** The country a subdivision code expands under, when it has one. */\r\n parent?: string\r\n}\r\n\r\n/** Fetches `<base>/<key>.json`; `base` may instead map a key to its URL. */\r\nexport function geoUrlSource(base: string | ((key: string) => string), init?: RequestInit): GeoSource {\r\n return async (key) => {\r\n const url = typeof base === \"function\" ? base(key) : `${base.replace(/\\/+$/, \"\")}/${key}.json`\r\n const response = await fetch(url, init)\r\n // Some object stores answer a missing key with 400, not 404.\r\n if (response.status === 404 || response.status === 400) return null\r\n if (!response.ok) throw new Error(`${url} → HTTP ${response.status}`)\r\n return response.json()\r\n }\r\n}\r\n\r\n/** Wraps a function returning the file as text, bytes or parsed JSON (e.g. `fs.readFile`). */\r\nexport function geoLoaderSource(\r\n load: (key: string) => Promise<string | ArrayBuffer | Uint8Array | object | null | undefined>\r\n): GeoSource {\r\n return async (key) => {\r\n const value = await load(key)\r\n if (value == null) return null\r\n if (typeof value === \"string\") return JSON.parse(value)\r\n if (value instanceof ArrayBuffer || value instanceof Uint8Array) {\r\n return JSON.parse(new TextDecoder().decode(value))\r\n }\r\n return value\r\n }\r\n}\r\n\r\nfunction definedFeature(code: string, definition: GeoDefinition, serial: number): GeoFeature {\r\n const shape = definition.shape.type === \"Feature\" ? definition.shape.geometry : definition.shape\r\n const feature = definition.shape.type === \"Feature\" ? definition.shape : null\r\n const polygons: readonly (readonly (readonly Position[])[])[] =\r\n shape.type === \"Polygon\" ? [shape.coordinates] : shape.coordinates\r\n let arcIndex = 0\r\n\r\n /**\r\n * One ring, wound the way d3 reads it. d3 takes the *inside* of a ring to be\r\n * the side its points go clockwise around, so an exterior must be small\r\n * (`geoArea` under a hemisphere) and a hole its complement. GeoJSON (RFC 7946)\r\n * writes the opposite way round, counter-clockwise exteriors, and a ring\r\n * taken as written would fill the rest of the sphere; so a ring that reads\r\n * the wrong way for its place is reversed.\r\n */\r\n const toRing = (ring: readonly Position[], exterior: boolean): GeoRingRef => {\r\n const closed = ring.length > 0 && ring[0][0] === ring[ring.length - 1][0] && ring[0][1] === ring[ring.length - 1][1]\r\n let coordinates = closed ? ring : [...ring, ring[0]]\r\n const encloses = geoArea({ type: \"Polygon\", coordinates: [coordinates as [number, number][]] }) <= 2 * Math.PI\r\n if (encloses !== exterior) coordinates = [...coordinates].reverse()\r\n const points = new Float64Array(coordinates.length * 2)\r\n coordinates.forEach(([lon, lat], i) => {\r\n points[i * 2] = lon\r\n points[i * 2 + 1] = lat\r\n })\r\n return { arc: { key: `define:${serial}:${code}:${arcIndex++}`, points, buckets: ringBuckets(points) }, reversed: false }\r\n }\r\n\r\n const measured: GeoPolygon[] = polygons.map((rings) => {\r\n const resolved = rings.map((ring, i) => [toRing(ring, i === 0)])\r\n const ringAreas = rings.map((ring) => {\r\n const area = geoArea({ type: \"Polygon\", coordinates: [ring as [number, number][]] })\r\n return area > 2 * Math.PI ? 4 * Math.PI - area : area\r\n })\r\n const area = Math.max(0, ringAreas[0] - ringAreas.slice(1).reduce((a, b) => a + b, 0))\r\n return { rings: resolved, ringAreas, area, mainland: true }\r\n })\r\n\r\n const name = definition.name ?? feature?.properties?.name ?? code\r\n return {\r\n code,\r\n name,\r\n nameNl: name,\r\n parent: definition.parent ?? (code.includes(\"-\") ? code.slice(0, 2) : null),\r\n first: true,\r\n listed: false,\r\n remote: false,\r\n polygons: measured,\r\n }\r\n}\r\n\r\nclass GeoRegistry {\r\n private _sources: GeoSource[] = []\r\n private _defined = new Map<string, { serial: number; feature: GeoFeature }>()\r\n private _generation = 0\r\n private _serial = 0\r\n\r\n /** Bumps whenever a source or a definition is added or removed. */\r\n get generation(): number {\r\n return this._generation\r\n }\r\n\r\n get hasSources(): boolean {\r\n return this._sources.length > 0\r\n }\r\n\r\n /** Adds a source after every source already registered. Returns its removal. */\r\n use(source: GeoSource): () => void {\r\n this._sources.push(source)\r\n this._generation++\r\n return () => {\r\n const i = this._sources.indexOf(source)\r\n if (i < 0) return\r\n this._sources.splice(i, 1)\r\n this._generation++\r\n }\r\n }\r\n\r\n /**\r\n * Shapes (GeoJSON, lon/lat) under codes of your choosing, checked before any\r\n * source. A definition replaces generated data for the same code.\r\n */\r\n define(shapes: Record<string, GeoShape | GeoDefinition>): () => void {\r\n const serial = ++this._serial\r\n const codes = Object.entries(shapes).map(([rawCode, value]) => {\r\n const code = rawCode.trim().toUpperCase()\r\n const definition = \"shape\" in value ? value : { shape: value }\r\n this._defined.set(code, { serial, feature: definedFeature(code, definition, serial) })\r\n return code\r\n })\r\n this._generation++\r\n return () => {\r\n for (const code of codes) {\r\n if (this._defined.get(code)?.serial === serial) this._defined.delete(code)\r\n }\r\n this._generation++\r\n }\r\n }\r\n\r\n defined(code: string): GeoFeature | undefined {\r\n return this._defined.get(code)?.feature\r\n }\r\n\r\n /** Removes every source and definition — for tests. */\r\n reset(): void {\r\n this._sources = []\r\n this._defined.clear()\r\n this._generation++\r\n }\r\n\r\n /**\r\n * Asks each source in registration order; the first non-null answer wins.\r\n * Resolves `null` only when every source answered that it has no such file.\r\n */\r\n async resolve(key: string): Promise<GeoFileData | GeoIndex | null> {\r\n if (this._sources.length === 0) {\r\n throw new Error(\"No geo source registered — call geoRegistry.use(geoUrlSource(…)) before rendering GeoBorder\")\r\n }\r\n let failure: unknown = null\r\n for (const source of [...this._sources]) {\r\n try {\r\n const value = await source(key)\r\n if (value != null) return value as GeoFileData | GeoIndex\r\n } catch (error) {\r\n failure ??= error\r\n }\r\n }\r\n if (failure) throw failure\r\n return null\r\n }\r\n\r\n /** Every listed region's code, names and parent, for a picker. */\r\n async index(): Promise<GeoIndex | null> {\r\n return (await this.resolve(`${GEO_DATA_VERSION}/index`)) as GeoIndex | null\r\n }\r\n}\r\n\r\nexport const geoRegistry = new GeoRegistry()\r\n"]}
@@ -0,0 +1,21 @@
1
+ import type { GeoFeature } from "./format.js";
2
+ export type GeoLevel = "country" | "state";
3
+ export type GeoFrame = "mainland" | "all";
4
+ /** `"fr, de"`, `["FR", "de"]` → `["FR", "DE"]`; unique, in order, empties dropped. */
5
+ export declare function normalizeIso(value: unknown): string[];
6
+ /** Every data file a selection reads, for `declareAssets`. Depends on nothing but its arguments. */
7
+ export declare function geoFilesFor(codes: readonly string[], level: GeoLevel): string[];
8
+ export interface GeoSelection {
9
+ features: GeoFeature[];
10
+ /** A file this selection needs has not landed yet. */
11
+ pending: boolean;
12
+ /** Codes whose file loaded without them. */
13
+ unknown: string[];
14
+ }
15
+ /**
16
+ * The features a selection draws. A bare country code at state level is its
17
+ * first-level subdivisions — minus the remote ones when framing the mainland —
18
+ * or the country itself when it has none.
19
+ */
20
+ export declare function selectGeoFeatures(codes: readonly string[], level: GeoLevel, frame: GeoFrame): GeoSelection;
21
+ //# sourceMappingURL=selection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selection.d.ts","sourceRoot":"","sources":["../../src/border/selection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAI1C,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAA;AAC1C,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,KAAK,CAAA;AAIzC,sFAAsF;AACtF,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CASrD;AAMD,oGAAoG;AACpG,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,QAAQ,GAAG,MAAM,EAAE,CAQ/E;AAED,MAAM,WAAW,YAAY;IACzB,QAAQ,EAAE,UAAU,EAAE,CAAA;IACtB,sDAAsD;IACtD,OAAO,EAAE,OAAO,CAAA;IAChB,4CAA4C;IAC5C,OAAO,EAAE,MAAM,EAAE,CAAA;CACpB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,GAAG,YAAY,CA6C1G"}