@bicharts/chart-host 0.6.0 → 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.
@@ -23,7 +23,7 @@ var require_papaparse_min = __commonJS({
23
23
  })(exports, function r() {
24
24
  var n = "undefined" != typeof self ? self : "undefined" != typeof window ? window : void 0 !== n ? n : {};
25
25
  var d2, s = !n.document && !!n.postMessage, a4 = n.IS_PAPA_WORKER || false, o = {}, h3 = 0, v2 = {};
26
- function P2(e) {
26
+ function P4(e) {
27
27
  return 65279 === e.charCodeAt(0) ? e.slice(1) : e;
28
28
  }
29
29
  function u2(e) {
@@ -146,7 +146,7 @@ var require_papaparse_min = __commonJS({
146
146
  return !y6(e4);
147
147
  })), _3()) {
148
148
  let t4 = function(e4, t5) {
149
- e4 = P2(e4), q4(m4.transformHeader) && (e4 = m4.transformHeader(e4, t5)), c4.push(e4);
149
+ e4 = P4(e4), q4(m4.transformHeader) && (e4 = m4.transformHeader(e4, t5)), c4.push(e4);
150
150
  };
151
151
  var t2 = t4;
152
152
  if (p4) if (Array.isArray(p4.data[0])) {
@@ -211,55 +211,55 @@ var require_papaparse_min = __commonJS({
211
211
  return e.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
212
212
  }
213
213
  function E4(C) {
214
- var S2 = (C = C || {}).delimiter, O3 = C.newline, x4 = C.comments, I2 = C.step, A = C.preview, T3 = C.fastMode, D4 = null, L2 = false, F4 = null == C.quoteChar ? '"' : C.quoteChar, j3 = F4;
215
- if (void 0 !== C.escapeChar && (j3 = C.escapeChar), ("string" != typeof S2 || -1 < v2.BAD_DELIMITERS.indexOf(S2)) && (S2 = ","), x4 === S2) throw new Error("Comment character same as delimiter");
214
+ var S = (C = C || {}).delimiter, O3 = C.newline, x4 = C.comments, I2 = C.step, A = C.preview, T3 = C.fastMode, D3 = null, L2 = false, F4 = null == C.quoteChar ? '"' : C.quoteChar, j3 = F4;
215
+ if (void 0 !== C.escapeChar && (j3 = C.escapeChar), ("string" != typeof S || -1 < v2.BAD_DELIMITERS.indexOf(S)) && (S = ","), x4 === S) throw new Error("Comment character same as delimiter");
216
216
  true === x4 ? x4 = "#" : ("string" != typeof x4 || -1 < v2.BAD_DELIMITERS.indexOf(x4)) && (x4 = false), "\n" !== O3 && "\r" !== O3 && "\r\n" !== O3 && (O3 = "\n");
217
217
  var z3 = 0, M2 = false;
218
218
  this.parse = function(i2, t, r2) {
219
219
  if ("string" != typeof i2) throw new Error("Input must be a string");
220
- var n2 = i2.length, e = S2.length, s2 = O3.length, a5 = x4.length, o2 = q4(I2), h4 = [], u4 = [], d3 = [], f5 = z3 = 0;
221
- if (!i2) return w2();
220
+ var n2 = i2.length, e = S.length, s2 = O3.length, a5 = x4.length, o2 = q4(I2), h4 = [], u4 = [], d3 = [], f5 = z3 = 0;
221
+ if (!i2) return w3();
222
222
  if (T3 || false !== T3 && -1 === i2.indexOf(F4)) {
223
223
  for (var l2 = i2.split(O3), c4 = 0; c4 < l2.length; c4++) {
224
224
  if (d3 = l2[c4], z3 += d3.length, c4 !== l2.length - 1) z3 += O3.length;
225
- else if (r2) return w2();
225
+ else if (r2) return w3();
226
226
  if (!x4 || d3.substring(0, a5) !== x4) {
227
227
  if (o2) {
228
- if (h4 = [], k2(d3.split(S2)), R2(), M2) return w2();
229
- } else k2(d3.split(S2));
230
- if (A && A <= c4) return h4 = h4.slice(0, A), w2(true);
228
+ if (h4 = [], k2(d3.split(S)), R2(), M2) return w3();
229
+ } else k2(d3.split(S));
230
+ if (A && A <= c4) return h4 = h4.slice(0, A), w3(true);
231
231
  }
232
232
  }
233
- return w2();
233
+ return w3();
234
234
  }
235
- for (var p4 = i2.indexOf(S2, z3), g4 = i2.indexOf(O3, z3), _3 = new RegExp(U2(j3) + U2(F4), "g"), m4 = i2.indexOf(F4, z3); ; ) if (i2[z3] === F4) for (m4 = z3, z3++; ; ) {
235
+ for (var p4 = i2.indexOf(S, z3), g4 = i2.indexOf(O3, z3), _3 = new RegExp(U2(j3) + U2(F4), "g"), m4 = i2.indexOf(F4, z3); ; ) if (i2[z3] === F4) for (m4 = z3, z3++; ; ) {
236
236
  if (-1 === (m4 = i2.indexOf(F4, m4 + 1))) return r2 || u4.push({ type: "Quotes", code: "MissingQuotes", message: "Quoted field unterminated", row: h4.length, index: z3 }), E5();
237
237
  if (m4 === n2 - 1) return E5(i2.substring(z3, m4).replace(_3, F4));
238
238
  if (F4 === j3 && i2[m4 + 1] === j3) m4++;
239
239
  else if (F4 === j3 || 0 === m4 || i2[m4 - 1] !== j3) {
240
- -1 !== p4 && p4 < m4 + 1 && (p4 = i2.indexOf(S2, m4 + 1));
240
+ -1 !== p4 && p4 < m4 + 1 && (p4 = i2.indexOf(S, m4 + 1));
241
241
  var y6 = v3(-1 === (g4 = -1 !== g4 && g4 < m4 + 1 ? i2.indexOf(O3, m4 + 1) : g4) ? p4 : Math.min(p4, g4));
242
- if (i2.substr(m4 + 1 + y6, e) === S2) {
243
- d3.push(i2.substring(z3, m4).replace(_3, F4)), i2[z3 = m4 + 1 + y6 + e] !== F4 && (m4 = i2.indexOf(F4, z3)), p4 = i2.indexOf(S2, z3), g4 = i2.indexOf(O3, z3);
242
+ if (i2.substr(m4 + 1 + y6, e) === S) {
243
+ d3.push(i2.substring(z3, m4).replace(_3, F4)), i2[z3 = m4 + 1 + y6 + e] !== F4 && (m4 = i2.indexOf(F4, z3)), p4 = i2.indexOf(S, z3), g4 = i2.indexOf(O3, z3);
244
244
  break;
245
245
  }
246
246
  y6 = v3(g4);
247
247
  if (i2.substring(m4 + 1 + y6, m4 + 1 + y6 + s2) === O3) {
248
- if (d3.push(i2.substring(z3, m4).replace(_3, F4)), b5(m4 + 1 + y6 + s2), p4 = i2.indexOf(S2, z3), m4 = i2.indexOf(F4, z3), o2 && (R2(), M2)) return w2();
249
- if (A && h4.length >= A) return w2(true);
248
+ if (d3.push(i2.substring(z3, m4).replace(_3, F4)), b5(m4 + 1 + y6 + s2), p4 = i2.indexOf(S, z3), m4 = i2.indexOf(F4, z3), o2 && (R2(), M2)) return w3();
249
+ if (A && h4.length >= A) return w3(true);
250
250
  break;
251
251
  }
252
252
  u4.push({ type: "Quotes", code: "InvalidQuotes", message: "Trailing quote on quoted field is malformed", row: h4.length, index: z3 }), m4++;
253
253
  }
254
254
  }
255
255
  else if (x4 && 0 === d3.length && i2.substring(z3, z3 + a5) === x4) {
256
- if (-1 === g4) return w2();
257
- z3 = g4 + s2, g4 = i2.indexOf(O3, z3), p4 = i2.indexOf(S2, z3);
258
- } else if (-1 !== p4 && (p4 < g4 || -1 === g4)) d3.push(i2.substring(z3, p4)), z3 = p4 + e, p4 = i2.indexOf(S2, z3);
256
+ if (-1 === g4) return w3();
257
+ z3 = g4 + s2, g4 = i2.indexOf(O3, z3), p4 = i2.indexOf(S, z3);
258
+ } else if (-1 !== p4 && (p4 < g4 || -1 === g4)) d3.push(i2.substring(z3, p4)), z3 = p4 + e, p4 = i2.indexOf(S, z3);
259
259
  else {
260
260
  if (-1 === g4) break;
261
- if (d3.push(i2.substring(z3, g4)), b5(g4 + s2), o2 && (R2(), M2)) return w2();
262
- if (A && h4.length >= A) return w2(true);
261
+ if (d3.push(i2.substring(z3, g4)), b5(g4 + s2), o2 && (R2(), M2)) return w3();
262
+ if (A && h4.length >= A) return w3(true);
263
263
  }
264
264
  return E5();
265
265
  function k2(e2) {
@@ -270,30 +270,30 @@ var require_papaparse_min = __commonJS({
270
270
  return t2 = -1 !== e2 && (e2 = i2.substring(m4 + 1, e2)) && "" === e2.trim() ? e2.length : t2;
271
271
  }
272
272
  function E5(e2) {
273
- return r2 || (void 0 === e2 && (e2 = i2.substring(z3)), d3.push(e2), z3 = n2, k2(d3), o2 && R2()), w2();
273
+ return r2 || (void 0 === e2 && (e2 = i2.substring(z3)), d3.push(e2), z3 = n2, k2(d3), o2 && R2()), w3();
274
274
  }
275
275
  function b5(e2) {
276
276
  z3 = e2, k2(d3), d3 = [], g4 = i2.indexOf(O3, z3);
277
277
  }
278
- function w2(e2) {
278
+ function w3(e2) {
279
279
  if (C.header && !t && h4.length && !L2) {
280
280
  var s4 = h4[0], a6 = /* @__PURE__ */ Object.create(null), o4 = new Set(s4);
281
281
  let n4 = false;
282
282
  for (let r4 = 0; r4 < s4.length; r4++) {
283
- let i4 = P2(s4[r4]);
283
+ let i4 = P4(s4[r4]);
284
284
  if (a6[i4 = q4(C.transformHeader) ? C.transformHeader(i4, r4) : i4]) {
285
285
  let e4, t2 = a6[i4];
286
286
  for (; e4 = i4 + "_" + t2, t2++, o4.has(e4); ) ;
287
- o4.add(e4), s4[r4] = e4, a6[i4]++, n4 = true, (D4 = null === D4 ? {} : D4)[e4] = i4;
287
+ o4.add(e4), s4[r4] = e4, a6[i4]++, n4 = true, (D3 = null === D3 ? {} : D3)[e4] = i4;
288
288
  } else a6[i4] = 1, s4[r4] = i4;
289
289
  o4.add(i4);
290
290
  }
291
291
  n4 && console.warn("Duplicate headers found and renamed."), L2 = true;
292
292
  }
293
- return { data: h4, errors: u4, meta: { delimiter: S2, linebreak: O3, aborted: M2, truncated: !!e2, cursor: f5 + (t || 0), renamedHeaders: D4 } };
293
+ return { data: h4, errors: u4, meta: { delimiter: S, linebreak: O3, aborted: M2, truncated: !!e2, cursor: f5 + (t || 0), renamedHeaders: D3 } };
294
294
  }
295
295
  function R2() {
296
- I2(w2()), h4 = [], u4 = [];
296
+ I2(w3()), h4 = [], u4 = [];
297
297
  }
298
298
  }, this.abort = function() {
299
299
  M2 = true;
@@ -339,7 +339,7 @@ var require_papaparse_min = __commonJS({
339
339
  return v2.parse = function(e, t) {
340
340
  var i2 = (t = t || {}).dynamicTyping || false;
341
341
  q4(i2) && (t.dynamicTypingFunction = i2, i2 = {});
342
- if (t.dynamicTyping = i2, t.transform = !!q4(t.transform) && t.transform, !t.worker || !v2.WORKERS_SUPPORTED) return i2 = null, v2.NODE_STREAM_INPUT, "string" == typeof e ? (e = P2(e), i2 = new (t.download ? f4 : c2)(t)) : true === e.readable && q4(e.read) && q4(e.on) ? i2 = new p2(t) : (n.File && e instanceof File || e instanceof Object) && (i2 = new l(t)), i2.stream(e);
342
+ if (t.dynamicTyping = i2, t.transform = !!q4(t.transform) && t.transform, !t.worker || !v2.WORKERS_SUPPORTED) return i2 = null, v2.NODE_STREAM_INPUT, "string" == typeof e ? (e = P4(e), i2 = new (t.download ? f4 : c2)(t)) : true === e.readable && q4(e.read) && q4(e.on) ? i2 = new p2(t) : (n.File && e instanceof File || e instanceof Object) && (i2 = new l(t)), i2.stream(e);
343
343
  (i2 = (() => {
344
344
  var e2;
345
345
  return !!v2.WORKERS_SUPPORTED && (e2 = (() => {
@@ -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";
@@ -507,11 +508,11 @@ function f(t) {
507
508
  return t > EPS ? Math.cbrt(t) : (KAPPA * t + 16) / 116;
508
509
  }
509
510
  function rgbToLab(r, g3, b4) {
510
- const R2 = linearise(r), G3 = linearise(g3), B2 = linearise(b4);
511
- const X2 = 0.4124564 * R2 + 0.3575761 * G3 + 0.1804375 * B2;
512
- const Y2 = 0.2126729 * R2 + 0.7151522 * G3 + 0.072175 * B2;
513
- const Z2 = 0.0193339 * R2 + 0.119192 * G3 + 0.9503041 * B2;
514
- const fx = f(X2 / Xn), fy = f(Y2 / Yn), fz = f(Z2 / Zn);
511
+ const R2 = linearise(r), G2 = linearise(g3), B2 = linearise(b4);
512
+ const X2 = 0.4124564 * R2 + 0.3575761 * G2 + 0.1804375 * B2;
513
+ const Y2 = 0.2126729 * R2 + 0.7151522 * G2 + 0.072175 * B2;
514
+ const Z3 = 0.0193339 * R2 + 0.119192 * G2 + 0.9503041 * B2;
515
+ const fx = f(X2 / Xn), fy = f(Y2 / Yn), fz = f(Z3 / Zn);
515
516
  return { L: 116 * fy - 16, a: 500 * (fx - fy), b: 200 * (fy - fz) };
516
517
  }
517
518
  function hexToLab(hex2) {
@@ -527,8 +528,8 @@ function deltaE2000(c1, c2) {
527
528
  const C1 = Math.hypot(c1.a, c1.b), C2 = Math.hypot(c2.a, c2.b);
528
529
  const Cbar = (C1 + C2) / 2;
529
530
  const C7 = Math.pow(Cbar, 7);
530
- const G3 = 0.5 * (1 - Math.sqrt(C7 / (C7 + Math.pow(25, 7))));
531
- const a1p = (1 + G3) * c1.a, a2p = (1 + G3) * c2.a;
531
+ const G2 = 0.5 * (1 - Math.sqrt(C7 / (C7 + Math.pow(25, 7))));
532
+ const a1p = (1 + G2) * c1.a, a2p = (1 + G2) * c2.a;
532
533
  const C1p = Math.hypot(a1p, c1.b), C2p = Math.hypot(a2p, c2.b);
533
534
  const neutral = C1p < NEUTRAL_CHROMA || C2p < NEUTRAL_CHROMA;
534
535
  const h1p = C1p < NEUTRAL_CHROMA ? 0 : (Math.atan2(c1.b, a1p) * DEG + 360) % 360;
@@ -568,11 +569,11 @@ function labToHex(lab) {
568
569
  const fy = (lab.L + 16) / 116, fx = fy + lab.a / 500, fz = fy - lab.b / 200;
569
570
  const X2 = Xn * finv(fx);
570
571
  const Y2 = Yn * (lab.L > KAPPA * EPS ? fy * fy * fy : lab.L / KAPPA);
571
- const Z2 = Zn * finv(fz);
572
+ const Z3 = Zn * finv(fz);
572
573
  const lin = [
573
- 3.2404542 * X2 - 1.5371385 * Y2 - 0.4985314 * Z2,
574
- -0.969266 * X2 + 1.8760108 * Y2 + 0.041556 * Z2,
575
- 0.0556434 * X2 - 0.2040259 * Y2 + 1.0572252 * Z2
574
+ 3.2404542 * X2 - 1.5371385 * Y2 - 0.4985314 * Z3,
575
+ -0.969266 * X2 + 1.8760108 * Y2 + 0.041556 * Z3,
576
+ 0.0556434 * X2 - 0.2040259 * Y2 + 1.0572252 * Z3
576
577
  ];
577
578
  return "#" + lin.map((v2) => {
578
579
  const c2 = Math.max(0, Math.min(1, v2));
@@ -1237,20 +1238,20 @@ function A3(n) {
1237
1238
  if (r && i && c3(r) !== i && (r = null), n.city !== void 0 && n.city !== null) {
1238
1239
  let a4 = u(String(n.city)), s = O(a4), f4 = s ? F(s, n.mapKind) : null;
1239
1240
  if (f4 && f4.length) {
1240
- let d2 = n.state === void 0 || n.state === null ? "" : String(n.state).trim(), R2 = d2 ? u(d2) : "", g3 = d2 ? Y(d2) : null, S2 = [], m2 = -1;
1241
+ let d2 = n.state === void 0 || n.state === null ? "" : String(n.state).trim(), R2 = d2 ? u(d2) : "", g3 = d2 ? Y(d2) : null, S = [], m2 = -1;
1241
1242
  for (let c2 of f4) {
1242
1243
  let l = c2.row, A = 0;
1243
1244
  if (d2 && l.a1 !== "") if (g3 && l.a1 === g3 || u(l.a1) === R2) A++;
1244
1245
  else continue;
1245
1246
  if (i) if (T(l.cc) === i) A++;
1246
1247
  else continue;
1247
- A > m2 ? (m2 = A, S2 = [c2]) : A === m2 && S2.push(c2);
1248
+ A > m2 ? (m2 = A, S = [c2]) : A === m2 && S.push(c2);
1248
1249
  }
1249
- S2.some((c2) => c2.primary) && (S2 = S2.filter((c2) => c2.primary));
1250
+ S.some((c2) => c2.primary) && (S = S.filter((c2) => c2.primary));
1250
1251
  let p2 = /* @__PURE__ */ new Map();
1251
- for (let c2 of S2) p2.set(c2.row.lon.toFixed(2) + "," + c2.row.lat.toFixed(2), c2.row);
1252
+ for (let c2 of S) p2.set(c2.row.lon.toFixed(2) + "," + c2.row.lat.toFixed(2), c2.row);
1252
1253
  if (p2.size === 1) {
1253
- let c2 = S2[0].row;
1254
+ let c2 = S[0].row;
1254
1255
  return { lat: c2.lat, lon: c2.lon, precision: "city" };
1255
1256
  }
1256
1257
  if (p2.size > 1) return { ambiguous: true, matches: p2.size };
@@ -1273,7 +1274,7 @@ function A3(n) {
1273
1274
  var G = { latlon: 0, city: 1, zip3: 2, state: 3, country: 4 };
1274
1275
  var x = 8;
1275
1276
  function y3(n, e) {
1276
- let t = new Array(n.length), o = new Array(n.length), i = new Array(n.length), r = /* @__PURE__ */ new Set(), a4 = [], s = /* @__PURE__ */ new Set(), f4 = [], d2 = /* @__PURE__ */ new Set(), R2 = [], g3 = { latlon: 0, city: 0, zip3: 0, state: 0, country: 0 }, S2 = 0, m2 = 0, p2 = null;
1277
+ let t = new Array(n.length), o = new Array(n.length), i = new Array(n.length), r = /* @__PURE__ */ new Set(), a4 = [], s = /* @__PURE__ */ new Set(), f4 = [], d2 = /* @__PURE__ */ new Set(), R2 = [], g3 = { latlon: 0, city: 0, zip3: 0, state: 0, country: 0 }, S = 0, m2 = 0, p2 = null;
1277
1278
  for (let l = 0; l < n.length; ++l) {
1278
1279
  let A = n[l], C = A3({ ...A, mapKind: e });
1279
1280
  if (S3(C)) {
@@ -1281,7 +1282,7 @@ function y3(n, e) {
1281
1282
  let M2 = K(A);
1282
1283
  M2 && !d2.has(M2.toLowerCase()) && (d2.add(M2.toLowerCase()), R2.length < x && R2.push(M2));
1283
1284
  } else if (C) {
1284
- if (t[l] = C.lat, o[l] = C.lon, i[l] = C.precision, S2++, g3[C.precision]++, (p2 === null || G[C.precision] > G[p2]) && (p2 = C.precision), G[C.precision] > G.city) {
1285
+ if (t[l] = C.lat, o[l] = C.lon, i[l] = C.precision, S++, g3[C.precision]++, (p2 === null || G[C.precision] > G[p2]) && (p2 = C.precision), G[C.precision] > G.city) {
1285
1286
  let M2 = K(A);
1286
1287
  M2 && !s.has(M2.toLowerCase()) && (s.add(M2.toLowerCase()), f4.length < x && f4.push(M2));
1287
1288
  }
@@ -1292,7 +1293,7 @@ function y3(n, e) {
1292
1293
  }
1293
1294
  }
1294
1295
  let c2 = !n3() && n.some((l) => l.city !== null && l.city !== void 0 && String(l.city).trim() !== "");
1295
- return { lat: t, lon: o, precisions: i, precision: p2, precisionCounts: g3, coarseExamples: f4, unmatched: a4, ambiguousRows: m2, ambiguousExamples: R2, matchedRows: S2, totalRows: n.length, ...c2 ? { cityTableMissing: true } : {} };
1296
+ return { lat: t, lon: o, precisions: i, precision: p2, precisionCounts: g3, coarseExamples: f4, unmatched: a4, ambiguousRows: m2, ambiguousExamples: R2, matchedRows: S, totalRows: n.length, ...c2 ? { cityTableMissing: true } : {} };
1296
1297
  }
1297
1298
  function K(n) {
1298
1299
  let e = [n.city, n.state, n.zip, n.country].filter((t) => t != null && String(t).trim() !== "").map((t) => String(t).trim()).join(", ");
@@ -1558,147 +1559,147 @@ var ct2 = new RegExp([String.raw`\bisMeasure\b`, String.raw`\bdataType\b`, Strin
1558
1559
 
1559
1560
  // ../shape-core/dist/index.mjs
1560
1561
  /*! @bicharts/shape-core — Apache-2.0. Bundled reference data: GeoNames (https://www.geonames.org/) CC BY 4.0; US Census/TIGER (public domain). Full text: NOTICE in this package. */
1561
- var F3 = 2;
1562
- var q3 = 400;
1563
- function E2(i) {
1564
- return !!E(i);
1565
- }
1566
- function S(i) {
1567
- let n = /* @__PURE__ */ new Set();
1568
- for (let t of i) {
1562
+ var E2 = 2;
1563
+ var Z2 = 400;
1564
+ function O2(o) {
1565
+ return !!E(o);
1566
+ }
1567
+ function P2(o) {
1568
+ let e = /* @__PURE__ */ new Set();
1569
+ for (let t of o) {
1569
1570
  if (t == null) continue;
1570
- let r = u(String(t));
1571
- if (!V(r) && !n.has(r) && (n.add(r), n.size >= q3)) break;
1571
+ let i = u(String(t));
1572
+ if (!V(i) && !e.has(i) && (e.add(i), e.size >= Z2)) break;
1572
1573
  }
1573
- return Array.from(n);
1574
+ return Array.from(e);
1574
1575
  }
1575
- function x3(i) {
1576
- let n = S(i);
1577
- if (n.length === 0 || O2(i) < 95) return false;
1578
- let t = n.filter((c2) => E2(c2) && !Y(c2)).length, r = n.filter((c2) => !E2(c2) && !!Y(c2)).length;
1579
- return t >= 1 && t >= r;
1576
+ function x3(o) {
1577
+ let e = P2(o);
1578
+ if (e.length === 0 || z2(o) < 95) return false;
1579
+ let t = e.filter((c2) => O2(c2) && !Y(c2)).length, i = e.filter((c2) => !O2(c2) && !!Y(c2)).length;
1580
+ return t >= 1 && t >= i;
1580
1581
  }
1581
- function W2(i, n) {
1582
- if (!Y(i)) return false;
1583
- let t = E(i);
1584
- return t ? n === "world" ? true : s3.has(t) : false;
1582
+ function j2(o, e) {
1583
+ if (!Y(o)) return false;
1584
+ let t = E(o);
1585
+ return t ? e === "world" ? true : s3.has(t) : false;
1585
1586
  }
1586
- function O2(i) {
1587
- let n = S(i);
1588
- if (n.length === 0) return 0;
1587
+ function z2(o) {
1588
+ let e = P2(o);
1589
+ if (e.length === 0) return 0;
1589
1590
  let t = 0;
1590
- for (let r of n) E2(r) && t++;
1591
- return Math.round(t / n.length * 1e3) / 10;
1591
+ for (let i of e) O2(i) && t++;
1592
+ return Math.round(t / e.length * 1e3) / 10;
1592
1593
  }
1593
- function D3(i) {
1594
- let n = S(i);
1595
- if (n.length === 0) return 0;
1594
+ function w2(o) {
1595
+ let e = P2(o);
1596
+ if (e.length === 0) return 0;
1596
1597
  let t = 0;
1597
- for (let r of n) Y(r) && t++;
1598
- return Math.round(t / n.length * 1e3) / 10;
1598
+ for (let i of e) Y(i) && t++;
1599
+ return Math.round(t / e.length * 1e3) / 10;
1599
1600
  }
1600
- function $2(i) {
1601
- let n = /* @__PURE__ */ new Set();
1602
- for (let t of i) {
1601
+ function H2(o) {
1602
+ let e = /* @__PURE__ */ new Set();
1603
+ for (let t of o) {
1603
1604
  if (t == null) continue;
1604
- let r = String(t).trim();
1605
- if (!V(u(r)) && !n.has(r) && (n.add(r), n.size >= q3)) break;
1605
+ let i = String(t).trim();
1606
+ if (!V(u(i)) && !e.has(i) && (e.add(i), e.size >= Z2)) break;
1606
1607
  }
1607
- return Array.from(n);
1608
+ return Array.from(e);
1608
1609
  }
1609
- function z2(i) {
1610
- let n = $2(i);
1611
- if (n.length === 0) return 0;
1610
+ function $2(o) {
1611
+ let e = H2(o);
1612
+ if (e.length === 0) return 0;
1612
1613
  let t = 0;
1613
- for (let r of n) Z(r).length > 0 && t++;
1614
- return Math.round(t / n.length * 1e3) / 10;
1614
+ for (let i of e) Z(i).length > 0 && t++;
1615
+ return Math.round(t / e.length * 1e3) / 10;
1615
1616
  }
1616
- function j2(i, n) {
1617
- return y2(n, rt) ? true : $2(i).some((t) => /^\d{5}(-\d{4})?$/.test(t.replace(/\.0+$/, "")));
1617
+ function q3(o, e) {
1618
+ return y2(e, rt) ? true : H2(o).some((t) => /^\d{5}(-\d{4})?$/.test(t.replace(/\.0+$/, "")));
1618
1619
  }
1619
- function yt2(i, n) {
1620
- let t = S(i);
1620
+ function yt2(o, e) {
1621
+ let t = P2(o);
1621
1622
  if (t.length === 0) return 0;
1622
- let r = 0;
1623
- for (let c2 of t) p3(c2, n) && r++;
1624
- return Math.round(r / t.length * 1e3) / 10;
1623
+ let i = 0;
1624
+ for (let c2 of t) p3(c2, e) && i++;
1625
+ return Math.round(i / t.length * 1e3) / 10;
1625
1626
  }
1626
- function G2(i, n) {
1627
+ function F3(o, e) {
1627
1628
  let t = 0;
1628
- for (let r of S(i)) n(r) && t++;
1629
+ for (let i of P2(o)) e(i) && t++;
1629
1630
  return t;
1630
1631
  }
1631
- function Ct(i, n) {
1632
+ function Ct(o, e) {
1632
1633
  let t = 0;
1633
- for (let r of $2(i)) n(r) && t++;
1634
+ for (let i of H2(o)) e(i) && t++;
1634
1635
  return t;
1635
1636
  }
1636
- function ht(i, n, t, r, c2) {
1637
- let l = [], a4 = [], o = {}, R2 = {}, h3 = new Set(i), f4 = (e) => n.map((s) => s[e]);
1638
- for (let e of ["city", "country"]) {
1639
- let s = t?.[e];
1640
- s && h3.has(s) && (o[e] = s);
1637
+ function ht(o, e, t, i, c2) {
1638
+ let u2 = [], a4 = [], r = {}, T3 = {}, h3 = new Set(o), f4 = (n) => e.map((s) => s[n]);
1639
+ for (let n of ["city", "country"]) {
1640
+ let s = t?.[n];
1641
+ s && h3.has(s) && (r[n] = s);
1641
1642
  }
1642
- let Y2 = new Set(c2 ?? i);
1643
- for (let e of ["lat", "lon"]) {
1644
- let s = t?.[e];
1645
- s && Y2.has(s) && (o[e] = s);
1643
+ let Y2 = new Set(c2 ?? o);
1644
+ for (let n of ["lat", "lon"]) {
1645
+ let s = t?.[n];
1646
+ s && Y2.has(s) && (r[n] = s);
1646
1647
  }
1647
1648
  let g3 = t?.zip;
1648
1649
  if (g3 && h3.has(g3)) {
1649
- let e = f4(g3), s = z2(e);
1650
- s < 95 ? a4.push(`zip=${g3} (only ${s}% of values read as ZIPs)`) : j2(e, g3) ? o.zip = g3 : a4.push(`zip=${g3} (all values are 3-4 digits with nothing to say they are postal)`);
1650
+ let n = f4(g3), s = $2(n);
1651
+ s < 95 ? a4.push(`zip=${g3} (only ${s}% of values read as ZIPs)`) : q3(n, g3) ? r.zip = g3 : a4.push(`zip=${g3} (all values are 3-4 digits with nothing to say they are postal)`);
1651
1652
  }
1652
1653
  let p2 = t?.state;
1653
1654
  if (p2 && h3.has(p2)) {
1654
- let e = f4(p2), s = S(e);
1655
- s.length > 0 && s.every((u2) => W2(u2, r)) ? a4.push(`state=${p2} (every value is "CA", which is both Canada and California)`) : x3(e) ? (a4.push(`state=${p2} (every value is a country, not a state)`), o.country || (o.country = p2)) : D3(e) < 95 ? a4.push(`state=${p2} (only ${D3(e)}% of values are states/provinces)`) : o.state = p2;
1655
+ let n = f4(p2), s = P2(n);
1656
+ s.length > 0 && s.every((l) => j2(l, i)) ? a4.push(`state=${p2} (every value is "CA", which is both Canada and California)`) : x3(n) ? (a4.push(`state=${p2} (every value is a country, not a state)`), r.country || (r.country = p2)) : w2(n) < 95 ? a4.push(`state=${p2} (only ${w2(n)}% of values are states/provinces)`) : r.state = p2;
1656
1657
  }
1657
- let y5 = new Set(Object.values(o).filter(Boolean)), A = i.filter((e) => !y5.has(e) && !e.startsWith("__"));
1658
- if (!o.state) {
1659
- let e = null;
1658
+ let y5 = new Set(Object.values(r).filter(Boolean)), A = o.filter((n) => !y5.has(n) && !n.startsWith("__"));
1659
+ if (!r.state) {
1660
+ let n = null;
1660
1661
  for (let s of A) {
1661
- let u2 = f4(s);
1662
- if (x3(u2)) continue;
1663
- let m2 = D3(u2);
1662
+ let l = f4(s);
1663
+ if (x3(l)) continue;
1664
+ let m2 = w2(l);
1664
1665
  if (m2 < 95) continue;
1665
- let w2 = G2(u2, (T3) => !!Y(T3)), Q3 = G2(u2, (T3) => !!Y(T3) && !W2(T3, r));
1666
- w2 < F3 && Q3 < 1 || (!e || m2 > e.pct) && (e = { name: s, pct: m2 });
1666
+ let D3 = F3(l, (R2) => !!Y(R2)), ee = F3(l, (R2) => !!Y(R2) && !j2(R2, i));
1667
+ D3 < E2 && ee < 1 || (!n || m2 > n.pct) && (n = { name: s, pct: m2 });
1667
1668
  }
1668
- e && (o.state = e.name, y5.add(e.name), l.push(`state=${e.name} (${e.pct}% states/provinces)`));
1669
+ n && (r.state = n.name, y5.add(n.name), u2.push(`state=${n.name} (${n.pct}% states/provinces)`));
1669
1670
  }
1670
- if (!o.zip) for (let e of A) {
1671
- if (y5.has(e)) continue;
1672
- let s = f4(e), u2 = z2(s);
1673
- if (!(u2 < 95) && j2(s, e) && !(Ct(s, (m2) => Z(m2).length > 0) < F3)) {
1674
- o.zip = e, y5.add(e), l.push(`zip=${e} (${u2}% ZIP codes)`);
1671
+ if (!r.zip) for (let n of A) {
1672
+ if (y5.has(n)) continue;
1673
+ let s = f4(n), l = $2(s);
1674
+ if (!(l < 95) && q3(s, n) && !(Ct(s, (m2) => Z(m2).length > 0) < E2)) {
1675
+ r.zip = n, y5.add(n), u2.push(`zip=${n} (${l}% ZIP codes)`);
1675
1676
  break;
1676
1677
  }
1677
1678
  }
1678
- let P2 = o.country;
1679
- if (!P2 || !x3(f4(P2))) {
1680
- let e = null;
1679
+ let S = r.country;
1680
+ if (!S || !x3(f4(S))) {
1681
+ let n = null;
1681
1682
  for (let s of A) {
1682
1683
  if (y5.has(s) || !x3(f4(s))) continue;
1683
- let u2 = O2(f4(s));
1684
- (!e || u2 > e.pct) && (e = { name: s, pct: u2 });
1684
+ let l = z2(f4(s));
1685
+ (!n || l > n.pct) && (n = { name: s, pct: l });
1685
1686
  }
1686
- e && (P2 && (a4.push(`country=${P2} (only ${O2(f4(P2))}% of values are country identifiers; using ${e.name} instead)`), R2.country = P2), o.country = e.name, y5.add(e.name), l.push(`country=${e.name}`));
1687
+ n && (S && (a4.push(`country=${S} (only ${z2(f4(S))}% of values are country identifiers; using ${n.name} instead)`), T3.country = S), r.country = n.name, y5.add(n.name), u2.push(`country=${n.name}`));
1687
1688
  }
1688
- if (!o.city) {
1689
- let e = null;
1689
+ if (!r.city) {
1690
+ let n = null;
1690
1691
  for (let s of A) {
1691
1692
  if (y5.has(s)) continue;
1692
- let u2 = f4(s), m2 = yt2(u2, r);
1693
- m2 < m3 || G2(u2, (w2) => p3(w2, r)) < F3 || (!e || m2 > e.pct) && (e = { name: s, pct: m2 });
1693
+ let l = f4(s), m2 = yt2(l, i);
1694
+ m2 < m3 || F3(l, (D3) => p3(D3, i)) < E2 || (!n || m2 > n.pct) && (n = { name: s, pct: m2 });
1694
1695
  }
1695
- e && (o.city = e.name, l.push(`city=${e.name} (${e.pct}% known cities)`));
1696
+ n && (r.city = n.name, u2.push(`city=${n.name} (${n.pct}% known cities)`));
1696
1697
  }
1697
- let B2 = o.country ? f4(o.country) : [], _2 = !!o.country && x3(B2), J2 = _2 ? new Set(B2.map((e) => E(e == null ? null : String(e))).filter(Boolean)).size : 0, H2 = _2 && J2 >= 2, L2 = !!(o.lat && o.lon) && n.some((e) => {
1698
- let s = +String(e[o.lat] ?? "").trim(), u2 = +String(e[o.lon] ?? "").trim();
1699
- return isFinite(s) && isFinite(u2) && s >= -90 && s <= 90 && u2 >= -180 && u2 <= 180 && String(e[o.lat] ?? "").trim() !== "" && String(e[o.lon] ?? "").trim() !== "";
1698
+ let B2 = r.country ? f4(r.country) : [], k2 = !!r.country && x3(B2), Q3 = k2 ? new Set(B2.map((n) => E(n == null ? null : String(n))).filter(Boolean)).size : 0, K3 = k2 && Q3 >= 2, _2 = !!(r.lat && r.lon) && e.some((n) => {
1699
+ let s = +String(n[r.lat] ?? "").trim(), l = +String(n[r.lon] ?? "").trim();
1700
+ return isFinite(s) && isFinite(l) && s >= -90 && s <= 90 && l >= -180 && l <= 180 && String(n[r.lat] ?? "").trim() !== "" && String(n[r.lon] ?? "").trim() !== "";
1700
1701
  });
1701
- return o.lat && o.lon && !L2 && a4.push(`lat/lon=${o.lat}/${o.lon} (no row holds a usable coordinate pair)`), o.country && !H2 && !(o.city || o.state || o.zip || L2) && a4.push(_2 ? `country=${o.country} (every row resolves to the same country - nothing to place apart)` : `country=${o.country} (values are not country identifiers)`), { bind: !!(o.city || o.state || o.zip || H2 || L2) ? o : null, backfilled: l, refused: a4, ...Object.keys(R2).length ? { labelFallback: R2 } : {} };
1702
+ return r.lat && r.lon && !_2 && a4.push(`lat/lon=${r.lat}/${r.lon} (no row holds a usable coordinate pair)`), r.country && !K3 && !(r.city || r.state || r.zip || _2) && a4.push(k2 ? `country=${r.country} (every row resolves to the same country - nothing to place apart)` : `country=${r.country} (values are not country identifiers)`), { bind: !!(r.city || r.state || r.zip || K3 || _2) ? r : null, backfilled: u2, refused: a4, ...Object.keys(T3).length ? { labelFallback: T3 } : {} };
1702
1703
  }
1703
1704
 
1704
1705
  // src/payload.ts
@@ -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) => {
@@ -2305,13 +2315,13 @@ function censusHitBands(container, doc) {
2305
2315
  if (!OPEN_TAGS.has(tag)) continue;
2306
2316
  const cs = styleOf2(el, ownerDoc);
2307
2317
  const open = isUnfilled(attrOrComputed(el, "fill", cs));
2308
- const w2 = widthPx(attrOrComputed(el, "stroke-width", cs) || "1");
2318
+ const w3 = widthPx(attrOrComputed(el, "stroke-width", cs) || "1");
2309
2319
  const geom = String(el.getAttribute?.("d") ?? "") || `${tag}#${String(el.getAttribute?.(ROW_IDX_ATTR) ?? "")}`;
2310
2320
  const inert = String(cs?.pointerEvents ?? el.style?.pointerEvents ?? "") === "none";
2311
- rows.push({ el, geom, w: w2, open, inert });
2312
- if (isFinite(w2)) {
2321
+ rows.push({ el, geom, w: w3, open, inert });
2322
+ if (isFinite(w3)) {
2313
2323
  const prev = widestByGeom.get(geom);
2314
- if (prev === void 0 || w2 > prev) widestByGeom.set(geom, w2);
2324
+ if (prev === void 0 || w3 > prev) widestByGeom.set(geom, w3);
2315
2325
  }
2316
2326
  }
2317
2327
  const out = { ...EMPTY3 };
@@ -2482,12 +2492,12 @@ function contentExtentOf(boxes) {
2482
2492
  if (usable.length === 0) return { w: 0, h: 0, source: "none" };
2483
2493
  const inFlow = usable.filter((b4) => !b4.floating);
2484
2494
  const counted = inFlow.length > 0 ? inFlow : usable;
2485
- let w2 = 0, h3 = 0;
2495
+ let w3 = 0, h3 = 0;
2486
2496
  for (const b4 of counted) {
2487
- if (b4.right > w2) w2 = b4.right;
2497
+ if (b4.right > w3) w3 = b4.right;
2488
2498
  if (b4.bottom > h3) h3 = b4.bottom;
2489
2499
  }
2490
- return { w: w2, h: h3, source: inFlow.length > 0 ? "in-flow" : "all-floating" };
2500
+ return { w: w3, h: h3, source: inFlow.length > 0 ? "in-flow" : "all-floating" };
2491
2501
  }
2492
2502
  function scrollFitFor(contentW, contentH, viewportW, viewportH, slackPx = SCROLL_SLACK_PX) {
2493
2503
  return {
@@ -2497,8 +2507,8 @@ function scrollFitFor(contentW, contentH, viewportW, viewportH, slackPx = SCROLL
2497
2507
  }
2498
2508
  var FIT_CONTENT_SELECTOR = "text, .d3-mark, .d3-legend-mark";
2499
2509
  var PHANTOM_FRACTION = 0.95;
2500
- function isPhantomBox(w2, h3, refW, refH) {
2501
- return w2 > refW * PHANTOM_FRACTION || h3 > refH * PHANTOM_FRACTION;
2510
+ function isPhantomBox(w3, h3, refW, refH) {
2511
+ return w3 > refW * PHANTOM_FRACTION || h3 > refH * PHANTOM_FRACTION;
2502
2512
  }
2503
2513
  var MAX_FRAME_GROW_FACTOR = 20;
2504
2514
  function planFrameGrow(inkBottomPx, elHeightPx, viewBoxH, ctmScale, slackPx = SCROLL_SLACK_PX, maxFactor = MAX_FRAME_GROW_FACTOR) {
@@ -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-DTAYO46G.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-DTAYO46G.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.0",
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",