@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.
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 +6 -6
  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
@@ -10,6 +10,8 @@
10
10
  // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11
11
  // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
12
 
13
+ import TILE_SOURCE_SEED from "./tile-sources.json";
14
+
13
15
  /**
14
16
  * A tile source describes *where* to fetch raster XYZ tiles and what
15
17
  * attribution text the renderer must display in the chrome canvas.
@@ -84,73 +86,217 @@ export class TemplatedTileSource implements TileSource {
84
86
  }
85
87
 
86
88
  /**
87
- * Identifier of the default tile providers shipped with `viewer-charts`.
88
- * Surfaced as the `map_tile_provider` PluginConfig enum so users can
89
- * pick light vs. dark vs. labels-only without writing a custom source.
89
+ * Declarative description of one raster XYZ tile provider — the shape
90
+ * of an entry in [tile-sources.json] and of the argument to
91
+ * `registerTileSource`. Everything the renderer needs to construct a
92
+ * concrete {@link TileSource} lives here; the TypeScript is generic
93
+ * over these entries and hardcodes no provider URLs.
90
94
  */
91
- export type TileProviderId =
92
- | "carto-positron"
93
- | "carto-dark-matter"
94
- | "carto-voyager";
95
+ export interface TileSourceSpec {
96
+ /** Registry key; the persisted `map_tile_provider` value. */
97
+ readonly id: string;
98
+
99
+ /** Human-readable enum-variant label on the settings panel. */
100
+ readonly label: string;
101
+
102
+ /**
103
+ * URL template with `{z}`/`{x}`/`{y}` placeholders and optional
104
+ * `{s}` subdomain rotation. A provider that needs an API key
105
+ * embeds it directly in the template it registers — keys never
106
+ * pass through `plugin_config`, so they never appear in `save()`
107
+ * output.
108
+ */
109
+ readonly template: string;
110
+
111
+ /** `{s}` rotation pool; required non-empty iff `template` has `{s}`. */
112
+ readonly subdomains: readonly string[];
113
+
114
+ /** See {@link TileSource.attribution}. */
115
+ readonly attribution: string;
116
+
117
+ /** See {@link TileSource.tileSize}. Default 256. */
118
+ readonly tile_size: number;
119
+
120
+ /** See {@link TileSource.maxZoom}. Default 19. */
121
+ readonly max_zoom: number;
122
+ }
95
123
 
96
124
  /**
97
- * CartoDB's "Positron" basemap — light, low-contrast, designed to sit
98
- * behind a chart overlay. Default for light themes.
125
+ * Validate + normalize an untrusted spec (a JSON entry or a
126
+ * `registerTileSource` argument). Throws `TypeError` naming the
127
+ * offending field; returns a frozen spec with defaults applied.
99
128
  */
100
- function cartoPositron(): TileSource {
101
- return new TemplatedTileSource(
102
- "carto-positron",
103
- "https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png",
104
- "© OpenStreetMap contributors © CARTO",
105
- 256,
106
- 19,
107
- ["a", "b", "c", "d"],
108
- );
129
+ export function parseTileSourceSpec(input: unknown): TileSourceSpec {
130
+ if (typeof input !== "object" || input === null) {
131
+ throw new TypeError("TileSourceSpec must be an object");
132
+ }
133
+
134
+ const raw = input as Record<string, unknown>;
135
+ const str = (key: string): string => {
136
+ const v = raw[key];
137
+ if (typeof v !== "string" || v.length === 0) {
138
+ throw new TypeError(
139
+ `TileSourceSpec.${key} must be a non-empty string`,
140
+ );
141
+ }
142
+
143
+ return v;
144
+ };
145
+
146
+ const id = str("id");
147
+ const label = str("label");
148
+ const template = str("template");
149
+ const attribution = str("attribution");
150
+ for (const placeholder of ["{z}", "{x}", "{y}"]) {
151
+ if (!template.includes(placeholder)) {
152
+ throw new TypeError(
153
+ `TileSourceSpec.template must contain "${placeholder}"`,
154
+ );
155
+ }
156
+ }
157
+
158
+ const rawSubdomains = raw["subdomains"] ?? [];
159
+ if (
160
+ !Array.isArray(rawSubdomains) ||
161
+ rawSubdomains.some((s) => typeof s !== "string" || s.length === 0)
162
+ ) {
163
+ throw new TypeError(
164
+ "TileSourceSpec.subdomains must be an array of non-empty strings",
165
+ );
166
+ }
167
+
168
+ const subdomains = Object.freeze([...rawSubdomains] as string[]);
169
+ if (template.includes("{s}") && subdomains.length === 0) {
170
+ throw new TypeError(
171
+ 'TileSourceSpec.template uses "{s}" but no subdomains were given',
172
+ );
173
+ }
174
+
175
+ const num = (key: string, dflt: number): number => {
176
+ const v = raw[key];
177
+ if (v === undefined) {
178
+ return dflt;
179
+ }
180
+
181
+ if (typeof v !== "number" || !Number.isFinite(v) || v <= 0) {
182
+ throw new TypeError(
183
+ `TileSourceSpec.${key} must be a positive number`,
184
+ );
185
+ }
186
+
187
+ return v;
188
+ };
189
+
190
+ return Object.freeze({
191
+ id,
192
+ label,
193
+ template,
194
+ subdomains,
195
+ attribution,
196
+ tile_size: num("tile_size", 256),
197
+ max_zoom: num("max_zoom", 19),
198
+ });
109
199
  }
110
200
 
111
201
  /**
112
- * CartoDB's "Dark Matter" basemap — dark, low-contrast. Default for
113
- * dark themes.
202
+ * 32-bit FNV-1a over a string, hex-encoded. Fingerprints a spec's
203
+ * fetch-relevant fields into the {@link TileSource.id} cache key.
114
204
  */
115
- function cartoDarkMatter(): TileSource {
116
- return new TemplatedTileSource(
117
- "carto-dark-matter",
118
- "https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png",
119
- "© OpenStreetMap contributors © CARTO",
120
- 256,
121
- 19,
122
- ["a", "b", "c", "d"],
123
- );
205
+ function fnv1a(s: string): string {
206
+ let h = 0x811c9dc5;
207
+ for (let i = 0; i < s.length; i++) {
208
+ h ^= s.charCodeAt(i);
209
+ h = Math.imul(h, 0x01000193);
210
+ }
211
+
212
+ return (h >>> 0).toString(16);
124
213
  }
125
214
 
126
215
  /**
127
- * CartoDB's "Voyager" basemap — full color, more land/water contrast
128
- * than Positron. Good when the chart glyphs are translucent.
216
+ * The set of known tile providers: the bundled entries from
217
+ * [tile-sources.json] plus any registered at runtime via
218
+ * `registerTileSource`. One instance exists per JS realm ({@link
219
+ * TILE_SOURCES}) — the plugin realm's is the source of truth for the
220
+ * settings-panel enum; the worker realm's resolves ids at render time.
221
+ * The realms need no eager mirroring: every `setPluginConfig` / `init`
222
+ * control message carries the resolved spec for the config's
223
+ * `map_tile_provider` alongside the config itself, so a worker can
224
+ * never hold a config whose spec it lacks.
129
225
  */
130
- function cartoVoyager(): TileSource {
131
- return new TemplatedTileSource(
132
- "carto-voyager",
133
- "https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}.png",
134
- "© OpenStreetMap contributors © CARTO",
135
- 256,
136
- 19,
137
- ["a", "b", "c", "d"],
138
- );
226
+ export class TileSourceRegistry {
227
+ private _specs = new Map<string, TileSourceSpec>();
228
+
229
+ constructor(seed: readonly unknown[]) {
230
+ for (const entry of seed) {
231
+ const spec = parseTileSourceSpec(entry);
232
+ this._specs.set(spec.id, spec);
233
+ }
234
+ }
235
+
236
+ /**
237
+ * Add (or replace, by id) a provider. Validates via
238
+ * {@link parseTileSourceSpec} and returns the normalized spec.
239
+ * Replacement is safe for live charts: the cache identity below is
240
+ * content-derived, so a changed template yields a new cache key
241
+ * and the tile layer drops its stale textures on next bind.
242
+ */
243
+ register(input: unknown): TileSourceSpec {
244
+ const spec = parseTileSourceSpec(input);
245
+ this._specs.set(spec.id, spec);
246
+ return spec;
247
+ }
248
+
249
+ /** Every known spec, bundled first, in insertion order. */
250
+ list(): readonly TileSourceSpec[] {
251
+ return [...this._specs.values()];
252
+ }
253
+
254
+ /** The spec registered under `id`, or `undefined` if unknown. */
255
+ specFor(id: string): TileSourceSpec | undefined {
256
+ return this._specs.get(id);
257
+ }
258
+
259
+ /**
260
+ * Resolve a `map_tile_provider` id to a concrete `TileSource`.
261
+ * Unknown ids fall back to the first bundled entry so a
262
+ * misconfigured `plugin_config` never produces a blank map — and
263
+ * so a config restored *before* its custom source is registered
264
+ * degrades to the default basemap until the next config forward
265
+ * carries the registered spec.
266
+ */
267
+ sourceFor(id: string): TileSource {
268
+ const spec = this._specs.get(id) ?? this._specs.values().next().value!;
269
+
270
+ // Cache identity = id + content hash of the fetch-relevant
271
+ // fields. Re-registering an id with a different template MUST
272
+ // invalidate `TileCache` entries (keyed on `TileSource.id`)
273
+ // or stale tiles from the old URL would keep rendering; the
274
+ // hash does that without any cross-realm revision state.
275
+ const fingerprint = fnv1a(
276
+ `${spec.template}${spec.subdomains.join(",")}`,
277
+ );
278
+
279
+ return new TemplatedTileSource(
280
+ `${spec.id}@${fingerprint}`,
281
+ spec.template,
282
+ spec.attribution,
283
+ spec.tile_size,
284
+ spec.max_zoom,
285
+ spec.subdomains,
286
+ );
287
+ }
139
288
  }
140
289
 
141
290
  /**
142
- * Resolve a `TileProviderId` (from PluginConfig) to a concrete
143
- * `TileSource`. Unknown ids fall back to Positron so a misconfigured
144
- * `_pluginConfig` never produces a blank map.
291
+ * Realm-wide provider registry, seeded from [tile-sources.json]. A
292
+ * malformed bundled entry fails loudly here, at first import.
145
293
  */
146
- export function tileSourceFor(id: TileProviderId | string): TileSource {
147
- switch (id) {
148
- case "carto-dark-matter":
149
- return cartoDarkMatter();
150
- case "carto-voyager":
151
- return cartoVoyager();
152
- case "carto-positron":
153
- default:
154
- return cartoPositron();
155
- }
294
+ export const TILE_SOURCES = new TileSourceRegistry(TILE_SOURCE_SEED);
295
+
296
+ /**
297
+ * Read-only listing of every known tile provider (bundled + runtime-
298
+ * registered), in settings-panel enum order. Public package export.
299
+ */
300
+ export function tileSources(): readonly TileSourceSpec[] {
301
+ return TILE_SOURCES.list();
156
302
  }
@@ -0,0 +1,18 @@
1
+ [
2
+ {
3
+ "id": "osm",
4
+ "label": "OpenStreetMap",
5
+ "template": "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
6
+ "attribution": "© OpenStreetMap contributors",
7
+ "tile_size": 256,
8
+ "max_zoom": 19
9
+ },
10
+ {
11
+ "id": "versatiles-satellite",
12
+ "label": "Satellite (VersaTiles)",
13
+ "template": "https://tiles.versatiles.org/tiles/satellite/{z}/{x}/{y}",
14
+ "attribution": "© VersaTiles (versatiles.org/sources)",
15
+ "tile_size": 256,
16
+ "max_zoom": 12
17
+ }
18
+ ]
@@ -95,11 +95,27 @@ const Y_AXIS = ["Y Axis"];
95
95
  const SELECT = "select";
96
96
  const TOGGLE = "toggle";
97
97
 
98
- const DEFAULT_MAX_CELLS = 2_000_000;
98
+ const DEFAULT_MAX_CELLS = 10_000_000;
99
99
  const DEFAULT_MAX_COLUMNS = 10_000;
100
100
 
101
101
  // Plugin-config field sets, by chart family.
102
102
  //
103
+ export const LEGEND_FIELDS: readonly PluginConfigField[] = [
104
+ "legend_mode",
105
+ "legend_size_mode",
106
+ "legend_width_px",
107
+ "legend_height_px",
108
+ "legend_anchor",
109
+ "legend_x",
110
+ "legend_y",
111
+ "legend_opacity",
112
+ ];
113
+
114
+ export const TOOLTIP_FIELDS: readonly PluginConfigField[] = [
115
+ "tooltip_max_column_px",
116
+ "tooltip_opacity",
117
+ ];
118
+
103
119
  // Series charts paint bars / lines / scatter / area glyphs (selected
104
120
  // per-column via `chart_type`), so the union covers every glyph that
105
121
  // might appear. `auto_alt_y_axis` + `series_zoom_mode` are Series-only.
@@ -113,6 +129,8 @@ const SERIES_FIELDS: readonly PluginConfigField[] = [
113
129
  "point_size_px",
114
130
  "band_inner_frac",
115
131
  "bar_inner_pad",
132
+ ...LEGEND_FIELDS,
133
+ ...TOOLTIP_FIELDS,
116
134
  ];
117
135
 
118
136
  // The band pipeline's historical split_by rendering is a single plot
@@ -137,6 +155,8 @@ const CARTESIAN_FIELDS: readonly PluginConfigField[] = [
137
155
  "domain_mode",
138
156
  "line_width_px",
139
157
  "point_size_px",
158
+ ...LEGEND_FIELDS,
159
+ ...TOOLTIP_FIELDS,
140
160
  ];
141
161
 
142
162
  // Candlestick/OHLC share the categorical-X build pipeline (band slots)
@@ -149,13 +169,20 @@ const FIN_FIELDS: readonly PluginConfigField[] = [
149
169
  "bar_inner_pad",
150
170
  "wick_width_px",
151
171
  "ohlc_line_width_px",
172
+ ...TOOLTIP_FIELDS,
152
173
  ];
153
174
 
154
- // Hierarchical — none of the listed fields apply.
155
- const NO_FIELDS: readonly PluginConfigField[] = [];
175
+ const TREE_FIELDS: readonly PluginConfigField[] = [
176
+ ...LEGEND_FIELDS,
177
+ ...TOOLTIP_FIELDS,
178
+ ];
156
179
 
157
180
  // Heatmap
158
- const HEATMAP_FIELDS: readonly PluginConfigField[] = ["facet_zoom_mode"];
181
+ const HEATMAP_FIELDS: readonly PluginConfigField[] = [
182
+ "facet_zoom_mode",
183
+ ...LEGEND_FIELDS,
184
+ ...TOOLTIP_FIELDS,
185
+ ];
159
186
 
160
187
  // Map — reuses the cartesian build pipeline with a Mercator
161
188
  // projection hook. Carries the basemap controls (`map_tile_provider`,
@@ -168,6 +195,9 @@ const MAP_BASE_FIELDS: readonly PluginConfigField[] = [
168
195
  "domain_mode",
169
196
  "map_tile_provider",
170
197
  "map_tile_alpha",
198
+ "numeric_axes",
199
+ ...LEGEND_FIELDS,
200
+ ...TOOLTIP_FIELDS,
171
201
  ];
172
202
  const MAP_SCATTER_FIELDS: readonly PluginConfigField[] = [
173
203
  ...MAP_BASE_FIELDS,
@@ -197,6 +227,8 @@ const DENSITY_FIELDS: readonly PluginConfigField[] = [
197
227
  "gradient_radius_px",
198
228
  "gradient_intensity",
199
229
  "gradient_heat_max",
230
+ ...LEGEND_FIELDS,
231
+ ...TOOLTIP_FIELDS,
200
232
  ];
201
233
 
202
234
  function make(
@@ -314,14 +346,16 @@ const CHARTS: ChartTypeConfig[] = [
314
346
  DENSITY_FIELDS,
315
347
  { ...CART_ROLES },
316
348
  ),
317
- make("Treemap", "treemap", HIER, TOGGLE, 1, HIER_NAMES, NO_FIELDS, {
349
+ make("Treemap", "treemap", HIER, TOGGLE, 1, HIER_NAMES, TREE_FIELDS, {
318
350
  ...HIER_ROLES,
351
+ plugin_field_defaults: { legend_mode: "sidebar" },
319
352
  }),
320
- make("Sunburst", "sunburst", HIER, TOGGLE, 1, HIER_NAMES, NO_FIELDS, {
353
+ make("Sunburst", "sunburst", HIER, TOGGLE, 1, HIER_NAMES, TREE_FIELDS, {
321
354
  ...HIER_ROLES,
322
355
  }),
323
356
  make("Heatmap", "heatmap", HIER, SELECT, 1, ["Color"], HEATMAP_FIELDS, {
324
357
  ...HEATMAP_ROLES,
358
+ plugin_field_defaults: { legend_mode: "sidebar" },
325
359
  }),
326
360
  make("Candlestick", "candlestick", FIN, TOGGLE, 1, FIN_NAMES, FIN_FIELDS, {
327
361
  ...FIN_ROLES,
@@ -0,0 +1,37 @@
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 {
14
+ DateFormatConfig,
15
+ NumberFormatConfig,
16
+ } from "@perspective-dev/viewer/src/ts/column-format.js";
17
+
18
+ /**
19
+ * The chart plugin's default per-column formats, declared to the viewer in
20
+ * `column_config_schema()` and applied by the render path under sparse or
21
+ * absent configs.
22
+ */
23
+ export const CHART_NUMBER_DEFAULTS: NumberFormatConfig = {
24
+ notation: "compact",
25
+ compactDisplay: "short",
26
+ minimumFractionDigits: 0,
27
+ maximumFractionDigits: 1,
28
+ };
29
+
30
+ export const CHART_DATETIME_DEFAULTS: DateFormatConfig = {
31
+ dateStyle: "medium",
32
+ timeStyle: "disabled",
33
+ };
34
+
35
+ export const CHART_DATE_DEFAULTS: DateFormatConfig = {
36
+ dateStyle: "medium",
37
+ };