@bicharts/chart-host 0.1.13 → 0.1.14

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.
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/geoNaRegions.ts"],
4
- "sourcesContent": ["// What DEFINES the North America basemap: which regions belong on it, how far north it\n// extends, and the pure geometry op that enforces that. No asset imports \u2014 geo.ts statically\n// pulls ~1.3 MB of generated geometry, so anything that only needs these decisions (tests,\n// tooling, future callers) shouldn't have to load the world to read them.\n\n// GREENLAND (\"GRL\") IS DELIBERATELY ABSENT (2026-07-25). It is geographically North\n// American, but it is an enormous and almost always data-less slab, and the NA point-map\n// archetype fitExtent()s to this basemap's FULL extent \u2014 so including it stretched the fit\n// ~40 degrees further east (basemap lon max -12.2 with it, -52.6 without) and squeezed the\n// actual continent. This affects ONLY the basemap: WORLD_110M is untouched, so GRL remains\n// a perfectly good joinable region on the world choropleths, which is where a Greenland\n// data point belongs. Do not \"fix\" this by adding GRL back.\nexport const NA_ISO3 = new Set([\n \"USA\", \"CAN\", \"MEX\", // continental\n \"GTM\", \"BLZ\", \"SLV\", \"HND\", \"NIC\", \"CRI\", \"PAN\", // Central America\n \"CUB\", \"JAM\", \"HTI\", \"DOM\", \"BHS\", \"PRI\", \"TTO\", // Greater Antilles + Bahamas\n]);\n\n// NORTHERN CUTOFF (2026-07-25). Dropping Greenland reclaimed the eastern half of the\n// frame but barely moved the TOP edge \u2014 Canada's Ellesmere/Axel Heiberg islands already reach\n// ~83\u00B0N, so the map still spent its height on empty Arctic. 75\u00B0N keeps every populated region\n// (Alaska's north coast ~71\u00B0N, Canadian mainland ~72\u00B0N) and cuts the uninhabited island bulk.\n// Safe against geoNaturalEarth1 specifically: it is PSEUDOCYLINDRICAL, so parallels project to\n// straight horizontal lines and a constant-latitude cut renders as an exactly straight edge \u2014\n// no densification needed along the seam.\nexport const NA_LAT_MAX = 75;\n\n// Sutherland\u2013Hodgman against the single half-plane lat <= latMax. Exact in lon/lat space\n// (the boundary is a parallel, i.e. a straight line there), so the only approximation is the\n// projection's own, which for this projection family is none along a parallel.\nfunction clipRingToLat(ring: number[][], latMax: number): number[][] {\n const out: number[][] = [];\n const n = ring.length;\n for (let i = 0; i < n; i++) {\n const cur = ring[i];\n const prev = ring[(i + n - 1) % n];\n const curIn = cur[1] <= latMax;\n const prevIn = prev[1] <= latMax;\n if (curIn !== prevIn) {\n // Crossing: emit the point exactly on the parallel.\n const dy = cur[1] - prev[1];\n const t = dy === 0 ? 0 : (latMax - prev[1]) / dy;\n out.push([prev[0] + t * (cur[0] - prev[0]), latMax]);\n }\n if (curIn) out.push(cur);\n }\n if (out.length && (out[0][0] !== out[out.length - 1][0] || out[0][1] !== out[out.length - 1][1])) {\n out.push(out[0]); // keep the ring closed\n }\n return out;\n}\n\n// Returns the feature clipped to lat <= latMax, or null when nothing survives (a region\n// entirely above the cutoff simply leaves the basemap). Non-polygon geometry passes through\n// untouched \u2014 the NA basemap is polygons only, but this must not silently mangle anything else.\nexport function clipFeatureToLat(feature: any, latMax: number): any | null {\n const g = feature && feature.geometry;\n if (!g) return null;\n\n const clipPolygon = (rings: number[][][]): number[][][] | null => {\n const kept = rings\n .map(r => clipRingToLat(r, latMax))\n .filter(r => r.length >= 4); // a closed ring needs 3 distinct points + the repeat\n // If the OUTER ring is gone the whole polygon is gone, holes included.\n return kept.length && kept[0].length >= 4 ? kept : null;\n };\n\n if (g.type === \"Polygon\") {\n const c = clipPolygon(g.coordinates as number[][][]);\n return c ? { ...feature, geometry: { type: \"Polygon\", coordinates: c } } : null;\n }\n if (g.type === \"MultiPolygon\") {\n const polys = (g.coordinates as number[][][][])\n .map(clipPolygon)\n .filter((p): p is number[][][] => p !== null);\n return polys.length ? { ...feature, geometry: { type: \"MultiPolygon\", coordinates: polys } } : null;\n }\n return feature;\n}\n"],
5
- "mappings": ";;;AAYO,IAAM,UAAU,oBAAI,IAAI;AAAA,EAC3B;AAAA,EAAO;AAAA,EAAO;AAAA;AAAA,EACd;AAAA,EAAO;AAAA,EAAO;AAAA,EAAO;AAAA,EAAO;AAAA,EAAO;AAAA,EAAO;AAAA;AAAA,EAC1C;AAAA,EAAO;AAAA,EAAO;AAAA,EAAO;AAAA,EAAO;AAAA,EAAO;AAAA,EAAO;AAAA;AAC9C,CAAC;AASM,IAAM,aAAa;AAK1B,SAAS,cAAc,MAAkB,QAA4B;AACjE,QAAM,MAAkB,CAAC;AACzB,QAAM,IAAI,KAAK;AACf,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AACxB,UAAM,MAAM,KAAK,CAAC;AAClB,UAAM,OAAO,MAAM,IAAI,IAAI,KAAK,CAAC;AACjC,UAAM,QAAQ,IAAI,CAAC,KAAK;AACxB,UAAM,SAAS,KAAK,CAAC,KAAK;AAC1B,QAAI,UAAU,QAAQ;AAElB,YAAM,KAAK,IAAI,CAAC,IAAI,KAAK,CAAC;AAC1B,YAAM,IAAI,OAAO,IAAI,KAAK,SAAS,KAAK,CAAC,KAAK;AAC9C,UAAI,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,CAAC,IAAI,MAAM,CAAC;AAAA,IACvD;AACA,QAAI,MAAO,KAAI,KAAK,GAAG;AAAA,EAC3B;AACA,MAAI,IAAI,WAAW,IAAI,CAAC,EAAE,CAAC,MAAM,IAAI,IAAI,SAAS,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC,EAAE,CAAC,MAAM,IAAI,IAAI,SAAS,CAAC,EAAE,CAAC,IAAI;AAC9F,QAAI,KAAK,IAAI,CAAC,CAAC;AAAA,EACnB;AACA,SAAO;AACX;AAKO,SAAS,iBAAiB,SAAc,QAA4B;AACvE,QAAM,IAAI,WAAW,QAAQ;AAC7B,MAAI,CAAC,EAAG,QAAO;AAEf,QAAM,cAAc,CAAC,UAA6C;AAC9D,UAAM,OAAO,MACR,IAAI,OAAK,cAAc,GAAG,MAAM,CAAC,EACjC,OAAO,OAAK,EAAE,UAAU,CAAC;AAE9B,WAAO,KAAK,UAAU,KAAK,CAAC,EAAE,UAAU,IAAI,OAAO;AAAA,EACvD;AAEA,MAAI,EAAE,SAAS,WAAW;AACtB,UAAM,IAAI,YAAY,EAAE,WAA2B;AACnD,WAAO,IAAI,EAAE,GAAG,SAAS,UAAU,EAAE,MAAM,WAAW,aAAa,EAAE,EAAE,IAAI;AAAA,EAC/E;AACA,MAAI,EAAE,SAAS,gBAAgB;AAC3B,UAAM,QAAS,EAAE,YACZ,IAAI,WAAW,EACf,OAAO,CAAC,MAAyB,MAAM,IAAI;AAChD,WAAO,MAAM,SAAS,EAAE,GAAG,SAAS,UAAU,EAAE,MAAM,gBAAgB,aAAa,MAAM,EAAE,IAAI;AAAA,EACnG;AACA,SAAO;AACX;",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": [],
4
- "sourcesContent": [],
5
- "mappings": "",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": [],
4
- "sourcesContent": [],
5
- "mappings": "",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": [],
4
- "sourcesContent": [],
5
- "mappings": "",
6
- "names": []
7
- }
package/dist/geo.mjs.map DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/geo.ts"],
4
- "sourcesContent": ["import { WORLD_110M } from \"./geoWorld110m.generated\";\nimport { US_STATES } from \"./geoUsStates.generated\";\nimport { US_ZIP3 } from \"./geoUsZip3.generated\";\nimport { NA_ISO3, NA_LAT_MAX, clipFeatureToLat } from \"./geoNaRegions\";\n\n// Geometry the D3 choropleth lanes hand to generated code as `options.geo`\n// (2026-07-22 \u2014 bundled, not fetched: each asset is well under ~180 KB gzipped,\n// so it rides the visual, needs no /geo/ hosting, and renders offline/air-gapped).\n// Moved into @bicharts/chart-host (Phase B) so the Power BI visual AND the MCP client share\n// ONE copy \u2014 MCP no longer reaches into the visual's src/. Keyed by the server-supplied\n// geoKind \u2192 the FeatureCollection whose feature.id is the join key generated code binds\n// against __geoIso__:\n// country-* \u2192 WORLD_110M (feature.id = ISO 3166-1 alpha-3)\n// us-state-code|name \u2192 US_STATES (feature.id = USPS, e.g. \"CA\")\n// us-zip5 \u2192 US_ZIP3 (feature.id = 3-digit prefix; the archetype\n// joins __geoIso__.slice(0,3) == feature.id)\n// County / other assets slot in here (own generated modules) as those lanes land.\nexport function geoForKind(geoKind: string | null | undefined): any | undefined {\n if (!geoKind) return undefined;\n const k = geoKind.toLowerCase();\n if (/^country/.test(k)) return WORLD_110M;\n if (k === \"us-state-code\" || k === \"us-state-name\") return US_STATES;\n if (k === \"us-zip5\") return US_ZIP3;\n if (k === \"north-america\") return northAmerica();\n return undefined;\n}\n\n// North America BASEMAP for point-map (lat/lon) types \u2014 e.g. North America (Bubbles).\n// Not a join target (no __geoIso__): pure grey context polygons. Filtered from the\n// already-bundled world asset at runtime (zero extra bundle bytes); polygons only \u2014\n// the world asset's centroid Point features (micro-island hubs) are join aids for the\n// choropleth and would just clutter a context map. Cached after first build. The\n// server routes this via LLMChartType.GeoAssetKind -> res.GeoKind = \"north-america\".\n// Membership (and the Greenland exclusion + its rationale) lives in geoNaRegions.ts so it can\n// be read without pulling this module's ~1.3 MB of generated geometry. Re-exported for callers\n// that already hold a geo.ts import.\nexport { NA_ISO3 };\nlet _na: any | undefined;\nfunction northAmerica(): any {\n if (!_na) {\n // Membership filter, then the northern cutoff. The archetype fitExtent()s to this\n // collection, so clipping the geometry (rather than only the fit) is what actually\n // reclaims the frame: land above the cutoff is gone, so it can neither drive the fit\n // nor spill over the top of the plot area into the header strip.\n _na = {\n type: \"FeatureCollection\",\n features: (WORLD_110M.features as any[])\n .filter((f: any) => NA_ISO3.has(f?.id) && f?.geometry && f.geometry.type !== \"Point\")\n .map((f: any) => clipFeatureToLat(f, NA_LAT_MAX))\n .filter((f: any) => f !== null),\n };\n }\n return _na;\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;AAiBO,SAAS,WAAW,SAAqD;AAC5E,MAAI,CAAC,QAAS,QAAO;AACrB,QAAM,IAAI,QAAQ,YAAY;AAC9B,MAAI,WAAW,KAAK,CAAC,EAAG,QAAO;AAC/B,MAAI,MAAM,mBAAmB,MAAM,gBAAiB,QAAO;AAC3D,MAAI,MAAM,UAAW,QAAO;AAC5B,MAAI,MAAM,gBAAiB,QAAO,aAAa;AAC/C,SAAO;AACX;AAYA,IAAI;AACJ,SAAS,eAAoB;AACzB,MAAI,CAAC,KAAK;AAKN,UAAM;AAAA,MACF,MAAM;AAAA,MACN,UAAW,WAAW,SACjB,OAAO,CAAC,MAAW,QAAQ,IAAI,GAAG,EAAE,KAAK,GAAG,YAAY,EAAE,SAAS,SAAS,OAAO,EACnF,IAAI,CAAC,MAAW,iBAAiB,GAAG,UAAU,CAAC,EAC/C,OAAO,CAAC,MAAW,MAAM,IAAI;AAAA,IACtC;AAAA,EACJ;AACA,SAAO;AACX;",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": [],
4
- "sourcesContent": [],
5
- "mappings": "",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": [],
4
- "sourcesContent": [],
5
- "mappings": "",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": [],
4
- "sourcesContent": [],
5
- "mappings": "",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": [],
4
- "sourcesContent": [],
5
- "mappings": "",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/react.tsx"],
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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",
6
- "names": []
7
- }