@haniffalab/cherita-react 1.3.0-dev.2025-05-28.9afc380f → 1.3.0-dev.2025-06-04.d986a94b

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 (30) hide show
  1. package/dist/cjs/components/dotplot/Dotplot.js +35 -5
  2. package/dist/cjs/components/full-page/FullPage.js +108 -50
  3. package/dist/cjs/components/full-page/PlotTypeSelector.js +57 -0
  4. package/dist/cjs/components/heatmap/Heatmap.js +35 -5
  5. package/dist/cjs/components/matrixplot/Matrixplot.js +35 -5
  6. package/dist/cjs/components/obs-list/ObsList.js +4 -3
  7. package/dist/cjs/components/scatterplot/SpatialControls.js +3 -3
  8. package/dist/cjs/components/toolbar/Toolbar.js +102 -0
  9. package/dist/cjs/components/violin/Violin.js +37 -6
  10. package/dist/cjs/constants/constants.js +14 -2
  11. package/dist/cjs/index.js +15 -21
  12. package/dist/css/cherita.css +76 -23
  13. package/dist/css/cherita.css.map +1 -1
  14. package/dist/esm/components/dotplot/Dotplot.js +36 -6
  15. package/dist/esm/components/full-page/FullPage.js +110 -50
  16. package/dist/esm/components/full-page/PlotTypeSelector.js +50 -0
  17. package/dist/esm/components/heatmap/Heatmap.js +36 -6
  18. package/dist/esm/components/matrixplot/Matrixplot.js +36 -6
  19. package/dist/esm/components/obs-list/ObsList.js +4 -3
  20. package/dist/esm/components/scatterplot/SpatialControls.js +3 -3
  21. package/dist/esm/components/toolbar/Toolbar.js +91 -0
  22. package/dist/esm/components/violin/Violin.js +39 -8
  23. package/dist/esm/constants/constants.js +13 -1
  24. package/dist/esm/index.js +4 -4
  25. package/package.json +2 -2
  26. package/scss/cherita.scss +0 -1
  27. package/scss/components/layouts.scss +69 -1
  28. package/scss/components/plotly.scss +19 -14
  29. package/dist/cjs/components/full-page/FullPagePseudospatial.js +0 -157
  30. package/dist/esm/components/full-page/FullPagePseudospatial.js +0 -149
@@ -5,15 +5,25 @@ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol"
5
5
  function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
6
6
  import React, { useCallback, useEffect, useRef, useState } from "react";
7
7
  import _ from "lodash";
8
- import { Alert } from "react-bootstrap";
8
+ import { Alert, Button } from "react-bootstrap";
9
9
  import Plot from "react-plotly.js";
10
+ import { PLOTLY_MODEBAR_BUTTONS } from "../../constants/constants";
10
11
  import { useDataset } from "../../context/DatasetContext";
11
12
  import { useFilteredData } from "../../context/FilterContext";
12
13
  import { useSettings } from "../../context/SettingsContext";
13
14
  import { LoadingSpinner } from "../../utils/LoadingIndicators";
14
15
  import { useDebouncedFetch } from "../../utils/requests";
15
- export function Heatmap() {
16
+ import { ControlsPlotlyToolbar, ObsPlotlyToolbar, VarPlotlyToolbar } from "../toolbar/Toolbar";
17
+ export function Heatmap(_ref) {
16
18
  var _settings$selectedObs, _settings$selectedObs2, _settings$selectedObs3;
19
+ let {
20
+ showObsBtn = false,
21
+ showVarsBtn = false,
22
+ showCtrlsBtn = false,
23
+ setShowObs,
24
+ setShowVars,
25
+ setShowControls
26
+ } = _ref;
17
27
  const ENDPOINT = "heatmap";
18
28
  const dataset = useDataset();
19
29
  const settings = useSettings();
@@ -90,17 +100,29 @@ export function Heatmap() {
90
100
  colorscale.current = settings.controls.colorScale;
91
101
  updateColorscale(colorscale.current);
92
102
  }, [settings.controls.colorScale, updateColorscale]);
103
+ const customModeBarButtons = _.compact([showObsBtn && ObsPlotlyToolbar({
104
+ onClick: setShowObs
105
+ }), showVarsBtn && VarPlotlyToolbar({
106
+ onClick: setShowVars
107
+ }), showCtrlsBtn && ControlsPlotlyToolbar({
108
+ onClick: setShowControls
109
+ })]);
110
+ const modeBarButtons = customModeBarButtons.length ? [customModeBarButtons, PLOTLY_MODEBAR_BUTTONS] : [PLOTLY_MODEBAR_BUTTONS];
93
111
  if (!serverError) {
94
112
  if (hasSelections) {
95
113
  return /*#__PURE__*/React.createElement("div", {
96
- className: "cherita-heatmap position-relative"
114
+ className: "cherita-plot cherita-heatmap position-relative"
97
115
  }, isPending && /*#__PURE__*/React.createElement(LoadingSpinner, null), /*#__PURE__*/React.createElement(Plot, {
98
116
  data: data,
99
117
  layout: layout,
100
118
  useResizeHandler: true,
101
119
  style: {
102
- maxWidth: "100%",
103
- maxHeight: "100%"
120
+ width: "100%",
121
+ height: "100%"
122
+ },
123
+ config: {
124
+ displaylogo: false,
125
+ modeBarButtons: modeBarButtons
104
126
  }
105
127
  }));
106
128
  }
@@ -108,7 +130,15 @@ export function Heatmap() {
108
130
  className: "cherita-heatmap"
109
131
  }, /*#__PURE__*/React.createElement(Alert, {
110
132
  variant: "light"
111
- }, "Select features and a category"));
133
+ }, "Select", " ", showVarsBtn ? /*#__PURE__*/React.createElement(Button, {
134
+ variant: "link",
135
+ className: "border-0 p-0 align-baseline",
136
+ onClick: setShowVars
137
+ }, "features") : "features", " ", "and a", " ", showObsBtn ? /*#__PURE__*/React.createElement(Button, {
138
+ variant: "link",
139
+ className: "border-0 p-0 align-baseline",
140
+ onClick: setShowObs
141
+ }, "category") : "category"));
112
142
  } else {
113
143
  return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Alert, {
114
144
  variant: "danger"
@@ -5,15 +5,25 @@ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol"
5
5
  function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
6
6
  import React, { useCallback, useEffect, useRef, useState } from "react";
7
7
  import _ from "lodash";
8
- import { Alert } from "react-bootstrap";
8
+ import { Alert, Button } from "react-bootstrap";
9
9
  import Plot from "react-plotly.js";
10
+ import { PLOTLY_MODEBAR_BUTTONS } from "../../constants/constants";
10
11
  import { useDataset } from "../../context/DatasetContext";
11
12
  import { useFilteredData } from "../../context/FilterContext";
12
13
  import { useSettings } from "../../context/SettingsContext";
13
14
  import { LoadingSpinner } from "../../utils/LoadingIndicators";
14
15
  import { useDebouncedFetch } from "../../utils/requests";
15
- export function Matrixplot() {
16
+ import { ControlsPlotlyToolbar, ObsPlotlyToolbar, VarPlotlyToolbar } from "../toolbar/Toolbar";
17
+ export function Matrixplot(_ref) {
16
18
  var _settings$selectedObs, _settings$selectedObs2, _settings$selectedObs3;
19
+ let {
20
+ showObsBtn = false,
21
+ showVarsBtn = false,
22
+ showCtrlsBtn = false,
23
+ setShowObs,
24
+ setShowVars,
25
+ setShowControls
26
+ } = _ref;
17
27
  const ENDPOINT = "matrixplot";
18
28
  const dataset = useDataset();
19
29
  const settings = useSettings();
@@ -92,17 +102,29 @@ export function Matrixplot() {
92
102
  colorscale.current = settings.controls.colorScale;
93
103
  updateColorscale(colorscale.current);
94
104
  }, [settings.controls.colorScale, updateColorscale]);
105
+ const customModeBarButtons = _.compact([showObsBtn && ObsPlotlyToolbar({
106
+ onClick: setShowObs
107
+ }), showVarsBtn && VarPlotlyToolbar({
108
+ onClick: setShowVars
109
+ }), showCtrlsBtn && ControlsPlotlyToolbar({
110
+ onClick: setShowControls
111
+ })]);
112
+ const modeBarButtons = customModeBarButtons.length ? [customModeBarButtons, PLOTLY_MODEBAR_BUTTONS] : [PLOTLY_MODEBAR_BUTTONS];
95
113
  if (!serverError) {
96
114
  if (hasSelections) {
97
115
  return /*#__PURE__*/React.createElement("div", {
98
- className: "cherita-matrixplot position-relative"
116
+ className: "cherita-plot cherita-matrixplot position-relative"
99
117
  }, isPending && /*#__PURE__*/React.createElement(LoadingSpinner, null), /*#__PURE__*/React.createElement(Plot, {
100
118
  data: data,
101
119
  layout: layout,
102
120
  useResizeHandler: true,
103
121
  style: {
104
- maxWidth: "100%",
105
- maxHeight: "100%"
122
+ width: "100%",
123
+ height: "100%"
124
+ },
125
+ config: {
126
+ displaylogo: false,
127
+ modeBarButtons: modeBarButtons
106
128
  }
107
129
  }));
108
130
  }
@@ -110,7 +132,15 @@ export function Matrixplot() {
110
132
  className: "cherita-matrixplot"
111
133
  }, /*#__PURE__*/React.createElement(Alert, {
112
134
  variant: "light"
113
- }, "Select features and a category"));
135
+ }, "Select", " ", showVarsBtn ? /*#__PURE__*/React.createElement(Button, {
136
+ variant: "link",
137
+ className: "border-0 p-0 align-baseline",
138
+ onClick: setShowVars
139
+ }, "features") : "features", " ", "and a", " ", showObsBtn ? /*#__PURE__*/React.createElement(Button, {
140
+ variant: "link",
141
+ className: "border-0 p-0 align-baseline",
142
+ onClick: setShowObs
143
+ }, "category") : "category"));
114
144
  } else {
115
145
  return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Alert, {
116
146
  variant: "danger"
@@ -48,7 +48,8 @@ export function ObsColsList(_ref2) {
48
48
  var _settings$selectedObs;
49
49
  let {
50
50
  showColor = true,
51
- enableObsGroups = true
51
+ enableObsGroups = true,
52
+ showSelectedAsActive = false
52
53
  } = _ref2;
53
54
  const ENDPOINT = "obs/cols";
54
55
  const dataset = useDataset();
@@ -215,7 +216,7 @@ export function ObsColsList(_ref2) {
215
216
  }
216
217
  const inLabelObs = _.some(settings.labelObs, i => i.name === item.name);
217
218
  const inSliceObs = settings.sliceBy.obs && ((_settings$selectedObs5 = settings.selectedObs) === null || _settings$selectedObs5 === void 0 ? void 0 : _settings$selectedObs5.name) === item.name;
218
- const isColorEncoding = settings.colorEncoding === COLOR_ENCODINGS.OBS && ((_settings$selectedObs6 = settings.selectedObs) === null || _settings$selectedObs6 === void 0 ? void 0 : _settings$selectedObs6.name) === item.name;
219
+ const isColorEncoding = (showSelectedAsActive || settings.colorEncoding === COLOR_ENCODINGS.OBS) && ((_settings$selectedObs6 = settings.selectedObs) === null || _settings$selectedObs6 === void 0 ? void 0 : _settings$selectedObs6.name) === item.name;
219
220
  return /*#__PURE__*/React.createElement("div", {
220
221
  className: "accordion-item",
221
222
  key: item.name
@@ -242,7 +243,7 @@ export function ObsColsList(_ref2) {
242
243
  event.stopPropagation();
243
244
  toggleColor(item);
244
245
  },
245
- title: "Is color encoding"
246
+ title: showSelectedAsActive ? "Is selected" : "Is color encoding"
246
247
  }, /*#__PURE__*/React.createElement(WaterDropIcon, null)))), /*#__PURE__*/React.createElement(Accordion.Collapse, {
247
248
  eventKey: item.name
248
249
  }, /*#__PURE__*/React.createElement("div", {
@@ -8,9 +8,9 @@ import { OverlayTrigger, Tooltip } from "react-bootstrap";
8
8
  import Button from "react-bootstrap/Button";
9
9
  import ButtonGroup from "react-bootstrap/ButtonGroup";
10
10
  import Dropdown from "react-bootstrap/Dropdown";
11
- import { useDataset } from "../../context/DatasetContext";
12
11
  import { OffcanvasControls } from "../offcanvas";
13
12
  import { ScatterplotControls } from "./ScatterplotControls";
13
+ import { BREAKPOINTS } from "../../constants/constants";
14
14
  import { useSettings, useSettingsDispatch } from "../../context/SettingsContext";
15
15
  export function SpatialControls(_ref) {
16
16
  var _features$features;
@@ -32,8 +32,8 @@ export function SpatialControls(_ref) {
32
32
  const [showControls, setShowControls] = useState(false);
33
33
  const handleCloseControls = () => setShowControls(false);
34
34
  const handleShowControls = () => setShowControls(true);
35
- const LgBreakpoint = useMediaQuery("(max-width: 991.98px)");
36
- const XlBreakpoint = useMediaQuery("(max-width: 1199.98px)");
35
+ const LgBreakpoint = useMediaQuery(BREAKPOINTS.LG);
36
+ const XlBreakpoint = useMediaQuery(BREAKPOINTS.XL);
37
37
  const showObsBtn = isFullscreen ? LgBreakpoint : true;
38
38
  const showVarsBtn = isFullscreen ? XlBreakpoint : true;
39
39
  const onSelect = (eventKey, event) => {
@@ -0,0 +1,91 @@
1
+ import React from "react";
2
+ import { faList, faSearch, faSliders } from "@fortawesome/free-solid-svg-icons";
3
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
4
+ import { Container, Nav, Navbar } from "react-bootstrap";
5
+ export const Toolbar = _ref => {
6
+ let {
7
+ showObsBtn = true,
8
+ showVarsBtn = true,
9
+ showCtrlsBtn = true,
10
+ setShowObs,
11
+ setShowVars,
12
+ setShowControls
13
+ } = _ref;
14
+ return /*#__PURE__*/React.createElement(Navbar, {
15
+ expand: "md",
16
+ bg: "primary",
17
+ variant: "dark",
18
+ className: "cherita-navbar"
19
+ }, /*#__PURE__*/React.createElement(Container, {
20
+ fluid: true
21
+ }, /*#__PURE__*/React.createElement(Navbar.Toggle, {
22
+ "aria-controls": "navbarScroll"
23
+ }), /*#__PURE__*/React.createElement(Navbar.Collapse, {
24
+ id: "navbarScroll"
25
+ }, /*#__PURE__*/React.createElement(Nav, {
26
+ navbarScroll: true
27
+ }, showObsBtn && /*#__PURE__*/React.createElement(Nav.Item, {
28
+ className: "me-2"
29
+ }, /*#__PURE__*/React.createElement(Nav.Link, {
30
+ onClick: () => setShowObs(true)
31
+ }, /*#__PURE__*/React.createElement(FontAwesomeIcon, {
32
+ icon: faList,
33
+ className: "me-2"
34
+ }), "Explore Categories")), showVarsBtn && /*#__PURE__*/React.createElement(Nav.Item, {
35
+ className: "me-2"
36
+ }, /*#__PURE__*/React.createElement(Nav.Link, {
37
+ onClick: () => setShowVars(true)
38
+ }, /*#__PURE__*/React.createElement(FontAwesomeIcon, {
39
+ icon: faSearch,
40
+ className: "me-2"
41
+ }), "Search Genes")), showCtrlsBtn && /*#__PURE__*/React.createElement(Nav.Item, {
42
+ className: "me-2"
43
+ }, /*#__PURE__*/React.createElement(Nav.Link, {
44
+ onClick: () => setShowControls(true)
45
+ }, /*#__PURE__*/React.createElement(FontAwesomeIcon, {
46
+ icon: faSliders,
47
+ className: "me-2"
48
+ }), "Controls"))))));
49
+ };
50
+ export const ObsPlotlyToolbar = _ref2 => {
51
+ let {
52
+ onClick
53
+ } = _ref2;
54
+ return {
55
+ name: "Categories",
56
+ icon: {
57
+ width: 512,
58
+ height: 512,
59
+ path: faList.icon[4]
60
+ },
61
+ click: onClick
62
+ };
63
+ };
64
+ export const VarPlotlyToolbar = _ref3 => {
65
+ let {
66
+ onClick
67
+ } = _ref3;
68
+ return {
69
+ name: "Features",
70
+ icon: {
71
+ width: 512,
72
+ height: 512,
73
+ path: faSearch.icon[4]
74
+ },
75
+ click: onClick
76
+ };
77
+ };
78
+ export const ControlsPlotlyToolbar = _ref4 => {
79
+ let {
80
+ onClick
81
+ } = _ref4;
82
+ return {
83
+ name: "Controls",
84
+ icon: {
85
+ width: 512,
86
+ height: 512,
87
+ path: faSliders.icon[4]
88
+ },
89
+ click: onClick
90
+ };
91
+ };
@@ -7,18 +7,25 @@ import React, { useEffect, useState } from "react";
7
7
  import { faCircleInfo } from "@fortawesome/free-solid-svg-icons";
8
8
  import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
9
9
  import _ from "lodash";
10
- import { Alert, OverlayTrigger, Tooltip } from "react-bootstrap";
10
+ import { Alert, Button, OverlayTrigger, Tooltip } from "react-bootstrap";
11
11
  import Plot from "react-plotly.js";
12
- import { VIOLIN_MODES } from "../../constants/constants";
12
+ import { PLOTLY_MODEBAR_BUTTONS, VIOLIN_MODES } from "../../constants/constants";
13
13
  import { useDataset } from "../../context/DatasetContext";
14
14
  import { useFilteredData } from "../../context/FilterContext";
15
15
  import { useSettings } from "../../context/SettingsContext";
16
16
  import { LoadingSpinner } from "../../utils/LoadingIndicators";
17
17
  import { useDebouncedFetch } from "../../utils/requests";
18
+ import { ControlsPlotlyToolbar, ObsPlotlyToolbar, VarPlotlyToolbar } from "../toolbar/Toolbar";
18
19
  export function Violin(_ref) {
19
20
  var _settings$selectedVar, _settings$selectedVar2, _settings$selectedVar3, _settings$selectedVar4, _settings$selectedObs, _settings$selectedObs2, _settings$selectedObs3;
20
21
  let {
21
- mode = VIOLIN_MODES.MULTIKEY
22
+ mode = VIOLIN_MODES.MULTIKEY,
23
+ showObsBtn = false,
24
+ showVarsBtn = false,
25
+ showCtrlsBtn = false,
26
+ setShowObs,
27
+ setShowVars,
28
+ setShowControls
22
29
  } = _ref;
23
30
  const ENDPOINT = "violin";
24
31
  const dataset = useDataset();
@@ -117,17 +124,29 @@ export function Violin(_ref) {
117
124
  setLayout(fetchedData.layout);
118
125
  }
119
126
  }, [fetchedData, hasSelections, isPending, serverError]);
127
+ const customModeBarButtons = _.compact([showObsBtn && ObsPlotlyToolbar({
128
+ onClick: setShowObs
129
+ }), showVarsBtn && VarPlotlyToolbar({
130
+ onClick: setShowVars
131
+ }), showCtrlsBtn && ControlsPlotlyToolbar({
132
+ onClick: setShowControls
133
+ })]);
134
+ const modeBarButtons = customModeBarButtons.length ? [customModeBarButtons, PLOTLY_MODEBAR_BUTTONS] : [PLOTLY_MODEBAR_BUTTONS];
120
135
  if (!serverError) {
121
136
  if (hasSelections) {
122
137
  return /*#__PURE__*/React.createElement("div", {
123
- className: "cherita-violin position-relative"
138
+ className: "cherita-plot cherita-violin position-relative"
124
139
  }, isPending && /*#__PURE__*/React.createElement(LoadingSpinner, null), /*#__PURE__*/React.createElement(Plot, {
125
140
  data: data,
126
141
  layout: layout,
127
142
  useResizeHandler: true,
128
143
  style: {
129
- maxWidth: "100%",
130
- maxHeight: "100%"
144
+ width: "100%",
145
+ height: "100%"
146
+ },
147
+ config: {
148
+ displaylogo: false,
149
+ modeBarButtons: modeBarButtons
131
150
  }
132
151
  }), (fetchedData === null || fetchedData === void 0 ? void 0 : fetchedData.resampled) && /*#__PURE__*/React.createElement(Alert, {
133
152
  variant: "warning"
@@ -142,9 +161,21 @@ export function Violin(_ref) {
142
161
  className: "cherita-violin"
143
162
  }, mode === VIOLIN_MODES.MULTIKEY && /*#__PURE__*/React.createElement(Alert, {
144
163
  variant: "light"
145
- }, "Select features"), mode === VIOLIN_MODES.GROUPBY && /*#__PURE__*/React.createElement(Alert, {
164
+ }, "Select", " ", showVarsBtn ? /*#__PURE__*/React.createElement(Button, {
165
+ variant: "link",
166
+ className: "border-0 p-0 align-baseline",
167
+ onClick: setShowVars
168
+ }, "features") : "features"), mode === VIOLIN_MODES.GROUPBY && /*#__PURE__*/React.createElement(Alert, {
146
169
  variant: "light"
147
- }, "Select categories and a feature"));
170
+ }, "Select", " ", showObsBtn ? /*#__PURE__*/React.createElement(Button, {
171
+ variant: "link",
172
+ className: "border-0 p-0 align-baseline",
173
+ onClick: setShowObs
174
+ }, "categories") : "categories", " ", "and a", " ", showVarsBtn ? /*#__PURE__*/React.createElement(Button, {
175
+ variant: "link",
176
+ className: "border-0 p-0 align-baseline",
177
+ onClick: setShowVars
178
+ }, "feature") : "feature"));
148
179
  } else {
149
180
  return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Alert, {
150
181
  variant: "danger"
@@ -1,4 +1,11 @@
1
1
  export const LOCAL_STORAGE_KEY = "CHERITA";
2
+ export const PLOT_TYPES = {
3
+ SCATTERPLOT: "scatterplot",
4
+ DOTPLOT: "dotplot",
5
+ HEATMAP: "heatmap",
6
+ MATRIXPLOT: "matrixplot",
7
+ VIOLINPLOT: "violinplot"
8
+ };
2
9
  export const COLOR_ENCODINGS = {
3
10
  VAR: "var",
4
11
  OBS: "obs"
@@ -85,4 +92,9 @@ export const PSEUDOSPATIAL_CATEGORICAL_MODES = {
85
92
 
86
93
  // `default` cols to be shown out of accordion, at top of obslist
87
94
  // default values from cellxgene schema
88
- export const DEFAULT_OBS_GROUP = ["assay", "cell_type", "development_stage", "disease", "donor_id", "organism", "self_reported_ethnicity", "sex", "suspension_type", "tissue", "tissue_type"];
95
+ export const DEFAULT_OBS_GROUP = ["assay", "cell_type", "development_stage", "disease", "donor_id", "organism", "self_reported_ethnicity", "sex", "suspension_type", "tissue", "tissue_type"];
96
+ export const PLOTLY_MODEBAR_BUTTONS = ["toImage", "zoom2d", "pan2d", "zoomIn2d", "zoomOut2d", "autoScale2d", "resetScale2d"];
97
+ export const BREAKPOINTS = {
98
+ LG: "(max-width: 991.98px)",
99
+ XL: "(max-width: 1199.98px)"
100
+ };
package/dist/esm/index.js CHANGED
@@ -1,22 +1,22 @@
1
1
  export { Dotplot } from "./components/dotplot/Dotplot";
2
2
  export { DotplotControls } from "./components/dotplot/DotplotControls";
3
+ export { FullPage } from "./components/full-page/FullPage";
3
4
  export { Heatmap } from "./components/heatmap/Heatmap";
4
5
  export { HeatmapControls } from "./components/heatmap/HeatmapControls";
5
6
  export { Matrixplot } from "./components/matrixplot/Matrixplot";
6
7
  export { MatrixplotControls } from "./components/matrixplot/MatrixplotControls";
7
8
  export { ObsColsList } from "./components/obs-list/ObsList";
8
9
  export { ObsmKeysList } from "./components/obsm-list/ObsmList";
10
+ export { OffcanvasControls, OffcanvasObs, OffcanvasObsm, OffcanvasVars } from "./components/offcanvas";
9
11
  export { Pseudospatial } from "./components/pseudospatial/Pseudospatial";
10
12
  export { Scatterplot } from "./components/scatterplot/Scatterplot";
11
13
  export { ScatterplotControls } from "./components/scatterplot/ScatterplotControls";
12
14
  export { SearchBar } from "./components/search-bar/SearchBar";
15
+ export { Toolbar } from "./components/toolbar/Toolbar";
13
16
  export { VarNamesList } from "./components/var-list/VarList";
14
17
  export { Violin } from "./components/violin/Violin";
15
18
  export { ViolinControls } from "./components/violin/ViolinControls";
16
- export { FullPage, FullPagePlots, FullPageScatterplot } from "./components/full-page/FullPage";
17
- export { FullPagePseudospatial } from "./components/full-page/FullPagePseudospatial";
18
- export { OffcanvasControls, OffcanvasObs, OffcanvasObsm, OffcanvasVars } from "./components/offcanvas";
19
19
  export { COLORSCALES } from "./constants/colorscales";
20
- export { SELECTION_MODES, VIOLIN_MODES } from "./constants/constants";
20
+ export { PLOT_TYPES, SELECTION_MODES, VIOLIN_MODES } from "./constants/constants";
21
21
  export { DatasetProvider } from "./context/DatasetContext";
22
22
  export { FilterProvider } from "./context/FilterContext";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haniffalab/cherita-react",
3
- "version": "1.3.0-dev.2025-05-28.9afc380f",
3
+ "version": "1.3.0-dev.2025-06-04.d986a94b",
4
4
  "author": "Haniffa Lab",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -126,5 +126,5 @@
126
126
  "url": "https://github.com/haniffalab/cherita-react/issues"
127
127
  },
128
128
  "homepage": "https://github.com/haniffalab/cherita-react#readme",
129
- "prereleaseSha": "9afc380fef6e4b57764414ea202fada84a34456f"
129
+ "prereleaseSha": "d986a94bdc972b9311bb9b027e3d08030fc30d79"
130
130
  }
package/scss/cherita.scss CHANGED
@@ -58,7 +58,6 @@ $prefix: "bs-" !default;
58
58
  /* End scrollbar styling */
59
59
 
60
60
  .cherita-container-plot {
61
- margin-top: 76px;
62
61
  padding: 20px;
63
62
  position: relative;
64
63
  min-height: 400px;
@@ -1,5 +1,6 @@
1
1
  .cherita-app {
2
2
  position: relative;
3
+ width: 100%;
3
4
  }
4
5
 
5
6
  .cherita-app {
@@ -50,6 +51,21 @@
50
51
  overflow-y: hidden;
51
52
  }
52
53
 
54
+ .sidebar-plotselector {
55
+ padding: 6px;
56
+ border-bottom: 1px solid #dee2e6;
57
+
58
+ .plotselector-icon {
59
+ padding-bottom: 2px;
60
+ cursor: pointer;
61
+
62
+ .active {
63
+ opacity: 1;
64
+ border-bottom: 2px solid #007bff;
65
+ }
66
+ }
67
+ }
68
+
53
69
  .sidebar-pseudospatial {
54
70
  padding: 10px;
55
71
  border-bottom: 1px solid #dee2e6;
@@ -108,6 +124,58 @@
108
124
  border-left: 1px solid #dee2e6;
109
125
  }
110
126
 
127
+ .cherita-app-canvas {
128
+ .cherita-plot {
129
+ height: 100%;
130
+ min-height: 400px;
131
+ }
132
+ }
133
+
134
+ .cherita-app-container {
135
+ @extend .p-0;
136
+ display: flex;
137
+ flex-wrap: nowrap;
138
+ width: 100%;
139
+ height: 100%;
140
+
141
+ .cherita-app-obs {
142
+ flex: 0 0 auto;
143
+ min-width: 350px;
144
+ max-width: 20%;
145
+ overflow-y: auto;
146
+ }
147
+
148
+ .cherita-app-canvas {
149
+ @extend .p-1;
150
+ flex: 1 1 auto;
151
+ min-width: 400px;
152
+ position: relative;
153
+ max-height: 100%;
154
+ display: flex;
155
+ flex-direction: column;
156
+
157
+ .cherita-navbar {
158
+ @extend .m-0;
159
+ @extend .d-block;
160
+ position: relative;
161
+ }
162
+ }
163
+
164
+ .cherita-app-sidebar {
165
+ flex: 0 0 auto;
166
+ min-width: 350px;
167
+ max-width: 20%;
168
+ position: relative;
169
+ }
170
+
171
+ @media (max-width: 1400px) {
172
+ .cherita-app-obs,
173
+ .cherita-app-sidebar {
174
+ max-width: 25%;
175
+ }
176
+ }
177
+ }
178
+
111
179
  .ps-xs-1 {
112
180
  padding-left: 0.15rem !important;
113
- }
181
+ }
@@ -1,30 +1,35 @@
1
1
  .js-plotly-plot .plotly .modebar {
2
- border-radius: 5px;
3
- background-color: rgba(0, 0, 0, 0.6);
4
- padding: 0 4px !important;
5
2
 
6
3
  .modebar-group {
7
- margin: 0 !important;
8
- padding: 0 !important;
9
- background-color: transparent !important;
4
+ @extend .bg-primary;
5
+ @extend .mx-1;
6
+ border-radius: 5px;
7
+ padding: 4px !important;
10
8
 
11
9
  .modebar-btn {
12
- fill: white !important; /* Ensures white icons */
13
- color: white !important; /* Ensures text/icons are visible */
10
+ display: inline-flex;
11
+ justify-content: center;
14
12
  position: relative;
15
- font-size: 16px;
16
- padding: 4px;
13
+ font-size: 1.25rem;
14
+ padding: 0.25rem;
17
15
  height: auto;
18
16
  cursor: pointer;
19
17
  line-height: normal;
20
18
 
21
19
  svg {
22
20
  position: relative;
23
- top: auto;
24
- bottom: auto;
25
- left: auto;
26
- right: auto;
21
+ top: 1px;
22
+
23
+ path {
24
+ fill: white !important;
25
+ color: white !important;
26
+ }
27
27
  }
28
28
  }
29
29
  }
30
30
  }
31
+
32
+ .js-plotly-plot .plotly .modebar--hover > :not(.watermark) {
33
+ opacity: 0.5;
34
+ transition: opacity 0.3s;
35
+ }