@bicharts/chart-host 0.6.41 → 0.6.43
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/{chunk-NMEXSUOR.mjs → chunk-MVM2R7K7.mjs} +173 -23
- package/dist/index.mjs +13 -1
- package/dist/react.mjs +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/selection.d.ts +61 -0
- package/package.json +1 -1
|
@@ -2030,6 +2030,30 @@ function stripJsComments(code) {
|
|
|
2030
2030
|
}
|
|
2031
2031
|
|
|
2032
2032
|
// src/selection.ts
|
|
2033
|
+
function rowIdxsFromMark(el) {
|
|
2034
|
+
if (!el) return [];
|
|
2035
|
+
const raw = el.getAttribute("data-row-idx");
|
|
2036
|
+
if (!raw) return [];
|
|
2037
|
+
const out = [];
|
|
2038
|
+
for (const tok of raw.split(",")) {
|
|
2039
|
+
const n = parseInt(tok.trim(), 10);
|
|
2040
|
+
if (!isNaN(n) && n >= 0) out.push(n);
|
|
2041
|
+
}
|
|
2042
|
+
return out;
|
|
2043
|
+
}
|
|
2044
|
+
function nextSelection(current, rowIdxs, mods = {}) {
|
|
2045
|
+
const cur = Array.from(current ?? []);
|
|
2046
|
+
if (mods.ctrl || mods.shift) {
|
|
2047
|
+
const next = new Set(cur);
|
|
2048
|
+
for (const r2 of rowIdxs) {
|
|
2049
|
+
if (next.has(r2)) next.delete(r2);
|
|
2050
|
+
else next.add(r2);
|
|
2051
|
+
}
|
|
2052
|
+
return Array.from(next);
|
|
2053
|
+
}
|
|
2054
|
+
const same = cur.length === rowIdxs.length && rowIdxs.every((r2) => cur.includes(r2));
|
|
2055
|
+
return same ? [] : rowIdxs.slice();
|
|
2056
|
+
}
|
|
2033
2057
|
function isInsideControl(target, container) {
|
|
2034
2058
|
let el = target;
|
|
2035
2059
|
if (el && el.nodeType !== 1) el = el.parentElement ?? el.parentNode ?? null;
|
|
@@ -2121,17 +2145,6 @@ function createMarkResolver(env) {
|
|
|
2121
2145
|
if (m2 && ev) return refineHitCorridor(m2, ev.clientX, ev.clientY, sel);
|
|
2122
2146
|
return m2;
|
|
2123
2147
|
};
|
|
2124
|
-
const rowIdxsFromMark = (el) => {
|
|
2125
|
-
if (!el) return [];
|
|
2126
|
-
const raw = el.getAttribute("data-row-idx");
|
|
2127
|
-
if (!raw) return [];
|
|
2128
|
-
const out = [];
|
|
2129
|
-
for (const tok of raw.split(",")) {
|
|
2130
|
-
const n = parseInt(tok.trim(), 10);
|
|
2131
|
-
if (!isNaN(n) && n >= 0) out.push(n);
|
|
2132
|
-
}
|
|
2133
|
-
return out;
|
|
2134
|
-
};
|
|
2135
2148
|
const penetrateOverlayAt = (x3, y4, sel) => {
|
|
2136
2149
|
try {
|
|
2137
2150
|
const stack = doc.elementsFromPoint(x3, y4);
|
|
@@ -2186,11 +2199,149 @@ function createMarkResolver(env) {
|
|
|
2186
2199
|
};
|
|
2187
2200
|
return { isInvisibleStrokePath, distToPathCenterline, refineHitCorridor, findMark, rowIdxsFromMark, penetrateOverlayAt, resolveByGeometry };
|
|
2188
2201
|
}
|
|
2202
|
+
function collectD3GlyphCenters(container, baseRect, out) {
|
|
2203
|
+
const Point = container.ownerDocument?.defaultView?.DOMPoint ?? globalThis.DOMPoint;
|
|
2204
|
+
const marks = container.querySelectorAll(`.${MARK_CLASS}.${MARK_SELECTED_CLASS}`);
|
|
2205
|
+
const rects = [];
|
|
2206
|
+
for (let i = 0; i < marks.length; i++) {
|
|
2207
|
+
const r2 = marks[i].getBoundingClientRect();
|
|
2208
|
+
rects.push(r2);
|
|
2209
|
+
}
|
|
2210
|
+
const CONTAINMENT_CAP = 300;
|
|
2211
|
+
const EPS2 = 1;
|
|
2212
|
+
const filterContainers = marks.length <= CONTAINMENT_CAP;
|
|
2213
|
+
const enclosesAnother = (ci) => {
|
|
2214
|
+
const c2 = rects[ci];
|
|
2215
|
+
const cArea = c2.width * c2.height;
|
|
2216
|
+
if (cArea <= 0) return false;
|
|
2217
|
+
for (let mj = 0; mj < rects.length; mj++) {
|
|
2218
|
+
if (mj === ci) continue;
|
|
2219
|
+
const m2 = rects[mj];
|
|
2220
|
+
const mArea = m2.width * m2.height;
|
|
2221
|
+
if (mArea <= 0 || mArea >= cArea) continue;
|
|
2222
|
+
if (m2.left >= c2.left - EPS2 && m2.right <= c2.right + EPS2 && m2.top >= c2.top - EPS2 && m2.bottom <= c2.bottom + EPS2) return true;
|
|
2223
|
+
}
|
|
2224
|
+
return false;
|
|
2225
|
+
};
|
|
2226
|
+
for (let i = 0; i < marks.length; i++) {
|
|
2227
|
+
const el = marks[i];
|
|
2228
|
+
const r2 = rects[i];
|
|
2229
|
+
if (r2.width === 0 && r2.height === 0) continue;
|
|
2230
|
+
if (filterContainers && enclosesAnother(i)) continue;
|
|
2231
|
+
const tag = el.tagName.toLowerCase();
|
|
2232
|
+
let sx;
|
|
2233
|
+
let sy;
|
|
2234
|
+
const cxA = el.getAttribute("data-cx"), cyA = el.getAttribute("data-cy");
|
|
2235
|
+
if (cxA != null && cyA != null && typeof el.getScreenCTM === "function") {
|
|
2236
|
+
const ctm = el.getScreenCTM();
|
|
2237
|
+
const cxN = parseFloat(cxA), cyN = parseFloat(cyA);
|
|
2238
|
+
if (ctm && isFinite(cxN) && isFinite(cyN)) {
|
|
2239
|
+
const p2 = new Point(cxN, cyN).matrixTransform(ctm);
|
|
2240
|
+
sx = p2.x;
|
|
2241
|
+
sy = p2.y;
|
|
2242
|
+
}
|
|
2243
|
+
}
|
|
2244
|
+
if (sx === void 0 && tag === "path" && typeof el.getPointAtLength === "function") {
|
|
2245
|
+
try {
|
|
2246
|
+
const len = el.getTotalLength();
|
|
2247
|
+
const ctm = el.getScreenCTM();
|
|
2248
|
+
if (len > 0 && ctm) {
|
|
2249
|
+
const dAttr = el.getAttribute("d") || "";
|
|
2250
|
+
const isArcSector = /[Aa]/.test(dAttr) && !/[CcSsQqTt]/.test(dAttr);
|
|
2251
|
+
let local;
|
|
2252
|
+
if (isArcSector) {
|
|
2253
|
+
const N2 = 24;
|
|
2254
|
+
let ax = 0, ay = 0;
|
|
2255
|
+
for (let k3 = 0; k3 < N2; k3++) {
|
|
2256
|
+
const sp = el.getPointAtLength(len * k3 / N2);
|
|
2257
|
+
ax += sp.x;
|
|
2258
|
+
ay += sp.y;
|
|
2259
|
+
}
|
|
2260
|
+
const cand = new Point(ax / N2, ay / N2);
|
|
2261
|
+
let inside = true;
|
|
2262
|
+
try {
|
|
2263
|
+
if (typeof el.isPointInFill === "function") {
|
|
2264
|
+
inside = el.isPointInFill(cand);
|
|
2265
|
+
}
|
|
2266
|
+
} catch {
|
|
2267
|
+
inside = true;
|
|
2268
|
+
}
|
|
2269
|
+
if (inside) local = cand;
|
|
2270
|
+
}
|
|
2271
|
+
if (!local) local = el.getPointAtLength(len / 2);
|
|
2272
|
+
const p2 = local.matrixTransform(ctm);
|
|
2273
|
+
sx = p2.x;
|
|
2274
|
+
sy = p2.y;
|
|
2275
|
+
}
|
|
2276
|
+
} catch {
|
|
2277
|
+
}
|
|
2278
|
+
}
|
|
2279
|
+
if (sx === void 0 || sy === void 0) {
|
|
2280
|
+
const isRect = tag === "rect";
|
|
2281
|
+
sx = isRect ? r2.left + r2.width * 0.8 : r2.left + r2.width / 2;
|
|
2282
|
+
sy = isRect ? r2.top + r2.height * 0.2 : r2.top + r2.height / 2;
|
|
2283
|
+
}
|
|
2284
|
+
out.push({ x: sx - baseRect.left, y: sy - baseRect.top });
|
|
2285
|
+
}
|
|
2286
|
+
}
|
|
2287
|
+
var SELECTION_GLYPH_CLASS = "lch-sel-glyph";
|
|
2288
|
+
function clearSelectionGlyphs(overlay) {
|
|
2289
|
+
if (overlay) {
|
|
2290
|
+
while (overlay.firstChild) overlay.removeChild(overlay.firstChild);
|
|
2291
|
+
}
|
|
2292
|
+
}
|
|
2293
|
+
function paintSelectionGlyphs(overlay, centers, style) {
|
|
2294
|
+
const doc = overlay.ownerDocument;
|
|
2295
|
+
const frag = doc.createDocumentFragment();
|
|
2296
|
+
const count = Math.min(centers.length, style.max ?? 600);
|
|
2297
|
+
for (let i = 0; i < count; i++) {
|
|
2298
|
+
const c2 = centers[i];
|
|
2299
|
+
const g3 = doc.createElement("span");
|
|
2300
|
+
g3.className = SELECTION_GLYPH_CLASS;
|
|
2301
|
+
g3.textContent = style.symbol;
|
|
2302
|
+
g3.style.position = "absolute";
|
|
2303
|
+
g3.style.left = c2.x + "px";
|
|
2304
|
+
g3.style.top = c2.y + "px";
|
|
2305
|
+
g3.style.transform = "translate(-50%, -50%)";
|
|
2306
|
+
g3.style.font = "700 11px/1 system-ui, -apple-system, Segoe UI, sans-serif";
|
|
2307
|
+
g3.style.color = style.color;
|
|
2308
|
+
const halo = style.halo;
|
|
2309
|
+
g3.style.textShadow = `-1px -1px 1px ${halo}, 1px -1px 1px ${halo}, -1px 1px 1px ${halo}, 1px 1px 1px ${halo}, 0 0 2px ${halo}`;
|
|
2310
|
+
g3.style.pointerEvents = "none";
|
|
2311
|
+
frag.appendChild(g3);
|
|
2312
|
+
}
|
|
2313
|
+
overlay.appendChild(frag);
|
|
2314
|
+
return count;
|
|
2315
|
+
}
|
|
2189
2316
|
|
|
2190
2317
|
// src/hitTargets.ts
|
|
2191
2318
|
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
2192
2319
|
var HIT_ATTR = "data-lch-hit";
|
|
2193
2320
|
var ELEMENT_CAP2 = 5e3;
|
|
2321
|
+
var mapsPresentationAttributes = /* @__PURE__ */ new WeakMap();
|
|
2322
|
+
function engineMapsPresentationAttributes(ownerDoc, view) {
|
|
2323
|
+
if (!ownerDoc || typeof ownerDoc !== "object") return false;
|
|
2324
|
+
const known = mapsPresentationAttributes.get(ownerDoc);
|
|
2325
|
+
if (known !== void 0) return known;
|
|
2326
|
+
let maps = false;
|
|
2327
|
+
try {
|
|
2328
|
+
const host = ownerDoc.documentElement;
|
|
2329
|
+
const probe = ownerDoc.createElementNS(SVG_NS, "svg");
|
|
2330
|
+
const shape = ownerDoc.createElementNS(SVG_NS, "rect");
|
|
2331
|
+
shape.setAttribute("fill", "none");
|
|
2332
|
+
probe.appendChild(shape);
|
|
2333
|
+
host.appendChild(probe);
|
|
2334
|
+
try {
|
|
2335
|
+
maps = String(view.getComputedStyle(shape).fill ?? "").trim().toLowerCase() === "none";
|
|
2336
|
+
} finally {
|
|
2337
|
+
host.removeChild(probe);
|
|
2338
|
+
}
|
|
2339
|
+
} catch {
|
|
2340
|
+
maps = false;
|
|
2341
|
+
}
|
|
2342
|
+
mapsPresentationAttributes.set(ownerDoc, maps);
|
|
2343
|
+
return maps;
|
|
2344
|
+
}
|
|
2194
2345
|
function ensureCrossfilterHitTargets(container, doc) {
|
|
2195
2346
|
const report = { tagged: 0, hitRects: 0, peFlips: 0, peStrokeOnly: 0 };
|
|
2196
2347
|
try {
|
|
@@ -2253,7 +2404,7 @@ function ensureCrossfilterHitTargets(container, doc) {
|
|
|
2253
2404
|
} else {
|
|
2254
2405
|
const cs = computed(el);
|
|
2255
2406
|
if (cs && cs.pointerEvents === "none") {
|
|
2256
|
-
const fill = String(el.getAttribute?.("fill") ?? cs.fill ?? "").trim().toLowerCase();
|
|
2407
|
+
const fill = String((engineMapsPresentationAttributes(ownerDoc, view) ? cs.fill : el.getAttribute?.("fill") ?? cs.fill) ?? "").trim().toLowerCase();
|
|
2257
2408
|
const unfilled = fill === "none" || fill === "transparent" || fill === "rgba(0, 0, 0, 0)";
|
|
2258
2409
|
if (el.style) el.style.pointerEvents = unfilled ? "stroke" : "all";
|
|
2259
2410
|
report.peFlips++;
|
|
@@ -3625,17 +3776,10 @@ function createChartHost(container, config) {
|
|
|
3625
3776
|
const rows = parseRowIdxs(el.getAttribute(ROW_IDX_ATTR));
|
|
3626
3777
|
if (!rows.length) return;
|
|
3627
3778
|
const tick = el.classList?.contains?.(AXIS_FILTER_CLASS) ? el : null;
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
else next.add(r2);
|
|
3633
|
-
}
|
|
3634
|
-
notify(Array.from(next), "user", tick);
|
|
3635
|
-
return;
|
|
3636
|
-
}
|
|
3637
|
-
const same = !!current && current.length === rows.length && rows.every((r2) => current.includes(r2));
|
|
3638
|
-
notify(same ? [] : rows, "user", same ? null : tick);
|
|
3779
|
+
const multi = !!(e?.ctrlKey || e?.metaKey || e?.shiftKey);
|
|
3780
|
+
const next = nextSelection(current, rows, { ctrl: !!(e?.ctrlKey || e?.metaKey), shift: !!e?.shiftKey });
|
|
3781
|
+
const toggledOff = !multi && next.length === 0;
|
|
3782
|
+
notify(next, "user", toggledOff ? null : tick);
|
|
3639
3783
|
};
|
|
3640
3784
|
container.addEventListener(XFILTER_REFRESH_EVENT, onXf);
|
|
3641
3785
|
container.addEventListener("click", onClick);
|
|
@@ -4058,8 +4202,14 @@ export {
|
|
|
4058
4202
|
Bn,
|
|
4059
4203
|
buildRenderPayload,
|
|
4060
4204
|
stripJsComments,
|
|
4205
|
+
rowIdxsFromMark,
|
|
4206
|
+
nextSelection,
|
|
4061
4207
|
isInsideControl,
|
|
4062
4208
|
createMarkResolver,
|
|
4209
|
+
collectD3GlyphCenters,
|
|
4210
|
+
SELECTION_GLYPH_CLASS,
|
|
4211
|
+
clearSelectionGlyphs,
|
|
4212
|
+
paintSelectionGlyphs,
|
|
4063
4213
|
ensureCrossfilterHitTargets,
|
|
4064
4214
|
censusMarks,
|
|
4065
4215
|
isBlankRender,
|
package/dist/index.mjs
CHANGED
|
@@ -65,6 +65,7 @@ import {
|
|
|
65
65
|
SCROLL_SLACK_PX,
|
|
66
66
|
SEASONAL_MARKERS_DEFAULT,
|
|
67
67
|
SELECTION_ACTIVE_CLASS,
|
|
68
|
+
SELECTION_GLYPH_CLASS,
|
|
68
69
|
VALUE_AXIS_BASELINE_DEFAULT,
|
|
69
70
|
VALUE_AXIS_MIN_FIT,
|
|
70
71
|
VIEW_ONLY_UI_STATE_KEYS,
|
|
@@ -86,6 +87,8 @@ import {
|
|
|
86
87
|
censusValuePlacement,
|
|
87
88
|
chartOwnsTimeline,
|
|
88
89
|
clearGeoCache,
|
|
90
|
+
clearSelectionGlyphs,
|
|
91
|
+
collectD3GlyphCenters,
|
|
89
92
|
colourSpreadFlag,
|
|
90
93
|
compileRenderFn,
|
|
91
94
|
compositeOver,
|
|
@@ -117,7 +120,9 @@ import {
|
|
|
117
120
|
loadGeo,
|
|
118
121
|
measureContainerBoxes,
|
|
119
122
|
needsScroll,
|
|
123
|
+
nextSelection,
|
|
120
124
|
noopViewStateProvider,
|
|
125
|
+
paintSelectionGlyphs,
|
|
121
126
|
periodTickSuppressesFeedback,
|
|
122
127
|
pillBacksGlyph,
|
|
123
128
|
pinScrolledAxis,
|
|
@@ -129,6 +134,7 @@ import {
|
|
|
129
134
|
requiredD3Plugins,
|
|
130
135
|
resolveAutoColorScale,
|
|
131
136
|
resolveOptions,
|
|
137
|
+
rowIdxsFromMark,
|
|
132
138
|
scrollFitFor,
|
|
133
139
|
sessionViewStateProvider,
|
|
134
140
|
stripEsmExports,
|
|
@@ -140,7 +146,7 @@ import {
|
|
|
140
146
|
unpinScrolledAxis,
|
|
141
147
|
valuePlacementFlag,
|
|
142
148
|
withoutViewOnlyKeys
|
|
143
|
-
} from "./chunk-
|
|
149
|
+
} from "./chunk-MVM2R7K7.mjs";
|
|
144
150
|
import "./chunk-A2GMXZP7.mjs";
|
|
145
151
|
import "./chunk-GHODWOAL.mjs";
|
|
146
152
|
|
|
@@ -2629,6 +2635,7 @@ export {
|
|
|
2629
2635
|
SCROLL_SLACK_PX,
|
|
2630
2636
|
SEASONAL_MARKERS_DEFAULT,
|
|
2631
2637
|
SELECTION_ACTIVE_CLASS,
|
|
2638
|
+
SELECTION_GLYPH_CLASS,
|
|
2632
2639
|
TRANSPORT_LOST_CHECKING_MESSAGE,
|
|
2633
2640
|
VALUE_AXIS_BASELINE_DEFAULT,
|
|
2634
2641
|
VALUE_AXIS_MIN_FIT,
|
|
@@ -2662,7 +2669,9 @@ export {
|
|
|
2662
2669
|
chartOwnsTimeline,
|
|
2663
2670
|
chooserFitsViewport,
|
|
2664
2671
|
clearGeoCache,
|
|
2672
|
+
clearSelectionGlyphs,
|
|
2665
2673
|
codeReadsDatesInLocalTime,
|
|
2674
|
+
collectD3GlyphCenters,
|
|
2666
2675
|
colourSpreadFlag,
|
|
2667
2676
|
compileRenderFn,
|
|
2668
2677
|
compileTrivialSource,
|
|
@@ -2725,12 +2734,14 @@ export {
|
|
|
2725
2734
|
needsScroll,
|
|
2726
2735
|
newQualifyGroupState,
|
|
2727
2736
|
newQualifyRefusalGroupState,
|
|
2737
|
+
nextSelection,
|
|
2728
2738
|
noopViewStateProvider,
|
|
2729
2739
|
normaliseAggregation,
|
|
2730
2740
|
normaliseProductFeedbackText,
|
|
2731
2741
|
normalizeFilterTerm,
|
|
2732
2742
|
orderMostDistinct,
|
|
2733
2743
|
orderRefusalsForDisplay,
|
|
2744
|
+
paintSelectionGlyphs,
|
|
2734
2745
|
parsePendingGenerate,
|
|
2735
2746
|
pendingRecoveryNextDelayMs,
|
|
2736
2747
|
pendingRecoveryRemainingMs,
|
|
@@ -2768,6 +2779,7 @@ export {
|
|
|
2768
2779
|
requiredD3Plugins,
|
|
2769
2780
|
resolveAutoColorScale,
|
|
2770
2781
|
resolveOptions,
|
|
2782
|
+
rowIdxsFromMark,
|
|
2771
2783
|
sameMarker,
|
|
2772
2784
|
scrollFitFor,
|
|
2773
2785
|
servedCorrelationProves,
|
package/dist/react.mjs
CHANGED
package/dist/types/index.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export { buildRenderPayload, type RenderPayload, type GeoPointBinding } from "./
|
|
|
9
9
|
export { codeReadsDatesInLocalTime, vegaSpecReadsDatesInLocalTime } from "./dateCells";
|
|
10
10
|
export { createChartHost, compileRenderFn, stripEsmExports, requiredD3Plugins, explainRenderFailure, sessionViewStateProvider, noopViewStateProvider, assembleD3, D3_PLUGIN_PACKAGES, type ChartHost, type ChartHostConfig, type RenderFn } from "./host";
|
|
11
11
|
export { createChartGroup, toSourceRows, syncMemberSelection, type ChartGroup, type ChartGroupMember, type ChartGroupSelection, type ChartGroupChange, type ChartGroupMemberOptions, type ChartGroupSourceOptions, type ChartGroupPayload } from "./group";
|
|
12
|
-
export { createMarkResolver, isInsideControl, type MarkResolver, type MarkResolverEnv } from "./selection";
|
|
12
|
+
export { createMarkResolver, isInsideControl, rowIdxsFromMark, nextSelection, collectD3GlyphCenters, clearSelectionGlyphs, paintSelectionGlyphs, SELECTION_GLYPH_CLASS, type MarkResolver, type MarkResolverEnv, type GlyphCenter, type SelectionGlyphStyle, type SelectionModifiers, } from "./selection";
|
|
13
13
|
export { planTrivialChart, compileTrivialSource, type TrivialPlan, type TrivialShapeKind } from "./trivial";
|
|
14
14
|
export { captureSvgSnapshot, svgToDataUrl, svgNaturalSize, rasterizeSvgToPngDataUrl, type SnapshotOptions } from "./snapshot";
|
|
15
15
|
export { shouldReview, buildReviewWire, bareBase64, actionFor, type ReviewGate, type ReviewWire, type ReviewVerdict, type ReviewAction } from "./review";
|
|
@@ -1,3 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The rows a mark names: its data-row-idx read as a comma list of non-negative whole
|
|
3
|
+
* numbers. A token that is not one names no row and is skipped; no attribute, no rows.
|
|
4
|
+
*/
|
|
5
|
+
export declare function rowIdxsFromMark(el: Element | null): number[];
|
|
6
|
+
/** The keys held during a click. Cmd counts as Ctrl. */
|
|
7
|
+
export interface SelectionModifiers {
|
|
8
|
+
ctrl?: boolean;
|
|
9
|
+
shift?: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* THE SELECTION A CLICK LEAVES - the one rule every host applies to a click on a mark that names
|
|
13
|
+
* `rowIdxs`, from the selection it holds (`current`).
|
|
14
|
+
*
|
|
15
|
+
* With Ctrl/Cmd or Shift the semantics are TOGGLE-PER-ROW, not union: each clicked row that is
|
|
16
|
+
* selected is removed and each that is not is added, so Ctrl-clicking a selected mark takes it
|
|
17
|
+
* off, and a mark spanning several rows (a legend swatch) toggles each of them - a naive union
|
|
18
|
+
* would leave a mark lit after the reader Ctrl-clicked it off. Toggling the last row off is a
|
|
19
|
+
* legitimate way to reach empty.
|
|
20
|
+
*
|
|
21
|
+
* Without a modifier a click REPLACES the selection, and a click on exactly the current selection
|
|
22
|
+
* - the same rows, compared with the selection the host holds now, never with a remembered click -
|
|
23
|
+
* clears it: the other half of the gesture. So a plain click that returns [] is a toggle-off.
|
|
24
|
+
* Comparing with a remembered click instead went stale whenever the selection changed under it (a
|
|
25
|
+
* clear from elsewhere, a re-derived selection), and the next click on the mark then did nothing.
|
|
26
|
+
*/
|
|
27
|
+
export declare function nextSelection(current: Iterable<number> | null | undefined, rowIdxs: readonly number[], mods?: SelectionModifiers): number[];
|
|
1
28
|
/**
|
|
2
29
|
* True when a click's target sits inside a reader-operated control the chart drew (CONTROL_CLASS
|
|
3
30
|
* on the target or an ancestor), looking no further out than `container` - a page that wraps the
|
|
@@ -20,3 +47,37 @@ export interface MarkResolver {
|
|
|
20
47
|
resolveByGeometry(x: number, y: number, sel: string): HTMLElement | null;
|
|
21
48
|
}
|
|
22
49
|
export declare function createMarkResolver(env: MarkResolverEnv): MarkResolver;
|
|
50
|
+
/** A glyph's centre, in pixels from the overlay's own top-left corner. */
|
|
51
|
+
export interface GlyphCenter {
|
|
52
|
+
x: number;
|
|
53
|
+
y: number;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Where each SELECTED mark in `container` gets its glyph (every `.d3-mark` that also carries the
|
|
57
|
+
* selected class), pushed onto `out` in document order, relative to `baseRect` (the overlay's own
|
|
58
|
+
* client rect). Throws what the platform throws; a host that must not fail its paint catches it.
|
|
59
|
+
*/
|
|
60
|
+
export declare function collectD3GlyphCenters(container: Element, baseRect: {
|
|
61
|
+
left: number;
|
|
62
|
+
top: number;
|
|
63
|
+
}, out: GlyphCenter[]): void;
|
|
64
|
+
/** The class every painted selection glyph carries. */
|
|
65
|
+
export declare const SELECTION_GLYPH_CLASS = "lch-sel-glyph";
|
|
66
|
+
/** Removes every glyph (every child) from the overlay. */
|
|
67
|
+
export declare function clearSelectionGlyphs(overlay: Element | null | undefined): void;
|
|
68
|
+
export interface SelectionGlyphStyle {
|
|
69
|
+
/** The character drawn at each centre. */
|
|
70
|
+
symbol: string;
|
|
71
|
+
/** The glyph's colour. */
|
|
72
|
+
color: string;
|
|
73
|
+
/** The halo drawn on every side of it, so it reads on a dark and a light mark alike. */
|
|
74
|
+
halo: string;
|
|
75
|
+
/** At most this many are drawn. Default 600, which keeps the DOM light on a huge selection. */
|
|
76
|
+
max?: number;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Draws one glyph per centre (up to `max`) into `overlay`, positioned from the overlay's own
|
|
80
|
+
* top-left corner and never hit-tested. Returns how many it drew. It does not clear the overlay
|
|
81
|
+
* first: a host clears it (clearSelectionGlyphs) before deciding whether to paint at all.
|
|
82
|
+
*/
|
|
83
|
+
export declare function paintSelectionGlyphs(overlay: Element, centers: readonly GlyphCenter[], style: SelectionGlyphStyle): number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bicharts/chart-host",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.43",
|
|
4
4
|
"description": "Run a BIC-generated D3 chart in any web host: compiles the generated render() function, applies the shared option defaults, resolves mark clicks (through tooltip overlays), owns the selection affordance, and translates row indices between cross-filtered charts. The same contract the BIC Power BI visual implements, minus Power BI. React bindings at @bicharts/chart-host/react.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|