@haniffalab/cherita-react 0.2.0-dev.2024-09-26.775b9a06 → 0.2.0-dev.2024-09-26.1ea62883

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 (32) hide show
  1. package/dist/App.scss +77 -8
  2. package/dist/components/Offcanvas/index.js +6 -2
  3. package/dist/components/dotplot/Dotplot.js +22 -5
  4. package/dist/components/dotplot/DotplotControls.js +11 -10
  5. package/dist/components/heatmap/Heatmap.js +22 -5
  6. package/dist/components/matrixplot/Matrixplot.js +22 -5
  7. package/dist/components/matrixplot/MatrixplotControls.js +8 -7
  8. package/dist/components/obs-list/ObsItem.js +394 -0
  9. package/dist/components/obs-list/ObsList.js +116 -299
  10. package/dist/components/obs-list/ObsToolbar.js +76 -0
  11. package/dist/components/scatterplot/Legend.js +4 -3
  12. package/dist/components/scatterplot/Scatterplot.js +129 -61
  13. package/dist/components/scatterplot/Toolbox.js +3 -2
  14. package/dist/components/search-bar/SearchBar.js +18 -2
  15. package/dist/components/search-bar/SearchResults.js +8 -8
  16. package/dist/components/var-list/VarItem.js +316 -0
  17. package/dist/components/var-list/VarList.js +167 -149
  18. package/dist/components/var-list/VarSet.js +214 -0
  19. package/dist/components/violin/Violin.js +46 -13
  20. package/dist/components/violin/ViolinControls.js +13 -18
  21. package/dist/constants/constants.js +41 -29
  22. package/dist/context/DatasetContext.js +91 -31
  23. package/dist/context/FilterContext.js +76 -0
  24. package/dist/helpers/map-helper.js +20 -15
  25. package/dist/helpers/zarr-helper.js +35 -13
  26. package/dist/index.js +7 -0
  27. package/dist/utils/VirtualizedList.js +69 -0
  28. package/dist/utils/requests.js +2 -2
  29. package/dist/utils/search.js +3 -56
  30. package/dist/utils/string.js +18 -0
  31. package/package.json +3 -2
  32. package/dist/components/obs-list/ObsValueList.js +0 -101
@@ -19,10 +19,12 @@ var _SpatialControls = require("./SpatialControls");
19
19
  var _Toolbox = require("./Toolbox");
20
20
  var _constants = require("../../constants/constants");
21
21
  var _DatasetContext = require("../../context/DatasetContext");
22
+ var _FilterContext = require("../../context/FilterContext");
22
23
  var _colorHelper = require("../../helpers/color-helper");
23
24
  var _mapHelper = require("../../helpers/map-helper");
24
25
  var _zarrHelper = require("../../helpers/zarr-helper");
25
26
  var _LoadingIndicators = require("../../utils/LoadingIndicators");
27
+ var _string = require("../../utils/string");
26
28
  var _jsxRuntime = require("react/jsx-runtime");
27
29
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
28
30
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
@@ -36,16 +38,27 @@ const INITIAL_VIEW_STATE = {
36
38
  pitch: 0,
37
39
  bearing: 0
38
40
  };
41
+ const EPSILON = 1e-6;
42
+ const meanData = (_i, data) => {
43
+ return _lodash.default.zipWith(...data, function () {
44
+ for (var _len = arguments.length, values = new Array(_len), _key = 0; _key < _len; _key++) {
45
+ values[_key] = arguments[_key];
46
+ }
47
+ return _lodash.default.mean(values);
48
+ });
49
+ };
39
50
  function Scatterplot(_ref) {
40
- var _dataset$selectedObs, _dataset$selectedObs2, _dataset$selectedObs6, _dataset$selectedObs8, _dataset$selectedObs10, _features$features2, _obsmData$serverError, _xData$serverError, _obsData$serverError, _labelObsData$serverE, _obsmData$data;
51
+ var _dataset$selectedVar, _dataset$selectedVar2, _dataset$selectedVar3, _dataset$selectedObs, _dataset$selectedObs2, _dataset$selectedObs7, _dataset$selectedObs11, _dataset$selectedObs12, _dataset$selectedObs13, _dataset$selectedObs15, _features$features2, _obsmData$serverError, _xData$serverError, _obsData$serverError, _labelObsData$serverE, _obsmData$data;
41
52
  let {
42
53
  radius = 30
43
54
  } = _ref;
44
55
  const dataset = (0, _DatasetContext.useDataset)();
45
56
  const dispatch = (0, _DatasetContext.useDatasetDispatch)();
57
+ const filterDispatch = (0, _FilterContext.useFilteredDataDispatch)();
46
58
  const {
47
59
  getColor
48
60
  } = (0, _colorHelper.useColor)();
61
+ const deckRef = (0, _react.useRef)(null);
49
62
  const [viewState, setViewState] = (0, _react.useState)(INITIAL_VIEW_STATE);
50
63
  const [isRendering, setIsRendering] = (0, _react.useState)(true);
51
64
  const [data, setData] = (0, _react.useState)({
@@ -66,23 +79,24 @@ function Scatterplot(_ref) {
66
79
  url: dataset.url,
67
80
  path: "obsm/" + dataset.selectedObsm
68
81
  });
69
- const [xParams, setXParams] = (0, _react.useState)({
82
+ const [xParams, setXParams] = (0, _react.useState)(!dataset.selectedVar ? [] : !((_dataset$selectedVar = dataset.selectedVar) !== null && _dataset$selectedVar !== void 0 && _dataset$selectedVar.isSet) ? [{
70
83
  url: dataset.url,
71
- path: "X"
72
- });
84
+ path: "X",
85
+ s: [null, (_dataset$selectedVar2 = dataset.selectedVar) === null || _dataset$selectedVar2 === void 0 ? void 0 : _dataset$selectedVar2.matrix_index]
86
+ }] : _lodash.default.map((_dataset$selectedVar3 = dataset.selectedVar) === null || _dataset$selectedVar3 === void 0 ? void 0 : _dataset$selectedVar3.vars, v => {
87
+ return {
88
+ url: dataset.url,
89
+ path: "X",
90
+ s: [null, v.matrix_index]
91
+ };
92
+ }));
73
93
  const [obsParams, setObsParams] = (0, _react.useState)({
74
94
  url: dataset.url,
75
- path: "obs/" + ((_dataset$selectedObs = dataset.selectedObs) === null || _dataset$selectedObs === void 0 ? void 0 : _dataset$selectedObs.name) + (((_dataset$selectedObs2 = dataset.selectedObs) === null || _dataset$selectedObs2 === void 0 ? void 0 : _dataset$selectedObs2.type) === _constants.OBS_TYPES.CONTINUOUS ? "" : "/codes")
95
+ path: "obs/" + ((_dataset$selectedObs = dataset.selectedObs) === null || _dataset$selectedObs === void 0 ? void 0 : _dataset$selectedObs.name) + (((_dataset$selectedObs2 = dataset.selectedObs) === null || _dataset$selectedObs2 === void 0 ? void 0 : _dataset$selectedObs2.type) === _constants.OBS_TYPES.CATEGORICAL ? "/codes" : "")
76
96
  });
77
97
  const [labelObsParams, setLabelObsParams] = (0, _react.useState)([]);
78
-
79
- // needs to be wrapped in useMemo as it is an array an could cause an infinite loop otherwise
80
- const xSelection = (0, _react.useMemo)(() => {
81
- var _dataset$selectedVar;
82
- return [null, (_dataset$selectedVar = dataset.selectedVar) === null || _dataset$selectedVar === void 0 ? void 0 : _dataset$selectedVar.matrix_index];
83
- }, [dataset.selectedVar]);
84
98
  const obsmData = (0, _zarrHelper.useZarr)(obsmParams, null, _zarrHelper.GET_OPTIONS);
85
- const xData = (0, _zarrHelper.useZarr)(xParams, xSelection, _zarrHelper.GET_OPTIONS);
99
+ const xData = (0, _zarrHelper.useMultipleZarr)(xParams, _zarrHelper.GET_OPTIONS, meanData);
86
100
  const obsData = (0, _zarrHelper.useZarr)(obsParams, null, _zarrHelper.GET_OPTIONS);
87
101
  const labelObsData = (0, _zarrHelper.useMultipleZarr)(labelObsParams, _zarrHelper.GET_OPTIONS);
88
102
  (0, _react.useEffect)(() => {
@@ -94,20 +108,25 @@ function Scatterplot(_ref) {
94
108
  });
95
109
  }, [dataset.selectedObsm]);
96
110
  (0, _react.useEffect)(() => {
97
- setXParams(p => {
98
- var _dataset$selectedVar2;
111
+ var _dataset$selectedVar4, _dataset$selectedVar5, _dataset$selectedVar6;
112
+ setXParams(!dataset.selectedVar ? [] : !((_dataset$selectedVar4 = dataset.selectedVar) !== null && _dataset$selectedVar4 !== void 0 && _dataset$selectedVar4.isSet) ? [{
113
+ url: dataset.url,
114
+ path: "X",
115
+ s: [null, (_dataset$selectedVar5 = dataset.selectedVar) === null || _dataset$selectedVar5 === void 0 ? void 0 : _dataset$selectedVar5.matrix_index]
116
+ }] : _lodash.default.map((_dataset$selectedVar6 = dataset.selectedVar) === null || _dataset$selectedVar6 === void 0 ? void 0 : _dataset$selectedVar6.vars, v => {
99
117
  return {
100
- ...p,
101
- s: [null, (_dataset$selectedVar2 = dataset.selectedVar) === null || _dataset$selectedVar2 === void 0 ? void 0 : _dataset$selectedVar2.matrix_index]
118
+ url: dataset.url,
119
+ path: "X",
120
+ s: [null, v.matrix_index]
102
121
  };
103
- });
104
- }, [dataset.selectedVar]);
122
+ }));
123
+ }, [dataset.selectedVar, dataset.url]);
105
124
  (0, _react.useEffect)(() => {
106
125
  setObsParams(p => {
107
126
  var _dataset$selectedObs3, _dataset$selectedObs4;
108
127
  return {
109
128
  ...p,
110
- path: "obs/" + ((_dataset$selectedObs3 = dataset.selectedObs) === null || _dataset$selectedObs3 === void 0 ? void 0 : _dataset$selectedObs3.name) + (((_dataset$selectedObs4 = dataset.selectedObs) === null || _dataset$selectedObs4 === void 0 ? void 0 : _dataset$selectedObs4.type) === _constants.OBS_TYPES.CONTINUOUS ? "" : "/codes")
129
+ path: "obs/" + ((_dataset$selectedObs3 = dataset.selectedObs) === null || _dataset$selectedObs3 === void 0 ? void 0 : _dataset$selectedObs3.name) + (((_dataset$selectedObs4 = dataset.selectedObs) === null || _dataset$selectedObs4 === void 0 ? void 0 : _dataset$selectedObs4.type) === _constants.OBS_TYPES.CATEGORICAL ? "/codes" : "")
111
130
  };
112
131
  });
113
132
  }, [dataset.selectedObs]);
@@ -115,7 +134,7 @@ function Scatterplot(_ref) {
115
134
  setLabelObsParams(_lodash.default.map(dataset.labelObs, obs => {
116
135
  return {
117
136
  url: dataset.url,
118
- path: "obs/" + obs.name + (obs.type === _constants.OBS_TYPES.CONTINUOUS ? "" : "/codes"),
137
+ path: "obs/" + obs.name + (obs.type === _constants.OBS_TYPES.CATEGORICAL ? "/codes" : ""),
119
138
  key: obs.name
120
139
  };
121
140
  }));
@@ -127,12 +146,6 @@ function Scatterplot(_ref) {
127
146
  url: dataset.url
128
147
  };
129
148
  });
130
- setXParams(p => {
131
- return {
132
- ...p,
133
- url: dataset.url
134
- };
135
- });
136
149
  setObsParams(p => {
137
150
  return {
138
151
  ...p,
@@ -145,6 +158,7 @@ function Scatterplot(_ref) {
145
158
 
146
159
  (0, _react.useEffect)(() => {
147
160
  if (!obsmData.isPending && !obsmData.serverError) {
161
+ var _deckRef$current, _deckRef$current2;
148
162
  setIsRendering(true);
149
163
  setData(d => {
150
164
  return {
@@ -157,7 +171,10 @@ function Scatterplot(_ref) {
157
171
  latitude,
158
172
  longitude,
159
173
  zoom
160
- } = mapHelper.fitBounds(obsmData.data);
174
+ } = mapHelper.fitBounds(obsmData.data, {
175
+ width: deckRef === null || deckRef === void 0 || (_deckRef$current = deckRef.current) === null || _deckRef$current === void 0 || (_deckRef$current = _deckRef$current.deck) === null || _deckRef$current === void 0 ? void 0 : _deckRef$current.width,
176
+ height: deckRef === null || deckRef === void 0 || (_deckRef$current2 = deckRef.current) === null || _deckRef$current2 === void 0 || (_deckRef$current2 = _deckRef$current2.deck) === null || _deckRef$current2 === void 0 ? void 0 : _deckRef$current2.height
177
+ });
161
178
  setViewState(v => {
162
179
  return {
163
180
  ...v,
@@ -176,12 +193,16 @@ function Scatterplot(_ref) {
176
193
  });
177
194
  }
178
195
  }, [dataset.selectedObsm, obsmData.data, obsmData.isPending, obsmData.serverError]);
179
- const bounds = (0, _react.useMemo)(() => {
196
+ const getBounds = (0, _react.useCallback)(() => {
197
+ var _deckRef$current3, _deckRef$current4;
180
198
  const {
181
199
  latitude,
182
200
  longitude,
183
201
  zoom
184
- } = new _mapHelper.MapHelper().fitBounds(data.positions);
202
+ } = new _mapHelper.MapHelper().fitBounds(data.positions, {
203
+ width: deckRef === null || deckRef === void 0 || (_deckRef$current3 = deckRef.current) === null || _deckRef$current3 === void 0 || (_deckRef$current3 = _deckRef$current3.deck) === null || _deckRef$current3 === void 0 ? void 0 : _deckRef$current3.width,
204
+ height: deckRef === null || deckRef === void 0 || (_deckRef$current4 = deckRef.current) === null || _deckRef$current4 === void 0 || (_deckRef$current4 = _deckRef$current4.deck) === null || _deckRef$current4 === void 0 ? void 0 : _deckRef$current4.height
205
+ });
185
206
  return {
186
207
  latitude,
187
208
  longitude,
@@ -247,17 +268,37 @@ function Scatterplot(_ref) {
247
268
  }, [dataset.colorEncoding, obsData.data, obsData.isPending, obsData.serverError, dataset.sliceBy.obs]);
248
269
  const isCategorical = (0, _react.useMemo)(() => {
249
270
  if (dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS) {
250
- var _dataset$selectedObs5;
251
- return ((_dataset$selectedObs5 = dataset.selectedObs) === null || _dataset$selectedObs5 === void 0 ? void 0 : _dataset$selectedObs5.type) === _constants.OBS_TYPES.CATEGORICAL;
271
+ var _dataset$selectedObs5, _dataset$selectedObs6;
272
+ return ((_dataset$selectedObs5 = dataset.selectedObs) === null || _dataset$selectedObs5 === void 0 ? void 0 : _dataset$selectedObs5.type) === _constants.OBS_TYPES.CATEGORICAL || ((_dataset$selectedObs6 = dataset.selectedObs) === null || _dataset$selectedObs6 === void 0 ? void 0 : _dataset$selectedObs6.type) === _constants.OBS_TYPES.BOOLEAN;
252
273
  } else {
253
274
  return false;
254
275
  }
255
- }, [dataset.colorEncoding, (_dataset$selectedObs6 = dataset.selectedObs) === null || _dataset$selectedObs6 === void 0 ? void 0 : _dataset$selectedObs6.type]);
276
+ }, [dataset.colorEncoding, (_dataset$selectedObs7 = dataset.selectedObs) === null || _dataset$selectedObs7 === void 0 ? void 0 : _dataset$selectedObs7.type]);
277
+ const isInBins = (v, binEdges, indices) => {
278
+ const lastEdge = _lodash.default.last(binEdges);
279
+ const allButLastEdges = _lodash.default.initial(binEdges);
280
+ // add epsilon to last edge to include the last value
281
+ const modifiedBinEdges = [...allButLastEdges, [lastEdge[0], lastEdge[1] + EPSILON]];
282
+ const binIndices = _lodash.default.difference(_lodash.default.range(binEdges.length), indices);
283
+ const ranges = _lodash.default.at(modifiedBinEdges, binIndices);
284
+ return _lodash.default.some(ranges, range => _lodash.default.inRange(v, ...range));
285
+ };
256
286
  const isInSlice = (0, _react.useCallback)((index, values, positions) => {
287
+ var _dataset$selectedObs9, _dataset$selectedObs10;
257
288
  let inSlice = true;
258
- if ((dataset.sliceBy.obs || isCategorical) && values) {
259
- var _dataset$selectedObs7;
260
- inSlice &= !_lodash.default.includes((_dataset$selectedObs7 = dataset.selectedObs) === null || _dataset$selectedObs7 === void 0 ? void 0 : _dataset$selectedObs7.omit, values[index]);
289
+ if (isCategorical && values) {
290
+ var _dataset$selectedObs8;
291
+ inSlice &= !_lodash.default.includes((_dataset$selectedObs8 = dataset.selectedObs) === null || _dataset$selectedObs8 === void 0 ? void 0 : _dataset$selectedObs8.omit, values[index]);
292
+ } else if ((dataset.sliceBy.obs || dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS && ((_dataset$selectedObs9 = dataset.selectedObs) === null || _dataset$selectedObs9 === void 0 ? void 0 : _dataset$selectedObs9.type) === _constants.OBS_TYPES.CONTINUOUS) && !!((_dataset$selectedObs10 = dataset.selectedObs) !== null && _dataset$selectedObs10 !== void 0 && _dataset$selectedObs10.omit.length) && values) {
293
+ if (dataset.selectedObs.type === _constants.OBS_TYPES.CATEGORICAL) {
294
+ inSlice &= !_lodash.default.includes(dataset.selectedObs.omit, values[index]);
295
+ } else if (dataset.selectedObs.type === _constants.OBS_TYPES.CONTINUOUS) {
296
+ if (Number.isNaN(values[index])) {
297
+ inSlice &= !_lodash.default.includes(dataset.selectedObs.omit, -1);
298
+ } else {
299
+ inSlice &= isInBins(values[index], dataset.selectedObs.bins.binEdges, _lodash.default.without(dataset.selectedObs.omit, -1));
300
+ }
301
+ }
261
302
  }
262
303
  if (dataset.sliceBy.polygons && positions) {
263
304
  inSlice &= _lodash.default.some(features === null || features === void 0 ? void 0 : features.features, (_f, i) => {
@@ -265,7 +306,7 @@ function Scatterplot(_ref) {
265
306
  });
266
307
  }
267
308
  return inSlice;
268
- }, [(_dataset$selectedObs8 = dataset.selectedObs) === null || _dataset$selectedObs8 === void 0 ? void 0 : _dataset$selectedObs8.omit, dataset.sliceBy.obs, dataset.sliceBy.polygons, features.features, isCategorical]);
309
+ }, [dataset.colorEncoding, (_dataset$selectedObs11 = dataset.selectedObs) === null || _dataset$selectedObs11 === void 0 || (_dataset$selectedObs11 = _dataset$selectedObs11.bins) === null || _dataset$selectedObs11 === void 0 ? void 0 : _dataset$selectedObs11.binEdges, (_dataset$selectedObs12 = dataset.selectedObs) === null || _dataset$selectedObs12 === void 0 ? void 0 : _dataset$selectedObs12.omit, (_dataset$selectedObs13 = dataset.selectedObs) === null || _dataset$selectedObs13 === void 0 ? void 0 : _dataset$selectedObs13.type, dataset.sliceBy.obs, dataset.sliceBy.polygons, features.features, isCategorical]);
269
310
  const {
270
311
  filteredIndices,
271
312
  valueMin,
@@ -293,8 +334,8 @@ function Scatterplot(_ref) {
293
334
  slicedLength: filtered.length
294
335
  };
295
336
  } else if (dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS) {
296
- var _dataset$selectedObs9;
297
- const isContinuous = ((_dataset$selectedObs9 = dataset.selectedObs) === null || _dataset$selectedObs9 === void 0 ? void 0 : _dataset$selectedObs9.type) === _constants.OBS_TYPES.CONTINUOUS;
337
+ var _dataset$selectedObs14;
338
+ const isContinuous = ((_dataset$selectedObs14 = dataset.selectedObs) === null || _dataset$selectedObs14 === void 0 ? void 0 : _dataset$selectedObs14.type) === _constants.OBS_TYPES.CONTINUOUS;
298
339
  const {
299
340
  filtered,
300
341
  filteredIndices
@@ -322,7 +363,13 @@ function Scatterplot(_ref) {
322
363
  slicedLength: data.values.length
323
364
  };
324
365
  }
325
- }, [data.positions, data.sliceValues, data.values, dataset.colorEncoding, (_dataset$selectedObs10 = dataset.selectedObs) === null || _dataset$selectedObs10 === void 0 ? void 0 : _dataset$selectedObs10.type, isInSlice]);
366
+ }, [data.positions, data.sliceValues, data.values, dataset.colorEncoding, (_dataset$selectedObs15 = dataset.selectedObs) === null || _dataset$selectedObs15 === void 0 ? void 0 : _dataset$selectedObs15.type, isInSlice]);
367
+ (0, _react.useEffect)(() => {
368
+ filterDispatch({
369
+ type: "set.obs.indices",
370
+ indices: dataset.sliceBy.obs || dataset.sliceBy.polygons ? filteredIndices : null
371
+ });
372
+ }, [dataset.sliceBy.obs, dataset.sliceBy.polygons, filterDispatch, filteredIndices]);
326
373
  (0, _react.useEffect)(() => {
327
374
  dispatch({
328
375
  type: "set.controls.valueRange",
@@ -408,20 +455,40 @@ function Scatterplot(_ref) {
408
455
  }
409
456
  setSelectedFeatureIndexes(f => info.object ? info.layer.id === "cherita-layer-draw" ? [info.index] : f : []);
410
457
  }
458
+ const getLabel = function (o, v) {
459
+ let isVar = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
460
+ if (isVar || o.type === _constants.OBS_TYPES.CONTINUOUS) {
461
+ return "".concat(o.name, ": ").concat((0, _string.prettyNumerical)(parseFloat(v)));
462
+ } else {
463
+ return "".concat(o.name, ": ").concat(o.codesMap[v]);
464
+ }
465
+ };
411
466
  const getTooltip = _ref4 => {
412
467
  let {
413
468
  object,
414
469
  index
415
470
  } = _ref4;
416
- return object && dataset.labelObs.length && {
417
- text: _lodash.default.map(labelObsData, (v, k) => {
471
+ if (!object) return;
472
+ const text = [];
473
+ if (dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS && dataset.selectedObs && !_lodash.default.some(dataset.labelObs, {
474
+ name: dataset.selectedObs.name
475
+ })) {
476
+ var _obsData$data;
477
+ text.push(getLabel(dataset.selectedObs, (_obsData$data = obsData.data) === null || _obsData$data === void 0 ? void 0 : _obsData$data[index]));
478
+ }
479
+ if (dataset.colorEncoding === _constants.COLOR_ENCODINGS.VAR && dataset.selectedVar) {
480
+ var _xData$data;
481
+ text.push(getLabel(dataset.selectedVar, (_xData$data = xData.data) === null || _xData$data === void 0 ? void 0 : _xData$data[index], true));
482
+ }
483
+ if (dataset.labelObs.length) {
484
+ text.push(..._lodash.default.map(labelObsData.data, (v, k) => {
418
485
  const labelObs = _lodash.default.find(dataset.labelObs, o => o.name === k);
419
- if (labelObs.type === _constants.OBS_TYPES.CONTINUOUS) {
420
- return "".concat(k, ": ").concat(parseFloat(v === null || v === void 0 ? void 0 : v[index]).toLocaleString());
421
- } else {
422
- return "".concat(k, ": ").concat(labelObs.codesMap[v === null || v === void 0 ? void 0 : v[index]]);
423
- }
424
- }).join("\n")
486
+ return getLabel(labelObs, v[index]);
487
+ }));
488
+ }
489
+ if (!text.length) return;
490
+ return {
491
+ text: text.length ? _lodash.default.compact(text).join("\n") : null
425
492
  };
426
493
  };
427
494
  const isPending = (isRendering || xData.isPending || obsmData.isPending) && !obsmData.isPending;
@@ -448,14 +515,15 @@ function Scatterplot(_ref) {
448
515
  isDragging
449
516
  } = _ref5;
450
517
  return mode !== _editModes.ViewMode ? "crosshair" : isDragging ? "grabbing" : "grab";
451
- }
518
+ },
519
+ ref: deckRef
452
520
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_SpatialControls.SpatialControls, {
453
521
  mode: mode,
454
522
  setMode: setMode,
455
523
  features: features,
456
524
  setFeatures: setFeatures,
457
525
  selectedFeatureIndexes: selectedFeatureIndexes,
458
- resetBounds: () => setViewState(bounds),
526
+ resetBounds: () => setViewState(getBounds()),
459
527
  increaseZoom: () => setViewState(v => ({
460
528
  ...v,
461
529
  zoom: v.zoom + 1
@@ -464,20 +532,20 @@ function Scatterplot(_ref) {
464
532
  ...v,
465
533
  zoom: v.zoom - 1
466
534
  }))
467
- }), error && !isPending && /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
468
- className: "cherita-alert",
469
- children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactBootstrap.Alert, {
470
- variant: "danger",
471
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactFontawesome.FontAwesomeIcon, {
472
- icon: _freeSolidSvgIcons.faTriangleExclamation
473
- }), "Error loading data"]
474
- })
475
535
  }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
476
536
  className: "cherita-spatial-footer",
477
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Toolbox.Toolbox, {
478
- mode: dataset.colorEncoding === _constants.COLOR_ENCODINGS.VAR ? dataset.selectedVar.name : dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS ? dataset.selectedObs.name : null,
479
- obsLength: parseInt((_obsmData$data = obsmData.data) === null || _obsmData$data === void 0 ? void 0 : _obsmData$data.length),
480
- slicedLength: parseInt(slicedLength)
537
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
538
+ className: "cherita-toolbox-footer",
539
+ children: [error && !isPending && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactBootstrap.Alert, {
540
+ variant: "danger",
541
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactFontawesome.FontAwesomeIcon, {
542
+ icon: _freeSolidSvgIcons.faTriangleExclamation
543
+ }), "\xA0Error loading data"]
544
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Toolbox.Toolbox, {
545
+ mode: dataset.colorEncoding === _constants.COLOR_ENCODINGS.VAR ? dataset.selectedVar.name : dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS ? dataset.selectedObs.name : null,
546
+ obsLength: parseInt((_obsmData$data = obsmData.data) === null || _obsmData$data === void 0 ? void 0 : _obsmData$data.length),
547
+ slicedLength: parseInt(slicedLength)
548
+ })]
481
549
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Legend.Legend, {
482
550
  isCategorical: isCategorical,
483
551
  min: min,
@@ -9,6 +9,7 @@ var _freeSolidSvgIcons = require("@fortawesome/free-solid-svg-icons");
9
9
  var _reactFontawesome = require("@fortawesome/react-fontawesome");
10
10
  var _Button = _interopRequireDefault(require("react-bootstrap/Button"));
11
11
  var _ButtonGroup = _interopRequireDefault(require("react-bootstrap/ButtonGroup"));
12
+ var _string = require("../../utils/string");
12
13
  var _ObsmList = require("../obsm-list/ObsmList");
13
14
  var _jsxRuntime = require("react/jsx-runtime");
14
15
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
@@ -28,10 +29,10 @@ function Toolbox(_ref) {
28
29
  }), " ", mode]
29
30
  }), (mode || !Number.isNaN(obsLength)) && (mode !== null && !Number.isNaN(slicedLength) && slicedLength !== obsLength ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_Button.default, {
30
31
  size: "sm",
31
- children: [slicedLength.toLocaleString(), " out of", " ", obsLength.toLocaleString(), " cells"]
32
+ children: [(0, _string.prettyNumerical)(slicedLength), " out of", " ", (0, _string.prettyNumerical)(obsLength), " cells"]
32
33
  }) : /*#__PURE__*/(0, _jsxRuntime.jsxs)(_Button.default, {
33
34
  size: "sm",
34
- children: [obsLength.toLocaleString(), " cells"]
35
+ children: [(0, _string.prettyNumerical)(obsLength), " cells"]
35
36
  }))]
36
37
  })
37
38
  });
@@ -12,10 +12,25 @@ var _jsxRuntime = require("react/jsx-runtime");
12
12
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
13
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
14
14
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
15
+ function onVarSelect(dispatch, item) {
16
+ dispatch({
17
+ type: "select.var",
18
+ var: item
19
+ });
20
+ dispatch({
21
+ type: "select.multivar",
22
+ var: item
23
+ });
24
+ dispatch({
25
+ type: "set.colorEncoding",
26
+ value: "var"
27
+ });
28
+ }
15
29
  function SearchBar(_ref) {
16
30
  let {
17
31
  searchVar = true,
18
- searchDiseases = false
32
+ searchDiseases = false,
33
+ handleSelect = onVarSelect
19
34
  } = _ref;
20
35
  const [showSuggestions, setShowSuggestions] = (0, _react.useState)(false);
21
36
  const [text, setText] = (0, _react.useState)("");
@@ -62,7 +77,8 @@ function SearchBar(_ref) {
62
77
  },
63
78
  children: [searchVar && /*#__PURE__*/(0, _jsxRuntime.jsx)(_SearchResults.VarSearchResults, {
64
79
  text: text,
65
- setShowSuggestions: setShowSuggestions
80
+ setShowSuggestions: setShowSuggestions,
81
+ handleSelect: handleSelect
66
82
  }), searchVar && searchDiseases && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.Dropdown.Divider, {}), searchDiseases && /*#__PURE__*/(0, _jsxRuntime.jsx)(_SearchResults.DiseasesSearchResults, {
67
83
  text: text,
68
84
  setShowSuggestions: setShowSuggestions
@@ -17,17 +17,18 @@ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e;
17
17
  function VarSearchResults(_ref) {
18
18
  let {
19
19
  text,
20
- setShowSuggestions
20
+ setShowSuggestions,
21
+ handleSelect
21
22
  } = _ref;
22
23
  const [suggestions, setSuggestions] = (0, _react.useState)([]);
24
+ const dispatch = (0, _DatasetContext.useDatasetDispatch)();
23
25
  const {
24
26
  setParams,
25
27
  data: {
26
28
  fetchedData = [],
27
29
  isPending,
28
30
  serverError
29
- },
30
- onSelect
31
+ }
31
32
  } = (0, _search.useVarSearch)();
32
33
  const deferredData = (0, _react.useDeferredValue)(suggestions);
33
34
  const isStale = deferredData !== fetchedData;
@@ -62,7 +63,7 @@ function VarSearchResults(_ref) {
62
63
  as: "button",
63
64
  disabled: isStale,
64
65
  onClick: () => {
65
- onSelect(item);
66
+ handleSelect(dispatch, item);
66
67
  _lodash.default.delay(() => {
67
68
  setShowSuggestions(false);
68
69
  }, 150);
@@ -70,7 +71,7 @@ function VarSearchResults(_ref) {
70
71
  children: item.name
71
72
  }, item.name);
72
73
  });
73
- }, [deferredData, isStale, onSelect, setShowSuggestions]);
74
+ }, [deferredData, dispatch, handleSelect, isStale, setShowSuggestions]);
74
75
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
75
76
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.Dropdown.Header, {
76
77
  children: "Features"
@@ -102,7 +103,6 @@ function DiseasesSearchResults(_ref2) {
102
103
  serverError
103
104
  }
104
105
  } = (0, _search.useDiseaseSearch)();
105
- (0, _search.useGetDisease)();
106
106
  const deferredData = (0, _react.useDeferredValue)(suggestions);
107
107
  const isStale = deferredData !== fetchedData;
108
108
  const updateParams = (0, _react.useMemo)(() => {
@@ -137,8 +137,8 @@ function DiseasesSearchResults(_ref2) {
137
137
  onClick: () => {
138
138
  dispatch({
139
139
  type: "select.disease",
140
- id: item === null || item === void 0 ? void 0 : item.disease_id,
141
- name: item === null || item === void 0 ? void 0 : item.disease_name
140
+ id: item.disease_id,
141
+ name: item.disease_name
142
142
  });
143
143
  _lodash.default.delay(() => {
144
144
  setShowSuggestions(false);