@perspective-dev/viewer-charts 5.2.0 → 5.3.1
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/candlestick/candlestick-render.d.ts +3 -0
- package/dist/esm/charts/cartesian/cartesian.d.ts +7 -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 +24 -9
- package/dist/esm/charts/chart.d.ts +81 -6
- package/dist/esm/charts/common/category-axis-resolver.d.ts +1 -1
- package/dist/esm/charts/common/draw-tooltip-box.d.ts +2 -1
- package/dist/esm/charts/common/tree-chart.d.ts +1 -0
- package/dist/esm/charts/common/tree-interact.d.ts +1 -1
- package/dist/esm/charts/heatmap/heatmap.d.ts +1 -0
- 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-type.d.ts +18 -0
- package/dist/esm/charts/series/series.d.ts +10 -1
- package/dist/esm/charts/sunburst/sunburst-render.d.ts +4 -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 +28 -1
- package/dist/esm/theme/gradient.d.ts +32 -0
- package/dist/esm/theme/overrides.d.ts +19 -0
- package/dist/esm/transport/protocol.d.ts +58 -5
- package/dist/esm/transport/renderer-transport.d.ts +3 -0
- package/dist/esm/utils/css.d.ts +4 -0
- package/dist/esm/worker/renderer.worker.d.ts +46 -1
- package/package.json +1 -1
- 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-build.ts +1 -0
- package/src/ts/charts/candlestick/candlestick-interact.ts +46 -40
- package/src/ts/charts/candlestick/candlestick-render.ts +81 -10
- package/src/ts/charts/candlestick/candlestick.ts +4 -3
- package/src/ts/charts/cartesian/cartesian-interact.ts +9 -3
- package/src/ts/charts/cartesian/cartesian-render.ts +374 -75
- package/src/ts/charts/cartesian/cartesian.ts +13 -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 +76 -42
- package/src/ts/charts/chart.ts +111 -7
- package/src/ts/charts/common/category-axis-resolver.ts +44 -5
- package/src/ts/charts/common/draw-tooltip-box.ts +13 -30
- package/src/ts/charts/common/tree-chart.ts +4 -0
- 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-build.ts +7 -1
- package/src/ts/charts/heatmap/heatmap-interact.ts +75 -8
- package/src/ts/charts/heatmap/heatmap-render.ts +105 -24
- package/src/ts/charts/heatmap/heatmap.ts +8 -3
- package/src/ts/charts/map/map.ts +3 -5
- package/src/ts/charts/series/series-build.ts +15 -2
- package/src/ts/charts/series/series-interact.ts +14 -24
- package/src/ts/charts/series/series-render.ts +310 -132
- package/src/ts/charts/series/series-type.ts +65 -0
- package/src/ts/charts/series/series.ts +31 -8
- package/src/ts/charts/sunburst/sunburst-render.ts +16 -1
- package/src/ts/charts/treemap/treemap-render.ts +12 -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 +48 -12
- 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 +330 -76
- package/src/ts/shaders/line.vert.glsl +5 -2
- package/src/ts/shaders/scatter.vert.glsl +0 -7
- package/src/ts/theme/gradient.ts +265 -1
- package/src/ts/theme/overrides.ts +76 -0
- package/src/ts/transport/protocol.ts +60 -4
- package/src/ts/transport/renderer-transport.ts +107 -14
- package/src/ts/utils/css.ts +12 -0
- package/src/ts/worker/dispatch.ts +6 -2
- package/src/ts/worker/renderer.worker.ts +191 -7
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
import type { CandlestickChart } from "./candlestick";
|
|
14
14
|
import { renderCandlestickChromeOverlay } from "./candlestick-render";
|
|
15
|
+
import { tooltipStyleOf } from "../../interaction/tooltip-grid";
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* Pixels of horizontal slack around the wick centerline so narrow
|
|
@@ -163,24 +164,24 @@ export function showCandlestickPinnedTooltip(
|
|
|
163
164
|
return;
|
|
164
165
|
}
|
|
165
166
|
|
|
166
|
-
const
|
|
167
|
-
if (
|
|
167
|
+
const grid = buildCandlestickTooltipLines(chart, idx);
|
|
168
|
+
if (grid.length === 0) {
|
|
168
169
|
return;
|
|
169
170
|
}
|
|
170
171
|
|
|
171
172
|
const xCenter = candles.xCenter[idx];
|
|
172
173
|
const yMid = (candles.high[idx] + candles.low[idx]) / 2;
|
|
173
174
|
const pos = chart._lastLayout.dataToPixel(xCenter, yMid);
|
|
174
|
-
|
|
175
|
-
// CSS bounds come from the chart's own layout, which is populated
|
|
176
|
-
// by the render path regardless of where the chart runs.
|
|
177
175
|
const cssWidth = chart._lastLayout.cssWidth;
|
|
178
176
|
const cssHeight = chart._lastLayout.cssHeight;
|
|
179
177
|
|
|
180
|
-
chart._tooltip.pin(
|
|
178
|
+
chart._tooltip.pin(
|
|
179
|
+
grid,
|
|
180
|
+
pos,
|
|
181
|
+
{ cssWidth, cssHeight },
|
|
182
|
+
tooltipStyleOf(chart._pluginConfig),
|
|
183
|
+
);
|
|
181
184
|
|
|
182
|
-
// Pinning hides the inline hover tooltip but does not change the
|
|
183
|
-
// WebGL pass — only the chrome overlay needs to redraw.
|
|
184
185
|
chart._hoveredIdx = -1;
|
|
185
186
|
renderCandlestickChromeOverlay(chart);
|
|
186
187
|
}
|
|
@@ -190,19 +191,14 @@ export function dismissCandlestickPinnedTooltip(chart: CandlestickChart): void {
|
|
|
190
191
|
chart._pinnedIdx = -1;
|
|
191
192
|
}
|
|
192
193
|
|
|
193
|
-
/**
|
|
194
|
-
* Build tooltip lines for candle at index `idx` in the columnar
|
|
195
|
-
* storage. Indexed access avoids materializing a `CandleRecord` POJO
|
|
196
|
-
* on the hot tooltip path.
|
|
197
|
-
*/
|
|
198
194
|
export function buildCandlestickTooltipLines(
|
|
199
195
|
chart: CandlestickChart,
|
|
200
196
|
idx: number,
|
|
201
|
-
): string[] {
|
|
202
|
-
const
|
|
197
|
+
): string[][] {
|
|
198
|
+
const grid: string[][] = [];
|
|
203
199
|
const candles = chart._candles;
|
|
204
200
|
if (idx < 0 || idx >= candles.count) {
|
|
205
|
-
return
|
|
201
|
+
return grid;
|
|
206
202
|
}
|
|
207
203
|
|
|
208
204
|
const catIdx = candles.catIdx[idx];
|
|
@@ -212,6 +208,34 @@ export function buildCandlestickTooltipLines(
|
|
|
212
208
|
const high = candles.high[idx];
|
|
213
209
|
const low = candles.low[idx];
|
|
214
210
|
|
|
211
|
+
const categoryText = candleCategoryText(chart, catIdx);
|
|
212
|
+
if (categoryText !== "") {
|
|
213
|
+
grid.push([categoryText]);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (splitIdx >= 0 && chart._splitPrefixes.length > 1) {
|
|
217
|
+
const prefix = chart._splitPrefixes[splitIdx];
|
|
218
|
+
if (prefix) {
|
|
219
|
+
grid.push([prefix]);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const openFmt = chart.getColumnFormatter(chart._columnSlots[0], "value");
|
|
224
|
+
const closeFmt = chart.getColumnFormatter(chart._columnSlots[1], "value");
|
|
225
|
+
const highFmt = chart.getColumnFormatter(chart._columnSlots[2], "value");
|
|
226
|
+
const lowFmt = chart.getColumnFormatter(chart._columnSlots[3], "value");
|
|
227
|
+
grid.push(["Open", openFmt(open)]);
|
|
228
|
+
grid.push(["Close", closeFmt(close)]);
|
|
229
|
+
grid.push(["High", highFmt(high)]);
|
|
230
|
+
grid.push(["Low", lowFmt(low)]);
|
|
231
|
+
|
|
232
|
+
return grid;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export function candleCategoryText(
|
|
236
|
+
chart: CandlestickChart,
|
|
237
|
+
catIdx: number,
|
|
238
|
+
): string {
|
|
215
239
|
if (
|
|
216
240
|
chart._categoryAxisMode === "numeric" &&
|
|
217
241
|
chart._numericCategoryDomain &&
|
|
@@ -219,8 +243,10 @@ export function buildCandlestickTooltipLines(
|
|
|
219
243
|
) {
|
|
220
244
|
const v = chart._categoryPositions[catIdx];
|
|
221
245
|
const xColumn = chart._groupBy[0];
|
|
222
|
-
|
|
223
|
-
}
|
|
246
|
+
return chart.getColumnFormatter(xColumn, "value")(v);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (chart._rowPaths.length > 0) {
|
|
224
250
|
const parts: string[] = [];
|
|
225
251
|
for (const rp of chart._rowPaths) {
|
|
226
252
|
const s = rp.labels[catIdx] ?? "";
|
|
@@ -229,28 +255,8 @@ export function buildCandlestickTooltipLines(
|
|
|
229
255
|
}
|
|
230
256
|
}
|
|
231
257
|
|
|
232
|
-
|
|
233
|
-
lines.push(parts.join(" › "));
|
|
234
|
-
}
|
|
235
|
-
} else {
|
|
236
|
-
lines.push(`Row ${catIdx + chart._rowOffset}`);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
if (splitIdx >= 0 && chart._splitPrefixes.length > 1) {
|
|
240
|
-
const prefix = chart._splitPrefixes[splitIdx];
|
|
241
|
-
if (prefix) {
|
|
242
|
-
lines.push(prefix);
|
|
243
|
-
}
|
|
258
|
+
return parts.join(" › ");
|
|
244
259
|
}
|
|
245
260
|
|
|
246
|
-
|
|
247
|
-
const closeFmt = chart.getColumnFormatter(chart._columnSlots[1], "value");
|
|
248
|
-
const highFmt = chart.getColumnFormatter(chart._columnSlots[2], "value");
|
|
249
|
-
const lowFmt = chart.getColumnFormatter(chart._columnSlots[3], "value");
|
|
250
|
-
lines.push(`Open: ${openFmt(open)}`);
|
|
251
|
-
lines.push(`Close: ${closeFmt(close)}`);
|
|
252
|
-
lines.push(`High: ${highFmt(high)}`);
|
|
253
|
-
lines.push(`Low: ${lowFmt(low)}`);
|
|
254
|
-
|
|
255
|
-
return lines;
|
|
261
|
+
return `Row ${catIdx + chart._rowOffset}`;
|
|
256
262
|
}
|
|
@@ -16,7 +16,12 @@ import { PlotLayout } from "../../layout/plot-layout";
|
|
|
16
16
|
import { sampleGradient } from "../../theme/gradient";
|
|
17
17
|
import { renderInPlotFrame } from "../../webgl/plot-frame";
|
|
18
18
|
import { renderCanvasTooltip } from "../../interaction/tooltip-controller";
|
|
19
|
-
import {
|
|
19
|
+
import { tooltipStyleOf } from "../../interaction/tooltip-grid";
|
|
20
|
+
import {
|
|
21
|
+
renderAxisHoverIndicators,
|
|
22
|
+
type AxisIndicator,
|
|
23
|
+
} from "../../interaction/axis-indicators";
|
|
24
|
+
import { computeNiceTicks, stepTickFormatter } from "../../layout/ticks";
|
|
20
25
|
import { type AxisDomain } from "../../axis/numeric-axis";
|
|
21
26
|
import {
|
|
22
27
|
renderBarAxesChrome,
|
|
@@ -27,7 +32,10 @@ import {
|
|
|
27
32
|
measureCategoricalAxisHeight,
|
|
28
33
|
type CategoricalDomain,
|
|
29
34
|
} from "../../axis/categorical-axis";
|
|
30
|
-
import {
|
|
35
|
+
import {
|
|
36
|
+
buildCandlestickTooltipLines,
|
|
37
|
+
candleCategoryText,
|
|
38
|
+
} from "./candlestick-interact";
|
|
31
39
|
import {
|
|
32
40
|
computeVisibleExtent,
|
|
33
41
|
type VisibleExtent,
|
|
@@ -230,7 +238,15 @@ export function renderCandlestickFrame(
|
|
|
230
238
|
chart._defer2D(() => renderCandlestickChromeOverlay(chart));
|
|
231
239
|
}
|
|
232
240
|
|
|
241
|
+
/**
|
|
242
|
+
* Draw axes chrome + (optional) tooltip onto the overlay canvas.
|
|
243
|
+
*/
|
|
233
244
|
export function renderCandlestickChromeOverlay(chart: CandlestickChart): void {
|
|
245
|
+
paintCandlestickChromeOverlay(chart);
|
|
246
|
+
chart.presentOverlay();
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function paintCandlestickChromeOverlay(chart: CandlestickChart): void {
|
|
234
250
|
if (
|
|
235
251
|
!chart._chromeCanvas ||
|
|
236
252
|
!chart._lastLayout ||
|
|
@@ -313,18 +329,73 @@ function renderCandlestickTooltip(chart: CandlestickChart): void {
|
|
|
313
329
|
const pos = layout.dataToPixel(xCenter, yMid);
|
|
314
330
|
const lines = buildCandlestickTooltipLines(chart, i);
|
|
315
331
|
const theme = chart._resolveTheme();
|
|
316
|
-
|
|
332
|
+
const dpr = chart._glManager?.dpr ?? 1;
|
|
333
|
+
|
|
334
|
+
let valueColumn = chart._columnSlots[1];
|
|
335
|
+
let value = candles.close[i];
|
|
336
|
+
if (valueColumn == null || !Number.isFinite(value)) {
|
|
337
|
+
valueColumn =
|
|
338
|
+
chart._columnSlots[0] ??
|
|
339
|
+
chart._columnSlots[2] ??
|
|
340
|
+
chart._columnSlots[3];
|
|
341
|
+
value = candles.open[i];
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
const datumPos = layout.dataToPixel(xCenter, value);
|
|
345
|
+
const indicators: AxisIndicator[] = [];
|
|
346
|
+
|
|
347
|
+
let categoryText: string;
|
|
348
|
+
if (
|
|
349
|
+
chart._categoryAxisMode === "numeric" &&
|
|
350
|
+
chart._numericCategoryDomain &&
|
|
351
|
+
chart._categoryPositions
|
|
352
|
+
) {
|
|
353
|
+
const catFmt =
|
|
354
|
+
chart.getColumnFormatter(chart._groupBy[0], "tick") ??
|
|
355
|
+
stepTickFormatter(
|
|
356
|
+
chart._numericCategoryDomain.isDate,
|
|
357
|
+
chart._lastCatTicks,
|
|
358
|
+
);
|
|
359
|
+
categoryText = catFmt(chart._categoryPositions[candles.catIdx[i]]);
|
|
360
|
+
} else {
|
|
361
|
+
categoryText = candleCategoryText(chart, candles.catIdx[i]);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
if (categoryText !== "") {
|
|
365
|
+
indicators.push({
|
|
366
|
+
side: "bottom",
|
|
367
|
+
px: datumPos.px,
|
|
368
|
+
py: datumPos.py,
|
|
369
|
+
text: categoryText,
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
if (Number.isFinite(value)) {
|
|
374
|
+
const valueFmt =
|
|
375
|
+
chart.getColumnFormatter(valueColumn, "tick") ??
|
|
376
|
+
stepTickFormatter(chart._lastYDomain?.isDate, chart._lastYTicks);
|
|
377
|
+
indicators.push({
|
|
378
|
+
side: "left",
|
|
379
|
+
px: datumPos.px,
|
|
380
|
+
py: datumPos.py,
|
|
381
|
+
text: valueFmt(value),
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
renderAxisHoverIndicators(
|
|
317
386
|
chart._chromeCanvas,
|
|
318
|
-
pos,
|
|
319
|
-
lines,
|
|
320
387
|
layout,
|
|
321
388
|
theme,
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
highlightRadius: 0,
|
|
326
|
-
},
|
|
389
|
+
dpr,
|
|
390
|
+
indicators,
|
|
391
|
+
chart._pluginConfig.tooltip_opacity,
|
|
327
392
|
);
|
|
393
|
+
|
|
394
|
+
renderCanvasTooltip(chart._chromeCanvas, pos, lines, layout, theme, dpr, {
|
|
395
|
+
...tooltipStyleOf(chart._pluginConfig),
|
|
396
|
+
crosshair: false,
|
|
397
|
+
highlightRadius: 0,
|
|
398
|
+
});
|
|
328
399
|
}
|
|
329
400
|
|
|
330
401
|
/**
|
|
@@ -212,9 +212,10 @@ export class CandlestickChart extends CategoricalYChart {
|
|
|
212
212
|
|
|
213
213
|
const catIdx = this._candles.catIdx[idx];
|
|
214
214
|
const splitIdx = this._candles.splitIdx[idx];
|
|
215
|
-
const groupByValues: (string | null)[] =
|
|
216
|
-
|
|
217
|
-
|
|
215
|
+
const groupByValues: (string | number | null)[] =
|
|
216
|
+
this._categoryAxisMode === "numeric" && this._categoryPositions
|
|
217
|
+
? [this._categoryPositions[catIdx] ?? null]
|
|
218
|
+
: this._rowPaths.map((level) => level.labels[catIdx] ?? null);
|
|
218
219
|
const splitKey = this._splitPrefixes[splitIdx] ?? "";
|
|
219
220
|
const splitByValues =
|
|
220
221
|
this._splitBy.length > 0 && splitKey !== ""
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
import type { CartesianChart } from "./cartesian";
|
|
14
14
|
import { renderCartesianChromeOverlay } from "./cartesian-render";
|
|
15
|
+
import { tooltipStyleOf } from "../../interaction/tooltip-grid";
|
|
15
16
|
|
|
16
17
|
const TOOLTIP_RADIUS_PX = 24;
|
|
17
18
|
|
|
@@ -311,7 +312,7 @@ export function showCartesianPinnedTooltip(
|
|
|
311
312
|
);
|
|
312
313
|
|
|
313
314
|
const serial = chart._lazyTooltip.beginPin();
|
|
314
|
-
chart.glyph.buildTooltipLines(chart, pointIdx).then((
|
|
315
|
+
chart.glyph.buildTooltipLines(chart, pointIdx).then((grid) => {
|
|
315
316
|
// Abandon the pin if the user moved on (another pin/dismiss
|
|
316
317
|
// between click and resolve) or the underlying view changed.
|
|
317
318
|
if (!chart._lazyTooltip.isPinFresh(serial)) {
|
|
@@ -322,11 +323,16 @@ export function showCartesianPinnedTooltip(
|
|
|
322
323
|
return;
|
|
323
324
|
}
|
|
324
325
|
|
|
325
|
-
if (
|
|
326
|
+
if (grid.length === 0) {
|
|
326
327
|
return;
|
|
327
328
|
}
|
|
328
329
|
|
|
329
|
-
chart._tooltip.pin(
|
|
330
|
+
chart._tooltip.pin(
|
|
331
|
+
grid,
|
|
332
|
+
pos,
|
|
333
|
+
layout,
|
|
334
|
+
tooltipStyleOf(chart._pluginConfig),
|
|
335
|
+
);
|
|
330
336
|
});
|
|
331
337
|
|
|
332
338
|
chart._hoveredIndex = -1;
|