@apollo-annotation/jbrowse-plugin-apollo 0.3.5 → 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 (136) hide show
  1. package/dist/index.esm.js +6964 -4598
  2. package/dist/index.esm.js.map +1 -1
  3. package/dist/jbrowse-plugin-apollo.cjs.development.js +6610 -4261
  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 +11563 -7493
  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 +23 -2
  13. package/src/ApolloInternetAccount/components/AuthTypeSelector.tsx +1 -0
  14. package/src/ApolloInternetAccount/components/LoginButtons.tsx +1 -1
  15. package/src/ApolloInternetAccount/components/LoginIcons.tsx +1 -1
  16. package/src/ApolloInternetAccount/configSchema.ts +1 -1
  17. package/src/ApolloInternetAccount/model.ts +11 -10
  18. package/src/ApolloJobModel.ts +1 -1
  19. package/src/ApolloRefNameAliasAdapter/ApolloRefNameAliasAdapter.ts +8 -6
  20. package/src/ApolloRefNameAliasAdapter/index.ts +2 -2
  21. package/src/ApolloSequenceAdapter/ApolloSequenceAdapter.ts +4 -4
  22. package/src/ApolloSequenceAdapter/index.ts +1 -1
  23. package/src/ApolloTextSearchAdapter/ApolloTextSearchAdapter.ts +8 -7
  24. package/src/ApolloTextSearchAdapter/index.ts +1 -1
  25. package/src/BackendDrivers/BackendDriver.ts +7 -7
  26. package/src/BackendDrivers/CollaborationServerDriver.ts +14 -10
  27. package/src/BackendDrivers/DesktopFileDriver.ts +11 -10
  28. package/src/BackendDrivers/InMemoryFileDriver.ts +10 -6
  29. package/src/ChangeManager.ts +15 -11
  30. package/src/FeatureDetailsWidget/ApolloFeatureDetailsWidget.tsx +8 -7
  31. package/src/FeatureDetailsWidget/ApolloTranscriptDetailsWidget.tsx +35 -14
  32. package/src/FeatureDetailsWidget/AttributeKey.tsx +50 -0
  33. package/src/FeatureDetailsWidget/AttributeKeySelector.tsx +104 -0
  34. package/src/FeatureDetailsWidget/Attributes.tsx +215 -367
  35. package/src/FeatureDetailsWidget/BasicInformation.tsx +6 -5
  36. package/src/FeatureDetailsWidget/DefaultAttributeEditor.tsx +104 -0
  37. package/src/FeatureDetailsWidget/DefaultAttributeViewer.tsx +22 -0
  38. package/src/FeatureDetailsWidget/FeatureDetailsNavigation.tsx +4 -4
  39. package/src/FeatureDetailsWidget/NumberTextField.tsx +1 -1
  40. package/src/FeatureDetailsWidget/Sequence.tsx +2 -2
  41. package/src/FeatureDetailsWidget/StringTextField.tsx +1 -1
  42. package/src/FeatureDetailsWidget/TranscriptSequence.tsx +15 -23
  43. package/src/FeatureDetailsWidget/TranscriptWidgetEditLocation.tsx +950 -196
  44. package/src/FeatureDetailsWidget/TranscriptWidgetSummary.tsx +8 -4
  45. package/src/FeatureDetailsWidget/model.ts +8 -3
  46. package/src/LinearApolloDisplay/components/LinearApolloDisplay.tsx +7 -7
  47. package/src/LinearApolloDisplay/glyphs/BoxGlyph.ts +59 -72
  48. package/src/LinearApolloDisplay/glyphs/GeneGlyph.ts +253 -60
  49. package/src/LinearApolloDisplay/glyphs/GenericChildGlyph.ts +52 -6
  50. package/src/LinearApolloDisplay/glyphs/Glyph.ts +16 -8
  51. package/src/LinearApolloDisplay/stateModel/base.ts +81 -10
  52. package/src/LinearApolloDisplay/stateModel/index.ts +4 -3
  53. package/src/LinearApolloDisplay/stateModel/layouts.ts +8 -39
  54. package/src/LinearApolloDisplay/stateModel/mouseEvents.ts +63 -46
  55. package/src/LinearApolloDisplay/stateModel/rendering.ts +60 -31
  56. package/src/LinearApolloSixFrameDisplay/components/LinearApolloSixFrameDisplay.tsx +226 -0
  57. package/src/LinearApolloSixFrameDisplay/components/TrackLines.tsx +32 -0
  58. package/src/LinearApolloSixFrameDisplay/components/index.ts +2 -0
  59. package/src/LinearApolloSixFrameDisplay/configSchema.ts +7 -0
  60. package/src/LinearApolloSixFrameDisplay/glyphs/GeneGlyph.ts +940 -0
  61. package/src/LinearApolloSixFrameDisplay/glyphs/Glyph.ts +63 -0
  62. package/src/LinearApolloSixFrameDisplay/glyphs/index.ts +1 -0
  63. package/src/LinearApolloSixFrameDisplay/index.ts +2 -0
  64. package/src/LinearApolloSixFrameDisplay/stateModel/base.ts +302 -0
  65. package/src/LinearApolloSixFrameDisplay/stateModel/index.ts +27 -0
  66. package/src/LinearApolloSixFrameDisplay/stateModel/layouts.ts +252 -0
  67. package/src/LinearApolloSixFrameDisplay/stateModel/mouseEvents.ts +368 -0
  68. package/src/LinearApolloSixFrameDisplay/stateModel/rendering.ts +201 -0
  69. package/src/LinearApolloSixFrameDisplay/types.ts +1 -0
  70. package/src/OntologyManager/OntologyStore/fulltext.test.ts +1 -1
  71. package/src/OntologyManager/OntologyStore/fulltext.ts +8 -3
  72. package/src/OntologyManager/OntologyStore/index.test.ts +3 -1
  73. package/src/OntologyManager/OntologyStore/index.ts +19 -14
  74. package/src/OntologyManager/OntologyStore/indexeddb-schema.ts +6 -5
  75. package/src/OntologyManager/OntologyStore/indexeddb-storage.ts +11 -5
  76. package/src/OntologyManager/index.ts +12 -7
  77. package/src/OntologyManager/util.ts +3 -2
  78. package/src/TabularEditor/HybridGrid/ChangeHandling.ts +2 -2
  79. package/src/TabularEditor/HybridGrid/Feature.tsx +13 -7
  80. package/src/TabularEditor/HybridGrid/FeatureAttributes.tsx +1 -1
  81. package/src/TabularEditor/HybridGrid/HybridGrid.tsx +3 -2
  82. package/src/TabularEditor/HybridGrid/ToolBar.tsx +1 -1
  83. package/src/TabularEditor/HybridGrid/featureContextMenuItems.ts +114 -22
  84. package/src/TabularEditor/TabularEditorPane.tsx +1 -1
  85. package/src/TabularEditor/model.ts +2 -2
  86. package/src/TabularEditor/types.ts +5 -2
  87. package/src/components/AddAssembly.tsx +182 -179
  88. package/src/components/AddAssemblyAliases.tsx +114 -0
  89. package/src/components/AddChildFeature.tsx +8 -10
  90. package/src/components/AddFeature.tsx +216 -44
  91. package/src/components/AddRefSeqAliases.tsx +14 -12
  92. package/src/components/CopyFeature.tsx +10 -11
  93. package/src/components/CreateApolloAnnotation.tsx +342 -158
  94. package/src/components/DeleteAssembly.tsx +9 -8
  95. package/src/components/DeleteFeature.tsx +362 -14
  96. package/src/components/Dialog.tsx +1 -1
  97. package/src/components/DownloadGFF3.tsx +31 -11
  98. package/src/components/FilterFeatures.tsx +6 -4
  99. package/src/components/FilterTranscripts.tsx +86 -0
  100. package/src/components/ImportFeatures.tsx +7 -6
  101. package/src/components/LogOut.tsx +5 -4
  102. package/src/components/ManageChecks.tsx +9 -8
  103. package/src/components/ManageUsers.tsx +11 -10
  104. package/src/components/MergeExons.tsx +193 -0
  105. package/src/components/MergeTranscripts.tsx +185 -0
  106. package/src/components/OntologyTermAutocomplete.tsx +5 -5
  107. package/src/components/OntologyTermMultiSelect.tsx +6 -6
  108. package/src/components/OpenLocalFile.tsx +4 -3
  109. package/src/components/SplitExon.tsx +134 -0
  110. package/src/components/ViewChangeLog.tsx +7 -6
  111. package/src/components/ViewCheckResults.tsx +8 -7
  112. package/src/components/index.ts +3 -0
  113. package/src/config.ts +5 -0
  114. package/src/extensions/annotationFromJBrowseFeature.test.ts +1 -0
  115. package/src/extensions/annotationFromJBrowseFeature.ts +13 -10
  116. package/src/extensions/annotationFromPileup.ts +104 -94
  117. package/src/index.ts +33 -50
  118. package/src/makeDisplayComponent.tsx +90 -37
  119. package/src/session/ClientDataStore.ts +21 -17
  120. package/src/session/session.ts +46 -39
  121. package/src/types.ts +4 -4
  122. package/src/util/annotationFeatureUtils.ts +66 -1
  123. package/src/util/copyToClipboard.ts +21 -0
  124. package/src/util/glyphUtils.ts +49 -0
  125. package/src/util/index.ts +5 -3
  126. package/src/util/loadAssemblyIntoClient.ts +10 -3
  127. package/src/util/mouseEventsUtils.ts +113 -0
  128. package/src/ApolloSixFrameRenderer/ApolloSixFrameRenderer.tsx +0 -13
  129. package/src/ApolloSixFrameRenderer/components/ApolloRendering.tsx +0 -707
  130. package/src/ApolloSixFrameRenderer/configSchema.ts +0 -7
  131. package/src/ApolloSixFrameRenderer/index.ts +0 -3
  132. package/src/SixFrameFeatureDisplay/components/TrackLines.tsx +0 -19
  133. package/src/SixFrameFeatureDisplay/components/index.ts +0 -1
  134. package/src/SixFrameFeatureDisplay/configSchema.ts +0 -21
  135. package/src/SixFrameFeatureDisplay/index.ts +0 -2
  136. package/src/SixFrameFeatureDisplay/stateModel.ts +0 -443
@@ -0,0 +1,368 @@
1
+ import {
2
+ type AnnotationFeature,
3
+ type TranscriptPartCoding,
4
+ } from '@apollo-annotation/mst'
5
+ import {
6
+ LocationEndChange,
7
+ LocationStartChange,
8
+ } from '@apollo-annotation/shared'
9
+ import type PluginManager from '@jbrowse/core/PluginManager'
10
+ import { type AnyConfigurationSchemaType } from '@jbrowse/core/configuration/configurationSchema'
11
+ import { type MenuItem } from '@jbrowse/core/ui'
12
+ import { type LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
13
+ import { autorun } from 'mobx'
14
+ import { type Instance, addDisposer, cast } from 'mobx-state-tree'
15
+ import { type CSSProperties } from 'react'
16
+
17
+ import { type Edge, getPropagatedLocationChanges } from '../../util'
18
+ import { type Coord } from '../components'
19
+ import { type Glyph } from '../glyphs/Glyph'
20
+ import { type CanvasMouseEvent } from '../types'
21
+
22
+ import { renderingModelFactory } from './rendering'
23
+
24
+ export interface FeatureAndGlyphUnderMouse {
25
+ cds: TranscriptPartCoding | null
26
+ feature: AnnotationFeature
27
+ topLevelFeature: AnnotationFeature
28
+ glyph: Glyph
29
+ }
30
+
31
+ /** extended information about the position of the mouse on the canvas, including the refName, bp, and displayedRegion number */
32
+ export interface MousePosition {
33
+ x: number
34
+ y: number
35
+ refName: string
36
+ bp: number
37
+ regionNumber: number
38
+ featureAndGlyphUnderMouse?: FeatureAndGlyphUnderMouse
39
+ }
40
+
41
+ export type MousePositionWithFeatureAndGlyph = Required<MousePosition>
42
+
43
+ export function isMousePositionWithFeatureAndGlyph(
44
+ mousePosition: MousePosition,
45
+ ): mousePosition is MousePositionWithFeatureAndGlyph {
46
+ return 'featureAndGlyphUnderMouse' in mousePosition
47
+ }
48
+
49
+ function getMousePosition(
50
+ event: CanvasMouseEvent,
51
+ lgv: LinearGenomeViewModel,
52
+ ): MousePosition {
53
+ const canvas = event.currentTarget
54
+ const { clientX, clientY } = event
55
+ const { left, top } = canvas.getBoundingClientRect()
56
+ const x = clientX - left
57
+ const y = clientY - top
58
+ const { coord: bp, index: regionNumber, refName } = lgv.pxToBp(x)
59
+ return { x, y, refName, bp, regionNumber }
60
+ }
61
+
62
+ export function mouseEventsModelIntermediateFactory(
63
+ pluginManager: PluginManager,
64
+ configSchema: AnyConfigurationSchemaType,
65
+ ) {
66
+ const LinearApolloSixFrameDisplayRendering = renderingModelFactory(
67
+ pluginManager,
68
+ configSchema,
69
+ )
70
+
71
+ return LinearApolloSixFrameDisplayRendering.named(
72
+ 'LinearApolloSixFrameDisplayMouseEvents',
73
+ )
74
+ .volatile(() => ({
75
+ apolloDragging: null as {
76
+ start: MousePosition
77
+ current: MousePosition
78
+ feature: AnnotationFeature
79
+ edge: Edge
80
+ shrinkParent: boolean
81
+ } | null,
82
+ cursor: undefined as CSSProperties['cursor'] | undefined,
83
+ apolloHover: undefined as FeatureAndGlyphUnderMouse | undefined,
84
+ }))
85
+ .views((self) => ({
86
+ getMousePosition(event: CanvasMouseEvent): MousePosition {
87
+ const mousePosition = getMousePosition(event, self.lgv)
88
+ const { bp, regionNumber, y } = mousePosition
89
+ const row = Math.floor(y / self.apolloRowHeight) + 1
90
+ const featureLayout = self.featureLayouts[regionNumber]
91
+ const layoutRow = featureLayout.get(row)
92
+ if (!layoutRow) {
93
+ return mousePosition
94
+ }
95
+ let foundFeature
96
+ if (self.geneTrackRowNums.includes(row)) {
97
+ foundFeature = layoutRow.find(
98
+ (f) =>
99
+ f.feature.type == 'exon' &&
100
+ bp >= f.feature.min &&
101
+ bp <= f.feature.max,
102
+ )
103
+ if (!foundFeature) {
104
+ foundFeature = layoutRow.find(
105
+ (f) => bp >= f.feature.min && bp <= f.feature.max,
106
+ )
107
+ }
108
+ } else {
109
+ foundFeature = layoutRow.find((f) => {
110
+ const featureID = f.feature.attributes.get('gff_id')?.toString()
111
+ return (
112
+ f.cds != null &&
113
+ bp >= f.cds.min &&
114
+ bp <= f.cds.max &&
115
+ (featureID === undefined ||
116
+ !self.filteredTranscripts.includes(featureID))
117
+ )
118
+ })
119
+ }
120
+ if (!foundFeature) {
121
+ return mousePosition
122
+ }
123
+ const { feature, cds } = foundFeature
124
+ const { topLevelFeature } = feature
125
+ const glyph = self.getGlyph(feature)
126
+ return {
127
+ ...mousePosition,
128
+ featureAndGlyphUnderMouse: { cds, feature, topLevelFeature, glyph },
129
+ }
130
+ },
131
+ }))
132
+ .actions((self) => ({
133
+ continueDrag(mousePosition: MousePosition, event: CanvasMouseEvent) {
134
+ if (!self.apolloDragging) {
135
+ throw new Error(
136
+ 'continueDrag() called with no current drag in progress',
137
+ )
138
+ }
139
+ event.stopPropagation()
140
+ self.apolloDragging = { ...self.apolloDragging, current: mousePosition }
141
+ },
142
+ setDragging(dragInfo?: typeof self.apolloDragging) {
143
+ self.apolloDragging = dragInfo ?? null
144
+ },
145
+ }))
146
+ .actions((self) => ({
147
+ setApolloHover(n?: (typeof self)['apolloHover']) {
148
+ self.apolloHover = n
149
+ },
150
+ setCursor(cursor?: CSSProperties['cursor']) {
151
+ if (self.cursor !== cursor) {
152
+ self.cursor = cursor
153
+ }
154
+ },
155
+ updateFilteredTranscripts(forms: string[]): void {
156
+ self.filteredTranscripts = cast(forms)
157
+ },
158
+ }))
159
+ .actions(() => ({
160
+ // onClick(event: CanvasMouseEvent) {
161
+ onClick() {
162
+ // TODO: set the selected feature
163
+ },
164
+ }))
165
+ }
166
+
167
+ export function mouseEventsModelFactory(
168
+ pluginManager: PluginManager,
169
+ configSchema: AnyConfigurationSchemaType,
170
+ ) {
171
+ const LinearApolloSixFrameDisplayMouseEvents =
172
+ mouseEventsModelIntermediateFactory(pluginManager, configSchema)
173
+
174
+ return LinearApolloSixFrameDisplayMouseEvents.views((self) => ({
175
+ contextMenuItems(contextCoord?: Coord): MenuItem[] {
176
+ const { apolloHover } = self
177
+ if (!(apolloHover && contextCoord)) {
178
+ return []
179
+ }
180
+ const { topLevelFeature } = apolloHover
181
+ const glyph = self.getGlyph(topLevelFeature)
182
+ return glyph.getContextMenuItems(self)
183
+ },
184
+ }))
185
+ .actions((self) => ({
186
+ // explicitly pass in a feature in case it's not the same as the one in
187
+ // mousePosition (e.g. if features are drawn overlapping).
188
+ startDrag(
189
+ mousePosition: MousePositionWithFeatureAndGlyph,
190
+ feature: AnnotationFeature,
191
+ edge: Edge,
192
+ shrinkParent = false,
193
+ ) {
194
+ self.apolloDragging = {
195
+ start: mousePosition,
196
+ current: mousePosition,
197
+ feature,
198
+ edge,
199
+ shrinkParent,
200
+ }
201
+ },
202
+ endDrag() {
203
+ if (!self.apolloDragging) {
204
+ throw new Error('endDrag() called with no current drag in progress')
205
+ }
206
+ const { current, edge, feature, start, shrinkParent } =
207
+ self.apolloDragging
208
+ // don't do anything if it was only dragged a tiny bit
209
+ if (Math.abs(current.x - start.x) <= 4) {
210
+ self.setDragging()
211
+ self.setCursor()
212
+ return
213
+ }
214
+ const { displayedRegions } = self.lgv
215
+ const region = displayedRegions[start.regionNumber]
216
+ const assembly = self.getAssemblyId(region.assemblyName)
217
+ const changes = getPropagatedLocationChanges(
218
+ feature,
219
+ current.bp,
220
+ edge,
221
+ shrinkParent,
222
+ )
223
+
224
+ const change: LocationEndChange | LocationStartChange =
225
+ edge === 'max'
226
+ ? new LocationEndChange({
227
+ typeName: 'LocationEndChange',
228
+ changedIds: changes.map((c) => c.featureId),
229
+ changes: changes.map((c) => ({
230
+ featureId: c.featureId,
231
+ oldEnd: c.oldLocation,
232
+ newEnd: c.newLocation,
233
+ })),
234
+ assembly,
235
+ })
236
+ : new LocationStartChange({
237
+ typeName: 'LocationStartChange',
238
+ changedIds: changes.map((c) => c.featureId),
239
+ changes: changes.map((c) => ({
240
+ featureId: c.featureId,
241
+ oldStart: c.oldLocation,
242
+ newStart: c.newLocation,
243
+ })),
244
+ assembly,
245
+ })
246
+ void self.changeManager.submit(change)
247
+ self.setDragging()
248
+ self.setCursor()
249
+ },
250
+ }))
251
+ .actions((self) => ({
252
+ onMouseDown(event: CanvasMouseEvent) {
253
+ const mousePosition = self.getMousePosition(event)
254
+ if (isMousePositionWithFeatureAndGlyph(mousePosition)) {
255
+ mousePosition.featureAndGlyphUnderMouse.glyph.onMouseDown(
256
+ self,
257
+ mousePosition,
258
+ event,
259
+ )
260
+ }
261
+ },
262
+ onMouseMove(event: CanvasMouseEvent) {
263
+ const mousePosition = self.getMousePosition(event)
264
+ if (self.apolloDragging) {
265
+ self.setCursor('col-resize')
266
+ self.continueDrag(mousePosition, event)
267
+ return
268
+ }
269
+ if (isMousePositionWithFeatureAndGlyph(mousePosition)) {
270
+ mousePosition.featureAndGlyphUnderMouse.glyph.onMouseMove(
271
+ self,
272
+ mousePosition,
273
+ event,
274
+ )
275
+ } else {
276
+ self.setApolloHover()
277
+ self.setCursor()
278
+ }
279
+ },
280
+ onMouseLeave(event: CanvasMouseEvent) {
281
+ self.setDragging()
282
+ self.setApolloHover()
283
+
284
+ const mousePosition = self.getMousePosition(event)
285
+ if (isMousePositionWithFeatureAndGlyph(mousePosition)) {
286
+ mousePosition.featureAndGlyphUnderMouse.glyph.onMouseLeave(
287
+ self,
288
+ mousePosition,
289
+ event,
290
+ )
291
+ }
292
+ },
293
+ onMouseUp(event: CanvasMouseEvent) {
294
+ const mousePosition = self.getMousePosition(event)
295
+ if (isMousePositionWithFeatureAndGlyph(mousePosition)) {
296
+ mousePosition.featureAndGlyphUnderMouse.glyph.onMouseUp(
297
+ self,
298
+ mousePosition,
299
+ event,
300
+ )
301
+ } else {
302
+ self.setSelectedFeature()
303
+ }
304
+
305
+ if (self.apolloDragging) {
306
+ self.endDrag()
307
+ }
308
+ },
309
+ }))
310
+ .actions((self) => ({
311
+ afterAttach() {
312
+ addDisposer(
313
+ self,
314
+ autorun(
315
+ () => {
316
+ // This type is wrong in @jbrowse/core
317
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
318
+ if (!self.lgv.initialized || self.regionCannotBeRendered()) {
319
+ return
320
+ }
321
+ const ctx = self.overlayCanvas?.getContext('2d')
322
+ if (!ctx) {
323
+ return
324
+ }
325
+ ctx.clearRect(
326
+ 0,
327
+ 0,
328
+ self.lgv.dynamicBlocks.totalWidthPx,
329
+ self.featuresHeight,
330
+ )
331
+
332
+ const { apolloDragging, apolloHover } = self
333
+ if (!apolloHover) {
334
+ return
335
+ }
336
+ const { glyph } = apolloHover
337
+
338
+ // draw mouseover hovers
339
+ glyph.drawHover(self, ctx)
340
+
341
+ // draw tooltip on hover
342
+ glyph.drawTooltip(self, ctx)
343
+
344
+ // dragging previews
345
+ if (apolloDragging) {
346
+ // NOTE: the glyph where the drag started is responsible for drawing the preview.
347
+ // it can call methods in other glyphs to help with this though.
348
+ const glyph = self.getGlyph(
349
+ apolloDragging.feature.topLevelFeature,
350
+ )
351
+ glyph.drawDragPreview(self, ctx)
352
+ }
353
+ },
354
+ { name: 'LinearApolloSixFrameDisplayRenderMouseoverAndDrag' },
355
+ ),
356
+ )
357
+ },
358
+ }))
359
+ }
360
+
361
+ export type LinearApolloSixFrameDisplayMouseEventsModel = ReturnType<
362
+ typeof mouseEventsModelIntermediateFactory
363
+ >
364
+ // eslint disable because of
365
+ // https://mobx-state-tree.js.org/tips/typescript#using-a-mst-type-at-design-time
366
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
367
+ export interface LinearApolloSixFrameDisplayMouseEvents
368
+ extends Instance<LinearApolloSixFrameDisplayMouseEventsModel> {}
@@ -0,0 +1,201 @@
1
+ /* eslint-disable @typescript-eslint/no-unnecessary-condition */
2
+ import type PluginManager from '@jbrowse/core/PluginManager'
3
+ import { type AnyConfigurationSchemaType } from '@jbrowse/core/configuration/configurationSchema'
4
+ import { doesIntersect2 } from '@jbrowse/core/util'
5
+ import { type Theme } from '@mui/material'
6
+ import { autorun } from 'mobx'
7
+ import { type Instance, addDisposer, types } from 'mobx-state-tree'
8
+
9
+ import { type ApolloSessionModel } from '../../session'
10
+
11
+ import { layoutsModelFactory } from './layouts'
12
+
13
+ export function renderingModelIntermediateFactory(
14
+ pluginManager: PluginManager,
15
+ configSchema: AnyConfigurationSchemaType,
16
+ ) {
17
+ const LinearApolloSixFrameDisplayLayouts = layoutsModelFactory(
18
+ pluginManager,
19
+ configSchema,
20
+ )
21
+
22
+ return LinearApolloSixFrameDisplayLayouts.named(
23
+ 'LinearApolloSixFrameDisplayRendering',
24
+ )
25
+ .props({
26
+ sequenceRowHeight: 15,
27
+ apolloRowHeight: 20,
28
+ detailsMinHeight: 200,
29
+ detailsHeight: 200,
30
+ lastRowTooltipBufferHeight: 80,
31
+ isShown: true,
32
+ filteredTranscripts: types.array(types.string),
33
+ })
34
+ .volatile(() => ({
35
+ canvas: null as HTMLCanvasElement | null,
36
+ overlayCanvas: null as HTMLCanvasElement | null,
37
+ collaboratorCanvas: null as HTMLCanvasElement | null,
38
+ theme: undefined as Theme | undefined,
39
+ }))
40
+ .views((self) => ({
41
+ get featuresHeight() {
42
+ const featureLabelSpacer = self.showFeatureLabels ? 2 : 1
43
+ return (
44
+ featureLabelSpacer * ((self.highestRow + 1) * self.apolloRowHeight) +
45
+ self.lastRowTooltipBufferHeight
46
+ )
47
+ },
48
+ }))
49
+ .actions((self) => ({
50
+ toggleShown() {
51
+ self.isShown = !self.isShown
52
+ },
53
+ setDetailsHeight(newHeight: number) {
54
+ self.detailsHeight = self.isShown
55
+ ? Math.max(
56
+ Math.min(newHeight, self.height - 100),
57
+ Math.min(self.height, self.detailsMinHeight),
58
+ )
59
+ : newHeight
60
+ },
61
+ setCanvas(canvas: HTMLCanvasElement | null) {
62
+ self.canvas = canvas
63
+ },
64
+ setOverlayCanvas(canvas: HTMLCanvasElement | null) {
65
+ self.overlayCanvas = canvas
66
+ },
67
+ setCollaboratorCanvas(canvas: HTMLCanvasElement | null) {
68
+ self.collaboratorCanvas = canvas
69
+ },
70
+ setTheme(theme: Theme) {
71
+ self.theme = theme
72
+ },
73
+ afterAttach() {
74
+ addDisposer(
75
+ self,
76
+ autorun(
77
+ () => {
78
+ if (!self.lgv.initialized || self.regionCannotBeRendered()) {
79
+ return
80
+ }
81
+ const ctx = self.collaboratorCanvas?.getContext('2d')
82
+ if (!ctx) {
83
+ return
84
+ }
85
+ ctx.clearRect(
86
+ 0,
87
+ 0,
88
+ self.lgv.dynamicBlocks.totalWidthPx,
89
+ self.featuresHeight,
90
+ )
91
+ for (const collaborator of (
92
+ self.session as unknown as ApolloSessionModel
93
+ ).collaborators) {
94
+ const { locations } = collaborator
95
+ if (locations.length === 0) {
96
+ continue
97
+ }
98
+ let idx = 0
99
+ for (const displayedRegion of self.lgv.displayedRegions) {
100
+ for (const location of locations) {
101
+ if (location.refSeq !== displayedRegion.refName) {
102
+ continue
103
+ }
104
+ const { end, refSeq, start } = location
105
+ const locationStartPxInfo = self.lgv.bpToPx({
106
+ refName: refSeq,
107
+ coord: start,
108
+ regionNumber: idx,
109
+ })
110
+ if (!locationStartPxInfo) {
111
+ continue
112
+ }
113
+ const locationStartPx =
114
+ locationStartPxInfo.offsetPx - self.lgv.offsetPx
115
+ const locationWidthPx = (end - start) / self.lgv.bpPerPx
116
+ ctx.fillStyle = 'rgba(0,255,0,.2)'
117
+ ctx.fillRect(locationStartPx, 1, locationWidthPx, 100)
118
+ ctx.fillStyle = 'black'
119
+ ctx.fillText(
120
+ collaborator.name,
121
+ locationStartPx + 1,
122
+ 11,
123
+ locationWidthPx - 2,
124
+ )
125
+ }
126
+ idx++
127
+ }
128
+ }
129
+ },
130
+ { name: 'LinearApolloSixFrameDisplayRenderCollaborators' },
131
+ ),
132
+ )
133
+ },
134
+ }))
135
+ }
136
+
137
+ export function renderingModelFactory(
138
+ pluginManager: PluginManager,
139
+ configSchema: AnyConfigurationSchemaType,
140
+ ) {
141
+ const LinearApolloSixFrameDisplayRendering =
142
+ renderingModelIntermediateFactory(pluginManager, configSchema)
143
+
144
+ return LinearApolloSixFrameDisplayRendering.actions((self) => ({
145
+ afterAttach() {
146
+ addDisposer(
147
+ self,
148
+ autorun(
149
+ () => {
150
+ const { canvas, featureLayouts, featuresHeight, lgv } = self
151
+ if (!lgv.initialized || self.regionCannotBeRendered()) {
152
+ return
153
+ }
154
+ const { displayedRegions, dynamicBlocks } = lgv
155
+
156
+ const ctx = canvas?.getContext('2d')
157
+ if (!ctx) {
158
+ return
159
+ }
160
+ ctx.clearRect(0, 0, dynamicBlocks.totalWidthPx, featuresHeight)
161
+ for (const [idx, featureLayout] of featureLayouts.entries()) {
162
+ const displayedRegion = displayedRegions[idx]
163
+ for (const [row, featureLayoutRow] of featureLayout.entries()) {
164
+ for (const { feature } of featureLayoutRow) {
165
+ if (!feature.looksLikeGene) {
166
+ continue
167
+ }
168
+ if (
169
+ !doesIntersect2(
170
+ displayedRegion.start,
171
+ displayedRegion.end,
172
+ feature.min,
173
+ feature.max,
174
+ )
175
+ ) {
176
+ continue
177
+ }
178
+ const { topLevelFeature } = feature
179
+ const glyph = self.getGlyph(topLevelFeature)
180
+ if (glyph !== undefined) {
181
+ glyph.draw(ctx, topLevelFeature, row, self, idx)
182
+ }
183
+ }
184
+ }
185
+ }
186
+ },
187
+ { name: 'LinearApolloSixFrameDisplayRenderFeatures' },
188
+ ),
189
+ )
190
+ },
191
+ }))
192
+ }
193
+
194
+ export type LinearApolloSixFrameDisplayRenderingModel = ReturnType<
195
+ typeof renderingModelIntermediateFactory
196
+ >
197
+ // eslint disable because of
198
+ // https://mobx-state-tree.js.org/tips/typescript#using-a-mst-type-at-design-time
199
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
200
+ export interface LinearApolloSixFrameDisplayRendering
201
+ extends Instance<LinearApolloSixFrameDisplayRenderingModel> {}
@@ -0,0 +1 @@
1
+ export type CanvasMouseEvent = React.MouseEvent<HTMLCanvasElement>
@@ -6,7 +6,7 @@ import {
6
6
  extractWords,
7
7
  getWords,
8
8
  } from './fulltext'
9
- import { OntologyDBNode } from './indexeddb-schema'
9
+ import { type OntologyDBNode } from './indexeddb-schema'
10
10
 
11
11
  const testNode: OntologyDBNode = {
12
12
  id: 'http://purl.obolibrary.org/obo/SO_0000001',
@@ -5,11 +5,16 @@
5
5
  import { checkAbortSignal } from '@jbrowse/core/util/aborting'
6
6
  import jsonpath from 'jsonpath'
7
7
 
8
+ import { type TextIndexFieldDefinition } from '..'
9
+
8
10
  import { stopwords } from './fulltext-stopwords'
9
- import { OntologyDBNode } from './indexeddb-schema'
11
+ import { type OntologyDBNode } from './indexeddb-schema'
10
12
  import { applyPrefixes } from './prefixes'
11
- import OntologyStore, { Transaction } from '.'
12
- import { TextIndexFieldDefinition } from '..'
13
+
14
+ // eslint-disable-next-line import/no-duplicates
15
+ import type OntologyStore from '.'
16
+ // eslint-disable-next-line import/no-duplicates
17
+ import { type Transaction } from '.'
13
18
 
14
19
  /** special value of jsonPath that gets the IRI (that is, ID) of the node with the configured prefixes applied */
15
20
  export const PREFIXED_ID_PATH = '$PREFIXED_ID'
@@ -4,8 +4,9 @@ import path from 'node:path'
4
4
 
5
5
  import { beforeAll, describe, expect, it, jest } from '@jest/globals'
6
6
 
7
+ import { type OntologyClass, isOntologyClass } from '..'
8
+
7
9
  import OntologyStore from '.'
8
- import { OntologyClass, isOntologyClass } from '..'
9
10
 
10
11
  jest.setTimeout(1_000_000_000)
11
12
 
@@ -19,6 +20,7 @@ const prefixes = new Map([
19
20
  // different "Object". This intercepts calls to "query" in this test and makes
20
21
  // sure the main scope "Object" is used.
21
22
  jest.mock('jsonpath', () => {
23
+ // eslint-disable-next-line @typescript-eslint/consistent-type-imports
22
24
  const original = jest.requireActual<typeof import('jsonpath')>('jsonpath')
23
25
  return {
24
26
  ...original,
@@ -2,34 +2,39 @@
2
2
 
3
3
  /* eslint-disable unicorn/no-await-expression-member */
4
4
  import {
5
- BlobLocation,
6
- LocalPathLocation,
7
- UriLocation,
5
+ type BlobLocation,
6
+ type LocalPathLocation,
7
+ type UriLocation,
8
8
  isLocalPathLocation,
9
9
  isUriLocation,
10
10
  } from '@jbrowse/core/util'
11
11
  import {
12
+ type IDBPTransaction,
13
+ type IndexNames,
14
+ type StoreNames,
12
15
  deleteDB,
13
- IDBPTransaction,
14
- IndexNames,
15
- StoreNames,
16
16
  } from 'idb/with-async-ittr'
17
17
 
18
+ import {
19
+ type OntologyClass,
20
+ type OntologyProperty,
21
+ type OntologyTerm,
22
+ isOntologyClass,
23
+ isOntologyProperty,
24
+ } from '..'
25
+
18
26
  import { textSearch } from './fulltext'
19
- import { OntologyDB, OntologyDBEdge, isDeprecated } from './indexeddb-schema'
27
+ import {
28
+ type OntologyDB,
29
+ type OntologyDBEdge,
30
+ isDeprecated,
31
+ } from './indexeddb-schema'
20
32
  import {
21
33
  getTextIndexFields,
22
34
  isDatabaseCurrent,
23
35
  loadOboGraphJson,
24
36
  openDatabase,
25
37
  } from './indexeddb-storage'
26
- import {
27
- OntologyClass,
28
- OntologyProperty,
29
- OntologyTerm,
30
- isOntologyClass,
31
- isOntologyProperty,
32
- } from '..'
33
38
 
34
39
  export type SourceLocation = UriLocation | LocalPathLocation | BlobLocation
35
40
 
@@ -1,12 +1,13 @@
1
1
  /** schema types used to strongly-type using the `idb` type system */
2
- import { DBSchema } from 'idb/with-async-ittr'
2
+ import { type DBSchema } from 'idb/with-async-ittr'
3
3
 
4
4
  import {
5
- Edge as OboGraphEdge,
6
- Meta as OboGraphMeta,
7
- Node as OboGraphNode,
5
+ type Edge as OboGraphEdge,
6
+ type Meta as OboGraphMeta,
7
+ type Node as OboGraphNode,
8
8
  } from './obo-graph-json-schema'
9
- import { OntologyStoreOptions, SourceLocation } from '.'
9
+
10
+ import { type OntologyStoreOptions, type SourceLocation } from '.'
10
11
 
11
12
  /** metadata about this IndexedDB ontology database */
12
13
  export interface Meta {