@jbrowse/app-core 2.13.1 → 2.15.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.
- package/dist/Assemblies/SessionAssembliesMixin.d.ts +2 -2
- package/dist/JBrowseConfig/index.js +1 -1
- package/dist/JBrowseModel/index.d.ts +2 -2
- package/dist/JBrowseModel/index.js +7 -7
- package/dist/ui/App/App.js +3 -16
- package/dist/ui/App/AppFab.js +3 -1
- package/dist/ui/App/AppToolbar.d.ts +2 -2
- package/dist/ui/App/Drawer.js +2 -2
- package/dist/ui/App/DrawerControls.js +9 -3
- package/dist/ui/App/DrawerHeader.js +6 -2
- package/dist/ui/App/DrawerWidget.js +6 -2
- package/dist/ui/App/DrawerWidgetSelector.js +3 -1
- package/dist/ui/App/ModalWidget.js +4 -6
- package/dist/ui/App/ViewContainer.js +1 -1
- package/dist/ui/App/ViewContainerTitle.js +3 -1
- package/dist/ui/App/ViewHeader.js +4 -2
- package/dist/ui/App/ViewLauncher.js +9 -4
- package/dist/ui/App/ViewMenu.js +18 -11
- package/dist/ui/App/ViewPanel.js +5 -1
- package/dist/ui/App/ViewsContainer.d.ts +19 -0
- package/dist/ui/App/ViewsContainer.js +26 -0
- package/esm/Assemblies/SessionAssembliesMixin.d.ts +2 -2
- package/esm/JBrowseConfig/index.js +1 -1
- package/esm/JBrowseModel/index.d.ts +2 -2
- package/esm/JBrowseModel/index.js +7 -7
- package/esm/ui/App/App.js +3 -16
- package/esm/ui/App/AppFab.js +3 -1
- package/esm/ui/App/AppToolbar.d.ts +2 -2
- package/esm/ui/App/Drawer.js +2 -2
- package/esm/ui/App/DrawerControls.js +9 -3
- package/esm/ui/App/DrawerHeader.js +6 -2
- package/esm/ui/App/DrawerWidget.js +6 -2
- package/esm/ui/App/DrawerWidgetSelector.js +3 -1
- package/esm/ui/App/ModalWidget.js +4 -6
- package/esm/ui/App/ViewContainer.js +1 -1
- package/esm/ui/App/ViewContainerTitle.js +3 -1
- package/esm/ui/App/ViewHeader.js +4 -2
- package/esm/ui/App/ViewLauncher.js +9 -4
- package/esm/ui/App/ViewMenu.js +18 -11
- package/esm/ui/App/ViewPanel.js +5 -1
- package/esm/ui/App/ViewsContainer.d.ts +19 -0
- package/esm/ui/App/ViewsContainer.js +21 -0
- package/package.json +6 -6
|
@@ -37,7 +37,7 @@ export declare function SessionAssembliesMixin(pluginManager: PluginManager, ass
|
|
|
37
37
|
/**
|
|
38
38
|
* #action
|
|
39
39
|
*/
|
|
40
|
-
addSessionAssembly(conf: AnyConfiguration): {
|
|
40
|
+
addSessionAssembly(conf: AnyConfiguration): ({
|
|
41
41
|
[x: string]: any;
|
|
42
42
|
} & import("mobx-state-tree/dist/internal").NonEmptyObject & {
|
|
43
43
|
setSubschema(slotName: string, data: Record<string, unknown>): Record<string, unknown> | ({
|
|
@@ -70,7 +70,7 @@ export declare function SessionAssembliesMixin(pluginManager: PluginManager, ass
|
|
|
70
70
|
defaultValue: string;
|
|
71
71
|
description: string;
|
|
72
72
|
};
|
|
73
|
-
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "name"
|
|
73
|
+
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "name">>>) | undefined;
|
|
74
74
|
/**
|
|
75
75
|
* #action
|
|
76
76
|
*/
|
|
@@ -137,7 +137,7 @@ export declare function JBrowseModelF({ pluginManager, assemblyConfigSchema, }:
|
|
|
137
137
|
/**
|
|
138
138
|
* #action
|
|
139
139
|
*/
|
|
140
|
-
addAssemblyConf(conf: AnyConfigurationModel): {
|
|
140
|
+
addAssemblyConf(conf: AnyConfigurationModel): ({
|
|
141
141
|
[x: string]: any;
|
|
142
142
|
} & import("mobx-state-tree/dist/internal").NonEmptyObject & {
|
|
143
143
|
setSubschema(slotName: string, data: Record<string, unknown>): Record<string, unknown> | ({
|
|
@@ -147,7 +147,7 @@ export declare function JBrowseModelF({ pluginManager, assemblyConfigSchema, }:
|
|
|
147
147
|
[x: string]: any;
|
|
148
148
|
} & import("mobx-state-tree/dist/internal").NonEmptyObject & any & import("mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>);
|
|
149
149
|
} & import("mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>);
|
|
150
|
-
} & import("mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType
|
|
150
|
+
} & import("mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>) | undefined;
|
|
151
151
|
/**
|
|
152
152
|
* #action
|
|
153
153
|
*/
|
|
@@ -30,7 +30,6 @@ function JBrowseModelF({ pluginManager, assemblyConfigSchema, }) {
|
|
|
30
30
|
* #getter
|
|
31
31
|
*/
|
|
32
32
|
get rpcManager() {
|
|
33
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
34
33
|
return (0, mobx_state_tree_1.getParent)(self).rpcManager;
|
|
35
34
|
},
|
|
36
35
|
}))
|
|
@@ -106,7 +105,6 @@ function JBrowseModelF({ pluginManager, assemblyConfigSchema, }) {
|
|
|
106
105
|
*/
|
|
107
106
|
addPlugin(pluginDefinition) {
|
|
108
107
|
self.plugins.push(pluginDefinition);
|
|
109
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
110
108
|
const rootModel = (0, mobx_state_tree_1.getParent)(self);
|
|
111
109
|
rootModel.setPluginsUpdated(true);
|
|
112
110
|
},
|
|
@@ -114,20 +112,22 @@ function JBrowseModelF({ pluginManager, assemblyConfigSchema, }) {
|
|
|
114
112
|
* #action
|
|
115
113
|
*/
|
|
116
114
|
removePlugin(pluginDefinition) {
|
|
117
|
-
self.plugins = (0, mobx_state_tree_1.cast)(self.plugins.filter(plugin =>
|
|
115
|
+
self.plugins = (0, mobx_state_tree_1.cast)(self.plugins.filter(plugin =>
|
|
116
|
+
// @ts-expect-error
|
|
117
|
+
plugin.url !== pluginDefinition.url ||
|
|
118
|
+
// @ts-expect-error
|
|
118
119
|
plugin.umdUrl !== pluginDefinition.umdUrl ||
|
|
120
|
+
// @ts-expect-error
|
|
119
121
|
plugin.cjsUrl !== pluginDefinition.cjsUrl ||
|
|
122
|
+
// @ts-expect-error
|
|
120
123
|
plugin.esmUrl !== pluginDefinition.esmUrl));
|
|
121
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
122
124
|
(0, mobx_state_tree_1.getParent)(self).setPluginsUpdated(true);
|
|
123
125
|
},
|
|
124
126
|
/**
|
|
125
127
|
* #action
|
|
126
128
|
*/
|
|
127
129
|
setDefaultSessionConf(sessionConf) {
|
|
128
|
-
const newDefault =
|
|
129
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
130
|
-
(0, mobx_state_tree_1.getParent)(self).session.name === sessionConf.name
|
|
130
|
+
const newDefault = (0, mobx_state_tree_1.getParent)(self).session.name === sessionConf.name
|
|
131
131
|
? (0, mobx_state_tree_1.getSnapshot)(sessionConf)
|
|
132
132
|
: (0, mobx_1.toJS)(sessionConf);
|
|
133
133
|
if (!newDefault.name) {
|
package/dist/ui/App/App.js
CHANGED
|
@@ -34,10 +34,9 @@ const mobx_react_1 = require("mobx-react");
|
|
|
34
34
|
const Snackbar_1 = __importDefault(require("@jbrowse/core/ui/Snackbar"));
|
|
35
35
|
// locals
|
|
36
36
|
const AppToolbar_1 = __importDefault(require("./AppToolbar"));
|
|
37
|
-
const ViewLauncher_1 = __importDefault(require("./ViewLauncher"));
|
|
38
|
-
const ViewPanel_1 = __importDefault(require("./ViewPanel"));
|
|
39
37
|
const DialogQueue_1 = __importDefault(require("./DialogQueue"));
|
|
40
38
|
const AppFab_1 = __importDefault(require("./AppFab"));
|
|
39
|
+
const ViewsContainer_1 = __importDefault(require("./ViewsContainer"));
|
|
41
40
|
const DrawerWidget = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./DrawerWidget'))));
|
|
42
41
|
const useStyles = (0, mui_1.makeStyles)()(theme => ({
|
|
43
42
|
root: {
|
|
@@ -52,10 +51,6 @@ const useStyles = (0, mui_1.makeStyles)()(theme => ({
|
|
|
52
51
|
gridTemplateRows: '[menubar] min-content [components] auto',
|
|
53
52
|
height: '100vh',
|
|
54
53
|
},
|
|
55
|
-
viewContainer: {
|
|
56
|
-
overflowY: 'auto',
|
|
57
|
-
gridRow: 'components',
|
|
58
|
-
},
|
|
59
54
|
appBar: {
|
|
60
55
|
flexGrow: 1,
|
|
61
56
|
gridRow: 'menubar',
|
|
@@ -66,14 +61,6 @@ const LazyDrawerWidget = (0, mobx_react_1.observer)(function (props) {
|
|
|
66
61
|
return (react_1.default.createElement(react_1.Suspense, { fallback: null },
|
|
67
62
|
react_1.default.createElement(DrawerWidget, { session: session })));
|
|
68
63
|
});
|
|
69
|
-
const ViewContainer = (0, mobx_react_1.observer)(function (props) {
|
|
70
|
-
const { session } = props;
|
|
71
|
-
const { views } = session;
|
|
72
|
-
const { classes } = useStyles();
|
|
73
|
-
return (react_1.default.createElement("div", { className: classes.viewContainer },
|
|
74
|
-
views.length > 0 ? (views.map(view => (react_1.default.createElement(ViewPanel_1.default, { key: `view-${view.id}`, view: view, session: session })))) : (react_1.default.createElement(ViewLauncher_1.default, { ...props })),
|
|
75
|
-
react_1.default.createElement("div", { style: { height: 300 } })));
|
|
76
|
-
});
|
|
77
64
|
const App = (0, mobx_react_1.observer)(function (props) {
|
|
78
65
|
const { session } = props;
|
|
79
66
|
const { classes } = useStyles();
|
|
@@ -81,13 +68,13 @@ const App = (0, mobx_react_1.observer)(function (props) {
|
|
|
81
68
|
const drawerVisible = visibleWidget && !minimized;
|
|
82
69
|
const d = drawerVisible ? `[drawer] ${drawerWidth}px` : undefined;
|
|
83
70
|
const grid = drawerPosition === 'right' ? ['[main] 1fr', d] : [d, '[main] 1fr'];
|
|
84
|
-
return (react_1.default.createElement("div", { className: classes.root, style: { gridTemplateColumns: grid
|
|
71
|
+
return (react_1.default.createElement("div", { className: classes.root, style: { gridTemplateColumns: grid.filter(f => !!f).join(' ') } },
|
|
85
72
|
drawerVisible && drawerPosition === 'left' ? (react_1.default.createElement(LazyDrawerWidget, { session: session })) : null,
|
|
86
73
|
react_1.default.createElement(DialogQueue_1.default, { session: session }),
|
|
87
74
|
react_1.default.createElement("div", { className: classes.appContainer },
|
|
88
75
|
react_1.default.createElement(material_1.AppBar, { className: classes.appBar, position: "static" },
|
|
89
76
|
react_1.default.createElement(AppToolbar_1.default, { ...props })),
|
|
90
|
-
react_1.default.createElement(
|
|
77
|
+
react_1.default.createElement(ViewsContainer_1.default, { ...props })),
|
|
91
78
|
react_1.default.createElement(AppFab_1.default, { session: session }),
|
|
92
79
|
drawerVisible && drawerPosition === 'right' ? (react_1.default.createElement(LazyDrawerWidget, { session: session })) : null,
|
|
93
80
|
react_1.default.createElement(Snackbar_1.default, { session: session })));
|
package/dist/ui/App/AppFab.js
CHANGED
|
@@ -27,7 +27,9 @@ const AppFab = (0, mobx_react_1.observer)(function ({ session, }) {
|
|
|
27
27
|
const { minimized, activeWidgets, drawerPosition } = session;
|
|
28
28
|
const { classes } = useStyles();
|
|
29
29
|
return activeWidgets.size > 0 && minimized ? (react_1.default.createElement(material_1.Tooltip, { title: "Open drawer widget" },
|
|
30
|
-
react_1.default.createElement(material_1.Fab, { className: drawerPosition === 'right' ? classes.right : classes.left, color: "primary", "data-testid": "drawer-maximize", onClick: () =>
|
|
30
|
+
react_1.default.createElement(material_1.Fab, { className: drawerPosition === 'right' ? classes.right : classes.left, color: "primary", "data-testid": "drawer-maximize", onClick: () => {
|
|
31
|
+
session.showWidgetDrawer();
|
|
32
|
+
} },
|
|
31
33
|
react_1.default.createElement(Launch_1.default, null)))) : null;
|
|
32
34
|
});
|
|
33
35
|
exports.default = AppFab;
|
|
@@ -3,13 +3,13 @@ import { SessionWithDrawerWidgets } from '@jbrowse/core/util';
|
|
|
3
3
|
import { MenuItem as JBMenuItem } from '@jbrowse/core/ui/Menu';
|
|
4
4
|
import { SnackbarMessage } from '@jbrowse/core/ui/SnackbarModel';
|
|
5
5
|
type AppSession = SessionWithDrawerWidgets & {
|
|
6
|
-
savedSessionNames: string[];
|
|
7
6
|
menus: {
|
|
8
7
|
label: string;
|
|
9
8
|
menuItems: JBMenuItem[];
|
|
10
9
|
}[];
|
|
11
|
-
|
|
10
|
+
savedSessionNames?: string[];
|
|
12
11
|
snackbarMessages: SnackbarMessage[];
|
|
12
|
+
renameCurrentSession: (arg: string) => void;
|
|
13
13
|
popSnackbarMessage: () => unknown;
|
|
14
14
|
};
|
|
15
15
|
declare const AppToolbar: ({ session, HeaderButtons, }: {
|
package/dist/ui/App/Drawer.js
CHANGED
|
@@ -54,7 +54,7 @@ const Drawer = (0, mobx_react_1.observer)(function ({ children, session, }) {
|
|
|
54
54
|
(0, react_1.useEffect)(() => {
|
|
55
55
|
function handleSelectView(e) {
|
|
56
56
|
var _a, _b, _c;
|
|
57
|
-
if (e.target instanceof Element && ((_a = ref
|
|
57
|
+
if (e.target instanceof Element && ((_a = ref.current) === null || _a === void 0 ? void 0 : _a.contains(e.target))) {
|
|
58
58
|
// @ts-ignore
|
|
59
59
|
const visibleWidgetId = (_c = (_b = session.visibleWidget) === null || _b === void 0 ? void 0 : _b.view) === null || _c === void 0 ? void 0 : _c.id;
|
|
60
60
|
if (visibleWidgetId) {
|
|
@@ -68,7 +68,7 @@ const Drawer = (0, mobx_react_1.observer)(function ({ children, session, }) {
|
|
|
68
68
|
document.removeEventListener('mousedown', handleSelectView);
|
|
69
69
|
document.removeEventListener('keydown', handleSelectView);
|
|
70
70
|
};
|
|
71
|
-
}, [
|
|
71
|
+
}, [session]);
|
|
72
72
|
return (react_1.default.createElement(material_1.Paper, { ref: ref, className: classes.paper, elevation: 16, square: true },
|
|
73
73
|
drawerPosition === 'right' ? (react_1.default.createElement(ResizeHandle_1.default, { onDrag: session.resizeDrawer, className: classes.resizeHandle, vertical: true })) : null,
|
|
74
74
|
children,
|
|
@@ -37,7 +37,9 @@ const DrawerControls = (0, mobx_react_1.observer)(function ({ session, }) {
|
|
|
37
37
|
const [anchorEl, setAnchorEl] = (0, react_1.useState)(null);
|
|
38
38
|
const { drawerPosition, visibleWidget } = session;
|
|
39
39
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
40
|
-
react_1.default.createElement(material_1.IconButton, { color: "inherit", onClick: event =>
|
|
40
|
+
react_1.default.createElement(material_1.IconButton, { color: "inherit", onClick: event => {
|
|
41
|
+
setAnchorEl(event.currentTarget);
|
|
42
|
+
} },
|
|
41
43
|
react_1.default.createElement(MoreVert_1.default, null)),
|
|
42
44
|
react_1.default.createElement(material_1.Tooltip, { title: "Minimize drawer" },
|
|
43
45
|
react_1.default.createElement(material_1.IconButton, { "data-testid": "drawer-minimize", color: "inherit", onClick: () => {
|
|
@@ -46,9 +48,13 @@ const DrawerControls = (0, mobx_react_1.observer)(function ({ session, }) {
|
|
|
46
48
|
} },
|
|
47
49
|
react_1.default.createElement(Minimize_1.default, null))),
|
|
48
50
|
react_1.default.createElement(material_1.Tooltip, { title: "Close drawer" },
|
|
49
|
-
react_1.default.createElement(material_1.IconButton, { color: "inherit", onClick: () =>
|
|
51
|
+
react_1.default.createElement(material_1.IconButton, { color: "inherit", onClick: () => {
|
|
52
|
+
session.hideWidget(visibleWidget);
|
|
53
|
+
} },
|
|
50
54
|
react_1.default.createElement(Close_1.default, null))),
|
|
51
|
-
react_1.default.createElement(material_1.Menu, { anchorEl: anchorEl, open: Boolean(anchorEl), onClose: () =>
|
|
55
|
+
react_1.default.createElement(material_1.Menu, { anchorEl: anchorEl, open: Boolean(anchorEl), onClose: () => {
|
|
56
|
+
setAnchorEl(null);
|
|
57
|
+
} }, ['left', 'right'].map(option => (react_1.default.createElement(material_1.MenuItem, { key: option, selected: drawerPosition === 'option', onClick: () => {
|
|
52
58
|
session.setDrawerPosition(option);
|
|
53
59
|
setAnchorEl(null);
|
|
54
60
|
} }, option))))));
|
|
@@ -31,11 +31,15 @@ const DrawerHeader = (0, mobx_react_1.observer)(function ({ session, setToolbarH
|
|
|
31
31
|
const viewWidgetId = (_b = (_a = session.visibleWidget) === null || _a === void 0 ? void 0 : _a.view) === null || _b === void 0 ? void 0 : _b.id;
|
|
32
32
|
return (react_1.default.createElement(material_1.AppBar, { position: "sticky", className: focusedViewId === viewWidgetId
|
|
33
33
|
? classes.headerFocused
|
|
34
|
-
: classes.headerUnfocused, ref: ref =>
|
|
34
|
+
: classes.headerUnfocused, ref: ref => {
|
|
35
|
+
setToolbarHeight((ref === null || ref === void 0 ? void 0 : ref.getBoundingClientRect().height) || 0);
|
|
36
|
+
} },
|
|
35
37
|
react_1.default.createElement(material_1.Toolbar, { disableGutters: true },
|
|
36
38
|
react_1.default.createElement(DrawerWidgetSelector_1.default, { session: session }),
|
|
37
39
|
react_1.default.createElement(material_1.Tooltip, { title: "Open drawer in dialog" },
|
|
38
|
-
react_1.default.createElement(material_1.IconButton, { color: "inherit", onClick: () =>
|
|
40
|
+
react_1.default.createElement(material_1.IconButton, { color: "inherit", onClick: () => {
|
|
41
|
+
onPopoutDrawer();
|
|
42
|
+
} },
|
|
39
43
|
react_1.default.createElement(Launch_1.default, null))),
|
|
40
44
|
react_1.default.createElement("div", { className: classes.spacer }),
|
|
41
45
|
react_1.default.createElement(DrawerControls_1.default, { session: session }))));
|
|
@@ -50,11 +50,15 @@ const DrawerWidget = (0, mobx_react_1.observer)(function ({ session, }) {
|
|
|
50
50
|
const [toolbarHeight, setToolbarHeight] = (0, react_1.useState)(0);
|
|
51
51
|
const [popoutDrawer, setPopoutDrawer] = (0, react_1.useState)(false);
|
|
52
52
|
return (react_1.default.createElement(Drawer_1.default, { session: session },
|
|
53
|
-
react_1.default.createElement(DrawerHeader_1.default, { onPopoutDrawer: () =>
|
|
53
|
+
react_1.default.createElement(DrawerHeader_1.default, { onPopoutDrawer: () => {
|
|
54
|
+
setPopoutDrawer(true);
|
|
55
|
+
}, session: session, setToolbarHeight: setToolbarHeight }),
|
|
54
56
|
react_1.default.createElement(react_1.Suspense, { fallback: react_1.default.createElement(ui_1.LoadingEllipses, null) },
|
|
55
57
|
react_1.default.createElement(react_error_boundary_1.ErrorBoundary, { FallbackComponent: ({ error }) => react_1.default.createElement(ui_1.ErrorMessage, { error: error }) }, DrawerComponent ? (popoutDrawer ? (react_1.default.createElement(react_1.default.Fragment, null,
|
|
56
58
|
react_1.default.createElement("div", null, "Opened in dialog..."),
|
|
57
|
-
react_1.default.createElement(ModalWidget, { session: session, onClose: () =>
|
|
59
|
+
react_1.default.createElement(ModalWidget, { session: session, onClose: () => {
|
|
60
|
+
setPopoutDrawer(false);
|
|
61
|
+
} }))) : (react_1.default.createElement(react_1.default.Fragment, null,
|
|
58
62
|
react_1.default.createElement(DrawerComponent, { model: visibleWidget, session: session, toolbarHeight: toolbarHeight }),
|
|
59
63
|
react_1.default.createElement("div", { style: { height: 300 } })))) : null))));
|
|
60
64
|
});
|
|
@@ -48,7 +48,9 @@ const DrawerWidgetSelector = (0, mobx_react_1.observer)(function ({ session, })
|
|
|
48
48
|
const { HeadingComponent, heading } = widgetType;
|
|
49
49
|
return (react_1.default.createElement(material_1.MenuItem, { "data-testid": `widget-drawer-selects-item-${widget.type}`, key: widget.id, value: widget.id },
|
|
50
50
|
HeadingComponent ? (react_1.default.createElement(HeadingComponent, { model: widget })) : (react_1.default.createElement(material_1.Typography, { variant: "h6", color: "inherit" }, heading)),
|
|
51
|
-
react_1.default.createElement(material_1.IconButton, { "data-testid": `${widget.type}-drawer-delete`, color: "inherit", "aria-label": "Delete", onClick: () =>
|
|
51
|
+
react_1.default.createElement(material_1.IconButton, { "data-testid": `${widget.type}-drawer-delete`, color: "inherit", "aria-label": "Delete", onClick: () => {
|
|
52
|
+
session.hideWidget(widget);
|
|
53
|
+
} },
|
|
52
54
|
react_1.default.createElement(Delete_1.default, null))));
|
|
53
55
|
}))));
|
|
54
56
|
});
|
|
@@ -67,12 +67,10 @@ const ModalWidget = (0, mobx_react_1.observer)(function ({ session, onClose, })
|
|
|
67
67
|
return null;
|
|
68
68
|
}
|
|
69
69
|
const { ReactComponent } = pluginManager.getWidgetType(visibleWidget.type);
|
|
70
|
-
const Component =
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
})
|
|
75
|
-
: null;
|
|
70
|
+
const Component = pluginManager.evaluateExtensionPoint('Core-replaceWidget', ReactComponent, {
|
|
71
|
+
session,
|
|
72
|
+
model: visibleWidget,
|
|
73
|
+
});
|
|
76
74
|
return (react_1.default.createElement(ui_1.Dialog, { open: true, onClose: onClose, maxWidth: "xl", header: react_1.default.createElement(DrawerAppBar, { onClose: onClose, session: session }) }, Component ? (react_1.default.createElement(react_1.Suspense, { fallback: react_1.default.createElement("div", null, "Loading...") },
|
|
77
75
|
react_1.default.createElement(material_1.Paper, { className: classes.paper },
|
|
78
76
|
react_1.default.createElement(Component, { model: visibleWidget, session: session, modal: true, overrideDimensions: {
|
|
@@ -54,7 +54,7 @@ const ViewContainer = (0, mobx_react_1.observer)(function ({ view, onClose, onMi
|
|
|
54
54
|
(0, react_1.useEffect)(() => {
|
|
55
55
|
function handleSelectView(e) {
|
|
56
56
|
var _a;
|
|
57
|
-
if (e.target instanceof Element && ((_a = ref
|
|
57
|
+
if (e.target instanceof Element && ((_a = ref.current) === null || _a === void 0 ? void 0 : _a.contains(e.target))) {
|
|
58
58
|
session.setFocusedViewId(view.id);
|
|
59
59
|
}
|
|
60
60
|
}
|
|
@@ -33,7 +33,9 @@ const ViewContainerTitle = (0, mobx_react_1.observer)(function ({ view, }) {
|
|
|
33
33
|
return (react_1.default.createElement(material_1.Tooltip, { title: "Rename view", arrow: true },
|
|
34
34
|
react_1.default.createElement(EditableTypography_1.default, { value: view.displayName ||
|
|
35
35
|
// @ts-expect-error
|
|
36
|
-
`${((_a = view.assemblyNames) === null || _a === void 0 ? void 0 : _a.join(',')) || 'Untitled view'}${view.minimized ? ' (minimized)' : ''}`, setValue: val =>
|
|
36
|
+
`${((_a = view.assemblyNames) === null || _a === void 0 ? void 0 : _a.join(',')) || 'Untitled view'}${view.minimized ? ' (minimized)' : ''}`, setValue: val => {
|
|
37
|
+
view.setDisplayName(val);
|
|
38
|
+
}, variant: "body2", classes: {
|
|
37
39
|
input: classes.input,
|
|
38
40
|
inputBase: classes.inputBase,
|
|
39
41
|
inputRoot: classes.inputRoot,
|
|
@@ -68,8 +68,10 @@ const ViewHeader = (0, mobx_react_1.observer)(function ({ view, onClose, onMinim
|
|
|
68
68
|
// scroll the view into view when first mounted. note: this effect will run
|
|
69
69
|
// only once, because of the empty array second param
|
|
70
70
|
(0, react_1.useEffect)(() => {
|
|
71
|
-
var _a
|
|
72
|
-
|
|
71
|
+
var _a;
|
|
72
|
+
if (typeof jest === 'undefined') {
|
|
73
|
+
(_a = scrollRef.current) === null || _a === void 0 ? void 0 : _a.scrollIntoView({ block: 'center' });
|
|
74
|
+
}
|
|
73
75
|
}, []);
|
|
74
76
|
return (react_1.default.createElement("div", { ref: scrollRef, className: classes.viewHeader },
|
|
75
77
|
react_1.default.createElement(ViewMenu_1.default, { model: view, IconProps: { className: classes.icon } }),
|
|
@@ -33,18 +33,23 @@ const useStyles = (0, mui_1.makeStyles)()(theme => ({
|
|
|
33
33
|
selectPaper: {
|
|
34
34
|
padding: theme.spacing(4),
|
|
35
35
|
},
|
|
36
|
+
m2: {
|
|
37
|
+
margin: 2,
|
|
38
|
+
},
|
|
36
39
|
}));
|
|
37
40
|
const ViewLauncher = (0, mobx_react_1.observer)(({ session }) => {
|
|
38
41
|
var _a;
|
|
39
42
|
const { classes } = useStyles();
|
|
40
43
|
const { pluginManager } = (0, util_1.getEnv)(session);
|
|
41
44
|
const viewTypes = pluginManager.getElementTypeRecord('view').all();
|
|
42
|
-
const [value, setValue] = (0, react_1.useState)((_a = viewTypes[0]) === null || _a === void 0 ? void 0 : _a.name);
|
|
45
|
+
const [value, setValue] = (0, react_1.useState)(((_a = viewTypes[0]) === null || _a === void 0 ? void 0 : _a.name) || '');
|
|
43
46
|
return (react_1.default.createElement(material_1.Paper, { className: classes.selectPaper },
|
|
44
47
|
react_1.default.createElement(material_1.Typography, null, "Select a view to launch"),
|
|
45
|
-
react_1.default.createElement(material_1.FormControl, {
|
|
46
|
-
react_1.default.createElement(material_1.Select, { value: value, onChange: event =>
|
|
47
|
-
|
|
48
|
+
react_1.default.createElement(material_1.FormControl, { className: classes.m2 },
|
|
49
|
+
react_1.default.createElement(material_1.Select, { value: value, onChange: event => {
|
|
50
|
+
setValue(event.target.value);
|
|
51
|
+
} }, viewTypes.map(({ displayName, name }) => (react_1.default.createElement(material_1.MenuItem, { key: name, value: name }, displayName))))),
|
|
52
|
+
react_1.default.createElement(material_1.FormControl, { className: classes.m2 },
|
|
48
53
|
react_1.default.createElement(material_1.Button, { onClick: () => session.addView(value, {}), variant: "contained", color: "primary" }, "Launch view"))));
|
|
49
54
|
});
|
|
50
55
|
exports.default = ViewLauncher;
|
package/dist/ui/App/ViewMenu.js
CHANGED
|
@@ -16,7 +16,6 @@ const KeyboardDoubleArrowUp_1 = __importDefault(require("@mui/icons-material/Key
|
|
|
16
16
|
const KeyboardArrowDown_1 = __importDefault(require("@mui/icons-material/KeyboardArrowDown"));
|
|
17
17
|
const KeyboardArrowUp_1 = __importDefault(require("@mui/icons-material/KeyboardArrowUp"));
|
|
18
18
|
const ViewMenu = (0, mobx_react_1.observer)(function ({ model, IconButtonProps, IconProps, }) {
|
|
19
|
-
const { menuItems } = model;
|
|
20
19
|
const session = (0, util_1.getSession)(model);
|
|
21
20
|
const popupState = (0, hooks_1.usePopupState)({
|
|
22
21
|
popupId: 'viewMenu',
|
|
@@ -26,12 +25,14 @@ const ViewMenu = (0, mobx_react_1.observer)(function ({ model, IconButtonProps,
|
|
|
26
25
|
// a confusing bug related to it! see
|
|
27
26
|
// https://github.com/GMOD/jbrowse-components/issues/4115
|
|
28
27
|
//
|
|
29
|
-
// Make sure to test the Breakpoint split view menu checkboxes if you
|
|
30
|
-
//
|
|
28
|
+
// Make sure to test the Breakpoint split view menu checkboxes if you intend
|
|
29
|
+
// to change this
|
|
31
30
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
32
31
|
react_1.default.createElement(material_1.IconButton, { ...IconButtonProps, ...(0, hooks_1.bindTrigger)(popupState), "data-testid": "view_menu_icon" },
|
|
33
32
|
react_1.default.createElement(Menu_1.default, { ...IconProps, fontSize: "small" })),
|
|
34
|
-
react_1.default.createElement(CascadingMenu_1.default, { ...(0, hooks_1.bindPopover)(popupState), onMenuItemClick: (_event, callback) =>
|
|
33
|
+
react_1.default.createElement(CascadingMenu_1.default, { ...(0, hooks_1.bindPopover)(popupState), onMenuItemClick: (_event, callback) => {
|
|
34
|
+
callback();
|
|
35
|
+
}, menuItems: [
|
|
35
36
|
...(session.views.length > 1
|
|
36
37
|
? [
|
|
37
38
|
{
|
|
@@ -41,30 +42,36 @@ const ViewMenu = (0, mobx_react_1.observer)(function ({ model, IconButtonProps,
|
|
|
41
42
|
{
|
|
42
43
|
label: 'Move view to top',
|
|
43
44
|
icon: KeyboardDoubleArrowUp_1.default,
|
|
44
|
-
onClick: () =>
|
|
45
|
+
onClick: () => {
|
|
46
|
+
session.moveViewToTop(model.id);
|
|
47
|
+
},
|
|
45
48
|
},
|
|
46
49
|
{
|
|
47
50
|
label: 'Move view up',
|
|
48
51
|
icon: KeyboardArrowUp_1.default,
|
|
49
|
-
onClick: () =>
|
|
52
|
+
onClick: () => {
|
|
53
|
+
session.moveViewUp(model.id);
|
|
54
|
+
},
|
|
50
55
|
},
|
|
51
56
|
{
|
|
52
57
|
label: 'Move view down',
|
|
53
58
|
icon: KeyboardArrowDown_1.default,
|
|
54
|
-
onClick: () =>
|
|
59
|
+
onClick: () => {
|
|
60
|
+
session.moveViewDown(model.id);
|
|
61
|
+
},
|
|
55
62
|
},
|
|
56
63
|
{
|
|
57
64
|
label: 'Move view to bottom',
|
|
58
65
|
icon: KeyboardDoubleArrowDown_1.default,
|
|
59
|
-
onClick: () =>
|
|
66
|
+
onClick: () => {
|
|
67
|
+
session.moveViewToBottom(model.id);
|
|
68
|
+
},
|
|
60
69
|
},
|
|
61
70
|
],
|
|
62
71
|
},
|
|
63
72
|
]
|
|
64
73
|
: []),
|
|
65
|
-
|
|
66
|
-
...((typeof menuItems === 'function' ? menuItems() : menuItems) ||
|
|
67
|
-
[]),
|
|
74
|
+
...model.menuItems(),
|
|
68
75
|
], popupState: popupState })));
|
|
69
76
|
});
|
|
70
77
|
exports.default = ViewMenu;
|
package/dist/ui/App/ViewPanel.js
CHANGED
|
@@ -43,7 +43,11 @@ const ViewPanel = (0, mobx_react_1.observer)(function ({ view, session, }) {
|
|
|
43
43
|
throw new Error(`unknown view type ${view.type}`);
|
|
44
44
|
}
|
|
45
45
|
const { ReactComponent } = viewType;
|
|
46
|
-
return (react_1.default.createElement(ViewContainer_1.default, { view: view, onClose: () =>
|
|
46
|
+
return (react_1.default.createElement(ViewContainer_1.default, { view: view, onClose: () => {
|
|
47
|
+
session.removeView(view);
|
|
48
|
+
}, onMinimize: () => {
|
|
49
|
+
view.setMinimized(!view.minimized);
|
|
50
|
+
} }, !view.minimized ? (react_1.default.createElement(react_error_boundary_1.ErrorBoundary, { FallbackComponent: ({ error }) => react_1.default.createElement(ErrorMessage_1.default, { error: error }) },
|
|
47
51
|
react_1.default.createElement(react_1.Suspense, { fallback: react_1.default.createElement(LoadingEllipses_1.default, { variant: "h6" }) },
|
|
48
52
|
react_1.default.createElement(ReactComponent, { model: view, session: session })))) : (false)));
|
|
49
53
|
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { SessionWithFocusedViewAndDrawerWidgets } from '@jbrowse/core/util';
|
|
3
|
+
import { SnackbarMessage } from '@jbrowse/core/ui/SnackbarModel';
|
|
4
|
+
import { MenuItem as JBMenuItem } from '@jbrowse/core/ui/Menu';
|
|
5
|
+
interface Props {
|
|
6
|
+
HeaderButtons?: React.ReactElement;
|
|
7
|
+
session: SessionWithFocusedViewAndDrawerWidgets & {
|
|
8
|
+
savedSessionNames: string[];
|
|
9
|
+
menus: {
|
|
10
|
+
label: string;
|
|
11
|
+
menuItems: JBMenuItem[];
|
|
12
|
+
}[];
|
|
13
|
+
renameCurrentSession: (arg: string) => void;
|
|
14
|
+
snackbarMessages: SnackbarMessage[];
|
|
15
|
+
popSnackbarMessage: () => unknown;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
declare const ViewsContainer: (props: Props) => React.JSX.Element;
|
|
19
|
+
export default ViewsContainer;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const react_1 = __importDefault(require("react"));
|
|
7
|
+
const mui_1 = require("tss-react/mui");
|
|
8
|
+
const mobx_react_1 = require("mobx-react");
|
|
9
|
+
// locals
|
|
10
|
+
const ViewLauncher_1 = __importDefault(require("./ViewLauncher"));
|
|
11
|
+
const ViewPanel_1 = __importDefault(require("./ViewPanel"));
|
|
12
|
+
const useStyles = (0, mui_1.makeStyles)()({
|
|
13
|
+
viewsContainer: {
|
|
14
|
+
overflowY: 'auto',
|
|
15
|
+
gridRow: 'components',
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
const ViewsContainer = (0, mobx_react_1.observer)(function ViewsContainer(props) {
|
|
19
|
+
const { session } = props;
|
|
20
|
+
const { views } = session;
|
|
21
|
+
const { classes } = useStyles();
|
|
22
|
+
return (react_1.default.createElement("div", { className: classes.viewsContainer },
|
|
23
|
+
views.length > 0 ? (views.map(view => (react_1.default.createElement(ViewPanel_1.default, { key: `view-${view.id}`, view: view, session: session })))) : (react_1.default.createElement(ViewLauncher_1.default, { ...props })),
|
|
24
|
+
react_1.default.createElement("div", { style: { height: 300 } })));
|
|
25
|
+
});
|
|
26
|
+
exports.default = ViewsContainer;
|
|
@@ -37,7 +37,7 @@ export declare function SessionAssembliesMixin(pluginManager: PluginManager, ass
|
|
|
37
37
|
/**
|
|
38
38
|
* #action
|
|
39
39
|
*/
|
|
40
|
-
addSessionAssembly(conf: AnyConfiguration): {
|
|
40
|
+
addSessionAssembly(conf: AnyConfiguration): ({
|
|
41
41
|
[x: string]: any;
|
|
42
42
|
} & import("mobx-state-tree/dist/internal").NonEmptyObject & {
|
|
43
43
|
setSubschema(slotName: string, data: Record<string, unknown>): Record<string, unknown> | ({
|
|
@@ -70,7 +70,7 @@ export declare function SessionAssembliesMixin(pluginManager: PluginManager, ass
|
|
|
70
70
|
defaultValue: string;
|
|
71
71
|
description: string;
|
|
72
72
|
};
|
|
73
|
-
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "name"
|
|
73
|
+
}, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, "name">>>) | undefined;
|
|
74
74
|
/**
|
|
75
75
|
* #action
|
|
76
76
|
*/
|
|
@@ -137,7 +137,7 @@ export declare function JBrowseModelF({ pluginManager, assemblyConfigSchema, }:
|
|
|
137
137
|
/**
|
|
138
138
|
* #action
|
|
139
139
|
*/
|
|
140
|
-
addAssemblyConf(conf: AnyConfigurationModel): {
|
|
140
|
+
addAssemblyConf(conf: AnyConfigurationModel): ({
|
|
141
141
|
[x: string]: any;
|
|
142
142
|
} & import("mobx-state-tree/dist/internal").NonEmptyObject & {
|
|
143
143
|
setSubschema(slotName: string, data: Record<string, unknown>): Record<string, unknown> | ({
|
|
@@ -147,7 +147,7 @@ export declare function JBrowseModelF({ pluginManager, assemblyConfigSchema, }:
|
|
|
147
147
|
[x: string]: any;
|
|
148
148
|
} & import("mobx-state-tree/dist/internal").NonEmptyObject & any & import("mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>);
|
|
149
149
|
} & import("mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>);
|
|
150
|
-
} & import("mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType
|
|
150
|
+
} & import("mobx-state-tree").IStateTreeNode<import("@jbrowse/core/configuration").AnyConfigurationSchemaType>) | undefined;
|
|
151
151
|
/**
|
|
152
152
|
* #action
|
|
153
153
|
*/
|
|
@@ -27,7 +27,6 @@ export function JBrowseModelF({ pluginManager, assemblyConfigSchema, }) {
|
|
|
27
27
|
* #getter
|
|
28
28
|
*/
|
|
29
29
|
get rpcManager() {
|
|
30
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
31
30
|
return getParent(self).rpcManager;
|
|
32
31
|
},
|
|
33
32
|
}))
|
|
@@ -103,7 +102,6 @@ export function JBrowseModelF({ pluginManager, assemblyConfigSchema, }) {
|
|
|
103
102
|
*/
|
|
104
103
|
addPlugin(pluginDefinition) {
|
|
105
104
|
self.plugins.push(pluginDefinition);
|
|
106
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
107
105
|
const rootModel = getParent(self);
|
|
108
106
|
rootModel.setPluginsUpdated(true);
|
|
109
107
|
},
|
|
@@ -111,20 +109,22 @@ export function JBrowseModelF({ pluginManager, assemblyConfigSchema, }) {
|
|
|
111
109
|
* #action
|
|
112
110
|
*/
|
|
113
111
|
removePlugin(pluginDefinition) {
|
|
114
|
-
self.plugins = cast(self.plugins.filter(plugin =>
|
|
112
|
+
self.plugins = cast(self.plugins.filter(plugin =>
|
|
113
|
+
// @ts-expect-error
|
|
114
|
+
plugin.url !== pluginDefinition.url ||
|
|
115
|
+
// @ts-expect-error
|
|
115
116
|
plugin.umdUrl !== pluginDefinition.umdUrl ||
|
|
117
|
+
// @ts-expect-error
|
|
116
118
|
plugin.cjsUrl !== pluginDefinition.cjsUrl ||
|
|
119
|
+
// @ts-expect-error
|
|
117
120
|
plugin.esmUrl !== pluginDefinition.esmUrl));
|
|
118
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
119
121
|
getParent(self).setPluginsUpdated(true);
|
|
120
122
|
},
|
|
121
123
|
/**
|
|
122
124
|
* #action
|
|
123
125
|
*/
|
|
124
126
|
setDefaultSessionConf(sessionConf) {
|
|
125
|
-
const newDefault =
|
|
126
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
127
|
-
getParent(self).session.name === sessionConf.name
|
|
127
|
+
const newDefault = getParent(self).session.name === sessionConf.name
|
|
128
128
|
? getSnapshot(sessionConf)
|
|
129
129
|
: toJS(sessionConf);
|
|
130
130
|
if (!newDefault.name) {
|
package/esm/ui/App/App.js
CHANGED
|
@@ -5,10 +5,9 @@ import { observer } from 'mobx-react';
|
|
|
5
5
|
import Snackbar from '@jbrowse/core/ui/Snackbar';
|
|
6
6
|
// locals
|
|
7
7
|
import AppToolbar from './AppToolbar';
|
|
8
|
-
import ViewLauncher from './ViewLauncher';
|
|
9
|
-
import ViewPanel from './ViewPanel';
|
|
10
8
|
import DialogQueue from './DialogQueue';
|
|
11
9
|
import AppFab from './AppFab';
|
|
10
|
+
import ViewsContainer from './ViewsContainer';
|
|
12
11
|
const DrawerWidget = lazy(() => import('./DrawerWidget'));
|
|
13
12
|
const useStyles = makeStyles()(theme => ({
|
|
14
13
|
root: {
|
|
@@ -23,10 +22,6 @@ const useStyles = makeStyles()(theme => ({
|
|
|
23
22
|
gridTemplateRows: '[menubar] min-content [components] auto',
|
|
24
23
|
height: '100vh',
|
|
25
24
|
},
|
|
26
|
-
viewContainer: {
|
|
27
|
-
overflowY: 'auto',
|
|
28
|
-
gridRow: 'components',
|
|
29
|
-
},
|
|
30
25
|
appBar: {
|
|
31
26
|
flexGrow: 1,
|
|
32
27
|
gridRow: 'menubar',
|
|
@@ -37,14 +32,6 @@ const LazyDrawerWidget = observer(function (props) {
|
|
|
37
32
|
return (React.createElement(Suspense, { fallback: null },
|
|
38
33
|
React.createElement(DrawerWidget, { session: session })));
|
|
39
34
|
});
|
|
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
35
|
const App = observer(function (props) {
|
|
49
36
|
const { session } = props;
|
|
50
37
|
const { classes } = useStyles();
|
|
@@ -52,13 +39,13 @@ const App = observer(function (props) {
|
|
|
52
39
|
const drawerVisible = visibleWidget && !minimized;
|
|
53
40
|
const d = drawerVisible ? `[drawer] ${drawerWidth}px` : undefined;
|
|
54
41
|
const grid = drawerPosition === 'right' ? ['[main] 1fr', d] : [d, '[main] 1fr'];
|
|
55
|
-
return (React.createElement("div", { className: classes.root, style: { gridTemplateColumns: grid
|
|
42
|
+
return (React.createElement("div", { className: classes.root, style: { gridTemplateColumns: grid.filter(f => !!f).join(' ') } },
|
|
56
43
|
drawerVisible && drawerPosition === 'left' ? (React.createElement(LazyDrawerWidget, { session: session })) : null,
|
|
57
44
|
React.createElement(DialogQueue, { session: session }),
|
|
58
45
|
React.createElement("div", { className: classes.appContainer },
|
|
59
46
|
React.createElement(AppBar, { className: classes.appBar, position: "static" },
|
|
60
47
|
React.createElement(AppToolbar, { ...props })),
|
|
61
|
-
React.createElement(
|
|
48
|
+
React.createElement(ViewsContainer, { ...props })),
|
|
62
49
|
React.createElement(AppFab, { session: session }),
|
|
63
50
|
drawerVisible && drawerPosition === 'right' ? (React.createElement(LazyDrawerWidget, { session: session })) : null,
|
|
64
51
|
React.createElement(Snackbar, { session: session })));
|
package/esm/ui/App/AppFab.js
CHANGED
|
@@ -22,7 +22,9 @@ const AppFab = observer(function ({ session, }) {
|
|
|
22
22
|
const { minimized, activeWidgets, drawerPosition } = session;
|
|
23
23
|
const { classes } = useStyles();
|
|
24
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: () =>
|
|
25
|
+
React.createElement(Fab, { className: drawerPosition === 'right' ? classes.right : classes.left, color: "primary", "data-testid": "drawer-maximize", onClick: () => {
|
|
26
|
+
session.showWidgetDrawer();
|
|
27
|
+
} },
|
|
26
28
|
React.createElement(LaunchIcon, null)))) : null;
|
|
27
29
|
});
|
|
28
30
|
export default AppFab;
|
|
@@ -3,13 +3,13 @@ import { SessionWithDrawerWidgets } from '@jbrowse/core/util';
|
|
|
3
3
|
import { MenuItem as JBMenuItem } from '@jbrowse/core/ui/Menu';
|
|
4
4
|
import { SnackbarMessage } from '@jbrowse/core/ui/SnackbarModel';
|
|
5
5
|
type AppSession = SessionWithDrawerWidgets & {
|
|
6
|
-
savedSessionNames: string[];
|
|
7
6
|
menus: {
|
|
8
7
|
label: string;
|
|
9
8
|
menuItems: JBMenuItem[];
|
|
10
9
|
}[];
|
|
11
|
-
|
|
10
|
+
savedSessionNames?: string[];
|
|
12
11
|
snackbarMessages: SnackbarMessage[];
|
|
12
|
+
renameCurrentSession: (arg: string) => void;
|
|
13
13
|
popSnackbarMessage: () => unknown;
|
|
14
14
|
};
|
|
15
15
|
declare const AppToolbar: ({ session, HeaderButtons, }: {
|
package/esm/ui/App/Drawer.js
CHANGED
|
@@ -26,7 +26,7 @@ const Drawer = observer(function ({ children, session, }) {
|
|
|
26
26
|
useEffect(() => {
|
|
27
27
|
function handleSelectView(e) {
|
|
28
28
|
var _a, _b, _c;
|
|
29
|
-
if (e.target instanceof Element && ((_a = ref
|
|
29
|
+
if (e.target instanceof Element && ((_a = ref.current) === null || _a === void 0 ? void 0 : _a.contains(e.target))) {
|
|
30
30
|
// @ts-ignore
|
|
31
31
|
const visibleWidgetId = (_c = (_b = session.visibleWidget) === null || _b === void 0 ? void 0 : _b.view) === null || _c === void 0 ? void 0 : _c.id;
|
|
32
32
|
if (visibleWidgetId) {
|
|
@@ -40,7 +40,7 @@ const Drawer = observer(function ({ children, session, }) {
|
|
|
40
40
|
document.removeEventListener('mousedown', handleSelectView);
|
|
41
41
|
document.removeEventListener('keydown', handleSelectView);
|
|
42
42
|
};
|
|
43
|
-
}, [
|
|
43
|
+
}, [session]);
|
|
44
44
|
return (React.createElement(Paper, { ref: ref, className: classes.paper, elevation: 16, square: true },
|
|
45
45
|
drawerPosition === 'right' ? (React.createElement(ResizeHandle, { onDrag: session.resizeDrawer, className: classes.resizeHandle, vertical: true })) : null,
|
|
46
46
|
children,
|
|
@@ -9,7 +9,9 @@ const DrawerControls = observer(function ({ session, }) {
|
|
|
9
9
|
const [anchorEl, setAnchorEl] = useState(null);
|
|
10
10
|
const { drawerPosition, visibleWidget } = session;
|
|
11
11
|
return (React.createElement(React.Fragment, null,
|
|
12
|
-
React.createElement(IconButton, { color: "inherit", onClick: event =>
|
|
12
|
+
React.createElement(IconButton, { color: "inherit", onClick: event => {
|
|
13
|
+
setAnchorEl(event.currentTarget);
|
|
14
|
+
} },
|
|
13
15
|
React.createElement(MoreVertIcon, null)),
|
|
14
16
|
React.createElement(Tooltip, { title: "Minimize drawer" },
|
|
15
17
|
React.createElement(IconButton, { "data-testid": "drawer-minimize", color: "inherit", onClick: () => {
|
|
@@ -18,9 +20,13 @@ const DrawerControls = observer(function ({ session, }) {
|
|
|
18
20
|
} },
|
|
19
21
|
React.createElement(MinimizeIcon, null))),
|
|
20
22
|
React.createElement(Tooltip, { title: "Close drawer" },
|
|
21
|
-
React.createElement(IconButton, { color: "inherit", onClick: () =>
|
|
23
|
+
React.createElement(IconButton, { color: "inherit", onClick: () => {
|
|
24
|
+
session.hideWidget(visibleWidget);
|
|
25
|
+
} },
|
|
22
26
|
React.createElement(CloseIcon, null))),
|
|
23
|
-
React.createElement(Menu, { anchorEl: anchorEl, open: Boolean(anchorEl), onClose: () =>
|
|
27
|
+
React.createElement(Menu, { anchorEl: anchorEl, open: Boolean(anchorEl), onClose: () => {
|
|
28
|
+
setAnchorEl(null);
|
|
29
|
+
} }, ['left', 'right'].map(option => (React.createElement(MenuItem, { key: option, selected: drawerPosition === 'option', onClick: () => {
|
|
24
30
|
session.setDrawerPosition(option);
|
|
25
31
|
setAnchorEl(null);
|
|
26
32
|
} }, option))))));
|
|
@@ -26,11 +26,15 @@ const DrawerHeader = observer(function ({ session, setToolbarHeight, onPopoutDra
|
|
|
26
26
|
const viewWidgetId = (_b = (_a = session.visibleWidget) === null || _a === void 0 ? void 0 : _a.view) === null || _b === void 0 ? void 0 : _b.id;
|
|
27
27
|
return (React.createElement(AppBar, { position: "sticky", className: focusedViewId === viewWidgetId
|
|
28
28
|
? classes.headerFocused
|
|
29
|
-
: classes.headerUnfocused, ref: ref =>
|
|
29
|
+
: classes.headerUnfocused, ref: ref => {
|
|
30
|
+
setToolbarHeight((ref === null || ref === void 0 ? void 0 : ref.getBoundingClientRect().height) || 0);
|
|
31
|
+
} },
|
|
30
32
|
React.createElement(Toolbar, { disableGutters: true },
|
|
31
33
|
React.createElement(DrawerWidgetSelector, { session: session }),
|
|
32
34
|
React.createElement(Tooltip, { title: "Open drawer in dialog" },
|
|
33
|
-
React.createElement(IconButton, { color: "inherit", onClick: () =>
|
|
35
|
+
React.createElement(IconButton, { color: "inherit", onClick: () => {
|
|
36
|
+
onPopoutDrawer();
|
|
37
|
+
} },
|
|
34
38
|
React.createElement(LaunchIcon, null))),
|
|
35
39
|
React.createElement("div", { className: classes.spacer }),
|
|
36
40
|
React.createElement(DrawerControls, { session: session }))));
|
|
@@ -22,11 +22,15 @@ const DrawerWidget = observer(function ({ session, }) {
|
|
|
22
22
|
const [toolbarHeight, setToolbarHeight] = useState(0);
|
|
23
23
|
const [popoutDrawer, setPopoutDrawer] = useState(false);
|
|
24
24
|
return (React.createElement(Drawer, { session: session },
|
|
25
|
-
React.createElement(DrawerHeader, { onPopoutDrawer: () =>
|
|
25
|
+
React.createElement(DrawerHeader, { onPopoutDrawer: () => {
|
|
26
|
+
setPopoutDrawer(true);
|
|
27
|
+
}, session: session, setToolbarHeight: setToolbarHeight }),
|
|
26
28
|
React.createElement(Suspense, { fallback: React.createElement(LoadingEllipses, null) },
|
|
27
29
|
React.createElement(ErrorBoundary, { FallbackComponent: ({ error }) => React.createElement(ErrorMessage, { error: error }) }, DrawerComponent ? (popoutDrawer ? (React.createElement(React.Fragment, null,
|
|
28
30
|
React.createElement("div", null, "Opened in dialog..."),
|
|
29
|
-
React.createElement(ModalWidget, { session: session, onClose: () =>
|
|
31
|
+
React.createElement(ModalWidget, { session: session, onClose: () => {
|
|
32
|
+
setPopoutDrawer(false);
|
|
33
|
+
} }))) : (React.createElement(React.Fragment, null,
|
|
30
34
|
React.createElement(DrawerComponent, { model: visibleWidget, session: session, toolbarHeight: toolbarHeight }),
|
|
31
35
|
React.createElement("div", { style: { height: 300 } })))) : null))));
|
|
32
36
|
});
|
|
@@ -43,7 +43,9 @@ const DrawerWidgetSelector = observer(function ({ session, }) {
|
|
|
43
43
|
const { HeadingComponent, heading } = widgetType;
|
|
44
44
|
return (React.createElement(MenuItem, { "data-testid": `widget-drawer-selects-item-${widget.type}`, key: widget.id, value: widget.id },
|
|
45
45
|
HeadingComponent ? (React.createElement(HeadingComponent, { model: widget })) : (React.createElement(Typography, { variant: "h6", color: "inherit" }, heading)),
|
|
46
|
-
React.createElement(IconButton, { "data-testid": `${widget.type}-drawer-delete`, color: "inherit", "aria-label": "Delete", onClick: () =>
|
|
46
|
+
React.createElement(IconButton, { "data-testid": `${widget.type}-drawer-delete`, color: "inherit", "aria-label": "Delete", onClick: () => {
|
|
47
|
+
session.hideWidget(widget);
|
|
48
|
+
} },
|
|
47
49
|
React.createElement(DeleteIcon, null))));
|
|
48
50
|
}))));
|
|
49
51
|
});
|
|
@@ -39,12 +39,10 @@ const ModalWidget = observer(function ({ session, onClose, }) {
|
|
|
39
39
|
return null;
|
|
40
40
|
}
|
|
41
41
|
const { ReactComponent } = pluginManager.getWidgetType(visibleWidget.type);
|
|
42
|
-
const Component =
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
})
|
|
47
|
-
: null;
|
|
42
|
+
const Component = pluginManager.evaluateExtensionPoint('Core-replaceWidget', ReactComponent, {
|
|
43
|
+
session,
|
|
44
|
+
model: visibleWidget,
|
|
45
|
+
});
|
|
48
46
|
return (React.createElement(Dialog, { open: true, onClose: onClose, maxWidth: "xl", header: React.createElement(DrawerAppBar, { onClose: onClose, session: session }) }, Component ? (React.createElement(Suspense, { fallback: React.createElement("div", null, "Loading...") },
|
|
49
47
|
React.createElement(Paper, { className: classes.paper },
|
|
50
48
|
React.createElement(Component, { model: visibleWidget, session: session, modal: true, overrideDimensions: {
|
|
@@ -26,7 +26,7 @@ const ViewContainer = observer(function ({ view, onClose, onMinimize, children,
|
|
|
26
26
|
useEffect(() => {
|
|
27
27
|
function handleSelectView(e) {
|
|
28
28
|
var _a;
|
|
29
|
-
if (e.target instanceof Element && ((_a = ref
|
|
29
|
+
if (e.target instanceof Element && ((_a = ref.current) === null || _a === void 0 ? void 0 : _a.contains(e.target))) {
|
|
30
30
|
session.setFocusedViewId(view.id);
|
|
31
31
|
}
|
|
32
32
|
}
|
|
@@ -28,7 +28,9 @@ const ViewContainerTitle = observer(function ({ view, }) {
|
|
|
28
28
|
return (React.createElement(Tooltip, { title: "Rename view", arrow: true },
|
|
29
29
|
React.createElement(EditableTypography, { value: view.displayName ||
|
|
30
30
|
// @ts-expect-error
|
|
31
|
-
`${((_a = view.assemblyNames) === null || _a === void 0 ? void 0 : _a.join(',')) || 'Untitled view'}${view.minimized ? ' (minimized)' : ''}`, setValue: val =>
|
|
31
|
+
`${((_a = view.assemblyNames) === null || _a === void 0 ? void 0 : _a.join(',')) || 'Untitled view'}${view.minimized ? ' (minimized)' : ''}`, setValue: val => {
|
|
32
|
+
view.setDisplayName(val);
|
|
33
|
+
}, variant: "body2", classes: {
|
|
32
34
|
input: classes.input,
|
|
33
35
|
inputBase: classes.inputBase,
|
|
34
36
|
inputRoot: classes.inputRoot,
|
package/esm/ui/App/ViewHeader.js
CHANGED
|
@@ -40,8 +40,10 @@ const ViewHeader = observer(function ({ view, onClose, onMinimize, }) {
|
|
|
40
40
|
// scroll the view into view when first mounted. note: this effect will run
|
|
41
41
|
// only once, because of the empty array second param
|
|
42
42
|
useEffect(() => {
|
|
43
|
-
var _a
|
|
44
|
-
|
|
43
|
+
var _a;
|
|
44
|
+
if (typeof jest === 'undefined') {
|
|
45
|
+
(_a = scrollRef.current) === null || _a === void 0 ? void 0 : _a.scrollIntoView({ block: 'center' });
|
|
46
|
+
}
|
|
45
47
|
}, []);
|
|
46
48
|
return (React.createElement("div", { ref: scrollRef, className: classes.viewHeader },
|
|
47
49
|
React.createElement(ViewMenu, { model: view, IconProps: { className: classes.icon } }),
|
|
@@ -8,18 +8,23 @@ const useStyles = makeStyles()(theme => ({
|
|
|
8
8
|
selectPaper: {
|
|
9
9
|
padding: theme.spacing(4),
|
|
10
10
|
},
|
|
11
|
+
m2: {
|
|
12
|
+
margin: 2,
|
|
13
|
+
},
|
|
11
14
|
}));
|
|
12
15
|
const ViewLauncher = observer(({ session }) => {
|
|
13
16
|
var _a;
|
|
14
17
|
const { classes } = useStyles();
|
|
15
18
|
const { pluginManager } = getEnv(session);
|
|
16
19
|
const viewTypes = pluginManager.getElementTypeRecord('view').all();
|
|
17
|
-
const [value, setValue] = useState((_a = viewTypes[0]) === null || _a === void 0 ? void 0 : _a.name);
|
|
20
|
+
const [value, setValue] = useState(((_a = viewTypes[0]) === null || _a === void 0 ? void 0 : _a.name) || '');
|
|
18
21
|
return (React.createElement(Paper, { className: classes.selectPaper },
|
|
19
22
|
React.createElement(Typography, null, "Select a view to launch"),
|
|
20
|
-
React.createElement(FormControl, {
|
|
21
|
-
React.createElement(Select, { value: value, onChange: event =>
|
|
22
|
-
|
|
23
|
+
React.createElement(FormControl, { className: classes.m2 },
|
|
24
|
+
React.createElement(Select, { value: value, onChange: event => {
|
|
25
|
+
setValue(event.target.value);
|
|
26
|
+
} }, viewTypes.map(({ displayName, name }) => (React.createElement(MenuItem, { key: name, value: name }, displayName))))),
|
|
27
|
+
React.createElement(FormControl, { className: classes.m2 },
|
|
23
28
|
React.createElement(Button, { onClick: () => session.addView(value, {}), variant: "contained", color: "primary" }, "Launch view"))));
|
|
24
29
|
});
|
|
25
30
|
export default ViewLauncher;
|
package/esm/ui/App/ViewMenu.js
CHANGED
|
@@ -11,7 +11,6 @@ import KeyboardDoubleArrowUpIcon from '@mui/icons-material/KeyboardDoubleArrowUp
|
|
|
11
11
|
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
|
|
12
12
|
import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp';
|
|
13
13
|
const ViewMenu = observer(function ({ model, IconButtonProps, IconProps, }) {
|
|
14
|
-
const { menuItems } = model;
|
|
15
14
|
const session = getSession(model);
|
|
16
15
|
const popupState = usePopupState({
|
|
17
16
|
popupId: 'viewMenu',
|
|
@@ -21,12 +20,14 @@ const ViewMenu = observer(function ({ model, IconButtonProps, IconProps, }) {
|
|
|
21
20
|
// a confusing bug related to it! see
|
|
22
21
|
// https://github.com/GMOD/jbrowse-components/issues/4115
|
|
23
22
|
//
|
|
24
|
-
// Make sure to test the Breakpoint split view menu checkboxes if you
|
|
25
|
-
//
|
|
23
|
+
// Make sure to test the Breakpoint split view menu checkboxes if you intend
|
|
24
|
+
// to change this
|
|
26
25
|
return (React.createElement(React.Fragment, null,
|
|
27
26
|
React.createElement(IconButton, { ...IconButtonProps, ...bindTrigger(popupState), "data-testid": "view_menu_icon" },
|
|
28
27
|
React.createElement(MenuIcon, { ...IconProps, fontSize: "small" })),
|
|
29
|
-
React.createElement(CascadingMenu, { ...bindPopover(popupState), onMenuItemClick: (_event, callback) =>
|
|
28
|
+
React.createElement(CascadingMenu, { ...bindPopover(popupState), onMenuItemClick: (_event, callback) => {
|
|
29
|
+
callback();
|
|
30
|
+
}, menuItems: [
|
|
30
31
|
...(session.views.length > 1
|
|
31
32
|
? [
|
|
32
33
|
{
|
|
@@ -36,30 +37,36 @@ const ViewMenu = observer(function ({ model, IconButtonProps, IconProps, }) {
|
|
|
36
37
|
{
|
|
37
38
|
label: 'Move view to top',
|
|
38
39
|
icon: KeyboardDoubleArrowUpIcon,
|
|
39
|
-
onClick: () =>
|
|
40
|
+
onClick: () => {
|
|
41
|
+
session.moveViewToTop(model.id);
|
|
42
|
+
},
|
|
40
43
|
},
|
|
41
44
|
{
|
|
42
45
|
label: 'Move view up',
|
|
43
46
|
icon: KeyboardArrowUpIcon,
|
|
44
|
-
onClick: () =>
|
|
47
|
+
onClick: () => {
|
|
48
|
+
session.moveViewUp(model.id);
|
|
49
|
+
},
|
|
45
50
|
},
|
|
46
51
|
{
|
|
47
52
|
label: 'Move view down',
|
|
48
53
|
icon: KeyboardArrowDownIcon,
|
|
49
|
-
onClick: () =>
|
|
54
|
+
onClick: () => {
|
|
55
|
+
session.moveViewDown(model.id);
|
|
56
|
+
},
|
|
50
57
|
},
|
|
51
58
|
{
|
|
52
59
|
label: 'Move view to bottom',
|
|
53
60
|
icon: KeyboardDoubleArrowDownIcon,
|
|
54
|
-
onClick: () =>
|
|
61
|
+
onClick: () => {
|
|
62
|
+
session.moveViewToBottom(model.id);
|
|
63
|
+
},
|
|
55
64
|
},
|
|
56
65
|
],
|
|
57
66
|
},
|
|
58
67
|
]
|
|
59
68
|
: []),
|
|
60
|
-
|
|
61
|
-
...((typeof menuItems === 'function' ? menuItems() : menuItems) ||
|
|
62
|
-
[]),
|
|
69
|
+
...model.menuItems(),
|
|
63
70
|
], popupState: popupState })));
|
|
64
71
|
});
|
|
65
72
|
export default ViewMenu;
|
package/esm/ui/App/ViewPanel.js
CHANGED
|
@@ -15,7 +15,11 @@ const ViewPanel = observer(function ({ view, session, }) {
|
|
|
15
15
|
throw new Error(`unknown view type ${view.type}`);
|
|
16
16
|
}
|
|
17
17
|
const { ReactComponent } = viewType;
|
|
18
|
-
return (React.createElement(ViewContainer, { view: view, onClose: () =>
|
|
18
|
+
return (React.createElement(ViewContainer, { view: view, onClose: () => {
|
|
19
|
+
session.removeView(view);
|
|
20
|
+
}, onMinimize: () => {
|
|
21
|
+
view.setMinimized(!view.minimized);
|
|
22
|
+
} }, !view.minimized ? (React.createElement(ErrorBoundary, { FallbackComponent: ({ error }) => React.createElement(ErrorMessage, { error: error }) },
|
|
19
23
|
React.createElement(Suspense, { fallback: React.createElement(LoadingEllipses, { variant: "h6" }) },
|
|
20
24
|
React.createElement(ReactComponent, { model: view, session: session })))) : (false)));
|
|
21
25
|
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { SessionWithFocusedViewAndDrawerWidgets } from '@jbrowse/core/util';
|
|
3
|
+
import { SnackbarMessage } from '@jbrowse/core/ui/SnackbarModel';
|
|
4
|
+
import { MenuItem as JBMenuItem } from '@jbrowse/core/ui/Menu';
|
|
5
|
+
interface Props {
|
|
6
|
+
HeaderButtons?: React.ReactElement;
|
|
7
|
+
session: SessionWithFocusedViewAndDrawerWidgets & {
|
|
8
|
+
savedSessionNames: string[];
|
|
9
|
+
menus: {
|
|
10
|
+
label: string;
|
|
11
|
+
menuItems: JBMenuItem[];
|
|
12
|
+
}[];
|
|
13
|
+
renameCurrentSession: (arg: string) => void;
|
|
14
|
+
snackbarMessages: SnackbarMessage[];
|
|
15
|
+
popSnackbarMessage: () => unknown;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
declare const ViewsContainer: (props: Props) => React.JSX.Element;
|
|
19
|
+
export default ViewsContainer;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { makeStyles } from 'tss-react/mui';
|
|
3
|
+
import { observer } from 'mobx-react';
|
|
4
|
+
// locals
|
|
5
|
+
import ViewLauncher from './ViewLauncher';
|
|
6
|
+
import ViewPanel from './ViewPanel';
|
|
7
|
+
const useStyles = makeStyles()({
|
|
8
|
+
viewsContainer: {
|
|
9
|
+
overflowY: 'auto',
|
|
10
|
+
gridRow: 'components',
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
const ViewsContainer = observer(function ViewsContainer(props) {
|
|
14
|
+
const { session } = props;
|
|
15
|
+
const { views } = session;
|
|
16
|
+
const { classes } = useStyles();
|
|
17
|
+
return (React.createElement("div", { className: classes.viewsContainer },
|
|
18
|
+
views.length > 0 ? (views.map(view => (React.createElement(ViewPanel, { key: `view-${view.id}`, view: view, session: session })))) : (React.createElement(ViewLauncher, { ...props })),
|
|
19
|
+
React.createElement("div", { style: { height: 300 } })));
|
|
20
|
+
});
|
|
21
|
+
export default ViewsContainer;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jbrowse/app-core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.15.0",
|
|
4
4
|
"description": "JBrowse 2 code shared between the 'full featured' apps e.g. jbrowse-web and jbrowse-desktop",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jbrowse",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"build:esm": "tsc --build tsconfig.build.esm.json",
|
|
33
33
|
"build:commonjs": "tsc --build tsconfig.build.commonjs.json",
|
|
34
34
|
"build": "npm run build:esm && npm run build:commonjs",
|
|
35
|
-
"test": "cd ../..; jest packages/app-core",
|
|
35
|
+
"test": "cd ../..; jest --passWithNoTests packages/app-core",
|
|
36
36
|
"clean": "rimraf dist esm *.tsbuildinfo",
|
|
37
37
|
"prebuild": "yarn clean",
|
|
38
38
|
"prepack": "yarn build && yarn useDist",
|
|
@@ -42,9 +42,9 @@
|
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@babel/runtime": "^7.16.3",
|
|
45
|
-
"@jbrowse/product-core": "^2.
|
|
46
|
-
"@mui/icons-material": "^
|
|
47
|
-
"@mui/material": "^
|
|
45
|
+
"@jbrowse/product-core": "^2.15.0",
|
|
46
|
+
"@mui/icons-material": "^6.0.0",
|
|
47
|
+
"@mui/material": "^6.0.0",
|
|
48
48
|
"copy-to-clipboard": "^3.3.1",
|
|
49
49
|
"react-error-boundary": "^4.0.3"
|
|
50
50
|
},
|
|
@@ -60,5 +60,5 @@
|
|
|
60
60
|
"publishConfig": {
|
|
61
61
|
"access": "public"
|
|
62
62
|
},
|
|
63
|
-
"gitHead": "
|
|
63
|
+
"gitHead": "87eeb1fbf8311dbf88d5e75b5a265f03beffdda8"
|
|
64
64
|
}
|