@kanaries/graphic-walker 0.3.7 → 0.3.8
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/components/pivotTable/index.d.ts +1 -1
- package/dist/graphic-walker.es.js +9859 -9802
- package/dist/graphic-walker.es.js.map +1 -1
- package/dist/graphic-walker.umd.js +88 -88
- package/dist/graphic-walker.umd.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/renderer/hooks.d.ts +15 -0
- package/dist/renderer/pureRenderer.d.ts +12 -0
- package/dist/renderer/specRenderer.d.ts +7 -1
- package/package.json +1 -1
- package/src/components/pivotTable/index.tsx +1 -1
- package/src/fields/aestheticFields.tsx +2 -0
- package/src/index.tsx +2 -0
- package/src/renderer/hooks.ts +73 -0
- package/src/renderer/index.tsx +61 -46
- package/src/renderer/pureRenderer.tsx +90 -0
- package/src/renderer/specRenderer.tsx +29 -23
- package/src/vis/spec/mark.ts +1 -1
- package/dist/utils/autoMark.d.ts +0 -7
- package/src/utils/autoMark.ts +0 -30
package/dist/index.d.ts
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { DeepReadonly, IFilterField, IRow, IViewField } from '../interfaces';
|
|
2
|
+
interface UseRendererProps {
|
|
3
|
+
data: IRow[];
|
|
4
|
+
allFields: Omit<IViewField, 'dragId'>[];
|
|
5
|
+
viewDimensions: IViewField[];
|
|
6
|
+
viewMeasures: IViewField[];
|
|
7
|
+
filters: readonly DeepReadonly<IFilterField>[];
|
|
8
|
+
defaultAggregated: boolean;
|
|
9
|
+
}
|
|
10
|
+
interface UseRendererResult {
|
|
11
|
+
viewData: IRow[];
|
|
12
|
+
loading: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare const useRenderer: (props: UseRendererProps) => UseRendererResult;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { IDarkMode, IRow, IThemeKey, DraggableFieldState, IVisualConfig } from '../interfaces';
|
|
3
|
+
import type { IReactVegaHandler } from '../vis/react-vega';
|
|
4
|
+
interface IPureRendererProps {
|
|
5
|
+
themeKey?: IThemeKey;
|
|
6
|
+
dark?: IDarkMode;
|
|
7
|
+
rawData?: IRow[];
|
|
8
|
+
visualState: DraggableFieldState;
|
|
9
|
+
visualConfig: IVisualConfig;
|
|
10
|
+
}
|
|
11
|
+
declare const _default: React.MemoExoticComponent<React.ForwardRefExoticComponent<Pick<IPureRendererProps & React.RefAttributes<IReactVegaHandler>, "key" | keyof IPureRendererProps> & React.RefAttributes<IReactVegaHandler>>>;
|
|
12
|
+
export default _default;
|
|
@@ -7,7 +7,13 @@ interface SpecRendererProps {
|
|
|
7
7
|
data: IRow[];
|
|
8
8
|
loading: boolean;
|
|
9
9
|
draggableFieldState: DeepReadonly<DraggableFieldState>;
|
|
10
|
-
visualConfig: IVisualConfig
|
|
10
|
+
visualConfig: DeepReadonly<IVisualConfig>;
|
|
11
|
+
onGeomClick?: ((values: any, e: any) => void) | undefined;
|
|
12
|
+
onChartResize?: ((width: number, height: number) => void) | undefined;
|
|
11
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Sans-store renderer of GraphicWalker.
|
|
16
|
+
* This is a pure component, which means it will not depend on any global state.
|
|
17
|
+
*/
|
|
12
18
|
declare const SpecRenderer: React.ForwardRefExoticComponent<SpecRendererProps & React.RefAttributes<IReactVegaHandler>>;
|
|
13
19
|
export default SpecRenderer;
|
package/package.json
CHANGED
|
@@ -39,7 +39,7 @@ interface PivotTableProps {
|
|
|
39
39
|
data: IRow[];
|
|
40
40
|
loading: boolean;
|
|
41
41
|
draggableFieldState: DeepReadonly<DraggableFieldState>;
|
|
42
|
-
visualConfig: IVisualConfig
|
|
42
|
+
visualConfig: DeepReadonly<IVisualConfig>;
|
|
43
43
|
}
|
|
44
44
|
const PivotTable: React.FC<PivotTableProps> = (props) => {
|
|
45
45
|
const { data, draggableFieldState } = props;
|
package/src/index.tsx
CHANGED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { useState, useEffect, useMemo, useRef } from 'react';
|
|
2
|
+
import { unstable_batchedUpdates } from 'react-dom';
|
|
3
|
+
import type { DeepReadonly, IFilterField, IRow, IViewField } from '../interfaces';
|
|
4
|
+
import { applyFilter, applyViewQuery, transformDataService } from '../services';
|
|
5
|
+
import { getMeaAggKey } from '../utils';
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
interface UseRendererProps {
|
|
9
|
+
data: IRow[];
|
|
10
|
+
allFields: Omit<IViewField, 'dragId'>[];
|
|
11
|
+
viewDimensions: IViewField[];
|
|
12
|
+
viewMeasures: IViewField[];
|
|
13
|
+
filters: readonly DeepReadonly<IFilterField>[];
|
|
14
|
+
defaultAggregated: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface UseRendererResult {
|
|
18
|
+
viewData: IRow[];
|
|
19
|
+
loading: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const useRenderer = (props: UseRendererProps): UseRendererResult => {
|
|
23
|
+
const { data, allFields, viewDimensions, viewMeasures, filters, defaultAggregated } = props;
|
|
24
|
+
const [computing, setComputing] = useState(false);
|
|
25
|
+
const taskIdRef = useRef(0);
|
|
26
|
+
|
|
27
|
+
const [viewData, setViewData] = useState<IRow[]>([]);
|
|
28
|
+
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
const taskId = ++taskIdRef.current;
|
|
31
|
+
setComputing(true);
|
|
32
|
+
applyFilter(data, filters)
|
|
33
|
+
.then((data) => transformDataService(data, allFields))
|
|
34
|
+
.then((d) => {
|
|
35
|
+
// setViewData(d);
|
|
36
|
+
const dims = viewDimensions;
|
|
37
|
+
const meas = viewMeasures;
|
|
38
|
+
return applyViewQuery(d, dims.concat(meas), {
|
|
39
|
+
op: defaultAggregated ? 'aggregate' : 'raw',
|
|
40
|
+
groupBy: dims.map((f) => f.fid),
|
|
41
|
+
measures: meas.map((f) => ({ field: f.fid, agg: f.aggName as any, asFieldKey: getMeaAggKey(f.fid, f.aggName!) })),
|
|
42
|
+
});
|
|
43
|
+
})
|
|
44
|
+
.then(data => {
|
|
45
|
+
if (taskId !== taskIdRef.current) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
unstable_batchedUpdates(() => {
|
|
49
|
+
setComputing(false);
|
|
50
|
+
setViewData(data);
|
|
51
|
+
});
|
|
52
|
+
}).catch((err) => {
|
|
53
|
+
if (taskId !== taskIdRef.current) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
console.error(err);
|
|
57
|
+
unstable_batchedUpdates(() => {
|
|
58
|
+
setComputing(false);
|
|
59
|
+
setViewData([]);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
return () => {
|
|
63
|
+
taskIdRef.current++;
|
|
64
|
+
};
|
|
65
|
+
}, [data, filters, viewDimensions, viewMeasures, defaultAggregated]);
|
|
66
|
+
|
|
67
|
+
return useMemo(() => {
|
|
68
|
+
return {
|
|
69
|
+
viewData,
|
|
70
|
+
loading: computing,
|
|
71
|
+
};
|
|
72
|
+
}, [viewData, computing]);
|
|
73
|
+
};
|
package/src/renderer/index.tsx
CHANGED
|
@@ -1,72 +1,85 @@
|
|
|
1
1
|
import { observer } from 'mobx-react-lite';
|
|
2
|
-
import React, { useState, useEffect, forwardRef } from 'react';
|
|
3
|
-
import { applyFilter, applyViewQuery, transformDataService } from '../services';
|
|
2
|
+
import React, { useState, useEffect, forwardRef, useRef, useCallback } from 'react';
|
|
4
3
|
import { DeepReadonly, DraggableFieldState, IDarkMode, IRow, IThemeKey, IVisualConfig } from '../interfaces';
|
|
5
4
|
import SpecRenderer from './specRenderer';
|
|
6
|
-
import { toJS } from 'mobx';
|
|
5
|
+
import { runInAction, toJS } from 'mobx';
|
|
7
6
|
import { useGlobalStore } from '../store';
|
|
8
7
|
import { IReactVegaHandler } from '../vis/react-vega';
|
|
9
8
|
import { unstable_batchedUpdates } from 'react-dom';
|
|
9
|
+
import { useRenderer } from './hooks';
|
|
10
10
|
import { initEncoding, initVisualConfig } from '../store/visualSpecStore';
|
|
11
|
-
import PivotTable from '../components/pivotTable';
|
|
12
|
-
import { getMeaAggKey } from '../utils';
|
|
13
11
|
|
|
14
12
|
interface RendererProps {
|
|
15
13
|
themeKey?: IThemeKey;
|
|
16
14
|
dark?: IDarkMode;
|
|
17
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* Renderer of GraphicWalker editor.
|
|
18
|
+
* Depending on global store.
|
|
19
|
+
*/
|
|
18
20
|
const Renderer = forwardRef<IReactVegaHandler, RendererProps>(function (props, ref) {
|
|
19
21
|
const { themeKey, dark } = props;
|
|
20
|
-
const [waiting, setWaiting] = useState<boolean>(false);
|
|
21
22
|
const { vizStore, commonStore } = useGlobalStore();
|
|
22
|
-
const { allFields, viewFilters, viewDimensions, viewMeasures } = vizStore;
|
|
23
|
+
const { allFields, viewFilters, viewDimensions, viewMeasures, visualConfig, draggableFieldState } = vizStore;
|
|
23
24
|
const { currentDataset } = commonStore;
|
|
24
25
|
const { dataSource } = currentDataset;
|
|
26
|
+
|
|
25
27
|
const [viewConfig, setViewConfig] = useState<IVisualConfig>(initVisualConfig);
|
|
26
28
|
const [encodings, setEncodings] = useState<DeepReadonly<DraggableFieldState>>(initEncoding);
|
|
27
|
-
|
|
28
29
|
const [viewData, setViewData] = useState<IRow[]>([]);
|
|
30
|
+
|
|
31
|
+
const { viewData: data, loading: waiting } = useRenderer({
|
|
32
|
+
data: dataSource,
|
|
33
|
+
allFields,
|
|
34
|
+
viewDimensions,
|
|
35
|
+
viewMeasures,
|
|
36
|
+
filters: viewFilters,
|
|
37
|
+
defaultAggregated: visualConfig.defaultAggregated,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Dependencies that should not trigger effect individually
|
|
41
|
+
const latestFromRef = useRef({
|
|
42
|
+
data,
|
|
43
|
+
draggableFieldState: toJS(draggableFieldState),
|
|
44
|
+
visualConfig: toJS(visualConfig),
|
|
45
|
+
});
|
|
46
|
+
latestFromRef.current = {
|
|
47
|
+
data,
|
|
48
|
+
draggableFieldState: toJS(draggableFieldState),
|
|
49
|
+
visualConfig: toJS(visualConfig),
|
|
50
|
+
};
|
|
51
|
+
|
|
29
52
|
useEffect(() => {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const dims = viewDimensions;
|
|
36
|
-
const meas = viewMeasures;
|
|
37
|
-
const config = toJS(vizStore.visualConfig);
|
|
38
|
-
return applyViewQuery(d, dims.concat(meas), {
|
|
39
|
-
op: config.defaultAggregated ? 'aggregate' : 'raw',
|
|
40
|
-
groupBy: dims.map((f) => f.fid),
|
|
41
|
-
measures: meas.map((f) => ({ field: f.fid, agg: f.aggName as any, asFieldKey: getMeaAggKey(f.fid, f.aggName!) })),
|
|
42
|
-
});
|
|
43
|
-
})
|
|
44
|
-
.then((data) => {
|
|
45
|
-
unstable_batchedUpdates(() => {
|
|
46
|
-
setViewData(data);
|
|
47
|
-
setWaiting(false);
|
|
48
|
-
setEncodings(toJS(vizStore.draggableFieldState));
|
|
49
|
-
setViewConfig(toJS(vizStore.visualConfig));
|
|
50
|
-
});
|
|
51
|
-
})
|
|
52
|
-
.catch((err) => {
|
|
53
|
-
console.error(err);
|
|
54
|
-
setWaiting(false);
|
|
53
|
+
if (waiting === false) {
|
|
54
|
+
unstable_batchedUpdates(() => {
|
|
55
|
+
setViewData(latestFromRef.current.data);
|
|
56
|
+
setEncodings(latestFromRef.current.draggableFieldState);
|
|
57
|
+
setViewConfig(latestFromRef.current.visualConfig);
|
|
55
58
|
});
|
|
56
|
-
|
|
59
|
+
}
|
|
60
|
+
}, [waiting, vizStore]);
|
|
57
61
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
62
|
+
const handleGeomClick = useCallback(
|
|
63
|
+
(values: any, e: any) => {
|
|
64
|
+
e.stopPropagation();
|
|
65
|
+
runInAction(() => {
|
|
66
|
+
commonStore.showEmbededMenu([e.pageX, e.pageY]);
|
|
67
|
+
commonStore.setFilters(values);
|
|
68
|
+
});
|
|
69
|
+
},
|
|
70
|
+
[]
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
const handleChartResize = useCallback(
|
|
74
|
+
(width: number, height: number) => {
|
|
75
|
+
vizStore.setChartLayout({
|
|
76
|
+
mode: 'fixed',
|
|
77
|
+
width,
|
|
78
|
+
height,
|
|
79
|
+
});
|
|
80
|
+
},
|
|
81
|
+
[vizStore]
|
|
82
|
+
);
|
|
70
83
|
|
|
71
84
|
return (
|
|
72
85
|
<SpecRenderer
|
|
@@ -77,6 +90,8 @@ const Renderer = forwardRef<IReactVegaHandler, RendererProps>(function (props, r
|
|
|
77
90
|
dark={dark}
|
|
78
91
|
draggableFieldState={encodings}
|
|
79
92
|
visualConfig={viewConfig}
|
|
93
|
+
onGeomClick={handleGeomClick}
|
|
94
|
+
onChartResize={handleChartResize}
|
|
80
95
|
/>
|
|
81
96
|
);
|
|
82
97
|
});
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import React, { useState, useEffect, forwardRef, useMemo, useRef } from 'react';
|
|
2
|
+
import { unstable_batchedUpdates } from 'react-dom';
|
|
3
|
+
import { toJS } from 'mobx';
|
|
4
|
+
import { observer } from 'mobx-react-lite';
|
|
5
|
+
import type { IDarkMode, IViewField, IRow, IThemeKey, DraggableFieldState, IVisualConfig } from '../interfaces';
|
|
6
|
+
import type { IReactVegaHandler } from '../vis/react-vega';
|
|
7
|
+
import SpecRenderer from './specRenderer';
|
|
8
|
+
import { useRenderer } from './hooks';
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
interface IPureRendererProps {
|
|
12
|
+
themeKey?: IThemeKey;
|
|
13
|
+
dark?: IDarkMode;
|
|
14
|
+
rawData?: IRow[];
|
|
15
|
+
visualState: DraggableFieldState;
|
|
16
|
+
visualConfig: IVisualConfig;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Render a readonly chart with given visualization schema.
|
|
21
|
+
* This is a pure component, which means it will not depend on any global state.
|
|
22
|
+
*/
|
|
23
|
+
const PureRenderer = forwardRef<IReactVegaHandler, IPureRendererProps>(function PureRenderer (props, ref) {
|
|
24
|
+
const {
|
|
25
|
+
themeKey,
|
|
26
|
+
dark,
|
|
27
|
+
rawData,
|
|
28
|
+
visualState,
|
|
29
|
+
visualConfig,
|
|
30
|
+
} = props;
|
|
31
|
+
const defaultAggregated = visualConfig?.defaultAggregated ?? false;
|
|
32
|
+
|
|
33
|
+
const [viewData, setViewData] = useState<IRow[]>([]);
|
|
34
|
+
|
|
35
|
+
const { allFields, viewDimensions, viewMeasures, filters } = useMemo(() => {
|
|
36
|
+
const viewDimensions: IViewField[] = [];
|
|
37
|
+
const viewMeasures: IViewField[] = [];
|
|
38
|
+
|
|
39
|
+
const { dimensions, measures, filters, ...state } = toJS(visualState);
|
|
40
|
+
const allFields = [...dimensions, ...measures];
|
|
41
|
+
|
|
42
|
+
const dKeys = Object.keys(state) as (keyof DraggableFieldState)[];
|
|
43
|
+
for (const dKey of dKeys) {
|
|
44
|
+
for (const f of state[dKey]) {
|
|
45
|
+
if (f.analyticType === 'dimension') {
|
|
46
|
+
viewDimensions.push(f);
|
|
47
|
+
} else if (f.analyticType === 'measure') {
|
|
48
|
+
viewMeasures.push(f);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return { allFields, viewDimensions, viewMeasures, filters };
|
|
54
|
+
}, [visualState]);
|
|
55
|
+
|
|
56
|
+
const { viewData: data, loading: waiting } = useRenderer({
|
|
57
|
+
data: rawData ?? [],
|
|
58
|
+
allFields,
|
|
59
|
+
viewDimensions,
|
|
60
|
+
viewMeasures,
|
|
61
|
+
filters,
|
|
62
|
+
defaultAggregated,
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Dependencies that should not trigger effect individually
|
|
66
|
+
const latestFromRef = useRef({ data });
|
|
67
|
+
latestFromRef.current = { data };
|
|
68
|
+
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
if (waiting === false) {
|
|
71
|
+
unstable_batchedUpdates(() => {
|
|
72
|
+
setViewData(latestFromRef.current.data);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}, [waiting]);
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<SpecRenderer
|
|
79
|
+
loading={waiting}
|
|
80
|
+
data={viewData}
|
|
81
|
+
ref={ref}
|
|
82
|
+
themeKey={themeKey}
|
|
83
|
+
dark={dark}
|
|
84
|
+
draggableFieldState={visualState}
|
|
85
|
+
visualConfig={visualConfig}
|
|
86
|
+
/>
|
|
87
|
+
);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
export default observer(PureRenderer);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { toJS } from 'mobx';
|
|
2
2
|
import { Resizable } from 're-resizable';
|
|
3
|
-
import React, {
|
|
3
|
+
import React, { forwardRef, useMemo } from 'react';
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import PivotTable from '../components/pivotTable';
|
|
6
6
|
import ReactVega, { IReactVegaHandler } from '../vis/react-vega';
|
|
7
7
|
import { DeepReadonly, DraggableFieldState, IDarkMode, IRow, IThemeKey, IVisualConfig, VegaGlobalConfig } from '../interfaces';
|
|
8
8
|
import LoadingLayer from '../components/loadingLayer';
|
|
@@ -15,13 +15,18 @@ interface SpecRendererProps {
|
|
|
15
15
|
data: IRow[];
|
|
16
16
|
loading: boolean;
|
|
17
17
|
draggableFieldState: DeepReadonly<DraggableFieldState>;
|
|
18
|
-
visualConfig: IVisualConfig
|
|
18
|
+
visualConfig: DeepReadonly<IVisualConfig>;
|
|
19
|
+
onGeomClick?: ((values: any, e: any) => void) | undefined;
|
|
20
|
+
onChartResize?: ((width: number, height: number) => void) | undefined;
|
|
19
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Sans-store renderer of GraphicWalker.
|
|
24
|
+
* This is a pure component, which means it will not depend on any global state.
|
|
25
|
+
*/
|
|
20
26
|
const SpecRenderer = forwardRef<IReactVegaHandler, SpecRendererProps>(function (
|
|
21
|
-
{ themeKey, dark, data, loading, draggableFieldState, visualConfig },
|
|
27
|
+
{ themeKey, dark, data, loading, draggableFieldState, visualConfig, onGeomClick, onChartResize },
|
|
22
28
|
ref
|
|
23
29
|
) {
|
|
24
|
-
const { vizStore, commonStore } = useGlobalStore();
|
|
25
30
|
// const { draggableFieldState, visualConfig } = vizStore;
|
|
26
31
|
const { geoms, interactiveScale, defaultAggregated, stack, showActions, size, format: _format, zeroScale } = visualConfig;
|
|
27
32
|
|
|
@@ -43,19 +48,11 @@ const SpecRenderer = forwardRef<IReactVegaHandler, SpecRendererProps>(function (
|
|
|
43
48
|
[columns]
|
|
44
49
|
);
|
|
45
50
|
|
|
51
|
+
const isPivotTable = geoms[0] === 'table';
|
|
52
|
+
|
|
46
53
|
const hasFacet = rowLeftFacetFields.length > 0 || colLeftFacetFields.length > 0;
|
|
47
54
|
|
|
48
|
-
const
|
|
49
|
-
(values: any, e: any) => {
|
|
50
|
-
e.stopPropagation();
|
|
51
|
-
runInAction(() => {
|
|
52
|
-
commonStore.showEmbededMenu([e.pageX, e.pageY]);
|
|
53
|
-
commonStore.setFilters(values);
|
|
54
|
-
});
|
|
55
|
-
},
|
|
56
|
-
[]
|
|
57
|
-
);
|
|
58
|
-
const enableResize = size.mode === 'fixed' && !hasFacet;
|
|
55
|
+
const enableResize = size.mode === 'fixed' && !hasFacet && Boolean(onChartResize);
|
|
59
56
|
const mediaTheme = useCurrentMediaTheme(dark);
|
|
60
57
|
const themeConfig = builtInThemes[themeKey ?? 'vega']?.[mediaTheme];
|
|
61
58
|
|
|
@@ -85,16 +82,25 @@ const SpecRenderer = forwardRef<IReactVegaHandler, SpecRendererProps>(function (
|
|
|
85
82
|
return config;
|
|
86
83
|
}, [themeConfig, zeroScale, format.normalizedNumberFormat, format.numberFormat, format.timeFormat])
|
|
87
84
|
|
|
85
|
+
if (isPivotTable) {
|
|
86
|
+
return (
|
|
87
|
+
<PivotTable
|
|
88
|
+
data={data}
|
|
89
|
+
draggableFieldState={draggableFieldState}
|
|
90
|
+
visualConfig={visualConfig}
|
|
91
|
+
loading={loading}
|
|
92
|
+
themeKey={themeKey}
|
|
93
|
+
dark={dark}
|
|
94
|
+
/>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
88
98
|
return (
|
|
89
99
|
<Resizable
|
|
90
100
|
className={enableResize ? 'border-blue-400 border-2 overflow-hidden' : ''}
|
|
91
101
|
style={{ padding: '12px' }}
|
|
92
102
|
onResizeStop={(e, direction, ref, d) => {
|
|
93
|
-
|
|
94
|
-
mode: 'fixed',
|
|
95
|
-
width: size.width + d.width,
|
|
96
|
-
height: size.height + d.height,
|
|
97
|
-
});
|
|
103
|
+
onChartResize?.(size.width + d.width, size.height + d.height);
|
|
98
104
|
}}
|
|
99
105
|
enable={
|
|
100
106
|
enableResize
|
|
@@ -139,7 +145,7 @@ const SpecRenderer = forwardRef<IReactVegaHandler, SpecRendererProps>(function (
|
|
|
139
145
|
width={size.width - 12 * 4}
|
|
140
146
|
height={size.height - 12 * 4}
|
|
141
147
|
ref={ref}
|
|
142
|
-
onGeomClick={
|
|
148
|
+
onGeomClick={onGeomClick}
|
|
143
149
|
/>
|
|
144
150
|
</Resizable>
|
|
145
151
|
);
|
package/src/vis/spec/mark.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { ISemanticType } from "../../interfaces";
|
|
|
7
7
|
*/
|
|
8
8
|
export function autoMark(semanticTypeList: ISemanticType[]): string {
|
|
9
9
|
if (semanticTypeList.length < 2) {
|
|
10
|
-
if (semanticTypeList[0] === "temporal") return "tick";
|
|
10
|
+
if (semanticTypeList[0] === "temporal" || semanticTypeList[0] === 'quantitative') return "tick";
|
|
11
11
|
return "bar";
|
|
12
12
|
}
|
|
13
13
|
const couter: Map<ISemanticType, number> = new Map();
|
package/dist/utils/autoMark.d.ts
DELETED
package/src/utils/autoMark.ts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { ISemanticType } from "../interfaces";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
*
|
|
5
|
-
* @param semanticTypeList semanticTypeList.length <= 2,调用时,手动将columns 和 rows的最后一个元素组合传进来
|
|
6
|
-
* @returns geom(mark) type
|
|
7
|
-
*/
|
|
8
|
-
export function autoMark(semanticTypeList: ISemanticType[]): string {
|
|
9
|
-
if (semanticTypeList.length < 2) {
|
|
10
|
-
if (semanticTypeList[0] === "temporal") return "tick";
|
|
11
|
-
return "bar";
|
|
12
|
-
}
|
|
13
|
-
const couter: Map<ISemanticType, number> = new Map();
|
|
14
|
-
(["nominal", "ordinal", "quantitative", "temporal"] as ISemanticType[]).forEach((s) => {
|
|
15
|
-
couter.set(s, 0);
|
|
16
|
-
});
|
|
17
|
-
for (let st of semanticTypeList) {
|
|
18
|
-
couter.set(st, couter.get(st)! + 1);
|
|
19
|
-
}
|
|
20
|
-
if (couter.get("nominal") === 1 || couter.get("ordinal") === 1) {
|
|
21
|
-
return "bar";
|
|
22
|
-
}
|
|
23
|
-
if (couter.get("temporal") === 1 && couter.get("quantitative") === 1) {
|
|
24
|
-
return "line";
|
|
25
|
-
}
|
|
26
|
-
if (couter.get("quantitative") === 2) {
|
|
27
|
-
return "point";
|
|
28
|
-
}
|
|
29
|
-
return "point";
|
|
30
|
-
}
|