@vitessce/scatterplot 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/deflate-24a61b7a.js +13 -0
- package/dist/index-d78d4568.js +142036 -0
- package/dist/index.js +15 -5
- package/dist/jpeg-19791032.js +840 -0
- package/dist/lerc-867fd2ef.js +2014 -0
- package/dist/lzw-40577136.js +128 -0
- package/dist/packbits-eab43a40.js +30 -0
- package/dist/pako.esm-68f84e2a.js +4022 -0
- package/dist/raw-66364181.js +12 -0
- package/dist/webimage-0fe27785.js +32 -0
- package/dist-tsc/EmptyMessage.d.ts +2 -0
- package/dist-tsc/EmptyMessage.d.ts.map +1 -0
- package/dist-tsc/Scatterplot.d.ts +10 -0
- package/dist-tsc/Scatterplot.d.ts.map +1 -0
- package/{dist → dist-tsc}/Scatterplot.js +12 -2
- package/dist-tsc/ScatterplotOptions.d.ts +2 -0
- package/dist-tsc/ScatterplotOptions.d.ts.map +1 -0
- package/{dist → dist-tsc}/ScatterplotOptions.js +13 -7
- package/dist-tsc/ScatterplotTooltipSubscriber.d.ts +2 -0
- package/dist-tsc/ScatterplotTooltipSubscriber.d.ts.map +1 -0
- package/dist-tsc/index.d.ts +6 -0
- package/dist-tsc/index.d.ts.map +1 -0
- package/dist-tsc/index.js +5 -0
- package/dist-tsc/shared-spatial-scatterplot/AbstractSpatialOrScatterplot.d.ts +82 -0
- package/dist-tsc/shared-spatial-scatterplot/AbstractSpatialOrScatterplot.d.ts.map +1 -0
- package/{dist → dist-tsc}/shared-spatial-scatterplot/AbstractSpatialOrScatterplot.js +9 -4
- package/dist-tsc/shared-spatial-scatterplot/ToolMenu.d.ts +4 -0
- package/dist-tsc/shared-spatial-scatterplot/ToolMenu.d.ts.map +1 -0
- package/{dist → dist-tsc}/shared-spatial-scatterplot/ToolMenu.js +32 -7
- package/dist-tsc/shared-spatial-scatterplot/ToolMenu.test.d.ts +2 -0
- package/dist-tsc/shared-spatial-scatterplot/ToolMenu.test.d.ts.map +1 -0
- package/dist-tsc/shared-spatial-scatterplot/ToolMenu.test.js +23 -0
- package/dist-tsc/shared-spatial-scatterplot/cursor.d.ts +4 -0
- package/dist-tsc/shared-spatial-scatterplot/cursor.d.ts.map +1 -0
- package/dist-tsc/shared-spatial-scatterplot/dynamic-opacity.d.ts +3 -0
- package/dist-tsc/shared-spatial-scatterplot/dynamic-opacity.d.ts.map +1 -0
- package/{dist → dist-tsc}/shared-spatial-scatterplot/dynamic-opacity.js +1 -1
- package/dist-tsc/shared-spatial-scatterplot/dynamic-opacity.test.d.ts +2 -0
- package/dist-tsc/shared-spatial-scatterplot/dynamic-opacity.test.d.ts.map +1 -0
- package/{dist → dist-tsc}/shared-spatial-scatterplot/dynamic-opacity.test.js +1 -1
- package/dist-tsc/shared-spatial-scatterplot/force-collide-rects.d.ts +13 -0
- package/dist-tsc/shared-spatial-scatterplot/force-collide-rects.d.ts.map +1 -0
- package/dist-tsc/shared-spatial-scatterplot/force-collide-rects.test.d.ts +2 -0
- package/dist-tsc/shared-spatial-scatterplot/force-collide-rects.test.d.ts.map +1 -0
- package/{dist → dist-tsc}/shared-spatial-scatterplot/force-collide-rects.test.js +1 -1
- package/dist-tsc/shared-spatial-scatterplot/index.d.ts +6 -0
- package/dist-tsc/shared-spatial-scatterplot/index.d.ts.map +1 -0
- package/dist-tsc/shared-spatial-scatterplot/index.js +5 -0
- package/dist-tsc/shared-spatial-scatterplot/quadtree.d.ts +10 -0
- package/dist-tsc/shared-spatial-scatterplot/quadtree.d.ts.map +1 -0
- package/{dist → dist-tsc}/shared-spatial-scatterplot/quadtree.js +1 -1
- package/package.json +25 -13
- package/src/EmptyMessage.js +11 -0
- package/src/Scatterplot.js +396 -0
- package/src/ScatterplotOptions.js +269 -0
- package/src/ScatterplotTooltipSubscriber.js +38 -0
- package/src/index.js +11 -0
- package/src/shared-spatial-scatterplot/AbstractSpatialOrScatterplot.js +280 -0
- package/src/shared-spatial-scatterplot/ToolMenu.js +143 -0
- package/src/shared-spatial-scatterplot/ToolMenu.test.jsx +26 -0
- package/src/shared-spatial-scatterplot/cursor.js +23 -0
- package/src/shared-spatial-scatterplot/dynamic-opacity.js +58 -0
- package/src/shared-spatial-scatterplot/dynamic-opacity.test.js +33 -0
- package/src/shared-spatial-scatterplot/force-collide-rects.js +189 -0
- package/src/shared-spatial-scatterplot/force-collide-rects.test.js +72 -0
- package/src/shared-spatial-scatterplot/index.js +8 -0
- package/src/shared-spatial-scatterplot/quadtree.js +27 -0
- package/dist/shared-spatial-scatterplot/ToolMenu.test.js +0 -16
- package/dist/shared-spatial-scatterplot/index.js +0 -5
- /package/{dist → dist-tsc}/EmptyMessage.js +0 -0
- /package/{dist → dist-tsc}/ScatterplotTooltipSubscriber.js +0 -0
- /package/{dist → dist-tsc}/shared-spatial-scatterplot/cursor.js +0 -0
- /package/{dist → dist-tsc}/shared-spatial-scatterplot/force-collide-rects.js +0 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { B as BaseDecoder } from "./index-d78d4568.js";
|
|
2
|
+
import "react";
|
|
3
|
+
import "@vitessce/vit-s";
|
|
4
|
+
import "react-dom";
|
|
5
|
+
class WebImageDecoder extends BaseDecoder {
|
|
6
|
+
constructor() {
|
|
7
|
+
super();
|
|
8
|
+
if (typeof createImageBitmap === "undefined") {
|
|
9
|
+
throw new Error("Cannot decode WebImage as `createImageBitmap` is not available");
|
|
10
|
+
} else if (typeof document === "undefined" && typeof OffscreenCanvas === "undefined") {
|
|
11
|
+
throw new Error("Cannot decode WebImage as neither `document` nor `OffscreenCanvas` is not available");
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
async decode(fileDirectory, buffer) {
|
|
15
|
+
const blob = new Blob([buffer]);
|
|
16
|
+
const imageBitmap = await createImageBitmap(blob);
|
|
17
|
+
let canvas;
|
|
18
|
+
if (typeof document !== "undefined") {
|
|
19
|
+
canvas = document.createElement("canvas");
|
|
20
|
+
canvas.width = imageBitmap.width;
|
|
21
|
+
canvas.height = imageBitmap.height;
|
|
22
|
+
} else {
|
|
23
|
+
canvas = new OffscreenCanvas(imageBitmap.width, imageBitmap.height);
|
|
24
|
+
}
|
|
25
|
+
const ctx = canvas.getContext("2d");
|
|
26
|
+
ctx.drawImage(imageBitmap, 0, 0);
|
|
27
|
+
return ctx.getImageData(0, 0, imageBitmap.width, imageBitmap.height).data.buffer;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export {
|
|
31
|
+
WebImageDecoder as default
|
|
32
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EmptyMessage.d.ts","sourceRoot":"","sources":["../src/EmptyMessage.js"],"names":[],"mappings":"AAEA,qEAQC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export default ScatterplotWrapper;
|
|
2
|
+
/**
|
|
3
|
+
* Need this wrapper function here,
|
|
4
|
+
* since we want to pass a forwardRef
|
|
5
|
+
* so that outer components can
|
|
6
|
+
* access the grandchild DeckGL ref,
|
|
7
|
+
* but we are using a class component.
|
|
8
|
+
*/
|
|
9
|
+
declare const ScatterplotWrapper: any;
|
|
10
|
+
//# sourceMappingURL=Scatterplot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Scatterplot.d.ts","sourceRoot":"","sources":["../src/Scatterplot.js"],"names":[],"mappings":";AA6XA;;;;;;GAMG;AACH,sCAKG"}
|
|
@@ -4,7 +4,7 @@ import React, { forwardRef } from 'react';
|
|
|
4
4
|
import { forceSimulation } from 'd3-force';
|
|
5
5
|
import { deck, getSelectionLayers, ScaledExpressionExtension, SelectionExtension, } from '@vitessce/gl';
|
|
6
6
|
import { getDefaultColor } from '@vitessce/utils';
|
|
7
|
-
import { AbstractSpatialOrScatterplot, createQuadTree, forceCollideRects, getOnHoverCallback, } from './shared-spatial-scatterplot';
|
|
7
|
+
import { AbstractSpatialOrScatterplot, createQuadTree, forceCollideRects, getOnHoverCallback, } from './shared-spatial-scatterplot/index.js';
|
|
8
8
|
const CELLS_LAYER_ID = 'scatterplot';
|
|
9
9
|
const LABEL_FONT_FAMILY = "-apple-system, 'Helvetica Neue', Arial, sans-serif";
|
|
10
10
|
const NUM_FORCE_SIMULATION_TICKS = 100;
|
|
@@ -58,8 +58,10 @@ const getPosition = (object, { index, data, target }) => {
|
|
|
58
58
|
* @param {function} props.setCellHighlight
|
|
59
59
|
* @param {function} props.updateViewInfo
|
|
60
60
|
* @param {function} props.onToolChange Callback for tool changes
|
|
61
|
-
* (lasso/pan
|
|
61
|
+
* (lasso/pan selection tools).
|
|
62
62
|
* @param {function} props.onCellClick Getter function for cell layer onClick.
|
|
63
|
+
* @param {object} props.originalViewState A viewState object to pass to
|
|
64
|
+
* setViewState upon clicking the recenter button.
|
|
63
65
|
*/
|
|
64
66
|
class Scatterplot extends AbstractSpatialOrScatterplot {
|
|
65
67
|
constructor(props) {
|
|
@@ -270,6 +272,7 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
|
|
|
270
272
|
'obsEmbeddingIndex', 'obsEmbedding', 'cellFilter', 'cellSelection', 'cellColors',
|
|
271
273
|
'cellRadius', 'cellOpacity', 'cellRadiusMode', 'geneExpressionColormap',
|
|
272
274
|
'geneExpressionColormapRange', 'geneSelection', 'cellColorEncoding',
|
|
275
|
+
'getExpressionValue',
|
|
273
276
|
].some(shallowDiff)) {
|
|
274
277
|
// Cells layer props changed.
|
|
275
278
|
this.onUpdateCellsLayer();
|
|
@@ -292,6 +295,12 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
|
|
|
292
295
|
this.forceUpdate();
|
|
293
296
|
}
|
|
294
297
|
}
|
|
298
|
+
recenter() {
|
|
299
|
+
const { originalViewState, setViewState } = this.props;
|
|
300
|
+
if (Array.isArray(originalViewState?.target) && typeof originalViewState?.zoom === 'number') {
|
|
301
|
+
setViewState(originalViewState);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
295
304
|
}
|
|
296
305
|
/**
|
|
297
306
|
* Need this wrapper function here,
|
|
@@ -301,4 +310,5 @@ class Scatterplot extends AbstractSpatialOrScatterplot {
|
|
|
301
310
|
* but we are using a class component.
|
|
302
311
|
*/
|
|
303
312
|
const ScatterplotWrapper = forwardRef((props, deckRef) => (_jsx(Scatterplot, { ...props, deckRef: deckRef })));
|
|
313
|
+
ScatterplotWrapper.displayName = 'ScatterplotWrapper';
|
|
304
314
|
export default ScatterplotWrapper;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ScatterplotOptions.d.ts","sourceRoot":"","sources":["../src/ScatterplotOptions.js"],"names":[],"mappings":"AASA,oEAmQC"}
|
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import React, { useCallback } from 'react';
|
|
3
|
-
import debounce from 'lodash
|
|
4
|
-
import Checkbox from '@material-ui/core
|
|
5
|
-
import Slider from '@material-ui/core/Slider';
|
|
6
|
-
import TableCell from '@material-ui/core/TableCell';
|
|
7
|
-
import TableRow from '@material-ui/core/TableRow';
|
|
3
|
+
import { debounce } from 'lodash-es';
|
|
4
|
+
import { Checkbox, Slider, TableCell, TableRow } from '@material-ui/core';
|
|
8
5
|
import { capitalize } from '@vitessce/utils';
|
|
9
6
|
import { usePlotOptionsStyles, CellColorEncodingOption, OptionsContainer, OptionSelect, } from '@vitessce/vit-s';
|
|
10
7
|
import { GLSL_COLORMAPS } from '@vitessce/gl';
|
|
11
8
|
export default function ScatterplotOptions(props) {
|
|
12
|
-
const { children, observationsLabel, cellRadius, setCellRadius, cellRadiusMode, setCellRadiusMode, cellOpacity, setCellOpacity, cellOpacityMode, setCellOpacityMode, cellSetLabelsVisible, setCellSetLabelsVisible, cellSetLabelSize, setCellSetLabelSize, cellSetPolygonsVisible, setCellSetPolygonsVisible, cellColorEncoding, setCellColorEncoding, geneExpressionColormap, setGeneExpressionColormap, geneExpressionColormapRange, setGeneExpressionColormapRange, } = props;
|
|
9
|
+
const { children, observationsLabel, cellRadius, setCellRadius, cellRadiusMode, setCellRadiusMode, cellOpacity, setCellOpacity, cellOpacityMode, setCellOpacityMode, cellSetLabelsVisible, setCellSetLabelsVisible, tooltipsVisible, setTooltipsVisible, cellSetLabelSize, setCellSetLabelSize, cellSetPolygonsVisible, setCellSetPolygonsVisible, cellColorEncoding, setCellColorEncoding, geneExpressionColormap, setGeneExpressionColormap, geneExpressionColormapRange, setGeneExpressionColormapRange, } = props;
|
|
13
10
|
const observationsLabelNice = capitalize(observationsLabel);
|
|
14
11
|
const classes = usePlotOptionsStyles();
|
|
15
12
|
function handleCellRadiusModeChange(event) {
|
|
@@ -27,6 +24,9 @@ export default function ScatterplotOptions(props) {
|
|
|
27
24
|
function handleLabelVisibilityChange(event) {
|
|
28
25
|
setCellSetLabelsVisible(event.target.checked);
|
|
29
26
|
}
|
|
27
|
+
function handleTooltipsVisibilityChange(event) {
|
|
28
|
+
setTooltipsVisible(event.target.checked);
|
|
29
|
+
}
|
|
30
30
|
function handleLabelSizeChange(event, value) {
|
|
31
31
|
setCellSetLabelSize(value);
|
|
32
32
|
}
|
|
@@ -40,7 +40,13 @@ export default function ScatterplotOptions(props) {
|
|
|
40
40
|
setGeneExpressionColormapRange(value);
|
|
41
41
|
}
|
|
42
42
|
const handleColormapRangeChangeDebounced = useCallback(debounce(handleColormapRangeChange, 5, { trailing: true }), [handleColormapRangeChange]);
|
|
43
|
-
return (_jsxs(OptionsContainer, { children: [children, _jsx(CellColorEncodingOption, { observationsLabel: observationsLabel, cellColorEncoding: cellColorEncoding, setCellColorEncoding: setCellColorEncoding }), _jsxs(TableRow, { children: [_jsxs(TableCell, { className: classes.labelCell, children: [observationsLabelNice, " Set Labels Visible"] }), _jsx(TableCell, { className: classes.inputCell, children: _jsx(Checkbox, { className: classes.checkbox, checked: cellSetLabelsVisible, onChange: handleLabelVisibilityChange, name: "scatterplot-option-cell-set-labels", color: "default" }) })] }), _jsxs(TableRow, { children: [
|
|
43
|
+
return (_jsxs(OptionsContainer, { children: [children, _jsx(CellColorEncodingOption, { observationsLabel: observationsLabel, cellColorEncoding: cellColorEncoding, setCellColorEncoding: setCellColorEncoding }), _jsxs(TableRow, { children: [_jsxs(TableCell, { className: classes.labelCell, children: [observationsLabelNice, " Set Labels Visible"] }), _jsx(TableCell, { className: classes.inputCell, children: _jsx(Checkbox, { className: classes.checkbox, checked: cellSetLabelsVisible, onChange: handleLabelVisibilityChange, name: "scatterplot-option-cell-set-labels", color: "default" }) })] }), _jsxs(TableRow, { children: [_jsx(TableCell, { className: classes.labelCell, children: "Tooltips Visible" }), _jsx(TableCell, { className: classes.inputCell, children: _jsx(Checkbox, { className: classes.checkbox,
|
|
44
|
+
/**
|
|
45
|
+
* We have to use "checked" here, not "value".
|
|
46
|
+
* The checkbox state is not persisting with value.
|
|
47
|
+
* For reference, https://v4.mui.com/api/checkbox/
|
|
48
|
+
*/
|
|
49
|
+
checked: tooltipsVisible, onChange: handleTooltipsVisibilityChange, name: "scatterplot-option-toltip-visibility", color: "default" }) })] }), _jsxs(TableRow, { children: [_jsxs(TableCell, { className: classes.labelCell, children: [observationsLabelNice, " Set Label Size"] }), _jsx(TableCell, { className: classes.inputCell, children: _jsx(Slider, { disabled: !cellSetLabelsVisible, classes: { root: classes.slider, valueLabel: classes.sliderValueLabel }, value: cellSetLabelSize, onChange: handleLabelSizeChange, "aria-labelledby": "cell-set-label-size-slider", valueLabelDisplay: "auto", step: 1, min: 8, max: 36 }) })] }), _jsxs(TableRow, { children: [_jsxs(TableCell, { className: classes.labelCell, children: [observationsLabelNice, " Set Polygons Visible"] }), _jsx(TableCell, { className: classes.inputCell, children: _jsx(Checkbox, { className: classes.checkbox, checked: cellSetPolygonsVisible, onChange: handlePolygonVisibilityChange, name: "scatterplot-option-cell-set-polygons", color: "default" }) })] }), _jsxs(TableRow, { children: [_jsxs(TableCell, { className: classes.labelCell, htmlFor: "cell-radius-mode-select", children: [observationsLabelNice, " Radius Mode"] }), _jsx(TableCell, { className: classes.inputCell, children: _jsxs(OptionSelect, { className: classes.select, value: cellRadiusMode, onChange: handleCellRadiusModeChange, inputProps: {
|
|
44
50
|
id: 'cell-radius-mode-select',
|
|
45
51
|
}, children: [_jsx("option", { value: "auto", children: "Auto" }), _jsx("option", { value: "manual", children: "Manual" })] }) })] }), _jsxs(TableRow, { children: [_jsxs(TableCell, { className: classes.labelCell, children: [observationsLabelNice, " Radius"] }), _jsx(TableCell, { className: classes.inputCell, children: _jsx(Slider, { disabled: cellRadiusMode !== 'manual', classes: { root: classes.slider, valueLabel: classes.sliderValueLabel }, value: cellRadius, onChange: handleRadiusChange, "aria-labelledby": "cell-radius-slider", valueLabelDisplay: "auto", step: 0.01, min: 0.01, max: 10 }) })] }), _jsxs(TableRow, { children: [_jsxs(TableCell, { className: classes.labelCell, htmlFor: "cell-opacity-mode-select", children: [observationsLabelNice, " Opacity Mode"] }), _jsx(TableCell, { className: classes.inputCell, children: _jsxs(OptionSelect, { className: classes.select, value: cellOpacityMode, onChange: handleCellOpacityModeChange, inputProps: {
|
|
46
52
|
id: 'cell-opacity-mode-select',
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ScatterplotTooltipSubscriber.d.ts","sourceRoot":"","sources":["../src/ScatterplotTooltipSubscriber.js"],"names":[],"mappings":"AAIA,qFAiCC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { default as Scatterplot } from "./Scatterplot.js";
|
|
2
|
+
export { default as ScatterplotOptions } from "./ScatterplotOptions.js";
|
|
3
|
+
export { default as ScatterplotTooltipSubscriber } from "./ScatterplotTooltipSubscriber.js";
|
|
4
|
+
export { default as EmptyMessage } from "./EmptyMessage.js";
|
|
5
|
+
export { getPointSizeDevicePixels, getPointOpacity, getOnHoverCallback, createQuadTree, AbstractSpatialOrScatterplot } from "./shared-spatial-scatterplot/index.js";
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { default as Scatterplot } from './Scatterplot.js';
|
|
2
|
+
export { default as ScatterplotOptions } from './ScatterplotOptions.js';
|
|
3
|
+
export { default as ScatterplotTooltipSubscriber } from './ScatterplotTooltipSubscriber.js';
|
|
4
|
+
export { default as EmptyMessage } from './EmptyMessage.js';
|
|
5
|
+
export { getPointSizeDevicePixels, getPointOpacity, getOnHoverCallback, createQuadTree, AbstractSpatialOrScatterplot, } from './shared-spatial-scatterplot/index.js';
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Abstract class component intended to be inherited by
|
|
3
|
+
* the Spatial and Scatterplot class components.
|
|
4
|
+
* Contains a common constructor, common DeckGL callbacks,
|
|
5
|
+
* and common render function.
|
|
6
|
+
*/
|
|
7
|
+
export default class AbstractSpatialOrScatterplot {
|
|
8
|
+
constructor(props: any);
|
|
9
|
+
state: {
|
|
10
|
+
gl: null;
|
|
11
|
+
tool: null;
|
|
12
|
+
};
|
|
13
|
+
viewport: object | null;
|
|
14
|
+
/**
|
|
15
|
+
* Called by DeckGL upon a viewState change,
|
|
16
|
+
* for example zoom or pan interaction.
|
|
17
|
+
* Emit the new viewState to the `setViewState`
|
|
18
|
+
* handler prop.
|
|
19
|
+
* @param {object} params
|
|
20
|
+
* @param {object} params.viewState The next deck.gl viewState.
|
|
21
|
+
*/
|
|
22
|
+
onViewStateChange({ viewState: nextViewState }: {
|
|
23
|
+
viewState: object;
|
|
24
|
+
}): void;
|
|
25
|
+
/**
|
|
26
|
+
* Called by DeckGL upon viewport
|
|
27
|
+
* initialization.
|
|
28
|
+
* @param {object} viewState
|
|
29
|
+
* @param {object} viewState.viewport
|
|
30
|
+
*/
|
|
31
|
+
onInitializeViewInfo({ viewport }: {
|
|
32
|
+
viewport: object;
|
|
33
|
+
}): void;
|
|
34
|
+
/**
|
|
35
|
+
* Called by DeckGL upon initialization,
|
|
36
|
+
* helps to understand when to pass layers
|
|
37
|
+
* to the DeckGL component.
|
|
38
|
+
* @param {object} gl The WebGL context object.
|
|
39
|
+
*/
|
|
40
|
+
onWebGLInitialized(gl: object): void;
|
|
41
|
+
/**
|
|
42
|
+
* Called by the ToolMenu buttons.
|
|
43
|
+
* Emits the new tool value to the
|
|
44
|
+
* `onToolChange` prop.
|
|
45
|
+
* @param {string} tool Name of tool.
|
|
46
|
+
*/
|
|
47
|
+
onToolChange(tool: string): void;
|
|
48
|
+
onHover(info: any): null | undefined;
|
|
49
|
+
/** Intended to be overridden by descendants.
|
|
50
|
+
* Resets the view type to its original position.
|
|
51
|
+
*/
|
|
52
|
+
recenter(): void;
|
|
53
|
+
/**
|
|
54
|
+
* Create the DeckGL layers.
|
|
55
|
+
* @returns {object[]} Array of
|
|
56
|
+
* DeckGL layer objects.
|
|
57
|
+
* Intended to be overriden by descendants.
|
|
58
|
+
*/
|
|
59
|
+
getLayers(): object[];
|
|
60
|
+
/**
|
|
61
|
+
* Emits a function to project from the
|
|
62
|
+
* cell ID space to the scatterplot or
|
|
63
|
+
* spatial coordinate space, via the
|
|
64
|
+
* `updateViewInfo` prop.
|
|
65
|
+
*/
|
|
66
|
+
viewInfoDidUpdate(obsIndex: any, obsLocations: any, makeGetObsCoords: any): void;
|
|
67
|
+
/**
|
|
68
|
+
* Intended to be overridden by descendants.
|
|
69
|
+
*/
|
|
70
|
+
componentDidUpdate(): void;
|
|
71
|
+
/**
|
|
72
|
+
* Intended to be overridden by descendants.
|
|
73
|
+
* @returns {boolean} Whether or not any layers are 3D.
|
|
74
|
+
*/
|
|
75
|
+
use3d(): boolean;
|
|
76
|
+
/**
|
|
77
|
+
* A common render function for both Spatial
|
|
78
|
+
* and Scatterplot components.
|
|
79
|
+
*/
|
|
80
|
+
render(): JSX.Element;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=AbstractSpatialOrScatterplot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AbstractSpatialOrScatterplot.d.ts","sourceRoot":"","sources":["../../src/shared-spatial-scatterplot/AbstractSpatialOrScatterplot.js"],"names":[],"mappings":"AAKA;;;;;GAKG;AACH;IACE,wBAeC;IAZC;;;MAGC;IAED,wBAAoB;IAStB;;;;;;;OAOG;IACH;QAF0B,SAAS,EAAxB,MAAM;aAYhB;IAED;;;;;OAKG;IACH;QAF6B,QAAQ,EAA1B,MAAM;aAIhB;IAED;;;;;OAKG;IACH,uBAFW,MAAM,QAIhB;IAED;;;;;OAKG;IACH,mBAFW,MAAM,QAQhB;IAcD,qCAkEC;IAuCD;;MAEE;IAEF,iBAAa;IAzHb;;;;;OAKG;IAEH,aALa,MAAM,EAAE,CAOpB;IAuED;;;;;OAKG;IACH,iFAqBC;IAED;;OAEG;IAEH,2BAEC;IAQD;;;OAGG;IAEH,SAHa,OAAO,CAKnB;IAED;;;OAGG;IACH,sBA2DC;CACF"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import React, { PureComponent } from 'react';
|
|
3
3
|
import { deck, DEFAULT_GL_OPTIONS } from '@vitessce/gl';
|
|
4
|
-
import ToolMenu from './ToolMenu';
|
|
5
|
-
import { getCursor, getCursorWithTool } from './cursor';
|
|
4
|
+
import ToolMenu from './ToolMenu.js';
|
|
5
|
+
import { getCursor, getCursorWithTool } from './cursor.js';
|
|
6
6
|
/**
|
|
7
7
|
* Abstract class component intended to be inherited by
|
|
8
8
|
* the Spatial and Scatterplot class components.
|
|
@@ -22,6 +22,7 @@ export default class AbstractSpatialOrScatterplot extends PureComponent {
|
|
|
22
22
|
this.onWebGLInitialized = this.onWebGLInitialized.bind(this);
|
|
23
23
|
this.onToolChange = this.onToolChange.bind(this);
|
|
24
24
|
this.onHover = this.onHover.bind(this);
|
|
25
|
+
this.recenter = this.recenter.bind(this);
|
|
25
26
|
}
|
|
26
27
|
/**
|
|
27
28
|
* Called by DeckGL upon a viewState change,
|
|
@@ -171,6 +172,11 @@ export default class AbstractSpatialOrScatterplot extends PureComponent {
|
|
|
171
172
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
172
173
|
componentDidUpdate() {
|
|
173
174
|
}
|
|
175
|
+
/** Intended to be overridden by descendants.
|
|
176
|
+
* Resets the view type to its original position.
|
|
177
|
+
*/
|
|
178
|
+
// eslint-disable-next-line class-methods-use-this
|
|
179
|
+
recenter() { }
|
|
174
180
|
/**
|
|
175
181
|
* Intended to be overridden by descendants.
|
|
176
182
|
* @returns {boolean} Whether or not any layers are 3D.
|
|
@@ -198,9 +204,8 @@ export default class AbstractSpatialOrScatterplot extends PureComponent {
|
|
|
198
204
|
|| this.obsLocationsData?.shape?.[1] < 100000));
|
|
199
205
|
return (_jsxs(_Fragment, { children: [_jsx(ToolMenu, { activeTool: tool, setActiveTool: this.onToolChange, visibleTools: {
|
|
200
206
|
pan: showPanTool && !hideTools,
|
|
201
|
-
selectRectangle: showCellSelectionTools && !hideTools,
|
|
202
207
|
selectLasso: showCellSelectionTools && !hideTools,
|
|
203
|
-
} }), _jsx(deck.DeckGL, { id: `deckgl-overlay-${uuid}`, ref: deckRef, views: [
|
|
208
|
+
}, recenterOnClick: this.recenter }), _jsx(deck.DeckGL, { id: `deckgl-overlay-${uuid}`, ref: deckRef, views: [
|
|
204
209
|
use3d
|
|
205
210
|
? new deck.OrbitView({ id: 'orbit', controller: true, orbitAxis: 'Y' })
|
|
206
211
|
: new deck.OrthographicView({
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToolMenu.d.ts","sourceRoot":"","sources":["../../src/shared-spatial-scatterplot/ToolMenu.js"],"names":[],"mappings":"AAsEA,kDAeC;AAED,oDAeC;AAED,0DAsCC"}
|
|
@@ -2,9 +2,17 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import clsx from 'clsx';
|
|
4
4
|
import { SELECTION_TYPE } from '@vitessce/gl';
|
|
5
|
-
import { PointerIconSVG,
|
|
5
|
+
import { PointerIconSVG, SelectLassoIconSVG } from '@vitessce/icons';
|
|
6
6
|
import { makeStyles } from '@material-ui/core';
|
|
7
|
+
import { CenterFocusStrong } from '@material-ui/icons';
|
|
7
8
|
const useStyles = makeStyles(() => ({
|
|
9
|
+
button: {
|
|
10
|
+
display: 'inline-flex',
|
|
11
|
+
'&:active': {
|
|
12
|
+
opacity: '.65',
|
|
13
|
+
extend: 'iconClicked',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
8
16
|
tool: {
|
|
9
17
|
position: 'absolute',
|
|
10
18
|
display: 'inline',
|
|
@@ -15,7 +23,12 @@ const useStyles = makeStyles(() => ({
|
|
|
15
23
|
opacity: '.90',
|
|
16
24
|
},
|
|
17
25
|
},
|
|
18
|
-
|
|
26
|
+
iconClicked: {
|
|
27
|
+
// Styles for the clicked state
|
|
28
|
+
boxShadow: 'none',
|
|
29
|
+
transform: 'scale(0.98)', // make the button slightly smaller
|
|
30
|
+
},
|
|
31
|
+
icon: {
|
|
19
32
|
// btn btn-outline-secondary mr-2 icon
|
|
20
33
|
padding: '0',
|
|
21
34
|
height: '2em',
|
|
@@ -36,9 +49,13 @@ const useStyles = makeStyles(() => ({
|
|
|
36
49
|
marginRight: '8px',
|
|
37
50
|
'& > svg': {
|
|
38
51
|
verticalAlign: 'middle',
|
|
52
|
+
color: 'black',
|
|
53
|
+
},
|
|
54
|
+
'&:active': {
|
|
55
|
+
extend: 'iconClicked',
|
|
39
56
|
},
|
|
40
57
|
},
|
|
41
|
-
|
|
58
|
+
toolActive: {
|
|
42
59
|
// active
|
|
43
60
|
color: '#fff',
|
|
44
61
|
backgroundColor: '#6c757d',
|
|
@@ -46,13 +63,21 @@ const useStyles = makeStyles(() => ({
|
|
|
46
63
|
boxShadow: '0 0 0 3px rgba(108, 117, 125, 0.5)',
|
|
47
64
|
},
|
|
48
65
|
}));
|
|
49
|
-
export function
|
|
66
|
+
export function IconTool(props) {
|
|
50
67
|
const { alt, onClick, isActive, children, } = props;
|
|
51
68
|
const classes = useStyles();
|
|
52
|
-
return (_jsx("button", { className: clsx(classes.
|
|
69
|
+
return (_jsx("button", { className: clsx(classes.icon, { [classes.toolActive]: isActive }), onClick: onClick, type: "button", title: alt, children: children }));
|
|
70
|
+
}
|
|
71
|
+
export function IconButton(props) {
|
|
72
|
+
const { alt, onClick, children, } = props;
|
|
73
|
+
const classes = useStyles();
|
|
74
|
+
return (_jsx("button", { className: clsx(classes.icon, classes.button), onClick: onClick, type: "button", title: alt, children: children }));
|
|
53
75
|
}
|
|
54
76
|
export default function ToolMenu(props) {
|
|
55
|
-
const { setActiveTool, activeTool, visibleTools = { pan: true,
|
|
77
|
+
const { setActiveTool, activeTool, visibleTools = { pan: true, selectLasso: true }, recenterOnClick = () => { }, } = props;
|
|
56
78
|
const classes = useStyles();
|
|
57
|
-
|
|
79
|
+
const onRecenterButtonCLick = () => {
|
|
80
|
+
recenterOnClick();
|
|
81
|
+
};
|
|
82
|
+
return (_jsxs("div", { className: classes.tool, children: [visibleTools.pan && (_jsx(IconTool, { alt: "pointer tool", onClick: () => setActiveTool(null), isActive: activeTool === null, children: _jsx(PointerIconSVG, {}) })), visibleTools.selectLasso ? (_jsx(IconTool, { alt: "select lasso", onClick: () => setActiveTool(SELECTION_TYPE.POLYGON), isActive: activeTool === SELECTION_TYPE.POLYGON, children: _jsx(SelectLassoIconSVG, {}) })) : null, _jsx(IconButton, { alt: "click to recenter", onClick: () => onRecenterButtonCLick(), children: _jsx(CenterFocusStrong, {}) })] }));
|
|
58
83
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToolMenu.test.d.ts","sourceRoot":"","sources":["../../src/shared-spatial-scatterplot/ToolMenu.test.jsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import '@testing-library/jest-dom';
|
|
3
|
+
import { cleanup, render } from '@testing-library/react';
|
|
4
|
+
import { afterEach, expect } from 'vitest';
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import { IconTool, IconButton } from './ToolMenu.js';
|
|
7
|
+
afterEach(() => {
|
|
8
|
+
cleanup();
|
|
9
|
+
});
|
|
10
|
+
describe('ToolMenu.js', () => {
|
|
11
|
+
describe('<IconTool />', () => {
|
|
12
|
+
it('renders with title attribute', () => {
|
|
13
|
+
const { container } = render(_jsx(IconTool, { isActive: true, alt: "Lasso" }));
|
|
14
|
+
expect(container.querySelectorAll('[title="Lasso"]').length).toEqual(1);
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
describe('<IconButton />', () => {
|
|
18
|
+
it('renders with title attribute', () => {
|
|
19
|
+
const { container } = render(_jsx(IconButton, { alt: "click to recenter" }));
|
|
20
|
+
expect(container.querySelectorAll('[title="click to recenter"]').length).toEqual(1);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export function getOnHoverCallback(obsIndex: any, setObsHighlight: any, setComponentHover: any): (info: any) => void;
|
|
2
|
+
export function getCursorWithTool(): string;
|
|
3
|
+
export function getCursor(interactionState: any): "default" | "grabbing";
|
|
4
|
+
//# sourceMappingURL=cursor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../../src/shared-spatial-scatterplot/cursor.js"],"names":[],"mappings":"AAKA,qHAiBC;AAtBM,4CAA2C;AAC3C,yEAEN"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export function getPointSizeDevicePixels(devicePixelRatio: any, zoom: any, xRange: any, yRange: any, width: any, height: any): any;
|
|
2
|
+
export function getPointOpacity(zoom: any, xRange: any, yRange: any, width: any, height: any, numCells: any, avgFillDensity: any): any;
|
|
3
|
+
//# sourceMappingURL=dynamic-opacity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dynamic-opacity.d.ts","sourceRoot":"","sources":["../../src/shared-spatial-scatterplot/dynamic-opacity.js"],"names":[],"mappings":"AAKA,mIA0BC;AAGD,uIAuBC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { deck } from '@vitessce/gl';
|
|
2
|
-
import clamp from 'lodash
|
|
2
|
+
import { clamp } from 'lodash-es';
|
|
3
3
|
// Reference: https://observablehq.com/@rreusser/selecting-the-right-opacity-for-2d-point-clouds
|
|
4
4
|
// Reference: https://observablehq.com/@bmschmidt/dot-density-election-maps-with-webgl
|
|
5
5
|
export function getPointSizeDevicePixels(devicePixelRatio, zoom, xRange, yRange, width, height) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dynamic-opacity.test.d.ts","sourceRoot":"","sources":["../../src/shared-spatial-scatterplot/dynamic-opacity.test.js"],"names":[],"mappings":""}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getPointSizeDevicePixels, getPointOpacity } from './dynamic-opacity';
|
|
1
|
+
import { getPointSizeDevicePixels, getPointOpacity } from './dynamic-opacity.js';
|
|
2
2
|
describe('dynamic-opacity.js', () => {
|
|
3
3
|
describe('getPointSizeDevicePixels', () => {
|
|
4
4
|
it('calculates point size', () => {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A force function to be used with d3.forceSimulation.
|
|
3
|
+
* This has been adapted for use here, with comments explaining each part.
|
|
4
|
+
* Reference: https://bl.ocks.org/cmgiven/547658968d365bcc324f3e62e175709b
|
|
5
|
+
*/
|
|
6
|
+
export function forceCollideRects(): {
|
|
7
|
+
(): void;
|
|
8
|
+
initialize(v: any): void;
|
|
9
|
+
iterations(...v: any[]): number | any;
|
|
10
|
+
strength(...v: any[]): number | any;
|
|
11
|
+
size(...v: any[]): () => any;
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=force-collide-rects.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"force-collide-rects.d.ts","sourceRoot":"","sources":["../../src/shared-spatial-scatterplot/force-collide-rects.js"],"names":[],"mappings":"AAkBA;;;;GAIG;AACH;;;;;;EAqKC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"force-collide-rects.test.d.ts","sourceRoot":"","sources":["../../src/shared-spatial-scatterplot/force-collide-rects.test.js"],"names":[],"mappings":""}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { forceSimulation } from 'd3-force';
|
|
2
|
-
import { forceCollideRects } from './force-collide-rects';
|
|
2
|
+
import { forceCollideRects } from './force-collide-rects.js';
|
|
3
3
|
describe('force-collide-rects.js', () => {
|
|
4
4
|
describe('forceCollideRects', () => {
|
|
5
5
|
it('can be initialized with a size function', () => {
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { default as AbstractSpatialOrScatterplot } from "./AbstractSpatialOrScatterplot.js";
|
|
2
|
+
export { createQuadTree } from "./quadtree.js";
|
|
3
|
+
export { forceCollideRects } from "./force-collide-rects.js";
|
|
4
|
+
export { getOnHoverCallback } from "./cursor.js";
|
|
5
|
+
export { getPointSizeDevicePixels, getPointOpacity } from "./dynamic-opacity.js";
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/shared-spatial-scatterplot/index.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { default as AbstractSpatialOrScatterplot } from './AbstractSpatialOrScatterplot.js';
|
|
2
|
+
export { createQuadTree } from './quadtree.js';
|
|
3
|
+
export { forceCollideRects } from './force-collide-rects.js';
|
|
4
|
+
export { getOnHoverCallback } from './cursor.js';
|
|
5
|
+
export { getPointSizeDevicePixels, getPointOpacity, } from './dynamic-opacity.js';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create a d3-quadtree object for cells data points.
|
|
3
|
+
* @param {array} cellsEntries Array of [cellId, cell] tuples,
|
|
4
|
+
* resulting from running Object.entries on the cells object.
|
|
5
|
+
* @param {function} getCellCoords Given a cell object, return the
|
|
6
|
+
* spatial/scatterplot coordinates [x, y].
|
|
7
|
+
* @returns {object} Quadtree instance.
|
|
8
|
+
*/
|
|
9
|
+
export function createQuadTree(obsEmbedding: any, getCellCoords: Function): object;
|
|
10
|
+
//# sourceMappingURL=quadtree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quadtree.d.ts","sourceRoot":"","sources":["../../src/shared-spatial-scatterplot/quadtree.js"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,4EAFa,MAAM,CAiBlB"}
|