@bicharts/chart-host 0.6.83 → 0.6.85

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.
@@ -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") Object.assign(out, ui.knobs);
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
- Dr,
3
+ Ct,
4
4
  Z,
5
5
  g,
6
- ht,
7
- kr,
8
- pt
9
- } from "./chunk-2XWE6YFO.mjs";
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 pt(col).suppressed;
438
+ return xt(col).suppressed;
439
439
  }
440
440
  function resolveAgg(col, requested, auto) {
441
441
  const fallback = () => {
442
- const d = Dr(col);
442
+ const d = ni(col);
443
443
  return d === "first" ? "count" : d;
444
444
  };
445
445
  if (auto) return fallback();
446
- return ht(col).indexOf(requested) >= 0 ? requested : fallback();
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 (kr(col, colAgg) && value != null) {
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
- } from "./chunk-7JWL6LYE.mjs";
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.14.0";
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";