@apollo-annotation/jbrowse-plugin-apollo 0.3.6 → 0.3.7

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 (56) hide show
  1. package/dist/index.esm.js +2679 -850
  2. package/dist/index.esm.js.map +1 -1
  3. package/dist/jbrowse-plugin-apollo.cjs.development.js +2676 -847
  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 +5194 -1258
  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 +4 -4
  12. package/src/ApolloInternetAccount/addMenuItems.ts +18 -0
  13. package/src/ChangeManager.ts +10 -6
  14. package/src/FeatureDetailsWidget/Attributes.tsx +8 -3
  15. package/src/FeatureDetailsWidget/TranscriptSequence.tsx +12 -20
  16. package/src/FeatureDetailsWidget/TranscriptWidgetEditLocation.tsx +929 -175
  17. package/src/FeatureDetailsWidget/TranscriptWidgetSummary.tsx +4 -0
  18. package/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx +1 -1
  19. package/src/LinearApolloDisplay/glyphs/BoxGlyph.ts +48 -60
  20. package/src/LinearApolloDisplay/glyphs/GeneGlyph.ts +244 -51
  21. package/src/LinearApolloDisplay/glyphs/GenericChildGlyph.ts +46 -1
  22. package/src/LinearApolloDisplay/glyphs/Glyph.ts +9 -1
  23. package/src/LinearApolloDisplay/stateModel/base.ts +29 -0
  24. package/src/LinearApolloDisplay/stateModel/mouseEvents.ts +51 -35
  25. package/src/LinearApolloDisplay/stateModel/rendering.ts +2 -1
  26. package/src/LinearApolloSixFrameDisplay/components/LinearApolloSixFrameDisplay.tsx +7 -2
  27. package/src/LinearApolloSixFrameDisplay/components/TrackLines.tsx +12 -20
  28. package/src/LinearApolloSixFrameDisplay/glyphs/GeneGlyph.ts +243 -124
  29. package/src/LinearApolloSixFrameDisplay/stateModel/base.ts +42 -1
  30. package/src/LinearApolloSixFrameDisplay/stateModel/layouts.ts +19 -3
  31. package/src/LinearApolloSixFrameDisplay/stateModel/mouseEvents.ts +53 -34
  32. package/src/LinearApolloSixFrameDisplay/stateModel/rendering.ts +4 -2
  33. package/src/OntologyManager/index.ts +4 -1
  34. package/src/TabularEditor/HybridGrid/Feature.tsx +4 -0
  35. package/src/TabularEditor/HybridGrid/featureContextMenuItems.ts +108 -16
  36. package/src/components/AddAssemblyAliases.tsx +114 -0
  37. package/src/components/AddChildFeature.tsx +3 -6
  38. package/src/components/AddFeature.tsx +14 -15
  39. package/src/components/CopyFeature.tsx +2 -4
  40. package/src/components/CreateApolloAnnotation.tsx +334 -151
  41. package/src/components/DeleteFeature.tsx +358 -11
  42. package/src/components/DownloadGFF3.tsx +20 -1
  43. package/src/components/FilterTranscripts.tsx +86 -0
  44. package/src/components/MergeExons.tsx +193 -0
  45. package/src/components/MergeTranscripts.tsx +185 -0
  46. package/src/components/SplitExon.tsx +134 -0
  47. package/src/components/index.ts +3 -0
  48. package/src/config.ts +5 -0
  49. package/src/extensions/annotationFromJBrowseFeature.ts +2 -0
  50. package/src/extensions/annotationFromPileup.ts +99 -89
  51. package/src/session/session.ts +26 -13
  52. package/src/util/annotationFeatureUtils.ts +65 -0
  53. package/src/util/copyToClipboard.ts +21 -0
  54. package/src/util/glyphUtils.ts +49 -0
  55. package/src/util/index.ts +2 -0
  56. package/src/util/mouseEventsUtils.ts +113 -0
@@ -13,7 +13,7 @@ import { autorun } from 'mobx'
13
13
  import { type Instance, addDisposer } from 'mobx-state-tree'
14
14
  import { type CSSProperties } from 'react'
15
15
 
16
- import { type Coord } from '../components'
16
+ import { type Edge, getPropagatedLocationChanges } from '../../util'
17
17
  import { type Glyph } from '../glyphs/Glyph'
18
18
  import { type CanvasMouseEvent } from '../types'
19
19
 
@@ -44,7 +44,7 @@ export function isMousePositionWithFeatureAndGlyph(
44
44
  }
45
45
 
46
46
  function getMousePosition(
47
- event: CanvasMouseEvent,
47
+ event: React.MouseEvent,
48
48
  lgv: LinearGenomeViewModel,
49
49
  ): MousePosition {
50
50
  const canvas = event.currentTarget
@@ -125,13 +125,14 @@ export function mouseEventsModelIntermediateFactory(
125
125
  start: MousePosition
126
126
  current: MousePosition
127
127
  feature: AnnotationFeature
128
- edge: 'min' | 'max'
128
+ edge: Edge
129
+ shrinkParent: boolean
129
130
  } | null,
130
131
  cursor: undefined as CSSProperties['cursor'] | undefined,
131
132
  apolloHover: undefined as FeatureAndGlyphUnderMouse | undefined,
132
133
  }))
133
134
  .views((self) => ({
134
- getMousePosition(event: CanvasMouseEvent): MousePosition {
135
+ getMousePosition(event: React.MouseEvent): MousePosition {
135
136
  const mousePosition = getMousePosition(event, self.lgv)
136
137
  const { bp, regionNumber, y } = mousePosition
137
138
  const row = Math.floor(y / self.apolloRowHeight)
@@ -196,6 +197,10 @@ export function mouseEventsModelIntermediateFactory(
196
197
  self.cursor = cursor
197
198
  }
198
199
  },
200
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
201
+ updateFilteredTranscripts(forms: string[]) {
202
+ return
203
+ },
199
204
  }))
200
205
  .actions(() => ({
201
206
  // onClick(event: CanvasMouseEvent) {
@@ -340,14 +345,18 @@ export function mouseEventsModelFactory(
340
345
  )
341
346
 
342
347
  return LinearApolloDisplayMouseEvents.views((self) => ({
343
- contextMenuItems(contextCoord?: Coord): MenuItem[] {
348
+ contextMenuItems(event: React.MouseEvent<HTMLDivElement>): MenuItem[] {
344
349
  const { apolloHover } = self
345
- if (!(apolloHover && contextCoord)) {
350
+ if (!apolloHover) {
346
351
  return []
347
352
  }
353
+ const mousePosition = self.getMousePosition(event)
348
354
  const { topLevelFeature } = apolloHover
349
355
  const glyph = self.getGlyph(topLevelFeature)
350
- return glyph.getContextMenuItems(self)
356
+ if (isMousePositionWithFeatureAndGlyph(mousePosition)) {
357
+ return glyph.getContextMenuItems(self, mousePosition)
358
+ }
359
+ return []
351
360
  },
352
361
  }))
353
362
  .actions((self) => ({
@@ -356,20 +365,23 @@ export function mouseEventsModelFactory(
356
365
  startDrag(
357
366
  mousePosition: MousePositionWithFeatureAndGlyph,
358
367
  feature: AnnotationFeature,
359
- edge: 'min' | 'max',
368
+ edge: Edge,
369
+ shrinkParent = false,
360
370
  ) {
361
371
  self.apolloDragging = {
362
372
  start: mousePosition,
363
373
  current: mousePosition,
364
374
  feature,
365
375
  edge,
376
+ shrinkParent,
366
377
  }
367
378
  },
368
379
  endDrag() {
369
380
  if (!self.apolloDragging) {
370
381
  throw new Error('endDrag() called with no current drag in progress')
371
382
  }
372
- const { current, edge, feature, start } = self.apolloDragging
383
+ const { current, edge, feature, start, shrinkParent } =
384
+ self.apolloDragging
373
385
  // don't do anything if it was only dragged a tiny bit
374
386
  if (Math.abs(current.x - start.x) <= 4) {
375
387
  self.setDragging()
@@ -379,33 +391,35 @@ export function mouseEventsModelFactory(
379
391
  const { displayedRegions } = self.lgv
380
392
  const region = displayedRegions[start.regionNumber]
381
393
  const assembly = self.getAssemblyId(region.assemblyName)
394
+ const changes = getPropagatedLocationChanges(
395
+ feature,
396
+ current.bp,
397
+ edge,
398
+ shrinkParent,
399
+ )
382
400
 
383
- let change: LocationEndChange | LocationStartChange
384
- if (edge === 'max') {
385
- const featureId = feature._id
386
- const oldEnd = feature.max
387
- const newEnd = current.bp
388
- change = new LocationEndChange({
389
- typeName: 'LocationEndChange',
390
- changedIds: [featureId],
391
- featureId,
392
- oldEnd,
393
- newEnd,
394
- assembly,
395
- })
396
- } else {
397
- const featureId = feature._id
398
- const oldStart = feature.min
399
- const newStart = current.bp
400
- change = new LocationStartChange({
401
- typeName: 'LocationStartChange',
402
- changedIds: [featureId],
403
- featureId,
404
- oldStart,
405
- newStart,
406
- assembly,
407
- })
408
- }
401
+ const change: LocationEndChange | LocationStartChange =
402
+ edge === 'max'
403
+ ? new LocationEndChange({
404
+ typeName: 'LocationEndChange',
405
+ changedIds: changes.map((c) => c.featureId),
406
+ changes: changes.map((c) => ({
407
+ featureId: c.featureId,
408
+ oldEnd: c.oldLocation,
409
+ newEnd: c.newLocation,
410
+ })),
411
+ assembly,
412
+ })
413
+ : new LocationStartChange({
414
+ typeName: 'LocationStartChange',
415
+ changedIds: changes.map((c) => c.featureId),
416
+ changes: changes.map((c) => ({
417
+ featureId: c.featureId,
418
+ oldStart: c.oldLocation,
419
+ newStart: c.newLocation,
420
+ })),
421
+ assembly,
422
+ })
409
423
  void self.changeManager.submit(change)
410
424
  self.setDragging()
411
425
  self.setCursor()
@@ -461,6 +475,8 @@ export function mouseEventsModelFactory(
461
475
  mousePosition,
462
476
  event,
463
477
  )
478
+ } else {
479
+ self.setSelectedFeature()
464
480
  }
465
481
 
466
482
  if (self.apolloDragging) {
@@ -4,7 +4,7 @@ import { type AnyConfigurationSchemaType } from '@jbrowse/core/configuration/con
4
4
  import { defaultCodonTable, doesIntersect2, revcom } from '@jbrowse/core/util'
5
5
  import { type Theme } from '@mui/material'
6
6
  import { autorun } from 'mobx'
7
- import { type Instance, addDisposer } from 'mobx-state-tree'
7
+ import { type Instance, addDisposer, types } from 'mobx-state-tree'
8
8
 
9
9
  import { type ApolloSessionModel } from '../../session'
10
10
 
@@ -27,6 +27,7 @@ export function renderingModelIntermediateFactory(
27
27
  detailsHeight: 200,
28
28
  lastRowTooltipBufferHeight: 40,
29
29
  isShown: true,
30
+ filteredTranscripts: types.array(types.string),
30
31
  })
31
32
  .volatile(() => ({
32
33
  canvas: null as HTMLCanvasElement | null,
@@ -109,8 +109,13 @@ export const LinearApolloSixFrameDisplay = observer(
109
109
  // Promise.resolve() in these 3 callbacks is to avoid infinite rendering loop
110
110
  // https://github.com/mobxjs/mobx/issues/3728#issuecomment-1715400931
111
111
  <>
112
- <TrackLines model={model} strand={1} />
113
- <TrackLines model={model} strand={-1} />
112
+ <TrackLines model={model} idx={0} />
113
+ <TrackLines
114
+ model={model}
115
+ hrStyle={{ margin: 0, top: 0, color: 'grey', opacity: 0.4 }}
116
+ idx={1}
117
+ />
118
+ <TrackLines model={model} idx={2} />
114
119
  <canvas
115
120
  ref={async (node: HTMLCanvasElement) => {
116
121
  await Promise.resolve()
@@ -5,36 +5,28 @@ import { type LinearApolloSixFrameDisplay } from '../stateModel'
5
5
 
6
6
  export const TrackLines = observer(function TrackLines({
7
7
  model,
8
- strand,
8
+ hrStyle = { margin: 0, top: 0, color: 'black' },
9
+ idx = 0,
9
10
  }: {
10
11
  model: LinearApolloSixFrameDisplay
11
- strand: number
12
+ hrStyle?: React.CSSProperties
13
+ idx: number
12
14
  }) {
13
- const { apolloRowHeight, highestRow, lastRowTooltipBufferHeight } = model
14
- return strand == 1 ? (
15
- <div
16
- style={{
17
- position: 'absolute',
18
- left: 0,
19
- top: (apolloRowHeight * (highestRow + 1)) / 2 - 2,
20
- width: '100%',
21
- }}
22
- >
23
- <hr style={{ margin: 0, top: 0, color: 'black' }} />
24
- </div>
25
- ) : (
15
+ const { apolloRowHeight, highestRow, showFeatureLabels } = model
16
+ const featureLabelSpacer = showFeatureLabels ? 2 : 1
17
+
18
+ return (
26
19
  <div
27
20
  style={{
28
21
  position: 'absolute',
29
22
  left: 0,
30
- bottom:
31
- (apolloRowHeight * (highestRow + 1) + lastRowTooltipBufferHeight) /
32
- 2 +
33
- 3,
23
+ top:
24
+ (apolloRowHeight * featureLabelSpacer * (highestRow + 1)) / 2 +
25
+ idx * featureLabelSpacer * apolloRowHeight,
34
26
  width: '100%',
35
27
  }}
36
28
  >
37
- <hr style={{ margin: 0, top: 0, color: 'black' }} />
29
+ <hr style={hrStyle} />
38
30
  </div>
39
31
  )
40
32
  })