@jbrowse/core 2.8.0 → 2.10.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/BaseFeatureWidget/BaseFeatureDetail/DataGridDetails.js +2 -2
- package/BaseFeatureWidget/BaseFeatureDetail/index.js +2 -1
- package/BaseFeatureWidget/index.d.ts +86 -1
- package/BaseFeatureWidget/index.js +62 -9
- package/PluginManager.d.ts +20 -1
- package/PluginManager.js +0 -1
- package/assemblyManager/assembly.d.ts +4 -3
- package/assemblyManager/assembly.js +16 -20
- package/assemblyManager/assemblyManager.d.ts +136 -23
- package/assemblyManager/assemblyManager.js +1 -1
- package/data_adapters/dataAdapterCache.d.ts +1 -0
- package/data_adapters/dataAdapterCache.js +4 -3
- package/package.json +2 -4
- package/pluggableElementTypes/models/baseTrackConfig.d.ts +8 -0
- package/pluggableElementTypes/models/baseTrackConfig.js +8 -0
- package/rpc/BaseRpcDriver.js +1 -1
- package/rpc/WebWorkerRpcDriver.d.ts +1 -0
- package/tsconfig.build.tsbuildinfo +1 -1
- package/ui/CascadingMenu.d.ts +1 -0
- package/ui/CascadingMenu.js +20 -16
- package/ui/CascadingMenuButton.d.ts +5 -1
- package/ui/CascadingMenuButton.js +44 -4
- package/ui/FileSelector/FileSelector.js +47 -33
- package/ui/Menu.d.ts +2 -1
- package/ui/Menu.js +7 -10
- package/ui/MenuButton.d.ts +4 -1
- package/ui/MenuButton.js +8 -2
- package/ui/SanitizedHTML.d.ts +2 -1
- package/ui/SanitizedHTML.js +2 -2
- package/util/analytics.js +1 -1
- package/util/index.d.ts +7 -4
- package/util/index.js +20 -4
- package/util/io/RemoteFileWithRangeCache.d.ts +1 -0
- package/util/io/RemoteFileWithRangeCache.js +3 -3
package/ui/CascadingMenu.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { MenuItem as JBMenuItem } from './Menu';
|
|
|
3
3
|
import { PopupState } from 'material-ui-popup-state/hooks';
|
|
4
4
|
declare function CascadingMenuChildren(props: {
|
|
5
5
|
onMenuItemClick: Function;
|
|
6
|
+
closeAfterItemClick?: boolean;
|
|
6
7
|
menuItems: JBMenuItem[];
|
|
7
8
|
popupState: PopupState;
|
|
8
9
|
}): React.JSX.Element;
|
package/ui/CascadingMenu.js
CHANGED
|
@@ -36,19 +36,20 @@ const CascadingContext = react_1.default.createContext({
|
|
|
36
36
|
parentPopupState: null,
|
|
37
37
|
rootPopupState: null,
|
|
38
38
|
});
|
|
39
|
-
function CascadingMenuItem({ onClick, ...props }) {
|
|
39
|
+
function CascadingMenuItem({ onClick, closeAfterItemClick, ...props }) {
|
|
40
40
|
const { rootPopupState } = (0, react_1.useContext)(CascadingContext);
|
|
41
41
|
if (!rootPopupState) {
|
|
42
42
|
throw new Error('must be used inside a CascadingMenu');
|
|
43
43
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
return (react_1.default.createElement(material_1.MenuItem, { ...props, onClick: event => {
|
|
45
|
+
if (closeAfterItemClick) {
|
|
46
|
+
rootPopupState.close();
|
|
47
|
+
}
|
|
48
|
+
onClick === null || onClick === void 0 ? void 0 : onClick(event);
|
|
49
|
+
} }));
|
|
49
50
|
}
|
|
50
|
-
function CascadingSubmenu({ title, inset, popupId, ...props }) {
|
|
51
|
-
const { parentPopupState } = react_1.
|
|
51
|
+
function CascadingSubmenu({ title, Icon, inset, popupId, ...props }) {
|
|
52
|
+
const { parentPopupState } = (0, react_1.useContext)(CascadingContext);
|
|
52
53
|
const popupState = (0, hooks_1.usePopupState)({
|
|
53
54
|
popupId,
|
|
54
55
|
variant: 'popover',
|
|
@@ -56,6 +57,8 @@ function CascadingSubmenu({ title, inset, popupId, ...props }) {
|
|
|
56
57
|
});
|
|
57
58
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
58
59
|
react_1.default.createElement(material_1.MenuItem, { ...(0, hooks_1.bindHover)(popupState), ...(0, hooks_1.bindFocus)(popupState) },
|
|
60
|
+
Icon ? (react_1.default.createElement(material_1.ListItemIcon, null,
|
|
61
|
+
react_1.default.createElement(Icon, null))) : null,
|
|
59
62
|
react_1.default.createElement(material_1.ListItemText, { primary: title, inset: inset }),
|
|
60
63
|
react_1.default.createElement(ChevronRight_1.default, null)),
|
|
61
64
|
react_1.default.createElement(CascadingSubmenuHover, { ...props, anchorOrigin: { vertical: 'top', horizontal: 'right' }, transformOrigin: { vertical: 'top', horizontal: 'left' }, popupState: popupState })));
|
|
@@ -70,8 +73,8 @@ function CascadingSubmenuHover({ popupState, onMenuItemClick, menuItems, classes
|
|
|
70
73
|
react_1.default.createElement(HoverMenu_1.default, { ...props, ...(0, hooks_1.bindMenu)(popupState) })));
|
|
71
74
|
}
|
|
72
75
|
function CascadingMenu({ popupState, onMenuItemClick, menuItems, ...props }) {
|
|
73
|
-
const { rootPopupState } = react_1.
|
|
74
|
-
const context = react_1.
|
|
76
|
+
const { rootPopupState } = (0, react_1.useContext)(CascadingContext);
|
|
77
|
+
const context = (0, react_1.useMemo)(() => ({
|
|
75
78
|
rootPopupState: rootPopupState || popupState,
|
|
76
79
|
parentPopupState: popupState,
|
|
77
80
|
}), [rootPopupState, popupState]);
|
|
@@ -87,16 +90,16 @@ function EndDecoration({ item }) {
|
|
|
87
90
|
}
|
|
88
91
|
return null;
|
|
89
92
|
}
|
|
90
|
-
function CascadingMenuList({ onMenuItemClick, menuItems, ...props }) {
|
|
93
|
+
function CascadingMenuList({ onMenuItemClick, closeAfterItemClick, menuItems, ...props }) {
|
|
91
94
|
function handleClick(callback) {
|
|
92
95
|
return (event) => {
|
|
93
96
|
onMenuItemClick(event, callback);
|
|
94
97
|
};
|
|
95
98
|
}
|
|
96
|
-
const hasIcon = menuItems.some(
|
|
99
|
+
const hasIcon = menuItems.some(m => 'icon' in m && m.icon);
|
|
97
100
|
return (react_1.default.createElement(react_1.default.Fragment, null, menuItems.map((item, idx) => {
|
|
98
|
-
return 'subMenu' in item ? (react_1.default.createElement(CascadingSubmenu, { key: `subMenu-${item.label}-${idx}`, popupId: `subMenu-${item.label}`, title: item.label, inset: hasIcon, onMenuItemClick: onMenuItemClick, menuItems: item.subMenu },
|
|
99
|
-
react_1.default.createElement(CascadingMenuList, { ...props, onMenuItemClick: onMenuItemClick, menuItems: item.subMenu }))) : item.type === 'divider' ? (react_1.default.createElement(material_1.Divider, { key: `divider-${idx}`, component: "li" })) : item.type === 'subHeader' ? (react_1.default.createElement(material_1.ListSubheader, { key: `subHeader-${item.label}-${idx}` }, item.label)) : (react_1.default.createElement(CascadingMenuItem, { key: `${item.label}-${idx}`, onClick: 'onClick' in item ? handleClick(item.onClick) : undefined, disabled: Boolean(item.disabled) },
|
|
101
|
+
return 'subMenu' in item ? (react_1.default.createElement(CascadingSubmenu, { key: `subMenu-${item.label}-${idx}`, popupId: `subMenu-${item.label}`, title: item.label, Icon: item.icon, inset: hasIcon && !item.icon, onMenuItemClick: onMenuItemClick, menuItems: item.subMenu },
|
|
102
|
+
react_1.default.createElement(CascadingMenuList, { ...props, closeAfterItemClick: closeAfterItemClick, onMenuItemClick: onMenuItemClick, menuItems: item.subMenu }))) : item.type === 'divider' ? (react_1.default.createElement(material_1.Divider, { key: `divider-${idx}`, component: "li" })) : item.type === 'subHeader' ? (react_1.default.createElement(material_1.ListSubheader, { key: `subHeader-${item.label}-${idx}` }, item.label)) : (react_1.default.createElement(CascadingMenuItem, { key: `${item.label}-${idx}`, closeAfterItemClick: closeAfterItemClick, onClick: 'onClick' in item ? handleClick(item.onClick) : undefined, disabled: Boolean(item.disabled) },
|
|
100
103
|
item.icon ? (react_1.default.createElement(material_1.ListItemIcon, null,
|
|
101
104
|
react_1.default.createElement(item.icon, null))) : null,
|
|
102
105
|
' ',
|
|
@@ -106,7 +109,8 @@ function CascadingMenuList({ onMenuItemClick, menuItems, ...props }) {
|
|
|
106
109
|
})));
|
|
107
110
|
}
|
|
108
111
|
function CascadingMenuChildren(props) {
|
|
109
|
-
|
|
110
|
-
|
|
112
|
+
const { closeAfterItemClick = true, ...rest } = props;
|
|
113
|
+
return (react_1.default.createElement(CascadingMenu, { ...rest },
|
|
114
|
+
react_1.default.createElement(CascadingMenuList, { ...rest, closeAfterItemClick: closeAfterItemClick })));
|
|
111
115
|
}
|
|
112
116
|
exports.default = CascadingMenuChildren;
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { MenuItem } from '@jbrowse/core/ui';
|
|
3
|
-
declare const CascadingMenuButton: ({ children, menuItems, ...rest }: {
|
|
3
|
+
declare const CascadingMenuButton: ({ children, menuItems, closeAfterItemClick, stopPropagation, setOpen, onClick: onClickExtra, ...rest }: {
|
|
4
4
|
[key: string]: unknown;
|
|
5
5
|
children?: React.ReactElement<any, string | React.JSXElementConstructor<any>> | undefined;
|
|
6
6
|
menuItems: MenuItem[];
|
|
7
|
+
closeAfterItemClick?: boolean | undefined;
|
|
8
|
+
stopPropagation?: boolean | undefined;
|
|
9
|
+
onClick?: (() => void) | undefined;
|
|
10
|
+
setOpen?: ((arg: boolean) => void) | undefined;
|
|
7
11
|
}) => React.JSX.Element;
|
|
8
12
|
export default CascadingMenuButton;
|
|
@@ -1,20 +1,60 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
27
|
};
|
|
5
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const react_1 =
|
|
29
|
+
const react_1 = __importStar(require("react"));
|
|
7
30
|
const CascadingMenu_1 = __importDefault(require("@jbrowse/core/ui/CascadingMenu"));
|
|
8
31
|
const material_1 = require("@mui/material");
|
|
9
32
|
const mobx_react_1 = require("mobx-react");
|
|
10
33
|
const hooks_1 = require("material-ui-popup-state/hooks");
|
|
11
|
-
const CascadingMenuButton = (0, mobx_react_1.observer)(function CascadingMenuButton({ children, menuItems, ...rest }) {
|
|
34
|
+
const CascadingMenuButton = (0, mobx_react_1.observer)(function CascadingMenuButton({ children, menuItems, closeAfterItemClick = true, stopPropagation, setOpen, onClick: onClickExtra, ...rest }) {
|
|
12
35
|
const popupState = (0, hooks_1.usePopupState)({
|
|
13
36
|
popupId: 'viewMenu',
|
|
14
37
|
variant: 'popover',
|
|
15
38
|
});
|
|
39
|
+
const { onClick, onTouchStart, ...rest2 } = (0, hooks_1.bindTrigger)(popupState);
|
|
40
|
+
const { isOpen } = popupState;
|
|
41
|
+
(0, react_1.useEffect)(() => {
|
|
42
|
+
setOpen === null || setOpen === void 0 ? void 0 : setOpen(isOpen);
|
|
43
|
+
}, [isOpen, setOpen]);
|
|
16
44
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
17
|
-
react_1.default.createElement(material_1.IconButton, {
|
|
18
|
-
|
|
45
|
+
react_1.default.createElement(material_1.IconButton, { onClick: event => {
|
|
46
|
+
if (stopPropagation) {
|
|
47
|
+
event.stopPropagation();
|
|
48
|
+
}
|
|
49
|
+
onClick(event);
|
|
50
|
+
onClickExtra === null || onClickExtra === void 0 ? void 0 : onClickExtra();
|
|
51
|
+
}, onTouchStart: event => {
|
|
52
|
+
if (stopPropagation) {
|
|
53
|
+
event.stopPropagation();
|
|
54
|
+
}
|
|
55
|
+
onTouchStart(event);
|
|
56
|
+
onClickExtra === null || onClickExtra === void 0 ? void 0 : onClickExtra();
|
|
57
|
+
}, ...rest2, ...rest, disabled: menuItems.length === 0 }, children),
|
|
58
|
+
react_1.default.createElement(CascadingMenu_1.default, { ...(0, hooks_1.bindPopover)(popupState), onMenuItemClick: (_, callback) => callback(), menuItems: menuItems, closeAfterItemClick: closeAfterItemClick, popupState: popupState })));
|
|
19
59
|
});
|
|
20
60
|
exports.default = CascadingMenuButton;
|
|
@@ -33,9 +33,10 @@ const material_1 = require("@mui/material");
|
|
|
33
33
|
const types_1 = require("../../util/types");
|
|
34
34
|
const LocalFileChooser_1 = __importDefault(require("./LocalFileChooser"));
|
|
35
35
|
const UrlChooser_1 = __importDefault(require("./UrlChooser"));
|
|
36
|
+
const util_1 = require("../../util");
|
|
36
37
|
// icons
|
|
37
38
|
const ArrowDropDown_1 = __importDefault(require("@mui/icons-material/ArrowDropDown"));
|
|
38
|
-
const
|
|
39
|
+
const NUM_SHOWN = 2;
|
|
39
40
|
function ToggleButtonWithTooltip(props) {
|
|
40
41
|
const { title, children, ...other } = props;
|
|
41
42
|
return (react_1.default.createElement(material_1.Tooltip, { title: title || '' },
|
|
@@ -53,35 +54,40 @@ const FileSelector = (0, mobx_react_1.observer)(function (props) {
|
|
|
53
54
|
const [toggleButtonValue, setToggleButtonValue] = (0, react_1.useState)(location && 'internetAccountId' in location && location.internetAccountId
|
|
54
55
|
? location.internetAccountId
|
|
55
56
|
: fileOrUrl);
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const [
|
|
57
|
+
const accounts = (0, types_1.isAppRootModel)(rootModel)
|
|
58
|
+
? rootModel.internetAccounts.filter(f => f.type !== 'HTTPBasicInternetAccount')
|
|
59
|
+
: [];
|
|
60
|
+
const [recentlyUsedInternetAccounts, setRecentlyUsedInternetAccounts] = (0, util_1.useLocalStorage)('fileSelector-recentlyUsedInternetAccounts', []);
|
|
61
|
+
const map = Object.fromEntries(accounts.map(a => [a.internetAccountId, a]));
|
|
62
|
+
const arr = [...new Set(accounts.map(s => s.internetAccountId))].sort((a, b) => recentlyUsedInternetAccounts.indexOf(a) -
|
|
63
|
+
recentlyUsedInternetAccounts.indexOf(b));
|
|
64
|
+
const shownAccounts = arr.slice(0, NUM_SHOWN);
|
|
65
|
+
const hiddenAccounts = arr.slice(NUM_SHOWN);
|
|
60
66
|
const [anchorEl, setAnchorEl] = (0, react_1.useState)(null);
|
|
61
|
-
const
|
|
62
|
-
const
|
|
67
|
+
const selectedAccount = map[toggleButtonValue];
|
|
68
|
+
const setLocationWithAccount = (0, react_1.useCallback)((location) => {
|
|
63
69
|
setLocation({
|
|
64
70
|
...location,
|
|
65
71
|
...((0, types_1.isUriLocation)(location)
|
|
66
|
-
? { internetAccountId:
|
|
72
|
+
? { internetAccountId: selectedAccount === null || selectedAccount === void 0 ? void 0 : selectedAccount.internetAccountId }
|
|
67
73
|
: {}),
|
|
68
74
|
});
|
|
69
|
-
}, [setLocation,
|
|
75
|
+
}, [setLocation, selectedAccount]);
|
|
70
76
|
(0, react_1.useEffect)(() => {
|
|
71
77
|
// if you swap account selection after inputting url
|
|
72
|
-
if (
|
|
78
|
+
if (selectedAccount &&
|
|
73
79
|
(0, types_1.isUriLocation)(location) &&
|
|
74
|
-
location.internetAccountId !==
|
|
75
|
-
|
|
80
|
+
location.internetAccountId !== selectedAccount.internetAccountId) {
|
|
81
|
+
setLocationWithAccount(location);
|
|
76
82
|
}
|
|
77
|
-
}, [location,
|
|
78
|
-
let locationInput = (react_1.default.createElement(UrlChooser_1.default, { ...props, setLocation:
|
|
83
|
+
}, [location, selectedAccount, setLocationWithAccount]);
|
|
84
|
+
let locationInput = (react_1.default.createElement(UrlChooser_1.default, { ...props, setLocation: setLocationWithAccount, label: selectedAccount === null || selectedAccount === void 0 ? void 0 : selectedAccount.selectorLabel }));
|
|
79
85
|
if (toggleButtonValue === 'file') {
|
|
80
86
|
locationInput = react_1.default.createElement(LocalFileChooser_1.default, { ...props });
|
|
81
87
|
}
|
|
82
|
-
if (
|
|
83
|
-
const { SelectorComponent } =
|
|
84
|
-
locationInput = (react_1.default.createElement(SelectorComponent, { ...props, setLocation:
|
|
88
|
+
if (selectedAccount === null || selectedAccount === void 0 ? void 0 : selectedAccount.SelectorComponent) {
|
|
89
|
+
const { SelectorComponent } = selectedAccount;
|
|
90
|
+
locationInput = (react_1.default.createElement(SelectorComponent, { ...props, setLocation: setLocationWithAccount }));
|
|
85
91
|
}
|
|
86
92
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
87
93
|
react_1.default.createElement(material_1.Box, { display: "flex" },
|
|
@@ -89,34 +95,42 @@ const FileSelector = (0, mobx_react_1.observer)(function (props) {
|
|
|
89
95
|
react_1.default.createElement(material_1.Box, { display: "flex", flexDirection: "row" },
|
|
90
96
|
react_1.default.createElement(material_1.Box, null,
|
|
91
97
|
react_1.default.createElement(material_1.ToggleButtonGroup, { value: toggleButtonValue, exclusive: true, onChange: (_event, newState) => {
|
|
98
|
+
setRecentlyUsedInternetAccounts([
|
|
99
|
+
...new Set([newState, ...recentlyUsedInternetAccounts].filter(util_1.notEmpty)),
|
|
100
|
+
]);
|
|
92
101
|
if (newState) {
|
|
93
102
|
setToggleButtonValue(newState);
|
|
94
103
|
}
|
|
95
104
|
if ((0, types_1.isUriLocation)(location)) {
|
|
96
|
-
|
|
105
|
+
setLocationWithAccount(location);
|
|
97
106
|
}
|
|
98
107
|
}, "aria-label": "file, url, or account picker" },
|
|
99
108
|
new URLSearchParams(window.location.search).get('adminKey') ? null : (react_1.default.createElement(material_1.ToggleButton, { value: "file", "aria-label": "local file" }, "File")),
|
|
100
109
|
react_1.default.createElement(material_1.ToggleButton, { value: "url", "aria-label": "url" }, "URL"),
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
:
|
|
104
|
-
|
|
110
|
+
shownAccounts.map(id => {
|
|
111
|
+
const { internetAccountId, name, toggleContents } = map[id];
|
|
112
|
+
return (react_1.default.createElement(ToggleButtonWithTooltip, { key: id, value: internetAccountId, title: name }, typeof toggleContents === 'string'
|
|
113
|
+
? shorten(toggleContents, 5)
|
|
114
|
+
: toggleContents || shorten(name, 5)));
|
|
115
|
+
}),
|
|
116
|
+
hiddenAccounts.length > 0 ? (
|
|
105
117
|
// @ts-expect-error
|
|
106
118
|
react_1.default.createElement(material_1.ToggleButton, { onClick: event => setAnchorEl(event.target), selected: false },
|
|
107
119
|
"More",
|
|
108
120
|
react_1.default.createElement(ArrowDropDown_1.default, null))) : null),
|
|
109
|
-
react_1.default.createElement(material_1.Menu, { open: Boolean(anchorEl), anchorEl: anchorEl, onClose: () => setAnchorEl(null), anchorOrigin: { vertical: 'bottom', horizontal: 'center' }, transformOrigin: { vertical: 'top', horizontal: 'center' } },
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
121
|
+
react_1.default.createElement(material_1.Menu, { open: Boolean(anchorEl), anchorEl: anchorEl, onClose: () => setAnchorEl(null), anchorOrigin: { vertical: 'bottom', horizontal: 'center' }, transformOrigin: { vertical: 'top', horizontal: 'center' } }, hiddenAccounts === null || hiddenAccounts === void 0 ? void 0 : hiddenAccounts.map(id => {
|
|
122
|
+
const { internetAccountId, name } = map[id];
|
|
123
|
+
return (react_1.default.createElement(material_1.MenuItem, { key: id, value: internetAccountId, onClick: () => {
|
|
124
|
+
setRecentlyUsedInternetAccounts([
|
|
125
|
+
...new Set([
|
|
126
|
+
internetAccountId,
|
|
127
|
+
...recentlyUsedInternetAccounts,
|
|
128
|
+
].filter(util_1.notEmpty)),
|
|
129
|
+
]);
|
|
130
|
+
setToggleButtonValue(internetAccountId);
|
|
131
|
+
setAnchorEl(null);
|
|
132
|
+
} }, name));
|
|
133
|
+
})))),
|
|
120
134
|
locationInput,
|
|
121
135
|
react_1.default.createElement(material_1.FormHelperText, null, description)));
|
|
122
136
|
});
|
package/ui/Menu.d.ts
CHANGED
package/ui/Menu.js
CHANGED
|
@@ -99,21 +99,18 @@ function MenuItemEndDecoration(props) {
|
|
|
99
99
|
return react_1.default.createElement("div", { className: classes.menuItemEndDecoration }, icon);
|
|
100
100
|
}
|
|
101
101
|
exports.MenuItemEndDecoration = MenuItemEndDecoration;
|
|
102
|
+
function checkIfValid(m) {
|
|
103
|
+
return m.type !== 'divider' && m.type !== 'subHeader' && !m.disabled;
|
|
104
|
+
}
|
|
102
105
|
function findNextValidIdx(menuItems, currentIdx) {
|
|
103
|
-
const idx = menuItems
|
|
104
|
-
.slice(currentIdx + 1)
|
|
105
|
-
.findIndex(menuItem => menuItem.type !== 'divider' &&
|
|
106
|
-
menuItem.type !== 'subHeader' &&
|
|
107
|
-
!menuItem.disabled);
|
|
106
|
+
const idx = menuItems.slice(currentIdx + 1).findIndex(checkIfValid);
|
|
108
107
|
if (idx === -1) {
|
|
109
108
|
return idx;
|
|
110
109
|
}
|
|
111
110
|
return currentIdx + 1 + idx;
|
|
112
111
|
}
|
|
113
112
|
function findPreviousValidIdx(menuItems, currentIdx) {
|
|
114
|
-
return (0, util_1.findLastIndex)(menuItems.slice(0, currentIdx),
|
|
115
|
-
menuItem.type !== 'subHeader' &&
|
|
116
|
-
!menuItem.disabled);
|
|
113
|
+
return (0, util_1.findLastIndex)(menuItems.slice(0, currentIdx), checkIfValid);
|
|
117
114
|
}
|
|
118
115
|
const MenuPage = react_1.default.forwardRef(function MenuPage2(props, ref) {
|
|
119
116
|
const [subMenuAnchorEl, setSubMenuAnchorEl] = (0, react_1.useState)();
|
|
@@ -198,7 +195,7 @@ const MenuPage = react_1.default.forwardRef(function MenuPage2(props, ref) {
|
|
|
198
195
|
const onClick = 'onClick' in menuItem
|
|
199
196
|
? handleClick(menuItem.onClick)
|
|
200
197
|
: undefined;
|
|
201
|
-
return (react_1.default.createElement(material_1.MenuItem, { key: menuItem.label, style: menuItemStyle, selected: idx === selectedMenuItemIdx, onClick: onClick, onMouseMove: e => {
|
|
198
|
+
return (react_1.default.createElement(material_1.MenuItem, { key: menuItem.id || String(menuItem.label), style: menuItemStyle, selected: idx === selectedMenuItemIdx, onClick: onClick, onMouseMove: e => {
|
|
202
199
|
if (e.currentTarget !== document.activeElement) {
|
|
203
200
|
e.currentTarget.focus();
|
|
204
201
|
setSelectedMenuItemIdx(idx);
|
|
@@ -246,7 +243,7 @@ const MenuPage = react_1.default.forwardRef(function MenuPage2(props, ref) {
|
|
|
246
243
|
menuItems.map((menuItem, idx) => {
|
|
247
244
|
let subMenu = null;
|
|
248
245
|
if ('subMenu' in menuItem) {
|
|
249
|
-
subMenu = (react_1.default.createElement(MenuPage, { key: menuItem.label, anchorEl: subMenuAnchorEl, open: isSubMenuOpen && openSubMenuIdx === idx, onClose: () => {
|
|
246
|
+
subMenu = (react_1.default.createElement(MenuPage, { key: menuItem.id || String(menuItem.label), anchorEl: subMenuAnchorEl, open: isSubMenuOpen && openSubMenuIdx === idx, onClose: () => {
|
|
250
247
|
setIsSubMenuOpen(false);
|
|
251
248
|
setSubMenuAnchorEl(undefined);
|
|
252
249
|
}, onMenuItemClick: onMenuItemClick, menuItems: menuItem.subMenu }));
|
package/ui/MenuButton.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { MenuItem } from '@jbrowse/core/ui';
|
|
3
|
-
declare const MenuButton: ({ children, menuItems, ...rest }: {
|
|
3
|
+
declare const MenuButton: ({ children, menuItems, closeAfterItemClick, stopPropagation, setOpen, ...rest }: {
|
|
4
4
|
[key: string]: unknown;
|
|
5
|
+
closeAfterItemClick?: boolean | undefined;
|
|
5
6
|
children?: React.ReactElement<any, string | React.JSXElementConstructor<any>> | undefined;
|
|
6
7
|
menuItems: MenuItem[];
|
|
8
|
+
stopPropagation?: boolean | undefined;
|
|
9
|
+
setOpen?: ((arg: boolean) => void) | undefined;
|
|
7
10
|
}) => React.JSX.Element;
|
|
8
11
|
export default MenuButton;
|
package/ui/MenuButton.js
CHANGED
|
@@ -30,13 +30,19 @@ const react_1 = __importStar(require("react"));
|
|
|
30
30
|
const Menu_1 = __importDefault(require("@jbrowse/core/ui/Menu"));
|
|
31
31
|
const material_1 = require("@mui/material");
|
|
32
32
|
const mobx_react_1 = require("mobx-react");
|
|
33
|
-
const MenuButton = (0, mobx_react_1.observer)(function MenuButton({ children, menuItems, ...rest }) {
|
|
33
|
+
const MenuButton = (0, mobx_react_1.observer)(function MenuButton({ children, menuItems, closeAfterItemClick = true, stopPropagation, setOpen, ...rest }) {
|
|
34
34
|
const [anchorEl, setAnchorEl] = (0, react_1.useState)();
|
|
35
|
+
const isOpen = !!anchorEl;
|
|
36
|
+
(0, react_1.useEffect)(() => {
|
|
37
|
+
setOpen === null || setOpen === void 0 ? void 0 : setOpen(isOpen);
|
|
38
|
+
}, [isOpen, setOpen]);
|
|
35
39
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
36
40
|
react_1.default.createElement(material_1.IconButton, { ...rest, onClick: event => setAnchorEl(event.currentTarget) }, children),
|
|
37
41
|
react_1.default.createElement(Menu_1.default, { open: !!anchorEl, anchorEl: anchorEl, onClose: () => setAnchorEl(undefined), onMenuItemClick: (_, callback) => {
|
|
38
42
|
callback();
|
|
39
|
-
|
|
43
|
+
if (closeAfterItemClick) {
|
|
44
|
+
setAnchorEl(undefined);
|
|
45
|
+
}
|
|
40
46
|
}, menuItems: menuItems })));
|
|
41
47
|
});
|
|
42
48
|
exports.default = MenuButton;
|
package/ui/SanitizedHTML.d.ts
CHANGED
package/ui/SanitizedHTML.js
CHANGED
|
@@ -58,7 +58,7 @@ function isHTML(str) {
|
|
|
58
58
|
// products/jbrowse-web/src/tests/Connection.test.tsx test (can delete mock to
|
|
59
59
|
// see)
|
|
60
60
|
//
|
|
61
|
-
function SanitizedHTML({ html: pre }) {
|
|
61
|
+
function SanitizedHTML({ html: pre, className, }) {
|
|
62
62
|
// try to add links to the text first
|
|
63
63
|
const html = (0, util_1.linkify)(pre);
|
|
64
64
|
const value = isHTML(html) ? html : (0, escape_html_1.default)(html);
|
|
@@ -74,7 +74,7 @@ function SanitizedHTML({ html: pre }) {
|
|
|
74
74
|
}
|
|
75
75
|
});
|
|
76
76
|
}
|
|
77
|
-
return (react_1.default.createElement("span", {
|
|
77
|
+
return (react_1.default.createElement("span", { className: className,
|
|
78
78
|
// eslint-disable-next-line react/no-danger
|
|
79
79
|
dangerouslySetInnerHTML: {
|
|
80
80
|
__html: dompurify_1.default.sanitize(value),
|
package/util/analytics.js
CHANGED
|
@@ -59,7 +59,7 @@ async function writeGAAnalytics(rootModel, initialTimestamp) {
|
|
|
59
59
|
var _a;
|
|
60
60
|
const jbrowseUser = 'UA-7115575-5';
|
|
61
61
|
const stats = {
|
|
62
|
-
'tracks-count': rootModel.jbrowse.tracks.length,
|
|
62
|
+
'tracks-count': rootModel.jbrowse.tracks.length, // this is all possible tracks
|
|
63
63
|
ver: rootModel.version,
|
|
64
64
|
electron: util_1.isElectron,
|
|
65
65
|
loadTime: Date.now() - initialTimestamp,
|
package/util/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import React from 'react';
|
|
2
2
|
import PluginManager from '../PluginManager';
|
|
3
3
|
import { IAnyStateTreeNode, IStateTreeNode, Instance } from 'mobx-state-tree';
|
|
4
4
|
import { IReactionPublic, IReactionOptions } from 'mobx';
|
|
@@ -16,7 +16,7 @@ export * from './offscreenCanvasUtils';
|
|
|
16
16
|
export declare function useDebounce<T>(value: T, delay: number): T;
|
|
17
17
|
export declare function useWidthSetter(view: {
|
|
18
18
|
setWidth: (arg: number) => void;
|
|
19
|
-
}, padding: string):
|
|
19
|
+
}, padding: string): React.RefObject<HTMLDivElement>;
|
|
20
20
|
export declare function useDebouncedCallback<T>(callback: (...args: T[]) => void, wait?: number): (...args: T[]) => void;
|
|
21
21
|
/**
|
|
22
22
|
* find the first node in the hierarchy that matches the given predicate
|
|
@@ -213,7 +213,7 @@ export declare function renameRegionsIfNeeded<ARGTYPE extends {
|
|
|
213
213
|
assemblyName?: string;
|
|
214
214
|
regions?: Region[];
|
|
215
215
|
signal?: AbortSignal;
|
|
216
|
-
adapterConfig: unknown
|
|
216
|
+
adapterConfig: Record<string, unknown>;
|
|
217
217
|
sessionId: string;
|
|
218
218
|
statusCallback?: (arg: string) => void;
|
|
219
219
|
}>(assemblyManager: AssemblyManager, args: ARGTYPE): Promise<ARGTYPE & {
|
|
@@ -389,6 +389,9 @@ interface BasicFeature {
|
|
|
389
389
|
refName: string;
|
|
390
390
|
}
|
|
391
391
|
export declare function gatherOverlaps(regions: BasicFeature[]): BasicFeature[];
|
|
392
|
-
export { default as SimpleFeature, type Feature, type SimpleFeatureSerialized, isFeature, } from './simpleFeature';
|
|
393
392
|
export declare function stripAlpha(str: string): string;
|
|
393
|
+
export declare function renderToStaticMarkup(node: React.ReactElement, createRootFn?: (elt: Element | DocumentFragment) => {
|
|
394
|
+
render: (node: React.ReactElement) => unknown;
|
|
395
|
+
}): string;
|
|
396
|
+
export { default as SimpleFeature, type Feature, type SimpleFeatureSerialized, isFeature, } from './simpleFeature';
|
|
394
397
|
export { blobToDataURL } from './blobToDataURL';
|
package/util/index.js
CHANGED
|
@@ -18,7 +18,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
18
18
|
};
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
20
|
exports.toLocale = exports.getBpDisplayStr = exports.isSupportedIndexingAdapter = exports.bytesForRegions = exports.objectHash = exports.hashCode = exports.updateStatus = exports.generateCodonTable = exports.defaultCodonTable = exports.defaultStops = exports.defaultStarts = exports.measureText = exports.rIC = exports.complement = exports.reverse = exports.revcom = exports.isElectron = exports.stringify = exports.shorten = exports.minmax = exports.renameRegionsIfNeeded = exports.renameRegionIfNeeded = exports.makeAbortableReaction = exports.findLast = exports.findLastIndex = exports.iterMap = exports.bpSpanPx = exports.featureSpanPx = exports.cartesianToPolar = exports.polarToCartesian = exports.degToRad = exports.radToDeg = exports.bpToPx = exports.clamp = exports.compareLocStrings = exports.compareLocs = exports.parseLocString = exports.parseLocStringOneBased = exports.assembleLocStringFast = exports.assembleLocString = exports.getContainingDisplay = exports.getContainingTrack = exports.getContainingView = exports.getSession = exports.findParentThatIs = exports.springAnimate = exports.findParentThat = exports.useDebouncedCallback = exports.useWidthSetter = exports.useDebounce = void 0;
|
|
21
|
-
exports.blobToDataURL = exports.
|
|
21
|
+
exports.blobToDataURL = exports.isFeature = exports.SimpleFeature = exports.renderToStaticMarkup = exports.stripAlpha = exports.gatherOverlaps = exports.mergeIntervals = exports.notEmpty = exports.groupBy = exports.avg = exports.sum = exports.min = exports.max = exports.localStorageSetItem = exports.localStorageGetItem = exports.getEnv = exports.measureGridWidth = exports.linkify = exports.coarseStripHTML = exports.getStr = exports.getUriLink = exports.useLocalStorage = exports.getLayoutId = exports.getViewParams = exports.getTickDisplayStr = void 0;
|
|
22
22
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
23
23
|
const react_1 = require("react");
|
|
24
24
|
const is_object_1 = __importDefault(require("is-object"));
|
|
@@ -30,6 +30,8 @@ const types_2 = require("./types");
|
|
|
30
30
|
// has to be the full path and not the relative path to get the jest mock
|
|
31
31
|
const useMeasure_1 = __importDefault(require("@jbrowse/core/util/useMeasure"));
|
|
32
32
|
const colord_1 = require("./colord");
|
|
33
|
+
// eslint-disable-next-line react/no-deprecated
|
|
34
|
+
const react_dom_1 = require("react-dom");
|
|
33
35
|
__exportStar(require("./types"), exports);
|
|
34
36
|
__exportStar(require("./aborting"), exports);
|
|
35
37
|
__exportStar(require("./when"), exports);
|
|
@@ -1132,13 +1134,27 @@ function gatherOverlaps(regions) {
|
|
|
1132
1134
|
return Object.values(memo).flatMap(group => mergeIntervals(group.sort((a, b) => a.start - b.start)));
|
|
1133
1135
|
}
|
|
1134
1136
|
exports.gatherOverlaps = gatherOverlaps;
|
|
1135
|
-
var simpleFeature_1 = require("./simpleFeature");
|
|
1136
|
-
Object.defineProperty(exports, "SimpleFeature", { enumerable: true, get: function () { return __importDefault(simpleFeature_1).default; } });
|
|
1137
|
-
Object.defineProperty(exports, "isFeature", { enumerable: true, get: function () { return simpleFeature_1.isFeature; } });
|
|
1138
1137
|
function stripAlpha(str) {
|
|
1139
1138
|
const c = (0, colord_1.colord)(str);
|
|
1140
1139
|
return c.alpha(1).toHex();
|
|
1141
1140
|
}
|
|
1142
1141
|
exports.stripAlpha = stripAlpha;
|
|
1142
|
+
// https://react.dev/reference/react-dom/server/renderToString#removing-rendertostring-from-the-client-code
|
|
1143
|
+
function renderToStaticMarkup(node, createRootFn) {
|
|
1144
|
+
const div = document.createElement('div');
|
|
1145
|
+
(0, react_dom_1.flushSync)(() => {
|
|
1146
|
+
if (createRootFn) {
|
|
1147
|
+
createRootFn(div).render(node);
|
|
1148
|
+
}
|
|
1149
|
+
else {
|
|
1150
|
+
(0, react_dom_1.render)(node, div);
|
|
1151
|
+
}
|
|
1152
|
+
});
|
|
1153
|
+
return div.innerHTML.replace('>', '>').replace('<', '<');
|
|
1154
|
+
}
|
|
1155
|
+
exports.renderToStaticMarkup = renderToStaticMarkup;
|
|
1156
|
+
var simpleFeature_1 = require("./simpleFeature");
|
|
1157
|
+
Object.defineProperty(exports, "SimpleFeature", { enumerable: true, get: function () { return __importDefault(simpleFeature_1).default; } });
|
|
1158
|
+
Object.defineProperty(exports, "isFeature", { enumerable: true, get: function () { return simpleFeature_1.isFeature; } });
|
|
1143
1159
|
var blobToDataURL_1 = require("./blobToDataURL");
|
|
1144
1160
|
Object.defineProperty(exports, "blobToDataURL", { enumerable: true, get: function () { return blobToDataURL_1.blobToDataURL; } });
|
|
@@ -14,9 +14,9 @@ function binaryRangeFetch(url, start, end, options = {}) {
|
|
|
14
14
|
}
|
|
15
15
|
const globalRangeCache = new http_range_fetcher_1.HttpRangeFetcher({
|
|
16
16
|
fetch: binaryRangeFetch,
|
|
17
|
-
size: 500 * 1024 ** 2,
|
|
18
|
-
chunkSize: 128 * 1024,
|
|
19
|
-
maxFetchSize: 100 * 1024 ** 2,
|
|
17
|
+
size: 500 * 1024 ** 2, // 500MiB
|
|
18
|
+
chunkSize: 128 * 1024, // 128KiB
|
|
19
|
+
maxFetchSize: 100 * 1024 ** 2, // 100MiB
|
|
20
20
|
minimumTTL: 24 * 60 * 60 * 1000, // 1 day
|
|
21
21
|
});
|
|
22
22
|
function clearCache() {
|