@bicharts/chart-host 0.6.115 → 0.6.117

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.
Files changed (35) hide show
  1. package/README.md +18 -0
  2. package/dist/adapters.mjs +3 -3
  3. package/dist/card.mjs +2 -2
  4. package/dist/category-colours.mjs +275 -0
  5. package/dist/{chunk-AQO4ROMU.mjs → chunk-63IUMWY2.mjs} +40 -3
  6. package/dist/{chunk-YOCYWON4.mjs → chunk-EFKGSDFF.mjs} +1 -1
  7. package/dist/{chunk-7K3F3RZ6.mjs → chunk-GZSYTDFN.mjs} +68 -275
  8. package/dist/{chunk-QLIRQJ6B.mjs → chunk-IW6BKFF5.mjs} +1 -1
  9. package/dist/{chunk-YSRMSDRP.mjs → chunk-JMLSNV5Q.mjs} +1 -1
  10. package/dist/chunk-JTZTTJJK.mjs +244 -0
  11. package/dist/{chunk-VPFP35XI.mjs → chunk-K2TH7D5V.mjs} +299 -299
  12. package/dist/{chunk-GXR7T6G5.mjs → chunk-QG5TENI3.mjs} +4 -0
  13. package/dist/{chunk-PQKLWYKK.mjs → chunk-RLOIA7QK.mjs} +1 -1
  14. package/dist/{chunk-CVTCR7HQ.mjs → chunk-TUZCM7SX.mjs} +2 -2
  15. package/dist/{chunk-DILJDN6C.mjs → chunk-VGJH63LZ.mjs} +1 -1
  16. package/dist/{chunk-2GW3S5VD.mjs → chunk-ZZBX5ZJ6.mjs} +15 -2
  17. package/dist/dax.mjs +23 -1
  18. package/dist/index.mjs +63 -16
  19. package/dist/legend-fit.mjs +3 -3
  20. package/dist/page.mjs +5 -5
  21. package/dist/provinces.mjs +4 -4
  22. package/dist/react.mjs +12 -11
  23. package/dist/testing.mjs +1 -1
  24. package/dist/types/categoryColours.d.ts +71 -0
  25. package/dist/types/contract.d.ts +2 -0
  26. package/dist/types/dax.d.ts +26 -0
  27. package/dist/types/filterScope.d.ts +10 -1
  28. package/dist/types/fit.d.ts +6 -1
  29. package/dist/types/fitDom.d.ts +13 -0
  30. package/dist/types/host.d.ts +10 -0
  31. package/dist/types/index.d.ts +4 -3
  32. package/dist/types/qualifyTable.d.ts +52 -0
  33. package/dist/zoom-memory.mjs +1 -1
  34. package/package.json +6 -1
  35. /package/dist/{chunk-5YSZABCS.mjs → chunk-LXTW6YII.mjs} +0 -0
@@ -4,11 +4,11 @@ import {
4
4
  claimParkedLasso,
5
5
  installLasso,
6
6
  lassoEffect
7
- } from "./chunk-CVTCR7HQ.mjs";
7
+ } from "./chunk-TUZCM7SX.mjs";
8
8
  import {
9
9
  censusHitBands,
10
10
  ensureCrossfilterHitTargets
11
- } from "./chunk-YOCYWON4.mjs";
11
+ } from "./chunk-EFKGSDFF.mjs";
12
12
  import {
13
13
  clearPress,
14
14
  clearSelectionGlyphs,
@@ -24,26 +24,34 @@ import {
24
24
  selectionRuleOf,
25
25
  trackPress,
26
26
  validRowSet
27
- } from "./chunk-PQKLWYKK.mjs";
27
+ } from "./chunk-RLOIA7QK.mjs";
28
28
  import {
29
29
  clipWindowOf,
30
30
  fitRenderedChart,
31
31
  rememberScroll,
32
+ restoreInnerScroll,
32
33
  takeScroll,
33
34
  unpinScrolledAxis
34
- } from "./chunk-AQO4ROMU.mjs";
35
+ } from "./chunk-63IUMWY2.mjs";
35
36
  import {
36
37
  geoFromCache
37
- } from "./chunk-5YSZABCS.mjs";
38
+ } from "./chunk-LXTW6YII.mjs";
38
39
  import {
39
40
  Fn,
40
- Or,
41
+ Lr,
42
+ Nt,
41
43
  Q,
42
- Rt,
43
44
  Yn,
44
45
  tt,
45
46
  xt
46
- } from "./chunk-VPFP35XI.mjs";
47
+ } from "./chunk-K2TH7D5V.mjs";
48
+ import {
49
+ SAME_SHADE_DELTA_E,
50
+ censusColourSpread,
51
+ deltaE2000,
52
+ hexToLab,
53
+ labToHex
54
+ } from "./chunk-JTZTTJJK.mjs";
47
55
  import {
48
56
  ACTIVE_TICK_CLASS,
49
57
  ANIM_LOOP_DELAY_DEFAULT,
@@ -88,7 +96,7 @@ import {
88
96
  XFILTER_REFRESH_EVENT,
89
97
  chartOwnsTimeline,
90
98
  periodTickSuppressesFeedback
91
- } from "./chunk-GXR7T6G5.mjs";
99
+ } from "./chunk-QG5TENI3.mjs";
92
100
 
93
101
  // src/labelContrast.ts
94
102
  function parseRGBA(c) {
@@ -249,237 +257,11 @@ function clamp01(v) {
249
257
  if (typeof v !== "number" || !isFinite(v)) return 1;
250
258
  return Math.max(0, Math.min(1, v));
251
259
  }
252
- function hexToRGB(hex2) {
253
- const p = toRGBA(hex2);
260
+ function hexToRGB(hex) {
261
+ const p = toRGBA(hex);
254
262
  return [p[0], p[1], p[2]];
255
263
  }
256
264
 
257
- // src/deltaE.ts
258
- function linearise(c) {
259
- const v = c / 255;
260
- return v <= 0.04045 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
261
- }
262
- var Xn = 0.95047;
263
- var Yn2 = 1;
264
- var Zn = 1.08883;
265
- var EPS = 216 / 24389;
266
- var KAPPA = 24389 / 27;
267
- function f(t) {
268
- return t > EPS ? Math.cbrt(t) : (KAPPA * t + 16) / 116;
269
- }
270
- function rgbToLab(r, g, b) {
271
- const R = linearise(r), G = linearise(g), B = linearise(b);
272
- const X = 0.4124564 * R + 0.3575761 * G + 0.1804375 * B;
273
- const Y = 0.2126729 * R + 0.7151522 * G + 0.072175 * B;
274
- const Z = 0.0193339 * R + 0.119192 * G + 0.9503041 * B;
275
- const fx = f(X / Xn), fy = f(Y / Yn2), fz = f(Z / Zn);
276
- return { L: 116 * fy - 16, a: 500 * (fx - fy), b: 200 * (fy - fz) };
277
- }
278
- function hexToLab(hex2) {
279
- const m = /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(hex2.trim());
280
- if (!m) return null;
281
- const h = m[1].length === 3 ? m[1][0] + m[1][0] + m[1][1] + m[1][1] + m[1][2] + m[1][2] : m[1];
282
- return rgbToLab(parseInt(h.slice(0, 2), 16), parseInt(h.slice(2, 4), 16), parseInt(h.slice(4, 6), 16));
283
- }
284
- var RAD = Math.PI / 180;
285
- var DEG = 180 / Math.PI;
286
- var NEUTRAL_CHROMA = 1e-4;
287
- function deltaE2000(c1, c2) {
288
- const C1 = Math.hypot(c1.a, c1.b), C2 = Math.hypot(c2.a, c2.b);
289
- const Cbar = (C1 + C2) / 2;
290
- const C7 = Math.pow(Cbar, 7);
291
- const G = 0.5 * (1 - Math.sqrt(C7 / (C7 + Math.pow(25, 7))));
292
- const a1p = (1 + G) * c1.a, a2p = (1 + G) * c2.a;
293
- const C1p = Math.hypot(a1p, c1.b), C2p = Math.hypot(a2p, c2.b);
294
- const neutral = C1p < NEUTRAL_CHROMA || C2p < NEUTRAL_CHROMA;
295
- const h1p = C1p < NEUTRAL_CHROMA ? 0 : (Math.atan2(c1.b, a1p) * DEG + 360) % 360;
296
- const h2p = C2p < NEUTRAL_CHROMA ? 0 : (Math.atan2(c2.b, a2p) * DEG + 360) % 360;
297
- const dLp = c2.L - c1.L;
298
- const dCp = C2p - C1p;
299
- let dhp;
300
- if (neutral) dhp = 0;
301
- else if (Math.abs(h2p - h1p) <= 180) dhp = h2p - h1p;
302
- else if (h2p - h1p > 180) dhp = h2p - h1p - 360;
303
- else dhp = h2p - h1p + 360;
304
- const dHp = 2 * Math.sqrt(C1p * C2p) * Math.sin(dhp / 2 * RAD);
305
- const Lbarp = (c1.L + c2.L) / 2;
306
- const Cbarp = (C1p + C2p) / 2;
307
- let hbarp;
308
- if (neutral) hbarp = h1p + h2p;
309
- else if (Math.abs(h1p - h2p) <= 180) hbarp = (h1p + h2p) / 2;
310
- else if (h1p + h2p < 360) hbarp = (h1p + h2p + 360) / 2;
311
- else hbarp = (h1p + h2p - 360) / 2;
312
- const T = 1 - 0.17 * Math.cos((hbarp - 30) * RAD) + 0.24 * Math.cos(2 * hbarp * RAD) + 0.32 * Math.cos((3 * hbarp + 6) * RAD) - 0.2 * Math.cos((4 * hbarp - 63) * RAD);
313
- const dTheta = 30 * Math.exp(-Math.pow((hbarp - 275) / 25, 2));
314
- const Cbarp7 = Math.pow(Cbarp, 7);
315
- const RC = 2 * Math.sqrt(Cbarp7 / (Cbarp7 + Math.pow(25, 7)));
316
- const RT = -RC * Math.sin(2 * dTheta * RAD);
317
- const Lm50 = Math.pow(Lbarp - 50, 2);
318
- const SL = 1 + 0.015 * Lm50 / Math.sqrt(20 + Lm50);
319
- const SC = 1 + 0.045 * Cbarp;
320
- const SH = 1 + 0.015 * Cbarp * T;
321
- const tL = dLp / SL, tC = dCp / SC, tH = dHp / SH;
322
- return Math.sqrt(tL * tL + tC * tC + tH * tH + RT * tC * tH);
323
- }
324
- function labToHex(lab) {
325
- const finv = (t) => {
326
- const t3 = t * t * t;
327
- return t3 > EPS ? t3 : (116 * t - 16) / KAPPA;
328
- };
329
- const fy = (lab.L + 16) / 116, fx = fy + lab.a / 500, fz = fy - lab.b / 200;
330
- const X = Xn * finv(fx);
331
- const Y = Yn2 * (lab.L > KAPPA * EPS ? fy * fy * fy : lab.L / KAPPA);
332
- const Z = Zn * finv(fz);
333
- const lin = [
334
- 3.2404542 * X - 1.5371385 * Y - 0.4985314 * Z,
335
- -0.969266 * X + 1.8760108 * Y + 0.041556 * Z,
336
- 0.0556434 * X - 0.2040259 * Y + 1.0572252 * Z
337
- ];
338
- return "#" + lin.map((v) => {
339
- const c = Math.max(0, Math.min(1, v));
340
- const g = c <= 31308e-7 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
341
- return Math.round(g * 255).toString(16).padStart(2, "0");
342
- }).join("");
343
- }
344
- function deltaEHex(a, b) {
345
- const la = hexToLab(a), lb = hexToLab(b);
346
- return la && lb ? deltaE2000(la, lb) : NaN;
347
- }
348
-
349
- // src/colourSpread.ts
350
- var SAME_SHADE_DELTA_E = 5;
351
- var MIN_RAMP_FILLS = 4;
352
- var RAMP_SLACK_MAX = 0.15;
353
- var MIN_MARKS = 24;
354
- var ELEMENT_CAP = 5e3;
355
- var MAX_CELLS = 48;
356
- var CELL_STEP = 32;
357
- var EMPTY = { marks: 0, distinctFills: 0, crowdShare: 0, spanDeltaE: 0 };
358
- function styleOf(el, doc) {
359
- try {
360
- const view = doc?.defaultView;
361
- return view?.getComputedStyle ? view.getComputedStyle(el) : null;
362
- } catch {
363
- return null;
364
- }
365
- }
366
- function fillOf(el, cs) {
367
- const a = el.getAttribute?.("fill");
368
- if (a !== null && a !== void 0 && String(a).trim() !== "") return String(a).trim();
369
- const c = cs?.fill;
370
- return c === null || c === void 0 ? "" : String(c).trim();
371
- }
372
- function toRgb(raw) {
373
- const s = raw.trim().toLowerCase();
374
- if (!s || s === "none" || s === "transparent") return null;
375
- const hex2 = /^#([0-9a-f]{3}|[0-9a-f]{6})$/.exec(s);
376
- if (hex2) {
377
- const h = hex2[1];
378
- const full = h.length === 3 ? h[0] + h[0] + h[1] + h[1] + h[2] + h[2] : h;
379
- return [
380
- parseInt(full.slice(0, 2), 16),
381
- parseInt(full.slice(2, 4), 16),
382
- parseInt(full.slice(4, 6), 16)
383
- ];
384
- }
385
- const m = /^rgba?\(\s*([\d.]+)[\s,]+([\d.]+)[\s,]+([\d.]+)\s*(?:[,/]\s*([\d.]+)\s*)?\)$/.exec(s);
386
- if (!m) return null;
387
- if (m[4] !== void 0 && parseFloat(m[4]) === 0) return null;
388
- return [Math.round(parseFloat(m[1])), Math.round(parseFloat(m[2])), Math.round(parseFloat(m[3]))];
389
- }
390
- function cellKey(rgb) {
391
- return [
392
- Math.round(rgb[0] / CELL_STEP),
393
- Math.round(rgb[1] / CELL_STEP),
394
- Math.round(rgb[2] / CELL_STEP)
395
- ].join(",");
396
- }
397
- function hex(rgb) {
398
- return "#" + rgb.map((v) => Math.max(0, Math.min(255, v)).toString(16).padStart(2, "0")).join("");
399
- }
400
- function censusColourSpread(container, doc) {
401
- if (!container || typeof container.querySelectorAll !== "function") return EMPTY;
402
- try {
403
- const els = Array.from(
404
- container.querySelectorAll(`.${MARK_CLASS}, [${ROW_IDX_ATTR}]`)
405
- );
406
- if (els.length === 0 || els.length > ELEMENT_CAP) return EMPTY;
407
- const ownerDoc = doc ?? container.ownerDocument;
408
- const painted = [];
409
- for (const el of els) {
410
- const rgb = toRgb(fillOf(el, styleOf(el, ownerDoc)));
411
- if (rgb) painted.push({ rgb, tag: String(el.tagName || "").toLowerCase() });
412
- }
413
- const byTag = /* @__PURE__ */ new Map();
414
- for (const p of painted) {
415
- const g = byTag.get(p.tag) ?? { fills: /* @__PURE__ */ new Set(), n: 0 };
416
- g.fills.add(p.rgb.join(","));
417
- g.n++;
418
- byTag.set(p.tag, g);
419
- }
420
- const overlays = new Set([...byTag].filter(([, g]) => g.fills.size === 1 && g.n >= MIN_MARKS).map(([t]) => t));
421
- const restFills = new Set([...byTag].filter(([t]) => !overlays.has(t)).flatMap(([, g]) => [...g.fills]));
422
- const counted = restFills.size > 1 ? painted.filter((p) => !overlays.has(p.tag)) : painted;
423
- const distinct = /* @__PURE__ */ new Set();
424
- const cells = /* @__PURE__ */ new Map();
425
- let marks = 0;
426
- for (const { rgb } of counted) {
427
- marks++;
428
- distinct.add(rgb.join(","));
429
- const k = cellKey(rgb);
430
- const cur = cells.get(k);
431
- if (cur) cur.n++;
432
- else cells.set(k, { rgb, n: 1 });
433
- }
434
- if (marks < MIN_MARKS || distinct.size < MIN_RAMP_FILLS) return EMPTY;
435
- const top = [...cells.values()].sort((a, b) => b.n - a.n).slice(0, MAX_CELLS);
436
- const cs = top.map((c) => hexToLab(hex(c.rgb))).filter((l) => l !== null);
437
- if (cs.length < MIN_RAMP_FILLS) return EMPTY;
438
- const d = cs.map(() => new Array(cs.length).fill(0));
439
- let span = 0, lo = 0, hi = 1;
440
- for (let i = 0; i < cs.length; i++) {
441
- for (let j = i + 1; j < cs.length; j++) {
442
- const v = deltaE2000(cs[i], cs[j]);
443
- d[i][j] = v;
444
- d[j][i] = v;
445
- if (v > span) {
446
- span = v;
447
- lo = i;
448
- hi = j;
449
- }
450
- }
451
- }
452
- if (span <= 0) return EMPTY;
453
- let slack = 0, interior = 0;
454
- for (let i = 0; i < cs.length; i++) {
455
- if (i === lo || i === hi) continue;
456
- slack += (d[lo][i] + d[i][hi]) / span - 1;
457
- interior++;
458
- }
459
- if (interior < 2 || slack / interior > RAMP_SLACK_MAX) return EMPTY;
460
- let crowd = 0;
461
- for (let i = 0; i < cs.length; i++) {
462
- let n = 0;
463
- for (let j = 0; j < cs.length; j++) {
464
- if (i === j || d[i][j] <= SAME_SHADE_DELTA_E) n += top[j].n;
465
- }
466
- if (n > crowd) crowd = n;
467
- }
468
- return {
469
- marks,
470
- distinctFills: distinct.size,
471
- crowdShare: Math.round(crowd / marks * 100),
472
- spanDeltaE: Math.round(span)
473
- };
474
- } catch {
475
- return EMPTY;
476
- }
477
- }
478
- function colourSpreadFlag(c) {
479
- if (c.marks === 0) return "";
480
- return "ramp:d3:crowd" + Math.min(80, Math.floor(c.crowdShare / 20) * 20);
481
- }
482
-
483
265
  // src/autoRamp.ts
484
266
  var AUTO_RAMP_CLASSES = 7;
485
267
  var AUTO_RAMP_DRAWN_OPACITY = 0.5;
@@ -498,9 +280,9 @@ function mixLab(a, b, t) {
498
280
  return { L: a.L + (b.L - a.L) * t, a: a.a + (b.a - a.a) * t, b: a.b + (b.b - a.b) * t };
499
281
  }
500
282
  function paintedOver(fg, canvas, alpha) {
501
- const f2 = [1, 3, 5].map((i) => parseInt(fg.slice(i, i + 2), 16));
283
+ const f = [1, 3, 5].map((i) => parseInt(fg.slice(i, i + 2), 16));
502
284
  const c = [1, 3, 5].map((i) => parseInt(canvas.slice(i, i + 2), 16));
503
- const mixed = f2.map((v, i) => Math.round(v * alpha + c[i] * (1 - alpha))).map((v) => v.toString(16).padStart(2, "0"));
285
+ const mixed = f.map((v, i) => Math.round(v * alpha + c[i] * (1 - alpha))).map((v) => v.toString(16).padStart(2, "0"));
504
286
  return hexToLab("#" + mixed.join(""));
505
287
  }
506
288
  function autoRampMinStep(low, high, canvas, classes = AUTO_RAMP_CLASSES, opacity = AUTO_RAMP_DRAWN_OPACITY) {
@@ -527,8 +309,8 @@ function resolveAutoColorScale(p) {
527
309
  if (key === memoKey) return memoValue;
528
310
  const bg = hexToLab(canvas);
529
311
  const darkCanvas = bg.L < 50;
530
- const usable = (hex2) => {
531
- const lab = hex2 ? hexToLab(hex2) : null;
312
+ const usable = (hex) => {
313
+ const lab = hex ? hexToLab(hex) : null;
532
314
  return !!lab && deltaE2000(lab, bg) >= MIN_ACCENT_VS_CANVAS;
533
315
  };
534
316
  const candidates = p.isHighContrast ? [normHex(p.themeAccent), normHex(p.themeFg)] : [...palette.map(normHex), normHex(p.themeAccent), normHex(p.themeFg)];
@@ -621,7 +403,7 @@ function collectOutlineMarks(container, filter) {
621
403
  } else add(m);
622
404
  }
623
405
  if (picked.length < 2 || picked.length > 300) return picked;
624
- const EPS2 = 1;
406
+ const EPS = 1;
625
407
  const rects = picked.map((m) => {
626
408
  try {
627
409
  return m.getBoundingClientRect();
@@ -639,7 +421,7 @@ function collectOutlineMarks(container, filter) {
639
421
  if (j === i || !r) continue;
640
422
  const a = r.width * r.height;
641
423
  if (!(a > 0) || a >= cArea) continue;
642
- if (r.left >= c.left - EPS2 && r.right <= c.right + EPS2 && r.top >= c.top - EPS2 && r.bottom <= c.bottom + EPS2) return false;
424
+ if (r.left >= c.left - EPS && r.right <= c.right + EPS && r.top >= c.top - EPS && r.bottom <= c.bottom + EPS) return false;
643
425
  }
644
426
  return true;
645
427
  });
@@ -948,8 +730,8 @@ function excelNumberFormat(col, values = []) {
948
730
  if (!sh) return null;
949
731
  let frac = 0;
950
732
  for (const v of values) {
951
- const f2 = fractionDigits(sh.percent ? Math.round(v * 100 * 1e9) / 1e9 : v);
952
- if (f2 > frac) frac = f2;
733
+ const f = fractionDigits(sh.percent ? Math.round(v * 100 * 1e9) / 1e9 : v);
734
+ if (f > frac) frac = f;
953
735
  }
954
736
  return codeFromShape(sh, frac);
955
737
  }
@@ -1245,7 +1027,7 @@ function bytesToBase64(bytes) {
1245
1027
  }
1246
1028
  function exportFormatsFor(hostFormats) {
1247
1029
  if (!Array.isArray(hostFormats)) return EXPORT_FORMATS.slice();
1248
- return EXPORT_FORMATS.filter((f2) => hostFormats.indexOf(f2) >= 0);
1030
+ return EXPORT_FORMATS.filter((f) => hostFormats.indexOf(f) >= 0);
1249
1031
  }
1250
1032
  function exportTableService(save, formats = EXPORT_FORMATS) {
1251
1033
  const allowed = formats.slice();
@@ -1573,7 +1355,7 @@ function resolvePointChannel(cols, rowObjs, point) {
1573
1355
  let labelCol;
1574
1356
  if (bind) {
1575
1357
  const dims = cols.filter((c) => !c.isMeasure).map((c) => c.name);
1576
- const res = Or(dims, rowObjs, bind, point?.mapKind, cols.map((c) => c.name));
1358
+ const res = Lr(dims, rowObjs, bind, point?.mapKind, cols.map((c) => c.name));
1577
1359
  bind = res.bind;
1578
1360
  rolesBackfilled = res.backfilled;
1579
1361
  rolesRefused = res.refused;
@@ -1750,7 +1532,7 @@ function buildRenderPayload(cols, rowObjs, geo, point, destination, opts) {
1750
1532
  }
1751
1533
  function longitudeBeside(names) {
1752
1534
  const words = (n) => n.replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase().split(/[^a-zÀ-ɏ]+/);
1753
- return names.find((n) => words(n).some((w) => w === "lon" || w === "lng" || w === "long" || w === "longitude")) ?? names.find((n) => Rt(words(n)) === "lon") ?? null;
1535
+ return names.find((n) => words(n).some((w) => w === "lon" || w === "lng" || w === "long" || w === "longitude")) ?? names.find((n) => Nt(words(n)) === "lon") ?? null;
1754
1536
  }
1755
1537
 
1756
1538
  // src/codeComments.ts
@@ -1976,9 +1758,9 @@ function followMarks(container, opts) {
1976
1758
  }
1977
1759
 
1978
1760
  // src/blankRender.ts
1979
- var EMPTY2 = { markCount: 0, legendMarkCount: 0, containerKind: "empty", declaresNoRowMarks: false };
1761
+ var EMPTY = { markCount: 0, legendMarkCount: 0, containerKind: "empty", declaresNoRowMarks: false };
1980
1762
  function censusMarks(container) {
1981
- if (!container || typeof container.querySelectorAll !== "function") return EMPTY2;
1763
+ if (!container || typeof container.querySelectorAll !== "function") return EMPTY;
1982
1764
  try {
1983
1765
  const marks = /* @__PURE__ */ new Set();
1984
1766
  for (const el of Array.from(container.querySelectorAll(`.${MARK_CLASS}`))) marks.add(el);
@@ -1997,7 +1779,7 @@ function censusMarks(container) {
1997
1779
  declaresNoRowMarks: !!container.querySelector(`[${NO_ROW_MARKS_ATTR}]`)
1998
1780
  };
1999
1781
  } catch {
2000
- return EMPTY2;
1782
+ return EMPTY;
2001
1783
  }
2002
1784
  }
2003
1785
  function isBlankRender(i) {
@@ -2021,8 +1803,8 @@ function censusClippedText(container) {
2021
1803
  try {
2022
1804
  const svg = container?.querySelector?.("svg");
2023
1805
  if (!svg) return none;
2024
- const f2 = svg.getBoundingClientRect();
2025
- if (!f2 || !(f2.width > 0) || !(f2.height > 0)) return none;
1806
+ const f = svg.getBoundingClientRect();
1807
+ if (!f || !(f.width > 0) || !(f.height > 0)) return none;
2026
1808
  const view = svg.ownerDocument?.defaultView;
2027
1809
  const clipped = [];
2028
1810
  let measured = 0;
@@ -2032,7 +1814,7 @@ function censusClippedText(container) {
2032
1814
  const s = view?.getComputedStyle?.(t);
2033
1815
  if (s && (s.display === "none" || s.visibility === "hidden" || s.opacity === "0")) continue;
2034
1816
  measured++;
2035
- const top = f2.top - r.top, left = f2.left - r.left, bottom = r.bottom - f2.bottom, right = r.right - f2.right;
1817
+ const top = f.top - r.top, left = f.left - r.left, bottom = r.bottom - f.bottom, right = r.right - f.right;
2036
1818
  if (top > CLIP_TOLERANCE_PX || left > CLIP_TOLERANCE_PX || bottom > CLIP_TOLERANCE_PX || right > CLIP_TOLERANCE_PX) {
2037
1819
  clipped.push({
2038
1820
  text: String(t.textContent ?? "").slice(0, 40),
@@ -2057,12 +1839,12 @@ function clippedTextFlag(c) {
2057
1839
  }
2058
1840
 
2059
1841
  // src/valuePlacement.ts
2060
- var MIN_MARKS2 = 24;
2061
- var ELEMENT_CAP2 = 5e3;
1842
+ var MIN_MARKS = 24;
1843
+ var ELEMENT_CAP = 5e3;
2062
1844
  var FIT_SAMPLE = 90;
2063
1845
  var VALUE_AXIS_MIN_FIT = 0.8;
2064
1846
  var MIN_AXIS_SPAN_PX = 40;
2065
- var EMPTY3 = { marks: 0, axis: "", column: "", fit: 0, offShare: 0, medianOffRadii: 0 };
1847
+ var EMPTY2 = { marks: 0, axis: "", column: "", fit: 0, offShare: 0, medianOffRadii: 0 };
2066
1848
  function num2(el, name) {
2067
1849
  const v = el.getAttribute?.(name);
2068
1850
  if (v === null || v === void 0 || String(v).trim() === "") return NaN;
@@ -2095,12 +1877,12 @@ function robustLine(v, pos) {
2095
1877
  }
2096
1878
  function censusValuePlacement(container, data) {
2097
1879
  try {
2098
- if (!container || typeof container.querySelectorAll !== "function") return EMPTY3;
1880
+ if (!container || typeof container.querySelectorAll !== "function") return EMPTY2;
2099
1881
  const rows = data?.rows;
2100
1882
  const columns = data?.columns ?? [];
2101
- if (!Array.isArray(rows) || !rows.length || !columns.length) return EMPTY3;
1883
+ if (!Array.isArray(rows) || !rows.length || !columns.length) return EMPTY2;
2102
1884
  const els = Array.from(container.querySelectorAll(`circle[${ROW_IDX_ATTR}]`));
2103
- if (els.length < MIN_MARKS2 || els.length > ELEMENT_CAP2) return EMPTY3;
1885
+ if (els.length < MIN_MARKS || els.length > ELEMENT_CAP) return EMPTY2;
2104
1886
  const dots = [];
2105
1887
  const seen = /* @__PURE__ */ new Set();
2106
1888
  for (const el of els) {
@@ -2113,7 +1895,7 @@ function censusValuePlacement(container, data) {
2113
1895
  seen.add(i);
2114
1896
  dots.push({ row, x, y, r });
2115
1897
  }
2116
- if (dots.length < MIN_MARKS2 || seen.size < dots.length * 0.9) return EMPTY3;
1898
+ if (dots.length < MIN_MARKS || seen.size < dots.length * 0.9) return EMPTY2;
2117
1899
  let best = null;
2118
1900
  for (let c = 0; c < columns.length; c++) {
2119
1901
  if (/^__.*__$/.test(String(columns[c]?.name ?? ""))) continue;
@@ -2158,7 +1940,7 @@ function censusValuePlacement(container, data) {
2158
1940
  }
2159
1941
  }
2160
1942
  }
2161
- if (!best) return EMPTY3;
1943
+ if (!best) return EMPTY2;
2162
1944
  let off = 0, measured = 0;
2163
1945
  const radii = [];
2164
1946
  dots.forEach((d, k) => {
@@ -2169,7 +1951,7 @@ function censusValuePlacement(container, data) {
2169
1951
  radii.push(inRadii);
2170
1952
  if (inRadii > 1) off++;
2171
1953
  });
2172
- if (measured < MIN_MARKS2) return EMPTY3;
1954
+ if (measured < MIN_MARKS) return EMPTY2;
2173
1955
  return {
2174
1956
  marks: measured,
2175
1957
  axis: best.axis,
@@ -2179,7 +1961,7 @@ function censusValuePlacement(container, data) {
2179
1961
  medianOffRadii: Math.round(median(radii) * 100) / 100
2180
1962
  };
2181
1963
  } catch {
2182
- return EMPTY3;
1964
+ return EMPTY2;
2183
1965
  }
2184
1966
  }
2185
1967
  function valuePlacementFlag(c) {
@@ -2192,7 +1974,7 @@ function valuePlacementFlag(c) {
2192
1974
  // src/labelContrastDom.ts
2193
1975
  var LABEL_CONTRAST_DONE_ATTR = "data-lch-contrast";
2194
1976
  var LABEL_CONTRAST_CAP = 2e3;
2195
- var EMPTY4 = {
1977
+ var EMPTY3 = {
2196
1978
  rects: 0,
2197
1979
  scanned: 0,
2198
1980
  fixed: 0,
@@ -2343,7 +2125,7 @@ function addPill(tx, fill) {
2343
2125
  }
2344
2126
  }
2345
2127
  function applyLabelContrast(container, opts = {}) {
2346
- const report = { ...EMPTY4 };
2128
+ const report = { ...EMPTY3 };
2347
2129
  if (!container) {
2348
2130
  report.skipped = "no-container";
2349
2131
  return report;
@@ -3797,11 +3579,11 @@ function createChartHost(container, config) {
3797
3579
  }
3798
3580
  return windowOf.get(el) ?? null;
3799
3581
  };
3800
- const EPS2 = 0.5;
3582
+ const EPS = 0.5;
3801
3583
  return (m, x, y) => {
3802
3584
  for (let el = m; el && el !== container; el = el.parentElement) {
3803
3585
  const w = read(el);
3804
- if (w && (x < w.left - EPS2 || x > w.right + EPS2 || y < w.top - EPS2 || y > w.bottom + EPS2)) return false;
3586
+ if (w && (x < w.left - EPS || x > w.right + EPS || y < w.top - EPS || y > w.bottom + EPS)) return false;
3805
3587
  }
3806
3588
  return true;
3807
3589
  };
@@ -4205,6 +3987,21 @@ function createChartHost(container, config) {
4205
3987
  } catch {
4206
3988
  }
4207
3989
  }
3990
+ if (config.onCategoryColourCensus) {
3991
+ const report = config.onCategoryColourCensus;
3992
+ const bg = resolved.backgroundColor ?? resolved.themeBg;
3993
+ const opts = {
3994
+ pageBg: typeof bg === "string" && bg ? bg : void 0,
3995
+ dimOpacity: typeof resolved.dimOpacity === "number" ? resolved.dimOpacity : void 0
3996
+ };
3997
+ import("./category-colours.mjs").then((m) => {
3998
+ try {
3999
+ report(m.censusCategoryColours(container, doc, opts));
4000
+ } catch {
4001
+ }
4002
+ }).catch(() => {
4003
+ });
4004
+ }
4208
4005
  if (config.onClippedTextCensus) {
4209
4006
  try {
4210
4007
  config.onClippedTextCensus(censusClippedText(container));
@@ -4218,6 +4015,7 @@ function createChartHost(container, config) {
4218
4015
  }
4219
4016
  }
4220
4017
  const scrollMem = takeScroll(container);
4018
+ if (keepScroll) restoreInnerScroll(container, scrollMem, scrollKey());
4221
4019
  if (fitOpts !== false) {
4222
4020
  try {
4223
4021
  const base = fitOpts === true ? {} : fitOpts;
@@ -4536,7 +4334,7 @@ function createChartHost(container, config) {
4536
4334
  }
4537
4335
 
4538
4336
  // src/group.ts
4539
- var EMPTY5 = Object.freeze({ sourceId: null, rows: Object.freeze([]) });
4337
+ var EMPTY4 = Object.freeze({ sourceId: null, rows: Object.freeze([]) });
4540
4338
  function toSourceRows(rowMap, payloadRowIdxs) {
4541
4339
  if (!rowMap) return payloadRowIdxs.slice();
4542
4340
  return payloadRowIdxs.map((i) => rowMap[i]).filter((i) => i !== void 0);
@@ -4574,7 +4372,7 @@ function createChartGroup(columns, rows, opts = {}) {
4574
4372
  let geo = opts.geo ?? null;
4575
4373
  let point = opts.point ?? null;
4576
4374
  let destination = opts.destination ?? null;
4577
- let selection = EMPTY5;
4375
+ let selection = EMPTY4;
4578
4376
  const subs = /* @__PURE__ */ new Set();
4579
4377
  const members = /* @__PURE__ */ new Set();
4580
4378
  const notify = (change) => {
@@ -4707,11 +4505,6 @@ export {
4707
4505
  straddles,
4708
4506
  minContrastOver,
4709
4507
  pickColorOver,
4710
- deltaEHex,
4711
- SAME_SHADE_DELTA_E,
4712
- MIN_RAMP_FILLS,
4713
- censusColourSpread,
4714
- colourSpreadFlag,
4715
4508
  AUTO_RAMP_CLASSES,
4716
4509
  AUTO_RAMP_DRAWN_OPACITY,
4717
4510
  AUTO_RAMP_MIN_STEP_DELTA_E,
@@ -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-GXR7T6G5.mjs";
4
+ } from "./chunk-QG5TENI3.mjs";
5
5
 
6
6
  // src/snapshot.ts
7
7
  var DEFAULT_TIMEOUT_MS = 2e3;
@@ -6,7 +6,7 @@ import {
6
6
  Vt,
7
7
  j,
8
8
  u
9
- } from "./chunk-VPFP35XI.mjs";
9
+ } from "./chunk-K2TH7D5V.mjs";
10
10
 
11
11
  // src/sourceDateFormat.ts
12
12
  function formatSourceDate(raw, opts = {}) {