@apollo-annotation/jbrowse-plugin-apollo 0.1.18 → 0.1.20

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 (85) hide show
  1. package/dist/index.esm.js +3189 -3575
  2. package/dist/index.esm.js.map +1 -1
  3. package/dist/jbrowse-plugin-apollo.cjs.development.js +3185 -3570
  4. package/dist/jbrowse-plugin-apollo.cjs.development.js.map +1 -1
  5. package/dist/jbrowse-plugin-apollo.cjs.production.min.js +1 -1
  6. package/dist/jbrowse-plugin-apollo.cjs.production.min.js.map +1 -1
  7. package/dist/jbrowse-plugin-apollo.umd.development.js +14884 -15905
  8. package/dist/jbrowse-plugin-apollo.umd.development.js.map +1 -1
  9. package/dist/jbrowse-plugin-apollo.umd.production.min.js +1 -1
  10. package/dist/jbrowse-plugin-apollo.umd.production.min.js.map +1 -1
  11. package/package.json +33 -33
  12. package/src/ApolloInternetAccount/addMenuItems.ts +18 -0
  13. package/src/ApolloInternetAccount/components/AuthTypeSelector.tsx +1 -0
  14. package/src/ApolloInternetAccount/configSchema.ts +5 -2
  15. package/src/ApolloInternetAccount/model.ts +14 -5
  16. package/src/ApolloRefNameAliasAdapter/ApolloRefNameAliasAdapter.ts +94 -0
  17. package/src/ApolloRefNameAliasAdapter/configSchema.ts +12 -0
  18. package/src/ApolloRefNameAliasAdapter/index.ts +21 -0
  19. package/src/ApolloSequenceAdapter/ApolloSequenceAdapter.ts +1 -0
  20. package/src/ApolloSixFrameRenderer/components/ApolloRendering.tsx +10 -10
  21. package/src/ApolloTextSearchAdapter/ApolloTextSearchAdapter.ts +35 -32
  22. package/src/BackendDrivers/BackendDriver.ts +8 -0
  23. package/src/BackendDrivers/CollaborationServerDriver.ts +49 -1
  24. package/src/BackendDrivers/DesktopFileDriver.ts +14 -1
  25. package/src/BackendDrivers/InMemoryFileDriver.ts +17 -1
  26. package/src/ChangeManager.ts +1 -1
  27. package/src/FeatureDetailsWidget/ApolloFeatureDetailsWidget.tsx +5 -25
  28. package/src/FeatureDetailsWidget/ApolloTranscriptDetailsWidget.tsx +82 -0
  29. package/src/FeatureDetailsWidget/Attributes.tsx +11 -3
  30. package/src/FeatureDetailsWidget/BasicInformation.tsx +38 -30
  31. package/src/FeatureDetailsWidget/Sequence.tsx +7 -7
  32. package/src/FeatureDetailsWidget/TranscriptBasic.tsx +446 -0
  33. package/src/FeatureDetailsWidget/TranscriptSequence.tsx +365 -0
  34. package/src/FeatureDetailsWidget/index.ts +2 -0
  35. package/src/FeatureDetailsWidget/model.ts +77 -9
  36. package/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx +0 -2
  37. package/src/LinearApolloDisplay/glyphs/BoxGlyph.ts +453 -380
  38. package/src/LinearApolloDisplay/glyphs/GeneGlyph.ts +520 -0
  39. package/src/LinearApolloDisplay/glyphs/GenericChildGlyph.ts +138 -134
  40. package/src/LinearApolloDisplay/glyphs/Glyph.ts +38 -370
  41. package/src/LinearApolloDisplay/glyphs/index.ts +1 -2
  42. package/src/LinearApolloDisplay/stateModel/base.ts +3 -6
  43. package/src/LinearApolloDisplay/stateModel/getGlyph.ts +30 -30
  44. package/src/LinearApolloDisplay/stateModel/index.ts +5 -1
  45. package/src/LinearApolloDisplay/stateModel/layouts.ts +32 -24
  46. package/src/LinearApolloDisplay/stateModel/mouseEvents.ts +206 -217
  47. package/src/LinearApolloDisplay/stateModel/rendering.ts +43 -67
  48. package/src/OntologyManager/OntologyStore/fulltext.ts +1 -1
  49. package/src/OntologyManager/OntologyStore/index.ts +2 -1
  50. package/src/OntologyManager/index.ts +6 -2
  51. package/src/OntologyManager/util.ts +2 -2
  52. package/src/SixFrameFeatureDisplay/stateModel.ts +15 -10
  53. package/src/TabularEditor/HybridGrid/ChangeHandling.ts +21 -46
  54. package/src/TabularEditor/HybridGrid/Feature.tsx +31 -82
  55. package/src/TabularEditor/HybridGrid/FeatureAttributes.tsx +3 -2
  56. package/src/TabularEditor/HybridGrid/HybridGrid.tsx +2 -3
  57. package/src/TabularEditor/HybridGrid/NumberCell.tsx +1 -0
  58. package/src/TabularEditor/HybridGrid/featureContextMenuItems.ts +46 -5
  59. package/src/TabularEditor/model.ts +5 -3
  60. package/src/components/AddAssembly.tsx +15 -9
  61. package/src/components/AddChildFeature.tsx +7 -73
  62. package/src/components/AddFeature.tsx +2 -57
  63. package/src/components/AddRefSeqAliases.tsx +285 -0
  64. package/src/components/CopyFeature.tsx +16 -33
  65. package/src/components/DeleteFeature.tsx +4 -6
  66. package/src/components/ImportFeatures.tsx +6 -3
  67. package/src/components/LogOut.tsx +105 -0
  68. package/src/components/ManageChecks.tsx +1 -0
  69. package/src/components/ManageUsers.tsx +21 -1
  70. package/src/components/ModifyFeatureAttribute.tsx +2 -2
  71. package/src/components/OntologyTermAutocomplete.tsx +0 -2
  72. package/src/components/OntologyTermMultiSelect.tsx +1 -0
  73. package/src/components/OpenLocalFile.tsx +6 -5
  74. package/src/components/ViewChangeLog.tsx +1 -0
  75. package/src/components/ViewCheckResults.tsx +1 -0
  76. package/src/components/index.ts +4 -0
  77. package/src/extensions/annotationFromPileup.ts +10 -16
  78. package/src/index.ts +57 -3
  79. package/src/session/ClientDataStore.ts +49 -46
  80. package/src/session/session.ts +186 -114
  81. package/src/util/loadAssemblyIntoClient.ts +4 -210
  82. package/src/FeatureDetailsWidget/RelatedFeature.tsx +0 -97
  83. package/src/LinearApolloDisplay/glyphs/CanonicalGeneGlyph.ts +0 -1204
  84. package/src/LinearApolloDisplay/glyphs/ImplicitExonGeneGlyph.ts +0 -716
  85. package/src/LinearApolloDisplay/stateModel/glyphs.ts +0 -47
@@ -1,6 +1,8 @@
1
- /* eslint-disable @typescript-eslint/no-unnecessary-condition */
2
- /* eslint-disable @typescript-eslint/no-unsafe-member-access */
3
- import { AnnotationFeatureI } from '@apollo-annotation/mst'
1
+ import { AnnotationFeature } from '@apollo-annotation/mst'
2
+ import {
3
+ LocationEndChange,
4
+ LocationStartChange,
5
+ } from '@apollo-annotation/shared'
4
6
  import { AnyConfigurationSchemaType } from '@jbrowse/core/configuration/configurationSchema'
5
7
  import PluginManager from '@jbrowse/core/PluginManager'
6
8
  import { MenuItem } from '@jbrowse/core/ui'
@@ -15,6 +17,13 @@ import { Glyph } from '../glyphs/Glyph'
15
17
  import { CanvasMouseEvent } from '../types'
16
18
  import { getGlyph } from './getGlyph'
17
19
  import { renderingModelFactory } from './rendering'
20
+ import { Frame, getFrame } from '@jbrowse/core/util'
21
+
22
+ export interface FeatureAndGlyphUnderMouse {
23
+ feature: AnnotationFeature
24
+ topLevelFeature: AnnotationFeature
25
+ glyph: Glyph
26
+ }
18
27
 
19
28
  /** extended information about the position of the mouse on the canvas, including the refName, bp, and displayedRegion number */
20
29
  export interface MousePosition {
@@ -23,20 +32,15 @@ export interface MousePosition {
23
32
  refName: string
24
33
  bp: number
25
34
  regionNumber: number
35
+ featureAndGlyphUnderMouse?: FeatureAndGlyphUnderMouse
26
36
  }
27
37
 
28
- export interface FeatureAndGlyphInfo {
29
- feature?: AnnotationFeatureI
30
- topLevelFeature?: AnnotationFeatureI
31
- glyph?: Glyph
32
- mousePosition?: MousePosition
33
- }
38
+ export type MousePositionWithFeatureAndGlyph = Required<MousePosition>
34
39
 
35
- export interface CDSDiscontinuousLocation {
36
- start: number
37
- end: number
38
- phase: 0 | 1 | 2 | undefined
39
- idx?: number
40
+ export function isMousePositionWithFeatureAndGlyph(
41
+ mousePosition: MousePosition,
42
+ ): mousePosition is MousePositionWithFeatureAndGlyph {
43
+ return 'featureAndGlyphUnderMouse' in mousePosition
40
44
  }
41
45
 
42
46
  function getMousePosition(
@@ -45,26 +49,45 @@ function getMousePosition(
45
49
  ): MousePosition {
46
50
  const canvas = event.currentTarget
47
51
  const { clientX, clientY } = event
48
- const { left, top } = canvas.getBoundingClientRect() || { left: 0, top: 0 }
52
+ const { left, top } = canvas.getBoundingClientRect()
49
53
  const x = clientX - left
50
54
  const y = clientY - top
51
55
  const { coord: bp, index: regionNumber, refName } = lgv.pxToBp(x)
52
56
  return { x, y, refName, bp, regionNumber }
53
57
  }
54
58
 
55
- function getSeqRow(feature: AnnotationFeatureI, bpPerPx: number) {
56
- const rowOffset = bpPerPx <= 1 ? 5 : 3
57
- if (feature.type === 'CDS' && feature.phase !== undefined) {
58
- return feature.strand === -1
59
- ? ((feature.end - feature.phase) % 3) + rowOffset
60
- : Math.abs(((feature.start + feature.phase) % 3) - 2)
59
+ function getTranslationRow(frame: Frame, bpPerPx: number) {
60
+ const offset = bpPerPx <= 1 ? 2 : 0
61
+ switch (frame) {
62
+ case 3: {
63
+ return 0
64
+ }
65
+ case 2: {
66
+ return 1
67
+ }
68
+ case 1: {
69
+ return 2
70
+ }
71
+ case -1: {
72
+ return 3 + offset
73
+ }
74
+ case -2: {
75
+ return 4 + offset
76
+ }
77
+ case -3: {
78
+ return 5 + offset
79
+ }
61
80
  }
81
+ }
62
82
 
63
- if (bpPerPx <= 1) {
64
- return feature.strand === -1 ? 4 : 3
83
+ function getSeqRow(
84
+ strand: 1 | -1 | undefined,
85
+ bpPerPx: number,
86
+ ): number | undefined {
87
+ if (bpPerPx > 1 || strand === undefined) {
88
+ return
65
89
  }
66
-
67
- return
90
+ return strand === 1 ? 3 : 4
68
91
  }
69
92
 
70
93
  function highlightSeq(
@@ -99,72 +122,62 @@ export function mouseEventsModelIntermediateFactory(
99
122
  return LinearApolloDisplayRendering.named('LinearApolloDisplayMouseEvents')
100
123
  .volatile(() => ({
101
124
  apolloDragging: null as {
102
- start: {
103
- glyph?: Glyph
104
- feature?: AnnotationFeatureI
105
- topLevelFeature?: AnnotationFeatureI
106
- discontinuousLocation?: CDSDiscontinuousLocation
107
- mousePosition: MousePosition
108
- }
109
- current: {
110
- glyph?: Glyph
111
- feature?: AnnotationFeatureI
112
- topLevelFeature?: AnnotationFeatureI
113
- mousePosition: MousePosition
114
- }
125
+ start: MousePosition
126
+ current: MousePosition
127
+ feature: AnnotationFeature
128
+ edge: 'min' | 'max'
115
129
  } | null,
116
130
  cursor: undefined as CSSProperties['cursor'] | undefined,
117
- apolloHover: null as FeatureAndGlyphInfo | null,
131
+ apolloHover: undefined as FeatureAndGlyphUnderMouse | undefined,
118
132
  }))
119
133
  .views((self) => ({
120
- getFeatureAndGlyphUnderMouse(
121
- event: CanvasMouseEvent,
122
- ): FeatureAndGlyphInfo {
134
+ getMousePosition(event: CanvasMouseEvent): MousePosition {
123
135
  const mousePosition = getMousePosition(event, self.lgv)
124
136
  const { bp, regionNumber, y } = mousePosition
125
137
  const row = Math.floor(y / self.apolloRowHeight)
126
138
  const featureLayout = self.featureLayouts[regionNumber]
127
139
  const layoutRow = featureLayout.get(row)
128
140
  if (!layoutRow) {
129
- return { mousePosition }
141
+ return mousePosition
130
142
  }
131
143
  const foundFeature = layoutRow.find(
132
144
  (f) => bp >= f[1].min && bp <= f[1].max,
133
145
  )
134
146
  if (!foundFeature) {
135
- return { mousePosition }
147
+ return mousePosition
136
148
  }
137
149
  const [featureRow, topLevelFeature] = foundFeature
138
- const glyph = getGlyph(topLevelFeature, self.lgv.bpPerPx)
150
+ const glyph = getGlyph(topLevelFeature)
139
151
  const feature = glyph.getFeatureFromLayout(
140
152
  topLevelFeature,
141
153
  bp,
142
154
  featureRow,
143
155
  )
144
- return { feature, topLevelFeature, glyph, mousePosition }
156
+ if (!feature) {
157
+ return mousePosition
158
+ }
159
+ return {
160
+ ...mousePosition,
161
+ featureAndGlyphUnderMouse: { feature, topLevelFeature, glyph },
162
+ }
145
163
  },
146
164
  }))
147
165
  .actions((self) => ({
148
- continueDrag(event: CanvasMouseEvent) {
166
+ continueDrag(mousePosition: MousePosition, event: CanvasMouseEvent) {
149
167
  if (!self.apolloDragging) {
150
168
  throw new Error(
151
169
  'continueDrag() called with no current drag in progress',
152
170
  )
153
171
  }
154
172
  event.stopPropagation()
155
- const { glyph } = self.apolloDragging.start
156
- const { mousePosition } = self.getFeatureAndGlyphUnderMouse(event)
157
- if (!(mousePosition && glyph)) {
158
- return
159
- }
160
- glyph.continueDrag(self, mousePosition)
173
+ self.apolloDragging = { ...self.apolloDragging, current: mousePosition }
161
174
  },
162
175
  setDragging(dragInfo?: typeof self.apolloDragging) {
163
176
  self.apolloDragging = dragInfo ?? null
164
177
  },
165
178
  }))
166
179
  .actions((self) => ({
167
- setApolloHover(n: (typeof self)['apolloHover']) {
180
+ setApolloHover(n?: (typeof self)['apolloHover']) {
168
181
  self.apolloHover = n
169
182
  },
170
183
  setCursor(cursor?: CSSProperties['cursor']) {
@@ -196,6 +209,8 @@ export function mouseEventsSeqHightlightModelFactory(
196
209
  self,
197
210
  autorun(
198
211
  () => {
212
+ // This type is wrong in @jbrowse/core
213
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
199
214
  if (!self.lgv.initialized || self.regionCannotBeRendered()) {
200
215
  return
201
216
  }
@@ -212,38 +227,43 @@ export function mouseEventsSeqHightlightModelFactory(
212
227
  self.lgv.bpPerPx <= 1 ? 125 : 95,
213
228
  )
214
229
 
215
- const {
216
- apolloHover,
217
- displayedRegions,
218
- lgv,
219
- regions,
220
- sequenceRowHeight,
221
- theme,
222
- } = self
230
+ const { apolloHover, lgv, regions, sequenceRowHeight, theme } = self
223
231
 
224
232
  if (!apolloHover) {
225
233
  return
226
234
  }
227
- const { feature, mousePosition } = apolloHover
228
- if (!feature || !mousePosition) {
229
- return
230
- }
235
+ const { feature } = apolloHover
231
236
 
232
237
  for (const [idx, region] of regions.entries()) {
233
- const row = getSeqRow(feature, lgv.bpPerPx)
234
- if (
235
- feature.discontinuousLocations &&
236
- feature.discontinuousLocations.length > 0
237
- ) {
238
- for (const dl of feature.discontinuousLocations) {
238
+ if (feature.type === 'CDS') {
239
+ const parentFeature = feature.parent
240
+ if (!parentFeature) {
241
+ continue
242
+ }
243
+ const cdsLocs = parentFeature.cdsLocations.find(
244
+ (loc) =>
245
+ feature.min === loc.at(0)?.min &&
246
+ feature.max === loc.at(-1)?.max,
247
+ )
248
+ if (!cdsLocs) {
249
+ continue
250
+ }
251
+ for (const dl of cdsLocs) {
252
+ const frame = getFrame(
253
+ dl.min,
254
+ dl.max,
255
+ feature.strand ?? 1,
256
+ dl.phase,
257
+ )
258
+ const row = getTranslationRow(frame, lgv.bpPerPx)
239
259
  const offset =
240
260
  (lgv.bpToPx({
241
261
  refName: region.refName,
242
- coord: dl.start,
262
+ coord: dl.min,
243
263
  regionNumber: idx,
244
264
  })?.offsetPx ?? 0) - lgv.offsetPx
245
- const widthPx = (dl.end - dl.start) / lgv.bpPerPx
246
- const startPx = displayedRegions[idx].reversed
265
+ const widthPx = (dl.max - dl.min) / lgv.bpPerPx
266
+ const startPx = lgv.displayedRegions[idx].reversed
247
267
  ? offset - widthPx
248
268
  : offset
249
269
 
@@ -257,14 +277,15 @@ export function mouseEventsSeqHightlightModelFactory(
257
277
  )
258
278
  }
259
279
  } else {
280
+ const row = getSeqRow(feature.strand, lgv.bpPerPx)
260
281
  const offset =
261
282
  (lgv.bpToPx({
262
283
  refName: region.refName,
263
- coord: feature.start,
284
+ coord: feature.min,
264
285
  regionNumber: idx,
265
286
  })?.offsetPx ?? 0) - lgv.offsetPx
266
287
  const widthPx = feature.length / lgv.bpPerPx
267
- const startPx = displayedRegions[idx].reversed
288
+ const startPx = lgv.displayedRegions[idx].reversed
268
289
  ? offset - widthPx
269
290
  : offset
270
291
 
@@ -297,118 +318,130 @@ export function mouseEventsModelFactory(
297
318
 
298
319
  return LinearApolloDisplayMouseEvents.views((self) => ({
299
320
  contextMenuItems(contextCoord?: Coord): MenuItem[] {
300
- const { apolloHover, lgv } = self
301
- const { topLevelFeature } = apolloHover ?? {}
302
- if (!(topLevelFeature && contextCoord)) {
321
+ const { apolloHover } = self
322
+ if (!(apolloHover && contextCoord)) {
303
323
  return []
304
324
  }
305
- const glyph = getGlyph(topLevelFeature, lgv.bpPerPx)
325
+ const { topLevelFeature } = apolloHover
326
+ const glyph = getGlyph(topLevelFeature)
306
327
  return glyph.getContextMenuItems(self)
307
328
  },
308
329
  }))
309
330
  .actions((self) => ({
310
- startDrag(event: CanvasMouseEvent) {
311
- const { feature, glyph, mousePosition, topLevelFeature } =
312
- self.getFeatureAndGlyphUnderMouse(event)
313
- if (feature && topLevelFeature && glyph && mousePosition) {
314
- let dl, idx
315
- if (
316
- feature.discontinuousLocations &&
317
- feature.discontinuousLocations.length > 0
318
- ) {
319
- for (let i = 0; i < feature.discontinuousLocations.length; i++) {
320
- if (
321
- mousePosition.bp >= feature.discontinuousLocations[i].start &&
322
- mousePosition.bp <= feature.discontinuousLocations[i].end
323
- ) {
324
- idx = i
325
- dl = feature.discontinuousLocations[idx]
326
- break
327
- }
328
- }
329
- }
330
- self.apolloDragging = {
331
- start: {
332
- glyph,
333
- feature,
334
- topLevelFeature,
335
- discontinuousLocation: dl
336
- ? {
337
- start: dl.start,
338
- end: dl.end,
339
- phase: dl.phase,
340
- idx,
341
- }
342
- : undefined,
343
- mousePosition,
344
- },
345
- current: { glyph, feature, topLevelFeature, mousePosition },
346
- }
347
- if (!glyph.startDrag(self, event)) {
348
- self.apolloDragging = null
349
- }
331
+ // explicitly pass in a feature in case it's not the same as the one in
332
+ // mousePosition (e.g. if features are drawn overlapping).
333
+ startDrag(
334
+ mousePosition: MousePositionWithFeatureAndGlyph,
335
+ feature: AnnotationFeature,
336
+ edge: 'min' | 'max',
337
+ ) {
338
+ self.apolloDragging = {
339
+ start: mousePosition,
340
+ current: mousePosition,
341
+ feature,
342
+ edge,
350
343
  }
351
344
  },
352
- endDrag(event: CanvasMouseEvent) {
353
- self.continueDrag(event)
354
- self.apolloDragging?.start.glyph?.executeDrag(self, event)
345
+ endDrag() {
346
+ if (!self.apolloDragging) {
347
+ throw new Error('endDrag() called with no current drag in progress')
348
+ }
349
+ const { current, edge, feature, start } = self.apolloDragging
350
+ // don't do anything if it was only dragged a tiny bit
351
+ if (Math.abs(current.x - start.x) <= 4) {
352
+ self.setDragging()
353
+ self.setCursor()
354
+ return
355
+ }
356
+ const { displayedRegions } = self.lgv
357
+ const region = displayedRegions[start.regionNumber]
358
+ const assembly = self.getAssemblyId(region.assemblyName)
359
+
360
+ let change: LocationEndChange | LocationStartChange
361
+ if (edge === 'max') {
362
+ const featureId = feature._id
363
+ const oldEnd = feature.max
364
+ const newEnd = current.bp
365
+ change = new LocationEndChange({
366
+ typeName: 'LocationEndChange',
367
+ changedIds: [featureId],
368
+ featureId,
369
+ oldEnd,
370
+ newEnd,
371
+ assembly,
372
+ })
373
+ } else {
374
+ const featureId = feature._id
375
+ const oldStart = feature.min
376
+ const newStart = current.bp
377
+ change = new LocationStartChange({
378
+ typeName: 'LocationStartChange',
379
+ changedIds: [featureId],
380
+ featureId,
381
+ oldStart,
382
+ newStart,
383
+ assembly,
384
+ })
385
+ }
386
+ void self.changeManager.submit(change)
355
387
  self.setDragging()
388
+ self.setCursor()
356
389
  },
357
390
  }))
358
391
  .actions((self) => ({
359
392
  onMouseDown(event: CanvasMouseEvent) {
360
- const { feature, glyph, topLevelFeature } =
361
- self.getFeatureAndGlyphUnderMouse(event)
362
- if (glyph && feature && topLevelFeature) {
363
- glyph.onMouseDown(self, event)
393
+ const mousePosition = self.getMousePosition(event)
394
+ if (isMousePositionWithFeatureAndGlyph(mousePosition)) {
395
+ mousePosition.featureAndGlyphUnderMouse.glyph.onMouseDown(
396
+ self,
397
+ mousePosition,
398
+ event,
399
+ )
364
400
  }
365
401
  },
366
402
  onMouseMove(event: CanvasMouseEvent) {
367
- const { buttons } = event
368
- const hover = self.getFeatureAndGlyphUnderMouse(event)
369
- const { glyph } = hover
370
- if (glyph) {
371
- glyph.onMouseMove(self, event)
403
+ const mousePosition = self.getMousePosition(event)
404
+ if (self.apolloDragging) {
405
+ self.setCursor('col-resize')
406
+ self.continueDrag(mousePosition, event)
407
+ return
372
408
  }
373
-
374
- if (buttons) {
375
- // if button 1 is being held down while moving, we must be dragging
376
- if (buttons === 1) {
377
- if (self.apolloDragging) {
378
- // otherwise update the drag state
379
- self.continueDrag(event)
380
- } else {
381
- // start drag if not already dragging
382
- self.startDrag(event)
383
- }
384
- }
409
+ if (isMousePositionWithFeatureAndGlyph(mousePosition)) {
410
+ mousePosition.featureAndGlyphUnderMouse.glyph.onMouseMove(
411
+ self,
412
+ mousePosition,
413
+ event,
414
+ )
385
415
  } else {
386
- // if no buttons, update mouseover hover
387
- const { feature, topLevelFeature } = hover
388
- if (feature && glyph && topLevelFeature) {
389
- self.setApolloHover(hover)
390
- } else {
391
- self.setApolloHover(null)
392
- self.setCursor()
393
- }
416
+ self.setApolloHover()
417
+ self.setCursor()
394
418
  }
395
419
  },
396
420
  onMouseLeave(event: CanvasMouseEvent) {
397
421
  self.setDragging()
422
+ self.setApolloHover()
398
423
 
399
- const { glyph } = self.getFeatureAndGlyphUnderMouse(event)
400
- if (glyph) {
401
- glyph.onMouseLeave(self, event)
424
+ const mousePosition = self.getMousePosition(event)
425
+ if (isMousePositionWithFeatureAndGlyph(mousePosition)) {
426
+ mousePosition.featureAndGlyphUnderMouse.glyph.onMouseLeave(
427
+ self,
428
+ mousePosition,
429
+ event,
430
+ )
402
431
  }
403
432
  },
404
433
  onMouseUp(event: CanvasMouseEvent) {
405
- const { glyph } = self.getFeatureAndGlyphUnderMouse(event)
406
- if (glyph) {
407
- glyph.onMouseUp(self, event)
434
+ const mousePosition = self.getMousePosition(event)
435
+ if (isMousePositionWithFeatureAndGlyph(mousePosition)) {
436
+ mousePosition.featureAndGlyphUnderMouse.glyph.onMouseUp(
437
+ self,
438
+ mousePosition,
439
+ event,
440
+ )
408
441
  }
409
442
 
410
443
  if (self.apolloDragging) {
411
- self.endDrag(event)
444
+ self.endDrag()
412
445
  }
413
446
  },
414
447
  }))
@@ -418,6 +451,8 @@ export function mouseEventsModelFactory(
418
451
  self,
419
452
  autorun(
420
453
  () => {
454
+ // This type is wrong in @jbrowse/core
455
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
421
456
  if (!self.lgv.initialized || self.regionCannotBeRendered()) {
422
457
  return
423
458
  }
@@ -432,73 +467,24 @@ export function mouseEventsModelFactory(
432
467
  self.featuresHeight,
433
468
  )
434
469
 
435
- const {
436
- apolloDragging,
437
- apolloHover,
438
- displayedRegions,
439
- featureLayouts,
440
- lgv,
441
- } = self
470
+ const { apolloDragging, apolloHover } = self
442
471
  if (!apolloHover) {
443
472
  return
444
473
  }
445
- const { feature, glyph } = apolloHover
446
- if (!feature) {
447
- return
448
- }
449
- let rowNum = 0
450
- let xOffset = 0
451
- let reversed = false
452
- for (const [idx, featureLayout] of featureLayouts.entries()) {
453
- const displayedRegion = displayedRegions[idx]
454
- for (const [row, featureLayoutRow] of featureLayout.entries()) {
455
- if (rowNum !== 0) {
456
- continue
457
- }
458
- for (const [, f] of featureLayoutRow) {
459
- for (const [, cf] of f.children ?? new Map()) {
460
- if (rowNum !== 0) {
461
- continue
462
- }
463
- xOffset =
464
- (lgv.bpToPx({
465
- refName: displayedRegion.refName,
466
- coord: feature.min,
467
- regionNumber: idx,
468
- })?.offsetPx ?? 0) - lgv.offsetPx
469
- ;({ reversed } = displayedRegion)
470
-
471
- if (cf._id === feature._id) {
472
- rowNum = row
473
- continue
474
- }
475
- for (const [, annotationFeature] of cf.children ??
476
- new Map()) {
477
- if (rowNum !== 0) {
478
- continue
479
- }
480
- if (annotationFeature._id === feature._id) {
481
- rowNum = row
482
- continue
483
- }
484
- }
485
- }
486
- }
487
- }
488
- }
474
+ const { glyph } = apolloHover
489
475
 
490
476
  // draw mouseover hovers
491
- glyph?.drawHover(self, ctx, rowNum, xOffset, reversed)
477
+ glyph.drawHover(self, ctx)
492
478
 
493
479
  // draw tooltip on hover
494
- glyph?.drawTooltip(self, ctx)
480
+ glyph.drawTooltip(self, ctx)
495
481
 
496
482
  // dragging previews
497
483
  if (apolloDragging) {
498
484
  // NOTE: the glyph where the drag started is responsible for drawing the preview.
499
485
  // it can call methods in other glyphs to help with this though.
500
-
501
- apolloDragging.start.glyph?.drawDragPreview(self, ctx)
486
+ const glyph = getGlyph(apolloDragging.feature.topLevelFeature)
487
+ glyph.drawDragPreview(self, ctx)
502
488
  }
503
489
  },
504
490
  { name: 'LinearApolloDisplayRenderMouseoverAndDrag' },
@@ -511,5 +497,8 @@ export function mouseEventsModelFactory(
511
497
  export type LinearApolloDisplayMouseEventsModel = ReturnType<
512
498
  typeof mouseEventsModelIntermediateFactory
513
499
  >
514
- export type LinearApolloDisplayMouseEvents =
515
- Instance<LinearApolloDisplayMouseEventsModel>
500
+ // eslint disable because of
501
+ // https://mobx-state-tree.js.org/tips/typescript#using-a-mst-type-at-design-time
502
+ // eslint-disable-next-line @typescript-eslint/no-empty-interface
503
+ export interface LinearApolloDisplayMouseEvents
504
+ extends Instance<LinearApolloDisplayMouseEventsModel> {}