@bicharts/chart-host 0.6.89 → 0.6.90
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/README.md +14 -0
- package/dist/adapters.mjs +3 -3
- package/dist/{chunk-YDHXOIAI.mjs → chunk-45VILLJT.mjs} +2 -0
- package/dist/{chunk-GOIG756B.mjs → chunk-CR7DSJVG.mjs} +1 -1
- package/dist/{chunk-562LF7XM.mjs → chunk-FHHT7DBM.mjs} +27 -6
- package/dist/{chunk-QHIPRAZK.mjs → chunk-NNLBFIWU.mjs} +51 -2
- package/dist/{chunk-XNS34AMM.mjs → chunk-PDVEIW42.mjs} +1 -1
- package/dist/{chunk-OG6RR2AJ.mjs → chunk-QHMLMF4L.mjs} +2 -2
- package/dist/{chunk-UBB5LNH4.mjs → chunk-VC3Z5CH7.mjs} +1 -1
- package/dist/{chunk-DJ5IJV57.mjs → chunk-VEVBXK44.mjs} +1 -1
- package/dist/index.mjs +15 -7
- package/dist/legend-fit.mjs +3 -3
- package/dist/page.mjs +4 -4
- package/dist/react.mjs +11 -9
- package/dist/testing.mjs +1 -1
- package/dist/types/contract.d.ts +1 -0
- package/dist/types/fit.d.ts +23 -0
- package/dist/types/fitDom.d.ts +24 -1
- package/dist/types/host.d.ts +9 -0
- package/dist/types/index.d.ts +3 -1
- package/dist/types/react.d.ts +6 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -420,6 +420,20 @@ only while `rememberAcrossSessions()` is true. It is keyed by the chart's code a
|
|
|
420
420
|
somewhere arbitrary. A chart with several zoomable panels is left alone. In React, pass the hook as
|
|
421
421
|
the `zoomMemory` prop of `<BicChart>`.
|
|
422
422
|
|
|
423
|
+
**A scrolled chart** keeps its place with no setup. A chart taller than its frame scrolls, and every
|
|
424
|
+
redraw empties the container, which used to send the reader back to the top. The host now parks the
|
|
425
|
+
scroll offset on the container before it clears it, and the fit puts it back once the new layout has
|
|
426
|
+
decided whether it still scrolls. The offset is clamped to what the new layout can scroll, and only
|
|
427
|
+
restored on an axis that still scrolls. That covers a resize, a filter, a restyle, and a new host
|
|
428
|
+
created on the same element. The memory is keyed by the chart (its `code`, or the `renderFn`'s
|
|
429
|
+
source text), so a different chart opens at the top, while a `renderFn` closure rebuilt on every draw
|
|
430
|
+
is still the same chart. It lives on the element for the session
|
|
431
|
+
only, and nothing is persisted. A page that manages the container's scrolling itself passes
|
|
432
|
+
`restoreScroll: false` (the `restoreScroll` prop of `<BicChart>`), and then nothing is remembered or
|
|
433
|
+
restored. A host that clears and fits its container on its own can use the same pieces:
|
|
434
|
+
`rememberScroll` before the clear, `takeScroll` after the render, and `fitRenderedChart`'s
|
|
435
|
+
`restoreScroll` option (or the pure `planScrollRestore`).
|
|
436
|
+
|
|
423
437
|
## Keeping a drawn chart readable inside its frame
|
|
424
438
|
|
|
425
439
|
A generated chart cannot know how wide its own legend text will come out, where its tick labels will
|
package/dist/adapters.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
censusHitBands,
|
|
4
4
|
ensureCrossfilterHitTargets,
|
|
5
5
|
hitBandFlag
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-PDVEIW42.mjs";
|
|
7
7
|
import {
|
|
8
8
|
clickWasDrag,
|
|
9
9
|
collectD3GlyphCenters,
|
|
@@ -12,13 +12,13 @@ import {
|
|
|
12
12
|
markKeyOf,
|
|
13
13
|
rowIdxsFromMark,
|
|
14
14
|
selectionRuleOf
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-VEVBXK44.mjs";
|
|
16
16
|
import {
|
|
17
17
|
AXIS_FILTER_CLASS,
|
|
18
18
|
LEGEND_MARK_CLASS,
|
|
19
19
|
MARK_CLASS,
|
|
20
20
|
ROW_IDX_ATTR
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-45VILLJT.mjs";
|
|
22
22
|
import "./chunk-GHODWOAL.mjs";
|
|
23
23
|
|
|
24
24
|
// src/adapters/types.ts
|
|
@@ -19,6 +19,7 @@ var CONTAINER_SLOT_ANIM_STOP = "__llmAnimStop";
|
|
|
19
19
|
var CONTAINER_SLOT_XF_CLEAR = "__llmXfClear";
|
|
20
20
|
var CONTAINER_SLOT_INITIAL_XF_MARK = "__llmInitialXfMark";
|
|
21
21
|
var CONTAINER_SLOT_UI_STATE = "__lchUiState";
|
|
22
|
+
var CONTAINER_SLOT_SCROLL = "__lchScroll";
|
|
22
23
|
var CONTAINER_SLOT_CLICKED_MARKS = "__lchClickedMarks";
|
|
23
24
|
var VIEW_ONLY_UI_STATE_KEYS = Object.freeze(["camera", "llmZoom"]);
|
|
24
25
|
function withoutViewOnlyKeys(bag) {
|
|
@@ -89,6 +90,7 @@ export {
|
|
|
89
90
|
CONTAINER_SLOT_XF_CLEAR,
|
|
90
91
|
CONTAINER_SLOT_INITIAL_XF_MARK,
|
|
91
92
|
CONTAINER_SLOT_UI_STATE,
|
|
93
|
+
CONTAINER_SLOT_SCROLL,
|
|
92
94
|
CONTAINER_SLOT_CLICKED_MARKS,
|
|
93
95
|
VIEW_ONLY_UI_STATE_KEYS,
|
|
94
96
|
withoutViewOnlyKeys,
|
|
@@ -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
|
import {
|
|
3
3
|
LASSO_KNOB_KEY
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-QHMLMF4L.mjs";
|
|
5
5
|
|
|
6
6
|
// src/filterScope.ts
|
|
7
7
|
function viewToken(view) {
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
import {
|
|
3
3
|
LASSO_OUTLINE_CLASS,
|
|
4
4
|
installLasso
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-QHMLMF4L.mjs";
|
|
6
6
|
import {
|
|
7
7
|
censusHitBands,
|
|
8
8
|
ensureCrossfilterHitTargets
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-PDVEIW42.mjs";
|
|
10
10
|
import {
|
|
11
11
|
clearPress,
|
|
12
12
|
clearSelectionGlyphs,
|
|
@@ -23,12 +23,14 @@ import {
|
|
|
23
23
|
selectionRuleOf,
|
|
24
24
|
trackPress,
|
|
25
25
|
validRowSet
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-VEVBXK44.mjs";
|
|
27
27
|
import {
|
|
28
28
|
clipWindowOf,
|
|
29
29
|
fitRenderedChart,
|
|
30
|
+
rememberScroll,
|
|
31
|
+
takeScroll,
|
|
30
32
|
unpinScrolledAxis
|
|
31
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-NNLBFIWU.mjs";
|
|
32
34
|
import {
|
|
33
35
|
Fn,
|
|
34
36
|
J3,
|
|
@@ -82,7 +84,7 @@ import {
|
|
|
82
84
|
XFILTER_REFRESH_EVENT,
|
|
83
85
|
chartOwnsTimeline,
|
|
84
86
|
periodTickSuppressesFeedback
|
|
85
|
-
} from "./chunk-
|
|
87
|
+
} from "./chunk-45VILLJT.mjs";
|
|
86
88
|
|
|
87
89
|
// src/labelContrast.ts
|
|
88
90
|
function parseRGBA(c) {
|
|
@@ -2521,6 +2523,20 @@ function createChartHost(container, config) {
|
|
|
2521
2523
|
}
|
|
2522
2524
|
}
|
|
2523
2525
|
};
|
|
2526
|
+
const keepScroll = config.restoreScroll !== false;
|
|
2527
|
+
let chartSource;
|
|
2528
|
+
const scrollKey = () => {
|
|
2529
|
+
if (config.code) return config.code;
|
|
2530
|
+
if (chartSource === void 0 && typeof config.renderFn === "function") {
|
|
2531
|
+
try {
|
|
2532
|
+
chartSource = Function.prototype.toString.call(config.renderFn);
|
|
2533
|
+
} catch {
|
|
2534
|
+
return config.renderFn;
|
|
2535
|
+
}
|
|
2536
|
+
}
|
|
2537
|
+
return chartSource;
|
|
2538
|
+
};
|
|
2539
|
+
let hasRendered = false;
|
|
2524
2540
|
const runPostRenderPasses = () => {
|
|
2525
2541
|
if (zoomMemory && zoomCap) {
|
|
2526
2542
|
try {
|
|
@@ -2608,9 +2624,11 @@ function createChartHost(container, config) {
|
|
|
2608
2624
|
} catch {
|
|
2609
2625
|
}
|
|
2610
2626
|
}
|
|
2627
|
+
const scrollMem = takeScroll(container);
|
|
2611
2628
|
if (fitOpts !== false) {
|
|
2612
2629
|
try {
|
|
2613
|
-
const
|
|
2630
|
+
const base = fitOpts === true ? {} : fitOpts;
|
|
2631
|
+
const r = fitRenderedChart(container, keepScroll ? { ...base, restoreScroll: { memory: scrollMem, key: scrollKey() } } : base);
|
|
2614
2632
|
config.onFit?.(r);
|
|
2615
2633
|
} catch {
|
|
2616
2634
|
}
|
|
@@ -2649,7 +2667,9 @@ function createChartHost(container, config) {
|
|
|
2649
2667
|
followGlyphs(false);
|
|
2650
2668
|
disposeLasso();
|
|
2651
2669
|
flushZoom();
|
|
2670
|
+
if (hasRendered && keepScroll) rememberScroll(container, scrollKey());
|
|
2652
2671
|
container.innerHTML = "";
|
|
2672
|
+
hasRendered = true;
|
|
2653
2673
|
if (!renderFn) {
|
|
2654
2674
|
if (!config.code) throw new Error("createChartHost: provide code or renderFn");
|
|
2655
2675
|
renderFn = compileRenderFn(config.code, win, doc, chartD3);
|
|
@@ -2816,6 +2836,7 @@ function createChartHost(container, config) {
|
|
|
2816
2836
|
dimVarSet = false;
|
|
2817
2837
|
}
|
|
2818
2838
|
annotationLayer.destroy();
|
|
2839
|
+
if (hasRendered && keepScroll) rememberScroll(container, scrollKey());
|
|
2819
2840
|
unpinScrolledAxis(container);
|
|
2820
2841
|
flushZoom();
|
|
2821
2842
|
followGlyphs(false);
|
|
@@ -1,7 +1,8 @@
|
|
|
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
|
+
CONTAINER_SLOT_SCROLL,
|
|
3
4
|
SNAPSHOT_SVG_ATTR
|
|
4
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-45VILLJT.mjs";
|
|
5
6
|
|
|
6
7
|
// src/fit.ts
|
|
7
8
|
var SCROLL_SLACK_PX = 8;
|
|
@@ -104,6 +105,15 @@ function axisPinPlacement(band, scrollTop, viewportH) {
|
|
|
104
105
|
if (band.bottom > scrollTop + viewportH) return "bottom";
|
|
105
106
|
return null;
|
|
106
107
|
}
|
|
108
|
+
var nonNegative = (n) => typeof n === "number" && isFinite(n) && n > 0 ? n : 0;
|
|
109
|
+
function planScrollRestore(saved, key, m) {
|
|
110
|
+
if (!saved || key === void 0 || key === null || saved.key !== key) return { x: 0, y: 0 };
|
|
111
|
+
const room = (content, view) => Math.max(0, nonNegative(content) - nonNegative(view));
|
|
112
|
+
return {
|
|
113
|
+
x: m.overflowX === "auto" ? Math.min(nonNegative(saved.x), room(m.scrollWidth, m.clientWidth)) : 0,
|
|
114
|
+
y: m.overflowY === "auto" ? Math.min(nonNegative(saved.y), room(m.scrollHeight, m.clientHeight)) : 0
|
|
115
|
+
};
|
|
116
|
+
}
|
|
107
117
|
|
|
108
118
|
// src/fitDom.ts
|
|
109
119
|
var FIT_WALK_CAP = 8e3;
|
|
@@ -256,6 +266,28 @@ function unpinScrolledAxis(container) {
|
|
|
256
266
|
} catch {
|
|
257
267
|
}
|
|
258
268
|
}
|
|
269
|
+
function rememberScroll(container, key) {
|
|
270
|
+
if (!container) return;
|
|
271
|
+
try {
|
|
272
|
+
const slot = container;
|
|
273
|
+
if (slot[CONTAINER_SLOT_SCROLL]) return;
|
|
274
|
+
if (container.querySelector(".llm-mm-scroll")) return;
|
|
275
|
+
const x = container.scrollLeft, y = container.scrollTop;
|
|
276
|
+
if (x > 0 || y > 0) slot[CONTAINER_SLOT_SCROLL] = { key, x, y };
|
|
277
|
+
} catch {
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
function takeScroll(container) {
|
|
281
|
+
if (!container) return null;
|
|
282
|
+
try {
|
|
283
|
+
const slot = container;
|
|
284
|
+
const m = slot[CONTAINER_SLOT_SCROLL] ?? null;
|
|
285
|
+
delete slot[CONTAINER_SLOT_SCROLL];
|
|
286
|
+
return m;
|
|
287
|
+
} catch {
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
259
291
|
function textHidden(t, view) {
|
|
260
292
|
if (t.getAttribute("display") === "none" || t.getAttribute("visibility") === "hidden") return true;
|
|
261
293
|
try {
|
|
@@ -476,7 +508,8 @@ function fitRenderedChart(container, opts = {}) {
|
|
|
476
508
|
overflowX: "hidden",
|
|
477
509
|
overflowY: "hidden",
|
|
478
510
|
reading: null,
|
|
479
|
-
axisPin: noPin("no-container")
|
|
511
|
+
axisPin: noPin("no-container"),
|
|
512
|
+
scrolledTo: null
|
|
480
513
|
};
|
|
481
514
|
if (!container) return result;
|
|
482
515
|
try {
|
|
@@ -537,6 +570,19 @@ function fitRenderedChart(container, opts = {}) {
|
|
|
537
570
|
if (opts.applyOverflow !== false) {
|
|
538
571
|
container.style.overflowX = fit.overflowX;
|
|
539
572
|
container.style.overflowY = fit.overflowY;
|
|
573
|
+
if (opts.restoreScroll) {
|
|
574
|
+
const to = planScrollRestore(opts.restoreScroll.memory, opts.restoreScroll.key, {
|
|
575
|
+
scrollWidth: container.scrollWidth,
|
|
576
|
+
scrollHeight: container.scrollHeight,
|
|
577
|
+
clientWidth: container.clientWidth,
|
|
578
|
+
clientHeight: container.clientHeight,
|
|
579
|
+
overflowX: fit.overflowX,
|
|
580
|
+
overflowY: fit.overflowY
|
|
581
|
+
});
|
|
582
|
+
if (container.scrollLeft !== to.x) container.scrollLeft = to.x;
|
|
583
|
+
if (container.scrollTop !== to.y) container.scrollTop = to.y;
|
|
584
|
+
result.scrolledTo = to;
|
|
585
|
+
}
|
|
540
586
|
if (fit.overflowY !== "auto") {
|
|
541
587
|
unpinScrolledAxis(container);
|
|
542
588
|
result.axisPin = noPin("not-scrolling");
|
|
@@ -571,12 +617,15 @@ export {
|
|
|
571
617
|
labelBand,
|
|
572
618
|
planAxisPin,
|
|
573
619
|
axisPinPlacement,
|
|
620
|
+
planScrollRestore,
|
|
574
621
|
ctmScaleOf,
|
|
575
622
|
svgInkReach,
|
|
576
623
|
clipWindowOf,
|
|
577
624
|
measureContainerBoxes,
|
|
578
625
|
fitReadingFor,
|
|
579
626
|
unpinScrolledAxis,
|
|
627
|
+
rememberScroll,
|
|
628
|
+
takeScroll,
|
|
580
629
|
pinScrolledAxis,
|
|
581
630
|
fitRenderedChart
|
|
582
631
|
};
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
gestureWasDrag,
|
|
5
5
|
isInsideControl,
|
|
6
6
|
rowIdxsFromMark
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-VEVBXK44.mjs";
|
|
8
8
|
import {
|
|
9
9
|
AXIS_FILTER_CLASS,
|
|
10
10
|
CONTROL_CLASS,
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
MARK_CLASS,
|
|
13
13
|
ROW_IDX_ATTR,
|
|
14
14
|
SNAPSHOT_SVG_ATTR
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-45VILLJT.mjs";
|
|
16
16
|
|
|
17
17
|
// src/lasso.ts
|
|
18
18
|
var LASSO_ROW_CAP = 5e3;
|
|
@@ -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
|
import {
|
|
3
3
|
SNAPSHOT_SVG_ATTR
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-45VILLJT.mjs";
|
|
5
5
|
|
|
6
6
|
// src/snapshot.ts
|
|
7
7
|
var DEFAULT_TIMEOUT_MS = 2e3;
|
package/dist/index.mjs
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
svgNaturalSize,
|
|
16
16
|
svgToDataUrl,
|
|
17
17
|
tableHostOf
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-VC3Z5CH7.mjs";
|
|
19
19
|
import {
|
|
20
20
|
ANNOTATION_CLASS,
|
|
21
21
|
ANNOTATION_LAYER_CLASS,
|
|
@@ -97,7 +97,7 @@ import {
|
|
|
97
97
|
toRGBA,
|
|
98
98
|
toSourceRows,
|
|
99
99
|
valuePlacementFlag
|
|
100
|
-
} from "./chunk-
|
|
100
|
+
} from "./chunk-FHHT7DBM.mjs";
|
|
101
101
|
import {
|
|
102
102
|
LASSO_AXES_SLOT,
|
|
103
103
|
LASSO_COUNT_CLASS,
|
|
@@ -122,13 +122,13 @@ import {
|
|
|
122
122
|
lassoVerdict,
|
|
123
123
|
pointInShape,
|
|
124
124
|
registerLassoAction
|
|
125
|
-
} from "./chunk-
|
|
125
|
+
} from "./chunk-QHMLMF4L.mjs";
|
|
126
126
|
import {
|
|
127
127
|
MIN_HIT_BAND_PX,
|
|
128
128
|
censusHitBands,
|
|
129
129
|
ensureCrossfilterHitTargets,
|
|
130
130
|
hitBandFlag
|
|
131
|
-
} from "./chunk-
|
|
131
|
+
} from "./chunk-PDVEIW42.mjs";
|
|
132
132
|
import {
|
|
133
133
|
CONTAINER_SLOT_PRESS_AT,
|
|
134
134
|
DRAG_NOT_CLICK_PX,
|
|
@@ -153,7 +153,7 @@ import {
|
|
|
153
153
|
selectionRuleOf,
|
|
154
154
|
trackPress,
|
|
155
155
|
validRowSet
|
|
156
|
-
} from "./chunk-
|
|
156
|
+
} from "./chunk-VEVBXK44.mjs";
|
|
157
157
|
import {
|
|
158
158
|
AXIS_PIN_BAND_PAD_PX,
|
|
159
159
|
AXIS_PIN_MAX_BAND_FRACTION,
|
|
@@ -176,10 +176,13 @@ import {
|
|
|
176
176
|
pinScrolledAxis,
|
|
177
177
|
planAxisPin,
|
|
178
178
|
planFrameGrow,
|
|
179
|
+
planScrollRestore,
|
|
180
|
+
rememberScroll,
|
|
179
181
|
scrollFitFor,
|
|
180
182
|
svgInkReach,
|
|
183
|
+
takeScroll,
|
|
181
184
|
unpinScrolledAxis
|
|
182
|
-
} from "./chunk-
|
|
185
|
+
} from "./chunk-NNLBFIWU.mjs";
|
|
183
186
|
import {
|
|
184
187
|
_3,
|
|
185
188
|
l,
|
|
@@ -205,6 +208,7 @@ import {
|
|
|
205
208
|
CONTAINER_SLOT_ANIM_STOP,
|
|
206
209
|
CONTAINER_SLOT_CLICKED_MARKS,
|
|
207
210
|
CONTAINER_SLOT_INITIAL_XF_MARK,
|
|
211
|
+
CONTAINER_SLOT_SCROLL,
|
|
208
212
|
CONTAINER_SLOT_UI_STATE,
|
|
209
213
|
CONTAINER_SLOT_XF_CLEAR,
|
|
210
214
|
CONTROL_CLASS,
|
|
@@ -237,7 +241,7 @@ import {
|
|
|
237
241
|
chartOwnsTimeline,
|
|
238
242
|
periodTickSuppressesFeedback,
|
|
239
243
|
withoutViewOnlyKeys
|
|
240
|
-
} from "./chunk-
|
|
244
|
+
} from "./chunk-45VILLJT.mjs";
|
|
241
245
|
import "./chunk-GHODWOAL.mjs";
|
|
242
246
|
|
|
243
247
|
// src/optionsVocabulary.ts
|
|
@@ -2154,6 +2158,7 @@ export {
|
|
|
2154
2158
|
CONTAINER_SLOT_CLICKED_MARKS,
|
|
2155
2159
|
CONTAINER_SLOT_INITIAL_XF_MARK,
|
|
2156
2160
|
CONTAINER_SLOT_PRESS_AT,
|
|
2161
|
+
CONTAINER_SLOT_SCROLL,
|
|
2157
2162
|
CONTAINER_SLOT_UI_STATE,
|
|
2158
2163
|
CONTAINER_SLOT_XF_CLEAR,
|
|
2159
2164
|
CONTROL_CLASS,
|
|
@@ -2393,6 +2398,7 @@ export {
|
|
|
2393
2398
|
pinScrolledAxis,
|
|
2394
2399
|
planAxisPin,
|
|
2395
2400
|
planFrameGrow,
|
|
2401
|
+
planScrollRestore,
|
|
2396
2402
|
planSelectionPaint,
|
|
2397
2403
|
planTrivialChart,
|
|
2398
2404
|
pointInShape,
|
|
@@ -2429,6 +2435,7 @@ export {
|
|
|
2429
2435
|
registerGeoAsset,
|
|
2430
2436
|
registerLassoAction,
|
|
2431
2437
|
relativeLuminance,
|
|
2438
|
+
rememberScroll,
|
|
2432
2439
|
requiredD3Plugins,
|
|
2433
2440
|
resolveAutoColorScale,
|
|
2434
2441
|
resolveOptions,
|
|
@@ -2455,6 +2462,7 @@ export {
|
|
|
2455
2462
|
svgToDataUrl,
|
|
2456
2463
|
syncMemberSelection,
|
|
2457
2464
|
tableHostOf,
|
|
2465
|
+
takeScroll,
|
|
2458
2466
|
toRGBA,
|
|
2459
2467
|
toSourceRows,
|
|
2460
2468
|
trackPress,
|
package/dist/legend-fit.mjs
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
import {
|
|
3
3
|
chartSvgOf,
|
|
4
4
|
tableHostOf
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-VC3Z5CH7.mjs";
|
|
6
6
|
import {
|
|
7
7
|
FIT_CONTENT_SELECTOR,
|
|
8
8
|
ctmScaleOf,
|
|
9
9
|
isPhantomBox
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import "./chunk-
|
|
10
|
+
} from "./chunk-NNLBFIWU.mjs";
|
|
11
|
+
import "./chunk-45VILLJT.mjs";
|
|
12
12
|
import "./chunk-GHODWOAL.mjs";
|
|
13
13
|
|
|
14
14
|
// src/legendFit/legendReconcile.ts
|
package/dist/page.mjs
CHANGED
|
@@ -14,10 +14,10 @@ import {
|
|
|
14
14
|
readControls,
|
|
15
15
|
viewFromToken,
|
|
16
16
|
viewToken
|
|
17
|
-
} from "./chunk-
|
|
18
|
-
import "./chunk-
|
|
19
|
-
import "./chunk-
|
|
20
|
-
import "./chunk-
|
|
17
|
+
} from "./chunk-CR7DSJVG.mjs";
|
|
18
|
+
import "./chunk-QHMLMF4L.mjs";
|
|
19
|
+
import "./chunk-VEVBXK44.mjs";
|
|
20
|
+
import "./chunk-45VILLJT.mjs";
|
|
21
21
|
import "./chunk-GHODWOAL.mjs";
|
|
22
22
|
export {
|
|
23
23
|
LINKED_HOVER_CLASS,
|
package/dist/react.mjs
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
payloadRowReader,
|
|
14
14
|
viewFromToken,
|
|
15
15
|
viewToken
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-CR7DSJVG.mjs";
|
|
17
17
|
import {
|
|
18
18
|
assembleD3,
|
|
19
19
|
createChartGroup,
|
|
@@ -22,14 +22,14 @@ import {
|
|
|
22
22
|
loadGeo,
|
|
23
23
|
syncMemberSelection,
|
|
24
24
|
toSourceRows
|
|
25
|
-
} from "./chunk-
|
|
26
|
-
import "./chunk-
|
|
27
|
-
import "./chunk-
|
|
28
|
-
import "./chunk-
|
|
29
|
-
import "./chunk-
|
|
25
|
+
} from "./chunk-FHHT7DBM.mjs";
|
|
26
|
+
import "./chunk-QHMLMF4L.mjs";
|
|
27
|
+
import "./chunk-PDVEIW42.mjs";
|
|
28
|
+
import "./chunk-VEVBXK44.mjs";
|
|
29
|
+
import "./chunk-NNLBFIWU.mjs";
|
|
30
30
|
import "./chunk-KQN5C7SZ.mjs";
|
|
31
31
|
import "./chunk-A2GMXZP7.mjs";
|
|
32
|
-
import "./chunk-
|
|
32
|
+
import "./chunk-45VILLJT.mjs";
|
|
33
33
|
import "./chunk-GHODWOAL.mjs";
|
|
34
34
|
|
|
35
35
|
// src/react.tsx
|
|
@@ -69,6 +69,7 @@ function BicChart(props) {
|
|
|
69
69
|
viewState,
|
|
70
70
|
zoomMemory,
|
|
71
71
|
labelContrast,
|
|
72
|
+
restoreScroll,
|
|
72
73
|
onLabelContrast,
|
|
73
74
|
onSelectionGlyphs,
|
|
74
75
|
layoutPass,
|
|
@@ -157,6 +158,7 @@ function BicChart(props) {
|
|
|
157
158
|
zoomMemory,
|
|
158
159
|
labelContrast,
|
|
159
160
|
layoutPass,
|
|
161
|
+
restoreScroll,
|
|
160
162
|
onLabelContrast: (r) => onLabelContrastRef.current?.(r),
|
|
161
163
|
onSelectionGlyphs: (r) => onSelectionGlyphsRef.current?.(r),
|
|
162
164
|
// A GETTER, not a wrapper: the host decides whether to
|
|
@@ -189,7 +191,7 @@ function BicChart(props) {
|
|
|
189
191
|
host.destroy();
|
|
190
192
|
hostRef.current = null;
|
|
191
193
|
};
|
|
192
|
-
}, [code, renderFn, d3, geoKind, labelContrast, layoutPass, controls]);
|
|
194
|
+
}, [code, renderFn, d3, geoKind, labelContrast, layoutPass, restoreScroll, controls]);
|
|
193
195
|
useLayoutEffect(() => {
|
|
194
196
|
const host = hostRef.current;
|
|
195
197
|
if (!host || !selects) return;
|
|
@@ -215,7 +217,7 @@ function BicChart(props) {
|
|
|
215
217
|
b.detach();
|
|
216
218
|
if (bindingRef.current === b) bindingRef.current = null;
|
|
217
219
|
};
|
|
218
|
-
}, [selects, code, renderFn, d3, geoKind, labelContrast, layoutPass]);
|
|
220
|
+
}, [selects, code, renderFn, d3, geoKind, labelContrast, layoutPass, restoreScroll]);
|
|
219
221
|
useEffect(() => {
|
|
220
222
|
if (!hostRef.current || !options) return;
|
|
221
223
|
if (builtWithRef.current?.optKey === optKey) return;
|
package/dist/testing.mjs
CHANGED
package/dist/types/contract.d.ts
CHANGED
|
@@ -35,6 +35,7 @@ export declare const CONTAINER_SLOT_ANIM_STOP = "__llmAnimStop";
|
|
|
35
35
|
export declare const CONTAINER_SLOT_XF_CLEAR = "__llmXfClear";
|
|
36
36
|
export declare const CONTAINER_SLOT_INITIAL_XF_MARK = "__llmInitialXfMark";
|
|
37
37
|
export declare const CONTAINER_SLOT_UI_STATE = "__lchUiState";
|
|
38
|
+
export declare const CONTAINER_SLOT_SCROLL = "__lchScroll";
|
|
38
39
|
export declare const CONTAINER_SLOT_CLICKED_MARKS = "__lchClickedMarks";
|
|
39
40
|
export declare const VIEW_ONLY_UI_STATE_KEYS: readonly string[];
|
|
40
41
|
/** The bag with every view-only key removed: what a host persists when the reader has not asked
|
package/dist/types/fit.d.ts
CHANGED
|
@@ -90,3 +90,26 @@ export type AxisPinEdge = "top" | "bottom";
|
|
|
90
90
|
* one drawn over it.
|
|
91
91
|
*/
|
|
92
92
|
export declare function axisPinPlacement(band: AxisBand, scrollTop: number, viewportH: number): AxisPinEdge | null;
|
|
93
|
+
/** A reader's scroll offsets and the identity of the chart they were made on. */
|
|
94
|
+
export interface ScrollMemory {
|
|
95
|
+
key: unknown;
|
|
96
|
+
x: number;
|
|
97
|
+
y: number;
|
|
98
|
+
}
|
|
99
|
+
/** What the container reports once the overflow is decided. */
|
|
100
|
+
export interface ScrollMetrics {
|
|
101
|
+
scrollWidth: number;
|
|
102
|
+
scrollHeight: number;
|
|
103
|
+
clientWidth: number;
|
|
104
|
+
clientHeight: number;
|
|
105
|
+
overflowX: string;
|
|
106
|
+
overflowY: string;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Where the scroll goes after a redraw. The saved offsets when the SAME chart is back, clamped to what the new layout can scroll and
|
|
110
|
+
* applied per axis only where the container scrolls; otherwise the origin. A new chart opens at the top.
|
|
111
|
+
*/
|
|
112
|
+
export declare function planScrollRestore(saved: ScrollMemory | null | undefined, key: unknown, m: ScrollMetrics): {
|
|
113
|
+
x: number;
|
|
114
|
+
y: number;
|
|
115
|
+
};
|
package/dist/types/fitDom.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ContentExtent, MeasuredBox, AxisPinEdge } from "./fit";
|
|
1
|
+
import type { ContentExtent, MeasuredBox, AxisPinEdge, ScrollMemory } from "./fit";
|
|
2
2
|
export declare function ctmScaleOf(m: {
|
|
3
3
|
a: number;
|
|
4
4
|
b: number;
|
|
@@ -59,6 +59,16 @@ export interface FitRenderedChartOptions {
|
|
|
59
59
|
* Set false for a host that draws its own sticky header.
|
|
60
60
|
*/
|
|
61
61
|
pinAxis?: boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Put the reader's scroll back once the overflow is decided: `memory` (what `takeScroll` handed
|
|
64
|
+
* back) is restored only when its key is `key`, the chart now drawn, clamped to what the new
|
|
65
|
+
* layout can scroll and only on an axis that scrolls. Applied before the axis pin, which places
|
|
66
|
+
* its copy from the scroll it finds. Absent, the container is left where the render put it.
|
|
67
|
+
*/
|
|
68
|
+
restoreScroll?: {
|
|
69
|
+
memory: ScrollMemory | null;
|
|
70
|
+
key: unknown;
|
|
71
|
+
};
|
|
62
72
|
}
|
|
63
73
|
export interface FitRenderedChartResult {
|
|
64
74
|
/** The frame was grown, so content that was being clipped is now painted. */
|
|
@@ -73,6 +83,11 @@ export interface FitRenderedChartResult {
|
|
|
73
83
|
reading: FitReading | null;
|
|
74
84
|
/** The axis pin: what was pinned when the container scrolls, or why nothing was. */
|
|
75
85
|
axisPin: AxisPinReport;
|
|
86
|
+
/** Where `restoreScroll` put the container ({0,0} for a different chart), or null when it was not asked or the overflow was not applied. */
|
|
87
|
+
scrolledTo: {
|
|
88
|
+
x: number;
|
|
89
|
+
y: number;
|
|
90
|
+
} | null;
|
|
76
91
|
}
|
|
77
92
|
export interface AxisPinReport {
|
|
78
93
|
pinned: boolean;
|
|
@@ -94,5 +109,13 @@ export interface AxisPinReport {
|
|
|
94
109
|
* when there is none. Hosts that clear the container themselves still need this for the
|
|
95
110
|
* listener, which outlives the overlay. */
|
|
96
111
|
export declare function unpinScrolledAxis(container: HTMLElement | null | undefined): void;
|
|
112
|
+
/**
|
|
113
|
+
* Remember where the container is scrolled, BEFORE the container is cleared. A memory already waiting is kept: a second render that
|
|
114
|
+
* starts before the first one restored sees an emptied (unscrolled) container, and must not overwrite what the reader really did.
|
|
115
|
+
* A diagram that scrolls inside itself remembers its own position, so it is left alone.
|
|
116
|
+
*/
|
|
117
|
+
export declare function rememberScroll(container: HTMLElement | null | undefined, key: unknown): void;
|
|
118
|
+
/** The waiting memory, removed. The one place it is consumed, so a stale memory can never outlive a render. */
|
|
119
|
+
export declare function takeScroll(container: HTMLElement | null | undefined): ScrollMemory | null;
|
|
97
120
|
export declare function pinScrolledAxis(container: HTMLElement | null | undefined, svg: SVGSVGElement | null | undefined): AxisPinReport;
|
|
98
121
|
export declare function fitRenderedChart(container: HTMLElement | null | undefined, opts?: FitRenderedChartOptions): FitRenderedChartResult;
|
package/dist/types/host.d.ts
CHANGED
|
@@ -181,6 +181,15 @@ export interface ChartHostConfig {
|
|
|
181
181
|
* reading without touching the chart (`grow: false`, `applyOverflow: false`).
|
|
182
182
|
*/
|
|
183
183
|
fit?: boolean | FitRenderedChartOptions;
|
|
184
|
+
/**
|
|
185
|
+
* KEEP THE READER'S SCROLL when the SAME chart is drawn again - a resize, a filter, a theme
|
|
186
|
+
* switch, or a new host on the same element. Default true: the offset is parked on the
|
|
187
|
+
* container before each clear and put back by the fit, clamped to what the new layout can
|
|
188
|
+
* scroll; a different chart (other code, or a renderFn with other source) opens at the top. Pass `false`
|
|
189
|
+
* for a page that manages the container's scrolling itself: nothing is remembered or restored,
|
|
190
|
+
* and a memory an earlier host left on the element is discarded at the next render.
|
|
191
|
+
*/
|
|
192
|
+
restoreScroll?: boolean;
|
|
184
193
|
/** The fit result after each render - what was grown, and how the chart measured. */
|
|
185
194
|
onFit?: (result: FitRenderedChartResult) => void;
|
|
186
195
|
/**
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { HOST_CONTRACT_VERSION, GEO_POINT_PRECISIONS, MARK_CLASS, LEGEND_MARK_CLASS, AXIS_FILTER_CLASS, ROW_IDX_ATTR, LIFT_SELECTED_CLASS, CONTROL_CLASS, NO_ROW_MARKS_ATTR, SELECTION_RULE_ATTR, SELECTION_RULE_CLICKED_MARKS, MARK_KEY_ATTR, CONTAINER_SLOT_CLICKED_MARKS, SNAPSHOT_SVG_ATTR, XFILTER_REFRESH_EVENT, CONTAINER_SLOT_ANIM_STOP, CONTAINER_SLOT_XF_CLEAR, CONTAINER_SLOT_INITIAL_XF_MARK, CONTAINER_SLOT_UI_STATE, VIEW_ONLY_UI_STATE_KEYS, withoutViewOnlyKeys, HOST_CONTAINER_CLASS, SELECTION_ACTIVE_CLASS, MARK_SELECTED_CLASS, ACTIVE_TICK_CLASS, DIM_OPACITY_VAR, DIM_OPACITY_DEFAULT, DIM_OPACITY_MIN, chartOwnsTimeline, periodTickSuppressesFeedback, ANIM_PLAY_SPEED_DEFAULT, ANIM_PLAY_SPEED_MIN, ANIM_PLAY_SPEED_MAX, ANIM_LOOP_DELAY_DEFAULT, ANIM_LOOP_DELAY_MIN, ANIM_MAX_IDEAL_FRAMES_DEFAULT, ANIM_MAX_IDEAL_FRAMES_MIN, ANIM_MAX_IDEAL_FRAMES_MAX, ANIMATION_OPTION_KEYS, COLOR_SCALE_SELF_CLAMP_PCT_DEFAULT, COLOR_SCALE_SELF_CLAMP_PCT_MIN, COLOR_SCALE_SELF_CLAMP_PCT_MAX, FLIP_MODE_DEFAULT, FLIP_INTERVAL_MIN_MS, FLIP_INTERVAL_MAX_MS, FLIP_DIRECTION_DEFAULT, APPROXIMATE_POSITIONS_DEFAULT, VALUE_AXIS_BASELINE_DEFAULT, SEASONAL_MARKERS_DEFAULT, MAX_MAP_POINTS_DEFAULT, type GeoPointPrecision, type GeoMapKind, type TimelineStyle, type FlipMode, type FlipDirection, type ApproximatePositions, type ValueAxisBaseline, type SeasonalMarkers, type ColorScaleScope, type RenderOptions, type ViewStateProvider, type ChartControlChange, type XfilterRefreshDetail, } from "./contract";
|
|
1
|
+
export { HOST_CONTRACT_VERSION, GEO_POINT_PRECISIONS, MARK_CLASS, LEGEND_MARK_CLASS, AXIS_FILTER_CLASS, ROW_IDX_ATTR, LIFT_SELECTED_CLASS, CONTROL_CLASS, NO_ROW_MARKS_ATTR, SELECTION_RULE_ATTR, SELECTION_RULE_CLICKED_MARKS, MARK_KEY_ATTR, CONTAINER_SLOT_CLICKED_MARKS, SNAPSHOT_SVG_ATTR, XFILTER_REFRESH_EVENT, CONTAINER_SLOT_ANIM_STOP, CONTAINER_SLOT_XF_CLEAR, CONTAINER_SLOT_INITIAL_XF_MARK, CONTAINER_SLOT_UI_STATE, CONTAINER_SLOT_SCROLL, VIEW_ONLY_UI_STATE_KEYS, withoutViewOnlyKeys, HOST_CONTAINER_CLASS, SELECTION_ACTIVE_CLASS, MARK_SELECTED_CLASS, ACTIVE_TICK_CLASS, DIM_OPACITY_VAR, DIM_OPACITY_DEFAULT, DIM_OPACITY_MIN, chartOwnsTimeline, periodTickSuppressesFeedback, ANIM_PLAY_SPEED_DEFAULT, ANIM_PLAY_SPEED_MIN, ANIM_PLAY_SPEED_MAX, ANIM_LOOP_DELAY_DEFAULT, ANIM_LOOP_DELAY_MIN, ANIM_MAX_IDEAL_FRAMES_DEFAULT, ANIM_MAX_IDEAL_FRAMES_MIN, ANIM_MAX_IDEAL_FRAMES_MAX, ANIMATION_OPTION_KEYS, COLOR_SCALE_SELF_CLAMP_PCT_DEFAULT, COLOR_SCALE_SELF_CLAMP_PCT_MIN, COLOR_SCALE_SELF_CLAMP_PCT_MAX, FLIP_MODE_DEFAULT, FLIP_INTERVAL_MIN_MS, FLIP_INTERVAL_MAX_MS, FLIP_DIRECTION_DEFAULT, APPROXIMATE_POSITIONS_DEFAULT, VALUE_AXIS_BASELINE_DEFAULT, SEASONAL_MARKERS_DEFAULT, MAX_MAP_POINTS_DEFAULT, type GeoPointPrecision, type GeoMapKind, type TimelineStyle, type FlipMode, type FlipDirection, type ApproximatePositions, type ValueAxisBaseline, type SeasonalMarkers, type ColorScaleScope, type RenderOptions, type ViewStateProvider, type ChartControlChange, type XfilterRefreshDetail, } from "./contract";
|
|
2
2
|
export { resolveOptions, type ResolveOptionsInput } from "./defaults";
|
|
3
3
|
export { OPTIONS_VOCABULARY, LIVE_OPTION_KEYS, MAX_MAP_POINTS_MIN, MAX_MAP_POINTS_MAX, LIMIT_COUNT_MAX, wireLimitCount, codeReadsOption, type OptionVocabularyEntry, type OptionTiming, type OptionWire, type OptionKey, } from "./optionsVocabulary";
|
|
4
4
|
export { loadGeo, geoFromCache, registerGeo, registerGeoAsset, geoAssetFor, clearGeoCache, type GeoAssetName, } from "./geoLazy";
|
|
@@ -42,6 +42,8 @@ export { SCROLL_SLACK_PX, MAX_FRAME_GROW_FACTOR, PHANTOM_FRACTION, FIT_CONTENT_S
|
|
|
42
42
|
export { fitRenderedChart, fitReadingFor, measureContainerBoxes, svgInkReach, ctmScaleOf, type FitReading, type InkReach, type FitRenderedChartOptions, type FitRenderedChartResult, } from "./fitDom";
|
|
43
43
|
export { AXIS_PIN_MIN_LABELS, AXIS_PIN_BAND_PAD_PX, AXIS_PIN_MAX_BAND_FRACTION, AXIS_PIN_TRACK_REACH_PX, isHorizontalLabelRow, labelBand, planAxisPin, axisPinPlacement, type LabelRowBox, type AxisBand, type AxisPinCandidate, type AxisPinPlan, type AxisPinEdge, } from "./fit";
|
|
44
44
|
export { pinScrolledAxis, unpinScrolledAxis, type AxisPinReport } from "./fitDom";
|
|
45
|
+
export { planScrollRestore, type ScrollMemory, type ScrollMetrics } from "./fit";
|
|
46
|
+
export { rememberScroll, takeScroll } from "./fitDom";
|
|
45
47
|
export { MIN_DELTA_E, pickDistinctColorFromSeed, buildPalette, buildPaletteFromSeed, orderMostDistinct, LEGIBLE_LIGHTNESS, type PaletteResult, type SeedForSlot, type PaletteOptions, } from "./palette";
|
|
46
48
|
export { deltaEHex } from "./deltaE";
|
|
47
49
|
export { resolveAutoColorScale, autoRampMinStep, autoRampCanvas, AUTO_RAMP_CLASSES, AUTO_RAMP_DRAWN_OPACITY, AUTO_RAMP_MIN_STEP_DELTA_E, type AutoColorScale, type AutoColorScaleInput } from "./autoRamp";
|
package/dist/types/react.d.ts
CHANGED
|
@@ -46,6 +46,12 @@ export interface BicChartProps {
|
|
|
46
46
|
* themed page is not white, and readability is measured against it. See createChartHost.
|
|
47
47
|
*/
|
|
48
48
|
labelContrast?: ChartHostConfig["labelContrast"];
|
|
49
|
+
/**
|
|
50
|
+
* KEEP THE READER'S SCROLL when the same chart repaints (new data, new options, a rebuild).
|
|
51
|
+
* Default on; a different chart opens at the top. Pass `false` for a page that manages the
|
|
52
|
+
* chart's scrolling itself. Host config: changing it rebuilds the host. See createChartHost.
|
|
53
|
+
*/
|
|
54
|
+
restoreScroll?: ChartHostConfig["restoreScroll"];
|
|
49
55
|
/** What the label-contrast pass did after each render - counts, for a page that logs. */
|
|
50
56
|
onLabelContrast?: ChartHostConfig["onLabelContrast"];
|
|
51
57
|
/** What the selection-glyph pass did after each paint, when `options.selectionGlyph` is set - counts, for a page
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bicharts/chart-host",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.90",
|
|
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",
|