@jbrowse/plugin-linear-genome-view 2.1.7 → 2.2.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 (147) hide show
  1. package/dist/BaseLinearDisplay/components/LinearBlocks.d.ts +2 -2
  2. package/dist/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js +2 -22
  3. package/dist/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js.map +1 -1
  4. package/dist/BaseLinearDisplay/components/Tooltip.d.ts +1 -1
  5. package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +149 -4
  6. package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.js +600 -464
  7. package/dist/BaseLinearDisplay/models/BaseLinearDisplayModel.js.map +1 -1
  8. package/dist/BaseLinearDisplay/models/baseLinearDisplayConfigSchema.js +19 -1
  9. package/dist/BaseLinearDisplay/models/baseLinearDisplayConfigSchema.js.map +1 -1
  10. package/dist/BaseLinearDisplay/models/serverSideRenderedBlock.d.ts +2 -2
  11. package/dist/BasicTrack/configSchema.d.ts +3 -0
  12. package/dist/BasicTrack/configSchema.js +18 -0
  13. package/dist/BasicTrack/configSchema.js.map +1 -0
  14. package/dist/BasicTrack/index.d.ts +3 -0
  15. package/dist/BasicTrack/index.js +18 -0
  16. package/dist/BasicTrack/index.js.map +1 -0
  17. package/dist/FeatureTrack/configSchema.d.ts +3 -0
  18. package/dist/FeatureTrack/configSchema.js +21 -0
  19. package/dist/FeatureTrack/configSchema.js.map +1 -0
  20. package/dist/FeatureTrack/index.d.ts +3 -0
  21. package/dist/FeatureTrack/index.js +18 -0
  22. package/dist/FeatureTrack/index.js.map +1 -0
  23. package/dist/LinearBareDisplay/configSchema.d.ts +5 -1
  24. package/dist/LinearBareDisplay/configSchema.js +12 -1
  25. package/dist/LinearBareDisplay/configSchema.js.map +1 -1
  26. package/dist/LinearBareDisplay/model.d.ts +16 -0
  27. package/dist/LinearBareDisplay/model.js +16 -0
  28. package/dist/LinearBareDisplay/model.js.map +1 -1
  29. package/dist/LinearBasicDisplay/configSchema.d.ts +5 -1
  30. package/dist/LinearBasicDisplay/configSchema.js +16 -1
  31. package/dist/LinearBasicDisplay/configSchema.js.map +1 -1
  32. package/dist/LinearBasicDisplay/model.d.ts +79 -8
  33. package/dist/LinearBasicDisplay/model.js +167 -111
  34. package/dist/LinearBasicDisplay/model.js.map +1 -1
  35. package/dist/LinearGenomeView/components/CenterLine.d.ts +1 -1
  36. package/dist/LinearGenomeView/components/GetSequenceDialog.d.ts +1 -1
  37. package/dist/LinearGenomeView/components/Gridlines.d.ts +1 -1
  38. package/dist/LinearGenomeView/components/Header.d.ts +1 -1
  39. package/dist/LinearGenomeView/components/ImportForm.d.ts +1 -1
  40. package/dist/LinearGenomeView/components/ImportForm.js +38 -31
  41. package/dist/LinearGenomeView/components/ImportForm.js.map +1 -1
  42. package/dist/LinearGenomeView/components/LinearGenomeView.d.ts +1 -1
  43. package/dist/LinearGenomeView/components/LinearGenomeView.js +2 -24
  44. package/dist/LinearGenomeView/components/LinearGenomeView.js.map +1 -1
  45. package/dist/LinearGenomeView/components/LinearGenomeViewSvg.d.ts +1 -1
  46. package/dist/LinearGenomeView/components/LinearGenomeViewSvg.js +7 -5
  47. package/dist/LinearGenomeView/components/LinearGenomeViewSvg.js.map +1 -1
  48. package/dist/LinearGenomeView/components/OverviewRubberBand.d.ts +1 -1
  49. package/dist/LinearGenomeView/components/OverviewScaleBar.d.ts +27 -35
  50. package/dist/LinearGenomeView/components/RubberBand.d.ts +1 -1
  51. package/dist/LinearGenomeView/components/ScaleBar.d.ts +1 -1
  52. package/dist/LinearGenomeView/components/TrackContainer.d.ts +1 -1
  53. package/dist/LinearGenomeView/components/TrackContainer.js +12 -9
  54. package/dist/LinearGenomeView/components/TrackContainer.js.map +1 -1
  55. package/dist/LinearGenomeView/components/TrackLabel.js +9 -1
  56. package/dist/LinearGenomeView/components/TrackLabel.js.map +1 -1
  57. package/dist/LinearGenomeView/components/TracksContainer.d.ts +1 -1
  58. package/dist/LinearGenomeView/index.d.ts +273 -18
  59. package/dist/LinearGenomeView/index.js +409 -90
  60. package/dist/LinearGenomeView/index.js.map +1 -1
  61. package/dist/index.d.ts +30 -90
  62. package/dist/index.js +4 -25
  63. package/dist/index.js.map +1 -1
  64. package/esm/BaseLinearDisplay/components/LinearBlocks.d.ts +2 -2
  65. package/esm/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js +2 -22
  66. package/esm/BaseLinearDisplay/components/ServerSideRenderedBlockContent.js.map +1 -1
  67. package/esm/BaseLinearDisplay/components/Tooltip.d.ts +1 -1
  68. package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.d.ts +149 -4
  69. package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.js +600 -464
  70. package/esm/BaseLinearDisplay/models/BaseLinearDisplayModel.js.map +1 -1
  71. package/esm/BaseLinearDisplay/models/baseLinearDisplayConfigSchema.js +19 -1
  72. package/esm/BaseLinearDisplay/models/baseLinearDisplayConfigSchema.js.map +1 -1
  73. package/esm/BaseLinearDisplay/models/serverSideRenderedBlock.d.ts +2 -2
  74. package/esm/BasicTrack/configSchema.d.ts +3 -0
  75. package/esm/BasicTrack/configSchema.js +16 -0
  76. package/esm/BasicTrack/configSchema.js.map +1 -0
  77. package/esm/BasicTrack/index.d.ts +3 -0
  78. package/esm/BasicTrack/index.js +13 -0
  79. package/esm/BasicTrack/index.js.map +1 -0
  80. package/esm/FeatureTrack/configSchema.d.ts +3 -0
  81. package/esm/FeatureTrack/configSchema.js +19 -0
  82. package/esm/FeatureTrack/configSchema.js.map +1 -0
  83. package/esm/FeatureTrack/index.d.ts +3 -0
  84. package/esm/FeatureTrack/index.js +13 -0
  85. package/esm/FeatureTrack/index.js.map +1 -0
  86. package/esm/LinearBareDisplay/configSchema.d.ts +5 -1
  87. package/esm/LinearBareDisplay/configSchema.js +14 -2
  88. package/esm/LinearBareDisplay/configSchema.js.map +1 -1
  89. package/esm/LinearBareDisplay/model.d.ts +16 -0
  90. package/esm/LinearBareDisplay/model.js +16 -0
  91. package/esm/LinearBareDisplay/model.js.map +1 -1
  92. package/esm/LinearBasicDisplay/configSchema.d.ts +5 -1
  93. package/esm/LinearBasicDisplay/configSchema.js +18 -2
  94. package/esm/LinearBasicDisplay/configSchema.js.map +1 -1
  95. package/esm/LinearBasicDisplay/model.d.ts +79 -8
  96. package/esm/LinearBasicDisplay/model.js +167 -111
  97. package/esm/LinearBasicDisplay/model.js.map +1 -1
  98. package/esm/LinearGenomeView/components/CenterLine.d.ts +1 -1
  99. package/esm/LinearGenomeView/components/GetSequenceDialog.d.ts +1 -1
  100. package/esm/LinearGenomeView/components/Gridlines.d.ts +1 -1
  101. package/esm/LinearGenomeView/components/Header.d.ts +1 -1
  102. package/esm/LinearGenomeView/components/ImportForm.d.ts +1 -1
  103. package/esm/LinearGenomeView/components/ImportForm.js +40 -33
  104. package/esm/LinearGenomeView/components/ImportForm.js.map +1 -1
  105. package/esm/LinearGenomeView/components/LinearGenomeView.d.ts +1 -1
  106. package/esm/LinearGenomeView/components/LinearGenomeView.js +3 -25
  107. package/esm/LinearGenomeView/components/LinearGenomeView.js.map +1 -1
  108. package/esm/LinearGenomeView/components/LinearGenomeViewSvg.d.ts +1 -1
  109. package/esm/LinearGenomeView/components/LinearGenomeViewSvg.js +7 -5
  110. package/esm/LinearGenomeView/components/LinearGenomeViewSvg.js.map +1 -1
  111. package/esm/LinearGenomeView/components/OverviewRubberBand.d.ts +1 -1
  112. package/esm/LinearGenomeView/components/OverviewScaleBar.d.ts +27 -35
  113. package/esm/LinearGenomeView/components/RubberBand.d.ts +1 -1
  114. package/esm/LinearGenomeView/components/ScaleBar.d.ts +1 -1
  115. package/esm/LinearGenomeView/components/TrackContainer.d.ts +1 -1
  116. package/esm/LinearGenomeView/components/TrackContainer.js +13 -10
  117. package/esm/LinearGenomeView/components/TrackContainer.js.map +1 -1
  118. package/esm/LinearGenomeView/components/TrackLabel.js +9 -1
  119. package/esm/LinearGenomeView/components/TrackLabel.js.map +1 -1
  120. package/esm/LinearGenomeView/components/TracksContainer.d.ts +1 -1
  121. package/esm/LinearGenomeView/index.d.ts +273 -18
  122. package/esm/LinearGenomeView/index.js +409 -90
  123. package/esm/LinearGenomeView/index.js.map +1 -1
  124. package/esm/index.d.ts +30 -90
  125. package/esm/index.js +4 -25
  126. package/esm/index.js.map +1 -1
  127. package/package.json +2 -2
  128. package/src/BaseLinearDisplay/components/ServerSideRenderedBlockContent.tsx +2 -24
  129. package/src/BaseLinearDisplay/models/BaseLinearDisplayModel.tsx +695 -555
  130. package/src/BaseLinearDisplay/models/baseLinearDisplayConfigSchema.ts +20 -1
  131. package/src/BasicTrack/configSchema.ts +23 -0
  132. package/src/BasicTrack/index.ts +18 -0
  133. package/src/FeatureTrack/configSchema.ts +27 -0
  134. package/src/FeatureTrack/index.ts +21 -0
  135. package/src/LinearBareDisplay/configSchema.ts +15 -2
  136. package/src/LinearBareDisplay/model.ts +16 -0
  137. package/src/LinearBasicDisplay/configSchema.ts +19 -2
  138. package/src/LinearBasicDisplay/model.ts +63 -11
  139. package/src/LinearGenomeView/components/ImportForm.tsx +85 -67
  140. package/src/LinearGenomeView/components/LinearGenomeView.tsx +3 -33
  141. package/src/LinearGenomeView/components/LinearGenomeViewSvg.tsx +21 -18
  142. package/src/LinearGenomeView/components/TrackContainer.tsx +38 -27
  143. package/src/LinearGenomeView/components/TrackLabel.tsx +10 -1
  144. package/src/LinearGenomeView/components/__snapshots__/LinearGenomeView.test.tsx.snap +204 -204
  145. package/src/LinearGenomeView/index.test.ts +33 -26
  146. package/src/LinearGenomeView/index.tsx +471 -133
  147. package/src/index.ts +6 -46
@@ -31,12 +31,13 @@ import MiniControls from './components/MiniControls';
31
31
  import Header from './components/Header';
32
32
  import ZoomControls from './components/ZoomControls';
33
33
  import LinearGenomeView from './components/LinearGenomeView';
34
+ // lazies
34
35
  const SequenceSearchDialog = lazy(() => import('./components/SequenceSearchDialog'));
35
36
  function calculateVisibleLocStrings(contentBlocks) {
36
37
  if (!contentBlocks.length) {
37
38
  return '';
38
39
  }
39
- const isSingleAssemblyName = contentBlocks.every(block => block.assemblyName === contentBlocks[0].assemblyName);
40
+ const isSingleAssemblyName = contentBlocks.every(b => b.assemblyName === contentBlocks[0].assemblyName);
40
41
  const locs = contentBlocks.map(block => assembleLocString({
41
42
  ...block,
42
43
  start: Math.round(block.start),
@@ -57,30 +58,87 @@ function localStorageGetItem(item) {
57
58
  ? localStorage.getItem(item)
58
59
  : undefined;
59
60
  }
61
+ /**
62
+ * #stateModel LinearGenomeView
63
+ */
60
64
  export function stateModelFactory(pluginManager) {
61
65
  return types
62
66
  .compose(BaseViewModel, types.model('LinearGenomeView', {
67
+ /**
68
+ * #property
69
+ */
63
70
  id: ElementId,
71
+ /**
72
+ * #property
73
+ * this is a string instead of the const literal 'LinearGenomeView' to reduce some
74
+ * typescripting strictness, but you should pass the string 'LinearGenomeView' to
75
+ * the model explicitly
76
+ */
64
77
  type: types.literal('LinearGenomeView'),
78
+ /**
79
+ * #property
80
+ * corresponds roughly to the horizontal scroll of the LGV
81
+ */
65
82
  offsetPx: 0,
83
+ /**
84
+ * #property
85
+ * corresponds roughly to the zoom level, base-pairs per pixel
86
+ */
66
87
  bpPerPx: 1,
88
+ /**
89
+ * #property
90
+ * currently displayed regions, can be a single chromosome, arbitrary subsections,
91
+ * or the entire set of chromosomes in the genome, but it not advised to use the
92
+ * entire set of chromosomes if your assembly is very fragmented
93
+ */
67
94
  displayedRegions: types.array(MUIRegion),
68
- // we use an array for the tracks because the tracks are displayed in a
69
- // specific order that we need to keep.
95
+ /**
96
+ * #property
97
+ * array of currently displayed tracks state models instances
98
+ */
70
99
  tracks: types.array(pluginManager.pluggableMstType('track', 'stateModel')),
100
+ /**
101
+ * #property
102
+ * array of currently displayed tracks state model's
103
+ */
71
104
  hideHeader: false,
105
+ /**
106
+ * #property
107
+ */
72
108
  hideHeaderOverview: false,
109
+ /**
110
+ * #property
111
+ */
73
112
  hideNoTracksActive: false,
113
+ /**
114
+ * #property
115
+ */
74
116
  trackSelectorType: types.optional(types.enumeration(['hierarchical']), 'hierarchical'),
117
+ /**
118
+ * #property
119
+ * how to display the track labels, can be "overlapping", "offset", or "hidden"
120
+ */
75
121
  trackLabels: types.optional(types.string, () => localStorageGetItem('lgv-trackLabels') || 'overlapping'),
122
+ /**
123
+ * #property
124
+ * show the "center line"
125
+ */
76
126
  showCenterLine: types.optional(types.boolean, () => {
77
127
  const setting = localStorageGetItem('lgv-showCenterLine');
78
128
  return setting !== undefined && setting !== null ? !!+setting : false;
79
129
  }),
130
+ /**
131
+ * #property
132
+ * show the "cytobands" in the overview scale bar
133
+ */
80
134
  showCytobandsSetting: types.optional(types.boolean, () => {
81
135
  const setting = localStorageGetItem('lgv-showCytobands');
82
136
  return setting !== undefined && setting !== null ? !!+setting : true;
83
137
  }),
138
+ /**
139
+ * #property
140
+ * show the "gridlines" in the track area
141
+ */
84
142
  showGridlines: true,
85
143
  }))
86
144
  .volatile(() => ({
@@ -103,15 +161,24 @@ export function stateModelFactory(pluginManager) {
103
161
  seqDialogDisplayed: false,
104
162
  }))
105
163
  .views(self => ({
164
+ /**
165
+ * #getter
166
+ */
106
167
  get width() {
107
168
  if (self.volatileWidth === undefined) {
108
169
  throw new Error('width undefined, make sure to check for model.initialized');
109
170
  }
110
171
  return self.volatileWidth;
111
172
  },
173
+ /**
174
+ * #getter
175
+ */
112
176
  get interRegionPaddingWidth() {
113
177
  return INTER_REGION_PADDING_WIDTH;
114
178
  },
179
+ /**
180
+ * #getter
181
+ */
115
182
  get assemblyNames() {
116
183
  return [
117
184
  ...new Set(self.displayedRegions.map(region => region.assemblyName)),
@@ -119,14 +186,23 @@ export function stateModelFactory(pluginManager) {
119
186
  },
120
187
  }))
121
188
  .views(self => ({
189
+ /**
190
+ * #method
191
+ */
122
192
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
123
193
  MiniControlsComponent() {
124
194
  return MiniControls;
125
195
  },
196
+ /**
197
+ * #method
198
+ */
126
199
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
127
200
  HeaderComponent() {
128
201
  return Header;
129
202
  },
203
+ /**
204
+ * #getter
205
+ */
130
206
  get assemblyErrors() {
131
207
  const { assemblyManager } = getSession(self);
132
208
  const { assemblyNames } = self;
@@ -135,23 +211,41 @@ export function stateModelFactory(pluginManager) {
135
211
  .filter(f => !!f)
136
212
  .join(', ');
137
213
  },
214
+ /**
215
+ * #getter
216
+ */
138
217
  get assembliesInitialized() {
139
218
  const { assemblyManager } = getSession(self);
140
219
  const { assemblyNames } = self;
141
220
  return assemblyNames.every(a => { var _a; return (_a = assemblyManager.get(a)) === null || _a === void 0 ? void 0 : _a.initialized; });
142
221
  },
222
+ /**
223
+ * #getter
224
+ */
143
225
  get initialized() {
144
226
  return self.volatileWidth !== undefined && this.assembliesInitialized;
145
227
  },
228
+ /**
229
+ * #getter
230
+ */
146
231
  get hasDisplayedRegions() {
147
232
  return self.displayedRegions.length > 0;
148
233
  },
234
+ /**
235
+ * #getter
236
+ */
149
237
  get isSearchDialogDisplayed() {
150
238
  return self.searchResults !== undefined;
151
239
  },
240
+ /**
241
+ * #getter
242
+ */
152
243
  get scaleBarHeight() {
153
244
  return SCALE_BAR_HEIGHT + RESIZE_HANDLE_HEIGHT;
154
245
  },
246
+ /**
247
+ * #getter
248
+ */
155
249
  get headerHeight() {
156
250
  if (self.hideHeader) {
157
251
  return 0;
@@ -161,44 +255,77 @@ export function stateModelFactory(pluginManager) {
161
255
  }
162
256
  return HEADER_BAR_HEIGHT + HEADER_OVERVIEW_HEIGHT;
163
257
  },
258
+ /**
259
+ * #getter
260
+ */
164
261
  get trackHeights() {
165
262
  return self.tracks
166
263
  .map(t => t.displays[0].height)
167
264
  .reduce((a, b) => a + b, 0);
168
265
  },
266
+ /**
267
+ * #getter
268
+ */
169
269
  get trackHeightsWithResizeHandles() {
170
270
  return this.trackHeights + self.tracks.length * RESIZE_HANDLE_HEIGHT;
171
271
  },
272
+ /**
273
+ * #getter
274
+ */
172
275
  get height() {
173
276
  return (this.trackHeightsWithResizeHandles +
174
277
  this.headerHeight +
175
278
  this.scaleBarHeight);
176
279
  },
280
+ /**
281
+ * #getter
282
+ */
177
283
  get totalBp() {
178
284
  return self.displayedRegions.reduce((a, b) => a + b.end - b.start, 0);
179
285
  },
286
+ /**
287
+ * #getter
288
+ */
180
289
  get maxBpPerPx() {
181
290
  return this.totalBp / (self.width * 0.9);
182
291
  },
292
+ /**
293
+ * #getter
294
+ */
183
295
  get minBpPerPx() {
184
296
  return 1 / 50;
185
297
  },
298
+ /**
299
+ * #getter
300
+ */
186
301
  get error() {
187
302
  return self.volatileError || this.assemblyErrors;
188
303
  },
304
+ /**
305
+ * #getter
306
+ */
189
307
  get maxOffset() {
190
308
  // objectively determined to keep the linear genome on the main screen
191
309
  const leftPadding = 10;
192
310
  return this.displayedRegionsTotalPx - leftPadding;
193
311
  },
312
+ /**
313
+ * #getter
314
+ */
194
315
  get minOffset() {
195
316
  // objectively determined to keep the linear genome on the main screen
196
317
  const rightPadding = 30;
197
318
  return -self.width + rightPadding;
198
319
  },
320
+ /**
321
+ * #getter
322
+ */
199
323
  get displayedRegionsTotalPx() {
200
324
  return this.totalBp / self.bpPerPx;
201
325
  },
326
+ /**
327
+ * #method
328
+ */
202
329
  renderProps() {
203
330
  return {
204
331
  ...getParentRenderProps(self),
@@ -206,6 +333,9 @@ export function stateModelFactory(pluginManager) {
206
333
  highResolutionScaling: getConf(getSession(self), 'highResolutionScaling'),
207
334
  };
208
335
  },
336
+ /**
337
+ * #method
338
+ */
209
339
  searchScope(assemblyName) {
210
340
  return {
211
341
  assemblyName,
@@ -213,9 +343,15 @@ export function stateModelFactory(pluginManager) {
213
343
  tracks: self.tracks,
214
344
  };
215
345
  },
346
+ /**
347
+ * #method
348
+ */
216
349
  getTrack(id) {
217
350
  return self.tracks.find(t => t.configuration.trackId === id);
218
351
  },
352
+ /**
353
+ * #method
354
+ */
219
355
  rankSearchResults(results) {
220
356
  // order of rank
221
357
  const openTrackIds = self.tracks.map(track => track.configuration.trackId);
@@ -226,7 +362,10 @@ export function stateModelFactory(pluginManager) {
226
362
  });
227
363
  return results;
228
364
  },
229
- // modifies view menu action onClick to apply to all tracks of same type
365
+ /**
366
+ * #method
367
+ * modifies view menu action onClick to apply to all tracks of same type
368
+ */
230
369
  rewriteOnClicks(trackType, viewMenuActions) {
231
370
  viewMenuActions.forEach(action => {
232
371
  // go to lowest level menu
@@ -245,6 +384,9 @@ export function stateModelFactory(pluginManager) {
245
384
  }
246
385
  });
247
386
  },
387
+ /**
388
+ * #getter
389
+ */
248
390
  get trackTypeActions() {
249
391
  const allActions = new Map();
250
392
  self.tracks.forEach(track => {
@@ -259,33 +401,60 @@ export function stateModelFactory(pluginManager) {
259
401
  },
260
402
  }))
261
403
  .actions(self => ({
404
+ /**
405
+ * #action
406
+ */
262
407
  setShowCytobands(flag) {
263
408
  self.showCytobandsSetting = flag;
264
409
  localStorage.setItem('lgv-showCytobands', `${+flag}`);
265
410
  },
411
+ /**
412
+ * #action
413
+ */
266
414
  setWidth(newWidth) {
267
415
  self.volatileWidth = newWidth;
268
416
  },
417
+ /**
418
+ * #action
419
+ */
269
420
  setError(error) {
270
421
  self.volatileError = error;
271
422
  },
423
+ /**
424
+ * #action
425
+ */
272
426
  toggleHeader() {
273
427
  self.hideHeader = !self.hideHeader;
274
428
  },
429
+ /**
430
+ * #action
431
+ */
275
432
  toggleHeaderOverview() {
276
433
  self.hideHeaderOverview = !self.hideHeaderOverview;
277
434
  },
435
+ /**
436
+ * #action
437
+ */
278
438
  toggleNoTracksActive() {
279
439
  self.hideNoTracksActive = !self.hideNoTracksActive;
280
440
  },
441
+ /**
442
+ * #action
443
+ */
281
444
  toggleShowGridlines() {
282
445
  self.showGridlines = !self.showGridlines;
283
446
  },
447
+ /**
448
+ * #action
449
+ */
284
450
  scrollTo(offsetPx) {
285
451
  const newOffsetPx = clamp(offsetPx, self.minOffset, self.maxOffset);
286
452
  self.offsetPx = newOffsetPx;
287
453
  return newOffsetPx;
288
454
  },
455
+ /**
456
+ * #action
457
+ */
289
458
  zoomTo(bpPerPx) {
290
459
  const newBpPerPx = clamp(bpPerPx, self.minBpPerPx, self.maxBpPerPx);
291
460
  if (newBpPerPx === self.bpPerPx) {
@@ -303,22 +472,37 @@ export function stateModelFactory(pluginManager) {
303
472
  viewWidth / 2));
304
473
  return newBpPerPx;
305
474
  },
475
+ /**
476
+ * #action
477
+ * sets offsets used in the get sequence dialog
478
+ */
306
479
  setOffsets(left, right) {
307
- // sets offsets used in the get sequence dialog
308
480
  self.leftOffset = left;
309
481
  self.rightOffset = right;
310
482
  },
483
+ /**
484
+ * #action
485
+ */
311
486
  setSearchResults(results, query) {
312
487
  self.searchResults = results;
313
488
  self.searchQuery = query;
314
489
  },
490
+ /**
491
+ * #action
492
+ */
315
493
  setGetSequenceDialogOpen(open) {
316
494
  self.seqDialogDisplayed = open;
317
495
  },
496
+ /**
497
+ * #action
498
+ */
318
499
  setNewView(bpPerPx, offsetPx) {
319
500
  this.zoomTo(bpPerPx);
320
501
  this.scrollTo(offsetPx);
321
502
  },
503
+ /**
504
+ * #action
505
+ */
322
506
  horizontallyFlip() {
323
507
  self.displayedRegions = cast(self.displayedRegions
324
508
  .slice()
@@ -326,6 +510,9 @@ export function stateModelFactory(pluginManager) {
326
510
  .map(region => ({ ...region, reversed: !region.reversed })));
327
511
  this.scrollTo(self.totalBp / self.bpPerPx - self.offsetPx - self.width);
328
512
  },
513
+ /**
514
+ * #action
515
+ */
329
516
  showTrack(trackId, initialSnapshot = {}, displayInitialSnapshot = {}) {
330
517
  const schema = pluginManager.pluggableConfigSchemaType('track');
331
518
  const conf = resolveIdentifier(schema, getRoot(self), trackId);
@@ -361,6 +548,9 @@ export function stateModelFactory(pluginManager) {
361
548
  }
362
549
  return t[0];
363
550
  },
551
+ /**
552
+ * #action
553
+ */
364
554
  hideTrack(trackId) {
365
555
  const schema = pluginManager.pluggableConfigSchemaType('track');
366
556
  const conf = resolveIdentifier(schema, getRoot(self), trackId);
@@ -370,6 +560,9 @@ export function stateModelFactory(pluginManager) {
370
560
  },
371
561
  }))
372
562
  .actions(self => ({
563
+ /**
564
+ * #action
565
+ */
373
566
  moveTrack(movingId, targetId) {
374
567
  const oldIndex = self.tracks.findIndex(track => track.id === movingId);
375
568
  if (oldIndex === -1) {
@@ -383,6 +576,9 @@ export function stateModelFactory(pluginManager) {
383
576
  self.tracks.splice(oldIndex, 1);
384
577
  self.tracks.splice(newIndex, 0, track);
385
578
  },
579
+ /**
580
+ * #action
581
+ */
386
582
  closeView() {
387
583
  const parent = getContainingView(self);
388
584
  if (parent) {
@@ -396,6 +592,9 @@ export function stateModelFactory(pluginManager) {
396
592
  getSession(self).removeView(self);
397
593
  }
398
594
  },
595
+ /**
596
+ * #action
597
+ */
399
598
  toggleTrack(trackId) {
400
599
  // if we have any tracks with that configuration, turn them off
401
600
  const hiddenCount = self.hideTrack(trackId);
@@ -404,18 +603,30 @@ export function stateModelFactory(pluginManager) {
404
603
  self.showTrack(trackId);
405
604
  }
406
605
  },
606
+ /**
607
+ * #action
608
+ */
407
609
  setTrackLabels(setting) {
408
610
  self.trackLabels = setting;
409
611
  localStorage.setItem('lgv-trackLabels', setting);
410
612
  },
613
+ /**
614
+ * #action
615
+ */
411
616
  toggleCenterLine() {
412
617
  self.showCenterLine = !self.showCenterLine;
413
618
  localStorage.setItem('lgv-showCenterLine', `${+self.showCenterLine}`);
414
619
  },
620
+ /**
621
+ * #action
622
+ */
415
623
  setDisplayedRegions(regions) {
416
624
  self.displayedRegions = cast(regions);
417
625
  self.zoomTo(self.bpPerPx);
418
626
  },
627
+ /**
628
+ * #action
629
+ */
419
630
  activateTrackSelector() {
420
631
  if (self.trackSelectorType === 'hierarchical') {
421
632
  const session = getSession(self);
@@ -428,6 +639,7 @@ export function stateModelFactory(pluginManager) {
428
639
  throw new Error(`invalid track selector type ${self.trackSelectorType}`);
429
640
  },
430
641
  /**
642
+ * #method
431
643
  * Helper method for the fetchSequence.
432
644
  * Retrieves the corresponding regions that were selected by the rubberband
433
645
  *
@@ -449,38 +661,51 @@ export function stateModelFactory(pluginManager) {
449
661
  end: Math.ceil(region.end),
450
662
  }));
451
663
  },
452
- // schedule something to be run after the next time displayedRegions is set
664
+ /**
665
+ * #action
666
+ * schedule something to be run after the next time displayedRegions is set
667
+ */
453
668
  afterDisplayedRegionsSet(cb) {
454
669
  self.afterDisplayedRegionsSetCallbacks.push(cb);
455
670
  },
671
+ /**
672
+ * #action
673
+ */
456
674
  horizontalScroll(distance) {
457
675
  const oldOffsetPx = self.offsetPx;
458
676
  // newOffsetPx is the actual offset after the scroll is clamped
459
677
  const newOffsetPx = self.scrollTo(self.offsetPx + distance);
460
678
  return newOffsetPx - oldOffsetPx;
461
679
  },
680
+ /**
681
+ * #action
682
+ */
462
683
  center() {
463
684
  const centerBp = self.totalBp / 2;
464
685
  const centerPx = centerBp / self.bpPerPx;
465
686
  self.scrollTo(Math.round(centerPx - self.width / 2));
466
687
  },
688
+ /**
689
+ * #action
690
+ */
467
691
  showAllRegions() {
468
692
  self.zoomTo(self.maxBpPerPx);
469
693
  this.center();
470
694
  },
695
+ /**
696
+ * #action
697
+ */
471
698
  showAllRegionsInAssembly(assemblyName) {
472
699
  const session = getSession(self);
473
700
  const { assemblyManager } = session;
474
701
  if (!assemblyName) {
475
- const assemblyNames = [
476
- ...new Set(self.displayedRegions.map(region => region.assemblyName)),
477
- ];
478
- if (assemblyNames.length > 1) {
479
- session.notify(`Can't perform this with multiple assemblies currently`);
702
+ const names = new Set(self.displayedRegions.map(r => r.assemblyName));
703
+ if (names.size > 1) {
704
+ session.notify(`Can't perform operation with multiple assemblies currently`);
480
705
  return;
481
706
  }
482
707
  ;
483
- [assemblyName] = assemblyNames;
708
+ [assemblyName] = [...names];
484
709
  }
485
710
  const assembly = assemblyManager.get(assemblyName);
486
711
  if (assembly) {
@@ -492,15 +717,24 @@ export function stateModelFactory(pluginManager) {
492
717
  }
493
718
  }
494
719
  },
720
+ /**
721
+ * #action
722
+ */
495
723
  setDraggingTrackId(idx) {
496
724
  self.draggingTrackId = idx;
497
725
  },
726
+ /**
727
+ * #action
728
+ */
498
729
  setScaleFactor(factor) {
499
730
  self.scaleFactor = factor;
500
731
  },
501
- // this "clears the view" and makes the view return to the import form
732
+ /**
733
+ * #action
734
+ * this "clears the view" and makes the view return to the import form
735
+ */
502
736
  clearView() {
503
- this.setDisplayedRegions([]);
737
+ self.displayedRegions.clear();
504
738
  self.tracks.clear();
505
739
  // it is necessary to run these after setting displayed regions empty
506
740
  // or else model.offsetPx gets set to Infinity and breaks
@@ -508,6 +742,10 @@ export function stateModelFactory(pluginManager) {
508
742
  self.scrollTo(0);
509
743
  self.zoomTo(10);
510
744
  },
745
+ /**
746
+ * #action
747
+ * creates an svg export and save using FileSaver
748
+ */
511
749
  async exportSvg(opts = {}) {
512
750
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
513
751
  const html = await renderToSvg(self, opts);
@@ -517,6 +755,10 @@ export function stateModelFactory(pluginManager) {
517
755
  }))
518
756
  .actions(self => {
519
757
  let cancelLastAnimation = () => { };
758
+ /**
759
+ * #action
760
+ * perform animated slide
761
+ */
520
762
  function slide(viewWidths) {
521
763
  const [animate, cancelAnimation] = springAnimate(self.offsetPx, self.offsetPx + self.width * viewWidths, self.scrollTo);
522
764
  cancelLastAnimation();
@@ -527,6 +769,10 @@ export function stateModelFactory(pluginManager) {
527
769
  })
528
770
  .actions(self => {
529
771
  let cancelLastAnimation = () => { };
772
+ /**
773
+ * #action
774
+ * perform animated zoom
775
+ */
530
776
  function zoom(targetBpPerPx) {
531
777
  self.zoomTo(self.bpPerPx);
532
778
  if (
@@ -548,17 +794,30 @@ export function stateModelFactory(pluginManager) {
548
794
  return { zoom };
549
795
  })
550
796
  .views(self => ({
797
+ /**
798
+ * #getter
799
+ */
551
800
  get canShowCytobands() {
552
801
  return self.displayedRegions.length === 1 && this.anyCytobandsExist;
553
802
  },
803
+ /**
804
+ * #getter
805
+ */
554
806
  get showCytobands() {
555
807
  return this.canShowCytobands && self.showCytobandsSetting;
556
808
  },
809
+ /**
810
+ * #getter
811
+ */
557
812
  get anyCytobandsExist() {
558
813
  const { assemblyManager } = getSession(self);
559
- const { assemblyNames } = self;
560
- return assemblyNames.some(asm => { var _a, _b; return (_b = (_a = assemblyManager.get(asm)) === null || _a === void 0 ? void 0 : _a.cytobands) === null || _b === void 0 ? void 0 : _b.length; });
814
+ return self.assemblyNames.some(a => { var _a, _b; return (_b = (_a = assemblyManager.get(a)) === null || _a === void 0 ? void 0 : _a.cytobands) === null || _b === void 0 ? void 0 : _b.length; });
561
815
  },
816
+ /**
817
+ * #getter
818
+ * the cytoband is displayed to the right of the chromosome name,
819
+ * and that offset is calculated manually with this method
820
+ */
562
821
  get cytobandOffset() {
563
822
  return this.showCytobands
564
823
  ? measureText(self.displayedRegions[0].refName, 12) + 15
@@ -566,6 +825,10 @@ export function stateModelFactory(pluginManager) {
566
825
  },
567
826
  }))
568
827
  .views(self => ({
828
+ /**
829
+ * #method
830
+ * return the view menu items
831
+ */
569
832
  menuItems() {
570
833
  const { canShowCytobands, showCytobands } = self;
571
834
  const session = getSession(self);
@@ -613,59 +876,57 @@ export function stateModelFactory(pluginManager) {
613
876
  icon: SyncAltIcon,
614
877
  onClick: self.horizontallyFlip,
615
878
  },
616
- { type: 'divider' },
617
- {
618
- label: 'Show all regions in assembly',
619
- icon: VisibilityIcon,
620
- onClick: self.showAllRegionsInAssembly,
621
- },
622
- {
623
- label: 'Show center line',
624
- icon: VisibilityIcon,
625
- type: 'checkbox',
626
- checked: self.showCenterLine,
627
- onClick: self.toggleCenterLine,
628
- },
629
- {
630
- label: 'Show header',
631
- icon: VisibilityIcon,
632
- type: 'checkbox',
633
- checked: !self.hideHeader,
634
- onClick: self.toggleHeader,
635
- },
636
879
  {
637
- label: 'Show header overview',
880
+ label: 'Show...',
638
881
  icon: VisibilityIcon,
639
- type: 'checkbox',
640
- checked: !self.hideHeaderOverview,
641
- onClick: self.toggleHeaderOverview,
642
- disabled: self.hideHeader,
643
- },
644
- {
645
- label: 'Show no tracks active button',
646
- icon: VisibilityIcon,
647
- type: 'checkbox',
648
- checked: !self.hideNoTracksActive,
649
- onClick: self.toggleNoTracksActive,
650
- },
651
- {
652
- label: 'Show guidelines',
653
- icon: VisibilityIcon,
654
- type: 'checkbox',
655
- checked: self.showGridlines,
656
- onClick: self.toggleShowGridlines,
657
- },
658
- ...(canShowCytobands
659
- ? [
882
+ subMenu: [
660
883
  {
661
- label: 'Show ideogram',
662
- icon: VisibilityIcon,
884
+ label: 'Show all regions in assembly',
885
+ onClick: self.showAllRegionsInAssembly,
886
+ },
887
+ {
888
+ label: 'Show center line',
663
889
  type: 'checkbox',
664
- checked: self.showCytobands,
665
- onClick: () => self.setShowCytobands(!showCytobands),
890
+ checked: self.showCenterLine,
891
+ onClick: self.toggleCenterLine,
666
892
  },
667
- ]
668
- : []),
893
+ {
894
+ label: 'Show header',
895
+ type: 'checkbox',
896
+ checked: !self.hideHeader,
897
+ onClick: self.toggleHeader,
898
+ },
899
+ {
900
+ label: 'Show header overview',
901
+ type: 'checkbox',
902
+ checked: !self.hideHeaderOverview,
903
+ onClick: self.toggleHeaderOverview,
904
+ disabled: self.hideHeader,
905
+ },
906
+ {
907
+ label: 'Show no tracks active button',
908
+ type: 'checkbox',
909
+ checked: !self.hideNoTracksActive,
910
+ onClick: self.toggleNoTracksActive,
911
+ },
912
+ {
913
+ label: 'Show guidelines',
914
+ type: 'checkbox',
915
+ checked: self.showGridlines,
916
+ onClick: self.toggleShowGridlines,
917
+ },
918
+ ...(canShowCytobands
919
+ ? [
920
+ {
921
+ label: 'Show ideogram',
922
+ type: 'checkbox',
923
+ checked: self.showCytobands,
924
+ onClick: () => self.setShowCytobands(!showCytobands),
925
+ },
926
+ ]
927
+ : []),
928
+ ],
929
+ },
669
930
  {
670
931
  label: 'Track labels',
671
932
  icon: LabelIcon,
@@ -708,6 +969,15 @@ export function stateModelFactory(pluginManager) {
708
969
  let currentlyCalculatedStaticBlocks;
709
970
  let stringifiedCurrentlyCalculatedStaticBlocks = '';
710
971
  return {
972
+ /**
973
+ * #getter
974
+ * static blocks are an important concept jbrowse uses to avoid
975
+ * re-rendering when you scroll to the side. when you horizontally
976
+ * scroll to the right, old blocks to the left may be removed, and
977
+ * new blocks may be instantiated on the right. tracks may use the
978
+ * static blocks to render their data for the region represented by
979
+ * the block
980
+ */
711
981
  get staticBlocks() {
712
982
  const ret = calculateStaticBlocks(self);
713
983
  const sret = JSON.stringify(ret);
@@ -717,27 +987,48 @@ export function stateModelFactory(pluginManager) {
717
987
  }
718
988
  return currentlyCalculatedStaticBlocks;
719
989
  },
990
+ /**
991
+ * #getter
992
+ * dynamic blocks represent the exact coordinates of the currently
993
+ * visible genome regions on the screen. they are similar to static
994
+ * blocks, but statcic blocks can go offscreen while dynamic blocks
995
+ * represent exactly what is on screen
996
+ */
720
997
  get dynamicBlocks() {
721
998
  return calculateDynamicBlocks(self);
722
999
  },
1000
+ /**
1001
+ * #getter
1002
+ * rounded dynamic blocks are dynamic blocks without fractions of bp
1003
+ */
723
1004
  get roundedDynamicBlocks() {
724
- return this.dynamicBlocks.contentBlocks.map(block => {
725
- return {
726
- ...block,
727
- start: Math.floor(block.start),
728
- end: Math.ceil(block.end),
729
- };
730
- });
1005
+ return this.dynamicBlocks.contentBlocks.map(block => ({
1006
+ ...block,
1007
+ start: Math.floor(block.start),
1008
+ end: Math.ceil(block.end),
1009
+ }));
731
1010
  },
1011
+ /**
1012
+ * #getter
1013
+ * a single "combo-locstring" representing all the regions visible
1014
+ * on the screen
1015
+ */
732
1016
  get visibleLocStrings() {
733
1017
  return calculateVisibleLocStrings(this.dynamicBlocks.contentBlocks);
734
1018
  },
1019
+ /**
1020
+ * #getter
1021
+ * same as visibleLocStrings, but only updated every 300ms
1022
+ */
735
1023
  get coarseVisibleLocStrings() {
736
1024
  return calculateVisibleLocStrings(self.coarseDynamicBlocks);
737
1025
  },
738
1026
  };
739
1027
  })
740
1028
  .actions(self => ({
1029
+ /**
1030
+ * #action
1031
+ */
741
1032
  setCoarseDynamicBlocks(blocks) {
742
1033
  self.coarseDynamicBlocks = blocks.contentBlocks;
743
1034
  self.coarseTotalBp = blocks.totalBp;
@@ -752,6 +1043,7 @@ export function stateModelFactory(pluginManager) {
752
1043
  }))
753
1044
  .actions(self => ({
754
1045
  /**
1046
+ * #action
755
1047
  * offset is the base-pair-offset in the displayed region, index is the index of the
756
1048
  * displayed region in the linear genome view
757
1049
  *
@@ -761,7 +1053,14 @@ export function stateModelFactory(pluginManager) {
761
1053
  moveTo(start, end) {
762
1054
  moveTo(self, start, end);
763
1055
  },
764
- navToLocString(locString, optAssemblyName) {
1056
+ /**
1057
+ * #action
1058
+ * navigate to the given locstring
1059
+ *
1060
+ * @param locString - e.g. "chr1:1-100"
1061
+ * @param optAssemblyName - (optional) the assembly name to use when navigating to the locstring
1062
+ */
1063
+ async navToLocString(locString, optAssemblyName) {
765
1064
  const { assemblyNames } = self;
766
1065
  const { assemblyManager } = getSession(self);
767
1066
  const { isValidRefName } = assemblyManager;
@@ -771,6 +1070,9 @@ export function stateModelFactory(pluginManager) {
771
1070
  .split(/(\s+)/)
772
1071
  .map(f => f.trim())
773
1072
  .filter(f => !!f);
1073
+ if (assemblyName) {
1074
+ await assemblyManager.waitForAssembly(assemblyName);
1075
+ }
774
1076
  // first try interpreting as a whitespace-separated sequence of
775
1077
  // multiple locstrings
776
1078
  try {
@@ -791,9 +1093,9 @@ export function stateModelFactory(pluginManager) {
791
1093
  throw e;
792
1094
  }
793
1095
  }
794
- const locations = parsedLocStrings === null || parsedLocStrings === void 0 ? void 0 : parsedLocStrings.map(region => {
1096
+ const locations = await Promise.all(parsedLocStrings === null || parsedLocStrings === void 0 ? void 0 : parsedLocStrings.map(async (region) => {
795
1097
  const asmName = region.assemblyName || assemblyName;
796
- const asm = assemblyManager.get(asmName);
1098
+ const asm = await assemblyManager.waitForAssembly(asmName);
797
1099
  const { refName } = region;
798
1100
  if (!asm) {
799
1101
  throw new Error(`assembly ${asmName} not found`);
@@ -806,7 +1108,7 @@ export function stateModelFactory(pluginManager) {
806
1108
  if (!canonicalRefName) {
807
1109
  throw new Error(`Could not find refName ${refName} in ${asm.name}`);
808
1110
  }
809
- const parentRegion = regions.find(region => region.refName === canonicalRefName);
1111
+ const parentRegion = regions.find(r => r.refName === canonicalRefName);
810
1112
  if (!parentRegion) {
811
1113
  throw new Error(`Could not find refName ${refName} in ${asmName}`);
812
1114
  }
@@ -815,7 +1117,7 @@ export function stateModelFactory(pluginManager) {
815
1117
  assemblyName: asmName,
816
1118
  parentRegion,
817
1119
  };
818
- });
1120
+ }));
819
1121
  if (locations.length === 1) {
820
1122
  const loc = locations[0];
821
1123
  self.setDisplayedRegions([
@@ -836,6 +1138,7 @@ export function stateModelFactory(pluginManager) {
836
1138
  }
837
1139
  },
838
1140
  /**
1141
+ * #action
839
1142
  * Navigate to a location based on its refName and optionally start, end,
840
1143
  * and assemblyName. Can handle if there are multiple displayedRegions
841
1144
  * from same refName. Only navigates to a location if it is entirely
@@ -844,11 +1147,14 @@ export function stateModelFactory(pluginManager) {
844
1147
  *
845
1148
  * Throws an error if navigation was unsuccessful
846
1149
  *
847
- * @param location - a proposed location to navigate to
1150
+ * @param query - a proposed location to navigate to
848
1151
  */
849
1152
  navTo(query) {
850
1153
  this.navToMultiple([query]);
851
1154
  },
1155
+ /**
1156
+ * #action
1157
+ */
852
1158
  navToMultiple(locations) {
853
1159
  const firstLocation = locations[0];
854
1160
  let { refName } = firstLocation;
@@ -913,31 +1219,31 @@ export function stateModelFactory(pluginManager) {
913
1219
  this.moveTo({ index, offset: f.reversed ? f.end - e : s - f.start }, { index, offset: f.reversed ? f.end - s : e - f.start });
914
1220
  return;
915
1221
  }
916
- let locationIndex = 0;
917
- let locationStart = 0;
918
- let locationEnd = 0;
919
- for (locationIndex; locationIndex < locations.length; locationIndex++) {
920
- const location = locations[locationIndex];
921
- const region = self.displayedRegions[index + locationIndex];
922
- locationStart = location.start || region.start;
923
- locationEnd = location.end || region.end;
1222
+ let idx = 0;
1223
+ let start = 0;
1224
+ let end = 0;
1225
+ for (idx; idx < locations.length; idx++) {
1226
+ const location = locations[idx];
1227
+ const region = self.displayedRegions[index + idx];
1228
+ start = location.start || region.start;
1229
+ end = location.end || region.end;
924
1230
  if (location.refName !== region.refName) {
925
1231
  throw new Error(`Entered location ${assembleLocString(location)} does not match with displayed regions`);
926
1232
  }
927
1233
  }
928
- locationIndex -= 1;
1234
+ idx -= 1;
929
1235
  const startDisplayedRegion = self.displayedRegions[index];
930
- const endDisplayedRegion = self.displayedRegions[index + locationIndex];
1236
+ const endDisplayedRegion = self.displayedRegions[index + idx];
931
1237
  this.moveTo({
932
1238
  index,
933
1239
  offset: startDisplayedRegion.reversed
934
1240
  ? startDisplayedRegion.end - e
935
1241
  : s - startDisplayedRegion.start,
936
1242
  }, {
937
- index: index + locationIndex,
1243
+ index: index + idx,
938
1244
  offset: endDisplayedRegion.reversed
939
- ? endDisplayedRegion.end - locationStart
940
- : locationEnd - endDisplayedRegion.start,
1245
+ ? endDisplayedRegion.end - start
1246
+ : end - endDisplayedRegion.start,
941
1247
  });
942
1248
  return;
943
1249
  }
@@ -950,6 +1256,9 @@ export function stateModelFactory(pluginManager) {
950
1256
  },
951
1257
  }))
952
1258
  .views(self => ({
1259
+ /**
1260
+ * #method
1261
+ */
953
1262
  rubberBandMenuItems() {
954
1263
  return [
955
1264
  {
@@ -967,10 +1276,14 @@ export function stateModelFactory(pluginManager) {
967
1276
  },
968
1277
  ];
969
1278
  },
1279
+ /**
1280
+ * #method
1281
+ */
970
1282
  bpToPx({ refName, coord, regionNumber, }) {
971
1283
  return bpToPx({ refName, coord, regionNumber, self });
972
1284
  },
973
1285
  /**
1286
+ * #method
974
1287
  * scrolls the view to center on the given bp. if that is not in any
975
1288
  * of the displayed regions, does nothing
976
1289
  * @param coord - basepair at which you want to center the view
@@ -987,9 +1300,15 @@ export function stateModelFactory(pluginManager) {
987
1300
  self.scrollTo(Math.round(centerPx.offsetPx - self.width / 2));
988
1301
  }
989
1302
  },
1303
+ /**
1304
+ * #method
1305
+ */
990
1306
  pxToBp(px) {
991
1307
  return pxToBp(self, px);
992
1308
  },
1309
+ /**
1310
+ * #getter
1311
+ */
993
1312
  get centerLineInfo() {
994
1313
  return self.displayedRegions.length
995
1314
  ? this.pxToBp(self.width / 2)