@bicharts/chart-host 0.1.7 → 0.1.9

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.
@@ -67,4 +67,4 @@ export {
67
67
  NA_LAT_MAX,
68
68
  clipFeatureToLat
69
69
  };
70
- //# sourceMappingURL=chunk-22B22PJU.mjs.map
70
+ //# sourceMappingURL=chunk-X7PWWEGM.mjs.map
@@ -1,12 +1,8 @@
1
1
  /*! @bicharts/chart-host — Apache-2.0. Bundled reference data: GeoNames (https://www.geonames.org/) CC BY 4.0; Natural Earth and US Census/TIGER (public domain). Full text: NOTICE in this package. */
2
2
  import {
3
- NA_ISO3,
4
- NA_LAT_MAX,
5
- clipFeatureToLat
6
- } from "./chunk-22B22PJU.mjs";
3
+ US_STATES
4
+ } from "./chunk-NWID6YOP.mjs";
7
5
  export {
8
- NA_ISO3,
9
- NA_LAT_MAX,
10
- clipFeatureToLat
6
+ US_STATES
11
7
  };
12
- //# sourceMappingURL=geoNaRegions-SAINMZXG.mjs.map
8
+ //# sourceMappingURL=geo-us-states.mjs.map
@@ -0,0 +1,8 @@
1
+ /*! @bicharts/chart-host — Apache-2.0. Bundled reference data: GeoNames (https://www.geonames.org/) CC BY 4.0; Natural Earth and US Census/TIGER (public domain). Full text: NOTICE in this package. */
2
+ import {
3
+ US_ZIP3
4
+ } from "./chunk-MHDS4Q5G.mjs";
5
+ export {
6
+ US_ZIP3
7
+ };
8
+ //# sourceMappingURL=geo-us-zip3.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "sourcesContent": [],
5
+ "mappings": "",
6
+ "names": []
7
+ }
@@ -0,0 +1,8 @@
1
+ /*! @bicharts/chart-host — Apache-2.0. Bundled reference data: GeoNames (https://www.geonames.org/) CC BY 4.0; Natural Earth and US Census/TIGER (public domain). Full text: NOTICE in this package. */
2
+ import {
3
+ WORLD_110M
4
+ } from "./chunk-23GNNTXQ.mjs";
5
+ export {
6
+ WORLD_110M
7
+ };
8
+ //# sourceMappingURL=geo-world.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "sourcesContent": [],
5
+ "mappings": "",
6
+ "names": []
7
+ }
package/dist/geo.mjs CHANGED
@@ -1,18 +1,18 @@
1
1
  /*! @bicharts/chart-host — Apache-2.0. Bundled reference data: GeoNames (https://www.geonames.org/) CC BY 4.0; Natural Earth and US Census/TIGER (public domain). Full text: NOTICE in this package. */
2
+ import {
3
+ NA_ISO3,
4
+ NA_LAT_MAX,
5
+ clipFeatureToLat
6
+ } from "./chunk-X7PWWEGM.mjs";
7
+ import {
8
+ WORLD_110M
9
+ } from "./chunk-23GNNTXQ.mjs";
2
10
  import {
3
11
  US_STATES
4
12
  } from "./chunk-NWID6YOP.mjs";
5
13
  import {
6
14
  US_ZIP3
7
15
  } from "./chunk-MHDS4Q5G.mjs";
8
- import {
9
- WORLD_110M
10
- } from "./chunk-23GNNTXQ.mjs";
11
- import {
12
- NA_ISO3,
13
- NA_LAT_MAX,
14
- clipFeatureToLat
15
- } from "./chunk-22B22PJU.mjs";
16
16
 
17
17
  // src/geo.ts
18
18
  function geoForKind(geoKind) {
package/dist/index.mjs CHANGED
@@ -25,14 +25,18 @@ import {
25
25
  SELECTION_ACTIVE_CLASS,
26
26
  XFILTER_REFRESH_EVENT,
27
27
  buildRenderPayload,
28
+ clearGeoCache,
28
29
  compileRenderFn,
29
30
  createChartHost,
30
31
  createMarkResolver,
32
+ geoAssetFor,
31
33
  geoFromCache,
32
34
  loadGeo,
33
35
  registerGeo,
36
+ registerGeoAsset,
34
37
  resolveOptions
35
- } from "./chunk-DF5QUB2N.mjs";
38
+ } from "./chunk-3NDJV3DA.mjs";
39
+ import "./chunk-X7PWWEGM.mjs";
36
40
  export {
37
41
  ANIM_MAX_IDEAL_FRAMES_DEFAULT,
38
42
  ANIM_MAX_IDEAL_FRAMES_MAX,
@@ -59,12 +63,15 @@ export {
59
63
  SELECTION_ACTIVE_CLASS,
60
64
  XFILTER_REFRESH_EVENT,
61
65
  buildRenderPayload,
66
+ clearGeoCache,
62
67
  compileRenderFn,
63
68
  createChartHost,
64
69
  createMarkResolver,
70
+ geoAssetFor,
65
71
  geoFromCache,
66
72
  loadGeo,
67
73
  registerGeo,
74
+ registerGeoAsset,
68
75
  resolveOptions
69
76
  };
70
77
  //# sourceMappingURL=index.mjs.map
package/dist/react.mjs CHANGED
@@ -2,7 +2,8 @@
2
2
  import {
3
3
  buildRenderPayload,
4
4
  createChartHost
5
- } from "./chunk-DF5QUB2N.mjs";
5
+ } from "./chunk-3NDJV3DA.mjs";
6
+ import "./chunk-X7PWWEGM.mjs";
6
7
 
7
8
  // src/react.tsx
8
9
  import { createContext, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
@@ -2,6 +2,6 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/react.tsx"],
4
4
  "sourcesContent": ["// React binding for @bicharts/chart-host \u2014 <BicChart> and <BicChartGroup>.\n//\n// This is ~150 lines that every consumer would otherwise write, and get subtly wrong in the\n// same four ways:\n//\n// 1. StrictMode double-mounts effects (React 19, dev). Without destroy() in cleanup an\n// animated chart leaks a running timer per mount \u2014 on every hot reload.\n// 2. Prop changes must not RECOMPILE. `options` -> setOptions (live restyle), `data` ->\n// setData; only new code/module tears down and rebuilds. A naive useEffect([deps])\n// recompiles on every prop change and throws away animation state.\n// 3. d3 must be INJECTED. There is no global in a bundler app, so `d3` is a required prop.\n// 4. The chart OWNS its container's DOM. React must never render children into it.\n//\n// Cross-chart filtering lives in <BicChartGroup> for a reason that is not cosmetic: rowIdx\n// values are positions WITHIN THE PAYLOAD A CHART RECEIVED. Filter the rows for chart B and\n// its payload renumbers from zero, so the same integers now denote different records \u2014\n// silently. The group owns the source table, builds each chart's payload, keeps the\n// payload-row -> source-row map, and translates selections across it. Consumers never see it.\nimport { createContext, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { createChartHost, type ChartHost, type ChartHostConfig } from \"./host\";\nimport type { ResolveOptionsInput } from \"./defaults\";\nimport { buildRenderPayload, type GeoPointBinding } from \"./payload\";\n\nexport interface BicChartProps {\n /** Generated render() source (an ES module's `code` export, or the raw string). */\n code?: string;\n /** Pre-compiled render function \u2014 the alternative to `code`. */\n renderFn?: ChartHostConfig[\"renderFn\"];\n /** The payload: { columns, rows, geoUnmatched?, geoPoint? } \u2014 MCP's data.sample.json verbatim. */\n data?: ChartHostConfig[\"data\"];\n /** Raw options; shared defaults/clamps are applied by resolveOptions. */\n options?: ResolveOptionsInput;\n /** REQUIRED: the d3 v7 namespace. There is no global in a bundled app. */\n d3: any;\n /** Attach the bundled geometry for this kind as options.geo (choropleth or basemap). */\n geoKind?: string;\n /** Identity within a <BicChartGroup> \u2014 the key other charts filter by. */\n id?: string;\n /** Take this group member's selection as a filter on THIS chart's rows. */\n filteredBy?: string;\n /** Selection callback in SOURCE row indices (group) or payload indices (standalone). */\n onSelect?: (rowIdxs: number[]) => void;\n className?: string;\n style?: React.CSSProperties;\n}\n\n// \u2500\u2500 Group coordination \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// ONE active selection for the group, tagged with which chart produced it \u2014 the same\n// model every BI tool uses. Every OTHER chart filters to it; the originating chart does\n// not (it keeps showing all its marks, with the selected ones highlighted, so the user\n// can see what they picked in context and click again to change it). That single rule\n// gives mutual cross-filtering for free: click a bubble and the table filters, click a\n// table row and the map filters, with no possibility of a feedback loop.\ninterface GroupSelection { sourceId: string | null; rows: number[] }\ninterface GroupCtx {\n /** Source rows as objects, shared by every member. */\n rows: Record<string, any>[];\n columns: any[];\n geo?: { column: string; kind: string } | null;\n point?: GeoPointBinding | null;\n /** Publish a member's selection, already translated to SOURCE row indices. */\n publish(id: string, sourceRowIdxs: number[]): void;\n /** The filter `id` should APPLY (null = show everything). Never its own selection. */\n filterFor(id: string | undefined): number[] | null;\n /** The whole group's active selection, whoever produced it. */\n selection: GroupSelection;\n clear(): void;\n}\nconst Ctx = createContext<GroupCtx | null>(null);\n\n/** Read the group's selection from a page \u2014 for a \"clear\" button or a count. */\nexport function useBicSelection() {\n const g = useContext(Ctx);\n return {\n rows: g?.selection.rows ?? [],\n sourceId: g?.selection.sourceId ?? null,\n clear: () => g?.clear(),\n };\n}\n\nexport interface BicChartGroupProps {\n /** The ONE source table. Every member's payload is derived from it. */\n rows: Record<string, any>[];\n columns: any[];\n /** Choropleth join binding, applied when building each member's payload. */\n geo?: { column: string; kind: string } | null;\n /** Point-map geocoding binding (city/state/zip/lat/lon column names). */\n point?: GeoPointBinding | null;\n children: ReactNode;\n}\n\n/**\n * Owns the source table and the selection bus. Members declare `id` and optionally\n * `filteredBy`; the group re-derives the filtered member's payload and translates row\n * indices in both directions, so a click in one chart filters another CORRECTLY.\n */\nexport function BicChartGroup({ rows, columns, geo, point, children }: BicChartGroupProps) {\n const [sel, setSel] = useState<GroupSelection>({ sourceId: null, rows: [] });\n const value = useMemo<GroupCtx>(() => ({\n rows, columns, geo, point,\n selection: sel,\n publish: (id, sourceRowIdxs) =>\n setSel(sourceRowIdxs.length ? { sourceId: id, rows: sourceRowIdxs }\n : { sourceId: null, rows: [] }),\n // A chart never filters itself \u2014 that is what keeps the gesture reversible:\n // the origin chart still shows every mark, so there is always something left\n // to click to change or clear the selection.\n filterFor: (id) => (sel.rows.length && sel.sourceId && sel.sourceId !== id) ? sel.rows : null,\n clear: () => setSel({ sourceId: null, rows: [] }),\n }), [rows, columns, geo, point, sel]);\n return <Ctx.Provider value={value}>{children}</Ctx.Provider>;\n}\n\n/** Build a payload for a subset of source rows, keeping the payload->source index map. */\nfunction payloadFor(g: GroupCtx, sourceIdxs: number[] | null) {\n const idxs = sourceIdxs ?? g.rows.map((_, i) => i);\n const subset = idxs.map(i => g.rows[i]);\n const p = buildRenderPayload(g.columns, subset, g.geo ?? undefined, g.point ?? undefined);\n // p.rows[k] corresponds to source row idxs[k]. __rowIdx__ inside the payload was\n // re-based to 0..n-1 by the builder \u2014 THIS map is what makes the indices comparable\n // across charts, and it is exactly what a hand-rolled integration forgets.\n return { payload: p, rowMap: idxs };\n}\n\nexport function BicChart(props: BicChartProps) {\n const { code, renderFn, options, d3, geoKind, id, filteredBy, onSelect, className, style } = props;\n const ref = useRef<HTMLDivElement | null>(null);\n const hostRef = useRef<ChartHost | null>(null);\n const rowMapRef = useRef<number[] | null>(null);\n const group = useContext(Ctx);\n\n // Resolve this chart's payload: from the group (filtered + mapped) or the raw prop.\n // `filteredBy` narrows this to ONE partner when a page wants explicit one-way wiring;\n // omit it and the chart responds to whichever sibling published \u2014 mutual by default.\n const active = group ? group.selection : null;\n const filterSel = !group ? null\n : (filteredBy ? (active!.sourceId === filteredBy ? group.filterFor(id) : null)\n : group.filterFor(id));\n const built = useMemo(() => {\n if (!group) return null;\n return payloadFor(group, filterSel);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [group, filterSel && filterSel.join(\",\")]);\n const data = built ? built.payload : props.data;\n rowMapRef.current = built ? built.rowMap : null;\n\n // Keep the newest callback without making it a rebuild trigger.\n const onSelectRef = useRef(onSelect);\n onSelectRef.current = onSelect;\n\n // BUILD/TEARDOWN \u2014 only when the code identity changes. useLayoutEffect so the chart\n // paints before the browser does, avoiding a flash of empty container.\n useLayoutEffect(() => {\n const el = ref.current;\n if (!el || (!code && !renderFn) || !data) return;\n const host = createChartHost(el, { code, renderFn, data, options, d3, geoKind });\n hostRef.current = host;\n const off = host.selection.onChange((payloadIdxs, source) => {\n // \"host\" = a programmatic clear WE issued (below) to drop a stale highlight.\n // Publishing it would overwrite the selection another chart just made \u2014 the\n // feedback loop that makes mutual cross-filtering fight itself.\n if (source === \"host\") return;\n const map = rowMapRef.current;\n // Translate to SOURCE indices before anything leaves this chart.\n const sourceIdxs = map ? payloadIdxs.map(i => map[i]).filter(i => i !== undefined) : payloadIdxs;\n if (group && id) group.publish(id, sourceIdxs);\n onSelectRef.current?.(sourceIdxs);\n });\n host.render();\n return () => {\n // StrictMode double-mount and every unmount land here: stop the timer, drop the\n // listeners, clear the DOM. Skipping this is the animated-chart leak.\n off();\n host.destroy();\n hostRef.current = null;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [code, renderFn, d3, geoKind]);\n\n // LIVE RESTYLE \u2014 options change without recompiling (colour scale, aggregation,\n // animMaxIdealFrames, maxMapPoints\u2026). This is the whole point of setOptions.\n const optKey = useMemo(() => JSON.stringify(options ?? {}), [options]);\n useEffect(() => {\n if (hostRef.current && options) hostRef.current.setOptions(options);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [optKey]);\n\n // DATA change (including a cross-filter re-derive) \u2014 repaint, never recompile.\n useEffect(() => {\n if (hostRef.current && data) hostRef.current.setData(data);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [data]);\n\n // Drop a STALE highlight: once the group's selection belongs to someone else (or was\n // cleared), this chart must stop showing its own marks as selected. Without it a\n // \"Clear\" button empties the filter while the origin chart stays visibly dimmed.\n useEffect(() => {\n const host = hostRef.current;\n if (!host || !group) return;\n const mine = group.selection.sourceId === id && group.selection.rows.length > 0;\n if (!mine && host.selection.current && host.selection.current.length) host.selection.clear();\n }, [group?.selection, id, group]);\n\n // No children: the chart owns this element's contents.\n return <div ref={ref} className={className} style={style} />;\n}\n"],
5
- "mappings": "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",
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1 @@
1
+ export { US_STATES } from "./geoUsStates.generated";
@@ -0,0 +1 @@
1
+ export { US_ZIP3 } from "./geoUsZip3.generated";
@@ -0,0 +1 @@
1
+ export { WORLD_110M } from "./geoWorld110m.generated";
@@ -1,3 +1,7 @@
1
+ /** The generated assets, as distinct from the many geoKinds that route to them. */
2
+ export type GeoAssetName = "world" | "us-states" | "us-zip3";
3
+ /** Normalise a server geoKind to the ASSET it needs — the one place that mapping lives. */
4
+ export declare function geoAssetFor(geoKind: string | null | undefined): GeoAssetName | null;
1
5
  /**
2
6
  * Load (and cache) the geometry for a geoKind. Per-asset dynamic import: requesting a US
3
7
  * state map never downloads the 810 KB zip3 asset. Resolves to undefined for an unknown
@@ -5,8 +9,25 @@
5
9
  */
6
10
  export declare function loadGeo(geoKind: string | null | undefined): Promise<any | undefined>;
7
11
  /** Synchronous cache read — what createChartHost uses, so render() stays sync. Returns
8
- * undefined until loadGeo() has resolved for this kind (or a provider supplied it). */
12
+ * undefined until the geometry has arrived by any of the three routes above. */
9
13
  export declare function geoFromCache(geoKind: string | null | undefined): any | undefined;
10
- /** Seed the cache from geometry the caller already holds — e.g. the MCP's data.geo.json,
11
- * or the sync geoForKind from the "@bicharts/chart-host/geo" subpath. */
14
+ /** Seed the cache for ONE EXACT geoKind from geometry the caller already holds — e.g. the
15
+ * MCP's data.geo.json, or the sync geoForKind from the "@bicharts/chart-host/geo" subpath. */
12
16
  export declare function registerGeo(geoKind: string, geo: any): void;
17
+ /**
18
+ * Seed the cache for an ASSET, serving every geoKind that routes to it — including the
19
+ * derived North America basemap once the world asset lands. This is the seam for a host that
20
+ * bundles some assets and fetches others: pass `WORLD_110M` from
21
+ * "@bicharts/chart-host/geo/world", or a JSON body parsed off your own CDN. The geometry must
22
+ * have the shape the generated asset has — a GeoJSON FeatureCollection whose feature.id is the
23
+ * join key — because generated code binds __geoIso__ against feature.id.
24
+ */
25
+ export declare function registerGeoAsset(asset: GeoAssetName, geo: any): void;
26
+ /**
27
+ * Drop every cached FeatureCollection, by kind and by asset. The cache is module-level and
28
+ * lives as long as the page, which is what a host wants while maps are on screen — this is
29
+ * the way back out: release ~1 MB when they are not, force a re-fetch of an asset that has
30
+ * been republished, or start a test from a cold cache. Bundled assets seeded via
31
+ * registerGeoAsset need re-seeding afterwards; loadGeo re-imports on its own.
32
+ */
33
+ export declare function clearGeoCache(): void;
@@ -1,6 +1,6 @@
1
1
  export * from "./contract";
2
2
  export { resolveOptions, type ResolveOptionsInput } from "./defaults";
3
- export { loadGeo, geoFromCache, registerGeo } from "./geoLazy";
3
+ export { loadGeo, geoFromCache, registerGeo, registerGeoAsset, geoAssetFor, clearGeoCache, type GeoAssetName, } from "./geoLazy";
4
4
  export { buildRenderPayload, type RenderPayload, type GeoPointBinding } from "./payload";
5
5
  export { createChartHost, compileRenderFn, type ChartHost, type ChartHostConfig, type RenderFn } from "./host";
6
6
  export { createMarkResolver, type MarkResolver, type MarkResolverEnv } from "./selection";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bicharts/chart-host",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "Run a BIC-generated D3 chart in any web host: compiles the generated render() function, applies the shared option defaults, resolves mark clicks (through tooltip overlays), owns the selection affordance, and translates row indices between cross-filtered charts. The same contract the BIC Power BI visual implements, minus Power BI. React bindings at @bicharts/chart-host/react.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -24,6 +24,21 @@
24
24
  "import": "./dist/geo.mjs",
25
25
  "default": "./dist/geo.mjs"
26
26
  },
27
+ "./geo/world": {
28
+ "types": "./dist/types/geo-world.d.ts",
29
+ "import": "./dist/geo-world.mjs",
30
+ "default": "./dist/geo-world.mjs"
31
+ },
32
+ "./geo/us-states": {
33
+ "types": "./dist/types/geo-us-states.d.ts",
34
+ "import": "./dist/geo-us-states.mjs",
35
+ "default": "./dist/geo-us-states.mjs"
36
+ },
37
+ "./geo/us-zip3": {
38
+ "types": "./dist/types/geo-us-zip3.d.ts",
39
+ "import": "./dist/geo-us-zip3.mjs",
40
+ "default": "./dist/geo-us-zip3.mjs"
41
+ },
27
42
  "./package.json": "./package.json"
28
43
  },
29
44
  "files": [