@bicharts/chart-host 0.6.102 → 0.6.105
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters.mjs +3 -3
- package/dist/card.mjs +2 -2
- package/dist/chunk-5WTQN5DL.mjs +96 -0
- package/dist/{chunk-M7MBTLDP.mjs → chunk-7XRQUFVH.mjs} +3 -1
- package/dist/{chunk-ASLRGGLV.mjs → chunk-CPLWAW3Z.mjs} +1 -1
- package/dist/{chunk-B6BLSIID.mjs → chunk-IE426WU6.mjs} +2 -2
- package/dist/{chunk-3JBJ2SIF.mjs → chunk-IE7TM6DX.mjs} +1 -1
- package/dist/{chunk-ALX4D2I2.mjs → chunk-K6UXTDMR.mjs} +675 -132
- package/dist/{chunk-D6A37G2G.mjs → chunk-MU4BWWO6.mjs} +10 -10
- package/dist/{chunk-5OCL4EFM.mjs → chunk-P2DLK7WZ.mjs} +1 -1
- package/dist/{chunk-PMA56BKD.mjs → chunk-PA5V6J6K.mjs} +1 -1
- package/dist/{chunk-CNT3QA3R.mjs → chunk-SYUJ4TPX.mjs} +961 -771
- package/dist/{chunk-WSNDXS3Z.mjs → chunk-TLIBO5PT.mjs} +1 -1
- package/dist/index.mjs +207 -17
- package/dist/legend-fit.mjs +3 -3
- package/dist/page.mjs +4 -4
- package/dist/provinces.mjs +229 -0
- package/dist/react.mjs +12 -10
- package/dist/testing.mjs +1 -1
- package/dist/types/admin1LookupLoader.d.ts +26 -0
- package/dist/types/contract.d.ts +9 -1
- package/dist/types/exportTable.d.ts +100 -0
- package/dist/types/host.d.ts +3 -2
- package/dist/types/hostLinks.d.ts +11 -0
- package/dist/types/index.d.ts +5 -2
- package/dist/types/optionsVocabulary.d.ts +5 -0
- package/dist/types/payload.d.ts +63 -4
- package/dist/types/provinceGeo.d.ts +38 -0
- package/dist/types/provinceHost.d.ts +47 -0
- package/dist/types/provinces.d.ts +3 -0
- package/dist/types/shareRate.d.ts +90 -0
- package/dist/zoom-memory.mjs +1 -1
- package/package.json +6 -1
|
@@ -4,11 +4,11 @@ import {
|
|
|
4
4
|
claimParkedLasso,
|
|
5
5
|
installLasso,
|
|
6
6
|
lassoEffect
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-IE426WU6.mjs";
|
|
8
8
|
import {
|
|
9
9
|
censusHitBands,
|
|
10
10
|
ensureCrossfilterHitTargets
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-CPLWAW3Z.mjs";
|
|
12
12
|
import {
|
|
13
13
|
clearPress,
|
|
14
14
|
clearSelectionGlyphs,
|
|
@@ -25,27 +25,25 @@ import {
|
|
|
25
25
|
selectionRuleOf,
|
|
26
26
|
trackPress,
|
|
27
27
|
validRowSet
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-P2DLK7WZ.mjs";
|
|
29
29
|
import {
|
|
30
30
|
clipWindowOf,
|
|
31
31
|
fitRenderedChart,
|
|
32
32
|
rememberScroll,
|
|
33
33
|
takeScroll,
|
|
34
34
|
unpinScrolledAxis
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-IE7TM6DX.mjs";
|
|
36
36
|
import {
|
|
37
|
+
geoFromCache
|
|
38
|
+
} from "./chunk-5WTQN5DL.mjs";
|
|
39
|
+
import {
|
|
40
|
+
Dt,
|
|
37
41
|
Fn,
|
|
38
|
-
J3,
|
|
39
42
|
Q,
|
|
43
|
+
Rr,
|
|
40
44
|
Yn,
|
|
41
|
-
ir,
|
|
42
45
|
tt
|
|
43
|
-
} from "./chunk-
|
|
44
|
-
import {
|
|
45
|
-
NA_ISO3,
|
|
46
|
-
NA_LAT_MAX,
|
|
47
|
-
clipFeatureToLat
|
|
48
|
-
} from "./chunk-A2GMXZP7.mjs";
|
|
46
|
+
} from "./chunk-SYUJ4TPX.mjs";
|
|
49
47
|
import {
|
|
50
48
|
ACTIVE_TICK_CLASS,
|
|
51
49
|
ANIM_LOOP_DELAY_DEFAULT,
|
|
@@ -79,6 +77,7 @@ import {
|
|
|
79
77
|
MARK_CLASS,
|
|
80
78
|
MARK_SELECTED_CLASS,
|
|
81
79
|
MAX_MAP_POINTS_DEFAULT,
|
|
80
|
+
NOTE_STYLE_ATTR,
|
|
82
81
|
NO_ROW_MARKS_ATTR,
|
|
83
82
|
ROW_IDX_ATTR,
|
|
84
83
|
SEASONAL_MARKERS_DEFAULT,
|
|
@@ -87,7 +86,7 @@ import {
|
|
|
87
86
|
XFILTER_REFRESH_EVENT,
|
|
88
87
|
chartOwnsTimeline,
|
|
89
88
|
periodTickSuppressesFeedback
|
|
90
|
-
} from "./chunk-
|
|
89
|
+
} from "./chunk-7XRQUFVH.mjs";
|
|
91
90
|
|
|
92
91
|
// src/labelContrast.ts
|
|
93
92
|
function parseRGBA(c) {
|
|
@@ -553,7 +552,505 @@ function resolveAutoColorScale(p) {
|
|
|
553
552
|
return memoValue;
|
|
554
553
|
}
|
|
555
554
|
|
|
555
|
+
// src/exportTable.ts
|
|
556
|
+
var EXPORT_FORMATS = Object.freeze(["xlsx", "csv"]);
|
|
557
|
+
var XLSX_MIME = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
|
|
558
|
+
var CSV_MIME = "text/csv";
|
|
559
|
+
var XLSX_MAX_ROWS = 1048576;
|
|
560
|
+
var XLSX_MAX_COLS = 16384;
|
|
561
|
+
var XLSX_MAX_CELL_CHARS = 32767;
|
|
562
|
+
function isBlank(v) {
|
|
563
|
+
return v === null || v === void 0 || typeof v === "string" && v.trim() === "";
|
|
564
|
+
}
|
|
565
|
+
function asNumber(v) {
|
|
566
|
+
if (isBlank(v) || typeof v === "boolean") return null;
|
|
567
|
+
if (v instanceof Date) return null;
|
|
568
|
+
const n = typeof v === "number" ? v : Number(String(v).trim());
|
|
569
|
+
return Number.isFinite(n) ? n : null;
|
|
570
|
+
}
|
|
571
|
+
function asTime(v) {
|
|
572
|
+
if (isBlank(v) || typeof v === "boolean") return null;
|
|
573
|
+
if (v instanceof Date) {
|
|
574
|
+
const t2 = v.getTime();
|
|
575
|
+
return Number.isFinite(t2) ? t2 : null;
|
|
576
|
+
}
|
|
577
|
+
if (typeof v === "number") return Number.isFinite(v) ? v : null;
|
|
578
|
+
const s = String(v).trim();
|
|
579
|
+
const day = /^(\d{4})-(\d{2})-(\d{2})$/.exec(s);
|
|
580
|
+
if (day) return Date.UTC(+day[1], +day[2] - 1, +day[3]);
|
|
581
|
+
const t = Date.parse(s);
|
|
582
|
+
return Number.isFinite(t) ? t : null;
|
|
583
|
+
}
|
|
584
|
+
function asBoolean(v) {
|
|
585
|
+
if (v === true || v === false) return v;
|
|
586
|
+
if (isBlank(v)) return null;
|
|
587
|
+
const s = String(v).trim().toLowerCase();
|
|
588
|
+
if (s === "true" || s === "1" || s === "yes") return true;
|
|
589
|
+
if (s === "false" || s === "0" || s === "no") return false;
|
|
590
|
+
return null;
|
|
591
|
+
}
|
|
592
|
+
function asText(v) {
|
|
593
|
+
if (v === null || v === void 0) return "";
|
|
594
|
+
if (v instanceof Date) return Number.isFinite(v.getTime()) ? v.toISOString() : "";
|
|
595
|
+
return String(v);
|
|
596
|
+
}
|
|
597
|
+
var DAY_MS = 864e5;
|
|
598
|
+
function hasTimeOfDay(t) {
|
|
599
|
+
return (t % DAY_MS + DAY_MS) % DAY_MS !== 0;
|
|
600
|
+
}
|
|
601
|
+
function pad2(n) {
|
|
602
|
+
return n < 10 ? "0" + n : String(n);
|
|
603
|
+
}
|
|
604
|
+
function isoDay(t) {
|
|
605
|
+
const d = new Date(t);
|
|
606
|
+
return d.getUTCFullYear() + "-" + pad2(d.getUTCMonth() + 1) + "-" + pad2(d.getUTCDate());
|
|
607
|
+
}
|
|
608
|
+
function isoDayTime(t) {
|
|
609
|
+
const d = new Date(t);
|
|
610
|
+
return isoDay(t) + " " + pad2(d.getUTCHours()) + ":" + pad2(d.getUTCMinutes()) + ":" + pad2(d.getUTCSeconds());
|
|
611
|
+
}
|
|
612
|
+
function excelSerial(t) {
|
|
613
|
+
const s = t / DAY_MS + 25569;
|
|
614
|
+
return s < 61 ? s - 1 : s;
|
|
615
|
+
}
|
|
616
|
+
var EXCEL_FIRST_DAY = Date.UTC(1900, 0, 1);
|
|
617
|
+
function fractionDigits(n) {
|
|
618
|
+
const s = String(Math.abs(n));
|
|
619
|
+
if (/e/i.test(s)) return 0;
|
|
620
|
+
const dot = s.indexOf(".");
|
|
621
|
+
return dot < 0 ? 0 : Math.min(15, s.length - dot - 1);
|
|
622
|
+
}
|
|
623
|
+
var D3_SPEC_RE = /^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;
|
|
624
|
+
function shapeFromD3(spec) {
|
|
625
|
+
const m = D3_SPEC_RE.exec(spec.trim());
|
|
626
|
+
if (!m) return null;
|
|
627
|
+
const sign = m[3] || "", symbol = m[4] || "", group = !!m[7], trim = !!m[9], type = m[10] || "";
|
|
628
|
+
const p = m[8] ? parseInt(m[8].slice(1), 10) : null;
|
|
629
|
+
const base = { prefix: symbol === "$" ? "$" : "", suffix: "", group, minD: 0, maxD: 0, percent: false, plus: sign === "+", parens: sign === "(", scientific: false };
|
|
630
|
+
if (type === "f") {
|
|
631
|
+
const d = p === null ? 6 : p;
|
|
632
|
+
return { ...base, maxD: d, minD: trim ? 0 : d };
|
|
633
|
+
}
|
|
634
|
+
if (type === "%") {
|
|
635
|
+
const d = p === null ? 6 : p;
|
|
636
|
+
return { ...base, percent: true, maxD: d, minD: trim ? 0 : d };
|
|
637
|
+
}
|
|
638
|
+
if (type === "d") return base;
|
|
639
|
+
if (type === "e") {
|
|
640
|
+
const d = p === null ? 6 : p;
|
|
641
|
+
return { ...base, scientific: true, maxD: d, minD: d };
|
|
642
|
+
}
|
|
643
|
+
if ((type === "" || type === "n" || type === "g" || type === "r") && (group || type === "n")) return { ...base, group: true, maxD: 15, minD: 0 };
|
|
644
|
+
return null;
|
|
645
|
+
}
|
|
646
|
+
function shapeFromModel(fmt) {
|
|
647
|
+
const sections = fmt.split(";");
|
|
648
|
+
const sec = sections[0];
|
|
649
|
+
const bracketSym = (/\[\$([^\-\]]+)/.exec(sec) || [])[1] || "";
|
|
650
|
+
const noTok = sec.replace(/\[[^\]]*\]/g, "");
|
|
651
|
+
const bare = noTok.replace(/"[^"]*"/g, "").replace(/\\./g, "");
|
|
652
|
+
const pct = bare.indexOf("%") >= 0;
|
|
653
|
+
if (!pct && !/[0#]/.test(bare)) return null;
|
|
654
|
+
let sym = bracketSym;
|
|
655
|
+
let symAfter = false;
|
|
656
|
+
if (!sym) {
|
|
657
|
+
const lit = /"([^"]*[$\u20AC\u00A3\u00A5][^"]*)"/.exec(noTok);
|
|
658
|
+
const cur = lit ? null : /\\?([$\u20AC\u00A3\u00A5])/.exec(noTok);
|
|
659
|
+
if (lit) sym = lit[1].trim();
|
|
660
|
+
else if (cur) sym = cur[1];
|
|
661
|
+
}
|
|
662
|
+
if (sym) {
|
|
663
|
+
const firstDigit = noTok.search(/[0#]/);
|
|
664
|
+
const at = noTok.indexOf(sym);
|
|
665
|
+
symAfter = at >= 0 && firstDigit >= 0 && at > firstDigit;
|
|
666
|
+
}
|
|
667
|
+
const dm = /\.([0#]+)/.exec(bare);
|
|
668
|
+
const maxD = dm ? dm[1].length : 0, minD = dm ? dm[1].replace(/#/g, "").length : 0;
|
|
669
|
+
return {
|
|
670
|
+
prefix: sym && !symAfter ? sym : "",
|
|
671
|
+
suffix: sym && symAfter ? sym : "",
|
|
672
|
+
group: bare.indexOf(",") >= 0,
|
|
673
|
+
minD,
|
|
674
|
+
maxD: Math.min(15, maxD),
|
|
675
|
+
percent: pct,
|
|
676
|
+
plus: /^\s*\+/.test(bare),
|
|
677
|
+
parens: sections.length > 1 && /\(/.test(sections[1]) && /\)/.test(sections[1]),
|
|
678
|
+
scientific: false
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
function quoteLiteral(s) {
|
|
682
|
+
return s ? '"' + s.replace(/"/g, "") + '"' : "";
|
|
683
|
+
}
|
|
684
|
+
function codeFromShape(sh, dataFrac) {
|
|
685
|
+
const d = Math.max(sh.minD, Math.min(sh.maxD, dataFrac));
|
|
686
|
+
if (sh.scientific) return "0" + (d > 0 ? "." + "0".repeat(d) : "") + "E+00";
|
|
687
|
+
const core = (sh.group ? "#,##0" : "0") + (d > 0 ? "." + "0".repeat(d) : "") + (sh.percent ? "%" : "");
|
|
688
|
+
const body = quoteLiteral(sh.prefix) + core + quoteLiteral(sh.suffix);
|
|
689
|
+
if (!sh.plus && !sh.parens) {
|
|
690
|
+
return body === "0" ? null : body;
|
|
691
|
+
}
|
|
692
|
+
const pos = (sh.plus ? "+" : "") + body;
|
|
693
|
+
const neg = sh.parens ? "(" + body + ")" : "-" + body;
|
|
694
|
+
return pos + ";" + neg + ";" + body;
|
|
695
|
+
}
|
|
696
|
+
function excelNumberFormat(col, values = []) {
|
|
697
|
+
let sh = null;
|
|
698
|
+
if (typeof col.d3Format === "string" && col.d3Format.trim()) sh = shapeFromD3(col.d3Format);
|
|
699
|
+
else if (typeof col.modelFormat === "string" && col.modelFormat.trim()) sh = shapeFromModel(col.modelFormat);
|
|
700
|
+
if (!sh) return null;
|
|
701
|
+
let frac = 0;
|
|
702
|
+
for (const v of values) {
|
|
703
|
+
const f2 = fractionDigits(sh.percent ? Math.round(v * 100 * 1e9) / 1e9 : v);
|
|
704
|
+
if (f2 > frac) frac = f2;
|
|
705
|
+
}
|
|
706
|
+
return codeFromShape(sh, frac);
|
|
707
|
+
}
|
|
708
|
+
var FORMULA_START_RE = /^[=+\-@\t\r]/;
|
|
709
|
+
function csvField(s) {
|
|
710
|
+
return /[",\r\n]/.test(s) ? '"' + s.replace(/"/g, '""') + '"' : s;
|
|
711
|
+
}
|
|
712
|
+
function columnUsesTime(table, ci) {
|
|
713
|
+
for (const r of table.rows) {
|
|
714
|
+
const t = asTime(r[ci]);
|
|
715
|
+
if (t !== null && hasTimeOfDay(t)) return true;
|
|
716
|
+
}
|
|
717
|
+
return false;
|
|
718
|
+
}
|
|
719
|
+
function tableToCsv(table) {
|
|
720
|
+
const cols = table.columns;
|
|
721
|
+
const withTime = cols.map((c, ci) => c.type === "date" && columnUsesTime(table, ci));
|
|
722
|
+
const lines = [cols.map((c) => csvField(guardText(c.name))).join(",")];
|
|
723
|
+
for (const row of table.rows) {
|
|
724
|
+
const out = [];
|
|
725
|
+
for (let ci = 0; ci < cols.length; ci++) {
|
|
726
|
+
const c = cols[ci], v = row[ci];
|
|
727
|
+
if (c.type === "number") {
|
|
728
|
+
const n = asNumber(v);
|
|
729
|
+
out.push(n === null ? "" : String(n));
|
|
730
|
+
continue;
|
|
731
|
+
}
|
|
732
|
+
if (c.type === "date") {
|
|
733
|
+
const t = asTime(v);
|
|
734
|
+
out.push(t === null ? csvField(guardText(asText(v))) : withTime[ci] ? isoDayTime(t) : isoDay(t));
|
|
735
|
+
continue;
|
|
736
|
+
}
|
|
737
|
+
if (c.type === "boolean") {
|
|
738
|
+
const b = asBoolean(v);
|
|
739
|
+
out.push(b === null ? csvField(guardText(asText(v))) : b ? "TRUE" : "FALSE");
|
|
740
|
+
continue;
|
|
741
|
+
}
|
|
742
|
+
out.push(csvField(guardText(asText(v))));
|
|
743
|
+
}
|
|
744
|
+
lines.push(out.join(","));
|
|
745
|
+
}
|
|
746
|
+
return "\uFEFF" + lines.join("\r\n") + "\r\n";
|
|
747
|
+
}
|
|
748
|
+
function guardText(s) {
|
|
749
|
+
return FORMULA_START_RE.test(s) ? "'" + s : s;
|
|
750
|
+
}
|
|
751
|
+
var XML_BAD_RE = /[\u0000-\u0008\u000B\u000C\u000E-\u001F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g;
|
|
752
|
+
function xmlText(s) {
|
|
753
|
+
return s.replace(XML_BAD_RE, "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
754
|
+
}
|
|
755
|
+
function columnLetters(ci) {
|
|
756
|
+
let s = "", n = ci + 1;
|
|
757
|
+
while (n > 0) {
|
|
758
|
+
const r = (n - 1) % 26;
|
|
759
|
+
s = String.fromCharCode(65 + r) + s;
|
|
760
|
+
n = Math.floor((n - 1) / 26);
|
|
761
|
+
}
|
|
762
|
+
return s;
|
|
763
|
+
}
|
|
764
|
+
function sheetName(title) {
|
|
765
|
+
let s = String(title ?? "").replace(/[\[\]:*?/\\]/g, " ").replace(XML_BAD_RE, "").replace(/\s+/g, " ").trim();
|
|
766
|
+
s = s.replace(/^'+|'+$/g, "").trim();
|
|
767
|
+
if (s.length > 31) s = s.slice(0, 31).trim();
|
|
768
|
+
if (!s || s.toLowerCase() === "history") s = "Data";
|
|
769
|
+
return s;
|
|
770
|
+
}
|
|
771
|
+
function exportFileName(title, format) {
|
|
772
|
+
let s = String(title ?? "").replace(XML_BAD_RE, "").replace(/[<>:"/\\|?*\u0000-\u001F]/g, " ").replace(/\s+/g, " ").trim();
|
|
773
|
+
s = s.replace(/[. ]+$/, "");
|
|
774
|
+
if (s.length > 80) s = s.slice(0, 80).trim();
|
|
775
|
+
if (!s || /^(con|prn|aux|nul|com\d|lpt\d)$/i.test(s)) s = "table";
|
|
776
|
+
return s + "." + format;
|
|
777
|
+
}
|
|
778
|
+
function tableToXlsx(table) {
|
|
779
|
+
const cols = table.columns.slice(0, XLSX_MAX_COLS);
|
|
780
|
+
const rows = table.rows.slice(0, XLSX_MAX_ROWS - 1);
|
|
781
|
+
const nC = cols.length;
|
|
782
|
+
const numFmtIds = {};
|
|
783
|
+
const numFmtList = [];
|
|
784
|
+
const xfFor = {};
|
|
785
|
+
const XF_DATE = 2, XF_DATETIME = 3;
|
|
786
|
+
let nextXf = 4;
|
|
787
|
+
const colXf = [];
|
|
788
|
+
const colTime = [];
|
|
789
|
+
for (let ci = 0; ci < nC; ci++) {
|
|
790
|
+
const c = cols[ci];
|
|
791
|
+
colTime.push(c.type === "date" && columnUsesTime({ columns: cols, rows }, ci));
|
|
792
|
+
if (c.type === "number") {
|
|
793
|
+
const vals = [];
|
|
794
|
+
for (const r of rows) {
|
|
795
|
+
const n = asNumber(r[ci]);
|
|
796
|
+
if (n !== null) vals.push(n);
|
|
797
|
+
}
|
|
798
|
+
const code = excelNumberFormat(c, vals);
|
|
799
|
+
if (code) {
|
|
800
|
+
if (numFmtIds[code] === void 0) {
|
|
801
|
+
numFmtIds[code] = 164 + numFmtList.length;
|
|
802
|
+
numFmtList.push(code);
|
|
803
|
+
}
|
|
804
|
+
if (xfFor[code] === void 0) xfFor[code] = nextXf++;
|
|
805
|
+
colXf.push(xfFor[code]);
|
|
806
|
+
} else colXf.push(0);
|
|
807
|
+
} else if (c.type === "date") colXf.push(colTime[ci] ? XF_DATETIME : XF_DATE);
|
|
808
|
+
else colXf.push(0);
|
|
809
|
+
}
|
|
810
|
+
const widths = cols.map((c) => Math.min(60, String(c.name).length + 3));
|
|
811
|
+
const sheetRows = [];
|
|
812
|
+
const ref = (ci, ri) => columnLetters(ci) + (ri + 1);
|
|
813
|
+
const head = [];
|
|
814
|
+
for (let ci = 0; ci < nC; ci++) head.push(inlineStr(ref(ci, 0), cols[ci].name, 1));
|
|
815
|
+
sheetRows.push('<row r="1">' + head.join("") + "</row>");
|
|
816
|
+
for (let ri = 0; ri < rows.length; ri++) {
|
|
817
|
+
const row = rows[ri], cells = [];
|
|
818
|
+
for (let ci = 0; ci < nC; ci++) {
|
|
819
|
+
const out = cellXml(cols[ci], row[ci], ref(ci, ri + 1), colXf[ci], colTime[ci]);
|
|
820
|
+
if (!out) continue;
|
|
821
|
+
cells.push(out.xml);
|
|
822
|
+
if (out.width > widths[ci]) widths[ci] = Math.min(60, out.width);
|
|
823
|
+
}
|
|
824
|
+
sheetRows.push('<row r="' + (ri + 2) + '">' + cells.join("") + "</row>");
|
|
825
|
+
}
|
|
826
|
+
const lastRef = nC ? columnLetters(nC - 1) + (rows.length + 1) : "A1";
|
|
827
|
+
const colsXml = nC ? "<cols>" + widths.map((w, ci) => '<col min="' + (ci + 1) + '" max="' + (ci + 1) + '" width="' + Math.max(8, Math.round(w + 1)) + '" customWidth="1"/>').join("") + "</cols>" : "";
|
|
828
|
+
const name = sheetName(table.title);
|
|
829
|
+
const sheetXml = XML_HEAD + '<worksheet xmlns="' + NS_MAIN + '" xmlns:r="' + NS_REL + '"><dimension ref="A1:' + lastRef + '"/><sheetViews><sheetView tabSelected="1" workbookViewId="0">' + (nC ? '<pane ySplit="1" topLeftCell="A2" activePane="bottomLeft" state="frozen"/><selection pane="bottomLeft" activeCell="A2" sqref="A2"/>' : "") + '</sheetView></sheetViews><sheetFormatPr defaultRowHeight="15"/>' + colsXml + "<sheetData>" + sheetRows.join("") + "</sheetData>" + (nC ? '<autoFilter ref="A1:' + lastRef + '"/>' : "") + "</worksheet>";
|
|
830
|
+
const workbookXml = XML_HEAD + '<workbook xmlns="' + NS_MAIN + '" xmlns:r="' + NS_REL + '"><bookViews><workbookView/></bookViews><sheets><sheet name="' + xmlText(name) + '" sheetId="1" r:id="rId1"/></sheets>' + (nC ? '<definedNames><definedName name="_xlnm._FilterDatabase" localSheetId="0" hidden="1">' + xmlText("'" + name.replace(/'/g, "''") + "'!$A$1:$" + columnLetters(nC - 1) + "$" + (rows.length + 1)) + "</definedName></definedNames>" : "") + "</workbook>";
|
|
831
|
+
const numFmtsXml = numFmtList.length ? '<numFmts count="' + numFmtList.length + '">' + numFmtList.map((code) => '<numFmt numFmtId="' + numFmtIds[code] + '" formatCode="' + xmlText(code) + '"/>').join("") + "</numFmts>" : "";
|
|
832
|
+
const xfs = [
|
|
833
|
+
'<xf numFmtId="0" fontId="0" fillId="0" borderId="0" xfId="0"/>',
|
|
834
|
+
'<xf numFmtId="0" fontId="1" fillId="0" borderId="0" xfId="0" applyFont="1"/>',
|
|
835
|
+
'<xf numFmtId="14" fontId="0" fillId="0" borderId="0" xfId="0" applyNumberFormat="1"/>',
|
|
836
|
+
'<xf numFmtId="22" fontId="0" fillId="0" borderId="0" xfId="0" applyNumberFormat="1"/>'
|
|
837
|
+
];
|
|
838
|
+
for (const code of numFmtList) xfs[xfFor[code]] = '<xf numFmtId="' + numFmtIds[code] + '" fontId="0" fillId="0" borderId="0" xfId="0" applyNumberFormat="1"/>';
|
|
839
|
+
const stylesXml = XML_HEAD + '<styleSheet xmlns="' + NS_MAIN + '">' + numFmtsXml + '<fonts count="2"><font><sz val="11"/><name val="Calibri"/><family val="2"/></font><font><b/><sz val="11"/><name val="Calibri"/><family val="2"/></font></fonts><fills count="2"><fill><patternFill patternType="none"/></fill><fill><patternFill patternType="gray125"/></fill></fills><borders count="1"><border><left/><right/><top/><bottom/><diagonal/></border></borders><cellStyleXfs count="1"><xf numFmtId="0" fontId="0" fillId="0" borderId="0"/></cellStyleXfs><cellXfs count="' + xfs.length + '">' + xfs.join("") + '</cellXfs><cellStyles count="1"><cellStyle name="Normal" xfId="0" builtinId="0"/></cellStyles></styleSheet>';
|
|
840
|
+
const contentTypes = XML_HEAD + '<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/><Default Extension="xml" ContentType="application/xml"/><Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/><Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/><Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"/></Types>';
|
|
841
|
+
const rootRels = XML_HEAD + '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/></Relationships>';
|
|
842
|
+
const workbookRels = XML_HEAD + '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/><Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/></Relationships>';
|
|
843
|
+
return zipStored([
|
|
844
|
+
["[Content_Types].xml", contentTypes],
|
|
845
|
+
["_rels/.rels", rootRels],
|
|
846
|
+
["xl/workbook.xml", workbookXml],
|
|
847
|
+
["xl/_rels/workbook.xml.rels", workbookRels],
|
|
848
|
+
["xl/styles.xml", stylesXml],
|
|
849
|
+
["xl/worksheets/sheet1.xml", sheetXml]
|
|
850
|
+
]);
|
|
851
|
+
}
|
|
852
|
+
var XML_HEAD = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n';
|
|
853
|
+
var NS_MAIN = "http://schemas.openxmlformats.org/spreadsheetml/2006/main";
|
|
854
|
+
var NS_REL = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
|
|
855
|
+
function inlineStr(r, text2, style) {
|
|
856
|
+
let s = String(text2);
|
|
857
|
+
if (s.length > XLSX_MAX_CELL_CHARS) s = s.slice(0, XLSX_MAX_CELL_CHARS);
|
|
858
|
+
return '<c r="' + r + '"' + (style ? ' s="' + style + '"' : "") + ' t="inlineStr"><is><t xml:space="preserve">' + xmlText(s) + "</t></is></c>";
|
|
859
|
+
}
|
|
860
|
+
function cellXml(c, v, r, xf, withTime) {
|
|
861
|
+
if (isBlank(v)) return null;
|
|
862
|
+
if (c.type === "number") {
|
|
863
|
+
const n = asNumber(v);
|
|
864
|
+
if (n !== null) return { xml: '<c r="' + r + '"' + (xf ? ' s="' + xf + '"' : "") + "><v>" + String(n) + "</v></c>", width: String(n).length + (Math.abs(n) >= 1e3 ? Math.floor(Math.log10(Math.abs(n)) / 3) : 0) + 2 };
|
|
865
|
+
} else if (c.type === "date") {
|
|
866
|
+
const t = asTime(v);
|
|
867
|
+
if (t !== null && t >= EXCEL_FIRST_DAY) return { xml: '<c r="' + r + '" s="' + xf + '"><v>' + String(excelSerial(t)) + "</v></c>", width: withTime ? 18 : 12 };
|
|
868
|
+
if (t !== null) {
|
|
869
|
+
const s2 = withTime ? isoDayTime(t) : isoDay(t);
|
|
870
|
+
return { xml: inlineStr(r, s2, 0), width: s2.length + 1 };
|
|
871
|
+
}
|
|
872
|
+
} else if (c.type === "boolean") {
|
|
873
|
+
const b = asBoolean(v);
|
|
874
|
+
if (b !== null) return { xml: '<c r="' + r + '" t="b"><v>' + (b ? 1 : 0) + "</v></c>", width: 7 };
|
|
875
|
+
}
|
|
876
|
+
const s = asText(v);
|
|
877
|
+
return { xml: inlineStr(r, s, 0), width: Math.min(60, longestLine(s) + 1) };
|
|
878
|
+
}
|
|
879
|
+
function longestLine(s) {
|
|
880
|
+
let mx = 0;
|
|
881
|
+
for (const line of s.split(/\r?\n/)) if (line.length > mx) mx = line.length;
|
|
882
|
+
return mx;
|
|
883
|
+
}
|
|
884
|
+
var CRC_TABLE = null;
|
|
885
|
+
function crc32(bytes) {
|
|
886
|
+
if (!CRC_TABLE) {
|
|
887
|
+
CRC_TABLE = new Uint32Array(256);
|
|
888
|
+
for (let n = 0; n < 256; n++) {
|
|
889
|
+
let c = n;
|
|
890
|
+
for (let k = 0; k < 8; k++) c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
|
|
891
|
+
CRC_TABLE[n] = c >>> 0;
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
let crc = 4294967295;
|
|
895
|
+
for (let i = 0; i < bytes.length; i++) crc = CRC_TABLE[(crc ^ bytes[i]) & 255] ^ crc >>> 8;
|
|
896
|
+
return (crc ^ 4294967295) >>> 0;
|
|
897
|
+
}
|
|
898
|
+
function utf8(s) {
|
|
899
|
+
return new TextEncoder().encode(s);
|
|
900
|
+
}
|
|
901
|
+
function zipStored(files) {
|
|
902
|
+
const DOS_TIME = 0, DOS_DATE = 0 << 9 | 1 << 5 | 1;
|
|
903
|
+
const locals = [], centrals = [];
|
|
904
|
+
let offset = 0;
|
|
905
|
+
for (const [name, content] of files) {
|
|
906
|
+
const nameBytes = utf8(name);
|
|
907
|
+
const data = typeof content === "string" ? utf8(content) : content;
|
|
908
|
+
const crc = crc32(data);
|
|
909
|
+
const local = new Uint8Array(30 + nameBytes.length);
|
|
910
|
+
const lv = new DataView(local.buffer);
|
|
911
|
+
lv.setUint32(0, 67324752, true);
|
|
912
|
+
lv.setUint16(4, 20, true);
|
|
913
|
+
lv.setUint16(6, 2048, true);
|
|
914
|
+
lv.setUint16(8, 0, true);
|
|
915
|
+
lv.setUint16(10, DOS_TIME, true);
|
|
916
|
+
lv.setUint16(12, DOS_DATE, true);
|
|
917
|
+
lv.setUint32(14, crc, true);
|
|
918
|
+
lv.setUint32(18, data.length, true);
|
|
919
|
+
lv.setUint32(22, data.length, true);
|
|
920
|
+
lv.setUint16(26, nameBytes.length, true);
|
|
921
|
+
lv.setUint16(28, 0, true);
|
|
922
|
+
local.set(nameBytes, 30);
|
|
923
|
+
const central = new Uint8Array(46 + nameBytes.length);
|
|
924
|
+
const cv = new DataView(central.buffer);
|
|
925
|
+
cv.setUint32(0, 33639248, true);
|
|
926
|
+
cv.setUint16(4, 20, true);
|
|
927
|
+
cv.setUint16(6, 20, true);
|
|
928
|
+
cv.setUint16(8, 2048, true);
|
|
929
|
+
cv.setUint16(10, 0, true);
|
|
930
|
+
cv.setUint16(12, DOS_TIME, true);
|
|
931
|
+
cv.setUint16(14, DOS_DATE, true);
|
|
932
|
+
cv.setUint32(16, crc, true);
|
|
933
|
+
cv.setUint32(20, data.length, true);
|
|
934
|
+
cv.setUint32(24, data.length, true);
|
|
935
|
+
cv.setUint16(28, nameBytes.length, true);
|
|
936
|
+
cv.setUint16(30, 0, true);
|
|
937
|
+
cv.setUint16(32, 0, true);
|
|
938
|
+
cv.setUint16(34, 0, true);
|
|
939
|
+
cv.setUint16(36, 0, true);
|
|
940
|
+
cv.setUint32(38, 0, true);
|
|
941
|
+
cv.setUint32(42, offset, true);
|
|
942
|
+
central.set(nameBytes, 46);
|
|
943
|
+
locals.push(local, data);
|
|
944
|
+
centrals.push(central);
|
|
945
|
+
offset += local.length + data.length;
|
|
946
|
+
}
|
|
947
|
+
const centralSize = centrals.reduce((s, c) => s + c.length, 0);
|
|
948
|
+
const end = new Uint8Array(22);
|
|
949
|
+
const ev = new DataView(end.buffer);
|
|
950
|
+
ev.setUint32(0, 101010256, true);
|
|
951
|
+
ev.setUint16(4, 0, true);
|
|
952
|
+
ev.setUint16(6, 0, true);
|
|
953
|
+
ev.setUint16(8, files.length, true);
|
|
954
|
+
ev.setUint16(10, files.length, true);
|
|
955
|
+
ev.setUint32(12, centralSize, true);
|
|
956
|
+
ev.setUint32(16, offset, true);
|
|
957
|
+
ev.setUint16(20, 0, true);
|
|
958
|
+
const total = offset + centralSize + end.length;
|
|
959
|
+
const out = new Uint8Array(total);
|
|
960
|
+
let at = 0;
|
|
961
|
+
for (const part of locals) {
|
|
962
|
+
out.set(part, at);
|
|
963
|
+
at += part.length;
|
|
964
|
+
}
|
|
965
|
+
for (const part of centrals) {
|
|
966
|
+
out.set(part, at);
|
|
967
|
+
at += part.length;
|
|
968
|
+
}
|
|
969
|
+
out.set(end, at);
|
|
970
|
+
return out;
|
|
971
|
+
}
|
|
972
|
+
function buildExportFile(table, format) {
|
|
973
|
+
const name = exportFileName(table.title, format);
|
|
974
|
+
if (format === "csv") {
|
|
975
|
+
const text2 = tableToCsv(table);
|
|
976
|
+
return { name, format, mime: CSV_MIME + ";charset=utf-8", bytes: utf8(text2), text: text2, table };
|
|
977
|
+
}
|
|
978
|
+
return { name, format, mime: XLSX_MIME, bytes: tableToXlsx(table), table };
|
|
979
|
+
}
|
|
980
|
+
function bytesToBase64(bytes) {
|
|
981
|
+
const A = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
982
|
+
let out = "";
|
|
983
|
+
let i = 0;
|
|
984
|
+
for (; i + 2 < bytes.length; i += 3) {
|
|
985
|
+
const n = bytes[i] << 16 | bytes[i + 1] << 8 | bytes[i + 2];
|
|
986
|
+
out += A[n >> 18 & 63] + A[n >> 12 & 63] + A[n >> 6 & 63] + A[n & 63];
|
|
987
|
+
}
|
|
988
|
+
const rest = bytes.length - i;
|
|
989
|
+
if (rest === 1) {
|
|
990
|
+
const n = bytes[i] << 16;
|
|
991
|
+
out += A[n >> 18 & 63] + A[n >> 12 & 63] + "==";
|
|
992
|
+
} else if (rest === 2) {
|
|
993
|
+
const n = bytes[i] << 16 | bytes[i + 1] << 8;
|
|
994
|
+
out += A[n >> 18 & 63] + A[n >> 12 & 63] + A[n >> 6 & 63] + "=";
|
|
995
|
+
}
|
|
996
|
+
return out;
|
|
997
|
+
}
|
|
998
|
+
function exportFormatsFor(hostFormats) {
|
|
999
|
+
if (!Array.isArray(hostFormats)) return EXPORT_FORMATS.slice();
|
|
1000
|
+
return EXPORT_FORMATS.filter((f2) => hostFormats.indexOf(f2) >= 0);
|
|
1001
|
+
}
|
|
1002
|
+
function exportTableService(save, formats = EXPORT_FORMATS) {
|
|
1003
|
+
const allowed = formats.slice();
|
|
1004
|
+
return async (table, format) => {
|
|
1005
|
+
try {
|
|
1006
|
+
if (!table || !Array.isArray(table.columns) || !Array.isArray(table.rows)) return false;
|
|
1007
|
+
if (allowed.indexOf(format) < 0) return false;
|
|
1008
|
+
const file = buildExportFile(table, format);
|
|
1009
|
+
const res = await save(file);
|
|
1010
|
+
return res !== false;
|
|
1011
|
+
} catch {
|
|
1012
|
+
return false;
|
|
1013
|
+
}
|
|
1014
|
+
};
|
|
1015
|
+
}
|
|
1016
|
+
function browserSaveFile(doc) {
|
|
1017
|
+
return (file) => {
|
|
1018
|
+
const d = doc ?? (typeof document !== "undefined" ? document : void 0);
|
|
1019
|
+
const view = d?.defaultView;
|
|
1020
|
+
const U = view?.URL ?? (typeof URL !== "undefined" ? URL : void 0);
|
|
1021
|
+
const B = view?.Blob ?? (typeof Blob !== "undefined" ? Blob : void 0);
|
|
1022
|
+
if (!d || !d.body || !U || typeof U.createObjectURL !== "function" || !B) return false;
|
|
1023
|
+
const blob = new B([file.bytes.slice()], { type: file.mime });
|
|
1024
|
+
const href = U.createObjectURL(blob);
|
|
1025
|
+
const a = d.createElement("a");
|
|
1026
|
+
a.href = href;
|
|
1027
|
+
a.download = file.name;
|
|
1028
|
+
a.rel = "noopener";
|
|
1029
|
+
a.style.display = "none";
|
|
1030
|
+
d.body.appendChild(a);
|
|
1031
|
+
try {
|
|
1032
|
+
a.click();
|
|
1033
|
+
} finally {
|
|
1034
|
+
a.remove();
|
|
1035
|
+
setTimeout(() => {
|
|
1036
|
+
try {
|
|
1037
|
+
U.revokeObjectURL(href);
|
|
1038
|
+
} catch {
|
|
1039
|
+
}
|
|
1040
|
+
}, 3e4);
|
|
1041
|
+
}
|
|
1042
|
+
return true;
|
|
1043
|
+
};
|
|
1044
|
+
}
|
|
1045
|
+
|
|
556
1046
|
// src/defaults.ts
|
|
1047
|
+
function hostExport(save, formats) {
|
|
1048
|
+
if (typeof save !== "function") return {};
|
|
1049
|
+
const offered = exportFormatsFor(Array.isArray(formats) ? formats : void 0);
|
|
1050
|
+
if (!offered.length) return {};
|
|
1051
|
+
const saveFile = save;
|
|
1052
|
+
return { saveFile, exportFormats: Object.freeze(offered), exportTable: exportTableService(saveFile, offered) };
|
|
1053
|
+
}
|
|
557
1054
|
function themedLand(p) {
|
|
558
1055
|
const bg = p.geoLandColor ? null : toRGBA(p.backgroundColor);
|
|
559
1056
|
if (!bg || bg[3] < 1 || relativeLuminance([bg[0], bg[1], bg[2]]) > 0.2) return void 0;
|
|
@@ -566,6 +1063,7 @@ var numberOr = (raw, dflt) => {
|
|
|
566
1063
|
return Number.isFinite(n) ? n : dflt;
|
|
567
1064
|
};
|
|
568
1065
|
function resolveOptions(p) {
|
|
1066
|
+
const exp = hostExport(p.saveFile, p.exportFormats);
|
|
569
1067
|
return {
|
|
570
1068
|
// ---- host fields: pass through exactly as supplied ----
|
|
571
1069
|
width: p.width,
|
|
@@ -589,6 +1087,15 @@ function resolveOptions(p) {
|
|
|
589
1087
|
dataComplete: p.dataComplete,
|
|
590
1088
|
rowsWithheld: p.rowsWithheld,
|
|
591
1089
|
rowsFilteredOut: p.rowsFilteredOut,
|
|
1090
|
+
// Host services (contract 1.18.0): a FUNCTION or nothing, so a junk value never reaches a chart as something
|
|
1091
|
+
// it would try to call. Passed through untouched otherwise: the host owns what opening or copying means.
|
|
1092
|
+
openUrl: typeof p.openUrl === "function" ? p.openUrl : void 0,
|
|
1093
|
+
copyText: typeof p.copyText === "function" ? p.copyText : void 0,
|
|
1094
|
+
// Exporting rows to a file (contract 1.19.0): exportTable is DERIVED from the host's saveFile, never taken from
|
|
1095
|
+
// the host, so a chart offers an export only where a file can really be kept. See hostExport above.
|
|
1096
|
+
saveFile: exp.saveFile,
|
|
1097
|
+
exportFormats: exp.exportFormats,
|
|
1098
|
+
exportTable: exp.exportTable,
|
|
592
1099
|
// NO LONGER A PASS-THROUGH. A host without a Max Map Points setting used to leave this
|
|
593
1100
|
// undefined, and every map chart then fell back to whatever number its own code carried -
|
|
594
1101
|
// 1000 in every archetype written so far - while the offer gate used the server's. One
|
|
@@ -658,6 +1165,8 @@ function resolveOptions(p) {
|
|
|
658
1165
|
// generated code); HC substitution has already happened in the caller.
|
|
659
1166
|
geoLandColor: p.geoLandColor || themedLand(p) || void 0,
|
|
660
1167
|
geoNoDataColor: p.geoNoDataColor || void 0,
|
|
1168
|
+
// Borders on unless the host says false: a province map of several countries needs them to read.
|
|
1169
|
+
geoBorders: p.geoBorders !== false,
|
|
661
1170
|
aggregation: (p.aggregation == null ? "" : String(p.aggregation)) || void 0,
|
|
662
1171
|
// A recognised value wins, anything else falls to the default: an unknown string must
|
|
663
1172
|
// never reach a chart as a live mode. Both of these are read on EVERY render, so a
|
|
@@ -760,87 +1269,6 @@ function resolveOptions(p) {
|
|
|
760
1269
|
};
|
|
761
1270
|
}
|
|
762
1271
|
|
|
763
|
-
// src/geoLazy.ts
|
|
764
|
-
var byKind = /* @__PURE__ */ new Map();
|
|
765
|
-
var byAsset = /* @__PURE__ */ new Map();
|
|
766
|
-
var _na;
|
|
767
|
-
function geoAssetFor(geoKind) {
|
|
768
|
-
if (!geoKind) return null;
|
|
769
|
-
const k = geoKind.toLowerCase();
|
|
770
|
-
if (/^country/.test(k)) return "world";
|
|
771
|
-
if (k === "north-america") return "world";
|
|
772
|
-
if (k === "world") return "world";
|
|
773
|
-
if (k === "us-state-code" || k === "us-state-name") return "us-states";
|
|
774
|
-
if (k === "us-zip5") return "us-zip3";
|
|
775
|
-
return null;
|
|
776
|
-
}
|
|
777
|
-
var _worldBase;
|
|
778
|
-
function worldBasemap(world) {
|
|
779
|
-
if (!_worldBase) {
|
|
780
|
-
_worldBase = {
|
|
781
|
-
type: "FeatureCollection",
|
|
782
|
-
features: world.features.filter((f2) => f2?.geometry && f2.geometry.type !== "Point")
|
|
783
|
-
};
|
|
784
|
-
}
|
|
785
|
-
return _worldBase;
|
|
786
|
-
}
|
|
787
|
-
function northAmerica(world) {
|
|
788
|
-
if (!_na) {
|
|
789
|
-
_na = {
|
|
790
|
-
type: "FeatureCollection",
|
|
791
|
-
features: world.features.filter((f2) => NA_ISO3.has(f2?.id) && f2?.geometry && f2.geometry.type !== "Point").map((f2) => clipFeatureToLat(f2, NA_LAT_MAX)).filter((f2) => f2 !== null)
|
|
792
|
-
};
|
|
793
|
-
}
|
|
794
|
-
return _na;
|
|
795
|
-
}
|
|
796
|
-
function fromAssets(key) {
|
|
797
|
-
const asset = geoAssetFor(key);
|
|
798
|
-
if (!asset) return void 0;
|
|
799
|
-
const geo = byAsset.get(asset);
|
|
800
|
-
if (!geo) return void 0;
|
|
801
|
-
if (key === "north-america") return northAmerica(geo);
|
|
802
|
-
if (key === "world") return worldBasemap(geo);
|
|
803
|
-
return geo;
|
|
804
|
-
}
|
|
805
|
-
async function loadGeo(geoKind) {
|
|
806
|
-
if (!geoKind) return void 0;
|
|
807
|
-
const key = geoKind.toLowerCase();
|
|
808
|
-
const already = geoFromCache(key);
|
|
809
|
-
if (already) return already;
|
|
810
|
-
const asset = geoAssetFor(key);
|
|
811
|
-
if (!asset) return void 0;
|
|
812
|
-
if (asset === "us-states") {
|
|
813
|
-
byAsset.set(asset, (await import("./geoUsStates.generated-JEFM6OHO.mjs")).US_STATES);
|
|
814
|
-
} else if (asset === "us-zip3") {
|
|
815
|
-
byAsset.set(asset, (await import("./geoUsZip3.generated-VSWL7D6F.mjs")).US_ZIP3);
|
|
816
|
-
} else {
|
|
817
|
-
byAsset.set(asset, (await import("./geoWorld110m.generated-TD2TA7S7.mjs")).WORLD_110M);
|
|
818
|
-
}
|
|
819
|
-
return fromAssets(key);
|
|
820
|
-
}
|
|
821
|
-
function geoFromCache(geoKind) {
|
|
822
|
-
if (!geoKind) return void 0;
|
|
823
|
-
const key = geoKind.toLowerCase();
|
|
824
|
-
return byKind.get(key) ?? fromAssets(key);
|
|
825
|
-
}
|
|
826
|
-
function registerGeo(geoKind, geo) {
|
|
827
|
-
if (geoKind && geo) byKind.set(geoKind.toLowerCase(), geo);
|
|
828
|
-
}
|
|
829
|
-
function registerGeoAsset(asset, geo) {
|
|
830
|
-
if (!asset || !geo) return;
|
|
831
|
-
byAsset.set(asset, geo);
|
|
832
|
-
if (asset === "world") {
|
|
833
|
-
_na = void 0;
|
|
834
|
-
_worldBase = void 0;
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
function clearGeoCache() {
|
|
838
|
-
byKind.clear();
|
|
839
|
-
byAsset.clear();
|
|
840
|
-
_na = void 0;
|
|
841
|
-
_worldBase = void 0;
|
|
842
|
-
}
|
|
843
|
-
|
|
844
1272
|
// src/payload.ts
|
|
845
1273
|
var ROW_IDX_COLUMN = "__rowIdx__";
|
|
846
1274
|
function resolvePointChannel(cols, rowObjs, point) {
|
|
@@ -854,7 +1282,7 @@ function resolvePointChannel(cols, rowObjs, point) {
|
|
|
854
1282
|
let labelCol;
|
|
855
1283
|
if (bind) {
|
|
856
1284
|
const dims = cols.filter((c) => !c.isMeasure).map((c) => c.name);
|
|
857
|
-
const res =
|
|
1285
|
+
const res = Rr(dims, rowObjs, bind, point?.mapKind, cols.map((c) => c.name));
|
|
858
1286
|
bind = res.bind;
|
|
859
1287
|
rolesBackfilled = res.backfilled;
|
|
860
1288
|
rolesRefused = res.refused;
|
|
@@ -864,7 +1292,7 @@ function resolvePointChannel(cols, rowObjs, point) {
|
|
|
864
1292
|
const hasPointBind = !!bind && !!(bind.city || bind.state || bind.zip || bind.country || bind.lat && bind.lon);
|
|
865
1293
|
if (hasPointBind) {
|
|
866
1294
|
const p = bind;
|
|
867
|
-
const built =
|
|
1295
|
+
const built = Dt(rowObjs.map((r) => ({
|
|
868
1296
|
lat: p.lat ? r[p.lat] : null,
|
|
869
1297
|
lon: p.lon ? r[p.lon] : null,
|
|
870
1298
|
city: p.city ? r[p.city] : null,
|
|
@@ -872,7 +1300,7 @@ function resolvePointChannel(cols, rowObjs, point) {
|
|
|
872
1300
|
zip: p.zip ? r[p.zip] : null,
|
|
873
1301
|
country: p.country ? r[p.country] : null,
|
|
874
1302
|
label: labelCol ? r[labelCol] : null
|
|
875
|
-
})), point?.mapKind);
|
|
1303
|
+
})), point?.mapKind, point?.region ?? null);
|
|
876
1304
|
pLat = built.lat;
|
|
877
1305
|
pLon = built.lon;
|
|
878
1306
|
pPrec = built.precisions;
|
|
@@ -922,7 +1350,29 @@ function buildRenderPayload(cols, rowObjs, geo, point, destination, opts) {
|
|
|
922
1350
|
let geoIso = null;
|
|
923
1351
|
let geoUnmatched;
|
|
924
1352
|
let geoUnmatchedDistinct;
|
|
925
|
-
|
|
1353
|
+
let geoProvince;
|
|
1354
|
+
if (geo && geo.column && geo.grain && geo.grain.toLowerCase() === "admin1" && geo.join) {
|
|
1355
|
+
const kind = (geo.kind || "").toLowerCase();
|
|
1356
|
+
const fb = geo.fallback ?? {};
|
|
1357
|
+
const isProvince = kind.startsWith("admin1-") || kind.startsWith("us-state-");
|
|
1358
|
+
const latCol = kind === "latlon" ? geo.column : fb.lat ?? null;
|
|
1359
|
+
const lonCol = fb.lon ?? (latCol ? longitudeBeside(cols.map((c) => c.name)) : null);
|
|
1360
|
+
const cityCol = kind.startsWith("city") ? geo.column : fb.city ?? null;
|
|
1361
|
+
const locate = geo.locate ?? void 0;
|
|
1362
|
+
const built = geo.join(rowObjs.map((r) => ({
|
|
1363
|
+
province: isProvince ? r[geo.column] : void 0,
|
|
1364
|
+
city: cityCol ? r[cityCol] : void 0,
|
|
1365
|
+
country: fb.country ? r[fb.country] : void 0,
|
|
1366
|
+
lat: latCol ? r[latCol] : void 0,
|
|
1367
|
+
lon: lonCol ? r[lonCol] : void 0
|
|
1368
|
+
})), { provinceKind: isProvince ? kind : null, deriveProvinces: geo.deriveProvinces, locate: locate ?? void 0 });
|
|
1369
|
+
geoIso = built.iso;
|
|
1370
|
+
geoUnmatched = { count: built.totalRows - built.matchedRows, examples: built.unmatched.slice(0, 8) };
|
|
1371
|
+
geoUnmatchedDistinct = built.unmatched.length;
|
|
1372
|
+
const sources = { province: 0, coordinates: 0, city: 0 };
|
|
1373
|
+
for (const s of built.source) if (s) sources[s]++;
|
|
1374
|
+
geoProvince = { sources, ambiguousRows: built.ambiguousRows, ambiguousExamples: built.ambiguousExamples, unplacedPoints: built.unplacedPoints };
|
|
1375
|
+
} else if (geo && geo.column && geo.kind && Yn(geo.kind)) {
|
|
926
1376
|
const built = Fn(rowObjs.map((r) => r[geo.column]), geo.kind);
|
|
927
1377
|
geoIso = built.iso;
|
|
928
1378
|
geoUnmatched = { count: built.totalRows - built.matchedRows, examples: built.unmatched.slice(0, 8) };
|
|
@@ -1003,9 +1453,14 @@ function buildRenderPayload(cols, rowObjs, geo, point, destination, opts) {
|
|
|
1003
1453
|
// the ordinary case adds no bytes.
|
|
1004
1454
|
...rolesRefused.length ? { geoPointRefused: rolesRefused } : {},
|
|
1005
1455
|
...utcDayColumns ? { dateCellsAreUtcDays: true, utcDayColumns } : {},
|
|
1006
|
-
...utcWallClockColumns ? { dateCellsAreUtcWallClock: true, utcWallClockColumns } : {}
|
|
1456
|
+
...utcWallClockColumns ? { dateCellsAreUtcWallClock: true, utcWallClockColumns } : {},
|
|
1457
|
+
...geoProvince ? { geoProvince } : {}
|
|
1007
1458
|
};
|
|
1008
1459
|
}
|
|
1460
|
+
function longitudeBeside(names) {
|
|
1461
|
+
const words = (n) => n.replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase().split(/[^a-zÀ-ɏ]+/);
|
|
1462
|
+
return names.find((n) => words(n).some((w) => w === "lon" || w === "lng" || w === "long" || w === "longitude")) ?? null;
|
|
1463
|
+
}
|
|
1009
1464
|
|
|
1010
1465
|
// src/codeComments.ts
|
|
1011
1466
|
function stripJsComments(code) {
|
|
@@ -1828,6 +2283,28 @@ function seenRight(el, right, stop) {
|
|
|
1828
2283
|
}
|
|
1829
2284
|
return right;
|
|
1830
2285
|
}
|
|
2286
|
+
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
2287
|
+
function overflowWindowOf(el) {
|
|
2288
|
+
const win = el.ownerDocument.defaultView;
|
|
2289
|
+
if (!win || el.namespaceURI === SVG_NS) return null;
|
|
2290
|
+
try {
|
|
2291
|
+
const o = win.getComputedStyle(el);
|
|
2292
|
+
const clips = (v) => !!v && v !== "visible";
|
|
2293
|
+
if (!o || !(clips(o.overflowX) || clips(o.overflowY) || clips(o.overflow))) return null;
|
|
2294
|
+
const r = el.getBoundingClientRect();
|
|
2295
|
+
if (!(r.width > 0 && r.height > 0)) return null;
|
|
2296
|
+
const h = el;
|
|
2297
|
+
const l = r.left + (h.clientLeft || 0), t = r.top + (h.clientTop || 0);
|
|
2298
|
+
const w = h.clientWidth > 0 ? h.clientWidth : r.width, ht = h.clientHeight > 0 ? h.clientHeight : r.height;
|
|
2299
|
+
return { l, t, r: l + w, b: t + ht };
|
|
2300
|
+
} catch {
|
|
2301
|
+
return null;
|
|
2302
|
+
}
|
|
2303
|
+
}
|
|
2304
|
+
var DOT = 8;
|
|
2305
|
+
var RING = 1.5;
|
|
2306
|
+
var DOT_HALF = DOT / 2 + RING;
|
|
2307
|
+
var DOT_IN = 8;
|
|
1831
2308
|
function createAnnotationLayer(container, onClick) {
|
|
1832
2309
|
let list = [];
|
|
1833
2310
|
let report = { shown: 0, notShown: 0 };
|
|
@@ -1846,7 +2323,22 @@ function createAnnotationLayer(container, onClick) {
|
|
|
1846
2323
|
if (win?.requestAnimationFrame) win.requestAnimationFrame(run);
|
|
1847
2324
|
else setTimeout(run, 16);
|
|
1848
2325
|
};
|
|
2326
|
+
const onInnerScroll = () => redrawSoon();
|
|
2327
|
+
const onOuterScroll = (e) => {
|
|
2328
|
+
const t = e.target;
|
|
2329
|
+
if (t && t.nodeType === 1 && t !== container && t.contains(container)) redrawSoon();
|
|
2330
|
+
};
|
|
2331
|
+
let listening = false;
|
|
1849
2332
|
const watch = (on) => {
|
|
2333
|
+
if (on && !listening) {
|
|
2334
|
+
container.addEventListener("scroll", onInnerScroll, { capture: true, passive: true });
|
|
2335
|
+
doc.addEventListener("scroll", onOuterScroll, { capture: true, passive: true });
|
|
2336
|
+
listening = true;
|
|
2337
|
+
} else if (!on && listening) {
|
|
2338
|
+
container.removeEventListener("scroll", onInnerScroll, { capture: true });
|
|
2339
|
+
doc.removeEventListener("scroll", onOuterScroll, { capture: true });
|
|
2340
|
+
listening = false;
|
|
2341
|
+
}
|
|
1850
2342
|
const MO = win?.MutationObserver;
|
|
1851
2343
|
if (on && !observer && MO) {
|
|
1852
2344
|
observer = new MO((records) => {
|
|
@@ -1885,19 +2377,28 @@ function createAnnotationLayer(container, onClick) {
|
|
|
1885
2377
|
const origin = container.getBoundingClientRect();
|
|
1886
2378
|
const open = origin.width > 0 && origin.height > 0 ? box(origin) : FREE;
|
|
1887
2379
|
const clipOf = /* @__PURE__ */ new Map();
|
|
2380
|
+
const windowOf = (el) => {
|
|
2381
|
+
if (!clipOf.has(el)) {
|
|
2382
|
+
if (el.namespaceURI === SVG_NS) {
|
|
2383
|
+
const w = clipWindowOf(el);
|
|
2384
|
+
clipOf.set(el, w && box(w));
|
|
2385
|
+
} else clipOf.set(el, overflowWindowOf(el));
|
|
2386
|
+
}
|
|
2387
|
+
return clipOf.get(el);
|
|
2388
|
+
};
|
|
2389
|
+
let inView = open;
|
|
2390
|
+
if (open !== FREE) for (let el = container.parentElement; inView && el && el !== doc.documentElement && el !== doc.body; el = el.parentElement) {
|
|
2391
|
+
const w = windowOf(el);
|
|
2392
|
+
if (w) inView = cut(inView, w);
|
|
2393
|
+
}
|
|
1888
2394
|
const viewOf = (m) => {
|
|
1889
|
-
let v =
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
}
|
|
1895
|
-
for (let el = m.parentElement; v && el && el !== svg && el !== container; el = el.parentElement) {
|
|
1896
|
-
if (!clipOf.has(el)) {
|
|
1897
|
-
const w2 = clipWindowOf(el);
|
|
1898
|
-
clipOf.set(el, w2 && box(w2));
|
|
2395
|
+
let v = inView;
|
|
2396
|
+
for (let el = m.parentElement; v && el && el !== container; el = el.parentElement) {
|
|
2397
|
+
if (el.namespaceURI === SVG_NS && el.localName === "svg") {
|
|
2398
|
+
const s = el.getBoundingClientRect();
|
|
2399
|
+
if (s.width > 0 && s.height > 0) v = cut(v, box(s));
|
|
1899
2400
|
}
|
|
1900
|
-
const w =
|
|
2401
|
+
const w = windowOf(el);
|
|
1901
2402
|
if (w) v = cut(v, w);
|
|
1902
2403
|
}
|
|
1903
2404
|
return v;
|
|
@@ -1959,6 +2460,30 @@ function createAnnotationLayer(container, onClick) {
|
|
|
1959
2460
|
placed.push(at(pick.x, pick.y));
|
|
1960
2461
|
return [pick.x, pick.y];
|
|
1961
2462
|
};
|
|
2463
|
+
const wantsDot = (m) => {
|
|
2464
|
+
const d = m?.closest(`[${NOTE_STYLE_ATTR}]`);
|
|
2465
|
+
return !!d && container.contains(d) && text(d.getAttribute(NOTE_STYLE_ATTR)).toLowerCase() === "dot";
|
|
2466
|
+
};
|
|
2467
|
+
const dotSpot = (v, whole) => {
|
|
2468
|
+
const fits = (b) => b.r - b.l >= 2 * DOT_IN && b.b - b.t >= 2 * DOT_IN;
|
|
2469
|
+
let x, y;
|
|
2470
|
+
if (!fits(whole)) {
|
|
2471
|
+
x = v.r;
|
|
2472
|
+
y = v.t;
|
|
2473
|
+
} else if (fits(v)) {
|
|
2474
|
+
x = v.r - DOT_IN;
|
|
2475
|
+
y = v.t + DOT_IN;
|
|
2476
|
+
} else return null;
|
|
2477
|
+
const e = Math.ceil(DOT_HALF);
|
|
2478
|
+
x = clampX(x, e);
|
|
2479
|
+
y = clampY(y, e);
|
|
2480
|
+
const g = { l: x - DOT_HALF, t: y - DOT_HALF, r: x + DOT_HALF, b: y + DOT_HALF };
|
|
2481
|
+
if (controls.some((c) => hits(g, c))) return null;
|
|
2482
|
+
placed.push(g);
|
|
2483
|
+
return [x, y];
|
|
2484
|
+
};
|
|
2485
|
+
const offX = -origin.left - (container.clientLeft || 0) + (container.scrollLeft || 0);
|
|
2486
|
+
const offY = -origin.top - (container.clientTop || 0) + (container.scrollTop || 0);
|
|
1962
2487
|
let shown = 0;
|
|
1963
2488
|
for (const a of list) {
|
|
1964
2489
|
const pairs = (a.where ? Object.entries(a.where) : a.column != null ? [[a.column, a.value]] : []).map(([c, v]) => [names.indexOf(c), text(v)]);
|
|
@@ -1968,7 +2493,7 @@ function createAnnotationLayer(container, onClick) {
|
|
|
1968
2493
|
if (pairs.every(([ci, v]) => text(row?.[ci]) === v)) for (const m of marksByRow.get(r) ?? []) hits2.add(m);
|
|
1969
2494
|
});
|
|
1970
2495
|
if (!hits2.size) continue;
|
|
1971
|
-
let best = null, bestMark = null, laidOut = false;
|
|
2496
|
+
let best = null, bestWhole = null, bestMark = null, laidOut = false;
|
|
1972
2497
|
for (const m of hits2) {
|
|
1973
2498
|
const b = m.getBoundingClientRect();
|
|
1974
2499
|
if (!(b.width > 0 && b.height > 0)) continue;
|
|
@@ -1976,33 +2501,43 @@ function createAnnotationLayer(container, onClick) {
|
|
|
1976
2501
|
const v = cut(box(b), viewOf(m));
|
|
1977
2502
|
if (v && (!best || area(v) > area(best))) {
|
|
1978
2503
|
best = v;
|
|
2504
|
+
bestWhole = box(b);
|
|
1979
2505
|
bestMark = m;
|
|
1980
2506
|
}
|
|
1981
2507
|
}
|
|
1982
|
-
const
|
|
2508
|
+
const dot = wantsDot(bestMark ?? hits2.values().next().value ?? null);
|
|
2509
|
+
const pt = !best ? null : dot ? dotSpot(best, bestWhole) : clear(best, (a.label ?? "\u2022").length, bestMark);
|
|
1983
2510
|
if (laidOut && !pt) continue;
|
|
1984
2511
|
shown++;
|
|
1985
2512
|
const badge = doc.createElement("div");
|
|
1986
2513
|
badge.className = ANNOTATION_CLASS;
|
|
1987
|
-
badge.textContent = a.label ?? "\u2022";
|
|
1988
|
-
if (a.title) badge.setAttribute("title", a.title);
|
|
1989
2514
|
badge.setAttribute("role", "button");
|
|
1990
|
-
|
|
2515
|
+
if (dot) {
|
|
2516
|
+
const label = text(a.label), title = text(a.title);
|
|
2517
|
+
badge.setAttribute("title", title ? label ? `(${label}) ${title}` : title : `Note on ${want}${label ? `: ${label}` : ""}`);
|
|
2518
|
+
badge.setAttribute("aria-label", `Note on ${want}${label ? `: ${label}` : ""}${title ? `. ${title}` : ""}`);
|
|
2519
|
+
} else {
|
|
2520
|
+
badge.textContent = a.label ?? "\u2022";
|
|
2521
|
+
if (a.title) badge.setAttribute("title", a.title);
|
|
2522
|
+
badge.setAttribute("aria-label", a.title ? `Note: ${a.title}` : `Note on ${want}`);
|
|
2523
|
+
}
|
|
1991
2524
|
Object.assign(badge.style, {
|
|
1992
2525
|
position: "absolute",
|
|
1993
|
-
left: `${Math.round(pt ? pt[0]
|
|
1994
|
-
top: `${Math.round(pt ? pt[1]
|
|
2526
|
+
left: `${Math.round(pt ? pt[0] + offX : 0)}px`,
|
|
2527
|
+
top: `${Math.round(pt ? pt[1] + offY : 0)}px`,
|
|
1995
2528
|
transform: "translate(-50%, -50%)",
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2529
|
+
...dot ? { width: `${DOT}px`, height: `${DOT}px`, boxSizing: "border-box", borderRadius: "50%" } : {
|
|
2530
|
+
minWidth: "16px",
|
|
2531
|
+
height: "16px",
|
|
2532
|
+
padding: "0 4px",
|
|
2533
|
+
boxSizing: "border-box",
|
|
2534
|
+
borderRadius: "8px",
|
|
2535
|
+
font: "600 10px/16px system-ui, sans-serif",
|
|
2536
|
+
textAlign: "center",
|
|
2537
|
+
color: theme.bg || "#ffffff"
|
|
2538
|
+
},
|
|
2004
2539
|
background: theme.accent || theme.fg || "#0f6cbd",
|
|
2005
|
-
boxShadow: `0 0 0
|
|
2540
|
+
boxShadow: `0 0 0 ${RING}px ${theme.bg || "#ffffff"}`,
|
|
2006
2541
|
cursor: onClick ? "pointer" : "default",
|
|
2007
2542
|
// Never pointer-events (a host failsafe turns it back on); visibility hides a badge whose mark
|
|
2008
2543
|
// has no box yet.
|
|
@@ -3240,13 +3775,21 @@ export {
|
|
|
3240
3775
|
autoRampMinStep,
|
|
3241
3776
|
autoRampCanvas,
|
|
3242
3777
|
resolveAutoColorScale,
|
|
3778
|
+
EXPORT_FORMATS,
|
|
3779
|
+
XLSX_MIME,
|
|
3780
|
+
CSV_MIME,
|
|
3781
|
+
excelSerial,
|
|
3782
|
+
excelNumberFormat,
|
|
3783
|
+
tableToCsv,
|
|
3784
|
+
sheetName,
|
|
3785
|
+
exportFileName,
|
|
3786
|
+
tableToXlsx,
|
|
3787
|
+
buildExportFile,
|
|
3788
|
+
bytesToBase64,
|
|
3789
|
+
exportFormatsFor,
|
|
3790
|
+
exportTableService,
|
|
3791
|
+
browserSaveFile,
|
|
3243
3792
|
resolveOptions,
|
|
3244
|
-
geoAssetFor,
|
|
3245
|
-
loadGeo,
|
|
3246
|
-
geoFromCache,
|
|
3247
|
-
registerGeo,
|
|
3248
|
-
registerGeoAsset,
|
|
3249
|
-
clearGeoCache,
|
|
3250
3793
|
buildRenderPayload,
|
|
3251
3794
|
stripJsComments,
|
|
3252
3795
|
censusMarks,
|