@jbrowse/app-core 4.3.0 → 5.0.0-beta.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 (154) hide show
  1. package/esm/AppSession/AppRootModel.d.ts +30 -0
  2. package/esm/AppSession/AppRootModel.js +1 -0
  3. package/esm/AppSession/AppSessionMixin.d.ts +1598 -0
  4. package/esm/AppSession/AppSessionMixin.js +62 -0
  5. package/esm/AppSession/index.d.ts +2 -0
  6. package/esm/AppSession/index.js +1 -0
  7. package/esm/Assemblies/AssembliesMixin.d.ts +225 -0
  8. package/esm/Assemblies/AssembliesMixin.js +149 -0
  9. package/esm/Assemblies/index.d.ts +1 -2
  10. package/esm/Assemblies/index.js +1 -2
  11. package/esm/HistoryManagement/index.d.ts +19 -0
  12. package/esm/HistoryManagement/index.js +42 -5
  13. package/esm/JBrowseConfig/RootConfiguration.d.ts +167 -78
  14. package/esm/JBrowseConfig/RootConfiguration.js +85 -7
  15. package/esm/JBrowseConfig/index.d.ts +169 -84
  16. package/esm/JBrowseConfig/index.js +62 -2
  17. package/esm/JBrowseModel/index.d.ts +176 -95
  18. package/esm/JBrowseModel/index.js +122 -21
  19. package/esm/RootMenu/index.d.ts +77 -2
  20. package/esm/RootMenu/index.js +107 -61
  21. package/esm/SessionSpec/index.d.ts +6 -0
  22. package/esm/SessionSpec/index.js +3 -0
  23. package/esm/SessionSpec/lgvUrlInit.d.ts +79 -0
  24. package/esm/SessionSpec/lgvUrlInit.js +158 -0
  25. package/esm/SessionSpec/loadSessionSpec.d.ts +21 -0
  26. package/esm/SessionSpec/loadSessionSpec.js +311 -0
  27. package/esm/SessionSpec/parseSessionSpecUrl.d.ts +13 -0
  28. package/esm/SessionSpec/parseSessionSpecUrl.js +196 -0
  29. package/esm/SessionSpec/types.d.ts +33 -0
  30. package/esm/SessionSpec/types.js +1 -0
  31. package/esm/WorkspaceLayout/LayoutRenderer.d.ts +24 -0
  32. package/esm/WorkspaceLayout/LayoutRenderer.js +185 -0
  33. package/esm/WorkspaceLayout/PanelView.d.ts +13 -0
  34. package/esm/WorkspaceLayout/PanelView.js +99 -0
  35. package/esm/WorkspaceLayout/TabStrip.d.ts +14 -0
  36. package/esm/WorkspaceLayout/TabStrip.js +226 -0
  37. package/esm/WorkspaceLayout/WorkspaceContainer.d.ts +16 -0
  38. package/esm/WorkspaceLayout/WorkspaceContainer.js +105 -0
  39. package/esm/WorkspaceLayout/WorkspacePanelActions.d.ts +24 -0
  40. package/esm/WorkspaceLayout/WorkspacePanelActions.js +120 -0
  41. package/esm/WorkspaceLayout/WorkspaceTab.d.ts +27 -0
  42. package/esm/WorkspaceLayout/WorkspaceTab.js +109 -0
  43. package/esm/WorkspaceLayout/dockviewTheme.d.ts +69 -0
  44. package/esm/WorkspaceLayout/dockviewTheme.js +82 -0
  45. package/esm/WorkspaceLayout/dropZone.d.ts +105 -0
  46. package/esm/WorkspaceLayout/dropZone.js +113 -0
  47. package/esm/WorkspaceLayout/index.d.ts +8 -0
  48. package/esm/WorkspaceLayout/index.js +4 -0
  49. package/esm/WorkspaceLayout/model.d.ts +240 -0
  50. package/esm/WorkspaceLayout/model.js +527 -0
  51. package/esm/WorkspaceLayout/panelChrome.d.ts +19 -0
  52. package/esm/WorkspaceLayout/panelChrome.js +4 -0
  53. package/esm/WorkspaceLayout/spec.d.ts +58 -0
  54. package/esm/WorkspaceLayout/spec.js +153 -0
  55. package/esm/WorkspaceLayout/splitter.d.ts +25 -0
  56. package/esm/WorkspaceLayout/splitter.js +37 -0
  57. package/esm/WorkspaceLayout/tree.d.ts +158 -0
  58. package/esm/WorkspaceLayout/tree.js +379 -0
  59. package/esm/WorkspaceLayout/useLayoutDrag.d.ts +34 -0
  60. package/esm/WorkspaceLayout/useLayoutDrag.js +232 -0
  61. package/esm/index.d.ts +16 -9
  62. package/esm/index.js +13 -9
  63. package/esm/menus.d.ts +63 -62
  64. package/esm/menus.js +131 -84
  65. package/esm/queryParams.d.ts +9 -0
  66. package/esm/queryParams.js +92 -0
  67. package/esm/sessionModelFactory.d.ts +18 -0
  68. package/esm/sessionModelFactory.js +1 -0
  69. package/esm/ui/App/App.d.ts +3 -14
  70. package/esm/ui/App/App.js +30 -17
  71. package/esm/ui/App/AppFab.d.ts +12 -3
  72. package/esm/ui/App/AppFab.js +15 -8
  73. package/esm/ui/App/AppReadyMarker.d.ts +34 -0
  74. package/esm/ui/App/AppReadyMarker.js +56 -0
  75. package/esm/ui/App/AppToolbar.d.ts +2 -14
  76. package/esm/ui/App/AppToolbar.js +23 -24
  77. package/esm/ui/App/ClassicViewsContainer.d.ts +3 -9
  78. package/esm/ui/App/ClassicViewsContainer.js +9 -8
  79. package/esm/ui/App/DialogQueue.d.ts +17 -1
  80. package/esm/ui/App/DialogQueue.js +30 -1
  81. package/esm/ui/App/Drawer.d.ts +1 -1
  82. package/esm/ui/App/Drawer.js +10 -39
  83. package/esm/ui/App/DrawerControls.d.ts +1 -5
  84. package/esm/ui/App/DrawerControls.js +1 -25
  85. package/esm/ui/App/DrawerHeader.d.ts +2 -3
  86. package/esm/ui/App/DrawerHeader.js +24 -10
  87. package/esm/ui/App/DrawerHeaderHelpButton.d.ts +1 -1
  88. package/esm/ui/App/DrawerHeaderHelpButton.js +3 -3
  89. package/esm/ui/App/DrawerHeaderHelpDialog.d.ts +2 -2
  90. package/esm/ui/App/DrawerHeaderHelpDialog.js +3 -4
  91. package/esm/ui/App/DrawerWidget.d.ts +1 -1
  92. package/esm/ui/App/DrawerWidget.js +9 -21
  93. package/esm/ui/App/JBrowseTabMenu.d.ts +2 -3
  94. package/esm/ui/App/JBrowseTabMenu.js +24 -5
  95. package/esm/ui/App/ViewButtons.d.ts +2 -4
  96. package/esm/ui/App/ViewButtons.js +15 -3
  97. package/esm/ui/App/ViewContainer.d.ts +3 -2
  98. package/esm/ui/App/ViewContainer.js +144 -24
  99. package/esm/ui/App/ViewContainerTitle.d.ts +1 -1
  100. package/esm/ui/App/ViewContainerTitle.js +9 -2
  101. package/esm/ui/App/ViewErrorFallback.d.ts +18 -0
  102. package/esm/ui/App/ViewErrorFallback.js +42 -0
  103. package/esm/ui/App/ViewHeader.d.ts +3 -4
  104. package/esm/ui/App/ViewHeader.js +28 -17
  105. package/esm/ui/App/ViewLauncher.d.ts +2 -8
  106. package/esm/ui/App/ViewLauncher.js +7 -5
  107. package/esm/ui/App/ViewMenu.d.ts +3 -5
  108. package/esm/ui/App/ViewMenu.js +87 -92
  109. package/esm/ui/App/ViewStack.d.ts +7 -0
  110. package/esm/ui/App/ViewStack.js +42 -0
  111. package/esm/ui/App/ViewWrapper.d.ts +15 -1
  112. package/esm/ui/App/ViewWrapper.js +26 -10
  113. package/esm/ui/App/ViewsContainer.d.ts +3 -8
  114. package/esm/ui/App/ViewsContainer.js +9 -6
  115. package/esm/ui/App/copyView.js +1 -1
  116. package/esm/ui/App/index.d.ts +2 -1
  117. package/esm/ui/App/index.js +3 -2
  118. package/esm/ui/App/lazyChunk.d.ts +13 -0
  119. package/esm/ui/App/lazyChunk.js +91 -0
  120. package/esm/ui/App/types.d.ts +12 -3
  121. package/esm/ui/App/types.js +1 -1
  122. package/esm/ui/App/useViewVisibility.d.ts +34 -0
  123. package/esm/ui/App/useViewVisibility.js +87 -0
  124. package/esm/ui/App/viewTitle.d.ts +5 -0
  125. package/esm/ui/App/viewTitle.js +9 -0
  126. package/esm/ui/index.d.ts +1 -1
  127. package/esm/ui/index.js +1 -1
  128. package/package.json +12 -17
  129. package/esm/AppFocus/index.d.ts +0 -5
  130. package/esm/AppFocus/index.js +0 -12
  131. package/esm/Assemblies/SessionAssembliesMixin.d.ts +0 -92
  132. package/esm/Assemblies/SessionAssembliesMixin.js +0 -53
  133. package/esm/Assemblies/TemporaryAssembliesMixin.d.ts +0 -10
  134. package/esm/Assemblies/TemporaryAssembliesMixin.js +0 -37
  135. package/esm/DockviewLayout/index.d.ts +0 -35
  136. package/esm/DockviewLayout/index.js +0 -111
  137. package/esm/ui/App/DockviewContext.d.ts +0 -22
  138. package/esm/ui/App/DockviewContext.js +0 -29
  139. package/esm/ui/App/DockviewLeftHeaderActions.d.ts +0 -2
  140. package/esm/ui/App/DockviewLeftHeaderActions.js +0 -58
  141. package/esm/ui/App/DockviewRightHeaderActions.d.ts +0 -2
  142. package/esm/ui/App/DockviewRightHeaderActions.js +0 -100
  143. package/esm/ui/App/DrawerWidgetSelector.d.ts +0 -5
  144. package/esm/ui/App/DrawerWidgetSelector.js +0 -47
  145. package/esm/ui/App/JBrowseViewPanel.d.ts +0 -8
  146. package/esm/ui/App/JBrowseViewPanel.js +0 -40
  147. package/esm/ui/App/JBrowseViewTab.d.ts +0 -8
  148. package/esm/ui/App/JBrowseViewTab.js +0 -97
  149. package/esm/ui/App/ModalWidget.d.ts +0 -6
  150. package/esm/ui/App/ModalWidget.js +0 -48
  151. package/esm/ui/App/TiledViewsContainer.d.ts +0 -6
  152. package/esm/ui/App/TiledViewsContainer.js +0 -366
  153. package/esm/ui/App/dockviewUtils.d.ts +0 -46
  154. package/esm/ui/App/dockviewUtils.js +0 -55
@@ -1,71 +1,117 @@
1
1
  import { types } from '@jbrowse/mobx-state-tree';
2
+ /**
3
+ * #stateModel RootAppMenuMixin
4
+ */
2
5
  export function RootAppMenuMixin() {
3
6
  return types
4
7
  .model({})
5
8
  .volatile(() => ({
9
+ // array reference is replaced (not mutated) so MobX observers detect the change
6
10
  mutableMenuActions: [],
7
11
  }))
8
- .actions(self => ({
9
- setMenus(newMenus) {
10
- self.mutableMenuActions = [
11
- ...self.mutableMenuActions,
12
- { type: 'setMenus', newMenus },
13
- ];
14
- },
15
- appendMenu(menuName) {
16
- self.mutableMenuActions = [
17
- ...self.mutableMenuActions,
18
- { type: 'appendMenu', menuName },
19
- ];
20
- },
21
- insertMenu(menuName, position) {
22
- self.mutableMenuActions = [
23
- ...self.mutableMenuActions,
24
- {
25
- type: 'insertMenu',
26
- menuName,
27
- position,
28
- },
29
- ];
30
- },
31
- appendToMenu(menuName, menuItem) {
32
- self.mutableMenuActions = [
33
- ...self.mutableMenuActions,
34
- {
35
- type: 'appendToMenu',
36
- menuName,
37
- menuItem,
38
- },
39
- ];
40
- },
41
- insertInMenu(menuName, menuItem, position) {
42
- self.mutableMenuActions.push({
43
- type: 'insertInMenu',
44
- menuName,
45
- menuItem,
46
- position,
47
- });
48
- },
49
- appendToSubMenu(menuPath, menuItem) {
50
- self.mutableMenuActions = [
51
- ...self.mutableMenuActions,
52
- {
53
- type: 'appendToSubMenu',
54
- menuPath,
55
- menuItem,
56
- },
57
- ];
58
- },
59
- insertInSubMenu(menuPath, menuItem, position) {
60
- self.mutableMenuActions = [
61
- ...self.mutableMenuActions,
62
- {
63
- type: 'insertInSubMenu',
64
- menuPath,
12
+ .actions(self => {
13
+ function pushAction(action) {
14
+ self.mutableMenuActions = [...self.mutableMenuActions, action];
15
+ }
16
+ return {
17
+ /**
18
+ * #action
19
+ * Replace the menu bar wholesale. Item contributions recorded before
20
+ * this one are dropped along with the menus they targeted, so a plugin
21
+ * adding to the existing bar wants `appendToMenu` instead.
22
+ *
23
+ * @param newMenus - The complete new set of top-level menus.
24
+ */
25
+ setMenus(newMenus) {
26
+ pushAction({ type: 'setMenus', newMenus });
27
+ },
28
+ /**
29
+ * #action
30
+ * Add a top-level menu, if the app bar does not already have one with
31
+ * this name.
32
+ *
33
+ * @param menuName - Name of the menu to add.
34
+ */
35
+ appendMenu(menuName) {
36
+ pushAction({ type: 'addMenu', menuName });
37
+ },
38
+ /**
39
+ * #action
40
+ * Insert a top-level menu, if the app bar does not already have one
41
+ * with this name.
42
+ *
43
+ * @param menuName - Name of the menu to insert.
44
+ *
45
+ * @param position - Position to insert menu. If negative, counts from the
46
+ * end, e.g. `insertMenu('My Menu', -1)` will insert the menu as the
47
+ * second-to-last one.
48
+ */
49
+ insertMenu(menuName, position) {
50
+ pushAction({ type: 'addMenu', menuName, position });
51
+ },
52
+ /**
53
+ * #action
54
+ * Add a menu item to a top-level menu, creating the menu if it does not
55
+ * exist.
56
+ *
57
+ * @param menuName - Name of the top-level menu to append to.
58
+ *
59
+ * @param menuItem - Menu item to append.
60
+ */
61
+ appendToMenu(menuName, menuItem) {
62
+ pushAction({ type: 'addItem', menuPath: [menuName], menuItem });
63
+ },
64
+ /**
65
+ * #action
66
+ * Insert a menu item into a top-level menu, creating the menu if it
67
+ * does not exist.
68
+ *
69
+ * @param menuName - Name of the top-level menu to insert into
70
+ *
71
+ * @param menuItem - Menu item to insert
72
+ *
73
+ * @param position - Position to insert menu item. If negative, counts
74
+ * from the end, e.g. `insertInMenu('My Menu', item, -1)` will insert the
75
+ * item as the second-to-last one.
76
+ */
77
+ insertInMenu(menuName, menuItem, position) {
78
+ pushAction({
79
+ type: 'addItem',
80
+ menuPath: [menuName],
65
81
  menuItem,
66
82
  position,
67
- },
68
- ];
69
- },
70
- }));
83
+ });
84
+ },
85
+ /**
86
+ * #action
87
+ * Add a menu item to a sub-menu, creating any part of the path that
88
+ * does not exist.
89
+ *
90
+ * @param menuPath - Path to the sub-menu to add to, starting with the
91
+ * top-level menu (e.g. `['File', 'Insert']`).
92
+ *
93
+ * @param menuItem - Menu item to append.
94
+ */
95
+ appendToSubMenu(menuPath, menuItem) {
96
+ pushAction({ type: 'addItem', menuPath, menuItem });
97
+ },
98
+ /**
99
+ * #action
100
+ * Insert a menu item into a sub-menu, creating any part of the path
101
+ * that does not exist.
102
+ *
103
+ * @param menuPath - Path to the sub-menu to add to, starting with the
104
+ * top-level menu (e.g. `['File', 'Insert']`).
105
+ *
106
+ * @param menuItem - Menu item to insert.
107
+ *
108
+ * @param position - Position to insert menu item. If negative, counts
109
+ * from the end, e.g. `insertInSubMenu(path, item, -1)` will insert the
110
+ * item as the second-to-last one.
111
+ */
112
+ insertInSubMenu(menuPath, menuItem, position) {
113
+ pushAction({ type: 'addItem', menuPath, menuItem, position });
114
+ },
115
+ };
116
+ });
71
117
  }
@@ -0,0 +1,6 @@
1
+ export { buildLgvInit, buildLgvInitFromParams, hubConnectionSpec, readHubUrlParam, readNavParam, readTracklistParam, shortHubLabel, splitHighlights, } from './lgvUrlInit.ts';
2
+ export { addSessionTracks, loadSessionSpec } from './loadSessionSpec.ts';
3
+ export { parseSessionSpecUrl } from './parseSessionSpecUrl.ts';
4
+ export type { LgvUrlInit } from './lgvUrlInit.ts';
5
+ export type { ParsedSessionSpec } from './parseSessionSpecUrl.ts';
6
+ export type { LayoutNode, ViewSpec } from './types.ts';
@@ -0,0 +1,3 @@
1
+ export { buildLgvInit, buildLgvInitFromParams, hubConnectionSpec, readHubUrlParam, readNavParam, readTracklistParam, shortHubLabel, splitHighlights, } from './lgvUrlInit.js';
2
+ export { addSessionTracks, loadSessionSpec } from './loadSessionSpec.js';
3
+ export { parseSessionSpecUrl } from './parseSessionSpecUrl.js';
@@ -0,0 +1,79 @@
1
+ export interface LgvUrlInit {
2
+ loc?: string;
3
+ assembly?: string;
4
+ tracks?: string[];
5
+ tracklist?: boolean;
6
+ nav?: boolean;
7
+ highlight?: string[];
8
+ displayedRegionNames?: string[];
9
+ }
10
+ export declare function splitHighlights(str: string): string[];
11
+ /**
12
+ * `&tracklist=` — only the literal `true` turns the track selector on.
13
+ *
14
+ * Absent stays absent rather than collapsing into the param's default:
15
+ * buildLgvInit's result is layered over a defaultSession's own pending init, so
16
+ * a `false` synthesized here would overwrite what that session set.
17
+ */
18
+ export declare function readTracklistParam(value: string | undefined): boolean | undefined;
19
+ /**
20
+ * `&nav=` — anything but the literal `false` leaves the navigation bar on.
21
+ *
22
+ * The opposite default to tracklist above, and deliberately so: the nav bar is
23
+ * on unless a link turns it off, the track selector is off unless a link turns
24
+ * it on. Absent stays absent for the same reason as tracklist.
25
+ */
26
+ export declare function readNavParam(value: string | undefined): boolean | undefined;
27
+ /**
28
+ * Normalizes already-decoded shorthand values into an LGV init.
29
+ *
30
+ * A param the URL omits is left off the result rather than set to undefined:
31
+ * jbrowse-web's applyDefaultSessionViewInit merges this over the view's own
32
+ * pending init, and a present-but-undefined key there would erase what the
33
+ * defaultSession set.
34
+ */
35
+ export declare function buildLgvInit(args: {
36
+ loc?: string;
37
+ tracks?: string;
38
+ assembly?: string;
39
+ tracklist?: boolean;
40
+ nav?: boolean;
41
+ highlight?: string;
42
+ regions?: string;
43
+ }): LgvUrlInit;
44
+ /**
45
+ * `&hubURL=` — a comma-separated list of hub.txt urls.
46
+ *
47
+ * Empty entries are dropped, so `&hubURL=` and `&hubURL=,,` are no hubs at all
48
+ * rather than a list of blanks. jbrowse-web learned that the hard way: a
49
+ * present-but-empty param is still truthy, which routed the load to a hub
50
+ * builder with no url to connect to and produced a session with nothing in it
51
+ * and no diagnostic.
52
+ */
53
+ export declare function readHubUrlParam(value: string | undefined): string[];
54
+ /**
55
+ * A short, readable label for a hub connection, before its hub.txt has been
56
+ * read: the second-to-last path segment, which for `…/myHub/hub.txt` is the
57
+ * hub's own directory. Beats showing the whole url in a track-selector category
58
+ * header.
59
+ */
60
+ export declare function shortHubLabel(url: string): string;
61
+ /**
62
+ * The `sessionConnections` entry for a hub url — the spec vocabulary for "attach
63
+ * this track hub", which loadSessionSpec registers before it launches any view.
64
+ */
65
+ export declare function hubConnectionSpec(url: string): {
66
+ type: string;
67
+ connectionId: string;
68
+ name: string;
69
+ hubTxtLocation: {
70
+ uri: string;
71
+ locationType: string;
72
+ };
73
+ };
74
+ /**
75
+ * The same init, read straight off a link's params. jbrowse-web decodes these
76
+ * into its loader's own properties first (they have to survive an HMR reload),
77
+ * so it calls buildLgvInit above; a caller holding a whole URL wants this.
78
+ */
79
+ export declare function buildLgvInitFromParams(params: URLSearchParams): LgvUrlInit;
@@ -0,0 +1,158 @@
1
+ import { parseRegionNames } from '@jbrowse/core/util';
2
+ // split a space-separated &highlight= URL param into individual highlights.
3
+ // spaces inside a JSON object ({...}) are not treated as delimiters, so a
4
+ // highlight like {"refName":"chr1","start":1,"end":2,"label":"my region"}
5
+ // survives intact alongside plain loc strings
6
+ export function splitHighlights(str) {
7
+ const out = [];
8
+ let depth = 0;
9
+ let cur = '';
10
+ for (const ch of str) {
11
+ if (ch === '{') {
12
+ depth++;
13
+ }
14
+ if (ch === '}') {
15
+ depth = Math.max(0, depth - 1);
16
+ }
17
+ if (ch === ' ' && depth === 0) {
18
+ if (cur) {
19
+ out.push(cur);
20
+ }
21
+ cur = '';
22
+ }
23
+ else {
24
+ cur += ch;
25
+ }
26
+ }
27
+ if (cur) {
28
+ out.push(cur);
29
+ }
30
+ return out;
31
+ }
32
+ /**
33
+ * `&tracklist=` — only the literal `true` turns the track selector on.
34
+ *
35
+ * Absent stays absent rather than collapsing into the param's default:
36
+ * buildLgvInit's result is layered over a defaultSession's own pending init, so
37
+ * a `false` synthesized here would overwrite what that session set.
38
+ */
39
+ export function readTracklistParam(value) {
40
+ return value === undefined ? undefined : value === 'true';
41
+ }
42
+ /**
43
+ * `&nav=` — anything but the literal `false` leaves the navigation bar on.
44
+ *
45
+ * The opposite default to tracklist above, and deliberately so: the nav bar is
46
+ * on unless a link turns it off, the track selector is off unless a link turns
47
+ * it on. Absent stays absent for the same reason as tracklist.
48
+ */
49
+ export function readNavParam(value) {
50
+ return value === undefined ? undefined : value !== 'false';
51
+ }
52
+ /**
53
+ * Normalizes already-decoded shorthand values into an LGV init.
54
+ *
55
+ * A param the URL omits is left off the result rather than set to undefined:
56
+ * jbrowse-web's applyDefaultSessionViewInit merges this over the view's own
57
+ * pending init, and a present-but-undefined key there would erase what the
58
+ * defaultSession set.
59
+ */
60
+ export function buildLgvInit(args) {
61
+ const { loc, tracks, assembly, tracklist, nav, highlight, regions } = args;
62
+ const init = {};
63
+ if (loc !== undefined) {
64
+ init.loc = loc;
65
+ }
66
+ if (assembly !== undefined) {
67
+ init.assembly = assembly;
68
+ }
69
+ if (tracks !== undefined) {
70
+ init.tracks = tracks.split(',');
71
+ }
72
+ if (tracklist !== undefined) {
73
+ init.tracklist = tracklist;
74
+ }
75
+ if (nav !== undefined) {
76
+ init.nav = nav;
77
+ }
78
+ if (highlight !== undefined) {
79
+ init.highlight = splitHighlights(highlight);
80
+ }
81
+ if (regions !== undefined) {
82
+ // restrict a whole-genome view (no loc) to these named chromosomes, in
83
+ // order; resolved through assembly aliases in afterAttach's showNamedRegions
84
+ //
85
+ // Through core's parser, the same one the import forms' chromosome boxes
86
+ // use, rather than a bare split: this is one syntax with one meaning, and
87
+ // the second reading of it dropped `chr2` from `&regions=chr1,%20chr2`
88
+ // without a word. Empty entries go with it — a present-but-empty
89
+ // `&regions=` is still truthy, and the list of one empty name it used to
90
+ // produce reported itself as having matched nothing. Same trap as
91
+ // readHubUrlParam below.
92
+ const names = parseRegionNames(regions);
93
+ if (names.length) {
94
+ init.displayedRegionNames = names;
95
+ }
96
+ }
97
+ return init;
98
+ }
99
+ /**
100
+ * `&hubURL=` — a comma-separated list of hub.txt urls.
101
+ *
102
+ * Empty entries are dropped, so `&hubURL=` and `&hubURL=,,` are no hubs at all
103
+ * rather than a list of blanks. jbrowse-web learned that the hard way: a
104
+ * present-but-empty param is still truthy, which routed the load to a hub
105
+ * builder with no url to connect to and produced a session with nothing in it
106
+ * and no diagnostic.
107
+ */
108
+ export function readHubUrlParam(value) {
109
+ return value?.split(',').filter(Boolean) ?? [];
110
+ }
111
+ /**
112
+ * A short, readable label for a hub connection, before its hub.txt has been
113
+ * read: the second-to-last path segment, which for `…/myHub/hub.txt` is the
114
+ * hub's own directory. Beats showing the whole url in a track-selector category
115
+ * header.
116
+ */
117
+ export function shortHubLabel(url) {
118
+ try {
119
+ const segments = new URL(url).pathname.split('/').filter(Boolean);
120
+ return segments.at(-2) ?? segments.at(-1) ?? url;
121
+ }
122
+ catch {
123
+ return url;
124
+ }
125
+ }
126
+ /**
127
+ * The `sessionConnections` entry for a hub url — the spec vocabulary for "attach
128
+ * this track hub", which loadSessionSpec registers before it launches any view.
129
+ */
130
+ export function hubConnectionSpec(url) {
131
+ return {
132
+ type: 'UCSCTrackHubConnection',
133
+ connectionId: url,
134
+ name: shortHubLabel(url),
135
+ hubTxtLocation: { uri: url, locationType: 'UriLocation' },
136
+ };
137
+ }
138
+ // URLSearchParams.get returns null for an absent param, and every reader here
139
+ // distinguishes absent from present-and-empty
140
+ function read(params, key) {
141
+ return params.get(key) ?? undefined;
142
+ }
143
+ /**
144
+ * The same init, read straight off a link's params. jbrowse-web decodes these
145
+ * into its loader's own properties first (they have to survive an HMR reload),
146
+ * so it calls buildLgvInit above; a caller holding a whole URL wants this.
147
+ */
148
+ export function buildLgvInitFromParams(params) {
149
+ return buildLgvInit({
150
+ loc: read(params, 'loc'),
151
+ assembly: read(params, 'assembly'),
152
+ tracks: read(params, 'tracks'),
153
+ tracklist: readTracklistParam(read(params, 'tracklist')),
154
+ nav: readNavParam(read(params, 'nav')),
155
+ highlight: read(params, 'highlight'),
156
+ regions: read(params, 'regions'),
157
+ });
158
+ }
@@ -0,0 +1,21 @@
1
+ import type { LayoutNode, ViewSpec } from './types.ts';
2
+ import type PluginManager from '@jbrowse/core/PluginManager';
3
+ import type { AbstractSessionModel } from '@jbrowse/core/util';
4
+ /**
5
+ * Register `&sessionTracks=` / a spec's `sessionTracks` into a session.
6
+ *
7
+ * Exported because the hub launch needs it too and must not reimplement it.
8
+ *
9
+ * A track that fails to register does not cost the caller the rest of them —
10
+ * same reasoning as the per-connection and per-view try/catch around it, one
11
+ * layer down.
12
+ */
13
+ export declare function addSessionTracks(session: AbstractSessionModel | undefined, tracks: Record<string, unknown>[]): void;
14
+ export declare function loadSessionSpec({ views, sessionAssemblies, sessionConnections, sessionTracks, layout, sessionName, }: {
15
+ views: ViewSpec[];
16
+ sessionAssemblies?: Record<string, unknown>[];
17
+ sessionConnections?: Record<string, unknown>[];
18
+ sessionTracks?: Record<string, unknown>[];
19
+ layout?: LayoutNode;
20
+ sessionName?: string;
21
+ }, pluginManager: PluginManager): Promise<void>;