@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.
Files changed (73) hide show
  1. package/dist/deflate-24a61b7a.js +13 -0
  2. package/dist/index-d78d4568.js +142036 -0
  3. package/dist/index.js +15 -5
  4. package/dist/jpeg-19791032.js +840 -0
  5. package/dist/lerc-867fd2ef.js +2014 -0
  6. package/dist/lzw-40577136.js +128 -0
  7. package/dist/packbits-eab43a40.js +30 -0
  8. package/dist/pako.esm-68f84e2a.js +4022 -0
  9. package/dist/raw-66364181.js +12 -0
  10. package/dist/webimage-0fe27785.js +32 -0
  11. package/dist-tsc/EmptyMessage.d.ts +2 -0
  12. package/dist-tsc/EmptyMessage.d.ts.map +1 -0
  13. package/dist-tsc/Scatterplot.d.ts +10 -0
  14. package/dist-tsc/Scatterplot.d.ts.map +1 -0
  15. package/{dist → dist-tsc}/Scatterplot.js +12 -2
  16. package/dist-tsc/ScatterplotOptions.d.ts +2 -0
  17. package/dist-tsc/ScatterplotOptions.d.ts.map +1 -0
  18. package/{dist → dist-tsc}/ScatterplotOptions.js +13 -7
  19. package/dist-tsc/ScatterplotTooltipSubscriber.d.ts +2 -0
  20. package/dist-tsc/ScatterplotTooltipSubscriber.d.ts.map +1 -0
  21. package/dist-tsc/index.d.ts +6 -0
  22. package/dist-tsc/index.d.ts.map +1 -0
  23. package/dist-tsc/index.js +5 -0
  24. package/dist-tsc/shared-spatial-scatterplot/AbstractSpatialOrScatterplot.d.ts +82 -0
  25. package/dist-tsc/shared-spatial-scatterplot/AbstractSpatialOrScatterplot.d.ts.map +1 -0
  26. package/{dist → dist-tsc}/shared-spatial-scatterplot/AbstractSpatialOrScatterplot.js +9 -4
  27. package/dist-tsc/shared-spatial-scatterplot/ToolMenu.d.ts +4 -0
  28. package/dist-tsc/shared-spatial-scatterplot/ToolMenu.d.ts.map +1 -0
  29. package/{dist → dist-tsc}/shared-spatial-scatterplot/ToolMenu.js +32 -7
  30. package/dist-tsc/shared-spatial-scatterplot/ToolMenu.test.d.ts +2 -0
  31. package/dist-tsc/shared-spatial-scatterplot/ToolMenu.test.d.ts.map +1 -0
  32. package/dist-tsc/shared-spatial-scatterplot/ToolMenu.test.js +23 -0
  33. package/dist-tsc/shared-spatial-scatterplot/cursor.d.ts +4 -0
  34. package/dist-tsc/shared-spatial-scatterplot/cursor.d.ts.map +1 -0
  35. package/dist-tsc/shared-spatial-scatterplot/dynamic-opacity.d.ts +3 -0
  36. package/dist-tsc/shared-spatial-scatterplot/dynamic-opacity.d.ts.map +1 -0
  37. package/{dist → dist-tsc}/shared-spatial-scatterplot/dynamic-opacity.js +1 -1
  38. package/dist-tsc/shared-spatial-scatterplot/dynamic-opacity.test.d.ts +2 -0
  39. package/dist-tsc/shared-spatial-scatterplot/dynamic-opacity.test.d.ts.map +1 -0
  40. package/{dist → dist-tsc}/shared-spatial-scatterplot/dynamic-opacity.test.js +1 -1
  41. package/dist-tsc/shared-spatial-scatterplot/force-collide-rects.d.ts +13 -0
  42. package/dist-tsc/shared-spatial-scatterplot/force-collide-rects.d.ts.map +1 -0
  43. package/dist-tsc/shared-spatial-scatterplot/force-collide-rects.test.d.ts +2 -0
  44. package/dist-tsc/shared-spatial-scatterplot/force-collide-rects.test.d.ts.map +1 -0
  45. package/{dist → dist-tsc}/shared-spatial-scatterplot/force-collide-rects.test.js +1 -1
  46. package/dist-tsc/shared-spatial-scatterplot/index.d.ts +6 -0
  47. package/dist-tsc/shared-spatial-scatterplot/index.d.ts.map +1 -0
  48. package/dist-tsc/shared-spatial-scatterplot/index.js +5 -0
  49. package/dist-tsc/shared-spatial-scatterplot/quadtree.d.ts +10 -0
  50. package/dist-tsc/shared-spatial-scatterplot/quadtree.d.ts.map +1 -0
  51. package/{dist → dist-tsc}/shared-spatial-scatterplot/quadtree.js +1 -1
  52. package/package.json +25 -13
  53. package/src/EmptyMessage.js +11 -0
  54. package/src/Scatterplot.js +396 -0
  55. package/src/ScatterplotOptions.js +269 -0
  56. package/src/ScatterplotTooltipSubscriber.js +38 -0
  57. package/src/index.js +11 -0
  58. package/src/shared-spatial-scatterplot/AbstractSpatialOrScatterplot.js +280 -0
  59. package/src/shared-spatial-scatterplot/ToolMenu.js +143 -0
  60. package/src/shared-spatial-scatterplot/ToolMenu.test.jsx +26 -0
  61. package/src/shared-spatial-scatterplot/cursor.js +23 -0
  62. package/src/shared-spatial-scatterplot/dynamic-opacity.js +58 -0
  63. package/src/shared-spatial-scatterplot/dynamic-opacity.test.js +33 -0
  64. package/src/shared-spatial-scatterplot/force-collide-rects.js +189 -0
  65. package/src/shared-spatial-scatterplot/force-collide-rects.test.js +72 -0
  66. package/src/shared-spatial-scatterplot/index.js +8 -0
  67. package/src/shared-spatial-scatterplot/quadtree.js +27 -0
  68. package/dist/shared-spatial-scatterplot/ToolMenu.test.js +0 -16
  69. package/dist/shared-spatial-scatterplot/index.js +0 -5
  70. /package/{dist → dist-tsc}/EmptyMessage.js +0 -0
  71. /package/{dist → dist-tsc}/ScatterplotTooltipSubscriber.js +0 -0
  72. /package/{dist → dist-tsc}/shared-spatial-scatterplot/cursor.js +0 -0
  73. /package/{dist → dist-tsc}/shared-spatial-scatterplot/force-collide-rects.js +0 -0
@@ -0,0 +1,12 @@
1
+ import { B as BaseDecoder } from "./index-d78d4568.js";
2
+ import "react";
3
+ import "@vitessce/vit-s";
4
+ import "react-dom";
5
+ class RawDecoder extends BaseDecoder {
6
+ decodeBlock(buffer) {
7
+ return buffer;
8
+ }
9
+ }
10
+ export {
11
+ RawDecoder as default
12
+ };
@@ -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,2 @@
1
+ export default function EmptyMessage(props: any): JSX.Element | null;
2
+ //# sourceMappingURL=EmptyMessage.d.ts.map
@@ -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/rectangle selection tools).
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,2 @@
1
+ export default function ScatterplotOptions(props: any): JSX.Element;
2
+ //# sourceMappingURL=ScatterplotOptions.d.ts.map
@@ -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/debounce';
4
- import Checkbox from '@material-ui/core/Checkbox';
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: [_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: {
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,2 @@
1
+ export default function ScatterplotTooltipSubscriber(props: any): JSX.Element | null;
2
+ //# sourceMappingURL=ScatterplotTooltipSubscriber.d.ts.map
@@ -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,4 @@
1
+ export function IconTool(props: any): JSX.Element;
2
+ export function IconButton(props: any): JSX.Element;
3
+ export default function ToolMenu(props: any): JSX.Element;
4
+ //# sourceMappingURL=ToolMenu.d.ts.map
@@ -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, SelectRectangleIconSVG, SelectLassoIconSVG } from '@vitessce/icons';
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
- iconButton: {
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
- iconButtonActive: {
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 IconButton(props) {
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.iconButton, { [classes.iconButtonActive]: isActive }), onClick: onClick, type: "button", title: alt, children: children }));
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, selectRectangle: true, selectLasso: true }, } = props;
77
+ const { setActiveTool, activeTool, visibleTools = { pan: true, selectLasso: true }, recenterOnClick = () => { }, } = props;
56
78
  const classes = useStyles();
57
- return (_jsxs("div", { className: classes.tool, children: [visibleTools.pan && (_jsx(IconButton, { alt: "pointer tool", onClick: () => setActiveTool(null), isActive: activeTool === null, children: _jsx(PointerIconSVG, {}) })), visibleTools.selectRectangle ? (_jsx(IconButton, { alt: "select rectangle", onClick: () => setActiveTool(SELECTION_TYPE.RECTANGLE), isActive: activeTool === SELECTION_TYPE.RECTANGLE, children: _jsx(SelectRectangleIconSVG, {}) })) : null, visibleTools.selectLasso ? (_jsx(IconButton, { alt: "select lasso", onClick: () => setActiveTool(SELECTION_TYPE.POLYGON), isActive: activeTool === SELECTION_TYPE.POLYGON, children: _jsx(SelectLassoIconSVG, {}) })) : null] }));
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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ToolMenu.test.d.ts.map
@@ -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/clamp';
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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=dynamic-opacity.test.d.ts.map
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=force-collide-rects.test.d.ts.map
@@ -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"}
@@ -1,5 +1,5 @@
1
1
  import { quadtree } from 'd3-quadtree';
2
- import range from 'lodash/range';
2
+ import { range } from 'lodash-es';
3
3
  /**
4
4
  * Create a d3-quadtree object for cells data points.
5
5
  * @param {array} cellsEntries Array of [cellId, cell] tuples,