@haniffalab/cherita-react 2.0.0 → 2.1.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 (67) hide show
  1. package/dist/cjs/components/dotplot/Dotplot.js +4 -5
  2. package/dist/cjs/components/dotplot/DotplotControls.js +7 -3
  3. package/dist/cjs/components/heatmap/Heatmap.js +4 -5
  4. package/dist/cjs/components/icons/HeatmapIcon.js +2 -2
  5. package/dist/cjs/components/matrixplot/Matrixplot.js +4 -5
  6. package/dist/cjs/components/obs-list/ObsItem.js +7 -7
  7. package/dist/cjs/components/offcanvas/OffCanvas.js +7 -4
  8. package/dist/cjs/components/plot/PlotTypeSelector.js +49 -10
  9. package/dist/cjs/components/pseudospatial/Pseudospatial.js +8 -5
  10. package/dist/cjs/components/scatterplot/Scatterplot.js +134 -136
  11. package/dist/cjs/components/scatterplot/ScatterplotLayer.js +144 -0
  12. package/dist/cjs/components/scatterplot/SpatialControls.js +7 -4
  13. package/dist/cjs/components/scatterplot/Toolbox.js +8 -4
  14. package/dist/cjs/components/search-bar/SearchBar.js +51 -29
  15. package/dist/cjs/components/search-bar/SearchInfo.js +2 -2
  16. package/dist/cjs/components/search-bar/SearchResults.js +9 -6
  17. package/dist/cjs/components/toolbar/Toolbar.js +10 -65
  18. package/dist/cjs/components/var-list/VarItem.js +4 -6
  19. package/dist/cjs/components/var-list/VarList.js +17 -9
  20. package/dist/cjs/components/var-list/VarListToolbar.js +1 -1
  21. package/dist/cjs/components/var-list/VarSet.js +7 -5
  22. package/dist/cjs/components/violin/Violin.js +6 -7
  23. package/dist/cjs/constants/constants.js +6 -3
  24. package/dist/cjs/context/DatasetContext.js +11 -2
  25. package/dist/cjs/context/SettingsContext.js +27 -2
  26. package/dist/cjs/helpers/color-helper.js +17 -12
  27. package/dist/cjs/index.js +0 -7
  28. package/dist/cjs/utils/Legend.js +6 -5
  29. package/dist/cjs/utils/requests.js +2 -2
  30. package/dist/cjs/views/ObservationFeature/StandardView.js +1 -1
  31. package/dist/cjs/views/PerturbationMap/ObsExplorer.js +11 -9
  32. package/dist/cjs/views/PerturbationMap/StandardView.js +2 -1
  33. package/dist/cjs/workers/scatterplotData.js +16 -0
  34. package/dist/esm/components/dotplot/Dotplot.js +5 -6
  35. package/dist/esm/components/dotplot/DotplotControls.js +6 -3
  36. package/dist/esm/components/heatmap/Heatmap.js +5 -6
  37. package/dist/esm/components/icons/HeatmapIcon.js +2 -2
  38. package/dist/esm/components/matrixplot/Matrixplot.js +5 -6
  39. package/dist/esm/components/obs-list/ObsItem.js +7 -7
  40. package/dist/esm/components/offcanvas/OffCanvas.js +7 -4
  41. package/dist/esm/components/plot/PlotTypeSelector.js +49 -10
  42. package/dist/esm/components/pseudospatial/Pseudospatial.js +8 -5
  43. package/dist/esm/components/scatterplot/Scatterplot.js +132 -134
  44. package/dist/esm/components/scatterplot/ScatterplotLayer.js +137 -0
  45. package/dist/esm/components/scatterplot/SpatialControls.js +7 -4
  46. package/dist/esm/components/scatterplot/Toolbox.js +8 -4
  47. package/dist/esm/components/search-bar/SearchBar.js +52 -30
  48. package/dist/esm/components/search-bar/SearchInfo.js +2 -2
  49. package/dist/esm/components/search-bar/SearchResults.js +9 -6
  50. package/dist/esm/components/toolbar/Toolbar.js +9 -63
  51. package/dist/esm/components/var-list/VarItem.js +4 -6
  52. package/dist/esm/components/var-list/VarList.js +17 -9
  53. package/dist/esm/components/var-list/VarListToolbar.js +1 -1
  54. package/dist/esm/components/var-list/VarSet.js +7 -5
  55. package/dist/esm/components/violin/Violin.js +7 -8
  56. package/dist/esm/constants/constants.js +5 -2
  57. package/dist/esm/context/DatasetContext.js +11 -2
  58. package/dist/esm/context/SettingsContext.js +27 -2
  59. package/dist/esm/helpers/color-helper.js +17 -12
  60. package/dist/esm/index.js +0 -1
  61. package/dist/esm/utils/Legend.js +6 -5
  62. package/dist/esm/utils/requests.js +2 -2
  63. package/dist/esm/views/ObservationFeature/StandardView.js +1 -1
  64. package/dist/esm/views/PerturbationMap/ObsExplorer.js +11 -9
  65. package/dist/esm/views/PerturbationMap/StandardView.js +2 -1
  66. package/dist/esm/workers/scatterplotData.js +10 -0
  67. package/package.json +6 -3
@@ -1,4 +1,5 @@
1
1
  import { Button, ButtonGroup, OverlayTrigger, Tooltip } from 'react-bootstrap';
2
+ import { useDataset } from '../../context/DatasetContext';
2
3
  import { formatNumerical } from '../../utils/string';
3
4
  import { ObsmKeysList } from '../obsm-list/ObsmList';
4
5
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
@@ -9,6 +10,9 @@ export function Toolbox(_ref) {
9
10
  slicedLength,
10
11
  setHasObsm
11
12
  } = _ref;
13
+ const {
14
+ obsLabel
15
+ } = useDataset();
12
16
  return /*#__PURE__*/_jsx("div", {
13
17
  className: "cherita-toolbox",
14
18
  children: /*#__PURE__*/_jsxs(ButtonGroup, {
@@ -18,7 +22,7 @@ export function Toolbox(_ref) {
18
22
  placement: "top",
19
23
  overlay: /*#__PURE__*/_jsxs(Tooltip, {
20
24
  id: "tooltip-dropped-mode",
21
- children: ["You have selected ", formatNumerical(slicedLength), " out of", ' ', formatNumerical(obsLength), " cells"]
25
+ children: ["You have selected ", formatNumerical(slicedLength), " out of", ' ', formatNumerical(obsLength), " ", obsLabel.plural]
22
26
  }),
23
27
  children: /*#__PURE__*/_jsxs(Button, {
24
28
  size: "sm",
@@ -27,13 +31,13 @@ export function Toolbox(_ref) {
27
31
  cursor: 'default'
28
32
  },
29
33
  "aria-disabled": "true",
30
- children: [formatNumerical(slicedLength), " of ", formatNumerical(obsLength), ' ', "cells"]
34
+ children: [formatNumerical(slicedLength), " of ", formatNumerical(obsLength), ' ', obsLabel.plural]
31
35
  })
32
36
  }) : /*#__PURE__*/_jsx(OverlayTrigger, {
33
37
  placement: "top",
34
38
  overlay: /*#__PURE__*/_jsxs(Tooltip, {
35
39
  id: "tooltip-dropped-mode",
36
- children: ["You are viewing ", formatNumerical(obsLength), " cells"]
40
+ children: ["You are viewing ", formatNumerical(obsLength), " ", obsLabel.plural]
37
41
  }),
38
42
  children: /*#__PURE__*/_jsxs(Button, {
39
43
  size: "sm",
@@ -42,7 +46,7 @@ export function Toolbox(_ref) {
42
46
  cursor: 'default'
43
47
  },
44
48
  "aria-disabled": "true",
45
- children: [formatNumerical(obsLength), " cells"]
49
+ children: [formatNumerical(obsLength), " ", obsLabel.plural]
46
50
  })
47
51
  }))]
48
52
  })
@@ -3,7 +3,7 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
3
3
  function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
4
4
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
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
- import { useState } from 'react';
6
+ import { useState, useRef, useCallback, useMemo } from 'react';
7
7
  import CloseIcon from '@mui/icons-material/Close';
8
8
  import SearchIcon from '@mui/icons-material/Search';
9
9
  import _ from 'lodash';
@@ -16,28 +16,41 @@ import Tab from 'react-bootstrap/Tab';
16
16
  import { DiseaseInfo, VarInfo } from './SearchInfo';
17
17
  import { DiseasesSearchResults, ObsSearchResults, VarSearchResults } from './SearchResults';
18
18
  import { COLOR_ENCODINGS } from '../../constants/constants';
19
+ import { useDataset } from '../../context/DatasetContext';
19
20
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
20
- const select = (dispatch, item) => {
21
- dispatch({
22
- type: 'select.var',
23
- var: item
24
- });
25
- dispatch({
26
- type: 'select.multivar',
27
- var: item
28
- });
29
- dispatch({
30
- type: 'set.colorEncoding',
31
- value: COLOR_ENCODINGS.VAR
32
- });
33
- };
34
- const debounceSelect = _.debounce(select, 500);
35
- function onVarSelect(dispatch, item) {
36
- dispatch({
37
- type: 'add.var',
38
- var: item
39
- });
40
- debounceSelect(dispatch, item);
21
+ function useVarSelect() {
22
+ const pendingVars = useRef(new Map());
23
+ const debouncedSelect = useMemo(() => _.debounce(dispatch => {
24
+ const vars = [...pendingVars.current.values()];
25
+ pendingVars.current.clear();
26
+ dispatch({
27
+ type: 'select.multivar.batch',
28
+ vars: vars
29
+ });
30
+ const lastItem = vars[vars.length - 1];
31
+ if (lastItem) {
32
+ dispatch({
33
+ type: 'select.var',
34
+ var: lastItem
35
+ });
36
+ dispatch({
37
+ type: 'set.colorEncoding',
38
+ value: COLOR_ENCODINGS.VAR
39
+ });
40
+ }
41
+ }, 500), []);
42
+ const onVarSelect = useCallback((dispatch, item) => {
43
+ dispatch({
44
+ type: 'add.var',
45
+ var: item
46
+ });
47
+ pendingVars.current.set(item.name, item);
48
+ debouncedSelect(dispatch);
49
+ }, [debouncedSelect]);
50
+ return {
51
+ onVarSelect,
52
+ debouncedSelect
53
+ };
41
54
  }
42
55
  function addVarSet(dispatch, _ref) {
43
56
  let {
@@ -65,7 +78,7 @@ export function SearchModal(_ref2) {
65
78
  text,
66
79
  setText,
67
80
  displayText,
68
- handleSelect = onVarSelect,
81
+ handleVarSelect,
69
82
  searchVar,
70
83
  searchDiseases,
71
84
  searchObs
@@ -85,6 +98,7 @@ export function SearchModal(_ref2) {
85
98
  const [varResultsLength, setVarResultsLength] = useState(null);
86
99
  const [diseaseResultsLength, setDiseaseResultsLength] = useState(null);
87
100
  const [obsResultsLength, setObsResultsLength] = useState(null);
101
+ const dataset = useDataset();
88
102
  return /*#__PURE__*/_jsxs(Modal, {
89
103
  show: show,
90
104
  onHide: handleClose,
@@ -160,7 +174,7 @@ export function SearchModal(_ref2) {
160
174
  children: [searchVar && /*#__PURE__*/_jsx(Nav.Item, {
161
175
  children: /*#__PURE__*/_jsxs(Nav.Link, {
162
176
  eventKey: FEATURE_TYPE.VAR,
163
- children: ["Genes", ' ', !!varResultsLength && "(".concat(varResultsLength, ")")]
177
+ children: [_.capitalize(dataset.varLabel.plural), ' ', !!varResultsLength && "(".concat(varResultsLength, ")")]
164
178
  })
165
179
  }), searchDiseases && /*#__PURE__*/_jsx(Nav.Item, {
166
180
  children: /*#__PURE__*/_jsxs(Nav.Link, {
@@ -170,7 +184,7 @@ export function SearchModal(_ref2) {
170
184
  }), searchObs && /*#__PURE__*/_jsx(Nav.Item, {
171
185
  children: /*#__PURE__*/_jsxs(Nav.Link, {
172
186
  eventKey: FEATURE_TYPE.OBS,
173
- children: ["Genes", ' ', !!obsResultsLength && "(".concat(obsResultsLength, ")")]
187
+ children: [_.capitalize(dataset.obsLabel.plural), ' ', !!obsResultsLength && "(".concat(obsResultsLength, ")")]
174
188
  })
175
189
  })]
176
190
  })
@@ -182,7 +196,7 @@ export function SearchModal(_ref2) {
182
196
  eventKey: FEATURE_TYPE.VAR,
183
197
  children: /*#__PURE__*/_jsx(VarSearchResults, {
184
198
  text: text,
185
- handleSelect: handleSelect,
199
+ handleSelect: handleVarSelect,
186
200
  selectedResult: selectedResult.var,
187
201
  setSelectedResult: item => setSelectedResult(prev => {
188
202
  return _objectSpread(_objectSpread({}, prev), {}, {
@@ -207,7 +221,6 @@ export function SearchModal(_ref2) {
207
221
  eventKey: FEATURE_TYPE.OBS,
208
222
  children: /*#__PURE__*/_jsx(ObsSearchResults, {
209
223
  text: text,
210
- handleSelect: handleSelect,
211
224
  selectedResult: selectedResult.obs,
212
225
  setSelectedResult: item => setSelectedResult(prev => {
213
226
  return _objectSpread(_objectSpread({}, prev), {}, {
@@ -230,7 +243,7 @@ export function SearchModal(_ref2) {
230
243
  if (tab === FEATURE_TYPE.DISEASE) {
231
244
  return /*#__PURE__*/_jsx(DiseaseInfo, {
232
245
  disease: selectedResult.disease,
233
- handleSelect: handleSelect,
246
+ handleSelect: handleVarSelect,
234
247
  addVarSet: addVarSet
235
248
  });
236
249
  } else if (tab === FEATURE_TYPE.OBS) {
@@ -259,8 +272,13 @@ export function SearchBar(_ref3) {
259
272
  searchObs = false
260
273
  } = _ref3;
261
274
  const [text, setText] = useState('');
262
- const displayText = [...(searchVar ? ['features'] : []), ...(searchDiseases ? ['diseases'] : [])].join(' and ');
275
+ const dataset = useDataset();
276
+ const displayText = [...(searchVar ? [dataset.varLabel.plural] : []), ...(searchDiseases ? ['diseases'] : []), ...(searchObs ? [dataset.obsLabel.plural] : [])].join(' and ');
263
277
  const [showModal, setShowModal] = useState(false);
278
+ const {
279
+ onVarSelect,
280
+ debouncedSelect
281
+ } = useVarSelect();
264
282
  return /*#__PURE__*/_jsxs("div", {
265
283
  children: [/*#__PURE__*/_jsx(Form, {
266
284
  onSubmit: e => {
@@ -286,7 +304,11 @@ export function SearchBar(_ref3) {
286
304
  searchVar: searchVar,
287
305
  searchDiseases: searchDiseases,
288
306
  searchObs: searchObs,
289
- handleClose: () => setShowModal(false)
307
+ handleVarSelect: onVarSelect,
308
+ handleClose: () => {
309
+ debouncedSelect.flush();
310
+ setShowModal(false);
311
+ }
290
312
  })]
291
313
  });
292
314
  }
@@ -176,8 +176,8 @@ export function DiseaseInfo(_ref2) {
176
176
  return /*#__PURE__*/_jsxs("div", {
177
177
  children: [/*#__PURE__*/_jsx("h5", {
178
178
  children: disease.disease_name
179
- }), /*#__PURE__*/_jsx("h6", {
180
- children: "Implicated genes"
179
+ }), /*#__PURE__*/_jsxs("h6", {
180
+ children: ["Implicated ", dataset.varLabel.plural]
181
181
  }), isPending ? /*#__PURE__*/_jsx("p", {
182
182
  children: "Loading..."
183
183
  }) : /*#__PURE__*/_jsxs(_Fragment, {
@@ -8,6 +8,7 @@ import { faPlus } from '@fortawesome/free-solid-svg-icons';
8
8
  import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
9
9
  import _ from 'lodash';
10
10
  import { Button, ListGroup } from 'react-bootstrap';
11
+ import { useDataset } from '../../context/DatasetContext';
11
12
  import { useSettingsDispatch } from '../../context/SettingsContext';
12
13
  import { useDiseaseSearch, useObsSearch, useVarSearch } from '../../utils/search';
13
14
  import { VirtualizedList } from '../../utils/VirtualizedList';
@@ -89,9 +90,10 @@ function SearchResultsBase(_ref) {
89
90
  });
90
91
  }
91
92
  export function VarSearchResults(props) {
93
+ const dataset = useDataset();
92
94
  return /*#__PURE__*/_jsx(SearchResultsBase, _objectSpread(_objectSpread({}, props), {}, {
93
95
  searchHook: useVarSearch,
94
- emptyLabel: "Search features",
96
+ emptyLabel: "Search for ".concat(dataset.varLabel.plural),
95
97
  itemRenderer: _ref2 => {
96
98
  var _item$index, _item$index2;
97
99
  let {
@@ -129,17 +131,18 @@ export function VarSearchResults(props) {
129
131
  }));
130
132
  }
131
133
  export function ObsSearchResults(props) {
134
+ const dataset = useDataset();
132
135
  return /*#__PURE__*/_jsx(SearchResultsBase, _objectSpread(_objectSpread({}, props), {}, {
133
136
  searchHook: useObsSearch,
134
- emptyLabel: "Search observations",
137
+ emptyLabel: "Search for ".concat(dataset.obsLabel.plural),
135
138
  itemRenderer: _ref3 => {
136
139
  let {
137
140
  item,
138
141
  dispatch,
139
- handleClose,
140
142
  selectedResult,
141
143
  setSelectedResult,
142
- isStale
144
+ isStale,
145
+ handleClose
143
146
  } = _ref3;
144
147
  const onObsSelect = (dispatch, item, closeModal) => {
145
148
  dispatch({
@@ -163,7 +166,7 @@ export function ObsSearchResults(props) {
163
166
  variant: "outline-secondary",
164
167
  title: "Add to list",
165
168
  disabled: isStale,
166
- onClick: () => onObsSelect(dispatch, item, props.handleClose),
169
+ onClick: () => onObsSelect(dispatch, item, handleClose),
167
170
  children: /*#__PURE__*/_jsx(FontAwesomeIcon, {
168
171
  icon: faPlus
169
172
  })
@@ -177,7 +180,7 @@ export function ObsSearchResults(props) {
177
180
  export function DiseasesSearchResults(props) {
178
181
  return /*#__PURE__*/_jsx(SearchResultsBase, _objectSpread(_objectSpread({}, props), {}, {
179
182
  searchHook: useDiseaseSearch,
180
- emptyLabel: "Search diseases",
183
+ emptyLabel: "Search for diseases",
181
184
  overscan: 250,
182
185
  estimateSize: () => 32,
183
186
  itemRenderer: _ref4 => {
@@ -1,75 +1,21 @@
1
1
  import { faList, faSearch, faSliders } from '@fortawesome/free-solid-svg-icons';
2
2
  import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
3
+ import _ from 'lodash';
3
4
  import { Container, Nav, Navbar, Button, ButtonGroup } from 'react-bootstrap';
5
+ import { useDataset } from '../../context/DatasetContext';
4
6
  import usePlotVisibility from '../../utils/usePlotVisibility';
5
7
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
6
- export const Toolbar = _ref => {
7
- let {
8
- setShowCategories,
9
- setShowSearch,
10
- setShowControls,
11
- Fullscreen
12
- } = _ref;
13
- const {
14
- showCategoriesBtn,
15
- showSearchBtn
16
- } = usePlotVisibility(isFullscreen);
17
- return /*#__PURE__*/_jsx(Navbar, {
18
- expand: "md",
19
- bg: "primary",
20
- variant: "dark",
21
- className: "cherita-navbar",
22
- children: /*#__PURE__*/_jsxs(Container, {
23
- fluid: true,
24
- children: [/*#__PURE__*/_jsx(Navbar.Toggle, {
25
- "aria-controls": "navbarScroll"
26
- }), /*#__PURE__*/_jsx(Navbar.Collapse, {
27
- id: "navbarScroll",
28
- children: /*#__PURE__*/_jsxs(Nav, {
29
- navbarScroll: true,
30
- children: [showCategoriesBtn && /*#__PURE__*/_jsx(Nav.Item, {
31
- className: "me-2",
32
- children: /*#__PURE__*/_jsxs(Nav.Link, {
33
- onClick: () => setShowCategories(true),
34
- children: [/*#__PURE__*/_jsx(FontAwesomeIcon, {
35
- icon: faList,
36
- className: "me-2"
37
- }), "Explore Categories"]
38
- })
39
- }), showSearchBtn && /*#__PURE__*/_jsx(Nav.Item, {
40
- className: "me-2",
41
- children: /*#__PURE__*/_jsxs(Nav.Link, {
42
- onClick: () => setShowSearch(true),
43
- children: [/*#__PURE__*/_jsx(FontAwesomeIcon, {
44
- icon: faSearch,
45
- className: "me-2"
46
- }), "Search Genes"]
47
- })
48
- }), /*#__PURE__*/_jsx(Nav.Item, {
49
- className: "me-2",
50
- children: /*#__PURE__*/_jsxs(Nav.Link, {
51
- onClick: () => setShowControls(true),
52
- children: [/*#__PURE__*/_jsx(FontAwesomeIcon, {
53
- icon: faSliders,
54
- className: "me-2"
55
- }), "Controls"]
56
- })
57
- }), ' ']
58
- })
59
- })]
60
- })
61
- });
62
- };
63
- export const PlotlyToolbar = _ref2 => {
8
+ export const PlotlyToolbar = _ref => {
64
9
  let {
65
10
  setShowCategories,
66
11
  setShowSearch,
67
12
  isFullscreen
68
- } = _ref2;
13
+ } = _ref;
69
14
  const {
70
15
  showCategoriesBtn,
71
16
  showSearchBtn
72
17
  } = usePlotVisibility(isFullscreen);
18
+ const dataset = useDataset();
73
19
  return /*#__PURE__*/_jsxs(ButtonGroup, {
74
20
  children: [showCategoriesBtn && /*#__PURE__*/_jsxs(Button, {
75
21
  variant: "primary",
@@ -82,18 +28,18 @@ export const PlotlyToolbar = _ref2 => {
82
28
  }), showSearchBtn && /*#__PURE__*/_jsxs(Button, {
83
29
  variant: "primary",
84
30
  onClick: () => setShowSearch(true),
85
- title: "Search Genes",
31
+ title: "Search ".concat(dataset.varLabel.plural),
86
32
  children: [/*#__PURE__*/_jsx(FontAwesomeIcon, {
87
33
  icon: faSearch,
88
34
  className: "me-1"
89
- }), "Genes"]
35
+ }), _.capitalize(dataset.varLabel.plural)]
90
36
  })]
91
37
  });
92
38
  };
93
- export const PlotlyModebarControls = _ref3 => {
39
+ export const PlotlyModebarControls = _ref2 => {
94
40
  let {
95
41
  onClick
96
- } = _ref3;
42
+ } = _ref2;
97
43
  return {
98
44
  name: 'Controls',
99
45
  icon: {
@@ -147,7 +147,7 @@ export function SelectionItem(_ref3) {
147
147
  className: "ms-auto d-flex align-items-center gap-1",
148
148
  children: [hasDiseaseInfo && /*#__PURE__*/_jsx(MoreVert, {}), /*#__PURE__*/_jsx(VarHistogram, {
149
149
  item: item
150
- }), showSetColorEncoding && /*#__PURE__*/_jsxs(Button, {
150
+ }), showSetColorEncoding && /*#__PURE__*/_jsx(Button, {
151
151
  type: "button",
152
152
  variant: isActive ? 'primary' : isNotInData ? 'outline-secondary' : 'outline-primary',
153
153
  className: "m-0 p-0 px-1",
@@ -157,11 +157,9 @@ export function SelectionItem(_ref3) {
157
157
  },
158
158
  disabled: isNotInData,
159
159
  title: isNotInData ? 'Not present in data' : isMultiple ? isActive ? 'Remove from plot' : 'Add to plot' : 'Set as color encoding',
160
- children: [!isMultiple && /*#__PURE__*/_jsx(FontAwesomeIcon, {
161
- icon: faDroplet
162
- }), isMultiple && /*#__PURE__*/_jsx(FontAwesomeIcon, {
163
- icon: faCheck
164
- })]
160
+ children: /*#__PURE__*/_jsx(FontAwesomeIcon, {
161
+ icon: isMultiple ? faCheck : faDroplet
162
+ })
165
163
  }, item.matrix_index), showRemove && /*#__PURE__*/_jsx(Button, {
166
164
  type: "button",
167
165
  className: "m-0 p-0 px-1",
@@ -58,25 +58,33 @@ export const sortMeans = (i, means) => {
58
58
  return means[i.name] || _.min(_.values(means)) - 1;
59
59
  };
60
60
  export function VarNamesList(_ref) {
61
+ var _selectedVar$matrix_i;
61
62
  let {
62
- mode = SELECTION_MODES.SINGLE,
63
- displayName = 'genes'
63
+ mode = SELECTION_MODES.SINGLE
64
64
  } = _ref;
65
65
  const settings = useSettings();
66
66
  const dispatch = useSettingsDispatch();
67
+ const dataset = useDataset();
67
68
  const selectedVar = useSelectedVar();
68
69
  const selectedMultiVar = useSelectedMultiVar();
69
70
  const settingsVars = useSettingsVars();
70
- const [active, setActive] = useState(mode === SELECTION_MODES.SINGLE ? (selectedVar === null || selectedVar === void 0 ? void 0 : selectedVar.matrix_index) || (selectedVar === null || selectedVar === void 0 ? void 0 : selectedVar.name) : selectedMultiVar.map(i => i.matrix_index || i.name));
71
+ const [active, setActive] = useState(mode === SELECTION_MODES.SINGLE ? (_selectedVar$matrix_i = selectedVar === null || selectedVar === void 0 ? void 0 : selectedVar.matrix_index) !== null && _selectedVar$matrix_i !== void 0 ? _selectedVar$matrix_i : selectedVar === null || selectedVar === void 0 ? void 0 : selectedVar.name : selectedMultiVar.map(i => {
72
+ var _i$matrix_index;
73
+ return (_i$matrix_index = i.matrix_index) !== null && _i$matrix_index !== void 0 ? _i$matrix_index : i.name;
74
+ }));
71
75
  const [sortedVars, setSortedVars] = useState([]);
72
76
  useEffect(() => {
73
77
  if (mode === SELECTION_MODES.SINGLE) {
74
- setActive((selectedVar === null || selectedVar === void 0 ? void 0 : selectedVar.matrix_index) || (selectedVar === null || selectedVar === void 0 ? void 0 : selectedVar.name));
78
+ var _selectedVar$matrix_i2;
79
+ setActive((_selectedVar$matrix_i2 = selectedVar === null || selectedVar === void 0 ? void 0 : selectedVar.matrix_index) !== null && _selectedVar$matrix_i2 !== void 0 ? _selectedVar$matrix_i2 : selectedVar === null || selectedVar === void 0 ? void 0 : selectedVar.name);
75
80
  }
76
81
  }, [mode, selectedVar]);
77
82
  useEffect(() => {
78
83
  if (mode === SELECTION_MODES.MULTIPLE) {
79
- setActive(selectedMultiVar.map(i => i.matrix_index || i.name));
84
+ setActive(selectedMultiVar.map(i => {
85
+ var _i$matrix_index2;
86
+ return (_i$matrix_index2 = i.matrix_index) !== null && _i$matrix_index2 !== void 0 ? _i$matrix_index2 : i.name;
87
+ }));
80
88
  }
81
89
  }, [mode, selectedMultiVar]);
82
90
  const varMeans = useVarMean(settingsVars, settings.varSort.var.sort === VAR_SORT.MATRIX);
@@ -144,9 +152,9 @@ export function VarNamesList(_ref) {
144
152
  children: [/*#__PURE__*/_jsxs("div", {
145
153
  className: "d-flex justify-content-between mb-2",
146
154
  children: [/*#__PURE__*/_jsx("h5", {
147
- children: _.capitalize(displayName)
155
+ children: _.capitalize(dataset.varLabel.plural)
148
156
  }), /*#__PURE__*/_jsxs(ButtonGroup, {
149
- "aria-label": "Feature options",
157
+ "aria-label": "Options",
150
158
  size: "sm",
151
159
  children: [/*#__PURE__*/_jsx(Button, {
152
160
  variant: "info",
@@ -175,9 +183,9 @@ export function VarNamesList(_ref) {
175
183
  })]
176
184
  })]
177
185
  }), /*#__PURE__*/_jsx(_Fragment, {
178
- children: !varList.length ? /*#__PURE__*/_jsx(Alert, {
186
+ children: !varList.length ? /*#__PURE__*/_jsxs(Alert, {
179
187
  variant: "light",
180
- children: "Search for a feature."
188
+ children: ["Search for ", dataset.varLabel.plural]
181
189
  }) : /*#__PURE__*/_jsxs(_Fragment, {
182
190
  children: [/*#__PURE__*/_jsx(VarListToolbar, {}), /*#__PURE__*/_jsxs("div", {
183
191
  className: "overflow-auto flex-grow-1 modern-scrollbars",
@@ -40,7 +40,7 @@ export function VarListToolbar(_ref) {
40
40
  className: "d-flex justify-content-end align-items-center mb-2",
41
41
  children: /*#__PURE__*/_jsxs(ToggleButtonGroup, {
42
42
  name: "sortfeatures",
43
- "aria-label": "Sort features by",
43
+ "aria-label": "Sort by",
44
44
  size: "sm",
45
45
  type: "radio",
46
46
  children: [/*#__PURE__*/_jsx(ToggleButton, {
@@ -5,6 +5,7 @@ import _ from 'lodash';
5
5
  import { Button, Collapse, ListGroup, OverlayTrigger, Tooltip } from 'react-bootstrap';
6
6
  import { SelectionItem } from './VarItem';
7
7
  import { COLOR_ENCODINGS, SELECTION_MODES } from '../../constants/constants';
8
+ import { useDataset } from '../../context/DatasetContext';
8
9
  import { useSettings, useSettingsDispatch } from '../../context/SettingsContext';
9
10
  import { SearchModal } from '../search-bar/SearchBar';
10
11
 
@@ -26,6 +27,7 @@ function SelectionSet(_ref) {
26
27
  removeSetVar,
27
28
  isMultiple = false
28
29
  } = _ref;
30
+ const dataset = useDataset();
29
31
  const [openSet, setOpenSet] = useState(false);
30
32
  const [showModal, setShowModal] = useState(false);
31
33
  const [searchText, setSearchText] = useState('');
@@ -38,9 +40,9 @@ function SelectionSet(_ref) {
38
40
  })
39
41
  }, v.name);
40
42
  }) : /*#__PURE__*/_jsx(ListGroup.Item, {
41
- children: /*#__PURE__*/_jsx("div", {
43
+ children: /*#__PURE__*/_jsxs("div", {
42
44
  className: "text-muted",
43
- children: "No features in this set"
45
+ children: ["No ", dataset.varLabel.plural, " in this set"]
44
46
  })
45
47
  });
46
48
  return /*#__PURE__*/_jsxs(_Fragment, {
@@ -59,8 +61,8 @@ function SelectionSet(_ref) {
59
61
  className: "d-flex align-items-center gap-1",
60
62
  children: [/*#__PURE__*/_jsx(OverlayTrigger, {
61
63
  placement: "top",
62
- overlay: /*#__PURE__*/_jsx(Tooltip, {
63
- children: "This set represents the mean value of its features"
64
+ overlay: /*#__PURE__*/_jsxs(Tooltip, {
65
+ children: ["This set represents the mean value of its", ' ', dataset.varLabel.plural]
64
66
  }),
65
67
  children: /*#__PURE__*/_jsx(FontAwesomeIcon, {
66
68
  icon: faCircleInfo
@@ -131,7 +133,7 @@ function SelectionSet(_ref) {
131
133
  handleClose: () => setShowModal(false),
132
134
  text: searchText,
133
135
  setText: setSearchText,
134
- displayText: 'features',
136
+ displayText: dataset.varLabel.plural,
135
137
  handleSelect: (d, i) => {
136
138
  addVarToSet(d, set, i);
137
139
  },
@@ -9,7 +9,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
9
9
  import _ from 'lodash';
10
10
  import { Badge, Button } from 'react-bootstrap';
11
11
  import Plot from 'react-plotly.js';
12
- import { PLOTLY_MODEBAR_BUTTONS, VIOLIN_MODES } from '../../constants/constants';
12
+ import { PLOT_TYPES, 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';
@@ -27,7 +27,6 @@ export function Violin(_ref) {
27
27
  setShowCategories,
28
28
  setShowSearch,
29
29
  setShowControls,
30
- plotType,
31
30
  setPlotType,
32
31
  isFullscreen = false
33
32
  } = _ref;
@@ -168,7 +167,7 @@ export function Violin(_ref) {
168
167
  return /*#__PURE__*/_jsxs(PlotAlert, {
169
168
  variant: "info",
170
169
  heading: "Set up your violin plot",
171
- plotType: plotType,
170
+ plotType: PLOT_TYPES.VIOLINPLOT,
172
171
  setPlotType: setPlotType,
173
172
  children: [mode === VIOLIN_MODES.MULTIKEY && /*#__PURE__*/_jsxs("p", {
174
173
  className: "p-0 m-0",
@@ -176,8 +175,8 @@ export function Violin(_ref) {
176
175
  variant: "link",
177
176
  className: "border-0 p-0 align-baseline",
178
177
  onClick: setShowSearch,
179
- children: "features"
180
- }) : 'features', ' ', "to display their expression distributions across all observations."]
178
+ children: dataset.varLabel.plural
179
+ }) : dataset.varLabel.plural, ' ', "to display their ", dataset.valueLabel, " distributions across all", ' ', dataset.obsLabel.plural, "."]
181
180
  }), mode === VIOLIN_MODES.GROUPBY && /*#__PURE__*/_jsxs("p", {
182
181
  className: "p-0 m-0",
183
182
  children: ["Select a", ' ', showCategoriesBtn ? /*#__PURE__*/_jsx(Button, {
@@ -189,15 +188,15 @@ export function Violin(_ref) {
189
188
  variant: "link",
190
189
  className: "border-0 p-0 align-baseline",
191
190
  onClick: setShowSearch,
192
- children: "feature"
193
- }) : 'feature', ' ', "to view its distribution within each group."]
191
+ children: dataset.varLabel.singular
192
+ }) : dataset.varLabel.singular, ' ', "to view its distribution within each group."]
194
193
  })]
195
194
  });
196
195
  } else {
197
196
  return /*#__PURE__*/_jsx(PlotAlert, {
198
197
  variant: "danger",
199
198
  heading: "Error displaying the violin plot",
200
- plotType: plotType,
199
+ plotType: PLOT_TYPES.VIOLINPLOT,
201
200
  setPlotType: setPlotType,
202
201
  children: serverError.message || 'An unexpected error occurred while generating the plot.'
203
202
  });
@@ -93,11 +93,14 @@ export const PSEUDOSPATIAL_CATEGORICAL_MODES = {
93
93
  // `default` cols to be shown out of accordion, at top of obslist
94
94
  // default values from cellxgene schema
95
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'];
96
+ export const PLOTLY_MODEBAR_BUTTONS = ['toImage', 'zoom2d', 'pan2d', 'zoomIn2d', 'zoomOut2d', 'autoScale2d'];
97
97
  export const BREAKPOINTS = {
98
98
  LG: '(max-width: 991.98px)',
99
99
  XL: '(max-width: 1199.98px)'
100
100
  };
101
101
 
102
102
  // In order of priority
103
- export const DEFAULT_OBSM_KEYS = ['x_umap', 'x_tsne', 'x_scvi', 'x_pca'];
103
+ export const DEFAULT_OBSM_KEYS = ['x_umap', 'x_tsne', 'x_scvi', 'x_pca'];
104
+ export const GRAY = [214, 212, 212];
105
+ export const GRAY_MIX = 0.95;
106
+ export const GRAY_ALPHA = 0.75;
@@ -51,7 +51,7 @@ const persistOptions = {
51
51
  return false;
52
52
  }
53
53
  },
54
- buster: "2.0.0" || '0.0.0'
54
+ buster: "2.1.0" || '0.0.0'
55
55
  // @TODO: add maxAge and api version numbers as buster
56
56
  };
57
57
  const initialDataset = {
@@ -72,7 +72,16 @@ const initialDataset = {
72
72
  dataUrl: null,
73
73
  // for additional data in a remote .parquet file
74
74
  dataFilterCols: null // map of obs cols to filter data in .parquet file
75
- }
75
+ },
76
+ obsLabel: {
77
+ singular: 'cell',
78
+ plural: 'cells'
79
+ },
80
+ varLabel: {
81
+ singular: 'gene',
82
+ plural: 'genes'
83
+ },
84
+ valueLabel: 'expression'
76
85
  };
77
86
  export function DatasetProvider(_ref2) {
78
87
  let {