@kanaries/graphic-walker 0.3.8 → 0.3.10

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.
@@ -1,10 +1,11 @@
1
- import React, { useEffect, useState, useMemo, forwardRef, useImperativeHandle, useRef } from 'react';
1
+ import React, { useEffect, useState, useMemo, forwardRef, useRef } from 'react';
2
2
  import embed from 'vega-embed';
3
3
  import { Subject, Subscription } from 'rxjs'
4
4
  import * as op from 'rxjs/operators';
5
5
  import type { ScenegraphEvent, View } from 'vega';
6
6
  import styled from 'styled-components';
7
7
 
8
+ import { useVegaExportApi } from '../utils/vegaApiExport';
8
9
  import { IViewField, IRow, IStackMode, VegaGlobalConfig } from '../interfaces';
9
10
  import { useTranslation } from 'react-i18next';
10
11
  import { getVegaTimeFormatRules } from './temporalFormat';
@@ -25,6 +26,7 @@ export interface IReactVegaHandler {
25
26
  downloadPNG: (filename?: string) => Promise<string[]>;
26
27
  }
27
28
  interface ReactVegaProps {
29
+ name?: string;
28
30
  rows: Readonly<IViewField[]>;
29
31
  columns: Readonly<IViewField[]>;
30
32
  dataSource: IRow[];
@@ -73,6 +75,7 @@ interface ParamStoreEntry {
73
75
 
74
76
  const ReactVega = forwardRef<IReactVegaHandler, ReactVegaProps>(function ReactVega (props, ref) {
75
77
  const {
78
+ name,
76
79
  dataSource = [],
77
80
  rows = [],
78
81
  columns = [],
@@ -150,7 +153,7 @@ const ReactVega = forwardRef<IReactVegaHandler, ReactVegaProps>(function ReactVe
150
153
  })
151
154
  }, [rowRepeatFields, colRepeatFields])
152
155
 
153
- const vegaRefs = useRef<View[]>([]);
156
+ const vegaRefs = useRef<{ x: number; y: number; w: number; h: number; view: View }[]>([]);
154
157
 
155
158
  useEffect(() => {
156
159
  vegaRefs.current = [];
@@ -218,7 +221,13 @@ const ReactVega = forwardRef<IReactVegaHandler, ReactVegaProps>(function ReactVe
218
221
 
219
222
  if (viewPlaceholders.length > 0 && viewPlaceholders[0].current) {
220
223
  embed(viewPlaceholders[0].current, spec, { mode: 'vega-lite', actions: showActions, timeFormatLocale: getVegaTimeFormatRules(i18n.language), config: vegaConfig }).then(res => {
221
- vegaRefs.current = [res.view];
224
+ vegaRefs.current = [{
225
+ w: res.view.container()?.clientWidth ?? res.view.width(),
226
+ h: res.view.container()?.clientHeight ?? res.view.height(),
227
+ x: 0,
228
+ y: 0,
229
+ view: res.view,
230
+ }];
222
231
  try {
223
232
  res.view.addEventListener('click', (e) => {
224
233
  click$.next(e);
@@ -250,6 +259,7 @@ const ReactVega = forwardRef<IReactVegaHandler, ReactVegaProps>(function ReactVe
250
259
  subscriptions.push(throttledParamStore$.subscribe(cb));
251
260
  };
252
261
  let index = 0;
262
+ vegaRefs.current = new Array(rowRepeatFields.length * colRepeatFields.length);
253
263
  for (let i = 0; i < rowRepeatFields.length; i++) {
254
264
  for (let j = 0; j < colRepeatFields.length; j++, index++) {
255
265
  const sourceId = index;
@@ -282,8 +292,15 @@ const ReactVega = forwardRef<IReactVegaHandler, ReactVegaProps>(function ReactVe
282
292
  ans.params = commonSpec.params;
283
293
  }
284
294
  if (node) {
295
+ const id = index;
285
296
  embed(node, ans, { mode: 'vega-lite', actions: showActions, timeFormatLocale: getVegaTimeFormatRules(i18n.language), config: vegaConfig }).then(res => {
286
- vegaRefs.current.push(res.view);
297
+ vegaRefs.current[id] = {
298
+ w: res.view.container()?.clientWidth ?? res.view.width(),
299
+ h: res.view.container()?.clientHeight ?? res.view.height(),
300
+ x: j,
301
+ y: i,
302
+ view: res.view,
303
+ };
287
304
  const paramStores = (res.vgSpec.data?.map(d => d.name) ?? []).filter(
288
305
  name => [BRUSH_SIGNAL_NAME, POINT_SIGNAL_NAME].map(p => `${p}_store`).includes(name)
289
306
  ).map(name => name.replace(/_store$/, ''));
@@ -374,45 +391,7 @@ const ReactVega = forwardRef<IReactVegaHandler, ReactVegaProps>(function ReactVe
374
391
  text
375
392
  ]);
376
393
 
377
- useImperativeHandle(ref, () => ({
378
- getSVGData() {
379
- return Promise.all(vegaRefs.current.map(view => view.toSVG()));
380
- },
381
- async getCanvasData() {
382
- const canvases = await Promise.all(vegaRefs.current.map(view => view.toCanvas()));
383
- return canvases.map(canvas => canvas.toDataURL('image/png'));
384
- },
385
- async downloadSVG(filename = `gw chart ${Date.now() % 1_000_000}`.padStart(6, '0')) {
386
- const data = await Promise.all(vegaRefs.current.map(view => view.toSVG()));
387
- const files: string[] = [];
388
- for (let i = 0; i < data.length; i += 1) {
389
- const d = data[i];
390
- const file = new File([d], `${filename}${data.length > 1 ? `_${i + 1}` : ''}.svg`);
391
- const url = URL.createObjectURL(file);
392
- const a = document.createElement('a');
393
- a.download = file.name;
394
- a.href = url;
395
- a.click();
396
- requestAnimationFrame(() => {
397
- URL.revokeObjectURL(url);
398
- });
399
- }
400
- return files;
401
- },
402
- async downloadPNG(filename = `gw chart ${Date.now() % 1_000_000}`.padStart(6, '0')) {
403
- const canvases = await Promise.all(vegaRefs.current.map(view => view.toCanvas(2)));
404
- const data = canvases.map(canvas => canvas.toDataURL('image/png', 1));
405
- const files: string[] = [];
406
- for (let i = 0; i < data.length; i += 1) {
407
- const d = data[i];
408
- const a = document.createElement('a');
409
- a.download = `${filename}${data.length > 1 ? `_${i + 1}` : ''}.png`;
410
- a.href = d.replace(/^data:image\/[^;]/, 'data:application/octet-stream');
411
- a.click();
412
- }
413
- return files;
414
- },
415
- }));
394
+ useVegaExportApi(name, vegaRefs, ref);
416
395
 
417
396
  return <CanvaContainer rowSize={Math.max(rowRepeatFields.length, 1)} colSize={Math.max(colRepeatFields.length, 1)}>
418
397
  {/* <div ref={container}></div> */}