@haniffalab/cherita-react 0.2.0-dev.2024-12-16.f02cfae4 → 0.2.0-dev.2024-12-16.67617f27

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.
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useFilter = void 0;
7
+ var _react = require("react");
8
+ var _turf = require("@turf/turf");
9
+ var _lodash = _interopRequireDefault(require("lodash"));
10
+ var _constants = require("../constants/constants");
11
+ var _DatasetContext = require("../context/DatasetContext");
12
+ var _FilterContext = require("../context/FilterContext");
13
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
14
+ const EPSILON = 1e-6;
15
+
16
+ // @TODO: polish hook
17
+ const useFilter = (data, features) => {
18
+ const dataset = (0, _DatasetContext.useDataset)();
19
+ const filterDataDispatch = (0, _FilterContext.useFilteredDataDispatch)();
20
+ const isInBins = (v, binEdges, indices) => {
21
+ const lastEdge = _lodash.default.last(binEdges);
22
+ const allButLastEdges = _lodash.default.initial(binEdges);
23
+ // add epsilon to last edge to include the last value
24
+ const modifiedBinEdges = [...allButLastEdges, [lastEdge[0], lastEdge[1] + EPSILON]];
25
+ const binIndices = _lodash.default.difference(_lodash.default.range(binEdges.length), indices);
26
+ const ranges = _lodash.default.at(modifiedBinEdges, binIndices);
27
+ return _lodash.default.some(ranges, range => _lodash.default.inRange(v, ...range));
28
+ };
29
+ const isCategorical = (0, _react.useMemo)(() => {
30
+ if (dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS) {
31
+ return dataset.selectedObs?.type === _constants.OBS_TYPES.CATEGORICAL || dataset.selectedObs?.type === _constants.OBS_TYPES.BOOLEAN;
32
+ } else {
33
+ return false;
34
+ }
35
+ }, [dataset.colorEncoding, dataset.selectedObs?.type]);
36
+ const isInSlice = (0, _react.useCallback)((index, values, positions) => {
37
+ let inSlice = true;
38
+ if (isCategorical && values) {
39
+ inSlice &= !_lodash.default.includes(dataset.selectedObs?.omit, values[index]);
40
+ } else if ((dataset.sliceBy.obs || dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS && dataset.selectedObs?.type === _constants.OBS_TYPES.CONTINUOUS) && !!dataset.selectedObs?.omit.length && values) {
41
+ if (dataset.selectedObs.type === _constants.OBS_TYPES.CATEGORICAL) {
42
+ inSlice &= !_lodash.default.includes(dataset.selectedObs.omit, values[index]);
43
+ } else if (dataset.selectedObs.type === _constants.OBS_TYPES.CONTINUOUS) {
44
+ if (isNaN(values[index])) {
45
+ inSlice &= !_lodash.default.includes(dataset.selectedObs.omit, -1);
46
+ } else {
47
+ inSlice &= isInBins(values[index], dataset.selectedObs.bins.binEdges, _lodash.default.without(dataset.selectedObs.omit, -1));
48
+ }
49
+ }
50
+ }
51
+ if (dataset.sliceBy.polygons && positions) {
52
+ inSlice &= _lodash.default.some(features?.features, (_f, i) => {
53
+ return (0, _turf.booleanPointInPolygon)((0, _turf.point)([positions[index][0], positions[index][1]]), features.features[i]);
54
+ });
55
+ }
56
+ return inSlice;
57
+ }, [dataset.colorEncoding, dataset.selectedObs?.bins?.binEdges, dataset.selectedObs?.omit, dataset.selectedObs?.type, dataset.sliceBy.obs, dataset.sliceBy.polygons, features?.features, isCategorical]);
58
+ const {
59
+ filteredIndices,
60
+ valueMin,
61
+ valueMax,
62
+ slicedLength
63
+ } = (0, _react.useMemo)(() => {
64
+ if (dataset.colorEncoding === _constants.COLOR_ENCODINGS.VAR) {
65
+ const {
66
+ filtered,
67
+ filteredIndices
68
+ } = _lodash.default.reduce(data.values, (acc, v, i) => {
69
+ if (isInSlice(i, data.sliceValues, data.positions)) {
70
+ acc.filtered.push(v);
71
+ acc.filteredIndices.add(i);
72
+ }
73
+ return acc;
74
+ }, {
75
+ filtered: [],
76
+ filteredIndices: new Set()
77
+ });
78
+ return {
79
+ filteredIndices: filteredIndices,
80
+ valueMin: _lodash.default.min(filtered),
81
+ valueMax: _lodash.default.max(filtered),
82
+ slicedLength: filtered.length
83
+ };
84
+ } else if (dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS) {
85
+ const isContinuous = dataset.selectedObs?.type === _constants.OBS_TYPES.CONTINUOUS;
86
+ const {
87
+ filtered,
88
+ filteredIndices
89
+ } = _lodash.default.reduce(data.values, (acc, v, i) => {
90
+ if (isInSlice(i, data.values, data.positions)) {
91
+ acc.filtered.push(v);
92
+ acc.filteredIndices.add(i);
93
+ }
94
+ return acc;
95
+ }, {
96
+ filtered: [],
97
+ filteredIndices: new Set()
98
+ });
99
+ return {
100
+ filteredIndices: filteredIndices,
101
+ valueMin: _lodash.default.min(isContinuous ? filtered : data.values),
102
+ valueMax: _lodash.default.max(isContinuous ? filtered : data.values),
103
+ slicedLength: filtered.length
104
+ };
105
+ } else {
106
+ return {
107
+ filteredIndices: null,
108
+ valueMin: _lodash.default.min(data.values),
109
+ valueMax: _lodash.default.max(data.values),
110
+ slicedLength: data.values.length
111
+ };
112
+ }
113
+ }, [data.positions, data.sliceValues, data.values, dataset.colorEncoding, dataset.selectedObs?.type, isInSlice]);
114
+
115
+ // @TODO: consider moving dispatch outside of hook, only return values
116
+ (0, _react.useEffect)(() => {
117
+ filterDataDispatch({
118
+ type: "set.obs.indices",
119
+ indices: dataset.sliceBy.obs || dataset.sliceBy.polygons ? filteredIndices : null
120
+ });
121
+ }, [dataset.sliceBy.obs, dataset.sliceBy.polygons, filterDataDispatch, filteredIndices]);
122
+ return {
123
+ filteredIndices,
124
+ valueMin,
125
+ valueMax,
126
+ slicedLength
127
+ };
128
+ };
129
+ exports.useFilter = useFilter;
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.Histogram = Histogram;
7
+ var _react = _interopRequireDefault(require("react"));
8
+ var _xCharts = require("@mui/x-charts");
9
+ var _lodash = _interopRequireDefault(require("lodash"));
10
+ var _LoadingIndicators = require("./LoadingIndicators");
11
+ var _string = require("./string");
12
+ var _jsxRuntime = require("react/jsx-runtime");
13
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
14
+ function Histogram(_ref) {
15
+ let {
16
+ data,
17
+ isPending,
18
+ altColor = false
19
+ } = _ref;
20
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
21
+ className: "feature-histogram-container",
22
+ children: isPending ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_LoadingIndicators.LoadingLinear, {}) : data ? /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
23
+ className: "feature-histogram m-1",
24
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_xCharts.SparkLineChart, {
25
+ plotType: "bar",
26
+ data: data.log10,
27
+ margin: {
28
+ top: 0,
29
+ right: 0,
30
+ bottom: 0,
31
+ left: 0
32
+ },
33
+ colors: altColor ? _xCharts.mangoFusionPalette : _xCharts.blueberryTwilightPalette,
34
+ showHighlight: true,
35
+ showTooltip: true,
36
+ valueFormatter: (v, _ref2) => {
37
+ let {
38
+ dataIndex
39
+ } = _ref2;
40
+ return `${(0, _string.formatNumerical)(data.hist[dataIndex])}`;
41
+ },
42
+ xAxis: {
43
+ data: _lodash.default.range(data.bin_edges?.length) || null,
44
+ valueFormatter: v => `Bin [${(0, _string.formatNumerical)(data.bin_edges[v][0], _string.FORMATS.EXPONENTIAL)}, ${(0, _string.formatNumerical)(data.bin_edges[v][1], _string.FORMATS.EXPONENTIAL)}${v === data.bin_edges.length - 1 ? "]" : ")"}`
45
+ },
46
+ slotProps: {
47
+ popper: {
48
+ className: "feature-histogram-tooltip"
49
+ }
50
+ }
51
+ })
52
+ }) : null
53
+ });
54
+ }
@@ -14,7 +14,7 @@ function VirtualizedList(_ref) {
14
14
  getDataAtIndex,
15
15
  count,
16
16
  ItemComponent,
17
- estimateSize = 44,
17
+ estimateSize = 45,
18
18
  overscan = 25,
19
19
  maxHeight = "80vh",
20
20
  ...props
@@ -32,7 +32,7 @@ function VirtualizedList(_ref) {
32
32
  const virtualItems = itemVirtualizer.getVirtualItems();
33
33
  (0, _react.useEffect)(() => {
34
34
  itemVirtualizer.measure();
35
- }, [itemVirtualizer, parentNode?.clientHeight]);
35
+ }, [itemVirtualizer, parentNode?.clientHeight, getDataAtIndex]);
36
36
  return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
37
37
  ref: refCallback,
38
38
  style: {
@@ -42,7 +42,10 @@ async function fetchData(endpoint, params) {
42
42
  return await response.json();
43
43
  }
44
44
  const useFetch = function (endpoint, params) {
45
- let opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
45
+ let opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
46
+ refetchOnMount: false,
47
+ refetchOnWindowFocus: false
48
+ };
46
49
  let apiUrl = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
47
50
  const {
48
51
  enabled = true
@@ -74,7 +77,10 @@ const useFetch = function (endpoint, params) {
74
77
  exports.useFetch = useFetch;
75
78
  const useDebouncedFetch = function (endpoint, params) {
76
79
  let delay = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 500;
77
- let opts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
80
+ let opts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {
81
+ refetchOnMount: false,
82
+ refetchOnWindowFocus: false
83
+ };
78
84
  let apiUrl = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;
79
85
  const {
80
86
  enabled = true
@@ -16,7 +16,8 @@ const useDiseaseSearch = () => {
16
16
  text: ""
17
17
  });
18
18
  const data = (0, _requests.useFetch)(ENDPOINT, params, {
19
- enabled: !!params.text.length
19
+ enabled: !!params.text.length,
20
+ refetchOnMount: true
20
21
  });
21
22
  return {
22
23
  params,
@@ -34,7 +35,8 @@ const useVarSearch = () => {
34
35
  text: ""
35
36
  });
36
37
  const data = (0, _requests.useFetch)(ENDPOINT, params, {
37
- enabled: !!params.text.length
38
+ enabled: !!params.text.length,
39
+ refetchOnMount: true
38
40
  });
39
41
  return {
40
42
  params,
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.FORMATS = void 0;
7
7
  exports.formatNumerical = formatNumerical;
8
+ exports.formatString = formatString;
8
9
  var _numbro = _interopRequireDefault(require("numbro"));
9
10
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
10
11
  const FORMATS = exports.FORMATS = {
@@ -61,4 +62,7 @@ function formatNumerical(n) {
61
62
  default:
62
63
  return formatThousand(n, precision);
63
64
  }
65
+ }
66
+ function formatString(s) {
67
+ return s.trim().replace(/_/g, " ");
64
68
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haniffalab/cherita-react",
3
- "version": "0.2.0-dev.2024-12-16.f02cfae4",
3
+ "version": "0.2.0-dev.2024-12-16.67617f27",
4
4
  "author": "",
5
5
  "license": "",
6
6
  "main": "dist/index.js",
@@ -101,5 +101,5 @@
101
101
  "url": "https://github.com/haniffalab/cherita-react/issues"
102
102
  },
103
103
  "homepage": "https://github.com/haniffalab/cherita-react#readme",
104
- "prereleaseSha": "f02cfae47749a5aeba88d12aefa8cee0367f9ddc"
104
+ "prereleaseSha": "67617f278b24035c633eed30a5b4d0136e3f77bb"
105
105
  }
package/scss/cherita.scss CHANGED
@@ -128,6 +128,10 @@
128
128
  background-color: #cce3ed;
129
129
  }
130
130
 
131
+ .obs-item {
132
+ box-sizing: border-box;
133
+ }
134
+
131
135
  .obs-value-list-check {
132
136
  padding-right: 1rem;
133
137
  word-break: auto-phrase;
@@ -268,6 +272,7 @@
268
272
  @extend .col-xxl-6;
269
273
 
270
274
  position: relative;
275
+ max-height: 100%;
271
276
  }
272
277
 
273
278
  .cherita-app-obs {