@kanaries/graphic-walker 0.4.1 → 0.4.3

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 (66) hide show
  1. package/dist/App.d.ts +5 -1
  2. package/dist/assets/buildMetricTable.worker-5555966a.js.map +1 -0
  3. package/dist/components/leafletRenderer/ChoroplethRenderer.d.ts +22 -0
  4. package/dist/components/leafletRenderer/POIRenderer.d.ts +20 -0
  5. package/dist/components/leafletRenderer/encodings.d.ts +7 -0
  6. package/dist/components/leafletRenderer/geoConfigPanel.d.ts +3 -0
  7. package/dist/components/leafletRenderer/index.d.ts +15 -0
  8. package/dist/components/leafletRenderer/tooltip.d.ts +9 -0
  9. package/dist/components/leafletRenderer/utils.d.ts +2 -0
  10. package/dist/components/pivotTable/index.d.ts +2 -1
  11. package/dist/components/pivotTable/inteface.d.ts +6 -2
  12. package/dist/components/pivotTable/leftTree.d.ts +1 -0
  13. package/dist/components/pivotTable/topTree.d.ts +2 -0
  14. package/dist/components/pivotTable/utils.d.ts +1 -2
  15. package/dist/config.d.ts +3 -2
  16. package/dist/graphic-walker.es.js +37811 -30386
  17. package/dist/graphic-walker.es.js.map +1 -1
  18. package/dist/graphic-walker.umd.js +145 -137
  19. package/dist/graphic-walker.umd.js.map +1 -1
  20. package/dist/interfaces.d.ts +28 -0
  21. package/dist/renderer/specRenderer.d.ts +2 -1
  22. package/dist/services.d.ts +7 -1
  23. package/dist/store/commonStore.d.ts +6 -0
  24. package/dist/store/visualSpecStore.d.ts +180 -4
  25. package/dist/utils/save.d.ts +1 -0
  26. package/dist/workers/buildPivotTable.d.ts +7 -0
  27. package/package.json +14 -2
  28. package/src/App.tsx +18 -4
  29. package/src/components/leafletRenderer/ChoroplethRenderer.tsx +312 -0
  30. package/src/components/leafletRenderer/POIRenderer.tsx +189 -0
  31. package/src/components/leafletRenderer/encodings.ts +194 -0
  32. package/src/components/leafletRenderer/geoConfigPanel.tsx +197 -0
  33. package/src/components/leafletRenderer/index.tsx +70 -0
  34. package/src/components/leafletRenderer/tooltip.tsx +24 -0
  35. package/src/components/leafletRenderer/utils.ts +52 -0
  36. package/src/components/pivotTable/index.tsx +171 -67
  37. package/src/components/pivotTable/inteface.ts +6 -2
  38. package/src/components/pivotTable/leftTree.tsx +24 -11
  39. package/src/components/pivotTable/metricTable.tsx +15 -10
  40. package/src/components/pivotTable/topTree.tsx +50 -17
  41. package/src/components/pivotTable/utils.ts +70 -11
  42. package/src/components/visualConfig/index.tsx +17 -1
  43. package/src/config.ts +27 -16
  44. package/src/dataSource/table.tsx +7 -11
  45. package/src/fields/aestheticFields.tsx +4 -0
  46. package/src/fields/fieldsContext.tsx +3 -0
  47. package/src/fields/posFields/index.tsx +8 -2
  48. package/src/global.d.ts +4 -4
  49. package/src/index.tsx +11 -9
  50. package/src/interfaces.ts +35 -0
  51. package/src/locales/en-US.json +27 -2
  52. package/src/locales/ja-JP.json +27 -2
  53. package/src/locales/zh-CN.json +27 -2
  54. package/src/renderer/hooks.ts +1 -1
  55. package/src/renderer/index.tsx +24 -1
  56. package/src/renderer/pureRenderer.tsx +27 -13
  57. package/src/renderer/specRenderer.tsx +46 -30
  58. package/src/services.ts +32 -23
  59. package/src/shadow-dom.tsx +7 -0
  60. package/src/store/commonStore.ts +29 -1
  61. package/src/store/visualSpecStore.ts +38 -23
  62. package/src/utils/save.ts +28 -1
  63. package/src/utils/vegaApiExport.ts +3 -0
  64. package/src/visualSettings/index.tsx +58 -6
  65. package/src/workers/buildMetricTable.worker.js +27 -0
  66. package/src/workers/buildPivotTable.ts +27 -0
package/src/index.tsx CHANGED
@@ -1,5 +1,5 @@
1
- import React, { type ForwardedRef, forwardRef } from "react";
2
- import { DOM } from "@kanaries/react-beautiful-dnd";
1
+ import React, { type ForwardedRef, forwardRef, useState } from "react";
2
+ import { DOMProvider } from "@kanaries/react-beautiful-dnd";
3
3
  import { observer } from "mobx-react-lite";
4
4
  import App, { IGWProps } from "./App";
5
5
  import { StoreWrapper } from "./store/index";
@@ -13,22 +13,24 @@ import "./empty_sheet.css";
13
13
  export const GraphicWalker = observer(forwardRef<IGWHandler, IGWProps>((props, ref) => {
14
14
  const { storeRef } = props;
15
15
 
16
+ const [shadowRoot, setShadowRoot] = useState<ShadowRoot | null>(null);
17
+
16
18
  const handleMount = (shadowRoot: ShadowRoot) => {
17
- DOM.setBody(shadowRoot);
18
- DOM.setHead(shadowRoot);
19
+ setShadowRoot(shadowRoot);
19
20
  };
20
21
  const handleUnmount = () => {
21
- DOM.setBody(document.body);
22
- DOM.setHead(document.head);
22
+ setShadowRoot(null);
23
23
  };
24
24
 
25
25
  return (
26
26
  <StoreWrapper keepAlive={props.keepAlive} storeRef={storeRef}>
27
27
  <AppRoot ref={ref as ForwardedRef<IGWHandlerInsider>}>
28
28
  <ShadowDom onMount={handleMount} onUnmount={handleUnmount}>
29
- <FieldsContextWrapper>
30
- <App {...props} />
31
- </FieldsContextWrapper>
29
+ <DOMProvider value={{ head: shadowRoot ?? document.head, body: shadowRoot ?? document.body }}>
30
+ <FieldsContextWrapper>
31
+ <App {...props} />
32
+ </FieldsContextWrapper>
33
+ </DOMProvider>
32
34
  </ShadowDom>
33
35
  </AppRoot>
34
36
  </StoreWrapper>
package/src/interfaces.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  import {Config as VgConfig, View} from 'vega';
2
2
  import {Config as VlConfig} from 'vega-lite';
3
+ import type { FeatureCollection } from 'geojson';
4
+ import type { feature } from 'topojson-client';
3
5
  import type {IViewQuery} from "./lib/viewQuery";
4
6
 
5
7
  export type DeepReadonly<T extends Record<keyof any, any>> = {
@@ -86,6 +88,8 @@ export interface IExpression {
86
88
  as: string;
87
89
  }
88
90
 
91
+ export type IGeoRole = 'longitude' | 'latitude' | 'none';
92
+
89
93
  export interface IField {
90
94
  /**
91
95
  * fid: key in data record
@@ -101,6 +105,7 @@ export interface IField {
101
105
  aggName?: string;
102
106
  semanticType: ISemanticType;
103
107
  analyticType: IAnalyticType;
108
+ geoRole?: IGeoRole;
104
109
  cmp?: (a: any, b: any) => number;
105
110
  computed?: boolean;
106
111
  expression?: IExpression;
@@ -183,6 +188,9 @@ export interface DraggableFieldState {
183
188
  shape: IViewField[];
184
189
  theta: IViewField[];
185
190
  radius: IViewField[];
191
+ longitude: IViewField[];
192
+ latitude: IViewField[];
193
+ geoId: IViewField[];
186
194
  details: IViewField[];
187
195
  filters: IFilterField[];
188
196
  text: IViewField[];
@@ -209,14 +217,21 @@ export type IFilterRule =
209
217
 
210
218
  export type IStackMode = 'none' | 'stack' | 'normalize' | 'zero' | 'center';
211
219
 
220
+ export type ICoordMode = 'generic' | 'geographic';
221
+
212
222
  export interface IVisualConfig {
213
223
  defaultAggregated: boolean;
214
224
  geoms: string[];
225
+ showTableSummary: boolean;
226
+ /** @default "generic" */
227
+ coordSystem?: ICoordMode;
215
228
  stack: IStackMode;
216
229
  showActions: boolean;
217
230
  interactiveScale: boolean;
218
231
  sorted: ISortMode;
219
232
  zeroScale: boolean;
233
+ /** @default false */
234
+ scaleIncludeUnmatchedChoropleth?: boolean;
220
235
  background?: string;
221
236
  format: {
222
237
  numberFormat?: string;
@@ -236,6 +251,8 @@ export interface IVisualConfig {
236
251
  width: number;
237
252
  height: number;
238
253
  };
254
+ geojson?: FeatureCollection;
255
+ geoKey?: string;
239
256
  limit: number;
240
257
  }
241
258
 
@@ -294,6 +311,7 @@ export interface IChartExportResult<T extends 'svg' | 'data-url' = 'svg' | 'data
294
311
  canvas(): HTMLCanvasElement | null;
295
312
  }[];
296
313
  container(): HTMLDivElement | null;
314
+ chartType?: string;
297
315
  }
298
316
 
299
317
  interface IExportChart {
@@ -448,3 +466,20 @@ export type IResponse<T> = (
448
466
  };
449
467
  }
450
468
  );
469
+
470
+ export type Topology = Parameters<typeof feature>[0];
471
+
472
+ export type IGeographicData = (
473
+ | {
474
+ type: 'GeoJSON';
475
+ data: FeatureCollection;
476
+ }
477
+ | {
478
+ type: 'TopoJSON';
479
+ data: Topology;
480
+ /**
481
+ * default to the first key of `objects` in Topology
482
+ */
483
+ objectKey?: string;
484
+ }
485
+ );
@@ -39,7 +39,14 @@
39
39
  "arc": "Arc",
40
40
  "boxplot": "Box (Box Plot)",
41
41
  "table": "Table",
42
- "text": "Text"
42
+ "text": "Text",
43
+ "poi": "POI",
44
+ "choropleth": "Choropleth"
45
+ },
46
+ "coord_system": {
47
+ "__enum__": "Coordinate System",
48
+ "generic": "Generic",
49
+ "geographic": "Geographic"
43
50
  },
44
51
  "stack_mode": {
45
52
  "__enum__": "Stack Mode",
@@ -77,7 +84,10 @@
77
84
  "radius": "Radius",
78
85
  "filters": "Filters",
79
86
  "details": "Details",
80
- "text": "Text"
87
+ "text": "Text",
88
+ "longitude": "Longitude",
89
+ "latitude": "Latitude",
90
+ "geoId": "Geometry ID"
81
91
  },
82
92
  "aggregator": {
83
93
  "sum": "Sum",
@@ -168,6 +178,21 @@
168
178
  "size_setting": {
169
179
  "width": "Width",
170
180
  "height": "Height"
181
+ },
182
+ "table": {
183
+ "summary": "Show summary"
184
+ },
185
+ "geography": "Geography Configuration",
186
+ "geography_settings": {
187
+ "geoKey": "Feature ID",
188
+ "format": "Format",
189
+ "geojson": "GeoJSON",
190
+ "topojson": "TopoJSON",
191
+ "objectKey": "Extract Feature Key",
192
+ "jsonInputPlaceholder": "Paste {{format}} here",
193
+ "href": "{{format}} URL",
194
+ "hrefPlaceholder": "Enter {{format}} URL",
195
+ "load": "Load"
171
196
  }
172
197
  },
173
198
  "DatasetFields": {
@@ -39,7 +39,14 @@
39
39
  "arc": "アーク",
40
40
  "boxplot": "ボックスプロット",
41
41
  "table": "表",
42
- "text": "本文"
42
+ "text": "テキスト",
43
+ "poi": "POI",
44
+ "choropleth": "コロプレス"
45
+ },
46
+ "coord_system": {
47
+ "__enum__": "座標系",
48
+ "generic": "ジェネリック",
49
+ "geographic": "地理"
43
50
  },
44
51
  "stack_mode": {
45
52
  "__enum__": "スタックモード",
@@ -76,7 +83,10 @@
76
83
  "theta": "角度",
77
84
  "radius": "半径",
78
85
  "filters": "フィルター",
79
- "text": "本文"
86
+ "text": "本文",
87
+ "longitude": "経度",
88
+ "latitude": "緯度",
89
+ "geoId": "地理ID"
80
90
  },
81
91
  "aggregator": {
82
92
  "sum": "合計",
@@ -167,6 +177,21 @@
167
177
  "size_setting": {
168
178
  "width": "幅",
169
179
  "height": "高さ"
180
+ },
181
+ "table": {
182
+ "summary": "サマリを表示"
183
+ },
184
+ "geography": "地理情報設定",
185
+ "geography_settings": {
186
+ "geoKey": "フィーチャーID",
187
+ "format": "データ形式",
188
+ "geojson": "GeoJSON",
189
+ "topojson": "TopoJSON",
190
+ "objectKey": "Feature のキー",
191
+ "jsonInputPlaceholder": "{{format}}をここに貼り付けてください",
192
+ "href": "{{format}} URL",
193
+ "hrefPlaceholder": "{{format}} URLを入力",
194
+ "load": "ロード"
170
195
  }
171
196
  },
172
197
  "DatasetFields": {
@@ -39,7 +39,14 @@
39
39
  "arc": "弧形",
40
40
  "boxplot": "统计箱",
41
41
  "table": "表格",
42
- "text": "文本"
42
+ "text": "文本",
43
+ "poi": "兴趣点",
44
+ "choropleth": "区域图"
45
+ },
46
+ "coord_system": {
47
+ "__enum__": "坐标系统",
48
+ "generic": "通用",
49
+ "geographic": "地理"
43
50
  },
44
51
  "layout_type": {
45
52
  "__enum__": "尺寸模式",
@@ -77,7 +84,10 @@
77
84
  "radius": "半径",
78
85
  "filters": "筛选器",
79
86
  "details": "信息",
80
- "text": "文本"
87
+ "text": "文本",
88
+ "longitude": "经度",
89
+ "latitude": "纬度",
90
+ "geoId": "地理 ID"
81
91
  },
82
92
  "aggregator": {
83
93
  "sum": "求和",
@@ -168,6 +178,21 @@
168
178
  "size_setting": {
169
179
  "width": "宽度",
170
180
  "height": "高度"
181
+ },
182
+ "table": {
183
+ "summary": "显示摘要"
184
+ },
185
+ "geography": "地理信息配置",
186
+ "geography_settings": {
187
+ "geoKey": "地理 ID",
188
+ "format": "数据格式",
189
+ "geojson": "GeoJSON",
190
+ "topojson": "TopoJSON",
191
+ "objectKey": "提取要素键",
192
+ "jsonInputPlaceholder": "在此粘贴 {{format}}",
193
+ "href": "{{format}} URL",
194
+ "hrefPlaceholder": "输入在线资源地址",
195
+ "load": "加载"
171
196
  }
172
197
  },
173
198
  "DatasetFields": {
@@ -8,7 +8,7 @@ import { dataQueryServer } from '../computation/serverComputation';
8
8
 
9
9
  export const useComputationFunc = (): IComputationFunction => {
10
10
  const { vizStore } = useGlobalStore();
11
- return vizStore.computationFuction;
11
+ return vizStore.computationFunction;
12
12
  };
13
13
 
14
14
  interface UseRendererProps {
@@ -8,8 +8,9 @@ import { useGlobalStore } from '../store';
8
8
  import { IReactVegaHandler } from '../vis/react-vega';
9
9
  import { unstable_batchedUpdates } from 'react-dom';
10
10
  import { useRenderer } from './hooks';
11
- import { initEncoding } from '../store/visualSpecStore';
11
+ import { initEncoding } from '../utils/save';
12
12
  import { useChartIndexControl } from '../utils/chartIndexControl';
13
+ import { LEAFLET_DEFAULT_HEIGHT, LEAFLET_DEFAULT_WIDTH } from '../components/leafletRenderer';
13
14
  import { initVisualConfig } from '../utils/save';
14
15
 
15
16
  interface RendererProps {
@@ -102,6 +103,27 @@ const Renderer = forwardRef<IReactVegaHandler, RendererProps>(function (props, r
102
103
  [vizStore]
103
104
  );
104
105
 
106
+ const isSpatial = viewConfig.coordSystem === 'geographic';
107
+
108
+ const sizeRef = useRef(viewConfig.size);
109
+ sizeRef.current = viewConfig.size;
110
+
111
+ useEffect(() => {
112
+ if (isSpatial) {
113
+ const prevSizeConfig = sizeRef.current;
114
+ if (sizeRef.current.width < LEAFLET_DEFAULT_WIDTH || sizeRef.current.height < LEAFLET_DEFAULT_HEIGHT) {
115
+ vizStore.setChartLayout({
116
+ mode: sizeRef.current.mode,
117
+ width: Math.max(prevSizeConfig.width, LEAFLET_DEFAULT_WIDTH),
118
+ height: Math.max(prevSizeConfig.height, LEAFLET_DEFAULT_HEIGHT),
119
+ });
120
+ return () => {
121
+ vizStore.setChartLayout(prevSizeConfig);
122
+ };
123
+ }
124
+ }
125
+ }, [isSpatial, vizStore]);
126
+
105
127
  return (
106
128
  <SpecRenderer
107
129
  name={chart?.name}
@@ -115,6 +137,7 @@ const Renderer = forwardRef<IReactVegaHandler, RendererProps>(function (props, r
115
137
  visualConfig={viewConfig}
116
138
  onGeomClick={handleGeomClick}
117
139
  onChartResize={handleChartResize}
140
+ computationFunction={computationFunction}
118
141
  />
119
142
  );
120
143
  });
@@ -3,6 +3,7 @@ import { unstable_batchedUpdates } from 'react-dom';
3
3
  import { toJS } from 'mobx';
4
4
  import { observer } from 'mobx-react-lite';
5
5
  import { ShadowDom } from '../shadow-dom';
6
+ import LeafletRenderer from '../components/leafletRenderer';
6
7
  import { withAppRoot } from '../components/appRoot';
7
8
  import type {
8
9
  IDarkMode,
@@ -54,7 +55,6 @@ const PureRenderer = forwardRef<IReactVegaHandler, IPureRendererProps>(function
54
55
  const defaultAggregated = visualConfig?.defaultAggregated ?? false;
55
56
 
56
57
  const [viewData, setViewData] = useState<IRow[]>([]);
57
-
58
58
  const { allFields, viewDimensions, viewMeasures, filters } = useMemo(() => {
59
59
  const viewDimensions: IViewField[] = [];
60
60
  const viewMeasures: IViewField[] = [];
@@ -86,7 +86,7 @@ const PureRenderer = forwardRef<IReactVegaHandler, IPureRendererProps>(function
86
86
  limit: limit ?? -1,
87
87
  computationFunction: computation,
88
88
  });
89
-
89
+ console.log(computation)
90
90
  // Dependencies that should not trigger effect individually
91
91
  const latestFromRef = useRef({ data });
92
92
  latestFromRef.current = { data };
@@ -99,20 +99,34 @@ const PureRenderer = forwardRef<IReactVegaHandler, IPureRendererProps>(function
99
99
  }
100
100
  }, [waiting]);
101
101
 
102
+ const { coordSystem = 'generic' } = visualConfig;
103
+ const isSpatial = coordSystem === 'geographic';
104
+
102
105
  return (
103
106
  <ShadowDom>
104
107
  <div className="relative">
105
- <SpecRenderer
106
- name={name}
107
- loading={waiting}
108
- data={viewData}
109
- ref={ref}
110
- themeKey={themeKey}
111
- dark={dark}
112
- draggableFieldState={visualState}
113
- visualConfig={visualConfig}
114
- locale={locale ?? 'en-US'}
115
- />
108
+ {isSpatial && (
109
+ <LeafletRenderer
110
+ name={name}
111
+ data={data}
112
+ draggableFieldState={visualState}
113
+ visualConfig={visualConfig}
114
+ />
115
+ )}
116
+ {isSpatial || (
117
+ <SpecRenderer
118
+ name={name}
119
+ loading={waiting}
120
+ data={viewData}
121
+ ref={ref}
122
+ themeKey={themeKey}
123
+ dark={dark}
124
+ draggableFieldState={visualState}
125
+ visualConfig={visualConfig}
126
+ locale={locale ?? 'en-US'}
127
+ computationFunction={computation}
128
+ />
129
+ )}
116
130
  </div>
117
131
  </ShadowDom>
118
132
  );
@@ -3,8 +3,9 @@ import { Resizable } from 're-resizable';
3
3
  import React, { forwardRef, useMemo } from 'react';
4
4
 
5
5
  import PivotTable from '../components/pivotTable';
6
+ import LeafletRenderer from '../components/leafletRenderer';
6
7
  import ReactVega, { IReactVegaHandler } from '../vis/react-vega';
7
- import { DeepReadonly, DraggableFieldState, IDarkMode, IRow, IThemeKey, IVisualConfig, VegaGlobalConfig } from '../interfaces';
8
+ import { DeepReadonly, DraggableFieldState, IDarkMode, IRow, IThemeKey, IVisualConfig, VegaGlobalConfig, IComputationFunction } from '../interfaces';
8
9
  import LoadingLayer from '../components/loadingLayer';
9
10
  import { useCurrentMediaTheme } from '../utils/media';
10
11
  import { builtInThemes } from '../vis/theme';
@@ -20,17 +21,18 @@ interface SpecRendererProps {
20
21
  onGeomClick?: ((values: any, e: any) => void) | undefined;
21
22
  onChartResize?: ((width: number, height: number) => void) | undefined;
22
23
  locale?: string;
24
+ computationFunction: IComputationFunction;
23
25
  }
24
26
  /**
25
27
  * Sans-store renderer of GraphicWalker.
26
28
  * This is a pure component, which means it will not depend on any global state.
27
29
  */
28
30
  const SpecRenderer = forwardRef<IReactVegaHandler, SpecRendererProps>(function (
29
- { name, themeKey, dark, data, loading, draggableFieldState, visualConfig, onGeomClick, onChartResize, locale },
31
+ { name, themeKey, dark, data, loading, draggableFieldState, visualConfig, onGeomClick, onChartResize, locale, computationFunction },
30
32
  ref
31
33
  ) {
32
34
  // const { draggableFieldState, visualConfig } = vizStore;
33
- const { geoms, interactiveScale, defaultAggregated, stack, showActions, size, format: _format, background, zeroScale, resolve } = visualConfig;
35
+ const { geoms, coordSystem = 'generic', interactiveScale, defaultAggregated, stack, showActions, size, format: _format, background, zeroScale, resolve } = visualConfig;
34
36
 
35
37
  const rows = draggableFieldState.rows;
36
38
  const columns = draggableFieldState.columns;
@@ -108,10 +110,13 @@ const SpecRenderer = forwardRef<IReactVegaHandler, SpecRendererProps>(function (
108
110
  loading={loading}
109
111
  themeKey={themeKey}
110
112
  dark={dark}
113
+ computationFunction={computationFunction}
111
114
  />
112
115
  );
113
116
  }
114
117
 
118
+ const isSpatial = coordSystem === 'geographic';
119
+
115
120
  return (
116
121
  <Resizable
117
122
  className={enableResize ? 'border-blue-400 border-2 overflow-hidden' : ''}
@@ -139,33 +144,44 @@ const SpecRenderer = forwardRef<IReactVegaHandler, SpecRendererProps>(function (
139
144
  }}
140
145
  >
141
146
  {loading && <LoadingLayer />}
142
- <ReactVega
143
- name={name}
144
- vegaConfig={vegaConfig}
145
- // format={format}
146
- layoutMode={size.mode}
147
- interactiveScale={interactiveScale}
148
- geomType={geoms[0]}
149
- defaultAggregate={defaultAggregated}
150
- stack={stack}
151
- dataSource={data}
152
- rows={rows}
153
- columns={columns}
154
- color={color[0]}
155
- theta={theta[0]}
156
- radius={radius[0]}
157
- shape={shape[0]}
158
- opacity={opacity[0]}
159
- size={sizeChannel[0]}
160
- details={details}
161
- text={text[0]}
162
- showActions={showActions}
163
- width={size.width - 12 * 4}
164
- height={size.height - 12 * 4}
165
- ref={ref}
166
- onGeomClick={onGeomClick}
167
- locale={locale}
168
- />
147
+ {isSpatial && (
148
+ <LeafletRenderer
149
+ name={name}
150
+ data={data}
151
+ draggableFieldState={draggableFieldState}
152
+ visualConfig={visualConfig}
153
+ vegaConfig={vegaConfig}
154
+ />
155
+ )}
156
+ {isSpatial || (
157
+ <ReactVega
158
+ name={name}
159
+ vegaConfig={vegaConfig}
160
+ // format={format}
161
+ layoutMode={size.mode}
162
+ interactiveScale={interactiveScale}
163
+ geomType={geoms[0]}
164
+ defaultAggregate={defaultAggregated}
165
+ stack={stack}
166
+ dataSource={data}
167
+ rows={rows}
168
+ columns={columns}
169
+ color={color[0]}
170
+ theta={theta[0]}
171
+ radius={radius[0]}
172
+ shape={shape[0]}
173
+ opacity={opacity[0]}
174
+ size={sizeChannel[0]}
175
+ details={details}
176
+ text={text[0]}
177
+ showActions={showActions}
178
+ width={size.width - 12 * 4}
179
+ height={size.height - 12 * 4}
180
+ ref={ref}
181
+ onGeomClick={onGeomClick}
182
+ locale={locale}
183
+ />
184
+ )}
169
185
  </Resizable>
170
186
  );
171
187
  });
package/src/services.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { toJS } from 'mobx';
2
- import { IRow, IMutField, Specification, IFilterFiledSimple, IExpression } from './interfaces';
2
+ import { IRow, IMutField, IViewField, Specification, IFilterFiledSimple, IExpression } from './interfaces';
3
+ import { INestNode } from "./components/pivotTable/inteface";
3
4
  /* eslint import/no-webpack-loader-syntax:0 */
4
5
  // @ts-ignore
5
6
  // eslint-disable-next-line
@@ -11,6 +12,7 @@ import { IRow, IMutField, Specification, IFilterFiledSimple, IExpression } from
11
12
  import FilterWorker from './workers/filter.worker?worker&inline';
12
13
  import TransformDataWorker from './workers/transform.worker?worker&inline';
13
14
  import ViewQueryWorker from './workers/viewQuery.worker?worker&inline';
15
+ import BuildMetricTableWorker from './workers/buildMetricTable.worker?worker&inline';
14
16
  import SortWorker from './workers/sort.worker?worker&inline';
15
17
 
16
18
  import { IViewQuery } from './lib/viewQuery';
@@ -105,22 +107,12 @@ interface PreAnalysisParams {
105
107
  // }
106
108
  // }
107
109
 
108
- let filterWorker: Worker | null = null;
109
- let filterWorkerAutoTerminator: NodeJS.Timeout | null = null;
110
110
 
111
111
  export const applyFilter = async (data: IRow[], filters: readonly IFilterFiledSimple[]): Promise<IRow[]> => {
112
112
  if (filters.length === 0) return data;
113
- if (filterWorkerAutoTerminator !== null) {
114
- clearTimeout(filterWorkerAutoTerminator);
115
- filterWorkerAutoTerminator = null;
116
- }
117
-
118
- if (filterWorker === null) {
119
- filterWorker = new FilterWorker();
120
- }
121
-
113
+ const worker = new FilterWorker();
122
114
  try {
123
- const res: IRow[] = await workerService(filterWorker, {
115
+ const res: IRow[] = await workerService(worker, {
124
116
  dataSource: data,
125
117
  filters: toJS(filters),
126
118
  });
@@ -130,15 +122,7 @@ export const applyFilter = async (data: IRow[], filters: readonly IFilterFiledSi
130
122
  // @ts-ignore @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause
131
123
  throw new Error('Uncaught error in FilterWorker', { cause: error });
132
124
  } finally {
133
- if (filterWorkerAutoTerminator !== null) {
134
- clearTimeout(filterWorkerAutoTerminator);
135
- }
136
-
137
- filterWorkerAutoTerminator = setTimeout(() => {
138
- filterWorker?.terminate();
139
- filterWorker = null;
140
- filterWorkerAutoTerminator = null;
141
- }, 60_000); // Destroy the worker when no request is received for 60 secs
125
+ worker.terminate();
142
126
  }
143
127
  };
144
128
 
@@ -171,7 +155,32 @@ export const applyViewQuery = async (data: IRow[], query: IViewQuery): Promise<I
171
155
  } finally {
172
156
  worker.terminate();
173
157
  }
174
- };
158
+ }
159
+
160
+ export const buildPivotTableService = async (dimsInRow: IViewField[],
161
+ dimsInColumn: IViewField[],
162
+ allData: IRow[],
163
+ aggData: IRow[],
164
+ collapsedKeyList: string[],
165
+ showTableSummary: boolean
166
+ ): Promise<{lt: INestNode, tt: INestNode, metric: (IRow | null)[][]}> => {
167
+ const worker = new BuildMetricTableWorker();
168
+ try {
169
+ const res: {lt: INestNode, tt: INestNode, metric: (IRow | null)[][]} = await workerService(worker, {
170
+ dimsInRow,
171
+ dimsInColumn,
172
+ allData,
173
+ aggData,
174
+ collapsedKeyList,
175
+ showTableSummary
176
+ });
177
+ return res;
178
+ } catch (error) {
179
+ throw new Error('Uncaught error in TableBuilderDataWorker', { cause: error });
180
+ } finally {
181
+ worker.terminate();
182
+ }
183
+ }
175
184
 
176
185
  export const applySort = async (
177
186
  data: IRow[],
@@ -36,6 +36,13 @@ export const ShadowDom: React.FC<IShadowDomProps> = function ShadowDom ({ onMoun
36
36
  <root.div {...attrs} mode="open" ref={rootRef}>
37
37
  <style>{tailwindStyle}</style>
38
38
  <style>{style}</style>
39
+ {/* Leaflet CSS file */}
40
+ <link
41
+ rel="stylesheet"
42
+ href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
43
+ integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
44
+ crossOrigin=""
45
+ />
39
46
  {shadowRoot && (
40
47
  <StyleSheetManager target={shadowRoot}>
41
48
  <ShadowDomContext.Provider value={{ root: shadowRoot }}>