@bicharts/chart-host 0.6.108 → 0.6.110
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-ABGDJ3NJ.mjs → chunk-3JCWTEEH.mjs} +11 -1
- package/dist/{chunk-MO2GR56D.mjs → chunk-5VQ3IQF7.mjs} +426 -20
- package/dist/{chunk-OSREEGBN.mjs → chunk-7XT5OJ6M.mjs} +1 -1
- package/dist/{chunk-UKXGOQMS.mjs → chunk-AEO5SFEQ.mjs} +1 -1
- package/dist/{chunk-JU2PQ22J.mjs → chunk-FT75ONSB.mjs} +17 -1
- package/dist/{chunk-ESBH2L6E.mjs → chunk-IL5M7K6Z.mjs} +2 -2
- package/dist/{chunk-LGWTV5PB.mjs → chunk-KGVNZR23.mjs} +1 -1
- package/dist/{chunk-PHUUFCJY.mjs → chunk-KY4FI2HA.mjs} +3 -1
- package/dist/{chunk-SYUJ4TPX.mjs → chunk-NJWR3DFK.mjs} +133 -132
- package/dist/{chunk-FCLPMC6Q.mjs → chunk-PELRAFYZ.mjs} +1 -1
- package/dist/{chunk-MU4BWWO6.mjs → chunk-Q43WOKSV.mjs} +1 -1
- package/dist/{chunk-5WTQN5DL.mjs → chunk-S564YXNE.mjs} +1 -1
- package/dist/geo-world.mjs +1 -1
- package/dist/geo.mjs +1 -1
- package/dist/{geoWorld110m.generated-TD2TA7S7.mjs → geoWorld110m-3PRV3V4G.mjs} +1 -1
- package/dist/index.mjs +32 -12
- package/dist/legend-fit.mjs +3 -3
- package/dist/page.mjs +6 -4
- package/dist/provinces.mjs +2 -2
- package/dist/react.mjs +38 -12
- package/dist/testing.mjs +1 -1
- package/dist/types/annotations.d.ts +3 -1
- package/dist/types/contract.d.ts +19 -1
- package/dist/types/defaults.d.ts +2 -1
- package/dist/types/filterScope.d.ts +8 -0
- package/dist/types/focusKeep.d.ts +12 -0
- package/dist/types/geo-world.d.ts +1 -1
- package/dist/types/geoWorld110m.d.ts +1 -0
- package/dist/types/host.d.ts +10 -0
- package/dist/types/index.d.ts +4 -2
- package/dist/types/keyboardMarks.d.ts +44 -0
- package/dist/types/page.d.ts +1 -1
- package/dist/types/react.d.ts +10 -1
- package/dist/zoom-memory.mjs +1 -1
- package/package.json +1 -1
|
@@ -4,11 +4,11 @@ import {
|
|
|
4
4
|
claimParkedLasso,
|
|
5
5
|
installLasso,
|
|
6
6
|
lassoEffect
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-IL5M7K6Z.mjs";
|
|
8
8
|
import {
|
|
9
9
|
censusHitBands,
|
|
10
10
|
ensureCrossfilterHitTargets
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-AEO5SFEQ.mjs";
|
|
12
12
|
import {
|
|
13
13
|
clearPress,
|
|
14
14
|
clearSelectionGlyphs,
|
|
@@ -25,25 +25,25 @@ import {
|
|
|
25
25
|
selectionRuleOf,
|
|
26
26
|
trackPress,
|
|
27
27
|
validRowSet
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-KGVNZR23.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-7XT5OJ6M.mjs";
|
|
36
36
|
import {
|
|
37
37
|
geoFromCache
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-S564YXNE.mjs";
|
|
39
39
|
import {
|
|
40
|
-
Dt,
|
|
41
40
|
Fn,
|
|
42
41
|
Q,
|
|
43
42
|
Rr,
|
|
44
43
|
Yn,
|
|
45
|
-
tt
|
|
46
|
-
|
|
44
|
+
tt,
|
|
45
|
+
xt
|
|
46
|
+
} from "./chunk-NJWR3DFK.mjs";
|
|
47
47
|
import {
|
|
48
48
|
ACTIVE_TICK_CLASS,
|
|
49
49
|
ANIM_LOOP_DELAY_DEFAULT,
|
|
@@ -75,6 +75,7 @@ import {
|
|
|
75
75
|
HOST_CONTRACT_VERSION,
|
|
76
76
|
LEGEND_MARK_CLASS,
|
|
77
77
|
LIFT_SELECTED_CLASS,
|
|
78
|
+
MARKS_INERT_CLASS,
|
|
78
79
|
MARK_CLASS,
|
|
79
80
|
MARK_SELECTED_CLASS,
|
|
80
81
|
MAX_MAP_POINTS_DEFAULT,
|
|
@@ -87,7 +88,7 @@ import {
|
|
|
87
88
|
XFILTER_REFRESH_EVENT,
|
|
88
89
|
chartOwnsTimeline,
|
|
89
90
|
periodTickSuppressesFeedback
|
|
90
|
-
} from "./chunk-
|
|
91
|
+
} from "./chunk-KY4FI2HA.mjs";
|
|
91
92
|
|
|
92
93
|
// src/labelContrast.ts
|
|
93
94
|
function parseRGBA(c) {
|
|
@@ -1070,6 +1071,21 @@ function cleanHostSelection(v) {
|
|
|
1070
1071
|
}
|
|
1071
1072
|
return out;
|
|
1072
1073
|
}
|
|
1074
|
+
function cleanFilterScope(v) {
|
|
1075
|
+
if (!v || typeof v !== "object" || !Array.isArray(v.values)) return void 0;
|
|
1076
|
+
const values = [];
|
|
1077
|
+
for (const x of v.values) {
|
|
1078
|
+
if (typeof x !== "string" && typeof x !== "number" && typeof x !== "boolean" && typeof x !== "bigint") continue;
|
|
1079
|
+
const s = String(x).trim();
|
|
1080
|
+
if (s && !values.includes(s)) values.push(s);
|
|
1081
|
+
}
|
|
1082
|
+
if (!values.length) return void 0;
|
|
1083
|
+
const field = typeof v.field === "string" ? v.field.trim() : "";
|
|
1084
|
+
const out = { field, values };
|
|
1085
|
+
const label = typeof v.label === "string" ? v.label.trim() : "";
|
|
1086
|
+
if (label) out.label = label;
|
|
1087
|
+
return out;
|
|
1088
|
+
}
|
|
1073
1089
|
var clamp = (n, lo, hi) => Math.max(lo, Math.min(hi, n));
|
|
1074
1090
|
var numberOr = (raw, dflt) => {
|
|
1075
1091
|
const n = raw == null || raw === "" ? NaN : Number(raw);
|
|
@@ -1104,6 +1120,8 @@ function resolveOptions(p) {
|
|
|
1104
1120
|
rowsFilteredOut: p.rowsFilteredOut,
|
|
1105
1121
|
// A host FACT about its selection (contract 1.21.0), cleaned, never invented: absent stays absent.
|
|
1106
1122
|
hostSelection: cleanHostSelection(p.hostSelection),
|
|
1123
|
+
// A host FACT about a filter applied before the rows arrived (contract 1.23.0), cleaned, never invented.
|
|
1124
|
+
filterScope: cleanFilterScope(p.filterScope),
|
|
1107
1125
|
// Host services (contract 1.18.0): a FUNCTION or nothing, so a junk value never reaches a chart as something
|
|
1108
1126
|
// it would try to call. Passed through untouched otherwise: the host owns what opening or copying means.
|
|
1109
1127
|
openUrl: typeof p.openUrl === "function" ? p.openUrl : void 0,
|
|
@@ -1159,6 +1177,8 @@ function resolveOptions(p) {
|
|
|
1159
1177
|
})(),
|
|
1160
1178
|
// A host FACT from the generate answer, true only for a literal true: silence never suppresses anything.
|
|
1161
1179
|
suppressSelectionGlyph: p.suppressSelectionGlyph === true ? true : void 0,
|
|
1180
|
+
// A host FACT (1.22.0): the chart works from the keyboard. True only for a literal true, like the one above.
|
|
1181
|
+
keyboardMarks: p.keyboardMarks === true ? true : void 0,
|
|
1162
1182
|
onSelect: p.onSelect,
|
|
1163
1183
|
// Control gestures (1.10.0). Passed straight through like onSelect: the host owns what a gesture MEANS,
|
|
1164
1184
|
// and a host that supplies nothing leaves every control behaving exactly as before.
|
|
@@ -1309,7 +1329,7 @@ function resolvePointChannel(cols, rowObjs, point) {
|
|
|
1309
1329
|
const hasPointBind = !!bind && !!(bind.city || bind.state || bind.zip || bind.country || bind.lat && bind.lon);
|
|
1310
1330
|
if (hasPointBind) {
|
|
1311
1331
|
const p = bind;
|
|
1312
|
-
const built =
|
|
1332
|
+
const built = xt(rowObjs.map((r) => ({
|
|
1313
1333
|
lat: p.lat ? r[p.lat] : null,
|
|
1314
1334
|
lon: p.lon ? r[p.lon] : null,
|
|
1315
1335
|
city: p.city ? r[p.city] : null,
|
|
@@ -2322,7 +2342,7 @@ var DOT = 8;
|
|
|
2322
2342
|
var RING = 1.5;
|
|
2323
2343
|
var DOT_HALF = DOT / 2 + RING;
|
|
2324
2344
|
var DOT_IN = 8;
|
|
2325
|
-
function createAnnotationLayer(container, onClick) {
|
|
2345
|
+
function createAnnotationLayer(container, onClick, opts) {
|
|
2326
2346
|
let list = [];
|
|
2327
2347
|
let report = { shown: 0, notShown: 0 };
|
|
2328
2348
|
let last = null;
|
|
@@ -2446,7 +2466,7 @@ function createAnnotationLayer(container, onClick) {
|
|
|
2446
2466
|
const after = own.filter((t) => t.b.l >= run.r && t.b.b > run.t && t.b.t < run.b).map((t) => t.b.l);
|
|
2447
2467
|
return { r: Math.min(run.r, seen), y: (run.t + run.b) / 2, next: after.length ? Math.min(...after) : v.r };
|
|
2448
2468
|
};
|
|
2449
|
-
const clear = (v, len, mark) => {
|
|
2469
|
+
const clear = (v, len, mark, whole = v) => {
|
|
2450
2470
|
const hw = Math.max(16, len * 6 + 8) / 2, hh = 8, g = 2;
|
|
2451
2471
|
const cx = (v.l + v.r) / 2, cy = (v.t + v.b) / 2;
|
|
2452
2472
|
const at = (x, y) => ({ l: x - hw, t: y - hh, r: x + hw, b: y + hh });
|
|
@@ -2459,6 +2479,7 @@ function createAnnotationLayer(container, onClick) {
|
|
|
2459
2479
|
const tries = [];
|
|
2460
2480
|
const add = (x, y, px = x, py = y) => tries.push({ x: clampX(x, hw), y: clampY(y, hh), px, py });
|
|
2461
2481
|
const label = rowLabel(v, mark);
|
|
2482
|
+
if (!label && whole !== v && rowLabel(whole, mark)) return null;
|
|
2462
2483
|
if (label) {
|
|
2463
2484
|
const x = label.r + g + hw;
|
|
2464
2485
|
if (x + hw <= label.next - g || label.next >= v.r) add(x, label.y, Math.min(x, v.r - 1), label.y);
|
|
@@ -2523,7 +2544,7 @@ function createAnnotationLayer(container, onClick) {
|
|
|
2523
2544
|
}
|
|
2524
2545
|
}
|
|
2525
2546
|
const dot = wantsDot(bestMark ?? hits2.values().next().value ?? null);
|
|
2526
|
-
const pt = !best ? null : dot ? dotSpot(best, bestWhole) : clear(best, (a.label ?? "\u2022").length, bestMark);
|
|
2547
|
+
const pt = !best ? null : dot ? dotSpot(best, bestWhole) : clear(best, (a.label ?? "\u2022").length, bestMark, bestWhole ?? best);
|
|
2527
2548
|
if (laidOut && !pt) continue;
|
|
2528
2549
|
shown++;
|
|
2529
2550
|
const badge = doc.createElement("div");
|
|
@@ -2564,6 +2585,15 @@ function createAnnotationLayer(container, onClick) {
|
|
|
2564
2585
|
e.stopPropagation();
|
|
2565
2586
|
onClick?.(a);
|
|
2566
2587
|
});
|
|
2588
|
+
if (opts?.keyboard?.()) {
|
|
2589
|
+
badge.setAttribute("tabindex", "0");
|
|
2590
|
+
badge.addEventListener("keydown", (e) => {
|
|
2591
|
+
if (e.key !== "Enter" && e.key !== " " && e.key !== "Spacebar") return;
|
|
2592
|
+
e.preventDefault();
|
|
2593
|
+
e.stopPropagation();
|
|
2594
|
+
onClick?.(a);
|
|
2595
|
+
});
|
|
2596
|
+
}
|
|
2567
2597
|
layer.appendChild(badge);
|
|
2568
2598
|
}
|
|
2569
2599
|
report = { shown, notShown: list.length - shown };
|
|
@@ -2590,6 +2620,235 @@ function createAnnotationLayer(container, onClick) {
|
|
|
2590
2620
|
};
|
|
2591
2621
|
}
|
|
2592
2622
|
|
|
2623
|
+
// src/focusKeep.ts
|
|
2624
|
+
function signatureOf(el) {
|
|
2625
|
+
const a = (n) => el.getAttribute(n) ?? "";
|
|
2626
|
+
const cls = Array.from(el.classList ?? []).filter((c) => !/^lch-|^bic-/.test(c)).sort().join(" ");
|
|
2627
|
+
return [el.localName, a("type"), cls, a("name"), a("placeholder"), a("aria-label"), a("role")].join("|");
|
|
2628
|
+
}
|
|
2629
|
+
function alike(container, sig) {
|
|
2630
|
+
const tag = sig.split("|", 1)[0];
|
|
2631
|
+
if (!tag) return [];
|
|
2632
|
+
return Array.from(container.querySelectorAll(tag)).filter((e) => signatureOf(e) === sig);
|
|
2633
|
+
}
|
|
2634
|
+
function rememberFocus(container) {
|
|
2635
|
+
try {
|
|
2636
|
+
const active = container.ownerDocument?.activeElement;
|
|
2637
|
+
if (!active || active === container || !container.contains(active)) return null;
|
|
2638
|
+
const sig = signatureOf(active);
|
|
2639
|
+
const nth = alike(container, sig).indexOf(active);
|
|
2640
|
+
const t = active;
|
|
2641
|
+
let start = null, end = null, dir = null;
|
|
2642
|
+
try {
|
|
2643
|
+
if (typeof t.selectionStart === "number") {
|
|
2644
|
+
start = t.selectionStart;
|
|
2645
|
+
end = t.selectionEnd;
|
|
2646
|
+
dir = t.selectionDirection ?? null;
|
|
2647
|
+
}
|
|
2648
|
+
} catch {
|
|
2649
|
+
}
|
|
2650
|
+
return { sig, nth: Math.max(0, nth), start, end, dir };
|
|
2651
|
+
} catch {
|
|
2652
|
+
return null;
|
|
2653
|
+
}
|
|
2654
|
+
}
|
|
2655
|
+
function restoreFocus(container, memory) {
|
|
2656
|
+
if (!memory) return false;
|
|
2657
|
+
try {
|
|
2658
|
+
const active = container.ownerDocument?.activeElement;
|
|
2659
|
+
if (active && active !== container && container.contains(active)) return false;
|
|
2660
|
+
const list = alike(container, memory.sig);
|
|
2661
|
+
const el = list[memory.nth] ?? (list.length === 1 ? list[0] : null);
|
|
2662
|
+
if (!el || typeof el.focus !== "function") return false;
|
|
2663
|
+
el.focus({ preventScroll: true });
|
|
2664
|
+
const t = el;
|
|
2665
|
+
if (memory.start != null && typeof t.setSelectionRange === "function") {
|
|
2666
|
+
const len = typeof t.value === "string" ? t.value.length : 0;
|
|
2667
|
+
try {
|
|
2668
|
+
t.setSelectionRange(Math.min(memory.start, len), Math.min(memory.end ?? memory.start, len), memory.dir ?? void 0);
|
|
2669
|
+
} catch {
|
|
2670
|
+
}
|
|
2671
|
+
}
|
|
2672
|
+
return container.ownerDocument?.activeElement === el;
|
|
2673
|
+
} catch {
|
|
2674
|
+
return false;
|
|
2675
|
+
}
|
|
2676
|
+
}
|
|
2677
|
+
|
|
2678
|
+
// src/keyboardMarks.ts
|
|
2679
|
+
var KEYBOARD_STAMP = "// bic:keyboard-marks";
|
|
2680
|
+
var STAMP_RE = /^[ \t]*\/\/[ \t]*bic:keyboard-marks\b/;
|
|
2681
|
+
var STAMP_HEAD_LINES = 12;
|
|
2682
|
+
function codeHasKeyboardStamp(code) {
|
|
2683
|
+
if (typeof code !== "string" || !code) return false;
|
|
2684
|
+
let start = 0;
|
|
2685
|
+
for (let n = 0; n < STAMP_HEAD_LINES && start <= code.length; n++) {
|
|
2686
|
+
const end = code.indexOf("\n", start);
|
|
2687
|
+
const line = code.slice(start, end < 0 ? code.length : end);
|
|
2688
|
+
if (STAMP_RE.test(line)) return true;
|
|
2689
|
+
if (end < 0) break;
|
|
2690
|
+
start = end + 1;
|
|
2691
|
+
}
|
|
2692
|
+
return false;
|
|
2693
|
+
}
|
|
2694
|
+
var KEYBOARD_CLASS = "lch-keyboard";
|
|
2695
|
+
var WIRED_ATTR = "data-lch-kb";
|
|
2696
|
+
var isDate = (v) => Object.prototype.toString.call(v) === "[object Date]";
|
|
2697
|
+
function rowNameOf(columns, row, culture) {
|
|
2698
|
+
if (!row) return null;
|
|
2699
|
+
const parts = [];
|
|
2700
|
+
(columns || []).forEach((c, i) => {
|
|
2701
|
+
const name = typeof c === "string" ? c : c?.name;
|
|
2702
|
+
const v = row[i];
|
|
2703
|
+
if (parts.length >= 4 || v == null || v === "" || typeof name === "string" && name.startsWith("__")) return;
|
|
2704
|
+
if (isDate(v)) {
|
|
2705
|
+
if (!Number.isNaN(v.getTime())) parts.push(v.toLocaleDateString(culture || void 0));
|
|
2706
|
+
return;
|
|
2707
|
+
}
|
|
2708
|
+
parts.push(typeof v === "number" ? v.toLocaleString(culture || void 0, { maximumFractionDigits: 2 }) : String(v));
|
|
2709
|
+
});
|
|
2710
|
+
return parts.length ? parts.join(", ") : null;
|
|
2711
|
+
}
|
|
2712
|
+
var isClearChord = (e) => !!e.ctrlKey && !!e.shiftKey && (e.key === "C" || e.key === "c");
|
|
2713
|
+
var NATIVE = /* @__PURE__ */ new Set(["input", "select", "textarea", "button", "a"]);
|
|
2714
|
+
var isNative = (el) => NATIVE.has((el.localName || "").toLowerCase()) || el.isContentEditable === true;
|
|
2715
|
+
var OWN_FOCUS = "input, select, textarea, button, a[href], [role=slider]";
|
|
2716
|
+
function isLeafControl(el, pressSelector) {
|
|
2717
|
+
try {
|
|
2718
|
+
return !el.querySelector(pressSelector) && !el.querySelector(OWN_FOCUS);
|
|
2719
|
+
} catch {
|
|
2720
|
+
return true;
|
|
2721
|
+
}
|
|
2722
|
+
}
|
|
2723
|
+
function installKeyboard(env) {
|
|
2724
|
+
const { container } = env;
|
|
2725
|
+
let rovingKey = null;
|
|
2726
|
+
let destroyed = false;
|
|
2727
|
+
const marksNow = () => {
|
|
2728
|
+
if (env.inert()) return [];
|
|
2729
|
+
return Array.from(container.querySelectorAll(env.markSelector)).filter((m) => !m.closest(env.skipSelector) && (m.getAttribute("data-row-idx") ?? "") !== "");
|
|
2730
|
+
};
|
|
2731
|
+
const wired = (el) => el.hasAttribute(WIRED_ATTR);
|
|
2732
|
+
const wire = (el, tabindex, role) => {
|
|
2733
|
+
if (el.hasAttribute("tabindex") && !wired(el)) return false;
|
|
2734
|
+
el.setAttribute(WIRED_ATTR, "");
|
|
2735
|
+
el.setAttribute("tabindex", tabindex);
|
|
2736
|
+
if (!el.hasAttribute("role")) el.setAttribute("role", role);
|
|
2737
|
+
return true;
|
|
2738
|
+
};
|
|
2739
|
+
const setRoving = (list, to) => {
|
|
2740
|
+
for (const m of list) if (wired(m)) m.setAttribute("tabindex", m === to ? "0" : "-1");
|
|
2741
|
+
rovingKey = env.keyOf(to);
|
|
2742
|
+
};
|
|
2743
|
+
const refresh = () => {
|
|
2744
|
+
if (destroyed) return;
|
|
2745
|
+
try {
|
|
2746
|
+
container.classList?.add(KEYBOARD_CLASS);
|
|
2747
|
+
const list = marksNow();
|
|
2748
|
+
for (const m of list) {
|
|
2749
|
+
if (!wire(m, "-1", "button")) continue;
|
|
2750
|
+
m.setAttribute("aria-pressed", env.isSelected(m) ? "true" : "false");
|
|
2751
|
+
if (!m.hasAttribute("aria-label") && !m.querySelector(":scope > title")) {
|
|
2752
|
+
const name = env.labelOf(m);
|
|
2753
|
+
if (name) m.setAttribute("aria-label", name);
|
|
2754
|
+
}
|
|
2755
|
+
}
|
|
2756
|
+
if (!list.length) {
|
|
2757
|
+
for (const m of Array.from(container.querySelectorAll(`[${WIRED_ATTR}]`)))
|
|
2758
|
+
if (m.matches(env.markSelector)) {
|
|
2759
|
+
m.removeAttribute("tabindex");
|
|
2760
|
+
m.removeAttribute(WIRED_ATTR);
|
|
2761
|
+
}
|
|
2762
|
+
}
|
|
2763
|
+
const own = list.filter(wired);
|
|
2764
|
+
if (own.length) {
|
|
2765
|
+
const keep = own.find((m) => env.keyOf(m) === rovingKey) ?? own.find((m) => env.isSelected(m)) ?? own[0];
|
|
2766
|
+
setRoving(own, keep);
|
|
2767
|
+
}
|
|
2768
|
+
for (const c of Array.from(container.querySelectorAll(env.pressSelector))) {
|
|
2769
|
+
if (isNative(c) || !isLeafControl(c, env.pressSelector)) continue;
|
|
2770
|
+
wire(c, "0", "button");
|
|
2771
|
+
}
|
|
2772
|
+
} catch {
|
|
2773
|
+
}
|
|
2774
|
+
};
|
|
2775
|
+
const onKey = (e) => {
|
|
2776
|
+
if (destroyed || e.defaultPrevented) return;
|
|
2777
|
+
const t = e.target;
|
|
2778
|
+
if (!t || !container.contains(t)) return;
|
|
2779
|
+
const k = e.key;
|
|
2780
|
+
if (isClearChord(e)) {
|
|
2781
|
+
e.preventDefault();
|
|
2782
|
+
env.clear();
|
|
2783
|
+
return;
|
|
2784
|
+
}
|
|
2785
|
+
const press = t.closest?.(env.pressSelector);
|
|
2786
|
+
if (press && wired(press) && container.contains(press)) {
|
|
2787
|
+
if (k === "Enter" || k === " " || k === "Spacebar") {
|
|
2788
|
+
e.preventDefault();
|
|
2789
|
+
const ME = container.ownerDocument.defaultView?.MouseEvent ?? MouseEvent;
|
|
2790
|
+
press.dispatchEvent(new ME("click", { bubbles: true, cancelable: true }));
|
|
2791
|
+
} else if (k === "Escape" && env.escapeClears !== false) env.clear();
|
|
2792
|
+
return;
|
|
2793
|
+
}
|
|
2794
|
+
const mark = t.closest?.(env.markSelector);
|
|
2795
|
+
if (!mark || !wired(mark) || !container.contains(mark)) return;
|
|
2796
|
+
const list = marksNow().filter(wired);
|
|
2797
|
+
const at = list.indexOf(mark);
|
|
2798
|
+
const go = (i) => {
|
|
2799
|
+
const to = list[Math.max(0, Math.min(list.length - 1, i))];
|
|
2800
|
+
if (!to) return;
|
|
2801
|
+
setRoving(list, to);
|
|
2802
|
+
try {
|
|
2803
|
+
to.focus({ preventScroll: false });
|
|
2804
|
+
} catch {
|
|
2805
|
+
}
|
|
2806
|
+
};
|
|
2807
|
+
switch (k) {
|
|
2808
|
+
case "ArrowRight":
|
|
2809
|
+
case "ArrowDown":
|
|
2810
|
+
e.preventDefault();
|
|
2811
|
+
go(at + 1);
|
|
2812
|
+
break;
|
|
2813
|
+
case "ArrowLeft":
|
|
2814
|
+
case "ArrowUp":
|
|
2815
|
+
e.preventDefault();
|
|
2816
|
+
go(at - 1);
|
|
2817
|
+
break;
|
|
2818
|
+
case "Home":
|
|
2819
|
+
e.preventDefault();
|
|
2820
|
+
go(0);
|
|
2821
|
+
break;
|
|
2822
|
+
case "End":
|
|
2823
|
+
e.preventDefault();
|
|
2824
|
+
go(list.length - 1);
|
|
2825
|
+
break;
|
|
2826
|
+
case "Enter":
|
|
2827
|
+
case " ":
|
|
2828
|
+
case "Spacebar":
|
|
2829
|
+
e.preventDefault();
|
|
2830
|
+
rovingKey = env.keyOf(mark);
|
|
2831
|
+
env.select(mark, { ctrl: !!(e.ctrlKey || e.metaKey), shift: !!e.shiftKey });
|
|
2832
|
+
break;
|
|
2833
|
+
case "Escape":
|
|
2834
|
+
if (env.escapeClears !== false) env.clear();
|
|
2835
|
+
break;
|
|
2836
|
+
}
|
|
2837
|
+
};
|
|
2838
|
+
container.addEventListener("keydown", onKey);
|
|
2839
|
+
return {
|
|
2840
|
+
refresh,
|
|
2841
|
+
destroy() {
|
|
2842
|
+
destroyed = true;
|
|
2843
|
+
container.removeEventListener("keydown", onKey);
|
|
2844
|
+
try {
|
|
2845
|
+
container.classList?.remove(KEYBOARD_CLASS);
|
|
2846
|
+
} catch {
|
|
2847
|
+
}
|
|
2848
|
+
}
|
|
2849
|
+
};
|
|
2850
|
+
}
|
|
2851
|
+
|
|
2593
2852
|
// src/host.ts
|
|
2594
2853
|
function sessionViewStateProvider(container) {
|
|
2595
2854
|
const holder = container;
|
|
@@ -2738,6 +2997,9 @@ function createChartHost(container, config) {
|
|
|
2738
2997
|
}
|
|
2739
2998
|
}
|
|
2740
2999
|
let lassoClaimed = false;
|
|
3000
|
+
let ownBag = null;
|
|
3001
|
+
const seedKey = (s) => s && typeof s === "object" ? JSON.stringify(s) : void 0;
|
|
3002
|
+
let lastSeed = seedKey(raw.uiState);
|
|
2741
3003
|
if (typeof raw.setUiState !== "function") {
|
|
2742
3004
|
const provider = config.viewState ?? sessionViewStateProvider(container);
|
|
2743
3005
|
let bag;
|
|
@@ -2751,6 +3013,7 @@ function createChartHost(container, config) {
|
|
|
2751
3013
|
if (raw.uiState && typeof raw.uiState === "object" && Object.keys(bag).length === 0)
|
|
2752
3014
|
Object.assign(bag, raw.uiState);
|
|
2753
3015
|
raw.uiState = bag;
|
|
3016
|
+
ownBag = { bag, provider };
|
|
2754
3017
|
raw.setUiState = (s) => {
|
|
2755
3018
|
if (!s || typeof s !== "object") return;
|
|
2756
3019
|
try {
|
|
@@ -2759,6 +3022,26 @@ function createChartHost(container, config) {
|
|
|
2759
3022
|
}
|
|
2760
3023
|
};
|
|
2761
3024
|
}
|
|
3025
|
+
const takeSeed = (partial) => {
|
|
3026
|
+
if (typeof partial.setUiState === "function") {
|
|
3027
|
+
ownBag = null;
|
|
3028
|
+
return partial;
|
|
3029
|
+
}
|
|
3030
|
+
if (!ownBag || !("uiState" in partial)) return partial;
|
|
3031
|
+
const { uiState: seed, ...rest } = partial;
|
|
3032
|
+
const key = seedKey(seed);
|
|
3033
|
+
if (key !== void 0 && key !== lastSeed) {
|
|
3034
|
+
lastSeed = key;
|
|
3035
|
+
const { bag, provider } = ownBag;
|
|
3036
|
+
for (const k of Object.keys(bag)) delete bag[k];
|
|
3037
|
+
Object.assign(bag, seed);
|
|
3038
|
+
try {
|
|
3039
|
+
provider.save({ ...bag });
|
|
3040
|
+
} catch {
|
|
3041
|
+
}
|
|
3042
|
+
}
|
|
3043
|
+
return rest;
|
|
3044
|
+
};
|
|
2762
3045
|
const resolveForHost = (input) => {
|
|
2763
3046
|
const out = resolveOptions(input);
|
|
2764
3047
|
return out.allowTooltips == null ? { ...out, allowTooltips: true } : out;
|
|
@@ -2773,7 +3056,9 @@ function createChartHost(container, config) {
|
|
|
2773
3056
|
let warnedLassoNoFilter = false;
|
|
2774
3057
|
const idScope = newIdScope();
|
|
2775
3058
|
let renderSeq = 0;
|
|
2776
|
-
const
|
|
3059
|
+
const keyboardOn = codeHasKeyboardStamp(config.code);
|
|
3060
|
+
let keyboard = null;
|
|
3061
|
+
const annotationLayer = createAnnotationLayer(container, (a) => config.onAnnotationClick?.(a), { keyboard: () => keyboardOn });
|
|
2777
3062
|
const drawAnnotations = () => annotationLayer.draw(
|
|
2778
3063
|
{ columns: data.columns, rows: data.rows },
|
|
2779
3064
|
{
|
|
@@ -2809,6 +3094,8 @@ function createChartHost(container, config) {
|
|
|
2809
3094
|
let selectionIsPeriod = false;
|
|
2810
3095
|
let selectionFromChart = false;
|
|
2811
3096
|
let selectionPublished = true;
|
|
3097
|
+
let publishedRows = [];
|
|
3098
|
+
let publishedFromChart = false;
|
|
2812
3099
|
const clickedMarks = () => container[CONTAINER_SLOT_CLICKED_MARKS] ?? null;
|
|
2813
3100
|
const setClickedMarks = (c) => {
|
|
2814
3101
|
try {
|
|
@@ -2857,7 +3144,18 @@ function createChartHost(container, config) {
|
|
|
2857
3144
|
anomaly badge, a highlight stroke) and must keep dimming with its datum. */
|
|
2858
3145
|
.${HOST_CONTAINER_CLASS} .${MARK_CLASS} { cursor: pointer; transition: opacity 120ms ease-in-out, filter 100ms ease-in-out; }
|
|
2859
3146
|
.${HOST_CONTAINER_CLASS} .${MARK_CLASS}:not([${ROW_IDX_ATTR}=""]):hover { filter: brightness(1.1) drop-shadow(0 0 1.5px rgba(0,0,0,0.5)) !important; }
|
|
2860
|
-
.${HOST_CONTAINER_CLASS}:has(.${MARK_CLASS}:not([${ROW_IDX_ATTR}=""]):hover) .${MARK_CLASS}:not(:hover):not([${ROW_IDX_ATTR}=""]) { opacity: 0.55; }
|
|
3147
|
+
.${HOST_CONTAINER_CLASS}:not(.${MARKS_INERT_CLASS}):has(.${MARK_CLASS}:not([${ROW_IDX_ATTR}=""]):hover) .${MARK_CLASS}:not(:hover):not([${ROW_IDX_ATTR}=""]) { opacity: 0.55; }
|
|
3148
|
+
/* A MARK THAT SELECTS NOTHING DOESN'T LOOK CLICKABLE: no pointer, over the inline cursor generated code
|
|
3149
|
+
sets on its marks, and no dimming of the others on hover (the rule above). A control the chart draws keeps its own. */
|
|
3150
|
+
.${HOST_CONTAINER_CLASS}.${MARKS_INERT_CLASS} .${MARK_CLASS} { cursor: default !important; }
|
|
3151
|
+
/* THE KEYBOARD'S FOCUS: a ring on the mark, control or badge that holds keyboard focus, in the colour the
|
|
3152
|
+
chart's text is drawn in, so it reads in either theme. A pointer's focus shows none. */
|
|
3153
|
+
.${HOST_CONTAINER_CLASS}.${KEYBOARD_CLASS} [${WIRED_ATTR}]:focus:not(:focus-visible) { outline: none; }
|
|
3154
|
+
.${HOST_CONTAINER_CLASS}.${KEYBOARD_CLASS} [${WIRED_ATTR}]:focus-visible,
|
|
3155
|
+
.${HOST_CONTAINER_CLASS} .bic-annotation:focus-visible { outline: 2px solid var(--lch-focus-ring, currentColor) !important; outline-offset: 2px; }
|
|
3156
|
+
/* A dimmed mark that takes keyboard focus is drawn at full strength while it has it, ring included: the dim would
|
|
3157
|
+
otherwise fade the ring with the mark. */
|
|
3158
|
+
.${HOST_CONTAINER_CLASS}.${KEYBOARD_CLASS}.${SELECTION_ACTIVE_CLASS} .${MARK_CLASS}[${WIRED_ATTR}]:focus-visible:not(.${MARK_SELECTED_CLASS}) { opacity: 1 !important; }
|
|
2861
3159
|
.${HOST_CONTAINER_CLASS}.${SELECTION_ACTIVE_CLASS} .${MARK_CLASS}:not(.${MARK_SELECTED_CLASS}):not([${ROW_IDX_ATTR}=""]) {
|
|
2862
3160
|
opacity: var(${DIM_OPACITY_VAR}, ${DIM_OPACITY_DEFAULT}) !important;
|
|
2863
3161
|
}
|
|
@@ -2890,9 +3188,18 @@ function createChartHost(container, config) {
|
|
|
2890
3188
|
} catch {
|
|
2891
3189
|
}
|
|
2892
3190
|
};
|
|
3191
|
+
const marksInert = () => {
|
|
3192
|
+
if (typeof config.marksSelect !== "function") return false;
|
|
3193
|
+
try {
|
|
3194
|
+
return config.marksSelect() === false;
|
|
3195
|
+
} catch {
|
|
3196
|
+
return false;
|
|
3197
|
+
}
|
|
3198
|
+
};
|
|
2893
3199
|
const paintSelection = () => {
|
|
2894
3200
|
if (destroyed) return;
|
|
2895
3201
|
try {
|
|
3202
|
+
container.classList?.[marksInert() ? "add" : "remove"](MARKS_INERT_CLASS);
|
|
2896
3203
|
const sel = current;
|
|
2897
3204
|
const active = !!sel && sel.length > 0;
|
|
2898
3205
|
const dim = active && !selectionIsPeriod;
|
|
@@ -3155,12 +3462,17 @@ function createChartHost(container, config) {
|
|
|
3155
3462
|
current = rowIdxs;
|
|
3156
3463
|
selectionFromChart = rowIdxs.length > 0 && fromChart;
|
|
3157
3464
|
selectionPublished = publish;
|
|
3465
|
+
if (publish) {
|
|
3466
|
+
publishedRows = rowIdxs;
|
|
3467
|
+
publishedFromChart = selectionFromChart;
|
|
3468
|
+
}
|
|
3158
3469
|
activeTickEl = rowIdxs.length ? tick ?? null : null;
|
|
3159
3470
|
selectionIsPeriod = rowIdxs.length > 0 && periodTickSuppressesFeedback(!!tick, chartOwnsTimeline(container));
|
|
3160
3471
|
if (!rowIdxs.length && !meta?.keepHidden) hiddenHeld = 0;
|
|
3161
3472
|
factFresh = true;
|
|
3162
3473
|
paintSelection();
|
|
3163
3474
|
paintGlyphLayer();
|
|
3475
|
+
keyboard?.refresh();
|
|
3164
3476
|
if (publish) for (const cb of subs) {
|
|
3165
3477
|
try {
|
|
3166
3478
|
cb(rowIdxs, source, meta);
|
|
@@ -3169,6 +3481,10 @@ function createChartHost(container, config) {
|
|
|
3169
3481
|
}
|
|
3170
3482
|
tellSelection();
|
|
3171
3483
|
};
|
|
3484
|
+
const restorePublished = (source) => {
|
|
3485
|
+
notify(publishedRows, source, void 0, publishedFromChart, false);
|
|
3486
|
+
selectionPublished = true;
|
|
3487
|
+
};
|
|
3172
3488
|
const selectFromLasso = (rows) => {
|
|
3173
3489
|
if (lassoEffect(resolved.lasso) === "highlight") {
|
|
3174
3490
|
notify(rows, "user", null, true, false);
|
|
@@ -3195,7 +3511,10 @@ function createChartHost(container, config) {
|
|
|
3195
3511
|
const onXf = (e) => {
|
|
3196
3512
|
const d = e?.detail || {};
|
|
3197
3513
|
xfAt = Date.now();
|
|
3198
|
-
if (d.clear)
|
|
3514
|
+
if (d.clear) {
|
|
3515
|
+
if (!selectionPublished && current && current.length) restorePublished(d.source || "chart");
|
|
3516
|
+
else notify([], d.source || "chart", void 0, false, true);
|
|
3517
|
+
} else if (marksInert()) return;
|
|
3199
3518
|
else if (d.mark) notify(parseRowIdxs(d.mark.getAttribute?.(ROW_IDX_ATTR)), d.source || "chart", d.mark, true);
|
|
3200
3519
|
else if (Array.isArray(d.rows)) notify(validRowSet(d.rows), d.source || "chart", null, true, true, d.keepHidden === true ? { keepHidden: true } : void 0);
|
|
3201
3520
|
};
|
|
@@ -3207,6 +3526,7 @@ function createChartHost(container, config) {
|
|
|
3207
3526
|
});
|
|
3208
3527
|
const clearFromGesture = () => {
|
|
3209
3528
|
if (current && current.length) {
|
|
3529
|
+
const clearingHighlight = !selectionPublished;
|
|
3210
3530
|
const slot = container[CONTAINER_SLOT_XF_CLEAR];
|
|
3211
3531
|
if (selectionFromChart && typeof slot === "function") {
|
|
3212
3532
|
try {
|
|
@@ -3214,7 +3534,9 @@ function createChartHost(container, config) {
|
|
|
3214
3534
|
} catch {
|
|
3215
3535
|
}
|
|
3216
3536
|
}
|
|
3217
|
-
if (
|
|
3537
|
+
if (clearingHighlight) {
|
|
3538
|
+
if (!selectionPublished) restorePublished("user");
|
|
3539
|
+
} else if (current && current.length) notify([], "user", void 0, false, true);
|
|
3218
3540
|
}
|
|
3219
3541
|
};
|
|
3220
3542
|
let lasso = null;
|
|
@@ -3231,6 +3553,9 @@ function createChartHost(container, config) {
|
|
|
3231
3553
|
const wasDrag = clickWasDrag(container, e);
|
|
3232
3554
|
clearPress(container);
|
|
3233
3555
|
if (wasDrag) return;
|
|
3556
|
+
const inert = marksInert();
|
|
3557
|
+
container.classList?.[inert ? "add" : "remove"](MARKS_INERT_CLASS);
|
|
3558
|
+
if (inert) return;
|
|
3234
3559
|
if (Date.now() - xfAt < XF_ECHO_MS) return;
|
|
3235
3560
|
if (isInsideControl(e?.target, container)) return;
|
|
3236
3561
|
let el = resolver.findMark(e?.target, clickSel, e);
|
|
@@ -3244,11 +3569,12 @@ function createChartHost(container, config) {
|
|
|
3244
3569
|
if (!rows.length) return;
|
|
3245
3570
|
const tick = el.classList?.contains?.(AXIS_FILTER_CLASS) ? el : null;
|
|
3246
3571
|
const multi = !!(e?.ctrlKey || e?.metaKey || e?.shiftKey);
|
|
3247
|
-
const
|
|
3572
|
+
const base = selectionPublished ? current : publishedRows;
|
|
3573
|
+
const next = nextSelection(base, rows, { ctrl: !!(e?.ctrlKey || e?.metaKey), shift: !!e?.shiftKey });
|
|
3248
3574
|
const toggledOff = !multi && next.length === 0;
|
|
3249
3575
|
setClickedMarks(nextClickedMarks(
|
|
3250
3576
|
clickedMarks(),
|
|
3251
|
-
|
|
3577
|
+
base,
|
|
3252
3578
|
markKeyOf(el),
|
|
3253
3579
|
next,
|
|
3254
3580
|
{ ctrl: !!(e?.ctrlKey || e?.metaKey), shift: !!e?.shiftKey }
|
|
@@ -3258,6 +3584,27 @@ function createChartHost(container, config) {
|
|
|
3258
3584
|
container.addEventListener(XFILTER_REFRESH_EVENT, onXf);
|
|
3259
3585
|
const untrackPress = trackPress(container);
|
|
3260
3586
|
container.addEventListener("click", onClick);
|
|
3587
|
+
if (keyboardOn) {
|
|
3588
|
+
const nameOfRow = (m) => {
|
|
3589
|
+
const r = parseRowIdxs(m.getAttribute(ROW_IDX_ATTR))[0];
|
|
3590
|
+
return rowNameOf(data.columns || [], r == null ? null : data.rows?.[r], resolved.cultureCode);
|
|
3591
|
+
};
|
|
3592
|
+
keyboard = installKeyboard({
|
|
3593
|
+
container,
|
|
3594
|
+
markSelector: clickSel,
|
|
3595
|
+
pressSelector: `.${CONTROL_CLASS}`,
|
|
3596
|
+
skipSelector: `.${ANNOTATION_LAYER_CLASS}, .${GLYPH_LAYER_CLASS}, .${LASSO_OUTLINE_CLASS}`,
|
|
3597
|
+
inert: marksInert,
|
|
3598
|
+
select: (m, mods) => {
|
|
3599
|
+
const ME = win?.MouseEvent ?? MouseEvent;
|
|
3600
|
+
m.dispatchEvent(new ME("click", { bubbles: true, cancelable: true, ctrlKey: mods.ctrl, shiftKey: mods.shift }));
|
|
3601
|
+
},
|
|
3602
|
+
clear: clearFromGesture,
|
|
3603
|
+
isSelected: (m) => !!m.classList?.contains(MARK_SELECTED_CLASS),
|
|
3604
|
+
labelOf: nameOfRow,
|
|
3605
|
+
keyOf: (m) => m.getAttribute(ROW_IDX_ATTR) ?? ""
|
|
3606
|
+
});
|
|
3607
|
+
}
|
|
3261
3608
|
container.classList?.add(HOST_CONTAINER_CLASS);
|
|
3262
3609
|
ensureAffordanceStyles();
|
|
3263
3610
|
const fitOpts = config.fit ?? true;
|
|
@@ -3405,6 +3752,15 @@ function createChartHost(container, config) {
|
|
|
3405
3752
|
} catch {
|
|
3406
3753
|
}
|
|
3407
3754
|
paintGlyphLayer();
|
|
3755
|
+
installLassoHere();
|
|
3756
|
+
keyboard?.refresh();
|
|
3757
|
+
const fw = focusWas;
|
|
3758
|
+
focusWas = null;
|
|
3759
|
+
restoreFocus(container, fw);
|
|
3760
|
+
selfRedraw?.takeRecords();
|
|
3761
|
+
watchSelfRedraw();
|
|
3762
|
+
};
|
|
3763
|
+
function installLassoHere() {
|
|
3408
3764
|
try {
|
|
3409
3765
|
lasso = installLasso({
|
|
3410
3766
|
container,
|
|
@@ -3415,7 +3771,38 @@ function createChartHost(container, config) {
|
|
|
3415
3771
|
});
|
|
3416
3772
|
} catch {
|
|
3417
3773
|
}
|
|
3774
|
+
}
|
|
3775
|
+
let selfRedraw = null;
|
|
3776
|
+
let focusWas = null;
|
|
3777
|
+
let notesHeld = (config.annotations ?? []).length > 0;
|
|
3778
|
+
const takesMarks = (n) => n.nodeType === 1 && (!!n.classList?.contains(MARK_CLASS) || !!n.querySelector?.(`.${MARK_CLASS}`));
|
|
3779
|
+
const lassoLost = () => !!lasso?.surface && !lasso.surface.isConnected;
|
|
3780
|
+
const repaintAfterChart = () => {
|
|
3781
|
+
if (destroyed) return;
|
|
3782
|
+
try {
|
|
3783
|
+
ensureCrossfilterHitTargets(container, doc);
|
|
3784
|
+
} catch {
|
|
3785
|
+
}
|
|
3786
|
+
paintSelection();
|
|
3787
|
+
try {
|
|
3788
|
+
drawAnnotations();
|
|
3789
|
+
} catch {
|
|
3790
|
+
}
|
|
3791
|
+
paintGlyphLayer(false);
|
|
3792
|
+
if (lassoLost()) installLassoHere();
|
|
3793
|
+
keyboard?.refresh();
|
|
3794
|
+
selfRedraw?.takeRecords();
|
|
3418
3795
|
};
|
|
3796
|
+
function watchSelfRedraw() {
|
|
3797
|
+
const MO = win?.MutationObserver;
|
|
3798
|
+
if (selfRedraw || !MO || destroyed) return;
|
|
3799
|
+
selfRedraw = new MO((records) => {
|
|
3800
|
+
if (destroyed || !records.some((r) => Array.from(r.removedNodes).some(takesMarks))) return;
|
|
3801
|
+
if (!(current && current.length) && !notesHeld && !lassoLost()) return;
|
|
3802
|
+
repaintAfterChart();
|
|
3803
|
+
});
|
|
3804
|
+
selfRedraw.observe(container, { childList: true, subtree: true });
|
|
3805
|
+
}
|
|
3419
3806
|
const renderFailure = (err) => {
|
|
3420
3807
|
const message = String(err?.message ?? err ?? "");
|
|
3421
3808
|
if (config.onInvalidSentinel && isInvalidSentinelError(message)) {
|
|
@@ -3435,7 +3822,9 @@ function createChartHost(container, config) {
|
|
|
3435
3822
|
disposeLasso();
|
|
3436
3823
|
flushZoom();
|
|
3437
3824
|
if (hasRendered && keepScroll) rememberScroll(container, scrollKey());
|
|
3825
|
+
focusWas = rememberFocus(container);
|
|
3438
3826
|
container.innerHTML = "";
|
|
3827
|
+
selfRedraw?.takeRecords();
|
|
3439
3828
|
hasRendered = true;
|
|
3440
3829
|
if (!renderFn) {
|
|
3441
3830
|
if (!config.code) throw new Error("createChartHost: provide code or renderFn");
|
|
@@ -3461,6 +3850,7 @@ function createChartHost(container, config) {
|
|
|
3461
3850
|
if (resolved.dateCellsAreUtcDays === void 0 && data.dateCellsAreUtcDays) resolved = { ...resolved, dateCellsAreUtcDays: true };
|
|
3462
3851
|
if (resolved.suppressSelectionGlyph === void 0 && data.meta?.suppressSelectionGlyph === true)
|
|
3463
3852
|
resolved = { ...resolved, suppressSelectionGlyph: true };
|
|
3853
|
+
if (keyboardOn) resolved = { ...resolved, keyboardMarks: true };
|
|
3464
3854
|
let outcome;
|
|
3465
3855
|
zoomCap = null;
|
|
3466
3856
|
if (zoomMemory && config.code && !config.renderFn) {
|
|
@@ -3536,7 +3926,7 @@ function createChartHost(container, config) {
|
|
|
3536
3926
|
// callback) must not clear, stop or annotate the chart that is on screen now.
|
|
3537
3927
|
setOptions(partial) {
|
|
3538
3928
|
if (destroyed) return;
|
|
3539
|
-
raw = { ...raw, ...partial };
|
|
3929
|
+
raw = { ...raw, ...takeSeed(partial ?? {}) };
|
|
3540
3930
|
resolved = resolveForHost(raw);
|
|
3541
3931
|
host.render();
|
|
3542
3932
|
},
|
|
@@ -3551,6 +3941,7 @@ function createChartHost(container, config) {
|
|
|
3551
3941
|
},
|
|
3552
3942
|
setAnnotations(list) {
|
|
3553
3943
|
if (destroyed) return;
|
|
3944
|
+
notesHeld = (list ?? []).length > 0;
|
|
3554
3945
|
annotationLayer.set(list);
|
|
3555
3946
|
try {
|
|
3556
3947
|
drawAnnotations();
|
|
@@ -3612,6 +4003,12 @@ function createChartHost(container, config) {
|
|
|
3612
4003
|
if (destroyed) return;
|
|
3613
4004
|
destroyed = true;
|
|
3614
4005
|
stopAnim();
|
|
4006
|
+
if (selfRedraw) {
|
|
4007
|
+
selfRedraw.disconnect();
|
|
4008
|
+
selfRedraw = null;
|
|
4009
|
+
}
|
|
4010
|
+
keyboard?.destroy();
|
|
4011
|
+
keyboard = null;
|
|
3615
4012
|
container.removeEventListener(XFILTER_REFRESH_EVENT, onXf);
|
|
3616
4013
|
container.removeEventListener("click", onClick);
|
|
3617
4014
|
untrackPress();
|
|
@@ -3836,6 +4233,7 @@ export {
|
|
|
3836
4233
|
exportTableService,
|
|
3837
4234
|
browserSaveFile,
|
|
3838
4235
|
cleanHostSelection,
|
|
4236
|
+
cleanFilterScope,
|
|
3839
4237
|
resolveOptions,
|
|
3840
4238
|
buildRenderPayload,
|
|
3841
4239
|
stripJsComments,
|
|
@@ -3858,6 +4256,14 @@ export {
|
|
|
3858
4256
|
invalidSentinelReason,
|
|
3859
4257
|
ANNOTATION_LAYER_CLASS,
|
|
3860
4258
|
ANNOTATION_CLASS,
|
|
4259
|
+
rememberFocus,
|
|
4260
|
+
restoreFocus,
|
|
4261
|
+
KEYBOARD_STAMP,
|
|
4262
|
+
codeHasKeyboardStamp,
|
|
4263
|
+
KEYBOARD_CLASS,
|
|
4264
|
+
WIRED_ATTR,
|
|
4265
|
+
rowNameOf,
|
|
4266
|
+
installKeyboard,
|
|
3861
4267
|
sessionViewStateProvider,
|
|
3862
4268
|
noopViewStateProvider,
|
|
3863
4269
|
assembleD3,
|