@bicharts/chart-host 0.6.1 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,16 +2,15 @@
2
2
 
3
3
  > **Make Generative AI for Charts *Better*.**
4
4
 
5
- That is what **RegiaBI** is for; this package is the part that runs the result in your page,
6
- so a generated chart behaves the same wherever it lands.
5
+ Describe the chart you want, or just hand over the data, and RegiaBI gives you back a working, interactive chart that fits your data on the first try — as source code you own. It goes into your repo and runs in the framework you already use: React, a plain web page, or whatever your coding agent is scaffolding. At run time there's no key, no call to us and nothing to pay per render: `@bicharts/chart-host`, the open-source runtime, makes the chart behave in your page — clicks, cross-filtering, selection — so that's code you don't have to write. You start from something that already works and spend your time on the last ten percent, in plain language or in the code itself; reading the code is an advantage, never the price of entry. And because the engine knows what each chart type can honestly say, it'll sometimes show you a view of your data you hadn't thought to ask for.
7
6
 
8
- Run a D3 chart generated by
9
- [Business Intelligence Champions](https://bizintelligencechampions.com) (BIC) in any web page.
7
+ **[Live demo](https://codexguy.github.io/bicharts-react-demo/)** ·
8
+ [RegiaBI for developers](https://bizintelligencechampions.com/regiabi/developers?loc=npmhost)
10
9
 
11
- A BIC chart is *generated source you own* — a plain `render(container, data, options)` function
12
- you commit to your repo. There is no API key at run time, no per-render cost, and no network
13
- call. This package is the host side: the ~80 lines every integrator would otherwise write, and
14
- the handful they would get subtly wrong.
10
+ This package is the runtime: it makes the chart you were handed behave in your page. A
11
+ generated chart is a plain `render(container, data, options)` function you commit to your repo,
12
+ and this is the host side — the ~80 lines every integrator would otherwise write, and the
13
+ handful they would get subtly wrong.
15
14
 
16
15
  It is the same contract the BIC Power BI visual implements, minus Power BI — so a chart looks
17
16
  and behaves the same wherever it runs.
@@ -435,12 +435,13 @@ var require_papaparse_min = __commonJS({
435
435
  });
436
436
 
437
437
  // src/contract.ts
438
- var HOST_CONTRACT_VERSION = "1.11.0";
438
+ var HOST_CONTRACT_VERSION = "1.12.0";
439
439
  var GEO_POINT_PRECISIONS = ["latlon", "city", "zip3", "state", "country"];
440
440
  var MARK_CLASS = "d3-mark";
441
441
  var LEGEND_MARK_CLASS = "d3-legend-mark";
442
442
  var AXIS_FILTER_CLASS = "d3-axis-filter";
443
443
  var LIFT_SELECTED_CLASS = "d3-lift-selected";
444
+ var CONTROL_CLASS = "lch-control";
444
445
  var ROW_IDX_ATTR = "data-row-idx";
445
446
  var XFILTER_REFRESH_EVENT = "llm-xfilter-refresh";
446
447
  var CONTAINER_SLOT_ANIM_STOP = "__llmAnimStop";
@@ -1992,6 +1993,15 @@ function stripJsComments(code) {
1992
1993
  }
1993
1994
 
1994
1995
  // src/selection.ts
1996
+ function isInsideControl(target, container) {
1997
+ let el = target;
1998
+ if (el && el.nodeType !== 1) el = el.parentElement ?? el.parentNode ?? null;
1999
+ while (el && el !== container) {
2000
+ if (el.nodeType === 1 && el.classList?.contains?.(CONTROL_CLASS)) return true;
2001
+ el = el.parentElement ?? el.parentNode ?? null;
2002
+ }
2003
+ return false;
2004
+ }
1995
2005
  function createMarkResolver(env) {
1996
2006
  const { root, doc, log } = env;
1997
2007
  const isElement = (t) => {
@@ -3555,6 +3565,7 @@ function createChartHost(container, config) {
3555
3565
  const clickSel = `.${MARK_CLASS}[${ROW_IDX_ATTR}], .${LEGEND_MARK_CLASS}[${ROW_IDX_ATTR}], .${AXIS_FILTER_CLASS}[${ROW_IDX_ATTR}]`;
3556
3566
  const onClick = (e) => {
3557
3567
  if (Date.now() - xfAt < XF_ECHO_MS) return;
3568
+ if (isInsideControl(e?.target, container)) return;
3558
3569
  let el = resolver.findMark(e?.target, clickSel, e);
3559
3570
  if (!el) el = resolver.penetrateOverlayAt(e?.clientX, e?.clientY, clickSel);
3560
3571
  if (!el) el = resolver.resolveByGeometry(e?.clientX, e?.clientY, clickSel);
@@ -3812,6 +3823,7 @@ export {
3812
3823
  LEGEND_MARK_CLASS,
3813
3824
  AXIS_FILTER_CLASS,
3814
3825
  LIFT_SELECTED_CLASS,
3826
+ CONTROL_CLASS,
3815
3827
  ROW_IDX_ATTR,
3816
3828
  XFILTER_REFRESH_EVENT,
3817
3829
  CONTAINER_SLOT_ANIM_STOP,
@@ -3872,6 +3884,7 @@ export {
3872
3884
  Jt,
3873
3885
  buildRenderPayload,
3874
3886
  stripJsComments,
3887
+ isInsideControl,
3875
3888
  createMarkResolver,
3876
3889
  ensureCrossfilterHitTargets,
3877
3890
  censusMarks,
package/dist/index.mjs CHANGED
@@ -27,6 +27,7 @@ import {
27
27
  CONTAINER_SLOT_INITIAL_XF_MARK,
28
28
  CONTAINER_SLOT_UI_STATE,
29
29
  CONTAINER_SLOT_XF_CLEAR,
30
+ CONTROL_CLASS,
30
31
  DARK_TEXT,
31
32
  DIM_OPACITY_DEFAULT,
32
33
  DIM_OPACITY_VAR,
@@ -105,6 +106,7 @@ import {
105
106
  invalidSentinelReason,
106
107
  isBlankRender,
107
108
  isHorizontalLabelRow,
109
+ isInsideControl,
108
110
  isInvalidSentinelError,
109
111
  isPhantomBox,
110
112
  isPillBackdropAlpha,
@@ -133,7 +135,7 @@ import {
133
135
  unpinScrolledAxis,
134
136
  valuePlacementFlag,
135
137
  withoutViewOnlyKeys
136
- } from "./chunk-RO6O22YG.mjs";
138
+ } from "./chunk-HC2IREJL.mjs";
137
139
  import "./chunk-A2GMXZP7.mjs";
138
140
  import "./chunk-GHODWOAL.mjs";
139
141
 
@@ -2438,6 +2440,7 @@ export {
2438
2440
  CONTAINER_SLOT_INITIAL_XF_MARK,
2439
2441
  CONTAINER_SLOT_UI_STATE,
2440
2442
  CONTAINER_SLOT_XF_CLEAR,
2443
+ CONTROL_CLASS,
2441
2444
  DARK_TEXT,
2442
2445
  DIM_OPACITY_DEFAULT,
2443
2446
  DIM_OPACITY_VAR,
@@ -2556,6 +2559,7 @@ export {
2556
2559
  isBlindMarker,
2557
2560
  isExcelDateFormat,
2558
2561
  isHorizontalLabelRow,
2562
+ isInsideControl,
2559
2563
  isInvalidSentinelError,
2560
2564
  isPhantomBox,
2561
2565
  isPillBackdropAlpha,
package/dist/react.mjs CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  createChartHost,
5
5
  geoFromCache,
6
6
  loadGeo
7
- } from "./chunk-RO6O22YG.mjs";
7
+ } from "./chunk-HC2IREJL.mjs";
8
8
  import "./chunk-A2GMXZP7.mjs";
9
9
  import "./chunk-GHODWOAL.mjs";
10
10
 
@@ -1,4 +1,4 @@
1
- export declare const HOST_CONTRACT_VERSION = "1.11.0";
1
+ export declare const HOST_CONTRACT_VERSION = "1.12.0";
2
2
  export type GeoPointPrecision = "latlon" | "city" | "zip3" | "state" | "country";
3
3
  /** Every valid tier, ordered most precise → coarsest. Runtime form of GeoPointPrecision. */
4
4
  export declare const GEO_POINT_PRECISIONS: readonly GeoPointPrecision[];
@@ -11,6 +11,7 @@ export declare const MARK_CLASS = "d3-mark";
11
11
  export declare const LEGEND_MARK_CLASS = "d3-legend-mark";
12
12
  export declare const AXIS_FILTER_CLASS = "d3-axis-filter";
13
13
  export declare const LIFT_SELECTED_CLASS = "d3-lift-selected";
14
+ export declare const CONTROL_CLASS = "lch-control";
14
15
  export declare const ROW_IDX_ATTR = "data-row-idx";
15
16
  export declare const XFILTER_REFRESH_EVENT = "llm-xfilter-refresh";
16
17
  export declare const CONTAINER_SLOT_ANIM_STOP = "__llmAnimStop";
@@ -1,4 +1,4 @@
1
- export { HOST_CONTRACT_VERSION, GEO_POINT_PRECISIONS, MARK_CLASS, LEGEND_MARK_CLASS, AXIS_FILTER_CLASS, ROW_IDX_ATTR, LIFT_SELECTED_CLASS, XFILTER_REFRESH_EVENT, CONTAINER_SLOT_ANIM_STOP, CONTAINER_SLOT_XF_CLEAR, CONTAINER_SLOT_INITIAL_XF_MARK, CONTAINER_SLOT_UI_STATE, VIEW_ONLY_UI_STATE_KEYS, withoutViewOnlyKeys, HOST_CONTAINER_CLASS, SELECTION_ACTIVE_CLASS, MARK_SELECTED_CLASS, ACTIVE_TICK_CLASS, DIM_OPACITY_VAR, DIM_OPACITY_DEFAULT, chartOwnsTimeline, periodTickSuppressesFeedback, ANIM_PLAY_SPEED_DEFAULT, ANIM_PLAY_SPEED_MIN, ANIM_PLAY_SPEED_MAX, ANIM_LOOP_DELAY_DEFAULT, ANIM_LOOP_DELAY_MIN, ANIM_MAX_IDEAL_FRAMES_DEFAULT, ANIM_MAX_IDEAL_FRAMES_MIN, ANIM_MAX_IDEAL_FRAMES_MAX, ANIMATION_OPTION_KEYS, COLOR_SCALE_SELF_CLAMP_PCT_DEFAULT, COLOR_SCALE_SELF_CLAMP_PCT_MIN, COLOR_SCALE_SELF_CLAMP_PCT_MAX, FLIP_MODE_DEFAULT, APPROXIMATE_POSITIONS_DEFAULT, VALUE_AXIS_BASELINE_DEFAULT, SEASONAL_MARKERS_DEFAULT, MAX_MAP_POINTS_DEFAULT, type GeoPointPrecision, type GeoMapKind, type TimelineStyle, type FlipMode, type ApproximatePositions, type ValueAxisBaseline, type SeasonalMarkers, type ColorScaleScope, type RenderOptions, type ViewStateProvider, type ChartControlChange, } from "./contract";
1
+ export { HOST_CONTRACT_VERSION, GEO_POINT_PRECISIONS, MARK_CLASS, LEGEND_MARK_CLASS, AXIS_FILTER_CLASS, ROW_IDX_ATTR, LIFT_SELECTED_CLASS, CONTROL_CLASS, XFILTER_REFRESH_EVENT, CONTAINER_SLOT_ANIM_STOP, CONTAINER_SLOT_XF_CLEAR, CONTAINER_SLOT_INITIAL_XF_MARK, CONTAINER_SLOT_UI_STATE, VIEW_ONLY_UI_STATE_KEYS, withoutViewOnlyKeys, HOST_CONTAINER_CLASS, SELECTION_ACTIVE_CLASS, MARK_SELECTED_CLASS, ACTIVE_TICK_CLASS, DIM_OPACITY_VAR, DIM_OPACITY_DEFAULT, chartOwnsTimeline, periodTickSuppressesFeedback, ANIM_PLAY_SPEED_DEFAULT, ANIM_PLAY_SPEED_MIN, ANIM_PLAY_SPEED_MAX, ANIM_LOOP_DELAY_DEFAULT, ANIM_LOOP_DELAY_MIN, ANIM_MAX_IDEAL_FRAMES_DEFAULT, ANIM_MAX_IDEAL_FRAMES_MIN, ANIM_MAX_IDEAL_FRAMES_MAX, ANIMATION_OPTION_KEYS, COLOR_SCALE_SELF_CLAMP_PCT_DEFAULT, COLOR_SCALE_SELF_CLAMP_PCT_MIN, COLOR_SCALE_SELF_CLAMP_PCT_MAX, FLIP_MODE_DEFAULT, APPROXIMATE_POSITIONS_DEFAULT, VALUE_AXIS_BASELINE_DEFAULT, SEASONAL_MARKERS_DEFAULT, MAX_MAP_POINTS_DEFAULT, type GeoPointPrecision, type GeoMapKind, type TimelineStyle, type FlipMode, type ApproximatePositions, type ValueAxisBaseline, type SeasonalMarkers, type ColorScaleScope, type RenderOptions, type ViewStateProvider, type ChartControlChange, } from "./contract";
2
2
  export { resolveOptions, type ResolveOptionsInput } from "./defaults";
3
3
  export { loadGeo, geoFromCache, registerGeo, registerGeoAsset, geoAssetFor, clearGeoCache, type GeoAssetName, } from "./geoLazy";
4
4
  /** REPLACE the bundled city gazetteer with another packed table. Rarely needed — see the
@@ -7,7 +7,7 @@ export declare function registerCityTable(packed: string): void;
7
7
  export { buildRenderPayload, type RenderPayload, type GeoPointBinding } from "./payload";
8
8
  export { codeReadsDatesInLocalTime, vegaSpecReadsDatesInLocalTime } from "./dateCells";
9
9
  export { createChartHost, compileRenderFn, stripEsmExports, requiredD3Plugins, explainRenderFailure, sessionViewStateProvider, noopViewStateProvider, type ChartHost, type ChartHostConfig, type RenderFn } from "./host";
10
- export { createMarkResolver, type MarkResolver, type MarkResolverEnv } from "./selection";
10
+ export { createMarkResolver, isInsideControl, type MarkResolver, type MarkResolverEnv } from "./selection";
11
11
  export { planTrivialChart, compileTrivialSource, type TrivialPlan, type TrivialShapeKind } from "./trivial";
12
12
  export { captureSvgSnapshot, svgToDataUrl, svgNaturalSize, rasterizeSvgToPngDataUrl, type SnapshotOptions } from "./snapshot";
13
13
  export { shouldReview, buildReviewWire, bareBase64, actionFor, type ReviewGate, type ReviewWire, type ReviewVerdict, type ReviewAction } from "./review";
@@ -1,3 +1,10 @@
1
+ /**
2
+ * True when a click's target sits inside a reader-operated control the chart drew (CONTROL_CLASS
3
+ * on the target or an ancestor), looking no further out than `container` - a page that wraps the
4
+ * whole chart in the class does not make every click a control click. A text node is read through
5
+ * its parent. A click inside a control is neither a selection nor a click on empty canvas.
6
+ */
7
+ export declare function isInsideControl(target: EventTarget | Node | null | undefined, container: Element): boolean;
1
8
  export interface MarkResolverEnv {
2
9
  root: HTMLElement;
3
10
  doc: Document;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bicharts/chart-host",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
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",