@vitessce/vega 2.0.3-beta.0 → 3.0.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.
- package/dist/index.js +62374 -2
- package/dist-tsc/ReactVega.d.ts +2 -0
- package/dist-tsc/ReactVega.d.ts.map +1 -0
- package/dist-tsc/VegaPlot.d.ts +9 -0
- package/dist-tsc/VegaPlot.d.ts.map +1 -0
- package/dist-tsc/VegaPlot.js +83 -0
- package/dist-tsc/index.d.ts +3 -0
- package/dist-tsc/index.d.ts.map +1 -0
- package/dist-tsc/index.js +2 -0
- package/dist-tsc/styles.d.ts +2 -0
- package/dist-tsc/styles.d.ts.map +1 -0
- package/dist-tsc/styles.js +18 -0
- package/dist-tsc/utils.d.ts +27 -0
- package/dist-tsc/utils.d.ts.map +1 -0
- package/{dist → dist-tsc}/utils.js +1 -0
- package/package.json +17 -6
- package/src/ReactVega.js +2 -0
- package/src/VegaPlot.js +118 -0
- package/src/index.js +2 -0
- package/src/styles.js +19 -0
- package/src/utils.js +31 -0
- package/dist/VegaPlot.js +0 -36
- /package/{dist → dist-tsc}/ReactVega.js +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ReactVega.d.ts","sourceRoot":"","sources":["../src/ReactVega.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A wrapper around the react-vega Vega component.
|
|
3
|
+
* @param {object} props
|
|
4
|
+
* @param {object} spec A vega or vega-lite spec.
|
|
5
|
+
* @param {object[]} data The plot data as an array of objects.
|
|
6
|
+
* @param {object} signalListeners Vega signal listeners. Optional.
|
|
7
|
+
*/
|
|
8
|
+
export function VegaPlot(props: object): JSX.Element | null;
|
|
9
|
+
//# sourceMappingURL=VegaPlot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VegaPlot.d.ts","sourceRoot":"","sources":["../src/VegaPlot.js"],"names":[],"mappings":"AAsCA;;;;;;GAMG;AACH,gCALW,MAAM,sBA6EhB"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React, { Suspense, useMemo } from 'react';
|
|
3
|
+
import { Handler } from 'vega-tooltip';
|
|
4
|
+
import clsx from 'clsx';
|
|
5
|
+
import { useTooltipStyles } from '@vitessce/tooltip';
|
|
6
|
+
import ReactVega from './ReactVega.js';
|
|
7
|
+
import { DATASET_NAME } from './utils.js';
|
|
8
|
+
import { useStyles } from './styles.js';
|
|
9
|
+
// TODO: React.lazy is not working with Vitessce in the portal-ui.
|
|
10
|
+
// For now, we can work around this by not using React.lazy,
|
|
11
|
+
// but for performance benefits that come with lazy-loading
|
|
12
|
+
// we should eventually try to resolve this issue.
|
|
13
|
+
// const ReactVega = React.lazy(() => import('./ReactVega'));
|
|
14
|
+
function isVega(spec) {
|
|
15
|
+
return spec.$schema === 'https://vega.github.io/schema/vega/v5.json';
|
|
16
|
+
}
|
|
17
|
+
function renderTooltipContents(tooltipText) {
|
|
18
|
+
const tableRows = Object.entries(tooltipText)
|
|
19
|
+
.map(([key, value]) => (`<tr key=${key}>
|
|
20
|
+
<th>${key}</th>
|
|
21
|
+
<td>${value}</td>
|
|
22
|
+
</tr>`))
|
|
23
|
+
.join('');
|
|
24
|
+
return (`<table>
|
|
25
|
+
<tbody>
|
|
26
|
+
${tableRows}
|
|
27
|
+
</tbody>
|
|
28
|
+
</table>`);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* A wrapper around the react-vega Vega component.
|
|
32
|
+
* @param {object} props
|
|
33
|
+
* @param {object} spec A vega or vega-lite spec.
|
|
34
|
+
* @param {object[]} data The plot data as an array of objects.
|
|
35
|
+
* @param {object} signalListeners Vega signal listeners. Optional.
|
|
36
|
+
*/
|
|
37
|
+
export function VegaPlot(props) {
|
|
38
|
+
const { spec: partialSpec, data, getTooltipText, signalListeners, } = props;
|
|
39
|
+
// eslint-disable-next-line no-unused-vars
|
|
40
|
+
const classes = useStyles();
|
|
41
|
+
const tooltipClasses = useTooltipStyles();
|
|
42
|
+
const tooltipHandler = useMemo(() => {
|
|
43
|
+
if (typeof getTooltipText === 'function') {
|
|
44
|
+
const tooltipConfig = {
|
|
45
|
+
theme: 'custom',
|
|
46
|
+
offsetX: 10,
|
|
47
|
+
offsetY: 10,
|
|
48
|
+
// Use table element to match packages/tooltip/TooltipContent implementation.
|
|
49
|
+
formatTooltip: tooltipText => `
|
|
50
|
+
<div class="${clsx(classes.tooltipContainer, tooltipClasses.tooltipContent)}">
|
|
51
|
+
${renderTooltipContents(tooltipText)}
|
|
52
|
+
</div>
|
|
53
|
+
`,
|
|
54
|
+
};
|
|
55
|
+
const handlerInstance = new Handler(tooltipConfig);
|
|
56
|
+
const originalCall = handlerInstance.call;
|
|
57
|
+
handlerInstance.call = (handler, event, item, value) => {
|
|
58
|
+
if (item && item.datum && value) {
|
|
59
|
+
const tooltipText = getTooltipText(item);
|
|
60
|
+
originalCall.call(this, handler, event, item, tooltipText);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
originalCall.call(this, handler, event, item, value);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
return handlerInstance.call;
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
69
|
+
}, [getTooltipText, classes.tooltipContainer, tooltipClasses.tooltipContent]);
|
|
70
|
+
const spec = useMemo(() => ({
|
|
71
|
+
...partialSpec,
|
|
72
|
+
data: (isVega(partialSpec)
|
|
73
|
+
? [
|
|
74
|
+
{ name: DATASET_NAME },
|
|
75
|
+
...partialSpec.data,
|
|
76
|
+
]
|
|
77
|
+
: { name: DATASET_NAME }),
|
|
78
|
+
}), [partialSpec]);
|
|
79
|
+
const vegaComponent = useMemo(() => (_jsx(ReactVega, { spec: spec, data: {
|
|
80
|
+
[DATASET_NAME]: data,
|
|
81
|
+
}, signalListeners: signalListeners, tooltip: tooltipHandler, renderer: "canvas", scaleFactor: 3 })), [spec, data, signalListeners, tooltipHandler]);
|
|
82
|
+
return (spec && data && data.length > 0 ? (_jsx(Suspense, { fallback: _jsx("div", { children: "Loading..." }), children: vegaComponent })) : null);
|
|
83
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../src/styles.js"],"names":[],"mappings":"AAEA,+GAgBI"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { makeStyles } from '@material-ui/core';
|
|
2
|
+
export const useStyles = makeStyles(theme => ({
|
|
3
|
+
'@global': {
|
|
4
|
+
'#vg-tooltip-element.vg-tooltip.custom-theme': {
|
|
5
|
+
boxShadow: '0px 2px 4px -1px rgba(0,0,0,0.2),0px 4px 5px 0px rgba(0,0,0,0.14),0px 1px 10px 0px rgba(0,0,0,0.12)',
|
|
6
|
+
padding: '0px',
|
|
7
|
+
backgroundColor: theme.palette.gridLayoutBackground,
|
|
8
|
+
color: theme.palette.secondaryForeground,
|
|
9
|
+
border: 'none',
|
|
10
|
+
opacity: 0.9,
|
|
11
|
+
fontSize: '12px',
|
|
12
|
+
borderRadius: '4px',
|
|
13
|
+
'& > div': {
|
|
14
|
+
backgroundColor: 'transparent',
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
}));
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export namespace VEGA_THEMES {
|
|
2
|
+
namespace dark {
|
|
3
|
+
const background: null;
|
|
4
|
+
namespace title {
|
|
5
|
+
const color: string;
|
|
6
|
+
}
|
|
7
|
+
const style: {
|
|
8
|
+
'guide-label': {
|
|
9
|
+
fill: string;
|
|
10
|
+
};
|
|
11
|
+
'guide-title': {
|
|
12
|
+
fill: string;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
namespace axis {
|
|
16
|
+
const domainColor: string;
|
|
17
|
+
const gridColor: string;
|
|
18
|
+
const tickColor: string;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
namespace light {
|
|
22
|
+
const background_1: null;
|
|
23
|
+
export { background_1 as background };
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export const DATASET_NAME: "table";
|
|
27
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,mCAAoC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vitessce/vega",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"author": "Gehlenborg Lab",
|
|
5
5
|
"homepage": "http://vitessce.io",
|
|
6
6
|
"repository": {
|
|
@@ -8,28 +8,39 @@
|
|
|
8
8
|
"url": "git+https://github.com/vitessce/vitessce.git"
|
|
9
9
|
},
|
|
10
10
|
"license": "MIT",
|
|
11
|
+
"type": "module",
|
|
11
12
|
"main": "dist/index.js",
|
|
12
13
|
"files": [
|
|
13
|
-
"
|
|
14
|
+
"src",
|
|
15
|
+
"dist",
|
|
16
|
+
"dist-tsc"
|
|
14
17
|
],
|
|
15
18
|
"dependencies": {
|
|
16
19
|
"@material-ui/core": "~4.12.3",
|
|
20
|
+
"clsx": "^1.1.1",
|
|
17
21
|
"react-vega": "^7.4.4",
|
|
18
22
|
"vega": "^5.21.0",
|
|
19
23
|
"vega-lite": "^5.1.1",
|
|
20
|
-
"vega-tooltip": "^0.27.0"
|
|
24
|
+
"vega-tooltip": "^0.27.0",
|
|
25
|
+
"@vitessce/tooltip": "3.0.0"
|
|
21
26
|
},
|
|
22
27
|
"devDependencies": {
|
|
23
28
|
"react": "^18.0.0",
|
|
24
|
-
"vite": "^3.0
|
|
29
|
+
"vite": "^4.3.0",
|
|
25
30
|
"vitest": "^0.23.4"
|
|
26
31
|
},
|
|
27
32
|
"peerDependencies": {
|
|
28
33
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
|
29
34
|
},
|
|
30
35
|
"scripts": {
|
|
31
|
-
"
|
|
32
|
-
"build": "tsc",
|
|
36
|
+
"bundle": "pnpm exec vite build -c ../../scripts/vite.config.js",
|
|
33
37
|
"test": "pnpm exec vitest --run -r ../../ --dir ."
|
|
38
|
+
},
|
|
39
|
+
"module": "dist/index.js",
|
|
40
|
+
"exports": {
|
|
41
|
+
".": {
|
|
42
|
+
"types": "./dist-tsc/index.d.ts",
|
|
43
|
+
"import": "./dist/index.js"
|
|
44
|
+
}
|
|
34
45
|
}
|
|
35
46
|
}
|
package/src/ReactVega.js
ADDED
package/src/VegaPlot.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import React, { Suspense, useMemo } from 'react';
|
|
2
|
+
import { Handler } from 'vega-tooltip';
|
|
3
|
+
import clsx from 'clsx';
|
|
4
|
+
import { useTooltipStyles } from '@vitessce/tooltip';
|
|
5
|
+
import ReactVega from './ReactVega.js';
|
|
6
|
+
import { DATASET_NAME } from './utils.js';
|
|
7
|
+
import { useStyles } from './styles.js';
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
// TODO: React.lazy is not working with Vitessce in the portal-ui.
|
|
11
|
+
// For now, we can work around this by not using React.lazy,
|
|
12
|
+
// but for performance benefits that come with lazy-loading
|
|
13
|
+
// we should eventually try to resolve this issue.
|
|
14
|
+
// const ReactVega = React.lazy(() => import('./ReactVega'));
|
|
15
|
+
|
|
16
|
+
function isVega(spec) {
|
|
17
|
+
return spec.$schema === 'https://vega.github.io/schema/vega/v5.json';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function renderTooltipContents(tooltipText) {
|
|
21
|
+
const tableRows = Object.entries(tooltipText)
|
|
22
|
+
.map(([key, value]) => (
|
|
23
|
+
`<tr key=${key}>
|
|
24
|
+
<th>${key}</th>
|
|
25
|
+
<td>${value}</td>
|
|
26
|
+
</tr>`
|
|
27
|
+
))
|
|
28
|
+
.join('');
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
`<table>
|
|
32
|
+
<tbody>
|
|
33
|
+
${tableRows}
|
|
34
|
+
</tbody>
|
|
35
|
+
</table>`
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* A wrapper around the react-vega Vega component.
|
|
41
|
+
* @param {object} props
|
|
42
|
+
* @param {object} spec A vega or vega-lite spec.
|
|
43
|
+
* @param {object[]} data The plot data as an array of objects.
|
|
44
|
+
* @param {object} signalListeners Vega signal listeners. Optional.
|
|
45
|
+
*/
|
|
46
|
+
export function VegaPlot(props) {
|
|
47
|
+
const {
|
|
48
|
+
spec: partialSpec,
|
|
49
|
+
data,
|
|
50
|
+
getTooltipText,
|
|
51
|
+
signalListeners,
|
|
52
|
+
} = props;
|
|
53
|
+
|
|
54
|
+
// eslint-disable-next-line no-unused-vars
|
|
55
|
+
const classes = useStyles();
|
|
56
|
+
const tooltipClasses = useTooltipStyles();
|
|
57
|
+
|
|
58
|
+
const tooltipHandler = useMemo(() => {
|
|
59
|
+
if (typeof getTooltipText === 'function') {
|
|
60
|
+
const tooltipConfig = {
|
|
61
|
+
theme: 'custom',
|
|
62
|
+
offsetX: 10,
|
|
63
|
+
offsetY: 10,
|
|
64
|
+
// Use table element to match packages/tooltip/TooltipContent implementation.
|
|
65
|
+
formatTooltip: tooltipText => `
|
|
66
|
+
<div class="${clsx(classes.tooltipContainer, tooltipClasses.tooltipContent)}">
|
|
67
|
+
${renderTooltipContents(tooltipText)}
|
|
68
|
+
</div>
|
|
69
|
+
`,
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const handlerInstance = new Handler(tooltipConfig);
|
|
73
|
+
const originalCall = handlerInstance.call;
|
|
74
|
+
handlerInstance.call = (handler, event, item, value) => {
|
|
75
|
+
if (item && item.datum && value) {
|
|
76
|
+
const tooltipText = getTooltipText(item);
|
|
77
|
+
originalCall.call(this, handler, event, item, tooltipText);
|
|
78
|
+
} else {
|
|
79
|
+
originalCall.call(this, handler, event, item, value);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
return handlerInstance.call;
|
|
83
|
+
}
|
|
84
|
+
return false;
|
|
85
|
+
}, [getTooltipText, classes.tooltipContainer, tooltipClasses.tooltipContent]);
|
|
86
|
+
|
|
87
|
+
const spec = useMemo(() => ({
|
|
88
|
+
...partialSpec,
|
|
89
|
+
data: (isVega(partialSpec)
|
|
90
|
+
? [
|
|
91
|
+
{ name: DATASET_NAME },
|
|
92
|
+
...partialSpec.data,
|
|
93
|
+
]
|
|
94
|
+
: { name: DATASET_NAME }
|
|
95
|
+
),
|
|
96
|
+
}), [partialSpec]);
|
|
97
|
+
|
|
98
|
+
const vegaComponent = useMemo(() => (
|
|
99
|
+
<ReactVega
|
|
100
|
+
spec={spec}
|
|
101
|
+
data={{
|
|
102
|
+
[DATASET_NAME]: data,
|
|
103
|
+
}}
|
|
104
|
+
signalListeners={signalListeners}
|
|
105
|
+
tooltip={tooltipHandler}
|
|
106
|
+
renderer="canvas"
|
|
107
|
+
scaleFactor={3}
|
|
108
|
+
/>
|
|
109
|
+
), [spec, data, signalListeners, tooltipHandler]);
|
|
110
|
+
|
|
111
|
+
return (
|
|
112
|
+
spec && data && data.length > 0 ? (
|
|
113
|
+
<Suspense fallback={<div>Loading...</div>}>
|
|
114
|
+
{vegaComponent}
|
|
115
|
+
</Suspense>
|
|
116
|
+
) : null
|
|
117
|
+
);
|
|
118
|
+
}
|
package/src/index.js
ADDED
package/src/styles.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { makeStyles } from '@material-ui/core';
|
|
2
|
+
|
|
3
|
+
export const useStyles = makeStyles(theme => ({
|
|
4
|
+
'@global': {
|
|
5
|
+
'#vg-tooltip-element.vg-tooltip.custom-theme': {
|
|
6
|
+
boxShadow: '0px 2px 4px -1px rgba(0,0,0,0.2),0px 4px 5px 0px rgba(0,0,0,0.14),0px 1px 10px 0px rgba(0,0,0,0.12)',
|
|
7
|
+
padding: '0px',
|
|
8
|
+
backgroundColor: theme.palette.gridLayoutBackground,
|
|
9
|
+
color: theme.palette.secondaryForeground,
|
|
10
|
+
border: 'none',
|
|
11
|
+
opacity: 0.9,
|
|
12
|
+
fontSize: '12px',
|
|
13
|
+
borderRadius: '4px',
|
|
14
|
+
'& > div': {
|
|
15
|
+
backgroundColor: 'transparent',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
}));
|
package/src/utils.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vega-Lite themes that can be passed to the `config` property
|
|
3
|
+
* of the vega-lite spec.
|
|
4
|
+
*/
|
|
5
|
+
export const VEGA_THEMES = {
|
|
6
|
+
dark: {
|
|
7
|
+
// The vega-themes dark theme.
|
|
8
|
+
// Reference: https://github.com/vega/vega-themes/blob/master/src/theme-dark.ts
|
|
9
|
+
background: null,
|
|
10
|
+
title: { color: '#fff' },
|
|
11
|
+
style: {
|
|
12
|
+
'guide-label': {
|
|
13
|
+
fill: '#fff',
|
|
14
|
+
},
|
|
15
|
+
'guide-title': {
|
|
16
|
+
fill: '#fff',
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
axis: {
|
|
20
|
+
domainColor: '#fff',
|
|
21
|
+
gridColor: '#888',
|
|
22
|
+
tickColor: '#fff',
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
light: {
|
|
26
|
+
// The default vega theme.
|
|
27
|
+
background: null,
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const DATASET_NAME = 'table';
|
package/dist/VegaPlot.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import React, { Suspense, useMemo } from 'react';
|
|
3
|
-
import { Handler } from 'vega-tooltip';
|
|
4
|
-
import ReactVega from './ReactVega';
|
|
5
|
-
// TODO: React.lazy is not working with Vitessce in the portal-ui.
|
|
6
|
-
// For now, we can work around this by not using React.lazy,
|
|
7
|
-
// but for performance benefits that come with lazy-loading
|
|
8
|
-
// we should eventually try to resolve this issue.
|
|
9
|
-
// const ReactVega = React.lazy(() => import('./ReactVega'));
|
|
10
|
-
export const DATASET_NAME = 'table';
|
|
11
|
-
function isVega(spec) {
|
|
12
|
-
return spec.$schema === 'https://vega.github.io/schema/vega/v5.json';
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* A wrapper around the react-vega Vega component.
|
|
16
|
-
* @param {object} props
|
|
17
|
-
* @param {object} spec A vega or vega-lite spec.
|
|
18
|
-
* @param {object[]} data The plot data as an array of objects.
|
|
19
|
-
* @param {object} signalListeners Vega signal listeners. Optional.
|
|
20
|
-
*/
|
|
21
|
-
export function VegaPlot(props) {
|
|
22
|
-
const { spec: partialSpec, data, signalListeners, } = props;
|
|
23
|
-
const spec = useMemo(() => ({
|
|
24
|
-
...partialSpec,
|
|
25
|
-
data: (isVega(partialSpec)
|
|
26
|
-
? [
|
|
27
|
-
{ name: DATASET_NAME },
|
|
28
|
-
...partialSpec.data,
|
|
29
|
-
]
|
|
30
|
-
: { name: DATASET_NAME }),
|
|
31
|
-
}), [partialSpec]);
|
|
32
|
-
const vegaComponent = useMemo(() => (_jsx(ReactVega, { spec: spec, data: {
|
|
33
|
-
[DATASET_NAME]: data,
|
|
34
|
-
}, signalListeners: signalListeners, tooltip: new Handler().call, renderer: "canvas", scaleFactor: 3 })), [spec, data, signalListeners]);
|
|
35
|
-
return (spec && data && data.length > 0 ? (_jsx(Suspense, { fallback: _jsx("div", { children: "Loading..." }), children: vegaComponent })) : null);
|
|
36
|
-
}
|
|
File without changes
|