@jbrowse/plugin-grid-bookmark 2.10.3 → 2.11.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 (29) hide show
  1. package/dist/GridBookmarkWidget/components/BookmarkGrid.js +1 -1
  2. package/dist/GridBookmarkWidget/components/Highlight/Highlight.d.ts +1 -1
  3. package/dist/GridBookmarkWidget/components/Highlight/Highlight.js +16 -23
  4. package/dist/GridBookmarkWidget/components/Highlight/OverviewHighlight.d.ts +9 -0
  5. package/dist/GridBookmarkWidget/components/Highlight/OverviewHighlight.js +79 -0
  6. package/dist/GridBookmarkWidget/components/Highlight/index.js +9 -0
  7. package/dist/GridBookmarkWidget/components/dialogs/ExportBookmarksDialog.js +5 -3
  8. package/dist/GridBookmarkWidget/components/dialogs/ImportBookmarksDialog.js +52 -29
  9. package/dist/GridBookmarkWidget/index.d.ts +1 -2
  10. package/dist/GridBookmarkWidget/index.js +3 -2
  11. package/dist/GridBookmarkWidget/model.js +1 -1
  12. package/dist/GridBookmarkWidget/utils.js +1 -1
  13. package/dist/index.d.ts +1 -1
  14. package/dist/index.js +2 -2
  15. package/esm/GridBookmarkWidget/components/BookmarkGrid.js +1 -1
  16. package/esm/GridBookmarkWidget/components/Highlight/Highlight.d.ts +1 -1
  17. package/esm/GridBookmarkWidget/components/Highlight/Highlight.js +17 -24
  18. package/esm/GridBookmarkWidget/components/Highlight/OverviewHighlight.d.ts +9 -0
  19. package/esm/GridBookmarkWidget/components/Highlight/OverviewHighlight.js +54 -0
  20. package/esm/GridBookmarkWidget/components/Highlight/index.js +9 -0
  21. package/esm/GridBookmarkWidget/components/dialogs/ExportBookmarksDialog.js +5 -3
  22. package/esm/GridBookmarkWidget/components/dialogs/ImportBookmarksDialog.js +55 -32
  23. package/esm/GridBookmarkWidget/index.d.ts +1 -2
  24. package/esm/GridBookmarkWidget/index.js +2 -2
  25. package/esm/GridBookmarkWidget/model.js +1 -1
  26. package/esm/GridBookmarkWidget/utils.js +1 -1
  27. package/esm/index.d.ts +1 -1
  28. package/esm/index.js +1 -1
  29. package/package.json +3 -3
@@ -118,7 +118,7 @@ const BookmarkGrid = (0, mobx_react_1.observer)(function ({ model, }) {
118
118
  const target = rows[row.id];
119
119
  model.updateBookmarkLabel(target, row.label);
120
120
  return row;
121
- }, onProcessRowUpdateError: e => session.notify(e.message, 'error'), checkboxSelection: true, onRowSelectionModelChange: newRowSelectionModel => {
121
+ }, onProcessRowUpdateError: e => session.notifyError(`${e}`, e), checkboxSelection: true, onRowSelectionModelChange: newRowSelectionModel => {
122
122
  if (bookmarksWithValidAssemblies.length > 0) {
123
123
  model.setSelectedBookmarks(newRowSelectionModel.map(value => ({
124
124
  ...rows[value],
@@ -3,5 +3,5 @@ import { IExtendedLGV } from '../../model';
3
3
  type LGV = IExtendedLGV;
4
4
  declare const Highlight: ({ model }: {
5
5
  model: LGV;
6
- }) => React.JSX.Element;
6
+ }) => React.JSX.Element[] | null;
7
7
  export default Highlight;
@@ -38,38 +38,29 @@ const useStyles = (0, mui_1.makeStyles)()({
38
38
  highlight: {
39
39
  height: '100%',
40
40
  position: 'absolute',
41
- textAlign: 'center',
42
41
  overflow: 'hidden',
43
- display: 'flex',
44
- alignItems: 'start',
45
42
  },
46
43
  });
47
44
  const Highlight = (0, mobx_react_1.observer)(function Highlight({ model }) {
48
45
  var _a;
49
46
  const { classes } = useStyles();
50
47
  const session = (0, util_1.getSession)(model);
48
+ const { assemblyManager } = session;
51
49
  const { showBookmarkHighlights, showBookmarkLabels } = model;
52
- const assemblyNames = new Set(session.assemblyNames);
53
50
  const bookmarkWidget = session.widgets.get('GridBookmark');
54
- const bookmarks = (0, react_1.useRef)((_a = bookmarkWidget === null || bookmarkWidget === void 0 ? void 0 : bookmarkWidget.bookmarks) !== null && _a !== void 0 ? _a : []);
55
51
  (0, react_1.useEffect)(() => {
56
52
  if (!bookmarkWidget) {
57
- const newBookmarkWidget = session.addWidget('GridBookmarkWidget', 'GridBookmark');
58
- bookmarks.current = newBookmarkWidget.bookmarks;
53
+ session.addWidget('GridBookmarkWidget', 'GridBookmark');
59
54
  }
60
55
  }, [session, bookmarkWidget]);
61
- return (react_1.default.createElement(react_1.default.Fragment, null, showBookmarkHighlights && bookmarks.current
62
- ? bookmarks.current
63
- .filter(value => assemblyNames.has(value.assemblyName))
64
- .map(r => {
65
- const s = model.bpToPx({
66
- refName: r.refName,
67
- coord: r.start,
68
- });
69
- const e = model.bpToPx({
70
- refName: r.refName,
71
- coord: r.end,
72
- });
56
+ const set = new Set(model.assemblyNames);
57
+ return showBookmarkHighlights
58
+ ? (_a = bookmarkWidget === null || bookmarkWidget === void 0 ? void 0 : bookmarkWidget.bookmarks) === null || _a === void 0 ? void 0 : _a.filter(value => set.has(value.assemblyName)).map(r => {
59
+ var _a;
60
+ const asm = assemblyManager.get(r.assemblyName);
61
+ const refName = (_a = asm === null || asm === void 0 ? void 0 : asm.getCanonicalRefName(r.refName)) !== null && _a !== void 0 ? _a : r.refName;
62
+ const s = model.bpToPx({ refName, coord: r.start });
63
+ const e = model.bpToPx({ refName, coord: r.end });
73
64
  return s && e
74
65
  ? {
75
66
  width: Math.max(Math.abs(e.offsetPx - s.offsetPx), 3),
@@ -78,14 +69,16 @@ const Highlight = (0, mobx_react_1.observer)(function Highlight({ model }) {
78
69
  label: r.label,
79
70
  }
80
71
  : undefined;
81
- })
82
- .filter(util_1.notEmpty)
83
- .map(({ left, width, highlight, label }, idx) => (react_1.default.createElement("div", { key: `${left}_${width}_${idx}`, className: classes.highlight, style: { left, width, background: highlight } }, showBookmarkLabels ? (react_1.default.createElement(material_1.Tooltip, { title: label, arrow: true },
72
+ }).filter(util_1.notEmpty).map(({ left, width, highlight, label }, idx) => (react_1.default.createElement("div", { key: `${left}_${width}_${idx}`, className: classes.highlight, style: {
73
+ left,
74
+ width,
75
+ background: highlight,
76
+ } }, showBookmarkLabels ? (react_1.default.createElement(material_1.Tooltip, { title: label, arrow: true },
84
77
  react_1.default.createElement(Bookmark_1.default, { fontSize: "small", sx: {
85
78
  color: `${(0, colord_1.colord)(highlight).alpha() !== 0
86
79
  ? (0, colord_1.colord)(highlight).alpha(0.8).toRgbString()
87
80
  : (0, colord_1.colord)(highlight).alpha(0).toRgbString()}`,
88
81
  } }))) : null)))
89
- : null));
82
+ : null;
90
83
  });
91
84
  exports.default = Highlight;
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { Base1DViewModel } from '@jbrowse/core/util/Base1DViewModel';
3
+ import { IExtendedLGV } from '../../model';
4
+ type LGV = IExtendedLGV;
5
+ declare const OverviewHighlight: ({ model, overview, }: {
6
+ model: LGV;
7
+ overview: Base1DViewModel;
8
+ }) => React.JSX.Element[] | null;
9
+ export default OverviewHighlight;
@@ -0,0 +1,79 @@
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
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ const react_1 = __importStar(require("react"));
27
+ const mobx_react_1 = require("mobx-react");
28
+ const mui_1 = require("tss-react/mui");
29
+ const util_1 = require("@jbrowse/core/util");
30
+ const material_1 = require("@mui/material");
31
+ const useStyles = (0, mui_1.makeStyles)()({
32
+ highlight: {
33
+ height: '100%',
34
+ position: 'absolute',
35
+ },
36
+ });
37
+ const OverviewHighlight = (0, mobx_react_1.observer)(function OverviewHighlight({ model, overview, }) {
38
+ const { cytobandOffset } = model;
39
+ const session = (0, util_1.getSession)(model);
40
+ const { classes } = useStyles();
41
+ const { assemblyManager } = session;
42
+ const { showBookmarkHighlights, showBookmarkLabels } = model;
43
+ const bookmarkWidget = session.widgets.get('GridBookmark');
44
+ (0, react_1.useEffect)(() => {
45
+ if (!bookmarkWidget) {
46
+ session.addWidget('GridBookmarkWidget', 'GridBookmark');
47
+ }
48
+ }, [session, bookmarkWidget]);
49
+ const assemblyNames = new Set(model.assemblyNames);
50
+ return showBookmarkHighlights
51
+ ? bookmarkWidget === null || bookmarkWidget === void 0 ? void 0 : bookmarkWidget.bookmarks.filter(r => assemblyNames.has(r.assemblyName)).map(r => {
52
+ var _a;
53
+ const asm = assemblyManager.get(r.assemblyName);
54
+ const refName = (_a = asm === null || asm === void 0 ? void 0 : asm.getCanonicalRefName(r.refName)) !== null && _a !== void 0 ? _a : r.refName;
55
+ const rev = r.reversed;
56
+ const s = overview.bpToPx({ refName, coord: rev ? r.end : r.start });
57
+ const e = overview.bpToPx({ refName, coord: rev ? r.start : r.end });
58
+ return s !== undefined && e !== undefined
59
+ ? {
60
+ width: Math.abs(e - s),
61
+ left: s + cytobandOffset,
62
+ highlight: r.highlight,
63
+ label: r.label,
64
+ }
65
+ : undefined;
66
+ }).filter(util_1.notEmpty).map((obj, idx) => {
67
+ const { left, width, highlight, label } = obj;
68
+ return (react_1.default.createElement(material_1.Tooltip, { key: JSON.stringify(obj) + '-' + idx, title: showBookmarkLabels ? label : '', arrow: true },
69
+ react_1.default.createElement("div", { className: classes.highlight, style: {
70
+ left,
71
+ width,
72
+ background: highlight,
73
+ borderLeft: `1px solid ${highlight}`,
74
+ borderRight: `1px solid ${highlight}`,
75
+ } })));
76
+ })
77
+ : null;
78
+ });
79
+ exports.default = OverviewHighlight;
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const react_1 = __importDefault(require("react"));
7
7
  // locals
8
8
  const Highlight_1 = __importDefault(require("./Highlight"));
9
+ const OverviewHighlight_1 = __importDefault(require("./OverviewHighlight"));
9
10
  function AddHighlightModelF(pluginManager) {
10
11
  pluginManager.addToExtensionPoint('LinearGenomeView-TracksContainerComponent',
11
12
  // @ts-expect-error
@@ -15,5 +16,13 @@ function AddHighlightModelF(pluginManager) {
15
16
  react_1.default.createElement(Highlight_1.default, { key: `highlight_grid_bookmark`, model: model }),
16
17
  ];
17
18
  });
19
+ pluginManager.addToExtensionPoint('LinearGenomeView-OverviewScalebarComponent',
20
+ // @ts-expect-error
21
+ (rest = [], { model, overview }) => {
22
+ return [
23
+ ...rest,
24
+ react_1.default.createElement(OverviewHighlight_1.default, { key: `overview_highlight_grid_bookmark`, model: model, overview: overview }),
25
+ ];
26
+ });
18
27
  }
19
28
  exports.default = AddHighlightModelF;
@@ -36,7 +36,9 @@ const GetApp_1 = __importDefault(require("@mui/icons-material/GetApp"));
36
36
  const utils_1 = require("../../utils");
37
37
  const useStyles = (0, mui_1.makeStyles)()({
38
38
  flexItem: {
39
- margin: 5,
39
+ display: 'flex',
40
+ alignItems: 'center',
41
+ gap: '5px',
40
42
  },
41
43
  container: {
42
44
  display: 'flex',
@@ -55,9 +57,9 @@ const ExportBookmarksDialog = (0, mobx_react_1.observer)(function ExportBookmark
55
57
  react_1.default.createElement("span", null, "All bookmarks will be exported."),
56
58
  react_1.default.createElement("br", null),
57
59
  react_1.default.createElement("span", null, "Use the checkboxes to select individual bookmarks to export."))) : ('Only selected bookmarks will be exported.')),
58
- react_1.default.createElement("div", { style: { display: 'flex', alignItems: 'center' } },
60
+ react_1.default.createElement("div", { className: classes.flexItem },
59
61
  react_1.default.createElement(material_1.Typography, null, "Format to download:"),
60
- react_1.default.createElement(material_1.Select, { size: "small", className: classes.flexItem, "data-testid": "selectFileType", value: fileType, onChange: event => setFileType(event.target.value) },
62
+ react_1.default.createElement(material_1.Select, { size: "small", value: fileType, onChange: event => setFileType(event.target.value) },
61
63
  react_1.default.createElement(material_1.MenuItem, { value: "BED" }, "BED"),
62
64
  react_1.default.createElement(material_1.MenuItem, { value: "TSV" }, "TSV")))),
63
65
  react_1.default.createElement(material_1.DialogActions, null,
@@ -34,23 +34,21 @@ const ui_1 = require("@jbrowse/core/ui");
34
34
  const material_1 = require("@mui/material");
35
35
  const io_1 = require("@jbrowse/core/util/io");
36
36
  const ui_2 = require("@jbrowse/core/ui");
37
- const AssemblySelector_1 = __importDefault(require("@jbrowse/core/ui/AssemblySelector"));
38
37
  const mui_1 = require("tss-react/mui");
39
38
  // icons
40
39
  const Publish_1 = __importDefault(require("@mui/icons-material/Publish"));
41
40
  const ExpandMore_1 = __importDefault(require("@mui/icons-material/ExpandMore"));
42
- const Help_1 = __importDefault(require("@mui/icons-material/Help"));
43
41
  const utils_1 = require("../../utils");
44
42
  const sessionSharing_1 = require("../../sessionSharing");
45
43
  const useStyles = (0, mui_1.makeStyles)()(theme => {
46
44
  var _a;
47
45
  return ({
48
- flexItem: {
49
- margin: 5,
50
- },
51
46
  expandIcon: {
52
47
  color: ((_a = theme.palette.tertiary) === null || _a === void 0 ? void 0 : _a.contrastText) || '#fff',
53
48
  },
49
+ minWidth: {
50
+ minWidth: 500,
51
+ },
54
52
  });
55
53
  });
56
54
  async function getBookmarksFromShareLink(shareLink, shareURL) {
@@ -62,18 +60,35 @@ async function getBookmarksFromShareLink(shareLink, shareURL) {
62
60
  const sharedSession = JSON.parse(await (0, utils_1.fromUrlSafeB64)(decryptedSession));
63
61
  return sharedSession.sharedBookmarks;
64
62
  }
65
- async function getBookmarksFromFile(location, selectedAsm) {
66
- const data = await (0, io_1.openLocation)(location).readFile('utf8');
67
- return data
68
- .split(/\n|\r\n|\r/)
69
- .filter(f => !!f.trim())
70
- .filter(f => !f.startsWith('#') &&
71
- !f.startsWith('track') &&
72
- !f.startsWith('browser'))
63
+ function guessFileType(header) {
64
+ return header.startsWith('chrom') && header.includes('assembly_name')
65
+ ? 'TSV'
66
+ : 'BED';
67
+ }
68
+ async function getBookmarksFromTSVFile(lines) {
69
+ if (lines[0].startsWith('chrom')) {
70
+ lines = lines.slice(1);
71
+ }
72
+ return lines
73
+ .filter(f => !f.startsWith('#'))
74
+ .map(line => {
75
+ const [refName, start, end, label, assemblyName] = line.split('\t');
76
+ return {
77
+ assemblyName: assemblyName,
78
+ refName,
79
+ start: +start,
80
+ end: +end,
81
+ label: label === '.' ? undefined : label,
82
+ };
83
+ });
84
+ }
85
+ async function getBookmarksFromBEDFile(lines, selectedAsm) {
86
+ return lines
87
+ .filter(f => !f.startsWith('#'))
73
88
  .map(line => {
74
- const [refName, start, end, label, assembly] = line.split('\t');
89
+ const [refName, start, end, label] = line.split('\t');
75
90
  return {
76
- assemblyName: assembly !== null && assembly !== void 0 ? assembly : selectedAsm,
91
+ assemblyName: selectedAsm,
77
92
  refName,
78
93
  start: +start,
79
94
  end: +end,
@@ -91,31 +106,39 @@ const ImportBookmarksDialog = (0, mobx_react_1.observer)(function ({ onClose, mo
91
106
  const [selectedAsm, setSelectedAsm] = (0, react_1.useState)(assemblyNames[0]);
92
107
  const [expanded, setExpanded] = (0, react_1.useState)('shareLinkAccordion');
93
108
  return (react_1.default.createElement(ui_2.Dialog, { open: true, onClose: onClose, maxWidth: "xl", title: "Import bookmarks" },
94
- react_1.default.createElement(material_1.DialogContent, null,
109
+ react_1.default.createElement(material_1.DialogContent, { className: classes.minWidth },
95
110
  react_1.default.createElement(material_1.Accordion, { expanded: expanded === 'shareLinkAccordion', onChange: () => setExpanded('shareLinkAccordion') },
96
111
  react_1.default.createElement(material_1.AccordionSummary, { expandIcon: react_1.default.createElement(ExpandMore_1.default, { className: classes.expandIcon }) },
97
- react_1.default.createElement(material_1.Typography, { style: { display: 'flex', alignItems: 'center', gap: '5px' } },
98
- "Import from share link",
99
- ' ',
100
- react_1.default.createElement(material_1.Tooltip, { title: "The appropriate share link for sharing bookmarks is one generated via the 'Share' button in the 'Bookmarked regions' drawer. Paste it below to import shared bookmarks." },
101
- react_1.default.createElement(Help_1.default, null)))),
112
+ react_1.default.createElement(material_1.Typography, { style: { display: 'flex', alignItems: 'center', gap: '5px' } }, "Import from share link")),
102
113
  react_1.default.createElement(material_1.AccordionDetails, null,
103
- react_1.default.createElement(material_1.TextField, { label: "Enter URL", variant: "outlined", style: { width: '100%' }, value: shareLink, onChange: e => setShareLink(e.target.value) }))),
114
+ react_1.default.createElement(material_1.Typography, null, "Paste a bookmark share link generated by the 'Share' button from the bookmarks widget"),
115
+ react_1.default.createElement(material_1.TextField, { label: "Enter Share URL", variant: "outlined", fullWidth: true, value: shareLink, onChange: e => setShareLink(e.target.value) }))),
104
116
  react_1.default.createElement(material_1.Accordion, { expanded: expanded === 'fileAccordion', onChange: () => setExpanded('fileAccordion') },
105
117
  react_1.default.createElement(material_1.AccordionSummary, { expandIcon: react_1.default.createElement(ExpandMore_1.default, { className: classes.expandIcon }) },
106
118
  react_1.default.createElement(material_1.Typography, null, "Import from file")),
107
119
  react_1.default.createElement(material_1.AccordionDetails, null,
108
- react_1.default.createElement(ui_1.FileSelector, { location: location, setLocation: setLocation, name: "File", description: "Choose a BED or TSV format file to import." }),
109
- react_1.default.createElement(AssemblySelector_1.default, { onChange: val => setSelectedAsm(val), helperText: `Select the assembly your bookmarks belong to (BED or TSV without assembly column).`, session: session, selected: selectedAsm }))),
110
- error ? (react_1.default.createElement(material_1.Typography, { color: "error", variant: "h6" }, `${error}`)) : null),
120
+ react_1.default.createElement(ui_1.FileSelector, { location: location, setLocation: setLocation, name: "File", description: `Choose a BED or TSV format file to import. Required TSV column headers are "chrom, start, end, label, assembly_name".` }),
121
+ react_1.default.createElement(ui_2.AssemblySelector, { onChange: val => setSelectedAsm(val), helperText: `Select the assembly for BED file.`, session: session, selected: selectedAsm }))),
122
+ error ? react_1.default.createElement(ui_1.ErrorMessage, { error: error }) : null),
111
123
  react_1.default.createElement(material_1.DialogActions, null,
112
124
  react_1.default.createElement(material_1.Button, { variant: "contained", color: "secondary", onClick: onClose }, "Cancel"),
113
- react_1.default.createElement(material_1.Button, { className: classes.flexItem, "data-testid": "dialogImport", variant: "contained", color: "primary", disabled: !location && !shareLink, startIcon: react_1.default.createElement(Publish_1.default, null), onClick: async () => {
125
+ react_1.default.createElement(material_1.Button, { "data-testid": "dialogImport", variant: "contained", color: "primary", disabled: !location && !shareLink, startIcon: react_1.default.createElement(Publish_1.default, null), onClick: async () => {
114
126
  try {
115
- if (location) {
116
- model.importBookmarks(await getBookmarksFromFile(location, selectedAsm));
127
+ if (expanded === 'fileAccordion' && location) {
128
+ const data = await (0, io_1.openLocation)(location).readFile('utf8');
129
+ const lines = data.split(/\n|\r\n|\r/).filter(f => !!f.trim());
130
+ const fileType = guessFileType(lines[0]);
131
+ if (fileType === 'BED') {
132
+ model.importBookmarks(await getBookmarksFromBEDFile(lines, selectedAsm));
133
+ }
134
+ else {
135
+ // TSV
136
+ model.importBookmarks(await getBookmarksFromTSVFile(lines));
137
+ }
117
138
  }
118
- else if (shareLink && (0, types_1.isSessionWithShareURL)(session)) {
139
+ else if (expanded === 'shareLinkAccordion' &&
140
+ shareLink &&
141
+ (0, types_1.isSessionWithShareURL)(session)) {
119
142
  model.importBookmarks(await getBookmarksFromShareLink(shareLink, session.shareURL));
120
143
  }
121
144
  onClose();
@@ -1,3 +1,2 @@
1
1
  import PluginManager from '@jbrowse/core/PluginManager';
2
- declare const _default: (pluginManager: PluginManager) => void;
3
- export default _default;
2
+ export default function GridBookmarkWidgetF(pluginManager: PluginManager): void;
@@ -33,7 +33,7 @@ const pluggableElementTypes_1 = require("@jbrowse/core/pluggableElementTypes");
33
33
  const model_1 = __importDefault(require("./model"));
34
34
  const Highlight_1 = __importDefault(require("./components/Highlight"));
35
35
  const configSchema = (0, configuration_1.ConfigurationSchema)('GridBookmarkWidget', {});
36
- exports.default = (pluginManager) => {
36
+ function GridBookmarkWidgetF(pluginManager) {
37
37
  pluginManager.addWidgetType(() => {
38
38
  return new pluggableElementTypes_1.WidgetType({
39
39
  name: 'GridBookmarkWidget',
@@ -44,4 +44,5 @@ exports.default = (pluginManager) => {
44
44
  });
45
45
  });
46
46
  (0, Highlight_1.default)(pluginManager);
47
- };
47
+ }
48
+ exports.default = GridBookmarkWidgetF;
@@ -20,7 +20,7 @@ const LabeledRegionModel = mobx_state_tree_1.types
20
20
  const SharedBookmarksModel = mobx_state_tree_1.types.model('SharedBookmarksModel', {
21
21
  sharedBookmarks: mobx_state_tree_1.types.maybe(mobx_state_tree_1.types.array(LabeledRegionModel)),
22
22
  });
23
- const localStorageKeyF = () => typeof window !== undefined
23
+ const localStorageKeyF = () => typeof window !== 'undefined'
24
24
  ? `bookmarks-${[window.location.host + window.location.pathname].join('-')}`
25
25
  : 'empty';
26
26
  /**
@@ -49,7 +49,7 @@ async function navToBookmark(locString, assembly, views, model) {
49
49
  }
50
50
  catch (e) {
51
51
  console.error(e);
52
- session.notify(`${e}`, 'error');
52
+ session.notifyError(`${e}`, e);
53
53
  }
54
54
  }
55
55
  exports.navToBookmark = navToBookmark;
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import Plugin from '@jbrowse/core/Plugin';
2
2
  import PluginManager from '@jbrowse/core/PluginManager';
3
- export default class extends Plugin {
3
+ export default class GridBookmarkPlugin extends Plugin {
4
4
  name: string;
5
5
  install(pluginManager: PluginManager): void;
6
6
  configure(pluginManager: PluginManager): void;
package/dist/index.js CHANGED
@@ -11,7 +11,7 @@ const Bookmarks_1 = __importDefault(require("@mui/icons-material/Bookmarks"));
11
11
  const Highlight_1 = __importDefault(require("@mui/icons-material/Highlight"));
12
12
  const Label_1 = __importDefault(require("@mui/icons-material/Label"));
13
13
  const GridBookmarkWidget_1 = __importDefault(require("./GridBookmarkWidget"));
14
- class default_1 extends Plugin_1.default {
14
+ class GridBookmarkPlugin extends Plugin_1.default {
15
15
  constructor() {
16
16
  super(...arguments);
17
17
  this.name = 'GridBookmarkPlugin';
@@ -180,4 +180,4 @@ class default_1 extends Plugin_1.default {
180
180
  }
181
181
  }
182
182
  }
183
- exports.default = default_1;
183
+ exports.default = GridBookmarkPlugin;
@@ -90,7 +90,7 @@ const BookmarkGrid = observer(function ({ model, }) {
90
90
  const target = rows[row.id];
91
91
  model.updateBookmarkLabel(target, row.label);
92
92
  return row;
93
- }, onProcessRowUpdateError: e => session.notify(e.message, 'error'), checkboxSelection: true, onRowSelectionModelChange: newRowSelectionModel => {
93
+ }, onProcessRowUpdateError: e => session.notifyError(`${e}`, e), checkboxSelection: true, onRowSelectionModelChange: newRowSelectionModel => {
94
94
  if (bookmarksWithValidAssemblies.length > 0) {
95
95
  model.setSelectedBookmarks(newRowSelectionModel.map(value => ({
96
96
  ...rows[value],
@@ -3,5 +3,5 @@ import { IExtendedLGV } from '../../model';
3
3
  type LGV = IExtendedLGV;
4
4
  declare const Highlight: ({ model }: {
5
5
  model: LGV;
6
- }) => React.JSX.Element;
6
+ }) => React.JSX.Element[] | null;
7
7
  export default Highlight;
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useRef } from 'react';
1
+ import React, { useEffect } from 'react';
2
2
  import { observer } from 'mobx-react';
3
3
  import { makeStyles } from 'tss-react/mui';
4
4
  import { getSession, notEmpty } from '@jbrowse/core/util';
@@ -10,38 +10,29 @@ const useStyles = makeStyles()({
10
10
  highlight: {
11
11
  height: '100%',
12
12
  position: 'absolute',
13
- textAlign: 'center',
14
13
  overflow: 'hidden',
15
- display: 'flex',
16
- alignItems: 'start',
17
14
  },
18
15
  });
19
16
  const Highlight = observer(function Highlight({ model }) {
20
17
  var _a;
21
18
  const { classes } = useStyles();
22
19
  const session = getSession(model);
20
+ const { assemblyManager } = session;
23
21
  const { showBookmarkHighlights, showBookmarkLabels } = model;
24
- const assemblyNames = new Set(session.assemblyNames);
25
22
  const bookmarkWidget = session.widgets.get('GridBookmark');
26
- const bookmarks = useRef((_a = bookmarkWidget === null || bookmarkWidget === void 0 ? void 0 : bookmarkWidget.bookmarks) !== null && _a !== void 0 ? _a : []);
27
23
  useEffect(() => {
28
24
  if (!bookmarkWidget) {
29
- const newBookmarkWidget = session.addWidget('GridBookmarkWidget', 'GridBookmark');
30
- bookmarks.current = newBookmarkWidget.bookmarks;
25
+ session.addWidget('GridBookmarkWidget', 'GridBookmark');
31
26
  }
32
27
  }, [session, bookmarkWidget]);
33
- return (React.createElement(React.Fragment, null, showBookmarkHighlights && bookmarks.current
34
- ? bookmarks.current
35
- .filter(value => assemblyNames.has(value.assemblyName))
36
- .map(r => {
37
- const s = model.bpToPx({
38
- refName: r.refName,
39
- coord: r.start,
40
- });
41
- const e = model.bpToPx({
42
- refName: r.refName,
43
- coord: r.end,
44
- });
28
+ const set = new Set(model.assemblyNames);
29
+ return showBookmarkHighlights
30
+ ? (_a = bookmarkWidget === null || bookmarkWidget === void 0 ? void 0 : bookmarkWidget.bookmarks) === null || _a === void 0 ? void 0 : _a.filter(value => set.has(value.assemblyName)).map(r => {
31
+ var _a;
32
+ const asm = assemblyManager.get(r.assemblyName);
33
+ const refName = (_a = asm === null || asm === void 0 ? void 0 : asm.getCanonicalRefName(r.refName)) !== null && _a !== void 0 ? _a : r.refName;
34
+ const s = model.bpToPx({ refName, coord: r.start });
35
+ const e = model.bpToPx({ refName, coord: r.end });
45
36
  return s && e
46
37
  ? {
47
38
  width: Math.max(Math.abs(e.offsetPx - s.offsetPx), 3),
@@ -50,14 +41,16 @@ const Highlight = observer(function Highlight({ model }) {
50
41
  label: r.label,
51
42
  }
52
43
  : undefined;
53
- })
54
- .filter(notEmpty)
55
- .map(({ left, width, highlight, label }, idx) => (React.createElement("div", { key: `${left}_${width}_${idx}`, className: classes.highlight, style: { left, width, background: highlight } }, showBookmarkLabels ? (React.createElement(Tooltip, { title: label, arrow: true },
44
+ }).filter(notEmpty).map(({ left, width, highlight, label }, idx) => (React.createElement("div", { key: `${left}_${width}_${idx}`, className: classes.highlight, style: {
45
+ left,
46
+ width,
47
+ background: highlight,
48
+ } }, showBookmarkLabels ? (React.createElement(Tooltip, { title: label, arrow: true },
56
49
  React.createElement(BookmarkIcon, { fontSize: "small", sx: {
57
50
  color: `${colord(highlight).alpha() !== 0
58
51
  ? colord(highlight).alpha(0.8).toRgbString()
59
52
  : colord(highlight).alpha(0).toRgbString()}`,
60
53
  } }))) : null)))
61
- : null));
54
+ : null;
62
55
  });
63
56
  export default Highlight;
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { Base1DViewModel } from '@jbrowse/core/util/Base1DViewModel';
3
+ import { IExtendedLGV } from '../../model';
4
+ type LGV = IExtendedLGV;
5
+ declare const OverviewHighlight: ({ model, overview, }: {
6
+ model: LGV;
7
+ overview: Base1DViewModel;
8
+ }) => React.JSX.Element[] | null;
9
+ export default OverviewHighlight;
@@ -0,0 +1,54 @@
1
+ import React, { useEffect } from 'react';
2
+ import { observer } from 'mobx-react';
3
+ import { makeStyles } from 'tss-react/mui';
4
+ import { getSession, notEmpty } from '@jbrowse/core/util';
5
+ import { Tooltip } from '@mui/material';
6
+ const useStyles = makeStyles()({
7
+ highlight: {
8
+ height: '100%',
9
+ position: 'absolute',
10
+ },
11
+ });
12
+ const OverviewHighlight = observer(function OverviewHighlight({ model, overview, }) {
13
+ const { cytobandOffset } = model;
14
+ const session = getSession(model);
15
+ const { classes } = useStyles();
16
+ const { assemblyManager } = session;
17
+ const { showBookmarkHighlights, showBookmarkLabels } = model;
18
+ const bookmarkWidget = session.widgets.get('GridBookmark');
19
+ useEffect(() => {
20
+ if (!bookmarkWidget) {
21
+ session.addWidget('GridBookmarkWidget', 'GridBookmark');
22
+ }
23
+ }, [session, bookmarkWidget]);
24
+ const assemblyNames = new Set(model.assemblyNames);
25
+ return showBookmarkHighlights
26
+ ? bookmarkWidget === null || bookmarkWidget === void 0 ? void 0 : bookmarkWidget.bookmarks.filter(r => assemblyNames.has(r.assemblyName)).map(r => {
27
+ var _a;
28
+ const asm = assemblyManager.get(r.assemblyName);
29
+ const refName = (_a = asm === null || asm === void 0 ? void 0 : asm.getCanonicalRefName(r.refName)) !== null && _a !== void 0 ? _a : r.refName;
30
+ const rev = r.reversed;
31
+ const s = overview.bpToPx({ refName, coord: rev ? r.end : r.start });
32
+ const e = overview.bpToPx({ refName, coord: rev ? r.start : r.end });
33
+ return s !== undefined && e !== undefined
34
+ ? {
35
+ width: Math.abs(e - s),
36
+ left: s + cytobandOffset,
37
+ highlight: r.highlight,
38
+ label: r.label,
39
+ }
40
+ : undefined;
41
+ }).filter(notEmpty).map((obj, idx) => {
42
+ const { left, width, highlight, label } = obj;
43
+ return (React.createElement(Tooltip, { key: JSON.stringify(obj) + '-' + idx, title: showBookmarkLabels ? label : '', arrow: true },
44
+ React.createElement("div", { className: classes.highlight, style: {
45
+ left,
46
+ width,
47
+ background: highlight,
48
+ borderLeft: `1px solid ${highlight}`,
49
+ borderRight: `1px solid ${highlight}`,
50
+ } })));
51
+ })
52
+ : null;
53
+ });
54
+ export default OverviewHighlight;
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  // locals
3
3
  import Highlight from './Highlight';
4
+ import OverviewHighlight from './OverviewHighlight';
4
5
  export default function AddHighlightModelF(pluginManager) {
5
6
  pluginManager.addToExtensionPoint('LinearGenomeView-TracksContainerComponent',
6
7
  // @ts-expect-error
@@ -10,4 +11,12 @@ export default function AddHighlightModelF(pluginManager) {
10
11
  React.createElement(Highlight, { key: `highlight_grid_bookmark`, model: model }),
11
12
  ];
12
13
  });
14
+ pluginManager.addToExtensionPoint('LinearGenomeView-OverviewScalebarComponent',
15
+ // @ts-expect-error
16
+ (rest = [], { model, overview }) => {
17
+ return [
18
+ ...rest,
19
+ React.createElement(OverviewHighlight, { key: `overview_highlight_grid_bookmark`, model: model, overview: overview }),
20
+ ];
21
+ });
13
22
  }
@@ -8,7 +8,9 @@ import GetAppIcon from '@mui/icons-material/GetApp';
8
8
  import { downloadBookmarkFile } from '../../utils';
9
9
  const useStyles = makeStyles()({
10
10
  flexItem: {
11
- margin: 5,
11
+ display: 'flex',
12
+ alignItems: 'center',
13
+ gap: '5px',
12
14
  },
13
15
  container: {
14
16
  display: 'flex',
@@ -27,9 +29,9 @@ const ExportBookmarksDialog = observer(function ExportBookmarksDialog({ model, o
27
29
  React.createElement("span", null, "All bookmarks will be exported."),
28
30
  React.createElement("br", null),
29
31
  React.createElement("span", null, "Use the checkboxes to select individual bookmarks to export."))) : ('Only selected bookmarks will be exported.')),
30
- React.createElement("div", { style: { display: 'flex', alignItems: 'center' } },
32
+ React.createElement("div", { className: classes.flexItem },
31
33
  React.createElement(Typography, null, "Format to download:"),
32
- React.createElement(Select, { size: "small", className: classes.flexItem, "data-testid": "selectFileType", value: fileType, onChange: event => setFileType(event.target.value) },
34
+ React.createElement(Select, { size: "small", value: fileType, onChange: event => setFileType(event.target.value) },
33
35
  React.createElement(MenuItem, { value: "BED" }, "BED"),
34
36
  React.createElement(MenuItem, { value: "TSV" }, "TSV")))),
35
37
  React.createElement(DialogActions, null,
@@ -2,27 +2,25 @@ import React, { useState } from 'react';
2
2
  import { observer } from 'mobx-react';
3
3
  import { getSession } from '@jbrowse/core/util';
4
4
  import { isSessionWithShareURL } from '@jbrowse/core/util/types';
5
- import { FileSelector } from '@jbrowse/core/ui';
6
- import { Button, DialogContent, DialogActions, Typography, TextField, Accordion, AccordionSummary, AccordionDetails, Tooltip, } from '@mui/material';
5
+ import { ErrorMessage, FileSelector } from '@jbrowse/core/ui';
6
+ import { Accordion, AccordionSummary, AccordionDetails, Button, DialogContent, DialogActions, TextField, Typography, } from '@mui/material';
7
7
  import { openLocation } from '@jbrowse/core/util/io';
8
- import { Dialog } from '@jbrowse/core/ui';
9
- import AssemblySelector from '@jbrowse/core/ui/AssemblySelector';
8
+ import { Dialog, AssemblySelector } from '@jbrowse/core/ui';
10
9
  import { makeStyles } from 'tss-react/mui';
11
10
  // icons
12
11
  import ImportIcon from '@mui/icons-material/Publish';
13
12
  import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
14
- import HelpIcon from '@mui/icons-material/Help';
15
13
  import { fromUrlSafeB64 } from '../../utils';
16
14
  import { readSessionFromDynamo } from '../../sessionSharing';
17
15
  const useStyles = makeStyles()(theme => {
18
16
  var _a;
19
17
  return ({
20
- flexItem: {
21
- margin: 5,
22
- },
23
18
  expandIcon: {
24
19
  color: ((_a = theme.palette.tertiary) === null || _a === void 0 ? void 0 : _a.contrastText) || '#fff',
25
20
  },
21
+ minWidth: {
22
+ minWidth: 500,
23
+ },
26
24
  });
27
25
  });
28
26
  async function getBookmarksFromShareLink(shareLink, shareURL) {
@@ -34,18 +32,35 @@ async function getBookmarksFromShareLink(shareLink, shareURL) {
34
32
  const sharedSession = JSON.parse(await fromUrlSafeB64(decryptedSession));
35
33
  return sharedSession.sharedBookmarks;
36
34
  }
37
- async function getBookmarksFromFile(location, selectedAsm) {
38
- const data = await openLocation(location).readFile('utf8');
39
- return data
40
- .split(/\n|\r\n|\r/)
41
- .filter(f => !!f.trim())
42
- .filter(f => !f.startsWith('#') &&
43
- !f.startsWith('track') &&
44
- !f.startsWith('browser'))
35
+ function guessFileType(header) {
36
+ return header.startsWith('chrom') && header.includes('assembly_name')
37
+ ? 'TSV'
38
+ : 'BED';
39
+ }
40
+ async function getBookmarksFromTSVFile(lines) {
41
+ if (lines[0].startsWith('chrom')) {
42
+ lines = lines.slice(1);
43
+ }
44
+ return lines
45
+ .filter(f => !f.startsWith('#'))
46
+ .map(line => {
47
+ const [refName, start, end, label, assemblyName] = line.split('\t');
48
+ return {
49
+ assemblyName: assemblyName,
50
+ refName,
51
+ start: +start,
52
+ end: +end,
53
+ label: label === '.' ? undefined : label,
54
+ };
55
+ });
56
+ }
57
+ async function getBookmarksFromBEDFile(lines, selectedAsm) {
58
+ return lines
59
+ .filter(f => !f.startsWith('#'))
45
60
  .map(line => {
46
- const [refName, start, end, label, assembly] = line.split('\t');
61
+ const [refName, start, end, label] = line.split('\t');
47
62
  return {
48
- assemblyName: assembly !== null && assembly !== void 0 ? assembly : selectedAsm,
63
+ assemblyName: selectedAsm,
49
64
  refName,
50
65
  start: +start,
51
66
  end: +end,
@@ -63,31 +78,39 @@ const ImportBookmarksDialog = observer(function ({ onClose, model, }) {
63
78
  const [selectedAsm, setSelectedAsm] = useState(assemblyNames[0]);
64
79
  const [expanded, setExpanded] = useState('shareLinkAccordion');
65
80
  return (React.createElement(Dialog, { open: true, onClose: onClose, maxWidth: "xl", title: "Import bookmarks" },
66
- React.createElement(DialogContent, null,
81
+ React.createElement(DialogContent, { className: classes.minWidth },
67
82
  React.createElement(Accordion, { expanded: expanded === 'shareLinkAccordion', onChange: () => setExpanded('shareLinkAccordion') },
68
83
  React.createElement(AccordionSummary, { expandIcon: React.createElement(ExpandMoreIcon, { className: classes.expandIcon }) },
69
- React.createElement(Typography, { style: { display: 'flex', alignItems: 'center', gap: '5px' } },
70
- "Import from share link",
71
- ' ',
72
- React.createElement(Tooltip, { title: "The appropriate share link for sharing bookmarks is one generated via the 'Share' button in the 'Bookmarked regions' drawer. Paste it below to import shared bookmarks." },
73
- React.createElement(HelpIcon, null)))),
84
+ React.createElement(Typography, { style: { display: 'flex', alignItems: 'center', gap: '5px' } }, "Import from share link")),
74
85
  React.createElement(AccordionDetails, null,
75
- React.createElement(TextField, { label: "Enter URL", variant: "outlined", style: { width: '100%' }, value: shareLink, onChange: e => setShareLink(e.target.value) }))),
86
+ React.createElement(Typography, null, "Paste a bookmark share link generated by the 'Share' button from the bookmarks widget"),
87
+ React.createElement(TextField, { label: "Enter Share URL", variant: "outlined", fullWidth: true, value: shareLink, onChange: e => setShareLink(e.target.value) }))),
76
88
  React.createElement(Accordion, { expanded: expanded === 'fileAccordion', onChange: () => setExpanded('fileAccordion') },
77
89
  React.createElement(AccordionSummary, { expandIcon: React.createElement(ExpandMoreIcon, { className: classes.expandIcon }) },
78
90
  React.createElement(Typography, null, "Import from file")),
79
91
  React.createElement(AccordionDetails, null,
80
- React.createElement(FileSelector, { location: location, setLocation: setLocation, name: "File", description: "Choose a BED or TSV format file to import." }),
81
- React.createElement(AssemblySelector, { onChange: val => setSelectedAsm(val), helperText: `Select the assembly your bookmarks belong to (BED or TSV without assembly column).`, session: session, selected: selectedAsm }))),
82
- error ? (React.createElement(Typography, { color: "error", variant: "h6" }, `${error}`)) : null),
92
+ React.createElement(FileSelector, { location: location, setLocation: setLocation, name: "File", description: `Choose a BED or TSV format file to import. Required TSV column headers are "chrom, start, end, label, assembly_name".` }),
93
+ React.createElement(AssemblySelector, { onChange: val => setSelectedAsm(val), helperText: `Select the assembly for BED file.`, session: session, selected: selectedAsm }))),
94
+ error ? React.createElement(ErrorMessage, { error: error }) : null),
83
95
  React.createElement(DialogActions, null,
84
96
  React.createElement(Button, { variant: "contained", color: "secondary", onClick: onClose }, "Cancel"),
85
- React.createElement(Button, { className: classes.flexItem, "data-testid": "dialogImport", variant: "contained", color: "primary", disabled: !location && !shareLink, startIcon: React.createElement(ImportIcon, null), onClick: async () => {
97
+ React.createElement(Button, { "data-testid": "dialogImport", variant: "contained", color: "primary", disabled: !location && !shareLink, startIcon: React.createElement(ImportIcon, null), onClick: async () => {
86
98
  try {
87
- if (location) {
88
- model.importBookmarks(await getBookmarksFromFile(location, selectedAsm));
99
+ if (expanded === 'fileAccordion' && location) {
100
+ const data = await openLocation(location).readFile('utf8');
101
+ const lines = data.split(/\n|\r\n|\r/).filter(f => !!f.trim());
102
+ const fileType = guessFileType(lines[0]);
103
+ if (fileType === 'BED') {
104
+ model.importBookmarks(await getBookmarksFromBEDFile(lines, selectedAsm));
105
+ }
106
+ else {
107
+ // TSV
108
+ model.importBookmarks(await getBookmarksFromTSVFile(lines));
109
+ }
89
110
  }
90
- else if (shareLink && isSessionWithShareURL(session)) {
111
+ else if (expanded === 'shareLinkAccordion' &&
112
+ shareLink &&
113
+ isSessionWithShareURL(session)) {
91
114
  model.importBookmarks(await getBookmarksFromShareLink(shareLink, session.shareURL));
92
115
  }
93
116
  onClose();
@@ -1,3 +1,2 @@
1
1
  import PluginManager from '@jbrowse/core/PluginManager';
2
- declare const _default: (pluginManager: PluginManager) => void;
3
- export default _default;
2
+ export default function GridBookmarkWidgetF(pluginManager: PluginManager): void;
@@ -5,7 +5,7 @@ import { WidgetType } from '@jbrowse/core/pluggableElementTypes';
5
5
  import stateModelFactory from './model';
6
6
  import AddHighlightModelF from './components/Highlight';
7
7
  const configSchema = ConfigurationSchema('GridBookmarkWidget', {});
8
- export default (pluginManager) => {
8
+ export default function GridBookmarkWidgetF(pluginManager) {
9
9
  pluginManager.addWidgetType(() => {
10
10
  return new WidgetType({
11
11
  name: 'GridBookmarkWidget',
@@ -16,4 +16,4 @@ export default (pluginManager) => {
16
16
  });
17
17
  });
18
18
  AddHighlightModelF(pluginManager);
19
- };
19
+ }
@@ -18,7 +18,7 @@ const LabeledRegionModel = types
18
18
  const SharedBookmarksModel = types.model('SharedBookmarksModel', {
19
19
  sharedBookmarks: types.maybe(types.array(LabeledRegionModel)),
20
20
  });
21
- const localStorageKeyF = () => typeof window !== undefined
21
+ const localStorageKeyF = () => typeof window !== 'undefined'
22
22
  ? `bookmarks-${[window.location.host + window.location.pathname].join('-')}`
23
23
  : 'empty';
24
24
  /**
@@ -23,7 +23,7 @@ export async function navToBookmark(locString, assembly, views, model) {
23
23
  }
24
24
  catch (e) {
25
25
  console.error(e);
26
- session.notify(`${e}`, 'error');
26
+ session.notifyError(`${e}`, e);
27
27
  }
28
28
  }
29
29
  export function downloadBookmarkFile(fileFormat, model) {
package/esm/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import Plugin from '@jbrowse/core/Plugin';
2
2
  import PluginManager from '@jbrowse/core/PluginManager';
3
- export default class extends Plugin {
3
+ export default class GridBookmarkPlugin extends Plugin {
4
4
  name: string;
5
5
  install(pluginManager: PluginManager): void;
6
6
  configure(pluginManager: PluginManager): void;
package/esm/index.js CHANGED
@@ -6,7 +6,7 @@ import BookmarksIcon from '@mui/icons-material/Bookmarks';
6
6
  import HighlightIcon from '@mui/icons-material/Highlight';
7
7
  import LabelIcon from '@mui/icons-material/Label';
8
8
  import GridBookmarkWidgetF from './GridBookmarkWidget';
9
- export default class extends Plugin {
9
+ export default class GridBookmarkPlugin extends Plugin {
10
10
  constructor() {
11
11
  super(...arguments);
12
12
  this.name = 'GridBookmarkPlugin';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/plugin-grid-bookmark",
3
- "version": "2.10.3",
3
+ "version": "2.11.1",
4
4
  "description": "JBrowse 2 grid bookmark widget",
5
5
  "keywords": [
6
6
  "jbrowse",
@@ -46,7 +46,7 @@
46
46
  "@jbrowse/plugin-config": "^2.0.0",
47
47
  "@jbrowse/plugin-linear-genome-view": "^2.0.0",
48
48
  "@mui/material": "^5.0.0",
49
- "@mui/x-data-grid": "^6.0.1",
49
+ "@mui/x-data-grid": "^7.0.0",
50
50
  "mobx": "^6.0.0",
51
51
  "mobx-react": "^9.0.0",
52
52
  "mobx-state-tree": "^5.0.0",
@@ -59,5 +59,5 @@
59
59
  "distModule": "esm/index.js",
60
60
  "srcModule": "src/index.ts",
61
61
  "module": "esm/index.js",
62
- "gitHead": "c8fc800cd17decd72b2e971c7a6add3b95214e72"
62
+ "gitHead": "11b28d66d782eb06f92ccb993108bb6c3c82819e"
63
63
  }