@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.
Files changed (104) hide show
  1. package/BaseFeatureWidget/BaseFeatureDetail.d.ts +3 -2
  2. package/BaseFeatureWidget/BaseFeatureDetail.js +43 -28
  3. package/BaseFeatureWidget/SequenceBox.js +4 -8
  4. package/BaseFeatureWidget/SequenceFeatureDetails.js +2 -1
  5. package/Plugin.d.ts +1 -1
  6. package/PluginLoader.d.ts +2 -2
  7. package/PluginManager.d.ts +6 -6
  8. package/ReExports/modules.d.ts +3 -3
  9. package/assemblyManager/assembly.d.ts +23 -17
  10. package/assemblyManager/assembly.js +75 -76
  11. package/assemblyManager/assemblyConfigSchema.d.ts +6 -2
  12. package/assemblyManager/assemblyConfigSchema.js +39 -2
  13. package/assemblyManager/assemblyManager.d.ts +76 -214
  14. package/assemblyManager/assemblyManager.js +17 -39
  15. package/configuration/configurationSchema.d.ts +2 -2
  16. package/data_adapters/BaseAdapter.d.ts +2 -2
  17. package/data_adapters/CytobandAdapter.js +7 -0
  18. package/data_adapters/dataAdapterCache.d.ts +1 -1
  19. package/package.json +2 -2
  20. package/pluggableElementTypes/AdapterType.d.ts +1 -1
  21. package/pluggableElementTypes/AddTrackWorkflowType.d.ts +2 -2
  22. package/pluggableElementTypes/RpcMethodType.d.ts +1 -1
  23. package/pluggableElementTypes/ViewType.d.ts +2 -2
  24. package/pluggableElementTypes/index.d.ts +2 -2
  25. package/pluggableElementTypes/models/BaseConnectionModelFactory.d.ts +23 -2
  26. package/pluggableElementTypes/models/BaseConnectionModelFactory.js +24 -2
  27. package/pluggableElementTypes/models/BaseDisplayModel.d.ts +62 -3
  28. package/pluggableElementTypes/models/BaseDisplayModel.js +138 -92
  29. package/pluggableElementTypes/models/BaseTrackModel.d.ts +49 -4
  30. package/pluggableElementTypes/models/BaseTrackModel.js +77 -26
  31. package/pluggableElementTypes/models/BaseViewModel.d.ts +22 -0
  32. package/pluggableElementTypes/models/BaseViewModel.js +41 -2
  33. package/pluggableElementTypes/models/InternetAccountModel.d.ts +53 -6
  34. package/pluggableElementTypes/models/InternetAccountModel.js +57 -6
  35. package/pluggableElementTypes/models/baseConnectionConfig.js +17 -1
  36. package/pluggableElementTypes/models/baseInternetAccountConfig.d.ts +2 -2
  37. package/pluggableElementTypes/models/baseInternetAccountConfig.js +27 -1
  38. package/pluggableElementTypes/models/baseTrackConfig.d.ts +5 -2
  39. package/pluggableElementTypes/models/baseTrackConfig.js +52 -1
  40. package/pluggableElementTypes/renderers/BoxRendererType.d.ts +2 -2
  41. package/pluggableElementTypes/renderers/BoxRendererType.js +2 -0
  42. package/pluggableElementTypes/renderers/ComparativeServerSideRendererType.d.ts +1 -1
  43. package/pluggableElementTypes/renderers/RendererType.d.ts +1 -1
  44. package/pluggableElementTypes/renderers/ServerSideRendererType.d.ts +1 -1
  45. package/pluggableElementTypes/renderers/util/serializableFilterChain.d.ts +2 -2
  46. package/rpc/MainThreadRpcDriver.d.ts +1 -1
  47. package/rpc/MainThreadRpcDriver.js +2 -2
  48. package/rpc/RpcManager.d.ts +2 -2
  49. package/rpc/WebWorkerRpcDriver.d.ts +5 -4
  50. package/rpc/WebWorkerRpcDriver.js +2 -2
  51. package/rpc/baseRpcConfig.d.ts +2 -0
  52. package/rpc/baseRpcConfig.js +18 -0
  53. package/rpc/configSchema.js +16 -10
  54. package/rpc/coreRpcMethods.d.ts +14 -14
  55. package/rpc/coreRpcMethods.js +60 -63
  56. package/rpc/mainThreadRpcConfig.d.ts +2 -0
  57. package/rpc/mainThreadRpcConfig.js +19 -0
  58. package/rpc/remoteAbortSignals.d.ts +1 -1
  59. package/rpc/webWorkerRpcConfig.d.ts +2 -0
  60. package/rpc/webWorkerRpcConfig.js +19 -0
  61. package/tsconfig.build.tsbuildinfo +1 -1
  62. package/ui/AboutDialog.js +2 -1
  63. package/ui/App.d.ts +2 -2
  64. package/ui/App.js +11 -10
  65. package/ui/AssemblySelector.d.ts +1 -1
  66. package/ui/AssemblySelector.js +12 -10
  67. package/ui/DrawerWidget.js +2 -1
  68. package/ui/EditableTypography.d.ts +4 -4
  69. package/ui/EditableTypography.js +7 -11
  70. package/ui/LoadingEllipses.d.ts +7 -0
  71. package/ui/LoadingEllipses.js +38 -0
  72. package/ui/Logo.d.ts +1 -1
  73. package/ui/Menu.d.ts +2 -2
  74. package/ui/Snackbar.d.ts +1 -1
  75. package/ui/ViewContainer.d.ts +2 -1
  76. package/ui/ViewContainer.js +34 -22
  77. package/ui/index.d.ts +1 -0
  78. package/ui/index.js +3 -1
  79. package/util/Base1DUtils.js +9 -3
  80. package/util/Base1DViewModel.d.ts +72 -2
  81. package/util/Base1DViewModel.js +94 -3
  82. package/util/blockTypes.d.ts +1 -1
  83. package/util/calculateDynamicBlocks.js +1 -1
  84. package/util/calculateStaticBlocks.js +1 -1
  85. package/util/index.d.ts +3 -1
  86. package/util/index.js +19 -9
  87. package/util/io/RemoteFileWithRangeCache.d.ts +1 -2
  88. package/util/io/RemoteFileWithRangeCache.js +2 -2
  89. package/util/io/index.js +3 -3
  90. package/util/jexl.d.ts +1 -1
  91. package/util/layouts/BaseLayout.d.ts +1 -1
  92. package/util/layouts/GranularRectLayout.d.ts +7 -2
  93. package/util/layouts/GranularRectLayout.js +29 -45
  94. package/util/layouts/MultiLayout.d.ts +2 -2
  95. package/util/layouts/MultiLayout.js +4 -6
  96. package/util/offscreenCanvasPonyfill.d.ts +2 -2
  97. package/util/offscreenCanvasUtils.d.ts +1 -1
  98. package/util/simpleFeature.d.ts +3 -0
  99. package/util/stats.d.ts +26 -0
  100. package/util/stats.js +9 -9
  101. package/util/tracks.d.ts +2 -2
  102. package/util/types/index.d.ts +15 -8
  103. package/util/types/index.js +8 -1
  104. 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, '&gt;')}</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 ? ('Loading file data...') : (react_1.default.createElement(BaseFeatureDetail_1.Attributes, { attributes: details })))) : null;
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 './index';
4
- declare type SnackbarMessage = [string, NotificationLevel, SnackAction];
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.Select, { value: value, onChange: event => setValue(event.target.value) }, viewTypes.map(({ name }) => (react_1.default.createElement(material_1.MenuItem, { key: name, value: name }, name)))),
143
- react_1.default.createElement(material_1.Button, { onClick: () => {
144
- session.addView(value, {});
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("div", null, "Loading...") },
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(react_error_boundary_1.ErrorBoundary, { key: `view-${view.id}`, FallbackComponent: ({ error }) => (react_1.default.createElement(ErrorMessage_1.default, { error: error })) },
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() },
@@ -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: string | undefined;
7
+ selected?: string | undefined;
8
8
  InputProps?: IIP | undefined;
9
9
  extra?: unknown;
10
10
  }) => JSX.Element;
@@ -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 util_1 = require("@jbrowse/core/util");
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 useStyles = (0, mui_1.makeStyles)()(() => ({
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] = (0, util_1.useLocalStorage)(`lastAssembly-${[
45
- window.location.host + window.location.pathname,
46
- config,
47
- extra,
48
- ].join('-')}`, selected);
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: error ? '' : selection, inputProps: { 'data-testid': 'assembly-selector' }, onChange: event => setLastSelected(event.target.value), error: !!error, InputProps: InputProps, disabled: !!error, className: classes.importFormEntry }, assemblyNames.map(name => {
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));
@@ -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("div", null, "Loading...") },
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
- declare type Variant = TypographyProps['variant'];
4
- declare type EditableTypographyClassKey = 'input' | 'inputBase' | 'inputRoot' | 'inputFocused';
5
- interface EditableTypographyPropTypes {
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<EditableTypographyPropTypes & React.RefAttributes<HTMLDivElement>>;
11
+ declare const EditableTypography: React.ForwardRefExoticComponent<Props & React.RefAttributes<HTMLDivElement>>;
12
12
  export default EditableTypography;
@@ -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 && inputNode.blur();
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
- if (clientWidth && clientWidth !== width) {
68
- setWidth(clientWidth);
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 }, editedValue === undefined ? value : editedValue)),
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: editedValue === undefined ? value : editedValue, onChange: event => setEditedValue(event.target.value), onKeyDown: event => {
82
+ }, value: val, onChange: event => setEditedValue(event.target.value), onKeyDown: event => {
85
83
  if (event.key === 'Enter') {
86
- inputNode && inputNode.blur();
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
- if (editedValue && editedValue !== value) {
94
- setValue(editedValue);
95
- }
91
+ setValue(editedValue || '');
96
92
  setEditedValue(undefined);
97
93
  } })));
98
94
  });
@@ -0,0 +1,7 @@
1
+ /// <reference types="react" />
2
+ import { TypographyProps } from '@mui/material';
3
+ interface Props extends TypographyProps {
4
+ message?: string;
5
+ }
6
+ export default function LoadingEllipses({ message, variant, ...rest }: Props): JSX.Element;
7
+ export {};
@@ -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
@@ -1,5 +1,5 @@
1
1
  /// <reference types="react" />
2
- declare type LogoVariant = 'color' | 'black' | 'white';
2
+ type LogoVariant = 'color' | 'black' | 'white';
3
3
  interface LogoProps {
4
4
  variant?: LogoVariant;
5
5
  }
package/ui/Menu.d.ts CHANGED
@@ -8,7 +8,7 @@ interface MenuItemEndDecorationSelectorProps {
8
8
  checked: boolean;
9
9
  disabled?: boolean;
10
10
  }
11
- declare type MenuItemEndDecorationProps = MenuItemEndDecorationSubMenuProps | MenuItemEndDecorationSelectorProps;
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 declare type MenuItem = MenuDivider | MenuSubHeader | NormalMenuItem | CheckboxMenuItem | RadioMenuItem | SubMenuItem;
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
- declare type SnackbarMessage = [string, NotificationLevel, SnackAction];
4
+ type SnackbarMessage = [string, NotificationLevel, SnackAction];
5
5
  interface SnackbarSession extends AbstractSessionModel {
6
6
  snackbarMessages: SnackbarMessage[];
7
7
  popSnackbarMessage: () => unknown;
@@ -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;
@@ -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
- // <=1.3.3 didn't use a function
82
- const items = typeof menuItems === 'function' ? menuItems() : menuItems;
83
- return (items === null || items === void 0 ? void 0 : items.length) ? (react_1.default.createElement(react_1.default.Fragment, null,
84
- react_1.default.createElement(material_1.IconButton, { ...IconButtonProps, style: { padding: 3 }, onClick: event => setAnchorEl(event.currentTarget), "data-testid": "view_menu_icon", size: "small" },
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: model.menuItems() }))) : null;
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, IconButtonProps: {
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": "close_view", classes: { root: classes.iconRoot }, edge: "end", size: "small", onClick: onClose },
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);
@@ -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
- const numBlocks = end.index - start.index;
32
- const targetBpPerPx = len / (width - interRegionPaddingWidth * numBlocks);
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 declare type Base1DViewStateModel = typeof Base1DView;
76
- export declare type Base1DViewModel = Instance<Base1DViewStateModel>;
145
+ export type Base1DViewStateModel = typeof Base1DView;
146
+ export type Base1DViewModel = Instance<Base1DViewStateModel>;
77
147
  export default Base1DView;