@bicharts/chart-host 0.6.63 → 0.6.65

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.
@@ -567,15 +567,15 @@ function decideLabelColor(textColor, fill, fillOpacity, pageBg, minContrast = MI
567
567
  return useLight ? { fix: true, color: LIGHT_TEXT, reason: "fixed-light" } : { fix: true, color: DARK_TEXT, reason: "fixed-dark" };
568
568
  }
569
569
  var GLYPH_SAMPLE_N = 3;
570
- function glyphSampleGrid(box, n = GLYPH_SAMPLE_N) {
570
+ function glyphSampleGrid(box2, n = GLYPH_SAMPLE_N) {
571
571
  const out = [];
572
- if (!box || !(box.width > 0) || !(box.height > 0) || !(n >= 1)) return out;
572
+ if (!box2 || !(box2.width > 0) || !(box2.height > 0) || !(n >= 1)) return out;
573
573
  const k3 = Math.floor(n);
574
574
  for (let i = 0; i < k3; i++) {
575
575
  for (let j4 = 0; j4 < k3; j4++) {
576
576
  out.push({
577
- x: box.left + box.width * (i + 0.5) / k3,
578
- y: box.top + box.height * (j4 + 0.5) / k3
577
+ x: box2.left + box2.width * (i + 0.5) / k3,
578
+ y: box2.top + box2.height * (j4 + 0.5) / k3
579
579
  });
580
580
  }
581
581
  }
@@ -586,14 +586,14 @@ var STRADDLE_ROWS = 2;
586
586
  var STRADDLE_MIN_SHARE = 0.125;
587
587
  var STRADDLE_TARGET_CONTRAST = 4.5;
588
588
  var STRADDLE_PILL_ALPHA = 0.9;
589
- function straddleSampleGrid(box) {
589
+ function straddleSampleGrid(box2) {
590
590
  const out = [];
591
- if (!box || !(box.width > 0) || !(box.height > 0)) return out;
591
+ if (!box2 || !(box2.width > 0) || !(box2.height > 0)) return out;
592
592
  for (let i = 0; i < STRADDLE_COLS; i++) {
593
593
  for (let j4 = 0; j4 < STRADDLE_ROWS; j4++) {
594
594
  out.push({
595
- x: box.left + box.width * (i + 0.5) / STRADDLE_COLS,
596
- y: box.top + box.height * (j4 + 0.5) / STRADDLE_ROWS
595
+ x: box2.left + box2.width * (i + 0.5) / STRADDLE_COLS,
596
+ y: box2.top + box2.height * (j4 + 0.5) / STRADDLE_ROWS
597
597
  });
598
598
  }
599
599
  }
@@ -1763,7 +1763,7 @@ function Fn(n, s2) {
1763
1763
  return { iso: o4, unmatched: I2, matchedRows: N, totalRows: n.length };
1764
1764
  }
1765
1765
 
1766
- // ../shape-core/dist/chunk-TBB6BEZ7.mjs
1766
+ // ../shape-core/dist/chunk-OPDY2YEA.mjs
1767
1767
  var import_papaparse = __toESM(require_papaparse_min(), 1);
1768
1768
  /*! @bicharts/shape-core — Apache-2.0. Bundled reference data: GeoNames (https://www.geonames.org/) CC BY 4.0; US Census/TIGER (public domain). Full text: NOTICE in this package. */
1769
1769
  var ze = { "north-america": "AG AI AW BB BL BM BQ BS BZ CA CR CU CW DM DO GD GL GP GT HN HT JM KN KY LC MF MQ MS MX NI PA PM PR SV SX TC TT US VC VG VI", "south-america": "AR BO BR CL CO EC FK GF GY PE PY SR UY VE", europe: "AD AL AT AX BA BE BG BY CH CY CZ DE DK EE ES FI FO FR GB GG GI GR HR HU IE IM IS IT JE LI LT LU LV MC MD ME MK MT NL NO PL PT RO RS RU SE SI SJ SK SM UA VA", africa: "AO BF BI BJ BW CD CF CG CI CM CV DJ DZ EG EH ER ET GA GH GM GN GQ GW KE KM LR LS LY MA MG ML MR MU MW MZ NA NE NG RE RW SC SD SH SL SN SO SS ST SZ TD TG TN TZ UG YT ZA ZM ZW", asia: "AE AF AM AZ BD BH BN BT CC CN CX GE HK ID IL IN IO IQ IR JO JP KG KH KP KR KW KZ LA LB LK MM MN MO MV MY NP OM PH PK PS QA SA SG SY TH TJ TL TM TR TW UZ VN YE", oceania: "AS AU CK FJ FM GU KI MH MP NC NF NR NU NZ PF PG PN PW SB TK TO TV UM VU WF WS", antarctica: "AQ BV GS HM TF" };
@@ -1869,7 +1869,7 @@ var Yt = new RegExp([String.raw`\bisMeasure\b`, String.raw`\bdataType\b`, String
1869
1869
  /*! @bicharts/shape-core — Apache-2.0. Bundled reference data: GeoNames (https://www.geonames.org/) CC BY 4.0; US Census/TIGER (public domain). Full text: NOTICE in this package. */
1870
1870
  var Z3 = 2;
1871
1871
  var me2 = 400;
1872
- function ee3(t) {
1872
+ function te(t) {
1873
1873
  return !!k(t);
1874
1874
  }
1875
1875
  function F3(t) {
@@ -1883,8 +1883,8 @@ function F3(t) {
1883
1883
  }
1884
1884
  function A2(t) {
1885
1885
  let e = F3(t);
1886
- if (e.length === 0 || te(t) < 95) return false;
1887
- let n = e.filter((u4) => ee3(u4) && !t3(u4)).length, o4 = e.filter((u4) => !ee3(u4) && !!t3(u4)).length;
1886
+ if (e.length === 0 || ne2(t) < 95) return false;
1887
+ let n = e.filter((u4) => te(u4) && !t3(u4)).length, o4 = e.filter((u4) => !te(u4) && !!t3(u4)).length;
1888
1888
  return n >= 1 && n >= o4;
1889
1889
  }
1890
1890
  function ce3(t, e) {
@@ -1892,11 +1892,11 @@ function ce3(t, e) {
1892
1892
  let n = k(t);
1893
1893
  return n ? e === "world" ? true : G3.has(n) : false;
1894
1894
  }
1895
- function te(t) {
1895
+ function ne2(t) {
1896
1896
  let e = F3(t);
1897
1897
  if (e.length === 0) return 0;
1898
1898
  let n = 0;
1899
- for (let o4 of e) ee3(o4) && n++;
1899
+ for (let o4 of e) te(o4) && n++;
1900
1900
  return Math.round(n / e.length * 1e3) / 10;
1901
1901
  }
1902
1902
  function z2(t) {
@@ -1906,7 +1906,7 @@ function z2(t) {
1906
1906
  for (let o4 of e) t3(o4) && n++;
1907
1907
  return Math.round(n / e.length * 1e3) / 10;
1908
1908
  }
1909
- function re2(t) {
1909
+ function oe2(t) {
1910
1910
  let e = /* @__PURE__ */ new Set();
1911
1911
  for (let n of t) {
1912
1912
  if (n == null) continue;
@@ -1915,15 +1915,15 @@ function re2(t) {
1915
1915
  }
1916
1916
  return Array.from(e);
1917
1917
  }
1918
- function ne2(t) {
1919
- let e = re2(t);
1918
+ function re2(t) {
1919
+ let e = oe2(t);
1920
1920
  if (e.length === 0) return 0;
1921
1921
  let n = 0;
1922
1922
  for (let o4 of e) r3(o4).length > 0 && n++;
1923
1923
  return Math.round(n / e.length * 1e3) / 10;
1924
1924
  }
1925
1925
  function de(t, e) {
1926
- return y(e, fn) ? true : re2(t).some((n) => /^\d{5}(-\d{4})?$/.test(n.replace(/\.0+$/, "")));
1926
+ return y(e, fn) ? true : oe2(t).some((n) => /^\d{5}(-\d{4})?$/.test(n.replace(/\.0+$/, "")));
1927
1927
  }
1928
1928
  function Bn2(t, e) {
1929
1929
  let n = F3(t);
@@ -1932,54 +1932,54 @@ function Bn2(t, e) {
1932
1932
  for (let u4 of n) j3(u4, e) && o4++;
1933
1933
  return Math.round(o4 / n.length * 1e3) / 10;
1934
1934
  }
1935
- function J5(t, e) {
1935
+ function ee3(t, e) {
1936
1936
  let n = 0;
1937
1937
  for (let o4 of F3(t)) e(o4) && n++;
1938
1938
  return n;
1939
1939
  }
1940
1940
  function jn(t, e) {
1941
1941
  let n = 0;
1942
- for (let o4 of re2(t)) e(o4) && n++;
1942
+ for (let o4 of oe2(t)) e(o4) && n++;
1943
1943
  return n;
1944
1944
  }
1945
1945
  function Yn3(t, e, n, o4, u4) {
1946
- let l2 = [], a3 = [], i = {}, b4 = {}, E4 = new Set(t), y2 = (s2) => e.map((c2) => c2[s2]);
1946
+ let l2 = [], a3 = [], i = {}, h4 = {}, C2 = new Set(t), y2 = (s2) => e.map((d2) => d2[s2]);
1947
1947
  for (let s2 of ["city", "country"]) {
1948
- let c2 = n?.[s2];
1949
- c2 && E4.has(c2) && (i[s2] = c2);
1948
+ let d2 = n?.[s2];
1949
+ d2 && C2.has(d2) && (i[s2] = d2);
1950
1950
  }
1951
1951
  let g5 = new Set(u4 ?? t);
1952
1952
  for (let s2 of ["lat", "lon"]) {
1953
- let c2 = n?.[s2];
1954
- c2 && g5.has(c2) && (i[s2] = c2);
1953
+ let d2 = n?.[s2];
1954
+ d2 && g5.has(d2) && (i[s2] = d2);
1955
1955
  }
1956
1956
  let f4 = n?.zip;
1957
- if (f4 && E4.has(f4)) {
1958
- let s2 = y2(f4), c2 = ne2(s2);
1959
- c2 < 95 ? a3.push(`zip=${f4} (only ${c2}% of values read as ZIPs)`) : de(s2, f4) ? i.zip = f4 : a3.push(`zip=${f4} (all values are 3-4 digits with nothing to say they are postal)`);
1957
+ if (f4 && C2.has(f4)) {
1958
+ let s2 = y2(f4), d2 = re2(s2);
1959
+ d2 < 95 ? a3.push(`zip=${f4} (only ${d2}% of values read as ZIPs)`) : de(s2, f4) ? i.zip = f4 : a3.push(`zip=${f4} (all values are 3-4 digits with nothing to say they are postal)`);
1960
1960
  }
1961
- let d2 = n?.state;
1962
- if (d2 && E4.has(d2)) {
1963
- let s2 = y2(d2), c2 = F3(s2);
1964
- c2.length > 0 && c2.every((S2) => ce3(S2, o4)) ? a3.push(`state=${d2} (every value is "CA", which is both Canada and California)`) : A2(s2) ? (a3.push(`state=${d2} (every value is a country, not a state)`), i.country || (i.country = d2)) : z2(s2) < 95 ? a3.push(`state=${d2} (only ${z2(s2)}% of values are states/provinces)`) : i.state = d2;
1961
+ let c2 = n?.state;
1962
+ if (c2 && C2.has(c2)) {
1963
+ let s2 = y2(c2), d2 = F3(s2);
1964
+ d2.length > 0 && d2.every((S2) => ce3(S2, o4)) ? a3.push(`state=${c2} (every value is "CA", which is both Canada and California)`) : A2(s2) ? (a3.push(`state=${c2} (every value is a country, not a state)`), i.country || (i.country = c2)) : z2(s2) < 95 ? a3.push(`state=${c2} (only ${z2(s2)}% of values are states/provinces)`) : i.state = c2;
1965
1965
  }
1966
- let p4 = new Set(Object.values(i).filter(Boolean)), h4 = t.filter((s2) => !p4.has(s2) && !s2.startsWith("__"));
1966
+ let p4 = new Set(Object.values(i).filter(Boolean)), b4 = t.filter((s2) => !p4.has(s2) && !s2.startsWith("__"));
1967
1967
  if (!i.state) {
1968
1968
  let s2 = null;
1969
- for (let c2 of h4) {
1970
- let S2 = y2(c2);
1969
+ for (let d2 of b4) {
1970
+ let S2 = y2(d2);
1971
1971
  if (A2(S2)) continue;
1972
- let P4 = z2(S2);
1973
- if (P4 < 95) continue;
1974
- let K3 = J5(S2, (D2) => !!t3(D2)), Ne = J5(S2, (D2) => !!t3(D2) && !ce3(D2, o4));
1975
- K3 < Z3 && Ne < 1 || (!s2 || P4 > s2.pct) && (s2 = { name: c2, pct: P4 });
1972
+ let _4 = z2(S2);
1973
+ if (_4 < 95) continue;
1974
+ let H2 = ee3(S2, (D2) => !!t3(D2)), Ne = ee3(S2, (D2) => !!t3(D2) && !ce3(D2, o4));
1975
+ H2 < Z3 && Ne < 1 || (!s2 || _4 > s2.pct) && (s2 = { name: d2, pct: _4 });
1976
1976
  }
1977
1977
  s2 && (i.state = s2.name, p4.add(s2.name), l2.push(`state=${s2.name} (${s2.pct}% states/provinces)`));
1978
1978
  }
1979
- if (!i.zip) for (let s2 of h4) {
1979
+ if (!i.zip) for (let s2 of b4) {
1980
1980
  if (p4.has(s2)) continue;
1981
- let c2 = y2(s2), S2 = ne2(c2);
1982
- if (!(S2 < 95) && de(c2, s2) && !(jn(c2, (P4) => r3(P4).length > 0) < Z3)) {
1981
+ let d2 = y2(s2), S2 = re2(d2);
1982
+ if (!(S2 < 95) && de(d2, s2) && !(jn(d2, (_4) => r3(_4).length > 0) < Z3)) {
1983
1983
  i.zip = s2, p4.add(s2), l2.push(`zip=${s2} (${S2}% ZIP codes)`);
1984
1984
  break;
1985
1985
  }
@@ -1987,31 +1987,31 @@ function Yn3(t, e, n, o4, u4) {
1987
1987
  let T = i.country;
1988
1988
  if (!T || !A2(y2(T))) {
1989
1989
  let s2 = null;
1990
- for (let c2 of h4) {
1991
- if (p4.has(c2) || !A2(y2(c2))) continue;
1992
- let S2 = te(y2(c2));
1993
- (!s2 || S2 > s2.pct) && (s2 = { name: c2, pct: S2 });
1990
+ for (let d2 of b4) {
1991
+ if (p4.has(d2) || !A2(y2(d2))) continue;
1992
+ let S2 = ne2(y2(d2));
1993
+ (!s2 || S2 > s2.pct) && (s2 = { name: d2, pct: S2 });
1994
1994
  }
1995
- s2 && (T && (a3.push(`country=${T} (only ${te(y2(T))}% of values are country identifiers; using ${s2.name} instead)`), b4.country = T), i.country = s2.name, p4.add(s2.name), l2.push(`country=${s2.name}`));
1995
+ s2 && (T && (a3.push(`country=${T} (only ${ne2(y2(T))}% of values are country identifiers; using ${s2.name} instead)`), h4.country = T), i.country = s2.name, p4.add(s2.name), l2.push(`country=${s2.name}`));
1996
1996
  }
1997
1997
  if (!i.city) {
1998
1998
  let s2 = null;
1999
- for (let c2 of h4) {
2000
- if (p4.has(c2)) continue;
2001
- let S2 = y2(c2), P4 = Bn2(S2, o4);
2002
- P4 < D3 || J5(S2, (K3) => j3(K3, o4)) < Z3 || (!s2 || P4 > s2.pct) && (s2 = { name: c2, pct: P4 });
1999
+ for (let d2 of b4) {
2000
+ if (p4.has(d2)) continue;
2001
+ let S2 = y2(d2), _4 = Bn2(S2, o4);
2002
+ _4 < D3 || ee3(S2, (H2) => j3(H2, o4)) < Z3 || (!s2 || _4 > s2.pct) && (s2 = { name: d2, pct: _4 });
2003
2003
  }
2004
2004
  s2 && (i.city = s2.name, l2.push(`city=${s2.name} (${s2.pct}% known cities)`));
2005
2005
  }
2006
2006
  let L4 = i.country ? y2(i.country) : [], R4 = !!i.country && A2(L4), M2 = R4 ? new Set(L4.map((s2) => k(s2 == null ? null : String(s2))).filter(Boolean)).size : 0, x3 = R4 && M2 >= 2, w3 = !!(i.lat && i.lon) && e.some((s2) => {
2007
- let c2 = +String(s2[i.lat] ?? "").trim(), S2 = +String(s2[i.lon] ?? "").trim();
2008
- return isFinite(c2) && isFinite(S2) && c2 >= -90 && c2 <= 90 && S2 >= -180 && S2 <= 180 && String(s2[i.lat] ?? "").trim() !== "" && String(s2[i.lon] ?? "").trim() !== "";
2007
+ let d2 = +String(s2[i.lat] ?? "").trim(), S2 = +String(s2[i.lon] ?? "").trim();
2008
+ return isFinite(d2) && isFinite(S2) && d2 >= -90 && d2 <= 90 && S2 >= -180 && S2 <= 180 && String(s2[i.lat] ?? "").trim() !== "" && String(s2[i.lon] ?? "").trim() !== "";
2009
2009
  });
2010
- return i.lat && i.lon && !w3 && a3.push(`lat/lon=${i.lat}/${i.lon} (no row holds a usable coordinate pair)`), i.country && !x3 && !(i.city || i.state || i.zip || w3) && a3.push(R4 ? `country=${i.country} (every row resolves to the same country - nothing to place apart)` : `country=${i.country} (values are not country identifiers)`), { bind: !!(i.city || i.state || i.zip || x3 || w3) ? i : null, backfilled: l2, refused: a3, ...Object.keys(b4).length ? { labelFallback: b4 } : {} };
2010
+ return i.lat && i.lon && !w3 && a3.push(`lat/lon=${i.lat}/${i.lon} (no row holds a usable coordinate pair)`), i.country && !x3 && !(i.city || i.state || i.zip || w3) && a3.push(R4 ? `country=${i.country} (every row resolves to the same country - nothing to place apart)` : `country=${i.country} (values are not country identifiers)`), { bind: !!(i.city || i.state || i.zip || x3 || w3) ? i : null, backfilled: l2, refused: a3, ...Object.keys(h4).length ? { labelFallback: h4 } : {} };
2011
2011
  }
2012
2012
  var r = (t, ...e) => ({ part: t, langs: Object.freeze(e) });
2013
- var oe2 = Object.freeze({ jaar: r("year", "nl"), kwartaal: r("quarter", "nl"), maand: r("month", "nl"), dag: r("day", "nl", "sv", "da", "nb"), jahr: r("year", "de"), quartal: r("quarter", "de"), monat: r("month", "de"), tag: r("day", "de"), ann\u00E9e: r("year", "fr"), mois: r("month", "fr"), jour: r("day", "fr"), trimestre: r("quarter", "fr", "es", "pt", "it"), a\u00F1o: r("year", "es"), mes: r("month", "es"), d\u00EDa: r("day", "es"), ano: r("year", "pt"), m\u00EAs: r("month", "pt"), dia: r("day", "pt"), anno: r("year", "it"), mese: r("month", "it"), giorno: r("day", "it"), \u0433\u043E\u0434: r("year", "ru"), \u043C\u0435\u0441\u044F\u0446: r("month", "ru"), \u0440\u0456\u043A: r("year", "uk"), \u043C\u0456\u0441\u044F\u0446\u044C: r("month", "uk"), \u043A\u0432\u0430\u0440\u0442\u0430\u043B: r("quarter", "ru", "uk"), \u0434\u0435\u043D\u044C: r("day", "ru", "uk"), rok: r("year", "pl", "cs", "sk"), kwarta\u0142: r("quarter", "pl"), miesi\u0105c: r("month", "pl"), dzie\u0144: r("day", "pl"), \u010Dtvrtlet\u00ED: r("quarter", "cs"), m\u011Bs\u00EDc: r("month", "cs"), den: r("day", "cs"), \u0161tvr\u0165rok: r("quarter", "sk"), mesiac: r("month", "sk"), de\u0148: r("day", "sk"), \u00E5r: r("year", "sv", "da", "nb"), kvartal: r("quarter", "sv", "da", "nb"), m\u00E5nad: r("month", "sv"), m\u00E5ned: r("month", "da", "nb"), vuosi: r("year", "fi"), vuosinelj\u00E4nnes: r("quarter", "fi"), kuukausi: r("month", "fi"), p\u00E4iv\u00E4: r("day", "fi"), \u00E9v: r("year", "hu"), negyed\u00E9v: r("quarter", "hu"), h\u00F3nap: r("month", "hu"), nap: r("day", "hu"), y\u0131l: r("year", "tr"), \u00E7eyrek: r("quarter", "tr"), ay: r("month", "tr"), g\u00FCn: r("day", "tr"), \u03AD\u03C4\u03BF\u03C2: r("year", "el"), \u03C4\u03C1\u03AF\u03BC\u03B7\u03BD\u03BF: r("quarter", "el"), \u03BC\u03AE\u03BD\u03B1\u03C2: r("month", "el"), \u03B7\u03BC\u03AD\u03C1\u03B1: r("day", "el"), an: r("year", "ro"), trimestru: r("quarter", "ro"), lun\u0103: r("month", "ro"), zi: r("day", "ro"), godina: r("year", "hr"), tromjese\u010Dje: r("quarter", "hr"), mjesec: r("month", "hr"), dan: r("day", "hr"), \u5E74: r("year", "ja", "zh"), \u56DB\u534A\u671F: r("quarter", "ja"), \u5B63\u5EA6: r("quarter", "zh"), \u6708: r("month", "ja", "zh"), \u65E5: r("day", "ja", "zh"), \uC5F0\uB3C4: r("year", "ko"), \uBD84\uAE30: r("quarter", "ko"), \uC6D4: r("month", "ko"), \uC77C: r("day", "ko"), tahun: r("year", "id"), kuartal: r("quarter", "id"), triwulan: r("quarter", "id"), bulan: r("month", "id"), hari: r("day", "id"), n\u0103m: r("year", "vi"), qu\u00FD: r("quarter", "vi"), th\u00E1ng: r("month", "vi"), ng\u00E0y: r("day", "vi"), \u0E1B\u0E35: r("year", "th"), \u0E44\u0E15\u0E23\u0E21\u0E32\u0E2A: r("quarter", "th"), \u0E40\u0E14\u0E37\u0E2D\u0E19: r("month", "th"), \u0E27\u0E31\u0E19: r("day", "th"), \u0627\u0644\u0633\u0646\u0629: r("year", "ar"), \u0633\u0646\u0629: r("year", "ar"), \u0627\u0644\u0639\u0627\u0645: r("year", "ar"), \u0639\u0627\u0645: r("year", "ar"), \u0627\u0644\u0631\u0628\u0639: r("quarter", "ar"), \u0631\u0628\u0639: r("quarter", "ar"), "\u0631\u0628\u0639 \u0627\u0644\u0633\u0646\u0629": r("quarter", "ar"), \u0627\u0644\u0634\u0647\u0631: r("month", "ar"), \u0634\u0647\u0631: r("month", "ar"), \u0627\u0644\u064A\u0648\u0645: r("day", "ar"), \u064A\u0648\u0645: r("day", "ar"), \u05E9\u05E0\u05D4: r("year", "he"), \u05E8\u05D1\u05E2\u05D5\u05DF: r("quarter", "he"), \u05D7\u05D5\u05D3\u05E9: r("month", "he"), \u05D9\u05D5\u05DD: r("day", "he"), \u0935\u0930\u094D\u0937: r("year", "hi"), \u0938\u093E\u0932: r("year", "hi"), \u0924\u093F\u092E\u093E\u0939\u0940: r("quarter", "hi"), \u092E\u0939\u0940\u0928\u093E: r("month", "hi"), \u092E\u093E\u0939: r("month", "hi"), \u0926\u093F\u0928: r("day", "hi"), \u0633\u0627\u0644: r("year", "fa"), \u0645\u0627\u0647: r("month", "fa"), \u0631\u0648\u0632: r("day", "fa") });
2014
- var Qn2 = Object.freeze(Array.from(new Set(Object.values(oe2).flatMap((t) => t.langs))));
2013
+ var ie2 = Object.freeze({ jaar: r("year", "nl"), kwartaal: r("quarter", "nl"), maand: r("month", "nl"), dag: r("day", "nl", "sv", "da", "nb"), jahr: r("year", "de"), quartal: r("quarter", "de"), monat: r("month", "de"), tag: r("day", "de"), ann\u00E9e: r("year", "fr"), mois: r("month", "fr"), jour: r("day", "fr"), trimestre: r("quarter", "fr", "es", "pt", "it"), a\u00F1o: r("year", "es"), mes: r("month", "es"), d\u00EDa: r("day", "es"), ano: r("year", "pt"), m\u00EAs: r("month", "pt"), dia: r("day", "pt"), anno: r("year", "it"), mese: r("month", "it"), giorno: r("day", "it"), \u0433\u043E\u0434: r("year", "ru"), \u043C\u0435\u0441\u044F\u0446: r("month", "ru"), \u0440\u0456\u043A: r("year", "uk"), \u043C\u0456\u0441\u044F\u0446\u044C: r("month", "uk"), \u043A\u0432\u0430\u0440\u0442\u0430\u043B: r("quarter", "ru", "uk"), \u0434\u0435\u043D\u044C: r("day", "ru", "uk"), rok: r("year", "pl", "cs", "sk"), kwarta\u0142: r("quarter", "pl"), miesi\u0105c: r("month", "pl"), dzie\u0144: r("day", "pl"), \u010Dtvrtlet\u00ED: r("quarter", "cs"), m\u011Bs\u00EDc: r("month", "cs"), den: r("day", "cs"), \u0161tvr\u0165rok: r("quarter", "sk"), mesiac: r("month", "sk"), de\u0148: r("day", "sk"), \u00E5r: r("year", "sv", "da", "nb"), kvartal: r("quarter", "sv", "da", "nb"), m\u00E5nad: r("month", "sv"), m\u00E5ned: r("month", "da", "nb"), vuosi: r("year", "fi"), vuosinelj\u00E4nnes: r("quarter", "fi"), kuukausi: r("month", "fi"), p\u00E4iv\u00E4: r("day", "fi"), \u00E9v: r("year", "hu"), negyed\u00E9v: r("quarter", "hu"), h\u00F3nap: r("month", "hu"), nap: r("day", "hu"), y\u0131l: r("year", "tr"), \u00E7eyrek: r("quarter", "tr"), ay: r("month", "tr"), g\u00FCn: r("day", "tr"), \u03AD\u03C4\u03BF\u03C2: r("year", "el"), \u03C4\u03C1\u03AF\u03BC\u03B7\u03BD\u03BF: r("quarter", "el"), \u03BC\u03AE\u03BD\u03B1\u03C2: r("month", "el"), \u03B7\u03BC\u03AD\u03C1\u03B1: r("day", "el"), an: r("year", "ro"), trimestru: r("quarter", "ro"), lun\u0103: r("month", "ro"), zi: r("day", "ro"), godina: r("year", "hr"), tromjese\u010Dje: r("quarter", "hr"), mjesec: r("month", "hr"), dan: r("day", "hr"), \u5E74: r("year", "ja", "zh"), \u56DB\u534A\u671F: r("quarter", "ja"), \u5B63\u5EA6: r("quarter", "zh"), \u6708: r("month", "ja", "zh"), \u65E5: r("day", "ja", "zh"), \uC5F0\uB3C4: r("year", "ko"), \uBD84\uAE30: r("quarter", "ko"), \uC6D4: r("month", "ko"), \uC77C: r("day", "ko"), tahun: r("year", "id"), kuartal: r("quarter", "id"), triwulan: r("quarter", "id"), bulan: r("month", "id"), hari: r("day", "id"), n\u0103m: r("year", "vi"), qu\u00FD: r("quarter", "vi"), th\u00E1ng: r("month", "vi"), ng\u00E0y: r("day", "vi"), \u0E1B\u0E35: r("year", "th"), \u0E44\u0E15\u0E23\u0E21\u0E32\u0E2A: r("quarter", "th"), \u0E40\u0E14\u0E37\u0E2D\u0E19: r("month", "th"), \u0E27\u0E31\u0E19: r("day", "th"), \u0627\u0644\u0633\u0646\u0629: r("year", "ar"), \u0633\u0646\u0629: r("year", "ar"), \u0627\u0644\u0639\u0627\u0645: r("year", "ar"), \u0639\u0627\u0645: r("year", "ar"), \u0627\u0644\u0631\u0628\u0639: r("quarter", "ar"), \u0631\u0628\u0639: r("quarter", "ar"), "\u0631\u0628\u0639 \u0627\u0644\u0633\u0646\u0629": r("quarter", "ar"), \u0627\u0644\u0634\u0647\u0631: r("month", "ar"), \u0634\u0647\u0631: r("month", "ar"), \u0627\u0644\u064A\u0648\u0645: r("day", "ar"), \u064A\u0648\u0645: r("day", "ar"), \u05E9\u05E0\u05D4: r("year", "he"), \u05E8\u05D1\u05E2\u05D5\u05DF: r("quarter", "he"), \u05D7\u05D5\u05D3\u05E9: r("month", "he"), \u05D9\u05D5\u05DD: r("day", "he"), \u0935\u0930\u094D\u0937: r("year", "hi"), \u0938\u093E\u0932: r("year", "hi"), \u0924\u093F\u092E\u093E\u0939\u0940: r("quarter", "hi"), \u092E\u0939\u0940\u0928\u093E: r("month", "hi"), \u092E\u093E\u0939: r("month", "hi"), \u0926\u093F\u0928: r("day", "hi"), \u0633\u0627\u0644: r("year", "fa"), \u0645\u0627\u0647: r("month", "fa"), \u0631\u0648\u0632: r("day", "fa") });
2014
+ var Qn2 = Object.freeze(Array.from(new Set(Object.values(ie2).flatMap((t) => t.langs))));
2015
2015
  var fe = Object.freeze(["fa", "ar", "he", "th"]);
2016
2016
  var Rr = Object.freeze({ integer: "number", decimal: "number", double: "number", datetime: "date", date: "date", boolean: "boolean", string: "text" });
2017
2017
  var Or = Object.freeze({ RENDER_START: "render-start", RENDER_OK: "render-ok", RENDER_ERROR: "render-error", VIEW: "view", VIEW_VERDICT: "view-verdict" });
@@ -2451,9 +2451,9 @@ function createMarkResolver(env) {
2451
2451
  const r2 = el.getBoundingClientRect ? el.getBoundingClientRect() : null;
2452
2452
  if (!r2 || r2.width <= 0 || r2.height <= 0) continue;
2453
2453
  if (x3 < r2.left || x3 > r2.right || y2 < r2.top || y2 > r2.bottom) continue;
2454
- const area = r2.width * r2.height;
2455
- if (area < bestArea) {
2456
- bestArea = area;
2454
+ const area2 = r2.width * r2.height;
2455
+ if (area2 < bestArea) {
2456
+ bestArea = area2;
2457
2457
  best = el;
2458
2458
  }
2459
2459
  }
@@ -3062,15 +3062,15 @@ function ctmScaleOf(m4) {
3062
3062
  }
3063
3063
  function svgInkReach(svg) {
3064
3064
  try {
3065
- const box = svg.getBoundingClientRect();
3066
- if (!(box.width > 0) || !(box.height > 0)) return null;
3065
+ const box2 = svg.getBoundingClientRect();
3066
+ if (!(box2.width > 0) || !(box2.height > 0)) return null;
3067
3067
  const els = svg.querySelectorAll(FIT_CONTENT_SELECTOR);
3068
3068
  const clipOf = clipWindowReader(svg);
3069
3069
  let right = -Infinity, bottom = -Infinity, seen = 0;
3070
3070
  for (let i = 0; i < els.length && seen < FIT_WALK_CAP; i++) {
3071
3071
  const r2 = els[i].getBoundingClientRect();
3072
3072
  if (r2.width <= 0 && r2.height <= 0) continue;
3073
- if (isPhantomBox(r2.width, r2.height, box.width, box.height)) continue;
3073
+ if (isPhantomBox(r2.width, r2.height, box2.width, box2.height)) continue;
3074
3074
  let rr = r2.right, rb = r2.bottom;
3075
3075
  const clip = clipOf(els[i]);
3076
3076
  if (clip) {
@@ -3083,51 +3083,39 @@ function svgInkReach(svg) {
3083
3083
  if (rb > bottom) bottom = rb;
3084
3084
  }
3085
3085
  if (seen === 0) return null;
3086
- return { right: right - box.left, bottom: bottom - box.top };
3086
+ return { right: right - box2.left, bottom: bottom - box2.top };
3087
+ } catch {
3088
+ return null;
3089
+ }
3090
+ }
3091
+ function clipWindowOf(el) {
3092
+ try {
3093
+ const m4 = /url\(\s*['"]?#([^'")\s]+)['"]?\s*\)/.exec(el.getAttribute("clip-path") || "");
3094
+ const cp = m4 ? (el.closest("svg") ?? el.ownerDocument).querySelector(`clipPath[id="${m4[1].replace(/"/g, '\\"')}"]`) : null;
3095
+ const ctm = cp ? el.getScreenCTM?.() : null;
3096
+ if (!cp || !ctm || cp.getAttribute("clipPathUnits") === "objectBoundingBox") return null;
3097
+ let l2 = Infinity, t = Infinity, r2 = -Infinity, b4 = -Infinity;
3098
+ for (let i = 0; i < cp.children.length; i++) {
3099
+ const bb = cp.children[i].getBBox?.();
3100
+ if (!bb || !(bb.width > 0) || !(bb.height > 0)) continue;
3101
+ for (const [x3, y2] of [[bb.x, bb.y], [bb.x + bb.width, bb.y], [bb.x, bb.y + bb.height], [bb.x + bb.width, bb.y + bb.height]]) {
3102
+ const sx = ctm.a * x3 + ctm.c * y2 + ctm.e, sy = ctm.b * x3 + ctm.d * y2 + ctm.f;
3103
+ l2 = Math.min(l2, sx);
3104
+ t = Math.min(t, sy);
3105
+ r2 = Math.max(r2, sx);
3106
+ b4 = Math.max(b4, sy);
3107
+ }
3108
+ }
3109
+ return isFinite(r2) && isFinite(b4) ? { left: l2, top: t, right: r2, bottom: b4 } : null;
3087
3110
  } catch {
3088
3111
  return null;
3089
3112
  }
3090
3113
  }
3091
3114
  function clipWindowReader(svg) {
3092
3115
  const own = /* @__PURE__ */ new Map();
3093
- const byId = (id) => {
3094
- try {
3095
- return svg.querySelector(`clipPath[id="${id.replace(/"/g, '\\"')}"]`);
3096
- } catch {
3097
- return null;
3098
- }
3099
- };
3100
3116
  const windowOf = (el) => {
3101
- if (own.has(el)) return own.get(el);
3102
- let win = null;
3103
- try {
3104
- const ref = el.getAttribute("clip-path") || "";
3105
- const m4 = /url\(\s*['"]?#([^'")\s]+)['"]?\s*\)/.exec(ref);
3106
- const cp = m4 ? byId(m4[1]) : null;
3107
- const ctm = cp ? el.getScreenCTM?.() : null;
3108
- if (cp && ctm && cp.getAttribute("clipPathUnits") !== "objectBoundingBox") {
3109
- let r2 = -Infinity, b4 = -Infinity;
3110
- for (let i = 0; i < cp.children.length; i++) {
3111
- const bb = cp.children[i].getBBox?.();
3112
- if (!bb || !(bb.width > 0) || !(bb.height > 0)) continue;
3113
- for (const [x3, y2] of [
3114
- [bb.x, bb.y],
3115
- [bb.x + bb.width, bb.y],
3116
- [bb.x, bb.y + bb.height],
3117
- [bb.x + bb.width, bb.y + bb.height]
3118
- ]) {
3119
- const sx = ctm.a * x3 + ctm.c * y2 + ctm.e, sy = ctm.b * x3 + ctm.d * y2 + ctm.f;
3120
- if (sx > r2) r2 = sx;
3121
- if (sy > b4) b4 = sy;
3122
- }
3123
- }
3124
- if (isFinite(r2) && isFinite(b4)) win = { right: r2, bottom: b4 };
3125
- }
3126
- } catch {
3127
- win = null;
3128
- }
3129
- own.set(el, win);
3130
- return win;
3117
+ if (!own.has(el)) own.set(el, clipWindowOf(el));
3118
+ return own.get(el);
3131
3119
  };
3132
3120
  return (el) => {
3133
3121
  let acc = null;
@@ -3895,7 +3883,34 @@ function invalidSentinelReason(text2, max = 240) {
3895
3883
  // src/annotations.ts
3896
3884
  var ANNOTATION_LAYER_CLASS = "bic-annotations";
3897
3885
  var ANNOTATION_CLASS = "bic-annotation";
3886
+ var ZOOM_PAD_CLASS = "llm-zoom-pad";
3898
3887
  var text = (v) => v == null ? "" : String(v).trim();
3888
+ var FREE = { l: -Infinity, t: -Infinity, r: Infinity, b: Infinity };
3889
+ var box = (r2) => ({ l: r2.left, t: r2.top, r: r2.right, b: r2.bottom });
3890
+ var area = (b4) => (b4.r - b4.l) * (b4.b - b4.t);
3891
+ var cut = (a3, b4) => {
3892
+ if (!a3) return null;
3893
+ const c2 = { l: Math.max(a3.l, b4.l), t: Math.max(a3.t, b4.t), r: Math.min(a3.r, b4.r), b: Math.min(a3.b, b4.b) };
3894
+ return c2.r > c2.l && c2.b > c2.t ? c2 : null;
3895
+ };
3896
+ function shapeTest(mark) {
3897
+ const g5 = mark;
3898
+ let inv = null;
3899
+ try {
3900
+ inv = g5?.isPointInFill ? g5.getScreenCTM?.()?.inverse() ?? null : null;
3901
+ } catch {
3902
+ inv = null;
3903
+ }
3904
+ if (!g5 || !inv) return () => true;
3905
+ const m4 = inv;
3906
+ return (x3, y2) => {
3907
+ try {
3908
+ return g5.isPointInFill({ x: m4.a * x3 + m4.c * y2 + m4.e, y: m4.b * x3 + m4.d * y2 + m4.f });
3909
+ } catch {
3910
+ return true;
3911
+ }
3912
+ };
3913
+ }
3899
3914
  var parseIdxs = (s2) => (s2 || "").split(",").map((x3) => parseInt(x3, 10)).filter((n) => Number.isFinite(n));
3900
3915
  function createAnnotationLayer(container, onClick) {
3901
3916
  let list = [];
@@ -3952,6 +3967,37 @@ function createAnnotationLayer(container, onClick) {
3952
3967
  else marksByRow.set(r2, [m4]);
3953
3968
  }
3954
3969
  const origin = container.getBoundingClientRect();
3970
+ const open = origin.width > 0 && origin.height > 0 ? box(origin) : FREE;
3971
+ const clipOf = /* @__PURE__ */ new Map();
3972
+ const viewOf = (m4) => {
3973
+ let v = open;
3974
+ const svg = m4.closest("svg");
3975
+ if (svg) {
3976
+ const s2 = svg.getBoundingClientRect();
3977
+ if (s2.width > 0 && s2.height > 0) v = cut(v, box(s2));
3978
+ }
3979
+ for (let el = m4.parentElement; v && el && el !== svg && el !== container; el = el.parentElement) {
3980
+ if (!clipOf.has(el)) {
3981
+ const w4 = clipWindowOf(el);
3982
+ clipOf.set(el, w4 && box(w4));
3983
+ }
3984
+ const w3 = clipOf.get(el);
3985
+ if (w3) v = cut(v, w3);
3986
+ }
3987
+ return v;
3988
+ };
3989
+ const controls = Array.from(container.querySelectorAll(`.${CONTROL_CLASS}, .${ZOOM_PAD_CLASS}`)).map((c2) => c2.getBoundingClientRect()).filter((r2) => r2.width > 0 && r2.height > 0).map(box);
3990
+ const clear = (v, len, mark) => {
3991
+ const hw = Math.max(16, len * 6 + 8) / 2, hh = 8, g5 = 2;
3992
+ const cx = (v.l + v.r) / 2, cy = (v.t + v.b) / 2;
3993
+ const free = (x3, y2) => x3 >= v.l && x3 <= v.r && y2 >= v.t && y2 <= v.b && controls.every((c2) => x3 + hw <= c2.l || x3 - hw >= c2.r || y2 + hh <= c2.t || y2 - hh >= c2.b);
3994
+ const onShape = shapeTest(mark);
3995
+ const tries = [[cx, cy]];
3996
+ for (let i = 0; i <= 8; i++) for (let j4 = 0; j4 <= 6; j4++) tries.push([v.l + (v.r - v.l) * i / 8, v.t + (v.b - v.t) * j4 / 6]);
3997
+ tries.sort((p4, q2) => Math.hypot(p4[0] - cx, p4[1] - cy) - Math.hypot(q2[0] - cx, q2[1] - cy));
3998
+ for (const c2 of controls) tries.push([cx, c2.b + hh + g5], [cx, c2.t - hh - g5], [c2.l - hw - g5, cy], [c2.r + hw + g5, cy]);
3999
+ return tries.find(([x3, y2]) => free(x3, y2) && onShape(x3, y2)) ?? tries.find(([x3, y2]) => free(x3, y2)) ?? null;
4000
+ };
3955
4001
  let shown = 0;
3956
4002
  for (const a3 of list) {
3957
4003
  const pairs = (a3.where ? Object.entries(a3.where) : a3.column != null ? [[a3.column, a3.value]] : []).map(([c2, v]) => [names.indexOf(c2), text(v)]);
@@ -3961,23 +4007,30 @@ function createAnnotationLayer(container, onClick) {
3961
4007
  if (pairs.every(([ci, v]) => text(row?.[ci]) === v)) for (const m4 of marksByRow.get(r2) ?? []) hits.add(m4);
3962
4008
  });
3963
4009
  if (!hits.size) continue;
3964
- shown++;
3965
- let best = null;
4010
+ let best = null, bestMark = null, laidOut = false;
3966
4011
  for (const m4 of hits) {
3967
4012
  const b4 = m4.getBoundingClientRect();
3968
- if (!best || b4.width * b4.height > best.width * best.height) best = b4;
4013
+ if (!(b4.width > 0 && b4.height > 0)) continue;
4014
+ laidOut = true;
4015
+ const v = cut(box(b4), viewOf(m4));
4016
+ if (v && (!best || area(v) > area(best))) {
4017
+ best = v;
4018
+ bestMark = m4;
4019
+ }
3969
4020
  }
4021
+ const pt2 = best ? clear(best, (a3.label ?? "\u2022").length, bestMark) : null;
4022
+ if (laidOut && !pt2) continue;
4023
+ shown++;
3970
4024
  const badge = doc.createElement("div");
3971
4025
  badge.className = ANNOTATION_CLASS;
3972
4026
  badge.textContent = a3.label ?? "\u2022";
3973
4027
  if (a3.title) badge.setAttribute("title", a3.title);
3974
4028
  badge.setAttribute("role", "button");
3975
4029
  badge.setAttribute("aria-label", a3.title ? `Note: ${a3.title}` : `Note on ${want}`);
3976
- const laidOut = !!best && best.width > 0 && best.height > 0;
3977
4030
  Object.assign(badge.style, {
3978
4031
  position: "absolute",
3979
- left: `${Math.round(laidOut ? best.left - origin.left + best.width / 2 : 0)}px`,
3980
- top: `${Math.round(laidOut ? best.top - origin.top + best.height / 2 : 0)}px`,
4032
+ left: `${Math.round(pt2 ? pt2[0] - origin.left : 0)}px`,
4033
+ top: `${Math.round(pt2 ? pt2[1] - origin.top : 0)}px`,
3981
4034
  transform: "translate(-50%, -50%)",
3982
4035
  minWidth: "16px",
3983
4036
  height: "16px",
package/dist/index.mjs CHANGED
@@ -122,7 +122,7 @@ import {
122
122
  toSourceRows,
123
123
  unpinScrolledAxis,
124
124
  valuePlacementFlag
125
- } from "./chunk-ZTTBWP3I.mjs";
125
+ } from "./chunk-3FNHUWNV.mjs";
126
126
  import "./chunk-A2GMXZP7.mjs";
127
127
  import {
128
128
  ACTIVE_TICK_CLASS,
@@ -2661,13 +2661,13 @@ function latePickupKeepsMarker(outcome) {
2661
2661
  return outcome === "transport";
2662
2662
  }
2663
2663
  function pollGiveUpKeepsMarker(outcome, m2) {
2664
- return outcome === "window-closed" && !!m2 && !isBlindMarker(m2);
2664
+ return (outcome === "window-closed" || outcome === "unreachable") && !!m2 && !isBlindMarker(m2);
2665
2665
  }
2666
2666
  function pendingRecoveryRemainingMs(m2, nowMs) {
2667
2667
  return Math.max(0, m2.t + PENDING_RECOVERY_WINDOW_MS - nowMs);
2668
2668
  }
2669
- function transportFailureShouldRecover(headersReceived, genNew) {
2670
- return headersReceived && genNew;
2669
+ function transportFailureShouldRecover(_headersReceived, genNew) {
2670
+ return genNew;
2671
2671
  }
2672
2672
  var TRANSPORT_LOST_CHECKING_MESSAGE = "The connection dropped while your chart was being generated - checking whether it finished on the server...";
2673
2673
  var GENERATION_CANCELLED_MESSAGE = "The connection dropped before the chart finished - nothing was charged. Generate again.";
@@ -2678,6 +2678,37 @@ function generationCancelledMessage(serverMessage) {
2678
2678
  const s2 = String(serverMessage ?? "").trim();
2679
2679
  return s2 !== "" ? s2 : GENERATION_CANCELLED_MESSAGE;
2680
2680
  }
2681
+ function recoveryFinalOutcome(r2) {
2682
+ if (!r2) return null;
2683
+ const o3 = String(r2.pollOutcome ?? "").trim().toLowerCase();
2684
+ if (r2.isGenerationCancelled === true || r2.isPollFinal === true && o3 === "cancelled") return "cancelled";
2685
+ if (r2.isPollFinal === true) return o3 === "not-received" ? "not-received" : "failed";
2686
+ if (r2.isPollFinal == null && r2.isVersionNotFound === true) {
2687
+ const c2 = String(r2.errorCode ?? "").trim().toUpperCase();
2688
+ if (c2 === "GENERATION_NOT_RECEIVED") return "not-received";
2689
+ if (c2 === "GENERATION_FAILED") return "failed";
2690
+ if (c2 === "GENERATION_CANCELLED") return "cancelled";
2691
+ }
2692
+ return null;
2693
+ }
2694
+ function recoveryProvesNothingCharged(o3) {
2695
+ return o3 === "cancelled" || o3 === "not-received";
2696
+ }
2697
+ function recoveryGiveUpRefunds(outcome) {
2698
+ return outcome === "window-closed" || outcome === "hard-error" || outcome === "unreachable";
2699
+ }
2700
+ var PENDING_RECOVERY_UNREACHABLE_POLLS = 3;
2701
+ function recoveryLooksUnreachable(transportFailuresInARow, everAnswered) {
2702
+ return !everAnswered && transportFailuresInARow >= PENDING_RECOVERY_UNREACHABLE_POLLS;
2703
+ }
2704
+ var GENERATION_NOT_RECEIVED_MESSAGE = "The charting service has no record of that request, so nothing was generated and nothing was charged. Generate again.";
2705
+ var GENERATION_FAILED_MESSAGE = "That chart didn't finish on the server, so there's nothing to show. Generate again.";
2706
+ var RECOVERY_UNREACHABLE_MESSAGE = "We couldn't reach the charting service to check on your chart - it may be offline, or blocked on this network. Try again in a moment.";
2707
+ function recoveryFinalMessage(o3, serverMessage) {
2708
+ const s2 = String(serverMessage ?? "").trim();
2709
+ if (s2 !== "") return s2;
2710
+ return o3 === "cancelled" ? GENERATION_CANCELLED_MESSAGE : o3 === "not-received" ? GENERATION_NOT_RECEIVED_MESSAGE : GENERATION_FAILED_MESSAGE;
2711
+ }
2681
2712
 
2682
2713
  // src/chartPick.ts
2683
2714
  function reconcileChartPick(pick, offered, autoLabel) {
@@ -2856,6 +2887,8 @@ export {
2856
2887
  FLIP_INTERVAL_MIN_MS,
2857
2888
  FLIP_MODE_DEFAULT,
2858
2889
  GENERATION_CANCELLED_MESSAGE,
2890
+ GENERATION_FAILED_MESSAGE,
2891
+ GENERATION_NOT_RECEIVED_MESSAGE,
2859
2892
  GEO_POINT_PRECISIONS,
2860
2893
  GLYPH_SAMPLE_N,
2861
2894
  HOST_CONTAINER_CLASS,
@@ -2889,6 +2922,7 @@ export {
2889
2922
  PENDING_RECOVERY_POLL_MS,
2890
2923
  PENDING_RECOVERY_SLOW_PHASE_MS,
2891
2924
  PENDING_RECOVERY_SLOW_POLL_MS,
2925
+ PENDING_RECOVERY_UNREACHABLE_POLLS,
2892
2926
  PENDING_RECOVERY_WINDOW_MS,
2893
2927
  PHANTOM_FRACTION,
2894
2928
  PILL_MIN_ALPHA,
@@ -2897,6 +2931,7 @@ export {
2897
2931
  PRODUCT_FEEDBACK_MAX_CHARS,
2898
2932
  PRODUCT_FEEDBACK_MIN_CHARS,
2899
2933
  QUALIFY_REFUSAL_UNSPECIFIED,
2934
+ RECOVERY_UNREACHABLE_MESSAGE,
2900
2935
  ROW_IDX_ATTR,
2901
2936
  SAME_SHADE_DELTA_E,
2902
2937
  SCROLL_SLACK_PX,
@@ -3049,8 +3084,13 @@ export {
3049
3084
  reconcileChartPick,
3050
3085
  reconcileModelPick,
3051
3086
  recoveryAnswerIsCancelled,
3087
+ recoveryFinalMessage,
3088
+ recoveryFinalOutcome,
3089
+ recoveryGiveUpRefunds,
3090
+ recoveryLooksUnreachable,
3052
3091
  recoveryOwnsTheSentence,
3053
3092
  recoveryPollRunning,
3093
+ recoveryProvesNothingCharged,
3054
3094
  refusalIsSelectable,
3055
3095
  registerCityTable,
3056
3096
  registerGeo,
package/dist/react.mjs CHANGED
@@ -22,7 +22,7 @@ import {
22
22
  loadGeo,
23
23
  syncMemberSelection,
24
24
  toSourceRows
25
- } from "./chunk-ZTTBWP3I.mjs";
25
+ } from "./chunk-3FNHUWNV.mjs";
26
26
  import "./chunk-A2GMXZP7.mjs";
27
27
  import "./chunk-WNGJUPEI.mjs";
28
28
  import "./chunk-GHODWOAL.mjs";
@@ -23,6 +23,9 @@ export interface AnnotationReport {
23
23
  }
24
24
  export declare const ANNOTATION_LAYER_CLASS = "bic-annotations";
25
25
  export declare const ANNOTATION_CLASS = "bic-annotation";
26
+ /** The class the d3.llmGeoZoom helper gives its button pad - a control drawn by a generated chart without the
27
+ * contract's CONTROL_CLASS, so the badge layer names it too. */
28
+ export declare const ZOOM_PAD_CLASS = "llm-zoom-pad";
26
29
  export interface AnnotationLayer {
27
30
  set(list: MarkAnnotation[]): void;
28
31
  /** Redraw against the container's current marks and the given data. */
@@ -7,6 +7,15 @@ export declare function svgInkReach(svg: SVGSVGElement): {
7
7
  right: number;
8
8
  bottom: number;
9
9
  } | null;
10
+ /** The window ONE element's own clip-path attribute opens, in screen coordinates - or null: no clip, a clip in
11
+ * objectBoundingBox units, or one that won't measure. Shared by the frame fit (right/bottom) and the note badges
12
+ * (the whole window). The clipPath is looked up within the element's own svg. */
13
+ export declare function clipWindowOf(el: Element): {
14
+ left: number;
15
+ top: number;
16
+ right: number;
17
+ bottom: number;
18
+ } | null;
10
19
  export type InkReach = (el: Element) => {
11
20
  right: number;
12
21
  bottom: number;
@@ -41,7 +41,7 @@ export { pinScrolledAxis, unpinScrolledAxis, type AxisPinReport } from "./fitDom
41
41
  export { MIN_DELTA_E, pickDistinctColorFromSeed, buildPalette, buildPaletteFromSeed, orderMostDistinct, LEGIBLE_LIGHTNESS, type PaletteResult, type SeedForSlot, type PaletteOptions, } from "./palette";
42
42
  export { deltaEHex } from "./deltaE";
43
43
  export { resolveAutoColorScale, autoRampMinStep, autoRampCanvas, AUTO_RAMP_CLASSES, AUTO_RAMP_DRAWN_OPACITY, AUTO_RAMP_MIN_STEP_DELTA_E, type AutoColorScale, type AutoColorScaleInput } from "./autoRamp";
44
- export { PENDING_RECOVERY_WINDOW_MS, PENDING_RECOVERY_POLL_MS, PENDING_RECOVERY_FIRST_POLL_MS, PENDING_RECOVERY_FAST_PHASE_MS, PENDING_RECOVERY_MID_POLL_MS, PENDING_RECOVERY_SLOW_PHASE_MS, PENDING_RECOVERY_SLOW_POLL_MS, pendingRecoveryNextDelayMs, encodePendingGenerate, parsePendingGenerate, markerArmedBlind, isBlindMarker, servedCorrelationProves, sameMarker, decidePendingRecovery, recoveryPollRunning, recoveryOwnsTheSentence, latePickupAction, latePickupKeepsMarker, pollGiveUpKeepsMarker, pendingRecoveryRemainingMs, transportFailureShouldRecover, TRANSPORT_LOST_CHECKING_MESSAGE, GENERATION_CANCELLED_MESSAGE, recoveryAnswerIsCancelled, generationCancelledMessage, type PendingGenerateMarker, type PendingRecoveryDecision, type LatePickupAction, } from "./pendingGenerate";
44
+ export { PENDING_RECOVERY_WINDOW_MS, PENDING_RECOVERY_POLL_MS, PENDING_RECOVERY_FIRST_POLL_MS, PENDING_RECOVERY_FAST_PHASE_MS, PENDING_RECOVERY_MID_POLL_MS, PENDING_RECOVERY_SLOW_PHASE_MS, PENDING_RECOVERY_SLOW_POLL_MS, pendingRecoveryNextDelayMs, encodePendingGenerate, parsePendingGenerate, markerArmedBlind, isBlindMarker, servedCorrelationProves, sameMarker, decidePendingRecovery, recoveryPollRunning, recoveryOwnsTheSentence, latePickupAction, latePickupKeepsMarker, pollGiveUpKeepsMarker, pendingRecoveryRemainingMs, transportFailureShouldRecover, TRANSPORT_LOST_CHECKING_MESSAGE, GENERATION_CANCELLED_MESSAGE, recoveryAnswerIsCancelled, generationCancelledMessage, recoveryFinalOutcome, recoveryProvesNothingCharged, recoveryGiveUpRefunds, recoveryLooksUnreachable, recoveryFinalMessage, PENDING_RECOVERY_UNREACHABLE_POLLS, GENERATION_NOT_RECEIVED_MESSAGE, GENERATION_FAILED_MESSAGE, RECOVERY_UNREACHABLE_MESSAGE, type PendingGenerateMarker, type PendingRecoveryDecision, type LatePickupAction, type RecoveryFinalOutcome, } from "./pendingGenerate";
45
45
  export { stripJsComments } from "./codeComments";
46
46
  export { reconcileChartPick, type ChartPickReconciliation } from "./chartPick";
47
47
  export { isDuplicateGenerate, armGenerateGuard, DUPLICATE_GENERATE_WINDOW_MS, type GenerateGuardKey, type GenerateGuardState, } from "./duplicateGenerateGuard";
@@ -147,20 +147,23 @@ export declare function latePickupAction(m: PendingGenerateMarker | null | undef
147
147
  */
148
148
  export declare function latePickupKeepsMarker(outcome: "found" | "not-yet" | "hard-error" | "transport"): boolean;
149
149
  /**
150
- * When the 15-minute poll runs out ("window-closed"), the marker STAYS for the next mount's late
151
- * pickup, as long as it carries a correlation. A definitive refusal ("hard-error") still clears it.
150
+ * When the 15-minute poll runs out ("window-closed"), or stops because no check could reach the
151
+ * service ("unreachable"), the marker STAYS for the next mount's late pickup, as long as it carries a
152
+ * correlation. A definitive refusal ("hard-error") or a final answer still clears it.
152
153
  */
153
154
  export declare function pollGiveUpKeepsMarker(outcome: string, m: PendingGenerateMarker | null | undefined): boolean;
154
155
  /** Milliseconds left in the recovery window from `nowMs`, floored at 0. */
155
156
  export declare function pendingRecoveryRemainingMs(m: PendingGenerateMarker, nowMs: number): number;
156
157
  /**
157
158
  * Whether a transport failure on a generate should hand off to the recovery poll (true) or fall back
158
- * to the ordinary retry (false). The discriminator is whether the service ACCEPTED the request: a
159
- * streaming endpoint commits its 200 headers the moment it starts, so headers-received plus a later
160
- * failure means the generate is running server-side and a retry would make a SECOND chart. No
161
- * headers means the service never saw it, and retrying is the right move.
159
+ * to the ordinary retry (false). A REAL GENERATE ALWAYS RECOVERS (2026-10-04). "No response headers"
160
+ * used to mean "the service never saw it", and behind a buffering proxy it never did: the proxy held
161
+ * the headers and the heartbeats while the service finished and charged (seen in production: every
162
+ * pre-header loss in a week had reached the server). A retry made a second chart; a
163
+ * poll by correlation costs nothing, and the server now says when nothing was received.
164
+ * `headersReceived` stays in the signature and decides nothing.
162
165
  */
163
- export declare function transportFailureShouldRecover(headersReceived: boolean, genNew: boolean): boolean;
166
+ export declare function transportFailureShouldRecover(_headersReceived: boolean, genNew: boolean): boolean;
164
167
  /**
165
168
  * WHAT A HOST SAYS THE MOMENT A GENERATE'S CONNECTION DROPS - before it knows anything else.
166
169
  *
@@ -189,3 +192,38 @@ export declare function recoveryAnswerIsCancelled(r: {
189
192
  } | null | undefined): boolean;
190
193
  /** The banner for a cancelled generation: the server's own sentence when it sent one, else the same words. */
191
194
  export declare function generationCancelledMessage(serverMessage: string | null | undefined): string;
195
+ /**
196
+ * THE RECOVERY POLL'S FINAL ANSWERS (2026-10-04). A server that knows the generation ended without a
197
+ * chart says so with `isPollFinal` and names the ending in `pollOutcome`; isVersionNotFound rides
198
+ * beside it for older hosts, so this is read FIRST. null = not final. A final answer with an outcome
199
+ * this build does not know reads as "failed": it is final, and it claims nothing about charges.
200
+ */
201
+ export type RecoveryFinalOutcome = "cancelled" | "failed" | "not-received";
202
+ export declare function recoveryFinalOutcome(r: {
203
+ isPollFinal?: boolean | null;
204
+ pollOutcome?: string | null;
205
+ isGenerationCancelled?: boolean | null;
206
+ isVersionNotFound?: boolean | null;
207
+ errorCode?: string | null;
208
+ } | null | undefined): RecoveryFinalOutcome | null;
209
+ /** Did the server PROVE nothing was charged? Only a cancel and a request it never received do; a
210
+ * failed generation's charge is its own, and a host claims nothing about it. */
211
+ export declare function recoveryProvesNothingCharged(o: string | null | undefined): boolean;
212
+ /** Does a recovery that ended this way send the refund? Only when it ended with NOTHING PAINTED and
213
+ * nothing proven - the window closed, the poll itself was refused, or the service could not be
214
+ * reached. The server holds the refund until the row exists and declines a painted chart (recover,
215
+ * then refund). Never for a final answer. */
216
+ export declare function recoveryGiveUpRefunds(outcome: string): boolean;
217
+ /** Polls in a row that could not reach the service, with no answer yet, that end the recovery as
218
+ * "unreachable" rather than waiting out the window (~32 s on the shared cadence). */
219
+ export declare const PENDING_RECOVERY_UNREACHABLE_POLLS = 3;
220
+ export declare function recoveryLooksUnreachable(transportFailuresInARow: number, everAnswered: boolean): boolean;
221
+ /** The server's words for the final answers, for a server that sent none and for a host that
222
+ * localises by code. */
223
+ export declare const GENERATION_NOT_RECEIVED_MESSAGE = "The charting service has no record of that request, so nothing was generated and nothing was charged. Generate again.";
224
+ export declare const GENERATION_FAILED_MESSAGE = "That chart didn't finish on the server, so there's nothing to show. Generate again.";
225
+ /** Neither the generate's answer nor any check reached us. Claims nothing about a charge: behind a
226
+ * proxy the generate may have arrived when the checks did not. */
227
+ export declare const RECOVERY_UNREACHABLE_MESSAGE = "We couldn't reach the charting service to check on your chart - it may be offline, or blocked on this network. Try again in a moment.";
228
+ /** The sentence for a final answer: the server's own when it sent one, else the same words. */
229
+ export declare function recoveryFinalMessage(o: RecoveryFinalOutcome, serverMessage: string | null | undefined): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bicharts/chart-host",
3
- "version": "0.6.63",
3
+ "version": "0.6.65",
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",