@bicharts/chart-host 0.6.77 → 0.6.78

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.
@@ -5,7 +5,18 @@ import {
5
5
  Xn,
6
6
  Yn,
7
7
  ge
8
- } from "./chunk-H2P63UMG.mjs";
8
+ } from "./chunk-L554L6HF.mjs";
9
+ import {
10
+ censusHitBands,
11
+ createMarkResolver,
12
+ ensureCrossfilterHitTargets,
13
+ isInsideControl,
14
+ markKeyOf,
15
+ nextClickedMarks,
16
+ nextSelection,
17
+ planSelectionPaint,
18
+ selectionRuleOf
19
+ } from "./chunk-MGAO2DR7.mjs";
9
20
  import {
10
21
  NA_ISO3,
11
22
  NA_LAT_MAX,
@@ -41,15 +52,12 @@ import {
41
52
  LEGEND_MARK_CLASS,
42
53
  LIFT_SELECTED_CLASS,
43
54
  MARK_CLASS,
44
- MARK_KEY_ATTR,
45
55
  MARK_SELECTED_CLASS,
46
56
  MAX_MAP_POINTS_DEFAULT,
47
57
  NO_ROW_MARKS_ATTR,
48
58
  ROW_IDX_ATTR,
49
59
  SEASONAL_MARKERS_DEFAULT,
50
60
  SELECTION_ACTIVE_CLASS,
51
- SELECTION_RULE_ATTR,
52
- SELECTION_RULE_CLICKED_MARKS,
53
61
  SNAPSHOT_SVG_ATTR,
54
62
  VALUE_AXIS_BASELINE_DEFAULT,
55
63
  XFILTER_REFRESH_EVENT,
@@ -1077,436 +1085,6 @@ function stripJsComments(code) {
1077
1085
  return out;
1078
1086
  }
1079
1087
 
1080
- // src/selection.ts
1081
- function rowIdxsFromMark(el) {
1082
- if (!el) return [];
1083
- const raw = el.getAttribute("data-row-idx");
1084
- if (!raw) return [];
1085
- const out = [];
1086
- for (const tok of raw.split(",")) {
1087
- const n = parseInt(tok.trim(), 10);
1088
- if (!isNaN(n) && n >= 0) out.push(n);
1089
- }
1090
- return out;
1091
- }
1092
- function nextSelection(current, rowIdxs, mods = {}) {
1093
- const cur = Array.from(current ?? []);
1094
- if (mods.ctrl || mods.shift) {
1095
- const next = new Set(cur);
1096
- for (const r of rowIdxs) {
1097
- if (next.has(r)) next.delete(r);
1098
- else next.add(r);
1099
- }
1100
- return Array.from(next);
1101
- }
1102
- const same = cur.length === rowIdxs.length && rowIdxs.every((r) => cur.includes(r));
1103
- return same ? [] : rowIdxs.slice();
1104
- }
1105
- function selectionRuleOf(container) {
1106
- try {
1107
- const el = container?.querySelector?.(`[${SELECTION_RULE_ATTR}]`);
1108
- return el?.getAttribute(SELECTION_RULE_ATTR) === SELECTION_RULE_CLICKED_MARKS ? "clicked-marks" : "any-row";
1109
- } catch {
1110
- return "any-row";
1111
- }
1112
- }
1113
- function markKeyOf(el) {
1114
- if (!el) return "";
1115
- const k = el.getAttribute(MARK_KEY_ATTR);
1116
- if (k != null && k !== "") return k;
1117
- return "rows:" + (el.getAttribute(ROW_IDX_ATTR) || "").replace(/\s+/g, "");
1118
- }
1119
- var toSet = (s) => new Set(Array.from(s ?? []));
1120
- function sameRowSet(a, b) {
1121
- const A = toSet(a), B = toSet(b);
1122
- if (A.size !== B.size) return false;
1123
- for (const r of A) if (!B.has(r)) return false;
1124
- return true;
1125
- }
1126
- function planSelectionPaint(marks, selection, rule, clicked) {
1127
- const sel = toSet(selection);
1128
- if (sel.size === 0) return { on: marks.map(() => false), mode: "none", keys: [] };
1129
- const anyRow = () => marks.map((m) => m.rows.some((r) => sel.has(r)));
1130
- if (rule !== "clicked-marks") return { on: anyRow(), mode: "any-row", keys: [] };
1131
- if (clicked && clicked.keys.length && sameRowSet(clicked.selection, sel)) {
1132
- const want = new Set(clicked.keys);
1133
- const on = marks.map((m) => m.rows.length > 0 && want.has(m.key));
1134
- if (on.some(Boolean)) return { on, mode: "clicked", keys: marks.filter((_, i) => on[i]).map((m) => m.key) };
1135
- }
1136
- const exact = marks.map((m) => m.rows.length > 0 && sameRowSet(m.rows, sel));
1137
- if (exact.some(Boolean)) return { on: exact, mode: "exact", keys: marks.filter((_, i) => exact[i]).map((m) => m.key) };
1138
- return { on: anyRow(), mode: "fallback-any-row", keys: [] };
1139
- }
1140
- function nextClickedMarks(prev, current, key, next, mods = {}) {
1141
- if (!next.length) return null;
1142
- if (!(mods.ctrl || mods.shift)) return { keys: [key], selection: next.slice() };
1143
- const held = prev && sameRowSet(prev.selection, current) ? prev.keys : [];
1144
- const keys = held.includes(key) ? held.filter((k) => k !== key) : [...held, key];
1145
- return { keys, selection: next.slice() };
1146
- }
1147
- function isInsideControl(target, container) {
1148
- let el = target;
1149
- if (el && el.nodeType !== 1) el = el.parentElement ?? el.parentNode ?? null;
1150
- while (el && el !== container) {
1151
- if (el.nodeType === 1 && el.classList?.contains?.(CONTROL_CLASS)) return true;
1152
- el = el.parentElement ?? el.parentNode ?? null;
1153
- }
1154
- return false;
1155
- }
1156
- function createMarkResolver(env) {
1157
- const { root, doc, log } = env;
1158
- const isElement = (t) => {
1159
- const E = doc?.defaultView?.Element ?? globalThis.Element;
1160
- if (E && t instanceof E) return true;
1161
- return !!t && typeof t.closest === "function" && typeof t.getAttribute === "function";
1162
- };
1163
- const viewStyle = (n) => {
1164
- try {
1165
- const gcs = doc?.defaultView?.getComputedStyle ?? (typeof getComputedStyle === "function" ? getComputedStyle : null);
1166
- return gcs ? gcs(n).pointerEvents : "";
1167
- } catch {
1168
- return "";
1169
- }
1170
- };
1171
- const isInvisibleStrokePath = (el) => {
1172
- if (el.tagName.toLowerCase() !== "path") return false;
1173
- const f2 = el.getAttribute("fill");
1174
- if (f2 !== null && f2 !== "" && f2 !== "none" && f2 !== "transparent") return false;
1175
- const s = (el.getAttribute("stroke") || "").trim().toLowerCase();
1176
- const so = parseFloat(el.getAttribute("stroke-opacity") || "1");
1177
- return s === "transparent" || s === "none" || so <= 0.01;
1178
- };
1179
- const distToPathCenterline = (el, x, y) => {
1180
- const L = el.getTotalLength();
1181
- if (!(L > 0)) return Number.MAX_VALUE;
1182
- const m = el.getScreenCTM();
1183
- if (!m) return Number.MAX_VALUE;
1184
- let best = Number.MAX_VALUE;
1185
- const N = 64;
1186
- for (let i = 0; i <= N; i++) {
1187
- const pt = el.getPointAtLength(L * i / N);
1188
- const dx = m.a * pt.x + m.c * pt.y + m.e - x;
1189
- const dy = m.b * pt.x + m.d * pt.y + m.f - y;
1190
- const d = dx * dx + dy * dy;
1191
- if (d < best) best = d;
1192
- }
1193
- return Math.sqrt(best);
1194
- };
1195
- const refineHitCorridor = (mark, x, y, sel) => {
1196
- try {
1197
- if (!mark || !isInvisibleStrokePath(mark) || !mark.getAttribute("data-row-idx")) return mark;
1198
- const stack = doc.elementsFromPoint(x, y);
1199
- const candidates = [];
1200
- for (const el of stack) {
1201
- if (!root.contains(el)) continue;
1202
- if (!el.matches || !el.matches(sel)) continue;
1203
- if (!el.getAttribute("data-row-idx")) continue;
1204
- if (!isInvisibleStrokePath(el)) continue;
1205
- candidates.push(el);
1206
- }
1207
- if (candidates.indexOf(mark) < 0) candidates.push(mark);
1208
- if (candidates.length < 2) return mark;
1209
- let best = mark;
1210
- let bestD = Number.MAX_VALUE;
1211
- for (const el of candidates) {
1212
- const d = distToPathCenterline(el, x, y);
1213
- if (d < bestD) {
1214
- bestD = d;
1215
- best = el;
1216
- }
1217
- }
1218
- if (best !== mark) {
1219
- log("d3-hit-corridor-refined", {
1220
- candidates: candidates.length,
1221
- distPx: Math.round(bestD),
1222
- fromRows: (mark.getAttribute("data-row-idx") || "").slice(0, 24),
1223
- toRows: (best.getAttribute("data-row-idx") || "").slice(0, 24)
1224
- });
1225
- }
1226
- return best;
1227
- } catch {
1228
- return mark;
1229
- }
1230
- };
1231
- const findMark = (target, sel = ".d3-mark", ev) => {
1232
- if (!isElement(target)) return null;
1233
- const el = target;
1234
- const m = el.closest(sel);
1235
- if (m && ev) return refineHitCorridor(m, ev.clientX, ev.clientY, sel);
1236
- return m;
1237
- };
1238
- const penetrateOverlayAt = (x, y, sel) => {
1239
- try {
1240
- const stack = doc.elementsFromPoint(x, y);
1241
- for (const el of stack) {
1242
- if (!root.contains(el) || !isElement(el)) continue;
1243
- const cand = el.matches(sel) ? el : el.closest(sel);
1244
- if (!cand || !root.contains(cand) || !cand.getAttribute("data-row-idx")) continue;
1245
- log("d3_click-overlay-penetrated", { tag: el.tagName, cls: el.getAttribute("class"), via: el === cand ? "self" : "closest" });
1246
- return cand;
1247
- }
1248
- } catch {
1249
- }
1250
- return null;
1251
- };
1252
- const resolveByGeometry = (x, y, sel) => {
1253
- try {
1254
- const cands = root.querySelectorAll(sel);
1255
- let best = null, bestArea = Number.MAX_VALUE;
1256
- if (cands.length <= 600) {
1257
- for (const el of Array.from(cands)) {
1258
- if (!el.getAttribute("data-row-idx")) continue;
1259
- const r = el.getBoundingClientRect ? el.getBoundingClientRect() : null;
1260
- if (!r || r.width <= 0 || r.height <= 0) continue;
1261
- if (x < r.left || x > r.right || y < r.top || y > r.bottom) continue;
1262
- const area2 = r.width * r.height;
1263
- if (area2 < bestArea) {
1264
- bestArea = area2;
1265
- best = el;
1266
- }
1267
- }
1268
- }
1269
- const hasHittableShape = (node) => {
1270
- const SHAPE = /^(rect|circle|ellipse|path|line|polygon|polyline|text|image|use)$/;
1271
- const all = [node, ...Array.from(node.querySelectorAll("*"))];
1272
- for (const n of all) {
1273
- const tag = (n.tagName || "").toLowerCase();
1274
- if (!SHAPE.test(tag)) continue;
1275
- const pe = viewStyle(n);
1276
- if (pe && pe !== "none") return true;
1277
- }
1278
- return false;
1279
- };
1280
- if (best && !hasHittableShape(best)) {
1281
- log("d3_click-geom-resolved", { rows: (best.getAttribute("data-row-idx") || "").slice(0, 24) });
1282
- return best;
1283
- } else if (best) {
1284
- log("d3_click-geom-skip-hittable", {});
1285
- }
1286
- } catch {
1287
- }
1288
- return null;
1289
- };
1290
- return { isInvisibleStrokePath, distToPathCenterline, refineHitCorridor, findMark, rowIdxsFromMark, penetrateOverlayAt, resolveByGeometry };
1291
- }
1292
- function collectD3GlyphCenters(container, baseRect, out) {
1293
- const Point = container.ownerDocument?.defaultView?.DOMPoint ?? globalThis.DOMPoint;
1294
- const marks = container.querySelectorAll(`.${MARK_CLASS}.${MARK_SELECTED_CLASS}`);
1295
- const rects = [];
1296
- for (let i = 0; i < marks.length; i++) {
1297
- const r = marks[i].getBoundingClientRect();
1298
- rects.push(r);
1299
- }
1300
- const CONTAINMENT_CAP = 300;
1301
- const EPS2 = 1;
1302
- const filterContainers = marks.length <= CONTAINMENT_CAP;
1303
- const enclosesAnother = (ci) => {
1304
- const c = rects[ci];
1305
- const cArea = c.width * c.height;
1306
- if (cArea <= 0) return false;
1307
- for (let mj = 0; mj < rects.length; mj++) {
1308
- if (mj === ci) continue;
1309
- const m = rects[mj];
1310
- const mArea = m.width * m.height;
1311
- if (mArea <= 0 || mArea >= cArea) continue;
1312
- if (m.left >= c.left - EPS2 && m.right <= c.right + EPS2 && m.top >= c.top - EPS2 && m.bottom <= c.bottom + EPS2) return true;
1313
- }
1314
- return false;
1315
- };
1316
- for (let i = 0; i < marks.length; i++) {
1317
- const el = marks[i];
1318
- const r = rects[i];
1319
- if (r.width === 0 && r.height === 0) continue;
1320
- if (filterContainers && enclosesAnother(i)) continue;
1321
- const tag = el.tagName.toLowerCase();
1322
- let sx;
1323
- let sy;
1324
- const cxA = el.getAttribute("data-cx"), cyA = el.getAttribute("data-cy");
1325
- if (cxA != null && cyA != null && typeof el.getScreenCTM === "function") {
1326
- const ctm = el.getScreenCTM();
1327
- const cxN = parseFloat(cxA), cyN = parseFloat(cyA);
1328
- if (ctm && isFinite(cxN) && isFinite(cyN)) {
1329
- const p = new Point(cxN, cyN).matrixTransform(ctm);
1330
- sx = p.x;
1331
- sy = p.y;
1332
- }
1333
- }
1334
- if (sx === void 0 && tag === "path" && typeof el.getPointAtLength === "function") {
1335
- try {
1336
- const len = el.getTotalLength();
1337
- const ctm = el.getScreenCTM();
1338
- if (len > 0 && ctm) {
1339
- const dAttr = el.getAttribute("d") || "";
1340
- const isArcSector = /[Aa]/.test(dAttr) && !/[CcSsQqTt]/.test(dAttr);
1341
- let local;
1342
- if (isArcSector) {
1343
- const N = 24;
1344
- let ax = 0, ay = 0;
1345
- for (let k = 0; k < N; k++) {
1346
- const sp = el.getPointAtLength(len * k / N);
1347
- ax += sp.x;
1348
- ay += sp.y;
1349
- }
1350
- const cand = new Point(ax / N, ay / N);
1351
- let inside = true;
1352
- try {
1353
- if (typeof el.isPointInFill === "function") {
1354
- inside = el.isPointInFill(cand);
1355
- }
1356
- } catch {
1357
- inside = true;
1358
- }
1359
- if (inside) local = cand;
1360
- }
1361
- if (!local) local = el.getPointAtLength(len / 2);
1362
- const p = local.matrixTransform(ctm);
1363
- sx = p.x;
1364
- sy = p.y;
1365
- }
1366
- } catch {
1367
- }
1368
- }
1369
- if (sx === void 0 || sy === void 0) {
1370
- const isRect = tag === "rect";
1371
- sx = isRect ? r.left + r.width * 0.8 : r.left + r.width / 2;
1372
- sy = isRect ? r.top + r.height * 0.2 : r.top + r.height / 2;
1373
- }
1374
- out.push({ x: sx - baseRect.left, y: sy - baseRect.top });
1375
- }
1376
- }
1377
- var SELECTION_GLYPH_CLASS = "lch-sel-glyph";
1378
- function clearSelectionGlyphs(overlay) {
1379
- if (overlay) {
1380
- while (overlay.firstChild) overlay.removeChild(overlay.firstChild);
1381
- }
1382
- }
1383
- function paintSelectionGlyphs(overlay, centers, style) {
1384
- const doc = overlay.ownerDocument;
1385
- const frag = doc.createDocumentFragment();
1386
- const count = Math.min(centers.length, style.max ?? 600);
1387
- for (let i = 0; i < count; i++) {
1388
- const c = centers[i];
1389
- const g = doc.createElement("span");
1390
- g.className = SELECTION_GLYPH_CLASS;
1391
- g.textContent = style.symbol;
1392
- g.style.position = "absolute";
1393
- g.style.left = c.x + "px";
1394
- g.style.top = c.y + "px";
1395
- g.style.transform = "translate(-50%, -50%)";
1396
- g.style.font = "700 11px/1 system-ui, -apple-system, Segoe UI, sans-serif";
1397
- g.style.color = style.color;
1398
- const halo = style.halo;
1399
- g.style.textShadow = `-1px -1px 1px ${halo}, 1px -1px 1px ${halo}, -1px 1px 1px ${halo}, 1px 1px 1px ${halo}, 0 0 2px ${halo}`;
1400
- g.style.pointerEvents = "none";
1401
- frag.appendChild(g);
1402
- }
1403
- overlay.appendChild(frag);
1404
- return count;
1405
- }
1406
-
1407
- // src/hitTargets.ts
1408
- var SVG_NS = "http://www.w3.org/2000/svg";
1409
- var HIT_ATTR = "data-lch-hit";
1410
- var ELEMENT_CAP2 = 5e3;
1411
- var mapsPresentationAttributes = /* @__PURE__ */ new WeakMap();
1412
- function engineMapsPresentationAttributes(ownerDoc, view) {
1413
- if (!ownerDoc || typeof ownerDoc !== "object") return false;
1414
- const known = mapsPresentationAttributes.get(ownerDoc);
1415
- if (known !== void 0) return known;
1416
- let maps = false;
1417
- try {
1418
- const host = ownerDoc.documentElement;
1419
- const probe = ownerDoc.createElementNS(SVG_NS, "svg");
1420
- const shape = ownerDoc.createElementNS(SVG_NS, "rect");
1421
- shape.setAttribute("fill", "none");
1422
- probe.appendChild(shape);
1423
- host.appendChild(probe);
1424
- try {
1425
- maps = String(view.getComputedStyle(shape).fill ?? "").trim().toLowerCase() === "none";
1426
- } finally {
1427
- host.removeChild(probe);
1428
- }
1429
- } catch {
1430
- maps = false;
1431
- }
1432
- mapsPresentationAttributes.set(ownerDoc, maps);
1433
- return maps;
1434
- }
1435
- function ensureCrossfilterHitTargets(container, doc) {
1436
- const report = { tagged: 0, hitRects: 0, peFlips: 0, peStrokeOnly: 0 };
1437
- try {
1438
- if (!container || typeof container.querySelectorAll !== "function") return report;
1439
- const els = container.querySelectorAll(
1440
- `.${MARK_CLASS}, .${LEGEND_MARK_CLASS}, .${AXIS_FILTER_CLASS}`
1441
- );
1442
- report.tagged = els.length;
1443
- if (els.length === 0 || els.length > ELEMENT_CAP2) return report;
1444
- const ownerDoc = doc ?? container.ownerDocument;
1445
- const view = ownerDoc?.defaultView;
1446
- const computed = (el) => {
1447
- try {
1448
- return view?.getComputedStyle ? view.getComputedStyle(el) : null;
1449
- } catch {
1450
- return null;
1451
- }
1452
- };
1453
- for (const el of Array.from(els)) {
1454
- const tag = String(el.tagName || "").toLowerCase();
1455
- if (tag === "g") {
1456
- if (!el.hasAttribute?.(ROW_IDX_ATTR)) continue;
1457
- if (el.querySelector?.(`rect[${HIT_ATTR}="1"]`)) continue;
1458
- const cls = el.getAttribute?.("class") || "";
1459
- const isFurniture = cls.indexOf(LEGEND_MARK_CLASS) >= 0 || cls.indexOf(AXIS_FILTER_CLASS) >= 0;
1460
- if (!isFurniture) {
1461
- let hasHittableChild = false;
1462
- const kids = el.querySelectorAll?.("*") ?? [];
1463
- for (const kid of Array.from(kids)) {
1464
- const ktag = String(kid.tagName || "").toLowerCase();
1465
- if (ktag === "g" || ktag === "tspan" || ktag === "title" || ktag === "defs") continue;
1466
- const cs = computed(kid);
1467
- if (!cs || cs.pointerEvents !== "none") {
1468
- hasHittableChild = true;
1469
- break;
1470
- }
1471
- }
1472
- if (hasHittableChild) continue;
1473
- }
1474
- let bb = null;
1475
- try {
1476
- bb = el.getBBox?.();
1477
- } catch {
1478
- bb = null;
1479
- }
1480
- if (!bb || !(bb.width > 0) || !(bb.height > 0)) continue;
1481
- const rect = ownerDoc.createElementNS(SVG_NS, "rect");
1482
- rect.setAttribute("x", String(bb.x));
1483
- rect.setAttribute("y", String(bb.y));
1484
- rect.setAttribute("width", String(bb.width));
1485
- rect.setAttribute("height", String(bb.height));
1486
- rect.setAttribute("fill", "transparent");
1487
- rect.setAttribute(HIT_ATTR, "1");
1488
- if (rect.style) {
1489
- rect.style.pointerEvents = "all";
1490
- rect.style.cursor = "pointer";
1491
- }
1492
- el.insertBefore(rect, el.firstChild);
1493
- report.hitRects++;
1494
- } else {
1495
- const cs = computed(el);
1496
- if (cs && cs.pointerEvents === "none") {
1497
- const fill = String((engineMapsPresentationAttributes(ownerDoc, view) ? cs.fill : el.getAttribute?.("fill") ?? cs.fill) ?? "").trim().toLowerCase();
1498
- const unfilled = fill === "none" || fill === "transparent" || fill === "rgba(0, 0, 0, 0)";
1499
- if (el.style) el.style.pointerEvents = unfilled ? "stroke" : "all";
1500
- report.peFlips++;
1501
- if (unfilled) report.peStrokeOnly++;
1502
- }
1503
- }
1504
- }
1505
- } catch {
1506
- }
1507
- return report;
1508
- }
1509
-
1510
1088
  // src/blankRender.ts
1511
1089
  var EMPTY2 = { markCount: 0, legendMarkCount: 0, containerKind: "empty", declaresNoRowMarks: false };
1512
1090
  function censusMarks(container) {
@@ -1545,87 +1123,6 @@ function blankRenderFlag(lang, cause) {
1545
1123
  return `blankrender:${clean(lang)}:${clean(cause)}`;
1546
1124
  }
1547
1125
 
1548
- // src/hitBands.ts
1549
- var MIN_HIT_BAND_PX = 8;
1550
- var ELEMENT_CAP3 = 5e3;
1551
- var EMPTY3 = {
1552
- openStrokes: 0,
1553
- interactive: 0,
1554
- hairline: 0,
1555
- uncovered: 0,
1556
- widestPx: 0
1557
- };
1558
- var OPEN_TAGS = /* @__PURE__ */ new Set(["path", "line", "polyline"]);
1559
- function styleOf2(el, doc) {
1560
- try {
1561
- const view = doc?.defaultView;
1562
- return view?.getComputedStyle ? view.getComputedStyle(el) : null;
1563
- } catch {
1564
- return null;
1565
- }
1566
- }
1567
- function attrOrComputed(el, name, cs) {
1568
- const a = el.getAttribute?.(name);
1569
- if (a !== null && a !== void 0 && String(a).trim() !== "") return String(a).trim();
1570
- const c = cs?.[name === "stroke-width" ? "strokeWidth" : name];
1571
- return c === null || c === void 0 ? "" : String(c).trim();
1572
- }
1573
- function isUnfilled(fill) {
1574
- const f2 = fill.toLowerCase();
1575
- return f2 === "none" || f2 === "transparent" || f2 === "rgba(0, 0, 0, 0)" || f2 === "rgba(0,0,0,0)";
1576
- }
1577
- function widthPx(raw) {
1578
- const m = /^(-?\d+(?:\.\d+)?)\s*(px)?$/i.exec(raw);
1579
- if (!m) return NaN;
1580
- const n = parseFloat(m[1]);
1581
- return isFinite(n) ? n : NaN;
1582
- }
1583
- function censusHitBands(container, doc) {
1584
- if (!container || typeof container.querySelectorAll !== "function") return EMPTY3;
1585
- try {
1586
- const els = Array.from(
1587
- container.querySelectorAll(`.${MARK_CLASS}, [${ROW_IDX_ATTR}]`)
1588
- );
1589
- if (els.length === 0 || els.length > ELEMENT_CAP3) return EMPTY3;
1590
- const ownerDoc = doc ?? container.ownerDocument;
1591
- const widestByGeom = /* @__PURE__ */ new Map();
1592
- const rows = [];
1593
- for (const el of els) {
1594
- const tag = String(el.tagName || "").toLowerCase();
1595
- if (!OPEN_TAGS.has(tag)) continue;
1596
- const cs = styleOf2(el, ownerDoc);
1597
- const open = isUnfilled(attrOrComputed(el, "fill", cs));
1598
- const w = widthPx(attrOrComputed(el, "stroke-width", cs) || "1");
1599
- const geom = String(el.getAttribute?.("d") ?? "") || `${tag}#${String(el.getAttribute?.(ROW_IDX_ATTR) ?? "")}`;
1600
- const inert = String(cs?.pointerEvents ?? el.style?.pointerEvents ?? "") === "none";
1601
- rows.push({ el, geom, w, open, inert });
1602
- if (isFinite(w)) {
1603
- const prev = widestByGeom.get(geom);
1604
- if (prev === void 0 || w > prev) widestByGeom.set(geom, w);
1605
- }
1606
- }
1607
- const out = { ...EMPTY3 };
1608
- for (const r of rows) {
1609
- if (!r.open) continue;
1610
- out.openStrokes++;
1611
- if (r.inert) continue;
1612
- out.interactive++;
1613
- if (isFinite(r.w) && r.w > out.widestPx) out.widestPx = Math.round(r.w);
1614
- if (!(r.w < MIN_HIT_BAND_PX)) continue;
1615
- out.hairline++;
1616
- const best = widestByGeom.get(r.geom);
1617
- if (best === void 0 || best < MIN_HIT_BAND_PX) out.uncovered++;
1618
- }
1619
- return out;
1620
- } catch {
1621
- return EMPTY3;
1622
- }
1623
- }
1624
- function hitBandFlag(c) {
1625
- if (c.interactive === 0) return "";
1626
- return c.uncovered > 0 ? "hitband:d3:thin" : "hitband:d3:ok";
1627
- }
1628
-
1629
1126
  // src/clippedText.ts
1630
1127
  var CLIP_TOLERANCE_PX = 1;
1631
1128
  var MAX_REPORTED = 8;
@@ -1671,11 +1168,11 @@ function clippedTextFlag(c) {
1671
1168
 
1672
1169
  // src/valuePlacement.ts
1673
1170
  var MIN_MARKS2 = 24;
1674
- var ELEMENT_CAP4 = 5e3;
1171
+ var ELEMENT_CAP2 = 5e3;
1675
1172
  var FIT_SAMPLE = 90;
1676
1173
  var VALUE_AXIS_MIN_FIT = 0.8;
1677
1174
  var MIN_AXIS_SPAN_PX = 40;
1678
- var EMPTY4 = { marks: 0, axis: "", column: "", fit: 0, offShare: 0, medianOffRadii: 0 };
1175
+ var EMPTY3 = { marks: 0, axis: "", column: "", fit: 0, offShare: 0, medianOffRadii: 0 };
1679
1176
  function num(el, name) {
1680
1177
  const v = el.getAttribute?.(name);
1681
1178
  if (v === null || v === void 0 || String(v).trim() === "") return NaN;
@@ -1708,12 +1205,12 @@ function robustLine(v, pos) {
1708
1205
  }
1709
1206
  function censusValuePlacement(container, data) {
1710
1207
  try {
1711
- if (!container || typeof container.querySelectorAll !== "function") return EMPTY4;
1208
+ if (!container || typeof container.querySelectorAll !== "function") return EMPTY3;
1712
1209
  const rows = data?.rows;
1713
1210
  const columns = data?.columns ?? [];
1714
- if (!Array.isArray(rows) || !rows.length || !columns.length) return EMPTY4;
1211
+ if (!Array.isArray(rows) || !rows.length || !columns.length) return EMPTY3;
1715
1212
  const els = Array.from(container.querySelectorAll(`circle[${ROW_IDX_ATTR}]`));
1716
- if (els.length < MIN_MARKS2 || els.length > ELEMENT_CAP4) return EMPTY4;
1213
+ if (els.length < MIN_MARKS2 || els.length > ELEMENT_CAP2) return EMPTY3;
1717
1214
  const dots = [];
1718
1215
  const seen = /* @__PURE__ */ new Set();
1719
1216
  for (const el of els) {
@@ -1726,7 +1223,7 @@ function censusValuePlacement(container, data) {
1726
1223
  seen.add(i);
1727
1224
  dots.push({ row, x, y, r });
1728
1225
  }
1729
- if (dots.length < MIN_MARKS2 || seen.size < dots.length * 0.9) return EMPTY4;
1226
+ if (dots.length < MIN_MARKS2 || seen.size < dots.length * 0.9) return EMPTY3;
1730
1227
  let best = null;
1731
1228
  for (let c = 0; c < columns.length; c++) {
1732
1229
  if (/^__.*__$/.test(String(columns[c]?.name ?? ""))) continue;
@@ -1771,7 +1268,7 @@ function censusValuePlacement(container, data) {
1771
1268
  }
1772
1269
  }
1773
1270
  }
1774
- if (!best) return EMPTY4;
1271
+ if (!best) return EMPTY3;
1775
1272
  let off = 0, measured = 0;
1776
1273
  const radii = [];
1777
1274
  dots.forEach((d, k) => {
@@ -1782,7 +1279,7 @@ function censusValuePlacement(container, data) {
1782
1279
  radii.push(inRadii);
1783
1280
  if (inRadii > 1) off++;
1784
1281
  });
1785
- if (measured < MIN_MARKS2) return EMPTY4;
1282
+ if (measured < MIN_MARKS2) return EMPTY3;
1786
1283
  return {
1787
1284
  marks: measured,
1788
1285
  axis: best.axis,
@@ -1792,7 +1289,7 @@ function censusValuePlacement(container, data) {
1792
1289
  medianOffRadii: Math.round(median(radii) * 100) / 100
1793
1290
  };
1794
1291
  } catch {
1795
- return EMPTY4;
1292
+ return EMPTY3;
1796
1293
  }
1797
1294
  }
1798
1295
  function valuePlacementFlag(c) {
@@ -2036,7 +1533,7 @@ function fitReadingFor(lane, c, slackPx = SCROLL_SLACK_PX, inkOf) {
2036
1533
  }
2037
1534
  var noPin = (reason) => ({ pinned: false, reason, bandPx: 0, axisAt: "", labels: 0, carried: 0, edge: null });
2038
1535
  var CONTAINER_SLOT_AXIS_PIN = "__bicAxisPin";
2039
- var SVG_NS2 = "http://www.w3.org/2000/svg";
1536
+ var SVG_NS = "http://www.w3.org/2000/svg";
2040
1537
  var AXIS_PIN_MAX_CARRIED = 12;
2041
1538
  function unpinScrolledAxis(container) {
2042
1539
  if (!container) return;
@@ -2174,7 +1671,7 @@ function pinScrolledAxis(container, svg) {
2174
1671
  if (!(r.right > r.left) || !(r.bottom > r.top)) continue;
2175
1672
  if (r.top >= band.top && r.bottom <= band.bottom) carried.push(t);
2176
1673
  }
2177
- const pinSvg = doc.createElementNS(SVG_NS2, "svg");
1674
+ const pinSvg = doc.createElementNS(SVG_NS, "svg");
2178
1675
  for (const a of ["font-family", "font-size", "font-weight", "font", "fill", "color", "text-rendering"]) {
2179
1676
  const v = svg.getAttribute(a);
2180
1677
  if (v) pinSvg.setAttribute(a, v);
@@ -2190,7 +1687,7 @@ function pinScrolledAxis(container, svg) {
2190
1687
  pinSvg.setAttribute("aria-hidden", "true");
2191
1688
  pinSvg.style.display = "block";
2192
1689
  pinSvg.style.pointerEvents = "none";
2193
- const back = doc.createElementNS(SVG_NS2, "rect");
1690
+ const back = doc.createElementNS(SVG_NS, "rect");
2194
1691
  back.setAttribute("x", String(vbX));
2195
1692
  back.setAttribute("y", String(vbY));
2196
1693
  back.setAttribute("width", String(vbW));
@@ -2355,7 +1852,7 @@ function fitRenderedChart(container, opts = {}) {
2355
1852
  // src/labelContrastDom.ts
2356
1853
  var LABEL_CONTRAST_DONE_ATTR = "data-lch-contrast";
2357
1854
  var LABEL_CONTRAST_CAP = 2e3;
2358
- var EMPTY5 = {
1855
+ var EMPTY4 = {
2359
1856
  rects: 0,
2360
1857
  scanned: 0,
2361
1858
  fixed: 0,
@@ -2506,7 +2003,7 @@ function addPill(tx, fill) {
2506
2003
  }
2507
2004
  }
2508
2005
  function applyLabelContrast(container, opts = {}) {
2509
- const report = { ...EMPTY5 };
2006
+ const report = { ...EMPTY4 };
2510
2007
  if (!container) {
2511
2008
  report.skipped = "no-container";
2512
2009
  return report;
@@ -3540,7 +3037,7 @@ function createChartHost(container, config) {
3540
3037
  }
3541
3038
 
3542
3039
  // src/group.ts
3543
- var EMPTY6 = Object.freeze({ sourceId: null, rows: Object.freeze([]) });
3040
+ var EMPTY5 = Object.freeze({ sourceId: null, rows: Object.freeze([]) });
3544
3041
  function toSourceRows(rowMap, payloadRowIdxs) {
3545
3042
  if (!rowMap) return payloadRowIdxs.slice();
3546
3043
  return payloadRowIdxs.map((i) => rowMap[i]).filter((i) => i !== void 0);
@@ -3578,7 +3075,7 @@ function createChartGroup(columns, rows, opts = {}) {
3578
3075
  let geo = opts.geo ?? null;
3579
3076
  let point = opts.point ?? null;
3580
3077
  let destination = opts.destination ?? null;
3581
- let selection = EMPTY6;
3078
+ let selection = EMPTY5;
3582
3079
  const subs = /* @__PURE__ */ new Set();
3583
3080
  const members = /* @__PURE__ */ new Set();
3584
3081
  const notify = (change) => {
@@ -3731,26 +3228,9 @@ export {
3731
3228
  clearGeoCache,
3732
3229
  buildRenderPayload,
3733
3230
  stripJsComments,
3734
- rowIdxsFromMark,
3735
- nextSelection,
3736
- selectionRuleOf,
3737
- markKeyOf,
3738
- sameRowSet,
3739
- planSelectionPaint,
3740
- nextClickedMarks,
3741
- isInsideControl,
3742
- createMarkResolver,
3743
- collectD3GlyphCenters,
3744
- SELECTION_GLYPH_CLASS,
3745
- clearSelectionGlyphs,
3746
- paintSelectionGlyphs,
3747
- ensureCrossfilterHitTargets,
3748
3231
  censusMarks,
3749
3232
  isBlankRender,
3750
3233
  blankRenderFlag,
3751
- MIN_HIT_BAND_PX,
3752
- censusHitBands,
3753
- hitBandFlag,
3754
3234
  CLIP_TOLERANCE_PX,
3755
3235
  censusClippedText,
3756
3236
  clippedTextFlag,