@jbrowse/plugin-breakpoint-split-view 2.6.1 → 2.6.2

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 (84) hide show
  1. package/dist/BreakpointAlignmentsFeatureDetail/BreakpointAlignmentsFeatureDetail.js +0 -1
  2. package/dist/BreakpointAlignmentsFeatureDetail/index.js +0 -1
  3. package/dist/BreakpointSplitView/BreakpointSplitView.js +0 -1
  4. package/dist/BreakpointSplitView/components/AlignmentConnections.js +0 -1
  5. package/dist/BreakpointSplitView/components/Breakends.js +0 -1
  6. package/dist/BreakpointSplitView/components/BreakpointSplitView.js +0 -1
  7. package/dist/BreakpointSplitView/components/ExportSvgDialog.js +0 -1
  8. package/dist/BreakpointSplitView/components/Overlay.js +0 -1
  9. package/dist/BreakpointSplitView/components/Translocations.js +0 -1
  10. package/dist/BreakpointSplitView/components/util.js +0 -1
  11. package/dist/BreakpointSplitView/index.js +0 -1
  12. package/dist/BreakpointSplitView/model.d.ts +1 -1
  13. package/dist/BreakpointSplitView/model.js +3 -3
  14. package/dist/BreakpointSplitView/svgcomponents/SVGBackground.js +0 -1
  15. package/dist/BreakpointSplitView/svgcomponents/SVGBreakpointSplitView.js +0 -1
  16. package/dist/BreakpointSplitView/util.js +0 -1
  17. package/dist/index.js +0 -1
  18. package/esm/BreakpointAlignmentsFeatureDetail/BreakpointAlignmentsFeatureDetail.js +0 -1
  19. package/esm/BreakpointAlignmentsFeatureDetail/index.js +0 -1
  20. package/esm/BreakpointSplitView/BreakpointSplitView.js +0 -1
  21. package/esm/BreakpointSplitView/components/AlignmentConnections.js +0 -1
  22. package/esm/BreakpointSplitView/components/Breakends.js +0 -1
  23. package/esm/BreakpointSplitView/components/BreakpointSplitView.js +0 -1
  24. package/esm/BreakpointSplitView/components/ExportSvgDialog.js +0 -1
  25. package/esm/BreakpointSplitView/components/Overlay.js +0 -1
  26. package/esm/BreakpointSplitView/components/Translocations.js +0 -1
  27. package/esm/BreakpointSplitView/components/util.js +0 -1
  28. package/esm/BreakpointSplitView/index.js +0 -1
  29. package/esm/BreakpointSplitView/model.d.ts +1 -1
  30. package/esm/BreakpointSplitView/model.js +3 -3
  31. package/esm/BreakpointSplitView/svgcomponents/SVGBackground.js +0 -1
  32. package/esm/BreakpointSplitView/svgcomponents/SVGBreakpointSplitView.js +0 -1
  33. package/esm/BreakpointSplitView/util.js +0 -1
  34. package/esm/index.js +0 -1
  35. package/package.json +3 -4
  36. package/dist/BreakpointAlignmentsFeatureDetail/BreakpointAlignmentsFeatureDetail.js.map +0 -1
  37. package/dist/BreakpointAlignmentsFeatureDetail/index.js.map +0 -1
  38. package/dist/BreakpointSplitView/BreakpointSplitView.js.map +0 -1
  39. package/dist/BreakpointSplitView/components/AlignmentConnections.js.map +0 -1
  40. package/dist/BreakpointSplitView/components/Breakends.js.map +0 -1
  41. package/dist/BreakpointSplitView/components/BreakpointSplitView.js.map +0 -1
  42. package/dist/BreakpointSplitView/components/ExportSvgDialog.js.map +0 -1
  43. package/dist/BreakpointSplitView/components/Overlay.js.map +0 -1
  44. package/dist/BreakpointSplitView/components/Translocations.js.map +0 -1
  45. package/dist/BreakpointSplitView/components/util.js.map +0 -1
  46. package/dist/BreakpointSplitView/index.js.map +0 -1
  47. package/dist/BreakpointSplitView/model.js.map +0 -1
  48. package/dist/BreakpointSplitView/svgcomponents/SVGBackground.js.map +0 -1
  49. package/dist/BreakpointSplitView/svgcomponents/SVGBreakpointSplitView.js.map +0 -1
  50. package/dist/BreakpointSplitView/util.js.map +0 -1
  51. package/dist/index.js.map +0 -1
  52. package/esm/BreakpointAlignmentsFeatureDetail/BreakpointAlignmentsFeatureDetail.js.map +0 -1
  53. package/esm/BreakpointAlignmentsFeatureDetail/index.js.map +0 -1
  54. package/esm/BreakpointSplitView/BreakpointSplitView.js.map +0 -1
  55. package/esm/BreakpointSplitView/components/AlignmentConnections.js.map +0 -1
  56. package/esm/BreakpointSplitView/components/Breakends.js.map +0 -1
  57. package/esm/BreakpointSplitView/components/BreakpointSplitView.js.map +0 -1
  58. package/esm/BreakpointSplitView/components/ExportSvgDialog.js.map +0 -1
  59. package/esm/BreakpointSplitView/components/Overlay.js.map +0 -1
  60. package/esm/BreakpointSplitView/components/Translocations.js.map +0 -1
  61. package/esm/BreakpointSplitView/components/util.js.map +0 -1
  62. package/esm/BreakpointSplitView/index.js.map +0 -1
  63. package/esm/BreakpointSplitView/model.js.map +0 -1
  64. package/esm/BreakpointSplitView/svgcomponents/SVGBackground.js.map +0 -1
  65. package/esm/BreakpointSplitView/svgcomponents/SVGBreakpointSplitView.js.map +0 -1
  66. package/esm/BreakpointSplitView/util.js.map +0 -1
  67. package/esm/index.js.map +0 -1
  68. package/src/BreakpointAlignmentsFeatureDetail/BreakpointAlignmentsFeatureDetail.tsx +0 -24
  69. package/src/BreakpointAlignmentsFeatureDetail/index.ts +0 -35
  70. package/src/BreakpointSplitView/BreakpointSplitView.ts +0 -100
  71. package/src/BreakpointSplitView/components/AlignmentConnections.tsx +0 -166
  72. package/src/BreakpointSplitView/components/Breakends.tsx +0 -141
  73. package/src/BreakpointSplitView/components/BreakpointSplitView.tsx +0 -95
  74. package/src/BreakpointSplitView/components/ExportSvgDialog.tsx +0 -149
  75. package/src/BreakpointSplitView/components/Overlay.tsx +0 -29
  76. package/src/BreakpointSplitView/components/Translocations.tsx +0 -147
  77. package/src/BreakpointSplitView/components/util.ts +0 -127
  78. package/src/BreakpointSplitView/index.ts +0 -17
  79. package/src/BreakpointSplitView/model.ts +0 -333
  80. package/src/BreakpointSplitView/svgcomponents/SVGBackground.tsx +0 -21
  81. package/src/BreakpointSplitView/svgcomponents/SVGBreakpointSplitView.tsx +0 -179
  82. package/src/BreakpointSplitView/util.ts +0 -89
  83. package/src/index.test.ts +0 -3
  84. package/src/index.ts +0 -15
@@ -1,333 +0,0 @@
1
- import React, { lazy } from 'react'
2
- import {
3
- types,
4
- getParent,
5
- onAction,
6
- addDisposer,
7
- getPath,
8
- Instance,
9
- } from 'mobx-state-tree'
10
- import { autorun } from 'mobx'
11
- import { saveAs } from 'file-saver'
12
-
13
- // jbrowse
14
- import {
15
- LinearGenomeViewModel,
16
- LinearGenomeViewStateModel,
17
- } from '@jbrowse/plugin-linear-genome-view'
18
- import PluginManager from '@jbrowse/core/PluginManager'
19
- import { BaseViewModel } from '@jbrowse/core/pluggableElementTypes/models'
20
- import { getSession, Feature, notEmpty } from '@jbrowse/core/util'
21
- import { AnyConfigurationModel, getConf } from '@jbrowse/core/configuration'
22
-
23
- // icons
24
- import PhotoCamera from '@mui/icons-material/PhotoCamera'
25
- import LinkIcon from '@mui/icons-material/Link'
26
-
27
- // locals
28
- import { intersect } from './util'
29
-
30
- // lazies
31
- const ExportSvgDialog = lazy(() => import('./components/ExportSvgDialog'))
32
-
33
- function calc(
34
- track: { displays: { searchFeatureByID: (str: string) => LayoutRecord }[] },
35
- feat: Feature,
36
- ) {
37
- return track.displays[0].searchFeatureByID(feat.id())
38
- }
39
-
40
- export interface ExportSvgOptions {
41
- rasterizeLayers?: boolean
42
- filename?: string
43
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
44
- Wrapper?: React.FC<any>
45
- fontSize?: number
46
- rulerHeight?: number
47
- textHeight?: number
48
- paddingHeight?: number
49
- headerHeight?: number
50
- cytobandHeight?: number
51
- trackLabels?: string
52
- themeName?: string
53
- }
54
-
55
- type LGV = LinearGenomeViewModel
56
-
57
- export interface Breakend {
58
- MateDirection: string
59
- Join: string
60
- Replacement: string
61
- MatePosition: string
62
- }
63
-
64
- export type LayoutRecord = [number, number, number, number]
65
-
66
- async function getBlockFeatures(
67
- model: BreakpointViewModel,
68
- track: { configuration: AnyConfigurationModel },
69
- ) {
70
- const { views } = model
71
- const { rpcManager, assemblyManager } = getSession(model)
72
- const assemblyName = model.views[0].assemblyNames[0]
73
- const assembly = await assemblyManager.waitForAssembly(assemblyName)
74
- if (!assembly) {
75
- return undefined // throw new Error(`assembly not found: "${assemblyName}"`)
76
- }
77
- const sessionId = track.configuration.trackId
78
- return Promise.all(
79
- views.map(async view =>
80
- (
81
- (await rpcManager.call(sessionId, 'CoreGetFeatures', {
82
- adapterConfig: getConf(track, ['adapter']),
83
- sessionId,
84
- regions: view.staticBlocks.contentBlocks,
85
- })) as Feature[][]
86
- ).flat(),
87
- ),
88
- )
89
- }
90
-
91
- export default function stateModelFactory(pluginManager: PluginManager) {
92
- const minHeight = 40
93
- const defaultHeight = 400
94
- const model = types
95
- .model('BreakpointSplitView', {
96
- type: types.literal('BreakpointSplitView'),
97
- height: types.optional(
98
- types.refinement(
99
- 'viewHeight',
100
- types.number,
101
- (n: number) => n >= minHeight,
102
- ),
103
- defaultHeight,
104
- ),
105
- trackSelectorType: 'hierarchical',
106
- showIntraviewLinks: true,
107
- linkViews: false,
108
- interactToggled: false,
109
- views: types.array(
110
- pluginManager.getViewType('LinearGenomeView')
111
- .stateModel as LinearGenomeViewStateModel,
112
- ),
113
- })
114
- .volatile(() => ({
115
- width: 800,
116
- matchedTrackFeatures: {} as { [key: string]: Feature[][] },
117
- }))
118
- .views(self => ({
119
- /**
120
- * #method
121
- * creates an svg export and save using FileSaver
122
- */
123
- async exportSvg(opts: ExportSvgOptions = {}) {
124
- const { renderToSvg } = await import(
125
- './svgcomponents/SVGBreakpointSplitView'
126
- )
127
- const html = await renderToSvg(self as BreakpointViewModel, opts)
128
- const blob = new Blob([html], { type: 'image/svg+xml' })
129
- saveAs(blob, opts.filename || 'image.svg')
130
- },
131
- }))
132
- .views(self => ({
133
- // Find all track ids that match across multiple views
134
- get matchedTracks() {
135
- return intersect(
136
- elt => elt.configuration.trackId as string,
137
- ...self.views.map(view => view.tracks),
138
- )
139
- },
140
-
141
- // Get tracks with a given trackId across multiple views
142
- getMatchedTracks(trackConfigId: string) {
143
- return self.views
144
- .map(view => view.getTrack(trackConfigId))
145
- .filter(f => !!f)
146
- },
147
-
148
- // Translocation features are handled differently
149
- // since they do not have a mate e.g. they are one sided
150
- hasTranslocations(trackConfigId: string) {
151
- return [...this.getTrackFeatures(trackConfigId).values()].find(
152
- f => f.get('type') === 'translocation',
153
- )
154
- },
155
-
156
- // Get a composite map of featureId->feature map for a track across
157
- // multiple views
158
- getTrackFeatures(trackConfigId: string) {
159
- return new Map(
160
- self.matchedTrackFeatures[trackConfigId]
161
- ?.flat()
162
- .map(f => [f.id(), f]),
163
- )
164
- },
165
-
166
- getMatchedFeaturesInLayout(trackConfigId: string, features: Feature[][]) {
167
- // use reverse to search the second track first
168
- const tracks = this.getMatchedTracks(trackConfigId)
169
-
170
- return features.map(c =>
171
- c
172
- .map(feature => {
173
- const level = tracks.findIndex(track => calc(track, feature))
174
- return level !== -1
175
- ? {
176
- feature,
177
- layout: calc(tracks[level], feature),
178
- level,
179
- }
180
- : undefined
181
- })
182
- .filter(notEmpty),
183
- )
184
- },
185
- }))
186
- .actions(self => ({
187
- afterAttach() {
188
- addDisposer(
189
- self,
190
- onAction(
191
- self,
192
- ({
193
- name,
194
- path,
195
- args,
196
- }: {
197
- name: string
198
- path?: string
199
- args?: unknown[]
200
- }) => {
201
- if (self.linkViews) {
202
- const actions = [
203
- 'horizontalScroll',
204
- 'zoomTo',
205
- 'setScaleFactor',
206
- 'showTrack',
207
- 'toggleTrack',
208
- 'hideTrack',
209
- 'setTrackLabels',
210
- 'toggleCenterLine',
211
- ]
212
- if (actions.includes(name) && path) {
213
- this.onSubviewAction(name, path, args)
214
- }
215
- }
216
- },
217
- ),
218
- )
219
- },
220
-
221
- onSubviewAction(actionName: string, path: string, args?: unknown[]) {
222
- self.views.forEach(view => {
223
- const ret = getPath(view)
224
- if (ret.lastIndexOf(path) !== ret.length - path.length) {
225
- // @ts-ignore
226
- view[actionName](args?.[0])
227
- }
228
- })
229
- },
230
-
231
- setWidth(newWidth: number) {
232
- self.width = newWidth
233
- self.views.forEach(v => v.setWidth(newWidth))
234
- },
235
-
236
- removeView(view: LGV) {
237
- self.views.remove(view)
238
- },
239
-
240
- closeView() {
241
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
242
- getParent<any>(self, 2).removeView(self)
243
- },
244
-
245
- toggleInteract() {
246
- self.interactToggled = !self.interactToggled
247
- },
248
- toggleIntraviewLinks() {
249
- self.showIntraviewLinks = !self.showIntraviewLinks
250
- },
251
- toggleLinkViews() {
252
- self.linkViews = !self.linkViews
253
- },
254
- setMatchedTrackFeatures(obj: { [key: string]: Feature[][] }) {
255
- self.matchedTrackFeatures = obj
256
- },
257
- }))
258
- .actions(self => ({
259
- afterAttach() {
260
- addDisposer(
261
- self,
262
- autorun(async () => {
263
- try {
264
- if (!self.views.every(view => view.initialized)) {
265
- return
266
- }
267
- self.setMatchedTrackFeatures(
268
- Object.fromEntries(
269
- await Promise.all(
270
- self.matchedTracks.map(async track => [
271
- track.configuration.trackId,
272
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
273
- await getBlockFeatures(self as any, track),
274
- ]),
275
- ),
276
- ),
277
- )
278
- } catch (e) {
279
- console.error(e)
280
- getSession(self).notify(`${e}`, 'error')
281
- }
282
- }),
283
- )
284
- },
285
-
286
- menuItems() {
287
- return [
288
- ...self.views
289
- .map((view, idx) => [idx, view.menuItems?.()] as const)
290
- .filter(f => !!f[1])
291
- .map(f => ({ label: `View ${f[0] + 1} Menu`, subMenu: f[1] })),
292
-
293
- {
294
- label: 'Show intra-view links',
295
- type: 'checkbox',
296
- checked: self.showIntraviewLinks,
297
- onClick: () => self.toggleIntraviewLinks(),
298
- },
299
- {
300
- label: 'Allow clicking alignment squiggles?',
301
- type: 'checkbox',
302
- checked: self.interactToggled,
303
- onClick: () => self.toggleInteract(),
304
- },
305
-
306
- {
307
- label: 'Link views',
308
- type: 'checkbox',
309
- icon: LinkIcon,
310
- checked: self.linkViews,
311
- onClick: () => {
312
- self.toggleLinkViews()
313
- },
314
- },
315
- {
316
- label: 'Export SVG',
317
- icon: PhotoCamera,
318
- onClick: (): void => {
319
- getSession(self).queueDialog(handleClose => [
320
- ExportSvgDialog,
321
- { model: self, handleClose },
322
- ])
323
- },
324
- },
325
- ]
326
- },
327
- }))
328
-
329
- return types.compose(BaseViewModel, model)
330
- }
331
-
332
- export type BreakpointViewStateModel = ReturnType<typeof stateModelFactory>
333
- export type BreakpointViewModel = Instance<BreakpointViewStateModel>
@@ -1,21 +0,0 @@
1
- import React from 'react'
2
- import { useTheme } from '@mui/material'
3
-
4
- export default function SVGBackground({
5
- width,
6
- height,
7
- shift,
8
- }: {
9
- width: number
10
- height: number
11
- shift: number
12
- }) {
13
- const theme = useTheme()
14
- return (
15
- <rect
16
- width={width + shift * 2}
17
- height={height}
18
- fill={theme.palette.background.default}
19
- />
20
- )
21
- }
@@ -1,179 +0,0 @@
1
- import React from 'react'
2
- import { renderToStaticMarkup } from 'react-dom/server'
3
- import { when } from 'mobx'
4
- import {
5
- AbstractSessionModel,
6
- getSession,
7
- max,
8
- measureText,
9
- sum,
10
- } from '@jbrowse/core/util'
11
- import { ThemeProvider } from '@mui/material'
12
- import { createJBrowseTheme } from '@jbrowse/core/ui'
13
-
14
- // locals
15
- import {
16
- SVGTracks,
17
- SVGRuler,
18
- totalHeight,
19
- LinearGenomeViewModel,
20
- } from '@jbrowse/plugin-linear-genome-view'
21
-
22
- // locals
23
- import SVGBackground from './SVGBackground'
24
- import { ExportSvgOptions, BreakpointViewModel } from '../model'
25
- import { getTrackName } from '@jbrowse/core/util/tracks'
26
- import Overlay from '../components/Overlay'
27
-
28
- type BSV = BreakpointViewModel
29
-
30
- function getTrackNameMaxLen(
31
- views: LinearGenomeViewModel[],
32
- fontSize: number,
33
- session: AbstractSessionModel,
34
- ) {
35
- return max(
36
- views.flatMap(view =>
37
- view.tracks.map(t =>
38
- measureText(getTrackName(t.configuration, session), fontSize),
39
- ),
40
- ),
41
- 0,
42
- )
43
- }
44
- function getTrackOffsets(
45
- view: LinearGenomeViewModel,
46
- textOffset: number,
47
- extra = 0,
48
- ) {
49
- const offsets = {} as { [key: string]: number }
50
- let curr = textOffset
51
- for (let i = 0; i < view.tracks.length; i++) {
52
- const track = view.tracks[i]
53
- offsets[track.configuration.trackId] = curr + extra
54
- curr += track.displays[0].height + textOffset
55
- }
56
- return offsets
57
- }
58
-
59
- // render LGV to SVG
60
- export async function renderToSvg(model: BSV, opts: ExportSvgOptions) {
61
- const {
62
- textHeight = 18,
63
- headerHeight = 30,
64
- rulerHeight = 30,
65
- fontSize = 13,
66
- trackLabels = 'offset',
67
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
68
- Wrapper = ({ children }: any) => <>{children}</>,
69
- themeName = 'default',
70
- } = opts
71
- const session = getSession(model)
72
- const theme = session.allThemes?.()[themeName]
73
- const { width, views } = model
74
- const shift = 50
75
- const offset = headerHeight + rulerHeight
76
-
77
- const heights = views.map(
78
- v => totalHeight(v.tracks, textHeight, trackLabels) + offset,
79
- )
80
- const totalHeightSvg = sum(heights) + 100
81
- const displayResults = await Promise.all(
82
- views.map(
83
- async view =>
84
- ({
85
- view,
86
- data: await Promise.all(
87
- view.tracks.map(async track => {
88
- const d = track.displays[0]
89
- await when(() => (d.ready !== undefined ? d.ready : true))
90
- return { track, result: await d.renderSvg({ ...opts, theme }) }
91
- }),
92
- ),
93
- } as const),
94
- ),
95
- )
96
-
97
- const trackLabelMaxLen = getTrackNameMaxLen(views, fontSize, session) + 40
98
- const trackLabelOffset = trackLabels === 'left' ? trackLabelMaxLen : 0
99
- const textOffset = trackLabels === 'offset' ? textHeight : 0
100
- const trackOffsets = [
101
- getTrackOffsets(views[0], textOffset, fontSize + offset),
102
- getTrackOffsets(views[1], textOffset, fontSize + heights[0] + offset),
103
- ]
104
- const w = width + trackLabelOffset
105
- const t = createJBrowseTheme(theme)
106
-
107
- // the xlink namespace is used for rendering <image> tag
108
- return renderToStaticMarkup(
109
- <ThemeProvider theme={t}>
110
- <Wrapper>
111
- <svg
112
- width={width}
113
- height={totalHeightSvg}
114
- xmlns="http://www.w3.org/2000/svg"
115
- xmlnsXlink="http://www.w3.org/1999/xlink"
116
- viewBox={[0, 0, w + shift * 2, totalHeightSvg].toString()}
117
- >
118
- <SVGBackground width={w} height={totalHeightSvg} shift={shift} />
119
- <g transform={`translate(${shift} ${fontSize})`}>
120
- <g transform={`translate(${trackLabelOffset})`}>
121
- <text x={0} fontSize={fontSize} fill={t.palette.text.primary}>
122
- {views[0].assemblyNames.join(', ')}
123
- </text>
124
-
125
- <SVGRuler model={displayResults[0].view} fontSize={fontSize} />
126
- </g>
127
- <SVGTracks
128
- textHeight={textHeight}
129
- trackLabels={trackLabels}
130
- fontSize={fontSize}
131
- model={displayResults[0].view}
132
- displayResults={displayResults[0].data}
133
- offset={offset}
134
- trackLabelOffset={trackLabelOffset}
135
- />
136
- </g>
137
-
138
- <g transform={`translate(${shift} ${fontSize + heights[0]})`}>
139
- <g transform={`translate(${trackLabelOffset})`}>
140
- <text x={0} fontSize={fontSize} fill={t.palette.text.primary}>
141
- {views[1].assemblyNames.join(', ')}
142
- </text>
143
- <SVGRuler model={displayResults[1].view} fontSize={fontSize} />
144
- </g>
145
- <SVGTracks
146
- textHeight={textHeight}
147
- trackLabels={trackLabels}
148
- fontSize={fontSize}
149
- model={displayResults[1].view}
150
- displayResults={displayResults[1].data}
151
- offset={offset}
152
- trackLabelOffset={trackLabelOffset}
153
- />
154
- </g>
155
-
156
- <defs>
157
- <clipPath id="clip-bsv">
158
- <rect x={0} y={0} width={width} height={totalHeightSvg} />
159
- </clipPath>
160
- </defs>
161
- <g
162
- transform={`translate(${trackLabelOffset + shift})`}
163
- clipPath="url(#clip-bsv)"
164
- >
165
- {model.matchedTracks.map(track => (
166
- <Overlay
167
- parentRef={{ current: null }}
168
- key={track.configuration.trackId}
169
- model={model}
170
- trackId={track.configuration.trackId}
171
- getTrackYPosOverride={(id, level) => trackOffsets[level][id]}
172
- />
173
- ))}
174
- </g>
175
- </svg>
176
- </Wrapper>
177
- </ThemeProvider>,
178
- )
179
- }
@@ -1,89 +0,0 @@
1
- import { useState, useEffect } from 'react'
2
- import { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
3
- import { clamp } from '@jbrowse/core/util'
4
-
5
- // locals
6
- import { LayoutRecord } from './model'
7
-
8
- type LGV = LinearGenomeViewModel
9
-
10
- interface Display {
11
- height: number
12
- scrollTop: number
13
- SNPCoverageDisplay?: { height: number }
14
- }
15
-
16
- interface Track {
17
- displays: Display[]
18
- }
19
-
20
- const [, TOP, , BOTTOM] = [0, 1, 2, 3]
21
-
22
- function cheight(chunk: LayoutRecord) {
23
- return chunk[BOTTOM] - chunk[TOP]
24
- }
25
-
26
- function heightFromSpecificLevel(
27
- views: LGV[],
28
- trackId: string,
29
- level: number,
30
- getYPosOverride?: (trackId: string, level: number) => number,
31
- ) {
32
- return getYPosOverride
33
- ? getYPosOverride(trackId, level)
34
- : views[level].trackRefs[trackId]?.getBoundingClientRect().top || 0
35
- }
36
-
37
- export function getPxFromCoordinate(view: LGV, refName: string, coord: number) {
38
- return ((view.bpToPx({ refName, coord }) || {}).offsetPx || 0) - view.offsetPx
39
- }
40
-
41
- // get's the yposition of a layout record in a track
42
- export function yPos(
43
- trackId: string,
44
- level: number,
45
- views: LGV[],
46
- tracks: Track[],
47
- c: LayoutRecord,
48
- getYPosOverride?: (trackId: string, level: number) => number,
49
- ) {
50
- const display = tracks[level].displays[0]
51
- const min = 0
52
- const max = display.height
53
- let offset = 0
54
- const { SNPCoverageDisplay } = display
55
- if (SNPCoverageDisplay) {
56
- offset = SNPCoverageDisplay.height
57
- }
58
- const yPos = getYPosOverride ? 0 : display.scrollTop
59
- return (
60
- clamp(c[TOP] - yPos + cheight(c) / 2 + offset, min, max) +
61
- heightFromSpecificLevel(views, trackId, level, getYPosOverride) +
62
- display.scrollTop
63
- )
64
- }
65
-
66
- // we combo a useEffect and useState combo to force rerender on snap changing.
67
- // the setup of this being a useEffect+useState makes it re-render once the
68
- // useEffect is called, which is generally the "next frame". If we removed the
69
- // below use
70
- export const useNextFrame = (variable: unknown) => {
71
- const [, setNextFrameState] = useState<unknown>()
72
- useEffect(() => {
73
- setNextFrameState(variable)
74
- }, [variable])
75
- }
76
-
77
- // https://stackoverflow.com/a/49186706/2129219 the array-intersection package
78
- // on npm has a large kb size, and we are just intersecting open track ids so
79
- // simple is better
80
- export function intersect<T>(
81
- cb: (l: T) => string,
82
- a1: T[] = [],
83
- a2: T[] = [],
84
- ...rest: T[][]
85
- ): T[] {
86
- const ids = new Set(a2.map(elt => cb(elt)))
87
- const a12 = a1.filter(value => ids.has(cb(value)))
88
- return rest.length === 0 ? a12 : intersect(cb, a12, ...rest)
89
- }
package/src/index.test.ts DELETED
@@ -1,3 +0,0 @@
1
- test('easy', () => {
2
- expect(1).toBe(1)
3
- })
package/src/index.ts DELETED
@@ -1,15 +0,0 @@
1
- import PluginManager from '@jbrowse/core/PluginManager'
2
- import Plugin from '@jbrowse/core/Plugin'
3
- import BreakpointAlignmentsWidgetF from './BreakpointAlignmentsFeatureDetail'
4
- import BreakpointSplitViewF from './BreakpointSplitView'
5
-
6
- export default class BreakpointSplitViewPlugin extends Plugin {
7
- name = 'BreakpointSplitViewPlugin'
8
-
9
- install(pluginManager: PluginManager) {
10
- BreakpointSplitViewF(pluginManager)
11
- BreakpointAlignmentsWidgetF(pluginManager)
12
- }
13
-
14
- configure() {}
15
- }