@haniffalab/cherita-react 1.4.1 → 1.4.2-dev.2025-10-29.e8bbb191

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 +100 -74
  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 +258 -210
  20. package/dist/cjs/components/obs-list/ObsList.js +161 -133
  21. package/dist/cjs/components/obs-list/ObsToolbar.js +2 -3
  22. package/dist/cjs/components/obsm-list/ObsmList.js +53 -38
  23. package/dist/cjs/components/offcanvas/index.js +61 -31
  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 +127 -99
  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 +168 -121
  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 +115 -88
  35. package/dist/cjs/components/var-list/VarList.js +85 -69
  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 -107
  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 +47 -47
  42. package/dist/cjs/context/DatasetContext.js +24 -16
  43. package/dist/cjs/context/FilterContext.js +11 -9
  44. package/dist/cjs/context/SettingsContext.js +255 -89
  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 +34 -27
  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 +64 -42
  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 +120 -93
  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 +273 -222
  82. package/dist/esm/components/obs-list/ObsList.js +176 -147
  83. package/dist/esm/components/obs-list/ObsToolbar.js +3 -3
  84. package/dist/esm/components/obsm-list/ObsmList.js +60 -44
  85. package/dist/esm/components/offcanvas/index.js +67 -37
  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 +148 -119
  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 +180 -132
  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 +126 -98
  97. package/dist/esm/components/var-list/VarList.js +99 -82
  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 -118
  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 +47 -47
  104. package/dist/esm/context/DatasetContext.js +31 -22
  105. package/dist/esm/context/FilterContext.js +11 -8
  106. package/dist/esm/context/SettingsContext.js +257 -90
  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 +35 -27
  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 +21 -9
  127. package/scss/cherita-bootstrap.scss +2 -2
  128. package/scss/cherita.scss +43 -17
  129. package/scss/components/accordions.scss +4 -1
  130. package/scss/components/layouts.scss +15 -33
  131. package/scss/components/lists.scss +8 -4
  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
@@ -6,34 +6,36 @@ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol"
6
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); }
7
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
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 React, { createContext, useContext, useEffect, useReducer } 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";
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";
12
14
  export const SettingsContext = /*#__PURE__*/createContext(null);
13
15
  export const SettingsDispatchContext = /*#__PURE__*/createContext(null);
14
-
15
- // @TODO: consider splitting constant values and dataset-resolved values
16
- // e.g. store only obs name in selectedObs, and resolved obs data (counts, values, etc.) elsewhere
17
- // e.g. store only var name in selectedVar, and resolved var data (index, matrix_index) elsewhere
18
- // would simplify passing and validating defaultSettings and localSettings
19
16
  const initialSettings = {
20
17
  selectedObs: null,
18
+ // { name: "obs_name", omit: ["obs_item"], bins: {} }
21
19
  selectedVar: null,
20
+ // { name: "var_name", isSet: false } or { name: "var_set_name", isSet: true, vars: [{ name: "var1" }, { name: "var2" }] }
22
21
  selectedObsm: null,
23
- selectedMultiObs: [],
22
+ // "obsm_name" (e.g. "X_umap")
24
23
  selectedMultiVar: [],
25
- colorEncoding: null,
24
+ // [{ name: "var_name", isSet: false }, { name: "var_set_name", isSet: true, vars: [{ name: "var1" }, { name: "var2" }] }]
26
25
  labelObs: [],
26
+ // [ "obs_name1", "obs_name2" ]
27
27
  vars: [],
28
+ // [{ name: "var_name", isSet: false }, { name: "var_set_name", isSet: true, vars: [{ name: "var1" }, { name: "var2" }] }]
29
+ colorEncoding: null,
28
30
  sliceBy: {
29
31
  obs: false,
30
32
  polygons: false
31
33
  },
32
34
  polygons: {},
33
35
  controls: {
34
- colorScale: "Viridis",
35
- valueRange: [0, 1],
36
+ colorScale: 'Viridis',
36
37
  range: [0, 1],
38
+ // normalized
37
39
  colorAxis: {
38
40
  dmin: 0,
39
41
  dmax: 1,
@@ -61,12 +63,26 @@ const initialSettings = {
61
63
  pseudospatial: {
62
64
  maskSet: null,
63
65
  maskValues: null,
64
- 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: {}
65
80
  }
66
81
  };
67
82
 
68
83
  // validate on initialization and reducer
69
84
  const validateSettings = settings => {
85
+ var _settings$selectedObs;
70
86
  // make sure selectedVar is in vars
71
87
  if (settings.selectedVar) {
72
88
  const inVars = _.some(settings.vars, v => v.name === settings.selectedVar.name);
@@ -77,7 +93,7 @@ const validateSettings = settings => {
77
93
 
78
94
  // make sure selectedMultiVar are in vars
79
95
  if (settings.selectedMultiVar) {
80
- const notInVars = _.differenceBy(settings.selectedMultiVar, settings.vars, "name");
96
+ const notInVars = _.differenceBy(settings.selectedMultiVar, settings.vars, 'name');
81
97
  if (notInVars.length) {
82
98
  settings.vars = [...settings.vars, ...notInVars];
83
99
  }
@@ -99,6 +115,21 @@ const validateSettings = settings => {
99
115
  settings.colorEncoding = null;
100
116
  }
101
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);
102
133
  return settings;
103
134
  };
104
135
  const initializer = _ref => {
@@ -107,9 +138,12 @@ const initializer = _ref => {
107
138
  defaultSettings,
108
139
  localSettings
109
140
  } = _ref;
110
- const mergedSettings = canOverrideSettings ? _.assign({}, initialSettings, defaultSettings, localSettings) : _.assign({}, initialSettings, defaultSettings);
141
+ const mergedSettings = canOverrideSettings ? _.defaultsDeep({}, localSettings, defaultSettings, initialSettings) : _.defaultsDeep({}, defaultSettings, initialSettings);
111
142
  return validateSettings(mergedSettings);
112
143
  };
144
+ const validate = settings => {
145
+ return settings ? validateSettings(settings) : null;
146
+ };
113
147
  export function SettingsProvider(_ref2) {
114
148
  let {
115
149
  dataset_url,
@@ -129,35 +163,50 @@ export function SettingsProvider(_ref2) {
129
163
 
130
164
  // If the buster is not set or does not match the current package version,
131
165
  // reset localSettings to avoid stale data
132
- if (!buster || buster !== "1.4.1") {
166
+ if (!buster || buster !== "1.4.2-dev.2025-10-29.e8bbb191") {
133
167
  localSettings = {};
134
168
  }
135
- const [settings, dispatch] = useReducer(settingsReducer, {
169
+ const initSettings = useRef(initializer({
136
170
  canOverrideSettings,
137
171
  defaultSettings,
138
172
  localSettings
139
- }, initializer);
173
+ }));
174
+ const resolvedSettings = useResolver(initSettings.current);
175
+ const [settings, dispatch] = useReducer(settingsReducer, resolvedSettings, validate);
140
176
  useEffect(() => {
141
- if (canOverrideSettings) {
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]);
187
+ useEffect(() => {
188
+ if (canOverrideSettings && settings) {
142
189
  try {
143
190
  localStorage.setItem(DATASET_STORAGE_KEY, JSON.stringify(_objectSpread({
144
- buster: "1.4.1" || "0.0.0",
191
+ buster: "1.4.2-dev.2025-10-29.e8bbb191" || '0.0.0',
145
192
  timestamp: Date.now()
146
- }, settings)));
193
+ }, _.omit(settings, 'data'))));
147
194
  } catch (err) {
148
- if (err.code === 22 || err.code === 1014 || err.name === "QuotaExceededError" || err.name === "NS_ERROR_DOM_QUOTA_REACHED") {
149
- 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');
150
197
  } else {
151
198
  console.err(err);
152
199
  }
153
200
  }
154
201
  }
155
202
  }, [DATASET_STORAGE_KEY, canOverrideSettings, settings]);
156
- return /*#__PURE__*/React.createElement(SettingsContext.Provider, {
157
- value: settings
158
- }, /*#__PURE__*/React.createElement(SettingsDispatchContext.Provider, {
159
- value: dispatch
160
- }, 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
+ });
161
210
  }
162
211
  export function useSettings() {
163
212
  return useContext(SettingsContext);
@@ -165,13 +214,70 @@ export function useSettings() {
165
214
  export function useSettingsDispatch() {
166
215
  return useContext(SettingsDispatchContext);
167
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
+ };
168
260
  function settingsReducer(settings, action) {
169
261
  switch (action.type) {
170
- case "select.obs":
262
+ case 'init':
263
+ {
264
+ return action.settings;
265
+ }
266
+ case 'select.obs':
171
267
  {
172
268
  var _action$obs;
173
- return _objectSpread(_objectSpread({}, settings), {}, {
174
- 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
+ }), {}, {
175
281
  controls: _objectSpread(_objectSpread({}, settings.controls), {}, {
176
282
  range: ((_action$obs = action.obs) === null || _action$obs === void 0 ? void 0 : _action$obs.type) === OBS_TYPES.CATEGORICAL ? [0, 1] : settings.controls.range
177
283
  }),
@@ -181,36 +287,50 @@ function settingsReducer(settings, action) {
181
287
  })
182
288
  });
183
289
  }
184
- case "select.obsm":
290
+ case 'select.obsm':
185
291
  {
186
292
  return _objectSpread(_objectSpread({}, settings), {}, {
187
293
  selectedObsm: action.obsm
188
294
  });
189
295
  }
190
- case "select.var":
296
+ case 'select.var':
191
297
  {
298
+ const {
299
+ settings: varSettings,
300
+ data: varData
301
+ } = splitVar(action.var);
192
302
  return validateSettings(_objectSpread(_objectSpread({}, settings), {}, {
193
- selectedVar: action.var
303
+ selectedVar: varSettings,
304
+ data: _objectSpread(_objectSpread({}, settings.data), {}, {
305
+ vars: _objectSpread(_objectSpread({}, settings.data.vars), varData)
306
+ })
194
307
  }));
195
308
  }
196
- case "select.multivar":
309
+ case 'select.multivar':
197
310
  {
198
311
  const inMultiVar = settings.selectedMultiVar.some(v => v.name === action.var.name);
199
312
  if (inMultiVar) {
200
313
  return validateSettings(_objectSpread({}, settings));
201
314
  } else {
315
+ const {
316
+ settings: varSettings,
317
+ data: varData
318
+ } = splitVar(action.var);
202
319
  return validateSettings(_objectSpread(_objectSpread({}, settings), {}, {
203
- 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
+ })
204
324
  }));
205
325
  }
206
326
  }
207
- case "deselect.multivar":
327
+ case 'deselect.multivar':
208
328
  {
209
329
  return validateSettings(_objectSpread(_objectSpread({}, settings), {}, {
210
330
  selectedMultiVar: settings.selectedMultiVar.filter(v => v !== action.var.name)
211
331
  }));
212
332
  }
213
- case "toggle.multivar":
333
+ case 'toggle.multivar':
214
334
  {
215
335
  const inMultiVar = settings.selectedMultiVar.some(v => v.name === action.var.name);
216
336
  if (inMultiVar) {
@@ -218,18 +338,25 @@ function settingsReducer(settings, action) {
218
338
  selectedMultiVar: settings.selectedMultiVar.filter(v => v.name !== action.var.name)
219
339
  }));
220
340
  } else {
341
+ const {
342
+ settings: varSettings,
343
+ data: varData
344
+ } = splitVar(action.var);
221
345
  return validateSettings(_objectSpread(_objectSpread({}, settings), {}, {
222
- 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
+ })
223
350
  }));
224
351
  }
225
352
  }
226
- case "set.colorEncoding":
353
+ case 'set.colorEncoding':
227
354
  {
228
355
  return validateSettings(_objectSpread(_objectSpread({}, settings), {}, {
229
356
  colorEncoding: action.value
230
357
  }));
231
358
  }
232
- case "reset.vars":
359
+ case 'reset.vars':
233
360
  {
234
361
  return validateSettings(_objectSpread(_objectSpread({}, settings), {}, {
235
362
  vars: [],
@@ -237,29 +364,36 @@ function settingsReducer(settings, action) {
237
364
  selectedMultiVar: []
238
365
  }));
239
366
  }
240
- case "reset.multiVar":
367
+ case 'reset.multiVar':
241
368
  {
242
369
  return validateSettings(_objectSpread(_objectSpread({}, settings), {}, {
243
370
  selectedMultiVar: []
244
371
  }));
245
372
  }
246
- case "reset.var":
373
+ case 'reset.var':
247
374
  {
248
375
  return validateSettings(_objectSpread(_objectSpread({}, settings), {}, {
249
376
  selectedVar: null
250
377
  }));
251
378
  }
252
- case "add.var":
379
+ case 'add.var':
253
380
  {
254
381
  if (settings.vars.find(v => v.name === action.var.name)) {
255
382
  return settings;
256
383
  } else {
384
+ const {
385
+ settings: varSettings,
386
+ data: varData
387
+ } = splitVar(action.var);
257
388
  return _objectSpread(_objectSpread({}, settings), {}, {
258
- 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
+ })
259
393
  });
260
394
  }
261
395
  }
262
- case "remove.var":
396
+ case 'remove.var':
263
397
  {
264
398
  var _settings$selectedVar;
265
399
  const selectedVar = ((_settings$selectedVar = settings.selectedVar) === null || _settings$selectedVar === void 0 ? void 0 : _settings$selectedVar.name) === action.var.name ? null : settings.selectedVar;
@@ -270,7 +404,7 @@ function settingsReducer(settings, action) {
270
404
  selectedMultiVar: selectedMultiVar
271
405
  }));
272
406
  }
273
- case "add.varSet.var":
407
+ case 'add.varSet.var':
274
408
  {
275
409
  const varSet = settings.vars.find(s => s.isSet && s.name === action.varSet.name);
276
410
  if (!varSet) {
@@ -280,7 +414,11 @@ function settingsReducer(settings, action) {
280
414
  return settings;
281
415
  } else {
282
416
  var _settings$selectedVar2;
283
- const varSetVars = [...varSet.vars, action.var];
417
+ const {
418
+ settings: varSettings,
419
+ data: varData
420
+ } = splitVar(action.var);
421
+ const varSetVars = [...varSet.vars, varSettings];
284
422
  const vars = settings.vars.map(v => {
285
423
  if (v.name === varSet.name) {
286
424
  return _objectSpread(_objectSpread({}, v), {}, {
@@ -305,11 +443,14 @@ function settingsReducer(settings, action) {
305
443
  return validateSettings(_objectSpread(_objectSpread({}, settings), {}, {
306
444
  vars: vars,
307
445
  selectedVar: selectedVar,
308
- selectedMultiVar: selectedMultiVar
446
+ selectedMultiVar: selectedMultiVar,
447
+ data: _objectSpread(_objectSpread({}, settings.data), {}, {
448
+ vars: _objectSpread(_objectSpread({}, settings.data.vars), varData)
449
+ })
309
450
  }));
310
451
  }
311
452
  }
312
- case "remove.varSet.var":
453
+ case 'remove.varSet.var':
313
454
  {
314
455
  const varSet = settings.vars.find(s => s.isSet && s.name === action.varSet.name);
315
456
  if (!varSet) {
@@ -361,7 +502,7 @@ function settingsReducer(settings, action) {
361
502
  }
362
503
  }
363
504
  }
364
- case "set.controls.colorScale":
505
+ case 'set.controls.colorScale':
365
506
  {
366
507
  return _objectSpread(_objectSpread({}, settings), {}, {
367
508
  controls: _objectSpread(_objectSpread({}, settings.controls), {}, {
@@ -369,15 +510,7 @@ function settingsReducer(settings, action) {
369
510
  })
370
511
  });
371
512
  }
372
- case "set.controls.valueRange":
373
- {
374
- return _objectSpread(_objectSpread({}, settings), {}, {
375
- controls: _objectSpread(_objectSpread({}, settings.controls), {}, {
376
- valueRange: action.valueRange
377
- })
378
- });
379
- }
380
- case "set.controls.range":
513
+ case 'set.controls.range':
381
514
  {
382
515
  return _objectSpread(_objectSpread({}, settings), {}, {
383
516
  controls: _objectSpread(_objectSpread({}, settings.controls), {}, {
@@ -385,7 +518,7 @@ function settingsReducer(settings, action) {
385
518
  })
386
519
  });
387
520
  }
388
- case "set.controls.colorAxis":
521
+ case 'set.controls.colorAxis':
389
522
  {
390
523
  return _objectSpread(_objectSpread({}, settings), {}, {
391
524
  controls: _objectSpread(_objectSpread({}, settings.controls), {}, {
@@ -393,7 +526,7 @@ function settingsReducer(settings, action) {
393
526
  })
394
527
  });
395
528
  }
396
- case "set.controls.colorAxis.crange":
529
+ case 'set.controls.colorAxis.crange':
397
530
  {
398
531
  return _objectSpread(_objectSpread({}, settings), {}, {
399
532
  controls: _objectSpread(_objectSpread({}, settings.controls), {}, {
@@ -404,7 +537,7 @@ function settingsReducer(settings, action) {
404
537
  })
405
538
  });
406
539
  }
407
- case "set.controls.colorAxis.cmin":
540
+ case 'set.controls.colorAxis.cmin':
408
541
  {
409
542
  return _objectSpread(_objectSpread({}, settings), {}, {
410
543
  controls: _objectSpread(_objectSpread({}, settings.controls), {}, {
@@ -414,7 +547,7 @@ function settingsReducer(settings, action) {
414
547
  })
415
548
  });
416
549
  }
417
- case "set.controls.colorAxis.cmax":
550
+ case 'set.controls.colorAxis.cmax':
418
551
  {
419
552
  return _objectSpread(_objectSpread({}, settings), {}, {
420
553
  controls: _objectSpread(_objectSpread({}, settings.controls), {}, {
@@ -424,7 +557,7 @@ function settingsReducer(settings, action) {
424
557
  })
425
558
  });
426
559
  }
427
- case "set.controls.scale":
560
+ case 'set.controls.scale':
428
561
  {
429
562
  return _objectSpread(_objectSpread({}, settings), {}, {
430
563
  controls: _objectSpread(_objectSpread({}, settings.controls), {}, {
@@ -434,7 +567,7 @@ function settingsReducer(settings, action) {
434
567
  })
435
568
  });
436
569
  }
437
- case "set.controls.meanOnlyExpressed":
570
+ case 'set.controls.meanOnlyExpressed':
438
571
  {
439
572
  return _objectSpread(_objectSpread({}, settings), {}, {
440
573
  controls: _objectSpread(_objectSpread({}, settings.controls), {}, {
@@ -442,7 +575,7 @@ function settingsReducer(settings, action) {
442
575
  })
443
576
  });
444
577
  }
445
- case "set.controls.expressionCutoff":
578
+ case 'set.controls.expressionCutoff':
446
579
  {
447
580
  return _objectSpread(_objectSpread({}, settings), {}, {
448
581
  controls: _objectSpread(_objectSpread({}, settings.controls), {}, {
@@ -450,24 +583,31 @@ function settingsReducer(settings, action) {
450
583
  })
451
584
  });
452
585
  }
453
- case "toggle.slice.obs":
586
+ case 'toggle.slice.obs':
454
587
  {
455
- if (_.isEqual(settings.selectedObs, action.obs)) {
588
+ if (settings.selectedObs && settings.selectedObs.name === action.obs.name) {
456
589
  return _objectSpread(_objectSpread({}, settings), {}, {
457
590
  sliceBy: _objectSpread(_objectSpread({}, settings.sliceBy), {}, {
458
591
  obs: !settings.sliceBy.obs
459
592
  })
460
593
  });
461
594
  } else {
595
+ const {
596
+ settings: obsSettings,
597
+ data: obsData
598
+ } = splitObs(action.obs);
462
599
  return _objectSpread(_objectSpread({}, settings), {}, {
463
- selectedObs: action.obs,
600
+ selectedObs: obsSettings,
601
+ data: _objectSpread(_objectSpread({}, settings.data), {}, {
602
+ obs: _objectSpread(_objectSpread({}, settings.data.obs), obsData)
603
+ }),
464
604
  sliceBy: _objectSpread(_objectSpread({}, settings.sliceBy), {}, {
465
605
  obs: true
466
606
  })
467
607
  });
468
608
  }
469
609
  }
470
- case "toggle.slice.polygons":
610
+ case 'toggle.slice.polygons':
471
611
  {
472
612
  return _objectSpread(_objectSpread({}, settings), {}, {
473
613
  sliceBy: _objectSpread(_objectSpread({}, settings.sliceBy), {}, {
@@ -475,7 +615,7 @@ function settingsReducer(settings, action) {
475
615
  })
476
616
  });
477
617
  }
478
- case "disable.slice.polygons":
618
+ case 'disable.slice.polygons':
479
619
  {
480
620
  return _objectSpread(_objectSpread({}, settings), {}, {
481
621
  sliceBy: _objectSpread(_objectSpread({}, settings.sliceBy), {}, {
@@ -483,29 +623,36 @@ function settingsReducer(settings, action) {
483
623
  })
484
624
  });
485
625
  }
486
- case "add.label.obs":
626
+ case 'add.label.obs':
487
627
  {
488
- if (settings.labelObs.find(i => _.isEqual(i, action.obs))) {
628
+ if (_.includes(settings.labelObs, action.obs.name)) {
489
629
  return settings;
490
630
  } else {
631
+ const {
632
+ settings: obsSettings,
633
+ data: obsData
634
+ } = splitObs(action.obs);
491
635
  return _objectSpread(_objectSpread({}, settings), {}, {
492
- 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
+ })
493
640
  });
494
641
  }
495
642
  }
496
- case "remove.label.obs":
643
+ case 'remove.label.obs':
497
644
  {
498
- return _objectSpread(_objectSpread({}, settings), {}, {
499
- labelObs: settings.labelObs.filter(a => a.name !== action.obsName)
500
- });
645
+ return validateSettings(_objectSpread(_objectSpread({}, settings), {}, {
646
+ labelObs: settings.labelObs.filter(a => a !== action.obsName)
647
+ }));
501
648
  }
502
- case "reset.label.obs":
649
+ case 'reset.label.obs':
503
650
  {
504
- return _objectSpread(_objectSpread({}, settings), {}, {
651
+ return validateSettings(_objectSpread(_objectSpread({}, settings), {}, {
505
652
  labelObs: []
506
- });
653
+ }));
507
654
  }
508
- case "set.varSort":
655
+ case 'set.varSort':
509
656
  {
510
657
  return _objectSpread(_objectSpread({}, settings), {}, {
511
658
  varSort: _objectSpread(_objectSpread({}, settings.varSort), {}, {
@@ -516,7 +663,7 @@ function settingsReducer(settings, action) {
516
663
  })
517
664
  });
518
665
  }
519
- case "set.varSort.sort":
666
+ case 'set.varSort.sort':
520
667
  {
521
668
  return _objectSpread(_objectSpread({}, settings), {}, {
522
669
  varSort: _objectSpread(_objectSpread({}, settings.varSort), {}, {
@@ -526,7 +673,7 @@ function settingsReducer(settings, action) {
526
673
  })
527
674
  });
528
675
  }
529
- case "set.varSort.sortOrder":
676
+ case 'set.varSort.sortOrder':
530
677
  {
531
678
  return _objectSpread(_objectSpread({}, settings), {}, {
532
679
  varSort: _objectSpread(_objectSpread({}, settings.varSort), {}, {
@@ -536,7 +683,7 @@ function settingsReducer(settings, action) {
536
683
  })
537
684
  });
538
685
  }
539
- case "set.polygons":
686
+ case 'set.polygons':
540
687
  {
541
688
  return _objectSpread(_objectSpread({}, settings), {}, {
542
689
  polygons: _objectSpread(_objectSpread({}, settings.polygons), {}, {
@@ -544,7 +691,7 @@ function settingsReducer(settings, action) {
544
691
  })
545
692
  });
546
693
  }
547
- case "set.pseudospatial.maskSet":
694
+ case 'set.pseudospatial.maskSet':
548
695
  {
549
696
  return _objectSpread(_objectSpread({}, settings), {}, {
550
697
  pseudospatial: _objectSpread(_objectSpread({}, settings.pseudospatial), {}, {
@@ -552,7 +699,7 @@ function settingsReducer(settings, action) {
552
699
  })
553
700
  });
554
701
  }
555
- case "set.pseudospatial.maskValues":
702
+ case 'set.pseudospatial.maskValues':
556
703
  {
557
704
  return _objectSpread(_objectSpread({}, settings), {}, {
558
705
  pseudospatial: _objectSpread(_objectSpread({}, settings.pseudospatial), {}, {
@@ -560,7 +707,7 @@ function settingsReducer(settings, action) {
560
707
  })
561
708
  });
562
709
  }
563
- case "set.pseudospatial.categoricalMode":
710
+ case 'set.pseudospatial.categoricalMode':
564
711
  {
565
712
  return _objectSpread(_objectSpread({}, settings), {}, {
566
713
  pseudospatial: _objectSpread(_objectSpread({}, settings.pseudospatial), {}, {
@@ -568,9 +715,29 @@ function settingsReducer(settings, action) {
568
715
  })
569
716
  });
570
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
+ }
571
738
  default:
572
739
  {
573
- throw Error("Unknown action: " + action.type);
740
+ throw Error('Unknown action: ' + action.type);
574
741
  }
575
742
  }
576
743
  }