@jbrowse/core 2.8.0 → 2.9.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.
@@ -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;
@@ -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
- const handleClick = (0, react_1.useCallback)((event) => {
45
- rootPopupState.close();
46
- onClick === null || onClick === void 0 ? void 0 : onClick(event);
47
- }, [rootPopupState, onClick]);
48
- return react_1.default.createElement(material_1.MenuItem, { ...props, onClick: handleClick });
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.default.useContext(CascadingContext);
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.default.useContext(CascadingContext);
74
- const context = react_1.default.useMemo(() => ({
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(menuItem => 'icon' in menuItem && menuItem.icon);
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
- return (react_1.default.createElement(CascadingMenu, { ...props },
110
- react_1.default.createElement(CascadingMenuList, { ...props })));
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 = __importDefault(require("react"));
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, { ...(0, hooks_1.bindTrigger)(popupState), ...rest, disabled: menuItems.length === 0 }, children),
18
- react_1.default.createElement(CascadingMenu_1.default, { ...(0, hooks_1.bindPopover)(popupState), onMenuItemClick: (_, callback) => callback(), menuItems: menuItems, popupState: popupState })));
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;
package/ui/Menu.d.ts CHANGED
@@ -20,7 +20,8 @@ export interface MenuSubHeader {
20
20
  label: string;
21
21
  }
22
22
  export interface BaseMenuItem {
23
- label: string;
23
+ id?: string;
24
+ label: React.ReactNode;
24
25
  priority?: number;
25
26
  subLabel?: string;
26
27
  icon?: React.ComponentType<SvgIconProps>;
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), menuItem => menuItem.type !== 'divider' &&
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 }));
@@ -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
- setAnchorEl(undefined);
43
+ if (closeAfterItemClick) {
44
+ setAnchorEl(undefined);
45
+ }
40
46
  }, menuItems: menuItems })));
41
47
  });
42
48
  exports.default = MenuButton;
@@ -1,4 +1,5 @@
1
1
  import React from 'react';
2
- export default function SanitizedHTML({ html: pre }: {
2
+ export default function SanitizedHTML({ html: pre, className, }: {
3
+ className?: string;
3
4
  html: string;
4
5
  }): React.JSX.Element;
@@ -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,
@@ -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() {