@haniffalab/cherita-react 1.0.0 → 1.1.0

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 (106) hide show
  1. package/LICENSE +1 -1
  2. package/dist/{components → cjs/components}/full-page/FullPage.js +32 -22
  3. package/dist/{components → cjs/components}/full-page/FullPagePseudospatial.js +7 -6
  4. package/dist/{components → cjs/components}/obs-list/ObsItem.js +88 -77
  5. package/dist/{components → cjs/components}/obs-list/ObsList.js +133 -50
  6. package/dist/cjs/components/obs-list/ObsToolbar.js +24 -0
  7. package/dist/{components → cjs/components}/obsm-list/ObsmList.js +8 -5
  8. package/dist/{components → cjs/components}/offcanvas/index.js +24 -20
  9. package/dist/{components → cjs/components}/pseudospatial/Pseudospatial.js +10 -9
  10. package/dist/{components → cjs/components}/pseudospatial/PseudospatialToolbar.js +4 -3
  11. package/dist/{components → cjs/components}/scatterplot/Scatterplot.js +33 -24
  12. package/dist/{components → cjs/components}/scatterplot/SpatialControls.js +43 -42
  13. package/dist/cjs/components/scatterplot/Toolbox.js +62 -0
  14. package/dist/{components → cjs/components}/search-bar/SearchBar.js +24 -7
  15. package/dist/{components → cjs/components}/search-bar/SearchResults.js +13 -17
  16. package/dist/{components → cjs/components}/var-list/VarItem.js +38 -29
  17. package/dist/{components → cjs/components}/var-list/VarList.js +59 -31
  18. package/dist/{components → cjs/components}/var-list/VarListToolbar.js +18 -14
  19. package/dist/{components → cjs/components}/var-list/VarSet.js +24 -20
  20. package/dist/{components → cjs/components}/violin/Violin.js +4 -3
  21. package/dist/{constants → cjs/constants}/constants.js +6 -2
  22. package/dist/{context → cjs/context}/DatasetContext.js +12 -11
  23. package/dist/{context → cjs/context}/FilterContext.js +4 -3
  24. package/dist/{context → cjs/context}/ZarrDataContext.js +4 -3
  25. package/dist/{helpers → cjs/helpers}/color-helper.js +12 -11
  26. package/dist/{helpers → cjs/helpers}/map-helper.js +8 -7
  27. package/dist/{helpers → cjs/helpers}/zarr-helper.js +30 -38
  28. package/dist/{utils → cjs/utils}/Filter.js +1 -1
  29. package/dist/{utils → cjs/utils}/Histogram.js +12 -8
  30. package/dist/{utils → cjs/utils}/ImageViewer.js +6 -5
  31. package/dist/{utils → cjs/utils}/Legend.js +8 -7
  32. package/dist/{utils → cjs/utils}/LoadingIndicators.js +5 -4
  33. package/dist/cjs/utils/Skeleton.js +19 -0
  34. package/dist/{utils → cjs/utils}/VirtualizedList.js +10 -9
  35. package/dist/{utils → cjs/utils}/requests.js +37 -39
  36. package/dist/{utils → cjs/utils}/string.js +9 -4
  37. package/dist/{utils → cjs/utils}/zarrData.js +12 -4
  38. package/dist/css/cherita.css +147 -152
  39. package/dist/css/cherita.css.map +1 -1
  40. package/dist/esm/components/dotplot/Dotplot.js +135 -0
  41. package/dist/esm/components/dotplot/DotplotControls.js +148 -0
  42. package/dist/esm/components/full-page/FullPage.js +143 -0
  43. package/dist/esm/components/full-page/FullPagePseudospatial.js +151 -0
  44. package/dist/esm/components/heatmap/Heatmap.js +105 -0
  45. package/dist/esm/components/heatmap/HeatmapControls.js +23 -0
  46. package/dist/esm/components/matrixplot/Matrixplot.js +107 -0
  47. package/dist/esm/components/matrixplot/MatrixplotControls.js +38 -0
  48. package/dist/esm/components/obs-list/ObsItem.js +484 -0
  49. package/dist/esm/components/obs-list/ObsList.js +338 -0
  50. package/dist/esm/components/obs-list/ObsToolbar.js +17 -0
  51. package/dist/esm/components/obsm-list/ObsmList.js +75 -0
  52. package/dist/esm/components/offcanvas/index.js +67 -0
  53. package/dist/esm/components/pseudospatial/Pseudospatial.js +228 -0
  54. package/dist/esm/components/pseudospatial/PseudospatialToolbar.js +123 -0
  55. package/dist/esm/components/scatterplot/Scatterplot.js +394 -0
  56. package/dist/esm/components/scatterplot/ScatterplotControls.js +71 -0
  57. package/dist/esm/components/scatterplot/SpatialControls.js +140 -0
  58. package/dist/esm/components/scatterplot/Toolbox.js +55 -0
  59. package/dist/esm/components/search-bar/SearchBar.js +90 -0
  60. package/dist/esm/components/search-bar/SearchResults.js +139 -0
  61. package/dist/esm/components/var-list/VarItem.js +254 -0
  62. package/dist/esm/components/var-list/VarList.js +291 -0
  63. package/dist/esm/components/var-list/VarListToolbar.js +87 -0
  64. package/dist/esm/components/var-list/VarSet.js +194 -0
  65. package/dist/esm/components/violin/Violin.js +141 -0
  66. package/dist/esm/components/violin/ViolinControls.js +24 -0
  67. package/dist/esm/constants/colorscales.js +22 -0
  68. package/dist/esm/constants/constants.js +88 -0
  69. package/dist/esm/context/DatasetContext.js +571 -0
  70. package/dist/esm/context/FilterContext.js +48 -0
  71. package/dist/esm/context/ZarrDataContext.js +26 -0
  72. package/dist/esm/helpers/color-helper.js +66 -0
  73. package/dist/esm/helpers/map-helper.js +53 -0
  74. package/dist/esm/helpers/zarr-helper.js +111 -0
  75. package/dist/esm/index.js +22 -0
  76. package/dist/esm/utils/Filter.js +147 -0
  77. package/dist/esm/utils/Histogram.js +44 -0
  78. package/dist/esm/utils/ImageViewer.js +27 -0
  79. package/dist/esm/utils/Legend.js +58 -0
  80. package/dist/esm/utils/LoadingIndicators.js +22 -0
  81. package/dist/esm/utils/Skeleton.js +12 -0
  82. package/dist/esm/utils/VirtualizedList.js +55 -0
  83. package/dist/esm/utils/errors.js +47 -0
  84. package/dist/esm/utils/requests.js +102 -0
  85. package/dist/esm/utils/search.js +39 -0
  86. package/dist/esm/utils/string.js +59 -0
  87. package/dist/esm/utils/zarrData.js +102 -0
  88. package/package.json +19 -7
  89. package/scss/cherita.scss +19 -50
  90. package/scss/components/accordions.scss +32 -0
  91. package/scss/components/layouts.scss +2 -1
  92. package/scss/components/lists.scss +14 -0
  93. package/dist/components/obs-list/ObsToolbar.js +0 -64
  94. package/dist/components/scatterplot/Toolbox.js +0 -31
  95. /package/dist/{components → cjs/components}/dotplot/Dotplot.js +0 -0
  96. /package/dist/{components → cjs/components}/dotplot/DotplotControls.js +0 -0
  97. /package/dist/{components → cjs/components}/heatmap/Heatmap.js +0 -0
  98. /package/dist/{components → cjs/components}/heatmap/HeatmapControls.js +0 -0
  99. /package/dist/{components → cjs/components}/matrixplot/Matrixplot.js +0 -0
  100. /package/dist/{components → cjs/components}/matrixplot/MatrixplotControls.js +0 -0
  101. /package/dist/{components → cjs/components}/scatterplot/ScatterplotControls.js +0 -0
  102. /package/dist/{components → cjs/components}/violin/ViolinControls.js +0 -0
  103. /package/dist/{constants → cjs/constants}/colorscales.js +0 -0
  104. /package/dist/{index.js → cjs/index.js} +0 -0
  105. /package/dist/{utils → cjs/utils}/errors.js +0 -0
  106. /package/dist/{utils → cjs/utils}/search.js +0 -0
@@ -0,0 +1,338 @@
1
+ import React, { useContext, useEffect, useMemo, useState } from "react";
2
+ import { faChevronDown, faChevronRight } from "@fortawesome/free-solid-svg-icons";
3
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
4
+ import CommentIcon from "@mui/icons-material/Comment";
5
+ import JoinInnerIcon from "@mui/icons-material/JoinInner";
6
+ import WaterDropIcon from "@mui/icons-material/WaterDrop";
7
+ import _ from "lodash";
8
+ import { Alert } from "react-bootstrap";
9
+ import Accordion from "react-bootstrap/Accordion";
10
+ import { useAccordionButton } from "react-bootstrap/AccordionButton";
11
+ import AccordionContext from "react-bootstrap/AccordionContext";
12
+ import { COLOR_ENCODINGS, DEFAULT_OBS_GROUP, OBS_TYPES } from "../../constants/constants";
13
+ import { useDataset, useDatasetDispatch } from "../../context/DatasetContext";
14
+ import { LoadingSpinner } from "../../utils/LoadingIndicators";
15
+ import { useFetch } from "../../utils/requests";
16
+ import { CategoricalObs, ContinuousObs } from "./ObsItem";
17
+
18
+ // @TODO: integrate ObsAccordionToggle with ObsColsList active, expandedItems, etc. to avoid duplication
19
+
20
+ const ObsAccordionToggle = _ref => {
21
+ let {
22
+ children,
23
+ eventKey,
24
+ handleAccordionToggle
25
+ } = _ref;
26
+ const {
27
+ activeEventKey
28
+ } = useContext(AccordionContext);
29
+ const decoratedOnClick = useAccordionButton(eventKey, () => {
30
+ handleAccordionToggle(eventKey);
31
+ });
32
+ const isCurrentEventKey = Array.isArray(activeEventKey) ? activeEventKey.includes(eventKey) : activeEventKey === eventKey;
33
+ return /*#__PURE__*/React.createElement("div", {
34
+ className: `obs-accordion-header ${isCurrentEventKey ? "active" : ""}`,
35
+ onClick: decoratedOnClick
36
+ }, /*#__PURE__*/React.createElement("span", {
37
+ className: "obs-accordion-header-chevron"
38
+ }, /*#__PURE__*/React.createElement(FontAwesomeIcon, {
39
+ icon: isCurrentEventKey ? faChevronDown : faChevronRight
40
+ })), /*#__PURE__*/React.createElement("span", {
41
+ className: "obs-accordion-header-title"
42
+ }, children));
43
+ };
44
+ export function ObsColsList(_ref2) {
45
+ let {
46
+ showColor = true,
47
+ enableObsGroups = true
48
+ } = _ref2;
49
+ const ENDPOINT = "obs/cols";
50
+ const dataset = useDataset();
51
+ const dispatch = useDatasetDispatch();
52
+ const [enableGroups, setEnableGroups] = useState(enableObsGroups);
53
+ const [obsCols, setObsCols] = useState(null);
54
+ const [active, setActive] = useState(dataset.selectedObs?.name);
55
+ const [expandedItems, setExpandedItems] = useState({});
56
+ const [params, setParams] = useState({
57
+ url: dataset.url
58
+ });
59
+ const obsGroups = useMemo(() => ({
60
+ default: _.union(DEFAULT_OBS_GROUP, dataset.obsGroups?.default),
61
+ ..._.omit(dataset.obsGroups, "default")
62
+ }), [dataset.obsGroups]);
63
+ useEffect(() => {
64
+ setParams(p => {
65
+ return {
66
+ ...p,
67
+ url: dataset.url
68
+ };
69
+ });
70
+ }, [dataset.url]);
71
+ const {
72
+ fetchedData,
73
+ isPending,
74
+ serverError
75
+ } = useFetch(ENDPOINT, params, {
76
+ refetchOnMount: false
77
+ });
78
+ useEffect(() => {
79
+ if (!isPending && !serverError && fetchedData) {
80
+ let filteredData = fetchedData;
81
+
82
+ // filter to only obs within an obsGroup
83
+ if (enableGroups) {
84
+ const groupFiltered = _.filter(filteredData, d => {
85
+ return _.some(obsGroups, g => _.includes(g, d.name));
86
+ });
87
+ if (!!filteredData.length && !groupFiltered.length) {
88
+ setEnableGroups(false);
89
+ console.warn(`No obs found in obsGroups ${JSON.stringify(obsGroups)}, disabling obsGroups`);
90
+ } else {
91
+ filteredData = groupFiltered;
92
+ }
93
+ }
94
+
95
+ // filter out discrete obs
96
+ filteredData = _.filter(filteredData, d => {
97
+ return d.type !== OBS_TYPES.DISCRETE;
98
+ });
99
+ setObsCols(_.keyBy(_.map(filteredData, d => {
100
+ return {
101
+ ...d,
102
+ codesMap: _.invert(d.codes),
103
+ omit: []
104
+ };
105
+ }), "name"));
106
+ }
107
+ }, [fetchedData, isPending, obsGroups, serverError, enableGroups]);
108
+ useEffect(() => {
109
+ if (obsCols && Object.keys(expandedItems).length === 0) {
110
+ const initialExpanded = Object.keys(obsCols).reduce((acc, key) => {
111
+ acc[key] = false;
112
+ return acc;
113
+ }, {});
114
+ if (active && obsCols[active]) {
115
+ initialExpanded[active] = true;
116
+ }
117
+ setExpandedItems(initialExpanded);
118
+ }
119
+ }, [obsCols, expandedItems, active]);
120
+
121
+ // @TODO: fix re-rendering performance issue
122
+ useEffect(() => {
123
+ if (obsCols) {
124
+ if (obsCols[dataset.selectedObs?.name]) {
125
+ setActive(dataset.selectedObs?.name);
126
+ } else {
127
+ setActive(null);
128
+ dispatch({
129
+ type: "select.obs",
130
+ obs: null
131
+ });
132
+ }
133
+ }
134
+ }, [dataset.selectedObs, dispatch, obsCols]);
135
+ const updateObs = updatedObs => {
136
+ setObsCols(o => {
137
+ return {
138
+ ...o,
139
+ [updatedObs.name]: updatedObs
140
+ };
141
+ });
142
+ };
143
+ const handleAccordionToggle = itemName => {
144
+ _.delay(
145
+ // to avoid contents of accordion disappearing while closing
146
+ () => {
147
+ setExpandedItems(prev => {
148
+ return {
149
+ ...prev,
150
+ [itemName]: !prev[itemName]
151
+ };
152
+ });
153
+ }, expandedItems[itemName] ? 250 : 0);
154
+ };
155
+ const toggleAll = item => {
156
+ const omit = item.omit.length ? [] : _.map(item.values, v => item.codes[v]);
157
+ setObsCols(o => {
158
+ return {
159
+ ...o,
160
+ [item.name]: {
161
+ ...item,
162
+ omit: omit
163
+ }
164
+ };
165
+ });
166
+ if (active === item.name) {
167
+ dispatch({
168
+ type: "select.obs",
169
+ obs: {
170
+ ...item,
171
+ omit: omit
172
+ }
173
+ });
174
+ }
175
+ };
176
+ const toggleLabel = item => {
177
+ const inLabelObs = _.some(dataset.labelObs, i => i.name === item.name);
178
+ if (inLabelObs) {
179
+ dispatch({
180
+ type: "remove.label.obs",
181
+ obsName: item.name
182
+ });
183
+ } else {
184
+ dispatch({
185
+ type: "add.label.obs",
186
+ obs: {
187
+ name: item.name,
188
+ type: item.type,
189
+ codesMap: item.codesMap
190
+ }
191
+ });
192
+ }
193
+ };
194
+ const toggleSlice = item => {
195
+ dispatch({
196
+ type: "toggle.slice.obs",
197
+ obs: item
198
+ });
199
+ };
200
+ const toggleColor = item => {
201
+ dispatch({
202
+ type: "select.obs",
203
+ obs: item
204
+ });
205
+ dispatch({
206
+ type: "set.colorEncoding",
207
+ value: COLOR_ENCODINGS.OBS
208
+ });
209
+ };
210
+ const toggleObs = (item, value) => {
211
+ let omit;
212
+ if (_.includes(item.omit, item.codes[value])) {
213
+ omit = item.omit.filter(i => i !== item.codes[value]);
214
+ } else {
215
+ omit = [...item.omit, item.codes[value]];
216
+ }
217
+ setObsCols(o => {
218
+ return {
219
+ ...o,
220
+ [item.name]: {
221
+ ...item,
222
+ omit: omit
223
+ }
224
+ };
225
+ });
226
+ if (active === item.name) {
227
+ dispatch({
228
+ type: "select.obs",
229
+ obs: {
230
+ ...item,
231
+ omit: omit
232
+ }
233
+ });
234
+ }
235
+ };
236
+ const obsItem = item => {
237
+ if (!item) {
238
+ return null;
239
+ }
240
+ if (item.type === OBS_TYPES.DISCRETE) {
241
+ return null;
242
+ }
243
+ const inLabelObs = _.some(dataset.labelObs, i => i.name === item.name);
244
+ const inSliceObs = dataset.sliceBy.obs && dataset.selectedObs?.name === item.name;
245
+ const isColorEncoding = dataset.colorEncoding === COLOR_ENCODINGS.OBS && dataset.selectedObs?.name === item.name;
246
+ return /*#__PURE__*/React.createElement("div", {
247
+ className: "accordion-item",
248
+ key: item.name
249
+ }, /*#__PURE__*/React.createElement(ObsAccordionToggle, {
250
+ eventKey: item.name,
251
+ handleAccordionToggle: handleAccordionToggle
252
+ }, /*#__PURE__*/React.createElement("div", null, item.name), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("span", {
253
+ className: `mx-1 cursor-pointer ${inLabelObs ? "active-icon" : "text-muted opacity-50"}`,
254
+ onClick: event => {
255
+ event.stopPropagation();
256
+ toggleLabel(item);
257
+ },
258
+ title: "Add to tooltip"
259
+ }, /*#__PURE__*/React.createElement(CommentIcon, null)), /*#__PURE__*/React.createElement("span", {
260
+ className: `mx-1 cursor-pointer ${inSliceObs ? "active-icon" : "text-muted opacity-50"}`,
261
+ onClick: event => {
262
+ event.stopPropagation();
263
+ toggleSlice(item);
264
+ },
265
+ title: "Filter applied"
266
+ }, /*#__PURE__*/React.createElement(JoinInnerIcon, null)), /*#__PURE__*/React.createElement("span", {
267
+ className: `mx-1 cursor-pointer ${isColorEncoding ? "active-icon" : "text-muted opacity-50"}`,
268
+ onClick: event => {
269
+ event.stopPropagation();
270
+ toggleColor(item);
271
+ },
272
+ title: "Is color encoding"
273
+ }, /*#__PURE__*/React.createElement(WaterDropIcon, null)))), /*#__PURE__*/React.createElement(Accordion.Collapse, {
274
+ eventKey: item.name
275
+ }, /*#__PURE__*/React.createElement("div", {
276
+ className: "obs-accordion-body"
277
+ }, expandedItems[item.name] && (item.type === OBS_TYPES.CATEGORICAL || item.type === OBS_TYPES.BOOLEAN ? /*#__PURE__*/React.createElement(CategoricalObs, {
278
+ key: item.name,
279
+ obs: item,
280
+ updateObs: updateObs,
281
+ toggleAll: () => toggleAll(item),
282
+ toggleObs: value => toggleObs(item, value),
283
+ toggleLabel: () => toggleLabel(item),
284
+ toggleSlice: () => toggleSlice(item),
285
+ toggleColor: () => toggleColor(item),
286
+ showColor: showColor
287
+ }) : /*#__PURE__*/React.createElement(ContinuousObs, {
288
+ key: item.name,
289
+ obs: item,
290
+ updateObs: updateObs,
291
+ toggleAll: () => toggleAll(item),
292
+ toggleObs: value => toggleObs(item, value),
293
+ toggleLabel: () => toggleLabel(item),
294
+ toggleSlice: () => toggleSlice(item),
295
+ toggleColor: () => toggleColor(item)
296
+ })))));
297
+ };
298
+ const groupList = _.map(_.keys(obsGroups), group => {
299
+ const key = `group-${group}`;
300
+ const groupItems = _.compact(_.map(_.sortBy(obsGroups[group], o => _.lowerCase(o.name)), item => {
301
+ return obsItem(obsCols?.[item]);
302
+ }));
303
+ if (group === "default") {
304
+ return groupItems;
305
+ } else {
306
+ return /*#__PURE__*/React.createElement(Accordion.Item, {
307
+ key: key,
308
+ eventKey: key,
309
+ className: "obs-group-accordion-item"
310
+ }, /*#__PURE__*/React.createElement(Accordion.Header, {
311
+ className: "obs-group-accordion-header"
312
+ }, group), /*#__PURE__*/React.createElement(Accordion.Body, {
313
+ className: "obs-group-accordion-body"
314
+ }, groupItems));
315
+ }
316
+ });
317
+ const obsList = enableGroups ? /*#__PURE__*/React.createElement(Accordion, {
318
+ className: "obs-group-accordion",
319
+ flush: true,
320
+ alwaysOpen: true
321
+ }, groupList) : _.map(_.sortBy(obsCols, o => _.lowerCase(o.name)), item => obsItem(item));
322
+ if (!serverError) {
323
+ return /*#__PURE__*/React.createElement("div", {
324
+ className: "position-relative h-100"
325
+ }, isPending ? /*#__PURE__*/React.createElement(LoadingSpinner, null) : !!obsCols && !_.size(obsCols) ? /*#__PURE__*/React.createElement(Alert, {
326
+ variant: "danger"
327
+ }, "No observations found.") : /*#__PURE__*/React.createElement(Accordion, {
328
+ flush: true,
329
+ defaultActiveKey: [active],
330
+ alwaysOpen: true,
331
+ className: "obs-accordion"
332
+ }, obsList));
333
+ } else {
334
+ return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Alert, {
335
+ variant: "danger"
336
+ }, serverError.message));
337
+ }
338
+ }
@@ -0,0 +1,17 @@
1
+ import React from "react";
2
+ import { Form } from "react-bootstrap";
3
+ export function ObsToolbar(_ref) {
4
+ let {
5
+ item,
6
+ showToggleAllObs = true,
7
+ onToggleAllObs
8
+ } = _ref;
9
+ const allToggledOn = !item.omit.length;
10
+ return showToggleAllObs && /*#__PURE__*/React.createElement(Form.Check, {
11
+ type: "switch",
12
+ id: "custom-switch",
13
+ label: "Toggle all",
14
+ checked: allToggledOn,
15
+ onChange: onToggleAllObs
16
+ });
17
+ }
@@ -0,0 +1,75 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import { Button, ButtonGroup, Dropdown, DropdownButton, OverlayTrigger, Tooltip } from "react-bootstrap";
3
+ import { useDataset, useDatasetDispatch } from "../../context/DatasetContext";
4
+ import { useFetch } from "../../utils/requests";
5
+ import { ObsmKeysListBtn } from "../../utils/Skeleton";
6
+ export function ObsmKeysList() {
7
+ const ENDPOINT = "obsm/keys";
8
+ const dataset = useDataset();
9
+ const dispatch = useDatasetDispatch();
10
+ const [obsmKeysList, setObsmKeysList] = useState([]);
11
+ const [active, setActive] = useState(null);
12
+ const [params, setParams] = useState({
13
+ url: dataset.url
14
+ });
15
+ useEffect(() => {
16
+ setParams(p => {
17
+ return {
18
+ ...p,
19
+ url: dataset.url
20
+ };
21
+ });
22
+ }, [dataset.url]);
23
+ const {
24
+ fetchedData,
25
+ isPending,
26
+ serverError
27
+ } = useFetch(ENDPOINT, params, {
28
+ refetchOnMount: false
29
+ });
30
+ useEffect(() => {
31
+ if (!isPending && !serverError && fetchedData) {
32
+ setObsmKeysList(fetchedData);
33
+ }
34
+ }, [fetchedData, isPending, serverError]);
35
+ useEffect(() => {
36
+ if (dataset.selectedObsm) {
37
+ setActive(dataset.selectedObsm);
38
+ }
39
+ }, [dataset.selectedObsm]);
40
+ const obsmList = obsmKeysList.map(item => {
41
+ return /*#__PURE__*/React.createElement(Dropdown.Item, {
42
+ key: item,
43
+ className: `custom ${active === item && "active"}`,
44
+ onClick: () => {
45
+ dispatch({
46
+ type: "select.obsm",
47
+ obsm: item
48
+ });
49
+ }
50
+ }, item);
51
+ });
52
+ if (!serverError) {
53
+ if (isPending) {
54
+ return /*#__PURE__*/React.createElement(ObsmKeysListBtn, null);
55
+ }
56
+ return /*#__PURE__*/React.createElement(DropdownButton, {
57
+ as: ButtonGroup,
58
+ title: dataset.selectedObsm || "Select an embedding",
59
+ variant: dataset.selectedObsm ? "primary" : "warning",
60
+ id: "bg-nested-dropdown",
61
+ size: "sm"
62
+ }, /*#__PURE__*/React.createElement(Dropdown.Header, null, "Embeddings"), obsmList);
63
+ } else {
64
+ return /*#__PURE__*/React.createElement(OverlayTrigger, {
65
+ placement: "top",
66
+ delay: {
67
+ show: 100,
68
+ hide: 200
69
+ },
70
+ overlay: /*#__PURE__*/React.createElement(Tooltip, null, serverError.message)
71
+ }, /*#__PURE__*/React.createElement(Button, {
72
+ variant: "danger"
73
+ }, "Error"));
74
+ }
75
+ }
@@ -0,0 +1,67 @@
1
+ import React from "react";
2
+ import Offcanvas from "react-bootstrap/Offcanvas";
3
+ import { SELECTION_MODES } from "../../constants/constants";
4
+ import { ObsColsList } from "../obs-list/ObsList";
5
+ import { ObsmKeysList } from "../obsm-list/ObsmList";
6
+ import { SearchBar } from "../search-bar/SearchBar";
7
+ import { VarNamesList } from "../var-list/VarList";
8
+ export function OffcanvasObs(_ref) {
9
+ let {
10
+ show,
11
+ handleClose,
12
+ ...props
13
+ } = _ref;
14
+ return /*#__PURE__*/React.createElement(Offcanvas, {
15
+ show: show,
16
+ onHide: handleClose,
17
+ scroll: true,
18
+ backdrop: false
19
+ }, /*#__PURE__*/React.createElement(Offcanvas.Header, {
20
+ closeButton: true
21
+ }, /*#__PURE__*/React.createElement(Offcanvas.Title, null, "Categories")), /*#__PURE__*/React.createElement(Offcanvas.Body, {
22
+ className: "p-0"
23
+ }, /*#__PURE__*/React.createElement(ObsColsList, props)));
24
+ }
25
+ export function OffcanvasObsm(_ref2) {
26
+ let {
27
+ show,
28
+ handleClose
29
+ } = _ref2;
30
+ return /*#__PURE__*/React.createElement(Offcanvas, {
31
+ show: show,
32
+ onHide: handleClose
33
+ }, /*#__PURE__*/React.createElement(Offcanvas.Header, {
34
+ closeButton: true
35
+ }, /*#__PURE__*/React.createElement(Offcanvas.Title, null, "Embedding space")), /*#__PURE__*/React.createElement(Offcanvas.Body, null, /*#__PURE__*/React.createElement(ObsmKeysList, null)));
36
+ }
37
+ export function OffcanvasVars(_ref3) {
38
+ let {
39
+ show,
40
+ handleClose,
41
+ mode = SELECTION_MODES.MULTIPLE
42
+ } = _ref3;
43
+ return /*#__PURE__*/React.createElement(Offcanvas, {
44
+ show: show,
45
+ onHide: handleClose
46
+ }, /*#__PURE__*/React.createElement(Offcanvas.Header, {
47
+ closeButton: true
48
+ }, /*#__PURE__*/React.createElement(Offcanvas.Title, null, "Features")), /*#__PURE__*/React.createElement(Offcanvas.Body, null, /*#__PURE__*/React.createElement(SearchBar, {
49
+ searchDiseases: true
50
+ }), /*#__PURE__*/React.createElement(VarNamesList, {
51
+ mode: mode
52
+ })));
53
+ }
54
+ export function OffcanvasControls(_ref4) {
55
+ let {
56
+ show,
57
+ handleClose,
58
+ Controls,
59
+ ...props
60
+ } = _ref4;
61
+ return /*#__PURE__*/React.createElement(Offcanvas, {
62
+ show: show,
63
+ onHide: handleClose
64
+ }, /*#__PURE__*/React.createElement(Offcanvas.Header, {
65
+ closeButton: true
66
+ }, /*#__PURE__*/React.createElement(Offcanvas.Title, null, "Controls")), /*#__PURE__*/React.createElement(Offcanvas.Body, null, /*#__PURE__*/React.createElement(Controls, props)));
67
+ }