@jbrowse/core 2.1.7 → 2.2.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.
- package/BaseFeatureWidget/BaseFeatureDetail.d.ts +3 -2
- package/BaseFeatureWidget/BaseFeatureDetail.js +43 -28
- package/BaseFeatureWidget/SequenceBox.js +4 -8
- package/BaseFeatureWidget/SequenceFeatureDetails.js +2 -1
- package/Plugin.d.ts +1 -1
- package/PluginLoader.d.ts +2 -2
- package/PluginManager.d.ts +6 -6
- package/ReExports/modules.d.ts +3 -3
- package/assemblyManager/assembly.d.ts +23 -17
- package/assemblyManager/assembly.js +75 -76
- package/assemblyManager/assemblyConfigSchema.d.ts +6 -2
- package/assemblyManager/assemblyConfigSchema.js +39 -2
- package/assemblyManager/assemblyManager.d.ts +76 -214
- package/assemblyManager/assemblyManager.js +17 -39
- package/configuration/configurationSchema.d.ts +2 -2
- package/data_adapters/BaseAdapter.d.ts +2 -2
- package/data_adapters/CytobandAdapter.js +7 -0
- package/data_adapters/dataAdapterCache.d.ts +1 -1
- package/package.json +2 -2
- package/pluggableElementTypes/AdapterType.d.ts +1 -1
- package/pluggableElementTypes/AddTrackWorkflowType.d.ts +2 -2
- package/pluggableElementTypes/RpcMethodType.d.ts +1 -1
- package/pluggableElementTypes/ViewType.d.ts +2 -2
- package/pluggableElementTypes/index.d.ts +2 -2
- package/pluggableElementTypes/models/BaseConnectionModelFactory.d.ts +23 -2
- package/pluggableElementTypes/models/BaseConnectionModelFactory.js +24 -2
- package/pluggableElementTypes/models/BaseDisplayModel.d.ts +62 -3
- package/pluggableElementTypes/models/BaseDisplayModel.js +138 -92
- package/pluggableElementTypes/models/BaseTrackModel.d.ts +49 -4
- package/pluggableElementTypes/models/BaseTrackModel.js +77 -26
- package/pluggableElementTypes/models/BaseViewModel.d.ts +22 -0
- package/pluggableElementTypes/models/BaseViewModel.js +41 -2
- package/pluggableElementTypes/models/InternetAccountModel.d.ts +53 -6
- package/pluggableElementTypes/models/InternetAccountModel.js +57 -6
- package/pluggableElementTypes/models/baseConnectionConfig.js +17 -1
- package/pluggableElementTypes/models/baseInternetAccountConfig.d.ts +2 -2
- package/pluggableElementTypes/models/baseInternetAccountConfig.js +27 -1
- package/pluggableElementTypes/models/baseTrackConfig.d.ts +5 -2
- package/pluggableElementTypes/models/baseTrackConfig.js +52 -1
- package/pluggableElementTypes/renderers/BoxRendererType.d.ts +2 -2
- package/pluggableElementTypes/renderers/BoxRendererType.js +2 -0
- package/pluggableElementTypes/renderers/ComparativeServerSideRendererType.d.ts +1 -1
- package/pluggableElementTypes/renderers/RendererType.d.ts +1 -1
- package/pluggableElementTypes/renderers/ServerSideRendererType.d.ts +1 -1
- package/pluggableElementTypes/renderers/util/serializableFilterChain.d.ts +2 -2
- package/rpc/MainThreadRpcDriver.d.ts +1 -1
- package/rpc/MainThreadRpcDriver.js +2 -2
- package/rpc/RpcManager.d.ts +2 -2
- package/rpc/WebWorkerRpcDriver.d.ts +5 -4
- package/rpc/WebWorkerRpcDriver.js +2 -2
- package/rpc/baseRpcConfig.d.ts +2 -0
- package/rpc/baseRpcConfig.js +18 -0
- package/rpc/configSchema.js +16 -10
- package/rpc/coreRpcMethods.d.ts +14 -14
- package/rpc/coreRpcMethods.js +60 -63
- package/rpc/mainThreadRpcConfig.d.ts +2 -0
- package/rpc/mainThreadRpcConfig.js +19 -0
- package/rpc/remoteAbortSignals.d.ts +1 -1
- package/rpc/webWorkerRpcConfig.d.ts +2 -0
- package/rpc/webWorkerRpcConfig.js +19 -0
- package/tsconfig.build.tsbuildinfo +1 -1
- package/ui/AboutDialog.js +2 -1
- package/ui/App.d.ts +2 -2
- package/ui/App.js +11 -10
- package/ui/AssemblySelector.d.ts +1 -1
- package/ui/AssemblySelector.js +12 -10
- package/ui/DrawerWidget.js +2 -1
- package/ui/EditableTypography.d.ts +4 -4
- package/ui/EditableTypography.js +7 -11
- package/ui/LoadingEllipses.d.ts +7 -0
- package/ui/LoadingEllipses.js +38 -0
- package/ui/Logo.d.ts +1 -1
- package/ui/Menu.d.ts +2 -2
- package/ui/Snackbar.d.ts +1 -1
- package/ui/ViewContainer.d.ts +2 -1
- package/ui/ViewContainer.js +34 -22
- package/ui/index.d.ts +1 -0
- package/ui/index.js +3 -1
- package/util/Base1DUtils.js +9 -3
- package/util/Base1DViewModel.d.ts +72 -2
- package/util/Base1DViewModel.js +94 -3
- package/util/blockTypes.d.ts +1 -1
- package/util/calculateDynamicBlocks.js +1 -1
- package/util/calculateStaticBlocks.js +1 -1
- package/util/index.d.ts +3 -1
- package/util/index.js +19 -9
- package/util/io/RemoteFileWithRangeCache.d.ts +1 -2
- package/util/io/RemoteFileWithRangeCache.js +2 -2
- package/util/io/index.js +3 -3
- package/util/jexl.d.ts +1 -1
- package/util/layouts/BaseLayout.d.ts +1 -1
- package/util/layouts/GranularRectLayout.d.ts +7 -2
- package/util/layouts/GranularRectLayout.js +29 -45
- package/util/layouts/MultiLayout.d.ts +2 -2
- package/util/layouts/MultiLayout.js +4 -6
- package/util/offscreenCanvasPonyfill.d.ts +2 -2
- package/util/offscreenCanvasUtils.d.ts +1 -1
- package/util/simpleFeature.d.ts +3 -0
- package/util/stats.d.ts +26 -0
- package/util/stats.js +9 -9
- package/util/tracks.d.ts +2 -2
- package/util/types/index.d.ts +15 -8
- package/util/types/index.js +8 -1
- package/util/types/util.d.ts +5 -5
package/ui/AboutDialog.js
CHANGED
|
@@ -33,6 +33,7 @@ const material_1 = require("@mui/material");
|
|
|
33
33
|
const Close_1 = __importDefault(require("@mui/icons-material/Close"));
|
|
34
34
|
const mui_1 = require("tss-react/mui");
|
|
35
35
|
const configuration_1 = require("../configuration");
|
|
36
|
+
const LoadingEllipses_1 = __importDefault(require("./LoadingEllipses"));
|
|
36
37
|
const util_1 = require("../util");
|
|
37
38
|
const tracks_1 = require("../util/tracks");
|
|
38
39
|
const BaseFeatureDetail_1 = require("../BaseFeatureWidget/BaseFeatureDetail");
|
|
@@ -86,7 +87,7 @@ function FileInfo({ config }) {
|
|
|
86
87
|
.replace(/>/g, '>')}</pre>`,
|
|
87
88
|
}
|
|
88
89
|
: info || {};
|
|
89
|
-
return info !== null ? (react_1.default.createElement(BaseFeatureDetail_1.BaseCard, { title: "File info" }, error ? (react_1.default.createElement(material_1.Typography, { color: "error" }, `${error}`)) : info === undefined ? (
|
|
90
|
+
return info !== null ? (react_1.default.createElement(BaseFeatureDetail_1.BaseCard, { title: "File info" }, error ? (react_1.default.createElement(material_1.Typography, { color: "error" }, `${error}`)) : info === undefined ? (react_1.default.createElement(LoadingEllipses_1.default, { message: "Loading file data" })) : (react_1.default.createElement(BaseFeatureDetail_1.Attributes, { attributes: details })))) : null;
|
|
90
91
|
}
|
|
91
92
|
exports.FileInfo = FileInfo;
|
|
92
93
|
function AboutContents({ config }) {
|
package/ui/App.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { NotificationLevel, SessionWithDrawerWidgets, SnackAction } from '../util';
|
|
3
|
-
import { MenuItem as JBMenuItem } from './
|
|
4
|
-
|
|
3
|
+
import { MenuItem as JBMenuItem } from './Menu';
|
|
4
|
+
type SnackbarMessage = [string, NotificationLevel, SnackAction];
|
|
5
5
|
declare const App: (props: {
|
|
6
6
|
HeaderButtons?: React.ReactElement<any, string | React.JSXElementConstructor<any>> | undefined;
|
|
7
7
|
session: SessionWithDrawerWidgets & {
|
package/ui/App.js
CHANGED
|
@@ -35,13 +35,15 @@ const mobx_react_1 = require("mobx-react");
|
|
|
35
35
|
const mobx_state_tree_1 = require("mobx-state-tree");
|
|
36
36
|
// locals
|
|
37
37
|
const configuration_1 = require("../configuration");
|
|
38
|
+
// ui elements
|
|
38
39
|
const DrawerWidget_1 = __importDefault(require("./DrawerWidget"));
|
|
39
40
|
const DropDownMenu_1 = __importDefault(require("./DropDownMenu"));
|
|
40
41
|
const ErrorMessage_1 = __importDefault(require("./ErrorMessage"));
|
|
42
|
+
const LoadingEllipses_1 = __importDefault(require("./LoadingEllipses"));
|
|
41
43
|
const EditableTypography_1 = __importDefault(require("./EditableTypography"));
|
|
42
|
-
const Logo_1 = require("./Logo");
|
|
43
44
|
const Snackbar_1 = __importDefault(require("./Snackbar"));
|
|
44
45
|
const ViewContainer_1 = __importDefault(require("./ViewContainer"));
|
|
46
|
+
const Logo_1 = require("./Logo");
|
|
45
47
|
const useStyles = (0, mui_1.makeStyles)()(theme => ({
|
|
46
48
|
root: {
|
|
47
49
|
fontFamily: 'Roboto',
|
|
@@ -139,10 +141,10 @@ const ViewLauncher = (0, mobx_react_1.observer)(({ session }) => {
|
|
|
139
141
|
const [value, setValue] = (0, react_1.useState)((_a = viewTypes[0]) === null || _a === void 0 ? void 0 : _a.name);
|
|
140
142
|
return (react_1.default.createElement(material_1.Paper, { className: classes.selectPaper },
|
|
141
143
|
react_1.default.createElement(material_1.Typography, null, "Select a view to launch"),
|
|
142
|
-
react_1.default.createElement(material_1.
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
}, variant: "contained", color: "primary" }, "Launch view")));
|
|
144
|
+
react_1.default.createElement(material_1.FormControl, { style: { margin: 2 } },
|
|
145
|
+
react_1.default.createElement(material_1.Select, { value: value, onChange: event => setValue(event.target.value) }, viewTypes.map(({ name }) => (react_1.default.createElement(material_1.MenuItem, { key: name, value: name }, name))))),
|
|
146
|
+
react_1.default.createElement(material_1.FormControl, { style: { margin: 2 } },
|
|
147
|
+
react_1.default.createElement(material_1.Button, { onClick: () => session.addView(value, {}), variant: "contained", color: "primary" }, "Launch view"))));
|
|
146
148
|
});
|
|
147
149
|
const ViewPanel = (0, mobx_react_1.observer)(({ view, session }) => {
|
|
148
150
|
const { pluginManager } = (0, mobx_state_tree_1.getEnv)(session);
|
|
@@ -151,9 +153,9 @@ const ViewPanel = (0, mobx_react_1.observer)(({ view, session }) => {
|
|
|
151
153
|
throw new Error(`unknown view type ${view.type}`);
|
|
152
154
|
}
|
|
153
155
|
const { ReactComponent } = viewType;
|
|
154
|
-
return (react_1.default.createElement(ViewContainer_1.default, { view: view, onClose: () => session.removeView(view) },
|
|
155
|
-
react_1.default.createElement(react_1.Suspense, { fallback: react_1.default.createElement(
|
|
156
|
-
react_1.default.createElement(ReactComponent, { model: view, session: session, getTrackType: pluginManager.getTrackType }))));
|
|
156
|
+
return (react_1.default.createElement(ViewContainer_1.default, { view: view, onClose: () => session.removeView(view), onMinimize: () => view.setMinimized(!view.minimized) }, !view.minimized ? (react_1.default.createElement(react_error_boundary_1.ErrorBoundary, { FallbackComponent: ({ error }) => react_1.default.createElement(ErrorMessage_1.default, { error: error }) },
|
|
157
|
+
react_1.default.createElement(react_1.Suspense, { fallback: react_1.default.createElement(LoadingEllipses_1.default, null) },
|
|
158
|
+
react_1.default.createElement(ReactComponent, { model: view, session: session, getTrackType: pluginManager.getTrackType })))) : (false)));
|
|
157
159
|
});
|
|
158
160
|
const App = (0, mobx_react_1.observer)((props) => {
|
|
159
161
|
const { session } = props;
|
|
@@ -184,8 +186,7 @@ const App = (0, mobx_react_1.observer)((props) => {
|
|
|
184
186
|
react_1.default.createElement(material_1.AppBar, { className: classes.appBar, position: "static" },
|
|
185
187
|
react_1.default.createElement(AppToolbar, { ...props }))),
|
|
186
188
|
react_1.default.createElement("div", { className: classes.components },
|
|
187
|
-
views.length ? (views.map(view => (react_1.default.createElement(
|
|
188
|
-
react_1.default.createElement(ViewPanel, { view: view, session: session }))))) : (react_1.default.createElement(ViewLauncher, { ...props })),
|
|
189
|
+
views.length ? (views.map(view => (react_1.default.createElement(ViewPanel, { key: `view-${view.id}`, view: view, session: session })))) : (react_1.default.createElement(ViewLauncher, { ...props })),
|
|
189
190
|
react_1.default.createElement("div", { style: { height: 300 } }))),
|
|
190
191
|
activeWidgets.size > 0 && minimized ? (react_1.default.createElement(material_1.Tooltip, { title: "Open drawer widget" },
|
|
191
192
|
react_1.default.createElement(material_1.Fab, { className: drawerPosition === 'right' ? classes.fabRight : classes.fabLeft, color: "primary", "data-testid": "drawer-maximize", onClick: () => session.showWidgetDrawer() },
|
package/ui/AssemblySelector.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { AbstractSessionModel } from '../util';
|
|
|
4
4
|
declare const AssemblySelector: ({ session, onChange, selected, InputProps, extra, }: {
|
|
5
5
|
session: AbstractSessionModel;
|
|
6
6
|
onChange: (arg: string) => void;
|
|
7
|
-
selected
|
|
7
|
+
selected?: string | undefined;
|
|
8
8
|
InputProps?: IIP | undefined;
|
|
9
9
|
extra?: unknown;
|
|
10
10
|
}) => JSX.Element;
|
package/ui/AssemblySelector.js
CHANGED
|
@@ -24,28 +24,30 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
26
|
const react_1 = __importStar(require("react"));
|
|
27
|
-
const mobx_react_1 = require("mobx-react");
|
|
28
27
|
const material_1 = require("@mui/material");
|
|
29
|
-
const
|
|
28
|
+
const mobx_react_1 = require("mobx-react");
|
|
30
29
|
const mui_1 = require("tss-react/mui");
|
|
31
30
|
// locals
|
|
32
31
|
const configuration_1 = require("../configuration");
|
|
33
|
-
const
|
|
32
|
+
const util_1 = require("../util");
|
|
33
|
+
const useStyles = (0, mui_1.makeStyles)()({
|
|
34
34
|
importFormEntry: {
|
|
35
35
|
minWidth: 180,
|
|
36
36
|
},
|
|
37
|
-
})
|
|
37
|
+
});
|
|
38
38
|
const AssemblySelector = (0, mobx_react_1.observer)(({ session, onChange, selected, InputProps, extra = 0, }) => {
|
|
39
39
|
const { classes } = useStyles();
|
|
40
40
|
const { assemblyNames, assemblyManager } = session;
|
|
41
41
|
// constructs a localstorage key based on host/path/config to help
|
|
42
42
|
// remember. non-config assists usage with e.g. embedded apps
|
|
43
43
|
const config = new URLSearchParams(window.location.search).get('config');
|
|
44
|
-
const [lastSelected, setLastSelected] =
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
const [lastSelected, setLastSelected] = typeof jest === 'undefined'
|
|
45
|
+
? (0, util_1.useLocalStorage)(`lastAssembly-${[
|
|
46
|
+
window.location.host + window.location.pathname,
|
|
47
|
+
config,
|
|
48
|
+
extra,
|
|
49
|
+
].join('-')}`, selected)
|
|
50
|
+
: (0, react_1.useState)(selected);
|
|
49
51
|
const selection = assemblyNames.includes(lastSelected || '')
|
|
50
52
|
? lastSelected
|
|
51
53
|
: selected;
|
|
@@ -55,7 +57,7 @@ const AssemblySelector = (0, mobx_react_1.observer)(({ session, onChange, select
|
|
|
55
57
|
}
|
|
56
58
|
}, [selection, onChange, selected]);
|
|
57
59
|
const error = assemblyNames.length ? '' : 'No configured assemblies';
|
|
58
|
-
return (react_1.default.createElement(material_1.TextField, { select: true, label: "Assembly", variant: "outlined", helperText: error || 'Select assembly to view', value:
|
|
60
|
+
return (react_1.default.createElement(material_1.TextField, { select: true, label: "Assembly", variant: "outlined", helperText: error || 'Select assembly to view', value: selection || '', inputProps: { 'data-testid': 'assembly-selector' }, onChange: event => setLastSelected(event.target.value), error: !!error, InputProps: InputProps, disabled: !!error, className: classes.importFormEntry }, assemblyNames.map(name => {
|
|
59
61
|
const assembly = assemblyManager.get(name);
|
|
60
62
|
const displayName = assembly ? (0, configuration_1.getConf)(assembly, 'displayName') : '';
|
|
61
63
|
return (react_1.default.createElement(material_1.MenuItem, { key: name, value: name }, displayName || name));
|
package/ui/DrawerWidget.js
CHANGED
|
@@ -32,6 +32,7 @@ const material_1 = require("@mui/material");
|
|
|
32
32
|
const mui_1 = require("tss-react/mui");
|
|
33
33
|
const mobx_react_1 = require("mobx-react");
|
|
34
34
|
const util_1 = require("../util");
|
|
35
|
+
const LoadingEllipses_1 = __importDefault(require("./LoadingEllipses"));
|
|
35
36
|
// icons
|
|
36
37
|
const Delete_1 = __importDefault(require("@mui/icons-material/Delete"));
|
|
37
38
|
const Close_1 = __importDefault(require("@mui/icons-material/Close"));
|
|
@@ -123,7 +124,7 @@ const DrawerWidget = (0, mobx_react_1.observer)(({ session }) => {
|
|
|
123
124
|
const [toolbarHeight, setToolbarHeight] = (0, react_1.useState)(0);
|
|
124
125
|
return (react_1.default.createElement(Drawer_1.default, { session: session },
|
|
125
126
|
react_1.default.createElement(DrawerHeader, { session: session, setToolbarHeight: setToolbarHeight }),
|
|
126
|
-
react_1.default.createElement(react_1.Suspense, { fallback: react_1.default.createElement(
|
|
127
|
+
react_1.default.createElement(react_1.Suspense, { fallback: react_1.default.createElement(LoadingEllipses_1.default, null) },
|
|
127
128
|
react_1.default.createElement(react_error_boundary_1.ErrorBoundary, { FallbackComponent: ({ error }) => react_1.default.createElement(ErrorMessage_1.default, { error: error }) }, DrawerComponent ? (react_1.default.createElement(DrawerComponent, { model: visibleWidget, session: session, toolbarHeight: toolbarHeight })) : null))));
|
|
128
129
|
});
|
|
129
130
|
exports.default = DrawerWidget;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { TypographyProps } from '@mui/material';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
interface
|
|
3
|
+
type Variant = TypographyProps['variant'];
|
|
4
|
+
type EditableTypographyClassKey = 'input' | 'inputBase' | 'inputRoot' | 'inputFocused';
|
|
5
|
+
interface Props {
|
|
6
6
|
value: string;
|
|
7
7
|
setValue: (value: string) => void;
|
|
8
8
|
variant: Variant;
|
|
9
9
|
classes?: Partial<Record<EditableTypographyClassKey, string>>;
|
|
10
10
|
}
|
|
11
|
-
declare const EditableTypography: React.ForwardRefExoticComponent<
|
|
11
|
+
declare const EditableTypography: React.ForwardRefExoticComponent<Props & React.RefAttributes<HTMLDivElement>>;
|
|
12
12
|
export default EditableTypography;
|
package/ui/EditableTypography.js
CHANGED
|
@@ -48,13 +48,12 @@ const useStyles = (0, mui_1.makeStyles)()(theme => ({
|
|
|
48
48
|
const EditableTypography = react_1.default.forwardRef((props, ref) => {
|
|
49
49
|
const { value, setValue, variant, ...other } = props;
|
|
50
50
|
const [editedValue, setEditedValue] = (0, react_1.useState)();
|
|
51
|
-
const [width, setWidth] = (0, react_1.useState)(0);
|
|
52
51
|
const [sizerNode, setSizerNode] = (0, react_1.useState)(null);
|
|
53
52
|
const [inputNode, setInputNode] = (0, react_1.useState)(null);
|
|
54
53
|
const [blur, setBlur] = (0, react_1.useState)(false);
|
|
55
54
|
(0, react_1.useEffect)(() => {
|
|
56
55
|
if (blur) {
|
|
57
|
-
inputNode
|
|
56
|
+
inputNode === null || inputNode === void 0 ? void 0 : inputNode.blur();
|
|
58
57
|
setBlur(false);
|
|
59
58
|
}
|
|
60
59
|
}, [blur, inputNode]);
|
|
@@ -64,12 +63,11 @@ const EditableTypography = react_1.default.forwardRef((props, ref) => {
|
|
|
64
63
|
const { classes } = useStyles(props, { props });
|
|
65
64
|
const theme = (0, material_1.useTheme)();
|
|
66
65
|
const clientWidth = sizerNode === null || sizerNode === void 0 ? void 0 : sizerNode.clientWidth;
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
66
|
+
const width = clientWidth || 0;
|
|
67
|
+
const val = editedValue === undefined ? value : editedValue;
|
|
70
68
|
return (react_1.default.createElement("div", { ...other, ref: ref },
|
|
71
69
|
react_1.default.createElement("div", { style: { position: 'relative' } },
|
|
72
|
-
react_1.default.createElement(material_1.Typography, { ref: (node) => setSizerNode(node), component: "span", variant: variant, className: classes.typography },
|
|
70
|
+
react_1.default.createElement(material_1.Typography, { ref: (node) => setSizerNode(node), component: "span", variant: variant, className: classes.typography }, val)),
|
|
73
71
|
react_1.default.createElement(material_1.InputBase, { inputRef: node => setInputNode(node), className: classes.inputBase, inputProps: {
|
|
74
72
|
style: {
|
|
75
73
|
width,
|
|
@@ -81,18 +79,16 @@ const EditableTypography = react_1.default.forwardRef((props, ref) => {
|
|
|
81
79
|
input: classes.input,
|
|
82
80
|
root: classes.inputRoot,
|
|
83
81
|
focused: classes.inputFocused,
|
|
84
|
-
}, value:
|
|
82
|
+
}, value: val, onChange: event => setEditedValue(event.target.value), onKeyDown: event => {
|
|
85
83
|
if (event.key === 'Enter') {
|
|
86
|
-
inputNode
|
|
84
|
+
inputNode === null || inputNode === void 0 ? void 0 : inputNode.blur();
|
|
87
85
|
}
|
|
88
86
|
else if (event.key === 'Escape') {
|
|
89
87
|
setEditedValue(undefined);
|
|
90
88
|
setBlur(true);
|
|
91
89
|
}
|
|
92
90
|
}, onBlur: () => {
|
|
93
|
-
|
|
94
|
-
setValue(editedValue);
|
|
95
|
-
}
|
|
91
|
+
setValue(editedValue || '');
|
|
96
92
|
setEditedValue(undefined);
|
|
97
93
|
} })));
|
|
98
94
|
});
|
|
@@ -0,0 +1,38 @@
|
|
|
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 material_1 = require("@mui/material");
|
|
8
|
+
const mui_1 = require("tss-react/mui");
|
|
9
|
+
const tss_react_1 = require("tss-react");
|
|
10
|
+
const useStyles = (0, mui_1.makeStyles)()({
|
|
11
|
+
dots: {
|
|
12
|
+
'&::after': {
|
|
13
|
+
display: 'inline-block',
|
|
14
|
+
content: '""',
|
|
15
|
+
width: '1em',
|
|
16
|
+
textAlign: 'left',
|
|
17
|
+
animation: `${(0, tss_react_1.keyframes) `
|
|
18
|
+
0% {
|
|
19
|
+
content: '';
|
|
20
|
+
}
|
|
21
|
+
25% {
|
|
22
|
+
content: '.';
|
|
23
|
+
}
|
|
24
|
+
50% {
|
|
25
|
+
content: '..';
|
|
26
|
+
}
|
|
27
|
+
75% {
|
|
28
|
+
content: '...';
|
|
29
|
+
}
|
|
30
|
+
`} 1.4s infinite ease-in-out`,
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
function LoadingEllipses({ message = 'Loading', variant = 'body2', ...rest }) {
|
|
35
|
+
const { classes } = useStyles();
|
|
36
|
+
return (react_1.default.createElement(material_1.Typography, { className: classes.dots, ...rest, variant: variant }, `${message || 'Loading'}`));
|
|
37
|
+
}
|
|
38
|
+
exports.default = LoadingEllipses;
|
package/ui/Logo.d.ts
CHANGED
package/ui/Menu.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ interface MenuItemEndDecorationSelectorProps {
|
|
|
8
8
|
checked: boolean;
|
|
9
9
|
disabled?: boolean;
|
|
10
10
|
}
|
|
11
|
-
|
|
11
|
+
type MenuItemEndDecorationProps = MenuItemEndDecorationSubMenuProps | MenuItemEndDecorationSelectorProps;
|
|
12
12
|
export declare function MenuItemEndDecoration(props: MenuItemEndDecorationProps): JSX.Element;
|
|
13
13
|
export interface MenuDivider {
|
|
14
14
|
priority?: number;
|
|
@@ -44,7 +44,7 @@ export interface SubMenuItem extends BaseMenuItem {
|
|
|
44
44
|
type?: 'subMenu';
|
|
45
45
|
subMenu: MenuItem[];
|
|
46
46
|
}
|
|
47
|
-
export
|
|
47
|
+
export type MenuItem = MenuDivider | MenuSubHeader | NormalMenuItem | CheckboxMenuItem | RadioMenuItem | SubMenuItem;
|
|
48
48
|
interface MenuProps extends PopoverProps {
|
|
49
49
|
menuItems: MenuItem[];
|
|
50
50
|
onMenuItemClick: (event: React.MouseEvent<HTMLLIElement, MouseEvent>, callback: Function) => void;
|
package/ui/Snackbar.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import { IAnyStateTreeNode } from 'mobx-state-tree';
|
|
3
3
|
import { AbstractSessionModel, NotificationLevel, SnackAction } from '../util';
|
|
4
|
-
|
|
4
|
+
type SnackbarMessage = [string, NotificationLevel, SnackAction];
|
|
5
5
|
interface SnackbarSession extends AbstractSessionModel {
|
|
6
6
|
snackbarMessages: SnackbarMessage[];
|
|
7
7
|
popSnackbarMessage: () => unknown;
|
package/ui/ViewContainer.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { IBaseViewModel } from '../pluggableElementTypes/models';
|
|
3
|
-
declare const ViewContainer: ({ view, onClose, style, children, }: {
|
|
3
|
+
declare const ViewContainer: ({ view, onClose, onMinimize, style, children, }: {
|
|
4
4
|
view: IBaseViewModel;
|
|
5
5
|
onClose: () => void;
|
|
6
|
+
onMinimize: () => void;
|
|
6
7
|
style?: React.CSSProperties | undefined;
|
|
7
8
|
children: React.ReactNode;
|
|
8
9
|
}) => JSX.Element;
|
package/ui/ViewContainer.js
CHANGED
|
@@ -29,13 +29,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
29
29
|
const react_1 = __importStar(require("react"));
|
|
30
30
|
const material_1 = require("@mui/material");
|
|
31
31
|
const mui_1 = require("tss-react/mui");
|
|
32
|
-
const styles_1 = require("@mui/material/styles");
|
|
33
32
|
const mobx_react_1 = require("mobx-react");
|
|
34
33
|
const mobx_state_tree_1 = require("mobx-state-tree");
|
|
35
34
|
const react_use_measure_1 = __importDefault(require("react-use-measure"));
|
|
36
35
|
// icons
|
|
37
36
|
const Close_1 = __importDefault(require("@mui/icons-material/Close"));
|
|
37
|
+
const Minimize_1 = __importDefault(require("@mui/icons-material/Minimize"));
|
|
38
|
+
const Add_1 = __importDefault(require("@mui/icons-material/Add"));
|
|
38
39
|
const Menu_1 = __importDefault(require("@mui/icons-material/Menu"));
|
|
40
|
+
const ArrowDownward_1 = __importDefault(require("@mui/icons-material/ArrowDownward"));
|
|
41
|
+
const ArrowUpward_1 = __importDefault(require("@mui/icons-material/ArrowUpward"));
|
|
42
|
+
// locals
|
|
43
|
+
const util_1 = require("../util");
|
|
39
44
|
const EditableTypography_1 = __importDefault(require("./EditableTypography"));
|
|
40
45
|
const Menu_2 = __importDefault(require("./Menu"));
|
|
41
46
|
const useStyles = (0, mui_1.makeStyles)()(theme => ({
|
|
@@ -50,14 +55,6 @@ const useStyles = (0, mui_1.makeStyles)()(theme => ({
|
|
|
50
55
|
grow: {
|
|
51
56
|
flexGrow: 1,
|
|
52
57
|
},
|
|
53
|
-
iconRoot: {
|
|
54
|
-
'&:hover': {
|
|
55
|
-
backgroundColor: (0, styles_1.alpha)(theme.palette.secondary.contrastText, theme.palette.action.hoverOpacity),
|
|
56
|
-
'@media (hover: none)': {
|
|
57
|
-
backgroundColor: 'transparent',
|
|
58
|
-
},
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
58
|
input: {
|
|
62
59
|
paddingBottom: 0,
|
|
63
60
|
paddingTop: 2,
|
|
@@ -78,17 +75,34 @@ const useStyles = (0, mui_1.makeStyles)()(theme => ({
|
|
|
78
75
|
const ViewMenu = (0, mobx_react_1.observer)(({ model, IconButtonProps, IconProps, }) => {
|
|
79
76
|
const [anchorEl, setAnchorEl] = (0, react_1.useState)();
|
|
80
77
|
const { menuItems } = model;
|
|
81
|
-
|
|
82
|
-
const items =
|
|
83
|
-
|
|
84
|
-
|
|
78
|
+
const session = (0, util_1.getSession)(model);
|
|
79
|
+
const items = [
|
|
80
|
+
...(session.views.length > 1
|
|
81
|
+
? [
|
|
82
|
+
{
|
|
83
|
+
label: 'Move view up',
|
|
84
|
+
icon: ArrowUpward_1.default,
|
|
85
|
+
onClick: () => session.moveViewUp(model.id),
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
label: 'Move view down',
|
|
89
|
+
icon: ArrowDownward_1.default,
|
|
90
|
+
onClick: () => session.moveViewDown(model.id),
|
|
91
|
+
},
|
|
92
|
+
]
|
|
93
|
+
: []),
|
|
94
|
+
// <=1.3.3 didn't use a function, so check as value also
|
|
95
|
+
...((typeof menuItems === 'function' ? menuItems() : menuItems) || []),
|
|
96
|
+
];
|
|
97
|
+
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
98
|
+
react_1.default.createElement(material_1.IconButton, { ...IconButtonProps, onClick: event => setAnchorEl(event.currentTarget), "data-testid": "view_menu_icon" },
|
|
85
99
|
react_1.default.createElement(Menu_1.default, { ...IconProps, fontSize: "small" })),
|
|
86
100
|
react_1.default.createElement(Menu_2.default, { anchorEl: anchorEl, open: Boolean(anchorEl), onMenuItemClick: (_event, callback) => {
|
|
87
101
|
callback();
|
|
88
102
|
setAnchorEl(undefined);
|
|
89
|
-
}, onClose: () => setAnchorEl(undefined), menuItems:
|
|
103
|
+
}, onClose: () => setAnchorEl(undefined), menuItems: items })));
|
|
90
104
|
});
|
|
91
|
-
const ViewContainer = (0, mobx_react_1.observer)(({ view, onClose, style, children, }) => {
|
|
105
|
+
const ViewContainer = (0, mobx_react_1.observer)(({ view, onClose, onMinimize, style, children, }) => {
|
|
92
106
|
var _a;
|
|
93
107
|
const { classes } = useStyles();
|
|
94
108
|
const theme = (0, material_1.useTheme)();
|
|
@@ -109,24 +123,22 @@ const ViewContainer = (0, mobx_react_1.observer)(({ view, onClose, style, childr
|
|
|
109
123
|
}, []);
|
|
110
124
|
return (react_1.default.createElement(material_1.Paper, { ref: ref, elevation: 12, className: classes.viewContainer, style: { ...style, padding: `0px ${padWidth} ${padWidth}` } },
|
|
111
125
|
react_1.default.createElement("div", { ref: scrollRef, style: { display: 'flex' } },
|
|
112
|
-
react_1.default.createElement(ViewMenu, { model: view,
|
|
113
|
-
classes: { root: classes.iconRoot },
|
|
114
|
-
edge: 'start',
|
|
115
|
-
}, IconProps: { className: classes.icon } }),
|
|
126
|
+
react_1.default.createElement(ViewMenu, { model: view, IconProps: { className: classes.icon } }),
|
|
116
127
|
react_1.default.createElement("div", { className: classes.grow }),
|
|
117
128
|
react_1.default.createElement(material_1.Tooltip, { title: "Rename view", arrow: true },
|
|
118
|
-
react_1.default.createElement(EditableTypography_1.default, { value: view.displayName ||
|
|
129
|
+
react_1.default.createElement(EditableTypography_1.default, { value: (view.displayName ||
|
|
119
130
|
(
|
|
120
131
|
// @ts-ignore
|
|
121
132
|
(_a = view.assemblyNames) === null || _a === void 0 ? void 0 : _a.join(',')) ||
|
|
122
|
-
'Untitled view', setValue: val => view.setDisplayName(val), variant: "body2", classes: {
|
|
133
|
+
'Untitled view') + (view.minimized ? ' (minimized)' : ''), setValue: val => view.setDisplayName(val), variant: "body2", classes: {
|
|
123
134
|
input: classes.input,
|
|
124
135
|
inputBase: classes.inputBase,
|
|
125
136
|
inputRoot: classes.inputRoot,
|
|
126
137
|
inputFocused: classes.inputFocused,
|
|
127
138
|
} })),
|
|
128
139
|
react_1.default.createElement("div", { className: classes.grow }),
|
|
129
|
-
react_1.default.createElement(material_1.IconButton, { "data-testid": "
|
|
140
|
+
react_1.default.createElement(material_1.IconButton, { "data-testid": "minimize_view", onClick: onMinimize }, view.minimized ? (react_1.default.createElement(Add_1.default, { className: classes.icon, fontSize: "small" })) : (react_1.default.createElement(Minimize_1.default, { className: classes.icon, fontSize: "small" }))),
|
|
141
|
+
react_1.default.createElement(material_1.IconButton, { "data-testid": "close_view", onClick: onClose },
|
|
130
142
|
react_1.default.createElement(Close_1.default, { className: classes.icon, fontSize: "small" }))),
|
|
131
143
|
react_1.default.createElement(material_1.Paper, null, children)));
|
|
132
144
|
});
|
package/ui/index.d.ts
CHANGED
|
@@ -14,4 +14,5 @@ export { default as FatalErrorDialog } from './FatalErrorDialog';
|
|
|
14
14
|
export { default as Menu } from './Menu';
|
|
15
15
|
export { default as CascadingMenu } from './CascadingMenu';
|
|
16
16
|
export { default as SanitizedHTML } from './SanitizedHTML';
|
|
17
|
+
export { default as LoadingEllipses } from './LoadingEllipses';
|
|
17
18
|
export * from './Menu';
|
package/ui/index.js
CHANGED
|
@@ -17,7 +17,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
17
17
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
18
|
};
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
-
exports.SanitizedHTML = exports.CascadingMenu = exports.Menu = exports.FatalErrorDialog = exports.Tooltip = exports.FactoryResetDialog = exports.EditableTypography = exports.ResizeHandle = exports.PrerenderedCanvas = exports.FileSelector = exports.AssemblySelector = exports.ErrorMessage = exports.ReturnToImportFormDialog = exports.App = exports.Logomark = exports.LogoFull = void 0;
|
|
20
|
+
exports.LoadingEllipses = exports.SanitizedHTML = exports.CascadingMenu = exports.Menu = exports.FatalErrorDialog = exports.Tooltip = exports.FactoryResetDialog = exports.EditableTypography = exports.ResizeHandle = exports.PrerenderedCanvas = exports.FileSelector = exports.AssemblySelector = exports.ErrorMessage = exports.ReturnToImportFormDialog = exports.App = exports.Logomark = exports.LogoFull = void 0;
|
|
21
21
|
__exportStar(require("./theme"), exports);
|
|
22
22
|
var Logo_1 = require("./Logo");
|
|
23
23
|
Object.defineProperty(exports, "LogoFull", { enumerable: true, get: function () { return Logo_1.LogoFull; } });
|
|
@@ -50,4 +50,6 @@ var CascadingMenu_1 = require("./CascadingMenu");
|
|
|
50
50
|
Object.defineProperty(exports, "CascadingMenu", { enumerable: true, get: function () { return __importDefault(CascadingMenu_1).default; } });
|
|
51
51
|
var SanitizedHTML_1 = require("./SanitizedHTML");
|
|
52
52
|
Object.defineProperty(exports, "SanitizedHTML", { enumerable: true, get: function () { return __importDefault(SanitizedHTML_1).default; } });
|
|
53
|
+
var LoadingEllipses_1 = require("./LoadingEllipses");
|
|
54
|
+
Object.defineProperty(exports, "LoadingEllipses", { enumerable: true, get: function () { return __importDefault(LoadingEllipses_1).default; } });
|
|
53
55
|
__exportStar(require("./Menu"), exports);
|
package/util/Base1DUtils.js
CHANGED
|
@@ -26,10 +26,16 @@ function moveTo(self, start, end) {
|
|
|
26
26
|
if (!start || !end) {
|
|
27
27
|
return;
|
|
28
28
|
}
|
|
29
|
-
const { width, interRegionPaddingWidth } = self;
|
|
29
|
+
const { width, interRegionPaddingWidth, displayedRegions, bpPerPx, minimumBlockWidth, } = self;
|
|
30
30
|
const len = lengthBetween(self, start, end);
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
let numBlocksWideEnough = 0;
|
|
32
|
+
for (let i = start.index; i < end.index; i++) {
|
|
33
|
+
const r = displayedRegions[i];
|
|
34
|
+
if ((r.end - r.start) / bpPerPx > minimumBlockWidth) {
|
|
35
|
+
numBlocksWideEnough++;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const targetBpPerPx = len / (width - interRegionPaddingWidth * numBlocksWideEnough);
|
|
33
39
|
const newBpPerPx = self.zoomTo(targetBpPerPx);
|
|
34
40
|
// If our target bpPerPx was smaller than the allowed minBpPerPx, adjust
|
|
35
41
|
// the scroll so the requested range is in the middle of the screen
|
|
@@ -22,21 +22,60 @@ declare const Base1DView: import("mobx-state-tree").IModelType<{
|
|
|
22
22
|
features: Feature[] | undefined;
|
|
23
23
|
volatileWidth: number;
|
|
24
24
|
} & {
|
|
25
|
+
/**
|
|
26
|
+
* #action
|
|
27
|
+
*/
|
|
25
28
|
setDisplayedRegions(regions: IRegion[]): void;
|
|
29
|
+
/**
|
|
30
|
+
* #action
|
|
31
|
+
*/
|
|
26
32
|
setBpPerPx(val: number): void;
|
|
33
|
+
/**
|
|
34
|
+
* #action
|
|
35
|
+
*/
|
|
27
36
|
setVolatileWidth(width: number): void;
|
|
28
37
|
} & {
|
|
38
|
+
/**
|
|
39
|
+
* #getter
|
|
40
|
+
*/
|
|
29
41
|
readonly width: number;
|
|
42
|
+
/**
|
|
43
|
+
* #getter
|
|
44
|
+
*/
|
|
30
45
|
readonly assemblyNames: string[];
|
|
46
|
+
/**
|
|
47
|
+
* #getter
|
|
48
|
+
*/
|
|
31
49
|
readonly displayedRegionsTotalPx: number;
|
|
50
|
+
/**
|
|
51
|
+
* #getter
|
|
52
|
+
*/
|
|
32
53
|
readonly maxOffset: number;
|
|
54
|
+
/**
|
|
55
|
+
* #getter
|
|
56
|
+
*/
|
|
33
57
|
readonly minOffset: number;
|
|
58
|
+
/**
|
|
59
|
+
* #getter
|
|
60
|
+
*/
|
|
34
61
|
readonly totalBp: number;
|
|
35
62
|
} & {
|
|
63
|
+
/**
|
|
64
|
+
* #getter
|
|
65
|
+
*/
|
|
36
66
|
readonly dynamicBlocks: import("./blockTypes").BlockSet;
|
|
67
|
+
/**
|
|
68
|
+
* #getter
|
|
69
|
+
*/
|
|
37
70
|
readonly staticBlocks: import("./blockTypes").BlockSet;
|
|
71
|
+
/**
|
|
72
|
+
* #getter
|
|
73
|
+
*/
|
|
38
74
|
readonly currBp: number;
|
|
39
75
|
} & {
|
|
76
|
+
/**
|
|
77
|
+
* #method
|
|
78
|
+
*/
|
|
40
79
|
pxToBp(px: number): {
|
|
41
80
|
coord: number;
|
|
42
81
|
index: number;
|
|
@@ -48,22 +87,53 @@ declare const Base1DView: import("mobx-state-tree").IModelType<{
|
|
|
48
87
|
end: number;
|
|
49
88
|
reversed: boolean;
|
|
50
89
|
};
|
|
90
|
+
/**
|
|
91
|
+
* #method
|
|
92
|
+
*/
|
|
51
93
|
bpToPx({ refName, coord, regionNumber, }: {
|
|
52
94
|
refName: string;
|
|
53
95
|
coord: number;
|
|
54
96
|
regionNumber?: number | undefined;
|
|
55
97
|
}): number | undefined;
|
|
56
98
|
} & {
|
|
99
|
+
/**
|
|
100
|
+
* #action
|
|
101
|
+
*/
|
|
57
102
|
setFeatures(features: Feature[]): void;
|
|
103
|
+
/**
|
|
104
|
+
* #action
|
|
105
|
+
* this makes a zoomed out view that shows all displayedRegions that makes
|
|
106
|
+
* the overview bar square with the scale bar
|
|
107
|
+
*/
|
|
58
108
|
showAllRegions(): void;
|
|
109
|
+
/**
|
|
110
|
+
* #action
|
|
111
|
+
*/
|
|
59
112
|
zoomOut(): void;
|
|
113
|
+
/**
|
|
114
|
+
* #action
|
|
115
|
+
*/
|
|
60
116
|
zoomIn(): void;
|
|
117
|
+
/**
|
|
118
|
+
* #action
|
|
119
|
+
*/
|
|
61
120
|
zoomTo(newBpPerPx: number, offset?: number): number;
|
|
121
|
+
/**
|
|
122
|
+
* #action
|
|
123
|
+
*/
|
|
62
124
|
scrollTo(offsetPx: number): number;
|
|
125
|
+
/**
|
|
126
|
+
* #action
|
|
127
|
+
*/
|
|
63
128
|
centerAt(coord: number, refName: string | undefined, regionNumber: number): void;
|
|
129
|
+
/**
|
|
130
|
+
* #action
|
|
131
|
+
* note: the scroll is clamped to keep the view on the main screen
|
|
132
|
+
*/
|
|
64
133
|
scroll(distance: number): number;
|
|
65
134
|
} & {
|
|
66
135
|
/**
|
|
136
|
+
* #action
|
|
67
137
|
* offset is the base-pair-offset in the displayed region, index is the index of the
|
|
68
138
|
* displayed region in the linear genome view
|
|
69
139
|
*
|
|
@@ -72,6 +142,6 @@ declare const Base1DView: import("mobx-state-tree").IModelType<{
|
|
|
72
142
|
*/
|
|
73
143
|
moveTo(start?: BpOffset, end?: BpOffset): void;
|
|
74
144
|
}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;
|
|
75
|
-
export
|
|
76
|
-
export
|
|
145
|
+
export type Base1DViewStateModel = typeof Base1DView;
|
|
146
|
+
export type Base1DViewModel = Instance<Base1DViewStateModel>;
|
|
77
147
|
export default Base1DView;
|