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

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 (150) hide show
  1. package/dist/BaseLinearDisplay/components/BaseLinearDisplay.d.ts +2 -3
  2. package/dist/BaseLinearDisplay/components/BaseLinearDisplay.js +4 -4
  3. package/dist/BaseLinearDisplay/components/BaseLinearDisplay.js.map +1 -1
  4. package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +11 -6
  5. package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.js +5 -9
  6. package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.js.map +1 -1
  7. package/dist/BaseLinearDisplay/models/serverSideRenderedBlock.js +4 -5
  8. package/dist/BaseLinearDisplay/models/serverSideRenderedBlock.js.map +1 -1
  9. package/dist/BaseLinearDisplay/models/util.js +2 -2
  10. package/dist/BaseLinearDisplay/models/util.js.map +1 -1
  11. package/dist/LaunchLinearGenomeView/index.js +1 -1
  12. package/dist/LaunchLinearGenomeView/index.js.map +1 -1
  13. package/dist/LinearBareDisplay/index.d.ts +2 -3
  14. package/dist/LinearBareDisplay/index.js +4 -2
  15. package/dist/LinearBareDisplay/index.js.map +1 -1
  16. package/dist/LinearBareDisplay/model.d.ts +2 -2
  17. package/dist/LinearBasicDisplay/index.d.ts +2 -3
  18. package/dist/LinearBasicDisplay/index.js +4 -2
  19. package/dist/LinearBasicDisplay/index.js.map +1 -1
  20. package/dist/LinearBasicDisplay/model.d.ts +14 -4
  21. package/dist/LinearGenomeView/components/ExportSvgDialog.js +1 -1
  22. package/dist/LinearGenomeView/components/ExportSvgDialog.js.map +1 -1
  23. package/dist/LinearGenomeView/components/ImportForm.d.ts +2 -2
  24. package/dist/LinearGenomeView/components/ImportForm.js +15 -19
  25. package/dist/LinearGenomeView/components/ImportForm.js.map +1 -1
  26. package/dist/LinearGenomeView/components/OverviewRubberband.d.ts +3 -4
  27. package/dist/LinearGenomeView/components/OverviewRubberband.js +8 -11
  28. package/dist/LinearGenomeView/components/OverviewRubberband.js.map +1 -1
  29. package/dist/LinearGenomeView/components/OverviewScalebar.d.ts +4 -5
  30. package/dist/LinearGenomeView/components/OverviewScalebar.js +5 -5
  31. package/dist/LinearGenomeView/components/OverviewScalebar.js.map +1 -1
  32. package/dist/LinearGenomeView/components/RefNameAutocomplete.d.ts +2 -1
  33. package/dist/LinearGenomeView/components/RefNameAutocomplete.js +35 -31
  34. package/dist/LinearGenomeView/components/RefNameAutocomplete.js.map +1 -1
  35. package/dist/LinearGenomeView/components/RubberbandSpan.d.ts +2 -2
  36. package/dist/LinearGenomeView/components/RubberbandSpan.js +2 -16
  37. package/dist/LinearGenomeView/components/RubberbandSpan.js.map +1 -1
  38. package/dist/LinearGenomeView/components/SearchBox.js +3 -3
  39. package/dist/LinearGenomeView/components/SearchBox.js.map +1 -1
  40. package/dist/LinearGenomeView/components/TrackLabel.js +3 -3
  41. package/dist/LinearGenomeView/components/TrackLabel.js.map +1 -1
  42. package/dist/LinearGenomeView/components/TracksContainer.d.ts +2 -3
  43. package/dist/LinearGenomeView/components/TracksContainer.js +9 -8
  44. package/dist/LinearGenomeView/components/TracksContainer.js.map +1 -1
  45. package/dist/LinearGenomeView/components/hooks.d.ts +6 -1
  46. package/dist/LinearGenomeView/components/hooks.js +1 -1
  47. package/dist/LinearGenomeView/components/hooks.js.map +1 -1
  48. package/dist/LinearGenomeView/index.js +8 -6
  49. package/dist/LinearGenomeView/index.js.map +1 -1
  50. package/dist/LinearGenomeView/model.d.ts +9 -11
  51. package/dist/LinearGenomeView/model.js +28 -31
  52. package/dist/LinearGenomeView/model.js.map +1 -1
  53. package/dist/LinearGenomeView/svgcomponents/SVGLinearGenomeView.d.ts +2 -3
  54. package/dist/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js +6 -5
  55. package/dist/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js.map +1 -1
  56. package/dist/LinearGenomeView/svgcomponents/SVGTrackLabel.js +2 -1
  57. package/dist/LinearGenomeView/svgcomponents/SVGTrackLabel.js.map +1 -1
  58. package/dist/LinearGenomeView/util.js +1 -1
  59. package/dist/LinearGenomeView/util.js.map +1 -1
  60. package/dist/index.d.ts +36 -38
  61. package/dist/index.js +21 -17
  62. package/dist/index.js.map +1 -1
  63. package/esm/BaseLinearDisplay/components/BaseLinearDisplay.d.ts +2 -3
  64. package/esm/BaseLinearDisplay/components/BaseLinearDisplay.js +2 -3
  65. package/esm/BaseLinearDisplay/components/BaseLinearDisplay.js.map +1 -1
  66. package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +11 -6
  67. package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.js +5 -9
  68. package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.js.map +1 -1
  69. package/esm/BaseLinearDisplay/models/serverSideRenderedBlock.js +4 -5
  70. package/esm/BaseLinearDisplay/models/serverSideRenderedBlock.js.map +1 -1
  71. package/esm/BaseLinearDisplay/models/util.js +2 -2
  72. package/esm/BaseLinearDisplay/models/util.js.map +1 -1
  73. package/esm/LaunchLinearGenomeView/index.js +1 -1
  74. package/esm/LaunchLinearGenomeView/index.js.map +1 -1
  75. package/esm/LinearBareDisplay/index.d.ts +2 -3
  76. package/esm/LinearBareDisplay/index.js +2 -1
  77. package/esm/LinearBareDisplay/index.js.map +1 -1
  78. package/esm/LinearBareDisplay/model.d.ts +2 -2
  79. package/esm/LinearBasicDisplay/index.d.ts +2 -3
  80. package/esm/LinearBasicDisplay/index.js +2 -1
  81. package/esm/LinearBasicDisplay/index.js.map +1 -1
  82. package/esm/LinearBasicDisplay/model.d.ts +14 -4
  83. package/esm/LinearGenomeView/components/ExportSvgDialog.js +1 -1
  84. package/esm/LinearGenomeView/components/ExportSvgDialog.js.map +1 -1
  85. package/esm/LinearGenomeView/components/ImportForm.d.ts +2 -2
  86. package/esm/LinearGenomeView/components/ImportForm.js +16 -20
  87. package/esm/LinearGenomeView/components/ImportForm.js.map +1 -1
  88. package/esm/LinearGenomeView/components/OverviewRubberband.d.ts +3 -4
  89. package/esm/LinearGenomeView/components/OverviewRubberband.js +8 -11
  90. package/esm/LinearGenomeView/components/OverviewRubberband.js.map +1 -1
  91. package/esm/LinearGenomeView/components/OverviewScalebar.d.ts +4 -5
  92. package/esm/LinearGenomeView/components/OverviewScalebar.js +4 -4
  93. package/esm/LinearGenomeView/components/OverviewScalebar.js.map +1 -1
  94. package/esm/LinearGenomeView/components/RefNameAutocomplete.d.ts +2 -1
  95. package/esm/LinearGenomeView/components/RefNameAutocomplete.js +36 -32
  96. package/esm/LinearGenomeView/components/RefNameAutocomplete.js.map +1 -1
  97. package/esm/LinearGenomeView/components/RubberbandSpan.d.ts +2 -2
  98. package/esm/LinearGenomeView/components/RubberbandSpan.js +3 -18
  99. package/esm/LinearGenomeView/components/RubberbandSpan.js.map +1 -1
  100. package/esm/LinearGenomeView/components/SearchBox.js +3 -3
  101. package/esm/LinearGenomeView/components/SearchBox.js.map +1 -1
  102. package/esm/LinearGenomeView/components/TrackLabel.js +3 -3
  103. package/esm/LinearGenomeView/components/TrackLabel.js.map +1 -1
  104. package/esm/LinearGenomeView/components/TracksContainer.d.ts +2 -3
  105. package/esm/LinearGenomeView/components/TracksContainer.js +9 -8
  106. package/esm/LinearGenomeView/components/TracksContainer.js.map +1 -1
  107. package/esm/LinearGenomeView/components/hooks.d.ts +6 -1
  108. package/esm/LinearGenomeView/components/hooks.js +1 -1
  109. package/esm/LinearGenomeView/components/hooks.js.map +1 -1
  110. package/esm/LinearGenomeView/index.js +8 -6
  111. package/esm/LinearGenomeView/index.js.map +1 -1
  112. package/esm/LinearGenomeView/model.d.ts +9 -11
  113. package/esm/LinearGenomeView/model.js +22 -26
  114. package/esm/LinearGenomeView/model.js.map +1 -1
  115. package/esm/LinearGenomeView/svgcomponents/SVGLinearGenomeView.d.ts +2 -3
  116. package/esm/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js +3 -3
  117. package/esm/LinearGenomeView/svgcomponents/SVGLinearGenomeView.js.map +1 -1
  118. package/esm/LinearGenomeView/svgcomponents/SVGTrackLabel.js +2 -1
  119. package/esm/LinearGenomeView/svgcomponents/SVGTrackLabel.js.map +1 -1
  120. package/esm/LinearGenomeView/util.js +1 -1
  121. package/esm/LinearGenomeView/util.js.map +1 -1
  122. package/esm/index.d.ts +36 -38
  123. package/esm/index.js +9 -6
  124. package/esm/index.js.map +1 -1
  125. package/package.json +2 -2
  126. package/src/BaseLinearDisplay/components/BaseLinearDisplay.tsx +4 -3
  127. package/src/BaseLinearDisplay/models/BaseLinearDisplayModel.tsx +6 -9
  128. package/src/BaseLinearDisplay/models/serverSideRenderedBlock.ts +6 -5
  129. package/src/BaseLinearDisplay/models/util.ts +2 -2
  130. package/src/LaunchLinearGenomeView/index.ts +1 -1
  131. package/src/LinearBareDisplay/index.ts +2 -1
  132. package/src/LinearBasicDisplay/index.ts +2 -1
  133. package/src/LinearGenomeView/components/ExportSvgDialog.tsx +1 -1
  134. package/src/LinearGenomeView/components/ImportForm.tsx +17 -26
  135. package/src/LinearGenomeView/components/OverviewRubberband.tsx +40 -49
  136. package/src/LinearGenomeView/components/OverviewScalebar.tsx +4 -4
  137. package/src/LinearGenomeView/components/RefNameAutocomplete.tsx +50 -48
  138. package/src/LinearGenomeView/components/RubberbandSpan.tsx +6 -23
  139. package/src/LinearGenomeView/components/SearchBox.tsx +3 -2
  140. package/src/LinearGenomeView/components/TrackLabel.tsx +74 -71
  141. package/src/LinearGenomeView/components/TracksContainer.tsx +8 -8
  142. package/src/LinearGenomeView/components/__snapshots__/LinearGenomeView.test.tsx.snap +7 -11
  143. package/src/LinearGenomeView/components/hooks.ts +7 -1
  144. package/src/LinearGenomeView/index.test.ts +3 -8
  145. package/src/LinearGenomeView/index.ts +8 -9
  146. package/src/LinearGenomeView/model.ts +31 -33
  147. package/src/LinearGenomeView/svgcomponents/SVGLinearGenomeView.tsx +5 -5
  148. package/src/LinearGenomeView/svgcomponents/SVGTrackLabel.tsx +2 -0
  149. package/src/LinearGenomeView/util.ts +1 -1
  150. package/src/index.ts +21 -31
@@ -60,81 +60,84 @@ interface Props {
60
60
  className?: string
61
61
  }
62
62
 
63
- const TrackLabel = React.forwardRef<HTMLDivElement, Props>(
64
- ({ track, className }, ref) => {
65
- const { classes, cx } = useStyles()
66
- const view = getContainingView(track) as LGV
67
- const session = getSession(track)
68
- const trackConf = track.configuration
69
- const minimized = track.minimized
70
- const trackId = getConf(track, 'trackId')
71
- const trackName = getTrackName(trackConf, session)
63
+ const TrackLabel = React.forwardRef<HTMLDivElement, Props>(function (
64
+ { track, className },
65
+ ref,
66
+ ) {
67
+ const { classes, cx } = useStyles()
68
+ const view = getContainingView(track) as LGV
69
+ const session = getSession(track)
70
+ const trackConf = track.configuration
71
+ const minimized = track.minimized
72
+ const trackId = getConf(track, 'trackId')
73
+ const trackName = getTrackName(trackConf, session)
72
74
 
73
- const popupState = usePopupState({
74
- popupId: 'trackLabelMenu',
75
- variant: 'popover',
76
- })
75
+ const popupState = usePopupState({
76
+ popupId: 'trackLabelMenu',
77
+ variant: 'popover',
78
+ })
77
79
 
78
- const items = [
79
- {
80
- label: minimized ? 'Restore track' : 'Minimize track',
81
- icon: minimized ? AddIcon : MinimizeIcon,
82
- onClick: () => track.setMinimized(!minimized),
83
- },
84
- ...(session.getTrackActionMenuItems?.(trackConf) || []),
85
- ...track.trackMenuItems(),
86
- ].sort((a, b) => (b.priority || 0) - (a.priority || 0))
80
+ const items = [
81
+ {
82
+ label: minimized ? 'Restore track' : 'Minimize track',
83
+ icon: minimized ? AddIcon : MinimizeIcon,
84
+ onClick: () => track.setMinimized(!minimized),
85
+ },
86
+ ...(session.getTrackActionMenuItems?.(trackConf) || []),
87
+ ...track.trackMenuItems(),
88
+ ].sort((a, b) => (b.priority || 0) - (a.priority || 0))
87
89
 
88
- return (
89
- <Paper ref={ref} className={cx(className, classes.root)}>
90
- <span
91
- draggable
92
- className={classes.dragHandle}
93
- onDragStart={event => {
94
- const target = event.currentTarget
95
- if (target.parentNode) {
96
- const parent = target.parentNode as HTMLElement
97
- event.dataTransfer.setDragImage(parent, 20, 20)
98
- view.setDraggingTrackId(track.id)
99
- }
100
- }}
101
- onDragEnd={() => view.setDraggingTrackId(undefined)}
102
- data-testid={`dragHandle-${view.id}-${trackId}`}
103
- >
104
- <DragIcon className={classes.dragHandleIcon} fontSize="small" />
105
- </span>
106
- <IconButton
107
- onClick={() => view.hideTrack(trackId)}
108
- className={classes.iconButton}
109
- title="close this track"
110
- >
111
- <CloseIcon fontSize="small" />
112
- </IconButton>
90
+ return (
91
+ <Paper ref={ref} className={cx(className, classes.root)}>
92
+ <span
93
+ draggable
94
+ className={classes.dragHandle}
95
+ onDragStart={event => {
96
+ const target = event.currentTarget
97
+ if (target.parentNode) {
98
+ const parent = target.parentNode as HTMLElement
99
+ event.dataTransfer.setDragImage(parent, 20, 20)
100
+ view.setDraggingTrackId(track.id)
101
+ }
102
+ }}
103
+ onDragEnd={() => view.setDraggingTrackId(undefined)}
104
+ data-testid={`dragHandle-${view.id}-${trackId}`}
105
+ >
106
+ <DragIcon className={classes.dragHandleIcon} fontSize="small" />
107
+ </span>
108
+ <IconButton
109
+ onClick={() => view.hideTrack(trackId)}
110
+ className={classes.iconButton}
111
+ title="close this track"
112
+ >
113
+ <CloseIcon fontSize="small" />
114
+ </IconButton>
113
115
 
114
- <Typography
115
- variant="body1"
116
- component="span"
117
- className={classes.trackName}
118
- >
119
- <SanitizedHTML html={trackName + (minimized ? ' (minimized)' : '')} />
120
- </Typography>
121
- <IconButton
122
- {...bindTrigger(popupState)}
123
- className={classes.iconButton}
124
- data-testid="track_menu_icon"
125
- disabled={!items.length}
126
- >
127
- <MoreVertIcon fontSize="small" />
128
- </IconButton>
129
- <CascadingMenu
130
- {...bindPopover(popupState)}
131
- onMenuItemClick={(_: unknown, callback: Function) => callback()}
132
- menuItems={items}
133
- popupState={popupState}
116
+ <Typography
117
+ variant="body1"
118
+ component="span"
119
+ className={classes.trackName}
120
+ >
121
+ <SanitizedHTML
122
+ html={`${trackName}${minimized ? ' (minimized)' : ''}`}
134
123
  />
135
- </Paper>
136
- )
137
- },
138
- )
124
+ </Typography>
125
+ <IconButton
126
+ {...bindTrigger(popupState)}
127
+ className={classes.iconButton}
128
+ data-testid="track_menu_icon"
129
+ disabled={items.length === 0}
130
+ >
131
+ <MoreVertIcon fontSize="small" />
132
+ </IconButton>
133
+ <CascadingMenu
134
+ {...bindPopover(popupState)}
135
+ onMenuItemClick={(_: unknown, callback: Function) => callback()}
136
+ menuItems={items}
137
+ popupState={popupState}
138
+ />
139
+ </Paper>
140
+ )
141
+ })
139
142
 
140
143
  export default observer(TrackLabel)
@@ -20,15 +20,11 @@ const useStyles = makeStyles()({
20
20
  position: 'relative',
21
21
  overflow: 'hidden',
22
22
  },
23
- spacer: {
24
- position: 'relative',
25
- height: 3,
26
- },
27
23
  })
28
24
 
29
25
  type LGV = LinearGenomeViewModel
30
26
 
31
- function TracksContainer({
27
+ export default observer(function TracksContainer({
32
28
  children,
33
29
  model,
34
30
  }: {
@@ -60,6 +56,12 @@ function TracksContainer({
60
56
  ref={ref}
61
57
  data-testid="trackContainer"
62
58
  className={classes.tracksContainer}
59
+ onClick={event => {
60
+ if (event.detail === 2) {
61
+ const left = ref.current?.getBoundingClientRect().left || 0
62
+ model.zoomTo(model.bpPerPx / 2, event.clientX - left, true)
63
+ }
64
+ }}
63
65
  onMouseDown={event => {
64
66
  mouseDown1(event)
65
67
  mouseDown2(event)
@@ -106,6 +108,4 @@ function TracksContainer({
106
108
  {children}
107
109
  </div>
108
110
  )
109
- }
110
-
111
- export default observer(TracksContainer)
111
+ })
@@ -11,7 +11,6 @@ exports[`renders one track, one region 1`] = `
11
11
  >
12
12
  <div
13
13
  class="css-dznme2-rubberbandControl"
14
- role="presentation"
15
14
  >
16
15
  <div
17
16
  class="css-16vhz0m-scalebar"
@@ -160,11 +159,11 @@ exports[`renders one track, one region 1`] = `
160
159
  <div
161
160
  class="MuiAutocomplete-root css-l3ln04-MuiAutocomplete-root"
162
161
  data-testid="autocomplete"
163
- style="width: 200px;"
162
+ style="width: 175px;"
164
163
  >
165
164
  <div
166
165
  class="MuiFormControl-root MuiFormControl-fullWidth MuiTextField-root css-1efd6m0-MuiFormControl-root-MuiTextField-root-headerRefName"
167
- style="margin: 7px; min-width: 175px;"
166
+ style="margin: 7px;"
168
167
  >
169
168
  <div
170
169
  class="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-colorPrimary MuiInputBase-fullWidth MuiInputBase-formControl MuiInputBase-adornedEnd MuiAutocomplete-inputRoot css-154xyx0-MuiInputBase-root-MuiOutlinedInput-root"
@@ -177,7 +176,7 @@ exports[`renders one track, one region 1`] = `
177
176
  autocapitalize="none"
178
177
  autocomplete="off"
179
178
  class="MuiInputBase-input MuiOutlinedInput-input MuiInputBase-inputAdornedEnd MuiAutocomplete-input MuiAutocomplete-inputFocused css-nxo287-MuiInputBase-input-MuiOutlinedInput-input"
180
- id="refNameAutocomplete-lgv"
179
+ id="mui-7"
181
180
  placeholder="Search for location"
182
181
  role="combobox"
183
182
  spellcheck="false"
@@ -276,8 +275,7 @@ exports[`renders one track, one region 1`] = `
276
275
  style="left: 0%; width: 0%;"
277
276
  />
278
277
  <span
279
- class="MuiSlider-thumb MuiSlider-thumbSizeSmall MuiSlider-thumbColorPrimary css-14gf62f-MuiSlider-thumb"
280
- data-focusvisible="false"
278
+ class="MuiSlider-thumb MuiSlider-thumbSizeSmall MuiSlider-thumbColorPrimary MuiSlider-thumb MuiSlider-thumbSizeSmall MuiSlider-thumbColorPrimary css-14gf62f-MuiSlider-thumb"
281
279
  data-index="0"
282
280
  style="left: 0%;"
283
281
  >
@@ -571,7 +569,6 @@ exports[`renders two tracks, two regions 1`] = `
571
569
  >
572
570
  <div
573
571
  class="css-dznme2-rubberbandControl"
574
- role="presentation"
575
572
  >
576
573
  <div
577
574
  class="css-16vhz0m-scalebar"
@@ -740,7 +737,7 @@ exports[`renders two tracks, two regions 1`] = `
740
737
  >
741
738
  <div
742
739
  class="MuiFormControl-root MuiFormControl-fullWidth MuiTextField-root css-1efd6m0-MuiFormControl-root-MuiTextField-root-headerRefName"
743
- style="margin: 7px; min-width: 175px;"
740
+ style="margin: 7px;"
744
741
  >
745
742
  <div
746
743
  class="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-colorPrimary MuiInputBase-fullWidth MuiInputBase-formControl MuiInputBase-adornedEnd MuiAutocomplete-inputRoot css-154xyx0-MuiInputBase-root-MuiOutlinedInput-root"
@@ -753,7 +750,7 @@ exports[`renders two tracks, two regions 1`] = `
753
750
  autocapitalize="none"
754
751
  autocomplete="off"
755
752
  class="MuiInputBase-input MuiOutlinedInput-input MuiInputBase-inputAdornedEnd MuiAutocomplete-input MuiAutocomplete-inputFocused css-nxo287-MuiInputBase-input-MuiOutlinedInput-input"
756
- id="refNameAutocomplete-lgv"
753
+ id="mui-9"
757
754
  placeholder="Search for location"
758
755
  role="combobox"
759
756
  spellcheck="false"
@@ -854,8 +851,7 @@ exports[`renders two tracks, two regions 1`] = `
854
851
  style="left: 0%; width: 9.774680693120512%;"
855
852
  />
856
853
  <span
857
- class="MuiSlider-thumb MuiSlider-thumbSizeSmall MuiSlider-thumbColorPrimary css-14gf62f-MuiSlider-thumb"
858
- data-focusvisible="false"
854
+ class="MuiSlider-thumb MuiSlider-thumbSizeSmall MuiSlider-thumbColorPrimary MuiSlider-thumb MuiSlider-thumbSizeSmall MuiSlider-thumbColorPrimary css-14gf62f-MuiSlider-thumb"
859
855
  data-index="0"
860
856
  style="left: 9.774680693120512%;"
861
857
  >
@@ -239,7 +239,12 @@ export function useRangeSelect(
239
239
 
240
240
  export function useWheelScroll(
241
241
  ref: React.RefObject<HTMLDivElement>,
242
- model: LGV,
242
+ model: {
243
+ bpPerPx: number
244
+ zoomTo: (arg: number, arg2?: number) => void
245
+ setScaleFactor: (arg: number) => void
246
+ horizontalScroll: (arg: number) => void
247
+ },
243
248
  ) {
244
249
  const delta = useRef(0)
245
250
  const timeout = useRef<Timer>()
@@ -266,6 +271,7 @@ export function useWheelScroll(
266
271
  delta.current > 0
267
272
  ? model.bpPerPx * (1 + delta.current)
268
273
  : model.bpPerPx / (1 - delta.current),
274
+ origEvent.clientX - (curr?.getBoundingClientRect().left || 0),
269
275
  )
270
276
  delta.current = 0
271
277
  }, 300)
@@ -96,7 +96,7 @@ function initialize() {
96
96
  assemblyManager: types.optional(AssemblyManager, {
97
97
  assemblies: {
98
98
  volvox: {
99
- // @ts-ignore
99
+ // @ts-expect-error
100
100
  regions: volvoxDisplayedRegions,
101
101
  },
102
102
  },
@@ -311,7 +311,6 @@ test('can navToMultiple', () => {
311
311
  describe('Zoom to selected displayed regions', () => {
312
312
  const { Session, LinearGenomeModel } = initialize()
313
313
  let model: LGV
314
- let largestBpPerPx: number
315
314
  beforeEach(() => {
316
315
  const session = Session.create({
317
316
  configuration: {},
@@ -357,7 +356,6 @@ describe('Zoom to selected displayed regions', () => {
357
356
  },
358
357
  )
359
358
 
360
- largestBpPerPx = model.bpPerPx
361
359
  expect(model.offsetPx).toEqual(0)
362
360
  expect(model.bpPerPx).toBeCloseTo(31.408)
363
361
  })
@@ -384,7 +382,6 @@ describe('Zoom to selected displayed regions', () => {
384
382
  expect(model.offsetPx).toEqual(0)
385
383
  // 10000 - 5000 = 5000 / 800 = 6.25
386
384
  expect(model.bpPerPx).toEqual(6.25)
387
- expect(model.bpPerPx).toBeLessThan(largestBpPerPx)
388
385
  })
389
386
 
390
387
  it('can select one region with start or end outside of displayed region', () => {
@@ -411,7 +408,6 @@ describe('Zoom to selected displayed regions', () => {
411
408
  expect(Math.abs(model.offsetPx)).toEqual(0)
412
409
  // endOffset 19000 - (-1) = 19001 / 800 = zoomTo(23.75)
413
410
  expect(model.bpPerPx).toBeCloseTo(23.75)
414
- expect(model.bpPerPx).toBeLessThan(largestBpPerPx)
415
411
  })
416
412
 
417
413
  it('can select over two regions in the same reference sequence', () => {
@@ -439,7 +435,6 @@ describe('Zoom to selected displayed regions', () => {
439
435
  expect(model.bpPerPx).toBeCloseTo(27.78, 0)
440
436
  // offset 5000 / bpPerPx (because that is the starting) = 180.5
441
437
  expect(model.offsetPx).toBe(181)
442
- expect(model.bpPerPx).toBeLessThan(largestBpPerPx)
443
438
  })
444
439
 
445
440
  it('can navigate to overlapping regions with a region between', () => {
@@ -585,7 +580,7 @@ test('can perform bpToPx in a way that makes sense on things that happen outside
585
580
  model.toggleHeaderOverview()
586
581
  expect(model.hideHeaderOverview).toEqual(true)
587
582
  model.toggleHeaderOverview()
588
- model.setError(Error('pxToBp failed to map to a region'))
583
+ model.setError(new Error('pxToBp failed to map to a region'))
589
584
  expect(`${model.error}`).toEqual('Error: pxToBp failed to map to a region')
590
585
  })
591
586
  // determined objectively by looking at
@@ -936,7 +931,7 @@ test('navToLocString with human assembly', async () => {
936
931
  assemblyManager: {
937
932
  assemblies: {
938
933
  hg38: {
939
- // @ts-ignore
934
+ // @ts-expect-error
940
935
  regions: hg38Regions,
941
936
  },
942
937
  },
@@ -4,15 +4,14 @@ import { ViewType } from '@jbrowse/core/pluggableElementTypes'
4
4
  import { stateModelFactory } from './model'
5
5
 
6
6
  export default (pluginManager: PluginManager) => {
7
- pluginManager.addViewType(
8
- () =>
9
- new ViewType({
10
- name: 'LinearGenomeView',
11
- displayName: 'Linear genome view',
12
- stateModel: stateModelFactory(pluginManager),
13
- ReactComponent: lazy(() => import('./components/LinearGenomeView')),
14
- }),
15
- )
7
+ pluginManager.addViewType(() => {
8
+ return new ViewType({
9
+ name: 'LinearGenomeView',
10
+ displayName: 'Linear genome view',
11
+ stateModel: stateModelFactory(pluginManager),
12
+ ReactComponent: lazy(() => import('./components/LinearGenomeView')),
13
+ })
14
+ })
16
15
  }
17
16
 
18
17
  export * from './model'
@@ -17,6 +17,7 @@ import {
17
17
  measureText,
18
18
  parseLocString,
19
19
  springAnimate,
20
+ sum,
20
21
  } from '@jbrowse/core/util'
21
22
  import BaseResult from '@jbrowse/core/TextSearch/BaseResults'
22
23
  import { BlockSet, BaseBlock } from '@jbrowse/core/util/blockTypes'
@@ -52,13 +53,10 @@ import MenuOpenIcon from '@mui/icons-material/MenuOpen'
52
53
 
53
54
  // locals
54
55
  import { renderToSvg } from './svgcomponents/SVGLinearGenomeView'
55
- import RefNameAutocomplete from './components/RefNameAutocomplete'
56
- import SearchBox from './components/SearchBox'
56
+
57
57
  import ExportSvgDlg from './components/ExportSvgDialog'
58
58
  import MiniControls from './components/MiniControls'
59
59
  import Header from './components/Header'
60
- import ZoomControls from './components/ZoomControls'
61
- import LinearGenomeView from './components/LinearGenomeView'
62
60
 
63
61
  // lazies
64
62
  const SequenceSearchDialog = lazy(
@@ -365,9 +363,7 @@ export function stateModelFactory(pluginManager: PluginManager) {
365
363
  * #getter
366
364
  */
367
365
  get trackHeights() {
368
- return self.tracks
369
- .map(t => t.displays[0].height)
370
- .reduce((a, b) => a + b, 0)
366
+ return sum(self.tracks.map(t => t.displays[0].height))
371
367
  },
372
368
 
373
369
  /**
@@ -478,14 +474,14 @@ export function stateModelFactory(pluginManager: PluginManager) {
478
474
  */
479
475
  rankSearchResults(results: BaseResult[]) {
480
476
  // order of rank
481
- const openTrackIds = self.tracks.map(
482
- track => track.configuration.trackId,
477
+ const openTrackIds = new Set(
478
+ self.tracks.map(track => track.configuration.trackId),
483
479
  )
484
- results.forEach(result => {
485
- if (openTrackIds.includes(result.trackId)) {
480
+ for (const result of results) {
481
+ if (openTrackIds.has(result.trackId)) {
486
482
  result.updateScore(result.getScore() + 1)
487
483
  }
488
- })
484
+ }
489
485
  return results
490
486
  },
491
487
 
@@ -583,25 +579,25 @@ export function stateModelFactory(pluginManager: PluginManager) {
583
579
  /**
584
580
  * #action
585
581
  */
586
- zoomTo(bpPerPx: number) {
582
+ zoomTo(bpPerPx: number, offset = self.width / 2, centerAtOffset = false) {
587
583
  const newBpPerPx = clamp(bpPerPx, self.minBpPerPx, self.maxBpPerPx)
588
584
  if (newBpPerPx === self.bpPerPx) {
589
585
  return newBpPerPx
590
586
  }
591
587
  const oldBpPerPx = self.bpPerPx
592
- self.bpPerPx = newBpPerPx
593
588
 
594
589
  if (Math.abs(oldBpPerPx - newBpPerPx) < 0.000001) {
595
590
  console.warn('zoomTo bpPerPx rounding error')
596
591
  return oldBpPerPx
597
592
  }
593
+ self.bpPerPx = newBpPerPx
598
594
 
599
- // tweak the offset so that the center of the view remains at the same coordinate
600
- const viewWidth = self.width
595
+ // tweak the offset so that the center of the view remains at the same
596
+ // coordinate
601
597
  this.scrollTo(
602
598
  Math.round(
603
- ((self.offsetPx + viewWidth / 2) * oldBpPerPx) / newBpPerPx -
604
- viewWidth / 2,
599
+ ((self.offsetPx + offset) * oldBpPerPx) / newBpPerPx -
600
+ (centerAtOffset ? self.width / 2 : offset),
605
601
  ),
606
602
  )
607
603
  return newBpPerPx
@@ -644,8 +640,7 @@ export function stateModelFactory(pluginManager: PluginManager) {
644
640
  */
645
641
  horizontallyFlip() {
646
642
  self.displayedRegions = cast(
647
- self.displayedRegions
648
- .slice()
643
+ [...self.displayedRegions]
649
644
  .reverse()
650
645
  .map(region => ({ ...region, reversed: !region.reversed })),
651
646
  )
@@ -670,9 +665,11 @@ export function stateModelFactory(pluginManager: PluginManager) {
670
665
  throw new Error(`Unknown track type ${conf.type}`)
671
666
  }
672
667
  const viewType = pluginManager.getViewType(self.type)
673
- const supportedDisplays = viewType.displayTypes.map(d => d.name)
668
+ const supportedDisplays = new Set(
669
+ viewType.displayTypes.map(d => d.name),
670
+ )
674
671
  const displayConf = conf.displays.find((d: AnyConfigurationModel) =>
675
- supportedDisplays.includes(d.type),
672
+ supportedDisplays.has(d.type),
676
673
  )
677
674
  if (!displayConf) {
678
675
  throw new Error(
@@ -1366,7 +1363,7 @@ export function stateModelFactory(pluginManager: PluginManager) {
1366
1363
  })
1367
1364
  } else {
1368
1365
  self.setDisplayedRegions(
1369
- // @ts-ignore
1366
+ // @ts-expect-error
1370
1367
  locations.map(r => (r.start === undefined ? r.parentRegion : r)),
1371
1368
  )
1372
1369
  self.showAllRegions()
@@ -1586,22 +1583,23 @@ export function stateModelFactory(pluginManager: PluginManager) {
1586
1583
  * #getter
1587
1584
  */
1588
1585
  get centerLineInfo() {
1589
- return self.displayedRegions.length
1586
+ return self.displayedRegions.length > 0
1590
1587
  ? this.pxToBp(self.width / 2)
1591
1588
  : undefined
1592
1589
  },
1593
1590
  }))
1594
1591
  }
1595
1592
 
1596
- export {
1597
- renderToSvg,
1598
- RefNameAutocomplete,
1599
- SearchBox,
1600
- ZoomControls,
1601
- LinearGenomeView,
1602
- }
1603
-
1604
1593
  export type LinearGenomeViewStateModel = ReturnType<typeof stateModelFactory>
1605
1594
  export type LinearGenomeViewModel = Instance<LinearGenomeViewStateModel>
1606
1595
 
1607
- export { default as ReactComponent } from './components/LinearGenomeView'
1596
+ export {
1597
+ default as ReactComponent,
1598
+ default as LinearGenomeView,
1599
+ } from './components/LinearGenomeView'
1600
+
1601
+ export { default as RefNameAutocomplete } from './components/RefNameAutocomplete'
1602
+ export { default as SearchBox } from './components/SearchBox'
1603
+ export { default as ZoomControls } from './components/ZoomControls'
1604
+
1605
+ export { renderToSvg } from './svgcomponents/SVGLinearGenomeView'
@@ -10,7 +10,7 @@ import { LinearGenomeViewModel, ExportSvgOptions } from '..'
10
10
  import SVGBackground from './SVGBackground'
11
11
  import SVGTracks from './SVGTracks'
12
12
  import SVGHeader from './SVGHeader'
13
- import SVGRuler from './SVGRuler'
13
+
14
14
  import { getTrackName } from '@jbrowse/core/util/tracks'
15
15
 
16
16
  type LGV = LinearGenomeViewModel
@@ -65,9 +65,8 @@ export async function renderToSvg(model: LGV, opts: ExportSvgOptions) {
65
65
  )
66
66
  const trackLabelMaxLen =
67
67
  max(
68
- tracks.map(
69
- t => measureText(getTrackName(t.configuration, session), fontSize),
70
- fontSize,
68
+ tracks.map(t =>
69
+ measureText(getTrackName(t.configuration, session), fontSize),
71
70
  ),
72
71
  0,
73
72
  ) + 40
@@ -111,4 +110,5 @@ export async function renderToSvg(model: LGV, opts: ExportSvgOptions) {
111
110
  )
112
111
  }
113
112
 
114
- export { SVGTracks, SVGRuler }
113
+ export { default as SVGRuler } from './SVGRuler'
114
+ export { default as SVGTracks } from './SVGTracks'
@@ -17,6 +17,7 @@ export default function SVGTrackLabel({
17
17
  const theme = useTheme()
18
18
  const fill = theme.palette.text.primary
19
19
  const xoff = trackLabels === 'overlay' ? 5 : 0
20
+ const yoff = trackLabels === 'offset' ? 5 : 0
20
21
  return trackLabels !== 'none' ? (
21
22
  <g>
22
23
  {trackLabels === 'left' ? (
@@ -33,6 +34,7 @@ export default function SVGTrackLabel({
33
34
  ) : (
34
35
  <text
35
36
  x={x + xoff}
37
+ y={yoff}
36
38
  fill={fill}
37
39
  fontSize={fontSize}
38
40
  dominantBaseline="hanging"
@@ -10,7 +10,7 @@ export function chooseGridPitch(
10
10
  ) {
11
11
  scale = Math.abs(scale)
12
12
  const minMajorPitchBp = minMajorPitchPx * scale
13
- const majorMagnitude = parseInt(
13
+ const majorMagnitude = Number.parseInt(
14
14
  Number(minMajorPitchBp).toExponential().split(/e/i)[1],
15
15
  10,
16
16
  )
package/src/index.ts CHANGED
@@ -9,32 +9,16 @@ import LineStyleIcon from '@mui/icons-material/LineStyle'
9
9
  import {
10
10
  BaseLinearDisplay,
11
11
  BaseLinearDisplayComponent,
12
- BlockModel,
13
- BlockMsg,
14
12
  baseLinearDisplayConfigSchema,
15
13
  } from './BaseLinearDisplay'
16
- import LinearBareDisplayF, {
17
- configSchemaFactory as linearBareDisplayConfigSchemaFactory,
18
- } from './LinearBareDisplay'
14
+ import LinearBareDisplayF from './LinearBareDisplay'
19
15
  import LinearGenomeViewF, {
20
- LinearGenomeViewModel,
21
- LinearGenomeViewStateModel,
22
- RefNameAutocomplete,
23
16
  SearchBox,
24
17
  ZoomControls,
25
18
  LinearGenomeView,
26
19
  } from './LinearGenomeView'
27
20
 
28
- import {
29
- renderToSvg,
30
- totalHeight,
31
- SVGTracks,
32
- SVGRuler,
33
- } from './LinearGenomeView/svgcomponents/SVGLinearGenomeView'
34
- import LinearBasicDisplayF, {
35
- configSchema as linearBasicDisplayConfigSchemaFactory,
36
- modelFactory as linearBasicDisplayModelFactory,
37
- } from './LinearBasicDisplay'
21
+ import LinearBasicDisplayF from './LinearBasicDisplay'
38
22
 
39
23
  import FeatureTrackF from './FeatureTrack'
40
24
  import BasicTrackF from './BasicTrack'
@@ -74,22 +58,28 @@ export default class LinearGenomeViewPlugin extends Plugin {
74
58
  }
75
59
  }
76
60
 
61
+ export type { BaseLinearDisplayModel, BlockModel } from './BaseLinearDisplay'
62
+
63
+ export { configSchemaFactory as linearBareDisplayConfigSchemaFactory } from './LinearBareDisplay'
77
64
  export {
65
+ BlockMsg,
78
66
  baseLinearDisplayConfigSchema,
79
- linearBareDisplayConfigSchemaFactory,
80
- linearBasicDisplayConfigSchemaFactory,
81
- linearBasicDisplayModelFactory,
82
- renderToSvg,
83
- totalHeight,
84
- SVGTracks,
85
- SVGRuler,
86
67
  BaseLinearDisplayComponent,
87
68
  BaseLinearDisplay,
69
+ } from './BaseLinearDisplay'
70
+ export {
71
+ type LinearGenomeViewModel,
88
72
  RefNameAutocomplete,
73
+ type LinearGenomeViewStateModel,
89
74
  SearchBox,
90
- BlockMsg,
91
- }
92
-
93
- export type { LinearGenomeViewModel, LinearGenomeViewStateModel, BlockModel }
94
-
95
- export type { BaseLinearDisplayModel } from './BaseLinearDisplay'
75
+ } from './LinearGenomeView'
76
+ export {
77
+ renderToSvg,
78
+ SVGTracks,
79
+ totalHeight,
80
+ SVGRuler,
81
+ } from './LinearGenomeView/svgcomponents/SVGLinearGenomeView'
82
+ export {
83
+ configSchema as linearBasicDisplayConfigSchemaFactory,
84
+ modelFactory as linearBasicDisplayModelFactory,
85
+ } from './LinearBasicDisplay'