@bicharts/chart-host 0.6.107 → 0.6.109

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 +1,7 @@
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
3
  LASSO_KNOB_KEY
4
- } from "./chunk-IE426WU6.mjs";
4
+ } from "./chunk-4DOKJ3R3.mjs";
5
5
 
6
6
  // src/filterScope.ts
7
7
  function viewToken(view) {
@@ -140,10 +140,17 @@ function createFilter(columns, opts = {}) {
140
140
  get version() {
141
141
  return version;
142
142
  },
143
- selectRows(selected, why = "page") {
143
+ selectRows(selected, why = "page", keep) {
144
144
  const list = (selected ?? []).filter((r) => r && typeof r === "object");
145
145
  remember(list);
146
- commit(dedupe(list.map((r) => keyOfRow(r, cols))), list, why);
146
+ const held = dedupe(toKeys(keep ?? [], cols.length));
147
+ if (!held.length) {
148
+ commit(dedupe(list.map((r) => keyOfRow(r, cols))), list, why);
149
+ return;
150
+ }
151
+ const keepSet = new Set(held.map(keyString));
152
+ const known = rows.filter((r) => keepSet.has(keyString(keyOfRow(r, cols))));
153
+ commit(dedupe(list.map((r) => keyOfRow(r, cols)).concat(held)), list.concat(known), why);
147
154
  },
148
155
  set(input, why = "page") {
149
156
  const ks = dedupe(toKeys(input, cols.length));
@@ -309,16 +316,6 @@ var sortedEq = (a, b) => {
309
316
  return x.every((v, i) => v === y[i]);
310
317
  };
311
318
  function bindFilter(host, filter, opts) {
312
- const token = {};
313
- const ownerKeys = () => keysString(filter.keys);
314
- const isMine = () => {
315
- const o = owners.get(filter);
316
- return !!o && o.token === token && o.keys === ownerKeys();
317
- };
318
- {
319
- const o = owners.get(filter);
320
- if (o && o.orphan && o.keys === ownerKeys()) owners.set(filter, { token, keys: o.keys, orphan: false });
321
- }
322
319
  const wanted = () => {
323
320
  if (!filter.active) return [];
324
321
  const out = [];
@@ -329,29 +326,37 @@ function bindFilter(host, filter, opts) {
329
326
  }
330
327
  return out;
331
328
  };
329
+ const hiddenKeys = () => {
330
+ if (!filter.active) return [];
331
+ const carried = /* @__PURE__ */ new Set();
332
+ const n = opts.rowCount();
333
+ for (let i = 0; i < n; i++) {
334
+ const r = opts.rowAt(i);
335
+ if (r) carried.add(keyString(keyOfRow(r, filter.columns)));
336
+ }
337
+ return filter.keys.filter((k) => !carried.has(keyString(k)));
338
+ };
332
339
  const paint = () => {
333
340
  const want = wanted();
334
341
  const cur = host.selection.current ?? [];
335
- if (sortedEq(want, cur)) return;
336
- if (want.length) host.selection.highlight(want);
337
- else if (cur.length) host.selection.clear();
342
+ if (!sortedEq(want, cur)) {
343
+ if (want.length) host.selection.highlight(want);
344
+ else if (cur.length) host.selection.clear();
345
+ }
346
+ host.selection.setHidden?.(hiddenKeys().length);
338
347
  };
339
- const offHost = host.selection.onChange((idxs, source) => {
348
+ const offHost = host.selection.onChange((idxs, source, meta) => {
340
349
  if (source === "host") return;
341
- if (!idxs.length) {
350
+ const keep = meta?.keepHidden ? hiddenKeys() : [];
351
+ if (!idxs.length && !keep.length) {
342
352
  if (filter.active) filter.clear("clear");
343
353
  return;
344
354
  }
345
355
  const rows = idxs.map((i) => opts.rowAt(i)).filter((r) => !!r);
346
- if (!rows.length) return;
347
- filter.selectRows(rows, "click");
348
- owners.set(filter, { token, keys: ownerKeys(), orphan: false });
349
- });
350
- const offFilter = filter.onChange(() => {
351
- const o = owners.get(filter);
352
- if (o && o.keys !== ownerKeys()) owners.delete(filter);
353
- paint();
356
+ if (!rows.length && !keep.length) return;
357
+ filter.selectRows(rows, "click", keep);
354
358
  });
359
+ const offFilter = filter.onChange(() => paint());
355
360
  const el = opts.container ?? null;
356
361
  let offHoverDom = () => {
357
362
  };
@@ -388,20 +393,11 @@ function bindFilter(host, filter, opts) {
388
393
  offHover = filter.onHover(paintHover);
389
394
  }
390
395
  return {
396
+ // NEW DATA NEVER DROPS A SELECTION (contract 1.21.0). A key the new rows do not carry stays selected, whoever selected
397
+ // it, as Power BI keeps a selected row a slicer hid: the page goes on filtering by it, the chip goes on naming it, and the
398
+ // chart is told how many of its keys it cannot show (hostSelection.hidden) so it can say so and offer a clear. It used
399
+ // to be cleared here (reason "data") when this chart had made it, which lost a reader's pick to someone else's filter.
391
400
  reconcile() {
392
- if (filter.active && opts.rowCount() > 0 && isMine()) {
393
- const drawn = /* @__PURE__ */ new Set();
394
- const n = opts.rowCount();
395
- for (let i = 0; i < n; i++) {
396
- const r = opts.rowAt(i);
397
- if (r) drawn.add(keyString(keyOfRow(r, filter.columns)));
398
- }
399
- const keep = filter.keys.filter((k) => drawn.has(keyString(k)));
400
- if (keep.length !== filter.keys.length) {
401
- filter.set(keep, "data");
402
- return;
403
- }
404
- }
405
401
  paint();
406
402
  },
407
403
  paint,
@@ -410,13 +406,9 @@ function bindFilter(host, filter, opts) {
410
406
  offFilter();
411
407
  offHoverDom();
412
408
  offHover();
413
- const o = owners.get(filter);
414
- if (o && o.token === token) owners.set(filter, { ...o, orphan: true });
415
409
  }
416
410
  };
417
411
  }
418
- var owners = /* @__PURE__ */ new WeakMap();
419
- var keysString = (keys) => keys.map((k) => keyString(k)).sort().join("|");
420
412
  function fromVegaInteraction(filter, events) {
421
413
  const before = filter.version;
422
414
  for (const ev of events ?? []) {
@@ -1421,10 +1421,10 @@ function Sr2(e, t) {
1421
1421
  return n;
1422
1422
  }
1423
1423
  function Rr(e, t, n, o2, a3) {
1424
- let u3 = [], l2 = [], i = {}, C3 = {}, b2 = new Set(e), h3 = (s2) => t.map((d2) => d2[s2]);
1424
+ let u3 = [], l2 = [], i = {}, y3 = {}, h3 = new Set(e), b2 = (s2) => t.map((d2) => d2[s2]);
1425
1425
  for (let s2 of ["city", "country"]) {
1426
1426
  let d2 = n?.[s2];
1427
- d2 && b2.has(d2) && (i[s2] = d2);
1427
+ d2 && h3.has(d2) && (i[s2] = d2);
1428
1428
  }
1429
1429
  let g5 = new Set(a3 ?? e);
1430
1430
  for (let s2 of ["lat", "lon"]) {
@@ -1432,20 +1432,20 @@ function Rr(e, t, n, o2, a3) {
1432
1432
  d2 && g5.has(d2) && (i[s2] = d2);
1433
1433
  }
1434
1434
  let f2 = n?.zip;
1435
- if (f2 && b2.has(f2)) {
1436
- let s2 = h3(f2), d2 = ie(s2);
1435
+ if (f2 && h3.has(f2)) {
1436
+ let s2 = b2(f2), d2 = ie(s2);
1437
1437
  d2 < 95 ? l2.push(`zip=${f2} (only ${d2}% of values read as ZIPs)`) : pe(s2, f2) ? i.zip = f2 : l2.push(`zip=${f2} (all values are 3-4 digits with nothing to say they are postal)`);
1438
1438
  }
1439
1439
  let c = n?.state;
1440
- if (c && b2.has(c)) {
1441
- let s2 = h3(c), d2 = F3(s2);
1440
+ if (c && h3.has(c)) {
1441
+ let s2 = b2(c), d2 = F3(s2);
1442
1442
  d2.length > 0 && d2.every((S) => fe(S, o2)) ? l2.push(`state=${c} (every value is "CA", which is both Canada and California)`) : N(s2) ? (l2.push(`state=${c} (every value is a country, not a state)`), i.country || (i.country = c)) : q4(s2) < 95 ? l2.push(`state=${c} (only ${q4(s2)}% of values are states/provinces)`) : i.state = c;
1443
1443
  }
1444
- let p3 = new Set(Object.values(i).filter(Boolean)), y3 = e.filter((s2) => !p3.has(s2) && !s2.startsWith("__"));
1444
+ let p3 = new Set(Object.values(i).filter(Boolean)), C3 = e.filter((s2) => !p3.has(s2) && !s2.startsWith("__"));
1445
1445
  if (!i.state) {
1446
1446
  let s2 = null;
1447
- for (let d2 of y3) {
1448
- let S = h3(d2);
1447
+ for (let d2 of C3) {
1448
+ let S = b2(d2);
1449
1449
  if (N(S)) continue;
1450
1450
  let O2 = q4(S);
1451
1451
  if (O2 < 95) continue;
@@ -1454,46 +1454,46 @@ function Rr(e, t, n, o2, a3) {
1454
1454
  }
1455
1455
  s2 && (i.state = s2.name, p3.add(s2.name), u3.push(`state=${s2.name} (${s2.pct}% states/provinces)`));
1456
1456
  }
1457
- if (!i.zip) for (let s2 of y3) {
1457
+ if (!i.zip) for (let s2 of C3) {
1458
1458
  if (p3.has(s2)) continue;
1459
- let d2 = h3(s2), S = ie(d2);
1459
+ let d2 = b2(s2), S = ie(d2);
1460
1460
  if (!(S < 95) && pe(d2, s2) && !(Sr2(d2, (O2) => Gn(O2).length > 0) < ee)) {
1461
1461
  i.zip = s2, p3.add(s2), u3.push(`zip=${s2} (${S}% ZIP codes)`);
1462
1462
  break;
1463
1463
  }
1464
1464
  }
1465
1465
  let T3 = i.country;
1466
- if (!T3 || !N(h3(T3))) {
1466
+ if (!T3 || !N(b2(T3))) {
1467
1467
  let s2 = null;
1468
- for (let d2 of y3) {
1469
- if (p3.has(d2) || !N(h3(d2))) continue;
1470
- let S = re(h3(d2));
1468
+ for (let d2 of C3) {
1469
+ if (p3.has(d2) || !N(b2(d2))) continue;
1470
+ let S = re(b2(d2));
1471
1471
  (!s2 || S > s2.pct) && (s2 = { name: d2, pct: S });
1472
1472
  }
1473
- s2 && (T3 && (l2.push(`country=${T3} (only ${re(h3(T3))}% of values are country identifiers; using ${s2.name} instead)`), C3.country = T3), i.country = s2.name, p3.add(s2.name), u3.push(`country=${s2.name}`));
1473
+ s2 && (T3 && (l2.push(`country=${T3} (only ${re(b2(T3))}% of values are country identifiers; using ${s2.name} instead)`), y3.country = T3), i.country = s2.name, p3.add(s2.name), u3.push(`country=${s2.name}`));
1474
1474
  }
1475
1475
  if (!i.city) {
1476
1476
  let s2 = null;
1477
- for (let d2 of y3) {
1477
+ for (let d2 of C3) {
1478
1478
  if (p3.has(d2)) continue;
1479
- let S = h3(d2), O2 = Tr2(S, o2);
1479
+ let S = b2(d2), O2 = Tr2(S, o2);
1480
1480
  O2 < ct || te(S, (H3) => Ht(H3, o2)) < ee || (!s2 || O2 > s2.pct) && (s2 = { name: d2, pct: O2 });
1481
1481
  }
1482
1482
  s2 && (i.city = s2.name, u3.push(`city=${s2.name} (${s2.pct}% known cities)`));
1483
1483
  }
1484
- let v2 = i.country ? h3(i.country) : [], R3 = !!i.country && N(v2), L3 = R3 ? new Set(v2.map((s2) => I(s2 == null ? null : String(s2))).filter(Boolean)).size : 0, x3 = R3 && L3 >= 2, w4 = !!(i.lat && i.lon) && t.some((s2) => {
1484
+ let A2 = i.country ? b2(i.country) : [], R3 = !!i.country && N(A2), v2 = R3 ? new Set(A2.map((s2) => I(s2 == null ? null : String(s2))).filter(Boolean)).size : 0, x3 = R3 && v2 >= 2, w4 = !!(i.lat && i.lon) && t.some((s2) => {
1485
1485
  let d2 = +String(s2[i.lat] ?? "").trim(), S = +String(s2[i.lon] ?? "").trim();
1486
1486
  return isFinite(d2) && isFinite(S) && d2 >= -90 && d2 <= 90 && S >= -180 && S <= 180 && String(s2[i.lat] ?? "").trim() !== "" && String(s2[i.lon] ?? "").trim() !== "";
1487
1487
  });
1488
- return i.lat && i.lon && !w4 && l2.push(`lat/lon=${i.lat}/${i.lon} (no row holds a usable coordinate pair)`), i.country && !x3 && !(i.city || i.state || i.zip || w4) && l2.push(R3 ? `country=${i.country} (every row resolves to the same country - nothing to place apart)` : `country=${i.country} (values are not country identifiers)`), { bind: !!(i.city || i.state || i.zip || x3 || w4) ? i : null, backfilled: u3, refused: l2, ...Object.keys(C3).length ? { labelFallback: C3 } : {} };
1488
+ return i.lat && i.lon && !w4 && l2.push(`lat/lon=${i.lat}/${i.lon} (no row holds a usable coordinate pair)`), i.country && !x3 && !(i.city || i.state || i.zip || w4) && l2.push(R3 ? `country=${i.country} (every row resolves to the same country - nothing to place apart)` : `country=${i.country} (values are not country identifiers)`), { bind: !!(i.city || i.state || i.zip || x3 || w4) ? i : null, backfilled: u3, refused: l2, ...Object.keys(y3).length ? { labelFallback: y3 } : {} };
1489
1489
  }
1490
1490
  var r = (e, ...t) => ({ part: e, langs: Object.freeze(t) });
1491
1491
  var ae = Object.freeze({ jaar: r("year", "nl"), kwartaal: r("quarter", "nl"), maand: r("month", "nl"), dag: r("day", "nl", "sv", "da", "nb"), jahr: r("year", "de"), quartal: r("quarter", "de"), monat: r("month", "de"), tag: r("day", "de"), ann\u00E9e: r("year", "fr"), mois: r("month", "fr"), jour: r("day", "fr"), trimestre: r("quarter", "fr", "es", "pt", "it"), a\u00F1o: r("year", "es"), mes: r("month", "es"), d\u00EDa: r("day", "es"), ano: r("year", "pt"), m\u00EAs: r("month", "pt"), dia: r("day", "pt"), anno: r("year", "it"), mese: r("month", "it"), giorno: r("day", "it"), \u0433\u043E\u0434: r("year", "ru"), \u043C\u0435\u0441\u044F\u0446: r("month", "ru"), \u0440\u0456\u043A: r("year", "uk"), \u043C\u0456\u0441\u044F\u0446\u044C: r("month", "uk"), \u043A\u0432\u0430\u0440\u0442\u0430\u043B: r("quarter", "ru", "uk"), \u0434\u0435\u043D\u044C: r("day", "ru", "uk"), rok: r("year", "pl", "cs", "sk"), kwarta\u0142: r("quarter", "pl"), miesi\u0105c: r("month", "pl"), dzie\u0144: r("day", "pl"), \u010Dtvrtlet\u00ED: r("quarter", "cs"), m\u011Bs\u00EDc: r("month", "cs"), den: r("day", "cs"), \u0161tvr\u0165rok: r("quarter", "sk"), mesiac: r("month", "sk"), de\u0148: r("day", "sk"), \u00E5r: r("year", "sv", "da", "nb"), kvartal: r("quarter", "sv", "da", "nb"), m\u00E5nad: r("month", "sv"), m\u00E5ned: r("month", "da", "nb"), vuosi: r("year", "fi"), vuosinelj\u00E4nnes: r("quarter", "fi"), kuukausi: r("month", "fi"), p\u00E4iv\u00E4: r("day", "fi"), \u00E9v: r("year", "hu"), negyed\u00E9v: r("quarter", "hu"), h\u00F3nap: r("month", "hu"), nap: r("day", "hu"), y\u0131l: r("year", "tr"), \u00E7eyrek: r("quarter", "tr"), ay: r("month", "tr"), g\u00FCn: r("day", "tr"), \u03AD\u03C4\u03BF\u03C2: r("year", "el"), \u03C4\u03C1\u03AF\u03BC\u03B7\u03BD\u03BF: r("quarter", "el"), \u03BC\u03AE\u03BD\u03B1\u03C2: r("month", "el"), \u03B7\u03BC\u03AD\u03C1\u03B1: r("day", "el"), an: r("year", "ro"), trimestru: r("quarter", "ro"), lun\u0103: r("month", "ro"), zi: r("day", "ro"), godina: r("year", "hr"), tromjese\u010Dje: r("quarter", "hr"), mjesec: r("month", "hr"), dan: r("day", "hr"), \u5E74: r("year", "ja", "zh"), \u56DB\u534A\u671F: r("quarter", "ja"), \u5B63\u5EA6: r("quarter", "zh"), \u6708: r("month", "ja", "zh"), \u65E5: r("day", "ja", "zh"), \uC5F0\uB3C4: r("year", "ko"), \uBD84\uAE30: r("quarter", "ko"), \uC6D4: r("month", "ko"), \uC77C: r("day", "ko"), tahun: r("year", "id"), kuartal: r("quarter", "id"), triwulan: r("quarter", "id"), bulan: r("month", "id"), hari: r("day", "id"), n\u0103m: r("year", "vi"), qu\u00FD: r("quarter", "vi"), th\u00E1ng: r("month", "vi"), ng\u00E0y: r("day", "vi"), \u0E1B\u0E35: r("year", "th"), \u0E44\u0E15\u0E23\u0E21\u0E32\u0E2A: r("quarter", "th"), \u0E40\u0E14\u0E37\u0E2D\u0E19: r("month", "th"), \u0E27\u0E31\u0E19: r("day", "th"), \u0627\u0644\u0633\u0646\u0629: r("year", "ar"), \u0633\u0646\u0629: r("year", "ar"), \u0627\u0644\u0639\u0627\u0645: r("year", "ar"), \u0639\u0627\u0645: r("year", "ar"), \u0627\u0644\u0631\u0628\u0639: r("quarter", "ar"), \u0631\u0628\u0639: r("quarter", "ar"), "\u0631\u0628\u0639 \u0627\u0644\u0633\u0646\u0629": r("quarter", "ar"), \u0627\u0644\u0634\u0647\u0631: r("month", "ar"), \u0634\u0647\u0631: r("month", "ar"), \u0627\u0644\u064A\u0648\u0645: r("day", "ar"), \u064A\u0648\u0645: r("day", "ar"), \u05E9\u05E0\u05D4: r("year", "he"), \u05E8\u05D1\u05E2\u05D5\u05DF: r("quarter", "he"), \u05D7\u05D5\u05D3\u05E9: r("month", "he"), \u05D9\u05D5\u05DD: r("day", "he"), \u0935\u0930\u094D\u0937: r("year", "hi"), \u0938\u093E\u0932: r("year", "hi"), \u0924\u093F\u092E\u093E\u0939\u0940: r("quarter", "hi"), \u092E\u0939\u0940\u0928\u093E: r("month", "hi"), \u092E\u093E\u0939: r("month", "hi"), \u0926\u093F\u0928: r("day", "hi"), \u0633\u0627\u0644: r("year", "fa"), \u0645\u0627\u0647: r("month", "fa"), \u0631\u0648\u0632: r("day", "fa") });
1492
1492
  var xr = Object.freeze(Array.from(new Set(Object.values(ae).flatMap((e) => e.langs))));
1493
1493
  var ye = Object.freeze(["fa", "ar", "he", "th"]);
1494
- var no = Object.freeze({ integer: "number", decimal: "number", double: "number", datetime: "date", date: "date", boolean: "boolean", string: "text" });
1495
- var co = Object.freeze({ RENDER_START: "render-start", RENDER_OK: "render-ok", RENDER_ERROR: "render-error", VIEW: "view", VIEW_VERDICT: "view-verdict", REDRAW: "redraw", INTERACT: "interact" });
1496
- var mo = Object.freeze(["open", "generate", "version", "rebind", "data", "sample", "fix", "resize", "other"]);
1494
+ var ro = Object.freeze({ integer: "number", decimal: "number", double: "number", datetime: "date", date: "date", boolean: "boolean", string: "text" });
1495
+ var mo = Object.freeze({ RENDER_START: "render-start", RENDER_OK: "render-ok", RENDER_ERROR: "render-error", VIEW: "view", VIEW_VERDICT: "view-verdict", REDRAW: "redraw", INTERACT: "interact" });
1496
+ var fo = Object.freeze(["open", "generate", "version", "rebind", "data", "sample", "fix", "resize", "other"]);
1497
1497
  var Ne = 2 ** 31 - 1;
1498
1498
 
1499
1499
  export {
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  CONTAINER_SLOT_SCROLL,
4
4
  SNAPSHOT_SVG_ATTR
5
- } from "./chunk-7XRQUFVH.mjs";
5
+ } from "./chunk-USZSHKIB.mjs";
6
6
 
7
7
  // src/fit.ts
8
8
  var SCROLL_SLACK_PX = 8;
@@ -1,7 +1,7 @@
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
 
3
3
  // src/contract.ts
4
- var HOST_CONTRACT_VERSION = "1.20.0";
4
+ var HOST_CONTRACT_VERSION = "1.22.0";
5
5
  var GEO_POINT_PRECISIONS = ["latlon", "city", "zip3", "state", "country"];
6
6
  var MARK_CLASS = "d3-mark";
7
7
  var LEGEND_MARK_CLASS = "d3-legend-mark";
@@ -16,6 +16,7 @@ var MARK_KEY_ATTR = "data-mark-key";
16
16
  var NO_ROW_MARKS_ATTR = "data-lch-no-row-marks";
17
17
  var SNAPSHOT_SVG_ATTR = "data-lch-snapshot";
18
18
  var XFILTER_REFRESH_EVENT = "llm-xfilter-refresh";
19
+ var CONTAINER_SLOT_HOST_SELECTION = "__lchHostSelection";
19
20
  var CONTAINER_SLOT_ANIM_STOP = "__llmAnimStop";
20
21
  var CONTAINER_SLOT_XF_CLEAR = "__llmXfClear";
21
22
  var CONTAINER_SLOT_INITIAL_XF_MARK = "__llmInitialXfMark";
@@ -33,6 +34,7 @@ function withoutViewOnlyKeys(bag) {
33
34
  var HOST_CONTAINER_CLASS = "bic-chart-host";
34
35
  var SELECTION_ACTIVE_CLASS = "lch-has-selection";
35
36
  var MARK_SELECTED_CLASS = "lch-mark-selected";
37
+ var MARKS_INERT_CLASS = "lch-marks-inert";
36
38
  var ACTIVE_TICK_CLASS = "lch-tick-active";
37
39
  var DIM_OPACITY_VAR = "--lch-dim-opacity";
38
40
  var DIM_OPACITY_DEFAULT = 0.25;
@@ -88,6 +90,7 @@ export {
88
90
  NO_ROW_MARKS_ATTR,
89
91
  SNAPSHOT_SVG_ATTR,
90
92
  XFILTER_REFRESH_EVENT,
93
+ CONTAINER_SLOT_HOST_SELECTION,
91
94
  CONTAINER_SLOT_ANIM_STOP,
92
95
  CONTAINER_SLOT_XF_CLEAR,
93
96
  CONTAINER_SLOT_INITIAL_XF_MARK,
@@ -99,6 +102,7 @@ export {
99
102
  HOST_CONTAINER_CLASS,
100
103
  SELECTION_ACTIVE_CLASS,
101
104
  MARK_SELECTED_CLASS,
105
+ MARKS_INERT_CLASS,
102
106
  ACTIVE_TICK_CLASS,
103
107
  DIM_OPACITY_VAR,
104
108
  DIM_OPACITY_DEFAULT,
package/dist/index.mjs CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  formatSourceDateFor,
6
6
  isExcelDateFormat,
7
7
  normaliseAggregation
8
- } from "./chunk-MU4BWWO6.mjs";
8
+ } from "./chunk-G4CKILIL.mjs";
9
9
  import {
10
10
  captureSvgSnapshot,
11
11
  chartSvgOf,
@@ -15,7 +15,7 @@ import {
15
15
  svgNaturalSize,
16
16
  svgToDataUrl,
17
17
  tableHostOf
18
- } from "./chunk-PA5V6J6K.mjs";
18
+ } from "./chunk-3EQOJHRA.mjs";
19
19
  import {
20
20
  ANNOTATION_CLASS,
21
21
  ANNOTATION_LAYER_CLASS,
@@ -29,6 +29,8 @@ import {
29
29
  DARK_TEXT,
30
30
  EXPORT_FORMATS,
31
31
  GLYPH_SAMPLE_N,
32
+ KEYBOARD_CLASS,
33
+ KEYBOARD_STAMP,
32
34
  LABEL_CONTRAST_CAP,
33
35
  LABEL_CONTRAST_DONE_ATTR,
34
36
  LABEL_PILL_CLASS,
@@ -47,6 +49,7 @@ import {
47
49
  STRADDLE_TARGET_CONTRAST,
48
50
  VALUE_AXIS_MIN_FIT,
49
51
  WHITE_TEXT_BG_LUM,
52
+ WIRED_ATTR,
50
53
  XLSX_MIME,
51
54
  applyLabelContrast,
52
55
  assembleD3,
@@ -63,7 +66,9 @@ import {
63
66
  censusColourSpread,
64
67
  censusMarks,
65
68
  censusValuePlacement,
69
+ cleanHostSelection,
66
70
  clippedTextFlag,
71
+ codeHasKeyboardStamp,
67
72
  colourSpreadFlag,
68
73
  compileRenderFn,
69
74
  compositeOver,
@@ -79,6 +84,7 @@ import {
79
84
  exportFormatsFor,
80
85
  exportTableService,
81
86
  glyphSampleGrid,
87
+ installKeyboard,
82
88
  invalidSentinelReason,
83
89
  isBlankRender,
84
90
  isInvalidSentinelError,
@@ -89,9 +95,12 @@ import {
89
95
  pickColorOver,
90
96
  pillBacksGlyph,
91
97
  relativeLuminance,
98
+ rememberFocus,
92
99
  requiredD3Plugins,
93
100
  resolveAutoColorScale,
94
101
  resolveOptions,
102
+ restoreFocus,
103
+ rowNameOf,
95
104
  scopeChartIds,
96
105
  sessionViewStateProvider,
97
106
  sheetName,
@@ -105,7 +114,7 @@ import {
105
114
  toRGBA,
106
115
  toSourceRows,
107
116
  valuePlacementFlag
108
- } from "./chunk-BWR35DEK.mjs";
117
+ } from "./chunk-JQ7FFCOE.mjs";
109
118
  import {
110
119
  LASSO_AXES_SLOT,
111
120
  LASSO_COUNT_CLASS,
@@ -132,13 +141,13 @@ import {
132
141
  lassoVerdict,
133
142
  pointInShape,
134
143
  registerLassoAction
135
- } from "./chunk-IE426WU6.mjs";
144
+ } from "./chunk-4DOKJ3R3.mjs";
136
145
  import {
137
146
  MIN_HIT_BAND_PX,
138
147
  censusHitBands,
139
148
  ensureCrossfilterHitTargets,
140
149
  hitBandFlag
141
- } from "./chunk-CPLWAW3Z.mjs";
150
+ } from "./chunk-GQLEU3VC.mjs";
142
151
  import {
143
152
  CONTAINER_SLOT_PRESS_AT,
144
153
  DRAG_NOT_CLICK_PX,
@@ -163,7 +172,7 @@ import {
163
172
  selectionRuleOf,
164
173
  trackPress,
165
174
  validRowSet
166
- } from "./chunk-P2DLK7WZ.mjs";
175
+ } from "./chunk-3ER4C7TG.mjs";
167
176
  import {
168
177
  AXIS_PIN_BAND_PAD_PX,
169
178
  AXIS_PIN_MAX_BAND_FRACTION,
@@ -192,7 +201,7 @@ import {
192
201
  svgInkReach,
193
202
  takeScroll,
194
203
  unpinScrolledAxis
195
- } from "./chunk-IE7TM6DX.mjs";
204
+ } from "./chunk-TN5JRULV.mjs";
196
205
  import {
197
206
  clearGeoCache,
198
207
  geoAssetFor,
@@ -205,7 +214,7 @@ import {
205
214
  Kt,
206
215
  l,
207
216
  o
208
- } from "./chunk-SYUJ4TPX.mjs";
217
+ } from "./chunk-TH577JHI.mjs";
209
218
  import "./chunk-A2GMXZP7.mjs";
210
219
  import {
211
220
  ACTIVE_TICK_CLASS,
@@ -225,6 +234,7 @@ import {
225
234
  COLOR_SCALE_SELF_CLAMP_PCT_MIN,
226
235
  CONTAINER_SLOT_ANIM_STOP,
227
236
  CONTAINER_SLOT_CLICKED_MARKS,
237
+ CONTAINER_SLOT_HOST_SELECTION,
228
238
  CONTAINER_SLOT_INITIAL_XF_MARK,
229
239
  CONTAINER_SLOT_SCROLL,
230
240
  CONTAINER_SLOT_UI_STATE,
@@ -242,6 +252,7 @@ import {
242
252
  HOST_CONTRACT_VERSION,
243
253
  LEGEND_MARK_CLASS,
244
254
  LIFT_SELECTED_CLASS,
255
+ MARKS_INERT_CLASS,
245
256
  MARK_CLASS,
246
257
  MARK_KEY_ATTR,
247
258
  MARK_SELECTED_CLASS,
@@ -260,7 +271,7 @@ import {
260
271
  chartOwnsTimeline,
261
272
  periodTickSuppressesFeedback,
262
273
  withoutViewOnlyKeys
263
- } from "./chunk-7XRQUFVH.mjs";
274
+ } from "./chunk-USZSHKIB.mjs";
264
275
  import "./chunk-GHODWOAL.mjs";
265
276
 
266
277
  // src/hostLinks.ts
@@ -2330,6 +2341,7 @@ export {
2330
2341
  COLOR_SCALE_SELF_CLAMP_PCT_MIN,
2331
2342
  CONTAINER_SLOT_ANIM_STOP,
2332
2343
  CONTAINER_SLOT_CLICKED_MARKS,
2344
+ CONTAINER_SLOT_HOST_SELECTION,
2333
2345
  CONTAINER_SLOT_INITIAL_XF_MARK,
2334
2346
  CONTAINER_SLOT_PRESS_AT,
2335
2347
  CONTAINER_SLOT_SCROLL,
@@ -2365,6 +2377,9 @@ export {
2365
2377
  HOST_CONTAINER_CLASS,
2366
2378
  HOST_CONTRACT_VERSION,
2367
2379
  INLINE_FILTER_MIN_ROWS,
2380
+ KEYBOARD_CLASS,
2381
+ KEYBOARD_STAMP,
2382
+ WIRED_ATTR as KEYBOARD_WIRED_ATTR,
2368
2383
  LABEL_CONTRAST_CAP,
2369
2384
  LABEL_CONTRAST_DONE_ATTR,
2370
2385
  LABEL_PILL_CLASS,
@@ -2391,6 +2406,7 @@ export {
2391
2406
  LIGHT_TEXT,
2392
2407
  LIMIT_COUNT_MAX,
2393
2408
  LIVE_OPTION_KEYS,
2409
+ MARKS_INERT_CLASS,
2394
2410
  MARK_CLASS,
2395
2411
  MARK_KEY_ATTR,
2396
2412
  MARK_SELECTED_CLASS,
@@ -2477,12 +2493,14 @@ export {
2477
2493
  chartOwnsTimeline,
2478
2494
  chartSvgOf,
2479
2495
  chooserFitsViewport,
2496
+ cleanHostSelection,
2480
2497
  clearGeoCache,
2481
2498
  clearLasso,
2482
2499
  clearPress,
2483
2500
  clearSelectionGlyphs,
2484
2501
  clickWasDrag,
2485
2502
  clippedTextFlag,
2503
+ codeHasKeyboardStamp,
2486
2504
  codeReadsDatesInLocalTime,
2487
2505
  codeReadsOption,
2488
2506
  collectD3GlyphCenters,
@@ -2533,6 +2551,7 @@ export {
2533
2551
  htmlNaturalSize,
2534
2552
  htmlToSvgDataUrl,
2535
2553
  inlineFilterGate,
2554
+ installKeyboard,
2536
2555
  installLasso,
2537
2556
  invalidSentinelReason,
2538
2557
  isBlankRender,
@@ -2626,11 +2645,14 @@ export {
2626
2645
  registerGeoAsset,
2627
2646
  registerLassoAction,
2628
2647
  relativeLuminance,
2648
+ rememberFocus,
2629
2649
  rememberScroll,
2630
2650
  requiredD3Plugins,
2631
2651
  resolveAutoColorScale,
2632
2652
  resolveOptions,
2653
+ restoreFocus,
2633
2654
  rowIdxsFromMark,
2655
+ rowNameOf,
2634
2656
  sameMarker,
2635
2657
  sameRowSet,
2636
2658
  scopeChartIds,
@@ -2,13 +2,13 @@
2
2
  import {
3
3
  chartSvgOf,
4
4
  tableHostOf
5
- } from "./chunk-PA5V6J6K.mjs";
5
+ } from "./chunk-3EQOJHRA.mjs";
6
6
  import {
7
7
  FIT_CONTENT_SELECTOR,
8
8
  ctmScaleOf,
9
9
  isPhantomBox
10
- } from "./chunk-IE7TM6DX.mjs";
11
- import "./chunk-7XRQUFVH.mjs";
10
+ } from "./chunk-TN5JRULV.mjs";
11
+ import "./chunk-USZSHKIB.mjs";
12
12
  import "./chunk-GHODWOAL.mjs";
13
13
 
14
14
  // src/legendFit/legendReconcile.ts
package/dist/page.mjs CHANGED
@@ -14,10 +14,10 @@ import {
14
14
  readControls,
15
15
  viewFromToken,
16
16
  viewToken
17
- } from "./chunk-TLIBO5PT.mjs";
18
- import "./chunk-IE426WU6.mjs";
19
- import "./chunk-P2DLK7WZ.mjs";
20
- import "./chunk-7XRQUFVH.mjs";
17
+ } from "./chunk-QAPZIFOB.mjs";
18
+ import "./chunk-4DOKJ3R3.mjs";
19
+ import "./chunk-3ER4C7TG.mjs";
20
+ import "./chunk-USZSHKIB.mjs";
21
21
  import "./chunk-GHODWOAL.mjs";
22
22
  export {
23
23
  LINKED_HOVER_CLASS,
@@ -7,7 +7,7 @@ import {
7
7
  Si,
8
8
  W,
9
9
  bt
10
- } from "./chunk-SYUJ4TPX.mjs";
10
+ } from "./chunk-TH577JHI.mjs";
11
11
  import "./chunk-A2GMXZP7.mjs";
12
12
  import "./chunk-GHODWOAL.mjs";
13
13
 
package/dist/react.mjs CHANGED
@@ -13,25 +13,25 @@ import {
13
13
  payloadRowReader,
14
14
  viewFromToken,
15
15
  viewToken
16
- } from "./chunk-TLIBO5PT.mjs";
16
+ } from "./chunk-QAPZIFOB.mjs";
17
17
  import {
18
18
  assembleD3,
19
19
  createChartGroup,
20
20
  createChartHost,
21
21
  syncMemberSelection,
22
22
  toSourceRows
23
- } from "./chunk-BWR35DEK.mjs";
24
- import "./chunk-IE426WU6.mjs";
25
- import "./chunk-CPLWAW3Z.mjs";
26
- import "./chunk-P2DLK7WZ.mjs";
27
- import "./chunk-IE7TM6DX.mjs";
23
+ } from "./chunk-JQ7FFCOE.mjs";
24
+ import "./chunk-4DOKJ3R3.mjs";
25
+ import "./chunk-GQLEU3VC.mjs";
26
+ import "./chunk-3ER4C7TG.mjs";
27
+ import "./chunk-TN5JRULV.mjs";
28
28
  import {
29
29
  geoFromCache,
30
30
  loadGeo
31
31
  } from "./chunk-5WTQN5DL.mjs";
32
- import "./chunk-SYUJ4TPX.mjs";
32
+ import "./chunk-TH577JHI.mjs";
33
33
  import "./chunk-A2GMXZP7.mjs";
34
- import "./chunk-7XRQUFVH.mjs";
34
+ import "./chunk-USZSHKIB.mjs";
35
35
  import "./chunk-GHODWOAL.mjs";
36
36
 
37
37
  // src/react.tsx
@@ -185,7 +185,11 @@ function BicChart(props) {
185
185
  // siblings of a chart that has an id in a group. This binding always
186
186
  // subscribes to the selection (for onSelect), so the host cannot count
187
187
  // subscribers here; an onSelect callback alone is not the page's filter.
188
- selectionReachesPage: () => !!reachRef.current.selects || !!(reachRef.current.group && reachRef.current.id)
188
+ selectionReachesPage: () => !!reachRef.current.selects || !!(reachRef.current.group && reachRef.current.id),
189
+ // Whether a click on a mark does anything at all: the same two,
190
+ // or an onSelect the page passed. A chart with none of them draws its marks
191
+ // inert rather than dimming the others for a click that filters nothing.
192
+ marksSelect: () => !!reachRef.current.selects || !!(reachRef.current.group && reachRef.current.id) || typeof onSelectRef.current === "function"
189
193
  });
190
194
  hostRef.current = host;
191
195
  builtAnnKeyRef.current = annKey;
package/dist/testing.mjs CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  MARK_CLASS,
5
5
  MARK_SELECTED_CLASS,
6
6
  ROW_IDX_ATTR
7
- } from "./chunk-7XRQUFVH.mjs";
7
+ } from "./chunk-USZSHKIB.mjs";
8
8
  import "./chunk-GHODWOAL.mjs";
9
9
 
10
10
  // src/testing/interact.ts
@@ -40,4 +40,6 @@ export interface AnnotationLayer {
40
40
  readonly report: AnnotationReport;
41
41
  destroy(): void;
42
42
  }
43
- export declare function createAnnotationLayer(container: HTMLElement, onClick?: (a: MarkAnnotation) => void): AnnotationLayer;
43
+ export declare function createAnnotationLayer(container: HTMLElement, onClick?: (a: MarkAnnotation) => void, opts?: {
44
+ keyboard?: () => boolean;
45
+ }): AnnotationLayer;
@@ -1,5 +1,5 @@
1
1
  import type { ExportFormat, ExportTableService, SaveFileService } from "./exportTable";
2
- export declare const HOST_CONTRACT_VERSION = "1.20.0";
2
+ export declare const HOST_CONTRACT_VERSION = "1.22.0";
3
3
  export type GeoPointPrecision = "latlon" | "city" | "zip3" | "state" | "country";
4
4
  /** Every valid tier, ordered most precise → coarsest. Runtime form of GeoPointPrecision. */
5
5
  export declare const GEO_POINT_PRECISIONS: readonly GeoPointPrecision[];
@@ -32,7 +32,25 @@ export type XfilterRefreshDetail = {
32
32
  } | {
33
33
  rows: readonly number[];
34
34
  source?: string;
35
+ keepHidden?: boolean;
35
36
  };
37
+ /**
38
+ * WHAT THE HOST HOLDS OF THE SELECTION (1.21.0), as RenderOptions.hostSelection on a draw and as the argument of the
39
+ * CONTAINER_SLOT_HOST_SELECTION slot between draws. Untrusted on the chart side like every option: rows are this draw's
40
+ * row indices (whole, non-negative), hidden a count.
41
+ */
42
+ export interface HostSelectionFact {
43
+ /** Row indices of this draw's data the host's selection holds, ascending. */
44
+ rows: readonly number[];
45
+ /** Held identities that match no row of this draw: a filter hid them, and the host still filters by them. */
46
+ hidden: number;
47
+ /** Set when the host kept fewer identities than a publish gave it. */
48
+ narrowed?: {
49
+ published: number;
50
+ kept: number;
51
+ };
52
+ }
53
+ export declare const CONTAINER_SLOT_HOST_SELECTION = "__lchHostSelection";
36
54
  export declare const CONTAINER_SLOT_ANIM_STOP = "__llmAnimStop";
37
55
  export declare const CONTAINER_SLOT_XF_CLEAR = "__llmXfClear";
38
56
  export declare const CONTAINER_SLOT_INITIAL_XF_MARK = "__llmInitialXfMark";
@@ -72,6 +90,7 @@ export interface ViewStateProvider {
72
90
  export declare const HOST_CONTAINER_CLASS = "bic-chart-host";
73
91
  export declare const SELECTION_ACTIVE_CLASS = "lch-has-selection";
74
92
  export declare const MARK_SELECTED_CLASS = "lch-mark-selected";
93
+ export declare const MARKS_INERT_CLASS = "lch-marks-inert";
75
94
  export declare const ACTIVE_TICK_CLASS = "lch-tick-active";
76
95
  export declare const DIM_OPACITY_VAR = "--lch-dim-opacity";
77
96
  export declare const DIM_OPACITY_DEFAULT = 0.25;
@@ -129,6 +148,7 @@ export interface RenderOptions {
129
148
  dataComplete?: boolean;
130
149
  rowsWithheld?: number;
131
150
  rowsFilteredOut?: number;
151
+ hostSelection?: HostSelectionFact;
132
152
  openUrl?: (url: string) => void;
133
153
  copyText?: (text: string) => boolean | void | Promise<boolean | void>;
134
154
  saveFile?: SaveFileService;
@@ -177,6 +197,10 @@ export interface RenderOptions {
177
197
  selectionGlyph?: "none" | "dot" | "check";
178
198
  /** A host FACT from the generate answer: this chart's family never takes a selection glyph. */
179
199
  suppressSelectionGlyph?: boolean;
200
+ /** A host FACT: this chart works from the keyboard (its code carries the keyboard stamp), so the host has made its
201
+ * selectable marks focusable. A chart or helper drawing its own controls (a flip arrow, a sort header) gives them
202
+ * a tabindex, a role and an Enter / Space press when this is true. */
203
+ keyboardMarks?: boolean;
180
204
  animAutoPlay?: boolean;
181
205
  animPlaySpeedMs?: number;
182
206
  animLoopDelaySec?: number;