@bicharts/chart-host 0.6.82 → 0.6.84
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 +10 -4
- package/dist/card.mjs +2 -2
- package/dist/{chunk-MP5S6MVW.mjs → chunk-2HKO6GEK.mjs} +70 -17
- package/dist/{chunk-ZRSEKV4I.mjs → chunk-2ZUUIZWL.mjs} +112 -112
- package/dist/chunk-7HKVV5T5.mjs +198 -0
- package/dist/{chunk-XIAL6EEC.mjs → chunk-DTOGTKAJ.mjs} +10 -2
- package/dist/{chunk-7HPVGRQ2.mjs → chunk-GG4U66E4.mjs} +9 -9
- package/dist/{chunk-MGAO2DR7.mjs → chunk-IURROJT7.mjs} +95 -193
- package/dist/{chunk-7JWL6LYE.mjs → chunk-MR6TL7QZ.mjs} +1 -1
- package/dist/chunk-QIRLWJBI.mjs +665 -0
- package/dist/index.mjs +123 -13
- package/dist/page.mjs +4 -1
- package/dist/react.mjs +7 -5
- package/dist/testing.mjs +1 -1
- package/dist/types/contract.d.ts +35 -1
- package/dist/types/index.d.ts +5 -4
- package/dist/types/lasso.d.ts +143 -0
- package/dist/types/pendingGenerate.d.ts +18 -2
- package/dist/types/qualifyGroups.d.ts +61 -3
- package/dist/types/selection.d.ts +51 -0
- package/package.json +1 -1
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/*! @bicharts/chart-host — Apache-2.0. Bundled reference data: GeoNames (https://www.geonames.org/) CC BY 4.0; Natural Earth and US Census/TIGER (public domain). Full text: NOTICE in this package. */
|
|
2
|
+
import {
|
|
3
|
+
AXIS_FILTER_CLASS,
|
|
4
|
+
LEGEND_MARK_CLASS,
|
|
5
|
+
MARK_CLASS,
|
|
6
|
+
ROW_IDX_ATTR
|
|
7
|
+
} from "./chunk-MR6TL7QZ.mjs";
|
|
8
|
+
|
|
9
|
+
// src/hitTargets.ts
|
|
10
|
+
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
11
|
+
var HIT_ATTR = "data-lch-hit";
|
|
12
|
+
var ELEMENT_CAP = 5e3;
|
|
13
|
+
var mapsPresentationAttributes = /* @__PURE__ */ new WeakMap();
|
|
14
|
+
function engineMapsPresentationAttributes(ownerDoc, view) {
|
|
15
|
+
if (!ownerDoc || typeof ownerDoc !== "object") return false;
|
|
16
|
+
const known = mapsPresentationAttributes.get(ownerDoc);
|
|
17
|
+
if (known !== void 0) return known;
|
|
18
|
+
let maps = false;
|
|
19
|
+
try {
|
|
20
|
+
const host = ownerDoc.documentElement;
|
|
21
|
+
const probe = ownerDoc.createElementNS(SVG_NS, "svg");
|
|
22
|
+
const shape = ownerDoc.createElementNS(SVG_NS, "rect");
|
|
23
|
+
shape.setAttribute("fill", "none");
|
|
24
|
+
probe.appendChild(shape);
|
|
25
|
+
host.appendChild(probe);
|
|
26
|
+
try {
|
|
27
|
+
maps = String(view.getComputedStyle(shape).fill ?? "").trim().toLowerCase() === "none";
|
|
28
|
+
} finally {
|
|
29
|
+
host.removeChild(probe);
|
|
30
|
+
}
|
|
31
|
+
} catch {
|
|
32
|
+
maps = false;
|
|
33
|
+
}
|
|
34
|
+
mapsPresentationAttributes.set(ownerDoc, maps);
|
|
35
|
+
return maps;
|
|
36
|
+
}
|
|
37
|
+
function ensureCrossfilterHitTargets(container, doc) {
|
|
38
|
+
const report = { tagged: 0, hitRects: 0, peFlips: 0, peStrokeOnly: 0 };
|
|
39
|
+
try {
|
|
40
|
+
if (!container || typeof container.querySelectorAll !== "function") return report;
|
|
41
|
+
const els = container.querySelectorAll(
|
|
42
|
+
`.${MARK_CLASS}, .${LEGEND_MARK_CLASS}, .${AXIS_FILTER_CLASS}`
|
|
43
|
+
);
|
|
44
|
+
report.tagged = els.length;
|
|
45
|
+
if (els.length === 0 || els.length > ELEMENT_CAP) return report;
|
|
46
|
+
const ownerDoc = doc ?? container.ownerDocument;
|
|
47
|
+
const view = ownerDoc?.defaultView;
|
|
48
|
+
const computed = (el) => {
|
|
49
|
+
try {
|
|
50
|
+
return view?.getComputedStyle ? view.getComputedStyle(el) : null;
|
|
51
|
+
} catch {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
for (const el of Array.from(els)) {
|
|
56
|
+
const tag = String(el.tagName || "").toLowerCase();
|
|
57
|
+
if (tag === "g") {
|
|
58
|
+
if (!el.hasAttribute?.(ROW_IDX_ATTR)) continue;
|
|
59
|
+
if (el.querySelector?.(`rect[${HIT_ATTR}="1"]`)) continue;
|
|
60
|
+
const cls = el.getAttribute?.("class") || "";
|
|
61
|
+
const isFurniture = cls.indexOf(LEGEND_MARK_CLASS) >= 0 || cls.indexOf(AXIS_FILTER_CLASS) >= 0;
|
|
62
|
+
if (!isFurniture) {
|
|
63
|
+
let hasHittableChild = false;
|
|
64
|
+
const kids = el.querySelectorAll?.("*") ?? [];
|
|
65
|
+
for (const kid of Array.from(kids)) {
|
|
66
|
+
const ktag = String(kid.tagName || "").toLowerCase();
|
|
67
|
+
if (ktag === "g" || ktag === "tspan" || ktag === "title" || ktag === "defs") continue;
|
|
68
|
+
const cs = computed(kid);
|
|
69
|
+
if (!cs || cs.pointerEvents !== "none") {
|
|
70
|
+
hasHittableChild = true;
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (hasHittableChild) continue;
|
|
75
|
+
}
|
|
76
|
+
let bb = null;
|
|
77
|
+
try {
|
|
78
|
+
bb = el.getBBox?.();
|
|
79
|
+
} catch {
|
|
80
|
+
bb = null;
|
|
81
|
+
}
|
|
82
|
+
if (!bb || !(bb.width > 0) || !(bb.height > 0)) continue;
|
|
83
|
+
const rect = ownerDoc.createElementNS(SVG_NS, "rect");
|
|
84
|
+
rect.setAttribute("x", String(bb.x));
|
|
85
|
+
rect.setAttribute("y", String(bb.y));
|
|
86
|
+
rect.setAttribute("width", String(bb.width));
|
|
87
|
+
rect.setAttribute("height", String(bb.height));
|
|
88
|
+
rect.setAttribute("fill", "transparent");
|
|
89
|
+
rect.setAttribute(HIT_ATTR, "1");
|
|
90
|
+
if (rect.style) {
|
|
91
|
+
rect.style.pointerEvents = "all";
|
|
92
|
+
rect.style.cursor = "pointer";
|
|
93
|
+
}
|
|
94
|
+
el.insertBefore(rect, el.firstChild);
|
|
95
|
+
report.hitRects++;
|
|
96
|
+
} else {
|
|
97
|
+
const cs = computed(el);
|
|
98
|
+
if (cs && cs.pointerEvents === "none") {
|
|
99
|
+
const fill = String((engineMapsPresentationAttributes(ownerDoc, view) ? cs.fill : el.getAttribute?.("fill") ?? cs.fill) ?? "").trim().toLowerCase();
|
|
100
|
+
const unfilled = fill === "none" || fill === "transparent" || fill === "rgba(0, 0, 0, 0)";
|
|
101
|
+
if (el.style) el.style.pointerEvents = unfilled ? "stroke" : "all";
|
|
102
|
+
report.peFlips++;
|
|
103
|
+
if (unfilled) report.peStrokeOnly++;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
} catch {
|
|
108
|
+
}
|
|
109
|
+
return report;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// src/hitBands.ts
|
|
113
|
+
var MIN_HIT_BAND_PX = 8;
|
|
114
|
+
var ELEMENT_CAP2 = 5e3;
|
|
115
|
+
var EMPTY = {
|
|
116
|
+
openStrokes: 0,
|
|
117
|
+
interactive: 0,
|
|
118
|
+
hairline: 0,
|
|
119
|
+
uncovered: 0,
|
|
120
|
+
widestPx: 0
|
|
121
|
+
};
|
|
122
|
+
var OPEN_TAGS = /* @__PURE__ */ new Set(["path", "line", "polyline"]);
|
|
123
|
+
function styleOf(el, doc) {
|
|
124
|
+
try {
|
|
125
|
+
const view = doc?.defaultView;
|
|
126
|
+
return view?.getComputedStyle ? view.getComputedStyle(el) : null;
|
|
127
|
+
} catch {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
function attrOrComputed(el, name, cs) {
|
|
132
|
+
const a = el.getAttribute?.(name);
|
|
133
|
+
if (a !== null && a !== void 0 && String(a).trim() !== "") return String(a).trim();
|
|
134
|
+
const c = cs?.[name === "stroke-width" ? "strokeWidth" : name];
|
|
135
|
+
return c === null || c === void 0 ? "" : String(c).trim();
|
|
136
|
+
}
|
|
137
|
+
function isUnfilled(fill) {
|
|
138
|
+
const f = fill.toLowerCase();
|
|
139
|
+
return f === "none" || f === "transparent" || f === "rgba(0, 0, 0, 0)" || f === "rgba(0,0,0,0)";
|
|
140
|
+
}
|
|
141
|
+
function widthPx(raw) {
|
|
142
|
+
const m = /^(-?\d+(?:\.\d+)?)\s*(px)?$/i.exec(raw);
|
|
143
|
+
if (!m) return NaN;
|
|
144
|
+
const n = parseFloat(m[1]);
|
|
145
|
+
return isFinite(n) ? n : NaN;
|
|
146
|
+
}
|
|
147
|
+
function censusHitBands(container, doc) {
|
|
148
|
+
if (!container || typeof container.querySelectorAll !== "function") return EMPTY;
|
|
149
|
+
try {
|
|
150
|
+
const els = Array.from(
|
|
151
|
+
container.querySelectorAll(`.${MARK_CLASS}, [${ROW_IDX_ATTR}]`)
|
|
152
|
+
);
|
|
153
|
+
if (els.length === 0 || els.length > ELEMENT_CAP2) return EMPTY;
|
|
154
|
+
const ownerDoc = doc ?? container.ownerDocument;
|
|
155
|
+
const widestByGeom = /* @__PURE__ */ new Map();
|
|
156
|
+
const rows = [];
|
|
157
|
+
for (const el of els) {
|
|
158
|
+
const tag = String(el.tagName || "").toLowerCase();
|
|
159
|
+
if (!OPEN_TAGS.has(tag)) continue;
|
|
160
|
+
const cs = styleOf(el, ownerDoc);
|
|
161
|
+
const open = isUnfilled(attrOrComputed(el, "fill", cs));
|
|
162
|
+
const w = widthPx(attrOrComputed(el, "stroke-width", cs) || "1");
|
|
163
|
+
const geom = String(el.getAttribute?.("d") ?? "") || `${tag}#${String(el.getAttribute?.(ROW_IDX_ATTR) ?? "")}`;
|
|
164
|
+
const inert = String(cs?.pointerEvents ?? el.style?.pointerEvents ?? "") === "none";
|
|
165
|
+
rows.push({ el, geom, w, open, inert });
|
|
166
|
+
if (isFinite(w)) {
|
|
167
|
+
const prev = widestByGeom.get(geom);
|
|
168
|
+
if (prev === void 0 || w > prev) widestByGeom.set(geom, w);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
const out = { ...EMPTY };
|
|
172
|
+
for (const r of rows) {
|
|
173
|
+
if (!r.open) continue;
|
|
174
|
+
out.openStrokes++;
|
|
175
|
+
if (r.inert) continue;
|
|
176
|
+
out.interactive++;
|
|
177
|
+
if (isFinite(r.w) && r.w > out.widestPx) out.widestPx = Math.round(r.w);
|
|
178
|
+
if (!(r.w < MIN_HIT_BAND_PX)) continue;
|
|
179
|
+
out.hairline++;
|
|
180
|
+
const best = widestByGeom.get(r.geom);
|
|
181
|
+
if (best === void 0 || best < MIN_HIT_BAND_PX) out.uncovered++;
|
|
182
|
+
}
|
|
183
|
+
return out;
|
|
184
|
+
} catch {
|
|
185
|
+
return EMPTY;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
function hitBandFlag(c) {
|
|
189
|
+
if (c.interactive === 0) return "";
|
|
190
|
+
return c.uncovered > 0 ? "hitband:d3:thin" : "hitband:d3:ok";
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export {
|
|
194
|
+
ensureCrossfilterHitTargets,
|
|
195
|
+
MIN_HIT_BAND_PX,
|
|
196
|
+
censusHitBands,
|
|
197
|
+
hitBandFlag
|
|
198
|
+
};
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
/*! @bicharts/chart-host — Apache-2.0. Bundled reference data: GeoNames (https://www.geonames.org/) CC BY 4.0; Natural Earth and US Census/TIGER (public domain). Full text: NOTICE in this package. */
|
|
2
|
+
import {
|
|
3
|
+
LASSO_KNOB_KEY
|
|
4
|
+
} from "./chunk-QIRLWJBI.mjs";
|
|
2
5
|
|
|
3
6
|
// src/filterScope.ts
|
|
4
7
|
function viewToken(view) {
|
|
@@ -437,6 +440,7 @@ function fromVegaInteraction(filter, events) {
|
|
|
437
440
|
}
|
|
438
441
|
|
|
439
442
|
// src/controls.ts
|
|
443
|
+
var isKnob = (key) => key !== LASSO_KNOB_KEY;
|
|
440
444
|
var same = (a, b) => a.length === b.length && a.every((x, i) => x.key === b[i].key && x.label === b[i].label && x.text === b[i].text && JSON.stringify(x.value) === JSON.stringify(b[i].value));
|
|
441
445
|
function createControls(initial) {
|
|
442
446
|
const ui = initial ? { knobs: { ...initial } } : {};
|
|
@@ -452,7 +456,9 @@ function createControls(initial) {
|
|
|
452
456
|
get values() {
|
|
453
457
|
const out = {};
|
|
454
458
|
for (const i of info) out[i.key] = i.value;
|
|
455
|
-
if (!info.length && ui.knobs && typeof ui.knobs === "object")
|
|
459
|
+
if (!info.length && ui.knobs && typeof ui.knobs === "object") {
|
|
460
|
+
for (const [k, v] of Object.entries(ui.knobs)) if (isKnob(k)) out[k] = v;
|
|
461
|
+
}
|
|
456
462
|
return out;
|
|
457
463
|
},
|
|
458
464
|
get info() {
|
|
@@ -473,7 +479,9 @@ function createControls(initial) {
|
|
|
473
479
|
for (const a of Array.from(appliers)) a();
|
|
474
480
|
},
|
|
475
481
|
reset() {
|
|
482
|
+
const kept = ui.knobs?.[LASSO_KNOB_KEY];
|
|
476
483
|
delete ui.knobs;
|
|
484
|
+
if (kept !== void 0) ui.knobs = { [LASSO_KNOB_KEY]: kept };
|
|
477
485
|
for (const a of Array.from(appliers)) a();
|
|
478
486
|
},
|
|
479
487
|
onChange(cb) {
|
|
@@ -500,7 +508,7 @@ function createControls(initial) {
|
|
|
500
508
|
function readControls(container) {
|
|
501
509
|
const bag = container.__lchKnobs;
|
|
502
510
|
if (!bag || typeof bag !== "object") return [];
|
|
503
|
-
const keys = Object.keys(bag);
|
|
511
|
+
const keys = Object.keys(bag).filter(isKnob);
|
|
504
512
|
if (!keys.length) return [];
|
|
505
513
|
const groups = Array.from(container.querySelectorAll("g.llm-slider"));
|
|
506
514
|
return keys.map((key, i) => {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/*! @bicharts/chart-host — Apache-2.0. Bundled reference data: GeoNames (https://www.geonames.org/) CC BY 4.0; Natural Earth and US Census/TIGER (public domain). Full text: NOTICE in this package. */
|
|
2
2
|
import {
|
|
3
|
-
|
|
3
|
+
Ct,
|
|
4
4
|
Z,
|
|
5
5
|
g,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
} from "./chunk-
|
|
6
|
+
ii,
|
|
7
|
+
ni,
|
|
8
|
+
xt
|
|
9
|
+
} from "./chunk-2ZUUIZWL.mjs";
|
|
10
10
|
|
|
11
11
|
// src/sourceDateFormat.ts
|
|
12
12
|
function formatSourceDate(raw, opts = {}) {
|
|
@@ -435,15 +435,15 @@ function displayText(col, raw, opts) {
|
|
|
435
435
|
return String(raw);
|
|
436
436
|
}
|
|
437
437
|
function isSuppressed(col) {
|
|
438
|
-
return
|
|
438
|
+
return xt(col).suppressed;
|
|
439
439
|
}
|
|
440
440
|
function resolveAgg(col, requested, auto) {
|
|
441
441
|
const fallback = () => {
|
|
442
|
-
const d =
|
|
442
|
+
const d = ni(col);
|
|
443
443
|
return d === "first" ? "count" : d;
|
|
444
444
|
};
|
|
445
445
|
if (auto) return fallback();
|
|
446
|
-
return
|
|
446
|
+
return Ct(col).indexOf(requested) >= 0 ? requested : fallback();
|
|
447
447
|
}
|
|
448
448
|
function toNumber(v) {
|
|
449
449
|
if (v == null || v === "") return null;
|
|
@@ -546,7 +546,7 @@ function computeSelectionCard(payload, selectedRowIdxs, opts = {}) {
|
|
|
546
546
|
}
|
|
547
547
|
const value = reduce(selVals, colAgg, selRaw);
|
|
548
548
|
let sharePct = null;
|
|
549
|
-
if (
|
|
549
|
+
if (ii(col, colAgg) && value != null) {
|
|
550
550
|
const allVals = [];
|
|
551
551
|
const allRaw = [];
|
|
552
552
|
for (let r = 0; r < rows.length; r++) {
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
/*! @bicharts/chart-host — Apache-2.0. Bundled reference data: GeoNames (https://www.geonames.org/) CC BY 4.0; Natural Earth and US Census/TIGER (public domain). Full text: NOTICE in this package. */
|
|
2
2
|
import {
|
|
3
|
-
AXIS_FILTER_CLASS,
|
|
4
3
|
CONTROL_CLASS,
|
|
5
|
-
LEGEND_MARK_CLASS,
|
|
6
4
|
MARK_CLASS,
|
|
7
5
|
MARK_KEY_ATTR,
|
|
8
6
|
MARK_SELECTED_CLASS,
|
|
9
7
|
ROW_IDX_ATTR,
|
|
10
8
|
SELECTION_RULE_ATTR,
|
|
11
|
-
SELECTION_RULE_CLICKED_MARKS
|
|
12
|
-
|
|
9
|
+
SELECTION_RULE_CLICKED_MARKS,
|
|
10
|
+
XFILTER_REFRESH_EVENT
|
|
11
|
+
} from "./chunk-MR6TL7QZ.mjs";
|
|
13
12
|
|
|
14
13
|
// src/selection.ts
|
|
15
14
|
function rowIdxsFromMark(el) {
|
|
@@ -23,6 +22,24 @@ function rowIdxsFromMark(el) {
|
|
|
23
22
|
}
|
|
24
23
|
return out;
|
|
25
24
|
}
|
|
25
|
+
var ROW_SET_MAX = 25e4;
|
|
26
|
+
function validRowSet(rows) {
|
|
27
|
+
if (!Array.isArray(rows)) return [];
|
|
28
|
+
const seen = /* @__PURE__ */ new Set();
|
|
29
|
+
const out = [];
|
|
30
|
+
for (const r of rows) {
|
|
31
|
+
if (typeof r !== "number" || !Number.isSafeInteger(r) || r < 0 || seen.has(r)) continue;
|
|
32
|
+
seen.add(r);
|
|
33
|
+
out.push(r || 0);
|
|
34
|
+
if (out.length >= ROW_SET_MAX) break;
|
|
35
|
+
}
|
|
36
|
+
return out;
|
|
37
|
+
}
|
|
38
|
+
function dispatchRowSet(container, rows, source = "chart") {
|
|
39
|
+
const win = container.ownerDocument?.defaultView ?? globalThis;
|
|
40
|
+
const Ev = win.CustomEvent ?? globalThis.CustomEvent;
|
|
41
|
+
container.dispatchEvent(new Ev(XFILTER_REFRESH_EVENT, { detail: { rows: validRowSet(rows), source }, bubbles: true }));
|
|
42
|
+
}
|
|
26
43
|
function nextSelection(current, rowIdxs, mods = {}) {
|
|
27
44
|
const cur = Array.from(current ?? []);
|
|
28
45
|
if (mods.ctrl || mods.shift) {
|
|
@@ -87,6 +104,69 @@ function isInsideControl(target, container) {
|
|
|
87
104
|
}
|
|
88
105
|
return false;
|
|
89
106
|
}
|
|
107
|
+
var DRAG_NOT_CLICK_PX = 5;
|
|
108
|
+
function gestureWasDrag(down, up, thresholdPx = DRAG_NOT_CLICK_PX) {
|
|
109
|
+
if (!down) return false;
|
|
110
|
+
return Math.abs(up.x - down.x) >= thresholdPx || Math.abs(up.y - down.y) >= thresholdPx;
|
|
111
|
+
}
|
|
112
|
+
var CONTAINER_SLOT_PRESS_AT = "__lchPressAt";
|
|
113
|
+
var pressRecord = (container) => {
|
|
114
|
+
const p = container?.[CONTAINER_SLOT_PRESS_AT];
|
|
115
|
+
return p && Number.isFinite(p.x) && Number.isFinite(p.y) ? p : null;
|
|
116
|
+
};
|
|
117
|
+
function pressOf(container) {
|
|
118
|
+
const p = pressRecord(container);
|
|
119
|
+
return p ? { x: p.x, y: p.y } : null;
|
|
120
|
+
}
|
|
121
|
+
function clearPress(container) {
|
|
122
|
+
try {
|
|
123
|
+
if (container) container[CONTAINER_SLOT_PRESS_AT] = null;
|
|
124
|
+
} catch {
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function trackPress(container) {
|
|
128
|
+
const doc = container.ownerDocument;
|
|
129
|
+
let stopWatching = null;
|
|
130
|
+
const endWatch = () => {
|
|
131
|
+
stopWatching?.();
|
|
132
|
+
stopWatching = null;
|
|
133
|
+
};
|
|
134
|
+
const onDown = (e) => {
|
|
135
|
+
endWatch();
|
|
136
|
+
const x = Number(e?.clientX), y = Number(e?.clientY);
|
|
137
|
+
if (!Number.isFinite(x) || !Number.isFinite(y)) return;
|
|
138
|
+
const rec = { x, y, dragged: false };
|
|
139
|
+
try {
|
|
140
|
+
container[CONTAINER_SLOT_PRESS_AT] = rec;
|
|
141
|
+
} catch {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const onMove = (m) => {
|
|
145
|
+
if (!rec.dragged && gestureWasDrag(rec, { x: Number(m?.clientX), y: Number(m?.clientY) })) rec.dragged = true;
|
|
146
|
+
};
|
|
147
|
+
doc.addEventListener("pointermove", onMove, true);
|
|
148
|
+
doc.addEventListener("pointerup", endWatch, true);
|
|
149
|
+
doc.addEventListener("pointercancel", endWatch, true);
|
|
150
|
+
stopWatching = () => {
|
|
151
|
+
doc.removeEventListener("pointermove", onMove, true);
|
|
152
|
+
doc.removeEventListener("pointerup", endWatch, true);
|
|
153
|
+
doc.removeEventListener("pointercancel", endWatch, true);
|
|
154
|
+
};
|
|
155
|
+
};
|
|
156
|
+
container.addEventListener("pointerdown", onDown, true);
|
|
157
|
+
return () => {
|
|
158
|
+
container.removeEventListener("pointerdown", onDown, true);
|
|
159
|
+
endWatch();
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
function clickWasDrag(container, click) {
|
|
163
|
+
if (!click || !(Number(click.detail) > 0)) return false;
|
|
164
|
+
const rec = pressRecord(container);
|
|
165
|
+
if (rec?.dragged) return true;
|
|
166
|
+
const x = Number(click.clientX), y = Number(click.clientY);
|
|
167
|
+
if (!Number.isFinite(x) || !Number.isFinite(y)) return false;
|
|
168
|
+
return gestureWasDrag(rec, { x, y });
|
|
169
|
+
}
|
|
90
170
|
function createMarkResolver(env) {
|
|
91
171
|
const { root, doc, log } = env;
|
|
92
172
|
const isElement = (t) => {
|
|
@@ -338,192 +418,11 @@ function paintSelectionGlyphs(overlay, centers, style) {
|
|
|
338
418
|
return count;
|
|
339
419
|
}
|
|
340
420
|
|
|
341
|
-
// src/hitTargets.ts
|
|
342
|
-
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
343
|
-
var HIT_ATTR = "data-lch-hit";
|
|
344
|
-
var ELEMENT_CAP = 5e3;
|
|
345
|
-
var mapsPresentationAttributes = /* @__PURE__ */ new WeakMap();
|
|
346
|
-
function engineMapsPresentationAttributes(ownerDoc, view) {
|
|
347
|
-
if (!ownerDoc || typeof ownerDoc !== "object") return false;
|
|
348
|
-
const known = mapsPresentationAttributes.get(ownerDoc);
|
|
349
|
-
if (known !== void 0) return known;
|
|
350
|
-
let maps = false;
|
|
351
|
-
try {
|
|
352
|
-
const host = ownerDoc.documentElement;
|
|
353
|
-
const probe = ownerDoc.createElementNS(SVG_NS, "svg");
|
|
354
|
-
const shape = ownerDoc.createElementNS(SVG_NS, "rect");
|
|
355
|
-
shape.setAttribute("fill", "none");
|
|
356
|
-
probe.appendChild(shape);
|
|
357
|
-
host.appendChild(probe);
|
|
358
|
-
try {
|
|
359
|
-
maps = String(view.getComputedStyle(shape).fill ?? "").trim().toLowerCase() === "none";
|
|
360
|
-
} finally {
|
|
361
|
-
host.removeChild(probe);
|
|
362
|
-
}
|
|
363
|
-
} catch {
|
|
364
|
-
maps = false;
|
|
365
|
-
}
|
|
366
|
-
mapsPresentationAttributes.set(ownerDoc, maps);
|
|
367
|
-
return maps;
|
|
368
|
-
}
|
|
369
|
-
function ensureCrossfilterHitTargets(container, doc) {
|
|
370
|
-
const report = { tagged: 0, hitRects: 0, peFlips: 0, peStrokeOnly: 0 };
|
|
371
|
-
try {
|
|
372
|
-
if (!container || typeof container.querySelectorAll !== "function") return report;
|
|
373
|
-
const els = container.querySelectorAll(
|
|
374
|
-
`.${MARK_CLASS}, .${LEGEND_MARK_CLASS}, .${AXIS_FILTER_CLASS}`
|
|
375
|
-
);
|
|
376
|
-
report.tagged = els.length;
|
|
377
|
-
if (els.length === 0 || els.length > ELEMENT_CAP) return report;
|
|
378
|
-
const ownerDoc = doc ?? container.ownerDocument;
|
|
379
|
-
const view = ownerDoc?.defaultView;
|
|
380
|
-
const computed = (el) => {
|
|
381
|
-
try {
|
|
382
|
-
return view?.getComputedStyle ? view.getComputedStyle(el) : null;
|
|
383
|
-
} catch {
|
|
384
|
-
return null;
|
|
385
|
-
}
|
|
386
|
-
};
|
|
387
|
-
for (const el of Array.from(els)) {
|
|
388
|
-
const tag = String(el.tagName || "").toLowerCase();
|
|
389
|
-
if (tag === "g") {
|
|
390
|
-
if (!el.hasAttribute?.(ROW_IDX_ATTR)) continue;
|
|
391
|
-
if (el.querySelector?.(`rect[${HIT_ATTR}="1"]`)) continue;
|
|
392
|
-
const cls = el.getAttribute?.("class") || "";
|
|
393
|
-
const isFurniture = cls.indexOf(LEGEND_MARK_CLASS) >= 0 || cls.indexOf(AXIS_FILTER_CLASS) >= 0;
|
|
394
|
-
if (!isFurniture) {
|
|
395
|
-
let hasHittableChild = false;
|
|
396
|
-
const kids = el.querySelectorAll?.("*") ?? [];
|
|
397
|
-
for (const kid of Array.from(kids)) {
|
|
398
|
-
const ktag = String(kid.tagName || "").toLowerCase();
|
|
399
|
-
if (ktag === "g" || ktag === "tspan" || ktag === "title" || ktag === "defs") continue;
|
|
400
|
-
const cs = computed(kid);
|
|
401
|
-
if (!cs || cs.pointerEvents !== "none") {
|
|
402
|
-
hasHittableChild = true;
|
|
403
|
-
break;
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
if (hasHittableChild) continue;
|
|
407
|
-
}
|
|
408
|
-
let bb = null;
|
|
409
|
-
try {
|
|
410
|
-
bb = el.getBBox?.();
|
|
411
|
-
} catch {
|
|
412
|
-
bb = null;
|
|
413
|
-
}
|
|
414
|
-
if (!bb || !(bb.width > 0) || !(bb.height > 0)) continue;
|
|
415
|
-
const rect = ownerDoc.createElementNS(SVG_NS, "rect");
|
|
416
|
-
rect.setAttribute("x", String(bb.x));
|
|
417
|
-
rect.setAttribute("y", String(bb.y));
|
|
418
|
-
rect.setAttribute("width", String(bb.width));
|
|
419
|
-
rect.setAttribute("height", String(bb.height));
|
|
420
|
-
rect.setAttribute("fill", "transparent");
|
|
421
|
-
rect.setAttribute(HIT_ATTR, "1");
|
|
422
|
-
if (rect.style) {
|
|
423
|
-
rect.style.pointerEvents = "all";
|
|
424
|
-
rect.style.cursor = "pointer";
|
|
425
|
-
}
|
|
426
|
-
el.insertBefore(rect, el.firstChild);
|
|
427
|
-
report.hitRects++;
|
|
428
|
-
} else {
|
|
429
|
-
const cs = computed(el);
|
|
430
|
-
if (cs && cs.pointerEvents === "none") {
|
|
431
|
-
const fill = String((engineMapsPresentationAttributes(ownerDoc, view) ? cs.fill : el.getAttribute?.("fill") ?? cs.fill) ?? "").trim().toLowerCase();
|
|
432
|
-
const unfilled = fill === "none" || fill === "transparent" || fill === "rgba(0, 0, 0, 0)";
|
|
433
|
-
if (el.style) el.style.pointerEvents = unfilled ? "stroke" : "all";
|
|
434
|
-
report.peFlips++;
|
|
435
|
-
if (unfilled) report.peStrokeOnly++;
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
} catch {
|
|
440
|
-
}
|
|
441
|
-
return report;
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
// src/hitBands.ts
|
|
445
|
-
var MIN_HIT_BAND_PX = 8;
|
|
446
|
-
var ELEMENT_CAP2 = 5e3;
|
|
447
|
-
var EMPTY = {
|
|
448
|
-
openStrokes: 0,
|
|
449
|
-
interactive: 0,
|
|
450
|
-
hairline: 0,
|
|
451
|
-
uncovered: 0,
|
|
452
|
-
widestPx: 0
|
|
453
|
-
};
|
|
454
|
-
var OPEN_TAGS = /* @__PURE__ */ new Set(["path", "line", "polyline"]);
|
|
455
|
-
function styleOf(el, doc) {
|
|
456
|
-
try {
|
|
457
|
-
const view = doc?.defaultView;
|
|
458
|
-
return view?.getComputedStyle ? view.getComputedStyle(el) : null;
|
|
459
|
-
} catch {
|
|
460
|
-
return null;
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
function attrOrComputed(el, name, cs) {
|
|
464
|
-
const a = el.getAttribute?.(name);
|
|
465
|
-
if (a !== null && a !== void 0 && String(a).trim() !== "") return String(a).trim();
|
|
466
|
-
const c = cs?.[name === "stroke-width" ? "strokeWidth" : name];
|
|
467
|
-
return c === null || c === void 0 ? "" : String(c).trim();
|
|
468
|
-
}
|
|
469
|
-
function isUnfilled(fill) {
|
|
470
|
-
const f = fill.toLowerCase();
|
|
471
|
-
return f === "none" || f === "transparent" || f === "rgba(0, 0, 0, 0)" || f === "rgba(0,0,0,0)";
|
|
472
|
-
}
|
|
473
|
-
function widthPx(raw) {
|
|
474
|
-
const m = /^(-?\d+(?:\.\d+)?)\s*(px)?$/i.exec(raw);
|
|
475
|
-
if (!m) return NaN;
|
|
476
|
-
const n = parseFloat(m[1]);
|
|
477
|
-
return isFinite(n) ? n : NaN;
|
|
478
|
-
}
|
|
479
|
-
function censusHitBands(container, doc) {
|
|
480
|
-
if (!container || typeof container.querySelectorAll !== "function") return EMPTY;
|
|
481
|
-
try {
|
|
482
|
-
const els = Array.from(
|
|
483
|
-
container.querySelectorAll(`.${MARK_CLASS}, [${ROW_IDX_ATTR}]`)
|
|
484
|
-
);
|
|
485
|
-
if (els.length === 0 || els.length > ELEMENT_CAP2) return EMPTY;
|
|
486
|
-
const ownerDoc = doc ?? container.ownerDocument;
|
|
487
|
-
const widestByGeom = /* @__PURE__ */ new Map();
|
|
488
|
-
const rows = [];
|
|
489
|
-
for (const el of els) {
|
|
490
|
-
const tag = String(el.tagName || "").toLowerCase();
|
|
491
|
-
if (!OPEN_TAGS.has(tag)) continue;
|
|
492
|
-
const cs = styleOf(el, ownerDoc);
|
|
493
|
-
const open = isUnfilled(attrOrComputed(el, "fill", cs));
|
|
494
|
-
const w = widthPx(attrOrComputed(el, "stroke-width", cs) || "1");
|
|
495
|
-
const geom = String(el.getAttribute?.("d") ?? "") || `${tag}#${String(el.getAttribute?.(ROW_IDX_ATTR) ?? "")}`;
|
|
496
|
-
const inert = String(cs?.pointerEvents ?? el.style?.pointerEvents ?? "") === "none";
|
|
497
|
-
rows.push({ el, geom, w, open, inert });
|
|
498
|
-
if (isFinite(w)) {
|
|
499
|
-
const prev = widestByGeom.get(geom);
|
|
500
|
-
if (prev === void 0 || w > prev) widestByGeom.set(geom, w);
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
const out = { ...EMPTY };
|
|
504
|
-
for (const r of rows) {
|
|
505
|
-
if (!r.open) continue;
|
|
506
|
-
out.openStrokes++;
|
|
507
|
-
if (r.inert) continue;
|
|
508
|
-
out.interactive++;
|
|
509
|
-
if (isFinite(r.w) && r.w > out.widestPx) out.widestPx = Math.round(r.w);
|
|
510
|
-
if (!(r.w < MIN_HIT_BAND_PX)) continue;
|
|
511
|
-
out.hairline++;
|
|
512
|
-
const best = widestByGeom.get(r.geom);
|
|
513
|
-
if (best === void 0 || best < MIN_HIT_BAND_PX) out.uncovered++;
|
|
514
|
-
}
|
|
515
|
-
return out;
|
|
516
|
-
} catch {
|
|
517
|
-
return EMPTY;
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
function hitBandFlag(c) {
|
|
521
|
-
if (c.interactive === 0) return "";
|
|
522
|
-
return c.uncovered > 0 ? "hitband:d3:thin" : "hitband:d3:ok";
|
|
523
|
-
}
|
|
524
|
-
|
|
525
421
|
export {
|
|
526
422
|
rowIdxsFromMark,
|
|
423
|
+
ROW_SET_MAX,
|
|
424
|
+
validRowSet,
|
|
425
|
+
dispatchRowSet,
|
|
527
426
|
nextSelection,
|
|
528
427
|
selectionRuleOf,
|
|
529
428
|
markKeyOf,
|
|
@@ -531,13 +430,16 @@ export {
|
|
|
531
430
|
planSelectionPaint,
|
|
532
431
|
nextClickedMarks,
|
|
533
432
|
isInsideControl,
|
|
433
|
+
DRAG_NOT_CLICK_PX,
|
|
434
|
+
gestureWasDrag,
|
|
435
|
+
CONTAINER_SLOT_PRESS_AT,
|
|
436
|
+
pressOf,
|
|
437
|
+
clearPress,
|
|
438
|
+
trackPress,
|
|
439
|
+
clickWasDrag,
|
|
534
440
|
createMarkResolver,
|
|
535
441
|
collectD3GlyphCenters,
|
|
536
442
|
SELECTION_GLYPH_CLASS,
|
|
537
443
|
clearSelectionGlyphs,
|
|
538
|
-
paintSelectionGlyphs
|
|
539
|
-
ensureCrossfilterHitTargets,
|
|
540
|
-
MIN_HIT_BAND_PX,
|
|
541
|
-
censusHitBands,
|
|
542
|
-
hitBandFlag
|
|
444
|
+
paintSelectionGlyphs
|
|
543
445
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*! @bicharts/chart-host — Apache-2.0. Bundled reference data: GeoNames (https://www.geonames.org/) CC BY 4.0; Natural Earth and US Census/TIGER (public domain). Full text: NOTICE in this package. */
|
|
2
2
|
|
|
3
3
|
// src/contract.ts
|
|
4
|
-
var HOST_CONTRACT_VERSION = "1.
|
|
4
|
+
var HOST_CONTRACT_VERSION = "1.16.0";
|
|
5
5
|
var GEO_POINT_PRECISIONS = ["latlon", "city", "zip3", "state", "country"];
|
|
6
6
|
var MARK_CLASS = "d3-mark";
|
|
7
7
|
var LEGEND_MARK_CLASS = "d3-legend-mark";
|