@perspective-dev/viewer-charts 5.3.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.
Files changed (92) hide show
  1. package/dist/cdn/perspective-viewer-charts.js +1 -2
  2. package/dist/cdn/perspective-viewer-charts.js.map +4 -4
  3. package/dist/esm/axis/legend.d.ts +53 -5
  4. package/dist/esm/axis/map-ticks.d.ts +15 -0
  5. package/dist/esm/charts/candlestick/candlestick-interact.d.ts +2 -6
  6. package/dist/esm/charts/cartesian/cartesian.d.ts +6 -0
  7. package/dist/esm/charts/cartesian/glyph.d.ts +2 -1
  8. package/dist/esm/charts/cartesian/glyphs/density.d.ts +2 -1
  9. package/dist/esm/charts/cartesian/glyphs/lines.d.ts +2 -1
  10. package/dist/esm/charts/cartesian/glyphs/points.d.ts +2 -1
  11. package/dist/esm/charts/cartesian/tooltip-lines.d.ts +1 -1
  12. package/dist/esm/charts/chart-base.d.ts +2 -0
  13. package/dist/esm/charts/chart.d.ts +77 -6
  14. package/dist/esm/charts/common/draw-tooltip-box.d.ts +2 -1
  15. package/dist/esm/charts/common/tree-interact.d.ts +1 -1
  16. package/dist/esm/charts/series/series-build.d.ts +7 -0
  17. package/dist/esm/charts/series/series-interact.d.ts +1 -1
  18. package/dist/esm/charts/series/series.d.ts +6 -0
  19. package/dist/esm/index.d.ts +2 -0
  20. package/dist/esm/interaction/axis-indicators.d.ts +11 -0
  21. package/dist/esm/interaction/host-sink-dom.d.ts +3 -2
  22. package/dist/esm/interaction/host-sink-message.d.ts +3 -2
  23. package/dist/esm/interaction/lazy-tooltip.d.ts +2 -2
  24. package/dist/esm/interaction/legend-controller.d.ts +246 -0
  25. package/dist/esm/interaction/tooltip-controller.d.ts +20 -95
  26. package/dist/esm/interaction/tooltip-grid.d.ts +33 -0
  27. package/dist/esm/layout/facet-grid.d.ts +6 -0
  28. package/dist/esm/layout/ticks.d.ts +1 -0
  29. package/dist/esm/map/tile-source.d.ts +77 -8
  30. package/dist/esm/perspective-viewer-charts.js +1 -2
  31. package/dist/esm/perspective-viewer-charts.js.map +4 -4
  32. package/dist/esm/plugin/charts.d.ts +2 -0
  33. package/dist/esm/plugin/format-defaults.d.ts +9 -0
  34. package/dist/esm/plugin/plugin.d.ts +20 -0
  35. package/dist/esm/theme/gradient.d.ts +1 -0
  36. package/dist/esm/transport/protocol.d.ts +45 -3
  37. package/dist/esm/transport/renderer-transport.d.ts +3 -0
  38. package/dist/esm/worker/renderer.worker.d.ts +19 -1
  39. package/package.json +1 -1
  40. package/src/css/perspective-viewer-charts.css +0 -1
  41. package/src/ts/axis/bar-axis.ts +2 -7
  42. package/src/ts/axis/legend.ts +351 -24
  43. package/src/ts/axis/map-ticks.ts +94 -0
  44. package/src/ts/axis/numeric-axis.ts +2 -9
  45. package/src/ts/charts/candlestick/candlestick-interact.ts +46 -40
  46. package/src/ts/charts/candlestick/candlestick-render.ts +73 -10
  47. package/src/ts/charts/cartesian/cartesian-interact.ts +9 -3
  48. package/src/ts/charts/cartesian/cartesian-render.ts +369 -75
  49. package/src/ts/charts/cartesian/cartesian.ts +9 -0
  50. package/src/ts/charts/cartesian/glyph.ts +6 -2
  51. package/src/ts/charts/cartesian/glyphs/density.ts +2 -2
  52. package/src/ts/charts/cartesian/glyphs/lines.ts +15 -11
  53. package/src/ts/charts/cartesian/glyphs/points.ts +9 -5
  54. package/src/ts/charts/cartesian/tooltip-lines.ts +8 -8
  55. package/src/ts/charts/chart-base.ts +34 -32
  56. package/src/ts/charts/chart.ts +106 -7
  57. package/src/ts/charts/common/draw-tooltip-box.ts +13 -30
  58. package/src/ts/charts/common/tree-chrome.ts +102 -23
  59. package/src/ts/charts/common/tree-interact.ts +18 -17
  60. package/src/ts/charts/heatmap/heatmap-interact.ts +65 -7
  61. package/src/ts/charts/heatmap/heatmap-render.ts +100 -24
  62. package/src/ts/charts/map/map.ts +3 -5
  63. package/src/ts/charts/series/series-build.ts +14 -2
  64. package/src/ts/charts/series/series-interact.ts +12 -11
  65. package/src/ts/charts/series/series-render.ts +305 -132
  66. package/src/ts/charts/series/series.ts +10 -0
  67. package/src/ts/charts/sunburst/sunburst-render.ts +7 -1
  68. package/src/ts/charts/treemap/treemap-render.ts +7 -1
  69. package/src/ts/data/view-reader.ts +1 -4
  70. package/src/ts/index.ts +2 -0
  71. package/src/ts/interaction/axis-indicators.ts +137 -0
  72. package/src/ts/interaction/host-sink-dom.ts +66 -2
  73. package/src/ts/interaction/host-sink-message.ts +8 -2
  74. package/src/ts/interaction/lazy-tooltip.ts +5 -5
  75. package/src/ts/interaction/legend-controller.ts +1084 -0
  76. package/src/ts/interaction/tooltip-controller.ts +43 -131
  77. package/src/ts/interaction/tooltip-grid.ts +187 -0
  78. package/src/ts/layout/facet-grid.ts +8 -1
  79. package/src/ts/layout/ticks.ts +12 -0
  80. package/src/ts/map/tile-loader.ts +16 -1
  81. package/src/ts/map/tile-source.ts +199 -53
  82. package/src/ts/map/tile-sources.json +18 -0
  83. package/src/ts/plugin/charts.ts +40 -6
  84. package/src/ts/plugin/format-defaults.ts +37 -0
  85. package/src/ts/plugin/plugin.ts +236 -67
  86. package/src/ts/shaders/line.vert.glsl +5 -2
  87. package/src/ts/shaders/scatter.vert.glsl +0 -7
  88. package/src/ts/theme/gradient.ts +24 -0
  89. package/src/ts/transport/protocol.ts +46 -2
  90. package/src/ts/transport/renderer-transport.ts +83 -4
  91. package/src/ts/worker/dispatch.ts +6 -2
  92. package/src/ts/worker/renderer.worker.ts +78 -2
@@ -63,5 +63,7 @@ export interface ChartTypeConfig {
63
63
  */
64
64
  plugin_field_defaults?: Partial<PluginConfig>;
65
65
  }
66
+ export declare const LEGEND_FIELDS: readonly PluginConfigField[];
67
+ export declare const TOOLTIP_FIELDS: readonly PluginConfigField[];
66
68
  declare const CHARTS: ChartTypeConfig[];
67
69
  export default CHARTS;
@@ -0,0 +1,9 @@
1
+ import type { DateFormatConfig, NumberFormatConfig } from "@perspective-dev/viewer/src/ts/column-format.js";
2
+ /**
3
+ * The chart plugin's default per-column formats, declared to the viewer in
4
+ * `column_config_schema()` and applied by the render path under sparse or
5
+ * absent configs.
6
+ */
7
+ export declare const CHART_NUMBER_DEFAULTS: NumberFormatConfig;
8
+ export declare const CHART_DATETIME_DEFAULTS: DateFormatConfig;
9
+ export declare const CHART_DATE_DEFAULTS: DateFormatConfig;
@@ -1,6 +1,24 @@
1
1
  import type { View } from "@perspective-dev/client";
2
2
  import type { IPerspectiveViewerPlugin, PluginStaticConfig } from "@perspective-dev/viewer";
3
3
  import { ChartTypeConfig } from "./charts";
4
+ import { type TileSourceSpec } from "../map/tile-source";
5
+ /**
6
+ * Register a raster XYZ tile provider at runtime. The provider joins
7
+ * the bundled [map/tile-sources.json] entries in the settings panel's
8
+ * `map_tile_provider` enum and resolves on any map chart from its next
9
+ * config forward onward — the resolved spec rides every outgoing
10
+ * `setPluginConfig` / `init` message alongside the config that names
11
+ * it, so no separate registry-sync operation exists. Re-registering an
12
+ * id replaces it (a changed template drops cached tiles via the
13
+ * content-derived cache identity); a chart currently displaying that
14
+ * id picks the replacement up on its next `restore()`. Throws
15
+ * `TypeError` on a malformed spec. Returns the normalized spec.
16
+ *
17
+ * A key-gated provider is registered with the key embedded in its
18
+ * `template` — keys never enter `plugin_config`, so they never appear
19
+ * in `save()` output.
20
+ */
21
+ export declare function registerTileSource(spec: unknown): TileSourceSpec;
4
22
  export declare class HTMLPerspectiveViewerWebGLPluginElement extends HTMLElement implements IPerspectiveViewerPlugin {
5
23
  _chartType: ChartTypeConfig;
6
24
  private _initialized;
@@ -86,6 +104,8 @@ export declare class HTMLPerspectiveViewerWebGLPluginElement extends HTMLElement
86
104
  * contexts ([webgl/context-pool.ts]), so a page can exceed the cap.
87
105
  */
88
106
  static setBlitMode(mode: "direct" | "blit"): void;
107
+ static registerTileSource(spec: unknown): TileSourceSpec;
108
+ static tileSources(): readonly TileSourceSpec[];
89
109
  get_static_config(): PluginStaticConfig;
90
110
  column_config_schema(column_type: string, group: string | undefined, column_name: string, current_value: Record<string, unknown> | null, viewer_config?: {
91
111
  columns?: (string | null)[];
@@ -60,6 +60,7 @@ export declare function sampleGradient(stops: GradientStop[], t: number): [numbe
60
60
  * - degenerate → 0.5 (single colour at the midpoint).
61
61
  */
62
62
  export declare function colorValueToT(value: number, colorMin: number, colorMax: number): number;
63
+ export declare function colorRangePivot(colorMin: number, colorMax: number): [number, number];
63
64
  /**
64
65
  * Convert a discrete series palette (from `--psp-charts--series-N--color`)
65
66
  * into a `GradientStop[]` with stops at `i / (N - 1)`. The resulting
@@ -1,6 +1,7 @@
1
1
  import type { FacetConfig, PluginConfig } from "../charts/chart";
2
2
  import type { PerspectiveClickDetail } from "../event-detail";
3
3
  import type { ThemeSnapshot } from "../theme/theme";
4
+ import type { TileSourceSpec } from "../map/tile-source";
4
5
  import type { ViewConfig } from "@perspective-dev/client";
5
6
  export type { ThemeSnapshot };
6
7
  /**
@@ -10,7 +11,7 @@ export type { ThemeSnapshot };
10
11
  * chart's own renderer control plane.
11
12
  */
12
13
  export type ControlMsg = InitMsg | SetViewByNameMsg | SetColumnsConfigMsg | SetPluginConfigMsg | SetBufferMaxCapacityMsg | LoadAndRenderMsg | RedrawMsg | DeselectMsg | ResizeMsg | ClearMsg | InvalidateThemeMsg | RestoreZoomMsg | ResetAllZoomsMsg | ResetExpandedDomainMsg | SaveZoomReqMsg | SnapshotPngReqMsg | InteractionMsg | DestroyMsg;
13
- export type WorkerMsg = ReadyMsg | ZoomChangedMsg | SaveZoomReplyMsg | SnapshotPngReplyMsg | PinTooltipMsg | DismissTooltipMsg | SetCursorMsg | UserClickMsg | UserSelectMsg | LoadAndRenderAckMsg | ResizeAckMsg | FrameBitmapMsg | ErrorMsg;
14
+ export type WorkerMsg = ReadyMsg | ZoomChangedMsg | SaveZoomReplyMsg | SnapshotPngReplyMsg | PinTooltipMsg | DismissTooltipMsg | SetCursorMsg | UserClickMsg | UserSelectMsg | PluginConfigDeltaMsg | LoadAndRenderAckMsg | ResizeAckMsg | FrameBitmapMsg | ErrorMsg;
14
15
  /**
15
16
  * Session-tagged envelopes for the shared-worker transport. Every
16
17
  * message between the host and the shared `Worker` carries a numeric
@@ -124,6 +125,16 @@ export interface InitMsg {
124
125
  */
125
126
  columnsConfig?: Record<string, any>;
126
127
  defaultChartType?: string;
128
+ /**
129
+ * Resolved spec for `pluginConfig.map_tile_provider`, when the
130
+ * plugin realm's registry knows the id — see
131
+ * {@link SetPluginConfigMsg.tileSource} for the invariant. Applied
132
+ * to the worker realm's registry before the chart impl is
133
+ * constructed. Bundled [map/tile-sources.json] entries ship inside
134
+ * the worker bundle, so this matters only for runtime-registered
135
+ * providers.
136
+ */
137
+ tileSource?: TileSourceSpec;
127
138
  /**
128
139
  * Pre-resolved CSS-variable theme snapshot from the host.
129
140
  */
@@ -202,6 +213,17 @@ export interface SetColumnsConfigMsg {
202
213
  export interface SetPluginConfigMsg {
203
214
  kind: "setPluginConfig";
204
215
  cfg: PluginConfig;
216
+ /**
217
+ * Resolved spec for `cfg.map_tile_provider`, when the plugin
218
+ * realm's registry knows the id. Riding the config keeps the two
219
+ * realms' registries convergent with NO eager mirroring: the
220
+ * worker registers this spec before applying `cfg`, so it can
221
+ * never hold a config whose provider it cannot resolve —
222
+ * regardless of when `registerTileSource` ran relative to
223
+ * renderer construction. Absent for unknown ids (the worker falls
224
+ * back to the default basemap).
225
+ */
226
+ tileSource?: TileSourceSpec;
205
227
  }
206
228
  export interface SetBufferMaxCapacityMsg {
207
229
  kind: "setBufferMaxCapacity";
@@ -245,6 +267,7 @@ export interface LoadAndRenderMsg {
245
267
  export interface LoadAndRenderAckMsg {
246
268
  kind: "loadAndRenderAck";
247
269
  msgId: number;
270
+ error?: string;
248
271
  }
249
272
  export interface RedrawMsg {
250
273
  kind: "redraw";
@@ -332,7 +355,8 @@ export interface SnapshotPngReqMsg {
332
355
  export interface SnapshotPngReplyMsg {
333
356
  kind: "snapshotPngReply";
334
357
  requestId: number;
335
- blob: Blob;
358
+ blob?: Blob;
359
+ error?: string;
336
360
  }
337
361
  export interface DestroyMsg {
338
362
  kind: "destroy";
@@ -407,7 +431,11 @@ export interface ErrorMsg {
407
431
  */
408
432
  export interface PinTooltipMsg {
409
433
  kind: "pinTooltip";
410
- lines: string[];
434
+ grid: string[][];
435
+ style: {
436
+ opacity: number;
437
+ maxColumnPx: number;
438
+ };
411
439
  pos: {
412
440
  px: number;
413
441
  py: number;
@@ -430,6 +458,20 @@ export interface SetCursorMsg {
430
458
  kind: "setCursor";
431
459
  cursor: string;
432
460
  }
461
+ /**
462
+ * Renderer → host: a completed legend gesture (sidebar width drag,
463
+ * floating move / resize) produced new values for the legend's
464
+ * `plugin_config` fields. Posted ONCE per gesture, at pointerup — never
465
+ * per pointermove — with only the fields the gesture changed. The host
466
+ * plugin persists them through the viewer's public `restore` surface
467
+ * (a user-gesture echo), which merges the host bucket, refreshes the
468
+ * settings form, and echoes one `setPluginConfig` back with the same
469
+ * values (a no-op by the worker's legend-field equality guard).
470
+ */
471
+ export interface PluginConfigDeltaMsg {
472
+ kind: "pluginConfigDelta";
473
+ fields: Record<string, string | number | boolean>;
474
+ }
433
475
  /**
434
476
  * Renderer → host: a user click landed on a chart glyph. Host
435
477
  * re-dispatches as `CustomEvent<PerspectiveClickDetail>` on the
@@ -58,6 +58,7 @@ export declare class RendererTransport {
58
58
  private _pending;
59
59
  private _pendingCounter;
60
60
  private _onZoomChanged;
61
+ private _onPluginConfigDelta;
61
62
  /**
62
63
  * Cached zoom-default flag pushed by the renderer after each zoom
63
64
  * mutation. Surfaced sync via `allZoomsDefault()`; updates between
@@ -126,6 +127,7 @@ export declare class RendererTransport {
126
127
  maxCells: number;
127
128
  precompileShaders?: boolean;
128
129
  onZoomChanged?: (isDefault: boolean) => void;
130
+ onPluginConfigDelta?: (fields: Record<string, string | number | boolean>) => void;
129
131
  });
130
132
  init(opts: {
131
133
  gl: HTMLCanvasElement;
@@ -245,6 +247,7 @@ export declare class RendererTransport {
245
247
  * worth catching at the worker side.
246
248
  */
247
249
  private _resolvePending;
250
+ private _rejectPending;
248
251
  /**
249
252
  * Blit-mode handler: draw a renderer-emitted frame into the
250
253
  * visible 2D-context display canvas, then close the bitmap so its
@@ -1,9 +1,10 @@
1
1
  import "./boot";
2
2
  import type { Client, Table, View } from "@perspective-dev/client";
3
3
  import { WebGLContextManager } from "../webgl/context-manager";
4
- import { ChartImplementation } from "../charts/chart";
4
+ import { ChartImplementation, type PluginConfig } from "../charts/chart";
5
5
  import { ZoomController } from "../interaction/zoom-controller";
6
6
  import type { InitMsg, InteractionEvent, LoadAndRenderMsg, WorkerMsg } from "../transport/protocol";
7
+ import { type TileSourceSpec } from "../map/tile-source";
7
8
  export declare class WorkerRenderer {
8
9
  chartImpl: ChartImplementation;
9
10
  glManager: WebGLContextManager;
@@ -53,6 +54,13 @@ export declare class WorkerRenderer {
53
54
  private _lastDragY;
54
55
  constructor(msg: InitMsg, client: Client, view: View, table: Table | null, controlPort: MessagePort, ImplClass: new () => ChartImplementation);
55
56
  setViewByName(name: string): void;
57
+ /**
58
+ * Registry write precedes the config apply — `cfg` may name the
59
+ * spec riding alongside it (see `SetPluginConfigMsg.tileSource`),
60
+ * and a replaced template must be registered first so the map
61
+ * chart's rebind sees the new content-derived cache id.
62
+ */
63
+ setPluginConfig(cfg: PluginConfig, tileSource?: TileSourceSpec): void;
56
64
  /**
57
65
  * Full data-fetch + render pipeline. Owns every `Client`/`Table`/
58
66
  * `View` await on the render path:
@@ -108,7 +116,17 @@ export declare class WorkerRenderer {
108
116
  * facet grid and controllers, so the resolution runs here.
109
117
  */
110
118
  private _resolveTarget;
119
+ /**
120
+ * Legend-first interaction routing. The chart's `LegendController`
121
+ * sees every forwarded event BEFORE the zoom / tooltip paths, so
122
+ * legend gestures (scroll, width drag, floating move / resize)
123
+ * structurally preempt plot pan / zoom / hover — a wheel over the
124
+ * legend can never zoom the plot under it, and a floating-panel
125
+ * drag can never start a pan.
126
+ */
127
+ private _legendInteraction;
111
128
  onInteraction(event: InteractionEvent): void;
129
+ private _routeInteraction;
112
130
  /**
113
131
  * Read the chart impl's `TooltipController`. Charts that don't use
114
132
  * one (no `attachTooltip` override) yield `null` and the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@perspective-dev/viewer-charts",
3
- "version": "5.3.0",
3
+ "version": "5.3.1",
4
4
  "description": "Perspective.js WebGL Plugin",
5
5
  "unpkg": "./dist/cdn/perspective-viewer-charts.js",
6
6
  "jsdelivr": "./dist/cdn/perspective-viewer-charts.js",
@@ -89,7 +89,6 @@
89
89
  border-radius: 3px;
90
90
  padding: 3px;
91
91
  overflow-y: auto;
92
- white-space: pre;
93
92
  z-index: 10;
94
93
  line-height: 16px;
95
94
  }
@@ -12,7 +12,7 @@
12
12
 
13
13
  import type { Canvas2D, Context2D } from "../charts/canvas-types";
14
14
  import { PlotLayout } from "../layout/plot-layout";
15
- import { formatTickValue, formatDateTickValue } from "../layout/ticks";
15
+ import { stepTickFormatter } from "../layout/ticks";
16
16
  import { initCanvas } from "./canvas";
17
17
  import {
18
18
  renderCategoricalXTicks,
@@ -37,12 +37,7 @@ function tickFormatter(
37
37
  return override;
38
38
  }
39
39
 
40
- if (!domain.isDate) {
41
- return formatTickValue;
42
- }
43
-
44
- const step = ticks.length > 1 ? ticks[1] - ticks[0] : 0;
45
- return (v: number) => formatDateTickValue(v, step);
40
+ return stepTickFormatter(domain.isDate, ticks);
46
41
  }
47
42
 
48
43
  /**