@jbrowse/plugin-linear-genome-view 2.3.3 → 2.4.0

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 (198) hide show
  1. package/dist/BaseLinearDisplay/components/Block.js +1 -1
  2. package/dist/BaseLinearDisplay/components/Block.js.map +1 -1
  3. package/dist/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js +11 -11
  4. package/dist/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js.map +1 -1
  5. package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +74 -4
  6. package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.js +41 -22
  7. package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.js.map +1 -1
  8. package/dist/BaseLinearDisplay/models/configSchema.js +8 -0
  9. package/dist/BaseLinearDisplay/models/configSchema.js.map +1 -1
  10. package/dist/BaseLinearDisplay/models/serverSideRenderedBlock.d.ts +1 -1
  11. package/dist/BaseLinearDisplay/models/serverSideRenderedBlock.js +5 -0
  12. package/dist/BaseLinearDisplay/models/serverSideRenderedBlock.js.map +1 -1
  13. package/dist/LinearBareDisplay/model.d.ts +62 -4
  14. package/dist/LinearBasicDisplay/model.d.ts +72 -14
  15. package/dist/LinearGenomeView/components/CenterLine.js +2 -2
  16. package/dist/LinearGenomeView/components/CenterLine.js.map +1 -1
  17. package/dist/LinearGenomeView/components/Cytobands.d.ts +118 -0
  18. package/dist/LinearGenomeView/components/Cytobands.js +92 -0
  19. package/dist/LinearGenomeView/components/Cytobands.js.map +1 -0
  20. package/dist/LinearGenomeView/components/ExportSvgDialog.d.ts +1 -1
  21. package/dist/LinearGenomeView/components/ExportSvgDialog.js +24 -3
  22. package/dist/LinearGenomeView/components/ExportSvgDialog.js.map +1 -1
  23. package/dist/LinearGenomeView/components/GetSequenceDialog.js +4 -1
  24. package/dist/LinearGenomeView/components/GetSequenceDialog.js.map +1 -1
  25. package/dist/LinearGenomeView/components/Gridlines.js +1 -1
  26. package/dist/LinearGenomeView/components/Gridlines.js.map +1 -1
  27. package/dist/LinearGenomeView/components/Header.js +3 -4
  28. package/dist/LinearGenomeView/components/Header.js.map +1 -1
  29. package/dist/LinearGenomeView/components/LinearGenomeView.js +1 -1
  30. package/dist/LinearGenomeView/components/MiniControls.js +5 -4
  31. package/dist/LinearGenomeView/components/MiniControls.js.map +1 -1
  32. package/dist/LinearGenomeView/components/OverviewScalebar.d.ts +1 -115
  33. package/dist/LinearGenomeView/components/OverviewScalebar.js +15 -99
  34. package/dist/LinearGenomeView/components/OverviewScalebar.js.map +1 -1
  35. package/dist/LinearGenomeView/components/RubberbandSpan.js +2 -2
  36. package/dist/LinearGenomeView/components/RubberbandSpan.js.map +1 -1
  37. package/dist/LinearGenomeView/components/TrackLabel.js +6 -5
  38. package/dist/LinearGenomeView/components/TrackLabel.js.map +1 -1
  39. package/dist/LinearGenomeView/components/ZoomControls.js +5 -4
  40. package/dist/LinearGenomeView/components/ZoomControls.js.map +1 -1
  41. package/dist/LinearGenomeView/components/util.d.ts +6 -0
  42. package/dist/LinearGenomeView/components/util.js +11 -1
  43. package/dist/LinearGenomeView/components/util.js.map +1 -1
  44. package/dist/LinearGenomeView/model.d.ts +10 -2
  45. package/dist/LinearGenomeView/model.js +6 -6
  46. package/dist/LinearGenomeView/model.js.map +1 -1
  47. package/dist/LinearGenomeView/svgcomponents/SVGBackground.d.ts +6 -0
  48. package/dist/LinearGenomeView/svgcomponents/SVGBackground.js +13 -0
  49. package/dist/LinearGenomeView/svgcomponents/SVGBackground.js.map +1 -0
  50. package/dist/LinearGenomeView/svgcomponents/SVGHeader.d.ts +10 -0
  51. package/dist/LinearGenomeView/svgcomponents/SVGHeader.js +55 -0
  52. package/dist/LinearGenomeView/svgcomponents/SVGHeader.js.map +1 -0
  53. package/dist/LinearGenomeView/svgcomponents/SVGLinearGenomeView.d.ts +13 -0
  54. package/dist/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js +56 -0
  55. package/dist/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js.map +1 -0
  56. package/dist/LinearGenomeView/svgcomponents/SVGRegionSeparators.d.ts +8 -0
  57. package/dist/LinearGenomeView/svgcomponents/SVGRegionSeparators.js +13 -0
  58. package/dist/LinearGenomeView/svgcomponents/SVGRegionSeparators.js.map +1 -0
  59. package/dist/LinearGenomeView/svgcomponents/SVGRuler.d.ts +8 -0
  60. package/dist/LinearGenomeView/svgcomponents/SVGRuler.js +51 -0
  61. package/dist/LinearGenomeView/svgcomponents/SVGRuler.js.map +1 -0
  62. package/dist/LinearGenomeView/svgcomponents/SVGScalebar.d.ts +8 -0
  63. package/dist/LinearGenomeView/svgcomponents/SVGScalebar.js +22 -0
  64. package/dist/LinearGenomeView/svgcomponents/SVGScalebar.js.map +1 -0
  65. package/dist/LinearGenomeView/svgcomponents/SVGTrackLabel.d.ts +8 -0
  66. package/dist/LinearGenomeView/svgcomponents/SVGTrackLabel.js +15 -0
  67. package/dist/LinearGenomeView/svgcomponents/SVGTrackLabel.js.map +1 -0
  68. package/dist/LinearGenomeView/svgcomponents/SVGTracks.d.ts +23 -0
  69. package/dist/LinearGenomeView/svgcomponents/SVGTracks.js +30 -0
  70. package/dist/LinearGenomeView/svgcomponents/SVGTracks.js.map +1 -0
  71. package/dist/LinearGenomeView/util.js +1 -1
  72. package/dist/LinearGenomeView/util.js.map +1 -1
  73. package/dist/index.d.ts +133 -18
  74. package/dist/index.js +6 -2
  75. package/dist/index.js.map +1 -1
  76. package/esm/BaseLinearDisplay/components/Block.js +1 -1
  77. package/esm/BaseLinearDisplay/components/Block.js.map +1 -1
  78. package/esm/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js +11 -11
  79. package/esm/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js.map +1 -1
  80. package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +74 -4
  81. package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.js +42 -23
  82. package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.js.map +1 -1
  83. package/esm/BaseLinearDisplay/models/configSchema.js +8 -0
  84. package/esm/BaseLinearDisplay/models/configSchema.js.map +1 -1
  85. package/esm/BaseLinearDisplay/models/serverSideRenderedBlock.d.ts +1 -1
  86. package/esm/BaseLinearDisplay/models/serverSideRenderedBlock.js +5 -0
  87. package/esm/BaseLinearDisplay/models/serverSideRenderedBlock.js.map +1 -1
  88. package/esm/LinearBareDisplay/model.d.ts +62 -4
  89. package/esm/LinearBasicDisplay/model.d.ts +72 -14
  90. package/esm/LinearGenomeView/components/CenterLine.js +2 -2
  91. package/esm/LinearGenomeView/components/CenterLine.js.map +1 -1
  92. package/esm/LinearGenomeView/components/Cytobands.d.ts +118 -0
  93. package/esm/LinearGenomeView/components/Cytobands.js +87 -0
  94. package/esm/LinearGenomeView/components/Cytobands.js.map +1 -0
  95. package/esm/LinearGenomeView/components/ExportSvgDialog.d.ts +1 -1
  96. package/esm/LinearGenomeView/components/ExportSvgDialog.js +25 -4
  97. package/esm/LinearGenomeView/components/ExportSvgDialog.js.map +1 -1
  98. package/esm/LinearGenomeView/components/GetSequenceDialog.js +4 -1
  99. package/esm/LinearGenomeView/components/GetSequenceDialog.js.map +1 -1
  100. package/esm/LinearGenomeView/components/Gridlines.js +1 -1
  101. package/esm/LinearGenomeView/components/Gridlines.js.map +1 -1
  102. package/esm/LinearGenomeView/components/Header.js +5 -6
  103. package/esm/LinearGenomeView/components/Header.js.map +1 -1
  104. package/esm/LinearGenomeView/components/LinearGenomeView.js +1 -1
  105. package/esm/LinearGenomeView/components/MiniControls.js +5 -4
  106. package/esm/LinearGenomeView/components/MiniControls.js.map +1 -1
  107. package/esm/LinearGenomeView/components/OverviewScalebar.d.ts +1 -115
  108. package/esm/LinearGenomeView/components/OverviewScalebar.js +12 -96
  109. package/esm/LinearGenomeView/components/OverviewScalebar.js.map +1 -1
  110. package/esm/LinearGenomeView/components/RubberbandSpan.js +2 -2
  111. package/esm/LinearGenomeView/components/RubberbandSpan.js.map +1 -1
  112. package/esm/LinearGenomeView/components/TrackLabel.js +6 -5
  113. package/esm/LinearGenomeView/components/TrackLabel.js.map +1 -1
  114. package/esm/LinearGenomeView/components/ZoomControls.js +5 -4
  115. package/esm/LinearGenomeView/components/ZoomControls.js.map +1 -1
  116. package/esm/LinearGenomeView/components/util.d.ts +6 -0
  117. package/esm/LinearGenomeView/components/util.js +9 -0
  118. package/esm/LinearGenomeView/components/util.js.map +1 -1
  119. package/esm/LinearGenomeView/model.d.ts +10 -2
  120. package/esm/LinearGenomeView/model.js +4 -4
  121. package/esm/LinearGenomeView/model.js.map +1 -1
  122. package/esm/LinearGenomeView/svgcomponents/SVGBackground.d.ts +6 -0
  123. package/esm/LinearGenomeView/svgcomponents/SVGBackground.js +7 -0
  124. package/esm/LinearGenomeView/svgcomponents/SVGBackground.js.map +1 -0
  125. package/esm/LinearGenomeView/svgcomponents/SVGHeader.d.ts +10 -0
  126. package/esm/LinearGenomeView/svgcomponents/SVGHeader.js +49 -0
  127. package/esm/LinearGenomeView/svgcomponents/SVGHeader.js.map +1 -0
  128. package/esm/LinearGenomeView/svgcomponents/SVGLinearGenomeView.d.ts +13 -0
  129. package/esm/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js +47 -0
  130. package/esm/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js.map +1 -0
  131. package/esm/LinearGenomeView/svgcomponents/SVGRegionSeparators.d.ts +8 -0
  132. package/esm/LinearGenomeView/svgcomponents/SVGRegionSeparators.js +7 -0
  133. package/esm/LinearGenomeView/svgcomponents/SVGRegionSeparators.js.map +1 -0
  134. package/esm/LinearGenomeView/svgcomponents/SVGRuler.d.ts +8 -0
  135. package/esm/LinearGenomeView/svgcomponents/SVGRuler.js +45 -0
  136. package/esm/LinearGenomeView/svgcomponents/SVGRuler.js.map +1 -0
  137. package/esm/LinearGenomeView/svgcomponents/SVGScalebar.d.ts +8 -0
  138. package/esm/LinearGenomeView/svgcomponents/SVGScalebar.js +16 -0
  139. package/esm/LinearGenomeView/svgcomponents/SVGScalebar.js.map +1 -0
  140. package/esm/LinearGenomeView/svgcomponents/SVGTrackLabel.d.ts +8 -0
  141. package/esm/LinearGenomeView/svgcomponents/SVGTrackLabel.js +9 -0
  142. package/esm/LinearGenomeView/svgcomponents/SVGTrackLabel.js.map +1 -0
  143. package/esm/LinearGenomeView/svgcomponents/SVGTracks.d.ts +23 -0
  144. package/esm/LinearGenomeView/svgcomponents/SVGTracks.js +24 -0
  145. package/esm/LinearGenomeView/svgcomponents/SVGTracks.js.map +1 -0
  146. package/esm/LinearGenomeView/util.js +1 -1
  147. package/esm/LinearGenomeView/util.js.map +1 -1
  148. package/esm/index.d.ts +133 -18
  149. package/esm/index.js +3 -2
  150. package/esm/index.js.map +1 -1
  151. package/package.json +3 -3
  152. package/src/BaseLinearDisplay/components/Block.tsx +1 -1
  153. package/src/BaseLinearDisplay/components/ServerSideRenderedBlockContent.tsx +11 -12
  154. package/src/BaseLinearDisplay/models/BaseLinearDisplayModel.tsx +53 -35
  155. package/src/BaseLinearDisplay/models/configSchema.ts +8 -0
  156. package/src/BaseLinearDisplay/models/serverSideRenderedBlock.ts +9 -17
  157. package/src/LinearGenomeView/components/CenterLine.tsx +2 -2
  158. package/src/LinearGenomeView/components/Cytobands.tsx +154 -0
  159. package/src/LinearGenomeView/components/ExportSvgDialog.tsx +56 -4
  160. package/src/LinearGenomeView/components/GetSequenceDialog.tsx +5 -1
  161. package/src/LinearGenomeView/components/Gridlines.tsx +1 -1
  162. package/src/LinearGenomeView/components/Header.tsx +6 -13
  163. package/src/LinearGenomeView/components/LinearGenomeView.test.tsx +8 -11
  164. package/src/LinearGenomeView/components/LinearGenomeView.tsx +1 -1
  165. package/src/LinearGenomeView/components/MiniControls.tsx +6 -7
  166. package/src/LinearGenomeView/components/OverviewScalebar.tsx +218 -381
  167. package/src/LinearGenomeView/components/RubberbandSpan.tsx +2 -2
  168. package/src/LinearGenomeView/components/TrackLabel.tsx +3 -5
  169. package/src/LinearGenomeView/components/ZoomControls.tsx +3 -4
  170. package/src/LinearGenomeView/components/__snapshots__/LinearGenomeView.test.tsx.snap +1240 -1203
  171. package/src/LinearGenomeView/components/util.ts +13 -0
  172. package/src/LinearGenomeView/index.test.ts +9 -5
  173. package/src/LinearGenomeView/model.ts +16 -5
  174. package/src/LinearGenomeView/svgcomponents/SVGBackground.tsx +21 -0
  175. package/src/LinearGenomeView/svgcomponents/SVGHeader.tsx +93 -0
  176. package/src/LinearGenomeView/svgcomponents/SVGLinearGenomeView.tsx +114 -0
  177. package/src/LinearGenomeView/svgcomponents/SVGRegionSeparators.tsx +31 -0
  178. package/src/LinearGenomeView/svgcomponents/SVGRuler.tsx +125 -0
  179. package/src/LinearGenomeView/svgcomponents/SVGScalebar.tsx +57 -0
  180. package/src/LinearGenomeView/svgcomponents/SVGTrackLabel.tsx +45 -0
  181. package/src/LinearGenomeView/svgcomponents/SVGTracks.tsx +67 -0
  182. package/src/LinearGenomeView/util.test.ts +7 -4
  183. package/src/LinearGenomeView/util.ts +2 -2
  184. package/src/index.ts +10 -1
  185. package/dist/LinearGenomeView/components/LinearGenomeViewSvg.d.ts +0 -4
  186. package/dist/LinearGenomeView/components/LinearGenomeViewSvg.js +0 -141
  187. package/dist/LinearGenomeView/components/LinearGenomeViewSvg.js.map +0 -1
  188. package/dist/LinearGenomeView/components/Ruler.d.ts +0 -11
  189. package/dist/LinearGenomeView/components/Ruler.js +0 -39
  190. package/dist/LinearGenomeView/components/Ruler.js.map +0 -1
  191. package/esm/LinearGenomeView/components/LinearGenomeViewSvg.d.ts +0 -4
  192. package/esm/LinearGenomeView/components/LinearGenomeViewSvg.js +0 -134
  193. package/esm/LinearGenomeView/components/LinearGenomeViewSvg.js.map +0 -1
  194. package/esm/LinearGenomeView/components/Ruler.d.ts +0 -11
  195. package/esm/LinearGenomeView/components/Ruler.js +0 -34
  196. package/esm/LinearGenomeView/components/Ruler.js.map +0 -1
  197. package/src/LinearGenomeView/components/LinearGenomeViewSvg.tsx +0 -307
  198. package/src/LinearGenomeView/components/Ruler.tsx +0 -78
@@ -29,6 +29,7 @@ import {
29
29
  getRpcSessionId,
30
30
  } from '@jbrowse/core/util/tracks'
31
31
 
32
+ // locals
32
33
  import ServerSideRenderedBlockContent from '../components/ServerSideRenderedBlockContent'
33
34
 
34
35
  // the MST state of a single server-side-rendered block in a display
@@ -65,7 +66,7 @@ const blockState = types
65
66
  makeAbortableReaction(
66
67
  self as any,
67
68
  renderBlockData,
68
- renderBlockEffect as any, // reaction doesn't expect async here
69
+ renderBlockEffect, // reaction doesn't expect async here
69
70
  {
70
71
  name: `${display.id}/${assembleLocString(self.region)} rendering`,
71
72
  delay: display.renderDelay,
@@ -140,7 +141,7 @@ const blockState = types
140
141
  self.renderProps = renderProps
141
142
  renderInProgress = undefined
142
143
  },
143
- setError(error: Error | unknown) {
144
+ setError(error: unknown) {
144
145
  console.error(error)
145
146
  if (renderInProgress && !renderInProgress.signal.aborted) {
146
147
  renderInProgress.abort()
@@ -260,24 +261,14 @@ export function renderBlockData(
260
261
  }
261
262
  }
262
263
 
263
- interface RenderProps {
264
- displayError: Error
265
- rendererType: any
266
- renderProps: { [key: string]: any }
267
- rpcManager: { call: Function }
268
- cannotBeRenderedReason: string
269
- renderArgs: { [key: string]: any }
270
- }
271
-
272
- interface ErrorProps {
273
- displayError: string
274
- }
275
-
276
264
  async function renderBlockEffect(
277
- props: RenderProps | ErrorProps,
265
+ props: ReturnType<typeof renderBlockData> | undefined,
278
266
  signal: AbortSignal,
279
267
  self: BlockModel,
280
268
  ) {
269
+ if (!props) {
270
+ return
271
+ }
281
272
  const {
282
273
  rendererType,
283
274
  renderProps,
@@ -285,7 +276,7 @@ async function renderBlockEffect(
285
276
  renderArgs,
286
277
  cannotBeRenderedReason,
287
278
  displayError,
288
- } = props as RenderProps
279
+ } = props
289
280
  if (!isAlive(self)) {
290
281
  return undefined
291
282
  }
@@ -315,5 +306,6 @@ async function renderBlockEffect(
315
306
  features,
316
307
  layout,
317
308
  maxHeightReached,
309
+ renderProps,
318
310
  }
319
311
  }
@@ -5,13 +5,13 @@ import { LinearGenomeViewModel } from '..'
5
5
 
6
6
  type LGV = LinearGenomeViewModel
7
7
 
8
- const useStyles = makeStyles()(() => ({
8
+ const useStyles = makeStyles()(theme => ({
9
9
  centerLineContainer: {
10
10
  background: 'transparent',
11
11
  height: '100%',
12
12
  zIndex: 5, // above the track but under menu
13
13
  position: 'absolute',
14
- border: '1px black dashed',
14
+ border: `1px ${theme.palette.action.active} dashed`,
15
15
  borderTop: 'none',
16
16
  borderBottom: 'none',
17
17
  pointerEvents: 'none',
@@ -0,0 +1,154 @@
1
+ import React from 'react'
2
+ import { observer } from 'mobx-react'
3
+
4
+ // core
5
+ import { Base1DViewModel } from '@jbrowse/core/util/Base1DViewModel'
6
+ import { ContentBlock } from '@jbrowse/core/util/blockTypes'
7
+ import { Assembly } from '@jbrowse/core/assemblyManager/assembly'
8
+
9
+ // locals
10
+ import { HEADER_OVERVIEW_HEIGHT } from '..'
11
+ import { getCytobands } from './util'
12
+
13
+ // rounded rect from https://stackoverflow.com/a/45889603/2129219
14
+ // prettier-ignore
15
+ function rightRoundedRect(x: number, y: number, width: number, height: number, radius: number) {
16
+ return "M" + x + "," + y
17
+ + "h" + (width - radius)
18
+ + "a" + radius + "," + radius + " 0 0 1 " + radius + "," + radius
19
+ + "v" + (height - 2 * radius)
20
+ + "a" + radius + "," + radius + " 0 0 1 " + -radius + "," + radius
21
+ + "h" + (radius - width)
22
+ + "z";
23
+ }
24
+
25
+ // prettier-ignore
26
+ function leftRoundedRect(x: number, y: number, width: number, height: number, radius: number ) {
27
+ return "M" + (x + radius) + "," + y
28
+ + "h" + (width - radius)
29
+ + "v" + height
30
+ + "h" + (radius - width)
31
+ + "a" + radius + "," + radius + " 0 0 1 " + (-radius) + "," + (-radius)
32
+ + "v" + (2 * radius - height)
33
+ + "a" + radius + "," + radius + " 0 0 1 " + radius + "," + (-radius)
34
+ + "z";
35
+ }
36
+
37
+ const colorMap: { [key: string]: string | undefined } = {
38
+ gneg: 'rgb(227,227,227)',
39
+ gpos25: 'rgb(142,142,142)',
40
+ gpos50: 'rgb(85,85,85)',
41
+ gpos100: 'rgb(0,0,0)',
42
+ gpos75: 'rgb(57,57,57)',
43
+ gvar: 'rgb(0,0,0)',
44
+ stalk: 'rgb(127,127,127)',
45
+ acen: '#800',
46
+ }
47
+
48
+ export default observer(function Cytobands({
49
+ overview,
50
+ block,
51
+ assembly,
52
+ }: {
53
+ overview: Base1DViewModel
54
+ assembly?: Assembly
55
+ block: ContentBlock
56
+ }) {
57
+ const { offsetPx, reversed } = block
58
+ const cytobands = getCytobands(assembly, block.refName)
59
+ const coords = cytobands.map(f => {
60
+ const { refName, start, end, type } = f
61
+ return [
62
+ overview.bpToPx({
63
+ refName,
64
+ coord: start,
65
+ }),
66
+ overview.bpToPx({
67
+ refName,
68
+ coord: end,
69
+ }),
70
+ type,
71
+ ]
72
+ })
73
+
74
+ const arr = cytobands || []
75
+ const lcap = reversed ? arr.length - 1 : 0
76
+ const rcap = reversed ? 0 : arr.length - 1
77
+
78
+ let firstCent = true
79
+ return (
80
+ <g transform={`translate(-${offsetPx})`}>
81
+ {coords.map(([start, end, type], index) => {
82
+ const key = `${start}-${end}-${type}`
83
+ if (type === 'acen' && firstCent) {
84
+ firstCent = false
85
+ return (
86
+ <polygon
87
+ key={key}
88
+ points={[
89
+ [start, 0],
90
+ [end, HEADER_OVERVIEW_HEIGHT / 2],
91
+ [start, HEADER_OVERVIEW_HEIGHT],
92
+ ].toString()}
93
+ fill={colorMap[type]}
94
+ />
95
+ )
96
+ }
97
+ if (type === 'acen' && !firstCent) {
98
+ return (
99
+ <polygon
100
+ key={key}
101
+ points={[
102
+ [start, HEADER_OVERVIEW_HEIGHT / 2],
103
+ [end, 0],
104
+ [end, HEADER_OVERVIEW_HEIGHT],
105
+ ].toString()}
106
+ fill={colorMap[type]}
107
+ />
108
+ )
109
+ }
110
+
111
+ if (lcap === index) {
112
+ return (
113
+ <path
114
+ key={key}
115
+ d={leftRoundedRect(
116
+ Math.min(start, end),
117
+ 0,
118
+ Math.abs(end - start),
119
+ HEADER_OVERVIEW_HEIGHT,
120
+ 8,
121
+ )}
122
+ fill={colorMap[type]}
123
+ />
124
+ )
125
+ } else if (rcap === index) {
126
+ return (
127
+ <path
128
+ key={key}
129
+ d={rightRoundedRect(
130
+ Math.min(start, end),
131
+ 0,
132
+ Math.abs(end - start) - 2,
133
+ HEADER_OVERVIEW_HEIGHT,
134
+ 8,
135
+ )}
136
+ fill={colorMap[type]}
137
+ />
138
+ )
139
+ } else {
140
+ return (
141
+ <rect
142
+ key={key}
143
+ x={Math.min(start, end)}
144
+ y={0}
145
+ width={Math.abs(end - start)}
146
+ height={HEADER_OVERVIEW_HEIGHT}
147
+ fill={colorMap[type]}
148
+ />
149
+ )
150
+ }
151
+ })}
152
+ </g>
153
+ )
154
+ })
@@ -6,10 +6,14 @@ import {
6
6
  DialogActions,
7
7
  DialogContent,
8
8
  FormControlLabel,
9
+ MenuItem,
9
10
  TextField,
10
11
  Typography,
11
12
  } from '@mui/material'
12
13
  import { Dialog, ErrorMessage } from '@jbrowse/core/ui'
14
+ import { getSession, useLocalStorage } from '@jbrowse/core/util'
15
+
16
+ // locals
13
17
  import { ExportSvgOptions } from '..'
14
18
 
15
19
  function LoadingMessage() {
@@ -21,19 +25,28 @@ function LoadingMessage() {
21
25
  )
22
26
  }
23
27
 
28
+ function useSvgLocal<T>(key: string, val: T) {
29
+ return useLocalStorage('svg-' + key, val)
30
+ }
31
+
24
32
  export default function ExportSvgDlg({
25
33
  model,
26
34
  handleClose,
27
35
  }: {
28
- model: { exportSvg(opts: ExportSvgOptions): void }
36
+ model: { exportSvg(opts: ExportSvgOptions): Promise<void> }
29
37
  handleClose: () => void
30
38
  }) {
31
- // @ts-ignore
39
+ const session = getSession(model)
32
40
  const offscreenCanvas = typeof OffscreenCanvas !== 'undefined'
33
41
  const [rasterizeLayers, setRasterizeLayers] = useState(offscreenCanvas)
34
42
  const [loading, setLoading] = useState(false)
35
- const [filename, setFilename] = useState('jbrowse.svg')
36
43
  const [error, setError] = useState<unknown>()
44
+ const [filename, setFilename] = useSvgLocal('file', 'jbrowse.svg')
45
+ const [trackLabels, setTrackLabels] = useSvgLocal('tracklabels', 'offset')
46
+ const [themeName, setThemeName] = useSvgLocal(
47
+ 'theme',
48
+ session.themeName || 'default',
49
+ )
37
50
  return (
38
51
  <Dialog open onClose={handleClose} title="Export SVG">
39
52
  <DialogContent>
@@ -47,6 +60,40 @@ export default function ExportSvgDlg({
47
60
  value={filename}
48
61
  onChange={event => setFilename(event.target.value)}
49
62
  />
63
+ <br />
64
+ <TextField
65
+ select
66
+ label="Track label positioning"
67
+ variant="outlined"
68
+ style={{ width: 150 }}
69
+ value={trackLabels}
70
+ onChange={event => setTrackLabels(event.target.value)}
71
+ >
72
+ <MenuItem value="offset">Offset</MenuItem>
73
+ <MenuItem value="overlay">Overlay</MenuItem>
74
+ <MenuItem value="left">Left</MenuItem>
75
+ <MenuItem value="none">None</MenuItem>
76
+ </TextField>
77
+ <br />
78
+ {session.allThemes ? (
79
+ <TextField
80
+ select
81
+ label="Theme"
82
+ variant="outlined"
83
+ value={themeName}
84
+ onChange={event => setThemeName(event.target.value)}
85
+ >
86
+ {Object.entries(session.allThemes()).map(([key, val]) => (
87
+ <MenuItem key={key} value={key}>
88
+ {
89
+ // @ts-ignore
90
+ val.name || '(Unknown name)'
91
+ }
92
+ </MenuItem>
93
+ ))}
94
+ </TextField>
95
+ ) : null}
96
+
50
97
  {offscreenCanvas ? (
51
98
  <FormControlLabel
52
99
  control={
@@ -80,7 +127,12 @@ export default function ExportSvgDlg({
80
127
  setLoading(true)
81
128
  setError(undefined)
82
129
  try {
83
- await model.exportSvg({ rasterizeLayers, filename })
130
+ await model.exportSvg({
131
+ rasterizeLayers,
132
+ filename,
133
+ trackLabels,
134
+ themeName,
135
+ })
84
136
  handleClose()
85
137
  } catch (e) {
86
138
  console.error(e)
@@ -161,7 +161,11 @@ function SequenceDialog({
161
161
  if (comp) {
162
162
  chunkSeq = complement(chunkSeq)
163
163
  }
164
- return { header: chunkLocstring, seq: chunkSeq }
164
+ return {
165
+ header:
166
+ chunkLocstring + (rev ? '-rev' : '') + (comp ? '-comp' : ''),
167
+ seq: chunkSeq,
168
+ }
165
169
  }),
166
170
  )
167
171
  : ''
@@ -38,7 +38,7 @@ const useStyles = makeStyles()(theme => ({
38
38
  width: 1,
39
39
  },
40
40
  majorTick: {
41
- background: theme.palette.text.secondary,
41
+ background: theme.palette.action.disabled,
42
42
  },
43
43
  minorTick: {
44
44
  background: theme.palette.divider,
@@ -1,6 +1,6 @@
1
1
  import React from 'react'
2
2
  import { observer } from 'mobx-react'
3
- import { Button, FormGroup, Typography, alpha } from '@mui/material'
3
+ import { Button, IconButton, FormGroup, Typography, alpha } from '@mui/material'
4
4
  import { makeStyles } from 'tss-react/mui'
5
5
  import { getBpDisplayStr } from '@jbrowse/core/util'
6
6
 
@@ -10,12 +10,7 @@ import ArrowForwardIcon from '@mui/icons-material/ArrowForward'
10
10
  import ArrowBackIcon from '@mui/icons-material/ArrowBack'
11
11
 
12
12
  // locals
13
- import {
14
- LinearGenomeViewModel,
15
- WIDGET_HEIGHT,
16
- SPACING,
17
- HEADER_BAR_HEIGHT,
18
- } from '..'
13
+ import { LinearGenomeViewModel, SPACING } from '..'
19
14
  import OverviewScalebar from './OverviewScalebar'
20
15
  import ZoomControls from './ZoomControls'
21
16
  import SearchBox from './SearchBox'
@@ -23,7 +18,6 @@ import SearchBox from './SearchBox'
23
18
  type LGV = LinearGenomeViewModel
24
19
  const useStyles = makeStyles()(theme => ({
25
20
  headerBar: {
26
- height: HEADER_BAR_HEIGHT,
27
21
  display: 'flex',
28
22
  },
29
23
  headerForm: {
@@ -36,7 +30,7 @@ const useStyles = makeStyles()(theme => ({
36
30
 
37
31
  panButton: {
38
32
  background: alpha(theme.palette.background.paper, 0.8),
39
- height: WIDGET_HEIGHT,
33
+ color: theme.palette.text.primary,
40
34
  margin: SPACING,
41
35
  },
42
36
  bp: {
@@ -47,7 +41,7 @@ const useStyles = makeStyles()(theme => ({
47
41
  toggleButton: {
48
42
  height: 44,
49
43
  border: 'none',
50
- margin: theme.spacing(0.5),
44
+ marginLeft: theme.spacing(4),
51
45
  },
52
46
  buttonSpacer: {
53
47
  marginRight: theme.spacing(2),
@@ -57,15 +51,14 @@ const useStyles = makeStyles()(theme => ({
57
51
  const HeaderButtons = observer(({ model }: { model: LGV }) => {
58
52
  const { classes } = useStyles()
59
53
  return (
60
- <Button
54
+ <IconButton
61
55
  onClick={model.activateTrackSelector}
62
56
  className={classes.toggleButton}
63
57
  title="Open track selector"
64
58
  value="track_select"
65
- color="secondary"
66
59
  >
67
60
  <TrackSelectorIcon className={classes.buttonSpacer} />
68
- </Button>
61
+ </IconButton>
69
62
  )
70
63
  })
71
64
 
@@ -1,7 +1,6 @@
1
1
  import React from 'react'
2
2
  import { fireEvent, render, waitFor } from '@testing-library/react'
3
3
  import { createTestSession } from '@jbrowse/web/src/rootModel'
4
- import '@testing-library/jest-dom/extend-expect'
5
4
  import 'requestidlecallback-polyfill'
6
5
 
7
6
  // locals
@@ -81,9 +80,8 @@ test('renders one track, one region', async () => {
81
80
  })
82
81
  const model = session.views[0]
83
82
  model.setWidth(800)
84
- const { container, queryByText, getByPlaceholderText, findByText } = render(
85
- <LinearGenomeView model={model} />,
86
- )
83
+ const { container, queryAllByTestId, getByPlaceholderText, findByText } =
84
+ render(<LinearGenomeView model={model} />)
87
85
  await findByText('Foo Track')
88
86
  // test needs to wait until it's updated to display 100 bp in the header to
89
87
  // make snapshot pass
@@ -94,8 +92,9 @@ test('renders one track, one region', async () => {
94
92
  (getByPlaceholderText('Search for location') as HTMLInputElement).value,
95
93
  ).toEqual('ctgA:1..100')
96
94
  })
97
- await waitFor(() => expect(queryByText('Loading')).not.toBeInTheDocument())
98
- expect(container.firstChild).toMatchSnapshot()
95
+ await waitFor(() => expect(queryAllByTestId('svgfeatures').length).toBe(1))
96
+ // snapshot has no features rendered
97
+ expect(container).toMatchSnapshot()
99
98
  })
100
99
 
101
100
  test('renders two tracks, two regions', async () => {
@@ -158,13 +157,11 @@ test('renders two tracks, two regions', async () => {
158
157
  })
159
158
  const model = session.views[0]
160
159
  model.setWidth(800)
161
- const { container, findByText, queryByText, findAllByTestId } = render(
160
+ const { container, findByText, queryAllByTestId } = render(
162
161
  <LinearGenomeView model={model} />,
163
162
  )
164
163
  await findByText('Foo Track')
165
164
  await findByText('798bp')
166
- await findAllByTestId('svgfeatures', {}, { timeout: 10000 })
167
- await waitFor(() => expect(queryByText('Loading')).not.toBeInTheDocument())
168
-
169
- expect(container.firstChild).toMatchSnapshot()
165
+ await waitFor(() => expect(queryAllByTestId('svgfeatures').length).toBe(4))
166
+ expect(container).toMatchSnapshot()
170
167
  }, 15000)
@@ -28,7 +28,7 @@ const LinearGenomeView = observer(({ model }: { model: LGV }) => {
28
28
  const { classes } = useStyles()
29
29
 
30
30
  if (!initialized && !error) {
31
- return <LoadingEllipses variant="h5" />
31
+ return <LoadingEllipses variant="h6" />
32
32
  }
33
33
  if (!hasDisplayedRegions || error) {
34
34
  return <ImportForm model={model} />
@@ -1,10 +1,14 @@
1
1
  import React, { useState } from 'react'
2
2
  import { observer } from 'mobx-react'
3
3
  import { IconButton, Paper } from '@mui/material'
4
+ import Menu from '@jbrowse/core/ui/Menu'
5
+
6
+ // icons
4
7
  import ZoomIn from '@mui/icons-material/ZoomIn'
5
8
  import ZoomOut from '@mui/icons-material/ZoomOut'
6
9
  import ArrowDown from '@mui/icons-material/KeyboardArrowDown'
7
- import Menu from '@jbrowse/core/ui/Menu'
10
+
11
+ // locals
8
12
  import { LinearGenomeViewModel } from '..'
9
13
 
10
14
  const MiniControls = observer((props: { model: LinearGenomeViewModel }) => {
@@ -15,10 +19,7 @@ const MiniControls = observer((props: { model: LinearGenomeViewModel }) => {
15
19
  return hideHeader ? (
16
20
  <div style={{ position: 'absolute', right: '0px', zIndex: '1001' }}>
17
21
  <Paper style={{ background: '#aaa7' }}>
18
- <IconButton
19
- color="secondary"
20
- onClick={event => setAnchorEl(event.currentTarget)}
21
- >
22
+ <IconButton onClick={event => setAnchorEl(event.currentTarget)}>
22
23
  <ArrowDown fontSize="small" />
23
24
  </IconButton>
24
25
 
@@ -26,7 +27,6 @@ const MiniControls = observer((props: { model: LinearGenomeViewModel }) => {
26
27
  data-testid="zoom_out"
27
28
  onClick={() => model.zoom(bpPerPx * 2)}
28
29
  disabled={bpPerPx >= maxBpPerPx - 0.0001 || scaleFactor !== 1}
29
- color="secondary"
30
30
  >
31
31
  <ZoomOut fontSize="small" />
32
32
  </IconButton>
@@ -34,7 +34,6 @@ const MiniControls = observer((props: { model: LinearGenomeViewModel }) => {
34
34
  data-testid="zoom_in"
35
35
  onClick={() => model.zoom(model.bpPerPx / 2)}
36
36
  disabled={bpPerPx <= minBpPerPx + 0.0001 || scaleFactor !== 1}
37
- color="secondary"
38
37
  >
39
38
  <ZoomIn fontSize="small" />
40
39
  </IconButton>