@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
@@ -10,7 +10,8 @@ var _constants = require("../constants/constants");
10
10
  var _DatasetContext = require("../context/DatasetContext");
11
11
  var _zarrHelper = require("../helpers/zarr-helper");
12
12
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
- const useObsmData = (obsm = null) => {
13
+ const useObsmData = function () {
14
+ let obsm = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
14
15
  const dataset = (0, _DatasetContext.useDataset)();
15
16
  obsm = obsm || dataset.selectedObsm;
16
17
  const [obsmParams, setObsmParams] = (0, _react.useState)({
@@ -29,9 +30,15 @@ const useObsmData = (obsm = null) => {
29
30
  };
30
31
  exports.useObsmData = useObsmData;
31
32
  const meanData = (_i, data) => {
32
- return _lodash.default.zipWith(...data, (...values) => _lodash.default.mean(values));
33
+ return _lodash.default.zipWith(...data, function () {
34
+ for (var _len = arguments.length, values = new Array(_len), _key = 0; _key < _len; _key++) {
35
+ values[_key] = arguments[_key];
36
+ }
37
+ return _lodash.default.mean(values);
38
+ });
33
39
  };
34
- const useXData = (agg = meanData) => {
40
+ const useXData = function () {
41
+ let agg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : meanData;
35
42
  const dataset = (0, _DatasetContext.useDataset)();
36
43
  const [xParams, setXParams] = (0, _react.useState)(!dataset.selectedVar ? [] : !dataset.selectedVar?.isSet ? [{
37
44
  url: dataset.url,
@@ -62,7 +69,8 @@ const useXData = (agg = meanData) => {
62
69
  }, agg);
63
70
  };
64
71
  exports.useXData = useXData;
65
- const useObsData = (obs = null) => {
72
+ const useObsData = function () {
73
+ let obs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
66
74
  const dataset = (0, _DatasetContext.useDataset)();
67
75
  obs = obs || dataset.selectedObs;
68
76
  const [obsParams, setObsParams] = (0, _react.useState)({
@@ -0,0 +1,135 @@
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, useDatasetDispatch } from "../../context/DatasetContext";
6
+ import { useFilteredData } from "../../context/FilterContext";
7
+ import { LoadingSpinner } from "../../utils/LoadingIndicators";
8
+ import { useDebouncedFetch } from "../../utils/requests";
9
+ export function Dotplot() {
10
+ const ENDPOINT = "dotplot";
11
+ const dataset = useDataset();
12
+ const {
13
+ obsIndices,
14
+ isSliced
15
+ } = useFilteredData();
16
+ const dispatch = useDatasetDispatch();
17
+ const colorscale = useRef(dataset.controls.colorScale);
18
+ const [data, setData] = useState([]);
19
+ const [layout, setLayout] = useState({});
20
+ const [hasSelections, setHasSelections] = useState(false);
21
+ const [params, setParams] = useState({
22
+ url: dataset.url,
23
+ obsCol: dataset.selectedObs,
24
+ obsValues: !dataset.selectedObs?.omit.length ? null : _.difference(_.values(dataset.selectedObs?.codes), dataset.selectedObs?.omit).map(c => dataset.selectedObs?.codesMap[c]),
25
+ varKeys: dataset.selectedMultiVar.map(i => i.isSet ? {
26
+ name: i.name,
27
+ indices: i.vars.map(v => v.index)
28
+ } : i.index),
29
+ obsIndices: isSliced ? [...(obsIndices || [])] : null,
30
+ standardScale: dataset.controls.standardScale,
31
+ meanOnlyExpressed: dataset.controls.meanOnlyExpressed,
32
+ expressionCutoff: dataset.controls.expressionCutoff,
33
+ varNamesCol: dataset.varNamesCol
34
+ });
35
+ // @TODO: set default scale
36
+
37
+ useEffect(() => {
38
+ if (dataset.selectedObs && dataset.selectedMultiVar.length) {
39
+ setHasSelections(true);
40
+ } else {
41
+ setHasSelections(false);
42
+ }
43
+ setParams(p => {
44
+ return {
45
+ ...p,
46
+ url: dataset.url,
47
+ obsCol: dataset.selectedObs,
48
+ obsValues: !dataset.selectedObs?.omit.length ? null : _.difference(_.values(dataset.selectedObs?.codes), dataset.selectedObs?.omit).map(c => dataset.selectedObs?.codesMap[c]),
49
+ varKeys: dataset.selectedMultiVar.map(i => i.isSet ? {
50
+ name: i.name,
51
+ indices: i.vars.map(v => v.index)
52
+ } : i.index),
53
+ obsIndices: isSliced ? [...(obsIndices || [])] : null,
54
+ standardScale: dataset.controls.standardScale,
55
+ meanOnlyExpressed: dataset.controls.meanOnlyExpressed,
56
+ expressionCutoff: dataset.controls.expressionCutoff,
57
+ varNamesCol: dataset.varNamesCol
58
+ };
59
+ });
60
+ }, [dataset.url, dataset.selectedObs, dataset.selectedMultiVar, dataset.controls.standardScale, dataset.controls.meanOnlyExpressed, dataset.controls.expressionCutoff, dataset.varNamesCol, isSliced, obsIndices]);
61
+ const updateColorscale = useCallback(colorscale => {
62
+ setLayout(l => {
63
+ return {
64
+ ...l,
65
+ coloraxis: {
66
+ ...l.coloraxis,
67
+ colorscale: colorscale
68
+ }
69
+ };
70
+ });
71
+ }, []);
72
+ const {
73
+ fetchedData,
74
+ isPending,
75
+ serverError
76
+ } = useDebouncedFetch(ENDPOINT, params, 500, {
77
+ enabled: !!params.obsCol && !!params.varKeys.length
78
+ });
79
+ useEffect(() => {
80
+ if (hasSelections && !isPending && !serverError) {
81
+ setData(fetchedData.data);
82
+ setLayout(fetchedData.layout);
83
+ dispatch({
84
+ type: "set.controls.colorAxis",
85
+ colorAxis: {
86
+ dmin: fetchedData.range.min.toFixed(1),
87
+ dmax: fetchedData.range.max.toFixed(1),
88
+ cmin: fetchedData.range.min.toFixed(1),
89
+ cmax: fetchedData.range.max.toFixed(1)
90
+ }
91
+ });
92
+ updateColorscale(colorscale.current);
93
+ }
94
+ }, [fetchedData, isPending, serverError, hasSelections, dispatch, updateColorscale]);
95
+ useEffect(() => {
96
+ colorscale.current = dataset.controls.colorScale;
97
+ updateColorscale(colorscale.current);
98
+ }, [dataset.controls.colorScale, updateColorscale]);
99
+ useEffect(() => {
100
+ setLayout(l => {
101
+ return {
102
+ ...l,
103
+ coloraxis: {
104
+ ...l.coloraxis,
105
+ cmin: dataset.controls.colorAxis.cmin,
106
+ cmax: dataset.controls.colorAxis.cmax
107
+ }
108
+ };
109
+ });
110
+ }, [dataset.controls.colorAxis.cmin, dataset.controls.colorAxis.cmax]);
111
+ if (!serverError) {
112
+ if (hasSelections) {
113
+ return /*#__PURE__*/React.createElement("div", {
114
+ className: "cherita-dotplot position-relative"
115
+ }, isPending && /*#__PURE__*/React.createElement(LoadingSpinner, null), /*#__PURE__*/React.createElement(Plot, {
116
+ data: data,
117
+ layout: layout,
118
+ useResizeHandler: true,
119
+ style: {
120
+ maxWidth: "100%",
121
+ maxHeight: "100%"
122
+ }
123
+ }));
124
+ }
125
+ return /*#__PURE__*/React.createElement("div", {
126
+ className: "cherita-dotplot"
127
+ }, /*#__PURE__*/React.createElement(Alert, {
128
+ variant: "light"
129
+ }, "Select features and a category"));
130
+ } else {
131
+ return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Alert, {
132
+ variant: "danger"
133
+ }, serverError.message));
134
+ }
135
+ }
@@ -0,0 +1,148 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import _ from "lodash";
3
+ import { Button, ButtonGroup, ButtonToolbar, Form, ToggleButton, InputGroup } from "react-bootstrap";
4
+ import Dropdown from "react-bootstrap/Dropdown";
5
+ import { COLORSCALES } from "../../constants/colorscales";
6
+ import { DOTPLOT_SCALES } from "../../constants/constants";
7
+ import { useDataset, useDatasetDispatch } from "../../context/DatasetContext";
8
+ export function DotplotControls() {
9
+ const dataset = useDataset();
10
+ const dispatch = useDatasetDispatch();
11
+ const [controls, setControls] = useState({
12
+ expressionCutoff: dataset.controls.expressionCutoff,
13
+ colorAxis: {
14
+ cmin: dataset.controls.colorAxis.cmin,
15
+ cmax: dataset.controls.colorAxis.cmax
16
+ }
17
+ });
18
+ useEffect(() => {
19
+ setControls(c => ({
20
+ ...c,
21
+ colorAxis: {
22
+ cmin: dataset.controls.colorAxis.cmin,
23
+ cmax: dataset.controls.colorAxis.cmax
24
+ },
25
+ expressionCutoff: dataset.controls.expressionCutoff
26
+ }));
27
+ }, [dataset.controls.colorAxis.cmin, dataset.controls.colorAxis.cmax, dataset.controls.expressionCutoff]);
28
+ const colorScaleList = _.keys(COLORSCALES).map(key => /*#__PURE__*/React.createElement(Dropdown.Item, {
29
+ key: key,
30
+ active: dataset.controls.colorScale === key,
31
+ onClick: () => {
32
+ dispatch({
33
+ type: "set.controls.colorScale",
34
+ colorScale: key
35
+ });
36
+ }
37
+ }, key));
38
+ const standardScaleList = _.values(DOTPLOT_SCALES).map(scale => /*#__PURE__*/React.createElement(Dropdown.Item, {
39
+ key: scale.value,
40
+ active: dataset.controls.scale.dotplot === scale,
41
+ onClick: () => {
42
+ dispatch({
43
+ type: "set.controls.scale",
44
+ plot: "dotplot",
45
+ scale: scale
46
+ });
47
+ }
48
+ }, scale.name));
49
+ return /*#__PURE__*/React.createElement(ButtonToolbar, null, /*#__PURE__*/React.createElement(ButtonGroup, null, /*#__PURE__*/React.createElement(Dropdown, null, /*#__PURE__*/React.createElement(Dropdown.Toggle, {
50
+ id: "dropdownColorscale",
51
+ variant: "light"
52
+ }, 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, {
53
+ id: "dropdownStandardScale",
54
+ variant: "light"
55
+ }, dataset.controls.scale.dotplot.name), /*#__PURE__*/React.createElement(Dropdown.Menu, null, standardScaleList)))), /*#__PURE__*/React.createElement(ButtonGroup, null, /*#__PURE__*/React.createElement(ToggleButton, {
56
+ id: "toggleMeanOnlyExpressed",
57
+ type: "checkbox",
58
+ variant: "outline-primary",
59
+ checked: dataset.controls.meanOnlyExpressed,
60
+ onChange: () => {
61
+ dispatch({
62
+ type: "set.controls.meanOnlyExpressed",
63
+ meanOnlyExpressed: !dataset.controls.meanOnlyExpressed
64
+ });
65
+ }
66
+ }, "Average only above cutoff")), /*#__PURE__*/React.createElement(Form, {
67
+ onSubmit: e => {
68
+ e.preventDefault();
69
+ dispatch({
70
+ type: "set.controls.expressionCutoff",
71
+ expressionCutoff: parseFloat(controls.expressionCutoff)
72
+ });
73
+ }
74
+ }, /*#__PURE__*/React.createElement(InputGroup, null, /*#__PURE__*/React.createElement(InputGroup.Text, null, "Expression Cutoff"), /*#__PURE__*/React.createElement(Form.Control, {
75
+ size: "sm",
76
+ type: "number",
77
+ step: "0.1",
78
+ min: 0.0,
79
+ value: controls.expressionCutoff,
80
+ onChange: e => {
81
+ setControls({
82
+ ...controls,
83
+ expressionCutoff: e.target.value
84
+ });
85
+ }
86
+ }), /*#__PURE__*/React.createElement(Button, {
87
+ type: "submit",
88
+ variant: "outline-primary"
89
+ }, "Apply"))), /*#__PURE__*/React.createElement(Form, {
90
+ onSubmit: e => {
91
+ e.preventDefault();
92
+ dispatch({
93
+ type: "set.controls.colorAxis.crange",
94
+ cmin: controls.colorAxis.cmin,
95
+ cmax: controls.colorAxis.cmax
96
+ });
97
+ }
98
+ }, /*#__PURE__*/React.createElement(InputGroup, null, /*#__PURE__*/React.createElement(InputGroup.Text, null, "Colorscale"), /*#__PURE__*/React.createElement(InputGroup.Text, null, "min"), /*#__PURE__*/React.createElement(Form.Control, {
99
+ name: "scaleMin",
100
+ size: "sm",
101
+ type: "number",
102
+ value: controls.colorAxis.cmin,
103
+ step: 0.1,
104
+ min: Math.min(dataset.controls.colorAxis.dmin, 0.0),
105
+ max: dataset.controls.colorAxis.dmax,
106
+ onChange: e => {
107
+ setControls({
108
+ ...controls,
109
+ colorAxis: {
110
+ ...controls.colorAxis,
111
+ cmin: e.target.value
112
+ }
113
+ });
114
+ }
115
+ }), /*#__PURE__*/React.createElement(InputGroup.Text, null, "max"), /*#__PURE__*/React.createElement(Form.Control, {
116
+ name: "scaleMax",
117
+ size: "sm",
118
+ type: "number",
119
+ value: controls.colorAxis.cmax,
120
+ step: 0.1,
121
+ min: controls.colorAxis.cmin,
122
+ max: dataset.controls.colorAxis.dmax,
123
+ onChange: e => {
124
+ if (parseFloat(e.target.value) > dataset.controls.colorAxis.dmax) {
125
+ e.target.value = dataset.controls.colorAxis.dmax.toFixed(1);
126
+ }
127
+ setControls({
128
+ ...controls,
129
+ colorAxis: {
130
+ ...controls.colorAxis,
131
+ cmax: e.target.value
132
+ }
133
+ });
134
+ }
135
+ }), /*#__PURE__*/React.createElement(Button, {
136
+ type: "submit",
137
+ variant: "outline-primary"
138
+ }, "Apply"), /*#__PURE__*/React.createElement(Button, {
139
+ variant: "outline-primary",
140
+ onClick: () => {
141
+ dispatch({
142
+ type: "set.controls.colorAxis.crange",
143
+ cmin: dataset.controls.colorAxis.dmin,
144
+ cmax: dataset.controls.colorAxis.dmax
145
+ });
146
+ }
147
+ }, "Autoscale"))));
148
+ }
@@ -0,0 +1,134 @@
1
+ function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
2
+ import React, { useEffect, useRef, useState } from "react";
3
+ import { Card, Nav, Navbar } from "react-bootstrap";
4
+ import { SELECTION_MODES, VIOLIN_MODES } from "../../constants/constants";
5
+ import { DatasetProvider } from "../../context/DatasetContext";
6
+ import { Dotplot } from "../dotplot/Dotplot";
7
+ import { Heatmap } from "../heatmap/Heatmap";
8
+ import { Matrixplot } from "../matrixplot/Matrixplot";
9
+ import { ObsColsList } from "../obs-list/ObsList";
10
+ import { OffcanvasControls, OffcanvasObs, OffcanvasObsm, OffcanvasVars } from "../offcanvas";
11
+ import { Scatterplot } from "../scatterplot/Scatterplot";
12
+ import { ScatterplotControls } from "../scatterplot/ScatterplotControls";
13
+ import { SearchBar } from "../search-bar/SearchBar";
14
+ import { VarNamesList } from "../var-list/VarList";
15
+ import { Violin } from "../violin/Violin";
16
+ export function FullPage(_ref) {
17
+ let {
18
+ children,
19
+ varMode = SELECTION_MODES.SINGLE,
20
+ ...props
21
+ } = _ref;
22
+ const appRef = useRef();
23
+ const [appDimensions, setAppDimensions] = useState({
24
+ width: 0,
25
+ height: 0
26
+ });
27
+ const [showObs, setShowObs] = useState(false);
28
+ const [showObsm, setShowObsm] = useState(false);
29
+ const [showVars, setShowVars] = useState(false);
30
+ const [showControls, setShowControls] = useState(false);
31
+ useEffect(() => {
32
+ const updateDimensions = () => {
33
+ if (appRef.current) {
34
+ // Get the distance from the top of the page to the target element
35
+ const rect = appRef.current.getBoundingClientRect();
36
+ const distanceFromTop = rect.top + window.scrollY;
37
+
38
+ // Calculate the available height for the Cherita app
39
+ const availableHeight = window.innerHeight - distanceFromTop;
40
+
41
+ // Update the dimensions to fit the viewport minus the navbar height
42
+ setAppDimensions({
43
+ width: appRef.current.offsetWidth,
44
+ height: availableHeight
45
+ });
46
+ }
47
+ };
48
+ window.addEventListener("resize", updateDimensions);
49
+ updateDimensions(); // Initial update
50
+ return () => window.removeEventListener("resize", updateDimensions);
51
+ }, []);
52
+ return /*#__PURE__*/React.createElement("div", {
53
+ ref: appRef,
54
+ className: "cherita-app",
55
+ style: {
56
+ height: appDimensions.height
57
+ }
58
+ }, /*#__PURE__*/React.createElement(DatasetProvider, props, /*#__PURE__*/React.createElement("div", {
59
+ className: "row g-0"
60
+ }, /*#__PURE__*/React.createElement("div", {
61
+ className: "cherita-app-obs modern-scrollbars border-end h-100"
62
+ }, /*#__PURE__*/React.createElement(ObsColsList, null)), /*#__PURE__*/React.createElement("div", {
63
+ className: "cherita-app-plot"
64
+ }, /*#__PURE__*/React.createElement("div", {
65
+ className: "position-relative"
66
+ }, /*#__PURE__*/React.createElement(Navbar, {
67
+ expand: "sm",
68
+ bg: "primary",
69
+ className: "cherita-navbar"
70
+ }, /*#__PURE__*/React.createElement("div", {
71
+ className: "container-fluid"
72
+ }, /*#__PURE__*/React.createElement(Navbar.Toggle, {
73
+ "aria-controls": "navbarScroll"
74
+ }), /*#__PURE__*/React.createElement(Navbar.Collapse, {
75
+ id: "navbarScroll"
76
+ }, /*#__PURE__*/React.createElement(Nav, {
77
+ className: "me-auto my-0",
78
+ navbarScroll: true
79
+ }, /*#__PURE__*/React.createElement(Nav.Item, {
80
+ className: "d-block d-lg-none"
81
+ }, /*#__PURE__*/React.createElement(Nav.Link, {
82
+ onClick: () => setShowObs(true)
83
+ }, "Observations")), /*#__PURE__*/React.createElement(Nav.Item, null, /*#__PURE__*/React.createElement(Nav.Link, {
84
+ onClick: () => setShowVars(true)
85
+ }, "Features"))), /*#__PURE__*/React.createElement(Nav, {
86
+ className: "d-flex"
87
+ }, /*#__PURE__*/React.createElement(Nav.Item, null, /*#__PURE__*/React.createElement(Nav.Link, {
88
+ onClick: () => setShowControls(true)
89
+ }, "Controls"))))))), children), /*#__PURE__*/React.createElement("div", {
90
+ className: "cherita-app-var"
91
+ }, /*#__PURE__*/React.createElement(Card, {
92
+ className: "cherita-app-features"
93
+ }, /*#__PURE__*/React.createElement(Card.Body, null, /*#__PURE__*/React.createElement(SearchBar, {
94
+ searchDiseases: true,
95
+ searchVar: true
96
+ }), /*#__PURE__*/React.createElement(VarNamesList, {
97
+ mode: varMode
98
+ })))), /*#__PURE__*/React.createElement("div", {
99
+ className: "col"
100
+ }, /*#__PURE__*/React.createElement(OffcanvasObs, {
101
+ show: showObs,
102
+ handleClose: () => setShowObs(false)
103
+ }), /*#__PURE__*/React.createElement(OffcanvasVars, {
104
+ show: showVars,
105
+ handleClose: () => setShowVars(false)
106
+ }), /*#__PURE__*/React.createElement(OffcanvasControls, {
107
+ show: showControls,
108
+ handleClose: () => setShowControls(false),
109
+ Controls: ScatterplotControls
110
+ }), /*#__PURE__*/React.createElement(OffcanvasObsm, {
111
+ show: showObsm,
112
+ handleClose: () => setShowObsm(false)
113
+ })))));
114
+ }
115
+ export function FullPageScatterplot(props) {
116
+ return /*#__PURE__*/React.createElement(FullPage, props, /*#__PURE__*/React.createElement(Scatterplot, null));
117
+ }
118
+ export function FullPagePlots(props) {
119
+ return /*#__PURE__*/React.createElement(FullPage, _extends({}, props, {
120
+ varMode: SELECTION_MODES.MULTIPLE
121
+ }), /*#__PURE__*/React.createElement("div", {
122
+ className: "container-fluid w-100 h-100 d-flex flex-column overflow-y-auto"
123
+ }, /*#__PURE__*/React.createElement("div", {
124
+ className: "row flex-grow-1"
125
+ }, /*#__PURE__*/React.createElement(Heatmap, null)), /*#__PURE__*/React.createElement("div", {
126
+ className: "row flex-grow-1"
127
+ }, /*#__PURE__*/React.createElement(Matrixplot, null)), /*#__PURE__*/React.createElement("div", {
128
+ className: "row flex-grow-1"
129
+ }, /*#__PURE__*/React.createElement(Dotplot, null)), /*#__PURE__*/React.createElement("div", {
130
+ className: "row flex-grow-1"
131
+ }, /*#__PURE__*/React.createElement(Violin, {
132
+ mode: VIOLIN_MODES.GROUPBY
133
+ }))));
134
+ }
@@ -0,0 +1,151 @@
1
+ import React, { useEffect, useRef, useState } from "react";
2
+ import { faArrowUpRightFromSquare } from "@fortawesome/free-solid-svg-icons";
3
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
4
+ import { Button, Card, Container, Modal, Nav, Navbar } from "react-bootstrap";
5
+ import { SELECTION_MODES } from "../../constants/constants";
6
+ import { DatasetProvider } from "../../context/DatasetContext";
7
+ import { ObsColsList } from "../obs-list/ObsList";
8
+ import { OffcanvasControls, OffcanvasObs, OffcanvasObsm, OffcanvasVars } from "../offcanvas";
9
+ import { Pseudospatial } from "../pseudospatial/Pseudospatial";
10
+ import { PseudospatialToolbar } from "../pseudospatial/PseudospatialToolbar";
11
+ import { Scatterplot } from "../scatterplot/Scatterplot";
12
+ import { ScatterplotControls } from "../scatterplot/ScatterplotControls";
13
+ import { SearchBar } from "../search-bar/SearchBar";
14
+ import { VarNamesList } from "../var-list/VarList";
15
+ export function FullPage(_ref) {
16
+ let {
17
+ children,
18
+ varMode = SELECTION_MODES.SINGLE,
19
+ ...props
20
+ } = _ref;
21
+ const appRef = useRef();
22
+ const [appDimensions, setAppDimensions] = useState({
23
+ width: 0,
24
+ height: 0
25
+ });
26
+ const [showObs, setShowObs] = useState(false);
27
+ const [showObsm, setShowObsm] = useState(false);
28
+ const [showVars, setShowVars] = useState(false);
29
+ const [showControls, setShowControls] = useState(false);
30
+ const [showPseudospatialControls, setShowPseudospatialControls] = useState(false);
31
+ const [showModal, setShowModal] = useState(false);
32
+ const [pseudospatialPlotType, setpseudospatialPlotType] = useState(null);
33
+ useEffect(() => {
34
+ const updateDimensions = () => {
35
+ if (appRef.current) {
36
+ // Get the distance from the top of the page to the target element
37
+ const rect = appRef.current.getBoundingClientRect();
38
+ const distanceFromTop = rect.top + window.scrollY;
39
+
40
+ // Calculate the available height for the Cherita app
41
+ const availableHeight = window.innerHeight - distanceFromTop;
42
+
43
+ // Update the dimensions to fit the viewport minus the navbar height
44
+ setAppDimensions({
45
+ width: appRef.current.offsetWidth,
46
+ height: availableHeight
47
+ });
48
+ }
49
+ };
50
+ window.addEventListener("resize", updateDimensions);
51
+ updateDimensions(); // Initial update
52
+ return () => window.removeEventListener("resize", updateDimensions);
53
+ }, []);
54
+ return /*#__PURE__*/React.createElement("div", {
55
+ ref: appRef,
56
+ className: "cherita-app",
57
+ style: {
58
+ height: appDimensions.height
59
+ }
60
+ }, /*#__PURE__*/React.createElement(DatasetProvider, props, /*#__PURE__*/React.createElement(Container, {
61
+ fluid: true,
62
+ className: "d-flex g-0",
63
+ style: {
64
+ height: appDimensions.height
65
+ }
66
+ }, /*#__PURE__*/React.createElement(Navbar, {
67
+ expand: "sm",
68
+ bg: "primary",
69
+ className: "cherita-navbar"
70
+ }, /*#__PURE__*/React.createElement("div", {
71
+ className: "container-fluid"
72
+ }, /*#__PURE__*/React.createElement(Navbar.Toggle, {
73
+ "aria-controls": "navbarScroll"
74
+ }), /*#__PURE__*/React.createElement(Navbar.Collapse, {
75
+ id: "navbarScroll"
76
+ }, /*#__PURE__*/React.createElement(Nav, {
77
+ className: "me-auto my-0",
78
+ navbarScroll: true
79
+ }, /*#__PURE__*/React.createElement(Nav.Item, {
80
+ className: "d-block d-lg-none"
81
+ }, /*#__PURE__*/React.createElement(Nav.Link, {
82
+ onClick: () => setShowObs(true)
83
+ }, "Observations")), /*#__PURE__*/React.createElement(Nav.Item, null, /*#__PURE__*/React.createElement(Nav.Link, {
84
+ onClick: () => setShowVars(true)
85
+ }, "Features"))), /*#__PURE__*/React.createElement(Nav, {
86
+ className: "d-flex"
87
+ }, /*#__PURE__*/React.createElement(Nav.Item, null, /*#__PURE__*/React.createElement(Nav.Link, {
88
+ onClick: () => setShowControls(true)
89
+ }, "Controls")))))), /*#__PURE__*/React.createElement("div", {
90
+ className: "cherita-app-obs modern-scrollbars border-end h-100"
91
+ }, /*#__PURE__*/React.createElement(ObsColsList, null)), /*#__PURE__*/React.createElement("div", {
92
+ className: "cherita-app-canvas flex-grow-1"
93
+ }, children), /*#__PURE__*/React.createElement("div", {
94
+ className: "cherita-app-sidebar p-3"
95
+ }, /*#__PURE__*/React.createElement(Card, null, /*#__PURE__*/React.createElement(Card.Header, {
96
+ className: "d-flex justify-content-evenly align-items-center"
97
+ }, /*#__PURE__*/React.createElement(Button, {
98
+ variant: "link",
99
+ onClick: () => setShowModal(true)
100
+ }, /*#__PURE__*/React.createElement(FontAwesomeIcon, {
101
+ icon: faArrowUpRightFromSquare
102
+ }))), /*#__PURE__*/React.createElement(Card.Body, {
103
+ className: "d-flex flex-column p-0"
104
+ }, /*#__PURE__*/React.createElement("div", {
105
+ className: "sidebar-pseudospatial"
106
+ }, /*#__PURE__*/React.createElement(Pseudospatial, {
107
+ className: "sidebar-pseudospatial",
108
+ plotType: pseudospatialPlotType,
109
+ setPlotType: setpseudospatialPlotType,
110
+ setShowControls: setShowPseudospatialControls
111
+ })), /*#__PURE__*/React.createElement("div", {
112
+ className: "sidebar-features modern-scrollbars"
113
+ }, /*#__PURE__*/React.createElement(SearchBar, {
114
+ searchDiseases: true,
115
+ searchVar: true
116
+ }), /*#__PURE__*/React.createElement(VarNamesList, {
117
+ mode: varMode
118
+ })))))), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Modal, {
119
+ show: showModal,
120
+ onHide: () => setShowModal(false),
121
+ centered: true
122
+ }, /*#__PURE__*/React.createElement(Modal.Header, {
123
+ closeButton: true
124
+ }), /*#__PURE__*/React.createElement(Modal.Body, null, /*#__PURE__*/React.createElement(Pseudospatial, {
125
+ plotType: pseudospatialPlotType,
126
+ setPlotType: setpseudospatialPlotType,
127
+ setShowControls: setShowPseudospatialControls,
128
+ height: 500
129
+ }))), /*#__PURE__*/React.createElement(OffcanvasObs, {
130
+ show: showObs,
131
+ handleClose: () => setShowObs(false)
132
+ }), /*#__PURE__*/React.createElement(OffcanvasVars, {
133
+ show: showVars,
134
+ handleClose: () => setShowVars(false)
135
+ }), /*#__PURE__*/React.createElement(OffcanvasControls, {
136
+ show: showControls,
137
+ handleClose: () => setShowControls(false),
138
+ Controls: ScatterplotControls
139
+ }), /*#__PURE__*/React.createElement(OffcanvasControls, {
140
+ show: showPseudospatialControls,
141
+ handleClose: () => setShowPseudospatialControls(false),
142
+ Controls: PseudospatialToolbar,
143
+ plotType: pseudospatialPlotType
144
+ }), /*#__PURE__*/React.createElement(OffcanvasObsm, {
145
+ show: showObsm,
146
+ handleClose: () => setShowObsm(false)
147
+ }))));
148
+ }
149
+ export function FullPagePseudospatial(props) {
150
+ return /*#__PURE__*/React.createElement(FullPage, props, /*#__PURE__*/React.createElement(Scatterplot, null));
151
+ }