insomni-plot 0.1.0-alpha.0
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/LICENSE.md +674 -0
- package/README.md +81 -0
- package/dist/core.d.mts +340 -0
- package/dist/core.mjs +1047 -0
- package/dist/index.d.mts +3426 -0
- package/dist/index.mjs +12762 -0
- package/dist/interactions-DEFL_F4E.mjs +5395 -0
- package/dist/range-presets-CzECsu3V.d.mts +1523 -0
- package/package.json +34 -0
- package/src/annotations.d.ts +121 -0
- package/src/annotations.ts +438 -0
- package/src/axis.d.ts +184 -0
- package/src/axis.test.ts +131 -0
- package/src/axis.ts +765 -0
- package/src/colorbar.d.ts +69 -0
- package/src/colorbar.ts +294 -0
- package/src/colors.d.ts +57 -0
- package/src/colors.test.ts +28 -0
- package/src/colors.ts +486 -0
- package/src/core.ts +299 -0
- package/src/format.d.ts +54 -0
- package/src/format.ts +138 -0
- package/src/grammar/accessibility.d.ts +147 -0
- package/src/grammar/accessibility.test.ts +199 -0
- package/src/grammar/accessibility.ts +443 -0
- package/src/grammar/aes.d.ts +35 -0
- package/src/grammar/aes.test.ts +75 -0
- package/src/grammar/aes.ts +120 -0
- package/src/grammar/annotations.d.ts +86 -0
- package/src/grammar/annotations.test.ts +68 -0
- package/src/grammar/annotations.ts +336 -0
- package/src/grammar/attach-brush.d.ts +44 -0
- package/src/grammar/attach-brush.test.ts +214 -0
- package/src/grammar/attach-brush.ts +111 -0
- package/src/grammar/attach-presets.d.ts +33 -0
- package/src/grammar/attach-presets.test.ts +106 -0
- package/src/grammar/attach-presets.ts +215 -0
- package/src/grammar/chart.d.ts +952 -0
- package/src/grammar/chart.test.ts +118 -0
- package/src/grammar/chart.ts +1172 -0
- package/src/grammar/color-utils.d.ts +29 -0
- package/src/grammar/color-utils.test.ts +53 -0
- package/src/grammar/color-utils.ts +66 -0
- package/src/grammar/constants.d.ts +45 -0
- package/src/grammar/constants.ts +61 -0
- package/src/grammar/coord.d.ts +183 -0
- package/src/grammar/coord.test.ts +355 -0
- package/src/grammar/coord.ts +619 -0
- package/src/grammar/data/pivot.d.ts +57 -0
- package/src/grammar/data/pivot.ts +107 -0
- package/src/grammar/emphasis-driver.d.ts +69 -0
- package/src/grammar/emphasis-driver.test.ts +199 -0
- package/src/grammar/emphasis-driver.ts +205 -0
- package/src/grammar/equality.d.ts +3 -0
- package/src/grammar/equality.ts +40 -0
- package/src/grammar/facet.d.ts +63 -0
- package/src/grammar/facet.test.ts +60 -0
- package/src/grammar/facet.ts +175 -0
- package/src/grammar/geoms/_categorical.d.ts +94 -0
- package/src/grammar/geoms/_categorical.ts +0 -0
- package/src/grammar/geoms/_distribution.d.ts +52 -0
- package/src/grammar/geoms/_distribution.ts +125 -0
- package/src/grammar/geoms/_mark.d.ts +69 -0
- package/src/grammar/geoms/_mark.ts +136 -0
- package/src/grammar/geoms/_shape.d.ts +41 -0
- package/src/grammar/geoms/_shape.ts +74 -0
- package/src/grammar/geoms/aggregate.d.ts +95 -0
- package/src/grammar/geoms/aggregate.test.ts +554 -0
- package/src/grammar/geoms/aggregate.ts +840 -0
- package/src/grammar/geoms/area.d.ts +32 -0
- package/src/grammar/geoms/area.test.ts +165 -0
- package/src/grammar/geoms/area.ts +578 -0
- package/src/grammar/geoms/band.d.ts +27 -0
- package/src/grammar/geoms/band.test.ts +57 -0
- package/src/grammar/geoms/band.ts +126 -0
- package/src/grammar/geoms/bar.d.ts +56 -0
- package/src/grammar/geoms/bar.test.ts +367 -0
- package/src/grammar/geoms/bar.ts +1054 -0
- package/src/grammar/geoms/boxplot.d.ts +129 -0
- package/src/grammar/geoms/boxplot.test.ts +299 -0
- package/src/grammar/geoms/boxplot.ts +834 -0
- package/src/grammar/geoms/connected-scatter.d.ts +27 -0
- package/src/grammar/geoms/connected-scatter.test.ts +157 -0
- package/src/grammar/geoms/connected-scatter.ts +63 -0
- package/src/grammar/geoms/emphasis.d.ts +76 -0
- package/src/grammar/geoms/emphasis.test.ts +135 -0
- package/src/grammar/geoms/emphasis.ts +162 -0
- package/src/grammar/geoms/histogram.d.ts +75 -0
- package/src/grammar/geoms/histogram.test.ts +262 -0
- package/src/grammar/geoms/histogram.ts +740 -0
- package/src/grammar/geoms/index.d.ts +20 -0
- package/src/grammar/geoms/index.ts +77 -0
- package/src/grammar/geoms/interval.d.ts +31 -0
- package/src/grammar/geoms/interval.test.ts +154 -0
- package/src/grammar/geoms/interval.ts +342 -0
- package/src/grammar/geoms/line.d.ts +38 -0
- package/src/grammar/geoms/line.test.ts +247 -0
- package/src/grammar/geoms/line.ts +659 -0
- package/src/grammar/geoms/point.d.ts +57 -0
- package/src/grammar/geoms/point.test.ts +163 -0
- package/src/grammar/geoms/point.ts +545 -0
- package/src/grammar/geoms/polar.test.ts +216 -0
- package/src/grammar/geoms/ribbon.d.ts +21 -0
- package/src/grammar/geoms/ribbon.test.ts +170 -0
- package/src/grammar/geoms/ribbon.ts +87 -0
- package/src/grammar/geoms/ridgeline.d.ts +89 -0
- package/src/grammar/geoms/ridgeline.test.ts +247 -0
- package/src/grammar/geoms/ridgeline.ts +1164 -0
- package/src/grammar/geoms/rolling.d.ts +43 -0
- package/src/grammar/geoms/rolling.test.ts +217 -0
- package/src/grammar/geoms/rolling.ts +387 -0
- package/src/grammar/geoms/rug.d.ts +28 -0
- package/src/grammar/geoms/rug.test.ts +126 -0
- package/src/grammar/geoms/rug.ts +214 -0
- package/src/grammar/geoms/rule.d.ts +23 -0
- package/src/grammar/geoms/rule.test.ts +69 -0
- package/src/grammar/geoms/rule.ts +212 -0
- package/src/grammar/geoms/smooth.d.ts +54 -0
- package/src/grammar/geoms/smooth.test.ts +78 -0
- package/src/grammar/geoms/smooth.ts +337 -0
- package/src/grammar/geoms/text.d.ts +29 -0
- package/src/grammar/geoms/text.test.ts +64 -0
- package/src/grammar/geoms/text.ts +234 -0
- package/src/grammar/geoms/tile.d.ts +61 -0
- package/src/grammar/geoms/tile.test.ts +157 -0
- package/src/grammar/geoms/tile.ts +621 -0
- package/src/grammar/geoms/types.d.ts +319 -0
- package/src/grammar/geoms/types.ts +362 -0
- package/src/grammar/geoms/violin.d.ts +85 -0
- package/src/grammar/geoms/violin.test.ts +187 -0
- package/src/grammar/geoms/violin.ts +672 -0
- package/src/grammar/index.d.ts +22 -0
- package/src/grammar/index.ts +269 -0
- package/src/grammar/interactions/_disposable.d.ts +5 -0
- package/src/grammar/interactions/_disposable.ts +23 -0
- package/src/grammar/interactions/_z.d.ts +4 -0
- package/src/grammar/interactions/_z.ts +16 -0
- package/src/grammar/interactions/brush-selection.test.ts +262 -0
- package/src/grammar/interactions/brush.d.ts +63 -0
- package/src/grammar/interactions/brush.test.ts +483 -0
- package/src/grammar/interactions/brush.ts +452 -0
- package/src/grammar/interactions/crosshair.d.ts +19 -0
- package/src/grammar/interactions/crosshair.test.ts +127 -0
- package/src/grammar/interactions/crosshair.ts +76 -0
- package/src/grammar/interactions/hit-layer.d.ts +64 -0
- package/src/grammar/interactions/hit-layer.ts +246 -0
- package/src/grammar/interactions/legend.d.ts +19 -0
- package/src/grammar/interactions/legend.ts +101 -0
- package/src/grammar/interactions/menu.d.ts +93 -0
- package/src/grammar/interactions/menu.test.ts +373 -0
- package/src/grammar/interactions/menu.ts +342 -0
- package/src/grammar/interactions/selection.d.ts +25 -0
- package/src/grammar/interactions/selection.test.ts +289 -0
- package/src/grammar/interactions/selection.ts +142 -0
- package/src/grammar/interactions/series-readout.d.ts +91 -0
- package/src/grammar/interactions/series-readout.test.ts +668 -0
- package/src/grammar/interactions/series-readout.ts +422 -0
- package/src/grammar/interactions/series-snap.d.ts +70 -0
- package/src/grammar/interactions/series-snap.test.ts +214 -0
- package/src/grammar/interactions/series-snap.ts +218 -0
- package/src/grammar/interactions/tooltip-axis.test.ts +176 -0
- package/src/grammar/interactions/tooltip-touch.browser.test.ts +49 -0
- package/src/grammar/interactions/tooltip-touch.test.ts +161 -0
- package/src/grammar/interactions/tooltip.d.ts +140 -0
- package/src/grammar/interactions/tooltip.test.ts +406 -0
- package/src/grammar/interactions/tooltip.ts +622 -0
- package/src/grammar/interactions/transitions.d.ts +34 -0
- package/src/grammar/interactions/transitions.test.ts +172 -0
- package/src/grammar/interactions/transitions.ts +160 -0
- package/src/grammar/layout.d.ts +68 -0
- package/src/grammar/layout.ts +186 -0
- package/src/grammar/legend-merge.test.ts +332 -0
- package/src/grammar/mount.d.ts +78 -0
- package/src/grammar/mount.test.ts +479 -0
- package/src/grammar/mount.ts +2112 -0
- package/src/grammar/palettes.d.ts +54 -0
- package/src/grammar/palettes.test.ts +80 -0
- package/src/grammar/palettes.ts +167 -0
- package/src/grammar/pan-zoom.test.ts +398 -0
- package/src/grammar/phylo.d.ts +65 -0
- package/src/grammar/phylo.test.ts +59 -0
- package/src/grammar/phylo.ts +112 -0
- package/src/grammar/pipeline.auto-ticks.test.ts +40 -0
- package/src/grammar/pipeline.d.ts +158 -0
- package/src/grammar/pipeline.test.ts +463 -0
- package/src/grammar/pipeline.ts +1233 -0
- package/src/grammar/profiling.d.ts +8 -0
- package/src/grammar/profiling.ts +24 -0
- package/src/grammar/scales.d.ts +188 -0
- package/src/grammar/scales.test.ts +181 -0
- package/src/grammar/scales.ts +800 -0
- package/src/grammar/svg.d.ts +3 -0
- package/src/grammar/svg.ts +39 -0
- package/src/grammar/theme.d.ts +261 -0
- package/src/grammar/theme.test.ts +105 -0
- package/src/grammar/theme.ts +490 -0
- package/src/heatmap/cpu.ts +109 -0
- package/src/heatmap/gpu.ts +565 -0
- package/src/heatmap/types.ts +177 -0
- package/src/heatmap.browser.test.ts +308 -0
- package/src/heatmap.test.ts +320 -0
- package/src/heatmap.ts +123 -0
- package/src/index.d.ts +1 -0
- package/src/index.ts +8 -0
- package/src/interactions.d.ts +48 -0
- package/src/interactions.test.ts +226 -0
- package/src/interactions.ts +394 -0
- package/src/layout/box.d.ts +48 -0
- package/src/layout/box.test.ts +107 -0
- package/src/layout/box.ts +143 -0
- package/src/legend.d.ts +115 -0
- package/src/legend.ts +422 -0
- package/src/marks/curve.d.ts +43 -0
- package/src/marks/curve.ts +244 -0
- package/src/marks/stack.d.ts +53 -0
- package/src/marks/stack.ts +184 -0
- package/src/marks.d.ts +273 -0
- package/src/marks.test.ts +541 -0
- package/src/marks.ts +1292 -0
- package/src/navigator.test.ts +174 -0
- package/src/navigator.ts +393 -0
- package/src/range-presets.d.ts +113 -0
- package/src/range-presets.test.ts +345 -0
- package/src/range-presets.ts +349 -0
- package/src/scales.d.ts +98 -0
- package/src/scales.test.ts +103 -0
- package/src/scales.ts +695 -0
- package/src/stats/index.d.ts +200 -0
- package/src/stats/index.test.ts +349 -0
- package/src/stats/index.ts +740 -0
- package/src/stats/regression.d.ts +38 -0
- package/src/stats/regression.test.ts +56 -0
- package/src/stats/regression.ts +396 -0
- package/src/stats/rolling-window.d.ts +55 -0
- package/src/stats/rolling-window.test.ts +237 -0
- package/src/stats/rolling-window.ts +256 -0
- package/src/test-setup.ts +19 -0
- package/src/viewport/axis-state.d.ts +72 -0
- package/src/viewport/axis-state.ts +476 -0
- package/src/viewport.d.ts +170 -0
- package/src/viewport.test.ts +363 -0
- package/src/viewport.ts +510 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
// Tests for P1-A: touch-tap (onPress) wiring in tooltip and series-readout.
|
|
2
|
+
//
|
|
3
|
+
// These are unit tests — no GPU, no canvas. They verify:
|
|
4
|
+
// 1. onPress calls commit() immediately (no settle delay)
|
|
5
|
+
// 2. onHoverEnter still goes through the settle debounce unchanged
|
|
6
|
+
// 3. onPress fires the onHover callback (so hoverSignal in mount gets the hit)
|
|
7
|
+
// 4. series-readout's onPress updates cursorX
|
|
8
|
+
|
|
9
|
+
import { createInvalidator, type GlyphAtlas, type TooltipBounds } from "insomni";
|
|
10
|
+
import { describe, expect, test, vi } from "vite-plus/test";
|
|
11
|
+
|
|
12
|
+
import type { CompiledHitTest, HoveredHit } from "../geoms/types.ts";
|
|
13
|
+
import { themeDefault } from "../theme.ts";
|
|
14
|
+
import { createGrammarTooltip } from "./tooltip.ts";
|
|
15
|
+
import type { GrammarHitLayer, HitEventContext, HitLayerSubscriber } from "./hit-layer.ts";
|
|
16
|
+
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// Helpers
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
|
|
21
|
+
interface Row {
|
|
22
|
+
name: string;
|
|
23
|
+
v: number;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function makeHit(data: readonly Row[], indices: number[]): CompiledHitTest<Row> {
|
|
27
|
+
return {
|
|
28
|
+
geomKind: "point",
|
|
29
|
+
positions: Float32Array.from(indices.flatMap((_, i) => [i * 10, 50])),
|
|
30
|
+
dataIndex: Int32Array.from(indices),
|
|
31
|
+
pickRadius: 5,
|
|
32
|
+
channels: {},
|
|
33
|
+
data,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function makePointer(x: number, y: number): HitEventContext["pointer"] {
|
|
38
|
+
return { x, y } as HitEventContext["pointer"];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Harness that exposes both onHoverEnter and onPress so tests can fire them
|
|
43
|
+
* directly, plus an optional settleDelay for debounce verification.
|
|
44
|
+
*/
|
|
45
|
+
function harness(opts?: { settleDelay?: number }) {
|
|
46
|
+
const data: Row[] = [
|
|
47
|
+
{ name: "A", v: 1 },
|
|
48
|
+
{ name: "B", v: 2 },
|
|
49
|
+
];
|
|
50
|
+
let sub: HitLayerSubscriber | null = null;
|
|
51
|
+
const hitLayer = {
|
|
52
|
+
subscribe(s: HitLayerSubscriber) {
|
|
53
|
+
sub = s;
|
|
54
|
+
return () => {
|
|
55
|
+
sub = null;
|
|
56
|
+
};
|
|
57
|
+
},
|
|
58
|
+
} as unknown as GrammarHitLayer;
|
|
59
|
+
|
|
60
|
+
const ctxFor = (idx: number): HitEventContext => ({
|
|
61
|
+
hit: { geomKind: "point", dataIndex: idx, data, x: idx * 10, y: 50 } as HoveredHit,
|
|
62
|
+
compiled: makeHit(data, [idx]) as CompiledHitTest<unknown>,
|
|
63
|
+
hitIndex: 0,
|
|
64
|
+
pointer: makePointer(idx * 10, 50),
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const onHover = vi.fn();
|
|
68
|
+
const tip = createGrammarTooltip(
|
|
69
|
+
{
|
|
70
|
+
hitLayer,
|
|
71
|
+
hudLayer: () => ({}) as never,
|
|
72
|
+
atlas: () => undefined as GlyphAtlas | undefined,
|
|
73
|
+
theme: () => themeDefault,
|
|
74
|
+
bounds: (): TooltipBounds => ({ x: 0, y: 0, width: 500, height: 500 }),
|
|
75
|
+
invalidator: createInvalidator(),
|
|
76
|
+
},
|
|
77
|
+
{ settleDelay: opts?.settleDelay, onHover },
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
tip,
|
|
82
|
+
onHover,
|
|
83
|
+
enter: (idx: number) => sub!.onHoverEnter!(ctxFor(idx)),
|
|
84
|
+
press: (idx: number) => sub!.onPress!(ctxFor(idx)),
|
|
85
|
+
leave: () => sub!.onHoverLeave!(ctxFor(0)),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// ---------------------------------------------------------------------------
|
|
90
|
+
// onPress bypasses settle
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
|
|
93
|
+
describe("createGrammarTooltip — onPress touch-tap path", () => {
|
|
94
|
+
test("onPress commits immediately even with a non-zero settleDelay", () => {
|
|
95
|
+
// With settleDelay=200ms, onHoverEnter would need step() to elapse before
|
|
96
|
+
// committing. onPress must commit synchronously.
|
|
97
|
+
const h = harness({ settleDelay: 200 });
|
|
98
|
+
h.press(0);
|
|
99
|
+
// onHover should have been fired immediately — no step() needed.
|
|
100
|
+
expect(h.onHover).toHaveBeenCalledTimes(1);
|
|
101
|
+
expect(h.onHover.mock.calls[0]![0]).toMatchObject({ dataIndex: 0 });
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test("onPress fires onHover with the hit object", () => {
|
|
105
|
+
const h = harness({ settleDelay: 100 });
|
|
106
|
+
h.press(1);
|
|
107
|
+
const hit = h.onHover.mock.calls[0]![0] as HoveredHit;
|
|
108
|
+
expect(hit.dataIndex).toBe(1);
|
|
109
|
+
expect(hit.x).toBe(10); // idx=1 → x=10
|
|
110
|
+
expect(hit.y).toBe(50);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test("onHoverEnter fires onHover immediately (crosshair) but defers tooltip show until settle", () => {
|
|
114
|
+
const h = harness({ settleDelay: 100 });
|
|
115
|
+
h.enter(0);
|
|
116
|
+
// onHover fires immediately for crosshair/hoverSignal.
|
|
117
|
+
expect(h.onHover).toHaveBeenCalledTimes(1);
|
|
118
|
+
expect(h.onHover.mock.calls[0]![0]).toMatchObject({ dataIndex: 0 });
|
|
119
|
+
// Mid-window: tooltip show still deferred; no extra onHover.
|
|
120
|
+
h.tip.step(0.05);
|
|
121
|
+
expect(h.onHover).toHaveBeenCalledTimes(1);
|
|
122
|
+
// Past the window: settle commits tooltip show without re-firing onHover.
|
|
123
|
+
h.tip.step(0.06);
|
|
124
|
+
expect(h.onHover).toHaveBeenCalledTimes(1);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
test("onPress while a hover settle is pending clears pending and commits immediately — no stale settle fires", () => {
|
|
128
|
+
const h = harness({ settleDelay: 100 });
|
|
129
|
+
// Start a hover but don't let it settle.
|
|
130
|
+
h.enter(0);
|
|
131
|
+
// onHover fires immediately for crosshair (call 1, dataIndex 0).
|
|
132
|
+
expect(h.onHover).toHaveBeenCalledTimes(1);
|
|
133
|
+
expect(h.onHover.mock.calls[0]![0]).toMatchObject({ dataIndex: 0 });
|
|
134
|
+
h.tip.step(0.05);
|
|
135
|
+
expect(h.onHover).toHaveBeenCalledTimes(1);
|
|
136
|
+
// Touch tap arrives before hover settles — should commit index 1 right away.
|
|
137
|
+
h.press(1);
|
|
138
|
+
// onPress fires commit which calls onHover (call 2, dataIndex 1).
|
|
139
|
+
expect(h.onHover).toHaveBeenCalledTimes(2);
|
|
140
|
+
expect(h.onHover.mock.calls[1]![0]).toMatchObject({ dataIndex: 1 });
|
|
141
|
+
// Step well past the settle window — the old pending was cleared by
|
|
142
|
+
// onPress, so no stale settle should fire.
|
|
143
|
+
h.tip.step(1.0);
|
|
144
|
+
expect(h.onHover).toHaveBeenCalledTimes(2);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
test("onPress with settleDelay=0 also commits immediately", () => {
|
|
148
|
+
const h = harness({ settleDelay: 0 });
|
|
149
|
+
h.press(0);
|
|
150
|
+
expect(h.onHover).toHaveBeenCalledTimes(1);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
test("onPress clears stale pending even when no previous enter was settling", () => {
|
|
154
|
+
// Verify the fix is idempotent — clearing null pending is safe.
|
|
155
|
+
const h = harness({ settleDelay: 100 });
|
|
156
|
+
h.press(0);
|
|
157
|
+
expect(h.onHover).toHaveBeenCalledTimes(1);
|
|
158
|
+
h.tip.step(1.0);
|
|
159
|
+
expect(h.onHover).toHaveBeenCalledTimes(1);
|
|
160
|
+
});
|
|
161
|
+
});
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { type GlyphAtlas, type Invalidator, type Layer, type TooltipBounds, type TooltipContent } from "insomni";
|
|
2
|
+
import type { AxisTooltipContentResolver, TooltipContentResolver, TooltipContentResult } from "../chart.ts";
|
|
3
|
+
import type { CompiledHitTest, HoveredHit, ScaleBundle } from "../geoms/types.ts";
|
|
4
|
+
import { type SnapGroup, type SnapResult } from "./series-snap.ts";
|
|
5
|
+
import type { Theme } from "../theme.ts";
|
|
6
|
+
import type { GrammarHitLayer } from "./hit-layer.ts";
|
|
7
|
+
export interface GrammarTooltipOptions {
|
|
8
|
+
/** Hover-intent delay before showing (ms). Default from theme.motion.tooltip.showDelay. */
|
|
9
|
+
showDelay?: number;
|
|
10
|
+
/** Linger before hiding (ms). Default from theme.motion.tooltip.hideDelay. */
|
|
11
|
+
hideDelay?: number;
|
|
12
|
+
/** Fade duration (ms). 0 disables. Default from theme.motion.tooltip.fadeMs. */
|
|
13
|
+
fadeMs?: number;
|
|
14
|
+
/**
|
|
15
|
+
* Hover-intent settle (ms). Coalesces rapid enter/leave/switch events so the
|
|
16
|
+
* tooltip only commits a show/hide once the cursor holds a target this long —
|
|
17
|
+
* sweeping across a dense mark grid or through gaps no longer fires an overlay
|
|
18
|
+
* re-render per cell. 0 disables (commit immediately).
|
|
19
|
+
* Default from theme.motion.tooltip.settleDelay.
|
|
20
|
+
*/
|
|
21
|
+
settleDelay?: number;
|
|
22
|
+
/** Override placement. Default "top". */
|
|
23
|
+
placement?: "top" | "bottom" | "left" | "right" | "auto";
|
|
24
|
+
/**
|
|
25
|
+
* Consumer-supplied content resolver. Returning a string / shorthand
|
|
26
|
+
* overrides the auto-built channel rows; returning null / undefined falls
|
|
27
|
+
* back to the default builder.
|
|
28
|
+
*/
|
|
29
|
+
content?: TooltipContentResolver;
|
|
30
|
+
/**
|
|
31
|
+
* Optional secondary observer fired alongside the tooltip's own show/hide.
|
|
32
|
+
* Receives the active `HoveredHit` (geom kind, data array reference, data
|
|
33
|
+
* index, snapped position) on enter, and `null` on leave. Used by the
|
|
34
|
+
* grammar crosshair to track hit positions, and by the mount to publish
|
|
35
|
+
* `hovered` as a public signal.
|
|
36
|
+
*
|
|
37
|
+
* Also fires on touch-tap (`onPress`) since that path calls `commit` which
|
|
38
|
+
* calls this callback, bypassing the settle debounce.
|
|
39
|
+
*/
|
|
40
|
+
onHover?(info: HoveredHit | null): void;
|
|
41
|
+
/**
|
|
42
|
+
* Trigger model. Default `"item"` (one box per hovered mark — unchanged).
|
|
43
|
+
* `"axis"` = floating unified readout snapping to the nearest data column.
|
|
44
|
+
*/
|
|
45
|
+
trigger?: "item" | "axis";
|
|
46
|
+
/** Snap axis for `trigger:"axis"`. Default `"x"`. */
|
|
47
|
+
axis?: "x" | "y";
|
|
48
|
+
/** Axis-mode content hook (replaces the auto rows when it returns a shorthand). */
|
|
49
|
+
axisContent?: AxisTooltipContentResolver;
|
|
50
|
+
/** Format the snapped column value (title) in axis mode. */
|
|
51
|
+
axisTitleFormat?: (v: unknown) => string;
|
|
52
|
+
/** Format each auto-built row's value in axis mode. */
|
|
53
|
+
axisValueFormat?: (v: unknown) => string;
|
|
54
|
+
}
|
|
55
|
+
export interface GrammarTooltipDeps {
|
|
56
|
+
hitLayer: GrammarHitLayer;
|
|
57
|
+
hudLayer: () => Layer;
|
|
58
|
+
atlas: () => GlyphAtlas | undefined;
|
|
59
|
+
theme: () => Theme;
|
|
60
|
+
bounds: () => TooltipBounds;
|
|
61
|
+
invalidator: Invalidator;
|
|
62
|
+
/**
|
|
63
|
+
* Optional: current cursor position in element-local CSS px. When provided,
|
|
64
|
+
* the tooltip anchor follows the cursor every frame while visible — no need
|
|
65
|
+
* to wait for a cell-transition enter event.
|
|
66
|
+
*/
|
|
67
|
+
pointerPos?: () => {
|
|
68
|
+
x: number;
|
|
69
|
+
y: number;
|
|
70
|
+
} | null;
|
|
71
|
+
/** Latest resolved scales (axis-mode swatch resolution). Optional. */
|
|
72
|
+
scales?: () => ScaleBundle | null;
|
|
73
|
+
/**
|
|
74
|
+
* Axis-mode pointer source: a full-frame interaction node registered by the
|
|
75
|
+
* mount. The tooltip subscribes for cursor tracking when `trigger:"axis"`.
|
|
76
|
+
* Returns an unregister fn.
|
|
77
|
+
*/
|
|
78
|
+
onAxisPointer?: (handlers: {
|
|
79
|
+
move(p: {
|
|
80
|
+
x: number;
|
|
81
|
+
y: number;
|
|
82
|
+
}): void;
|
|
83
|
+
leave(): void;
|
|
84
|
+
}) => () => void;
|
|
85
|
+
}
|
|
86
|
+
export interface GrammarTooltip {
|
|
87
|
+
/** Tick opacity + delay timers. */
|
|
88
|
+
step(dt: number): void;
|
|
89
|
+
/** Draw into the hud layer. */
|
|
90
|
+
draw(): void;
|
|
91
|
+
dispose(): void;
|
|
92
|
+
/** Push fresh compiled hit-tests (axis mode only; item mode ignores). */
|
|
93
|
+
syncHits?<T>(hits: readonly CompiledHitTest<T>[]): void;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Best-effort default formatter. Numbers go through `Intl.NumberFormat` with
|
|
97
|
+
* adaptive precision; Dates through ISO; booleans/strings stringify.
|
|
98
|
+
*/
|
|
99
|
+
export declare function defaultFormat(value: unknown): string;
|
|
100
|
+
/**
|
|
101
|
+
* Normalize a consumer-supplied resolver result into the canvas tooltip's
|
|
102
|
+
* `TooltipContent` shape. Returns null if the result is null/undefined so the
|
|
103
|
+
* caller can fall through to the default builder.
|
|
104
|
+
*
|
|
105
|
+
* - `string` → single value-only row.
|
|
106
|
+
* - `{ title, rows }` shorthand → rows mapped through the default formatter
|
|
107
|
+
* (strings pass through) with accent → row color via theme.
|
|
108
|
+
*
|
|
109
|
+
* Exported for tests and for reuse by alternative tooltip hosts.
|
|
110
|
+
*/
|
|
111
|
+
export declare function normalizeTooltipContent(result: TooltipContentResult | null | undefined, theme: Theme): TooltipContent | null;
|
|
112
|
+
/**
|
|
113
|
+
* Resolve final tooltip content for a hit: run the consumer resolver if any,
|
|
114
|
+
* normalize the result, and fall back to the default channel-driven content
|
|
115
|
+
* when the resolver returns null/undefined.
|
|
116
|
+
*/
|
|
117
|
+
export declare function resolveTooltipContent<T>(hit: CompiledHitTest<T>, hitIndex: number, theme: Theme, resolver?: TooltipContentResolver): TooltipContent;
|
|
118
|
+
/**
|
|
119
|
+
* Build the axis-mode tooltip content from a snap result. Pure (no GPU / no
|
|
120
|
+
* closure state) so it is unit-testable. For `axis:"x"` each auto row's value
|
|
121
|
+
* is the series Y; for `axis:"y"` it is the series X. When `axisContent`
|
|
122
|
+
* returns a shorthand it REPLACES the auto rows (normalized through the theme).
|
|
123
|
+
*/
|
|
124
|
+
export declare function buildAxisTooltipContent(args: {
|
|
125
|
+
result: SnapResult;
|
|
126
|
+
axis: "x" | "y";
|
|
127
|
+
scales: ScaleBundle | null;
|
|
128
|
+
theme: Theme;
|
|
129
|
+
titleFormat: (v: unknown) => string;
|
|
130
|
+
valueFormat: (v: unknown) => string;
|
|
131
|
+
axisContent?: AxisTooltipContentResolver;
|
|
132
|
+
}): TooltipContent;
|
|
133
|
+
/** Project a snap group's picked hit to a `HoveredHit` (for crosshair snap). */
|
|
134
|
+
export declare function hoveredHitFromGroup(g: SnapGroup): HoveredHit;
|
|
135
|
+
export declare function createGrammarTooltip(deps: GrammarTooltipDeps, opts?: GrammarTooltipOptions): GrammarTooltip;
|
|
136
|
+
/** @internal — exposed for unit tests only. */
|
|
137
|
+
export declare const __test__: {
|
|
138
|
+
buildAxisTooltipContent: typeof buildAxisTooltipContent;
|
|
139
|
+
hoveredHitFromGroup: typeof hoveredHitFromGroup;
|
|
140
|
+
};
|