@perspective-dev/viewer-charts 5.3.0 → 5.4.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/dist/cdn/perspective-viewer-charts.js +1 -2
- package/dist/cdn/perspective-viewer-charts.js.map +4 -4
- package/dist/esm/axis/legend.d.ts +53 -5
- package/dist/esm/axis/map-ticks.d.ts +15 -0
- package/dist/esm/charts/candlestick/candlestick-interact.d.ts +2 -6
- package/dist/esm/charts/cartesian/cartesian.d.ts +6 -0
- package/dist/esm/charts/cartesian/glyph.d.ts +2 -1
- package/dist/esm/charts/cartesian/glyphs/density.d.ts +2 -1
- package/dist/esm/charts/cartesian/glyphs/lines.d.ts +2 -1
- package/dist/esm/charts/cartesian/glyphs/points.d.ts +2 -1
- package/dist/esm/charts/cartesian/tooltip-lines.d.ts +1 -1
- package/dist/esm/charts/chart-base.d.ts +2 -0
- package/dist/esm/charts/chart.d.ts +77 -6
- package/dist/esm/charts/common/draw-tooltip-box.d.ts +2 -1
- package/dist/esm/charts/common/tree-interact.d.ts +1 -1
- package/dist/esm/charts/series/series-build.d.ts +7 -0
- package/dist/esm/charts/series/series-interact.d.ts +1 -1
- package/dist/esm/charts/series/series.d.ts +6 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/interaction/axis-indicators.d.ts +11 -0
- package/dist/esm/interaction/host-sink-dom.d.ts +3 -2
- package/dist/esm/interaction/host-sink-message.d.ts +3 -2
- package/dist/esm/interaction/lazy-tooltip.d.ts +2 -2
- package/dist/esm/interaction/legend-controller.d.ts +246 -0
- package/dist/esm/interaction/tooltip-controller.d.ts +20 -95
- package/dist/esm/interaction/tooltip-grid.d.ts +33 -0
- package/dist/esm/layout/facet-grid.d.ts +6 -0
- package/dist/esm/layout/ticks.d.ts +1 -0
- package/dist/esm/map/tile-source.d.ts +77 -8
- package/dist/esm/perspective-viewer-charts.js +1 -2
- package/dist/esm/perspective-viewer-charts.js.map +4 -4
- package/dist/esm/plugin/charts.d.ts +2 -0
- package/dist/esm/plugin/format-defaults.d.ts +9 -0
- package/dist/esm/plugin/plugin.d.ts +20 -0
- package/dist/esm/theme/gradient.d.ts +1 -0
- package/dist/esm/transport/protocol.d.ts +45 -3
- package/dist/esm/transport/renderer-transport.d.ts +3 -0
- package/dist/esm/worker/renderer.worker.d.ts +19 -1
- package/package.json +6 -6
- package/src/css/perspective-viewer-charts.css +0 -1
- package/src/ts/axis/bar-axis.ts +2 -7
- package/src/ts/axis/legend.ts +351 -24
- package/src/ts/axis/map-ticks.ts +94 -0
- package/src/ts/axis/numeric-axis.ts +2 -9
- package/src/ts/charts/candlestick/candlestick-interact.ts +46 -40
- package/src/ts/charts/candlestick/candlestick-render.ts +73 -10
- package/src/ts/charts/cartesian/cartesian-interact.ts +9 -3
- package/src/ts/charts/cartesian/cartesian-render.ts +369 -75
- package/src/ts/charts/cartesian/cartesian.ts +9 -0
- package/src/ts/charts/cartesian/glyph.ts +6 -2
- package/src/ts/charts/cartesian/glyphs/density.ts +2 -2
- package/src/ts/charts/cartesian/glyphs/lines.ts +15 -11
- package/src/ts/charts/cartesian/glyphs/points.ts +9 -5
- package/src/ts/charts/cartesian/tooltip-lines.ts +8 -8
- package/src/ts/charts/chart-base.ts +34 -32
- package/src/ts/charts/chart.ts +106 -7
- package/src/ts/charts/common/draw-tooltip-box.ts +13 -30
- package/src/ts/charts/common/tree-chrome.ts +102 -23
- package/src/ts/charts/common/tree-interact.ts +18 -17
- package/src/ts/charts/heatmap/heatmap-interact.ts +65 -7
- package/src/ts/charts/heatmap/heatmap-render.ts +100 -24
- package/src/ts/charts/map/map.ts +3 -5
- package/src/ts/charts/series/series-build.ts +14 -2
- package/src/ts/charts/series/series-interact.ts +12 -11
- package/src/ts/charts/series/series-render.ts +305 -132
- package/src/ts/charts/series/series.ts +10 -0
- package/src/ts/charts/sunburst/sunburst-render.ts +7 -1
- package/src/ts/charts/treemap/treemap-render.ts +7 -1
- package/src/ts/data/view-reader.ts +1 -4
- package/src/ts/index.ts +2 -0
- package/src/ts/interaction/axis-indicators.ts +137 -0
- package/src/ts/interaction/host-sink-dom.ts +66 -2
- package/src/ts/interaction/host-sink-message.ts +8 -2
- package/src/ts/interaction/lazy-tooltip.ts +5 -5
- package/src/ts/interaction/legend-controller.ts +1084 -0
- package/src/ts/interaction/tooltip-controller.ts +43 -131
- package/src/ts/interaction/tooltip-grid.ts +187 -0
- package/src/ts/layout/facet-grid.ts +8 -1
- package/src/ts/layout/ticks.ts +12 -0
- package/src/ts/map/tile-loader.ts +16 -1
- package/src/ts/map/tile-source.ts +199 -53
- package/src/ts/map/tile-sources.json +18 -0
- package/src/ts/plugin/charts.ts +40 -6
- package/src/ts/plugin/format-defaults.ts +37 -0
- package/src/ts/plugin/plugin.ts +236 -67
- package/src/ts/shaders/line.vert.glsl +5 -2
- package/src/ts/shaders/scatter.vert.glsl +0 -7
- package/src/ts/theme/gradient.ts +24 -0
- package/src/ts/transport/protocol.ts +46 -2
- package/src/ts/transport/renderer-transport.ts +83 -4
- package/src/ts/worker/dispatch.ts +6 -2
- package/src/ts/worker/renderer.worker.ts +78 -2
|
@@ -23,6 +23,7 @@ import { Theme } from "../../theme/theme";
|
|
|
23
23
|
import { resolvePalette, type Vec3 } from "../../theme/palette";
|
|
24
24
|
import { type GradientStop } from "../../theme/gradient";
|
|
25
25
|
import { buildFacetGrid } from "../../layout/facet-grid";
|
|
26
|
+
import { legendTreeGutter } from "../../interaction/legend-controller";
|
|
26
27
|
import { leafColor, leafRGBA, luminance } from "../common/leaf-color";
|
|
27
28
|
import treemapVert from "../../shaders/treemap.vert.glsl";
|
|
28
29
|
import treemapFrag from "../../shaders/treemap.frag.glsl";
|
|
@@ -70,7 +71,12 @@ export function renderTreemapFrame(
|
|
|
70
71
|
? chart._uniqueColorLabels.size > 1
|
|
71
72
|
: chart._colorMode === "numeric" &&
|
|
72
73
|
chart._colorMin < chart._colorMax;
|
|
73
|
-
const legendW =
|
|
74
|
+
const legendW = legendTreeGutter(
|
|
75
|
+
chart._pluginConfig,
|
|
76
|
+
hasLegend,
|
|
77
|
+
90,
|
|
78
|
+
chart._colorMode === "series" ? chart._uniqueColorLabels.size : 0,
|
|
79
|
+
);
|
|
74
80
|
|
|
75
81
|
// Scratch buffer for the ordered-layout child ids. Worst case:
|
|
76
82
|
// active children at every level = store.count. Reuse the chart's
|
|
@@ -95,12 +95,9 @@ export async function viewToColumnDataMap(
|
|
|
95
95
|
} else if (vals instanceof Float64Array) {
|
|
96
96
|
// Datetime/Date columns are emitted as Float64 to keep
|
|
97
97
|
// millisecond precision; numeric Float64 also lands here
|
|
98
|
-
// when `float32` mode is off.
|
|
99
|
-
// chart's CPU mirrors and extents will rebase to f32 at
|
|
100
|
-
// upload time.
|
|
98
|
+
// when `float32` mode is off.
|
|
101
99
|
result.set(name, { type: "float64", values: vals, valid });
|
|
102
100
|
} else {
|
|
103
|
-
// Fallback: treat as float32
|
|
104
101
|
// TODO: Instance check if this needs a copy?
|
|
105
102
|
result.set(name, {
|
|
106
103
|
type: "float32",
|
package/src/ts/index.ts
CHANGED
|
@@ -15,6 +15,8 @@ import { HTMLPerspectiveViewerWebGLPluginElement } from "./plugin/plugin";
|
|
|
15
15
|
|
|
16
16
|
export type { PerspectiveClickDetail } from "./event-detail";
|
|
17
17
|
export { PerspectiveSelectDetail } from "./event-detail";
|
|
18
|
+
export { registerTileSource } from "./plugin/plugin";
|
|
19
|
+
export { tileSources, type TileSourceSpec } from "./map/tile-source";
|
|
18
20
|
|
|
19
21
|
export function register(...plugin_names: string[]) {
|
|
20
22
|
const plugins = new Set(
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
2
|
+
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
|
3
|
+
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
|
4
|
+
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
|
5
|
+
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
|
6
|
+
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
|
7
|
+
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
|
8
|
+
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
|
9
|
+
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
|
10
|
+
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
|
+
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
|
+
|
|
13
|
+
import type { Canvas2D, Context2D } from "../charts/canvas-types";
|
|
14
|
+
import type { PlotLayout } from "../layout/plot-layout";
|
|
15
|
+
import type { Theme } from "../theme/theme";
|
|
16
|
+
|
|
17
|
+
export type AxisSide = "bottom" | "left" | "right";
|
|
18
|
+
|
|
19
|
+
export interface AxisIndicator {
|
|
20
|
+
side: AxisSide;
|
|
21
|
+
|
|
22
|
+
px: number;
|
|
23
|
+
py: number;
|
|
24
|
+
|
|
25
|
+
text: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const BADGE_FONT_PX = 11;
|
|
29
|
+
const BADGE_PAD_H = 4;
|
|
30
|
+
const BADGE_PAD_V = 2;
|
|
31
|
+
const BADGE_GAP = 4;
|
|
32
|
+
|
|
33
|
+
export function renderAxisHoverIndicators(
|
|
34
|
+
canvas: Canvas2D | null,
|
|
35
|
+
layout: PlotLayout,
|
|
36
|
+
theme: Theme,
|
|
37
|
+
dpr: number,
|
|
38
|
+
indicators: AxisIndicator[],
|
|
39
|
+
opacity: number = 1.0,
|
|
40
|
+
): void {
|
|
41
|
+
if (!canvas || indicators.length === 0) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const ctx = canvas.getContext("2d") as Context2D | null;
|
|
46
|
+
if (!ctx) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const plot = layout.plotRect;
|
|
51
|
+
ctx.save();
|
|
52
|
+
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
53
|
+
ctx.scale(dpr, dpr);
|
|
54
|
+
ctx.font = `${BADGE_FONT_PX}px ${theme.fontFamily}`;
|
|
55
|
+
|
|
56
|
+
for (const ind of indicators) {
|
|
57
|
+
if (
|
|
58
|
+
ind.px < plot.x ||
|
|
59
|
+
ind.px > plot.x + plot.width ||
|
|
60
|
+
ind.py < plot.y ||
|
|
61
|
+
ind.py > plot.y + plot.height
|
|
62
|
+
) {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
drawTraceLine(ctx, ind, plot, theme);
|
|
67
|
+
drawBadge(ctx, ind, layout, theme, opacity);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
ctx.restore();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function drawTraceLine(
|
|
74
|
+
ctx: Context2D,
|
|
75
|
+
ind: AxisIndicator,
|
|
76
|
+
plot: { x: number; y: number; width: number; height: number },
|
|
77
|
+
theme: Theme,
|
|
78
|
+
): void {
|
|
79
|
+
ctx.strokeStyle = theme.tickColor;
|
|
80
|
+
ctx.lineWidth = 1;
|
|
81
|
+
ctx.setLineDash([4, 4]);
|
|
82
|
+
ctx.beginPath();
|
|
83
|
+
ctx.moveTo(ind.px, ind.py);
|
|
84
|
+
if (ind.side === "bottom") {
|
|
85
|
+
ctx.lineTo(ind.px, plot.y + plot.height);
|
|
86
|
+
} else if (ind.side === "left") {
|
|
87
|
+
ctx.lineTo(plot.x, ind.py);
|
|
88
|
+
} else {
|
|
89
|
+
ctx.lineTo(plot.x + plot.width, ind.py);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
ctx.stroke();
|
|
93
|
+
ctx.setLineDash([]);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function drawBadge(
|
|
97
|
+
ctx: Context2D,
|
|
98
|
+
ind: AxisIndicator,
|
|
99
|
+
layout: PlotLayout,
|
|
100
|
+
theme: Theme,
|
|
101
|
+
opacity: number,
|
|
102
|
+
): void {
|
|
103
|
+
const plot = layout.plotRect;
|
|
104
|
+
const boxW = ctx.measureText(ind.text).width + BADGE_PAD_H * 2;
|
|
105
|
+
const boxH = BADGE_FONT_PX + BADGE_PAD_V * 2 + 2;
|
|
106
|
+
|
|
107
|
+
let bx: number;
|
|
108
|
+
let by: number;
|
|
109
|
+
if (ind.side === "bottom") {
|
|
110
|
+
bx = ind.px - boxW / 2;
|
|
111
|
+
by = plot.y + plot.height + BADGE_GAP;
|
|
112
|
+
} else if (ind.side === "left") {
|
|
113
|
+
bx = plot.x - BADGE_GAP - boxW;
|
|
114
|
+
by = ind.py - boxH / 2;
|
|
115
|
+
} else {
|
|
116
|
+
bx = plot.x + plot.width + BADGE_GAP;
|
|
117
|
+
by = ind.py - boxH / 2;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
bx = Math.min(Math.max(bx, 0), Math.max(0, layout.cssWidth - boxW));
|
|
121
|
+
by = Math.min(Math.max(by, 0), Math.max(0, layout.cssHeight - boxH));
|
|
122
|
+
|
|
123
|
+
ctx.globalAlpha = Math.min(1, Math.max(0, opacity));
|
|
124
|
+
ctx.fillStyle = theme.tooltipBg;
|
|
125
|
+
ctx.strokeStyle = theme.tooltipBorder;
|
|
126
|
+
ctx.lineWidth = 1;
|
|
127
|
+
ctx.beginPath();
|
|
128
|
+
ctx.rect(bx, by, boxW, boxH);
|
|
129
|
+
ctx.fill();
|
|
130
|
+
ctx.stroke();
|
|
131
|
+
ctx.globalAlpha = 1.0;
|
|
132
|
+
|
|
133
|
+
ctx.fillStyle = theme.tooltipText;
|
|
134
|
+
ctx.textAlign = "left";
|
|
135
|
+
ctx.textBaseline = "middle";
|
|
136
|
+
ctx.fillText(ind.text, bx + BADGE_PAD_H, by + boxH / 2 + 1);
|
|
137
|
+
}
|
|
@@ -11,6 +11,13 @@
|
|
|
11
11
|
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
12
|
|
|
13
13
|
import type { CssBounds, HostSink } from "./tooltip-controller";
|
|
14
|
+
import {
|
|
15
|
+
DEFAULT_TOOLTIP_STYLE,
|
|
16
|
+
NUMERIC_RE,
|
|
17
|
+
TOOLTIP_COL_GAP,
|
|
18
|
+
type TooltipContent,
|
|
19
|
+
type TooltipStyle,
|
|
20
|
+
} from "./tooltip-grid";
|
|
14
21
|
|
|
15
22
|
/**
|
|
16
23
|
* Host-side `HostSink` that materializes pinned tooltips as a `<div>`
|
|
@@ -29,16 +36,17 @@ export class DomHostSink implements HostSink {
|
|
|
29
36
|
}
|
|
30
37
|
|
|
31
38
|
pin(
|
|
32
|
-
|
|
39
|
+
grid: TooltipContent,
|
|
33
40
|
pos: { px: number; py: number },
|
|
34
41
|
bounds: CssBounds,
|
|
42
|
+
style: TooltipStyle = DEFAULT_TOOLTIP_STYLE,
|
|
35
43
|
): void {
|
|
36
44
|
this.dismiss();
|
|
37
45
|
const div = document.createElement("div");
|
|
38
46
|
|
|
39
47
|
div.className = "webgl-tooltip";
|
|
40
48
|
div.style.maxHeight = `${Math.round(bounds.cssHeight * 0.6)}px`;
|
|
41
|
-
div
|
|
49
|
+
renderTooltipGridDom(div, grid, style);
|
|
42
50
|
|
|
43
51
|
if (getComputedStyle(this._parent).position === "static") {
|
|
44
52
|
this._parent.style.position = "relative";
|
|
@@ -83,3 +91,59 @@ export class DomHostSink implements HostSink {
|
|
|
83
91
|
this._glCanvas.style.cursor = cursor;
|
|
84
92
|
}
|
|
85
93
|
}
|
|
94
|
+
|
|
95
|
+
function renderTooltipGridDom(
|
|
96
|
+
root: HTMLDivElement,
|
|
97
|
+
grid: TooltipContent,
|
|
98
|
+
style: TooltipStyle,
|
|
99
|
+
): void {
|
|
100
|
+
const ncols = grid.reduce((n, row) => Math.max(n, row.length), 0);
|
|
101
|
+
root.style.display = "grid";
|
|
102
|
+
root.style.gridTemplateColumns = `repeat(${Math.max(1, ncols)}, minmax(0, max-content))`;
|
|
103
|
+
root.style.columnGap = `${TOOLTIP_COL_GAP}px`;
|
|
104
|
+
if (style.opacity < 1) {
|
|
105
|
+
const pct = Math.max(0, Math.round(style.opacity * 100));
|
|
106
|
+
root.style.background = `color-mix(in srgb, var(--psp-charts--tooltip--background) ${pct}%, transparent)`;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const rightAlign: boolean[] = [];
|
|
110
|
+
for (const row of grid) {
|
|
111
|
+
if (row.length <= 1) {
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
for (let j = 1; j < row.length; j++) {
|
|
116
|
+
if (row[j] === "") {
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const numeric = NUMERIC_RE.test(row[j]);
|
|
121
|
+
rightAlign[j] =
|
|
122
|
+
rightAlign[j] === undefined
|
|
123
|
+
? numeric
|
|
124
|
+
: rightAlign[j] && numeric;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
for (const row of grid) {
|
|
129
|
+
const span = row.length <= 1;
|
|
130
|
+
for (let j = 0; j < Math.max(1, row.length); j++) {
|
|
131
|
+
const cell = document.createElement("div");
|
|
132
|
+
cell.textContent = row[j] ?? "";
|
|
133
|
+
cell.style.maxWidth = `${style.maxColumnPx * (span ? 2 : 1)}px`;
|
|
134
|
+
cell.style.overflow = "hidden";
|
|
135
|
+
cell.style.textOverflow = "ellipsis";
|
|
136
|
+
cell.style.whiteSpace = "nowrap";
|
|
137
|
+
if (span) {
|
|
138
|
+
cell.style.gridColumn = "1 / -1";
|
|
139
|
+
} else if (rightAlign[j]) {
|
|
140
|
+
cell.style.textAlign = "right";
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
root.appendChild(cell);
|
|
144
|
+
if (span) {
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
@@ -23,6 +23,11 @@ import type {
|
|
|
23
23
|
UserClickPayload,
|
|
24
24
|
UserSelectPayload,
|
|
25
25
|
} from "./tooltip-controller";
|
|
26
|
+
import {
|
|
27
|
+
DEFAULT_TOOLTIP_STYLE,
|
|
28
|
+
type TooltipContent,
|
|
29
|
+
type TooltipStyle,
|
|
30
|
+
} from "./tooltip-grid";
|
|
26
31
|
|
|
27
32
|
/**
|
|
28
33
|
* The subset of `WorkerMsg`s that flow chart → host through a
|
|
@@ -52,11 +57,12 @@ export class MessageHostSink implements HostSink {
|
|
|
52
57
|
}
|
|
53
58
|
|
|
54
59
|
pin(
|
|
55
|
-
|
|
60
|
+
grid: TooltipContent,
|
|
56
61
|
pos: { px: number; py: number },
|
|
57
62
|
bounds: CssBounds,
|
|
63
|
+
style: TooltipStyle = DEFAULT_TOOLTIP_STYLE,
|
|
58
64
|
): void {
|
|
59
|
-
this._send({ kind: "pinTooltip",
|
|
65
|
+
this._send({ kind: "pinTooltip", grid, style, pos, bounds });
|
|
60
66
|
}
|
|
61
67
|
|
|
62
68
|
dismiss(): void {
|
|
@@ -32,7 +32,7 @@ export class LazyTooltip<Target> {
|
|
|
32
32
|
/**
|
|
33
33
|
* Cached lines for the latest committed hover, or `null`.
|
|
34
34
|
*/
|
|
35
|
-
|
|
35
|
+
grid: string[][] | null = null;
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
38
|
* Identity of the entity `lines` describe. `null` when cleared.
|
|
@@ -50,7 +50,7 @@ export class LazyTooltip<Target> {
|
|
|
50
50
|
* the write.
|
|
51
51
|
*/
|
|
52
52
|
beginHover(target: Target): number {
|
|
53
|
-
this.
|
|
53
|
+
this.grid = null;
|
|
54
54
|
this.hoveredTarget = target;
|
|
55
55
|
return ++this._hoverSerial;
|
|
56
56
|
}
|
|
@@ -60,12 +60,12 @@ export class LazyTooltip<Target> {
|
|
|
60
60
|
* when the write happened (caller should repaint), false when the
|
|
61
61
|
* serial was stale.
|
|
62
62
|
*/
|
|
63
|
-
commitHover(serial: number,
|
|
63
|
+
commitHover(serial: number, grid: string[][]): boolean {
|
|
64
64
|
if (serial !== this._hoverSerial) {
|
|
65
65
|
return false;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
this.
|
|
68
|
+
this.grid = grid;
|
|
69
69
|
return true;
|
|
70
70
|
}
|
|
71
71
|
|
|
@@ -73,7 +73,7 @@ export class LazyTooltip<Target> {
|
|
|
73
73
|
* Clear hover state (mouse left, view changed, etc.).
|
|
74
74
|
*/
|
|
75
75
|
clearHover(): void {
|
|
76
|
-
this.
|
|
76
|
+
this.grid = null;
|
|
77
77
|
this.hoveredTarget = null;
|
|
78
78
|
this._hoverSerial++;
|
|
79
79
|
}
|