jbrowse-plugin-mafviewer 1.4.5 → 1.4.6

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 (169) hide show
  1. package/dist/BigMafAdapter/BigMafAdapter.js +4 -5
  2. package/dist/BigMafAdapter/BigMafAdapter.js.map +1 -1
  3. package/dist/BigMafAdapter/configSchema.d.ts +2 -2
  4. package/dist/LinearMafDisplay/components/LinearMafDisplayComponent.js +38 -108
  5. package/dist/LinearMafDisplay/components/LinearMafDisplayComponent.js.map +1 -1
  6. package/dist/LinearMafDisplay/components/MAFTooltip.d.ts +0 -3
  7. package/dist/LinearMafDisplay/components/MAFTooltip.js.map +1 -1
  8. package/dist/LinearMafDisplay/components/MsaHighlightOverlay.d.ts +9 -0
  9. package/dist/LinearMafDisplay/components/MsaHighlightOverlay.js +34 -0
  10. package/dist/LinearMafDisplay/components/MsaHighlightOverlay.js.map +1 -0
  11. package/dist/LinearMafDisplay/components/Sidebar/SvgWrapper.js +1 -1
  12. package/dist/LinearMafDisplay/components/Sidebar/SvgWrapper.js.map +1 -1
  13. package/dist/LinearMafDisplay/components/useDragSelection.d.ts +25 -0
  14. package/dist/LinearMafDisplay/components/useDragSelection.js +103 -0
  15. package/dist/LinearMafDisplay/components/useDragSelection.js.map +1 -0
  16. package/dist/LinearMafDisplay/configSchema.d.ts +3 -30
  17. package/dist/LinearMafDisplay/stateModel.d.ts +1043 -121
  18. package/dist/LinearMafDisplay/stateModel.js +85 -41
  19. package/dist/LinearMafDisplay/stateModel.js.map +1 -1
  20. package/dist/LinearMafDisplay/types.d.ts +2 -2
  21. package/dist/LinearMafDisplay/util.d.ts +5 -0
  22. package/dist/LinearMafDisplay/util.js +25 -4
  23. package/dist/LinearMafDisplay/util.js.map +1 -1
  24. package/dist/LinearMafRenderer/LinearMafRenderer.d.ts +41 -5
  25. package/dist/LinearMafRenderer/LinearMafRenderer.js +1 -1
  26. package/dist/LinearMafRenderer/LinearMafRenderer.js.map +1 -1
  27. package/dist/LinearMafRenderer/components/LinearMafRendering.d.ts +14 -5
  28. package/dist/LinearMafRenderer/components/LinearMafRendering.js +21 -19
  29. package/dist/LinearMafRenderer/components/LinearMafRendering.js.map +1 -1
  30. package/dist/LinearMafRenderer/configSchema.d.ts +1 -6
  31. package/dist/LinearMafRenderer/configSchema.js +1 -6
  32. package/dist/LinearMafRenderer/configSchema.js.map +1 -1
  33. package/dist/LinearMafRenderer/rendering/insertions.d.ts +1 -1
  34. package/dist/LinearMafRenderer/rendering/insertions.js +2 -2
  35. package/dist/LinearMafRenderer/rendering/mismatches.d.ts +1 -1
  36. package/dist/LinearMafRenderer/rendering/mismatches.js +3 -3
  37. package/dist/LinearMafRenderer/rendering/types.d.ts +1 -1
  38. package/dist/MafAddTrackWorkflow/AddTrackWorkflow.js +1 -1
  39. package/dist/MafAddTrackWorkflow/AddTrackWorkflow.js.map +1 -1
  40. package/dist/MafAddTrackWorkflow/index.js +1 -1
  41. package/dist/MafAddTrackWorkflow/index.js.map +1 -1
  42. package/dist/MafGetSequences/MafGetSequences.d.ts +1 -0
  43. package/dist/MafGetSequences/MafGetSequences.js +2 -1
  44. package/dist/MafGetSequences/MafGetSequences.js.map +1 -1
  45. package/dist/MafSequenceWidget/LabelsCanvas.d.ts +8 -0
  46. package/dist/MafSequenceWidget/LabelsCanvas.js +37 -0
  47. package/dist/MafSequenceWidget/LabelsCanvas.js.map +1 -0
  48. package/dist/MafSequenceWidget/MafSequenceHoverHighlight.d.ts +6 -0
  49. package/dist/MafSequenceWidget/MafSequenceHoverHighlight.js +52 -0
  50. package/dist/MafSequenceWidget/MafSequenceHoverHighlight.js.map +1 -0
  51. package/dist/MafSequenceWidget/MafSequenceHoverHighlightExtension.d.ts +2 -0
  52. package/dist/MafSequenceWidget/MafSequenceHoverHighlightExtension.js +12 -0
  53. package/dist/MafSequenceWidget/MafSequenceHoverHighlightExtension.js.map +1 -0
  54. package/dist/MafSequenceWidget/MafSequenceWidget.d.ts +6 -0
  55. package/dist/MafSequenceWidget/MafSequenceWidget.js +189 -0
  56. package/dist/MafSequenceWidget/MafSequenceWidget.js.map +1 -0
  57. package/dist/MafSequenceWidget/SequenceCanvas.d.ts +12 -0
  58. package/dist/MafSequenceWidget/SequenceCanvas.js +86 -0
  59. package/dist/MafSequenceWidget/SequenceCanvas.js.map +1 -0
  60. package/dist/MafSequenceWidget/SequenceDisplay.d.ts +12 -0
  61. package/dist/MafSequenceWidget/SequenceDisplay.js +117 -0
  62. package/dist/MafSequenceWidget/SequenceDisplay.js.map +1 -0
  63. package/dist/MafSequenceWidget/SequenceTooltip.d.ts +11 -0
  64. package/dist/MafSequenceWidget/SequenceTooltip.js +39 -0
  65. package/dist/MafSequenceWidget/SequenceTooltip.js.map +1 -0
  66. package/dist/MafSequenceWidget/baseColors.d.ts +3 -0
  67. package/dist/MafSequenceWidget/baseColors.js +64 -0
  68. package/dist/MafSequenceWidget/baseColors.js.map +1 -0
  69. package/dist/MafSequenceWidget/colToGenomePos.d.ts +13 -0
  70. package/dist/MafSequenceWidget/colToGenomePos.js +32 -0
  71. package/dist/MafSequenceWidget/colToGenomePos.js.map +1 -0
  72. package/dist/MafSequenceWidget/colToGenomePos.test.d.ts +1 -0
  73. package/dist/MafSequenceWidget/colToGenomePos.test.js +136 -0
  74. package/dist/MafSequenceWidget/colToGenomePos.test.js.map +1 -0
  75. package/dist/MafSequenceWidget/configSchema.d.ts +1 -0
  76. package/dist/MafSequenceWidget/configSchema.js +3 -0
  77. package/dist/MafSequenceWidget/configSchema.js.map +1 -0
  78. package/dist/MafSequenceWidget/constants.d.ts +4 -0
  79. package/dist/MafSequenceWidget/constants.js +5 -0
  80. package/dist/MafSequenceWidget/constants.js.map +1 -0
  81. package/dist/MafSequenceWidget/index.d.ts +2 -0
  82. package/dist/MafSequenceWidget/index.js +16 -0
  83. package/dist/MafSequenceWidget/index.js.map +1 -0
  84. package/dist/MafSequenceWidget/stateModelFactory.d.ts +67 -0
  85. package/dist/MafSequenceWidget/stateModelFactory.js +21 -0
  86. package/dist/MafSequenceWidget/stateModelFactory.js.map +1 -0
  87. package/dist/MafTabixAdapter/MafTabixAdapter.js +4 -35
  88. package/dist/MafTabixAdapter/MafTabixAdapter.js.map +1 -1
  89. package/dist/MafTabixAdapter/configSchema.d.ts +4 -4
  90. package/dist/MafTrack/configSchema.d.ts +16 -11
  91. package/dist/index.js +2 -0
  92. package/dist/index.js.map +1 -1
  93. package/dist/jbrowse-plugin-mafviewer.umd.production.min.js +12 -24
  94. package/dist/jbrowse-plugin-mafviewer.umd.production.min.js.map +4 -4
  95. package/dist/util/clipboard.d.ts +2 -0
  96. package/dist/util/clipboard.js +28 -0
  97. package/dist/util/clipboard.js.map +1 -0
  98. package/dist/util/fastaUtils.d.ts +2 -1
  99. package/dist/util/fastaUtils.js +72 -2
  100. package/dist/util/fastaUtils.js.map +1 -1
  101. package/dist/util/fastaUtils.test.js +190 -0
  102. package/dist/util/fastaUtils.test.js.map +1 -1
  103. package/dist/util/parseAssemblyName.d.ts +32 -0
  104. package/dist/util/parseAssemblyName.js +87 -0
  105. package/dist/util/parseAssemblyName.js.map +1 -0
  106. package/dist/util/parseAssemblyName.test.d.ts +1 -0
  107. package/dist/util/parseAssemblyName.test.js +269 -0
  108. package/dist/util/parseAssemblyName.test.js.map +1 -0
  109. package/package.json +7 -7
  110. package/src/BigMafAdapter/BigMafAdapter.ts +5 -5
  111. package/src/LinearMafDisplay/components/LinearMafDisplayComponent.tsx +62 -144
  112. package/src/LinearMafDisplay/components/MAFTooltip.tsx +0 -3
  113. package/src/LinearMafDisplay/components/MsaHighlightOverlay.tsx +62 -0
  114. package/src/LinearMafDisplay/components/Sidebar/SvgWrapper.tsx +1 -1
  115. package/src/LinearMafDisplay/components/useDragSelection.ts +159 -0
  116. package/src/LinearMafDisplay/stateModel.ts +135 -48
  117. package/src/LinearMafDisplay/types.ts +2 -2
  118. package/src/LinearMafDisplay/util.ts +31 -5
  119. package/src/LinearMafRenderer/LinearMafRenderer.ts +1 -1
  120. package/src/LinearMafRenderer/components/LinearMafRendering.tsx +38 -24
  121. package/src/LinearMafRenderer/configSchema.ts +1 -6
  122. package/src/LinearMafRenderer/rendering/insertions.ts +2 -2
  123. package/src/LinearMafRenderer/rendering/mismatches.ts +3 -3
  124. package/src/LinearMafRenderer/rendering/types.ts +1 -1
  125. package/src/MafAddTrackWorkflow/AddTrackWorkflow.tsx +1 -1
  126. package/src/MafAddTrackWorkflow/index.ts +1 -1
  127. package/src/MafGetSequences/MafGetSequences.ts +10 -2
  128. package/src/MafSequenceWidget/LabelsCanvas.tsx +58 -0
  129. package/src/MafSequenceWidget/MafSequenceHoverHighlight.tsx +83 -0
  130. package/src/MafSequenceWidget/MafSequenceHoverHighlightExtension.tsx +24 -0
  131. package/src/MafSequenceWidget/MafSequenceWidget.tsx +294 -0
  132. package/src/MafSequenceWidget/SequenceCanvas.tsx +136 -0
  133. package/src/MafSequenceWidget/SequenceDisplay.tsx +188 -0
  134. package/src/MafSequenceWidget/SequenceTooltip.tsx +70 -0
  135. package/src/MafSequenceWidget/baseColors.ts +76 -0
  136. package/src/MafSequenceWidget/colToGenomePos.test.ts +166 -0
  137. package/src/MafSequenceWidget/colToGenomePos.ts +40 -0
  138. package/src/MafSequenceWidget/configSchema.ts +3 -0
  139. package/src/MafSequenceWidget/constants.ts +4 -0
  140. package/src/MafSequenceWidget/index.ts +24 -0
  141. package/src/MafSequenceWidget/stateModelFactory.ts +43 -0
  142. package/src/MafTabixAdapter/MafTabixAdapter.ts +12 -51
  143. package/src/index.ts +2 -0
  144. package/src/util/__snapshots__/fastaUtils.test.ts.snap +35 -0
  145. package/src/util/clipboard.ts +35 -0
  146. package/src/util/fastaUtils.test.ts +199 -0
  147. package/src/util/fastaUtils.ts +94 -1
  148. package/src/util/parseAssemblyName.test.ts +350 -0
  149. package/src/util/parseAssemblyName.ts +106 -0
  150. package/dist/LinearMafDisplay/components/GetSequenceDialog/GetSequenceDialog.d.ts +0 -11
  151. package/dist/LinearMafDisplay/components/GetSequenceDialog/GetSequenceDialog.js +0 -97
  152. package/dist/LinearMafDisplay/components/GetSequenceDialog/GetSequenceDialog.js.map +0 -1
  153. package/dist/LinearMafDisplay/components/InsertionSequenceDialog/InsertionSequenceDialog.d.ts +0 -14
  154. package/dist/LinearMafDisplay/components/InsertionSequenceDialog/InsertionSequenceDialog.js +0 -69
  155. package/dist/LinearMafDisplay/components/InsertionSequenceDialog/InsertionSequenceDialog.js.map +0 -1
  156. package/dist/LinearMafDisplay/components/util.d.ts +0 -1
  157. package/dist/LinearMafDisplay/components/util.js +0 -8
  158. package/dist/LinearMafDisplay/components/util.js.map +0 -1
  159. package/dist/util/fetchSequences.d.ts +0 -18
  160. package/dist/util/fetchSequences.js +0 -39
  161. package/dist/util/fetchSequences.js.map +0 -1
  162. package/dist/util/useSequences.d.ts +0 -21
  163. package/dist/util/useSequences.js +0 -64
  164. package/dist/util/useSequences.js.map +0 -1
  165. package/src/LinearMafDisplay/components/GetSequenceDialog/GetSequenceDialog.tsx +0 -175
  166. package/src/LinearMafDisplay/components/InsertionSequenceDialog/InsertionSequenceDialog.tsx +0 -105
  167. package/src/LinearMafDisplay/components/util.ts +0 -7
  168. package/src/util/fetchSequences.ts +0 -57
  169. package/src/util/useSequences.ts +0 -90
@@ -4,47 +4,61 @@ import { PrerenderedCanvas } from '@jbrowse/core/ui'
4
4
  import Flatbush from 'flatbush'
5
5
  import { observer } from 'mobx-react'
6
6
 
7
- import { Sample } from '../../LinearMafDisplay/types'
8
- import { RenderedBase } from '../rendering'
7
+ import type { Sample } from '../../LinearMafDisplay/types'
8
+ import type { RenderedBase } from '../rendering'
9
9
 
10
- type SerializedRBush = any
10
+ interface DisplayModel {
11
+ setHoveredInfo?: (info: Record<string, unknown> | undefined) => void
12
+ setHighlightedRowNames?: (names: string[] | undefined) => void
13
+ showInsertionSequenceDialog?: (data: {
14
+ sequence: string
15
+ sampleLabel: string
16
+ chr: string
17
+ pos: number
18
+ }) => void
19
+ }
11
20
 
12
21
  const LinearMafRendering = observer(function (props: {
13
22
  width: number
14
23
  height: number
15
- displayModel: any
16
- flatbush: SerializedRBush
24
+ displayModel: DisplayModel
25
+ flatbush: ArrayBuffer
17
26
  items: RenderedBase[]
18
27
  samples: Sample[]
19
28
  }) {
20
29
  const { items, displayModel, height, samples, flatbush } = props
21
30
  const ref = useRef<HTMLDivElement>(null)
22
31
  const flatbush2 = useMemo(() => Flatbush.from(flatbush), [flatbush])
23
- const [isOverLargeInsertion, setIsOverLargeInsertion] = useState(false)
32
+ const [isOverInsertion, setIsOverInsertion] = useState(false)
24
33
 
25
34
  const getFeatureUnderMouse = useCallback(
26
35
  (eventClientX: number, eventClientY: number) => {
27
36
  let offsetX = 0
28
37
  let offsetY = 0
29
38
  if (ref.current) {
30
- const r = ref.current.getBoundingClientRect()
31
- offsetX = eventClientX - r.left
32
- offsetY = eventClientY - r.top
39
+ const rect = ref.current.getBoundingClientRect()
40
+ offsetX = eventClientX - rect.left
41
+ offsetY = eventClientY - rect.top
33
42
  }
34
43
 
35
- const x = flatbush2.search(offsetX, offsetY, offsetX + 1, offsetY + 1)
36
- if (x.length) {
37
- const elt = x.find(idx => items[idx]?.isInsertion)
38
- const r = elt !== undefined ? items[elt]! : items[x[0]!]!
39
- const s = samples[r.sampleId]
40
- return {
41
- ...r,
42
- sampleId: s?.id ?? 'unknown',
43
- sampleLabel: s?.label || s?.id || 'unknown',
44
- }
45
- } else {
44
+ const hits = flatbush2.search(offsetX, offsetY, offsetX + 1, offsetY + 1)
45
+ if (hits.length === 0) {
46
+ return undefined
47
+ }
48
+
49
+ const insertionHit = hits.find(idx => items[idx]?.isInsertion)
50
+ const hitIdx = insertionHit ?? hits[0]
51
+ const item = hitIdx !== undefined ? items[hitIdx] : undefined
52
+ if (!item) {
46
53
  return undefined
47
54
  }
55
+
56
+ const sample = samples[item.rowIndex]
57
+ return {
58
+ ...item,
59
+ sampleId: sample?.id ?? 'unknown',
60
+ sampleLabel: sample?.label || sample?.id || 'unknown',
61
+ }
48
62
  },
49
63
  [flatbush2, items, samples],
50
64
  )
@@ -54,7 +68,7 @@ const LinearMafRendering = observer(function (props: {
54
68
  ref={ref}
55
69
  onClick={e => {
56
70
  const feature = getFeatureUnderMouse(e.clientX, e.clientY)
57
- if (feature?.isLargeInsertion) {
71
+ if (feature?.isInsertion) {
58
72
  displayModel.showInsertionSequenceDialog?.({
59
73
  sequence: feature.base,
60
74
  sampleLabel: feature.sampleLabel,
@@ -69,18 +83,18 @@ const LinearMafRendering = observer(function (props: {
69
83
  displayModel.setHighlightedRowNames?.(
70
84
  feature?.sampleId ? [feature.sampleId] : undefined,
71
85
  )
72
- setIsOverLargeInsertion(!!feature?.isLargeInsertion)
86
+ setIsOverInsertion(!!feature?.isInsertion)
73
87
  }}
74
88
  onMouseLeave={() => {
75
89
  displayModel.setHoveredInfo?.(undefined)
76
90
  displayModel.setHighlightedRowNames?.(undefined)
77
- setIsOverLargeInsertion(false)
91
+ setIsOverInsertion(false)
78
92
  }}
79
93
  style={{
80
94
  overflow: 'visible',
81
95
  position: 'relative',
82
96
  height,
83
- cursor: isOverLargeInsertion ? 'pointer' : 'default',
97
+ cursor: isOverInsertion ? 'pointer' : 'default',
84
98
  }}
85
99
  >
86
100
  <PrerenderedCanvas
@@ -7,12 +7,7 @@ function x() {} // eslint-disable-line @typescript-eslint/no-unused-vars
7
7
 
8
8
  const configSchema = ConfigurationSchema(
9
9
  'LinearMafRenderer',
10
- {
11
- baseColor: {
12
- type: 'color',
13
- defaultValue: 'lightgrey',
14
- },
15
- },
10
+ {},
16
11
  {
17
12
  /**
18
13
  * #baseConfiguration
@@ -23,7 +23,7 @@ export function renderInsertions(
23
23
  leftPx: number,
24
24
  rowTop: number,
25
25
  bpPerPx: number,
26
- sampleId: number,
26
+ rowIndex: number,
27
27
  alignmentStart: number,
28
28
  chr: string,
29
29
  ) {
@@ -146,7 +146,7 @@ export function renderInsertions(
146
146
  pos: genomicOffset + alignmentStart,
147
147
  chr,
148
148
  base: insertionSequence,
149
- sampleId,
149
+ rowIndex,
150
150
  isInsertion: true,
151
151
  isLargeInsertion,
152
152
  },
@@ -21,7 +21,7 @@ export function renderMismatches(
21
21
  seq: string,
22
22
  leftPx: number,
23
23
  rowTop: number,
24
- sampleId: number,
24
+ rowIndex: number,
25
25
  alignmentStart: number,
26
26
  chr: string,
27
27
  ) {
@@ -70,7 +70,7 @@ export function renderMismatches(
70
70
  pos: genomicOffset + alignmentStart,
71
71
  chr,
72
72
  base: currentChar!,
73
- sampleId,
73
+ rowIndex,
74
74
  },
75
75
  )
76
76
  }
@@ -100,7 +100,7 @@ export function renderMismatches(
100
100
  pos: genomicOffset + alignmentStart,
101
101
  chr,
102
102
  base: currentChar!,
103
- sampleId,
103
+ rowIndex,
104
104
  },
105
105
  )
106
106
  }
@@ -25,7 +25,7 @@ export interface RenderedBase {
25
25
  pos: number
26
26
  chr: string
27
27
  base: string
28
- sampleId: number
28
+ rowIndex: number
29
29
  isInsertion?: boolean
30
30
  isLargeInsertion?: boolean
31
31
  }
@@ -7,6 +7,7 @@ import {
7
7
  isSessionModelWithWidgets,
8
8
  isSessionWithAddTracks,
9
9
  } from '@jbrowse/core/util'
10
+ import { getRoot } from '@jbrowse/mobx-state-tree'
10
11
  import {
11
12
  Button,
12
13
  FormControl,
@@ -17,7 +18,6 @@ import {
17
18
  RadioGroup,
18
19
  TextField,
19
20
  } from '@mui/material'
20
- import { getRoot } from 'mobx-state-tree'
21
21
  import { makeStyles } from 'tss-react/mui'
22
22
 
23
23
  import type { AddTrackModel } from '@jbrowse/plugin-data-management'
@@ -1,6 +1,6 @@
1
1
  import PluginManager from '@jbrowse/core/PluginManager'
2
2
  import { AddTrackWorkflowType } from '@jbrowse/core/pluggableElementTypes'
3
- import { types } from 'mobx-state-tree'
3
+ import { types } from '@jbrowse/mobx-state-tree'
4
4
 
5
5
  import MultiMAFWidget from './AddTrackWorkflow'
6
6
 
@@ -21,6 +21,7 @@ export default class MafGetSequences extends RpcMethodTypeWithFiltersAndRenameRe
21
21
  headers?: Record<string, string>
22
22
  regions: Region[]
23
23
  showAllLetters: boolean
24
+ includeInsertions?: boolean
24
25
  },
25
26
  rpcDriverClassName: string,
26
27
  ) {
@@ -28,8 +29,14 @@ export default class MafGetSequences extends RpcMethodTypeWithFiltersAndRenameRe
28
29
  args,
29
30
  rpcDriverClassName,
30
31
  )
31
- const { samples, regions, adapterConfig, sessionId, showAllLetters } =
32
- deserializedArgs
32
+ const {
33
+ samples,
34
+ regions,
35
+ adapterConfig,
36
+ sessionId,
37
+ showAllLetters,
38
+ includeInsertions,
39
+ } = deserializedArgs
33
40
  const dataAdapter = (
34
41
  await getAdapter(this.pluginManager, sessionId, adapterConfig)
35
42
  ).dataAdapter as BaseFeatureDataAdapter
@@ -42,6 +49,7 @@ export default class MafGetSequences extends RpcMethodTypeWithFiltersAndRenameRe
42
49
  samples,
43
50
  regions,
44
51
  showAllLetters,
52
+ includeInsertions,
45
53
  })
46
54
  }
47
55
  }
@@ -0,0 +1,58 @@
1
+ import React, { useEffect, useRef } from 'react'
2
+
3
+ import { useTheme } from '@mui/material'
4
+
5
+ import { CHAR_WIDTH, FONT, LABEL_PADDING, ROW_HEIGHT } from './constants'
6
+
7
+ import type { Sample } from '../LinearMafDisplay/types'
8
+
9
+ interface LabelsCanvasProps {
10
+ samples: Sample[]
11
+ maxLabelLength: number
12
+ }
13
+
14
+ export default function LabelsCanvas({
15
+ samples,
16
+ maxLabelLength,
17
+ }: LabelsCanvasProps) {
18
+ const theme = useTheme()
19
+ const canvasRef = useRef<HTMLCanvasElement>(null)
20
+
21
+ const labelWidth = maxLabelLength * CHAR_WIDTH + LABEL_PADDING
22
+ const canvasHeight = samples.length * ROW_HEIGHT
23
+
24
+ useEffect(() => {
25
+ const canvas = canvasRef.current
26
+ if (!canvas) {
27
+ return
28
+ }
29
+
30
+ const ctx = canvas.getContext('2d')
31
+ if (!ctx) {
32
+ return
33
+ }
34
+
35
+ const dpr = window.devicePixelRatio || 1
36
+ canvas.width = labelWidth * dpr
37
+ canvas.height = canvasHeight * dpr
38
+ canvas.style.width = `${labelWidth}px`
39
+ canvas.style.height = `${canvasHeight}px`
40
+ ctx.scale(dpr, dpr)
41
+
42
+ ctx.fillStyle = theme.palette.background.paper
43
+ ctx.fillRect(0, 0, labelWidth, canvasHeight)
44
+
45
+ ctx.font = FONT
46
+ ctx.textBaseline = 'top'
47
+
48
+ for (let rowIdx = 0; rowIdx < samples.length; rowIdx++) {
49
+ const sample = samples[rowIdx]!
50
+ const y = rowIdx * ROW_HEIGHT
51
+
52
+ ctx.fillStyle = theme.palette.text.secondary
53
+ ctx.fillText(sample.label ?? sample.id, 2, y + 2)
54
+ }
55
+ }, [samples, labelWidth, canvasHeight, theme])
56
+
57
+ return <canvas ref={canvasRef} style={{ display: 'block' }} />
58
+ }
@@ -0,0 +1,83 @@
1
+ import React from 'react'
2
+
3
+ import { getSession } from '@jbrowse/core/util'
4
+ import { colord } from '@jbrowse/core/util/colord'
5
+ import { observer } from 'mobx-react'
6
+ import { makeStyles } from 'tss-react/mui'
7
+
8
+ import type { MafSequenceWidgetModel } from './stateModelFactory'
9
+ import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
10
+
11
+ const useStyles = makeStyles()(theme => ({
12
+ highlight: {
13
+ height: '100%',
14
+ position: 'absolute',
15
+ background: colord(theme.palette.primary.main).alpha(0.4).toRgbString(),
16
+ borderLeft: `2px solid ${theme.palette.primary.main}`,
17
+ borderRight: `2px solid ${theme.palette.primary.main}`,
18
+ pointerEvents: 'none',
19
+ zIndex: 10,
20
+ },
21
+ }))
22
+
23
+ const MafSequenceHoverHighlight = observer(function MafSequenceHoverHighlight({
24
+ model,
25
+ }: {
26
+ model: LinearGenomeViewModel
27
+ }) {
28
+ const { classes } = useStyles()
29
+ const session = getSession(model)
30
+ const { assemblyManager } = session
31
+
32
+ // Find MafSequenceWidget instances that are connected to this view
33
+ const widgets =
34
+ 'widgets' in session ? (session.widgets as Map<string, unknown>) : undefined
35
+ if (!widgets) {
36
+ return null
37
+ }
38
+
39
+ const highlights: React.ReactNode[] = []
40
+
41
+ for (const [, widget] of widgets) {
42
+ const w = widget as {
43
+ type?: string
44
+ connectedViewId?: string
45
+ hoverHighlight?: unknown
46
+ }
47
+ if (w.type === 'MafSequenceWidget' && w.connectedViewId === model.id) {
48
+ const mafWidget = widget as MafSequenceWidgetModel
49
+ const { hoverHighlight } = mafWidget
50
+
51
+ if (hoverHighlight) {
52
+ const { refName, start, end, assemblyName } = hoverHighlight
53
+ const assembly = assemblyManager.get(assemblyName)
54
+ const canonicalRefName =
55
+ assembly?.getCanonicalRefName(refName) ?? refName
56
+
57
+ const startPx = model.bpToPx({
58
+ refName: canonicalRefName,
59
+ coord: start,
60
+ })
61
+ const endPx = model.bpToPx({ refName: canonicalRefName, coord: end })
62
+
63
+ if (startPx && endPx) {
64
+ const left =
65
+ Math.min(startPx.offsetPx, endPx.offsetPx) - model.offsetPx
66
+ const width = Math.max(Math.abs(endPx.offsetPx - startPx.offsetPx), 3)
67
+
68
+ highlights.push(
69
+ <div
70
+ key={`maf-hover-${mafWidget.id}`}
71
+ className={classes.highlight}
72
+ style={{ left, width }}
73
+ />,
74
+ )
75
+ }
76
+ }
77
+ }
78
+ }
79
+
80
+ return <>{highlights}</>
81
+ })
82
+
83
+ export default MafSequenceHoverHighlight
@@ -0,0 +1,24 @@
1
+ import React from 'react'
2
+
3
+ import MafSequenceHoverHighlight from './MafSequenceHoverHighlight'
4
+
5
+ import type PluginManager from '@jbrowse/core/PluginManager'
6
+ import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
7
+
8
+ export default function MafSequenceHoverHighlightExtensionF(
9
+ pluginManager: PluginManager,
10
+ ) {
11
+ pluginManager.addToExtensionPoint(
12
+ 'LinearGenomeView-TracksContainerComponent',
13
+ (rest: React.ReactNode[], props: Record<string, unknown>) => {
14
+ const model = props.model as LinearGenomeViewModel
15
+ return [
16
+ ...rest,
17
+ <MafSequenceHoverHighlight
18
+ key="maf-sequence-hover-highlight"
19
+ model={model}
20
+ />,
21
+ ]
22
+ },
23
+ )
24
+ }