@haniffalab/cherita-react 1.0.0-dev.2025-03-13.bda9e1a6 → 1.0.0-dev.2025-03-24.e68f9e22

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 (95) hide show
  1. package/dist/{components → cjs/components}/full-page/FullPage.js +6 -5
  2. package/dist/{components → cjs/components}/full-page/FullPagePseudospatial.js +6 -5
  3. package/dist/{components → cjs/components}/obs-list/ObsItem.js +50 -46
  4. package/dist/{components → cjs/components}/obs-list/ObsList.js +9 -7
  5. package/dist/{components → cjs/components}/obs-list/ObsToolbar.js +12 -11
  6. package/dist/{components → cjs/components}/offcanvas/index.js +24 -20
  7. package/dist/{components → cjs/components}/pseudospatial/Pseudospatial.js +9 -8
  8. package/dist/{components → cjs/components}/pseudospatial/PseudospatialToolbar.js +4 -3
  9. package/dist/{components → cjs/components}/scatterplot/Scatterplot.js +31 -22
  10. package/dist/{components → cjs/components}/scatterplot/SpatialControls.js +11 -10
  11. package/dist/{components → cjs/components}/scatterplot/Toolbox.js +6 -5
  12. package/dist/{components → cjs/components}/search-bar/SearchBar.js +6 -5
  13. package/dist/{components → cjs/components}/search-bar/SearchResults.js +11 -9
  14. package/dist/{components → cjs/components}/var-list/VarItem.js +32 -27
  15. package/dist/{components → cjs/components}/var-list/VarList.js +21 -12
  16. package/dist/{components → cjs/components}/var-list/VarListToolbar.js +4 -3
  17. package/dist/{components → cjs/components}/var-list/VarSet.js +21 -18
  18. package/dist/{components → cjs/components}/violin/Violin.js +4 -3
  19. package/dist/{context → cjs/context}/DatasetContext.js +11 -9
  20. package/dist/{context → cjs/context}/FilterContext.js +4 -3
  21. package/dist/{context → cjs/context}/ZarrDataContext.js +4 -3
  22. package/dist/{helpers → cjs/helpers}/color-helper.js +12 -11
  23. package/dist/{helpers → cjs/helpers}/map-helper.js +8 -7
  24. package/dist/{helpers → cjs/helpers}/zarr-helper.js +25 -15
  25. package/dist/{utils → cjs/utils}/Histogram.js +12 -8
  26. package/dist/{utils → cjs/utils}/ImageViewer.js +6 -5
  27. package/dist/{utils → cjs/utils}/Legend.js +8 -7
  28. package/dist/{utils → cjs/utils}/LoadingIndicators.js +5 -4
  29. package/dist/{utils → cjs/utils}/VirtualizedList.js +10 -9
  30. package/dist/{utils → cjs/utils}/requests.js +33 -21
  31. package/dist/{utils → cjs/utils}/string.js +9 -4
  32. package/dist/{utils → cjs/utils}/zarrData.js +12 -4
  33. package/dist/esm/components/dotplot/Dotplot.js +135 -0
  34. package/dist/esm/components/dotplot/DotplotControls.js +148 -0
  35. package/dist/esm/components/full-page/FullPage.js +134 -0
  36. package/dist/esm/components/full-page/FullPagePseudospatial.js +151 -0
  37. package/dist/esm/components/heatmap/Heatmap.js +105 -0
  38. package/dist/esm/components/heatmap/HeatmapControls.js +23 -0
  39. package/dist/esm/components/matrixplot/Matrixplot.js +107 -0
  40. package/dist/esm/components/matrixplot/MatrixplotControls.js +38 -0
  41. package/dist/esm/components/obs-list/ObsItem.js +477 -0
  42. package/dist/esm/components/obs-list/ObsList.js +256 -0
  43. package/dist/esm/components/obs-list/ObsToolbar.js +58 -0
  44. package/dist/esm/components/obsm-list/ObsmList.js +72 -0
  45. package/dist/esm/components/offcanvas/index.js +67 -0
  46. package/dist/esm/components/pseudospatial/Pseudospatial.js +228 -0
  47. package/dist/esm/components/pseudospatial/PseudospatialToolbar.js +123 -0
  48. package/dist/esm/components/scatterplot/Scatterplot.js +394 -0
  49. package/dist/esm/components/scatterplot/ScatterplotControls.js +71 -0
  50. package/dist/esm/components/scatterplot/SpatialControls.js +140 -0
  51. package/dist/esm/components/scatterplot/Toolbox.js +25 -0
  52. package/dist/esm/components/search-bar/SearchBar.js +74 -0
  53. package/dist/esm/components/search-bar/SearchResults.js +139 -0
  54. package/dist/esm/components/var-list/VarItem.js +250 -0
  55. package/dist/esm/components/var-list/VarList.js +272 -0
  56. package/dist/esm/components/var-list/VarListToolbar.js +84 -0
  57. package/dist/esm/components/var-list/VarSet.js +193 -0
  58. package/dist/esm/components/violin/Violin.js +141 -0
  59. package/dist/esm/components/violin/ViolinControls.js +24 -0
  60. package/dist/esm/constants/colorscales.js +22 -0
  61. package/dist/esm/constants/constants.js +84 -0
  62. package/dist/esm/context/DatasetContext.js +572 -0
  63. package/dist/esm/context/FilterContext.js +48 -0
  64. package/dist/esm/context/ZarrDataContext.js +26 -0
  65. package/dist/esm/helpers/color-helper.js +66 -0
  66. package/dist/esm/helpers/map-helper.js +53 -0
  67. package/dist/esm/helpers/zarr-helper.js +129 -0
  68. package/dist/esm/index.js +22 -0
  69. package/dist/esm/utils/Filter.js +147 -0
  70. package/dist/esm/utils/Histogram.js +44 -0
  71. package/dist/esm/utils/ImageViewer.js +27 -0
  72. package/dist/esm/utils/Legend.js +58 -0
  73. package/dist/esm/utils/LoadingIndicators.js +22 -0
  74. package/dist/esm/utils/VirtualizedList.js +55 -0
  75. package/dist/esm/utils/errors.js +47 -0
  76. package/dist/esm/utils/requests.js +116 -0
  77. package/dist/esm/utils/search.js +39 -0
  78. package/dist/esm/utils/string.js +59 -0
  79. package/dist/esm/utils/zarrData.js +102 -0
  80. package/package.json +16 -5
  81. /package/dist/{components → cjs/components}/dotplot/Dotplot.js +0 -0
  82. /package/dist/{components → cjs/components}/dotplot/DotplotControls.js +0 -0
  83. /package/dist/{components → cjs/components}/heatmap/Heatmap.js +0 -0
  84. /package/dist/{components → cjs/components}/heatmap/HeatmapControls.js +0 -0
  85. /package/dist/{components → cjs/components}/matrixplot/Matrixplot.js +0 -0
  86. /package/dist/{components → cjs/components}/matrixplot/MatrixplotControls.js +0 -0
  87. /package/dist/{components → cjs/components}/obsm-list/ObsmList.js +0 -0
  88. /package/dist/{components → cjs/components}/scatterplot/ScatterplotControls.js +0 -0
  89. /package/dist/{components → cjs/components}/violin/ViolinControls.js +0 -0
  90. /package/dist/{constants → cjs/constants}/colorscales.js +0 -0
  91. /package/dist/{constants → cjs/constants}/constants.js +0 -0
  92. /package/dist/{index.js → cjs/index.js} +0 -0
  93. /package/dist/{utils → cjs/utils}/Filter.js +0 -0
  94. /package/dist/{utils → cjs/utils}/errors.js +0 -0
  95. /package/dist/{utils → cjs/utils}/search.js +0 -0
@@ -0,0 +1,105 @@
1
+ import React, { useCallback, useEffect, useRef, useState } from "react";
2
+ import _ from "lodash";
3
+ import { Alert } from "react-bootstrap";
4
+ import Plot from "react-plotly.js";
5
+ import { useDataset } from "../../context/DatasetContext";
6
+ import { useFilteredData } from "../../context/FilterContext";
7
+ import { LoadingSpinner } from "../../utils/LoadingIndicators";
8
+ import { useDebouncedFetch } from "../../utils/requests";
9
+ export function Heatmap() {
10
+ const ENDPOINT = "heatmap";
11
+ const dataset = useDataset();
12
+ const {
13
+ obsIndices,
14
+ isSliced
15
+ } = useFilteredData();
16
+ const colorscale = useRef(dataset.controls.colorScale);
17
+ const [data, setData] = useState([]);
18
+ const [layout, setLayout] = useState({});
19
+ const [hasSelections, setHasSelections] = useState(false);
20
+ const [params, setParams] = useState({
21
+ url: dataset.url,
22
+ obsCol: dataset.selectedObs,
23
+ obsValues: !dataset.selectedObs?.omit.length ? null : _.difference(_.values(dataset.selectedObs?.codes), dataset.selectedObs?.omit).map(c => dataset.selectedObs?.codesMap[c]),
24
+ varKeys: dataset.selectedMultiVar.map(i => i.isSet ? {
25
+ name: i.name,
26
+ indices: i.vars.map(v => v.index)
27
+ } : i.index),
28
+ obsIndices: isSliced ? [...(obsIndices || [])] : null,
29
+ varNamesCol: dataset.varNamesCol
30
+ });
31
+ useEffect(() => {
32
+ if (dataset.selectedObs && dataset.selectedMultiVar.length) {
33
+ setHasSelections(true);
34
+ } else {
35
+ setHasSelections(false);
36
+ }
37
+ setParams(p => {
38
+ return {
39
+ ...p,
40
+ url: dataset.url,
41
+ obsCol: dataset.selectedObs,
42
+ obsValues: !dataset.selectedObs?.omit.length ? null : _.difference(_.values(dataset.selectedObs?.codes), dataset.selectedObs?.omit).map(c => dataset.selectedObs?.codesMap[c]),
43
+ varKeys: dataset.selectedMultiVar.map(i => i.isSet ? {
44
+ name: i.name,
45
+ indices: i.vars.map(v => v.index)
46
+ } : i.index),
47
+ obsIndices: isSliced ? [...(obsIndices || [])] : null,
48
+ varNamesCol: dataset.varNamesCol
49
+ };
50
+ });
51
+ }, [dataset.selectedMultiVar, dataset.selectedObs, dataset.url, dataset.varNamesCol, obsIndices, isSliced]);
52
+ const updateColorscale = useCallback(colorscale => {
53
+ setLayout(l => {
54
+ return {
55
+ ...l,
56
+ coloraxis: {
57
+ ...l.coloraxis,
58
+ colorscale: colorscale
59
+ }
60
+ };
61
+ });
62
+ }, []);
63
+ const {
64
+ fetchedData,
65
+ isPending,
66
+ serverError
67
+ } = useDebouncedFetch(ENDPOINT, params, 500, {
68
+ enabled: !!params.obsCol && !!params.varKeys.length
69
+ });
70
+ useEffect(() => {
71
+ if (hasSelections && !isPending && !serverError) {
72
+ setData(fetchedData.data);
73
+ setLayout(fetchedData.layout);
74
+ updateColorscale(colorscale.current);
75
+ }
76
+ }, [fetchedData, hasSelections, isPending, serverError, updateColorscale]);
77
+ useEffect(() => {
78
+ colorscale.current = dataset.controls.colorScale;
79
+ updateColorscale(colorscale.current);
80
+ }, [dataset.controls.colorScale, updateColorscale]);
81
+ if (!serverError) {
82
+ if (hasSelections) {
83
+ return /*#__PURE__*/React.createElement("div", {
84
+ className: "cherita-heatmap position-relative"
85
+ }, isPending && /*#__PURE__*/React.createElement(LoadingSpinner, null), /*#__PURE__*/React.createElement(Plot, {
86
+ data: data,
87
+ layout: layout,
88
+ useResizeHandler: true,
89
+ style: {
90
+ maxWidth: "100%",
91
+ maxHeight: "100%"
92
+ }
93
+ }));
94
+ }
95
+ return /*#__PURE__*/React.createElement("div", {
96
+ className: "cherita-heatmap"
97
+ }, /*#__PURE__*/React.createElement(Alert, {
98
+ variant: "light"
99
+ }, "Select features and a category"));
100
+ } else {
101
+ return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Alert, {
102
+ variant: "danger"
103
+ }, serverError.message));
104
+ }
105
+ }
@@ -0,0 +1,23 @@
1
+ import React from "react";
2
+ import _ from "lodash";
3
+ import { Dropdown } from "react-bootstrap";
4
+ import { COLORSCALES } from "../../constants/colorscales";
5
+ import { useDataset, useDatasetDispatch } from "../../context/DatasetContext";
6
+ export function HeatmapControls() {
7
+ const dataset = useDataset();
8
+ const dispatch = useDatasetDispatch();
9
+ const colormapList = _.keys(COLORSCALES).map(key => /*#__PURE__*/React.createElement(Dropdown.Item, {
10
+ key: key,
11
+ active: dataset.controls.colorScale === key,
12
+ onClick: () => {
13
+ dispatch({
14
+ type: "set.controls.colorScale",
15
+ colorScale: key
16
+ });
17
+ }
18
+ }, key));
19
+ return /*#__PURE__*/React.createElement(Dropdown, null, /*#__PURE__*/React.createElement(Dropdown.Toggle, {
20
+ id: "dropdownColorscale",
21
+ variant: "light"
22
+ }, dataset.controls.colorScale), /*#__PURE__*/React.createElement(Dropdown.Menu, null, colormapList));
23
+ }
@@ -0,0 +1,107 @@
1
+ import React, { useCallback, useEffect, useRef, useState } from "react";
2
+ import _ from "lodash";
3
+ import { Alert } from "react-bootstrap";
4
+ import Plot from "react-plotly.js";
5
+ import { useDataset } from "../../context/DatasetContext";
6
+ import { useFilteredData } from "../../context/FilterContext";
7
+ import { LoadingSpinner } from "../../utils/LoadingIndicators";
8
+ import { useDebouncedFetch } from "../../utils/requests";
9
+ export function Matrixplot() {
10
+ const ENDPOINT = "matrixplot";
11
+ const dataset = useDataset();
12
+ const {
13
+ obsIndices,
14
+ isSliced
15
+ } = useFilteredData();
16
+ const colorscale = useRef(dataset.controls.colorScale);
17
+ const [data, setData] = useState([]);
18
+ const [layout, setLayout] = useState({});
19
+ const [hasSelections, setHasSelections] = useState(false);
20
+ const [params, setParams] = useState({
21
+ url: dataset.url,
22
+ obsCol: dataset.selectedObs,
23
+ obsValues: !dataset.selectedObs?.omit.length ? null : _.difference(_.values(dataset.selectedObs?.codes), dataset.selectedObs?.omit).map(c => dataset.selectedObs?.codesMap[c]),
24
+ varKeys: dataset.selectedMultiVar.map(i => i.isSet ? {
25
+ name: i.name,
26
+ indices: i.vars.map(v => v.index)
27
+ } : i.index),
28
+ obsIndices: isSliced ? [...(obsIndices || [])] : null,
29
+ standardScale: dataset.controls.standardScale,
30
+ varNamesCol: dataset.varNamesCol
31
+ });
32
+ useEffect(() => {
33
+ if (dataset.selectedObs && dataset.selectedMultiVar.length) {
34
+ setHasSelections(true);
35
+ } else {
36
+ setHasSelections(false);
37
+ }
38
+ setParams(p => {
39
+ return {
40
+ ...p,
41
+ url: dataset.url,
42
+ obsCol: dataset.selectedObs,
43
+ obsValues: !dataset.selectedObs?.omit.length ? null : _.difference(_.values(dataset.selectedObs?.codes), dataset.selectedObs?.omit).map(c => dataset.selectedObs?.codesMap[c]),
44
+ varKeys: dataset.selectedMultiVar.map(i => i.isSet ? {
45
+ name: i.name,
46
+ indices: i.vars.map(v => v.index)
47
+ } : i.index),
48
+ obsIndices: isSliced ? [...(obsIndices || [])] : null,
49
+ standardScale: dataset.controls.standardScale,
50
+ varNamesCol: dataset.varNamesCol
51
+ };
52
+ });
53
+ }, [dataset.controls.standardScale, dataset.selectedMultiVar, dataset.selectedObs, dataset.url, dataset.varNamesCol, obsIndices, isSliced]);
54
+ const updateColorscale = useCallback(colorscale => {
55
+ setLayout(l => {
56
+ return {
57
+ ...l,
58
+ coloraxis: {
59
+ ...l.coloraxis,
60
+ colorscale: colorscale
61
+ }
62
+ };
63
+ });
64
+ }, []);
65
+ const {
66
+ fetchedData,
67
+ isPending,
68
+ serverError
69
+ } = useDebouncedFetch(ENDPOINT, params, 500, {
70
+ enabled: !!params.obsCol && !!params.varKeys.length
71
+ });
72
+ useEffect(() => {
73
+ if (hasSelections && !isPending && !serverError) {
74
+ setData(fetchedData.data);
75
+ setLayout(fetchedData.layout);
76
+ updateColorscale(colorscale.current);
77
+ }
78
+ }, [fetchedData, hasSelections, isPending, serverError, updateColorscale]);
79
+ useEffect(() => {
80
+ colorscale.current = dataset.controls.colorScale;
81
+ updateColorscale(colorscale.current);
82
+ }, [dataset.controls.colorScale, updateColorscale]);
83
+ if (!serverError) {
84
+ if (hasSelections) {
85
+ return /*#__PURE__*/React.createElement("div", {
86
+ className: "cherita-matrixplot position-relative"
87
+ }, isPending && /*#__PURE__*/React.createElement(LoadingSpinner, null), /*#__PURE__*/React.createElement(Plot, {
88
+ data: data,
89
+ layout: layout,
90
+ useResizeHandler: true,
91
+ style: {
92
+ maxWidth: "100%",
93
+ maxHeight: "100%"
94
+ }
95
+ }));
96
+ }
97
+ return /*#__PURE__*/React.createElement("div", {
98
+ className: "cherita-matrixplot"
99
+ }, /*#__PURE__*/React.createElement(Alert, {
100
+ variant: "light"
101
+ }, "Select features and a category"));
102
+ } else {
103
+ return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Alert, {
104
+ variant: "danger"
105
+ }, serverError.message));
106
+ }
107
+ }
@@ -0,0 +1,38 @@
1
+ import React from "react";
2
+ import _ from "lodash";
3
+ import { Dropdown, ButtonGroup, ButtonToolbar, InputGroup } from "react-bootstrap";
4
+ import { COLORSCALES } from "../../constants/colorscales";
5
+ import { MATRIXPLOT_SCALES } from "../../constants/constants";
6
+ import { useDataset, useDatasetDispatch } from "../../context/DatasetContext";
7
+ export function MatrixplotControls() {
8
+ const dataset = useDataset();
9
+ const dispatch = useDatasetDispatch();
10
+ const colorScaleList = _.keys(COLORSCALES).map(key => /*#__PURE__*/React.createElement(Dropdown.Item, {
11
+ key: key,
12
+ active: dataset.controls.colorScale === key,
13
+ onClick: () => {
14
+ dispatch({
15
+ type: "set.controls.colorScale",
16
+ colorScale: key
17
+ });
18
+ }
19
+ }, key));
20
+ const standardScaleList = _.values(MATRIXPLOT_SCALES).map(scale => /*#__PURE__*/React.createElement(Dropdown.Item, {
21
+ key: scale.value,
22
+ active: dataset.controls.scale.matrixplot.name === scale.name,
23
+ onClick: () => {
24
+ dispatch({
25
+ type: "set.controls.scale",
26
+ plot: "matrixplot",
27
+ scale: scale
28
+ });
29
+ }
30
+ }, scale.name));
31
+ return /*#__PURE__*/React.createElement(ButtonToolbar, null, /*#__PURE__*/React.createElement(ButtonGroup, null, /*#__PURE__*/React.createElement(Dropdown, null, /*#__PURE__*/React.createElement(Dropdown.Toggle, {
32
+ id: "dropdownColorscale",
33
+ variant: "light"
34
+ }, dataset.controls.colorScale), /*#__PURE__*/React.createElement(Dropdown.Menu, null, colorScaleList))), /*#__PURE__*/React.createElement(ButtonGroup, null, /*#__PURE__*/React.createElement(InputGroup, null, /*#__PURE__*/React.createElement(InputGroup.Text, null, "Standard scale"), /*#__PURE__*/React.createElement(Dropdown, null, /*#__PURE__*/React.createElement(Dropdown.Toggle, {
35
+ id: "dropdownStandardScale",
36
+ variant: "light"
37
+ }, dataset.controls.scale.matrixplot.name), /*#__PURE__*/React.createElement(Dropdown.Menu, null, standardScaleList)))));
38
+ }