@jbrowse/plugin-linear-genome-view 2.10.3 → 2.11.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.
Files changed (52) hide show
  1. package/dist/BaseLinearDisplay/models/serverSideRenderedBlock.js +0 -1
  2. package/dist/LaunchLinearGenomeView/index.js +14 -6
  3. package/dist/LinearBasicDisplay/components/SetMaxHeight.d.ts +1 -1
  4. package/dist/LinearGenomeView/components/Cytobands.d.ts +1 -125
  5. package/dist/LinearGenomeView/components/ExportSvgDialog.js +9 -5
  6. package/dist/LinearGenomeView/components/Highlight.d.ts +3 -3
  7. package/dist/LinearGenomeView/components/Highlight.js +21 -17
  8. package/dist/LinearGenomeView/components/MiniControls.js +13 -15
  9. package/dist/LinearGenomeView/components/OverviewHighlight.d.ts +1 -1
  10. package/dist/LinearGenomeView/components/OverviewHighlight.js +20 -11
  11. package/dist/LinearGenomeView/components/OverviewRubberband.d.ts +1 -1
  12. package/dist/LinearGenomeView/components/OverviewScalebar.js +4 -1
  13. package/dist/LinearGenomeView/components/OverviewScalebarPolygon.d.ts +1 -1
  14. package/dist/LinearGenomeView/components/RefNameAutocomplete/index.d.ts +9 -9
  15. package/dist/LinearGenomeView/components/RefNameAutocomplete/index.js +28 -35
  16. package/dist/LinearGenomeView/components/Rubberband.d.ts +1 -1
  17. package/dist/LinearGenomeView/components/SearchBox.d.ts +1 -1
  18. package/dist/LinearGenomeView/components/SearchResultsTable.js +1 -1
  19. package/dist/LinearGenomeView/components/TrackContainer.js +10 -23
  20. package/dist/LinearGenomeView/components/TrackLabel.js +33 -6
  21. package/dist/LinearGenomeView/components/ZoomControls.js +4 -4
  22. package/dist/LinearGenomeView/model.d.ts +67 -7
  23. package/dist/LinearGenomeView/model.js +102 -16
  24. package/dist/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js +1 -1
  25. package/dist/index.d.ts +159 -21
  26. package/esm/BaseLinearDisplay/models/serverSideRenderedBlock.js +0 -1
  27. package/esm/LaunchLinearGenomeView/index.js +14 -6
  28. package/esm/LinearBasicDisplay/components/SetMaxHeight.d.ts +1 -1
  29. package/esm/LinearGenomeView/components/Cytobands.d.ts +1 -125
  30. package/esm/LinearGenomeView/components/ExportSvgDialog.js +9 -5
  31. package/esm/LinearGenomeView/components/Highlight.d.ts +3 -3
  32. package/esm/LinearGenomeView/components/Highlight.js +21 -17
  33. package/esm/LinearGenomeView/components/MiniControls.js +14 -16
  34. package/esm/LinearGenomeView/components/OverviewHighlight.d.ts +1 -1
  35. package/esm/LinearGenomeView/components/OverviewHighlight.js +20 -11
  36. package/esm/LinearGenomeView/components/OverviewRubberband.d.ts +1 -1
  37. package/esm/LinearGenomeView/components/OverviewScalebar.js +5 -2
  38. package/esm/LinearGenomeView/components/OverviewScalebarPolygon.d.ts +1 -1
  39. package/esm/LinearGenomeView/components/RefNameAutocomplete/index.d.ts +9 -9
  40. package/esm/LinearGenomeView/components/RefNameAutocomplete/index.js +28 -35
  41. package/esm/LinearGenomeView/components/Rubberband.d.ts +1 -1
  42. package/esm/LinearGenomeView/components/SearchBox.d.ts +1 -1
  43. package/esm/LinearGenomeView/components/SearchResultsTable.js +1 -1
  44. package/esm/LinearGenomeView/components/TrackContainer.js +10 -23
  45. package/esm/LinearGenomeView/components/TrackLabel.js +33 -6
  46. package/esm/LinearGenomeView/components/TracksContainer.js +2 -2
  47. package/esm/LinearGenomeView/components/ZoomControls.js +4 -4
  48. package/esm/LinearGenomeView/model.d.ts +67 -7
  49. package/esm/LinearGenomeView/model.js +103 -17
  50. package/esm/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js +1 -1
  51. package/esm/index.d.ts +159 -21
  52. package/package.json +2 -2
@@ -74,7 +74,7 @@ function SearchResultsTable({ searchResults, assemblyName: optAssemblyName, mode
74
74
  }
75
75
  catch (e) {
76
76
  console.error(e);
77
- session.notify(`${e}`, 'error');
77
+ session.notifyError(`${e}`, e);
78
78
  }
79
79
  handleClose();
80
80
  }, color: "primary", variant: "contained" }, "Go")))))))));
@@ -33,7 +33,6 @@ const mobx_react_1 = require("mobx-react");
33
33
  const mobx_state_tree_1 = require("mobx-state-tree");
34
34
  const react_error_boundary_1 = require("react-error-boundary");
35
35
  const ui_1 = require("@jbrowse/core/ui");
36
- const util_1 = require("@jbrowse/core/util");
37
36
  const TrackLabelContainer_1 = __importDefault(require("./TrackLabelContainer"));
38
37
  const TrackRenderingContainer_1 = __importDefault(require("./TrackRenderingContainer"));
39
38
  const useStyles = (0, mui_1.makeStyles)()({
@@ -46,40 +45,28 @@ const useStyles = (0, mui_1.makeStyles)()({
46
45
  position: 'relative',
47
46
  zIndex: 2,
48
47
  },
49
- overlay: {
50
- pointerEvents: 'none',
51
- position: 'absolute',
52
- top: 0,
53
- left: 0,
54
- width: '100%',
55
- zIndex: 3,
56
- },
57
48
  });
58
49
  const TrackContainer = (0, mobx_react_1.observer)(function ({ model, track, }) {
59
50
  const { classes } = useStyles();
60
51
  const display = track.displays[0];
61
52
  const { draggingTrackId } = model;
62
- const ref2 = (0, react_1.useRef)(null);
63
- const dimmed = draggingTrackId !== undefined && draggingTrackId !== display.id;
64
- const debouncedOnDragEnter = (0, util_1.useDebouncedCallback)(() => {
65
- if ((0, mobx_state_tree_1.isAlive)(display) && dimmed) {
66
- model.moveTrack(draggingTrackId, track.id);
67
- }
68
- }, 100);
69
- return (react_1.default.createElement(material_1.Paper, { ref: ref2, className: classes.root, variant: "outlined", onClick: event => {
53
+ const ref = (0, react_1.useRef)(null);
54
+ return (react_1.default.createElement(material_1.Paper, { ref: ref, className: classes.root, variant: "outlined", onClick: event => {
70
55
  var _a;
71
56
  if (event.detail === 2 && !track.displays[0].featureIdUnderMouse) {
72
- const left = ((_a = ref2.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect().left) || 0;
57
+ const left = ((_a = ref.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect().left) || 0;
73
58
  model.zoomTo(model.bpPerPx / 2, event.clientX - left, true);
74
59
  }
75
60
  } },
76
61
  react_1.default.createElement(TrackLabelContainer_1.default, { track: track, view: model }),
77
62
  react_1.default.createElement(react_error_boundary_1.ErrorBoundary, { FallbackComponent: e => react_1.default.createElement(ui_1.ErrorMessage, { error: e.error }) },
78
- react_1.default.createElement(TrackRenderingContainer_1.default, { model: model, track: track, onDragEnter: debouncedOnDragEnter })),
79
- react_1.default.createElement("div", { className: classes.overlay, style: {
80
- height: display.height,
81
- background: dimmed ? 'rgba(0, 0, 0, 0.4)' : undefined,
82
- }, onDragEnter: debouncedOnDragEnter }),
63
+ react_1.default.createElement(TrackRenderingContainer_1.default, { model: model, track: track, onDragEnter: () => {
64
+ if ((0, mobx_state_tree_1.isAlive)(display) &&
65
+ draggingTrackId !== undefined &&
66
+ draggingTrackId !== display.id) {
67
+ model.moveTrack(draggingTrackId, track.id);
68
+ }
69
+ } })),
83
70
  react_1.default.createElement(ui_1.ResizeHandle, { onDrag: display.resizeHeight, className: classes.resizeHandle })));
84
71
  });
85
72
  exports.default = TrackContainer;
@@ -17,6 +17,10 @@ const MoreVert_1 = __importDefault(require("@mui/icons-material/MoreVert"));
17
17
  const Close_1 = __importDefault(require("@mui/icons-material/Close"));
18
18
  const Minimize_1 = __importDefault(require("@mui/icons-material/Minimize"));
19
19
  const Add_1 = __importDefault(require("@mui/icons-material/Add"));
20
+ const KeyboardDoubleArrowDown_1 = __importDefault(require("@mui/icons-material/KeyboardDoubleArrowDown"));
21
+ const KeyboardDoubleArrowUp_1 = __importDefault(require("@mui/icons-material/KeyboardDoubleArrowUp"));
22
+ const KeyboardArrowDown_1 = __importDefault(require("@mui/icons-material/KeyboardArrowDown"));
23
+ const KeyboardArrowUp_1 = __importDefault(require("@mui/icons-material/KeyboardArrowUp"));
20
24
  const TrackLabelDragHandle_1 = __importDefault(require("./TrackLabelDragHandle"));
21
25
  const useStyles = (0, mui_1.makeStyles)()(theme => ({
22
26
  root: {
@@ -24,9 +28,6 @@ const useStyles = (0, mui_1.makeStyles)()(theme => ({
24
28
  '&:hover': {
25
29
  background: theme.palette.background.paper,
26
30
  },
27
- transition: theme.transitions.create(['background'], {
28
- duration: theme.transitions.duration.shortest,
29
- }),
30
31
  },
31
32
  trackName: {
32
33
  margin: '0 auto',
@@ -49,9 +50,35 @@ const TrackLabel = (0, mobx_react_1.observer)(react_1.default.forwardRef(functio
49
50
  const trackName = (0, tracks_1.getTrackName)(trackConf, session);
50
51
  const items = [
51
52
  {
52
- label: minimized ? 'Restore track' : 'Minimize track',
53
- icon: minimized ? Add_1.default : Minimize_1.default,
54
- onClick: () => track.setMinimized(!minimized),
53
+ label: 'Track order',
54
+ type: 'subMenu',
55
+ subMenu: [
56
+ {
57
+ label: minimized ? 'Restore track' : 'Minimize track',
58
+ icon: minimized ? Add_1.default : Minimize_1.default,
59
+ onClick: () => track.setMinimized(!minimized),
60
+ },
61
+ {
62
+ label: 'Move track to top',
63
+ icon: KeyboardDoubleArrowUp_1.default,
64
+ onClick: () => view.moveTrackToTop(track.id),
65
+ },
66
+ {
67
+ label: 'Move track up',
68
+ icon: KeyboardArrowUp_1.default,
69
+ onClick: () => view.moveTrackUp(track.id),
70
+ },
71
+ {
72
+ label: 'Move track down',
73
+ icon: KeyboardArrowDown_1.default,
74
+ onClick: () => view.moveTrackDown(track.id),
75
+ },
76
+ {
77
+ label: 'Move track to bottom',
78
+ icon: KeyboardDoubleArrowDown_1.default,
79
+ onClick: () => view.moveTrackToBottom(track.id),
80
+ },
81
+ ],
55
82
  },
56
83
  ...(((_a = session.getTrackActionMenuItems) === null || _a === void 0 ? void 0 : _a.call(session, trackConf)) || []),
57
84
  ...track.trackMenuItems(),
@@ -45,16 +45,16 @@ const useStyles = (0, mui_1.makeStyles)()(theme => ({
45
45
  }));
46
46
  const ZoomControls = (0, mobx_react_1.observer)(function ({ model, }) {
47
47
  const { classes } = useStyles();
48
- const { maxBpPerPx, minBpPerPx, bpPerPx, scaleFactor } = model;
48
+ const { maxBpPerPx, minBpPerPx, bpPerPx } = model;
49
49
  const [value, setValue] = (0, react_1.useState)(-Math.log2(bpPerPx) * 100);
50
50
  (0, react_1.useEffect)(() => {
51
51
  setValue(-Math.log2(bpPerPx) * 100);
52
52
  }, [setValue, bpPerPx]);
53
53
  return (react_1.default.createElement("div", { className: classes.container },
54
- react_1.default.createElement(material_1.IconButton, { "data-testid": "zoom_out", onClick: () => model.zoom(bpPerPx * 2), disabled: bpPerPx >= maxBpPerPx - 0.0001 || scaleFactor !== 1, size: "large" },
54
+ react_1.default.createElement(material_1.IconButton, { "data-testid": "zoom_out", onClick: () => model.zoom(bpPerPx * 2), disabled: bpPerPx >= maxBpPerPx - 0.0001, size: "large" },
55
55
  react_1.default.createElement(ZoomOut_1.default, null)),
56
- react_1.default.createElement(material_1.Slider, { size: "small", className: classes.slider, value: value, min: -Math.log2(maxBpPerPx) * 100, max: -Math.log2(minBpPerPx) * 100, onChange: (_, val) => setValue(val), onChangeCommitted: () => model.zoomTo(2 ** (-value / 100)), disabled: scaleFactor !== 1 }),
57
- react_1.default.createElement(material_1.IconButton, { "data-testid": "zoom_in", onClick: () => model.zoom(model.bpPerPx / 2), disabled: bpPerPx <= minBpPerPx + 0.0001 || scaleFactor !== 1, size: "large" },
56
+ react_1.default.createElement(material_1.Slider, { size: "small", className: classes.slider, value: value, min: -Math.log2(maxBpPerPx) * 100, max: -Math.log2(minBpPerPx) * 100, onChange: (_, val) => setValue(val), onChangeCommitted: () => model.zoomTo(2 ** (-value / 100)) }),
57
+ react_1.default.createElement(material_1.IconButton, { "data-testid": "zoom_in", onClick: () => model.zoom(model.bpPerPx / 2), disabled: bpPerPx <= minBpPerPx + 0.0001, size: "large" },
58
58
  react_1.default.createElement(ZoomIn_1.default, null))));
59
59
  });
60
60
  exports.default = ZoomControls;
@@ -81,7 +81,8 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
81
81
  showCytobandsSetting: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<boolean>, [undefined]>;
82
82
  trackLabels: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
83
83
  showGridlines: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
84
- highlight: import("mobx-state-tree").IMaybe<import("mobx-state-tree").IType<Required<ParsedLocString>, Required<ParsedLocString>, Required<ParsedLocString>>>;
84
+ highlight: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").IArrayType<import("mobx-state-tree").IType<Required<ParsedLocString>, Required<ParsedLocString>, Required<ParsedLocString>>>, [undefined]>;
85
+ colorByCDS: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<boolean>, [undefined]>;
85
86
  }, {
86
87
  width: number;
87
88
  } & {
@@ -224,6 +225,10 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
224
225
  */
225
226
  readonly trackTypeActions: Map<string, MenuItem[]>;
226
227
  } & {
228
+ /**
229
+ * #action
230
+ */
231
+ setColorByCDS(flag: boolean): void;
227
232
  /**
228
233
  * #action
229
234
  */
@@ -255,7 +260,15 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
255
260
  /**
256
261
  * #action
257
262
  */
258
- setHighlight(highlight: Required<ParsedLocString> | undefined): void;
263
+ addToHighlights(highlight: Required<ParsedLocString>): void;
264
+ /**
265
+ * #action
266
+ */
267
+ setHighlight(highlight: Required<ParsedLocString>[] | undefined): void;
268
+ /**
269
+ * #action
270
+ */
271
+ removeHighlight(highlight: Required<ParsedLocString>): void;
259
272
  /**
260
273
  * #action
261
274
  */
@@ -292,6 +305,22 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
292
305
  */
293
306
  hideTrack(trackId: string): number;
294
307
  } & {
308
+ /**
309
+ * #action
310
+ */
311
+ moveTrackDown(id: string): void;
312
+ /**
313
+ * #action
314
+ */
315
+ moveTrackUp(id: string): void;
316
+ /**
317
+ * #action
318
+ */
319
+ moveTrackToTop(id: string): void;
320
+ /**
321
+ * #action
322
+ */
323
+ moveTrackToBottom(id: string): void;
295
324
  /**
296
325
  * #action
297
326
  */
@@ -528,20 +557,21 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
528
557
  bpToPx({ refName, coord, regionNumber, }: {
529
558
  refName: string;
530
559
  coord: number;
531
- regionNumber?: number | undefined;
560
+ regionNumber?: number;
532
561
  }): {
533
562
  index: number;
534
563
  offsetPx: number;
535
564
  } | undefined;
536
565
  /**
537
566
  * #method
538
- * scrolls the view to center on the given bp. if that is not in any
539
- * of the displayed regions, does nothing
567
+ * scrolls the view to center on the given bp. if that is not in any of
568
+ * the displayed regions, does nothing
569
+ *
540
570
  * @param coord - basepair at which you want to center the view
541
571
  * @param refName - refName of the displayedRegion you are centering at
542
572
  * @param regionNumber - index of the displayedRegion
543
573
  */
544
- centerAt(coord: number, refName: string, regionNumber: number): void;
574
+ centerAt(coord: number, refName: string, regionNumber?: number): void;
545
575
  /**
546
576
  * #method
547
577
  */
@@ -572,7 +602,37 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
572
602
  } | undefined;
573
603
  } & {
574
604
  afterCreate(): void;
575
- }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;
605
+ }, import("mobx-state-tree").ModelCreationType<import("mobx-state-tree/dist/internal").ExtractCFromProps<{
606
+ id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
607
+ displayName: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
608
+ minimized: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
609
+ } & {
610
+ id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
611
+ type: import("mobx-state-tree").IType<string | undefined, string, string>;
612
+ offsetPx: import("mobx-state-tree").IType<number | undefined, number, number>;
613
+ bpPerPx: import("mobx-state-tree").IType<number | undefined, number, number>;
614
+ displayedRegions: import("mobx-state-tree").IArrayType<import("mobx-state-tree").IModelType<{
615
+ refName: import("mobx-state-tree").ISimpleType<string>;
616
+ start: import("mobx-state-tree").ISimpleType<number>;
617
+ end: import("mobx-state-tree").ISimpleType<number>;
618
+ reversed: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<boolean>, [undefined]>;
619
+ } & {
620
+ assemblyName: import("mobx-state-tree").ISimpleType<string>;
621
+ }, {
622
+ setRefName(newRefName: string): void;
623
+ }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
624
+ tracks: import("mobx-state-tree").IArrayType<import("mobx-state-tree").IAnyType>;
625
+ hideHeader: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
626
+ hideHeaderOverview: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
627
+ hideNoTracksActive: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
628
+ trackSelectorType: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
629
+ showCenterLine: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<boolean>, [undefined]>;
630
+ showCytobandsSetting: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<boolean>, [undefined]>;
631
+ trackLabels: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
632
+ showGridlines: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
633
+ highlight: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").IArrayType<import("mobx-state-tree").IType<Required<ParsedLocString>, Required<ParsedLocString>, Required<ParsedLocString>>>, [undefined]>;
634
+ colorByCDS: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<boolean>, [undefined]>;
635
+ }>>, import("mobx-state-tree")._NotCustomized>;
576
636
  export type LinearGenomeViewStateModel = ReturnType<typeof stateModelFactory>;
577
637
  export type LinearGenomeViewModel = Instance<LinearGenomeViewStateModel>;
578
638
  export { default as ReactComponent, default as LinearGenomeView, } from './components/LinearGenomeView';
@@ -50,6 +50,8 @@ const FolderOpen_1 = __importDefault(require("@mui/icons-material/FolderOpen"));
50
50
  const PhotoCamera_1 = __importDefault(require("@mui/icons-material/PhotoCamera"));
51
51
  const ZoomIn_1 = __importDefault(require("@mui/icons-material/ZoomIn"));
52
52
  const MenuOpen_1 = __importDefault(require("@mui/icons-material/MenuOpen"));
53
+ const Palette_1 = __importDefault(require("@mui/icons-material/Palette"));
54
+ const Search_1 = __importDefault(require("@mui/icons-material/Search"));
53
55
  const MiniControls_1 = __importDefault(require("./components/MiniControls"));
54
56
  const Header_1 = __importDefault(require("./components/Header"));
55
57
  const util_2 = require("./util");
@@ -126,7 +128,6 @@ function stateModelFactory(pluginManager) {
126
128
  tracks: mobx_state_tree_1.types.array(pluginManager.pluggableMstType('track', 'stateModel')),
127
129
  /**
128
130
  * #property
129
- * array of currently displayed tracks state model's
130
131
  */
131
132
  hideHeader: false,
132
133
  /**
@@ -169,7 +170,12 @@ function stateModelFactory(pluginManager) {
169
170
  * #property
170
171
  * highlights on the LGV from the URL parameters
171
172
  */
172
- highlight: mobx_state_tree_1.types.maybe(mobx_state_tree_1.types.frozen()),
173
+ highlight: mobx_state_tree_1.types.optional(mobx_state_tree_1.types.array(mobx_state_tree_1.types.frozen()), []),
174
+ /**
175
+ * #property
176
+ * color by CDS
177
+ */
178
+ colorByCDS: mobx_state_tree_1.types.optional(mobx_state_tree_1.types.boolean, () => Boolean(JSON.parse((0, util_1.localStorageGetItem)('lgv-colorByCDS') || 'false'))),
173
179
  }))
174
180
  .volatile(() => ({
175
181
  volatileWidth: undefined,
@@ -360,7 +366,7 @@ function stateModelFactory(pluginManager) {
360
366
  return {
361
367
  ...(0, tracks_1.getParentRenderProps)(self),
362
368
  bpPerPx: self.bpPerPx,
363
- highResolutionScaling: (0, configuration_1.getConf)((0, util_1.getSession)(self), 'highResolutionScaling'),
369
+ colorByCDS: self.colorByCDS,
364
370
  };
365
371
  },
366
372
  /**
@@ -431,6 +437,12 @@ function stateModelFactory(pluginManager) {
431
437
  },
432
438
  }))
433
439
  .actions(self => ({
440
+ /**
441
+ * #action
442
+ */
443
+ setColorByCDS(flag) {
444
+ self.colorByCDS = flag;
445
+ },
434
446
  /**
435
447
  * #action
436
448
  */
@@ -473,11 +485,24 @@ function stateModelFactory(pluginManager) {
473
485
  setShowGridlines(b) {
474
486
  self.showGridlines = b;
475
487
  },
488
+ /**
489
+ * #action
490
+ */
491
+ addToHighlights(highlight) {
492
+ var _a;
493
+ (_a = self.highlight) === null || _a === void 0 ? void 0 : _a.push(highlight);
494
+ },
476
495
  /**
477
496
  * #action
478
497
  */
479
498
  setHighlight(highlight) {
480
- self.highlight = highlight;
499
+ self.highlight = (0, mobx_state_tree_1.cast)(highlight);
500
+ },
501
+ /**
502
+ * #action
503
+ */
504
+ removeHighlight(highlight) {
505
+ self.highlight.remove(highlight);
481
506
  },
482
507
  /**
483
508
  * #action
@@ -598,6 +623,47 @@ function stateModelFactory(pluginManager) {
598
623
  },
599
624
  }))
600
625
  .actions(self => ({
626
+ /**
627
+ * #action
628
+ */
629
+ moveTrackDown(id) {
630
+ const idx = self.tracks.findIndex(v => v.id === id);
631
+ if (idx === -1) {
632
+ return;
633
+ }
634
+ if (idx !== -1 && idx < self.tracks.length - 1) {
635
+ self.tracks.splice(idx, 2, self.tracks[idx + 1], self.tracks[idx]);
636
+ }
637
+ },
638
+ /**
639
+ * #action
640
+ */
641
+ moveTrackUp(id) {
642
+ const idx = self.tracks.findIndex(track => track.id === id);
643
+ if (idx > 0) {
644
+ self.tracks.splice(idx - 1, 2, self.tracks[idx], self.tracks[idx - 1]);
645
+ }
646
+ },
647
+ /**
648
+ * #action
649
+ */
650
+ moveTrackToTop(id) {
651
+ const idx = self.tracks.findIndex(track => track.id === id);
652
+ self.tracks = (0, mobx_state_tree_1.cast)([
653
+ self.tracks[idx],
654
+ ...self.tracks.filter(track => track.id !== id),
655
+ ]);
656
+ },
657
+ /**
658
+ * #action
659
+ */
660
+ moveTrackToBottom(id) {
661
+ const idx = self.tracks.findIndex(track => track.id === id);
662
+ self.tracks = (0, mobx_state_tree_1.cast)([
663
+ ...self.tracks.filter(track => track.id !== id),
664
+ self.tracks[idx],
665
+ ]);
666
+ },
601
667
  /**
602
668
  * #action
603
669
  */
@@ -610,9 +676,9 @@ function stateModelFactory(pluginManager) {
610
676
  if (newIndex === -1) {
611
677
  throw new Error(`Track ID ${targetId} not found`);
612
678
  }
613
- const track = (0, mobx_state_tree_1.getSnapshot)(self.tracks[oldIndex]);
614
- self.tracks.splice(oldIndex, 1);
615
- self.tracks.splice(newIndex, 0, track);
679
+ const tracks = self.tracks.filter((_, idx) => idx !== oldIndex);
680
+ tracks.splice(newIndex, 0, self.tracks[oldIndex]);
681
+ self.tracks = (0, mobx_state_tree_1.cast)(tracks);
616
682
  },
617
683
  /**
618
684
  * #action
@@ -803,7 +869,7 @@ function stateModelFactory(pluginManager) {
803
869
  * perform animated slide
804
870
  */
805
871
  function slide(viewWidths) {
806
- const [animate, cancelAnimation] = (0, util_1.springAnimate)(self.offsetPx, self.offsetPx + self.width * viewWidths, self.scrollTo);
872
+ const [animate, cancelAnimation] = (0, util_1.springAnimate)(self.offsetPx, self.offsetPx + self.width * viewWidths, self.scrollTo, undefined, undefined, 200);
807
873
  cancelLastAnimation();
808
874
  cancelLastAnimation = cancelAnimation;
809
875
  animate();
@@ -890,6 +956,7 @@ function stateModelFactory(pluginManager) {
890
956
  ? [
891
957
  {
892
958
  label: 'Sequence search',
959
+ icon: Search_1.default,
893
960
  onClick: () => {
894
961
  (0, util_1.getSession)(self).queueDialog(handleClose => [
895
962
  SequenceSearchDialog,
@@ -919,6 +986,13 @@ function stateModelFactory(pluginManager) {
919
986
  icon: SyncAlt_1.default,
920
987
  onClick: self.horizontallyFlip,
921
988
  },
989
+ {
990
+ label: 'Color by CDS',
991
+ type: 'checkbox',
992
+ checked: self.colorByCDS,
993
+ icon: Palette_1.default,
994
+ onClick: () => self.setColorByCDS(!self.colorByCDS),
995
+ },
922
996
  {
923
997
  label: 'Show...',
924
998
  icon: Visibility_1.default,
@@ -1083,11 +1157,10 @@ function stateModelFactory(pluginManager) {
1083
1157
  }, { delay: 150 }));
1084
1158
  (0, mobx_state_tree_1.addDisposer)(self, (0, mobx_1.autorun)(() => {
1085
1159
  const s = (s) => JSON.stringify(s);
1086
- const { showCytobandsSetting, showCenterLine } = self;
1087
- if (typeof localStorage !== 'undefined') {
1088
- localStorage.setItem('lgv-showCytobands', s(showCytobandsSetting));
1089
- localStorage.setItem('lgv-showCenterLine', s(showCenterLine));
1090
- }
1160
+ const { showCytobandsSetting, showCenterLine, colorByCDS } = self;
1161
+ (0, util_1.localStorageSetItem)('lgv-showCytobands', s(showCytobandsSetting));
1162
+ (0, util_1.localStorageSetItem)('lgv-showCenterLine', s(showCenterLine));
1163
+ (0, util_1.localStorageSetItem)('lgv-colorByCDS', s(colorByCDS));
1091
1164
  }));
1092
1165
  },
1093
1166
  }))
@@ -1271,8 +1344,9 @@ function stateModelFactory(pluginManager) {
1271
1344
  },
1272
1345
  /**
1273
1346
  * #method
1274
- * scrolls the view to center on the given bp. if that is not in any
1275
- * of the displayed regions, does nothing
1347
+ * scrolls the view to center on the given bp. if that is not in any of
1348
+ * the displayed regions, does nothing
1349
+ *
1276
1350
  * @param coord - basepair at which you want to center the view
1277
1351
  * @param refName - refName of the displayedRegion you are centering at
1278
1352
  * @param regionNumber - index of the displayedRegion
@@ -1330,7 +1404,19 @@ function stateModelFactory(pluginManager) {
1330
1404
  document.removeEventListener('keydown', handler);
1331
1405
  });
1332
1406
  },
1333
- }));
1407
+ }))
1408
+ .preProcessSnapshot(snap => {
1409
+ if (!snap) {
1410
+ return snap;
1411
+ }
1412
+ const { highlight, ...rest } = snap;
1413
+ return {
1414
+ highlight: Array.isArray(highlight) || highlight === undefined
1415
+ ? highlight
1416
+ : [highlight],
1417
+ ...rest,
1418
+ };
1419
+ });
1334
1420
  }
1335
1421
  exports.stateModelFactory = stateModelFactory;
1336
1422
  var LinearGenomeView_1 = require("./components/LinearGenomeView");
@@ -19,7 +19,7 @@ const util_2 = require("./util");
19
19
  // render LGV to SVG
20
20
  async function renderToSvg(model, opts) {
21
21
  await (0, mobx_1.when)(() => model.initialized);
22
- const { textHeight = 18, headerHeight = 40, rulerHeight = 50, fontSize = 13, cytobandHeight = 100, trackLabels = 'offset', themeName = 'default', Wrapper = ({ children }) => react_1.default.createElement(react_1.default.Fragment, null, children), } = opts;
22
+ const { textHeight = 18, headerHeight = 40, rulerHeight = 50, fontSize = 13, cytobandHeight = 100, trackLabels = 'offset', themeName = 'default', Wrapper = ({ children }) => children, } = opts;
23
23
  const session = (0, util_1.getSession)(model);
24
24
  const { allThemes } = session;
25
25
  // eslint-disable-next-line @typescript-eslint/no-explicit-any