@haniffalab/cherita-react 1.3.0 → 1.3.1-dev.2025-10-29.def77f5f

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 (137) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/components/controls/Controls.js +38 -30
  3. package/dist/cjs/components/dotplot/Dotplot.js +85 -57
  4. package/dist/cjs/components/dotplot/DotplotControls.js +103 -83
  5. package/dist/cjs/components/full-page/FullPage.js +167 -114
  6. package/dist/cjs/components/full-page/PlotAlert.js +45 -0
  7. package/dist/cjs/components/full-page/PlotTypeSelector.js +102 -0
  8. package/dist/cjs/components/heatmap/Heatmap.js +83 -53
  9. package/dist/cjs/components/heatmap/HeatmapControls.js +6 -3
  10. package/dist/cjs/components/icons/DotPlotIcon.js +64 -0
  11. package/dist/cjs/components/icons/HeatmapIcon.js +45 -0
  12. package/dist/cjs/components/icons/MatrixPlotIcon.1.js +57 -0
  13. package/dist/cjs/components/icons/MatrixPlotIcon.js +59 -0
  14. package/dist/cjs/components/icons/ScatterplotIcon.1.js +164 -0
  15. package/dist/cjs/components/icons/ScatterplotIcon.js +144 -0
  16. package/dist/cjs/components/icons/ViolinPlotIcon.js +42 -0
  17. package/dist/cjs/components/matrixplot/Matrixplot.js +83 -54
  18. package/dist/cjs/components/matrixplot/MatrixplotControls.js +8 -5
  19. package/dist/cjs/components/obs-list/ObsItem.js +305 -216
  20. package/dist/cjs/components/obs-list/ObsList.js +164 -128
  21. package/dist/cjs/components/obs-list/ObsToolbar.js +2 -3
  22. package/dist/cjs/components/obsm-list/ObsmList.js +67 -28
  23. package/dist/cjs/components/offcanvas/index.js +62 -27
  24. package/dist/cjs/components/pseudospatial/Pseudospatial.js +132 -76
  25. package/dist/cjs/components/pseudospatial/PseudospatialToolbar.js +122 -74
  26. package/dist/cjs/components/scatterplot/Scatterplot.js +223 -175
  27. package/dist/cjs/components/scatterplot/ScatterplotControls.js +45 -31
  28. package/dist/cjs/components/scatterplot/SpatialControls.js +143 -116
  29. package/dist/cjs/components/scatterplot/Toolbox.js +41 -30
  30. package/dist/cjs/components/search-bar/SearchBar.js +176 -120
  31. package/dist/cjs/components/search-bar/SearchInfo.js +79 -85
  32. package/dist/cjs/components/search-bar/SearchResults.js +93 -71
  33. package/dist/cjs/components/toolbar/Toolbar.js +111 -0
  34. package/dist/cjs/components/var-list/VarItem.js +131 -103
  35. package/dist/cjs/components/var-list/VarList.js +96 -74
  36. package/dist/cjs/components/var-list/VarListToolbar.js +59 -54
  37. package/dist/cjs/components/var-list/VarSet.js +126 -108
  38. package/dist/cjs/components/violin/Violin.js +124 -81
  39. package/dist/cjs/components/violin/ViolinControls.js +8 -5
  40. package/dist/cjs/constants/colorscales.js +19 -19
  41. package/dist/cjs/constants/constants.js +54 -39
  42. package/dist/cjs/context/DatasetContext.js +27 -17
  43. package/dist/cjs/context/FilterContext.js +11 -9
  44. package/dist/cjs/context/SettingsContext.js +339 -125
  45. package/dist/cjs/context/ZarrDataContext.js +6 -5
  46. package/dist/cjs/helpers/color-helper.js +2 -2
  47. package/dist/cjs/helpers/map-helper.js +2 -1
  48. package/dist/cjs/helpers/zarr-helper.js +3 -3
  49. package/dist/cjs/index.js +15 -21
  50. package/dist/cjs/utils/Filter.js +16 -11
  51. package/dist/cjs/utils/Histogram.js +35 -33
  52. package/dist/cjs/utils/ImageViewer.js +11 -8
  53. package/dist/cjs/utils/Legend.js +37 -30
  54. package/dist/cjs/utils/LoadingIndicators.js +15 -13
  55. package/dist/cjs/utils/Resolver.js +213 -0
  56. package/dist/cjs/utils/Skeleton.js +10 -10
  57. package/dist/cjs/utils/StyledTooltip.js +44 -0
  58. package/dist/cjs/utils/VirtualizedList.js +36 -29
  59. package/dist/cjs/utils/errors.js +15 -15
  60. package/dist/cjs/utils/requests.js +21 -9
  61. package/dist/cjs/utils/search.js +4 -4
  62. package/dist/cjs/utils/string.js +6 -6
  63. package/dist/cjs/utils/zarrData.js +20 -21
  64. package/dist/css/cherita.css +188 -65
  65. package/dist/css/cherita.css.map +1 -1
  66. package/dist/esm/components/controls/Controls.js +43 -35
  67. package/dist/esm/components/dotplot/Dotplot.js +93 -64
  68. package/dist/esm/components/dotplot/DotplotControls.js +106 -85
  69. package/dist/esm/components/full-page/FullPage.js +180 -124
  70. package/dist/esm/components/full-page/PlotAlert.js +39 -0
  71. package/dist/esm/components/full-page/PlotTypeSelector.js +95 -0
  72. package/dist/esm/components/heatmap/Heatmap.js +91 -60
  73. package/dist/esm/components/heatmap/HeatmapControls.js +8 -4
  74. package/dist/esm/components/icons/DotPlotIcon.js +58 -0
  75. package/dist/esm/components/icons/HeatmapIcon.js +39 -0
  76. package/dist/esm/components/icons/MatrixPlotIcon.1.js +51 -0
  77. package/dist/esm/components/icons/MatrixPlotIcon.js +53 -0
  78. package/dist/esm/components/icons/ScatterplotIcon.1.js +158 -0
  79. package/dist/esm/components/icons/ScatterplotIcon.js +138 -0
  80. package/dist/esm/components/icons/ViolinPlotIcon.js +36 -0
  81. package/dist/esm/components/matrixplot/Matrixplot.js +91 -61
  82. package/dist/esm/components/matrixplot/MatrixplotControls.js +10 -6
  83. package/dist/esm/components/obs-list/ObsItem.js +320 -228
  84. package/dist/esm/components/obs-list/ObsList.js +179 -142
  85. package/dist/esm/components/obs-list/ObsToolbar.js +3 -3
  86. package/dist/esm/components/obsm-list/ObsmList.js +71 -32
  87. package/dist/esm/components/offcanvas/index.js +68 -33
  88. package/dist/esm/components/pseudospatial/Pseudospatial.js +145 -88
  89. package/dist/esm/components/pseudospatial/PseudospatialToolbar.js +127 -78
  90. package/dist/esm/components/scatterplot/Scatterplot.js +243 -194
  91. package/dist/esm/components/scatterplot/ScatterplotControls.js +50 -35
  92. package/dist/esm/components/scatterplot/SpatialControls.js +155 -127
  93. package/dist/esm/components/scatterplot/Toolbox.js +44 -32
  94. package/dist/esm/components/search-bar/SearchBar.js +187 -130
  95. package/dist/esm/components/search-bar/SearchInfo.js +86 -91
  96. package/dist/esm/components/search-bar/SearchResults.js +100 -77
  97. package/dist/esm/components/toolbar/Toolbar.js +101 -0
  98. package/dist/esm/components/var-list/VarItem.js +142 -113
  99. package/dist/esm/components/var-list/VarList.js +108 -88
  100. package/dist/esm/components/var-list/VarListToolbar.js +64 -58
  101. package/dist/esm/components/var-list/VarSet.js +134 -115
  102. package/dist/esm/components/violin/Violin.js +135 -91
  103. package/dist/esm/components/violin/ViolinControls.js +10 -6
  104. package/dist/esm/constants/colorscales.js +19 -19
  105. package/dist/esm/constants/constants.js +53 -38
  106. package/dist/esm/context/DatasetContext.js +34 -23
  107. package/dist/esm/context/FilterContext.js +11 -8
  108. package/dist/esm/context/SettingsContext.js +341 -126
  109. package/dist/esm/context/ZarrDataContext.js +8 -6
  110. package/dist/esm/helpers/color-helper.js +5 -5
  111. package/dist/esm/helpers/map-helper.js +4 -3
  112. package/dist/esm/helpers/zarr-helper.js +6 -6
  113. package/dist/esm/index.js +22 -22
  114. package/dist/esm/utils/Filter.js +22 -17
  115. package/dist/esm/utils/Histogram.js +39 -37
  116. package/dist/esm/utils/ImageViewer.js +12 -8
  117. package/dist/esm/utils/Legend.js +44 -36
  118. package/dist/esm/utils/LoadingIndicators.js +16 -13
  119. package/dist/esm/utils/Resolver.js +201 -0
  120. package/dist/esm/utils/Skeleton.js +11 -10
  121. package/dist/esm/utils/StyledTooltip.js +38 -0
  122. package/dist/esm/utils/VirtualizedList.js +37 -29
  123. package/dist/esm/utils/errors.js +15 -15
  124. package/dist/esm/utils/requests.js +24 -12
  125. package/dist/esm/utils/search.js +7 -7
  126. package/dist/esm/utils/string.js +7 -7
  127. package/dist/esm/utils/zarrData.js +27 -28
  128. package/package.json +24 -10
  129. package/scss/cherita-bootstrap.scss +2 -2
  130. package/scss/cherita.scss +65 -17
  131. package/scss/components/accordions.scss +15 -2
  132. package/scss/components/layouts.scss +116 -30
  133. package/scss/components/lists.scss +16 -5
  134. package/scss/components/plotly.scss +40 -23
  135. package/scss/components/plots.scss +14 -1
  136. package/dist/cjs/components/full-page/FullPagePseudospatial.js +0 -157
  137. package/dist/esm/components/full-page/FullPagePseudospatial.js +0 -149
@@ -4,7 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.Scatterplot = Scatterplot;
7
- var _react = _interopRequireWildcard(require("react"));
7
+ var _react = require("react");
8
8
  var _layers = require("@deck.gl/layers");
9
9
  var _react2 = require("@deck.gl/react");
10
10
  var _freeSolidSvgIcons = require("@fortawesome/free-solid-svg-icons");
@@ -16,6 +16,7 @@ var _reactBootstrap = require("react-bootstrap");
16
16
  var _SpatialControls = require("./SpatialControls");
17
17
  var _Toolbox = require("./Toolbox");
18
18
  var _constants = require("../../constants/constants");
19
+ var _DatasetContext = require("../../context/DatasetContext");
19
20
  var _FilterContext = require("../../context/FilterContext");
20
21
  var _SettingsContext = require("../../context/SettingsContext");
21
22
  var _ZarrDataContext = require("../../context/ZarrDataContext");
@@ -23,10 +24,12 @@ var _colorHelper = require("../../helpers/color-helper");
23
24
  var _mapHelper = require("../../helpers/map-helper");
24
25
  var _Legend = require("../../utils/Legend");
25
26
  var _LoadingIndicators = require("../../utils/LoadingIndicators");
27
+ var _Resolver = require("../../utils/Resolver");
26
28
  var _string = require("../../utils/string");
27
29
  var _zarrData = require("../../utils/zarrData");
30
+ var _PlotAlert = require("../full-page/PlotAlert");
31
+ var _jsxRuntime = require("react/jsx-runtime");
28
32
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
29
- function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
30
33
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
31
34
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
32
35
  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; }
@@ -42,13 +45,18 @@ const INITIAL_VIEW_STATE = {
42
45
  bearing: 0
43
46
  };
44
47
  function Scatterplot(_ref) {
45
- var _settings$selectedObs3, _features$features2, _obsmData$serverError, _xData$serverError, _obsData$serverError, _labelObsData$serverE, _settings$selectedVar, _settings$selectedObs4, _obsmData$data;
48
+ var _features$features2, _obsmData$serverError, _labelObsData$serverE, _settings$selectedVar, _data$positions;
46
49
  let {
47
- radius = 30,
50
+ radius = null,
48
51
  setShowObs,
49
52
  setShowVars,
53
+ plotType,
54
+ setPlotType,
50
55
  isFullscreen = false
51
56
  } = _ref;
57
+ const {
58
+ useUnsColors
59
+ } = (0, _DatasetContext.useDataset)();
52
60
  const settings = (0, _SettingsContext.useSettings)();
53
61
  const {
54
62
  obsIndices,
@@ -63,17 +71,21 @@ function Scatterplot(_ref) {
63
71
  const deckRef = (0, _react.useRef)(null);
64
72
  const [viewState, setViewState] = (0, _react.useState)(INITIAL_VIEW_STATE);
65
73
  const [isRendering, setIsRendering] = (0, _react.useState)(true);
74
+ const [radiusScale, setRadiusScale] = (0, _react.useState)(radius || 1);
75
+ const [isPending, setIsPending] = (0, _react.useState)(false);
66
76
  const [data, setData] = (0, _react.useState)({
67
- ids: [],
68
77
  positions: [],
69
- values: [],
70
- sliceValues: []
78
+ values: []
71
79
  });
80
+ const [coordsError, setCoordsError] = (0, _react.useState)(null);
81
+ const [hasObsm, setHasObsm] = (0, _react.useState)(true);
82
+ const [dataError, setDataError] = (0, _react.useState)(null);
83
+ const selectedObs = (0, _Resolver.useSelectedObs)();
72
84
 
73
85
  // EditableGeoJsonLayer
74
86
  const [mode, setMode] = (0, _react.useState)(() => _editModes.ViewMode);
75
87
  const [features, setFeatures] = (0, _react.useState)({
76
- type: "FeatureCollection",
88
+ type: 'FeatureCollection',
77
89
  features: settings.polygons[settings.selectedObsm] || []
78
90
  });
79
91
  const [selectedFeatureIndexes, setSelectedFeatureIndexes] = (0, _react.useState)([]);
@@ -85,24 +97,74 @@ function Scatterplot(_ref) {
85
97
  const labelObsData = (0, _zarrData.useLabelObsData)();
86
98
  // @TODO: assert length of obsmData, xData, obsData is equal
87
99
 
100
+ const getRadiusScale = (0, _react.useCallback)(bounds => {
101
+ if (!!radius) return radius;
102
+ // From 28 degrees ~= 30km -> 30m radius
103
+ const lonDim = bounds[1][0] - bounds[0][0];
104
+ const latDim = bounds[1][1] - bounds[0][1];
105
+ const minDim = Math.min(lonDim, latDim);
106
+ const rs = 0.01 / minDim * 111111;
107
+ return rs;
108
+ }, [radius]);
88
109
  (0, _react.useEffect)(() => {
89
- if (!obsmData.isPending && !obsmData.serverError) {
90
- var _deckRef$current, _deckRef$current2;
91
- setIsRendering(true);
110
+ if (obsmData.isPending || settings.colorEncoding === _constants.COLOR_ENCODINGS.VAR && xData.isPending || settings.colorEncoding === _constants.COLOR_ENCODINGS.OBS && obsData.isPending) {
111
+ setIsPending(true);
112
+ } else {
113
+ setIsPending(false);
92
114
  setData(d => {
93
- return _objectSpread(_objectSpread({}, d), {}, {
94
- positions: obsmData.data
95
- });
115
+ let values = d.values;
116
+ if (settings.colorEncoding === _constants.COLOR_ENCODINGS.VAR) {
117
+ if (!xData.serverError) {
118
+ values = xData.data;
119
+ setDataError(null);
120
+ } else {
121
+ values = [];
122
+ setDataError(xData.serverError);
123
+ }
124
+ } else if (settings.colorEncoding === _constants.COLOR_ENCODINGS.OBS) {
125
+ if (!obsData.serverError) {
126
+ values = obsData.data;
127
+ setDataError(null);
128
+ } else {
129
+ values = [];
130
+ setDataError(obsData.serverError);
131
+ }
132
+ }
133
+ if (!obsmData.serverError && obsmData.data) {
134
+ if (obsmData.data[0].length !== 2) {
135
+ setCoordsError('Invalid coordinates. Expected 2D coordinates');
136
+ return {
137
+ positions: [],
138
+ values: []
139
+ };
140
+ }
141
+ setCoordsError(null);
142
+ return {
143
+ positions: obsmData.data,
144
+ values: values
145
+ };
146
+ }
147
+ return {
148
+ positions: d.positions,
149
+ values: values
150
+ };
96
151
  });
152
+ }
153
+ }, [obsData.data, obsData.isPending, obsData.serverError, obsmData.data, obsmData.isPending, obsmData.serverError, settings.colorEncoding, xData.data, xData.isPending, xData.serverError]);
154
+ (0, _react.useEffect)(() => {
155
+ if (data.positions && !!data.positions.length) {
156
+ var _deckRef$current, _deckRef$current2;
97
157
  const mapHelper = new _mapHelper.MapHelper();
98
158
  const {
99
159
  latitude,
100
160
  longitude,
101
- zoom
102
- } = mapHelper.fitBounds(obsmData.data, {
161
+ zoom,
162
+ bounds
163
+ } = mapHelper.fitBounds(data.positions, {
103
164
  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,
104
165
  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
105
166
  });
167
+ setRadiusScale(getRadiusScale(bounds));
106
168
  setViewState(v => {
107
169
  return _objectSpread(_objectSpread({}, v), {}, {
108
170
  longitude: longitude,
@@ -110,15 +172,8 @@ function Scatterplot(_ref) {
110
172
  zoom: zoom
111
173
  });
112
174
  });
113
- } else if (!obsmData.isPending && obsmData.serverError) {
114
- setIsRendering(true);
115
- setData(d => {
116
- return _objectSpread(_objectSpread({}, d), {}, {
117
- positions: []
118
- });
119
- });
120
175
  }
121
- }, [settings.selectedObsm, obsmData.data, obsmData.isPending, obsmData.serverError]);
176
+ }, [getRadiusScale, obsmData.data, obsmData.isPending, obsmData.serverError, data.positions]);
122
177
  const getBounds = (0, _react.useCallback)(() => {
123
178
  var _deckRef$current3, _deckRef$current4;
124
179
  const {
@@ -135,71 +190,45 @@ function Scatterplot(_ref) {
135
190
  zoom
136
191
  };
137
192
  }, [data.positions]);
138
- (0, _react.useEffect)(() => {
139
- if (settings.colorEncoding === _constants.COLOR_ENCODINGS.VAR) {
140
- setIsRendering(true);
141
- if (!xData.isPending && !xData.serverError) {
142
- // @TODO: add condition to check obs slicing
143
- setData(d => {
144
- return _objectSpread(_objectSpread({}, d), {}, {
145
- values: xData.data
146
- });
147
- });
148
- } else if (!xData.isPending && xData.serverError) {
149
- setData(d => {
150
- return _objectSpread(_objectSpread({}, d), {}, {
151
- values: []
152
- });
153
- });
154
- }
155
- }
156
- }, [settings.colorEncoding, xData.data, xData.isPending, xData.serverError, getColor]);
157
- (0, _react.useEffect)(() => {
158
- if (settings.colorEncoding === _constants.COLOR_ENCODINGS.OBS) {
159
- setIsRendering(true);
160
- if (!obsData.isPending && !obsData.serverError) {
161
- setData(d => {
162
- return _objectSpread(_objectSpread({}, d), {}, {
163
- values: obsData.data
164
- });
165
- });
166
- } else if (!obsData.isPending && obsData.serverError) {
167
- setData(d => {
168
- return _objectSpread(_objectSpread({}, d), {}, {
169
- values: []
170
- });
171
- });
172
- }
173
- } else if (settings.colorEncoding === _constants.COLOR_ENCODINGS.VAR && settings.sliceBy.obs) {
174
- if (!obsData.isPending && !obsData.serverError) {
175
- setData(d => {
176
- return _objectSpread(_objectSpread({}, d), {}, {
177
- sliceValues: obsData.data
178
- });
179
- });
180
- } else if (!obsData.isPending && obsData.serverError) {
181
- setData(d => {
182
- return _objectSpread(_objectSpread({}, d), {}, {
183
- sliceValues: []
184
- });
185
- });
186
- }
193
+
194
+ // Make stable references for getOriginalIndex and sortedIndexMap
195
+ const identityGetOriginalIndex = (0, _react.useCallback)(i => i, []);
196
+ const identitySortedIndexMap = (0, _react.useMemo)(() => ({
197
+ get: key => key
198
+ }), []);
199
+ const {
200
+ sortedData,
201
+ getOriginalIndex,
202
+ sortedIndexMap
203
+ } = (0, _react.useMemo)(() => {
204
+ if ((settings.colorEncoding === _constants.COLOR_ENCODINGS.VAR || settings.colorEncoding === _constants.COLOR_ENCODINGS.OBS && (selectedObs === null || selectedObs === void 0 ? void 0 : selectedObs.type) === _constants.OBS_TYPES.CONTINUOUS) && data.positions && data.values && data.positions.length === data.values.length) {
205
+ const sortedIndices = _lodash.default.map(data.values, (_v, i) => i).sort((a, b) => data.values[a] - data.values[b]);
206
+ const sortedIndexMap = new Map(_lodash.default.map(sortedIndices, (originalIndex, sortedIndex) => [originalIndex, sortedIndex]));
207
+ return {
208
+ sortedData: _lodash.default.mapValues(data, (v, _k) => {
209
+ return v ? _lodash.default.at(v, sortedIndices) : v;
210
+ }),
211
+ getOriginalIndex: i => sortedIndices[i],
212
+ sortedIndexMap: sortedIndexMap
213
+ };
187
214
  }
188
- }, [settings.colorEncoding, obsData.data, obsData.isPending, obsData.serverError, settings.sliceBy.obs]);
215
+ return {
216
+ sortedData: data,
217
+ getOriginalIndex: identityGetOriginalIndex,
218
+ // return original index
219
+ sortedIndexMap: identitySortedIndexMap // return original index
220
+ };
221
+ }, [data, identityGetOriginalIndex, identitySortedIndexMap, selectedObs === null || selectedObs === void 0 ? void 0 : selectedObs.type, settings.colorEncoding]);
222
+ const sortedObsIndices = (0, _react.useMemo)(() => {
223
+ return obsIndices ? new Set(Array.from(obsIndices, i => sortedIndexMap.get(i))) : obsIndices;
224
+ }, [obsIndices, sortedIndexMap]);
189
225
  const isCategorical = (0, _react.useMemo)(() => {
190
226
  if (settings.colorEncoding === _constants.COLOR_ENCODINGS.OBS) {
191
- var _settings$selectedObs, _settings$selectedObs2;
192
- return ((_settings$selectedObs = settings.selectedObs) === null || _settings$selectedObs === void 0 ? void 0 : _settings$selectedObs.type) === _constants.OBS_TYPES.CATEGORICAL || ((_settings$selectedObs2 = settings.selectedObs) === null || _settings$selectedObs2 === void 0 ? void 0 : _settings$selectedObs2.type) === _constants.OBS_TYPES.BOOLEAN;
227
+ return (selectedObs === null || selectedObs === void 0 ? void 0 : selectedObs.type) === _constants.OBS_TYPES.CATEGORICAL || (selectedObs === null || selectedObs === void 0 ? void 0 : selectedObs.type) === _constants.OBS_TYPES.BOOLEAN;
193
228
  } else {
194
229
  return false;
195
230
  }
196
- }, [settings.colorEncoding, (_settings$selectedObs3 = settings.selectedObs) === null || _settings$selectedObs3 === void 0 ? void 0 : _settings$selectedObs3.type]);
197
- (0, _react.useEffect)(() => {
198
- dispatch({
199
- type: "set.controls.valueRange",
200
- valueRange: [valueMin, valueMax]
201
- });
202
- }, [dispatch, valueMax, valueMin]);
231
+ }, [settings.colorEncoding, selectedObs === null || selectedObs === void 0 ? void 0 : selectedObs.type]);
203
232
  const {
204
233
  min,
205
234
  max
@@ -211,28 +240,30 @@ function Scatterplot(_ref) {
211
240
  let {
212
241
  index
213
242
  } = _ref2;
214
- const grayOut = obsIndices && !obsIndices.has(index);
215
- return getColor({
216
- value: (data.values[index] - min) / (max - min),
243
+ const grayOut = isPending || sortedObsIndices && !sortedObsIndices.has(index);
244
+ return getColor(_objectSpread({
245
+ value: (sortedData.values[index] - min) / (max - min),
217
246
  categorical: isCategorical,
218
247
  grayOut: grayOut
219
- }) || [0, 0, 0, 100];
220
- }, [data.values, obsIndices, getColor, isCategorical, max, min]);
248
+ }, useUnsColors && settings.colorEncoding === _constants.COLOR_ENCODINGS.OBS && selectedObs !== null && selectedObs !== void 0 && selectedObs.colors ? {
249
+ colorscale: selectedObs === null || selectedObs === void 0 ? void 0 : selectedObs.colors
250
+ } : {})) || [0, 0, 0, 100];
251
+ }, [isPending, sortedObsIndices, getColor, sortedData.values, min, max, isCategorical, useUnsColors, settings.colorEncoding, selectedObs === null || selectedObs === void 0 ? void 0 : selectedObs.colors]);
221
252
 
222
253
  // @TODO: add support for pseudospatial hover to reflect in radius
223
254
  const getRadius = (0, _react.useCallback)((_d, _ref3) => {
224
255
  let {
225
256
  index
226
257
  } = _ref3;
227
- const grayOut = obsIndices && !obsIndices.has(index);
258
+ const grayOut = sortedObsIndices && !sortedObsIndices.has(index);
228
259
  return grayOut ? 1 : 3;
229
- }, [obsIndices]);
260
+ }, [sortedObsIndices]);
230
261
  const memoizedLayers = (0, _react.useMemo)(() => {
231
262
  return [new _layers.ScatterplotLayer({
232
- id: "cherita-layer-scatterplot",
263
+ id: 'cherita-layer-scatterplot',
233
264
  pickable: true,
234
- data: data.positions,
235
- radiusScale: radius,
265
+ data: sortedData.positions,
266
+ radiusScale: radiusScale,
236
267
  radiusMinPixels: 1,
237
268
  getPosition: d => d,
238
269
  getFillColor: getFillColor,
@@ -242,7 +273,7 @@ function Scatterplot(_ref) {
242
273
  getRadius: getRadius
243
274
  }
244
275
  }), new _layers2.EditableGeoJsonLayer({
245
- id: "cherita-layer-draw",
276
+ id: 'cherita-layer-draw',
246
277
  data: features,
247
278
  mode: mode,
248
279
  selectedFeatureIndexes,
@@ -254,7 +285,7 @@ function Scatterplot(_ref) {
254
285
  } = _ref4;
255
286
  setFeatures(updatedData);
256
287
  let updatedSelectedFeatureIndexes = selectedFeatureIndexes;
257
- if (editType === "addFeature") {
288
+ if (editType === 'addFeature') {
258
289
  const {
259
290
  featureIndexes
260
291
  } = editContext;
@@ -275,20 +306,20 @@ function Scatterplot(_ref) {
275
306
  }
276
307
  }
277
308
  })];
278
- }, [data.positions, features, getFillColor, getRadius, mode, radius, selectedFeatureIndexes]);
309
+ }, [sortedData.positions, features, getFillColor, getRadius, mode, radiusScale, selectedFeatureIndexes]);
279
310
  const layers = (0, _react.useDeferredValue)(mode === _editModes.ViewMode ? memoizedLayers.reverse() : memoizedLayers); // draw scatterplot on top of polygons when in ViewMode
280
311
 
281
312
  (0, _react.useEffect)(() => {
282
313
  var _features$features;
283
314
  if (!(features !== null && features !== void 0 && (_features$features = features.features) !== null && _features$features !== void 0 && _features$features.length)) {
284
315
  dispatch({
285
- type: "disable.slice.polygons"
316
+ type: 'disable.slice.polygons'
286
317
  });
287
318
  }
288
319
  }, [dispatch, features === null || features === void 0 || (_features$features2 = features.features) === null || _features$features2 === void 0 ? void 0 : _features$features2.length]);
289
320
  (0, _react.useEffect)(() => {
290
321
  dispatch({
291
- type: "set.polygons",
322
+ type: 'set.polygons',
292
323
  obsm: settings.selectedObsm,
293
324
  polygons: (features === null || features === void 0 ? void 0 : features.features) || []
294
325
  });
@@ -298,7 +329,7 @@ function Scatterplot(_ref) {
298
329
  // don't change selection while editing
299
330
  return;
300
331
  }
301
- setSelectedFeatureIndexes(f => info.object ? info.layer.id === "cherita-layer-draw" ? [info.index] : f : []);
332
+ setSelectedFeatureIndexes(f => info.object ? info.layer.id === 'cherita-layer-draw' ? [info.index] : f : []);
302
333
  }
303
334
  const getLabel = function (o, v) {
304
335
  let isVar = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
@@ -313,97 +344,114 @@ function Scatterplot(_ref) {
313
344
  object,
314
345
  index
315
346
  } = _ref5;
316
- if (!object || (object === null || object === void 0 ? void 0 : object.type) === "Feature") return;
347
+ if (!object || (object === null || object === void 0 ? void 0 : object.type) === 'Feature') return;
317
348
  const text = [];
318
- if (settings.colorEncoding === _constants.COLOR_ENCODINGS.OBS && settings.selectedObs && !_lodash.default.some(settings.labelObs, {
319
- name: settings.selectedObs.name
320
- })) {
321
- var _obsData$data;
322
- text.push(getLabel(settings.selectedObs, (_obsData$data = obsData.data) === null || _obsData$data === void 0 ? void 0 : _obsData$data[index]));
349
+ if (settings.colorEncoding === _constants.COLOR_ENCODINGS.OBS && selectedObs && !_lodash.default.includes(settings.labelObs, selectedObs.name)) {
350
+ var _data$values;
351
+ text.push(getLabel(selectedObs, (_data$values = data.values) === null || _data$values === void 0 ? void 0 : _data$values[getOriginalIndex(index)]));
323
352
  }
324
353
  if (settings.colorEncoding === _constants.COLOR_ENCODINGS.VAR && settings.selectedVar) {
325
- var _xData$data;
326
- text.push(getLabel(settings.selectedVar, (_xData$data = xData.data) === null || _xData$data === void 0 ? void 0 : _xData$data[index], true));
354
+ var _data$values2;
355
+ text.push(getLabel(settings.selectedVar, (_data$values2 = data.values) === null || _data$values2 === void 0 ? void 0 : _data$values2[getOriginalIndex(index)], true));
327
356
  }
328
357
  if (settings.labelObs.length) {
329
358
  text.push(..._lodash.default.map(labelObsData.data, (v, k) => {
330
- const labelObs = _lodash.default.find(settings.labelObs, o => o.name === k);
331
- return getLabel(labelObs, v[index]);
359
+ const labelObs = settings.data.obs[k];
360
+ return getLabel(labelObs, v[getOriginalIndex(index)]);
332
361
  }));
333
362
  }
334
363
  if (!text.length) return;
335
- const grayOut = obsIndices && !obsIndices.has(index);
364
+ const grayOut = sortedObsIndices && !sortedObsIndices.has(index);
336
365
  return {
337
- text: text.length ? _lodash.default.compact(text).join("\n") : null,
338
- className: grayOut ? "tooltip-grayout" : "deck-tooltip",
366
+ text: text.length ? _lodash.default.compact(text).join('\n') : null,
367
+ className: grayOut ? 'tooltip-grayout' : 'deck-tooltip',
339
368
  style: !grayOut ? {
340
- "border-left": "3px solid ".concat((0, _colorHelper.rgbToHex)(getFillColor(null, {
369
+ 'border-left': "3px solid ".concat((0, _colorHelper.rgbToHex)(getFillColor(null, {
341
370
  index
342
371
  })))
343
372
  } : {
344
- "border-left": "none"
373
+ 'border-left': 'none'
345
374
  }
346
375
  };
347
376
  };
348
- const isPending = (isRendering || xData.isPending || obsmData.isPending) && !obsmData.isPending;
349
- const error = settings.selectedObsm && ((_obsmData$serverError = obsmData.serverError) === null || _obsmData$serverError === void 0 ? void 0 : _obsmData$serverError.length) || settings.colorEncoding === _constants.COLOR_ENCODINGS.VAR && ((_xData$serverError = xData.serverError) === null || _xData$serverError === void 0 ? void 0 : _xData$serverError.length) || settings.colorEncoding === _constants.COLOR_ENCODINGS.OBS && ((_obsData$serverError = obsData.serverError) === null || _obsData$serverError === void 0 ? void 0 : _obsData$serverError.length) || settings.labelObs.lengh && ((_labelObsData$serverE = labelObsData.serverError) === null || _labelObsData$serverE === void 0 ? void 0 : _labelObsData$serverE.length);
350
- return /*#__PURE__*/_react.default.createElement("div", {
351
- className: "cherita-container-scatterplot"
352
- }, /*#__PURE__*/_react.default.createElement("div", {
353
- className: "cherita-scatterplot"
354
- }, obsmData.isPending && /*#__PURE__*/_react.default.createElement(_LoadingIndicators.LoadingSpinner, {
355
- disableShrink: true
356
- }), isPending && /*#__PURE__*/_react.default.createElement(_LoadingIndicators.LoadingLinear, null), /*#__PURE__*/_react.default.createElement(_react2.DeckGL, {
357
- viewState: viewState,
358
- onViewStateChange: e => setViewState(e.viewState),
359
- controller: {
360
- doubleClickZoom: mode === _editModes.ViewMode
361
- },
362
- layers: layers,
363
- onClick: onLayerClick,
364
- getTooltip: getTooltip,
365
- onAfterRender: () => {
366
- setIsRendering(false);
367
- },
368
- useDevicePixels: false,
369
- getCursor: _ref6 => {
370
- let {
371
- isDragging
372
- } = _ref6;
373
- return mode !== _editModes.ViewMode ? "crosshair" : isDragging ? "grabbing" : "grab";
374
- },
375
- ref: deckRef
376
- }), /*#__PURE__*/_react.default.createElement(_SpatialControls.SpatialControls, {
377
- mode: mode,
378
- setMode: setMode,
379
- features: features,
380
- setFeatures: setFeatures,
381
- selectedFeatureIndexes: selectedFeatureIndexes,
382
- resetBounds: () => setViewState(getBounds()),
383
- increaseZoom: () => setViewState(v => _objectSpread(_objectSpread({}, v), {}, {
384
- zoom: v.zoom + 1
385
- })),
386
- decreaseZoom: () => setViewState(v => _objectSpread(_objectSpread({}, v), {}, {
387
- zoom: v.zoom - 1
388
- })),
389
- setShowObs: setShowObs,
390
- setShowVars: setShowVars,
391
- isFullscreen: isFullscreen
392
- }), /*#__PURE__*/_react.default.createElement("div", {
393
- className: "cherita-spatial-footer"
394
- }, /*#__PURE__*/_react.default.createElement("div", {
395
- className: "cherita-toolbox-footer"
396
- }, error && !isPending && /*#__PURE__*/_react.default.createElement(_reactBootstrap.Alert, {
397
- variant: "danger"
398
- }, /*#__PURE__*/_react.default.createElement(_reactFontawesome.FontAwesomeIcon, {
399
- icon: _freeSolidSvgIcons.faTriangleExclamation
400
- }), "\xA0Error loading data"), /*#__PURE__*/_react.default.createElement(_Toolbox.Toolbox, {
401
- mode: settings.colorEncoding === _constants.COLOR_ENCODINGS.VAR ? (_settings$selectedVar = settings.selectedVar) === null || _settings$selectedVar === void 0 ? void 0 : _settings$selectedVar.name : settings.colorEncoding === _constants.COLOR_ENCODINGS.OBS ? (_settings$selectedObs4 = settings.selectedObs) === null || _settings$selectedObs4 === void 0 ? void 0 : _settings$selectedObs4.name : null,
402
- obsLength: parseInt((_obsmData$data = obsmData.data) === null || _obsmData$data === void 0 ? void 0 : _obsmData$data.length),
403
- slicedLength: parseInt(slicedLength)
404
- })), /*#__PURE__*/_react.default.createElement(_Legend.Legend, {
405
- isCategorical: isCategorical,
406
- min: min,
407
- max: max
408
- }))));
377
+ const error = settings.selectedObsm && ((_obsmData$serverError = obsmData.serverError) === null || _obsmData$serverError === void 0 ? void 0 : _obsmData$serverError.length) || dataError || settings.labelObs.length && ((_labelObsData$serverE = labelObsData.serverError) === null || _labelObsData$serverE === void 0 ? void 0 : _labelObsData$serverE.length) || coordsError;
378
+ if (!hasObsm) {
379
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_PlotAlert.PlotAlert, {
380
+ variant: "info",
381
+ heading: "Scatterplot unavailable for this dataset",
382
+ plotType: plotType,
383
+ setPlotType: setPlotType,
384
+ children: "This dataset does not include any embeddings, so a scatterplot cannot be displayed. Please choose a different plot type to explore the data."
385
+ });
386
+ }
387
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
388
+ className: "cherita-container-scatterplot",
389
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
390
+ className: "cherita-scatterplot",
391
+ children: [obsmData.isPending && /*#__PURE__*/(0, _jsxRuntime.jsx)(_LoadingIndicators.LoadingSpinner, {
392
+ disableShrink: true
393
+ }), isPending && /*#__PURE__*/(0, _jsxRuntime.jsx)(_LoadingIndicators.LoadingLinear, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_react2.DeckGL, {
394
+ viewState: viewState,
395
+ onViewStateChange: e => setViewState(e.viewState),
396
+ controller: {
397
+ doubleClickZoom: mode === _editModes.ViewMode
398
+ },
399
+ layers: layers,
400
+ onClick: onLayerClick,
401
+ getTooltip: getTooltip,
402
+ onAfterRender: () => {
403
+ setIsRendering(false);
404
+ },
405
+ useDevicePixels: false,
406
+ getCursor: _ref6 => {
407
+ let {
408
+ isDragging
409
+ } = _ref6;
410
+ return mode !== _editModes.ViewMode ? 'crosshair' : isDragging ? 'grabbing' : 'grab';
411
+ },
412
+ ref: deckRef
413
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_SpatialControls.SpatialControls, {
414
+ mode: mode,
415
+ setMode: setMode,
416
+ features: features,
417
+ setFeatures: setFeatures,
418
+ selectedFeatureIndexes: selectedFeatureIndexes,
419
+ resetBounds: () => setViewState(getBounds()),
420
+ increaseZoom: () => setViewState(v => _objectSpread(_objectSpread({}, v), {}, {
421
+ zoom: v.zoom + 1
422
+ })),
423
+ decreaseZoom: () => setViewState(v => _objectSpread(_objectSpread({}, v), {}, {
424
+ zoom: v.zoom - 1
425
+ })),
426
+ setShowObs: setShowObs,
427
+ setShowVars: setShowVars,
428
+ isFullscreen: isFullscreen
429
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
430
+ className: "cherita-spatial-footer",
431
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
432
+ className: "cherita-toolbox-footer",
433
+ children: [!!error && !isRendering && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactBootstrap.Alert, {
434
+ variant: "danger",
435
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactBootstrap.Alert.Heading, {
436
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactFontawesome.FontAwesomeIcon, {
437
+ icon: _freeSolidSvgIcons.faTriangleExclamation
438
+ }), "\xA0Error loading data"]
439
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("p", {
440
+ className: "mb-0",
441
+ children: error.message
442
+ })]
443
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Toolbox.Toolbox, {
444
+ mode: settings.colorEncoding === _constants.COLOR_ENCODINGS.VAR ? (_settings$selectedVar = settings.selectedVar) === null || _settings$selectedVar === void 0 ? void 0 : _settings$selectedVar.name : settings.colorEncoding === _constants.COLOR_ENCODINGS.OBS ? selectedObs === null || selectedObs === void 0 ? void 0 : selectedObs.name : null,
445
+ obsLength: parseInt((_data$positions = data.positions) === null || _data$positions === void 0 ? void 0 : _data$positions.length),
446
+ slicedLength: parseInt(slicedLength),
447
+ setHasObsm: setHasObsm
448
+ })]
449
+ }), !error && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Legend.Legend, {
450
+ isCategorical: isCategorical,
451
+ min: min,
452
+ max: max
453
+ })]
454
+ })]
455
+ })
456
+ });
409
457
  }