@jbrowse/app-core 2.6.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 (107) hide show
  1. package/LICENSE +201 -0
  2. package/dist/Assemblies/SessionAssembliesMixin.d.ts +72 -0
  3. package/dist/Assemblies/SessionAssembliesMixin.js +44 -0
  4. package/dist/Assemblies/TemporaryAssembliesMixin.d.ts +22 -0
  5. package/dist/Assemblies/TemporaryAssembliesMixin.js +45 -0
  6. package/dist/Assemblies/index.d.ts +2 -0
  7. package/dist/Assemblies/index.js +18 -0
  8. package/dist/HistoryManagement/index.d.ts +30 -0
  9. package/dist/HistoryManagement/index.js +54 -0
  10. package/dist/JBrowseConfig/index.d.ts +158 -0
  11. package/dist/JBrowseConfig/index.js +155 -0
  12. package/dist/JBrowseModel/index.d.ts +144 -0
  13. package/dist/JBrowseModel/index.js +132 -0
  14. package/dist/RootMenu/index.d.ts +68 -0
  15. package/dist/RootMenu/index.js +142 -0
  16. package/dist/index.d.ts +6 -0
  17. package/dist/index.js +22 -0
  18. package/dist/ui/App/App.d.ts +19 -0
  19. package/dist/ui/App/App.js +95 -0
  20. package/dist/ui/App/AppFab.d.ts +6 -0
  21. package/dist/ui/App/AppFab.js +32 -0
  22. package/dist/ui/App/AppToolbar.d.ts +19 -0
  23. package/dist/ui/App/AppToolbar.js +54 -0
  24. package/dist/ui/App/DialogQueue.d.ts +6 -0
  25. package/dist/ui/App/DialogQueue.js +32 -0
  26. package/dist/ui/App/Drawer.d.ts +8 -0
  27. package/dist/ui/App/Drawer.js +34 -0
  28. package/dist/ui/App/DrawerWidget.d.ts +6 -0
  29. package/dist/ui/App/DrawerWidget.js +132 -0
  30. package/dist/ui/App/ViewContainer.d.ts +9 -0
  31. package/dist/ui/App/ViewContainer.js +76 -0
  32. package/dist/ui/App/ViewContainerTitle.d.ts +6 -0
  33. package/dist/ui/App/ViewContainerTitle.js +42 -0
  34. package/dist/ui/App/ViewLauncher.d.ts +18 -0
  35. package/dist/ui/App/ViewLauncher.js +50 -0
  36. package/dist/ui/App/ViewMenu.d.ts +9 -0
  37. package/dist/ui/App/ViewMenu.js +38 -0
  38. package/dist/ui/App/ViewPanel.d.ts +19 -0
  39. package/dist/ui/App/ViewPanel.js +50 -0
  40. package/dist/ui/App/index.d.ts +1 -0
  41. package/dist/ui/App/index.js +17 -0
  42. package/dist/ui/index.d.ts +1 -0
  43. package/dist/ui/index.js +17 -0
  44. package/esm/Assemblies/SessionAssembliesMixin.d.ts +72 -0
  45. package/esm/Assemblies/SessionAssembliesMixin.js +40 -0
  46. package/esm/Assemblies/TemporaryAssembliesMixin.d.ts +22 -0
  47. package/esm/Assemblies/TemporaryAssembliesMixin.js +41 -0
  48. package/esm/Assemblies/index.d.ts +2 -0
  49. package/esm/Assemblies/index.js +2 -0
  50. package/esm/HistoryManagement/index.d.ts +30 -0
  51. package/esm/HistoryManagement/index.js +47 -0
  52. package/esm/JBrowseConfig/index.d.ts +158 -0
  53. package/esm/JBrowseConfig/index.js +148 -0
  54. package/esm/JBrowseModel/index.d.ts +144 -0
  55. package/esm/JBrowseModel/index.js +128 -0
  56. package/esm/RootMenu/index.d.ts +68 -0
  57. package/esm/RootMenu/index.js +138 -0
  58. package/esm/index.d.ts +6 -0
  59. package/esm/index.js +6 -0
  60. package/esm/ui/App/App.d.ts +19 -0
  61. package/esm/ui/App/App.js +66 -0
  62. package/esm/ui/App/AppFab.d.ts +6 -0
  63. package/esm/ui/App/AppFab.js +27 -0
  64. package/esm/ui/App/AppToolbar.d.ts +19 -0
  65. package/esm/ui/App/AppToolbar.js +49 -0
  66. package/esm/ui/App/DialogQueue.d.ts +6 -0
  67. package/esm/ui/App/DialogQueue.js +7 -0
  68. package/esm/ui/App/Drawer.d.ts +8 -0
  69. package/esm/ui/App/Drawer.js +29 -0
  70. package/esm/ui/App/DrawerWidget.d.ts +6 -0
  71. package/esm/ui/App/DrawerWidget.js +104 -0
  72. package/esm/ui/App/ViewContainer.d.ts +9 -0
  73. package/esm/ui/App/ViewContainer.js +48 -0
  74. package/esm/ui/App/ViewContainerTitle.d.ts +6 -0
  75. package/esm/ui/App/ViewContainerTitle.js +37 -0
  76. package/esm/ui/App/ViewLauncher.d.ts +18 -0
  77. package/esm/ui/App/ViewLauncher.js +25 -0
  78. package/esm/ui/App/ViewMenu.d.ts +9 -0
  79. package/esm/ui/App/ViewMenu.js +33 -0
  80. package/esm/ui/App/ViewPanel.d.ts +19 -0
  81. package/esm/ui/App/ViewPanel.js +22 -0
  82. package/esm/ui/App/index.d.ts +1 -0
  83. package/esm/ui/App/index.js +1 -0
  84. package/esm/ui/index.d.ts +1 -0
  85. package/esm/ui/index.js +1 -0
  86. package/package.json +66 -0
  87. package/src/Assemblies/SessionAssembliesMixin.ts +50 -0
  88. package/src/Assemblies/TemporaryAssembliesMixin.ts +51 -0
  89. package/src/Assemblies/index.ts +2 -0
  90. package/src/HistoryManagement/index.ts +56 -0
  91. package/src/JBrowseConfig/index.ts +173 -0
  92. package/src/JBrowseModel/index.ts +150 -0
  93. package/src/RootMenu/index.ts +157 -0
  94. package/src/index.ts +6 -0
  95. package/src/ui/App/App.tsx +117 -0
  96. package/src/ui/App/AppFab.tsx +45 -0
  97. package/src/ui/App/AppToolbar.tsx +89 -0
  98. package/src/ui/App/DialogQueue.tsx +22 -0
  99. package/src/ui/App/Drawer.tsx +56 -0
  100. package/src/ui/App/DrawerWidget.tsx +238 -0
  101. package/src/ui/App/ViewContainer.tsx +76 -0
  102. package/src/ui/App/ViewContainerTitle.tsx +55 -0
  103. package/src/ui/App/ViewLauncher.tsx +64 -0
  104. package/src/ui/App/ViewMenu.tsx +54 -0
  105. package/src/ui/App/ViewPanel.tsx +63 -0
  106. package/src/ui/App/index.ts +1 -0
  107. package/src/ui/index.ts +1 -0
@@ -0,0 +1,66 @@
1
+ import React, { Suspense, lazy } from 'react';
2
+ import { AppBar } from '@mui/material';
3
+ import { makeStyles } from 'tss-react/mui';
4
+ import { observer } from 'mobx-react';
5
+ import Snackbar from '@jbrowse/core/ui/Snackbar';
6
+ // locals
7
+ import AppToolbar from './AppToolbar';
8
+ import ViewLauncher from './ViewLauncher';
9
+ import ViewPanel from './ViewPanel';
10
+ import DialogQueue from './DialogQueue';
11
+ import AppFab from './AppFab';
12
+ const DrawerWidget = lazy(() => import('./DrawerWidget'));
13
+ const useStyles = makeStyles()(theme => ({
14
+ root: {
15
+ display: 'grid',
16
+ height: '100vh',
17
+ width: '100%',
18
+ colorScheme: theme.palette.mode,
19
+ },
20
+ appContainer: {
21
+ gridColumn: 'main',
22
+ display: 'grid',
23
+ gridTemplateRows: '[menubar] min-content [components] auto',
24
+ height: '100vh',
25
+ },
26
+ viewContainer: {
27
+ overflowY: 'auto',
28
+ gridRow: 'components',
29
+ },
30
+ appBar: {
31
+ flexGrow: 1,
32
+ gridRow: 'menubar',
33
+ },
34
+ }));
35
+ const LazyDrawerWidget = observer(function (props) {
36
+ const { session } = props;
37
+ return (React.createElement(Suspense, { fallback: React.createElement(React.Fragment, null) },
38
+ React.createElement(DrawerWidget, { session: session })));
39
+ });
40
+ const ViewContainer = observer(function (props) {
41
+ const { session } = props;
42
+ const { views } = session;
43
+ const { classes } = useStyles();
44
+ return (React.createElement("div", { className: classes.viewContainer },
45
+ views.length > 0 ? (views.map(view => (React.createElement(ViewPanel, { key: `view-${view.id}`, view: view, session: session })))) : (React.createElement(ViewLauncher, { ...props })),
46
+ React.createElement("div", { style: { height: 300 } })));
47
+ });
48
+ const App = observer(function (props) {
49
+ const { session } = props;
50
+ const { classes } = useStyles();
51
+ const { minimized, visibleWidget, drawerWidth, drawerPosition } = session;
52
+ const drawerVisible = visibleWidget && !minimized;
53
+ const d = drawerVisible ? `[drawer] ${drawerWidth}px` : undefined;
54
+ const grid = drawerPosition === 'right' ? ['[main] 1fr', d] : [d, '[main] 1fr'];
55
+ return (React.createElement("div", { className: classes.root, style: { gridTemplateColumns: grid === null || grid === void 0 ? void 0 : grid.filter(f => !!f).join(' ') } },
56
+ drawerVisible && drawerPosition === 'left' ? (React.createElement(LazyDrawerWidget, { session: session })) : null,
57
+ React.createElement(DialogQueue, { session: session }),
58
+ React.createElement("div", { className: classes.appContainer },
59
+ React.createElement(AppBar, { className: classes.appBar, position: "static" },
60
+ React.createElement(AppToolbar, { ...props })),
61
+ React.createElement(ViewContainer, { ...props })),
62
+ React.createElement(AppFab, { session: session }),
63
+ drawerVisible && drawerPosition === 'right' ? (React.createElement(LazyDrawerWidget, { session: session })) : null,
64
+ React.createElement(Snackbar, { session: session })));
65
+ });
66
+ export { App };
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ import { SessionWithDrawerWidgets } from '@jbrowse/core/util';
3
+ declare const _default: ({ session, }: {
4
+ session: SessionWithDrawerWidgets;
5
+ }) => React.JSX.Element | null;
6
+ export default _default;
@@ -0,0 +1,27 @@
1
+ import React from 'react';
2
+ import { Fab, Tooltip } from '@mui/material';
3
+ import { makeStyles } from 'tss-react/mui';
4
+ import { observer } from 'mobx-react';
5
+ // icons
6
+ import LaunchIcon from '@mui/icons-material/Launch';
7
+ const useStyles = makeStyles()(theme => ({
8
+ left: {
9
+ zIndex: 10000,
10
+ position: 'fixed',
11
+ bottom: theme.spacing(2),
12
+ left: theme.spacing(2),
13
+ },
14
+ right: {
15
+ zIndex: 10000,
16
+ position: 'fixed',
17
+ bottom: theme.spacing(2),
18
+ right: theme.spacing(2),
19
+ },
20
+ }));
21
+ export default observer(function AppFab({ session, }) {
22
+ const { minimized, activeWidgets, drawerPosition } = session;
23
+ const { classes } = useStyles();
24
+ return activeWidgets.size > 0 && minimized ? (React.createElement(Tooltip, { title: "Open drawer widget" },
25
+ React.createElement(Fab, { className: drawerPosition === 'right' ? classes.right : classes.left, color: "primary", "data-testid": "drawer-maximize", onClick: () => session.showWidgetDrawer() },
26
+ React.createElement(LaunchIcon, null)))) : null;
27
+ });
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ import { SessionWithDrawerWidgets } from '@jbrowse/core/util';
3
+ import { MenuItem as JBMenuItem } from '@jbrowse/core/ui/Menu';
4
+ import { SnackbarMessage } from '@jbrowse/core/ui/SnackbarModel';
5
+ type AppSession = SessionWithDrawerWidgets & {
6
+ savedSessionNames: string[];
7
+ menus: {
8
+ label: string;
9
+ menuItems: JBMenuItem[];
10
+ }[];
11
+ renameCurrentSession: (arg: string) => void;
12
+ snackbarMessages: SnackbarMessage[];
13
+ popSnackbarMessage: () => unknown;
14
+ };
15
+ declare const AppToolbar: ({ session, HeaderButtons, }: {
16
+ HeaderButtons?: React.ReactElement<any, string | React.JSXElementConstructor<any>> | undefined;
17
+ session: AppSession;
18
+ }) => React.JSX.Element;
19
+ export default AppToolbar;
@@ -0,0 +1,49 @@
1
+ import React from 'react';
2
+ import { Toolbar, Tooltip } from '@mui/material';
3
+ import { makeStyles } from 'tss-react/mui';
4
+ import { observer } from 'mobx-react';
5
+ import DropDownMenu from '@jbrowse/core/ui/DropDownMenu';
6
+ import EditableTypography from '@jbrowse/core/ui/EditableTypography';
7
+ import AppLogo from '@jbrowse/core/ui/AppLogo';
8
+ const useStyles = makeStyles()(theme => ({
9
+ grow: {
10
+ flexGrow: 1,
11
+ },
12
+ inputBase: {
13
+ color: theme.palette.primary.contrastText,
14
+ },
15
+ inputRoot: {
16
+ '&:hover': {
17
+ backgroundColor: theme.palette.primary.light,
18
+ },
19
+ },
20
+ inputFocused: {
21
+ borderColor: theme.palette.secondary.main,
22
+ backgroundColor: theme.palette.primary.light,
23
+ },
24
+ }));
25
+ const AppToolbar = observer(function ({ session, HeaderButtons = React.createElement("div", null), }) {
26
+ const { classes } = useStyles();
27
+ const { savedSessionNames, name, menus } = session;
28
+ return (React.createElement(Toolbar, null,
29
+ menus.map(menu => (React.createElement(DropDownMenu, { key: menu.label, menuTitle: menu.label, menuItems: menu.menuItems, session: session }))),
30
+ React.createElement("div", { className: classes.grow }),
31
+ React.createElement(Tooltip, { title: "Rename Session", arrow: true },
32
+ React.createElement(EditableTypography, { value: name, setValue: newName => {
33
+ if (savedSessionNames === null || savedSessionNames === void 0 ? void 0 : savedSessionNames.includes(newName)) {
34
+ session.notify(`Cannot rename session to "${newName}", a saved session with that name already exists`, 'warning');
35
+ }
36
+ else {
37
+ session.renameCurrentSession(newName);
38
+ }
39
+ }, variant: "body1", classes: {
40
+ inputBase: classes.inputBase,
41
+ inputRoot: classes.inputRoot,
42
+ inputFocused: classes.inputFocused,
43
+ } })),
44
+ HeaderButtons,
45
+ React.createElement("div", { className: classes.grow }),
46
+ React.createElement("div", { style: { width: 150, maxHeight: 48 } },
47
+ React.createElement(AppLogo, { session: session }))));
48
+ });
49
+ export default AppToolbar;
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ import { SessionWithDrawerWidgets } from '@jbrowse/core/util';
3
+ declare const _default: ({ session, }: {
4
+ session: SessionWithDrawerWidgets;
5
+ }) => React.JSX.Element;
6
+ export default _default;
@@ -0,0 +1,7 @@
1
+ import React, { Suspense } from 'react';
2
+ import { observer } from 'mobx-react';
3
+ export default observer(function ({ session, }) {
4
+ const { DialogComponent, DialogProps } = session;
5
+ return (React.createElement(React.Fragment, null, DialogComponent ? (React.createElement(Suspense, { fallback: React.createElement(React.Fragment, null) },
6
+ React.createElement(DialogComponent, { ...DialogProps }))) : null));
7
+ });
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import { SessionWithDrawerWidgets } from '@jbrowse/core/util/types';
3
+ declare function Drawer({ children, session, }: {
4
+ children: React.ReactNode;
5
+ session: SessionWithDrawerWidgets;
6
+ }): React.JSX.Element;
7
+ declare const _default: typeof Drawer;
8
+ export default _default;
@@ -0,0 +1,29 @@
1
+ import React from 'react';
2
+ import { Paper } from '@mui/material';
3
+ import { makeStyles } from 'tss-react/mui';
4
+ import { observer } from 'mobx-react';
5
+ import ResizeHandle from '@jbrowse/core/ui/ResizeHandle';
6
+ const useStyles = makeStyles()(theme => ({
7
+ paper: {
8
+ overflowY: 'auto',
9
+ height: '100%',
10
+ zIndex: theme.zIndex.drawer,
11
+ outline: 'none',
12
+ background: theme.palette.background.default,
13
+ },
14
+ resizeHandle: {
15
+ width: 4,
16
+ position: 'fixed',
17
+ top: 0,
18
+ zIndex: theme.zIndex.drawer + 1,
19
+ },
20
+ }));
21
+ function Drawer({ children, session, }) {
22
+ const { drawerPosition, drawerWidth } = session;
23
+ const { classes } = useStyles();
24
+ return (React.createElement(Paper, { className: classes.paper, elevation: 16, square: true },
25
+ drawerPosition === 'right' ? (React.createElement(ResizeHandle, { onDrag: session.resizeDrawer, className: classes.resizeHandle, vertical: true })) : null,
26
+ children,
27
+ drawerPosition === 'left' ? (React.createElement(ResizeHandle, { onDrag: session.resizeDrawer, className: classes.resizeHandle, style: { left: drawerWidth }, vertical: true })) : null));
28
+ }
29
+ export default observer(Drawer);
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ import { SessionWithDrawerWidgets } from '@jbrowse/core/util/types';
3
+ declare const DrawerWidget: ({ session, }: {
4
+ session: SessionWithDrawerWidgets;
5
+ }) => React.JSX.Element;
6
+ export default DrawerWidget;
@@ -0,0 +1,104 @@
1
+ import React, { Suspense, useState } from 'react';
2
+ import { ErrorBoundary } from 'react-error-boundary';
3
+ import { AppBar, FormControl, IconButton, Menu, MenuItem, Select, Toolbar, Tooltip, Typography, } from '@mui/material';
4
+ import { makeStyles } from 'tss-react/mui';
5
+ import { observer } from 'mobx-react';
6
+ import { getEnv } from '@jbrowse/core/util';
7
+ import LoadingEllipses from '@jbrowse/core/ui/LoadingEllipses';
8
+ import ErrorMessage from '@jbrowse/core/ui/ErrorMessage';
9
+ // icons
10
+ import DeleteIcon from '@mui/icons-material/Delete';
11
+ import CloseIcon from '@mui/icons-material/Close';
12
+ import MinimizeIcon from '@mui/icons-material/Minimize';
13
+ import MoreVertIcon from '@mui/icons-material/MoreVert';
14
+ // locals
15
+ import Drawer from './Drawer';
16
+ const useStyles = makeStyles()(theme => ({
17
+ formControl: {
18
+ margin: 0,
19
+ },
20
+ spacer: {
21
+ flexGrow: 1,
22
+ },
23
+ drawerSelect: {
24
+ margin: 0,
25
+ color: theme.palette.secondary.contrastText,
26
+ },
27
+ dropDownIcon: {
28
+ color: theme.palette.secondary.contrastText,
29
+ },
30
+ header: {
31
+ background: theme.palette.secondary.main,
32
+ },
33
+ }));
34
+ const DrawerHeader = observer(function ({ session, setToolbarHeight, }) {
35
+ const { pluginManager } = getEnv(session);
36
+ const { visibleWidget, activeWidgets, drawerPosition } = session;
37
+ const { classes } = useStyles();
38
+ const [anchorEl, setAnchorEl] = useState(null);
39
+ return (React.createElement(AppBar, { position: "sticky", className: classes.header, ref: ref => setToolbarHeight((ref === null || ref === void 0 ? void 0 : ref.getBoundingClientRect().height) || 0) },
40
+ React.createElement(Toolbar, { disableGutters: true },
41
+ React.createElement(FormControl, { className: classes.formControl },
42
+ React.createElement(Select, { value: visibleWidget === null || visibleWidget === void 0 ? void 0 : visibleWidget.id, "data-testid": "widget-drawer-selects", className: classes.drawerSelect, classes: { icon: classes.dropDownIcon }, renderValue: widgetId => {
43
+ const widget = session.activeWidgets.get(widgetId);
44
+ if (!widget) {
45
+ return (React.createElement(Typography, { variant: "h6", color: "inherit" }, "Unknown widget"));
46
+ }
47
+ const widgetType = pluginManager.getWidgetType(widget.type);
48
+ const { HeadingComponent, heading } = widgetType;
49
+ return HeadingComponent ? (React.createElement(HeadingComponent, { model: widget })) : (React.createElement(Typography, { variant: "h6", color: "inherit" }, heading));
50
+ }, onChange: e => {
51
+ const w = session.activeWidgets.get(e.target.value);
52
+ if (w) {
53
+ session.showWidget(w);
54
+ }
55
+ else {
56
+ session.notify(`Widget not found ${e.target.value}`, 'warning');
57
+ }
58
+ } }, [...activeWidgets.values()].map(widget => {
59
+ const widgetType = pluginManager.getWidgetType(widget.type);
60
+ const { HeadingComponent, heading } = widgetType;
61
+ return (React.createElement(MenuItem, { "data-testid": `widget-drawer-selects-item-${widget.type}`, key: widget.id, value: widget.id },
62
+ HeadingComponent ? (React.createElement(HeadingComponent, { model: widget })) : (React.createElement(Typography, { variant: "h6", color: "inherit" }, heading)),
63
+ React.createElement(IconButton, { "data-testid": `${widget.type}-drawer-delete`, color: "inherit", "aria-label": "Delete", onClick: () => session.hideWidget(widget) },
64
+ React.createElement(DeleteIcon, null))));
65
+ }))),
66
+ React.createElement("div", { className: classes.spacer }),
67
+ React.createElement("div", null,
68
+ React.createElement(IconButton, { "data-testid": "drawer-close", color: "inherit", onClick: event => setAnchorEl(event.currentTarget) },
69
+ React.createElement(MoreVertIcon, null)),
70
+ React.createElement(Tooltip, { title: "Minimize drawer" },
71
+ React.createElement(IconButton, { "data-testid": "drawer-minimize", color: "inherit", onClick: () => {
72
+ session.notify(`Drawer minimized, click button on ${drawerPosition} side of screen to re-open`, 'info');
73
+ session.minimizeWidgetDrawer();
74
+ } },
75
+ React.createElement(MinimizeIcon, null))),
76
+ React.createElement(Tooltip, { title: "Close drawer" },
77
+ React.createElement(IconButton, { "data-testid": "drawer-close", color: "inherit", onClick: () => session.hideWidget(visibleWidget) },
78
+ React.createElement(CloseIcon, null))))),
79
+ React.createElement(Menu, { anchorEl: anchorEl, open: Boolean(anchorEl), onClose: () => setAnchorEl(null) }, ['left', 'right'].map(option => (React.createElement(MenuItem, { key: option, selected: drawerPosition === 'option', onClick: () => {
80
+ session.setDrawerPosition(option);
81
+ setAnchorEl(null);
82
+ } }, option))))));
83
+ });
84
+ const DrawerWidget = observer(function ({ session, }) {
85
+ const { visibleWidget } = session;
86
+ const { pluginManager } = getEnv(session);
87
+ const DrawerComponent = visibleWidget
88
+ ? pluginManager.evaluateExtensionPoint('Core-replaceWidget', pluginManager.getWidgetType(visibleWidget.type).ReactComponent, {
89
+ session,
90
+ model: visibleWidget,
91
+ })
92
+ : null;
93
+ // we track the toolbar height because components that use virtualized
94
+ // height want to be able to fill the contained, minus the toolbar height
95
+ // (the position static/sticky is included in AutoSizer estimates)
96
+ const [toolbarHeight, setToolbarHeight] = useState(0);
97
+ return (React.createElement(Drawer, { session: session },
98
+ React.createElement(DrawerHeader, { session: session, setToolbarHeight: setToolbarHeight }),
99
+ React.createElement(Suspense, { fallback: React.createElement(LoadingEllipses, null) },
100
+ React.createElement(ErrorBoundary, { FallbackComponent: ({ error }) => React.createElement(ErrorMessage, { error: error }) }, DrawerComponent ? (React.createElement(React.Fragment, null,
101
+ React.createElement(DrawerComponent, { model: visibleWidget, session: session, toolbarHeight: toolbarHeight }),
102
+ React.createElement("div", { style: { height: 300 } }))) : null))));
103
+ });
104
+ export default DrawerWidget;
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { IBaseViewModel } from '@jbrowse/core/pluggableElementTypes/models';
3
+ declare const _default: ({ view, onClose, onMinimize, children, }: {
4
+ view: IBaseViewModel;
5
+ onClose: () => void;
6
+ onMinimize: () => void;
7
+ children: React.ReactNode;
8
+ }) => React.JSX.Element;
9
+ export default _default;
@@ -0,0 +1,48 @@
1
+ import React, { useEffect, useRef } from 'react';
2
+ import { IconButton, Paper, useTheme } from '@mui/material';
3
+ import { makeStyles } from 'tss-react/mui';
4
+ import { observer } from 'mobx-react';
5
+ import { useWidthSetter } from '@jbrowse/core/util';
6
+ // icons
7
+ import CloseIcon from '@mui/icons-material/Close';
8
+ import MinimizeIcon from '@mui/icons-material/Minimize';
9
+ import AddIcon from '@mui/icons-material/Add';
10
+ // locals
11
+ import ViewMenu from './ViewMenu';
12
+ import ViewContainerTitle from './ViewContainerTitle';
13
+ const useStyles = makeStyles()(theme => ({
14
+ viewContainer: {
15
+ overflow: 'hidden',
16
+ background: theme.palette.secondary.main,
17
+ margin: theme.spacing(0.5),
18
+ padding: `0 ${theme.spacing(1)} ${theme.spacing(1)}`,
19
+ },
20
+ icon: {
21
+ color: theme.palette.secondary.contrastText,
22
+ },
23
+ grow: {
24
+ flexGrow: 1,
25
+ },
26
+ }));
27
+ export default observer(function ({ view, onClose, onMinimize, children, }) {
28
+ const { classes } = useStyles();
29
+ const theme = useTheme();
30
+ const ref = useWidthSetter(view, theme.spacing(1));
31
+ const scrollRef = useRef(null);
32
+ // scroll the view into view when first mounted. note: this effect will run
33
+ // only once, because of the empty array second param
34
+ useEffect(() => {
35
+ var _a, _b;
36
+ (_b = (_a = scrollRef.current) === null || _a === void 0 ? void 0 : _a.scrollIntoView) === null || _b === void 0 ? void 0 : _b.call(_a, { block: 'center' });
37
+ }, []);
38
+ return (React.createElement(Paper, { ref: ref, elevation: 12, className: classes.viewContainer },
39
+ React.createElement("div", { ref: scrollRef, style: { display: 'flex' } },
40
+ React.createElement(ViewMenu, { model: view, IconProps: { className: classes.icon } }),
41
+ React.createElement("div", { className: classes.grow }),
42
+ React.createElement(ViewContainerTitle, { view: view }),
43
+ React.createElement("div", { className: classes.grow }),
44
+ React.createElement(IconButton, { "data-testid": "minimize_view", onClick: onMinimize }, view.minimized ? (React.createElement(AddIcon, { className: classes.icon, fontSize: "small" })) : (React.createElement(MinimizeIcon, { className: classes.icon, fontSize: "small" }))),
45
+ React.createElement(IconButton, { "data-testid": "close_view", onClick: onClose },
46
+ React.createElement(CloseIcon, { className: classes.icon, fontSize: "small" }))),
47
+ React.createElement(Paper, null, children)));
48
+ });
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ import { IBaseViewModel } from '@jbrowse/core/pluggableElementTypes';
3
+ declare const _default: ({ view, }: {
4
+ view: IBaseViewModel;
5
+ }) => React.JSX.Element;
6
+ export default _default;
@@ -0,0 +1,37 @@
1
+ import React from 'react';
2
+ import { Tooltip } from '@mui/material';
3
+ import { makeStyles } from 'tss-react/mui';
4
+ import { observer } from 'mobx-react';
5
+ // locals
6
+ import EditableTypography from '@jbrowse/core/ui/EditableTypography';
7
+ const useStyles = makeStyles()(theme => ({
8
+ input: {
9
+ paddingBottom: 0,
10
+ paddingTop: 2,
11
+ },
12
+ inputBase: {
13
+ color: theme.palette.secondary.contrastText,
14
+ },
15
+ inputRoot: {
16
+ '&:hover': {
17
+ backgroundColor: theme.palette.secondary.light,
18
+ },
19
+ },
20
+ inputFocused: {
21
+ borderColor: theme.palette.primary.main,
22
+ backgroundColor: theme.palette.secondary.light,
23
+ },
24
+ }));
25
+ export default observer(function ViewContainerTitle({ view, }) {
26
+ var _a;
27
+ const { classes } = useStyles();
28
+ return (React.createElement(Tooltip, { title: "Rename view", arrow: true },
29
+ React.createElement(EditableTypography, { value: view.displayName ||
30
+ // @ts-expect-error
31
+ `${((_a = view.assemblyNames) === null || _a === void 0 ? void 0 : _a.join(',')) || 'Untitled view'}${view.minimized ? ' (minimized)' : ''}`, setValue: val => view.setDisplayName(val), variant: "body2", classes: {
32
+ input: classes.input,
33
+ inputBase: classes.inputBase,
34
+ inputRoot: classes.inputRoot,
35
+ inputFocused: classes.inputFocused,
36
+ } })));
37
+ });
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+ import { SessionWithDrawerWidgets } from '@jbrowse/core/util';
3
+ import { MenuItem as JBMenuItem } from '@jbrowse/core/ui/Menu';
4
+ import { SnackbarMessage } from '@jbrowse/core/ui/SnackbarModel';
5
+ type AppSession = SessionWithDrawerWidgets & {
6
+ savedSessionNames: string[];
7
+ menus: {
8
+ label: string;
9
+ menuItems: JBMenuItem[];
10
+ }[];
11
+ renameCurrentSession: (arg: string) => void;
12
+ snackbarMessages: SnackbarMessage[];
13
+ popSnackbarMessage: () => unknown;
14
+ };
15
+ declare const ViewLauncher: ({ session }: {
16
+ session: AppSession;
17
+ }) => React.JSX.Element;
18
+ export default ViewLauncher;
@@ -0,0 +1,25 @@
1
+ import React, { useState } from 'react';
2
+ import { Button, FormControl, MenuItem, Paper, Select, Typography, } from '@mui/material';
3
+ import { observer } from 'mobx-react';
4
+ import { makeStyles } from 'tss-react/mui';
5
+ // locals
6
+ import { getEnv } from '@jbrowse/core/util';
7
+ const useStyles = makeStyles()(theme => ({
8
+ selectPaper: {
9
+ padding: theme.spacing(4),
10
+ },
11
+ }));
12
+ const ViewLauncher = observer(({ session }) => {
13
+ var _a;
14
+ const { classes } = useStyles();
15
+ const { pluginManager } = getEnv(session);
16
+ const viewTypes = pluginManager.getElementTypeRecord('view').all();
17
+ const [value, setValue] = useState((_a = viewTypes[0]) === null || _a === void 0 ? void 0 : _a.name);
18
+ return (React.createElement(Paper, { className: classes.selectPaper },
19
+ React.createElement(Typography, null, "Select a view to launch"),
20
+ React.createElement(FormControl, { style: { margin: 2 } },
21
+ React.createElement(Select, { value: value, onChange: event => setValue(event.target.value) }, viewTypes.map(({ displayName, name }) => (React.createElement(MenuItem, { key: name, value: name }, displayName))))),
22
+ React.createElement(FormControl, { style: { margin: 2 } },
23
+ React.createElement(Button, { onClick: () => session.addView(value, {}), variant: "contained", color: "primary" }, "Launch view"))));
24
+ });
25
+ export default ViewLauncher;
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { SvgIconProps, IconButtonProps as IconButtonPropsType } from '@mui/material';
3
+ import { IBaseViewModel } from '@jbrowse/core/pluggableElementTypes/models';
4
+ declare const ViewMenu: ({ model, IconButtonProps, IconProps, }: {
5
+ model: IBaseViewModel;
6
+ IconButtonProps?: IconButtonPropsType | undefined;
7
+ IconProps: SvgIconProps;
8
+ }) => React.JSX.Element | null;
9
+ export default ViewMenu;
@@ -0,0 +1,33 @@
1
+ import React from 'react';
2
+ import { observer } from 'mobx-react';
3
+ import { getSession } from '@jbrowse/core/util';
4
+ import CascadingMenuButton from '@jbrowse/core/ui/CascadingMenuButton';
5
+ // icons
6
+ import MenuIcon from '@mui/icons-material/Menu';
7
+ import ArrowDownward from '@mui/icons-material/ArrowDownward';
8
+ import ArrowUpward from '@mui/icons-material/ArrowUpward';
9
+ const ViewMenu = observer(function ({ model, IconButtonProps, IconProps, }) {
10
+ const { menuItems } = model;
11
+ const session = getSession(model);
12
+ const items = [
13
+ ...(session.views.length > 1
14
+ ? [
15
+ {
16
+ label: 'Move view up',
17
+ icon: ArrowUpward,
18
+ onClick: () => session.moveViewUp(model.id),
19
+ },
20
+ {
21
+ label: 'Move view down',
22
+ icon: ArrowDownward,
23
+ onClick: () => session.moveViewDown(model.id),
24
+ },
25
+ ]
26
+ : []),
27
+ // <=1.3.3 didn't use a function, so check as value also
28
+ ...((typeof menuItems === 'function' ? menuItems() : menuItems) || []),
29
+ ];
30
+ return items.length ? (React.createElement(CascadingMenuButton, { menuItems: items, "data-testid": "view_menu_icon" },
31
+ React.createElement(MenuIcon, { ...IconProps, fontSize: "small" }))) : null;
32
+ });
33
+ export default ViewMenu;
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ import { AbstractViewModel, SessionWithDrawerWidgets } from '@jbrowse/core/util';
3
+ import { SnackbarMessage } from '@jbrowse/core/ui/SnackbarModel';
4
+ import { MenuItem as JBMenuItem } from '@jbrowse/core/ui/Menu';
5
+ type AppSession = SessionWithDrawerWidgets & {
6
+ savedSessionNames: string[];
7
+ menus: {
8
+ label: string;
9
+ menuItems: JBMenuItem[];
10
+ }[];
11
+ snackbarMessages: SnackbarMessage[];
12
+ renameCurrentSession: (arg: string) => void;
13
+ popSnackbarMessage: () => unknown;
14
+ };
15
+ declare const ViewPanel: ({ view, session, }: {
16
+ view: AbstractViewModel;
17
+ session: AppSession;
18
+ }) => React.JSX.Element;
19
+ export default ViewPanel;
@@ -0,0 +1,22 @@
1
+ import React, { Suspense } from 'react';
2
+ import { ErrorBoundary } from 'react-error-boundary';
3
+ import { observer } from 'mobx-react';
4
+ // locals
5
+ import { getEnv, } from '@jbrowse/core/util';
6
+ // ui elements
7
+ import ErrorMessage from '@jbrowse/core/ui/ErrorMessage';
8
+ import LoadingEllipses from '@jbrowse/core/ui/LoadingEllipses';
9
+ // locals
10
+ import ViewContainer from './ViewContainer';
11
+ const ViewPanel = observer(function ({ view, session, }) {
12
+ const { pluginManager } = getEnv(session);
13
+ const viewType = pluginManager.getViewType(view.type);
14
+ if (!viewType) {
15
+ throw new Error(`unknown view type ${view.type}`);
16
+ }
17
+ const { ReactComponent } = viewType;
18
+ return (React.createElement(ViewContainer, { view: view, onClose: () => session.removeView(view), onMinimize: () => view.setMinimized(!view.minimized) }, !view.minimized ? (React.createElement(ErrorBoundary, { FallbackComponent: ({ error }) => React.createElement(ErrorMessage, { error: error }) },
19
+ React.createElement(Suspense, { fallback: React.createElement(LoadingEllipses, { variant: "h6" }) },
20
+ React.createElement(ReactComponent, { model: view, session: session })))) : (false)));
21
+ });
22
+ export default ViewPanel;
@@ -0,0 +1 @@
1
+ export * from './App';
@@ -0,0 +1 @@
1
+ export * from './App';
@@ -0,0 +1 @@
1
+ export * from './App';
@@ -0,0 +1 @@
1
+ export * from './App';