@haniffalab/cherita-react 1.2.0 → 1.3.0-dev.2025-05-28.9afc380f
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.
- package/dist/cjs/components/controls/Controls.js +60 -0
- package/dist/cjs/components/dotplot/Dotplot.js +47 -38
- package/dist/cjs/components/dotplot/DotplotControls.js +77 -114
- package/dist/cjs/components/full-page/FullPage.js +29 -33
- package/dist/cjs/components/full-page/FullPagePseudospatial.js +30 -33
- package/dist/cjs/components/heatmap/Heatmap.js +33 -22
- package/dist/cjs/components/heatmap/HeatmapControls.js +2 -19
- package/dist/cjs/components/matrixplot/Matrixplot.js +35 -24
- package/dist/cjs/components/matrixplot/MatrixplotControls.js +4 -34
- package/dist/cjs/components/obs-list/ObsItem.js +63 -51
- package/dist/cjs/components/obs-list/ObsList.js +53 -48
- package/dist/cjs/components/obsm-list/ObsmList.js +17 -12
- package/dist/cjs/components/offcanvas/index.js +14 -11
- package/dist/cjs/components/pseudospatial/Pseudospatial.js +78 -68
- package/dist/cjs/components/pseudospatial/PseudospatialToolbar.js +27 -21
- package/dist/cjs/components/scatterplot/Scatterplot.js +82 -76
- package/dist/cjs/components/scatterplot/ScatterplotControls.js +18 -31
- package/dist/cjs/components/scatterplot/SpatialControls.js +53 -23
- package/dist/cjs/components/scatterplot/Toolbox.js +1 -18
- package/dist/cjs/components/search-bar/SearchBar.js +156 -59
- package/dist/cjs/components/search-bar/SearchInfo.js +182 -0
- package/dist/cjs/components/search-bar/SearchResults.js +90 -60
- package/dist/cjs/components/var-list/VarItem.js +52 -75
- package/dist/cjs/components/var-list/VarList.js +47 -172
- package/dist/cjs/components/var-list/VarListToolbar.js +7 -8
- package/dist/cjs/components/var-list/VarSet.js +66 -57
- package/dist/cjs/components/violin/Violin.js +54 -43
- package/dist/cjs/components/violin/ViolinControls.js +4 -20
- package/dist/cjs/context/DatasetContext.js +26 -513
- package/dist/cjs/context/FilterContext.js +9 -8
- package/dist/cjs/context/SettingsContext.js +539 -0
- package/dist/cjs/context/ZarrDataContext.js +1 -2
- package/dist/cjs/helpers/color-helper.js +8 -8
- package/dist/cjs/helpers/zarr-helper.js +19 -16
- package/dist/cjs/utils/Filter.js +25 -21
- package/dist/cjs/utils/Histogram.js +4 -3
- package/dist/cjs/utils/ImageViewer.js +1 -2
- package/dist/cjs/utils/Legend.js +18 -12
- package/dist/cjs/utils/LoadingIndicators.js +1 -1
- package/dist/cjs/utils/VirtualizedList.js +16 -13
- package/dist/cjs/utils/errors.js +20 -22
- package/dist/cjs/utils/requests.js +13 -10
- package/dist/cjs/utils/zarrData.js +31 -50
- package/dist/css/cherita.css +84 -24
- package/dist/css/cherita.css.map +1 -1
- package/dist/esm/components/controls/Controls.js +51 -0
- package/dist/esm/components/dotplot/Dotplot.js +47 -37
- package/dist/esm/components/dotplot/DotplotControls.js +77 -112
- package/dist/esm/components/full-page/FullPage.js +29 -32
- package/dist/esm/components/full-page/FullPagePseudospatial.js +30 -32
- package/dist/esm/components/heatmap/Heatmap.js +32 -20
- package/dist/esm/components/heatmap/HeatmapControls.js +3 -20
- package/dist/esm/components/matrixplot/Matrixplot.js +34 -22
- package/dist/esm/components/matrixplot/MatrixplotControls.js +5 -35
- package/dist/esm/components/obs-list/ObsItem.js +63 -49
- package/dist/esm/components/obs-list/ObsList.js +53 -47
- package/dist/esm/components/obsm-list/ObsmList.js +17 -11
- package/dist/esm/components/offcanvas/index.js +14 -11
- package/dist/esm/components/pseudospatial/Pseudospatial.js +77 -66
- package/dist/esm/components/pseudospatial/PseudospatialToolbar.js +27 -20
- package/dist/esm/components/scatterplot/Scatterplot.js +81 -74
- package/dist/esm/components/scatterplot/ScatterplotControls.js +18 -29
- package/dist/esm/components/scatterplot/SpatialControls.js +54 -23
- package/dist/esm/components/scatterplot/Toolbox.js +1 -18
- package/dist/esm/components/search-bar/SearchBar.js +156 -59
- package/dist/esm/components/search-bar/SearchInfo.js +173 -0
- package/dist/esm/components/search-bar/SearchResults.js +91 -60
- package/dist/esm/components/var-list/VarItem.js +53 -76
- package/dist/esm/components/var-list/VarList.js +47 -171
- package/dist/esm/components/var-list/VarListToolbar.js +6 -6
- package/dist/esm/components/var-list/VarSet.js +67 -57
- package/dist/esm/components/violin/Violin.js +53 -41
- package/dist/esm/components/violin/ViolinControls.js +5 -21
- package/dist/esm/context/DatasetContext.js +25 -510
- package/dist/esm/context/FilterContext.js +8 -6
- package/dist/esm/context/SettingsContext.js +528 -0
- package/dist/esm/helpers/color-helper.js +8 -8
- package/dist/esm/helpers/zarr-helper.js +19 -16
- package/dist/esm/utils/Filter.js +25 -21
- package/dist/esm/utils/Histogram.js +4 -3
- package/dist/esm/utils/Legend.js +17 -10
- package/dist/esm/utils/LoadingIndicators.js +1 -1
- package/dist/esm/utils/VirtualizedList.js +15 -11
- package/dist/esm/utils/errors.js +20 -22
- package/dist/esm/utils/requests.js +13 -10
- package/dist/esm/utils/zarrData.js +33 -51
- package/package.json +6 -3
- package/scss/cherita.scss +50 -9
- package/scss/components/layouts.scss +24 -13
- package/scss/components/lists.scss +10 -0
- package/scss/components/plots.scss +3 -5
package/dist/esm/utils/Filter.js
CHANGED
|
@@ -2,8 +2,8 @@ import { useEffect, useCallback, useMemo } from "react";
|
|
|
2
2
|
import { booleanPointInPolygon, point } from "@turf/turf";
|
|
3
3
|
import _ from "lodash";
|
|
4
4
|
import { COLOR_ENCODINGS, OBS_TYPES } from "../constants/constants";
|
|
5
|
-
import { useDataset } from "../context/DatasetContext";
|
|
6
5
|
import { useFilteredDataDispatch } from "../context/FilterContext";
|
|
6
|
+
import { useSettings } from "../context/SettingsContext";
|
|
7
7
|
const EPSILON = 1e-6;
|
|
8
8
|
const isInBins = (v, binEdges, indices) => {
|
|
9
9
|
const lastEdge = _.last(binEdges);
|
|
@@ -15,7 +15,7 @@ const isInBins = (v, binEdges, indices) => {
|
|
|
15
15
|
return _.some(ranges, range => _.inRange(v, ...range));
|
|
16
16
|
};
|
|
17
17
|
const isInPolygons = (polygons, positions, index) => {
|
|
18
|
-
if (!polygons
|
|
18
|
+
if (!(polygons !== null && polygons !== void 0 && polygons.length) || !(positions !== null && positions !== void 0 && positions.length)) {
|
|
19
19
|
return false;
|
|
20
20
|
}
|
|
21
21
|
return _.some(polygons, (_f, i) => {
|
|
@@ -23,13 +23,14 @@ const isInPolygons = (polygons, positions, index) => {
|
|
|
23
23
|
});
|
|
24
24
|
};
|
|
25
25
|
const isInValues = (omit, value) => {
|
|
26
|
-
if (!omit
|
|
26
|
+
if (!(omit !== null && omit !== void 0 && omit.length)) {
|
|
27
27
|
return true;
|
|
28
28
|
}
|
|
29
29
|
return !_.includes(omit, value);
|
|
30
30
|
};
|
|
31
31
|
export const useFilter = data => {
|
|
32
|
-
|
|
32
|
+
var _settings$selectedObs, _settings$selectedObs2, _settings$selectedObs3, _settings$selectedObs4, _settings$selectedObs7, _settings$selectedObs8;
|
|
33
|
+
const settings = useSettings();
|
|
33
34
|
const filterDataDispatch = useFilteredDataDispatch();
|
|
34
35
|
const {
|
|
35
36
|
obsmData,
|
|
@@ -38,31 +39,33 @@ export const useFilter = data => {
|
|
|
38
39
|
isPending,
|
|
39
40
|
serverError
|
|
40
41
|
} = data;
|
|
41
|
-
const isCategorical =
|
|
42
|
-
const isContinuous =
|
|
43
|
-
const sliceByObs =
|
|
42
|
+
const isCategorical = ((_settings$selectedObs = settings.selectedObs) === null || _settings$selectedObs === void 0 ? void 0 : _settings$selectedObs.type) === OBS_TYPES.CATEGORICAL || ((_settings$selectedObs2 = settings.selectedObs) === null || _settings$selectedObs2 === void 0 ? void 0 : _settings$selectedObs2.type) === OBS_TYPES.BOOLEAN;
|
|
43
|
+
const isContinuous = ((_settings$selectedObs3 = settings.selectedObs) === null || _settings$selectedObs3 === void 0 ? void 0 : _settings$selectedObs3.type) === OBS_TYPES.CONTINUOUS;
|
|
44
|
+
const sliceByObs = settings.colorEncoding === COLOR_ENCODINGS.OBS && !!((_settings$selectedObs4 = settings.selectedObs) !== null && _settings$selectedObs4 !== void 0 && _settings$selectedObs4.omit.length) || settings.sliceBy.obs;
|
|
44
45
|
const isInObsSlice = useCallback((index, values) => {
|
|
45
46
|
let inSlice = true;
|
|
46
47
|
if (values && sliceByObs) {
|
|
47
48
|
if (isCategorical) {
|
|
48
|
-
|
|
49
|
+
var _settings$selectedObs5;
|
|
50
|
+
inSlice &= isInValues((_settings$selectedObs5 = settings.selectedObs) === null || _settings$selectedObs5 === void 0 ? void 0 : _settings$selectedObs5.omit, values[index]);
|
|
49
51
|
} else if (isContinuous) {
|
|
50
52
|
if (isNaN(values[index])) {
|
|
51
|
-
|
|
53
|
+
var _settings$selectedObs6;
|
|
54
|
+
inSlice &= isInValues((_settings$selectedObs6 = settings.selectedObs) === null || _settings$selectedObs6 === void 0 ? void 0 : _settings$selectedObs6.omit, -1);
|
|
52
55
|
} else {
|
|
53
|
-
inSlice &= isInBins(values[index],
|
|
56
|
+
inSlice &= isInBins(values[index], settings.selectedObs.bins.binEdges, _.without(settings.selectedObs.omit, -1));
|
|
54
57
|
}
|
|
55
58
|
}
|
|
56
59
|
}
|
|
57
60
|
return inSlice;
|
|
58
|
-
}, [
|
|
61
|
+
}, [(_settings$selectedObs7 = settings.selectedObs) === null || _settings$selectedObs7 === void 0 || (_settings$selectedObs7 = _settings$selectedObs7.bins) === null || _settings$selectedObs7 === void 0 ? void 0 : _settings$selectedObs7.binEdges, (_settings$selectedObs8 = settings.selectedObs) === null || _settings$selectedObs8 === void 0 ? void 0 : _settings$selectedObs8.omit, isCategorical, isContinuous, sliceByObs]);
|
|
59
62
|
const isInPolygonsSlice = useCallback((index, positions) => {
|
|
60
63
|
let inSlice = true;
|
|
61
|
-
if (
|
|
62
|
-
inSlice &= isInPolygons(
|
|
64
|
+
if (settings.sliceBy.polygons && positions) {
|
|
65
|
+
inSlice &= isInPolygons(settings.polygons[settings.selectedObsm], positions, index);
|
|
63
66
|
}
|
|
64
67
|
return inSlice;
|
|
65
|
-
}, [
|
|
68
|
+
}, [settings.polygons, settings.selectedObsm, settings.sliceBy.polygons]);
|
|
66
69
|
const isInSlice = useCallback((index, values, positions) => {
|
|
67
70
|
return isInObsSlice(index, values) && isInPolygonsSlice(index, positions);
|
|
68
71
|
}, [isInObsSlice, isInPolygonsSlice]);
|
|
@@ -80,7 +83,7 @@ export const useFilter = data => {
|
|
|
80
83
|
slicedLength: null
|
|
81
84
|
};
|
|
82
85
|
}
|
|
83
|
-
if (
|
|
86
|
+
if (settings.colorEncoding === COLOR_ENCODINGS.VAR) {
|
|
84
87
|
const {
|
|
85
88
|
filtered,
|
|
86
89
|
filteredIndices
|
|
@@ -100,7 +103,7 @@ export const useFilter = data => {
|
|
|
100
103
|
valueMax: _.max(filtered),
|
|
101
104
|
slicedLength: filtered.length
|
|
102
105
|
};
|
|
103
|
-
} else if (
|
|
106
|
+
} else if (settings.colorEncoding === COLOR_ENCODINGS.OBS) {
|
|
104
107
|
const {
|
|
105
108
|
filtered,
|
|
106
109
|
filteredIndices
|
|
@@ -121,16 +124,17 @@ export const useFilter = data => {
|
|
|
121
124
|
slicedLength: filtered.length
|
|
122
125
|
};
|
|
123
126
|
} else {
|
|
127
|
+
var _obsData$data;
|
|
124
128
|
return {
|
|
125
129
|
filteredIndices: null,
|
|
126
130
|
valueMin: _.min(obsData.data),
|
|
127
131
|
valueMax: _.max(obsData.data),
|
|
128
|
-
slicedLength: obsData.data
|
|
132
|
+
slicedLength: (_obsData$data = obsData.data) === null || _obsData$data === void 0 ? void 0 : _obsData$data.length
|
|
129
133
|
};
|
|
130
134
|
}
|
|
131
|
-
}, [
|
|
132
|
-
const isSliced = sliceByObs ||
|
|
133
|
-
// const isSliced =
|
|
135
|
+
}, [settings.colorEncoding, isContinuous, isInSlice, isPending, obsData.data, obsmData.data, serverError, xData.data]);
|
|
136
|
+
const isSliced = sliceByObs || settings.sliceBy.polygons;
|
|
137
|
+
// const isSliced = settings.sliceBy.obs || settings.sliceBy.polygons;
|
|
134
138
|
|
|
135
139
|
useEffect(() => {
|
|
136
140
|
if (!isPending && !serverError) {
|
|
@@ -143,5 +147,5 @@ export const useFilter = data => {
|
|
|
143
147
|
isSliced: isSliced
|
|
144
148
|
});
|
|
145
149
|
}
|
|
146
|
-
}, [
|
|
150
|
+
}, [settings.sliceBy.obs, settings.sliceBy.polygons, filterDataDispatch, filteredIndices, isPending, isSliced, serverError, slicedLength, valueMax, valueMin]);
|
|
147
151
|
};
|
|
@@ -4,6 +4,7 @@ import _ from "lodash";
|
|
|
4
4
|
import { LoadingLinear } from "./LoadingIndicators";
|
|
5
5
|
import { formatNumerical, FORMATS } from "./string";
|
|
6
6
|
export function Histogram(_ref) {
|
|
7
|
+
var _data$bin_edges;
|
|
7
8
|
let {
|
|
8
9
|
data,
|
|
9
10
|
isPending,
|
|
@@ -29,11 +30,11 @@ export function Histogram(_ref) {
|
|
|
29
30
|
let {
|
|
30
31
|
dataIndex
|
|
31
32
|
} = _ref2;
|
|
32
|
-
return
|
|
33
|
+
return "".concat(formatNumerical(data.hist[dataIndex]));
|
|
33
34
|
},
|
|
34
35
|
xAxis: {
|
|
35
|
-
data: _.range(data.bin_edges
|
|
36
|
-
valueFormatter: v =>
|
|
36
|
+
data: _.range((_data$bin_edges = data.bin_edges) === null || _data$bin_edges === void 0 ? void 0 : _data$bin_edges.length) || null,
|
|
37
|
+
valueFormatter: v => "Bin [".concat(formatNumerical(data.bin_edges[v][0], FORMATS.EXPONENTIAL), ", ").concat(formatNumerical(data.bin_edges[v][1], FORMATS.EXPONENTIAL)).concat(v === data.bin_edges.length - 1 ? "]" : ")")
|
|
37
38
|
},
|
|
38
39
|
slotProps: {
|
|
39
40
|
popper: {
|
package/dist/esm/utils/Legend.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import React, { useMemo } from "react";
|
|
2
|
+
import { faDroplet } from "@fortawesome/free-solid-svg-icons";
|
|
3
|
+
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
2
4
|
import _ from "lodash";
|
|
3
5
|
import { formatNumerical, FORMATS } from "./string";
|
|
4
6
|
import { COLOR_ENCODINGS } from "../constants/constants";
|
|
5
|
-
import {
|
|
7
|
+
import { useSettings } from "../context/SettingsContext";
|
|
6
8
|
import { rgbToHex, useColor } from "../helpers/color-helper";
|
|
7
9
|
export function Legend(_ref) {
|
|
8
10
|
let {
|
|
@@ -12,7 +14,7 @@ export function Legend(_ref) {
|
|
|
12
14
|
colorscale = null,
|
|
13
15
|
addText = ""
|
|
14
16
|
} = _ref;
|
|
15
|
-
const
|
|
17
|
+
const settings = useSettings();
|
|
16
18
|
const {
|
|
17
19
|
getColor
|
|
18
20
|
} = useColor();
|
|
@@ -32,27 +34,32 @@ export function Legend(_ref) {
|
|
|
32
34
|
});
|
|
33
35
|
});
|
|
34
36
|
}, [colorscale, getColor, isCategorical]);
|
|
35
|
-
if (
|
|
37
|
+
if (settings.colorEncoding && !isCategorical) {
|
|
38
|
+
var _settings$selectedVar, _settings$selectedObs;
|
|
36
39
|
return /*#__PURE__*/React.createElement("div", {
|
|
37
40
|
className: "cherita-legend"
|
|
38
41
|
}, /*#__PURE__*/React.createElement("div", {
|
|
39
42
|
className: "gradient"
|
|
40
43
|
}, /*#__PURE__*/React.createElement("p", {
|
|
41
44
|
className: "small m-0 p-0"
|
|
42
|
-
},
|
|
45
|
+
}, /*#__PURE__*/React.createElement(FontAwesomeIcon, {
|
|
46
|
+
icon: faDroplet,
|
|
47
|
+
className: "me-1"
|
|
48
|
+
}), (settings.colorEncoding === COLOR_ENCODINGS.VAR ? (_settings$selectedVar = settings.selectedVar) === null || _settings$selectedVar === void 0 ? void 0 : _settings$selectedVar.name : (_settings$selectedObs = settings.selectedObs) === null || _settings$selectedObs === void 0 ? void 0 : _settings$selectedObs.name) + addText), spanList, /*#__PURE__*/React.createElement("span", {
|
|
43
49
|
className: "domain-min"
|
|
44
50
|
}, formatNumerical(min, FORMATS.EXPONENTIAL)), /*#__PURE__*/React.createElement("span", {
|
|
45
51
|
className: "domain-med"
|
|
46
52
|
}, formatNumerical((min + max) * 0.5, FORMATS.EXPONENTIAL)), /*#__PURE__*/React.createElement("span", {
|
|
47
53
|
className: "domain-max"
|
|
48
54
|
}, formatNumerical(max, FORMATS.EXPONENTIAL))));
|
|
49
|
-
} else {
|
|
55
|
+
} else if (settings.colorEncoding === COLOR_ENCODINGS.OBS && settings.selectedObs) {
|
|
50
56
|
return /*#__PURE__*/React.createElement("div", {
|
|
51
|
-
className: "cherita-legend"
|
|
52
|
-
}, /*#__PURE__*/React.createElement("div", {
|
|
53
|
-
className: "gradient"
|
|
57
|
+
className: "cherita-legend categorical"
|
|
54
58
|
}, /*#__PURE__*/React.createElement("p", {
|
|
55
|
-
className: "
|
|
56
|
-
},
|
|
59
|
+
className: "legend-text text-end m-0 p-0"
|
|
60
|
+
}, /*#__PURE__*/React.createElement(FontAwesomeIcon, {
|
|
61
|
+
icon: faDroplet,
|
|
62
|
+
className: "me-2"
|
|
63
|
+
}), settings.selectedObs.name));
|
|
57
64
|
}
|
|
58
65
|
}
|
|
@@ -9,7 +9,7 @@ export const LoadingSpinner = _ref => {
|
|
|
9
9
|
className: "loading-spinner"
|
|
10
10
|
}, /*#__PURE__*/React.createElement(CircularProgress, {
|
|
11
11
|
disableShrink: disableShrink
|
|
12
|
-
}), text
|
|
12
|
+
}), (text === null || text === void 0 ? void 0 : text.length) && /*#__PURE__*/React.createElement("span", {
|
|
13
13
|
className: "visually-hidden"
|
|
14
14
|
}, text));
|
|
15
15
|
};
|
|
@@ -1,16 +1,20 @@
|
|
|
1
|
+
const _excluded = ["getDataAtIndex", "count", "ItemComponent", "estimateSize", "overscan", "maxHeight"];
|
|
1
2
|
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
3
|
+
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; }
|
|
4
|
+
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; }
|
|
2
5
|
import React, { useCallback, useEffect, useState } from "react";
|
|
3
6
|
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
4
7
|
export function VirtualizedList(_ref) {
|
|
8
|
+
var _virtualItems$0$start, _virtualItems$;
|
|
5
9
|
let {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
getDataAtIndex,
|
|
11
|
+
count,
|
|
12
|
+
ItemComponent,
|
|
13
|
+
estimateSize = 45,
|
|
14
|
+
overscan = 25,
|
|
15
|
+
maxHeight = "65vh"
|
|
16
|
+
} = _ref,
|
|
17
|
+
props = _objectWithoutProperties(_ref, _excluded);
|
|
14
18
|
const [parentNode, setParentNode] = useState(null);
|
|
15
19
|
const itemVirtualizer = useVirtualizer({
|
|
16
20
|
count: count,
|
|
@@ -24,7 +28,7 @@ export function VirtualizedList(_ref) {
|
|
|
24
28
|
const virtualItems = itemVirtualizer.getVirtualItems();
|
|
25
29
|
useEffect(() => {
|
|
26
30
|
itemVirtualizer.measure();
|
|
27
|
-
}, [itemVirtualizer, parentNode
|
|
31
|
+
}, [itemVirtualizer, parentNode === null || parentNode === void 0 ? void 0 : parentNode.clientHeight, getDataAtIndex]);
|
|
28
32
|
return /*#__PURE__*/React.createElement("div", {
|
|
29
33
|
ref: refCallback,
|
|
30
34
|
style: {
|
|
@@ -34,7 +38,7 @@ export function VirtualizedList(_ref) {
|
|
|
34
38
|
className: "modern-scrollbars"
|
|
35
39
|
}, /*#__PURE__*/React.createElement("div", {
|
|
36
40
|
style: {
|
|
37
|
-
height:
|
|
41
|
+
height: "".concat(itemVirtualizer.getTotalSize(), "px"),
|
|
38
42
|
width: "100%",
|
|
39
43
|
position: "relative",
|
|
40
44
|
willChange: "transform"
|
|
@@ -45,7 +49,7 @@ export function VirtualizedList(_ref) {
|
|
|
45
49
|
top: 0,
|
|
46
50
|
left: 0,
|
|
47
51
|
width: "100%",
|
|
48
|
-
transform:
|
|
52
|
+
transform: "translateY(".concat((_virtualItems$0$start = (_virtualItems$ = virtualItems[0]) === null || _virtualItems$ === void 0 ? void 0 : _virtualItems$.start) !== null && _virtualItems$0$start !== void 0 ? _virtualItems$0$start : 0, "px)")
|
|
49
53
|
}
|
|
50
54
|
}, virtualItems.map(virtualItem => /*#__PURE__*/React.createElement("div", {
|
|
51
55
|
key: virtualItem.key,
|
package/dist/esm/utils/errors.js
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
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
|
+
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
|
+
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
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
5
|
+
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
1
6
|
export const parseError = err => {
|
|
2
7
|
if (err === DOMException.TIMEOUT_ERR) {
|
|
3
8
|
return {
|
|
@@ -5,42 +10,35 @@ export const parseError = err => {
|
|
|
5
10
|
name: err
|
|
6
11
|
};
|
|
7
12
|
}
|
|
8
|
-
switch (err
|
|
13
|
+
switch (err === null || err === void 0 ? void 0 : err.name) {
|
|
9
14
|
case "TypeError":
|
|
10
|
-
return {
|
|
11
|
-
...err,
|
|
15
|
+
return _objectSpread(_objectSpread({}, err), {}, {
|
|
12
16
|
message: "Failed to fetch data from server"
|
|
13
|
-
};
|
|
17
|
+
});
|
|
14
18
|
case "ReadZarrError":
|
|
15
|
-
return {
|
|
16
|
-
...err,
|
|
19
|
+
return _objectSpread(_objectSpread({}, err), {}, {
|
|
17
20
|
message: "Failed to read AnnData-Zarr"
|
|
18
|
-
};
|
|
21
|
+
});
|
|
19
22
|
case "InvalidObs":
|
|
20
|
-
return {
|
|
21
|
-
...err,
|
|
23
|
+
return _objectSpread(_objectSpread({}, err), {}, {
|
|
22
24
|
message: "Observation not found in dataset"
|
|
23
|
-
};
|
|
25
|
+
});
|
|
24
26
|
case "InvalidVar":
|
|
25
|
-
return {
|
|
26
|
-
...err,
|
|
27
|
+
return _objectSpread(_objectSpread({}, err), {}, {
|
|
27
28
|
message: "Feature not found in dataset"
|
|
28
|
-
};
|
|
29
|
+
});
|
|
29
30
|
case "InvalidKey":
|
|
30
|
-
return {
|
|
31
|
-
...err,
|
|
31
|
+
return _objectSpread(_objectSpread({}, err), {}, {
|
|
32
32
|
message: "Key not found in datset"
|
|
33
|
-
};
|
|
33
|
+
});
|
|
34
34
|
case "BadRequest":
|
|
35
|
-
return {
|
|
36
|
-
...err,
|
|
35
|
+
return _objectSpread(_objectSpread({}, err), {}, {
|
|
37
36
|
message: "Invalid request to server"
|
|
38
|
-
};
|
|
37
|
+
});
|
|
39
38
|
case "InternalServerError":
|
|
40
|
-
return {
|
|
41
|
-
...err,
|
|
39
|
+
return _objectSpread(_objectSpread({}, err), {}, {
|
|
42
40
|
message: "Server error"
|
|
43
|
-
};
|
|
41
|
+
});
|
|
44
42
|
default:
|
|
45
43
|
return err;
|
|
46
44
|
}
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
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
|
+
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
|
+
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
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
5
|
+
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
1
6
|
import { useQuery } from "@tanstack/react-query";
|
|
2
7
|
import { useDebounce } from "@uidotdev/usehooks";
|
|
3
8
|
import { parseError } from "./errors";
|
|
@@ -42,7 +47,7 @@ export const useFetch = function (endpoint, params) {
|
|
|
42
47
|
data: fetchedData = null,
|
|
43
48
|
isLoading: isPending = false,
|
|
44
49
|
error: serverError = null
|
|
45
|
-
} = useQuery({
|
|
50
|
+
} = useQuery(_objectSpread({
|
|
46
51
|
queryKey: [endpoint, params],
|
|
47
52
|
queryFn: _ref => {
|
|
48
53
|
let {
|
|
@@ -54,11 +59,10 @@ export const useFetch = function (endpoint, params) {
|
|
|
54
59
|
let {
|
|
55
60
|
error
|
|
56
61
|
} = _ref2;
|
|
57
|
-
if ([400, 401, 403, 404, 422].includes(error
|
|
62
|
+
if ([400, 401, 403, 404, 422].includes(error === null || error === void 0 ? void 0 : error.status)) return false;
|
|
58
63
|
return failureCount < 3;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
});
|
|
64
|
+
}
|
|
65
|
+
}, opts));
|
|
62
66
|
return {
|
|
63
67
|
fetchedData,
|
|
64
68
|
isPending,
|
|
@@ -77,7 +81,7 @@ export const useDebouncedFetch = function (endpoint, params) {
|
|
|
77
81
|
data: fetchedData = null,
|
|
78
82
|
isLoading: isPending = false,
|
|
79
83
|
error: serverError = null
|
|
80
|
-
} = useQuery({
|
|
84
|
+
} = useQuery(_objectSpread({
|
|
81
85
|
queryKey: [endpoint, debouncedParams],
|
|
82
86
|
queryFn: _ref3 => {
|
|
83
87
|
let {
|
|
@@ -89,11 +93,10 @@ export const useDebouncedFetch = function (endpoint, params) {
|
|
|
89
93
|
let {
|
|
90
94
|
error
|
|
91
95
|
} = _ref4;
|
|
92
|
-
if ([400, 401, 403, 404, 422].includes(error
|
|
96
|
+
if ([400, 401, 403, 404, 422].includes(error === null || error === void 0 ? void 0 : error.status)) return false;
|
|
93
97
|
return failureCount < 3;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
});
|
|
98
|
+
}
|
|
99
|
+
}, opts));
|
|
97
100
|
return {
|
|
98
101
|
fetchedData,
|
|
99
102
|
isPending,
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useMemo } from "react";
|
|
2
2
|
import _ from "lodash";
|
|
3
|
+
import { slice } from "zarr";
|
|
3
4
|
import { OBS_TYPES } from "../constants/constants";
|
|
4
5
|
import { useDataset } from "../context/DatasetContext";
|
|
6
|
+
import { useSettings } from "../context/SettingsContext";
|
|
5
7
|
import { GET_OPTIONS, useZarr, useMultipleZarr } from "../helpers/zarr-helper";
|
|
8
|
+
|
|
9
|
+
// @TODO: support specifying slice to load from context
|
|
6
10
|
export const useObsmData = function () {
|
|
7
11
|
let obsm = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
|
8
12
|
const dataset = useDataset();
|
|
9
|
-
|
|
10
|
-
|
|
13
|
+
const settings = useSettings();
|
|
14
|
+
obsm = obsm || settings.selectedObsm;
|
|
15
|
+
const obsmParams = useMemo(() => ({
|
|
11
16
|
url: dataset.url,
|
|
12
|
-
path: "obsm/" + obsm
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
url: dataset.url,
|
|
17
|
-
path: "obsm/" + obsm
|
|
18
|
-
});
|
|
19
|
-
}, [dataset.url, obsm]);
|
|
20
|
-
return useZarr(obsmParams, null, GET_OPTIONS, {
|
|
17
|
+
path: "obsm/" + obsm,
|
|
18
|
+
s: [null, slice(null, 2)] // load only [:, :2]
|
|
19
|
+
}), [dataset.url, obsm]);
|
|
20
|
+
return useZarr(obsmParams, GET_OPTIONS, {
|
|
21
21
|
enabled: !!obsm
|
|
22
22
|
});
|
|
23
23
|
};
|
|
@@ -32,70 +32,52 @@ const meanData = (_i, data) => {
|
|
|
32
32
|
export const useXData = function () {
|
|
33
33
|
let agg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : meanData;
|
|
34
34
|
const dataset = useDataset();
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}] : _.map(dataset.selectedVar?.vars, v => {
|
|
40
|
-
return {
|
|
35
|
+
const settings = useSettings();
|
|
36
|
+
const xParams = useMemo(() => {
|
|
37
|
+
var _settings$selectedVar, _settings$selectedVar2, _settings$selectedVar3;
|
|
38
|
+
return !settings.selectedVar ? [] : !((_settings$selectedVar = settings.selectedVar) !== null && _settings$selectedVar !== void 0 && _settings$selectedVar.isSet) ? [{
|
|
41
39
|
url: dataset.url,
|
|
42
40
|
path: "X",
|
|
43
|
-
s: [null,
|
|
44
|
-
}
|
|
45
|
-
}));
|
|
46
|
-
useEffect(() => {
|
|
47
|
-
setXParams(!dataset.selectedVar ? [] : !dataset.selectedVar?.isSet ? [{
|
|
48
|
-
url: dataset.url,
|
|
49
|
-
path: "X",
|
|
50
|
-
s: [null, dataset.selectedVar?.matrix_index]
|
|
51
|
-
}] : _.map(dataset.selectedVar?.vars, v => {
|
|
41
|
+
s: [null, (_settings$selectedVar2 = settings.selectedVar) === null || _settings$selectedVar2 === void 0 ? void 0 : _settings$selectedVar2.matrix_index]
|
|
42
|
+
}] : _.map((_settings$selectedVar3 = settings.selectedVar) === null || _settings$selectedVar3 === void 0 ? void 0 : _settings$selectedVar3.vars, v => {
|
|
52
43
|
return {
|
|
53
44
|
url: dataset.url,
|
|
54
45
|
path: "X",
|
|
55
46
|
s: [null, v.matrix_index]
|
|
56
47
|
};
|
|
57
|
-
})
|
|
58
|
-
}, [dataset.url,
|
|
48
|
+
});
|
|
49
|
+
}, [dataset.url, settings.selectedVar]);
|
|
59
50
|
return useMultipleZarr(xParams, GET_OPTIONS, {
|
|
60
51
|
enabled: !!xParams.length
|
|
61
52
|
}, agg);
|
|
62
53
|
};
|
|
63
54
|
export const useObsData = function () {
|
|
55
|
+
var _obs3, _obs4;
|
|
64
56
|
let obs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
|
65
57
|
const dataset = useDataset();
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
useEffect(() => {
|
|
72
|
-
setObsParams({
|
|
58
|
+
const settings = useSettings();
|
|
59
|
+
obs = obs || settings.selectedObs;
|
|
60
|
+
const obsParams = useMemo(() => {
|
|
61
|
+
var _obs, _obs2;
|
|
62
|
+
return {
|
|
73
63
|
url: dataset.url,
|
|
74
|
-
path: "obs/" + obs
|
|
75
|
-
}
|
|
76
|
-
}, [dataset.url, obs]);
|
|
77
|
-
return useZarr(obsParams,
|
|
64
|
+
path: "obs/" + ((_obs = obs) === null || _obs === void 0 ? void 0 : _obs.name) + (((_obs2 = obs) === null || _obs2 === void 0 ? void 0 : _obs2.type) === OBS_TYPES.CATEGORICAL ? "/codes" : "")
|
|
65
|
+
};
|
|
66
|
+
}, [dataset.url, (_obs3 = obs) === null || _obs3 === void 0 ? void 0 : _obs3.name, (_obs4 = obs) === null || _obs4 === void 0 ? void 0 : _obs4.type]);
|
|
67
|
+
return useZarr(obsParams, GET_OPTIONS, {
|
|
78
68
|
enabled: !!obs
|
|
79
69
|
});
|
|
80
70
|
};
|
|
81
71
|
export const useLabelObsData = () => {
|
|
82
72
|
const dataset = useDataset();
|
|
83
|
-
const
|
|
73
|
+
const settings = useSettings();
|
|
74
|
+
const labelObsParams = useMemo(() => _.map(settings.labelObs, obs => {
|
|
84
75
|
return {
|
|
85
76
|
url: dataset.url,
|
|
86
77
|
path: "obs/" + obs.name + (obs.type === OBS_TYPES.CATEGORICAL ? "/codes" : ""),
|
|
87
78
|
key: obs.name
|
|
88
79
|
};
|
|
89
|
-
}));
|
|
90
|
-
useEffect(() => {
|
|
91
|
-
setLabelObsParams(_.map(dataset.labelObs, obs => {
|
|
92
|
-
return {
|
|
93
|
-
url: dataset.url,
|
|
94
|
-
path: "obs/" + obs.name + (obs.type === OBS_TYPES.CATEGORICAL ? "/codes" : ""),
|
|
95
|
-
key: obs.name
|
|
96
|
-
};
|
|
97
|
-
}));
|
|
98
|
-
}, [dataset.labelObs, dataset.url]);
|
|
80
|
+
}), [dataset.url, settings.labelObs]);
|
|
99
81
|
return useMultipleZarr(labelObsParams, GET_OPTIONS, {
|
|
100
82
|
enabled: !!labelObsParams.length
|
|
101
83
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@haniffalab/cherita-react",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0-dev.2025-05-28.9afc380f",
|
|
4
4
|
"author": "Haniffa Lab",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
@@ -77,6 +77,8 @@
|
|
|
77
77
|
"jest": "^29.7.0",
|
|
78
78
|
"jest-environment-jsdom": "^29.7.0",
|
|
79
79
|
"prettier": "^3.5.3",
|
|
80
|
+
"react": "^18.2.0",
|
|
81
|
+
"react-dom": "^18.2.0",
|
|
80
82
|
"sass": "1.77.6",
|
|
81
83
|
"stylelint": "^16.10.0",
|
|
82
84
|
"stylelint-config-prettier": "^9.0.5",
|
|
@@ -123,5 +125,6 @@
|
|
|
123
125
|
"bugs": {
|
|
124
126
|
"url": "https://github.com/haniffalab/cherita-react/issues"
|
|
125
127
|
},
|
|
126
|
-
"homepage": "https://github.com/haniffalab/cherita-react#readme"
|
|
127
|
-
|
|
128
|
+
"homepage": "https://github.com/haniffalab/cherita-react#readme",
|
|
129
|
+
"prereleaseSha": "9afc380fef6e4b57764414ea202fada84a34456f"
|
|
130
|
+
}
|
package/scss/cherita.scss
CHANGED
|
@@ -14,7 +14,7 @@ $prefix: "bs-" !default;
|
|
|
14
14
|
height: 100%;
|
|
15
15
|
width: 100%;
|
|
16
16
|
display: flex;
|
|
17
|
-
z-index:
|
|
17
|
+
z-index: 2;
|
|
18
18
|
opacity: 0.75;
|
|
19
19
|
position: absolute;
|
|
20
20
|
justify-content: center;
|
|
@@ -73,15 +73,13 @@ $prefix: "bs-" !default;
|
|
|
73
73
|
.cherita-spatial-footer {
|
|
74
74
|
position: absolute;
|
|
75
75
|
z-index: 10;
|
|
76
|
-
bottom:
|
|
76
|
+
bottom: 0;
|
|
77
77
|
display: flex;
|
|
78
78
|
justify-content: space-between;
|
|
79
|
-
align-items:
|
|
79
|
+
align-items: end;
|
|
80
80
|
flex-wrap: wrap;
|
|
81
81
|
width: 100%;
|
|
82
|
-
padding
|
|
83
|
-
padding-right: 1rem;
|
|
84
|
-
padding-bottom: 1rem;
|
|
82
|
+
padding: 1rem;
|
|
85
83
|
pointer-events: none;
|
|
86
84
|
|
|
87
85
|
> * {
|
|
@@ -105,6 +103,41 @@ $prefix: "bs-" !default;
|
|
|
105
103
|
.cherita-legend {
|
|
106
104
|
order: 2;
|
|
107
105
|
width: 12rem;
|
|
106
|
+
color: #333;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.cherita-legend.categorical {
|
|
110
|
+
display: flex;
|
|
111
|
+
align-items: center;
|
|
112
|
+
justify-content: flex-end;
|
|
113
|
+
padding-left: 1rem;
|
|
114
|
+
flex: 1;
|
|
115
|
+
overflow: hidden;
|
|
116
|
+
white-space: nowrap;
|
|
117
|
+
text-overflow: ellipsis;
|
|
118
|
+
pointer-events: auto;
|
|
119
|
+
.legend-text {
|
|
120
|
+
overflow: hidden;
|
|
121
|
+
text-overflow: ellipsis;
|
|
122
|
+
white-space: nowrap;
|
|
123
|
+
max-width: 100%;
|
|
124
|
+
display: inline-block;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
@media (max-width: 600px) {
|
|
129
|
+
.cherita-spatial-footer {
|
|
130
|
+
flex-direction: column;
|
|
131
|
+
align-items: center;
|
|
132
|
+
justify-content: center;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.cherita-legend {
|
|
136
|
+
flex-direction: column;
|
|
137
|
+
align-items: center;
|
|
138
|
+
margin-top: 1rem;
|
|
139
|
+
padding: 0;
|
|
140
|
+
}
|
|
108
141
|
}
|
|
109
142
|
|
|
110
143
|
.cherita-accordion-active .accordion-button {
|
|
@@ -248,6 +281,11 @@ $gauge-padding: 0.15rem;
|
|
|
248
281
|
font-size: 0.85rem !important;
|
|
249
282
|
}
|
|
250
283
|
|
|
284
|
+
.feature-disease-info-list {
|
|
285
|
+
max-height: 300px;
|
|
286
|
+
overflow-y: auto;
|
|
287
|
+
}
|
|
288
|
+
|
|
251
289
|
.feature-disease-info {
|
|
252
290
|
font-weight: 300;
|
|
253
291
|
padding-left: 0 !important;
|
|
@@ -352,9 +390,6 @@ $gauge-padding: 0.15rem;
|
|
|
352
390
|
}
|
|
353
391
|
|
|
354
392
|
.search-results {
|
|
355
|
-
max-height: 25vh;
|
|
356
|
-
overflow-y: scroll;
|
|
357
|
-
|
|
358
393
|
.dropdown-item {
|
|
359
394
|
white-space: normal;
|
|
360
395
|
overflow-wrap: break-word;
|
|
@@ -365,3 +400,9 @@ $gauge-padding: 0.15rem;
|
|
|
365
400
|
margin-right: 0.4rem;
|
|
366
401
|
width: 1rem;
|
|
367
402
|
}
|
|
403
|
+
|
|
404
|
+
.ellipsis-text {
|
|
405
|
+
white-space: nowrap;
|
|
406
|
+
overflow: hidden;
|
|
407
|
+
text-overflow: ellipsis;
|
|
408
|
+
}
|