@weng-lab/genomebrowser-ui 0.4.0-beta.2 → 0.4.1

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 (33) hide show
  1. package/dist/TrackSelect/Folders/biosamples/data/{human_with_wgbs.json.d.ts → humans_fixed.json.d.ts} +511 -511
  2. package/dist/TrackSelect/Folders/biosamples/shared/types.d.ts +1 -1
  3. package/dist/TrackSelect/Folders/index.d.ts +2 -0
  4. package/dist/TrackSelect/Folders/psychscreen/data/human.json.d.ts +815 -0
  5. package/dist/TrackSelect/Folders/psychscreen/human.d.ts +1 -0
  6. package/dist/TrackSelect/Folders/psychscreen/shared/PsychscreenGroupingCell.d.ts +2 -0
  7. package/dist/TrackSelect/Folders/psychscreen/shared/columns.d.ts +7 -0
  8. package/dist/TrackSelect/Folders/psychscreen/shared/createFolder.d.ts +9 -0
  9. package/dist/TrackSelect/Folders/psychscreen/shared/toTrack.d.ts +5 -0
  10. package/dist/TrackSelect/Folders/psychscreen/shared/types.d.ts +12 -0
  11. package/dist/TrackSelect/trackContext.d.ts +2 -1
  12. package/dist/TrackSelect/types.d.ts +1 -1
  13. package/dist/genomebrowser-ui.es.js +1408 -1263
  14. package/dist/genomebrowser-ui.es.js.map +1 -1
  15. package/package.json +4 -3
  16. package/src/TrackSelect/DataGrid/DataGridWrapper.tsx +9 -5
  17. package/src/TrackSelect/Folders/biosamples/data/fix-human-collections.mjs +119 -0
  18. package/src/TrackSelect/Folders/biosamples/data/humans_fixed.json +59909 -0
  19. package/src/TrackSelect/Folders/biosamples/human.ts +1 -1
  20. package/src/TrackSelect/Folders/biosamples/shared/columns.tsx +2 -2
  21. package/src/TrackSelect/Folders/biosamples/shared/types.ts +1 -1
  22. package/src/TrackSelect/Folders/index.ts +4 -0
  23. package/src/TrackSelect/Folders/psychscreen/data/human.json +812 -0
  24. package/src/TrackSelect/Folders/psychscreen/human.ts +10 -0
  25. package/src/TrackSelect/Folders/psychscreen/shared/PsychscreenGroupingCell.tsx +78 -0
  26. package/src/TrackSelect/Folders/psychscreen/shared/columns.tsx +52 -0
  27. package/src/TrackSelect/Folders/psychscreen/shared/createFolder.ts +45 -0
  28. package/src/TrackSelect/Folders/psychscreen/shared/toTrack.ts +48 -0
  29. package/src/TrackSelect/Folders/psychscreen/shared/types.ts +14 -0
  30. package/src/TrackSelect/TreeView/CustomTreeItem.tsx +10 -2
  31. package/src/TrackSelect/TreeView/TreeViewWrapper.tsx +4 -1
  32. package/src/TrackSelect/trackContext.ts +2 -0
  33. package/src/TrackSelect/types.ts +1 -1
@@ -0,0 +1,10 @@
1
+ import { createPsychscreenFolder } from "./shared/createFolder";
2
+ import humanData from "./data/human.json";
3
+ import { PsychscreenDataFile } from "./shared/types";
4
+
5
+ export const humanPsychscreenFolder = createPsychscreenFolder({
6
+ id: "human-psychscreen",
7
+ label: "PsychSCREEN",
8
+ description: "PsychSCREEN browser tracks",
9
+ data: humanData as PsychscreenDataFile,
10
+ });
@@ -0,0 +1,78 @@
1
+ import ChevronRightIcon from "@mui/icons-material/ChevronRight";
2
+ import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
3
+ import { Box, IconButton, Tooltip } from "@mui/material";
4
+ import { alpha } from "@mui/material/styles";
5
+ import {
6
+ GridGroupNode,
7
+ GridRenderCellParams,
8
+ useGridApiContext,
9
+ } from "@mui/x-data-grid-premium";
10
+ import { getPsychscreenCategoryColor } from "./columns";
11
+
12
+ export function PsychscreenGroupingCell(params: GridRenderCellParams) {
13
+ const apiRef = useGridApiContext();
14
+ const isGroup = params.rowNode.type === "group";
15
+ const groupNode = params.rowNode as GridGroupNode;
16
+ const isExpanded = isGroup ? groupNode.childrenExpanded : false;
17
+ const groupingField = isGroup ? groupNode.groupingField : null;
18
+ const isCategoryGroup = groupingField === "category";
19
+ const color = getPsychscreenCategoryColor(
20
+ isCategoryGroup ? String(params.value ?? "") : params.row.category,
21
+ );
22
+ const label = String(params.formattedValue ?? params.value ?? "");
23
+ const depth = params.rowNode.depth ?? 0;
24
+
25
+ const handleExpandClick = (e: React.MouseEvent) => {
26
+ e.stopPropagation();
27
+ apiRef.current.setRowChildrenExpansion(params.id, !isExpanded);
28
+ };
29
+
30
+ return (
31
+ <Box
32
+ sx={{
33
+ display: "flex",
34
+ alignItems: "center",
35
+ width: "100%",
36
+ gap: 1,
37
+ ml: depth * 2,
38
+ }}
39
+ >
40
+ {isGroup && (
41
+ <IconButton size="small" onClick={handleExpandClick} sx={{ mr: 0.25 }}>
42
+ {isExpanded ? (
43
+ <ExpandMoreIcon fontSize="small" />
44
+ ) : (
45
+ <ChevronRightIcon fontSize="small" />
46
+ )}
47
+ </IconButton>
48
+ )}
49
+ {isCategoryGroup && (
50
+ <Box
51
+ sx={{
52
+ width: 9,
53
+ height: 9,
54
+ borderRadius: "50%",
55
+ bgcolor: alpha(color, 0.65),
56
+ flexShrink: 0,
57
+ }}
58
+ />
59
+ )}
60
+ <Tooltip title={label} placement="top-start" enterDelay={500}>
61
+ <Box
62
+ sx={{
63
+ bgcolor: isCategoryGroup ? alpha(color, 0.06) : undefined,
64
+ borderRadius: isCategoryGroup ? 1 : undefined,
65
+ px: isCategoryGroup ? 0.75 : 0,
66
+ overflow: "hidden",
67
+ textOverflow: "ellipsis",
68
+ whiteSpace: "nowrap",
69
+ flex: 1,
70
+ fontWeight: isGroup ? 700 : undefined,
71
+ }}
72
+ >
73
+ {label}
74
+ </Box>
75
+ </Tooltip>
76
+ </Box>
77
+ );
78
+ }
@@ -0,0 +1,52 @@
1
+ import { GridColDef } from "@mui/x-data-grid-premium";
2
+ import { PsychscreenTrackInfo } from "./types";
3
+
4
+ export const psychscreenCategoryColors: Record<string, string> = {
5
+ "Epigenetic Tracks": "#9479bc",
6
+ "Deep Learned Models": "#758c7b",
7
+ "Pseudo bulk ATAC": "#cd8c66",
8
+ "Evolutionary Conservation": "#c0a9e2",
9
+ "ATAC Seq Peaks": "#9479bc",
10
+ };
11
+
12
+ export function getPsychscreenCategoryColor(category: string) {
13
+ return psychscreenCategoryColors[category] ?? "#000000";
14
+ }
15
+
16
+ const titleCol: GridColDef<PsychscreenTrackInfo> = {
17
+ field: "title",
18
+ headerName: "Title",
19
+ flex: 1,
20
+ minWidth: 240,
21
+ };
22
+
23
+ const categoryCol: GridColDef<PsychscreenTrackInfo> = {
24
+ field: "category",
25
+ headerName: "Category",
26
+ flex: 1,
27
+ minWidth: 180,
28
+ };
29
+
30
+ const subcategoryCol: GridColDef<PsychscreenTrackInfo> = {
31
+ field: "subcategory",
32
+ headerName: "Subcategory",
33
+ flex: 1,
34
+ minWidth: 240,
35
+ };
36
+
37
+ const trackTypeCol: GridColDef<PsychscreenTrackInfo> = {
38
+ field: "trackType",
39
+ headerName: "Track Type",
40
+ width: 120,
41
+ };
42
+
43
+ export const defaultColumns: GridColDef<PsychscreenTrackInfo>[] = [
44
+ titleCol,
45
+ categoryCol,
46
+ subcategoryCol,
47
+ trackTypeCol,
48
+ ];
49
+
50
+ export const defaultGroupingModel = ["category", "subcategory"];
51
+
52
+ export const defaultLeafField = "title";
@@ -0,0 +1,45 @@
1
+ import { FolderDefinition } from "../../types";
2
+ import { PsychscreenDataFile, PsychscreenTrackInfo } from "./types";
3
+ import {
4
+ defaultColumns,
5
+ defaultGroupingModel,
6
+ defaultLeafField,
7
+ } from "./columns";
8
+ import { PsychscreenGroupingCell } from "./PsychscreenGroupingCell";
9
+ import { createPsychscreenTrack } from "./toTrack";
10
+
11
+ function transformData(
12
+ folderId: string,
13
+ data: PsychscreenDataFile,
14
+ ): PsychscreenTrackInfo[] {
15
+ return data.map((row) => ({
16
+ ...row,
17
+ sourceId: row.id,
18
+ id: `${folderId}/${row.id}`,
19
+ }));
20
+ }
21
+
22
+ export interface CreatePsychscreenFolderOptions {
23
+ id: string;
24
+ label: string;
25
+ description?: string;
26
+ data: PsychscreenDataFile;
27
+ }
28
+
29
+ export function createPsychscreenFolder(
30
+ options: CreatePsychscreenFolderOptions,
31
+ ): FolderDefinition<PsychscreenTrackInfo> {
32
+ const { id, label, description, data } = options;
33
+
34
+ return {
35
+ id,
36
+ label,
37
+ description,
38
+ rows: transformData(id, data),
39
+ columns: defaultColumns,
40
+ groupingModel: defaultGroupingModel,
41
+ leafField: defaultLeafField,
42
+ createTrack: createPsychscreenTrack,
43
+ GroupingCellComponent: PsychscreenGroupingCell,
44
+ };
45
+ }
@@ -0,0 +1,48 @@
1
+ import {
2
+ BigBedConfig,
3
+ BigWigConfig,
4
+ DisplayMode,
5
+ Track,
6
+ TrackType,
7
+ } from "@weng-lab/genomebrowser";
8
+ import { CreateTrackOptions } from "../../types";
9
+ import { PsychscreenTrackInfo } from "./types";
10
+
11
+ export type PsychscreenTrackContext = {};
12
+
13
+ const defaultBigWig: Omit<BigWigConfig, "id" | "title" | "url"> = {
14
+ trackType: TrackType.BigWig,
15
+ height: 50,
16
+ displayMode: DisplayMode.Full,
17
+ titleSize: 12,
18
+ };
19
+
20
+ const defaultBigBed: Omit<BigBedConfig, "id" | "title" | "url"> = {
21
+ trackType: TrackType.BigBed,
22
+ height: 30,
23
+ displayMode: DisplayMode.Dense,
24
+ titleSize: 12,
25
+ };
26
+
27
+ export function createPsychscreenTrack(
28
+ row: PsychscreenTrackInfo,
29
+ _options: CreateTrackOptions,
30
+ ): Track {
31
+ if (row.trackType === "bigbed") {
32
+ return {
33
+ ...defaultBigBed,
34
+ id: row.id,
35
+ title: row.title,
36
+ url: row.url,
37
+ color: row.color ?? "#000000",
38
+ };
39
+ }
40
+
41
+ return {
42
+ ...defaultBigWig,
43
+ id: row.id,
44
+ title: row.title,
45
+ url: row.url,
46
+ color: row.color ?? "#000000",
47
+ };
48
+ }
@@ -0,0 +1,14 @@
1
+ export type PsychscreenTrackType = "bigwig" | "bigbed";
2
+
3
+ export type PsychscreenTrackInfo = {
4
+ id: string;
5
+ sourceId?: string;
6
+ category: string;
7
+ subcategory: string;
8
+ title: string;
9
+ url: string;
10
+ trackType: PsychscreenTrackType;
11
+ color?: string;
12
+ };
13
+
14
+ export type PsychscreenDataFile = PsychscreenTrackInfo[];
@@ -155,10 +155,18 @@ export const CustomTreeItem = React.forwardRef(function CustomTreeItem(
155
155
  getLabelProps,
156
156
  getGroupTransitionProps,
157
157
  status,
158
- } = useTreeItem({ id, itemId, children, label, disabled, rootRef: ref });
158
+ } = useTreeItem({
159
+ id,
160
+ itemId,
161
+ children,
162
+ label,
163
+ disabled,
164
+ rootRef: ref as never,
165
+ });
159
166
 
160
167
  const item = useTreeItemModel<ExtendedTreeItemProps>(itemId)!;
161
168
  const icon = getIconFromTreeItemType(item.icon, renderIcon);
169
+ const rootProps = getRootProps(other) as React.ComponentPropsWithoutRef<"li">;
162
170
 
163
171
  const handleRemoveIconClick = (e: React.MouseEvent) => {
164
172
  e.stopPropagation();
@@ -167,7 +175,7 @@ export const CustomTreeItem = React.forwardRef(function CustomTreeItem(
167
175
 
168
176
  return (
169
177
  <TreeItemProvider {...getContextProviderProps()}>
170
- <TreeItemRoot {...getRootProps(other)}>
178
+ <TreeItemRoot {...rootProps}>
171
179
  <TreeItemContent {...getContentProps()}>
172
180
  <TreeItemIconContainer {...getIconContainerProps()}>
173
181
  <TreeItemIcon status={status} />
@@ -101,7 +101,10 @@ function FolderTree({
101
101
  <RichTreeView
102
102
  items={items}
103
103
  expandedItems={expandedItems}
104
- onExpandedItemsChange={(_event, ids) => setExpandedItems(ids)}
104
+ onExpandedItemsChange={(
105
+ _event: React.SyntheticEvent | null,
106
+ ids: string[],
107
+ ) => setExpandedItems(ids)}
105
108
  slots={{ item: TreeItem }}
106
109
  slotProps={{
107
110
  item: {
@@ -2,8 +2,10 @@ import type { BiosampleTrackContext } from "./Folders/biosamples/shared/toTrack"
2
2
  import type { GeneTrackContext } from "./Folders/genes/shared/toTrack";
3
3
  import type { MohdTrackContext } from "./Folders/mohd/shared/toTrack";
4
4
  import type { OtherTracksTrackContext } from "./Folders/other-tracks/shared/toTrack";
5
+ import type { PsychscreenTrackContext } from "./Folders/psychscreen/shared/toTrack";
5
6
 
6
7
  export type TrackSelectTrackContext = GeneTrackContext &
7
8
  BiosampleTrackContext &
8
9
  MohdTrackContext &
10
+ PsychscreenTrackContext &
9
11
  OtherTracksTrackContext;
@@ -50,7 +50,7 @@ export interface CustomLabelProps {
50
50
  export interface CustomTreeItemProps
51
51
  extends
52
52
  Omit<UseTreeItemParameters, "rootRef">,
53
- Omit<React.HTMLAttributes<HTMLLIElement>, "onFocus"> {
53
+ Omit<React.HTMLAttributes<HTMLLIElement>, "children" | "onFocus"> {
54
54
  onRemove?: (item: TreeViewBaseItem<ExtendedTreeItemProps>) => void;
55
55
  renderIcon?: (name: string) => ReactNode;
56
56
  }