@jbrowse/plugin-linear-genome-view 5.0.0-beta.16 → 5.0.0-beta.18

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 (33) hide show
  1. package/esm/FeatureTrack/configSchema.d.ts +3 -1
  2. package/esm/FeatureTrack/configSchema.js +3 -1
  3. package/esm/LinearGenomeView/afterAttach.js +6 -4
  4. package/esm/LinearGenomeView/axisConfigSchema.d.ts +18 -0
  5. package/esm/LinearGenomeView/axisConfigSchema.js +22 -0
  6. package/esm/LinearGenomeView/components/Highlight.js +21 -5
  7. package/esm/LinearGenomeView/components/HighlightBand.js +18 -13
  8. package/esm/LinearGenomeView/components/HighlightChip.js +9 -4
  9. package/esm/LinearGenomeView/components/HighlightLabelDialog.d.ts +6 -0
  10. package/esm/LinearGenomeView/components/HighlightLabelDialog.js +18 -0
  11. package/esm/LinearGenomeView/components/LinearGenomeViewContainer.js +3 -1
  12. package/esm/LinearGenomeView/components/SVGHighlightBand.js +3 -3
  13. package/esm/LinearGenomeView/components/TracksContainer.js +2 -2
  14. package/esm/LinearGenomeView/components/useSearchBoxPrefs.d.ts +1 -1
  15. package/esm/LinearGenomeView/components/useSearchBoxPrefs.js +1 -1
  16. package/esm/LinearGenomeView/components/useSideScroll.d.ts +3 -2
  17. package/esm/LinearGenomeView/components/useSideScroll.js +13 -8
  18. package/esm/LinearGenomeView/launchKeys.d.ts +1 -1
  19. package/esm/LinearGenomeView/launchKeys.js +6 -5
  20. package/esm/LinearGenomeView/menuItems.js +4 -4
  21. package/esm/LinearGenomeView/model.d.ts +114 -22
  22. package/esm/LinearGenomeView/model.js +133 -50
  23. package/esm/LinearGenomeView/rExport/rScript.d.ts +21 -0
  24. package/esm/LinearGenomeView/rExport/rScript.js +3 -3
  25. package/esm/LinearGenomeView/sharedScaleContainer.js +2 -12
  26. package/esm/LinearGenomeView/showFiles.d.ts +2 -0
  27. package/esm/LinearGenomeView/showFiles.js +19 -0
  28. package/esm/LinearGenomeView/svgcomponents/useViewSvgFigure.js +2 -2
  29. package/esm/TrackModifiers/index.d.ts +80 -0
  30. package/esm/TrackModifiers/index.js +212 -0
  31. package/esm/index.d.ts +3 -1
  32. package/esm/index.js +1 -0
  33. package/package.json +9 -8
@@ -1,4 +1,4 @@
1
- import type { BpOffset, ExportSvgOptions, HighlightType, InitState, NavLocation, ViewTrackLabelMode, VolatileGuide } from './types.ts';
1
+ import type { BpOffset, ExportSvgOptions, HighlightInput, HighlightType, InitState, NavLocation, ViewTrackLabelMode, VolatileGuide } from './types.ts';
2
2
  import type { RegionEdit } from './util.ts';
3
3
  import type PluginManager from '@jbrowse/core/PluginManager';
4
4
  import type BaseResult from '@jbrowse/core/TextSearch/BaseResults';
@@ -20,18 +20,24 @@ export interface SearchPickerRow {
20
20
  trackName: string;
21
21
  }
22
22
  /**
23
- * The hits of a name search that point at more than one place, waiting for the
24
- * user to choose. A host draws them however it likes: the Material view shows
25
- * a dialog, and `SearchPicker` in `@jbrowse/display-ui/embed` a plain list.
23
+ * A name search's hits as a host lists them: what `view.search` returns, and
24
+ * what the picker holds.
26
25
  */
27
- export interface SearchPickerState {
26
+ export interface SearchHits {
28
27
  query: string;
29
28
  assemblyName: string;
30
- /** one row per place, hits in a track the view already shows first */
29
+ /** one row per hit, hits in a track the view already shows first */
31
30
  rows: SearchPickerRow[];
32
- /** navigates to the row's place, reports a failure and closes the picker */
31
+ /** lands on the row's place and reports a failure */
33
32
  pick: (id: string) => Promise<unknown>;
34
33
  }
34
+ /**
35
+ * The hits of a name search that point at more than one place, waiting for the
36
+ * user to choose; its `pick` also closes the picker. A host draws them however
37
+ * it likes: the Material view shows a dialog, and `SearchPicker` in
38
+ * `@jbrowse/display-ui/embed` a plain list.
39
+ */
40
+ export type SearchPickerState = SearchHits;
35
41
  export type { PaddingSpan } from './util.ts';
36
42
  export interface HighlightRegion {
37
43
  assemblyName?: string;
@@ -55,7 +61,7 @@ export interface HighlightRegion {
55
61
  * views: [
56
62
  * {
57
63
  * type: 'LinearGenomeView',
58
- * colorByCDS: true,
64
+ * colorByFrame: true,
59
65
  * assembly: 'hg38',
60
66
  * loc: 'chr1:1,000,000-1,100,000',
61
67
  * tracks: ['genes', 'alignments'],
@@ -65,7 +71,7 @@ export interface HighlightRegion {
65
71
  * ```
66
72
  * `assembly`, `loc`, `tracks`, `tracklist`, `nav` and `highlight` need
67
73
  * on-attach resolution and are captured into the `launch` property below;
68
- * `colorByCDS`, `showAminoAcids`, `showCenterLine` and `trackLabels` are plain
74
+ * `colorByFrame`, `showAminoAcids`, `showCenterLine` and `trackLabels` are plain
69
75
  * view props MST restores natively. Both are written the same way.
70
76
  * At runtime the same model is driven imperatively — every property and action
71
77
  * below is reachable on `viewState.session.views[0]`:
@@ -80,7 +86,7 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
80
86
  id: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<string>, [undefined]>;
81
87
  displayName: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<string>>;
82
88
  minimized: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
83
- }, "colorByCDS" | "displayedRegions" | "hideHeader" | "hideHeaderOverview" | "hideNoTracksActive" | "id" | "launch" | "legacyBpPerPx" | "scalebarOnly" | "showAminoAcids" | "showCenterLine" | "showCytobands" | "showGridlines" | "showTrackOutlines" | "trackLabels" | "trackSelectorType" | "tracks" | "type" | "windowStartBp" | "windowWidthBp"> & {
89
+ }, "axis" | "colorByFrame" | "displayedRegions" | "hideHeader" | "hideHeaderOverview" | "hideNoTracksActive" | "id" | "launch" | "legacyBpPerPx" | "scalebarOnly" | "showAminoAcids" | "showCenterLine" | "showCytobands" | "showTrackOutlines" | "trackLabels" | "trackSelectorType" | "tracks" | "type" | "windowStartBp" | "windowWidthBp"> & {
84
90
  id: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<string>, [undefined]>;
85
91
  type: import("@jbrowse/mobx-state-tree").IType<string | undefined, string, string>;
86
92
  windowStartBp: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<number>, [undefined]>;
@@ -95,8 +101,14 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
95
101
  showCenterLine: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
96
102
  showCytobands: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
97
103
  trackLabels: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<string>, [undefined]>;
98
- showGridlines: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
99
- colorByCDS: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
104
+ axis: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
105
+ readonly grid: {
106
+ type: "boolean";
107
+ } & {
108
+ defaultValue: boolean;
109
+ };
110
+ }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined, undefined, import("@jbrowse/core/configuration").ConfigurationSchemaRequirement<Partial<Record<string, string[]>>, string>, any>>, [undefined]>;
111
+ colorByFrame: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
100
112
  showAminoAcids: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
101
113
  showTrackOutlines: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
102
114
  scalebarOnly: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
@@ -166,6 +178,13 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
166
178
  * #volatile
167
179
  */
168
180
  coarseBpPerPx: number;
181
+ /**
182
+ * #volatile
183
+ * the scroll offset the coarse blocks were laid out at, in px at
184
+ * `coarseBpPerPx`: the settled viewport's left edge, which the first
185
+ * coarse block is not while the view is scrolled before the first region
186
+ */
187
+ coarseOffsetPx: number;
169
188
  /**
170
189
  * #volatile
171
190
  */
@@ -184,6 +203,11 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
184
203
  */
185
204
  volatileGuides: VolatileGuide[];
186
205
  } & {
206
+ /**
207
+ * #getter
208
+ * `axis.grid`: whether the ruler's ticks run down through the tracks.
209
+ */
210
+ readonly axisGrid: boolean;
187
211
  /**
188
212
  * #getter
189
213
  * the launch state that still has something to apply — the gate every
@@ -857,7 +881,7 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
857
881
  /**
858
882
  * #action
859
883
  */
860
- setColorByCDS(flag: boolean): void;
884
+ setColorByFrame(flag: boolean): void;
861
885
  /**
862
886
  * #action
863
887
  */
@@ -916,7 +940,7 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
916
940
  /**
917
941
  * #action
918
942
  */
919
- setShowGridlines(b: boolean): void;
943
+ setAxisGrid(grid: boolean): void;
920
944
  /**
921
945
  * #action
922
946
  * set temporary vertical guides (e.g., for LD display hover)
@@ -956,6 +980,15 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
956
980
  * there and shows the track its index came from
957
981
  */
958
982
  setSearchResults(searchResults: BaseResult[], searchQuery: string, assemblyName: string, onPick?: (result: BaseResult) => Promise<unknown>): void;
983
+ /**
984
+ * #action
985
+ * Search the view's assembly by name, for a host listing the hits
986
+ * itself. A row's `pick` lands as the search box does: it navigates
987
+ * there and shows the track the hit's index came from.
988
+ */
989
+ search(query: string, opts?: {
990
+ signal?: AbortSignal;
991
+ }): Promise<SearchHits>;
959
992
  /**
960
993
  * #action
961
994
  */
@@ -977,6 +1010,22 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
977
1010
  * loaded: loads it, then shows
978
1011
  */
979
1012
  launchTrack(trackId: string, initialSnapshot?: any, displayInitialSnapshot?: any, inlineConf?: Record<string, unknown>): Promise<any>;
1013
+ /**
1014
+ * #action
1015
+ * Replace the highlights `highlights` reads, each written as the launch
1016
+ * spec's `highlight` writes one: a locstring, or an object whose
1017
+ * `assemblyName` defaults to the view's. Throws on one that names no
1018
+ * region, writing none.
1019
+ */
1020
+ setHighlights(highlights: readonly (string | HighlightInput)[]): void;
1021
+ /**
1022
+ * #action
1023
+ * Show files from the user's disk as session tracks: one per data file,
1024
+ * beside the index among them that names it, its type guessed from its
1025
+ * name. Adds nothing when one file has no known type. Resolves the new
1026
+ * tracks' ids.
1027
+ */
1028
+ showFiles(files: readonly File[]): Promise<string[]>;
980
1029
  } & {
981
1030
  /**
982
1031
  * #method
@@ -1808,7 +1857,7 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
1808
1857
  id: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<string>, [undefined]>;
1809
1858
  displayName: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<string>>;
1810
1859
  minimized: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
1811
- }, "colorByCDS" | "displayedRegions" | "hideHeader" | "hideHeaderOverview" | "hideNoTracksActive" | "id" | "launch" | "legacyBpPerPx" | "scalebarOnly" | "showAminoAcids" | "showCenterLine" | "showCytobands" | "showGridlines" | "showTrackOutlines" | "trackLabels" | "trackSelectorType" | "tracks" | "type" | "windowStartBp" | "windowWidthBp"> & {
1860
+ }, "axis" | "colorByFrame" | "displayedRegions" | "hideHeader" | "hideHeaderOverview" | "hideNoTracksActive" | "id" | "launch" | "legacyBpPerPx" | "scalebarOnly" | "showAminoAcids" | "showCenterLine" | "showCytobands" | "showTrackOutlines" | "trackLabels" | "trackSelectorType" | "tracks" | "type" | "windowStartBp" | "windowWidthBp"> & {
1812
1861
  id: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<string>, [undefined]>;
1813
1862
  type: import("@jbrowse/mobx-state-tree").IType<string | undefined, string, string>;
1814
1863
  windowStartBp: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<number>, [undefined]>;
@@ -1823,8 +1872,14 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
1823
1872
  showCenterLine: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
1824
1873
  showCytobands: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
1825
1874
  trackLabels: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<string>, [undefined]>;
1826
- showGridlines: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
1827
- colorByCDS: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
1875
+ axis: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
1876
+ readonly grid: {
1877
+ type: "boolean";
1878
+ } & {
1879
+ defaultValue: boolean;
1880
+ };
1881
+ }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined, undefined, import("@jbrowse/core/configuration").ConfigurationSchemaRequirement<Partial<Record<string, string[]>>, string>, any>>, [undefined]>;
1882
+ colorByFrame: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
1828
1883
  showAminoAcids: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
1829
1884
  showTrackOutlines: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
1830
1885
  scalebarOnly: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
@@ -1894,6 +1949,13 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
1894
1949
  * #volatile
1895
1950
  */
1896
1951
  coarseBpPerPx: number;
1952
+ /**
1953
+ * #volatile
1954
+ * the scroll offset the coarse blocks were laid out at, in px at
1955
+ * `coarseBpPerPx`: the settled viewport's left edge, which the first
1956
+ * coarse block is not while the view is scrolled before the first region
1957
+ */
1958
+ coarseOffsetPx: number;
1897
1959
  /**
1898
1960
  * #volatile
1899
1961
  */
@@ -1912,6 +1974,11 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
1912
1974
  */
1913
1975
  volatileGuides: VolatileGuide[];
1914
1976
  } & {
1977
+ /**
1978
+ * #getter
1979
+ * `axis.grid`: whether the ruler's ticks run down through the tracks.
1980
+ */
1981
+ readonly axisGrid: boolean;
1915
1982
  /**
1916
1983
  * #getter
1917
1984
  * the launch state that still has something to apply — the gate every
@@ -2585,7 +2652,7 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
2585
2652
  /**
2586
2653
  * #action
2587
2654
  */
2588
- setColorByCDS(flag: boolean): void;
2655
+ setColorByFrame(flag: boolean): void;
2589
2656
  /**
2590
2657
  * #action
2591
2658
  */
@@ -2644,7 +2711,7 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
2644
2711
  /**
2645
2712
  * #action
2646
2713
  */
2647
- setShowGridlines(b: boolean): void;
2714
+ setAxisGrid(grid: boolean): void;
2648
2715
  /**
2649
2716
  * #action
2650
2717
  * set temporary vertical guides (e.g., for LD display hover)
@@ -2684,6 +2751,15 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
2684
2751
  * there and shows the track its index came from
2685
2752
  */
2686
2753
  setSearchResults(searchResults: BaseResult[], searchQuery: string, assemblyName: string, onPick?: (result: BaseResult) => Promise<unknown>): void;
2754
+ /**
2755
+ * #action
2756
+ * Search the view's assembly by name, for a host listing the hits
2757
+ * itself. A row's `pick` lands as the search box does: it navigates
2758
+ * there and shows the track the hit's index came from.
2759
+ */
2760
+ search(query: string, opts?: {
2761
+ signal?: AbortSignal;
2762
+ }): Promise<SearchHits>;
2687
2763
  /**
2688
2764
  * #action
2689
2765
  */
@@ -2705,6 +2781,22 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
2705
2781
  * loaded: loads it, then shows
2706
2782
  */
2707
2783
  launchTrack(trackId: string, initialSnapshot?: any, displayInitialSnapshot?: any, inlineConf?: Record<string, unknown>): Promise<any>;
2784
+ /**
2785
+ * #action
2786
+ * Replace the highlights `highlights` reads, each written as the launch
2787
+ * spec's `highlight` writes one: a locstring, or an object whose
2788
+ * `assemblyName` defaults to the view's. Throws on one that names no
2789
+ * region, writing none.
2790
+ */
2791
+ setHighlights(highlights: readonly (string | HighlightInput)[]): void;
2792
+ /**
2793
+ * #action
2794
+ * Show files from the user's disk as session tracks: one per data file,
2795
+ * beside the index among them that names it, its type guessed from its
2796
+ * name. Adds nothing when one file has no known type. Resolves the new
2797
+ * tracks' ids.
2798
+ */
2799
+ showFiles(files: readonly File[]): Promise<string[]>;
2708
2800
  } & {
2709
2801
  /**
2710
2802
  * #method
@@ -3532,7 +3624,7 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
3532
3624
  } & {
3533
3625
  afterCreate(): void;
3534
3626
  afterAttach(): void;
3535
- }, import("@jbrowse/mobx-state-tree")._NotCustomized, import("@jbrowse/mobx-state-tree")._NotCustomized>, InitState, "bpPerPx" | "offsetPx" | "showCytobandsSetting">, {
3627
+ }, import("@jbrowse/mobx-state-tree")._NotCustomized, import("@jbrowse/mobx-state-tree")._NotCustomized>, InitState, "bpPerPx" | "colorByCDS" | "offsetPx" | "showCytobandsSetting">, {
3536
3628
  displayName: string | undefined;
3537
3629
  minimized: boolean;
3538
3630
  id: string;
@@ -3548,8 +3640,8 @@ export declare function stateModelFactory(pluginManager: PluginManager): import(
3548
3640
  trackSelectorType: "hierarchical";
3549
3641
  showCytobands: boolean;
3550
3642
  trackLabels: string;
3551
- showGridlines: boolean;
3552
- colorByCDS: boolean;
3643
+ axis: import("@jbrowse/mobx-state-tree").ModelSnapshotType<Record<string, any>>;
3644
+ colorByFrame: boolean;
3553
3645
  showAminoAcids: boolean;
3554
3646
  showTrackOutlines: boolean;
3555
3647
  scalebarOnly: boolean;
@@ -1,5 +1,5 @@
1
1
  import { canonicalLocString } from '@jbrowse/core/TextSearch/places';
2
- import { getConf } from '@jbrowse/core/configuration';
2
+ import { getConf, readConfObject } from '@jbrowse/core/configuration';
3
3
  import { BaseViewModel } from '@jbrowse/core/pluggableElementTypes/models';
4
4
  import { exportViewSvg } from '@jbrowse/core/svg/exportViewSvg';
5
5
  import { assembleLocString, clamp, getBpDisplayStr, getNotificationSink, getSession, isSessionModelWithWidgets, localStorageGetBoolean, localStorageGetItem, localStorageSetBoolean, localStorageSetItem, springAnimate, sum, } from '@jbrowse/core/util';
@@ -8,6 +8,7 @@ import { scaleBandHeights } from '@jbrowse/core/util/bandHeight';
8
8
  import { wholeBaseRegions } from '@jbrowse/core/util/blockTypes';
9
9
  import calculateDynamicBlocks from '@jbrowse/core/util/calculateDynamicBlocks';
10
10
  import calculateStaticBlocks from '@jbrowse/core/util/calculateStaticBlocks';
11
+ import { coerceHighlight } from '@jbrowse/core/util/highlights';
11
12
  import { hideTrackGeneric, launchToggleTrackGeneric, launchTrackGeneric, showTrackGeneric, toggleTrackGeneric, } from '@jbrowse/core/util/tracks';
12
13
  import { ElementId } from '@jbrowse/core/util/types/mst';
13
14
  import { highlightsOnAssemblies } from '@jbrowse/core/util/viewHighlights';
@@ -15,10 +16,11 @@ import { assemblyErrorMessage, computeViewStatus, viewLoading, } from '@jbrowse/
15
16
  import { pendingLaunch, withLaunchInput, } from '@jbrowse/core/util/withLaunchInput';
16
17
  import { MIN_DISPLAY_HEIGHT } from '@jbrowse/display-kit/const';
17
18
  import { contentRightEdgePx } from '@jbrowse/display-kit/regionHost';
18
- import { cast, getParent, hasParent, isAlive, types, } from '@jbrowse/mobx-state-tree';
19
+ import { cast, getParent, getSnapshot, hasParent, isAlive, types, } from '@jbrowse/mobx-state-tree';
19
20
  import { observable, when } from 'mobx';
20
- import { handleSelectedRegion, isOpenInView, navToOption, } from '../searchUtils.js';
21
+ import { fetchResults, handleSelectedRegion, isOpenInView, navToOption, } from '../searchUtils.js';
21
22
  import { doAfterAttach } from './afterAttach.js';
23
+ import { linearGenomeViewAxisConfigSchema } from './axisConfigSchema.js';
22
24
  import { getCytobands, shouldSwapTracks } from './components/util.js';
23
25
  import { HEADER_BAR_HEIGHT, HEADER_OVERVIEW_HEIGHT, MIN_BP_PER_PX, MINIMIZED_TRACK_HEIGHT, MINIMUM_BLOCK_WIDTH, RESIZE_ALL_HANDLE_HEIGHT, RESIZE_HANDLE_HEIGHT, SCALE_BAR_HEIGHT, SHOW_ALL_REGIONS_FILL, TRACK_OUTLINE_BORDER, TRACK_TOP_GAP, } from './consts.js';
24
26
  import { planFlight } from './flyTo.js';
@@ -26,7 +28,43 @@ import { setupKeyboardHandler } from './keyboardHandler.js';
26
28
  import { lgvLaunchKeys } from './launchKeys.js';
27
29
  import { buildHighlightsSubMenuItems, buildMenuItems, buildRubberBandMenuItems, buildRubberbandClickMenuItems, } from './menuItems.js';
28
30
  import { sharedScaleContainerOf } from './sharedScaleContainer.js';
31
+ import { showFiles } from './showFiles.js';
29
32
  import { calculateVisibleLocStrings, cytobandLabelGutterWidth, expandRegion, fitAllRegionsWindow, generateLocations, getGridlineTicks, getPaddingSpans, getScalebarLabels, getScalebarRefNameLabels, regionsOrientation, setDisplayedRegionsKeepingCenter, } from './util.js';
33
+ function searchHitsOf(model, results, query, assemblyName, land) {
34
+ const session = getSession(model);
35
+ const assembly = session.assemblyManager.get(assemblyName);
36
+ const ordered = [...results].sort((a, b) => Number(isOpenInView(b, model)) - Number(isOpenInView(a, model)));
37
+ return {
38
+ query,
39
+ assemblyName,
40
+ rows: ordered.map(result => {
41
+ const location = result.getLocation() ?? '';
42
+ const trackId = result.getTrackId();
43
+ return {
44
+ id: result.getId(),
45
+ label: result.getLabel(),
46
+ location: assembly && location
47
+ ? canonicalLocString(location, assembly)
48
+ : location,
49
+ trackName: trackId ? (session.getTrackById(trackId)?.name ?? '') : '',
50
+ };
51
+ }),
52
+ pick: async (id) => {
53
+ const picked = ordered.find(result => result.getId() === id);
54
+ try {
55
+ if (picked) {
56
+ await land(picked);
57
+ }
58
+ }
59
+ catch (e) {
60
+ console.error(e);
61
+ if (isAlive(model)) {
62
+ getNotificationSink(model).notifyError(`${e}`, e);
63
+ }
64
+ }
65
+ },
66
+ };
67
+ }
30
68
  /**
31
69
  * Calculate the offsetPx needed to center content within a viewport.
32
70
  * Returns a negative offset when content is smaller than viewport (padding on left).
@@ -154,7 +192,7 @@ function isTrackSelectorVisible(self) {
154
192
  * views: [
155
193
  * {
156
194
  * type: 'LinearGenomeView',
157
- * colorByCDS: true,
195
+ * colorByFrame: true,
158
196
  * assembly: 'hg38',
159
197
  * loc: 'chr1:1,000,000-1,100,000',
160
198
  * tracks: ['genes', 'alignments'],
@@ -164,7 +202,7 @@ function isTrackSelectorVisible(self) {
164
202
  * ```
165
203
  * `assembly`, `loc`, `tracks`, `tracklist`, `nav` and `highlight` need
166
204
  * on-attach resolution and are captured into the `launch` property below;
167
- * `colorByCDS`, `showAminoAcids`, `showCenterLine` and `trackLabels` are plain
205
+ * `colorByFrame`, `showAminoAcids`, `showCenterLine` and `trackLabels` are plain
168
206
  * view props MST restores natively. Both are written the same way.
169
207
  * At runtime the same model is driven imperatively — every property and action
170
208
  * below is reachable on `viewState.session.views[0]`:
@@ -267,7 +305,7 @@ export function stateModelFactory(pluginManager) {
267
305
  /**
268
306
  * #property
269
307
  * show the "center line". A personal preference: never in a session
270
- * snapshot. It, showCytobands, trackLabels, colorByCDS, showAminoAcids
308
+ * snapshot. It, showCytobands, trackLabels, colorByFrame, showAminoAcids
271
309
  * and showTrackOutlines start from this browser's last choice, which
272
310
  * their setters record.
273
311
  */
@@ -291,20 +329,21 @@ export function stateModelFactory(pluginManager) {
291
329
  trackLabels: types.optional(types.string, () => localStorageGetItem('lgv-trackLabels') ?? ''),
292
330
  /**
293
331
  * #property
294
- * show the "gridlines" in the track area
332
+ * The ruler's guide, a [](/docs/config/lineargenomeviewaxis) object:
333
+ * `{ grid: false }` stops its ticks running down through the tracks.
295
334
  */
296
- showGridlines: types.stripDefault(types.boolean, true),
335
+ axis: types.stripDefault(linearGenomeViewAxisConfigSchema, {}),
297
336
  /**
298
337
  * #property
299
338
  * color CDS segments by reading frame
300
339
  */
301
- colorByCDS: types.optional(types.boolean, () => localStorageGetBoolean('lgv-colorByCDS', false)),
340
+ colorByFrame: types.optional(types.boolean, () => localStorageGetBoolean('lgv-colorByFrame', false)),
302
341
  /**
303
342
  * #property
304
343
  * draw translated codons on coding features once zoomed in far enough:
305
344
  * an alternating per-codon shading, and the amino acid letters on top of
306
- * it at base-level zoom. Independent of `colorByCDS`, which only recolors
307
- * the segments by frame.
345
+ * it at base-level zoom. Independent of `colorByFrame`, which only
346
+ * recolors the segments by frame.
308
347
  */
309
348
  showAminoAcids: types.optional(types.boolean, () => localStorageGetBoolean('lgv-showAminoAcids', true)),
310
349
  /**
@@ -386,6 +425,13 @@ export function stateModelFactory(pluginManager) {
386
425
  // displays that lay out against it; `setWidth` seeds the true one at
387
426
  // the first measure.
388
427
  coarseBpPerPx: 1,
428
+ /**
429
+ * #volatile
430
+ * the scroll offset the coarse blocks were laid out at, in px at
431
+ * `coarseBpPerPx`: the settled viewport's left edge, which the first
432
+ * coarse block is not while the view is scrolled before the first region
433
+ */
434
+ coarseOffsetPx: 0,
389
435
  /**
390
436
  * #volatile
391
437
  */
@@ -406,6 +452,13 @@ export function stateModelFactory(pluginManager) {
406
452
  };
407
453
  })
408
454
  .views(self => ({
455
+ /**
456
+ * #getter
457
+ * `axis.grid`: whether the ruler's ticks run down through the tracks.
458
+ */
459
+ get axisGrid() {
460
+ return readConfObject(self.axis, 'grid');
461
+ },
409
462
  // The viewport in pixels, derived from the window it frames — declared
410
463
  // ahead of every other getter so that the ~300 reads of `self.bpPerPx` /
411
464
  // `self.offsetPx` across the codebase go on resolving by name. Only the
@@ -1053,9 +1106,9 @@ export function stateModelFactory(pluginManager) {
1053
1106
  /**
1054
1107
  * #action
1055
1108
  */
1056
- setColorByCDS(flag) {
1057
- self.colorByCDS = flag;
1058
- localStorageSetBoolean('lgv-colorByCDS', flag);
1109
+ setColorByFrame(flag) {
1110
+ self.colorByFrame = flag;
1111
+ localStorageSetBoolean('lgv-colorByFrame', flag);
1059
1112
  },
1060
1113
  /**
1061
1114
  * #action
@@ -1130,6 +1183,7 @@ export function stateModelFactory(pluginManager) {
1130
1183
  // The debounced coarse autorun is 500ms out; a restored snapshot's
1131
1184
  // consumers would lay out and fetch at 1 bp/px until then.
1132
1185
  self.coarseBpPerPx = self.bpPerPx;
1186
+ self.coarseOffsetPx = self.offsetPx;
1133
1187
  }
1134
1188
  },
1135
1189
  /**
@@ -1171,8 +1225,8 @@ export function stateModelFactory(pluginManager) {
1171
1225
  /**
1172
1226
  * #action
1173
1227
  */
1174
- setShowGridlines(b) {
1175
- self.showGridlines = b;
1228
+ setAxisGrid(grid) {
1229
+ self.axis = cast({ ...getSnapshot(self.axis), grid });
1176
1230
  },
1177
1231
  /**
1178
1232
  * #action
@@ -1255,40 +1309,11 @@ export function stateModelFactory(pluginManager) {
1255
1309
  model: self,
1256
1310
  assemblyName,
1257
1311
  })) {
1258
- const session = getSession(self);
1259
- const assembly = session.assemblyManager.get(assemblyName);
1260
- const ordered = [...searchResults].sort((a, b) => Number(isOpenInView(b, self)) -
1261
- Number(isOpenInView(a, self)));
1312
+ const hits = searchHitsOf(self, searchResults, searchQuery, assemblyName, onPick);
1262
1313
  const picker = {
1263
- query: searchQuery,
1264
- assemblyName,
1265
- rows: ordered.map(result => {
1266
- const location = result.getLocation() ?? '';
1267
- const trackId = result.getTrackId();
1268
- return {
1269
- id: result.getId(),
1270
- label: result.getLabel(),
1271
- location: assembly && location
1272
- ? canonicalLocString(location, assembly)
1273
- : location,
1274
- trackName: trackId
1275
- ? (session.getTrackById(trackId)?.name ?? '')
1276
- : '',
1277
- };
1278
- }),
1314
+ ...hits,
1279
1315
  pick: async (id) => {
1280
- const picked = ordered.find(result => result.getId() === id);
1281
- try {
1282
- if (picked) {
1283
- await onPick(picked);
1284
- }
1285
- }
1286
- catch (e) {
1287
- console.error(e);
1288
- if (isAlive(self)) {
1289
- getNotificationSink(self).notifyError(`${e}`, e);
1290
- }
1291
- }
1316
+ await hits.pick(id);
1292
1317
  if (isAlive(self) && self.searchPicker === picker) {
1293
1318
  self.closeSearchPicker();
1294
1319
  }
@@ -1296,6 +1321,31 @@ export function stateModelFactory(pluginManager) {
1296
1321
  };
1297
1322
  self.searchPicker = picker;
1298
1323
  },
1324
+ /**
1325
+ * #action
1326
+ * Search the view's assembly by name, for a host listing the hits
1327
+ * itself. A row's `pick` lands as the search box does: it navigates
1328
+ * there and shows the track the hit's index came from.
1329
+ */
1330
+ async search(query, opts) {
1331
+ const assemblyName = self.assemblyNames[0] ?? self.launchAssemblyName;
1332
+ if (!assemblyName) {
1333
+ throw new Error('the view has no assembly to search yet');
1334
+ }
1335
+ const { assemblyManager, textSearchManager } = getSession(self);
1336
+ const results = await fetchResults({
1337
+ queryString: query,
1338
+ assemblyName,
1339
+ textSearchManager,
1340
+ assembly: await assemblyManager.waitForAssembly(assemblyName),
1341
+ signal: opts?.signal,
1342
+ });
1343
+ return searchHitsOf(self, results, query, assemblyName, result => navToOption({
1344
+ option: result,
1345
+ model: self,
1346
+ assemblyName,
1347
+ }));
1348
+ },
1299
1349
  /**
1300
1350
  * #action
1301
1351
  */
@@ -1328,6 +1378,34 @@ export function stateModelFactory(pluginManager) {
1328
1378
  async launchTrack(trackId, initialSnapshot = {}, displayInitialSnapshot = {}, inlineConf) {
1329
1379
  return launchTrackGeneric(self, trackId, initialSnapshot, displayInitialSnapshot, inlineConf);
1330
1380
  },
1381
+ /**
1382
+ * #action
1383
+ * Replace the highlights `highlights` reads, each written as the launch
1384
+ * spec's `highlight` writes one: a locstring, or an object whose
1385
+ * `assemblyName` defaults to the view's. Throws on one that names no
1386
+ * region, writing none.
1387
+ */
1388
+ setHighlights(highlights) {
1389
+ const session = getSession(self);
1390
+ const assemblyName = self.assemblyNames[0] ?? self.launchAssemblyName ?? '';
1391
+ session.setHighlights(highlights.map(h => {
1392
+ const highlight = coerceHighlight(h, assemblyName, (ref, asm) => session.assemblyManager.isValidRefName(ref, asm ?? assemblyName));
1393
+ if (!highlight) {
1394
+ throw new Error(`not a region to highlight: ${JSON.stringify(h)}`);
1395
+ }
1396
+ return highlight;
1397
+ }));
1398
+ },
1399
+ /**
1400
+ * #action
1401
+ * Show files from the user's disk as session tracks: one per data file,
1402
+ * beside the index among them that names it, its type guessed from its
1403
+ * name. Adds nothing when one file has no known type. Resolves the new
1404
+ * tracks' ids.
1405
+ */
1406
+ async showFiles(files) {
1407
+ return showFiles(self, files);
1408
+ },
1331
1409
  }))
1332
1410
  .views(self => ({
1333
1411
  /**
@@ -2158,6 +2236,9 @@ export function stateModelFactory(pluginManager) {
2158
2236
  self.coarseTotalBp = blocks.totalBp;
2159
2237
  self.coarseBpPerPx = bpPerPx;
2160
2238
  }
2239
+ // on every call, since a scroll through the padding before the first
2240
+ // region moves the viewport and leaves the blocks the same
2241
+ self.coarseOffsetPx = self.offsetPx;
2161
2242
  },
2162
2243
  }))
2163
2244
  .actions(self => ({
@@ -2891,12 +2972,14 @@ export function stateModelFactory(pluginManager) {
2891
2972
  return snap;
2892
2973
  }
2893
2974
  // v4's `showCytobandsSetting` persists as the bare `showCytobands` prop
2894
- // (the capability-gated getter is `effectiveShowCytobands`).
2895
- const { showCytobandsSetting, offsetPx, bpPerPx, ...rest } = snap;
2975
+ // (the capability-gated getter is `effectiveShowCytobands`), and v4's
2976
+ // `colorByCDS` as `colorByFrame`.
2977
+ const { showCytobandsSetting, colorByCDS, offsetPx, bpPerPx, ...rest } = snap;
2896
2978
  return {
2897
2979
  ...(showCytobandsSetting !== undefined
2898
2980
  ? { showCytobands: showCytobandsSetting }
2899
2981
  : {}),
2982
+ ...(colorByCDS !== undefined ? { colorByFrame: colorByCDS } : {}),
2900
2983
  // The viewport used to persist as pixels. Half of that converts
2901
2984
  // exactly and needs no width — the left edge in bp is offsetPx *
2902
2985
  // bpPerPx — and half of it cannot convert at all, because the width
@@ -15,6 +15,18 @@ export interface RExportTrack {
15
15
  heightMode?: unknown;
16
16
  height?: unknown;
17
17
  }
18
+ /**
19
+ * Each display ggjbrowse reads, by the reader that reads it, and the adapters
20
+ * it opens (the slot holding the file and the extension the reader knows it
21
+ * by).
22
+ */
23
+ export declare const READERS: Record<string, {
24
+ call: string;
25
+ adapters: Record<string, {
26
+ slot?: string;
27
+ ext?: RegExp;
28
+ }>;
29
+ }>;
18
30
  /** The ggjbrowse release whose readers and `jbrowse_stack` the script calls. */
19
31
  export declare const GGJBROWSE_VERSION = "0.10.0";
20
32
  /**
@@ -35,6 +47,15 @@ export declare function rValue(value: unknown): string;
35
47
  * `file://` URL as its path, or a `localPath`.
36
48
  */
37
49
  export declare function locationPath(location: unknown): string | undefined;
50
+ /**
51
+ * Each sequence adapter `jbrowse_assembly()` builds from a path, by the
52
+ * extension ggjbrowse reads it off, and the index each takes beside it.
53
+ */
54
+ export declare const SEQUENCE_ADAPTERS: Record<string, {
55
+ slot: string;
56
+ ext: RegExp;
57
+ beside: Record<string, string>;
58
+ }>;
38
59
  /**
39
60
  * The view's assembly as the R value every reader takes: `jbrowse_assembly()`
40
61
  * of its sequence and alias files where ggjbrowse builds the same config from