@haniffalab/cherita-react 1.3.0-dev.2025-06-06.f1eddad0 → 1.3.1-dev.2025-10-29.6de4119f

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 (138) 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 +67 -69
  4. package/dist/cjs/components/dotplot/DotplotControls.js +103 -83
  5. package/dist/cjs/components/full-page/FullPage.js +99 -105
  6. package/dist/cjs/components/full-page/PlotAlert.js +45 -0
  7. package/dist/cjs/components/full-page/PlotTypeSelector.js +89 -44
  8. package/dist/cjs/components/heatmap/Heatmap.js +65 -65
  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 +65 -66
  18. package/dist/cjs/components/matrixplot/MatrixplotControls.js +8 -5
  19. package/dist/cjs/components/obs-list/ObsItem.js +267 -205
  20. package/dist/cjs/components/obs-list/ObsList.js +161 -129
  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 +128 -100
  27. package/dist/cjs/components/scatterplot/ScatterplotControls.js +45 -31
  28. package/dist/cjs/components/scatterplot/SpatialControls.js +140 -113
  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 +76 -50
  32. package/dist/cjs/components/search-bar/SearchResults.js +93 -71
  33. package/dist/cjs/components/toolbar/Toolbar.js +46 -37
  34. package/dist/cjs/components/var-list/VarItem.js +131 -103
  35. package/dist/cjs/components/var-list/VarList.js +85 -71
  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 +109 -97
  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 +51 -48
  42. package/dist/cjs/context/DatasetContext.js +26 -17
  43. package/dist/cjs/context/FilterContext.js +11 -9
  44. package/dist/cjs/context/SettingsContext.js +271 -88
  45. package/dist/cjs/context/ZarrDataContext.js +6 -5
  46. package/dist/cjs/helpers/color-helper.js +2 -2
  47. package/dist/cjs/helpers/zarr-helper.js +3 -3
  48. package/dist/cjs/utils/Filter.js +16 -11
  49. package/dist/cjs/utils/Histogram.js +35 -33
  50. package/dist/cjs/utils/ImageViewer.js +11 -8
  51. package/dist/cjs/utils/Legend.js +37 -30
  52. package/dist/cjs/utils/LoadingIndicators.js +15 -13
  53. package/dist/cjs/utils/Resolver.js +213 -0
  54. package/dist/cjs/utils/Skeleton.js +10 -10
  55. package/dist/cjs/utils/StyledTooltip.js +44 -0
  56. package/dist/cjs/utils/VirtualizedList.js +36 -29
  57. package/dist/cjs/utils/errors.js +15 -15
  58. package/dist/cjs/utils/requests.js +21 -9
  59. package/dist/cjs/utils/search.js +4 -4
  60. package/dist/cjs/utils/string.js +6 -6
  61. package/dist/cjs/utils/zarrData.js +20 -21
  62. package/dist/css/cherita.css +135 -65
  63. package/dist/css/cherita.css.map +1 -1
  64. package/dist/esm/components/controls/Controls.js +43 -35
  65. package/dist/esm/components/dotplot/Dotplot.js +77 -78
  66. package/dist/esm/components/dotplot/DotplotControls.js +106 -85
  67. package/dist/esm/components/full-page/FullPage.js +119 -124
  68. package/dist/esm/components/full-page/PlotAlert.js +39 -0
  69. package/dist/esm/components/full-page/PlotTypeSelector.js +90 -45
  70. package/dist/esm/components/heatmap/Heatmap.js +75 -74
  71. package/dist/esm/components/heatmap/HeatmapControls.js +8 -4
  72. package/dist/esm/components/icons/DotPlotIcon.js +58 -0
  73. package/dist/esm/components/icons/HeatmapIcon.js +39 -0
  74. package/dist/esm/components/icons/MatrixPlotIcon.1.js +51 -0
  75. package/dist/esm/components/icons/MatrixPlotIcon.js +53 -0
  76. package/dist/esm/components/icons/ScatterplotIcon.1.js +158 -0
  77. package/dist/esm/components/icons/ScatterplotIcon.js +138 -0
  78. package/dist/esm/components/icons/ViolinPlotIcon.js +36 -0
  79. package/dist/esm/components/matrixplot/Matrixplot.js +75 -75
  80. package/dist/esm/components/matrixplot/MatrixplotControls.js +10 -6
  81. package/dist/esm/components/obs-list/ObsItem.js +282 -217
  82. package/dist/esm/components/obs-list/ObsList.js +176 -143
  83. package/dist/esm/components/obs-list/ObsToolbar.js +3 -3
  84. package/dist/esm/components/obsm-list/ObsmList.js +71 -32
  85. package/dist/esm/components/offcanvas/index.js +68 -33
  86. package/dist/esm/components/pseudospatial/Pseudospatial.js +145 -88
  87. package/dist/esm/components/pseudospatial/PseudospatialToolbar.js +127 -78
  88. package/dist/esm/components/scatterplot/Scatterplot.js +149 -120
  89. package/dist/esm/components/scatterplot/ScatterplotControls.js +50 -35
  90. package/dist/esm/components/scatterplot/SpatialControls.js +153 -125
  91. package/dist/esm/components/scatterplot/Toolbox.js +44 -32
  92. package/dist/esm/components/search-bar/SearchBar.js +187 -130
  93. package/dist/esm/components/search-bar/SearchInfo.js +86 -59
  94. package/dist/esm/components/search-bar/SearchResults.js +100 -77
  95. package/dist/esm/components/toolbar/Toolbar.js +49 -39
  96. package/dist/esm/components/var-list/VarItem.js +142 -113
  97. package/dist/esm/components/var-list/VarList.js +99 -84
  98. package/dist/esm/components/var-list/VarListToolbar.js +64 -58
  99. package/dist/esm/components/var-list/VarSet.js +134 -115
  100. package/dist/esm/components/violin/Violin.js +121 -108
  101. package/dist/esm/components/violin/ViolinControls.js +10 -6
  102. package/dist/esm/constants/colorscales.js +19 -19
  103. package/dist/esm/constants/constants.js +50 -47
  104. package/dist/esm/context/DatasetContext.js +33 -23
  105. package/dist/esm/context/FilterContext.js +11 -8
  106. package/dist/esm/context/SettingsContext.js +273 -89
  107. package/dist/esm/context/ZarrDataContext.js +8 -6
  108. package/dist/esm/helpers/color-helper.js +5 -5
  109. package/dist/esm/helpers/map-helper.js +2 -2
  110. package/dist/esm/helpers/zarr-helper.js +6 -6
  111. package/dist/esm/index.js +22 -22
  112. package/dist/esm/utils/Filter.js +22 -17
  113. package/dist/esm/utils/Histogram.js +39 -37
  114. package/dist/esm/utils/ImageViewer.js +12 -8
  115. package/dist/esm/utils/Legend.js +44 -36
  116. package/dist/esm/utils/LoadingIndicators.js +16 -13
  117. package/dist/esm/utils/Resolver.js +201 -0
  118. package/dist/esm/utils/Skeleton.js +11 -10
  119. package/dist/esm/utils/StyledTooltip.js +38 -0
  120. package/dist/esm/utils/VirtualizedList.js +37 -29
  121. package/dist/esm/utils/errors.js +15 -15
  122. package/dist/esm/utils/requests.js +24 -12
  123. package/dist/esm/utils/search.js +7 -7
  124. package/dist/esm/utils/string.js +7 -7
  125. package/dist/esm/utils/zarrData.js +27 -28
  126. package/package.json +20 -8
  127. package/scss/cherita-bootstrap.scss +2 -2
  128. package/scss/cherita.scss +65 -16
  129. package/scss/components/accordions.scss +15 -2
  130. package/scss/components/layouts.scss +68 -50
  131. package/scss/components/lists.scss +16 -5
  132. package/scss/components/plotly.scss +38 -26
  133. package/scss/components/plots.scss +14 -1
  134. package/dist/assets/images/plots/dotplot.svg +0 -152
  135. package/dist/assets/images/plots/heatmap.svg +0 -193
  136. package/dist/assets/images/plots/matrixplot.svg +0 -275
  137. package/dist/assets/images/plots/scatterplot.svg +0 -198
  138. package/dist/assets/images/plots/violin.svg +0 -50
@@ -1,36 +1,41 @@
1
+ const _excluded = ["buster", "timestamp"];
1
2
  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; }
2
3
  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; }
3
4
  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
5
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
5
6
  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 React, { createContext, useContext, useEffect, useReducer } from "react";
7
- import _ from "lodash";
8
- import { COLOR_ENCODINGS, DOTPLOT_SCALES, LOCAL_STORAGE_KEY, MATRIXPLOT_SCALES, OBS_TYPES, PSEUDOSPATIAL_CATEGORICAL_MODES, VAR_SORT, VAR_SORT_ORDER, VIOLINPLOT_SCALES } from "../constants/constants";
7
+ function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
8
+ function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
9
+ import { createContext, useContext, useEffect, useReducer, useRef } from 'react';
10
+ import _ from 'lodash';
11
+ import { COLOR_ENCODINGS, DOTPLOT_SCALES, LOCAL_STORAGE_KEY, MATRIXPLOT_SCALES, OBS_TYPES, PSEUDOSPATIAL_CATEGORICAL_MODES, VAR_SORT, VAR_SORT_ORDER, VIOLINPLOT_SCALES } from '../constants/constants';
12
+ import { useResolver } from '../utils/Resolver';
13
+ import { jsx as _jsx } from "react/jsx-runtime";
9
14
  export const SettingsContext = /*#__PURE__*/createContext(null);
10
15
  export const SettingsDispatchContext = /*#__PURE__*/createContext(null);
11
-
12
- // @TODO: consider splitting constant values and dataset-resolved values
13
- // e.g. store only obs name in selectedObs, and resolved obs data (counts, values, etc.) elsewhere
14
- // e.g. store only var name in selectedVar, and resolved var data (index, matrix_index) elsewhere
15
- // would simplify passing and validating defaultSettings and localSettings
16
16
  const initialSettings = {
17
17
  selectedObs: null,
18
+ // { name: "obs_name", omit: ["obs_item"], bins: {} }
18
19
  selectedVar: null,
20
+ // { name: "var_name", isSet: false } or { name: "var_set_name", isSet: true, vars: [{ name: "var1" }, { name: "var2" }] }
19
21
  selectedObsm: null,
20
- selectedMultiObs: [],
22
+ // "obsm_name" (e.g. "X_umap")
21
23
  selectedMultiVar: [],
22
- colorEncoding: null,
24
+ // [{ name: "var_name", isSet: false }, { name: "var_set_name", isSet: true, vars: [{ name: "var1" }, { name: "var2" }] }]
23
25
  labelObs: [],
26
+ // [ "obs_name1", "obs_name2" ]
24
27
  vars: [],
28
+ // [{ name: "var_name", isSet: false }, { name: "var_set_name", isSet: true, vars: [{ name: "var1" }, { name: "var2" }] }]
29
+ colorEncoding: null,
25
30
  sliceBy: {
26
31
  obs: false,
27
32
  polygons: false
28
33
  },
29
34
  polygons: {},
30
35
  controls: {
31
- colorScale: "Viridis",
32
- valueRange: [0, 1],
36
+ colorScale: 'Viridis',
33
37
  range: [0, 1],
38
+ // normalized
34
39
  colorAxis: {
35
40
  dmin: 0,
36
41
  dmax: 1,
@@ -58,12 +63,26 @@ const initialSettings = {
58
63
  pseudospatial: {
59
64
  maskSet: null,
60
65
  maskValues: null,
61
- categoricalMode: PSEUDOSPATIAL_CATEGORICAL_MODES.ACROSS.value
66
+ categoricalMode: PSEUDOSPATIAL_CATEGORICAL_MODES.ACROSS.value,
67
+ refImg: {
68
+ visible: false,
69
+ opacity: 1
70
+ }
71
+ },
72
+ // dataset resolved values
73
+ data: {
74
+ // store resolved obs and vars from selectedObs, selectedVar, selectedMultiVar, vars, labelObs
75
+ // keys to be removed when not in any selection
76
+ obs: {},
77
+ vars: {},
78
+ // store maskSets and values
79
+ pseudospatial: {}
62
80
  }
63
81
  };
64
82
 
65
83
  // validate on initialization and reducer
66
84
  const validateSettings = settings => {
85
+ var _settings$selectedObs;
67
86
  // make sure selectedVar is in vars
68
87
  if (settings.selectedVar) {
69
88
  const inVars = _.some(settings.vars, v => v.name === settings.selectedVar.name);
@@ -74,7 +93,7 @@ const validateSettings = settings => {
74
93
 
75
94
  // make sure selectedMultiVar are in vars
76
95
  if (settings.selectedMultiVar) {
77
- const notInVars = _.differenceBy(settings.selectedMultiVar, settings.vars, "name");
96
+ const notInVars = _.differenceBy(settings.selectedMultiVar, settings.vars, 'name');
78
97
  if (notInVars.length) {
79
98
  settings.vars = [...settings.vars, ...notInVars];
80
99
  }
@@ -96,6 +115,21 @@ const validateSettings = settings => {
96
115
  settings.colorEncoding = null;
97
116
  }
98
117
  }
118
+
119
+ // pseudospatial
120
+ if (!settings.pseudospatial.maskSet && settings.pseudospatial.maskValues) {
121
+ settings.pseudospatial.maskValues = null;
122
+ }
123
+
124
+ // Keep only obs in use (selectedObs, labelObs) in data.obs
125
+ const obsNames = _.uniq(_.compact([(_settings$selectedObs = settings.selectedObs) === null || _settings$selectedObs === void 0 ? void 0 : _settings$selectedObs.name, ...settings.labelObs]));
126
+ const intersectionObs = _.intersection(_.keys(settings.data.obs), obsNames);
127
+ settings.data.obs = _.pick(settings.data.obs, intersectionObs);
128
+
129
+ // Keep only vars in use (settings.vars) in data.vars
130
+ const varNames = _.flatMap(settings.vars, v => v.isSet ? _.map(v.vars, vv => vv.name) : v.name);
131
+ const intersectionVars = _.intersection(_.keys(settings.data.vars), varNames);
132
+ settings.data.vars = _.pick(settings.data.vars, intersectionVars);
99
133
  return settings;
100
134
  };
101
135
  const initializer = _ref => {
@@ -104,9 +138,12 @@ const initializer = _ref => {
104
138
  defaultSettings,
105
139
  localSettings
106
140
  } = _ref;
107
- const mergedSettings = canOverrideSettings ? _.assign({}, initialSettings, defaultSettings, localSettings) : _.assign({}, initialSettings, defaultSettings);
141
+ const mergedSettings = canOverrideSettings ? _.defaultsDeep({}, localSettings, defaultSettings, initialSettings) : _.defaultsDeep({}, defaultSettings, initialSettings);
108
142
  return validateSettings(mergedSettings);
109
143
  };
144
+ const validate = settings => {
145
+ return settings ? validateSettings(settings) : null;
146
+ };
110
147
  export function SettingsProvider(_ref2) {
111
148
  let {
112
149
  dataset_url,
@@ -117,30 +154,59 @@ export function SettingsProvider(_ref2) {
117
154
  const DATASET_STORAGE_KEY = "".concat(LOCAL_STORAGE_KEY, "-").concat(dataset_url);
118
155
  // Use localStorage directly instead of useLocalStorage due to unnecessary re-renders
119
156
  // https://github.com/uidotdev/usehooks/issues/157
120
- const localSettings = JSON.parse(localStorage.getItem(DATASET_STORAGE_KEY)) || {};
121
- const [settings, dispatch] = useReducer(settingsReducer, {
157
+ let _ref3 = JSON.parse(localStorage.getItem(DATASET_STORAGE_KEY)) || {},
158
+ {
159
+ buster,
160
+ timestamp
161
+ } = _ref3,
162
+ localSettings = _objectWithoutProperties(_ref3, _excluded);
163
+
164
+ // If the buster is not set or does not match the current package version,
165
+ // reset localSettings to avoid stale data
166
+ if (!buster || buster !== "1.3.1-dev.2025-10-29.6de4119f") {
167
+ localSettings = {};
168
+ }
169
+ const initSettings = useRef(initializer({
122
170
  canOverrideSettings,
123
171
  defaultSettings,
124
172
  localSettings
125
- }, initializer);
173
+ }));
174
+ const resolvedSettings = useResolver(initSettings.current);
175
+ const [settings, dispatch] = useReducer(settingsReducer, resolvedSettings, validate);
176
+ useEffect(() => {
177
+ // If resolvedSettings is null, do not update settings
178
+ if (resolvedSettings) {
179
+ const validatedSettings = validateSettings(resolvedSettings);
180
+ console.log('Initial settings:', validatedSettings);
181
+ dispatch({
182
+ type: 'init',
183
+ settings: validatedSettings
184
+ });
185
+ }
186
+ }, [resolvedSettings]);
126
187
  useEffect(() => {
127
- if (canOverrideSettings) {
188
+ if (canOverrideSettings && settings) {
128
189
  try {
129
- localStorage.setItem(DATASET_STORAGE_KEY, JSON.stringify(settings));
190
+ localStorage.setItem(DATASET_STORAGE_KEY, JSON.stringify(_objectSpread({
191
+ buster: "1.3.1-dev.2025-10-29.6de4119f" || '0.0.0',
192
+ timestamp: Date.now()
193
+ }, _.omit(settings, 'data'))));
130
194
  } catch (err) {
131
- if (err.code === 22 || err.code === 1014 || err.name === "QuotaExceededError" || err.name === "NS_ERROR_DOM_QUOTA_REACHED") {
132
- console.err("Browser storage quota exceeded");
195
+ if (err.code === 22 || err.code === 1014 || err.name === 'QuotaExceededError' || err.name === 'NS_ERROR_DOM_QUOTA_REACHED') {
196
+ console.err('Browser storage quota exceeded');
133
197
  } else {
134
198
  console.err(err);
135
199
  }
136
200
  }
137
201
  }
138
202
  }, [DATASET_STORAGE_KEY, canOverrideSettings, settings]);
139
- return /*#__PURE__*/React.createElement(SettingsContext.Provider, {
140
- value: settings
141
- }, /*#__PURE__*/React.createElement(SettingsDispatchContext.Provider, {
142
- value: dispatch
143
- }, children));
203
+ return /*#__PURE__*/_jsx(SettingsContext.Provider, {
204
+ value: settings,
205
+ children: /*#__PURE__*/_jsx(SettingsDispatchContext.Provider, {
206
+ value: dispatch,
207
+ children: settings && children
208
+ })
209
+ });
144
210
  }
145
211
  export function useSettings() {
146
212
  return useContext(SettingsContext);
@@ -148,13 +214,70 @@ export function useSettings() {
148
214
  export function useSettingsDispatch() {
149
215
  return useContext(SettingsDispatchContext);
150
216
  }
217
+ const OBS_DATA_KEYS = ['name', 'type',
218
+ // categorical and numerical
219
+ 'codes', 'codesMap', 'values', 'n_values', 'value_counts',
220
+ // numerical
221
+ 'bins', 'min', 'max', 'mean', 'median', 'n_unique'];
222
+ const splitObs = obs => {
223
+ if (!obs) return {
224
+ settings: null,
225
+ data: {}
226
+ };
227
+ const settings = _.pick(obs, ['name', 'omit', 'bins']);
228
+ const data = obs ? {
229
+ [obs.name]: _.pick(obs, OBS_DATA_KEYS)
230
+ } : {};
231
+ return {
232
+ settings,
233
+ data
234
+ };
235
+ };
236
+ const splitVar = v => {
237
+ if (!v) return {
238
+ settings: null,
239
+ data: {}
240
+ };
241
+ let settings, data;
242
+ if (v.isSet) {
243
+ settings = _objectSpread(_objectSpread({}, _.pick(v, ['name', 'isSet'])), {}, {
244
+ vars: _.map(v.vars, vv => ({
245
+ name: vv.name
246
+ }))
247
+ });
248
+ data = _.fromPairs(_.map(v.vars, vv => [vv.name, _.pick(vv, ['name', 'index', 'matrix_index'])]));
249
+ } else {
250
+ settings = _.pick(v, ['name', 'isSet']);
251
+ data = {
252
+ [v.name]: _.pick(v, ['name', 'index', 'matrix_index'])
253
+ };
254
+ }
255
+ return {
256
+ settings,
257
+ data
258
+ };
259
+ };
151
260
  function settingsReducer(settings, action) {
152
261
  switch (action.type) {
153
- case "select.obs":
262
+ case 'init':
263
+ {
264
+ return action.settings;
265
+ }
266
+ case 'select.obs':
154
267
  {
155
268
  var _action$obs;
156
- return _objectSpread(_objectSpread({}, settings), {}, {
157
- selectedObs: action.obs,
269
+ const {
270
+ settings: obsSettings,
271
+ data: obsData
272
+ } = splitObs(action.obs);
273
+ return _objectSpread(_objectSpread(_objectSpread({}, settings), action.obs ? {
274
+ selectedObs: obsSettings,
275
+ data: _objectSpread(_objectSpread({}, settings.data), {}, {
276
+ obs: _objectSpread(_objectSpread({}, settings.data.obs), obsData)
277
+ })
278
+ } : {
279
+ selectedObs: null
280
+ }), {}, {
158
281
  controls: _objectSpread(_objectSpread({}, settings.controls), {}, {
159
282
  range: ((_action$obs = action.obs) === null || _action$obs === void 0 ? void 0 : _action$obs.type) === OBS_TYPES.CATEGORICAL ? [0, 1] : settings.controls.range
160
283
  }),
@@ -164,36 +287,50 @@ function settingsReducer(settings, action) {
164
287
  })
165
288
  });
166
289
  }
167
- case "select.obsm":
290
+ case 'select.obsm':
168
291
  {
169
292
  return _objectSpread(_objectSpread({}, settings), {}, {
170
293
  selectedObsm: action.obsm
171
294
  });
172
295
  }
173
- case "select.var":
296
+ case 'select.var':
174
297
  {
298
+ const {
299
+ settings: varSettings,
300
+ data: varData
301
+ } = splitVar(action.var);
175
302
  return validateSettings(_objectSpread(_objectSpread({}, settings), {}, {
176
- selectedVar: action.var
303
+ selectedVar: varSettings,
304
+ data: _objectSpread(_objectSpread({}, settings.data), {}, {
305
+ vars: _objectSpread(_objectSpread({}, settings.data.vars), varData)
306
+ })
177
307
  }));
178
308
  }
179
- case "select.multivar":
309
+ case 'select.multivar':
180
310
  {
181
311
  const inMultiVar = settings.selectedMultiVar.some(v => v.name === action.var.name);
182
312
  if (inMultiVar) {
183
313
  return validateSettings(_objectSpread({}, settings));
184
314
  } else {
315
+ const {
316
+ settings: varSettings,
317
+ data: varData
318
+ } = splitVar(action.var);
185
319
  return validateSettings(_objectSpread(_objectSpread({}, settings), {}, {
186
- selectedMultiVar: [...settings.selectedMultiVar, action.var]
320
+ selectedMultiVar: [...settings.selectedMultiVar, varSettings],
321
+ data: _objectSpread(_objectSpread({}, settings.data), {}, {
322
+ vars: _objectSpread(_objectSpread({}, settings.data.vars), varData)
323
+ })
187
324
  }));
188
325
  }
189
326
  }
190
- case "deselect.multivar":
327
+ case 'deselect.multivar':
191
328
  {
192
329
  return validateSettings(_objectSpread(_objectSpread({}, settings), {}, {
193
330
  selectedMultiVar: settings.selectedMultiVar.filter(v => v !== action.var.name)
194
331
  }));
195
332
  }
196
- case "toggle.multivar":
333
+ case 'toggle.multivar':
197
334
  {
198
335
  const inMultiVar = settings.selectedMultiVar.some(v => v.name === action.var.name);
199
336
  if (inMultiVar) {
@@ -201,18 +338,25 @@ function settingsReducer(settings, action) {
201
338
  selectedMultiVar: settings.selectedMultiVar.filter(v => v.name !== action.var.name)
202
339
  }));
203
340
  } else {
341
+ const {
342
+ settings: varSettings,
343
+ data: varData
344
+ } = splitVar(action.var);
204
345
  return validateSettings(_objectSpread(_objectSpread({}, settings), {}, {
205
- selectedMultiVar: [...settings.selectedMultiVar, action.var]
346
+ selectedMultiVar: [...settings.selectedMultiVar, varSettings],
347
+ data: _objectSpread(_objectSpread({}, settings.data), {}, {
348
+ vars: _objectSpread(_objectSpread({}, settings.data.vars), varData)
349
+ })
206
350
  }));
207
351
  }
208
352
  }
209
- case "set.colorEncoding":
353
+ case 'set.colorEncoding':
210
354
  {
211
355
  return validateSettings(_objectSpread(_objectSpread({}, settings), {}, {
212
356
  colorEncoding: action.value
213
357
  }));
214
358
  }
215
- case "reset.vars":
359
+ case 'reset.vars':
216
360
  {
217
361
  return validateSettings(_objectSpread(_objectSpread({}, settings), {}, {
218
362
  vars: [],
@@ -220,29 +364,36 @@ function settingsReducer(settings, action) {
220
364
  selectedMultiVar: []
221
365
  }));
222
366
  }
223
- case "reset.multiVar":
367
+ case 'reset.multiVar':
224
368
  {
225
369
  return validateSettings(_objectSpread(_objectSpread({}, settings), {}, {
226
370
  selectedMultiVar: []
227
371
  }));
228
372
  }
229
- case "reset.var":
373
+ case 'reset.var':
230
374
  {
231
375
  return validateSettings(_objectSpread(_objectSpread({}, settings), {}, {
232
376
  selectedVar: null
233
377
  }));
234
378
  }
235
- case "add.var":
379
+ case 'add.var':
236
380
  {
237
381
  if (settings.vars.find(v => v.name === action.var.name)) {
238
382
  return settings;
239
383
  } else {
384
+ const {
385
+ settings: varSettings,
386
+ data: varData
387
+ } = splitVar(action.var);
240
388
  return _objectSpread(_objectSpread({}, settings), {}, {
241
- vars: [...settings.vars, action.var]
389
+ vars: [...settings.vars, varSettings],
390
+ data: _objectSpread(_objectSpread({}, settings.data), {}, {
391
+ vars: _objectSpread(_objectSpread({}, settings.data.vars), varData)
392
+ })
242
393
  });
243
394
  }
244
395
  }
245
- case "remove.var":
396
+ case 'remove.var':
246
397
  {
247
398
  var _settings$selectedVar;
248
399
  const selectedVar = ((_settings$selectedVar = settings.selectedVar) === null || _settings$selectedVar === void 0 ? void 0 : _settings$selectedVar.name) === action.var.name ? null : settings.selectedVar;
@@ -253,7 +404,7 @@ function settingsReducer(settings, action) {
253
404
  selectedMultiVar: selectedMultiVar
254
405
  }));
255
406
  }
256
- case "add.varSet.var":
407
+ case 'add.varSet.var':
257
408
  {
258
409
  const varSet = settings.vars.find(s => s.isSet && s.name === action.varSet.name);
259
410
  if (!varSet) {
@@ -263,7 +414,11 @@ function settingsReducer(settings, action) {
263
414
  return settings;
264
415
  } else {
265
416
  var _settings$selectedVar2;
266
- const varSetVars = [...varSet.vars, action.var];
417
+ const {
418
+ settings: varSettings,
419
+ data: varData
420
+ } = splitVar(action.var);
421
+ const varSetVars = [...varSet.vars, varSettings];
267
422
  const vars = settings.vars.map(v => {
268
423
  if (v.name === varSet.name) {
269
424
  return _objectSpread(_objectSpread({}, v), {}, {
@@ -288,11 +443,14 @@ function settingsReducer(settings, action) {
288
443
  return validateSettings(_objectSpread(_objectSpread({}, settings), {}, {
289
444
  vars: vars,
290
445
  selectedVar: selectedVar,
291
- selectedMultiVar: selectedMultiVar
446
+ selectedMultiVar: selectedMultiVar,
447
+ data: _objectSpread(_objectSpread({}, settings.data), {}, {
448
+ vars: _objectSpread(_objectSpread({}, settings.data.vars), varData)
449
+ })
292
450
  }));
293
451
  }
294
452
  }
295
- case "remove.varSet.var":
453
+ case 'remove.varSet.var':
296
454
  {
297
455
  const varSet = settings.vars.find(s => s.isSet && s.name === action.varSet.name);
298
456
  if (!varSet) {
@@ -344,7 +502,7 @@ function settingsReducer(settings, action) {
344
502
  }
345
503
  }
346
504
  }
347
- case "set.controls.colorScale":
505
+ case 'set.controls.colorScale':
348
506
  {
349
507
  return _objectSpread(_objectSpread({}, settings), {}, {
350
508
  controls: _objectSpread(_objectSpread({}, settings.controls), {}, {
@@ -352,15 +510,7 @@ function settingsReducer(settings, action) {
352
510
  })
353
511
  });
354
512
  }
355
- case "set.controls.valueRange":
356
- {
357
- return _objectSpread(_objectSpread({}, settings), {}, {
358
- controls: _objectSpread(_objectSpread({}, settings.controls), {}, {
359
- valueRange: action.valueRange
360
- })
361
- });
362
- }
363
- case "set.controls.range":
513
+ case 'set.controls.range':
364
514
  {
365
515
  return _objectSpread(_objectSpread({}, settings), {}, {
366
516
  controls: _objectSpread(_objectSpread({}, settings.controls), {}, {
@@ -368,7 +518,7 @@ function settingsReducer(settings, action) {
368
518
  })
369
519
  });
370
520
  }
371
- case "set.controls.colorAxis":
521
+ case 'set.controls.colorAxis':
372
522
  {
373
523
  return _objectSpread(_objectSpread({}, settings), {}, {
374
524
  controls: _objectSpread(_objectSpread({}, settings.controls), {}, {
@@ -376,7 +526,7 @@ function settingsReducer(settings, action) {
376
526
  })
377
527
  });
378
528
  }
379
- case "set.controls.colorAxis.crange":
529
+ case 'set.controls.colorAxis.crange':
380
530
  {
381
531
  return _objectSpread(_objectSpread({}, settings), {}, {
382
532
  controls: _objectSpread(_objectSpread({}, settings.controls), {}, {
@@ -387,7 +537,7 @@ function settingsReducer(settings, action) {
387
537
  })
388
538
  });
389
539
  }
390
- case "set.controls.colorAxis.cmin":
540
+ case 'set.controls.colorAxis.cmin':
391
541
  {
392
542
  return _objectSpread(_objectSpread({}, settings), {}, {
393
543
  controls: _objectSpread(_objectSpread({}, settings.controls), {}, {
@@ -397,7 +547,7 @@ function settingsReducer(settings, action) {
397
547
  })
398
548
  });
399
549
  }
400
- case "set.controls.colorAxis.cmax":
550
+ case 'set.controls.colorAxis.cmax':
401
551
  {
402
552
  return _objectSpread(_objectSpread({}, settings), {}, {
403
553
  controls: _objectSpread(_objectSpread({}, settings.controls), {}, {
@@ -407,7 +557,7 @@ function settingsReducer(settings, action) {
407
557
  })
408
558
  });
409
559
  }
410
- case "set.controls.scale":
560
+ case 'set.controls.scale':
411
561
  {
412
562
  return _objectSpread(_objectSpread({}, settings), {}, {
413
563
  controls: _objectSpread(_objectSpread({}, settings.controls), {}, {
@@ -417,7 +567,7 @@ function settingsReducer(settings, action) {
417
567
  })
418
568
  });
419
569
  }
420
- case "set.controls.meanOnlyExpressed":
570
+ case 'set.controls.meanOnlyExpressed':
421
571
  {
422
572
  return _objectSpread(_objectSpread({}, settings), {}, {
423
573
  controls: _objectSpread(_objectSpread({}, settings.controls), {}, {
@@ -425,7 +575,7 @@ function settingsReducer(settings, action) {
425
575
  })
426
576
  });
427
577
  }
428
- case "set.controls.expressionCutoff":
578
+ case 'set.controls.expressionCutoff':
429
579
  {
430
580
  return _objectSpread(_objectSpread({}, settings), {}, {
431
581
  controls: _objectSpread(_objectSpread({}, settings.controls), {}, {
@@ -433,24 +583,31 @@ function settingsReducer(settings, action) {
433
583
  })
434
584
  });
435
585
  }
436
- case "toggle.slice.obs":
586
+ case 'toggle.slice.obs':
437
587
  {
438
- if (_.isEqual(settings.selectedObs, action.obs)) {
588
+ if (settings.selectedObs && settings.selectedObs.name === action.obs.name) {
439
589
  return _objectSpread(_objectSpread({}, settings), {}, {
440
590
  sliceBy: _objectSpread(_objectSpread({}, settings.sliceBy), {}, {
441
591
  obs: !settings.sliceBy.obs
442
592
  })
443
593
  });
444
594
  } else {
595
+ const {
596
+ settings: obsSettings,
597
+ data: obsData
598
+ } = splitObs(action.obs);
445
599
  return _objectSpread(_objectSpread({}, settings), {}, {
446
- selectedObs: action.obs,
600
+ selectedObs: obsSettings,
601
+ data: _objectSpread(_objectSpread({}, settings.data), {}, {
602
+ obs: _objectSpread(_objectSpread({}, settings.data.obs), obsData)
603
+ }),
447
604
  sliceBy: _objectSpread(_objectSpread({}, settings.sliceBy), {}, {
448
605
  obs: true
449
606
  })
450
607
  });
451
608
  }
452
609
  }
453
- case "toggle.slice.polygons":
610
+ case 'toggle.slice.polygons':
454
611
  {
455
612
  return _objectSpread(_objectSpread({}, settings), {}, {
456
613
  sliceBy: _objectSpread(_objectSpread({}, settings.sliceBy), {}, {
@@ -458,7 +615,7 @@ function settingsReducer(settings, action) {
458
615
  })
459
616
  });
460
617
  }
461
- case "disable.slice.polygons":
618
+ case 'disable.slice.polygons':
462
619
  {
463
620
  return _objectSpread(_objectSpread({}, settings), {}, {
464
621
  sliceBy: _objectSpread(_objectSpread({}, settings.sliceBy), {}, {
@@ -466,29 +623,36 @@ function settingsReducer(settings, action) {
466
623
  })
467
624
  });
468
625
  }
469
- case "add.label.obs":
626
+ case 'add.label.obs':
470
627
  {
471
- if (settings.labelObs.find(i => _.isEqual(i, action.obs))) {
628
+ if (_.includes(settings.labelObs, action.obs.name)) {
472
629
  return settings;
473
630
  } else {
631
+ const {
632
+ settings: obsSettings,
633
+ data: obsData
634
+ } = splitObs(action.obs);
474
635
  return _objectSpread(_objectSpread({}, settings), {}, {
475
- labelObs: [...settings.labelObs, action.obs]
636
+ labelObs: [...settings.labelObs, obsSettings.name],
637
+ data: _objectSpread(_objectSpread({}, settings.data), {}, {
638
+ obs: _objectSpread(_objectSpread({}, settings.data.obs), obsData)
639
+ })
476
640
  });
477
641
  }
478
642
  }
479
- case "remove.label.obs":
643
+ case 'remove.label.obs':
480
644
  {
481
- return _objectSpread(_objectSpread({}, settings), {}, {
482
- labelObs: settings.labelObs.filter(a => a.name !== action.obsName)
483
- });
645
+ return validateSettings(_objectSpread(_objectSpread({}, settings), {}, {
646
+ labelObs: settings.labelObs.filter(a => a !== action.obsName)
647
+ }));
484
648
  }
485
- case "reset.label.obs":
649
+ case 'reset.label.obs':
486
650
  {
487
- return _objectSpread(_objectSpread({}, settings), {}, {
651
+ return validateSettings(_objectSpread(_objectSpread({}, settings), {}, {
488
652
  labelObs: []
489
- });
653
+ }));
490
654
  }
491
- case "set.varSort":
655
+ case 'set.varSort':
492
656
  {
493
657
  return _objectSpread(_objectSpread({}, settings), {}, {
494
658
  varSort: _objectSpread(_objectSpread({}, settings.varSort), {}, {
@@ -499,7 +663,7 @@ function settingsReducer(settings, action) {
499
663
  })
500
664
  });
501
665
  }
502
- case "set.varSort.sort":
666
+ case 'set.varSort.sort':
503
667
  {
504
668
  return _objectSpread(_objectSpread({}, settings), {}, {
505
669
  varSort: _objectSpread(_objectSpread({}, settings.varSort), {}, {
@@ -509,7 +673,7 @@ function settingsReducer(settings, action) {
509
673
  })
510
674
  });
511
675
  }
512
- case "set.varSort.sortOrder":
676
+ case 'set.varSort.sortOrder':
513
677
  {
514
678
  return _objectSpread(_objectSpread({}, settings), {}, {
515
679
  varSort: _objectSpread(_objectSpread({}, settings.varSort), {}, {
@@ -519,7 +683,7 @@ function settingsReducer(settings, action) {
519
683
  })
520
684
  });
521
685
  }
522
- case "set.polygons":
686
+ case 'set.polygons':
523
687
  {
524
688
  return _objectSpread(_objectSpread({}, settings), {}, {
525
689
  polygons: _objectSpread(_objectSpread({}, settings.polygons), {}, {
@@ -527,7 +691,7 @@ function settingsReducer(settings, action) {
527
691
  })
528
692
  });
529
693
  }
530
- case "set.pseudospatial.maskSet":
694
+ case 'set.pseudospatial.maskSet':
531
695
  {
532
696
  return _objectSpread(_objectSpread({}, settings), {}, {
533
697
  pseudospatial: _objectSpread(_objectSpread({}, settings.pseudospatial), {}, {
@@ -535,7 +699,7 @@ function settingsReducer(settings, action) {
535
699
  })
536
700
  });
537
701
  }
538
- case "set.pseudospatial.maskValues":
702
+ case 'set.pseudospatial.maskValues':
539
703
  {
540
704
  return _objectSpread(_objectSpread({}, settings), {}, {
541
705
  pseudospatial: _objectSpread(_objectSpread({}, settings.pseudospatial), {}, {
@@ -543,7 +707,7 @@ function settingsReducer(settings, action) {
543
707
  })
544
708
  });
545
709
  }
546
- case "set.pseudospatial.categoricalMode":
710
+ case 'set.pseudospatial.categoricalMode':
547
711
  {
548
712
  return _objectSpread(_objectSpread({}, settings), {}, {
549
713
  pseudospatial: _objectSpread(_objectSpread({}, settings.pseudospatial), {}, {
@@ -551,9 +715,29 @@ function settingsReducer(settings, action) {
551
715
  })
552
716
  });
553
717
  }
718
+ case 'toggle.pseudospatial.refImg.visible':
719
+ {
720
+ return _objectSpread(_objectSpread({}, settings), {}, {
721
+ pseudospatial: _objectSpread(_objectSpread({}, settings.pseudospatial), {}, {
722
+ refImg: _objectSpread(_objectSpread({}, settings.pseudospatial.refImg), {}, {
723
+ visible: !settings.pseudospatial.refImg.visible
724
+ })
725
+ })
726
+ });
727
+ }
728
+ case 'set.pseudospatial.refImg.opacity':
729
+ {
730
+ return _objectSpread(_objectSpread({}, settings), {}, {
731
+ pseudospatial: _objectSpread(_objectSpread({}, settings.pseudospatial), {}, {
732
+ refImg: _objectSpread(_objectSpread({}, settings.pseudospatial.refImg), {}, {
733
+ opacity: action.opacity
734
+ })
735
+ })
736
+ });
737
+ }
554
738
  default:
555
739
  {
556
- throw Error("Unknown action: " + action.type);
740
+ throw Error('Unknown action: ' + action.type);
557
741
  }
558
742
  }
559
743
  }