@bicharts/chart-host 0.6.106 → 0.6.108

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/dist/adapters.mjs CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  censusHitBands,
4
4
  ensureCrossfilterHitTargets,
5
5
  hitBandFlag
6
- } from "./chunk-CPLWAW3Z.mjs";
6
+ } from "./chunk-UKXGOQMS.mjs";
7
7
  import {
8
8
  clickWasDrag,
9
9
  collectD3GlyphCenters,
@@ -12,13 +12,13 @@ import {
12
12
  markKeyOf,
13
13
  rowIdxsFromMark,
14
14
  selectionRuleOf
15
- } from "./chunk-P2DLK7WZ.mjs";
15
+ } from "./chunk-LGWTV5PB.mjs";
16
16
  import {
17
17
  AXIS_FILTER_CLASS,
18
18
  LEGEND_MARK_CLASS,
19
19
  MARK_CLASS,
20
20
  ROW_IDX_ATTR
21
- } from "./chunk-7XRQUFVH.mjs";
21
+ } from "./chunk-PHUUFCJY.mjs";
22
22
  import "./chunk-GHODWOAL.mjs";
23
23
 
24
24
  // src/adapters/types.ts
@@ -4,7 +4,7 @@ import {
4
4
  gestureWasDrag,
5
5
  isInsideControl,
6
6
  rowIdxsFromMark
7
- } from "./chunk-P2DLK7WZ.mjs";
7
+ } from "./chunk-LGWTV5PB.mjs";
8
8
  import {
9
9
  AXIS_FILTER_CLASS,
10
10
  CONTROL_CLASS,
@@ -12,7 +12,7 @@ import {
12
12
  MARK_CLASS,
13
13
  ROW_IDX_ATTR,
14
14
  SNAPSHOT_SVG_ATTR
15
- } from "./chunk-7XRQUFVH.mjs";
15
+ } from "./chunk-PHUUFCJY.mjs";
16
16
 
17
17
  // src/lasso.ts
18
18
  var LASSO_ROW_CAP = 5e3;
@@ -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
  SNAPSHOT_SVG_ATTR
4
- } from "./chunk-7XRQUFVH.mjs";
4
+ } from "./chunk-PHUUFCJY.mjs";
5
5
 
6
6
  // src/snapshot.ts
7
7
  var DEFAULT_TIMEOUT_MS = 2e3;
@@ -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-ESBH2L6E.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 ?? []) {
@@ -8,7 +8,7 @@ import {
8
8
  SELECTION_RULE_ATTR,
9
9
  SELECTION_RULE_CLICKED_MARKS,
10
10
  XFILTER_REFRESH_EVENT
11
- } from "./chunk-7XRQUFVH.mjs";
11
+ } from "./chunk-PHUUFCJY.mjs";
12
12
 
13
13
  // src/selection.ts
14
14
  function rowIdxsFromMark(el) {
@@ -4,11 +4,11 @@ import {
4
4
  claimParkedLasso,
5
5
  installLasso,
6
6
  lassoEffect
7
- } from "./chunk-IE426WU6.mjs";
7
+ } from "./chunk-ESBH2L6E.mjs";
8
8
  import {
9
9
  censusHitBands,
10
10
  ensureCrossfilterHitTargets
11
- } from "./chunk-CPLWAW3Z.mjs";
11
+ } from "./chunk-UKXGOQMS.mjs";
12
12
  import {
13
13
  clearPress,
14
14
  clearSelectionGlyphs,
@@ -25,14 +25,14 @@ import {
25
25
  selectionRuleOf,
26
26
  trackPress,
27
27
  validRowSet
28
- } from "./chunk-P2DLK7WZ.mjs";
28
+ } from "./chunk-LGWTV5PB.mjs";
29
29
  import {
30
30
  clipWindowOf,
31
31
  fitRenderedChart,
32
32
  rememberScroll,
33
33
  takeScroll,
34
34
  unpinScrolledAxis
35
- } from "./chunk-IE7TM6DX.mjs";
35
+ } from "./chunk-OSREEGBN.mjs";
36
36
  import {
37
37
  geoFromCache
38
38
  } from "./chunk-5WTQN5DL.mjs";
@@ -61,6 +61,7 @@ import {
61
61
  COLOR_SCALE_SELF_CLAMP_PCT_MIN,
62
62
  CONTAINER_SLOT_ANIM_STOP,
63
63
  CONTAINER_SLOT_CLICKED_MARKS,
64
+ CONTAINER_SLOT_HOST_SELECTION,
64
65
  CONTAINER_SLOT_INITIAL_XF_MARK,
65
66
  CONTAINER_SLOT_UI_STATE,
66
67
  CONTAINER_SLOT_XF_CLEAR,
@@ -86,7 +87,7 @@ import {
86
87
  XFILTER_REFRESH_EVENT,
87
88
  chartOwnsTimeline,
88
89
  periodTickSuppressesFeedback
89
- } from "./chunk-7XRQUFVH.mjs";
90
+ } from "./chunk-PHUUFCJY.mjs";
90
91
 
91
92
  // src/labelContrast.ts
92
93
  function parseRGBA(c) {
@@ -1057,6 +1058,18 @@ function themedLand(p) {
1057
1058
  const fg = toRGBA(p.themeFg) ?? [255, 255, 255, 1];
1058
1059
  return "#" + compositeOver([fg[0], fg[1], fg[2], 0.18], [bg[0], bg[1], bg[2]]).map((v) => v.toString(16).padStart(2, "0")).join("");
1059
1060
  }
1061
+ function cleanHostSelection(v) {
1062
+ if (!v || typeof v !== "object" || !Array.isArray(v.rows)) return void 0;
1063
+ const raw = v.rows;
1064
+ const rows = Array.from(new Set(raw.filter((n2) => typeof n2 === "number" && Number.isInteger(n2) && n2 >= 0))).sort((a, b) => a - b);
1065
+ const h = Number(v.hidden);
1066
+ const out = { rows, hidden: Number.isFinite(h) && h > 0 ? Math.floor(h) : 0 };
1067
+ const n = v.narrowed;
1068
+ if (n && typeof n === "object" && Number.isInteger(n.published) && Number.isInteger(n.kept) && n.kept >= 0 && n.kept < n.published) {
1069
+ out.narrowed = { published: n.published, kept: n.kept };
1070
+ }
1071
+ return out;
1072
+ }
1060
1073
  var clamp = (n, lo, hi) => Math.max(lo, Math.min(hi, n));
1061
1074
  var numberOr = (raw, dflt) => {
1062
1075
  const n = raw == null || raw === "" ? NaN : Number(raw);
@@ -1080,6 +1093,8 @@ function resolveOptions(p) {
1080
1093
  // tests/defaults.test.ts now compares the two lists, because four instances of one
1081
1094
  // omission is a missing check, not four mistakes.
1082
1095
  geoPointDest: p.geoPointDest,
1096
+ // Why a point map placed nothing (the resolver's sentences), passed through untouched.
1097
+ geoPointRefused: p.geoPointRefused,
1083
1098
  // A host FACT about the data it serialised (contract 1.9.0), passed through untouched.
1084
1099
  dateCellsAreUtcDays: p.dateCellsAreUtcDays,
1085
1100
  // Host FACTS about whether every row arrived (contract 1.15.0), passed through untouched: an
@@ -1087,6 +1102,8 @@ function resolveOptions(p) {
1087
1102
  dataComplete: p.dataComplete,
1088
1103
  rowsWithheld: p.rowsWithheld,
1089
1104
  rowsFilteredOut: p.rowsFilteredOut,
1105
+ // A host FACT about its selection (contract 1.21.0), cleaned, never invented: absent stays absent.
1106
+ hostSelection: cleanHostSelection(p.hostSelection),
1090
1107
  // Host services (contract 1.18.0): a FUNCTION or nothing, so a junk value never reaches a chart as something
1091
1108
  // it would try to call. Passed through untouched otherwise: the host owns what opening or copying means.
1092
1109
  openUrl: typeof p.openUrl === "function" ? p.openUrl : void 0,
@@ -2800,6 +2817,21 @@ function createChartHost(container, config) {
2800
2817
  }
2801
2818
  };
2802
2819
  const subs = /* @__PURE__ */ new Set();
2820
+ let hiddenHeld = 0;
2821
+ let factFresh = true;
2822
+ const selectionFact = () => {
2823
+ const n = Array.isArray(data?.rows) ? data.rows.length : 0;
2824
+ const rows = Array.from(new Set((current ?? []).filter((r) => Number.isInteger(r) && r >= 0 && r < n))).sort((a, b) => a - b);
2825
+ return { rows, hidden: hiddenHeld };
2826
+ };
2827
+ const tellSelection = () => {
2828
+ const slot = container[CONTAINER_SLOT_HOST_SELECTION];
2829
+ if (typeof slot !== "function") return;
2830
+ try {
2831
+ slot(selectionFact());
2832
+ } catch {
2833
+ }
2834
+ };
2803
2835
  const ensureAffordanceStyles = () => {
2804
2836
  try {
2805
2837
  if (!doc || doc.getElementById("bic-chart-host-affordances")) return;
@@ -3118,22 +3150,24 @@ function createChartHost(container, config) {
3118
3150
  }
3119
3151
  }
3120
3152
  };
3121
- const notify = (rowIdxs, source, tick, fromChart = false, publish = true) => {
3153
+ const notify = (rowIdxs, source, tick, fromChart = false, publish = true, meta) => {
3122
3154
  if (destroyed) return;
3123
3155
  current = rowIdxs;
3124
3156
  selectionFromChart = rowIdxs.length > 0 && fromChart;
3125
3157
  selectionPublished = publish;
3126
3158
  activeTickEl = rowIdxs.length ? tick ?? null : null;
3127
3159
  selectionIsPeriod = rowIdxs.length > 0 && periodTickSuppressesFeedback(!!tick, chartOwnsTimeline(container));
3160
+ if (!rowIdxs.length && !meta?.keepHidden) hiddenHeld = 0;
3161
+ factFresh = true;
3128
3162
  paintSelection();
3129
3163
  paintGlyphLayer();
3130
- if (!publish) return;
3131
- for (const cb of subs) {
3164
+ if (publish) for (const cb of subs) {
3132
3165
  try {
3133
- cb(rowIdxs, source);
3166
+ cb(rowIdxs, source, meta);
3134
3167
  } catch {
3135
3168
  }
3136
3169
  }
3170
+ tellSelection();
3137
3171
  };
3138
3172
  const selectFromLasso = (rows) => {
3139
3173
  if (lassoEffect(resolved.lasso) === "highlight") {
@@ -3163,7 +3197,7 @@ function createChartHost(container, config) {
3163
3197
  xfAt = Date.now();
3164
3198
  if (d.clear) notify([], d.source || "chart", void 0, false, selectionPublished || !(current && current.length));
3165
3199
  else if (d.mark) notify(parseRowIdxs(d.mark.getAttribute?.(ROW_IDX_ATTR)), d.source || "chart", d.mark, true);
3166
- else if (Array.isArray(d.rows)) notify(validRowSet(d.rows), d.source || "chart", null, true);
3200
+ else if (Array.isArray(d.rows)) notify(validRowSet(d.rows), d.source || "chart", null, true, true, d.keepHidden === true ? { keepHidden: true } : void 0);
3167
3201
  };
3168
3202
  const resolver = createMarkResolver({
3169
3203
  root: container,
@@ -3423,6 +3457,7 @@ function createChartHost(container, config) {
3423
3457
  if (resolved.geoUnmatched === void 0 && data.geoUnmatched) resolved = { ...resolved, geoUnmatched: data.geoUnmatched };
3424
3458
  if (resolved.geoPoint === void 0 && data.geoPoint) resolved = { ...resolved, geoPoint: data.geoPoint };
3425
3459
  if (resolved.geoPointDest === void 0 && data.geoPointDest) resolved = { ...resolved, geoPointDest: data.geoPointDest };
3460
+ if (resolved.geoPointRefused === void 0 && data.geoPointRefused?.length) resolved = { ...resolved, geoPointRefused: data.geoPointRefused };
3426
3461
  if (resolved.dateCellsAreUtcDays === void 0 && data.dateCellsAreUtcDays) resolved = { ...resolved, dateCellsAreUtcDays: true };
3427
3462
  if (resolved.suppressSelectionGlyph === void 0 && data.meta?.suppressSelectionGlyph === true)
3428
3463
  resolved = { ...resolved, suppressSelectionGlyph: true };
@@ -3440,6 +3475,7 @@ function createChartHost(container, config) {
3440
3475
  zoomCap = null;
3441
3476
  }
3442
3477
  }
3478
+ if (raw.hostSelection == null) resolved.hostSelection = factFresh ? selectionFact() : void 0;
3443
3479
  try {
3444
3480
  try {
3445
3481
  outcome = renderFn(container, { columns: data.columns, rows: data.rows }, resolved);
@@ -3507,6 +3543,7 @@ function createChartHost(container, config) {
3507
3543
  setData(next) {
3508
3544
  if (destroyed) return;
3509
3545
  data = next;
3546
+ factFresh = false;
3510
3547
  host.render();
3511
3548
  },
3512
3549
  get options() {
@@ -3552,6 +3589,15 @@ function createChartHost(container, config) {
3552
3589
  if (lasso && lasso.rows().length && !sameRowSet(rows, lasso.rows())) lasso.clear({ publish: false, source: "host" });
3553
3590
  notify(rows, "host");
3554
3591
  },
3592
+ setHidden(count) {
3593
+ if (destroyed) return;
3594
+ const n = Number(count);
3595
+ const next = Number.isFinite(n) && n > 0 ? Math.floor(n) : 0;
3596
+ if (next === hiddenHeld && factFresh) return;
3597
+ hiddenHeld = next;
3598
+ factFresh = true;
3599
+ tellSelection();
3600
+ },
3555
3601
  get current() {
3556
3602
  return current;
3557
3603
  }
@@ -3789,6 +3835,7 @@ export {
3789
3835
  exportFormatsFor,
3790
3836
  exportTableService,
3791
3837
  browserSaveFile,
3838
+ cleanHostSelection,
3792
3839
  resolveOptions,
3793
3840
  buildRenderPayload,
3794
3841
  stripJsComments,
@@ -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-PHUUFCJY.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.21.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";
@@ -88,6 +89,7 @@ export {
88
89
  NO_ROW_MARKS_ATTR,
89
90
  SNAPSHOT_SVG_ATTR,
90
91
  XFILTER_REFRESH_EVENT,
92
+ CONTAINER_SLOT_HOST_SELECTION,
91
93
  CONTAINER_SLOT_ANIM_STOP,
92
94
  CONTAINER_SLOT_XF_CLEAR,
93
95
  CONTAINER_SLOT_INITIAL_XF_MARK,
@@ -4,7 +4,7 @@ import {
4
4
  LEGEND_MARK_CLASS,
5
5
  MARK_CLASS,
6
6
  ROW_IDX_ATTR
7
- } from "./chunk-7XRQUFVH.mjs";
7
+ } from "./chunk-PHUUFCJY.mjs";
8
8
 
9
9
  // src/hitTargets.ts
10
10
  var SVG_NS = "http://www.w3.org/2000/svg";
package/dist/index.mjs CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  svgNaturalSize,
16
16
  svgToDataUrl,
17
17
  tableHostOf
18
- } from "./chunk-PA5V6J6K.mjs";
18
+ } from "./chunk-FCLPMC6Q.mjs";
19
19
  import {
20
20
  ANNOTATION_CLASS,
21
21
  ANNOTATION_LAYER_CLASS,
@@ -63,6 +63,7 @@ import {
63
63
  censusColourSpread,
64
64
  censusMarks,
65
65
  censusValuePlacement,
66
+ cleanHostSelection,
66
67
  clippedTextFlag,
67
68
  colourSpreadFlag,
68
69
  compileRenderFn,
@@ -105,7 +106,7 @@ import {
105
106
  toRGBA,
106
107
  toSourceRows,
107
108
  valuePlacementFlag
108
- } from "./chunk-K6UXTDMR.mjs";
109
+ } from "./chunk-MO2GR56D.mjs";
109
110
  import {
110
111
  LASSO_AXES_SLOT,
111
112
  LASSO_COUNT_CLASS,
@@ -132,13 +133,13 @@ import {
132
133
  lassoVerdict,
133
134
  pointInShape,
134
135
  registerLassoAction
135
- } from "./chunk-IE426WU6.mjs";
136
+ } from "./chunk-ESBH2L6E.mjs";
136
137
  import {
137
138
  MIN_HIT_BAND_PX,
138
139
  censusHitBands,
139
140
  ensureCrossfilterHitTargets,
140
141
  hitBandFlag
141
- } from "./chunk-CPLWAW3Z.mjs";
142
+ } from "./chunk-UKXGOQMS.mjs";
142
143
  import {
143
144
  CONTAINER_SLOT_PRESS_AT,
144
145
  DRAG_NOT_CLICK_PX,
@@ -163,7 +164,7 @@ import {
163
164
  selectionRuleOf,
164
165
  trackPress,
165
166
  validRowSet
166
- } from "./chunk-P2DLK7WZ.mjs";
167
+ } from "./chunk-LGWTV5PB.mjs";
167
168
  import {
168
169
  AXIS_PIN_BAND_PAD_PX,
169
170
  AXIS_PIN_MAX_BAND_FRACTION,
@@ -192,7 +193,7 @@ import {
192
193
  svgInkReach,
193
194
  takeScroll,
194
195
  unpinScrolledAxis
195
- } from "./chunk-IE7TM6DX.mjs";
196
+ } from "./chunk-OSREEGBN.mjs";
196
197
  import {
197
198
  clearGeoCache,
198
199
  geoAssetFor,
@@ -225,6 +226,7 @@ import {
225
226
  COLOR_SCALE_SELF_CLAMP_PCT_MIN,
226
227
  CONTAINER_SLOT_ANIM_STOP,
227
228
  CONTAINER_SLOT_CLICKED_MARKS,
229
+ CONTAINER_SLOT_HOST_SELECTION,
228
230
  CONTAINER_SLOT_INITIAL_XF_MARK,
229
231
  CONTAINER_SLOT_SCROLL,
230
232
  CONTAINER_SLOT_UI_STATE,
@@ -260,7 +262,7 @@ import {
260
262
  chartOwnsTimeline,
261
263
  periodTickSuppressesFeedback,
262
264
  withoutViewOnlyKeys
263
- } from "./chunk-7XRQUFVH.mjs";
265
+ } from "./chunk-PHUUFCJY.mjs";
264
266
  import "./chunk-GHODWOAL.mjs";
265
267
 
266
268
  // src/hostLinks.ts
@@ -2130,7 +2132,7 @@ function transportFailureShouldRecover(_headersReceived, genNew) {
2130
2132
  return genNew;
2131
2133
  }
2132
2134
  var TRANSPORT_LOST_CHECKING_MESSAGE = "The connection dropped while your chart was being generated - checking whether it finished on the server...";
2133
- var GENERATION_CANCELLED_MESSAGE = "The connection dropped before the chart finished - nothing was charged. Generate again.";
2135
+ var GENERATION_CANCELLED_MESSAGE = "The connection dropped before the chart finished. You were charged only for the work already done. Generate again.";
2134
2136
  function recoveryAnswerIsCancelled(r2) {
2135
2137
  return !!r2 && r2.isGenerationCancelled === true;
2136
2138
  }
@@ -2153,7 +2155,7 @@ function recoveryFinalOutcome(r2) {
2153
2155
  return null;
2154
2156
  }
2155
2157
  function recoveryProvesNothingCharged(o3) {
2156
- return o3 === "cancelled" || o3 === "not-received";
2158
+ return o3 === "not-received";
2157
2159
  }
2158
2160
  function recoveryGiveUpRefunds(outcome) {
2159
2161
  return outcome === "window-closed" || outcome === "hard-error" || outcome === "unreachable";
@@ -2330,6 +2332,7 @@ export {
2330
2332
  COLOR_SCALE_SELF_CLAMP_PCT_MIN,
2331
2333
  CONTAINER_SLOT_ANIM_STOP,
2332
2334
  CONTAINER_SLOT_CLICKED_MARKS,
2335
+ CONTAINER_SLOT_HOST_SELECTION,
2333
2336
  CONTAINER_SLOT_INITIAL_XF_MARK,
2334
2337
  CONTAINER_SLOT_PRESS_AT,
2335
2338
  CONTAINER_SLOT_SCROLL,
@@ -2477,6 +2480,7 @@ export {
2477
2480
  chartOwnsTimeline,
2478
2481
  chartSvgOf,
2479
2482
  chooserFitsViewport,
2483
+ cleanHostSelection,
2480
2484
  clearGeoCache,
2481
2485
  clearLasso,
2482
2486
  clearPress,
@@ -2,13 +2,13 @@
2
2
  import {
3
3
  chartSvgOf,
4
4
  tableHostOf
5
- } from "./chunk-PA5V6J6K.mjs";
5
+ } from "./chunk-FCLPMC6Q.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-OSREEGBN.mjs";
11
+ import "./chunk-PHUUFCJY.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-JU2PQ22J.mjs";
18
+ import "./chunk-ESBH2L6E.mjs";
19
+ import "./chunk-LGWTV5PB.mjs";
20
+ import "./chunk-PHUUFCJY.mjs";
21
21
  import "./chunk-GHODWOAL.mjs";
22
22
  export {
23
23
  LINKED_HOVER_CLASS,
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-JU2PQ22J.mjs";
17
17
  import {
18
18
  assembleD3,
19
19
  createChartGroup,
20
20
  createChartHost,
21
21
  syncMemberSelection,
22
22
  toSourceRows
23
- } from "./chunk-K6UXTDMR.mjs";
24
- import "./chunk-IE426WU6.mjs";
25
- import "./chunk-CPLWAW3Z.mjs";
26
- import "./chunk-P2DLK7WZ.mjs";
27
- import "./chunk-IE7TM6DX.mjs";
23
+ } from "./chunk-MO2GR56D.mjs";
24
+ import "./chunk-ESBH2L6E.mjs";
25
+ import "./chunk-UKXGOQMS.mjs";
26
+ import "./chunk-LGWTV5PB.mjs";
27
+ import "./chunk-OSREEGBN.mjs";
28
28
  import {
29
29
  geoFromCache,
30
30
  loadGeo
31
31
  } from "./chunk-5WTQN5DL.mjs";
32
32
  import "./chunk-SYUJ4TPX.mjs";
33
33
  import "./chunk-A2GMXZP7.mjs";
34
- import "./chunk-7XRQUFVH.mjs";
34
+ import "./chunk-PHUUFCJY.mjs";
35
35
  import "./chunk-GHODWOAL.mjs";
36
36
 
37
37
  // src/react.tsx
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-PHUUFCJY.mjs";
8
8
  import "./chunk-GHODWOAL.mjs";
9
9
 
10
10
  // src/testing/interact.ts
@@ -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.21.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";
@@ -124,10 +142,12 @@ export interface RenderOptions {
124
142
  rolesBackfilled?: string[];
125
143
  rolesRefused?: string[];
126
144
  } | null;
145
+ geoPointRefused?: string[];
127
146
  dateCellsAreUtcDays?: boolean;
128
147
  dataComplete?: boolean;
129
148
  rowsWithheld?: number;
130
149
  rowsFilteredOut?: number;
150
+ hostSelection?: HostSelectionFact;
131
151
  openUrl?: (url: string) => void;
132
152
  copyText?: (text: string) => boolean | void | Promise<boolean | void>;
133
153
  saveFile?: SaveFileService;
@@ -1,4 +1,5 @@
1
- import { type RenderOptions } from "./contract";
1
+ import { type RenderOptions, type HostSelectionFact } from "./contract";
2
+ export declare function cleanHostSelection(v: unknown): HostSelectionFact | undefined;
2
3
  export type ResolveOptionsInput = {
3
4
  [K in keyof RenderOptions]?: any;
4
5
  };
@@ -62,8 +62,9 @@ export interface Filter {
62
62
  readonly reason: FilterChangeReason | null;
63
63
  /** Bumped on every change: a cheap identity for memoising on the filter's state. */
64
64
  readonly version: number;
65
- /** Select these rows' keys (replacing the selection). An empty list clears. */
66
- selectRows(rows: readonly Record<string, unknown>[], reason?: FilterChangeReason): void;
65
+ /** Select these rows' keys (replacing the selection). An empty list clears. `keep` adds keys held already that these
66
+ * rows cannot name (keys another filter hid from the chart that made the selection): they stay selected. */
67
+ selectRows(rows: readonly Record<string, unknown>[], reason?: FilterChangeReason, keep?: readonly FilterKey[]): void;
67
68
  /** Select keys by value: one value per key (a one-column filter) or one array per key. */
68
69
  set(keys: readonly unknown[] | readonly FilterKey[] | unknown, reason?: FilterChangeReason): void;
69
70
  /** Clear the selection (and every bound chart's marks). */
@@ -119,9 +120,8 @@ export declare function createFilter(columns: string | readonly string[], opts?:
119
120
  export declare function createFilterScope(): FilterScope;
120
121
  export interface FilterBinding {
121
122
  /**
122
- * Call after the chart is handed new data. A selection whose key is still drawn is repainted;
123
- * one whose key is gone is cleared (reason "data") when this chart made it. An empty payload is
124
- * treated as data still arriving, not as the key being gone.
123
+ * Call after the chart is handed new data. The selection is repainted where its keys are drawn now, and a key the new
124
+ * rows do not carry stays selected (the chart is told how many through hostSelection.hidden): new data never clears it.
125
125
  */
126
126
  reconcile(): void;
127
127
  /** Repaint the filter's selection onto the chart's marks. */
@@ -2,6 +2,11 @@ import { type RenderOptions, type ViewStateProvider } from "./contract";
2
2
  import { type ResolveOptionsInput } from "./defaults";
3
3
  import { type SelectionRule, type SelectionPaintMode } from "./selection";
4
4
  /** What onSelectionPaint reports: the declared rule, how this paint decided, and how many marks it lit. */
5
+ /** What a selection change carries besides its rows (1.21.0): `keepHidden` when the chart's set is what the reader holds among
6
+ * the rows in view, so a subscriber that holds keys the data no longer carries keeps them. */
7
+ export interface SelectionChangeMeta {
8
+ keepHidden?: boolean;
9
+ }
5
10
  export interface SelectionPaintReport {
6
11
  rule: SelectionRule;
7
12
  mode: SelectionPaintMode;
@@ -55,6 +60,8 @@ export interface ChartHostConfig {
55
60
  * into options exactly like geoPoint, so a host that hands over the whole payload
56
61
  * gets both ends annotated without knowing the field exists. */
57
62
  geoPointDest?: RenderOptions["geoPointDest"];
63
+ /** Why a point map placed nothing (the resolver's sentences) - promoted into options exactly like geoPoint. */
64
+ geoPointRefused?: string[];
58
65
  /** Set by buildRenderPayload(..., { utcDays: true }) - promoted into options exactly like geoPoint. */
59
66
  dateCellsAreUtcDays?: boolean;
60
67
  /** Provenance the MCP stamps into data.sample.json. `hostContract` is checked
@@ -302,7 +309,7 @@ export interface ChartHost {
302
309
  selection: {
303
310
  /** Subscribe to cross-filter changes (mark clicks + the chart's own
304
311
  * llm-xfilter-refresh dispatches). rowIdxs = [] means cleared. */
305
- onChange(cb: (rowIdxs: number[], source: string) => void): () => void;
312
+ onChange(cb: (rowIdxs: number[], source: string, meta?: SelectionChangeMeta) => void): () => void;
306
313
  /** Clear the chart's own selection (calls __llmXfClear when the chart set it). */
307
314
  clear(): void;
308
315
  /**
@@ -321,6 +328,12 @@ export interface ChartHost {
321
328
  * republish what the other just sent and fight itself.
322
329
  */
323
330
  highlight(rowIdxs: number[]): void;
331
+ /**
332
+ * How many of the selection's identities the data on screen does not carry (1.21.0): a filter keyed by value that
333
+ * another filter narrowed knows, this host does not. Told to the chart (RenderOptions.hostSelection and the
334
+ * CONTAINER_SLOT_HOST_SELECTION slot), so a checkbox column can say "2 selected, 2 hidden". A clear resets it.
335
+ */
336
+ setHidden?(count: number): void;
324
337
  readonly current: number[] | null;
325
338
  };
326
339
  animation: {
@@ -1,5 +1,5 @@
1
- export { HOST_CONTRACT_VERSION, GEO_POINT_PRECISIONS, MARK_CLASS, LEGEND_MARK_CLASS, AXIS_FILTER_CLASS, ROW_IDX_ATTR, LIFT_SELECTED_CLASS, CONTROL_CLASS, NO_ROW_MARKS_ATTR, NOTE_STYLE_ATTR, SELECTION_RULE_ATTR, SELECTION_RULE_CLICKED_MARKS, MARK_KEY_ATTR, CONTAINER_SLOT_CLICKED_MARKS, SNAPSHOT_SVG_ATTR, XFILTER_REFRESH_EVENT, CONTAINER_SLOT_ANIM_STOP, CONTAINER_SLOT_XF_CLEAR, CONTAINER_SLOT_INITIAL_XF_MARK, CONTAINER_SLOT_UI_STATE, CONTAINER_SLOT_SCROLL, VIEW_ONLY_UI_STATE_KEYS, withoutViewOnlyKeys, HOST_CONTAINER_CLASS, SELECTION_ACTIVE_CLASS, MARK_SELECTED_CLASS, ACTIVE_TICK_CLASS, DIM_OPACITY_VAR, DIM_OPACITY_DEFAULT, DIM_OPACITY_MIN, 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, FLIP_INTERVAL_MIN_MS, FLIP_INTERVAL_MAX_MS, FLIP_DIRECTION_DEFAULT, APPROXIMATE_POSITIONS_DEFAULT, VALUE_AXIS_BASELINE_DEFAULT, SEASONAL_MARKERS_DEFAULT, MAX_MAP_POINTS_DEFAULT, type GeoPointPrecision, type GeoMapKind, type TimelineStyle, type FlipMode, type FlipDirection, type ApproximatePositions, type ValueAxisBaseline, type SeasonalMarkers, type ColorScaleScope, type RenderOptions, type ViewStateProvider, type ChartControlChange, type XfilterRefreshDetail, } from "./contract";
2
- export { resolveOptions, type ResolveOptionsInput } from "./defaults";
1
+ export { HOST_CONTRACT_VERSION, GEO_POINT_PRECISIONS, MARK_CLASS, LEGEND_MARK_CLASS, AXIS_FILTER_CLASS, ROW_IDX_ATTR, LIFT_SELECTED_CLASS, CONTROL_CLASS, NO_ROW_MARKS_ATTR, NOTE_STYLE_ATTR, SELECTION_RULE_ATTR, SELECTION_RULE_CLICKED_MARKS, MARK_KEY_ATTR, CONTAINER_SLOT_CLICKED_MARKS, SNAPSHOT_SVG_ATTR, XFILTER_REFRESH_EVENT, CONTAINER_SLOT_ANIM_STOP, CONTAINER_SLOT_XF_CLEAR, CONTAINER_SLOT_INITIAL_XF_MARK, CONTAINER_SLOT_UI_STATE, CONTAINER_SLOT_SCROLL, CONTAINER_SLOT_HOST_SELECTION, VIEW_ONLY_UI_STATE_KEYS, withoutViewOnlyKeys, HOST_CONTAINER_CLASS, SELECTION_ACTIVE_CLASS, MARK_SELECTED_CLASS, ACTIVE_TICK_CLASS, DIM_OPACITY_VAR, DIM_OPACITY_DEFAULT, DIM_OPACITY_MIN, 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, FLIP_INTERVAL_MIN_MS, FLIP_INTERVAL_MAX_MS, FLIP_DIRECTION_DEFAULT, APPROXIMATE_POSITIONS_DEFAULT, VALUE_AXIS_BASELINE_DEFAULT, SEASONAL_MARKERS_DEFAULT, MAX_MAP_POINTS_DEFAULT, type GeoPointPrecision, type GeoMapKind, type TimelineStyle, type FlipMode, type FlipDirection, type ApproximatePositions, type ValueAxisBaseline, type SeasonalMarkers, type ColorScaleScope, type RenderOptions, type ViewStateProvider, type ChartControlChange, type XfilterRefreshDetail, type HostSelectionFact, } from "./contract";
2
+ export { resolveOptions, cleanHostSelection, type ResolveOptionsInput } from "./defaults";
3
3
  export { hostLinkServices, type HostLinkServices, type ClipboardLike } from "./hostLinks";
4
4
  export { tableToCsv, tableToXlsx, buildExportFile, exportFileName, sheetName as exportSheetName, excelNumberFormat, excelSerial, bytesToBase64, exportFormatsFor, exportTableService, browserSaveFile, EXPORT_FORMATS, XLSX_MIME, CSV_MIME, type ExportTable, type ExportColumn, type ExportColumnType, type ExportCell, type ExportFormat, type ExportFile, type SaveFileService, type ExportTableService, } from "./exportTable";
5
5
  export { OPTIONS_VOCABULARY, LIVE_OPTION_KEYS, MAX_MAP_POINTS_MIN, MAX_MAP_POINTS_MAX, LIMIT_COUNT_MAX, wireLimitCount, codeReadsOption, type OptionVocabularyEntry, type OptionTiming, type OptionWire, type OptionKey, } from "./optionsVocabulary";
@@ -9,7 +9,7 @@ export { loadGeo, geoFromCache, registerGeo, registerGeoAsset, geoAssetFor, clea
9
9
  export declare function registerCityTable(packed: string): void;
10
10
  export { buildRenderPayload, type RenderPayload, type GeoPointBinding, type GeoBinding, type GeoProvinceReport, type ProvinceJoin } from "./payload";
11
11
  export { codeReadsDatesInLocalTime, vegaSpecReadsDatesInLocalTime } from "./dateCells";
12
- export { createChartHost, compileRenderFn, stripEsmExports, requiredD3Plugins, explainRenderFailure, sessionViewStateProvider, noopViewStateProvider, assembleD3, D3_PLUGIN_PACKAGES, type ChartHost, type ChartHostConfig, type RenderFn, type SelectionPaintReport } from "./host";
12
+ export { createChartHost, compileRenderFn, stripEsmExports, requiredD3Plugins, explainRenderFailure, sessionViewStateProvider, noopViewStateProvider, assembleD3, D3_PLUGIN_PACKAGES, type ChartHost, type ChartHostConfig, type RenderFn, type SelectionPaintReport, type SelectionChangeMeta } from "./host";
13
13
  export { ANNOTATION_CLASS, ANNOTATION_LAYER_CLASS, type MarkAnnotation, type AnnotationReport } from "./annotations";
14
14
  export type { MarkNoteLike, NoteBadgeOptions } from "./markNotes";
15
15
  export type { Controls, ControlInfo, ControlsAttachment } from "./controls";
@@ -190,7 +190,7 @@ export declare const TRANSPORT_LOST_CHECKING_MESSAGE = "The connection dropped w
190
190
  * own. The server's errorMessage is preferred - it is the one author of the sentence - and this is the same
191
191
  * sentence, for a server that set the flag and left the message blank.
192
192
  */
193
- export declare const GENERATION_CANCELLED_MESSAGE = "The connection dropped before the chart finished - nothing was charged. Generate again.";
193
+ export declare const GENERATION_CANCELLED_MESSAGE = "The connection dropped before the chart finished. You were charged only for the work already done. Generate again.";
194
194
  /**
195
195
  * Is this recovery answer the server saying the generation was CANCELLED - so nothing will ever be ready?
196
196
  *
@@ -217,9 +217,10 @@ export declare function recoveryFinalOutcome(r: {
217
217
  isVersionNotFound?: boolean | null;
218
218
  errorCode?: string | null;
219
219
  } | null | undefined): RecoveryFinalOutcome | null;
220
- /** Did the server PROVE nothing was charged? Only a cancel and a request it never received do; a
221
- * failed generation's charge is its own, and a generate that died with a restart may have been charged
222
- * before its record was written, so a host claims nothing about either. */
220
+ /** Did the server PROVE nothing was charged? Only a request it never received does. A cancel is billed for
221
+ * the passes that ran before it; a failed generation's charge is its own, and a
222
+ * generate that died with a restart may have been charged before its record was written, so a host claims
223
+ * nothing about any of those. */
223
224
  export declare function recoveryProvesNothingCharged(o: string | null | undefined): boolean;
224
225
  /** Does a recovery that ended this way send the refund? Only when it ended with NOTHING PAINTED and
225
226
  * nothing proven - the window closed, the poll itself was refused, or the service could not be
@@ -95,7 +95,7 @@ export interface BicChartProps {
95
95
  * THE PAGE FILTER THIS CHART SELECTS - from useBicFilter("RegionCode"). A click sets it, the
96
96
  * same click or a click on empty canvas clears it, and the filter's state is painted onto the
97
97
  * marks whoever changed it: `filter.clear()` from a page button clears the marks too. New data
98
- * keeps a selection whose key is still drawn and clears (reason "data") one whose key is gone.
98
+ * keeps the selection, a key it no longer draws included; the chart is told how many are hidden.
99
99
  * The page reads `filter.value` / `filter.row` and never writes a select handler. With
100
100
  * `selects`, the filter owns what this chart shows as selected.
101
101
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bicharts/chart-host",
3
- "version": "0.6.106",
3
+ "version": "0.6.108",
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",