@bicharts/chart-host 0.6.111 → 0.6.113

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.
@@ -21,7 +21,6 @@ import {
21
21
  nextSelection,
22
22
  paintSelectionGlyphs,
23
23
  planSelectionPaint,
24
- sameRowSet,
25
24
  selectionRuleOf,
26
25
  trackPress,
27
26
  validRowSet
@@ -35,15 +34,16 @@ import {
35
34
  } from "./chunk-7XT5OJ6M.mjs";
36
35
  import {
37
36
  geoFromCache
38
- } from "./chunk-S564YXNE.mjs";
37
+ } from "./chunk-5YSZABCS.mjs";
39
38
  import {
40
39
  Fn,
41
40
  Q,
42
- Rr,
41
+ Rt,
43
42
  Yn,
43
+ _r,
44
44
  tt,
45
45
  xt
46
- } from "./chunk-NJWR3DFK.mjs";
46
+ } from "./chunk-FIG5DIW7.mjs";
47
47
  import {
48
48
  ACTIVE_TICK_CLASS,
49
49
  ANIM_LOOP_DELAY_DEFAULT,
@@ -1319,7 +1319,7 @@ function resolvePointChannel(cols, rowObjs, point) {
1319
1319
  let labelCol;
1320
1320
  if (bind) {
1321
1321
  const dims = cols.filter((c) => !c.isMeasure).map((c) => c.name);
1322
- const res = Rr(dims, rowObjs, bind, point?.mapKind, cols.map((c) => c.name));
1322
+ const res = _r(dims, rowObjs, bind, point?.mapKind, cols.map((c) => c.name));
1323
1323
  bind = res.bind;
1324
1324
  rolesBackfilled = res.backfilled;
1325
1325
  rolesRefused = res.refused;
@@ -1496,7 +1496,7 @@ function buildRenderPayload(cols, rowObjs, geo, point, destination, opts) {
1496
1496
  }
1497
1497
  function longitudeBeside(names) {
1498
1498
  const words = (n) => n.replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase().split(/[^a-zÀ-ɏ]+/);
1499
- return names.find((n) => words(n).some((w) => w === "lon" || w === "lng" || w === "long" || w === "longitude")) ?? null;
1499
+ return names.find((n) => words(n).some((w) => w === "lon" || w === "lng" || w === "long" || w === "longitude")) ?? names.find((n) => Rt(words(n)) === "lon") ?? null;
1500
1500
  }
1501
1501
 
1502
1502
  // src/codeComments.ts
@@ -2227,6 +2227,26 @@ function invalidSentinelReason(text2, max = 240) {
2227
2227
  return cap <= 3 ? reason.slice(0, cap) : reason.slice(0, cap - 3).trimEnd() + "...";
2228
2228
  }
2229
2229
 
2230
+ // src/rowGrowth.ts
2231
+ var ROW_GROWTH_MIN_RATIO = 10;
2232
+ var ROW_GROWTH_MIN_EXTRA = 500;
2233
+ function rowGrowthNotice(builtFor, rendered, opts = {}) {
2234
+ const b = typeof builtFor === "number" && Number.isFinite(builtFor) ? Math.floor(builtFor) : NaN;
2235
+ const r = typeof rendered === "number" && Number.isFinite(rendered) ? Math.floor(rendered) : NaN;
2236
+ if (!(b > 0) || !(r > 0)) return null;
2237
+ if (r < b * ROW_GROWTH_MIN_RATIO || r - b < ROW_GROWTH_MIN_EXTRA) return null;
2238
+ const fmt = opts.formatCount ?? ((n) => n.toLocaleString("en-US"));
2239
+ const tail = opts.canGenerate === false ? "enter a license to generate a chart for this data." : "Generate to rebuild it for this data.";
2240
+ return {
2241
+ code: "row-growth",
2242
+ severity: "data",
2243
+ builtFor: b,
2244
+ rendered: r,
2245
+ text: `Built for ${fmt(b)} row${b === 1 ? "" : "s"}, now showing ${fmt(r)} - ${tail}`,
2246
+ locationToken: `grow:${b}`
2247
+ };
2248
+ }
2249
+
2230
2250
  // src/annotations.ts
2231
2251
  var ANNOTATION_LAYER_CLASS = "bic-annotations";
2232
2252
  var ANNOTATION_CLASS = "bic-annotation";
@@ -2647,7 +2667,10 @@ function rememberFocus(container) {
2647
2667
  }
2648
2668
  } catch {
2649
2669
  }
2650
- return { sig, nth: Math.max(0, nth), start, end, dir };
2670
+ const out = { sig, nth: Math.max(0, nth), start, end, dir };
2671
+ const row = active.getAttribute("data-row-idx");
2672
+ if (row != null && row !== "") out.row = row;
2673
+ return out;
2651
2674
  } catch {
2652
2675
  return null;
2653
2676
  }
@@ -2658,7 +2681,8 @@ function restoreFocus(container, memory) {
2658
2681
  const active = container.ownerDocument?.activeElement;
2659
2682
  if (active && active !== container && container.contains(active)) return false;
2660
2683
  const list = alike(container, memory.sig);
2661
- const el = list[memory.nth] ?? (list.length === 1 ? list[0] : null);
2684
+ const sameRow = memory.row != null ? list.find((e) => e.getAttribute("data-row-idx") === memory.row) : void 0;
2685
+ const el = sameRow ?? list[memory.nth] ?? (list.length === 1 ? list[0] : null);
2662
2686
  if (!el || typeof el.focus !== "function") return false;
2663
2687
  el.focus({ preventScroll: true });
2664
2688
  const t = el;
@@ -2674,6 +2698,73 @@ function restoreFocus(container, memory) {
2674
2698
  return false;
2675
2699
  }
2676
2700
  }
2701
+ function trackFocus(container) {
2702
+ let el = null;
2703
+ let memory = null;
2704
+ let disposed = false;
2705
+ const doc = container.ownerDocument;
2706
+ const view = doc?.defaultView;
2707
+ const forget = () => {
2708
+ el = null;
2709
+ memory = null;
2710
+ };
2711
+ const note = () => {
2712
+ if (disposed) return;
2713
+ const m = rememberFocus(container);
2714
+ el = m ? doc?.activeElement ?? null : null;
2715
+ memory = m;
2716
+ };
2717
+ const onIn = () => note();
2718
+ const onOut = (e) => {
2719
+ const to = e.relatedTarget;
2720
+ if (to) {
2721
+ if (!container.contains(to)) forget();
2722
+ return;
2723
+ }
2724
+ const was = el;
2725
+ try {
2726
+ view?.setTimeout(() => {
2727
+ if (disposed || el !== was || !was || !was.isConnected) return;
2728
+ const active = doc?.activeElement;
2729
+ if (!active || !container.contains(active)) forget();
2730
+ }, 0);
2731
+ } catch {
2732
+ }
2733
+ };
2734
+ container.addEventListener("focusin", onIn);
2735
+ container.addEventListener("focusout", onOut);
2736
+ note();
2737
+ return {
2738
+ takeLost() {
2739
+ if (disposed || !el || !memory || el.isConnected) return null;
2740
+ const active = doc?.activeElement;
2741
+ const fell = !active || active === doc?.body || active === doc?.documentElement || active === container;
2742
+ if (!fell) {
2743
+ if (!container.contains(active)) forget();
2744
+ return null;
2745
+ }
2746
+ const out = { ...memory };
2747
+ const t = el;
2748
+ try {
2749
+ if (typeof t.selectionStart === "number") {
2750
+ out.start = t.selectionStart;
2751
+ out.end = t.selectionEnd;
2752
+ out.dir = t.selectionDirection ?? null;
2753
+ }
2754
+ } catch {
2755
+ }
2756
+ forget();
2757
+ return out;
2758
+ },
2759
+ forget,
2760
+ dispose() {
2761
+ disposed = true;
2762
+ forget();
2763
+ container.removeEventListener("focusin", onIn);
2764
+ container.removeEventListener("focusout", onOut);
2765
+ }
2766
+ };
2767
+ }
2677
2768
 
2678
2769
  // src/keyboardMarks.ts
2679
2770
  var KEYBOARD_STAMP = "// bic:keyboard-marks";
@@ -2831,16 +2922,55 @@ function installKeyboard(env) {
2831
2922
  env.select(mark, { ctrl: !!(e.ctrlKey || e.metaKey), shift: !!e.shiftKey });
2832
2923
  break;
2833
2924
  case "Escape":
2925
+ hideTip();
2834
2926
  if (env.escapeClears !== false) env.clear();
2835
2927
  break;
2836
2928
  }
2837
2929
  };
2838
2930
  container.addEventListener("keydown", onKey);
2931
+ let tipOn = null;
2932
+ const hover = (el, enter) => {
2933
+ try {
2934
+ const view = container.ownerDocument.defaultView;
2935
+ const r = typeof el.getBoundingClientRect === "function" ? el.getBoundingClientRect() : null;
2936
+ const x = r ? r.left + r.width / 2 : 0, y = r ? r.top + r.height / 2 : 0;
2937
+ const ME = view?.MouseEvent ?? MouseEvent;
2938
+ const PE = view?.PointerEvent;
2939
+ const names = enter ? ["pointerover", "pointerenter", "mouseover", "mouseenter", "pointermove", "mousemove"] : ["pointerout", "pointerleave", "mouseout", "mouseleave"];
2940
+ for (const n of names) {
2941
+ const E = n.startsWith("pointer") && PE ? PE : ME;
2942
+ el.dispatchEvent(new E(n, { bubbles: !/enter|leave/.test(n), cancelable: true, clientX: x, clientY: y }));
2943
+ }
2944
+ } catch {
2945
+ }
2946
+ };
2947
+ const hideTip = () => {
2948
+ const el = tipOn;
2949
+ tipOn = null;
2950
+ if (el) hover(el, false);
2951
+ };
2952
+ const onFocusIn = (e) => {
2953
+ if (destroyed) return;
2954
+ const mark = e.target?.closest?.(env.markSelector);
2955
+ if (!mark || !wired(mark) || !container.contains(mark) || mark === tipOn) return;
2956
+ hideTip();
2957
+ tipOn = mark;
2958
+ hover(mark, true);
2959
+ };
2960
+ const onFocusOut = (e) => {
2961
+ const to = e.relatedTarget;
2962
+ if (tipOn && (!to || !tipOn.contains(to))) hideTip();
2963
+ };
2964
+ container.addEventListener("focusin", onFocusIn);
2965
+ container.addEventListener("focusout", onFocusOut);
2839
2966
  return {
2840
2967
  refresh,
2841
2968
  destroy() {
2842
2969
  destroyed = true;
2843
2970
  container.removeEventListener("keydown", onKey);
2971
+ container.removeEventListener("focusin", onFocusIn);
2972
+ container.removeEventListener("focusout", onFocusOut);
2973
+ hideTip();
2844
2974
  try {
2845
2975
  container.classList?.remove(KEYBOARD_CLASS);
2846
2976
  } catch {
@@ -3044,13 +3174,19 @@ function createChartHost(container, config) {
3044
3174
  };
3045
3175
  const resolveForHost = (input) => {
3046
3176
  const out = resolveOptions(input);
3047
- return out.allowTooltips == null ? { ...out, allowTooltips: true } : out;
3177
+ const named = (v) => typeof v === "string" && v.trim() !== "";
3178
+ const bg = named(out.backgroundColor) ? out.backgroundColor : void 0;
3179
+ const themeBg = named(out.themeBg) ? out.themeBg : void 0;
3180
+ const filled = bg && !themeBg ? { themeBg: bg } : themeBg && !bg ? { backgroundColor: themeBg } : null;
3181
+ const withBg = filled ? { ...out, ...filled } : out;
3182
+ return withBg.allowTooltips == null ? { ...withBg, allowTooltips: true } : withBg;
3048
3183
  };
3049
3184
  if (!lassoClaimed) claimParkedLasso(container, lassoKey);
3050
3185
  let resolved = resolveForHost(raw);
3051
3186
  let renderFn = config.renderFn ?? null;
3052
3187
  let destroyed = false;
3053
3188
  let warnedGeo = false;
3189
+ let warnedGrowth = false;
3054
3190
  let warnedBlank = false;
3055
3191
  let warnedIds = false;
3056
3192
  let warnedLassoNoFilter = false;
@@ -3579,7 +3715,8 @@ function createChartHost(container, config) {
3579
3715
  next,
3580
3716
  { ctrl: !!(e?.ctrlKey || e?.metaKey), shift: !!e?.shiftKey }
3581
3717
  ));
3582
- notify(next, "user", toggledOff ? null : tick);
3718
+ const fromLabel = !!tick && !multi && !toggledOff && !chartOwnsTimeline(container);
3719
+ notify(next, "user", toggledOff ? null : tick, false, true, fromLabel ? { fromLabel: true } : void 0);
3583
3720
  };
3584
3721
  container.addEventListener(XFILTER_REFRESH_EVENT, onXf);
3585
3722
  const untrackPress = trackPress(container);
@@ -3714,6 +3851,20 @@ function createChartHost(container, config) {
3714
3851
  }
3715
3852
  } catch {
3716
3853
  }
3854
+ try {
3855
+ const growth = rowGrowthNotice(config.builtForRows, data.rows ? data.rows.length : 0);
3856
+ if (growth) {
3857
+ if (config.onRowGrowth) config.onRowGrowth(growth);
3858
+ else if (!warnedGrowth) {
3859
+ warnedGrowth = true;
3860
+ try {
3861
+ (win?.console ?? console)?.warn(`[@bicharts/chart-host] ${growth.text}`);
3862
+ } catch {
3863
+ }
3864
+ }
3865
+ }
3866
+ } catch {
3867
+ }
3717
3868
  if (config.onHitBandCensus) {
3718
3869
  try {
3719
3870
  config.onHitBandCensus(censusHitBands(container, doc));
@@ -3793,13 +3944,29 @@ function createChartHost(container, config) {
3793
3944
  keyboard?.refresh();
3794
3945
  selfRedraw?.takeRecords();
3795
3946
  };
3947
+ const focusTrack = (() => {
3948
+ try {
3949
+ return trackFocus(container);
3950
+ } catch {
3951
+ return null;
3952
+ }
3953
+ })();
3796
3954
  function watchSelfRedraw() {
3797
3955
  const MO = win?.MutationObserver;
3798
3956
  if (selfRedraw || !MO || destroyed) return;
3799
3957
  selfRedraw = new MO((records) => {
3800
- if (destroyed || !records.some((r) => Array.from(r.removedNodes).some(takesMarks))) return;
3801
- if (!(current && current.length) && !notesHeld && !lassoLost()) return;
3802
- repaintAfterChart();
3958
+ if (destroyed) return;
3959
+ const tookMarks = records.some((r) => Array.from(r.removedNodes).some(takesMarks));
3960
+ const lost = focusTrack?.takeLost() ?? null;
3961
+ if (tookMarks && (current && current.length || notesHeld || lassoLost() || keyboard)) repaintAfterChart();
3962
+ else if (lost) keyboard?.refresh();
3963
+ if (lost) {
3964
+ try {
3965
+ restoreFocus(container, lost);
3966
+ } catch {
3967
+ }
3968
+ }
3969
+ selfRedraw?.takeRecords();
3803
3970
  });
3804
3971
  selfRedraw.observe(container, { childList: true, subtree: true });
3805
3972
  }
@@ -3825,6 +3992,7 @@ function createChartHost(container, config) {
3825
3992
  if (hasRendered && keepScroll) rememberScroll(container, scrollKey());
3826
3993
  container.innerHTML = "";
3827
3994
  selfRedraw?.takeRecords();
3995
+ focusTrack?.forget();
3828
3996
  hasRendered = true;
3829
3997
  if (!renderFn) {
3830
3998
  if (!config.code) throw new Error("createChartHost: provide code or renderFn");
@@ -3977,7 +4145,10 @@ function createChartHost(container, config) {
3977
4145
  highlight(rowIdxs) {
3978
4146
  if (destroyed) return;
3979
4147
  const rows = Array.isArray(rowIdxs) ? rowIdxs.slice() : [];
3980
- if (lasso && lasso.rows().length && !sameRowSet(rows, lasso.rows())) lasso.clear({ publish: false, source: "host" });
4148
+ if (lasso && lasso.rows().length) {
4149
+ const painted = new Set(rows);
4150
+ if (!lasso.rows().every((r) => painted.has(r))) lasso.clear({ publish: false, source: "host" });
4151
+ }
3981
4152
  notify(rows, "host");
3982
4153
  },
3983
4154
  setHidden(count) {
@@ -4007,6 +4178,7 @@ function createChartHost(container, config) {
4007
4178
  selfRedraw.disconnect();
4008
4179
  selfRedraw = null;
4009
4180
  }
4181
+ focusTrack?.dispose();
4010
4182
  keyboard?.destroy();
4011
4183
  keyboard = null;
4012
4184
  container.removeEventListener(XFILTER_REFRESH_EVENT, onXf);
@@ -4254,10 +4426,14 @@ export {
4254
4426
  scopeChartIds,
4255
4427
  isInvalidSentinelError,
4256
4428
  invalidSentinelReason,
4429
+ ROW_GROWTH_MIN_RATIO,
4430
+ ROW_GROWTH_MIN_EXTRA,
4431
+ rowGrowthNotice,
4257
4432
  ANNOTATION_LAYER_CLASS,
4258
4433
  ANNOTATION_CLASS,
4259
4434
  rememberFocus,
4260
4435
  restoreFocus,
4436
+ trackFocus,
4261
4437
  KEYBOARD_STAMP,
4262
4438
  codeHasKeyboardStamp,
4263
4439
  KEYBOARD_CLASS,
@@ -5,14 +5,47 @@ var WORLD_110M = { "type": "FeatureCollection", "features": [{ "type": "Feature"
5
5
 
6
6
  // src/geoWorld110m.ts
7
7
  var JOIN_KEY_FOR_NAME = { Kosovo: "XKX" };
8
+ var TERRITORY_PARTS = [
9
+ { from: "FRA", to: "GUF", name: "French Guiana", window: [-56, 1, -50, 7] },
10
+ { from: "NOR", to: "SJM", name: "Svalbard and Jan Mayen", window: [-10, 74, 40, 82] }
11
+ ];
12
+ var ringInside = (ring, [x0, y0, x1, y1]) => ring.every(([x, y]) => x >= x0 && x <= x1 && y >= y0 && y <= y1);
13
+ var isPolygonal = (f) => f?.geometry?.type === "Polygon" || f?.geometry?.type === "MultiPolygon";
14
+ function splitTerritories(features) {
15
+ const hasPolygon = new Set(features.filter(isPolygonal).map((f) => f.id));
16
+ const out = [];
17
+ for (const f of features) {
18
+ const rules = f?.geometry?.type === "MultiPolygon" ? TERRITORY_PARTS.filter((r) => r.from === f.id && !hasPolygon.has(r.to)) : [];
19
+ if (!rules.length) {
20
+ out.push(f);
21
+ continue;
22
+ }
23
+ let kept = f.geometry.coordinates;
24
+ const split = [];
25
+ for (const r of rules) {
26
+ const moved = kept.filter((p) => ringInside(p[0], r.window));
27
+ if (!moved.length || moved.length === kept.length) continue;
28
+ kept = kept.filter((p) => !moved.includes(p));
29
+ split.push({
30
+ type: "Feature",
31
+ id: r.to,
32
+ properties: { ...f.properties, name: r.name },
33
+ geometry: moved.length === 1 ? { type: "Polygon", coordinates: moved[0] } : { type: "MultiPolygon", coordinates: moved }
34
+ });
35
+ }
36
+ out.push(split.length ? { ...f, geometry: { ...f.geometry, coordinates: kept } } : f, ...split);
37
+ }
38
+ return out;
39
+ }
8
40
  var WORLD_110M2 = {
9
41
  ...WORLD_110M,
10
- features: WORLD_110M.features.map((f) => {
42
+ features: splitTerritories(WORLD_110M.features.map((f) => {
11
43
  const to = JOIN_KEY_FOR_NAME[f?.id];
12
44
  return to ? { ...f, id: to } : f;
13
- })
45
+ }))
14
46
  };
15
47
 
16
48
  export {
49
+ TERRITORY_PARTS,
17
50
  WORLD_110M2 as WORLD_110M
18
51
  };
package/dist/dax.mjs CHANGED
@@ -1,4 +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
+ import {
3
+ isAnyValue
4
+ } from "./chunk-2KLFIGTQ.mjs";
2
5
  import "./chunk-GHODWOAL.mjs";
3
6
 
4
7
  // src/dax.ts
@@ -28,8 +31,17 @@ function treatAs(selection, ...columnRefs) {
28
31
  for (const k of keys) {
29
32
  if (k.length < width) throw new Error(`treatAs: a key has ${k.length} value(s) for ${width} column(s)`);
30
33
  }
31
- const rows = keys.map((k) => width === 1 ? daxLiteral(k[0]) : `(${k.slice(0, width).map(daxLiteral).join(", ")})`);
32
- return `TREATAS({${rows.join(", ")}}, ${columnRefs.map((c) => c.trim()).join(", ")})`;
34
+ const refs = columnRefs.map((c) => c.trim());
35
+ const pattern = (k) => k.slice(0, width).map((v) => isAnyValue(v) ? "*" : "=").join("");
36
+ const patterns = new Set(keys.map(pattern));
37
+ if (patterns.size === 1) {
38
+ const fixed = [...patterns][0].split("").map((p, i) => p === "=" ? i : -1).filter((i) => i >= 0);
39
+ if (!fixed.length) return null;
40
+ const rows = keys.map((k) => fixed.length === 1 ? daxLiteral(k[fixed[0]]) : `(${fixed.map((i) => daxLiteral(k[i])).join(", ")})`);
41
+ return `TREATAS({${rows.join(", ")}}, ${fixed.map((i) => refs[i]).join(", ")})`;
42
+ }
43
+ const preds = keys.map((k) => `(${k.slice(0, width).map((v, i) => isAnyValue(v) ? null : `${refs[i]} = ${daxLiteral(v)}`).filter(Boolean).join(" && ") || "TRUE()"})`);
44
+ return `FILTER(CROSSJOIN(${refs.map((r) => `VALUES(${r})`).join(", ")}), ${preds.join(" || ")})`;
33
45
  }
34
46
  function calculateTable(table, ...filters) {
35
47
  const live = filters.filter((f) => typeof f === "string" && f.trim().length > 0);
@@ -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
  WORLD_110M
4
- } from "./chunk-3JCWTEEH.mjs";
4
+ } from "./chunk-ZI5HXXM2.mjs";
5
5
  import "./chunk-GHODWOAL.mjs";
6
6
  export {
7
7
  WORLD_110M
package/dist/geo.mjs CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-A2GMXZP7.mjs";
7
7
  import {
8
8
  WORLD_110M
9
- } from "./chunk-3JCWTEEH.mjs";
9
+ } from "./chunk-ZI5HXXM2.mjs";
10
10
  import {
11
11
  US_STATES
12
12
  } from "./chunk-75ZJSYIF.mjs";
@@ -1,8 +1,10 @@
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
+ TERRITORY_PARTS,
3
4
  WORLD_110M
4
- } from "./chunk-3JCWTEEH.mjs";
5
+ } from "./chunk-ZI5HXXM2.mjs";
5
6
  import "./chunk-GHODWOAL.mjs";
6
7
  export {
8
+ TERRITORY_PARTS,
7
9
  WORLD_110M
8
10
  };
package/dist/index.mjs CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  formatSourceDateFor,
6
6
  isExcelDateFormat,
7
7
  normaliseAggregation
8
- } from "./chunk-Q43WOKSV.mjs";
8
+ } from "./chunk-OLCUKXKL.mjs";
9
9
  import {
10
10
  captureSvgSnapshot,
11
11
  chartSvgOf,
@@ -41,6 +41,8 @@ import {
41
41
  PILL_MIN_ALPHA,
42
42
  PILL_MIN_COVERAGE,
43
43
  PILL_OPAQUE_ALPHA,
44
+ ROW_GROWTH_MIN_EXTRA,
45
+ ROW_GROWTH_MIN_RATIO,
44
46
  SAME_SHADE_DELTA_E,
45
47
  STRADDLE_COLS,
46
48
  STRADDLE_MIN_SHARE,
@@ -101,6 +103,7 @@ import {
101
103
  resolveAutoColorScale,
102
104
  resolveOptions,
103
105
  restoreFocus,
106
+ rowGrowthNotice,
104
107
  rowNameOf,
105
108
  scopeChartIds,
106
109
  sessionViewStateProvider,
@@ -114,8 +117,9 @@ import {
114
117
  tableToXlsx,
115
118
  toRGBA,
116
119
  toSourceRows,
120
+ trackFocus,
117
121
  valuePlacementFlag
118
- } from "./chunk-CASW2BIB.mjs";
122
+ } from "./chunk-TE54AFRN.mjs";
119
123
  import {
120
124
  LASSO_AXES_SLOT,
121
125
  LASSO_COUNT_CLASS,
@@ -210,12 +214,12 @@ import {
210
214
  loadGeo,
211
215
  registerGeo,
212
216
  registerGeoAsset
213
- } from "./chunk-S564YXNE.mjs";
217
+ } from "./chunk-5YSZABCS.mjs";
214
218
  import {
215
219
  Ot,
216
220
  l,
217
221
  o
218
- } from "./chunk-NJWR3DFK.mjs";
222
+ } from "./chunk-FIG5DIW7.mjs";
219
223
  import "./chunk-A2GMXZP7.mjs";
220
224
  import {
221
225
  ACTIVE_TICK_CLASS,
@@ -2441,6 +2445,8 @@ export {
2441
2445
  QUALIFY_TILE_REFUSAL_CODES,
2442
2446
  QUALIFY_TOO_SMALL_HEADING,
2443
2447
  RECOVERY_UNREACHABLE_MESSAGE,
2448
+ ROW_GROWTH_MIN_EXTRA,
2449
+ ROW_GROWTH_MIN_RATIO,
2444
2450
  ROW_IDX_ATTR,
2445
2451
  ROW_SET_MAX,
2446
2452
  SAME_SHADE_DELTA_E,
@@ -2653,6 +2659,7 @@ export {
2653
2659
  resolveAutoColorScale,
2654
2660
  resolveOptions,
2655
2661
  restoreFocus,
2662
+ rowGrowthNotice,
2656
2663
  rowIdxsFromMark,
2657
2664
  rowNameOf,
2658
2665
  sameMarker,
@@ -2683,6 +2690,7 @@ export {
2683
2690
  takeScroll,
2684
2691
  toRGBA,
2685
2692
  toSourceRows,
2693
+ trackFocus,
2686
2694
  trackPress,
2687
2695
  transportFailureShouldRecover,
2688
2696
  unpinScrolledAxis,
package/dist/page.mjs CHANGED
@@ -1,26 +1,31 @@
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
- LINKED_HOVER_CLASS,
4
3
  attachControls,
5
4
  badgeKey,
6
- bindFilter,
7
5
  createControls,
6
+ noteBadges,
7
+ notesFor,
8
+ readControls
9
+ } from "./chunk-GTJG3SMD.mjs";
10
+ import "./chunk-IL5M7K6Z.mjs";
11
+ import "./chunk-KGVNZR23.mjs";
12
+ import "./chunk-KY4FI2HA.mjs";
13
+ import {
14
+ ANY_VALUE,
15
+ LINKED_HOVER_CLASS,
16
+ bindFilter,
8
17
  createFilter,
9
18
  createFilterScope,
10
19
  filterScopeOf,
11
20
  fromVegaInteraction,
12
- noteBadges,
13
- notesFor,
21
+ isAnyValue,
14
22
  payloadRowReader,
15
- readControls,
16
23
  viewFromToken,
17
24
  viewToken
18
- } from "./chunk-FT75ONSB.mjs";
19
- import "./chunk-IL5M7K6Z.mjs";
20
- import "./chunk-KGVNZR23.mjs";
21
- import "./chunk-KY4FI2HA.mjs";
25
+ } from "./chunk-2KLFIGTQ.mjs";
22
26
  import "./chunk-GHODWOAL.mjs";
23
27
  export {
28
+ ANY_VALUE,
24
29
  LINKED_HOVER_CLASS,
25
30
  attachControls,
26
31
  badgeKey,
@@ -30,6 +35,7 @@ export {
30
35
  createFilterScope,
31
36
  filterScopeOf,
32
37
  fromVegaInteraction,
38
+ isAnyValue,
33
39
  noteBadges,
34
40
  notesFor,
35
41
  payloadRowReader,
@@ -2,12 +2,13 @@
2
2
  import {
3
3
  geoFromCache,
4
4
  registerGeo
5
- } from "./chunk-S564YXNE.mjs";
5
+ } from "./chunk-5YSZABCS.mjs";
6
6
  import {
7
- Si,
7
+ Mi,
8
+ Rt,
8
9
  W,
9
10
  bt
10
- } from "./chunk-NJWR3DFK.mjs";
11
+ } from "./chunk-FIG5DIW7.mjs";
11
12
  import "./chunk-A2GMXZP7.mjs";
12
13
  import "./chunk-GHODWOAL.mjs";
13
14
 
@@ -197,6 +198,11 @@ function provinceBinding(res, cols, opts) {
197
198
  const kindOf = (c) => String(c.geoKind ?? "");
198
199
  const words = (n) => n.replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase().split(/[^a-z]+/);
199
200
  const named = (re) => cols.find((c) => words(c.name).some((w) => re.test(w)))?.name ?? null;
201
+ const accentWords = (n) => n.replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase().split(/[^a-zÀ-ɏ]+/);
202
+ const localized = (axis) => cols.find((c) => Rt(accentWords(c.name)) === axis)?.name ?? null;
203
+ const lat = named(/^(lat|latitude)$/), lon = named(/^(lon|lng|long|longitude)$/);
204
+ const localLat = localized("lat"), localLon = localized("lon");
205
+ const usePair = localLat !== null && localLon !== null;
200
206
  return {
201
207
  column: res.geoColumn,
202
208
  kind: res.geoKind,
@@ -205,11 +211,11 @@ function provinceBinding(res, cols, opts) {
205
211
  fallback: {
206
212
  city: dims.find((c) => kindOf(c).startsWith("city"))?.name ?? null,
207
213
  country: dims.find((c) => kindOf(c).startsWith("country"))?.name ?? null,
208
- lat: named(/^(lat|latitude)$/),
209
- lon: named(/^(lon|lng|long|longitude)$/)
214
+ lat: lat ?? (usePair ? localLat : null),
215
+ lon: lon ?? (usePair ? localLon : null)
210
216
  },
211
217
  deriveProvinces: opts.deriveProvinces,
212
- join: Si,
218
+ join: Mi,
213
219
  locate: opts.geo ? provinceLocator(opts.geo) : null
214
220
  };
215
221
  }