@jbrowse/plugin-breakpoint-split-view 3.7.0 → 4.0.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 (102) hide show
  1. package/esm/BreakpointAlignmentsFeatureDetail/BreakpointAlignmentsFeatureDetail.js +1 -1
  2. package/esm/BreakpointAlignmentsFeatureDetail/index.js +2 -2
  3. package/esm/BreakpointGetFeatures/BreakpointGetFeatures.d.ts +51 -0
  4. package/esm/BreakpointGetFeatures/BreakpointGetFeatures.js +57 -0
  5. package/esm/BreakpointGetFeatures/index.d.ts +2 -0
  6. package/esm/BreakpointGetFeatures/index.js +4 -0
  7. package/esm/BreakpointSplitView/BreakpointSplitView.js +33 -47
  8. package/esm/BreakpointSplitView/components/AlignmentConnections.d.ts +2 -7
  9. package/esm/BreakpointSplitView/components/AlignmentConnections.js +20 -25
  10. package/esm/BreakpointSplitView/components/Breakends.d.ts +2 -7
  11. package/esm/BreakpointSplitView/components/Breakends.js +28 -59
  12. package/esm/BreakpointSplitView/components/BreakpointSplitView.d.ts +1 -1
  13. package/esm/BreakpointSplitView/components/BreakpointSplitView.js +19 -6
  14. package/esm/BreakpointSplitView/components/BreakpointSplitViewOverlay.d.ts +1 -1
  15. package/esm/BreakpointSplitView/components/BreakpointSplitViewOverlay.js +3 -3
  16. package/esm/BreakpointSplitView/components/ExportSvgDialog.d.ts +1 -1
  17. package/esm/BreakpointSplitView/components/ExportSvgDialog.js +5 -1
  18. package/esm/BreakpointSplitView/components/Header.d.ts +2 -2
  19. package/esm/BreakpointSplitView/components/Header.js +4 -4
  20. package/esm/BreakpointSplitView/components/HeaderSearchBoxes.js +2 -2
  21. package/esm/BreakpointSplitView/components/Overlay.d.ts +1 -1
  22. package/esm/BreakpointSplitView/components/Overlay.js +8 -11
  23. package/esm/BreakpointSplitView/components/PairedFeatures.d.ts +2 -7
  24. package/esm/BreakpointSplitView/components/PairedFeatures.js +22 -47
  25. package/esm/BreakpointSplitView/components/Rubberband.d.ts +6 -0
  26. package/esm/BreakpointSplitView/components/Rubberband.js +27 -0
  27. package/esm/BreakpointSplitView/components/RubberbandSpan.d.ts +15 -0
  28. package/esm/BreakpointSplitView/components/RubberbandSpan.js +30 -0
  29. package/esm/BreakpointSplitView/components/RubberbandTooltip.d.ts +5 -0
  30. package/esm/BreakpointSplitView/components/RubberbandTooltip.js +17 -0
  31. package/esm/BreakpointSplitView/components/Translocations.d.ts +2 -7
  32. package/esm/BreakpointSplitView/components/Translocations.js +23 -58
  33. package/esm/BreakpointSplitView/components/VerticalGuide.d.ts +6 -0
  34. package/esm/BreakpointSplitView/components/VerticalGuide.js +24 -0
  35. package/esm/BreakpointSplitView/components/overlayUtils.d.ts +24 -0
  36. package/esm/BreakpointSplitView/components/overlayUtils.js +47 -0
  37. package/esm/BreakpointSplitView/components/rubberbandUtil.d.ts +4 -0
  38. package/esm/BreakpointSplitView/components/rubberbandUtil.js +3 -0
  39. package/esm/BreakpointSplitView/components/useRangeSelect.d.ts +59 -0
  40. package/esm/BreakpointSplitView/components/useRangeSelect.js +121 -0
  41. package/esm/BreakpointSplitView/components/util.js +1 -2
  42. package/esm/BreakpointSplitView/getClip.js +4 -4
  43. package/esm/BreakpointSplitView/index.js +2 -2
  44. package/esm/BreakpointSplitView/model.d.ts +402 -117
  45. package/esm/BreakpointSplitView/model.js +105 -41
  46. package/esm/BreakpointSplitView/svgcomponents/SVGBreakpointSplitView.d.ts +2 -2
  47. package/esm/BreakpointSplitView/svgcomponents/SVGBreakpointSplitView.js +8 -8
  48. package/esm/BreakpointSplitView/types.d.ts +8 -0
  49. package/esm/BreakpointSplitView/util.d.ts +1 -1
  50. package/esm/BreakpointSplitView/util.js +8 -17
  51. package/esm/LaunchBreakpointSplitView/index.d.ts +2 -0
  52. package/esm/LaunchBreakpointSplitView/index.js +12 -0
  53. package/esm/index.js +7 -6
  54. package/package.json +28 -34
  55. package/dist/BreakpointAlignmentsFeatureDetail/BreakpointAlignmentsFeatureDetail.d.ts +0 -10
  56. package/dist/BreakpointAlignmentsFeatureDetail/BreakpointAlignmentsFeatureDetail.js +0 -12
  57. package/dist/BreakpointAlignmentsFeatureDetail/index.d.ts +0 -2
  58. package/dist/BreakpointAlignmentsFeatureDetail/index.js +0 -67
  59. package/dist/BreakpointSplitView/BreakpointSplitView.d.ts +0 -34
  60. package/dist/BreakpointSplitView/BreakpointSplitView.js +0 -84
  61. package/dist/BreakpointSplitView/components/AlignmentConnections.d.ts +0 -8
  62. package/dist/BreakpointSplitView/components/AlignmentConnections.js +0 -133
  63. package/dist/BreakpointSplitView/components/Breakends.d.ts +0 -8
  64. package/dist/BreakpointSplitView/components/Breakends.js +0 -95
  65. package/dist/BreakpointSplitView/components/BreakpointSplitView.d.ts +0 -5
  66. package/dist/BreakpointSplitView/components/BreakpointSplitView.js +0 -46
  67. package/dist/BreakpointSplitView/components/BreakpointSplitViewOverlay.d.ts +0 -5
  68. package/dist/BreakpointSplitView/components/BreakpointSplitViewOverlay.js +0 -33
  69. package/dist/BreakpointSplitView/components/ExportSvgDialog.d.ts +0 -7
  70. package/dist/BreakpointSplitView/components/ExportSvgDialog.js +0 -57
  71. package/dist/BreakpointSplitView/components/Header.d.ts +0 -5
  72. package/dist/BreakpointSplitView/components/Header.js +0 -52
  73. package/dist/BreakpointSplitView/components/HeaderSearchBoxes.d.ts +0 -5
  74. package/dist/BreakpointSplitView/components/HeaderSearchBoxes.js +0 -24
  75. package/dist/BreakpointSplitView/components/Overlay.d.ts +0 -8
  76. package/dist/BreakpointSplitView/components/Overlay.js +0 -27
  77. package/dist/BreakpointSplitView/components/PairedFeatures.d.ts +0 -8
  78. package/dist/BreakpointSplitView/components/PairedFeatures.js +0 -75
  79. package/dist/BreakpointSplitView/components/Translocations.d.ts +0 -8
  80. package/dist/BreakpointSplitView/components/Translocations.js +0 -99
  81. package/dist/BreakpointSplitView/components/getOrientationColor.d.ts +0 -41
  82. package/dist/BreakpointSplitView/components/getOrientationColor.js +0 -103
  83. package/dist/BreakpointSplitView/components/util.d.ts +0 -8
  84. package/dist/BreakpointSplitView/components/util.js +0 -142
  85. package/dist/BreakpointSplitView/getClip.d.ts +0 -1
  86. package/dist/BreakpointSplitView/getClip.js +0 -10
  87. package/dist/BreakpointSplitView/index.d.ts +0 -2
  88. package/dist/BreakpointSplitView/index.js +0 -52
  89. package/dist/BreakpointSplitView/model.d.ts +0 -344
  90. package/dist/BreakpointSplitView/model.js +0 -256
  91. package/dist/BreakpointSplitView/svgcomponents/SVGBackground.d.ts +0 -5
  92. package/dist/BreakpointSplitView/svgcomponents/SVGBackground.js +0 -10
  93. package/dist/BreakpointSplitView/svgcomponents/SVGBreakpointSplitView.d.ts +0 -5
  94. package/dist/BreakpointSplitView/svgcomponents/SVGBreakpointSplitView.js +0 -41
  95. package/dist/BreakpointSplitView/svgcomponents/util.d.ts +0 -4
  96. package/dist/BreakpointSplitView/svgcomponents/util.js +0 -18
  97. package/dist/BreakpointSplitView/types.d.ts +0 -22
  98. package/dist/BreakpointSplitView/types.js +0 -2
  99. package/dist/BreakpointSplitView/util.d.ts +0 -28
  100. package/dist/BreakpointSplitView/util.js +0 -67
  101. package/dist/index.d.ts +0 -7
  102. package/dist/index.js +0 -20
@@ -1,14 +1,12 @@
1
1
  import { lazy } from 'react';
2
2
  import { BaseViewModel } from '@jbrowse/core/pluggableElementTypes/models';
3
3
  import { getSession, notEmpty } from '@jbrowse/core/util';
4
+ import { addDisposer, addMiddleware, cast, getPath, types, } from '@jbrowse/mobx-state-tree';
4
5
  import LinkIcon from '@mui/icons-material/Link';
5
6
  import PhotoCamera from '@mui/icons-material/PhotoCamera';
6
- import { saveAs } from 'file-saver';
7
7
  import { autorun } from 'mobx';
8
- import { addDisposer, getPath, onAction, types } from 'mobx-state-tree';
9
- import { getClip } from './getClip';
10
- import { calc, getBlockFeatures, intersect } from './util';
11
- const ExportSvgDialog = lazy(() => import('./components/ExportSvgDialog'));
8
+ import { calc, getBlockFeatures, intersect } from "./util.js";
9
+ const ExportSvgDialog = lazy(() => import("./components/ExportSvgDialog.js"));
12
10
  export default function stateModelFactory(pluginManager) {
13
11
  const defaultHeight = 400;
14
12
  return types
@@ -22,17 +20,29 @@ export default function stateModelFactory(pluginManager) {
22
20
  showHeader: false,
23
21
  views: types.array(pluginManager.getViewType('LinearGenomeView')
24
22
  .stateModel),
23
+ init: types.frozen(),
25
24
  }))
26
25
  .volatile(() => ({
27
26
  width: 800,
28
27
  matchedTrackFeatures: {},
28
+ }))
29
+ .views(self => ({
30
+ get hasSomethingToShow() {
31
+ return self.views.length > 0 || !!self.init;
32
+ },
33
+ get initialized() {
34
+ return self.views.length > 0 && self.views.every(v => v.initialized);
35
+ },
36
+ get showImportForm() {
37
+ return !this.hasSomethingToShow;
38
+ },
29
39
  }))
30
40
  .views(self => ({
31
41
  async exportSvg(opts = {}) {
32
- const { renderToSvg } = await import('./svgcomponents/SVGBreakpointSplitView');
42
+ const { renderToSvg } = await import("./svgcomponents/SVGBreakpointSplitView.js");
33
43
  const html = await renderToSvg(self, opts);
34
- const blob = new Blob([html], { type: 'image/svg+xml' });
35
- saveAs(blob, opts.filename || 'image.svg');
44
+ const { saveAs } = await import('file-saver-es');
45
+ saveAs(new Blob([html], { type: 'image/svg+xml' }), opts.filename || 'image.svg');
36
46
  },
37
47
  }))
38
48
  .views(self => ({
@@ -44,40 +54,44 @@ export default function stateModelFactory(pluginManager) {
44
54
  getMatchedTracks(trackConfigId) {
45
55
  return self.views
46
56
  .map(view => view.getTrack(trackConfigId))
47
- .filter(f => !!f);
57
+ .filter(notEmpty);
48
58
  },
49
59
  hasTranslocations(trackConfigId) {
50
- return [...this.getTrackFeatures(trackConfigId).values()].find(f => f.get('type') === 'translocation');
60
+ return [...this.getTrackFeatures(trackConfigId).values()].some(f => f.get('type') === 'translocation');
51
61
  },
52
62
  hasPairedFeatures(trackConfigId) {
53
- return [...this.getTrackFeatures(trackConfigId).values()].find(f => f.get('type') === 'paired_feature');
63
+ return [...this.getTrackFeatures(trackConfigId).values()].some(f => f.get('type') === 'paired_feature');
54
64
  },
55
65
  getTrackFeatures(trackConfigId) {
56
- var _a;
57
- return new Map((_a = self.matchedTrackFeatures[trackConfigId]) === null || _a === void 0 ? void 0 : _a.flat().map(f => [f.id(), f]));
66
+ return new Map(self.matchedTrackFeatures[trackConfigId]
67
+ ?.flat()
68
+ .map(f => [f.id(), f]));
58
69
  },
59
70
  getMatchedFeaturesInLayout(trackConfigId, features) {
60
71
  const tracks = this.getMatchedTracks(trackConfigId);
61
72
  return features.map(c => c
62
73
  .map(feature => {
63
- const level = tracks.findIndex(track => calc(track, feature));
64
- return level !== -1
65
- ? {
66
- feature,
67
- layout: calc(tracks[level], feature),
68
- level,
69
- clipPos: getClip(feature.get('CIGAR'), feature.get('strand')),
74
+ for (const [level, track] of tracks.entries()) {
75
+ const layout = calc(track, feature);
76
+ if (layout) {
77
+ return {
78
+ feature,
79
+ layout,
80
+ level,
81
+ clipLengthAtStartOfRead: feature.get('clipLengthAtStartOfRead') ?? 0,
82
+ };
70
83
  }
71
- : undefined;
84
+ }
85
+ return undefined;
72
86
  })
73
87
  .filter(notEmpty));
74
88
  },
75
89
  }))
76
90
  .actions(self => ({
77
91
  afterAttach() {
78
- addDisposer(self, onAction(self, ({ name, path, args, }) => {
79
- if (self.linkViews) {
80
- const actions = [
92
+ addDisposer(self, addMiddleware(self, (rawCall, next) => {
93
+ if (rawCall.type === 'action' && rawCall.id === rawCall.rootId) {
94
+ const syncActions = [
81
95
  'horizontalScroll',
82
96
  'zoomTo',
83
97
  'setScaleFactor',
@@ -87,20 +101,21 @@ export default function stateModelFactory(pluginManager) {
87
101
  'setTrackLabels',
88
102
  'toggleCenterLine',
89
103
  ];
90
- if (actions.includes(name) && path) {
91
- this.onSubviewAction(name, path, args);
104
+ if (self.linkViews && syncActions.includes(rawCall.name)) {
105
+ const sourcePath = getPath(rawCall.context);
106
+ next(rawCall);
107
+ for (const view of self.views) {
108
+ const viewPath = getPath(view);
109
+ if (viewPath !== sourcePath) {
110
+ view[rawCall.name](rawCall.args[0]);
111
+ }
112
+ }
113
+ return;
92
114
  }
93
115
  }
116
+ next(rawCall);
94
117
  }));
95
118
  },
96
- onSubviewAction(actionName, path, args) {
97
- for (const view of self.views) {
98
- const ret = getPath(view);
99
- if (!ret.endsWith(path)) {
100
- view[actionName](args === null || args === void 0 ? void 0 : args[0]);
101
- }
102
- }
103
- },
104
119
  setWidth(newWidth) {
105
120
  self.width = newWidth;
106
121
  for (const v of self.views) {
@@ -125,15 +140,33 @@ export default function stateModelFactory(pluginManager) {
125
140
  reverseViewOrder() {
126
141
  self.views.reverse();
127
142
  },
143
+ setInit(init) {
144
+ self.init = init;
145
+ },
146
+ setViews(viewInits) {
147
+ self.views = cast(viewInits.map(viewInit => ({
148
+ type: 'LinearGenomeView',
149
+ hideHeader: true,
150
+ init: viewInit,
151
+ })));
152
+ },
128
153
  }))
129
154
  .actions(self => ({
130
155
  afterAttach() {
156
+ addDisposer(self, autorun(function breakpointSplitViewInitAutorun() {
157
+ const { init, width } = self;
158
+ if (!width || !init) {
159
+ return;
160
+ }
161
+ self.setViews(init.views);
162
+ self.setInit(undefined);
163
+ }, { name: 'BreakpointSplitViewInit' }));
131
164
  addDisposer(self, autorun(async () => {
132
165
  try {
133
166
  if (!self.views.every(view => view.initialized)) {
134
167
  return;
135
168
  }
136
- if (self.matchedTracks.some(track => { var _a, _b; return (_b = (_a = track.displays[0]).notReady) === null || _b === void 0 ? void 0 : _b.call(_a); })) {
169
+ if (self.matchedTracks.some(track => track.displays[0].notReady?.())) {
137
170
  return;
138
171
  }
139
172
  self.setMatchedTrackFeatures(Object.fromEntries(await Promise.all(self.matchedTracks.map(async (track) => [
@@ -145,15 +178,16 @@ export default function stateModelFactory(pluginManager) {
145
178
  console.error(e);
146
179
  getSession(self).notifyError(`${e}`, e);
147
180
  }
181
+ }, {
182
+ name: 'BreakpointFeatureFetcher',
183
+ delay: 1000,
148
184
  }));
149
185
  },
150
186
  menuItems() {
151
187
  return [
152
- ...self.views
153
- .map((view, idx) => [idx, view.menuItems()])
154
- .map(f => ({
155
- label: `Row ${f[0] + 1} view menu`,
156
- subMenu: f[1],
188
+ ...self.views.map((view, idx) => ({
189
+ label: `Row ${idx + 1} view menu`,
190
+ subMenu: view.menuItems(),
157
191
  })),
158
192
  ...(self.views.length > 1
159
193
  ? [
@@ -213,5 +247,35 @@ export default function stateModelFactory(pluginManager) {
213
247
  },
214
248
  ];
215
249
  },
216
- }));
250
+ rubberBandMenuItems() {
251
+ return [
252
+ {
253
+ label: 'Zoom to region(s)',
254
+ onClick: () => {
255
+ for (const view of self.views) {
256
+ const { leftOffset, rightOffset } = view;
257
+ if (leftOffset && rightOffset) {
258
+ view.moveTo(leftOffset, rightOffset);
259
+ }
260
+ }
261
+ },
262
+ },
263
+ ];
264
+ },
265
+ }))
266
+ .postProcessSnapshot(snap => {
267
+ if (!snap) {
268
+ return snap;
269
+ }
270
+ const { init, height, trackSelectorType, showIntraviewLinks, linkViews, interactiveOverlay, showHeader, ...rest } = snap;
271
+ return {
272
+ ...rest,
273
+ ...(height !== 400 ? { height } : {}),
274
+ ...(trackSelectorType !== 'hierarchical' ? { trackSelectorType } : {}),
275
+ ...(!showIntraviewLinks ? { showIntraviewLinks } : {}),
276
+ ...(linkViews ? { linkViews } : {}),
277
+ ...(!interactiveOverlay ? { interactiveOverlay } : {}),
278
+ ...(showHeader ? { showHeader } : {}),
279
+ };
280
+ });
217
281
  }
@@ -1,5 +1,5 @@
1
- import type { BreakpointViewModel } from '../model';
2
- import type { ExportSvgOptions } from '../types';
1
+ import type { BreakpointViewModel } from '../model.ts';
2
+ import type { ExportSvgOptions } from '../types.ts';
3
3
  type BSV = BreakpointViewModel;
4
4
  export declare function renderToSvg(model: BSV, opts: ExportSvgOptions): Promise<string>;
5
5
  export {};
@@ -1,17 +1,16 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { createJBrowseTheme } from '@jbrowse/core/ui';
3
3
  import { getSession, renderToStaticMarkup, sum } from '@jbrowse/core/util';
4
- import { SVGRuler, SVGTracks, totalHeight, } from '@jbrowse/plugin-linear-genome-view';
4
+ import { SVGGridlines, SVGRuler, SVGTracks, totalHeight, } from '@jbrowse/plugin-linear-genome-view';
5
5
  import { ThemeProvider } from '@mui/material';
6
6
  import { when } from 'mobx';
7
- import SVGBackground from './SVGBackground';
8
- import { getTrackNameMaxLen, getTrackOffsets } from './util';
9
- import Overlay from '../components/Overlay';
7
+ import SVGBackground from "./SVGBackground.js";
8
+ import { getTrackNameMaxLen, getTrackOffsets } from "./util.js";
9
+ import Overlay from "../components/Overlay.js";
10
10
  export async function renderToSvg(model, opts) {
11
- var _a;
12
- const { textHeight = 18, headerHeight = 30, rulerHeight = 30, fontSize = 13, trackLabels = 'offset', Wrapper = ({ children }) => children, themeName = 'default', } = opts;
11
+ const { textHeight = 18, headerHeight = 30, rulerHeight = 30, fontSize = 13, trackLabels = 'offset', showGridlines = false, Wrapper = ({ children }) => children, themeName = 'default', } = opts;
13
12
  const session = getSession(model);
14
- const theme = (_a = session.allThemes) === null || _a === void 0 ? void 0 : _a.call(session)[themeName];
13
+ const theme = session.allThemes?.()[themeName];
15
14
  const { width, views } = model;
16
15
  const shift = 50;
17
16
  const offset = headerHeight + rulerHeight;
@@ -31,5 +30,6 @@ export async function renderToSvg(model, opts) {
31
30
  const trackOffsets = views.map((view, idx) => getTrackOffsets(view, textOffset, fontSize + (idx > 0 ? heights[idx - 1] : 0) + offset));
32
31
  const w = width + trackLabelOffset;
33
32
  const t = createJBrowseTheme(theme);
34
- return renderToStaticMarkup(_jsx(ThemeProvider, { theme: t, children: _jsx(Wrapper, { children: _jsxs("svg", { width: width, height: totalHeightSvg, xmlns: "http://www.w3.org/2000/svg", xmlnsXlink: "http://www.w3.org/1999/xlink", viewBox: [0, 0, w + shift * 2, totalHeightSvg].toString(), children: [_jsx(SVGBackground, { width: w, height: totalHeightSvg, shift: shift }), views[0] ? (_jsxs("g", { transform: `translate(${shift} ${fontSize})`, children: [_jsxs("g", { transform: `translate(${trackLabelOffset})`, children: [_jsx("text", { x: 0, fontSize: fontSize, fill: t.palette.text.primary, children: views[0].assemblyNames.join(', ') }), _jsx(SVGRuler, { model: displayResults[0].view, fontSize: fontSize })] }), _jsx("g", { transform: `translate(0 ${offset})`, children: _jsx(SVGTracks, { textHeight: textHeight, trackLabels: trackLabels, fontSize: fontSize, model: displayResults[0].view, displayResults: displayResults[0].data, trackLabelOffset: trackLabelOffset }) })] })) : null, views[1] ? (_jsxs("g", { transform: `translate(${shift} ${fontSize + heights[0]})`, children: [_jsxs("g", { transform: `translate(${trackLabelOffset})`, children: [_jsx("text", { x: 0, fontSize: fontSize, fill: t.palette.text.primary, children: views[1].assemblyNames.join(', ') }), _jsx(SVGRuler, { model: displayResults[1].view, fontSize: fontSize })] }), _jsx("g", { transform: `translate(0 ${offset})`, children: _jsx(SVGTracks, { textHeight: textHeight, trackLabels: trackLabels, fontSize: fontSize, model: displayResults[1].view, displayResults: displayResults[1].data, trackLabelOffset: trackLabelOffset }) })] })) : null, _jsx("defs", { children: _jsx("clipPath", { id: "clip-bsv", children: _jsx("rect", { x: 0, y: 0, width: width, height: totalHeightSvg }) }) }), _jsx("g", { transform: `translate(${trackLabelOffset + shift})`, clipPath: "url(#clip-bsv)", children: model.matchedTracks.map(track => (_jsx(Overlay, { parentRef: { current: null }, model: model, trackId: track.configuration.trackId, getTrackYPosOverride: (id, level) => trackOffsets[level][id] }, track.configuration.trackId))) })] }) }) }));
33
+ const tracksHeights = views.map(v => totalHeight(v.tracks, textHeight, trackLabels));
34
+ return renderToStaticMarkup(_jsx(ThemeProvider, { theme: t, children: _jsx(Wrapper, { children: _jsxs("svg", { width: width, height: totalHeightSvg, xmlns: "http://www.w3.org/2000/svg", xmlnsXlink: "http://www.w3.org/1999/xlink", viewBox: [0, 0, w + shift * 2, totalHeightSvg].toString(), children: [_jsx(SVGBackground, { width: w, height: totalHeightSvg, shift: shift }), views[0] ? (_jsxs("g", { transform: `translate(${shift} ${fontSize})`, children: [_jsxs("g", { transform: `translate(${trackLabelOffset})`, children: [_jsx("text", { x: 0, fontSize: fontSize, fill: t.palette.text.primary, children: views[0].assemblyNames.join(', ') }), _jsx(SVGRuler, { model: displayResults[0].view, fontSize: fontSize })] }), showGridlines ? (_jsx("g", { transform: `translate(${trackLabelOffset} ${offset})`, children: _jsx(SVGGridlines, { model: displayResults[0].view, height: tracksHeights[0] }) })) : null, _jsx("g", { transform: `translate(0 ${offset})`, children: _jsx(SVGTracks, { textHeight: textHeight, trackLabels: trackLabels, fontSize: fontSize, model: displayResults[0].view, displayResults: displayResults[0].data, trackLabelOffset: trackLabelOffset }) })] })) : null, views[1] ? (_jsxs("g", { transform: `translate(${shift} ${fontSize + heights[0]})`, children: [_jsxs("g", { transform: `translate(${trackLabelOffset})`, children: [_jsx("text", { x: 0, fontSize: fontSize, fill: t.palette.text.primary, children: views[1].assemblyNames.join(', ') }), _jsx(SVGRuler, { model: displayResults[1].view, fontSize: fontSize })] }), showGridlines ? (_jsx("g", { transform: `translate(${trackLabelOffset} ${offset})`, children: _jsx(SVGGridlines, { model: displayResults[1].view, height: tracksHeights[1] }) })) : null, _jsx("g", { transform: `translate(0 ${offset})`, children: _jsx(SVGTracks, { textHeight: textHeight, trackLabels: trackLabels, fontSize: fontSize, model: displayResults[1].view, displayResults: displayResults[1].data, trackLabelOffset: trackLabelOffset }) })] })) : null, _jsx("defs", { children: _jsx("clipPath", { id: "clip-bsv", children: _jsx("rect", { x: 0, y: 0, width: width, height: totalHeightSvg }) }) }), _jsx("g", { transform: `translate(${trackLabelOffset + shift})`, clipPath: "url(#clip-bsv)", children: model.matchedTracks.map(track => (_jsx(Overlay, { parentRef: { current: null }, model: model, trackId: track.configuration.trackId, getTrackYPosOverride: (id, level) => trackOffsets[level][id] }, track.configuration.trackId))) })] }) }) }));
35
35
  }
@@ -12,6 +12,14 @@ export interface ExportSvgOptions {
12
12
  cytobandHeight?: number;
13
13
  trackLabels?: string;
14
14
  themeName?: string;
15
+ showGridlines?: boolean;
16
+ }
17
+ export interface BreakpointSplitViewInit {
18
+ views: {
19
+ loc?: string;
20
+ assembly: string;
21
+ tracks?: string[];
22
+ }[];
15
23
  }
16
24
  export interface Breakend {
17
25
  MateDirection: string;
@@ -1,4 +1,4 @@
1
- import type { LayoutRecord } from './types';
1
+ import type { LayoutRecord } from './types.ts';
2
2
  import type { AnyConfigurationModel } from '@jbrowse/core/configuration';
3
3
  import type { Feature } from '@jbrowse/core/util';
4
4
  import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view';
@@ -7,28 +7,20 @@ function cheight(chunk) {
7
7
  return chunk[BOTTOM] - chunk[TOP];
8
8
  }
9
9
  export function heightFromSpecificLevel(views, trackId, level, getYPosOverride) {
10
- var _a;
11
10
  return getYPosOverride
12
11
  ? getYPosOverride(trackId, level)
13
- : ((_a = views[level].trackRefs[trackId]) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect().top) || 0;
12
+ : views[level].trackRefs[trackId]?.getBoundingClientRect().top || 0;
14
13
  }
15
14
  export function getPxFromCoordinate(view, refName, coord) {
16
- var _a;
17
- return (((_a = view.bpToPx({ refName, coord })) === null || _a === void 0 ? void 0 : _a.offsetPx) || 0) - view.offsetPx;
15
+ return (view.bpToPx({ refName, coord })?.offsetPx || 0) - view.offsetPx;
18
16
  }
19
17
  export function yPos(trackId, level, views, tracks, c, getYPosOverride) {
20
18
  const display = tracks[level].displays[0];
21
- const min = 0;
22
19
  const max = display.height;
23
- let offset = 0;
24
- const { SNPCoverageDisplay } = display;
25
- if (SNPCoverageDisplay) {
26
- offset = SNPCoverageDisplay.height;
27
- }
28
- const yPos = getYPosOverride ? 0 : display.scrollTop;
29
- return (clamp(c[TOP] - yPos + cheight(c) / 2 + offset, min, max) +
30
- heightFromSpecificLevel(views, trackId, level, getYPosOverride) +
31
- display.scrollTop);
20
+ const offset = display.SNPCoverageDisplay?.height ?? 0;
21
+ const scrollTop = getYPosOverride ? 0 : display.scrollTop;
22
+ return (clamp(c[TOP] - scrollTop + cheight(c) / 2 + offset, offset, max) +
23
+ heightFromSpecificLevel(views, trackId, level, getYPosOverride));
32
24
  }
33
25
  export const useNextFrame = (variable) => {
34
26
  const [, setNextFrameState] = useState();
@@ -42,14 +34,13 @@ export function intersect(cb, a1 = [], a2 = [], ...rest) {
42
34
  return rest.length === 0 ? a12 : intersect(cb, a12, ...rest);
43
35
  }
44
36
  export function calc(track, f) {
45
- var _a, _b;
46
- return (_b = (_a = track.displays[0]).searchFeatureByID) === null || _b === void 0 ? void 0 : _b.call(_a, f.id());
37
+ return track.displays[0].searchFeatureByID?.(f.id());
47
38
  }
48
39
  export async function getBlockFeatures(model, track) {
49
40
  const { views } = model;
50
41
  const { rpcManager } = getSession(model);
51
42
  const sessionId = getRpcSessionId(track);
52
- return Promise.all(views.flatMap(async (view) => (await rpcManager.call(sessionId, 'CoreGetFeatures', {
43
+ return Promise.all(views.flatMap(async (view) => (await rpcManager.call(sessionId, 'BreakpointGetFeatures', {
53
44
  adapterConfig: getConf(track, ['adapter']),
54
45
  sessionId,
55
46
  regions: view.staticBlocks.contentBlocks,
@@ -0,0 +1,2 @@
1
+ import type PluginManager from '@jbrowse/core/PluginManager';
2
+ export default function LaunchBreakpointSplitViewF(pluginManager: PluginManager): void;
@@ -0,0 +1,12 @@
1
+ export default function LaunchBreakpointSplitViewF(pluginManager) {
2
+ pluginManager.addToExtensionPoint('LaunchView-BreakpointSplitView', async ({ session, views, }) => {
3
+ if (views.length < 2) {
4
+ throw new Error('BreakpointSplitView requires at least 2 views to be specified');
5
+ }
6
+ session.addView('BreakpointSplitView', {
7
+ init: {
8
+ views,
9
+ },
10
+ });
11
+ });
12
+ }
package/esm/index.js CHANGED
@@ -1,14 +1,15 @@
1
1
  import Plugin from '@jbrowse/core/Plugin';
2
- import BreakpointAlignmentsWidgetF from './BreakpointAlignmentsFeatureDetail';
3
- import BreakpointSplitViewF from './BreakpointSplitView';
2
+ import BreakpointAlignmentsWidgetF from "./BreakpointAlignmentsFeatureDetail/index.js";
3
+ import BreakpointGetFeaturesF from "./BreakpointGetFeatures/index.js";
4
+ import BreakpointSplitViewF from "./BreakpointSplitView/index.js";
5
+ import LaunchBreakpointSplitViewF from "./LaunchBreakpointSplitView/index.js";
4
6
  export default class BreakpointSplitViewPlugin extends Plugin {
5
- constructor() {
6
- super(...arguments);
7
- this.name = 'BreakpointSplitViewPlugin';
8
- }
7
+ name = 'BreakpointSplitViewPlugin';
9
8
  install(pluginManager) {
10
9
  BreakpointSplitViewF(pluginManager);
11
10
  BreakpointAlignmentsWidgetF(pluginManager);
11
+ LaunchBreakpointSplitViewF(pluginManager);
12
+ BreakpointGetFeaturesF(pluginManager);
12
13
  }
13
14
  configure() { }
14
15
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/plugin-breakpoint-split-view",
3
- "version": "3.7.0",
3
+ "version": "4.0.0",
4
4
  "description": "JBrowse 2 breakpoint detail split view",
5
5
  "keywords": [
6
6
  "jbrowse",
@@ -15,48 +15,42 @@
15
15
  "directory": "plugins/breakpoint-split-view"
16
16
  },
17
17
  "author": "JBrowse Team",
18
- "distMain": "dist/index.js",
19
- "srcMain": "src/index.ts",
20
- "main": "dist/index.js",
18
+ "main": "esm/index.js",
21
19
  "files": [
22
- "dist",
23
20
  "esm"
24
21
  ],
25
- "scripts": {
26
- "build": "npm-run-all build:*",
27
- "test": "cd ../..; jest --passWithNoTests plugins/breakpoint-split-view",
28
- "prepublishOnly": "yarn test",
29
- "prepack": "yarn build && yarn useDist",
30
- "postpack": "yarn useSrc",
31
- "useDist": "node ../../scripts/useDist.js",
32
- "useSrc": "node ../../scripts/useSrc.js",
33
- "prebuild": "npm run clean",
34
- "build:esm": "tsc --build tsconfig.build.esm.json",
35
- "build:commonjs": "tsc --build tsconfig.build.commonjs.json",
36
- "clean": "rimraf dist esm *.tsbuildinfo"
37
- },
38
22
  "dependencies": {
39
- "@gmod/vcf": "^6.0.8",
40
- "@jbrowse/core": "^3.7.0",
41
- "@jbrowse/plugin-linear-genome-view": "^3.7.0",
42
- "@mui/icons-material": "^7.0.0",
43
- "@mui/material": "^7.0.0",
44
- "@types/file-saver": "^2.0.1",
45
- "file-saver": "^2.0.0",
46
- "mobx": "^6.0.0",
47
- "mobx-react": "^9.0.0",
48
- "mobx-state-tree": "^5.0.0",
49
- "tss-react": "^4.0.0"
23
+ "@gmod/vcf": "^6.1.0",
24
+ "@jbrowse/mobx-state-tree": "^5.5.0",
25
+ "@mui/icons-material": "^7.3.6",
26
+ "@mui/material": "^7.3.6",
27
+ "@types/file-saver-es": "^2.0.3",
28
+ "file-saver-es": "^2.0.5",
29
+ "mobx": "^6.15.0",
30
+ "mobx-react": "^9.2.1",
31
+ "@jbrowse/core": "^4.0.0",
32
+ "@jbrowse/plugin-linear-genome-view": "^4.0.0"
50
33
  },
51
34
  "peerDependencies": {
52
35
  "react": ">=16.8.4",
53
36
  "react-dom": ">=16.8.4"
54
37
  },
55
- "distModule": "esm/index.js",
56
- "srcModule": "src/index.ts",
57
- "module": "esm/index.js",
58
38
  "publishConfig": {
59
39
  "access": "public"
60
40
  },
61
- "gitHead": "85bdd0d58286b7adbfd408146b15847676317635"
62
- }
41
+ "sideEffects": false,
42
+ "scripts": {
43
+ "build": "pnpm run /^build:/",
44
+ "test": "cd ../..; jest --passWithNoTests plugins/breakpoint-split-view",
45
+ "prebuild": "pnpm clean",
46
+ "build:esm": "tsc -p tsconfig.build.esm.json",
47
+ "clean": "rimraf esm *.tsbuildinfo"
48
+ },
49
+ "types": "esm/index.d.ts",
50
+ "exports": {
51
+ ".": {
52
+ "types": "./esm/index.d.ts",
53
+ "import": "./esm/index.js"
54
+ }
55
+ }
56
+ }
@@ -1,10 +0,0 @@
1
- import type { SimpleFeatureSerialized } from '@jbrowse/core/util';
2
- declare const BreakpointAlignmentsFeatureDetail: ({ model, }: {
3
- model: {
4
- featureData: {
5
- feature1: SimpleFeatureSerialized;
6
- feature2: SimpleFeatureSerialized;
7
- };
8
- };
9
- }) => import("react/jsx-runtime").JSX.Element;
10
- export default BreakpointAlignmentsFeatureDetail;
@@ -1,12 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const jsx_runtime_1 = require("react/jsx-runtime");
4
- const BaseFeatureDetail_1 = require("@jbrowse/core/BaseFeatureWidget/BaseFeatureDetail");
5
- const material_1 = require("@mui/material");
6
- const mobx_react_1 = require("mobx-react");
7
- const BreakpointAlignmentsFeatureDetail = (0, mobx_react_1.observer)(function ({ model, }) {
8
- const { featureData } = model;
9
- const { feature1, feature2 } = structuredClone(featureData);
10
- return ((0, jsx_runtime_1.jsxs)(material_1.Paper, { children: [(0, jsx_runtime_1.jsx)(BaseFeatureDetail_1.BaseCoreDetails, { title: "Feature 1", feature: feature1 }), (0, jsx_runtime_1.jsx)(BaseFeatureDetail_1.BaseCoreDetails, { title: "Feature 2", feature: feature2 }), (0, jsx_runtime_1.jsx)(BaseFeatureDetail_1.BaseAttributes, { title: "Feature 1 attributes", feature: feature1 }), (0, jsx_runtime_1.jsx)(BaseFeatureDetail_1.BaseAttributes, { title: "Feature 2 attributes", feature: feature2 })] }));
11
- });
12
- exports.default = BreakpointAlignmentsFeatureDetail;
@@ -1,2 +0,0 @@
1
- import type PluginManager from '@jbrowse/core/PluginManager';
2
- export default function BreakpointAlignmentsFeatureDetailF(pluginManager: PluginManager): void;
@@ -1,67 +0,0 @@
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 () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.default = BreakpointAlignmentsFeatureDetailF;
37
- const react_1 = require("react");
38
- const configuration_1 = require("@jbrowse/core/configuration");
39
- const pluggableElementTypes_1 = require("@jbrowse/core/pluggableElementTypes");
40
- const mst_1 = require("@jbrowse/core/util/types/mst");
41
- const mobx_state_tree_1 = require("mobx-state-tree");
42
- const configSchema = (0, configuration_1.ConfigurationSchema)('BreakpointAlignmentsWidget', {});
43
- const stateModel = mobx_state_tree_1.types
44
- .model('BreakpointAlignmentsWidget', {
45
- id: mst_1.ElementId,
46
- type: mobx_state_tree_1.types.literal('BreakpointAlignmentsWidget'),
47
- featureData: mobx_state_tree_1.types.frozen(),
48
- })
49
- .actions(self => ({
50
- setFeatureData(data) {
51
- self.featureData = data;
52
- },
53
- clearFeatureData() {
54
- self.featureData = undefined;
55
- },
56
- }));
57
- function BreakpointAlignmentsFeatureDetailF(pluginManager) {
58
- pluginManager.addWidgetType(() => {
59
- return new pluggableElementTypes_1.WidgetType({
60
- name: 'BreakpointAlignmentsWidget',
61
- heading: 'Breakpoint feature details',
62
- configSchema,
63
- stateModel,
64
- ReactComponent: (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./BreakpointAlignmentsFeatureDetail')))),
65
- });
66
- });
67
- }
@@ -1,34 +0,0 @@
1
- import ViewType from '@jbrowse/core/pluggableElementTypes/ViewType';
2
- import { type AbstractSessionModel, type Feature } from '@jbrowse/core/util';
3
- import type { Assembly } from '@jbrowse/core/assemblyManager/assembly';
4
- export default class BreakpointSplitViewType extends ViewType {
5
- getBreakendCoveringRegions({ feature, assembly, }: {
6
- feature: Feature;
7
- assembly: Assembly;
8
- }): {
9
- pos: number;
10
- refName: string;
11
- mateRefName: string;
12
- matePos: any;
13
- };
14
- singleLevelSnapshotFromBreakendFeature({ feature, session, assemblyName, }: {
15
- feature: Feature;
16
- session: AbstractSessionModel;
17
- assemblyName: string;
18
- }): {
19
- coverage: {
20
- pos: number;
21
- refName: string;
22
- mateRefName: string;
23
- matePos: any;
24
- };
25
- snap: {
26
- type: string;
27
- views: {
28
- type: string;
29
- displayedRegions: import("@jbrowse/core/assemblyManager/assembly").BasicRegion[];
30
- }[];
31
- displayName: string;
32
- };
33
- };
34
- }