@weng-lab/genomebrowser-ui 0.1.11 → 0.2.0-beta.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 (84) hide show
  1. package/.env.local +1 -0
  2. package/dist/TrackSelect/DataGrid/DefaultGroupingCell.d.ts +6 -0
  3. package/dist/TrackSelect/FolderList/Breadcrumb.d.ts +6 -0
  4. package/dist/TrackSelect/FolderList/FolderCard.d.ts +6 -0
  5. package/dist/TrackSelect/FolderList/FolderList.d.ts +6 -0
  6. package/dist/TrackSelect/{Data/humanBiosamples.json.d.ts → Folders/biosamples/data/human.json.d.ts} +1940 -1919
  7. package/dist/TrackSelect/{Data/mouseBiosamples.json.d.ts → Folders/biosamples/data/mouse.json.d.ts} +408 -357
  8. package/dist/TrackSelect/Folders/biosamples/human.d.ts +7 -0
  9. package/dist/TrackSelect/Folders/biosamples/mouse.d.ts +7 -0
  10. package/dist/TrackSelect/Folders/biosamples/shared/AssayToggle.d.ts +14 -0
  11. package/dist/TrackSelect/Folders/biosamples/shared/BiosampleGroupingCell.d.ts +6 -0
  12. package/dist/TrackSelect/Folders/biosamples/shared/BiosampleTreeItem.d.ts +7 -0
  13. package/dist/TrackSelect/Folders/biosamples/shared/columns.d.ts +14 -0
  14. package/dist/TrackSelect/Folders/biosamples/shared/constants.d.ts +19 -0
  15. package/dist/TrackSelect/Folders/biosamples/shared/createFolder.d.ts +24 -0
  16. package/dist/TrackSelect/Folders/biosamples/shared/treeBuilder.d.ts +25 -0
  17. package/dist/TrackSelect/Folders/biosamples/shared/types.d.ts +44 -0
  18. package/dist/TrackSelect/Folders/genes/data/human.json.d.ts +10 -0
  19. package/dist/TrackSelect/Folders/genes/data/mouse.json.d.ts +10 -0
  20. package/dist/TrackSelect/Folders/genes/human.d.ts +7 -0
  21. package/dist/TrackSelect/Folders/genes/mouse.d.ts +7 -0
  22. package/dist/TrackSelect/Folders/genes/shared/columns.d.ts +14 -0
  23. package/dist/TrackSelect/Folders/genes/shared/createFolder.d.ts +12 -0
  24. package/dist/TrackSelect/Folders/genes/shared/treeBuilder.d.ts +13 -0
  25. package/dist/TrackSelect/Folders/genes/shared/types.d.ts +26 -0
  26. package/dist/TrackSelect/Folders/index.d.ts +14 -0
  27. package/dist/TrackSelect/Folders/types.d.ts +76 -0
  28. package/dist/TrackSelect/TrackSelect.d.ts +12 -5
  29. package/dist/TrackSelect/TreeView/CustomTreeItem.d.ts +3 -0
  30. package/dist/TrackSelect/TreeView/TreeViewWrapper.d.ts +1 -1
  31. package/dist/TrackSelect/store.d.ts +1 -2
  32. package/dist/TrackSelect/types.d.ts +24 -62
  33. package/dist/genomebrowser-ui.es.js +1373 -2117
  34. package/dist/genomebrowser-ui.es.js.map +1 -1
  35. package/dist/lib.d.ts +2 -2
  36. package/package.json +3 -3
  37. package/src/TrackSelect/DataGrid/DataGridWrapper.tsx +36 -20
  38. package/src/TrackSelect/DataGrid/DefaultGroupingCell.tsx +64 -0
  39. package/src/TrackSelect/FolderList/Breadcrumb.tsx +38 -0
  40. package/src/TrackSelect/FolderList/FolderCard.tsx +51 -0
  41. package/src/TrackSelect/FolderList/FolderList.tsx +47 -0
  42. package/src/TrackSelect/Folders/NEW.md +929 -0
  43. package/src/TrackSelect/{Data → Folders/biosamples/data}/formatBiosamples.go +2 -2
  44. package/src/TrackSelect/{Data/humanBiosamples.json → Folders/biosamples/data/human.json} +1940 -1919
  45. package/src/TrackSelect/{Data/mouseBiosamples.json → Folders/biosamples/data/mouse.json} +408 -357
  46. package/src/TrackSelect/Folders/biosamples/human.ts +17 -0
  47. package/src/TrackSelect/Folders/biosamples/mouse.ts +17 -0
  48. package/src/TrackSelect/Folders/biosamples/shared/AssayToggle.tsx +65 -0
  49. package/src/TrackSelect/{DataGrid/GroupingCell.tsx → Folders/biosamples/shared/BiosampleGroupingCell.tsx} +7 -5
  50. package/src/TrackSelect/Folders/biosamples/shared/BiosampleTreeItem.tsx +15 -0
  51. package/src/TrackSelect/{DataGrid → Folders/biosamples/shared}/columns.tsx +31 -17
  52. package/src/TrackSelect/Folders/biosamples/shared/constants.tsx +116 -0
  53. package/src/TrackSelect/Folders/biosamples/shared/createFolder.ts +116 -0
  54. package/src/TrackSelect/Folders/biosamples/shared/treeBuilder.ts +227 -0
  55. package/src/TrackSelect/Folders/biosamples/shared/types.ts +48 -0
  56. package/src/TrackSelect/Folders/genes/data/human.json +7 -0
  57. package/src/TrackSelect/Folders/genes/data/mouse.json +7 -0
  58. package/src/TrackSelect/Folders/genes/human.ts +16 -0
  59. package/src/TrackSelect/Folders/genes/mouse.ts +16 -0
  60. package/src/TrackSelect/Folders/genes/shared/columns.tsx +42 -0
  61. package/src/TrackSelect/Folders/genes/shared/createFolder.ts +68 -0
  62. package/src/TrackSelect/Folders/genes/shared/treeBuilder.ts +45 -0
  63. package/src/TrackSelect/Folders/genes/shared/types.ts +29 -0
  64. package/src/TrackSelect/Folders/index.ts +27 -0
  65. package/src/TrackSelect/Folders/types.ts +95 -0
  66. package/src/TrackSelect/TrackSelect.tsx +409 -311
  67. package/src/TrackSelect/TreeView/CustomTreeItem.tsx +217 -0
  68. package/src/TrackSelect/TreeView/TreeViewWrapper.tsx +47 -42
  69. package/src/TrackSelect/store.ts +103 -46
  70. package/src/TrackSelect/types.ts +28 -74
  71. package/src/lib.ts +2 -2
  72. package/test/main.tsx +113 -169
  73. package/.claude/settings.local.json +0 -7
  74. package/dist/TrackSelect/DataGrid/CustomToolbar.d.ts +0 -12
  75. package/dist/TrackSelect/DataGrid/GroupingCell.d.ts +0 -2
  76. package/dist/TrackSelect/DataGrid/columns.d.ts +0 -4
  77. package/dist/TrackSelect/DataGrid/dataGridHelpers.d.ts +0 -49
  78. package/dist/TrackSelect/TreeView/treeViewHelpers.d.ts +0 -49
  79. package/dist/TrackSelect/consts.d.ts +0 -11
  80. package/src/TrackSelect/DataGrid/CustomToolbar.tsx +0 -152
  81. package/src/TrackSelect/DataGrid/dataGridHelpers.tsx +0 -155
  82. package/src/TrackSelect/TreeView/treeViewHelpers.tsx +0 -475
  83. package/src/TrackSelect/consts.ts +0 -92
  84. package/src/TrackSelect/issues.md +0 -404
package/test/main.tsx CHANGED
@@ -1,19 +1,19 @@
1
+ /// <reference types="vite/client" />
2
+
1
3
  // react
2
4
  import { useCallback, useEffect, useMemo, useState } from "react";
3
5
  import { createRoot } from "react-dom/client";
4
6
 
7
+ // license
8
+ import { LicenseInfo } from "@mui/x-license";
9
+ const muiLicenseKey = import.meta.env.VITE_MUI_X_LICENSE_KEY;
10
+ if (muiLicenseKey) {
11
+ LicenseInfo.setLicenseKey(muiLicenseKey);
12
+ }
13
+
5
14
  // mui
6
15
  import EditIcon from "@mui/icons-material/Edit";
7
- import CloseIcon from "@mui/icons-material/Close";
8
- import {
9
- Box,
10
- Button,
11
- Dialog,
12
- DialogContent,
13
- DialogTitle,
14
- IconButton,
15
- Typography,
16
- } from "@mui/material";
16
+ import { Button } from "@mui/material";
17
17
 
18
18
  // weng lab
19
19
  import {
@@ -32,7 +32,9 @@ import {
32
32
  } from "@weng-lab/genomebrowser";
33
33
 
34
34
  // local
35
- import { createSelectionStore, TrackSelect, RowInfo } from "../src/lib";
35
+ import { foldersByAssembly, TrackSelect } from "../src/lib";
36
+ import type { BiosampleRowInfo } from "../src/TrackSelect/Folders/biosamples/shared/types";
37
+ import type { GeneRowInfo } from "../src/TrackSelect/Folders/genes/shared/types";
36
38
  import { Exon } from "@weng-lab/genomebrowser/dist/components/tracks/transcript/types";
37
39
 
38
40
  interface Transcript {
@@ -44,10 +46,7 @@ interface Transcript {
44
46
  color?: string;
45
47
  }
46
48
 
47
- const enum Assembly {
48
- human = "GRCh38",
49
- mouse = "mm10",
50
- }
49
+ type Assembly = "GRCh38" | "mm10";
51
50
 
52
51
  // Callback types for track interactions (using any to avoid type conflicts with library types)
53
52
  interface TrackCallbacks {
@@ -78,25 +77,9 @@ function injectCallbacks(track: Track, callbacks: TrackCallbacks): Track {
78
77
  return track;
79
78
  }
80
79
 
81
- function getLocalStorage(assembly: Assembly): Set<string> | null {
82
- if (typeof window === "undefined" || !window.sessionStorage) return null;
83
-
84
- const selectedIds = sessionStorage.getItem(assembly + "-selected-tracks");
85
- if (!selectedIds) return null;
86
- const idsArray = JSON.parse(selectedIds) as string[];
87
- return new Set(idsArray);
88
- }
89
-
90
- function setLocalStorage(trackIds: Set<string>, assembly: Assembly) {
91
- sessionStorage.setItem(
92
- assembly + "-selected-tracks",
93
- JSON.stringify([...trackIds]),
94
- );
95
- }
96
-
97
80
  function Main() {
98
81
  const [open, setOpen] = useState(false);
99
- const currentAssembly = Assembly.mouse;
82
+ const currentAssembly: Assembly = "mm10";
100
83
 
101
84
  const browserStore = createBrowserStoreMemo({
102
85
  // chr12:53,380,176-53,416,446
@@ -151,67 +134,78 @@ function Main() {
151
134
  const insertTrack = trackStore((s) => s.insertTrack);
152
135
  const removeTrack = trackStore((s) => s.removeTrack);
153
136
 
154
- const selectionStore = useMemo(() => {
155
- const localIds = getLocalStorage(currentAssembly);
156
- const ids = localIds != null ? localIds : new Set<string>();
157
- return createSelectionStore(currentAssembly, ids);
158
- }, [currentAssembly]);
137
+ const folders = useMemo(
138
+ () => foldersByAssembly[currentAssembly],
139
+ [currentAssembly],
140
+ );
159
141
 
160
- const rowById = selectionStore((s) => s.rowById);
142
+ const storageKey = `${currentAssembly}-selected-tracks`;
161
143
 
162
- // Handle submit: sync tracks to browser and save to localStorage
144
+ const initialSelection = useMemo(
145
+ () =>
146
+ (currentAssembly as Assembly) === "GRCh38"
147
+ ? defaultHumanSelections
148
+ : defaultMouseSelections,
149
+ [currentAssembly],
150
+ );
151
+
152
+ // sync tracks to browser and save to localStorage
163
153
  const handleSubmit = useCallback(
164
- (newTrackIds: Set<string>) => {
154
+ (selectedByFolder: Map<string, Set<string>>) => {
165
155
  const currentIds = new Set(tracks.map((t) => t.id));
156
+ const selectedIds = new Set<string>();
157
+ const tracksToAdd: Array<{ row: unknown; folderId: string }> = [];
158
+
159
+ for (const folder of folders) {
160
+ const folderSelection =
161
+ selectedByFolder.get(folder.id) ?? new Set<string>();
162
+ folderSelection.forEach((id) => {
163
+ selectedIds.add(id);
164
+ if (currentIds.has(id)) {
165
+ return;
166
+ }
167
+ const row = folder.rowById.get(id);
168
+ if (row) {
169
+ tracksToAdd.push({ row, folderId: folder.id });
170
+ }
171
+ });
172
+ }
166
173
 
167
- // Build tracks to add from newTrackIds + rowById lookup
168
- const tracksToAdd = Array.from(newTrackIds)
169
- .filter((id) => !currentIds.has(id)) // not in current track list
170
- .map((id) => rowById.get(id)) // get RowInfo object
171
- .filter((track): track is RowInfo => track !== undefined); // filter out undefined
172
-
173
- const tracksToRemove = tracks.filter((t) => {
174
- return !t.id.includes("ignore") && !newTrackIds.has(t.id);
175
- });
176
-
177
- console.log("removing", tracksToRemove);
174
+ const tracksToRemove = tracks.filter((t) => !selectedIds.has(t.id));
178
175
  for (const t of tracksToRemove) {
179
176
  removeTrack(t.id);
180
177
  }
181
178
 
182
- for (const s of tracksToAdd) {
183
- const track = generateTrack(s, callbacks);
179
+ for (const { row, folderId } of tracksToAdd) {
180
+ const track = generateTrack(
181
+ row as BiosampleRowInfo | GeneRowInfo,
182
+ folderId,
183
+ currentAssembly,
184
+ callbacks,
185
+ );
184
186
  if (track === null) continue;
185
187
  insertTrack(track);
186
188
  }
187
-
188
- // Save the track IDs (not the auto-generated group IDs)
189
- setLocalStorage(newTrackIds, currentAssembly);
190
- // Close the dialog
191
- setOpen(false);
192
189
  },
193
- [tracks, removeTrack, insertTrack, callbacks],
190
+ [tracks, removeTrack, insertTrack, callbacks, folders, currentAssembly],
194
191
  );
195
192
 
196
- const handleCancel = () => {
197
- setOpen(false);
198
- };
199
-
200
- // Handle reset: clear selections and remove non-default tracks
201
- const handleReset = () => {
202
- // Clear the selection store
203
- selectionStore.getState().clear();
204
-
205
- // Remove all non-default tracks from the browser
206
- const tracksToRemove = tracks.filter((t) => !t.id.includes("ignore"));
207
- for (const t of tracksToRemove) {
193
+ // clear selections and remove all tracks
194
+ const handleClear = () => {
195
+ for (const t of tracks) {
208
196
  removeTrack(t.id);
209
197
  }
210
-
211
- // Clear localStorage for selected tracks
212
- setLocalStorage(new Set(), currentAssembly);
213
198
  };
214
199
 
200
+ // On first load, if no stored selection exists, apply initial selection
201
+ useEffect(() => {
202
+ const stored = sessionStorage.getItem(storageKey);
203
+ if (!stored) {
204
+ handleSubmit(initialSelection);
205
+ }
206
+ // eslint-disable-next-line react-hooks/exhaustive-deps
207
+ }, []);
208
+
215
209
  return (
216
210
  <>
217
211
  <Button
@@ -222,38 +216,17 @@ function Main() {
222
216
  >
223
217
  Select Tracks
224
218
  </Button>
225
- <Dialog
219
+ <TrackSelect
220
+ folders={folders}
221
+ storageKey={storageKey}
222
+ initialSelection={initialSelection}
223
+ onSubmit={handleSubmit}
224
+ onClear={handleClear}
225
+ maxTracks={30}
226
226
  open={open}
227
227
  onClose={() => setOpen(false)}
228
- maxWidth="lg"
229
- fullWidth
230
- >
231
- <DialogTitle
232
- bgcolor="#0c184a"
233
- color="white"
234
- display={"flex"}
235
- justifyContent={"space-between"}
236
- alignItems={"center"}
237
- fontWeight={"bold"}
238
- >
239
- Biosample Tracks
240
- <IconButton
241
- size="large"
242
- onClick={() => setOpen(false)}
243
- sx={{ color: "white", padding: 0 }}
244
- >
245
- <CloseIcon fontSize="large" />
246
- </IconButton>
247
- </DialogTitle>
248
- <DialogContent sx={{ marginTop: "5px" }}>
249
- <TrackSelect
250
- store={selectionStore}
251
- onSubmit={handleSubmit}
252
- onCancel={handleCancel}
253
- onReset={handleReset}
254
- />
255
- </DialogContent>
256
- </Dialog>
228
+ title="Biosample Tracks"
229
+ />
257
230
  <GQLWrapper>
258
231
  <Browser browserStore={browserStore} trackStore={trackStore} />
259
232
  </GQLWrapper>
@@ -271,29 +244,40 @@ const ASSAY_COLORS: Record<string, string> = {
271
244
  atac: "#02c7b9",
272
245
  rnaseq: "#00aa00",
273
246
  chromhmm: "#00ff00",
274
- ccre: "#0c184a",
247
+ ccre: "#000000",
275
248
  };
276
249
 
277
- function generateTrack(sel: RowInfo, callbacks?: TrackCallbacks): Track {
250
+ function generateTrack(
251
+ row: BiosampleRowInfo | GeneRowInfo,
252
+ folderId: string,
253
+ assembly: Assembly,
254
+ callbacks?: TrackCallbacks,
255
+ ): Track | null {
256
+ // Handle gene folders
257
+ if (folderId.includes("genes")) {
258
+ const geneRow = row as GeneRowInfo;
259
+ const track: Track = {
260
+ ...defaultTranscript,
261
+ id: geneRow.id,
262
+ assembly,
263
+ version: geneRow.versions[geneRow.versions.length - 1], // latest version
264
+ };
265
+ return callbacks ? injectCallbacks(track, callbacks) : track;
266
+ }
267
+
268
+ // Handle biosample folders
269
+ const sel = row as BiosampleRowInfo;
278
270
  const color = ASSAY_COLORS[sel.assay.toLowerCase()] || "#000000";
279
271
  let track: Track;
280
272
 
281
273
  switch (sel.assay.toLowerCase()) {
282
274
  case "chromhmm":
283
- track = {
284
- ...defaultBigBed,
285
- id: sel.id,
286
- url: sel.url,
287
- title: sel.displayname,
288
- color,
289
- };
290
- break;
291
275
  case "ccre":
292
276
  track = {
293
277
  ...defaultBigBed,
294
278
  id: sel.id,
295
279
  url: sel.url,
296
- title: sel.displayname,
280
+ title: sel.displayName,
297
281
  color,
298
282
  };
299
283
  break;
@@ -302,7 +286,7 @@ function generateTrack(sel: RowInfo, callbacks?: TrackCallbacks): Track {
302
286
  ...defaultBigWig,
303
287
  id: sel.id,
304
288
  url: sel.url,
305
- title: sel.displayname,
289
+ title: sel.displayName,
306
290
  color,
307
291
  };
308
292
  }
@@ -341,11 +325,8 @@ export const defaultTranscript: Omit<
341
325
  export function useLocalTracks(assembly: string, callbacks?: TrackCallbacks) {
342
326
  const localTracks = getLocalTracks(assembly);
343
327
 
344
- const defaultTracks =
345
- assembly === "GRCh38" ? defaultHumanTracks : defaultMouseTracks;
346
-
347
- // Get base tracks (from storage or defaults)
348
- let initialTracks = localTracks || defaultTracks;
328
+ // Start empty if no stored tracks - TrackSelect will populate defaults
329
+ let initialTracks: Track[] = localTracks || [];
349
330
 
350
331
  // Inject callbacks if provided (callbacks are lost on JSON serialization)
351
332
  if (callbacks) {
@@ -366,7 +347,7 @@ export function useLocalTracks(assembly: string, callbacks?: TrackCallbacks) {
366
347
  export function getLocalTracks(assembly: string): Track[] | null {
367
348
  if (typeof window === "undefined" || !window.sessionStorage) return null;
368
349
 
369
- const localTracks = sessionStorage.getItem(assembly + "-" + "tracks");
350
+ const localTracks = sessionStorage.getItem(assembly + "-tracks");
370
351
  if (!localTracks) return null;
371
352
  const localTracksJson = JSON.parse(localTracks) as Track[];
372
353
  return localTracksJson;
@@ -376,50 +357,13 @@ export function setLocalTracks(tracks: Track[], assembly: string) {
376
357
  sessionStorage.setItem(assembly + "-tracks", JSON.stringify(tracks));
377
358
  }
378
359
 
379
- const defaultHumanTracks = [
380
- {
381
- ...defaultTranscript,
382
- color: ASSAY_COLORS.ccre,
383
- id: "human-genes-ignore",
384
- assembly: "GRCh38",
385
- version: 40,
386
- },
387
- {
388
- ...defaultBigBed,
389
- color: ASSAY_COLORS.ccre,
390
- id: "human-ccre-ignore",
391
- title: "All cCREs colored by group",
392
- url: "https://downloads.wenglab.org/GRCh38-cCREs.DCC.bigBed",
393
- },
394
- {
395
- ...defaultBigWig,
396
- color: ASSAY_COLORS.dnase,
397
- id: "human-dnase-aggregate-ignore",
398
- title: "Aggregated DNase signal, all ENCODE biosamples",
399
- url: "https://downloads.wenglab.org/DNAse_All_ENCODE_MAR20_2024_merged.bw",
400
- },
401
- ];
402
-
403
- const defaultMouseTracks = [
404
- {
405
- ...defaultTranscript,
406
- color: ASSAY_COLORS.ccre,
407
- id: "mouse-genes-ignore",
408
- assembly: "mm10",
409
- version: 21,
410
- },
411
- {
412
- ...defaultBigBed,
413
- color: ASSAY_COLORS.ccre,
414
- id: "mouse-ccre-ignore",
415
- title: "All cCREs colored by group",
416
- url: "https://downloads.wenglab.org/mm10-cCREs.DCC.bigBed",
417
- },
418
- {
419
- ...defaultBigWig,
420
- color: ASSAY_COLORS.dnase,
421
- id: "mouse-dnase-aggregate-ignore",
422
- title: "Aggregated DNase signal, all ENCODE biosamples",
423
- url: "https://downloads.wenglab.org/DNase_MM10_ENCODE_DEC2024_merged_nanrm.bigWig",
424
- },
425
- ];
360
+ // Default selections for TrackSelect UI (uses folder row IDs)
361
+ const defaultHumanSelections = new Map<string, Set<string>>([
362
+ ["human-genes", new Set(["genocode-basic"])],
363
+ ["human-biosamples", new Set(["ccre-aggregate", "dnase-aggregate"])],
364
+ ]);
365
+
366
+ const defaultMouseSelections = new Map<string, Set<string>>([
367
+ ["mouse-genes", new Set(["genocode-basic"])],
368
+ ["mouse-biosamples", new Set(["ccre-aggregate", "dnase-aggregate"])],
369
+ ]);
@@ -1,7 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "Bash(grep:*)"
5
- ]
6
- }
7
- }
@@ -1,12 +0,0 @@
1
- import { GridToolbarProps, ToolbarPropsOverrides } from '@mui/x-data-grid-premium';
2
- import { DataGridProps } from '../types';
3
- type CustomToolbarProps = {
4
- label: DataGridProps["label"];
5
- downloadFileName: DataGridProps["downloadFileName"];
6
- labelTooltip: DataGridProps["labelTooltip"];
7
- toolbarSlot?: DataGridProps["toolbarSlot"];
8
- toolbarStyle?: DataGridProps["toolbarStyle"];
9
- toolbarIconColor?: DataGridProps["toolbarIconColor"];
10
- } & GridToolbarProps & ToolbarPropsOverrides;
11
- export declare function CustomToolbar({ label, downloadFileName, labelTooltip, toolbarSlot, toolbarStyle, toolbarIconColor, ...restToolbarProps }: CustomToolbarProps): import("react/jsx-runtime").JSX.Element;
12
- export {};
@@ -1,2 +0,0 @@
1
- import { GridRenderCellParams } from '@mui/x-data-grid-premium';
2
- export default function GroupingCell(params: GridRenderCellParams): import("react/jsx-runtime").JSX.Element;
@@ -1,4 +0,0 @@
1
- import { GridColDef } from '@mui/x-data-grid-premium';
2
- import { RowInfo } from '../types';
3
- export declare const sortedByAssayColumns: GridColDef<RowInfo>[];
4
- export declare const defaultColumns: GridColDef<RowInfo>[];
@@ -1,49 +0,0 @@
1
- import { FuseResult } from 'fuse.js';
2
- import { RowInfo, SearchTracksProps, TrackInfo } from '../types';
3
- import { Assembly } from '../consts';
4
- export declare function getTracksData(assembly: Assembly): {
5
- tracks: {
6
- name: string;
7
- ontology: string;
8
- lifeStage: string;
9
- sampleType: string;
10
- displayname: string;
11
- assays: {
12
- id: string;
13
- assay: string;
14
- url: string;
15
- experimentAccession: string;
16
- fileAccession: string;
17
- }[];
18
- }[];
19
- };
20
- export declare function getTracksByAssayAndOntology(assay: string, ontology: string, tracksData: ReturnType<typeof getTracksData>): TrackInfo[];
21
- /** Flatten TrackInfo into RowInfo objects for DataGrid display.
22
- * @param track TrackInfo object containing information from JSON file
23
- * @returns Array of flattened RowInfo objects, one per assay
24
- */
25
- export declare function flattenIntoRows(track: TrackInfo): RowInfo[];
26
- /**
27
- * Fuzzy search in tracks stored in a JSON file.
28
- *
29
- * @param jsonStructure - Dot-separated path to the data array in the JSON structure.
30
- * @param query - The search query string.
31
- * @param keyWeightMap - Array of keys to search within each track object.
32
- * Can look like ["name", "author"] or if weighted, [
33
- {
34
- name: 'title',
35
- weight: 0.3
36
- },
37
- {
38
- name: 'author',
39
- weight: 0.7
40
- }
41
- ].
42
- * @param threshold - (Optional) Threshold for the fuzzy search (default is 0.5).
43
- * Smaller = stricter match, larger = fuzzier since 0 is perfect match and 1 is worst match.
44
- * @param limit - (Optional) Maximum number of results to return (default is 10).
45
- * @returns FuseResult object containing the search results.
46
- */
47
- export declare function searchTracks({ jsonStructure, query, keyWeightMap, threshold, tracksData, }: SearchTracksProps & {
48
- tracksData: ReturnType<typeof getTracksData>;
49
- }): FuseResult<TrackInfo>[];
@@ -1,49 +0,0 @@
1
- import { TreeViewBaseItem } from '@mui/x-tree-view';
2
- import { default as React } from 'react';
3
- import { CustomTreeItemProps, ExtendedTreeItemProps, RowInfo, SearchTracksProps } from '../types';
4
- import { FuseResult } from 'fuse.js';
5
- /**
6
- * Builds tree in the sorted by assay view
7
- * @param selectedIds: list of ids (from useSelectionStore)
8
- * @param root: Root TreeViewBaseItem
9
- * @param rowById: Mapping between an id (experimentAccession) and its RowInfo object
10
- * @returns all of the items for the RichTreeView in TreeViewWrapper
11
- */
12
- export declare function buildSortedAssayTreeView(selectedIds: string[], root: TreeViewBaseItem<ExtendedTreeItemProps>, rowById: Map<string, RowInfo>): TreeViewBaseItem<ExtendedTreeItemProps>[];
13
- /**
14
- * Builds tree in the sorted by assay view
15
- * @param selectedIds: list of ids (from useSelectionStore)
16
- * @param root: Root TreeViewBaseItem
17
- * @param rowById: Mapping between an id (experimentAccession) and its RowInfo object
18
- * @returns all of the items for the RichTreeView in TreeViewWrapper
19
- */
20
- export declare function buildTreeView(selectedIds: string[], root: TreeViewBaseItem<ExtendedTreeItemProps>, rowById: Map<string, RowInfo>): TreeViewBaseItem<ExtendedTreeItemProps>[];
21
- /**
22
- * Fuzzy search of active tracks.
23
- *
24
- * @param treeItems - TreeBaseViewItems from the tree.
25
- * @param query - The search query string.
26
- * @param keyWeightMap - Array of keys to search within each track object.
27
- * Can look like ["name", "author"] or if weighted, [
28
- {
29
- name: 'title',
30
- weight: 0.3
31
- },
32
- {
33
- name: 'author',
34
- weight: 0.7
35
- }
36
- ].
37
- * @param threshold - (Optional) Threshold for the fuzzy search (default is 0.5).
38
- * Smaller = stricter match, larger = fuzzier since 0 is perfect match and 1 is worst match.
39
- * @param limit - (Optional) Maximum number of results to return (default is 10).
40
- * @returns FuseResult object containing the search results.
41
- */
42
- export declare function searchTreeItems({ treeItems, query, keyWeightMap, threshold, limit, }: SearchTracksProps): FuseResult<RowInfo>[];
43
- /**
44
- * Creates the assay icon for DataGrid and RichTreeView
45
- * @param type: assay type
46
- * @returns an icon of the assay's respective color
47
- */
48
- export declare function AssayIcon(type: string): import("react/jsx-runtime").JSX.Element;
49
- export declare const CustomTreeItem: React.ForwardRefExoticComponent<CustomTreeItemProps & React.RefAttributes<HTMLLIElement>>;
@@ -1,11 +0,0 @@
1
- import { RowInfo } from './types';
2
- export type Assembly = "GRCh38" | "mm10";
3
- export declare const assayTypes: string[];
4
- export declare const ontologyTypes: string[];
5
- /**
6
- * Build rows and rowById for a specific assembly
7
- */
8
- export declare function buildRowsForAssembly(assembly: Assembly): {
9
- rows: RowInfo[];
10
- rowById: Map<string, RowInfo>;
11
- };
@@ -1,152 +0,0 @@
1
- import * as React from "react";
2
- import {
3
- Toolbar,
4
- ToolbarButton,
5
- FilterPanelTrigger,
6
- ExportCsv,
7
- ExportPrint,
8
- GridToolbarProps,
9
- ToolbarPropsOverrides,
10
- ExportExcel,
11
- } from "@mui/x-data-grid-premium";
12
- import Tooltip from "@mui/material/Tooltip";
13
- import Menu from "@mui/material/Menu";
14
- import Badge from "@mui/material/Badge";
15
- import FilterListIcon from "@mui/icons-material/FilterList";
16
- import FileDownloadIcon from "@mui/icons-material/FileDownload";
17
- import MenuItem from "@mui/material/MenuItem";
18
- import Divider from "@mui/material/Divider";
19
- import Typography from "@mui/material/Typography";
20
- import { DataGridProps } from "../types";
21
- import { InfoOutline } from "@mui/icons-material";
22
-
23
- type CustomToolbarProps = {
24
- label: DataGridProps["label"];
25
- downloadFileName: DataGridProps["downloadFileName"];
26
- labelTooltip: DataGridProps["labelTooltip"];
27
- toolbarSlot?: DataGridProps["toolbarSlot"];
28
- toolbarStyle?: DataGridProps["toolbarStyle"];
29
- toolbarIconColor?: DataGridProps["toolbarIconColor"];
30
- } & GridToolbarProps &
31
- ToolbarPropsOverrides;
32
-
33
- export function CustomToolbar({
34
- label,
35
- downloadFileName,
36
- labelTooltip,
37
- toolbarSlot,
38
- toolbarStyle,
39
- toolbarIconColor,
40
- ...restToolbarProps
41
- }: CustomToolbarProps) {
42
- const [exportMenuOpen, setExportMenuOpen] = React.useState(false);
43
- const exportMenuTriggerRef = React.useRef<HTMLButtonElement>(null);
44
-
45
- const iconColor = toolbarIconColor ?? "inherit";
46
-
47
- return (
48
- <Toolbar style={{ ...toolbarStyle }}>
49
- {typeof label !== "string" && label}
50
- <Typography
51
- fontWeight="medium"
52
- sx={{ flex: 1, mx: 0.5, display: "flex", alignItems: "center", gap: 1 }}
53
- >
54
- {typeof label === "string" && label}
55
- {/* ReactNode can be more than just an element, string, or number but not accounting for that for simplicity */}
56
- {labelTooltip &&
57
- (typeof labelTooltip === "string" ||
58
- typeof labelTooltip === "number") ? (
59
- <Tooltip title={labelTooltip}>
60
- <InfoOutline fontSize="inherit" color="primary" />
61
- </Tooltip>
62
- ) : (
63
- labelTooltip
64
- )}
65
- </Typography>
66
- {toolbarSlot && (
67
- <>
68
- {toolbarSlot}
69
- <Divider
70
- orientation="vertical"
71
- variant="middle"
72
- flexItem
73
- sx={{ mx: 0.5 }}
74
- />
75
- </>
76
- )}
77
-
78
- <Tooltip title="Filters">
79
- <FilterPanelTrigger
80
- render={(props, state) => (
81
- <ToolbarButton {...props} color="default">
82
- <Badge
83
- badgeContent={state.filterCount}
84
- color="primary"
85
- variant="dot"
86
- >
87
- <FilterListIcon fontSize="small" htmlColor={iconColor} />
88
- </Badge>
89
- </ToolbarButton>
90
- )}
91
- />
92
- </Tooltip>
93
- <Divider
94
- orientation="vertical"
95
- variant="middle"
96
- flexItem
97
- sx={{ mx: 0.5 }}
98
- />
99
- <Tooltip title="Export">
100
- <ToolbarButton
101
- ref={exportMenuTriggerRef}
102
- id="export-menu-trigger"
103
- aria-controls="export-menu"
104
- aria-haspopup="true"
105
- aria-expanded={exportMenuOpen ? "true" : undefined}
106
- onClick={() => setExportMenuOpen(true)}
107
- >
108
- <FileDownloadIcon fontSize="small" htmlColor={iconColor} />
109
- </ToolbarButton>
110
- </Tooltip>
111
-
112
- <Menu
113
- id="export-menu"
114
- anchorEl={exportMenuTriggerRef.current}
115
- open={exportMenuOpen}
116
- onClose={() => setExportMenuOpen(false)}
117
- anchorOrigin={{ vertical: "bottom", horizontal: "right" }}
118
- transformOrigin={{ vertical: "top", horizontal: "right" }}
119
- slotProps={{
120
- list: {
121
- "aria-labelledby": "export-menu-trigger",
122
- },
123
- }}
124
- >
125
- <ExportPrint
126
- options={{ ...restToolbarProps.printOptions }}
127
- render={<MenuItem />}
128
- onClick={() => setExportMenuOpen(false)}
129
- >
130
- Print
131
- </ExportPrint>
132
- <ExportCsv
133
- options={{
134
- fileName: typeof label === "string" ? label : downloadFileName,
135
- ...restToolbarProps.csvOptions,
136
- }}
137
- render={<MenuItem />}
138
- onClick={() => setExportMenuOpen(false)}
139
- >
140
- Download as CSV
141
- </ExportCsv>
142
- <ExportExcel
143
- options={{ ...restToolbarProps.excelOptions }}
144
- render={<MenuItem />}
145
- onClick={() => setExportMenuOpen(false)}
146
- >
147
- Download as Excel
148
- </ExportExcel>
149
- </Menu>
150
- </Toolbar>
151
- );
152
- }